diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2026-05-18 23:10:59 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2026-05-18 23:41:44 +0800 |
| commit | fc87c009806dcc98867f6b58efe29b042aa01dee (patch) | |
| tree | 8f59b3f4a5b66e9dfef2d40c8d318e258a521228 /node_modules/svgo/lib/stringifier.js | |
| parent | 3336b2356ee6152d9c6ae59bd9b87ccbc0958407 (diff) | |
node: updatemain
Diffstat (limited to 'node_modules/svgo/lib/stringifier.js')
| -rw-r--r-- | node_modules/svgo/lib/stringifier.js | 295 |
1 files changed, 0 insertions, 295 deletions
diff --git a/node_modules/svgo/lib/stringifier.js b/node_modules/svgo/lib/stringifier.js deleted file mode 100644 index 1a710869..00000000 --- a/node_modules/svgo/lib/stringifier.js +++ /dev/null @@ -1,295 +0,0 @@ -'use strict'; - -/** - * @typedef {import('./types').XastParent} XastParent - * @typedef {import('./types').XastRoot} XastRoot - * @typedef {import('./types').XastElement} XastElement - * @typedef {import('./types').XastInstruction} XastInstruction - * @typedef {import('./types').XastDoctype} XastDoctype - * @typedef {import('./types').XastText} XastText - * @typedef {import('./types').XastCdata} XastCdata - * @typedef {import('./types').XastComment} XastComment - * @typedef {import('./types').StringifyOptions} StringifyOptions - */ - -const { textElems } = require('../plugins/_collections'); - -/** - * @typedef {{ - * indent: string, - * textContext: ?XastElement, - * indentLevel: number, - * }} State - */ - -/** - * @typedef {Required<StringifyOptions>} Options - */ - -/** - * @type {(char: string) => string} - */ -const encodeEntity = (char) => { - return entities[char]; -}; - -/** @type {Options} */ -const defaults = { - doctypeStart: '<!DOCTYPE', - doctypeEnd: '>', - procInstStart: '<?', - procInstEnd: '?>', - tagOpenStart: '<', - tagOpenEnd: '>', - tagCloseStart: '</', - tagCloseEnd: '>', - tagShortStart: '<', - tagShortEnd: '/>', - attrStart: '="', - attrEnd: '"', - commentStart: '<!--', - commentEnd: '-->', - cdataStart: '<![CDATA[', - cdataEnd: ']]>', - textStart: '', - textEnd: '', - indent: 4, - regEntities: /[&'"<>]/g, - regValEntities: /[&"<>]/g, - encodeEntity, - pretty: false, - useShortTags: true, - eol: 'lf', - finalNewline: false, -}; - -/** @type {Record<string, string>} */ -const entities = { - '&': '&', - "'": ''', - '"': '"', - '>': '>', - '<': '<', -}; - -/** - * convert XAST to SVG string - * - * @type {(data: XastRoot, config: StringifyOptions) => string} - */ -const stringifySvg = (data, userOptions = {}) => { - /** - * @type {Options} - */ - const config = { ...defaults, ...userOptions }; - const indent = config.indent; - let newIndent = ' '; - if (typeof indent === 'number' && Number.isNaN(indent) === false) { - newIndent = indent < 0 ? '\t' : ' '.repeat(indent); - } else if (typeof indent === 'string') { - newIndent = indent; - } - /** - * @type {State} - */ - const state = { - indent: newIndent, - textContext: null, - indentLevel: 0, - }; - const eol = config.eol === 'crlf' ? '\r\n' : '\n'; - if (config.pretty) { - config.doctypeEnd += eol; - config.procInstEnd += eol; - config.commentEnd += eol; - config.cdataEnd += eol; - config.tagShortEnd += eol; - config.tagOpenEnd += eol; - config.tagCloseEnd += eol; - config.textEnd += eol; - } - let svg = stringifyNode(data, config, state); - if (config.finalNewline && svg.length > 0 && !svg.endsWith('\n')) { - svg += eol; - } - return svg; -}; -exports.stringifySvg = stringifySvg; - -/** - * @type {(node: XastParent, config: Options, state: State) => string} - */ -const stringifyNode = (data, config, state) => { - let svg = ''; - state.indentLevel += 1; - for (const item of data.children) { - if (item.type === 'element') { - svg += stringifyElement(item, config, state); - } - if (item.type === 'text') { - svg += stringifyText(item, config, state); - } - if (item.type === 'doctype') { - svg += stringifyDoctype(item, config); - } - if (item.type === 'instruction') { - svg += stringifyInstruction(item, config); - } - if (item.type === 'comment') { - svg += stringifyComment(item, config); - } - if (item.type === 'cdata') { - svg += stringifyCdata(item, config, state); - } - } - state.indentLevel -= 1; - return svg; -}; - -/** - * create indent string in accordance with the current node level. - * - * @type {(config: Options, state: State) => string} - */ -const createIndent = (config, state) => { - let indent = ''; - if (config.pretty && state.textContext == null) { - indent = state.indent.repeat(state.indentLevel - 1); - } - return indent; -}; - -/** - * @type {(node: XastDoctype, config: Options) => string} - */ -const stringifyDoctype = (node, config) => { - return config.doctypeStart + node.data.doctype + config.doctypeEnd; -}; - -/** - * @type {(node: XastInstruction, config: Options) => string} - */ -const stringifyInstruction = (node, config) => { - return ( - config.procInstStart + node.name + ' ' + node.value + config.procInstEnd - ); -}; - -/** - * @type {(node: XastComment, config: Options) => string} - */ -const stringifyComment = (node, config) => { - return config.commentStart + node.value + config.commentEnd; -}; - -/** - * @type {(node: XastCdata, config: Options, state: State) => string} - */ -const stringifyCdata = (node, config, state) => { - return ( - createIndent(config, state) + - config.cdataStart + - node.value + - config.cdataEnd - ); -}; - -/** - * @type {(node: XastElement, config: Options, state: State) => string} - */ -const stringifyElement = (node, config, state) => { - // empty element and short tag - if (node.children.length === 0) { - if (config.useShortTags) { - return ( - createIndent(config, state) + - config.tagShortStart + - node.name + - stringifyAttributes(node, config) + - config.tagShortEnd - ); - } else { - return ( - createIndent(config, state) + - config.tagShortStart + - node.name + - stringifyAttributes(node, config) + - config.tagOpenEnd + - config.tagCloseStart + - node.name + - config.tagCloseEnd - ); - } - // non-empty element - } else { - let tagOpenStart = config.tagOpenStart; - let tagOpenEnd = config.tagOpenEnd; - let tagCloseStart = config.tagCloseStart; - let tagCloseEnd = config.tagCloseEnd; - let openIndent = createIndent(config, state); - let closeIndent = createIndent(config, state); - - if (state.textContext) { - tagOpenStart = defaults.tagOpenStart; - tagOpenEnd = defaults.tagOpenEnd; - tagCloseStart = defaults.tagCloseStart; - tagCloseEnd = defaults.tagCloseEnd; - openIndent = ''; - } else if (textElems.has(node.name)) { - tagOpenEnd = defaults.tagOpenEnd; - tagCloseStart = defaults.tagCloseStart; - closeIndent = ''; - state.textContext = node; - } - - const children = stringifyNode(node, config, state); - - if (state.textContext === node) { - state.textContext = null; - } - - return ( - openIndent + - tagOpenStart + - node.name + - stringifyAttributes(node, config) + - tagOpenEnd + - children + - closeIndent + - tagCloseStart + - node.name + - tagCloseEnd - ); - } -}; - -/** - * @type {(node: XastElement, config: Options) => string} - */ -const stringifyAttributes = (node, config) => { - let attrs = ''; - for (const [name, value] of Object.entries(node.attributes)) { - // TODO remove attributes without values support in v3 - if (value !== undefined) { - const encodedValue = value - .toString() - .replace(config.regValEntities, config.encodeEntity); - attrs += ' ' + name + config.attrStart + encodedValue + config.attrEnd; - } else { - attrs += ' ' + name; - } - } - return attrs; -}; - -/** - * @type {(node: XastText, config: Options, state: State) => string} - */ -const stringifyText = (node, config, state) => { - return ( - createIndent(config, state) + - config.textStart + - node.value.replace(config.regEntities, config.encodeEntity) + - (state.textContext ? '' : config.textEnd) - ); -}; |
