turnish 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/node.ts","../src/utilities.ts","../src/default-rules.ts","../src/rules.ts","../src/collapse-whitespace.ts","../src/html-parser.ts","../src/root-node.ts","../src/index.ts"],"sourcesContent":["import { isBlock, isVoid, hasVoid, isMeaningfulWhenBlank, hasMeaningfulWhenBlank } from '@/utilities'\n\ninterface Options {\n preformattedCode?: boolean;\n}\n\ninterface FlankingWhitespace {\n leading: string;\n trailing: string;\n}\n\ninterface EdgeWhitespace extends FlankingWhitespace {\n leadingAscii: string;\n leadingNonAscii: string;\n trailingNonAscii: string;\n trailingAscii: string;\n}\n\nexport interface ExtendedNode extends Element {\n isBlock: boolean;\n isCode: boolean;\n isBlank: boolean;\n flankingWhitespace: FlankingWhitespace;\n}\n\nexport function ExtendedNode(node: Node, options: Options): ExtendedNode {\n const extended = node as ExtendedNode;\n extended.isBlock = isBlock(extended);\n extended.isCode = extended.nodeName === 'CODE' || (extended.parentNode as ExtendedNode)?.isCode;\n extended.isBlank = isBlank(extended);\n extended.flankingWhitespace = flankingWhitespace(extended, options);\n return extended;\n}\n\nfunction isBlank(node: ExtendedNode): boolean {\n return (\n !isVoid(node) &&\n !isMeaningfulWhenBlank(node) &&\n /^\\s*$/i.test(node.textContent || '') &&\n !hasVoid(node) &&\n !hasMeaningfulWhenBlank(node)\n )\n}\n\nfunction flankingWhitespace(node: ExtendedNode, options: Options): FlankingWhitespace {\n const extendedNode = node as ExtendedNode;\n\n if (extendedNode.isBlock || (options.preformattedCode && extendedNode.isCode)) {\n return { leading: '', trailing: '' };\n }\n\n const edges = edgeWhitespace(node.textContent || '');\n\n // abandon leading ASCII WS if left-flanked by ASCII WS\n if (edges.leadingAscii && isFlankedByWhitespace('left', node, options)) {\n edges.leading = edges.leadingNonAscii;\n }\n\n // abandon trailing ASCII WS if right-flanked by ASCII WS\n if (edges.trailingAscii && isFlankedByWhitespace('right', node, options)) {\n edges.trailing = edges.trailingNonAscii;\n }\n\n return { leading: edges.leading, trailing: edges.trailing };\n}\n\nfunction edgeWhitespace(string: string): EdgeWhitespace {\n const m = string.match(/^(([ \\t\\r\\n]*)(\\s*))(?:(?=\\S)[\\s\\S]*\\S)?((\\s*?)([ \\t\\r\\n]*))$/);\n\n if (!m) {\n return {\n leading: '',\n leadingAscii: '',\n leadingNonAscii: '',\n trailing: '',\n trailingNonAscii: '',\n trailingAscii: ''\n };\n }\n\n return {\n leading: m[1], // whole string for whitespace-only strings\n leadingAscii: m[2],\n leadingNonAscii: m[3],\n trailing: m[4], // empty for whitespace-only strings\n trailingNonAscii: m[5],\n trailingAscii: m[6]\n };\n}\n\nfunction isFlankedByWhitespace(side: 'left' | 'right', node: Element, options: Options): boolean {\n let sibling: Element | null;\n let regExp: RegExp;\n let isFlanked: boolean | undefined;\n\n if (side === 'left') {\n sibling = node.previousElementSibling;\n regExp = / $/;\n } else {\n sibling = node.nextElementSibling;\n regExp = /^ /;\n }\n\n if (sibling) {\n if (sibling.nodeType === 3) {\n isFlanked = regExp.test(sibling.nodeValue || '');\n } else if (options.preformattedCode && sibling.nodeName === 'CODE') {\n isFlanked = false;\n } else if (sibling.nodeType === 1 && !isBlock(sibling)) {\n isFlanked = regExp.test(sibling.textContent || '');\n }\n }\n\n return isFlanked || false;\n}\n\nexport const NodeTypes = {\n Element: 1,\n Text: 3,\n CDATASection: 4,\n Comment: 8\n} as const;\n\nexport type NodeType = typeof NodeTypes[keyof typeof NodeTypes];\n","import { ExtendedNode, NodeTypes } from \"./node\";\n\nexport function repeat(character: string, count: number) {\n return Array(count + 1).join(character)\n}\n\nexport function trimLeadingNewlines(string: string) {\n return string.replace(/^\\n*/, '')\n}\n\nexport function trimTrailingNewlines(string: string) {\n // avoid match-at-end regexp bottleneck, see #370\n let indexEnd = string.length\n while (indexEnd > 0 && string[indexEnd - 1] === '\\n') indexEnd--\n return string.substring(0, indexEnd)\n}\n\nexport function trimNewlines(string: string) {\n return trimTrailingNewlines(trimLeadingNewlines(string))\n}\n\nexport const blockElements = [\n 'ADDRESS', 'ARTICLE', 'ASIDE', 'AUDIO', 'BLOCKQUOTE', 'BODY', 'CANVAS',\n 'CENTER', 'DD', 'DIR', 'DIV', 'DL', 'DT', 'FIELDSET', 'FIGCAPTION', 'FIGURE',\n 'FOOTER', 'FORM', 'FRAMESET', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEADER',\n 'HGROUP', 'HR', 'HTML', 'ISINDEX', 'LI', 'MAIN', 'MENU', 'NAV', 'NOFRAMES',\n 'NOSCRIPT', 'OL', 'OUTPUT', 'P', 'PRE', 'SECTION', 'TABLE', 'TBODY', 'TD',\n 'TFOOT', 'TH', 'THEAD', 'TR', 'UL'\n]\n\nexport function isBlock(node: Node) {\n return is(node, blockElements)\n}\n\nexport const voidElements = [\n 'AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT',\n 'KEYGEN', 'LINK', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR'\n]\n\nexport function isVoid(node: Node) {\n return is(node, voidElements)\n}\n\nexport function hasVoid(node: Node) {\n return has(node, voidElements)\n}\n\nconst meaningfulWhenBlankElements = [\n 'A', 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TH', 'TD', 'IFRAME', 'SCRIPT',\n 'AUDIO', 'VIDEO'\n]\n\nexport const standardMarkdownElements = [\n 'P', 'BR', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE',\n 'UL', 'OL', 'LI', 'PRE', 'CODE', 'HR', 'A', 'EM', 'I', 'STRONG',\n 'B', 'IMG', 'DIV', 'SPAN', 'TABLE', 'THEAD', 'TBODY', 'TR', 'TH', 'TD'\n]\n\nexport function isMeaningfulWhenBlank(node: Node) {\n return is(node, meaningfulWhenBlankElements)\n}\n\nexport function hasMeaningfulWhenBlank(node: Node) {\n return has(node, meaningfulWhenBlankElements)\n}\n\nfunction is(node: Node, tagNames: string[]) {\n return tagNames.indexOf(node.nodeName) >= 0\n}\n\nfunction has(node: Node, tagNames: string[]) {\n return (\n tagNames.some(function (tagName) {\n if (node.nodeType !== NodeTypes.Element) {\n return false;\n }\n return (node as Element).getElementsByTagName(tagName).length\n })\n )\n}\n\nexport function sanitizeWhitespace(string: string): string {\n return string ? string.replace(/(\\n+\\s*)+/g, '\\n') : '';\n}\n\nexport function sanitizedLinkContent(content: string): string {\n const sanitized = sanitizeWhitespace(content);\n return sanitized\n .replace(/[\\t\\r\\n]+/g, ' ')\n .replace(/ {2,}/g, ' ')\n .replace(/([()])/g, '\\\\$1')\n .trim();\n}\n\nexport function sanitizedLinkTitle(content: string): string {\n const sanitized = sanitizeWhitespace(content);\n return sanitized\n .replace(/[\\t\\r\\n]+/g, ' ');\n}\n\nexport type RequireOnly<T, K extends keyof T> =\n T & Required<Pick<T, K>>;\n","\nimport { Rule } from '@/rules';\nimport { TurnishOptions } from '@/index';\nimport { repeat, RequireOnly, sanitizedLinkContent, sanitizedLinkTitle, trimNewlines } from '@/utilities';\nimport { url } from 'inspector';\n\nexport const defaultRules: { [key: string]: Rule } = {}\n\ndefaultRules.paragraph = {\n filter: 'p',\n replacement: function (content: string): string {\n return '\\n\\n' + content + '\\n\\n';\n }\n};\n\ndefaultRules.lineBreak = {\n filter: 'br',\n replacement: function (_content: string, _node: Node, options: TurnishOptions): string {\n return options.br + '\\n';\n }\n};\n\ndefaultRules.heading = {\n filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],\n replacement: function (content: string, node: Node, options: TurnishOptions): string {\n const hLevel = Number(node.nodeName.charAt(1));\n if (options.headingStyle === 'setext' && hLevel < 3) {\n const underline = repeat((hLevel === 1 ? '=' : '-'), content.length);\n return (\n '\\n\\n' + content + '\\n' + underline + '\\n\\n'\n );\n } else {\n return '\\n\\n' + repeat('#', hLevel) + ' ' + content + '\\n\\n';\n }\n }\n};\n\ndefaultRules.blockquote = {\n filter: 'blockquote',\n replacement: function (content: string): string {\n content = trimNewlines(content).replace(/^/gm, '> ');\n return '\\n\\n' + content + '\\n\\n';\n }\n};\n\ndefaultRules.list = {\n filter: ['ul', 'ol'],\n replacement: function (content: string, node: Node): string {\n const parent = node.parentNode as Element;\n if (parent.nodeName === 'LI' && parent.lastElementChild === node) {\n return '\\n' + content;\n } else {\n return '\\n\\n' + content + '\\n\\n';\n }\n }\n};\n\ndefaultRules.listItem = {\n filter: 'li',\n replacement: function (content: string, node: Node, options: TurnishOptions): string {\n let prefix = options.bulletListMarker + ' ';\n const parent = node.parentNode as Element;\n if (parent.nodeName === 'OL') {\n const start = parent.getAttribute('start');\n const index = Array.prototype.indexOf.call(parent.children, node);\n prefix = (start ? Number(start) + index : index + 1) + '. ';\n }\n const isParagraph = /\\n$/.test(content);\n content = trimNewlines(content) + (isParagraph ? '\\n' : '');\n content = content.replace(/\\n/gm, '\\n' + ' '.repeat(prefix.length)); // indent\n return (\n prefix + content + (node.nextSibling ? '\\n' : '')\n );\n }\n};\n\ndefaultRules.indentedCodeBlock = {\n filter: function (node: Node, options: TurnishOptions): boolean {\n return !!(\n options &&\n options.codeBlockStyle === 'indented' &&\n node.nodeName === 'PRE' &&\n node.firstChild &&\n (node.firstChild as Element).nodeName === 'CODE'\n );\n },\n replacement: function (_content: string, node: Node): string {\n if (!node || !node.firstChild) return '';\n return (\n '\\n\\n ' +\n (node.firstChild as Element).textContent!.replace(/\\n/g, '\\n ') +\n '\\n\\n'\n );\n }\n};\n\ndefaultRules.fencedCodeBlock = {\n filter: function (node: Node, options: TurnishOptions): boolean {\n return !!(\n options &&\n options.codeBlockStyle === 'fenced' &&\n node.nodeName === 'PRE' &&\n node.firstChild &&\n (node.firstChild as Element).nodeName === 'CODE'\n );\n },\n replacement: function (_content: string, node: Node, options: TurnishOptions): string {\n if (!node.firstChild) {\n return '';\n }\n const codeElem = node.firstChild as Element;\n const className = codeElem.getAttribute('class') || '';\n const language = (className.match(/language-(\\S+)/) || [null, ''])[1];\n const code = codeElem.textContent || '';\n const fenceChar = options.fence?.charAt(0) || '`';\n let fenceSize = 3;\n const fenceInCodeRegex = new RegExp('^' + fenceChar + '{3,}', 'gm');\n let match;\n while ((match = fenceInCodeRegex.exec(code))) {\n if (match[0].length >= fenceSize) {\n fenceSize = match[0].length + 1;\n }\n }\n const fence = repeat(fenceChar, fenceSize);\n return (\n '\\n\\n' + fence + language + '\\n' +\n code.replace(/\\n$/, '') +\n '\\n' + fence + '\\n\\n'\n );\n }\n};\n\ndefaultRules.horizontalRule = {\n filter: 'hr',\n replacement: function (_content: string, _node: Node, options: TurnishOptions): string {\n return '\\n\\n' + options.hr + '\\n\\n';\n }\n};\n\ndefaultRules.inlineLink = {\n filter: function (node: Node, options: TurnishOptions): boolean {\n return !!(\n options?.linkStyle === 'inlined' &&\n node.nodeName === 'A' &&\n (node as Element).getAttribute('href')\n );\n },\n replacement: function (content: string, node: Node): string {\n const sanitizedContent = sanitizedLinkContent(content);\n let href = (node as Element)\n .getAttribute('href')\n ?.replace(/([()])/g, '\\\\$1');\n let title: string;\n const titleAttr = (node as Element).getAttribute('title');\n if (titleAttr) {\n const sanitizedTitle = sanitizedLinkTitle(titleAttr);\n title = ' \"' + sanitizedTitle.replace(/\"/g, '\\\\\"') + '\"';\n } else {\n title = '';\n }\n return '[' + sanitizedContent + '](' + href + title + ')';\n }\n};\n\nconst referenceLinkRule: RequireOnly<Rule, \"urlReferenceIdMap\" | \"references\"> = {\n filter: function (node: Node, options: TurnishOptions): boolean {\n return !!(\n options &&\n options.linkStyle === 'referenced' &&\n node.nodeName === 'A' &&\n (node as Element).getAttribute('href')\n );\n },\n replacement: function (content: string, node: Node, options: TurnishOptions): string {\n const self = referenceLinkRule;\n\n const href = (node as Element).getAttribute('href');\n let title: string;\n const titleAttr = (node as Element).getAttribute('title');\n if (titleAttr) {\n const sanitizedTitle = sanitizedLinkTitle(titleAttr);\n title = ' \"' + sanitizedTitle + '\"';\n } else {\n title = '';\n }\n const referenceKey = href + title;\n\n let replacement: string;\n let reference: string;\n switch (options.linkReferenceStyle) {\n case 'collapsed':\n replacement = '[' + content + '][]';\n reference = '[' + content + ']: ' + referenceKey;\n break;\n case 'shortcut':\n replacement = '[' + content + ']';\n reference = '[' + content + ']: ' + referenceKey;\n break;\n default: {\n let id: number;\n const existingKey = self.urlReferenceIdMap.get(referenceKey);\n if (options.linkReferenceDeduplication === 'full' && existingKey) {\n id = existingKey;\n reference = '[' + id + ']: ' + href + title;\n } else {\n id = self.references.length + 1;\n self.urlReferenceIdMap.set(referenceKey, id);\n reference = '[' + id + ']: ' + href + title;\n self.references.push(reference);\n }\n replacement = '[' + content + '][' + id + ']';\n break;\n }\n }\n\n if (options.linkReferenceStyle !== 'full') {\n // Check if we should deduplicate\n if (options.linkReferenceDeduplication === 'full') {\n if (!self.urlReferenceIdMap.has(referenceKey)) {\n self.urlReferenceIdMap.set(referenceKey, 1);\n self.references.push(reference);\n }\n } else {\n self.references.push(reference);\n }\n }\n return replacement;\n },\n references: [],\n urlReferenceIdMap: new Map<string, number>(),\n append: (): string => {\n const self = referenceLinkRule;\n let references = '';\n if (self.references && self.references.length) {\n references = '\\n\\n' + self.references.join('\\n') + '\\n\\n';\n self.references = [];\n self.urlReferenceIdMap = new Map();\n }\n return references;\n }\n};\n\ndefaultRules.referenceLink = referenceLinkRule;\n\ndefaultRules.emphasis = {\n filter: ['em', 'i'],\n replacement: (content: string, _node: Node, options: TurnishOptions): string => {\n content = content.trim();\n if (!content) { return ''; }\n return options.emDelimiter + content + options.emDelimiter;\n }\n};\n\ndefaultRules.strong = {\n filter: ['strong', 'b'],\n replacement: (content: string, _node: Node, options: TurnishOptions): string => {\n content = content.trim();\n if (!content) { return ''; }\n return options.strongDelimiter + content + options.strongDelimiter;\n }\n};\n\ndefaultRules.code = {\n filter: (node: Node): boolean => {\n const hasSiblings = node.previousSibling || node.nextSibling;\n const parent = node.parentNode as Element;\n const isCodeBlock = parent.nodeName === 'PRE' && !hasSiblings;\n return node.nodeName === 'CODE' && !isCodeBlock;\n },\n replacement: (content: string): string => {\n const trimmed = content.replace(/\\r?\\n|\\r/g, ' ');\n const extraSpace = /^`|^ .*?[^ ].* $|`$/.test(trimmed) ? ' ' : '';\n let delimiter = '`';\n const matches: string[] = trimmed.match(/`+/gm) || [];\n while (matches.includes(delimiter)) delimiter = delimiter + '`';\n return delimiter + extraSpace + trimmed + extraSpace + delimiter;\n }\n};\n\ndefaultRules.image = {\n filter: 'img',\n replacement: function (_content: string, node: Node): string {\n const altAttr = (node as Element).getAttribute('alt');\n const alt = altAttr ? sanitizedLinkTitle(altAttr) : '';\n const src = (node as Element).getAttribute('src') || '';\n const titleAttr = (node as Element).getAttribute('title');\n const title = titleAttr ? sanitizedLinkTitle(titleAttr) : '';\n const titlePart = title ? ' \"' + title + '\"' : '';\n return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : '';\n }\n};\n","/**\n * Manages a collection of rules used to convert HTML to Markdown\n */\nimport { ExtendedNode } from \"./node\";\nimport { TurnishOptions } from \"@/index\";\nimport { standardMarkdownElements } from \"./utilities\";\n\nexport type RuleFilterFunction = (node: ExtendedNode, options: TurnishOptions) => boolean;\nexport type RuleFilter = string | string[] | RuleFilterFunction;\n\ntype RuleReplacementFunction = (...args: any[]) => string;\n\nexport interface Rule {\n filter?: RuleFilter;\n replacement: RuleReplacementFunction | ((content: string, node: any, options: TurnishOptions, previousNode?: any) => string);\n references?: string[];\n /// Map of URL+title combinations to their reference IDs, used for link reference deduplication.\n /// When linkReferenceDeduplication is 'full', this tracks which URLs have already been assigned a reference number to avoid creating duplicate references.\n urlReferenceIdMap?: Map<string, number>;\n append?: (options: TurnishOptions) => string;\n}\n\nexport class Rules {\n options: TurnishOptions;\n private _keep: Rule[];\n private _remove: Rule[];\n blankRule: Rule;\n keepReplacement: RuleReplacementFunction;\n markdownIncludingHtmlReplacement: RuleReplacementFunction;\n defaultRule: Rule;\n array: Rule[];\n\n constructor(options: TurnishOptions) {\n this.options = options;\n this._keep = [];\n this._remove = [];\n\n this.blankRule = {\n replacement: options.blankReplacement\n };\n\n this.keepReplacement = options.keepReplacement;\n this.markdownIncludingHtmlReplacement = options.markdownIncludingHtmlReplacement;\n\n this.defaultRule = {\n replacement: options.defaultReplacement\n };\n\n this.array = [];\n for (const key in options.rules) {\n this.array.push(options.rules[key]);\n }\n }\n\n add(key: string, rule: Rule): void {\n this.array.unshift(rule);\n }\n\n keep(filter: RuleFilter): void {\n this._keep.unshift({\n filter: filter,\n replacement: this.keepReplacement\n });\n }\n\n remove(filter: RuleFilter): void {\n this._remove.unshift({\n filter: filter,\n replacement: function () {\n return '';\n }\n });\n }\n\n forNode(node: ExtendedNode): Rule {\n if (node.isBlank) {\n return this.blankRule;\n }\n if (this.options.htmlRetentionMode === 'preserveAll' && this.isUnsupportedElement(node)) {\n return {\n replacement: this.keepReplacement\n };\n }\n if (this.options.htmlRetentionMode === 'markdownIncludingHtml' && this.isUnsupportedElement(node)) {\n return {\n replacement: this.markdownIncludingHtmlReplacement\n };\n }\n\n let rule: Rule | undefined;\n if ((rule = findRule(this.array, node, this.options))) {\n return rule;\n }\n if ((rule = findRule(this._keep, node, this.options))) {\n return rule;\n }\n if ((rule = findRule(this._remove, node, this.options))) {\n return rule;\n }\n return this.defaultRule;\n }\n\n /// Check if an element is unsupported for Markdown conversion.\n private isUnsupportedElement(node: ExtendedNode): boolean {\n const nodeName = node.nodeName;\n\n if (nodeName === 'PRE' && node.firstChild && (node.firstChild as Element).nodeName === 'CODE') {\n const codeElem = node.firstChild as Element;\n if (codeElem.attributes && codeElem.attributes.length > 0) {\n for (let i = 0; i < codeElem.attributes.length; i++) {\n const attrName = codeElem.attributes[i].name.toLowerCase();\n if (attrName !== 'class') {\n return true;\n }\n }\n }\n }\n\n if (node.attributes && node.attributes.length > 0) {\n switch (nodeName) {\n case 'IMG':\n for (let i = 0; i < node.attributes.length; i++) {\n const attrName = node.attributes[i].name.toLowerCase();\n if (attrName !== 'src' && attrName !== 'alt' && attrName !== 'title') {\n return true;\n }\n }\n return false;\n case 'A':\n for (let i = 0; i < node.attributes.length; i++) {\n const attrName = node.attributes[i].name.toLowerCase();\n if (attrName !== 'href' && attrName !== 'title') {\n return true;\n }\n }\n return false;\n case 'CODE':\n const parent = node.parentNode as Element;\n if (parent && parent.nodeName === 'PRE') {\n for (let i = 0; i < node.attributes.length; i++) {\n const attrName = node.attributes[i].name.toLowerCase();\n if (attrName !== 'class') {\n return true;\n }\n }\n return false;\n }\n default:\n return true;\n }\n }\n // Elements that are not standard HTML elements are unsupported\n if (standardMarkdownElements.indexOf(nodeName) === -1) {\n return true;\n }\n return false;\n }\n\n forEach(fn: (rule: Rule, index: number) => void): void {\n for (let i = 0; i < this.array.length; i++) {\n fn(this.array[i], i);\n }\n }\n}\n\nfunction findRule(rules: Rule[], node: ExtendedNode, options: TurnishOptions): Rule | undefined {\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n if (filterValue(rule, node, options)) return rule;\n }\n return undefined;\n}\n\nfunction filterValue(rule: Rule, node: ExtendedNode, options: TurnishOptions): boolean {\n const filter = rule.filter;\n if (typeof filter === 'string') {\n if (filter === node.nodeName.toLowerCase()) {\n return true;\n }\n } else if (Array.isArray(filter)) {\n if (filter.indexOf(node.nodeName.toLowerCase()) > -1) {\n return true;\n }\n } else if (typeof filter === 'function') {\n if (filter(node, options)) {\n return true;\n }\n } else {\n throw new TypeError('`filter` needs to be a string, array, or function');\n }\n return false;\n}\n","/**\n * The collapseWhitespace function is adapted from collapse-whitespace\n * by Luc Thevenard.\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Luc Thevenard <lucthevenard@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport { NodeTypes } from \"./node\";\n\n/**\n * collapseWhitespace(options) removes extraneous whitespace from an the given element.\n *\n * @param {Object} options\n */\ninterface CollapseWhitespaceOptions {\n element: Node;\n isBlock: (node: Node) => boolean;\n isVoid: (node: Node) => boolean;\n isPre?: (node: Node) => boolean;\n}\n\nfunction collapseWhitespace(options: CollapseWhitespaceOptions): void {\n const element = options.element\n const isBlock = options.isBlock\n const isVoid = options.isVoid\n const isPre = options.isPre || function (node: Node): boolean {\n return node.nodeName === 'PRE';\n };\n\n if (!element.firstChild || isPre(element)) return\n\n let prevText: Text | null = null;\n let keepLeadingWs = false\n\n let prev: Node | null = null;\n let node: Node = next(prev, element, isPre);\n\n while (node !== element) {\n if (node.nodeType === NodeTypes.Text || node.nodeType === NodeTypes.CDATASection) {\n const textNode = node as Text;\n let text = textNode.data.replace(/[ \\r\\n\\t]+/g, ' ');\n\n if ((!prevText || / $/.test(prevText.data)) &&\n !keepLeadingWs && text[0] === ' ') {\n text = text.substr(1);\n }\n\n // `text` might be empty at this point.\n if (!text) {\n node = remove(node);\n continue;\n }\n\n textNode.data = text;\n\n prevText = textNode;\n } else if (node.nodeType === NodeTypes.Element) {\n if (isBlock(node) || node.nodeName === 'BR') {\n if (prevText) {\n prevText.data = prevText.data.replace(/ $/, '');\n }\n\n prevText = null;\n keepLeadingWs = false;\n } else if (isVoid(node) || isPre(node)) {\n // Avoid trimming space around non-block, non-BR void elements and inline PRE.\n prevText = null;\n keepLeadingWs = true;\n } else if (prevText) {\n // Drop protection if set previously.\n keepLeadingWs = false;\n }\n } else {\n node = remove(node);\n continue;\n }\n\n const nextNode = next(prev, node, isPre);\n prev = node;\n node = nextNode;\n }\n\n if (prevText) {\n prevText.data = prevText.data.replace(/ $/, '');\n if (!prevText.data) {\n remove(prevText);\n }\n }\n}\n\n/**\n * remove(node) removes the given node from the DOM and returns the\n * next node in the sequence.\n *\n * @param {Node} node\n * @return {Node} node\n */\nfunction remove(node: Node): Node {\n const nextNode: Node | null = node.nextSibling ?? node.parentNode;\n if (node.parentNode) {\n node.parentNode.removeChild(node);\n }\n return nextNode as Node;\n}\n\n/**\n * next(prev, current, isPre) returns the next node in the sequence, given the\n * current and previous nodes.\n *\n * @param {Node} prev\n * @param {Node} current\n * @param {Function} isPre\n * @return {Node}\n */\nfunction next(prev: Node | null, current: Node, isPre: (node: Node) => boolean): Node {\n if ((prev && prev.parentNode === current) || isPre(current)) {\n const nextNode: Node | null = current.nextSibling ?? current.parentNode;\n return nextNode as Node;\n }\n const nextNode: Node | null = current.firstChild ?? current.nextSibling ?? current.parentNode;\n return nextNode as Node;\n}\n\nexport default collapseWhitespace\n","/*\n * Set up window for Node.js\n */\n\nconst root: typeof globalThis = typeof window !== 'undefined' ? window : (typeof globalThis !== 'undefined' ? globalThis : {} as any)\n\n/*\n * Parsing HTML strings\n */\n\nfunction canParseHTMLNatively() {\n const Parser = typeof root.DOMParser !== 'undefined' ? root.DOMParser : undefined;\n let canParse = false;\n if (!Parser) return false;\n // Adapted from https://gist.github.com/1129031\n // Firefox/Opera/IE throw errors on unsupported types\n try {\n // WebKit returns null on unsupported types\n if (new Parser().parseFromString('', 'text/html')) {\n canParse = true;\n }\n } catch (e) { }\n return canParse;\n}\n\nexport class HTMLParser {\n // This will be assigned per environment below\n parseFromString(_input: string, _type?: string): Document {\n throw new Error('Not implemented')\n }\n}\n\nfunction createParser(): HTMLParser {\n const isBrowser =\n typeof window !== 'undefined' &&\n typeof document !== 'undefined' &&\n (typeof process === 'undefined' || (process as any).browser === true)\n\n if (typeof window !== 'undefined') {\n // Browser environment: use DOM API\n class HTMLParserBrowser extends HTMLParser {\n parseFromString(input: string, _type?: string): Document {\n const doc = document.implementation.createHTMLDocument('')\n doc.open()\n doc.write(input)\n doc.close()\n return doc\n }\n }\n return new HTMLParserBrowser()\n } else {\n const domino = require('@mixmark-io/domino') as {\n createDocument: (html: string) => Document\n }\n class HTMLParserNode extends HTMLParser {\n parseFromString(input: string, _type?: string): Document {\n return domino.createDocument(input);\n }\n }\n return new HTMLParserNode()\n }\n}\n\nexport const createHTMLParser = (): HTMLParser =>\n canParseHTMLNatively()\n ? new root.DOMParser()\n : createParser()\n","import collapseWhitespace from '@/collapse-whitespace'\nimport { createHTMLParser, HTMLParser } from '@/html-parser'\nimport { isBlock, isVoid } from '@/utilities'\n\ninterface RootNodeOptions {\n preformattedCode?: boolean\n}\n\nexport default function RootNode(\n input: string | Node,\n { preformattedCode }: RootNodeOptions\n): Element {\n let root: Element\n if (typeof input === 'string') {\n const doc = htmlParser().parseFromString(\n // DOM parsers arrange elements in the <head> and <body>.\n // Wrapping in a custom element ensures elements are reliably arranged in\n // a single element.\n '<x-turnish id=\"turnish-root\">' + input + '</x-turnish>',\n 'text/html'\n )\n root = doc.getElementById('turnish-root') as Element\n } else {\n root = input.cloneNode(true) as Element\n }\n collapseWhitespace({\n element: root,\n isBlock: isBlock,\n isVoid: isVoid,\n isPre: preformattedCode ? isPreOrCode : undefined\n })\n\n return root\n}\n\nlet _htmlParser: HTMLParser | undefined\nfunction htmlParser(): HTMLParser {\n return (_htmlParser ??= createHTMLParser())\n}\n\nfunction isPreOrCode(node: Node): boolean {\n return node.nodeName === 'PRE' || node.nodeName === 'CODE';\n}\n","import { defaultRules } from '@/default-rules'\nimport { Rules, Rule, RuleFilter } from '@/rules'\nimport { trimLeadingNewlines, trimTrailingNewlines } from '@/utilities'\nimport RootNode from '@/root-node'\nimport { ExtendedNode, NodeTypes } from '@/node';\nconst reduce = Array.prototype.reduce\n\ntype EscapeRule = [RegExp, string];\n\nconst escapes: EscapeRule[] = [\n [/\\\\/g, '\\\\\\\\'],\n [/\\*/g, '\\\\*'],\n [/_/g, '\\\\_'],\n [/^-/g, '\\\\-'],\n [/^\\+ /g, '\\\\+ '],\n [/^(=+)/g, '\\\\$1'],\n [/^(#{1,6}) /g, '\\\\$1 '],\n [/`/g, '\\\\`'],\n [/^~~~/g, '\\\\~~~'],\n [/\\[/g, '\\\\['],\n [/\\]/g, '\\\\]'],\n [/<([^>]*)>/g, '\\\\<$1\\\\>'],\n [/^>/g, '\\\\>'],\n [/^(\\d+)\\. /g, '$1\\\\. ']\n];\n\ntype Plugin = (service: Turnish) => void;\n\nexport interface TurnishOptions {\n rules?: { [key: string]: Rule };\n headingStyle?: 'setext' | 'atx';\n hr?: string;\n bulletListMarker?: '*' | '-' | '+';\n codeBlockStyle?: 'indented' | 'fenced';\n fence?: string;\n emDelimiter?: '_' | '*';\n strongDelimiter?: '**' | '__';\n linkStyle?: 'inlined' | 'referenced';\n linkReferenceStyle?: 'full' | 'collapsed' | 'shortcut';\n linkReferenceDeduplication?: 'none' | 'full';\n br?: string;\n preformattedCode?: boolean;\n htmlRetentionMode?: 'standard' | 'preserveAll' | 'markdownIncludingHtml';\n blankReplacement: (content: string, node: ExtendedNode) => string;\n keepReplacement: (content: string, node: ExtendedNode) => string;\n markdownIncludingHtmlReplacement: (content: string, node: ExtendedNode) => string;\n defaultReplacement: (content: string, node: ExtendedNode) => string;\n [key: string]: any;\n}\n\n\nconst defaultOptions: TurnishOptions = {\n rules: defaultRules,\n headingStyle: 'atx',\n hr: '---',\n bulletListMarker: '-',\n codeBlockStyle: 'fenced',\n fence: '```',\n emDelimiter: '*',\n strongDelimiter: '**',\n linkStyle: 'inlined',\n linkReferenceStyle: 'full',\n linkReferenceDeduplication: 'full',\n br: ' ',\n preformattedCode: false,\n htmlRetentionMode: 'standard',\n blankReplacement: (content: string, node: ExtendedNode): string => {\n return node.isBlock ? '\\n\\n' : '';\n },\n keepReplacement: (content: string, node: ExtendedNode): string => {\n return node.isBlock ? '\\n\\n' + node.outerHTML + '\\n\\n' : node.outerHTML;\n },\n markdownIncludingHtmlReplacement: (content: string, node: ExtendedNode): string => {\n const tagName = node.nodeName.toLowerCase();\n\n let attributes = '';\n if (node.attributes && node.attributes.length > 0) {\n const attrs: string[] = [];\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n attrs.push(`${attr.name}=\"${attr.value}\"`);\n }\n attributes = ' ' + attrs.join(' ');\n }\n\n attributes += ' markdown=\"1\"';\n\n const openTag = `<${tagName}${attributes}>`;\n const closeTag = `</${tagName}>`;\n\n const trimmedContent = content.trim();\n const html = openTag + '\\n' + trimmedContent + '\\n' + closeTag;\n\n return node.isBlock ? '\\n\\n' + html + '\\n\\n' : html;\n },\n defaultReplacement: function (content: string, node: ExtendedNode): string {\n return node.isBlock ? '\\n\\n' + content + '\\n\\n' : content;\n }\n};\n\nexport default class Turnish {\n options: TurnishOptions;\n rules: Rules;\n\n constructor(options?: Partial<TurnishOptions>) {\n this.options = Object.assign({}, defaultOptions, options);\n this.rules = new Rules(this.options);\n }\n\n /**\n * The entry point for converting a string or DOM node to Markdown\n * @public\n * @param {InputType} input The string or DOM node to convert\n * @returns A Markdown representation of the input\n * @type string\n */\n render(input: InputType): string {\n if (!canConvert(input)) {\n throw new TypeError(\n input + ' is not a string, or an element/document/fragment node.'\n );\n }\n if (input === '') {\n return '';\n }\n const output = this.process(RootNode(input, this.options));\n return this.postProcess(output);\n }\n\n /**\n * Add one or more plugins\n * @public\n * @param {Plugin|Plugin[]} plugin The plugin or array of plugins to add\n * @returns The Turnish instance for chaining\n * @type Object\n */\n use(plugin: Plugin | Plugin[]): Turnish {\n if (Array.isArray(plugin)) {\n for (let i = 0; i < plugin.length; i++) this.use(plugin[i]);\n } else if (typeof plugin === 'function') {\n plugin(this);\n } else {\n throw new TypeError('plugin must be a Function or an Array of Functions');\n }\n return this;\n }\n\n /**\n * Adds a rule\n * @public\n * @param {string} key The unique key of the rule\n * @param {Object} rule The rule\n * @returns The Turnish instance for chaining\n * @type Object\n */\n addRule(key: string, rule: Rule): Turnish {\n this.rules.add(key, rule);\n return this;\n }\n\n /**\n * Keep a node (as HTML) that matches the filter\n * @public\n * @param {RuleFilter} filter The unique key of the rule\n * @returns The Turnish instance for chaining\n * @type Object\n */\n keep(filter: RuleFilter): Turnish {\n this.rules.keep(filter);\n return this;\n }\n\n /**\n * Remove a node that matches the filter\n * @public\n * @param {string|Array|Function} filter The unique key of the rule\n * @returns The Turnish instance for chaining\n * @type Object\n */\n remove(filter: RuleFilter): Turnish {\n this.rules.remove(filter);\n return this;\n }\n\n /**\n * Escapes Markdown syntax\n * @public\n * @param {string} string The string to escape\n * @returns A string with Markdown syntax escaped\n * @type string\n */\n escape(string: string): string {\n return escapes.reduce(function (accumulator: string, escape: EscapeRule) {\n return accumulator.replace(escape[0], escape[1]);\n }, string);\n }\n\n\n /**\n * Reduces a DOM node down to its Markdown string equivalent\n * @private\n * @param {HTMLElement} parentNode The node to convert\n * @returns A Markdown representation of the node\n * @type string\n */\n process(this: Turnish, parentNode: Node): string {\n return Array.from(parentNode.childNodes).reduce((output, node) => {\n const extended = ExtendedNode(node, this.options);\n let replacement = '';\n if (extended.nodeType === NodeTypes.Text) {\n const value = extended.nodeValue ?? ''; // ensure a string\n replacement = extended.isCode ? value : this.escape(value);\n } else if (extended.nodeType === NodeTypes.Element) {\n replacement = this.replacementForNode(extended);\n }\n return join(output, replacement);\n }, '');\n }\n\n /**\n * Appends strings as each rule requires and trims the output\n * @private\n * @param {string} output The conversion output\n * @returns A trimmed version of the ouput\n * @type string\n */\n postProcess(output: string): string {\n for (const rule of this.rules.array) {\n if (rule.append) {\n output = join(output, rule.append(this.options))\n }\n }\n return output\n .replace(/^[\\t\\r\\n]+/, '')\n .replace(/[\\t\\r\\n\\s]+$/, '')\n }\n\n\n /**\n * Converts an element node to its Markdown equivalent\n * @private\n * @param {ExtendedNode} node The node to convert\n * @returns A Markdown representation of the node\n * @type string\n */\n replacementForNode(node: ExtendedNode) {\n const rule = this.rules.forNode(node)\n let content = this.process(node)\n const whitespace = node.flankingWhitespace\n if (whitespace.leading || whitespace.trailing) {\n content = content.trim()\n }\n return (\n whitespace.leading +\n rule.replacement(content, node, this.options) +\n whitespace.trailing\n )\n }\n}\n\n/**\n * Joins replacement to the current output with appropriate number of new lines\n * @private\n * @param {string} output The current conversion output\n * @param {string} replacement The string to append to the output\n * @returns Joined output\n * @type string\n */\nfunction join(output: string, replacement: string): string {\n const s1 = trimTrailingNewlines(output)\n const s2 = trimLeadingNewlines(replacement)\n const nls = Math.max(output.length - s1.length, replacement.length - s2.length)\n const separator = '\\n\\n'.substring(0, nls)\n\n return s1 + separator + s2\n}\n\n/**\n * Determines whether an input can be converted\n * @private\n * @param {string|HTMLElement} input Describe this parameter\n * @returns Describe what it returns\n * @type string|Object|Array|Boolean|Number\n */\ntype InputType = string | HTMLElement | Document | DocumentFragment;\nfunction canConvert(input: any): input is InputType {\n return (\n input != null && (\n typeof input === 'string' ||\n (input.nodeType && (\n input.nodeType === 1 || input.nodeType === 9 || input.nodeType === 11\n ))\n )\n );\n}\n"],"names":["ExtendedNode","node","options","extended","isBlock","isBlank","flankingWhitespace","isVoid","isMeaningfulWhenBlank","hasVoid","hasMeaningfulWhenBlank","extendedNode","edges","edgeWhitespace","isFlankedByWhitespace","string","m","side","sibling","regExp","isFlanked","NodeTypes","repeat","character","count","trimLeadingNewlines","trimTrailingNewlines","indexEnd","trimNewlines","blockElements","is","voidElements","has","meaningfulWhenBlankElements","standardMarkdownElements","tagNames","tagName","sanitizeWhitespace","sanitizedLinkContent","content","sanitizedLinkTitle","defaultRules","_content","_node","hLevel","underline","parent","prefix","start","index","isParagraph","codeElem","language","code","fenceChar","fenceSize","fenceInCodeRegex","match","fence","sanitizedContent","href","title","titleAttr","referenceLinkRule","self","referenceKey","replacement","reference","id","existingKey","references","hasSiblings","isCodeBlock","trimmed","extraSpace","delimiter","matches","altAttr","alt","src","titlePart","Rules","key","rule","filter","findRule","nodeName","attrName","fn","i","rules","filterValue","collapseWhitespace","element","isPre","prevText","keepLeadingWs","prev","next","textNode","text","remove","nextNode","current","root","canParseHTMLNatively","Parser","canParse","HTMLParser","_input","_type","createParser","HTMLParserBrowser","input","doc","domino","HTMLParserNode","createHTMLParser","RootNode","preformattedCode","htmlParser","isPreOrCode","_htmlParser","escapes","defaultOptions","attributes","attrs","attr","openTag","closeTag","trimmedContent","html","Turnish","canConvert","output","plugin","accumulator","escape","parentNode","value","join","whitespace","s1","s2","nls","separator"],"mappings":"AAyBO,SAASA,EAAaC,GAAYC,GAAgC;AACvE,QAAMC,IAAWF;AACjB,SAAAE,EAAS,UAAUC,EAAQD,CAAQ,GACnCA,EAAS,SAASA,EAAS,aAAa,UAAWA,EAAS,YAA6B,QACzFA,EAAS,UAAUE,EAAQF,CAAQ,GACnCA,EAAS,qBAAqBG,EAAmBH,GAAUD,CAAO,GAC3DC;AACT;AAEA,SAASE,EAAQJ,GAA6B;AAC5C,SACE,CAACM,EAAON,CAAI,KACZ,CAACO,EAAsBP,CAAI,KAC3B,SAAS,KAAKA,EAAK,eAAe,EAAE,KACpC,CAACQ,EAAQR,CAAI,KACb,CAACS,EAAuBT,CAAI;AAEhC;AAEA,SAASK,EAAmBL,GAAoBC,GAAsC;AACpF,QAAMS,IAAeV;AAErB,MAAIU,EAAa,WAAYT,EAAQ,oBAAoBS,EAAa;AACpE,WAAO,EAAE,SAAS,IAAI,UAAU,GAAA;AAGlC,QAAMC,IAAQC,EAAeZ,EAAK,eAAe,EAAE;AAGnD,SAAIW,EAAM,gBAAgBE,EAAsB,QAAQb,GAAMC,CAAO,MACnEU,EAAM,UAAUA,EAAM,kBAIpBA,EAAM,iBAAiBE,EAAsB,SAASb,GAAMC,CAAO,MACrEU,EAAM,WAAWA,EAAM,mBAGlB,EAAE,SAASA,EAAM,SAAS,UAAUA,EAAM,SAAA;AACnD;AAEA,SAASC,EAAeE,GAAgC;AACtD,QAAMC,IAAID,EAAO,MAAM,+DAA+D;AAEtF,SAAKC,IAWE;AAAA,IACL,SAASA,EAAE,CAAC;AAAA;AAAA,IACZ,cAAcA,EAAE,CAAC;AAAA,IACjB,iBAAiBA,EAAE,CAAC;AAAA,IACpB,UAAUA,EAAE,CAAC;AAAA;AAAA,IACb,kBAAkBA,EAAE,CAAC;AAAA,IACrB,eAAeA,EAAE,CAAC;AAAA,EAAA,IAhBX;AAAA,IACL,SAAS;AAAA,IACT,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,eAAe;AAAA,EAAA;AAYrB;AAEA,SAASF,EAAsBG,GAAwBhB,GAAeC,GAA2B;AAC/F,MAAIgB,GACAC,GACAC;AAEJ,SAAIH,MAAS,UACXC,IAAUjB,EAAK,wBACfkB,IAAS,SAETD,IAAUjB,EAAK,oBACfkB,IAAS,OAGPD,MACEA,EAAQ,aAAa,IACvBE,IAAYD,EAAO,KAAKD,EAAQ,aAAa,EAAE,IACtChB,EAAQ,oBAAoBgB,EAAQ,aAAa,SAC1DE,IAAY,KACHF,EAAQ,aAAa,KAAK,CAACd,EAAQc,CAAO,MACnDE,IAAYD,EAAO,KAAKD,EAAQ,eAAe,EAAE,KAI9CE,KAAa;AACtB;AAEO,MAAMC,IAAY;AAAA,EACvB,SAAS;AAAA,EACT,MAAM;AAAA,EACN,cAAc;AAEhB;ACvHO,SAASC,EAAOC,GAAmBC,GAAe;AACvD,SAAO,MAAMA,IAAQ,CAAC,EAAE,KAAKD,CAAS;AACxC;AAEO,SAASE,EAAoBV,GAAgB;AAClD,SAAOA,EAAO,QAAQ,QAAQ,EAAE;AAClC;AAEO,SAASW,EAAqBX,GAAgB;AAEnD,MAAIY,IAAWZ,EAAO;AACtB,SAAOY,IAAW,KAAKZ,EAAOY,IAAW,CAAC,MAAM;AAAA,IAAM,CAAAA;AACtD,SAAOZ,EAAO,UAAU,GAAGY,CAAQ;AACrC;AAEO,SAASC,EAAab,GAAgB;AAC3C,SAAOW,EAAqBD,EAAoBV,CAAM,CAAC;AACzD;AAEO,MAAMc,IAAgB;AAAA,EAC3B;AAAA,EAAW;AAAA,EAAW;AAAA,EAAS;AAAA,EAAS;AAAA,EAAc;AAAA,EAAQ;AAAA,EAC9D;AAAA,EAAU;AAAA,EAAM;AAAA,EAAO;AAAA,EAAO;AAAA,EAAM;AAAA,EAAM;AAAA,EAAY;AAAA,EAAc;AAAA,EACpE;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAY;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAU;AAAA,EAAM;AAAA,EAAQ;AAAA,EAAW;AAAA,EAAM;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAO;AAAA,EAChE;AAAA,EAAY;AAAA,EAAM;AAAA,EAAU;AAAA,EAAK;AAAA,EAAO;AAAA,EAAW;AAAA,EAAS;AAAA,EAAS;AAAA,EACrE;AAAA,EAAS;AAAA,EAAM;AAAA,EAAS;AAAA,EAAM;AAChC;AAEO,SAASzB,EAAQH,GAAY;AAClC,SAAO6B,EAAG7B,GAAM4B,CAAa;AAC/B;AAEO,MAAME,IAAe;AAAA,EAC1B;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAM;AAAA,EAAO;AAAA,EAAW;AAAA,EAAS;AAAA,EAAM;AAAA,EAAO;AAAA,EAC9D;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAS;AACxD;AAEO,SAASxB,EAAON,GAAY;AACjC,SAAO6B,EAAG7B,GAAM8B,CAAY;AAC9B;AAEO,SAAStB,EAAQR,GAAY;AAClC,SAAO+B,EAAI/B,GAAM8B,CAAY;AAC/B;AAEA,MAAME,IAA8B;AAAA,EAClC;AAAA,EAAK;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAM;AAAA,EAAM;AAAA,EAAU;AAAA,EAC/D;AAAA,EAAS;AACX,GAEaC,IAA2B;AAAA,EACtC;AAAA,EAAK;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC/C;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAM;AAAA,EAAK;AAAA,EAAM;AAAA,EAAK;AAAA,EACvD;AAAA,EAAK;AAAA,EAAO;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAM;AAAA,EAAM;AACpE;AAEO,SAAS1B,EAAsBP,GAAY;AAChD,SAAO6B,EAAG7B,GAAMgC,CAA2B;AAC7C;AAEO,SAASvB,EAAuBT,GAAY;AACjD,SAAO+B,EAAI/B,GAAMgC,CAA2B;AAC9C;AAEA,SAASH,EAAG7B,GAAYkC,GAAoB;AAC1C,SAAOA,EAAS,QAAQlC,EAAK,QAAQ,KAAK;AAC5C;AAEA,SAAS+B,EAAI/B,GAAYkC,GAAoB;AAC3C,SACEA,EAAS,KAAK,SAAUC,GAAS;AAC/B,WAAInC,EAAK,aAAaoB,EAAU,UACvB,KAEDpB,EAAiB,qBAAqBmC,CAAO,EAAE;AAAA,EACzD,CAAC;AAEL;AAEO,SAASC,EAAmBtB,GAAwB;AACzD,SAAOA,IAASA,EAAO,QAAQ,cAAc;AAAA,CAAI,IAAI;AACvD;AAEO,SAASuB,EAAqBC,GAAyB;AAE5D,SADkBF,EAAmBE,CAAO,EAEzC,QAAQ,cAAc,GAAG,EACzB,QAAQ,UAAU,GAAG,EACrB,QAAQ,WAAW,MAAM,EACzB,KAAA;AACL;AAEO,SAASC,EAAmBD,GAAyB;AAE1D,SADkBF,EAAmBE,CAAO,EAEzC,QAAQ,cAAc,GAAG;AAC9B;AC5FO,MAAME,IAAwC,CAAA;AAErDA,EAAa,YAAY;AAAA,EACvB,QAAQ;AAAA,EACR,aAAa,SAAUF,GAAyB;AAC9C,WAAO;AAAA;AAAA,IAASA,IAAU;AAAA;AAAA;AAAA,EAC5B;AACF;AAEAE,EAAa,YAAY;AAAA,EACvB,QAAQ;AAAA,EACR,aAAa,SAAUC,GAAkBC,GAAazC,GAAiC;AACrF,WAAOA,EAAQ,KAAK;AAAA;AAAA,EACtB;AACF;AAEAuC,EAAa,UAAU;AAAA,EACrB,QAAQ,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAAA,EAC3C,aAAa,SAAUF,GAAiBtC,GAAYC,GAAiC;AACnF,UAAM0C,IAAS,OAAO3C,EAAK,SAAS,OAAO,CAAC,CAAC;AAC7C,QAAIC,EAAQ,iBAAiB,YAAY0C,IAAS,GAAG;AACnD,YAAMC,IAAYvB,EAAQsB,MAAW,IAAI,MAAM,KAAML,EAAQ,MAAM;AACnE,aACE;AAAA;AAAA,IAASA,IAAU;AAAA,IAAOM,IAAY;AAAA;AAAA;AAAA,IAE1C;AACE,aAAO;AAAA;AAAA,IAASvB,EAAO,KAAKsB,CAAM,IAAI,MAAML,IAAU;AAAA;AAAA;AAAA,EAE1D;AACF;AAEAE,EAAa,aAAa;AAAA,EACxB,QAAQ;AAAA,EACR,aAAa,SAAUF,GAAyB;AAC9C,WAAAA,IAAUX,EAAaW,CAAO,EAAE,QAAQ,OAAO,IAAI,GAC5C;AAAA;AAAA,IAASA,IAAU;AAAA;AAAA;AAAA,EAC5B;AACF;AAEAE,EAAa,OAAO;AAAA,EAClB,QAAQ,CAAC,MAAM,IAAI;AAAA,EACnB,aAAa,SAAUF,GAAiBtC,GAAoB;AAC1D,UAAM6C,IAAS7C,EAAK;AACpB,WAAI6C,EAAO,aAAa,QAAQA,EAAO,qBAAqB7C,IACnD;AAAA,IAAOsC,IAEP;AAAA;AAAA,IAASA,IAAU;AAAA;AAAA;AAAA,EAE9B;AACF;AAEAE,EAAa,WAAW;AAAA,EACtB,QAAQ;AAAA,EACR,aAAa,SAAUF,GAAiBtC,GAAYC,GAAiC;AACnF,QAAI6C,IAAS7C,EAAQ,mBAAmB;AACxC,UAAM4C,IAAS7C,EAAK;AACpB,QAAI6C,EAAO,aAAa,MAAM;AAC5B,YAAME,IAAQF,EAAO,aAAa,OAAO,GACnCG,IAAQ,MAAM,UAAU,QAAQ,KAAKH,EAAO,UAAU7C,CAAI;AAChE,MAAA8C,KAAUC,IAAQ,OAAOA,CAAK,IAAIC,IAAQA,IAAQ,KAAK;AAAA,IACzD;AACA,UAAMC,IAAc,MAAM,KAAKX,CAAO;AACtC,WAAAA,IAAUX,EAAaW,CAAO,KAAKW,IAAc;AAAA,IAAO,KACxDX,IAAUA,EAAQ,QAAQ,QAAQ;AAAA,IAAO,IAAI,OAAOQ,EAAO,MAAM,CAAC,GAEhEA,IAASR,KAAWtC,EAAK,cAAc;AAAA,IAAO;AAAA,EAElD;AACF;AAEAwC,EAAa,oBAAoB;AAAA,EAC/B,QAAQ,SAAUxC,GAAYC,GAAkC;AAC9D,WAAO,CAAC,EACNA,KACAA,EAAQ,mBAAmB,cAC3BD,EAAK,aAAa,SAClBA,EAAK,cACJA,EAAK,WAAuB,aAAa;AAAA,EAE9C;AAAA,EACA,aAAa,SAAUyC,GAAkBzC,GAAoB;AAC3D,WAAI,CAACA,KAAQ,CAACA,EAAK,aAAmB,KAEpC;AAAA;AAAA,QACCA,EAAK,WAAuB,YAAa,QAAQ,OAAO;AAAA,KAAQ,IACjE;AAAA;AAAA;AAAA,EAEJ;AACF;AAEAwC,EAAa,kBAAkB;AAAA,EAC7B,QAAQ,SAAUxC,GAAYC,GAAkC;AAC9D,WAAO,CAAC,EACNA,KACAA,EAAQ,mBAAmB,YAC3BD,EAAK,aAAa,SAClBA,EAAK,cACJA,EAAK,WAAuB,aAAa;AAAA,EAE9C;AAAA,EACA,aAAa,SAAUyC,GAAkBzC,GAAYC,GAAiC;AACpF,QAAI,CAACD,EAAK;AACR,aAAO;AAET,UAAMkD,IAAWlD,EAAK,YAEhBmD,MADYD,EAAS,aAAa,OAAO,KAAK,IACxB,MAAM,gBAAgB,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,GAC9DE,IAAOF,EAAS,eAAe,IAC/BG,IAAYpD,EAAQ,OAAO,OAAO,CAAC,KAAK;AAC9C,QAAIqD,IAAY;AAChB,UAAMC,IAAmB,IAAI,OAAO,MAAMF,IAAY,QAAQ,IAAI;AAClE,QAAIG;AACJ,WAAQA,IAAQD,EAAiB,KAAKH,CAAI;AACxC,MAAII,EAAM,CAAC,EAAE,UAAUF,MACrBA,IAAYE,EAAM,CAAC,EAAE,SAAS;AAGlC,UAAMC,IAAQpC,EAAOgC,GAAWC,CAAS;AACzC,WACE;AAAA;AAAA,IAASG,IAAQN,IAAW;AAAA,IAC5BC,EAAK,QAAQ,OAAO,EAAE,IACtB;AAAA,IAAOK,IAAQ;AAAA;AAAA;AAAA,EAEnB;AACF;AAEAjB,EAAa,iBAAiB;AAAA,EAC5B,QAAQ;AAAA,EACR,aAAa,SAAUC,GAAkBC,GAAazC,GAAiC;AACrF,WAAO;AAAA;AAAA,IAASA,EAAQ,KAAK;AAAA;AAAA;AAAA,EAC/B;AACF;AAEAuC,EAAa,aAAa;AAAA,EACxB,QAAQ,SAAUxC,GAAYC,GAAkC;AAC9D,WAAO,CAAC,EACNA,GAAS,cAAc,aACvBD,EAAK,aAAa,OACjBA,EAAiB,aAAa,MAAM;AAAA,EAEzC;AAAA,EACA,aAAa,SAAUsC,GAAiBtC,GAAoB;AAC1D,UAAM0D,IAAmBrB,EAAqBC,CAAO;AACrD,QAAIqB,IAAQ3D,EACT,aAAa,MAAM,GAClB,QAAQ,WAAW,MAAM,GACzB4D;AACJ,UAAMC,IAAa7D,EAAiB,aAAa,OAAO;AACxD,WAAI6D,IAEFD,IAAQ,OADerB,EAAmBsB,CAAS,EACrB,QAAQ,MAAM,KAAK,IAAI,MAErDD,IAAQ,IAEH,MAAMF,IAAmB,OAAOC,IAAOC,IAAQ;AAAA,EACxD;AACF;AAEA,MAAME,IAA2E;AAAA,EAC/E,QAAQ,SAAU9D,GAAYC,GAAkC;AAC9D,WAAO,CAAC,EACNA,KACAA,EAAQ,cAAc,gBACtBD,EAAK,aAAa,OACjBA,EAAiB,aAAa,MAAM;AAAA,EAEzC;AAAA,EACA,aAAa,SAAUsC,GAAiBtC,GAAYC,GAAiC;AACnF,UAAM8D,IAAOD,GAEPH,IAAQ3D,EAAiB,aAAa,MAAM;AAClD,QAAI4D;AACJ,UAAMC,IAAa7D,EAAiB,aAAa,OAAO;AACxD,IAAI6D,IAEFD,IAAQ,OADerB,EAAmBsB,CAAS,IACnB,MAEhCD,IAAQ;AAEV,UAAMI,IAAeL,IAAOC;AAE5B,QAAIK,GACAC;AACJ,YAAQjE,EAAQ,oBAAA;AAAA,MACd,KAAK;AACH,QAAAgE,IAAc,MAAM3B,IAAU,OAC9B4B,IAAY,MAAM5B,IAAU,QAAQ0B;AACpC;AAAA,MACF,KAAK;AACH,QAAAC,IAAc,MAAM3B,IAAU,KAC9B4B,IAAY,MAAM5B,IAAU,QAAQ0B;AACpC;AAAA,MACF,SAAS;AACP,YAAIG;AACJ,cAAMC,IAAcL,EAAK,kBAAkB,IAAIC,CAAY;AAC3D,QAAI/D,EAAQ,+BAA+B,UAAUmE,KACnDD,IAAKC,GACLF,IAAY,MAAMC,IAAK,QAAQR,IAAOC,MAEtCO,IAAKJ,EAAK,WAAW,SAAS,GAC9BA,EAAK,kBAAkB,IAAIC,GAAcG,CAAE,GAC3CD,IAAY,MAAMC,IAAK,QAAQR,IAAOC,GACtCG,EAAK,WAAW,KAAKG,CAAS,IAEhCD,IAAc,MAAM3B,IAAU,OAAO6B,IAAK;AAC1C;AAAA,MACF;AAAA,IAAA;AAGF,WAAIlE,EAAQ,uBAAuB,WAE7BA,EAAQ,+BAA+B,SACpC8D,EAAK,kBAAkB,IAAIC,CAAY,MAC1CD,EAAK,kBAAkB,IAAIC,GAAc,CAAC,GAC1CD,EAAK,WAAW,KAAKG,CAAS,KAGhCH,EAAK,WAAW,KAAKG,CAAS,IAG3BD;AAAA,EACT;AAAA,EACA,YAAY,CAAA;AAAA,EACZ,uCAAuB,IAAA;AAAA,EACvB,QAAQ,MAAc;AACpB,UAAMF,IAAOD;AACb,QAAIO,IAAa;AACjB,WAAIN,EAAK,cAAcA,EAAK,WAAW,WACrCM,IAAa;AAAA;AAAA,IAASN,EAAK,WAAW,KAAK;AAAA,CAAI,IAAI;AAAA;AAAA,GACnDA,EAAK,aAAa,CAAA,GAClBA,EAAK,wCAAwB,IAAA,IAExBM;AAAA,EACT;AACF;AAEA7B,EAAa,gBAAgBsB;AAE7BtB,EAAa,WAAW;AAAA,EACtB,QAAQ,CAAC,MAAM,GAAG;AAAA,EAClB,aAAa,CAACF,GAAiBI,GAAazC,OAC1CqC,IAAUA,EAAQ,KAAA,GACbA,IACErC,EAAQ,cAAcqC,IAAUrC,EAAQ,cADxB;AAG3B;AAEAuC,EAAa,SAAS;AAAA,EACpB,QAAQ,CAAC,UAAU,GAAG;AAAA,EACtB,aAAa,CAACF,GAAiBI,GAAazC,OAC1CqC,IAAUA,EAAQ,KAAA,GACbA,IACErC,EAAQ,kBAAkBqC,IAAUrC,EAAQ,kBAD5B;AAG3B;AAEAuC,EAAa,OAAO;AAAA,EAClB,QAAQ,CAACxC,MAAwB;AAC/B,UAAMsE,IAActE,EAAK,mBAAmBA,EAAK,aAE3CuE,IADSvE,EAAK,WACO,aAAa,SAAS,CAACsE;AAClD,WAAOtE,EAAK,aAAa,UAAU,CAACuE;AAAA,EACtC;AAAA,EACA,aAAa,CAACjC,MAA4B;AACxC,UAAMkC,IAAUlC,EAAQ,QAAQ,aAAa,GAAG,GAC1CmC,IAAa,sBAAsB,KAAKD,CAAO,IAAI,MAAM;AAC/D,QAAIE,IAAY;AAChB,UAAMC,IAAoBH,EAAQ,MAAM,MAAM,KAAK,CAAA;AACnD,WAAOG,EAAQ,SAASD,CAAS,SAAeA,IAAY;AAC5D,WAAOA,IAAYD,IAAaD,IAAUC,IAAaC;AAAA,EACzD;AACF;AAEAlC,EAAa,QAAQ;AAAA,EACnB,QAAQ;AAAA,EACR,aAAa,SAAUC,GAAkBzC,GAAoB;AAC3D,UAAM4E,IAAW5E,EAAiB,aAAa,KAAK,GAC9C6E,IAAMD,IAAUrC,EAAmBqC,CAAO,IAAI,IAC9CE,IAAO9E,EAAiB,aAAa,KAAK,KAAK,IAC/C6D,IAAa7D,EAAiB,aAAa,OAAO,GAClD4D,IAAQC,IAAYtB,EAAmBsB,CAAS,IAAI,IACpDkB,IAAYnB,IAAQ,OAAOA,IAAQ,MAAM;AAC/C,WAAOkB,IAAM,OAAOD,IAAM,OAAYC,IAAMC,IAAY,MAAM;AAAA,EAChE;AACF;AC5QO,MAAMC,EAAM;AAAA,EACjB;AAAA,EACQ;AAAA,EACA;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY/E,GAAyB;AACnC,SAAK,UAAUA,GACf,KAAK,QAAQ,CAAA,GACb,KAAK,UAAU,CAAA,GAEf,KAAK,YAAY;AAAA,MACf,aAAaA,EAAQ;AAAA,IAAA,GAGvB,KAAK,kBAAkBA,EAAQ,iBAC/B,KAAK,mCAAmCA,EAAQ,kCAEhD,KAAK,cAAc;AAAA,MACjB,aAAaA,EAAQ;AAAA,IAAA,GAGvB,KAAK,QAAQ,CAAA;AACb,eAAWgF,KAAOhF,EAAQ;AACxB,WAAK,MAAM,KAAKA,EAAQ,MAAMgF,CAAG,CAAC;AAAA,EAEtC;AAAA,EAEA,IAAIA,GAAaC,GAAkB;AACjC,SAAK,MAAM,QAAQA,CAAI;AAAA,EACzB;AAAA,EAEA,KAAKC,GAA0B;AAC7B,SAAK,MAAM,QAAQ;AAAA,MACjB,QAAAA;AAAA,MACA,aAAa,KAAK;AAAA,IAAA,CACnB;AAAA,EACH;AAAA,EAEA,OAAOA,GAA0B;AAC/B,SAAK,QAAQ,QAAQ;AAAA,MACnB,QAAAA;AAAA,MACA,aAAa,WAAY;AACvB,eAAO;AAAA,MACT;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EAEA,QAAQnF,GAA0B;AAChC,QAAIA,EAAK;AACP,aAAO,KAAK;AAEd,QAAI,KAAK,QAAQ,sBAAsB,iBAAiB,KAAK,qBAAqBA,CAAI;AACpF,aAAO;AAAA,QACL,aAAa,KAAK;AAAA,MAAA;AAGtB,QAAI,KAAK,QAAQ,sBAAsB,2BAA2B,KAAK,qBAAqBA,CAAI;AAC9F,aAAO;AAAA,QACL,aAAa,KAAK;AAAA,MAAA;AAItB,QAAIkF;AAOJ,YANKA,IAAOE,EAAS,KAAK,OAAOpF,GAAM,KAAK,OAAO,OAG9CkF,IAAOE,EAAS,KAAK,OAAOpF,GAAM,KAAK,OAAO,OAG9CkF,IAAOE,EAAS,KAAK,SAASpF,GAAM,KAAK,OAAO,KAC5CkF,IAEF,KAAK;AAAA,EACd;AAAA;AAAA,EAGQ,qBAAqBlF,GAA6B;AACxD,UAAMqF,IAAWrF,EAAK;AAEtB,QAAIqF,MAAa,SAASrF,EAAK,cAAeA,EAAK,WAAuB,aAAa,QAAQ;AAC7F,YAAMkD,IAAWlD,EAAK;AACtB,UAAIkD,EAAS,cAAcA,EAAS,WAAW,SAAS;AACtD,iBAAS,IAAI,GAAG,IAAIA,EAAS,WAAW,QAAQ;AAE9C,cADiBA,EAAS,WAAW,CAAC,EAAE,KAAK,YAAA,MAC5B;AACf,mBAAO;AAAA;AAAA,IAIf;AAEA,QAAIlD,EAAK,cAAcA,EAAK,WAAW,SAAS;AAC9C,cAAQqF,GAAA;AAAA,QACN,KAAK;AACH,mBAAS,IAAI,GAAG,IAAIrF,EAAK,WAAW,QAAQ,KAAK;AAC/C,kBAAMsF,IAAWtF,EAAK,WAAW,CAAC,EAAE,KAAK,YAAA;AACzC,gBAAIsF,MAAa,SAASA,MAAa,SAASA,MAAa;AAC3D,qBAAO;AAAA,UAEX;AACA,iBAAO;AAAA,QACT,KAAK;AACH,mBAAS,IAAI,GAAG,IAAItF,EAAK,WAAW,QAAQ,KAAK;AAC/C,kBAAMsF,IAAWtF,EAAK,WAAW,CAAC,EAAE,KAAK,YAAA;AACzC,gBAAIsF,MAAa,UAAUA,MAAa;AACtC,qBAAO;AAAA,UAEX;AACA,iBAAO;AAAA,QACT,KAAK;AACH,gBAAMzC,IAAS7C,EAAK;AACpB,cAAI6C,KAAUA,EAAO,aAAa,OAAO;AACvC,qBAAS,IAAI,GAAG,IAAI7C,EAAK,WAAW,QAAQ;AAE1C,kBADiBA,EAAK,WAAW,CAAC,EAAE,KAAK,YAAA,MACxB;AACf,uBAAO;AAGX,mBAAO;AAAA,UACT;AAAA,QACF;AACE,iBAAO;AAAA,MAAA;AAIb,WAAIiC,EAAyB,QAAQoD,CAAQ,MAAM;AAAA,EAIrD;AAAA,EAEA,QAAQE,GAA+C;AACrD,aAASC,IAAI,GAAGA,IAAI,KAAK,MAAM,QAAQA;AACrC,MAAAD,EAAG,KAAK,MAAMC,CAAC,GAAGA,CAAC;AAAA,EAEvB;AACF;AAEA,SAASJ,EAASK,GAAezF,GAAoBC,GAA2C;AAC9F,WAASuF,IAAI,GAAGA,IAAIC,EAAM,QAAQD,KAAK;AACrC,UAAMN,IAAOO,EAAMD,CAAC;AACpB,QAAIE,EAAYR,GAAMlF,GAAMC,CAAO,EAAG,QAAOiF;AAAA,EAC/C;AAEF;AAEA,SAASQ,EAAYR,GAAYlF,GAAoBC,GAAkC;AACrF,QAAMkF,IAASD,EAAK;AACpB,MAAI,OAAOC,KAAW;AACpB,QAAIA,MAAWnF,EAAK,SAAS,YAAA;AAC3B,aAAO;AAAA,aAEA,MAAM,QAAQmF,CAAM;AAC7B,QAAIA,EAAO,QAAQnF,EAAK,SAAS,YAAA,CAAa,IAAI;AAChD,aAAO;AAAA,aAEA,OAAOmF,KAAW;AAC3B,QAAIA,EAAOnF,GAAMC,CAAO;AACtB,aAAO;AAAA;AAGT,UAAM,IAAI,UAAU,mDAAmD;AAEzE,SAAO;AACT;ACtJA,SAAS0F,EAAmB1F,GAA0C;AACpE,QAAM2F,IAAU3F,EAAQ,SAClBE,IAAUF,EAAQ,SAClBK,IAASL,EAAQ,QACjB4F,IAAQ5F,EAAQ,SAAS,SAAUD,GAAqB;AAC5D,WAAOA,EAAK,aAAa;AAAA,EAC3B;AAEA,MAAI,CAAC4F,EAAQ,cAAcC,EAAMD,CAAO,EAAG;AAE3C,MAAIE,IAAwB,MACxBC,IAAgB,IAEhBC,IAAoB,MACpBhG,IAAaiG,EAAKD,GAAMJ,GAASC,CAAK;AAE1C,SAAO7F,MAAS4F,KAAS;AACvB,QAAI5F,EAAK,aAAaoB,EAAU,QAAQpB,EAAK,aAAaoB,EAAU,cAAc;AAChF,YAAM8E,IAAWlG;AACjB,UAAImG,IAAOD,EAAS,KAAK,QAAQ,eAAe,GAAG;AAQnD,WANK,CAACJ,KAAY,KAAK,KAAKA,EAAS,IAAI,MACvC,CAACC,KAAiBI,EAAK,CAAC,MAAM,QAC9BA,IAAOA,EAAK,OAAO,CAAC,IAIlB,CAACA,GAAM;AACT,QAAAnG,IAAOoG,EAAOpG,CAAI;AAClB;AAAA,MACF;AAEA,MAAAkG,EAAS,OAAOC,GAEhBL,IAAWI;AAAA,IACb,WAAWlG,EAAK,aAAaoB,EAAU;AACrC,MAAIjB,EAAQH,CAAI,KAAKA,EAAK,aAAa,QACjC8F,MACFA,EAAS,OAAOA,EAAS,KAAK,QAAQ,MAAM,EAAE,IAGhDA,IAAW,MACXC,IAAgB,MACPzF,EAAON,CAAI,KAAK6F,EAAM7F,CAAI,KAEnC8F,IAAW,MACXC,IAAgB,MACPD,MAETC,IAAgB;AAAA,SAEb;AACL,MAAA/F,IAAOoG,EAAOpG,CAAI;AAClB;AAAA,IACF;AAEA,UAAMqG,IAAWJ,EAAKD,GAAMhG,GAAM6F,CAAK;AACvC,IAAAG,IAAOhG,GACPA,IAAOqG;AAAA,EACT;AAEA,EAAIP,MACFA,EAAS,OAAOA,EAAS,KAAK,QAAQ,MAAM,EAAE,GACzCA,EAAS,QACZM,EAAON,CAAQ;AAGrB;AASA,SAASM,EAAOpG,GAAkB;AAChC,QAAMqG,IAAwBrG,EAAK,eAAeA,EAAK;AACvD,SAAIA,EAAK,cACPA,EAAK,WAAW,YAAYA,CAAI,GAE3BqG;AACT;AAWA,SAASJ,EAAKD,GAAmBM,GAAeT,GAAsC;AACpF,SAAKG,KAAQA,EAAK,eAAeM,KAAYT,EAAMS,CAAO,IAC1BA,EAAQ,eAAeA,EAAQ,aAGjCA,EAAQ,cAAcA,EAAQ,eAAeA,EAAQ;AAErF;ACzIA,MAAMC,IAA0B,OAAO,SAAW,MAAc,SAAU,OAAO,aAAe,MAAc,aAAa,CAAA;AAM3H,SAASC,IAAuB;AAC9B,QAAMC,IAAS,OAAOF,EAAK,YAAc,MAAcA,EAAK,YAAY;AACxE,MAAIG,IAAW;AACf,MAAI,CAACD,EAAQ,QAAO;AAGpB,MAAI;AAEF,IAAI,IAAIA,EAAA,EAAS,gBAAgB,IAAI,WAAW,MAC9CC,IAAW;AAAA,EAEf,QAAY;AAAA,EAAE;AACd,SAAOA;AACT;AAEO,MAAMC,EAAW;AAAA;AAAA,EAEtB,gBAAgBC,GAAgBC,GAA0B;AACxD,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AACF;AAEA,SAASC,IAA2B;AAMlC,MAJE,OAAO,SAAW,OAClB,OAAO,WAAa,QACnB,OAAO,UAAY,OAAgB,QAAgB,UAElD,OAAO,SAAW,KAAa;AAAA,IAEjC,MAAMC,UAA0BJ,EAAW;AAAA,MACzC,gBAAgBK,GAAeH,GAA0B;AACvD,cAAMI,IAAM,SAAS,eAAe,mBAAmB,EAAE;AACzD,eAAAA,EAAI,KAAA,GACJA,EAAI,MAAMD,CAAK,GACfC,EAAI,MAAA,GACGA;AAAA,MACT;AAAA,IAAA;AAEF,WAAO,IAAIF,EAAA;AAAA,EACb,OAAO;AACL,UAAMG,IAAS,QAAQ,oBAAoB;AAAA,IAG3C,MAAMC,UAAuBR,EAAW;AAAA,MACtC,gBAAgBK,GAAeH,GAA0B;AACvD,eAAOK,EAAO,eAAeF,CAAK;AAAA,MACpC;AAAA,IAAA;AAEF,WAAO,IAAIG,EAAA;AAAA,EACb;AACF;AAEO,MAAMC,IAAmB,MAC9BZ,EAAA,IACI,IAAID,EAAK,UAAA,IACTO,EAAA;AC1DN,SAAwBO,EACtBL,GACA,EAAE,kBAAAM,KACO;AACT,MAAIf;AACJ,SAAI,OAAOS,KAAU,WAQnBT,IAPYgB,IAAa;AAAA;AAAA;AAAA;AAAA,IAIvB,kCAAkCP,IAAQ;AAAA,IAC1C;AAAA,EAAA,EAES,eAAe,cAAc,IAExCT,IAAOS,EAAM,UAAU,EAAI,GAE7BrB,EAAmB;AAAA,IACjB,SAASY;AAAA,IACT,SAAApG;AAAA,IACA,QAAAG;AAAA,IACA,OAAOgH,IAAmBE,IAAc;AAAA,EAAA,CACzC,GAEMjB;AACT;AAEA,IAAIkB;AACJ,SAASF,IAAyB;AAChC,SAAQE,MAAgBL,EAAA;AAC1B;AAEA,SAASI,EAAYxH,GAAqB;AACxC,SAAOA,EAAK,aAAa,SAASA,EAAK,aAAa;AACtD;ACjCA,MAAM0H,KAAwB;AAAA,EAC5B,CAAC,OAAO,MAAM;AAAA,EACd,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,MAAM,KAAK;AAAA,EACZ,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,SAAS,MAAM;AAAA,EAChB,CAAC,UAAU,MAAM;AAAA,EACjB,CAAC,eAAe,OAAO;AAAA,EACvB,CAAC,MAAM,KAAK;AAAA,EACZ,CAAC,SAAS,OAAO;AAAA,EACjB,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,cAAc,UAAU;AAAA,EACzB,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,cAAc,QAAQ;AACzB,GA2BMC,KAAiC;AAAA,EACrC,OAAOnF;AAAA,EACP,cAAc;AAAA,EACd,IAAI;AAAA,EACJ,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,oBAAoB;AAAA,EACpB,4BAA4B;AAAA,EAC5B,IAAI;AAAA,EACJ,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,kBAAkB,CAACF,GAAiBtC,MAC3BA,EAAK,UAAU;AAAA;AAAA,IAAS;AAAA,EAEjC,iBAAiB,CAACsC,GAAiBtC,MAC1BA,EAAK,UAAU;AAAA;AAAA,IAASA,EAAK,YAAY;AAAA;AAAA,IAASA,EAAK;AAAA,EAEhE,kCAAkC,CAACsC,GAAiBtC,MAA+B;AACjF,UAAMmC,IAAUnC,EAAK,SAAS,YAAA;AAE9B,QAAI4H,IAAa;AACjB,QAAI5H,EAAK,cAAcA,EAAK,WAAW,SAAS,GAAG;AACjD,YAAM6H,IAAkB,CAAA;AACxB,eAASrC,IAAI,GAAGA,IAAIxF,EAAK,WAAW,QAAQwF,KAAK;AAC/C,cAAMsC,IAAO9H,EAAK,WAAWwF,CAAC;AAC9B,QAAAqC,EAAM,KAAK,GAAGC,EAAK,IAAI,KAAKA,EAAK,KAAK,GAAG;AAAA,MAC3C;AACA,MAAAF,IAAa,MAAMC,EAAM,KAAK,GAAG;AAAA,IACnC;AAEA,IAAAD,KAAc;AAEd,UAAMG,IAAU,IAAI5F,CAAO,GAAGyF,CAAU,KAClCI,IAAW,KAAK7F,CAAO,KAEvB8F,IAAiB3F,EAAQ,KAAA,GACzB4F,IAAOH,IAAU;AAAA,IAAOE,IAAiB;AAAA,IAAOD;AAEtD,WAAOhI,EAAK,UAAU;AAAA;AAAA,IAASkI,IAAO;AAAA;AAAA,IAASA;AAAA,EACjD;AAAA,EACA,oBAAoB,SAAU5F,GAAiBtC,GAA4B;AACzE,WAAOA,EAAK,UAAU;AAAA;AAAA,IAASsC,IAAU;AAAA;AAAA,IAASA;AAAA,EACpD;AACF;AAEA,MAAqB6F,GAAQ;AAAA,EAC3B;AAAA,EACA;AAAA,EAEA,YAAYlI,GAAmC;AAC7C,SAAK,UAAU,OAAO,OAAO,CAAA,GAAI0H,IAAgB1H,CAAO,GACxD,KAAK,QAAQ,IAAI+E,EAAM,KAAK,OAAO;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAOgC,GAA0B;AAC/B,QAAI,CAACoB,GAAWpB,CAAK;AACnB,YAAM,IAAI;AAAA,QACRA,IAAQ;AAAA,MAAA;AAGZ,QAAIA,MAAU;AACZ,aAAO;AAET,UAAMqB,IAAS,KAAK,QAAQhB,EAASL,GAAO,KAAK,OAAO,CAAC;AACzD,WAAO,KAAK,YAAYqB,CAAM;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAIC,GAAoC;AACtC,QAAI,MAAM,QAAQA,CAAM;AACtB,eAAS9C,IAAI,GAAGA,IAAI8C,EAAO,QAAQ9C,IAAK,MAAK,IAAI8C,EAAO9C,CAAC,CAAC;AAAA,aACjD,OAAO8C,KAAW;AAC3B,MAAAA,EAAO,IAAI;AAAA;AAEX,YAAM,IAAI,UAAU,oDAAoD;AAE1E,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAQrD,GAAaC,GAAqB;AACxC,gBAAK,MAAM,IAAID,GAAKC,CAAI,GACjB;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,KAAKC,GAA6B;AAChC,gBAAK,MAAM,KAAKA,CAAM,GACf;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAOA,GAA6B;AAClC,gBAAK,MAAM,OAAOA,CAAM,GACjB;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAOrE,GAAwB;AAC7B,WAAO4G,GAAQ,OAAO,SAAUa,GAAqBC,GAAoB;AACvE,aAAOD,EAAY,QAAQC,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,IACjD,GAAG1H,CAAM;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAuB2H,GAA0B;AAC/C,WAAO,MAAM,KAAKA,EAAW,UAAU,EAAE,OAAO,CAACJ,GAAQrI,MAAS;AAChE,YAAME,IAAWH,EAAaC,GAAM,KAAK,OAAO;AAChD,UAAIiE,IAAc;AAClB,UAAI/D,EAAS,aAAakB,EAAU,MAAM;AACxC,cAAMsH,IAAQxI,EAAS,aAAa;AACpC,QAAA+D,IAAc/D,EAAS,SAASwI,IAAQ,KAAK,OAAOA,CAAK;AAAA,MAC3D,MAAA,CAAWxI,EAAS,aAAakB,EAAU,YACzC6C,IAAc,KAAK,mBAAmB/D,CAAQ;AAEhD,aAAOyI,EAAKN,GAAQpE,CAAW;AAAA,IACjC,GAAG,EAAE;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAYoE,GAAwB;AAClC,eAAWnD,KAAQ,KAAK,MAAM;AAC5B,MAAIA,EAAK,WACPmD,IAASM,EAAKN,GAAQnD,EAAK,OAAO,KAAK,OAAO,CAAC;AAGnD,WAAOmD,EACJ,QAAQ,cAAc,EAAE,EACxB,QAAQ,gBAAgB,EAAE;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,mBAAmBrI,GAAoB;AACrC,UAAMkF,IAAO,KAAK,MAAM,QAAQlF,CAAI;AACpC,QAAIsC,IAAU,KAAK,QAAQtC,CAAI;AAC/B,UAAM4I,IAAa5I,EAAK;AACxB,YAAI4I,EAAW,WAAWA,EAAW,cACnCtG,IAAUA,EAAQ,KAAA,IAGlBsG,EAAW,UACX1D,EAAK,YAAY5C,GAAStC,GAAM,KAAK,OAAO,IAC5C4I,EAAW;AAAA,EAEf;AACF;AAUA,SAASD,EAAKN,GAAgBpE,GAA6B;AACzD,QAAM4E,IAAKpH,EAAqB4G,CAAM,GAChCS,IAAKtH,EAAoByC,CAAW,GACpC8E,IAAM,KAAK,IAAIV,EAAO,SAASQ,EAAG,QAAQ5E,EAAY,SAAS6E,EAAG,MAAM,GACxEE,IAAY;AAAA;AAAA,EAAO,UAAU,GAAGD,CAAG;AAEzC,SAAOF,IAAKG,IAAYF;AAC1B;AAUA,SAASV,GAAWpB,GAAgC;AAClD,SACEA,KAAS,SACP,OAAOA,KAAU,YAChBA,EAAM,aACLA,EAAM,aAAa,KAAKA,EAAM,aAAa,KAAKA,EAAM,aAAa;AAI3E;"}
@@ -0,0 +1,68 @@
1
+ (function(p,h){typeof exports=="object"&&typeof module<"u"?module.exports=h():typeof define=="function"&&define.amd?define(h):(p=typeof globalThis<"u"?globalThis:p||self,p.Turnish=h())})(this,(function(){"use strict";function p(t,e){const n=t;return n.isBlock=T(n),n.isCode=n.nodeName==="CODE"||n.parentNode?.isCode,n.isBlank=h(n),n.flankingWhitespace=H(n,e),n}function h(t){return!O(t)&&!U(t)&&/^\s*$/i.test(t.textContent||"")&&!$(t)&&!z(t)}function H(t,e){const n=t;if(n.isBlock||e.preformattedCode&&n.isCode)return{leading:"",trailing:""};const r=_(t.textContent||"");return r.leadingAscii&&C("left",t,e)&&(r.leading=r.leadingNonAscii),r.trailingAscii&&C("right",t,e)&&(r.trailing=r.trailingNonAscii),{leading:r.leading,trailing:r.trailing}}function _(t){const e=t.match(/^(([ \t\r\n]*)(\s*))(?:(?=\S)[\s\S]*\S)?((\s*?)([ \t\r\n]*))$/);return e?{leading:e[1],leadingAscii:e[2],leadingNonAscii:e[3],trailing:e[4],trailingNonAscii:e[5],trailingAscii:e[6]}:{leading:"",leadingAscii:"",leadingNonAscii:"",trailing:"",trailingNonAscii:"",trailingAscii:""}}function C(t,e,n){let r,i,s;return t==="left"?(r=e.previousElementSibling,i=/ $/):(r=e.nextElementSibling,i=/^ /),r&&(r.nodeType===3?s=i.test(r.nodeValue||""):n.preformattedCode&&r.nodeName==="CODE"?s=!1:r.nodeType===1&&!T(r)&&(s=i.test(r.textContent||""))),s||!1}const m={Element:1,Text:3,CDATASection:4};function N(t,e){return Array(e+1).join(t)}function b(t){return t.replace(/^\n*/,"")}function x(t){let e=t.length;for(;e>0&&t[e-1]===`
2
+ `;)e--;return t.substring(0,e)}function D(t){return x(b(t))}const v=["ADDRESS","ARTICLE","ASIDE","AUDIO","BLOCKQUOTE","BODY","CANVAS","CENTER","DD","DIR","DIV","DL","DT","FIELDSET","FIGCAPTION","FIGURE","FOOTER","FORM","FRAMESET","H1","H2","H3","H4","H5","H6","HEADER","HGROUP","HR","HTML","ISINDEX","LI","MAIN","MENU","NAV","NOFRAMES","NOSCRIPT","OL","OUTPUT","P","PRE","SECTION","TABLE","TBODY","TD","TFOOT","TH","THEAD","TR","UL"];function T(t){return R(t,v)}const w=["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"];function O(t){return R(t,w)}function $(t){return L(t,w)}const S=["A","TABLE","THEAD","TBODY","TFOOT","TH","TD","IFRAME","SCRIPT","AUDIO","VIDEO"],F=["P","BR","H1","H2","H3","H4","H5","H6","BLOCKQUOTE","UL","OL","LI","PRE","CODE","HR","A","EM","I","STRONG","B","IMG","DIV","SPAN","TABLE","THEAD","TBODY","TR","TH","TD"];function U(t){return R(t,S)}function z(t){return L(t,S)}function R(t,e){return e.indexOf(t.nodeName)>=0}function L(t,e){return e.some(function(n){return t.nodeType!==m.Element?!1:t.getElementsByTagName(n).length})}function M(t){return t?t.replace(/(\n+\s*)+/g,`
3
+ `):""}function V(t){return M(t).replace(/[\t\r\n]+/g," ").replace(/ {2,}/g," ").replace(/([()])/g,"\\$1").trim()}function g(t){return M(t).replace(/[\t\r\n]+/g," ")}const f={};f.paragraph={filter:"p",replacement:function(t){return`
4
+
5
+ `+t+`
6
+
7
+ `}},f.lineBreak={filter:"br",replacement:function(t,e,n){return n.br+`
8
+ `}},f.heading={filter:["h1","h2","h3","h4","h5","h6"],replacement:function(t,e,n){const r=Number(e.nodeName.charAt(1));if(n.headingStyle==="setext"&&r<3){const i=N(r===1?"=":"-",t.length);return`
9
+
10
+ `+t+`
11
+ `+i+`
12
+
13
+ `}else return`
14
+
15
+ `+N("#",r)+" "+t+`
16
+
17
+ `}},f.blockquote={filter:"blockquote",replacement:function(t){return t=D(t).replace(/^/gm,"> "),`
18
+
19
+ `+t+`
20
+
21
+ `}},f.list={filter:["ul","ol"],replacement:function(t,e){const n=e.parentNode;return n.nodeName==="LI"&&n.lastElementChild===e?`
22
+ `+t:`
23
+
24
+ `+t+`
25
+
26
+ `}},f.listItem={filter:"li",replacement:function(t,e,n){let r=n.bulletListMarker+" ";const i=e.parentNode;if(i.nodeName==="OL"){const a=i.getAttribute("start"),o=Array.prototype.indexOf.call(i.children,e);r=(a?Number(a)+o:o+1)+". "}const s=/\n$/.test(t);return t=D(t)+(s?`
27
+ `:""),t=t.replace(/\n/gm,`
28
+ `+" ".repeat(r.length)),r+t+(e.nextSibling?`
29
+ `:"")}},f.indentedCodeBlock={filter:function(t,e){return!!(e&&e.codeBlockStyle==="indented"&&t.nodeName==="PRE"&&t.firstChild&&t.firstChild.nodeName==="CODE")},replacement:function(t,e){return!e||!e.firstChild?"":`
30
+
31
+ `+e.firstChild.textContent.replace(/\n/g,`
32
+ `)+`
33
+
34
+ `}},f.fencedCodeBlock={filter:function(t,e){return!!(e&&e.codeBlockStyle==="fenced"&&t.nodeName==="PRE"&&t.firstChild&&t.firstChild.nodeName==="CODE")},replacement:function(t,e,n){if(!e.firstChild)return"";const r=e.firstChild,s=((r.getAttribute("class")||"").match(/language-(\S+)/)||[null,""])[1],a=r.textContent||"",o=n.fence?.charAt(0)||"`";let l=3;const u=new RegExp("^"+o+"{3,}","gm");let c;for(;c=u.exec(a);)c[0].length>=l&&(l=c[0].length+1);const d=N(o,l);return`
35
+
36
+ `+d+s+`
37
+ `+a.replace(/\n$/,"")+`
38
+ `+d+`
39
+
40
+ `}},f.horizontalRule={filter:"hr",replacement:function(t,e,n){return`
41
+
42
+ `+n.hr+`
43
+
44
+ `}},f.inlineLink={filter:function(t,e){return!!(e?.linkStyle==="inlined"&&t.nodeName==="A"&&t.getAttribute("href"))},replacement:function(t,e){const n=V(t);let r=e.getAttribute("href")?.replace(/([()])/g,"\\$1"),i;const s=e.getAttribute("title");return s?i=' "'+g(s).replace(/"/g,'\\"')+'"':i="","["+n+"]("+r+i+")"}};const E={filter:function(t,e){return!!(e&&e.linkStyle==="referenced"&&t.nodeName==="A"&&t.getAttribute("href"))},replacement:function(t,e,n){const r=E,i=e.getAttribute("href");let s;const a=e.getAttribute("title");a?s=' "'+g(a)+'"':s="";const o=i+s;let l,u;switch(n.linkReferenceStyle){case"collapsed":l="["+t+"][]",u="["+t+"]: "+o;break;case"shortcut":l="["+t+"]",u="["+t+"]: "+o;break;default:{let c;const d=r.urlReferenceIdMap.get(o);n.linkReferenceDeduplication==="full"&&d?(c=d,u="["+c+"]: "+i+s):(c=r.references.length+1,r.urlReferenceIdMap.set(o,c),u="["+c+"]: "+i+s,r.references.push(u)),l="["+t+"]["+c+"]";break}}return n.linkReferenceStyle!=="full"&&(n.linkReferenceDeduplication==="full"?r.urlReferenceIdMap.has(o)||(r.urlReferenceIdMap.set(o,1),r.references.push(u)):r.references.push(u)),l},references:[],urlReferenceIdMap:new Map,append:()=>{const t=E;let e="";return t.references&&t.references.length&&(e=`
45
+
46
+ `+t.references.join(`
47
+ `)+`
48
+
49
+ `,t.references=[],t.urlReferenceIdMap=new Map),e}};f.referenceLink=E,f.emphasis={filter:["em","i"],replacement:(t,e,n)=>(t=t.trim(),t?n.emDelimiter+t+n.emDelimiter:"")},f.strong={filter:["strong","b"],replacement:(t,e,n)=>(t=t.trim(),t?n.strongDelimiter+t+n.strongDelimiter:"")},f.code={filter:t=>{const e=t.previousSibling||t.nextSibling,r=t.parentNode.nodeName==="PRE"&&!e;return t.nodeName==="CODE"&&!r},replacement:t=>{const e=t.replace(/\r?\n|\r/g," "),n=/^`|^ .*?[^ ].* $|`$/.test(e)?" ":"";let r="`";const i=e.match(/`+/gm)||[];for(;i.includes(r);)r=r+"`";return r+n+e+n+r}},f.image={filter:"img",replacement:function(t,e){const n=e.getAttribute("alt"),r=n?g(n):"",i=e.getAttribute("src")||"",s=e.getAttribute("title"),a=s?g(s):"",o=a?' "'+a+'"':"";return i?"!["+r+"]("+i+o+")":""}};class W{options;_keep;_remove;blankRule;keepReplacement;markdownIncludingHtmlReplacement;defaultRule;array;constructor(e){this.options=e,this._keep=[],this._remove=[],this.blankRule={replacement:e.blankReplacement},this.keepReplacement=e.keepReplacement,this.markdownIncludingHtmlReplacement=e.markdownIncludingHtmlReplacement,this.defaultRule={replacement:e.defaultReplacement},this.array=[];for(const n in e.rules)this.array.push(e.rules[n])}add(e,n){this.array.unshift(n)}keep(e){this._keep.unshift({filter:e,replacement:this.keepReplacement})}remove(e){this._remove.unshift({filter:e,replacement:function(){return""}})}forNode(e){if(e.isBlank)return this.blankRule;if(this.options.htmlRetentionMode==="preserveAll"&&this.isUnsupportedElement(e))return{replacement:this.keepReplacement};if(this.options.htmlRetentionMode==="markdownIncludingHtml"&&this.isUnsupportedElement(e))return{replacement:this.markdownIncludingHtmlReplacement};let n;return(n=k(this.array,e,this.options))||(n=k(this._keep,e,this.options))||(n=k(this._remove,e,this.options))?n:this.defaultRule}isUnsupportedElement(e){const n=e.nodeName;if(n==="PRE"&&e.firstChild&&e.firstChild.nodeName==="CODE"){const r=e.firstChild;if(r.attributes&&r.attributes.length>0){for(let i=0;i<r.attributes.length;i++)if(r.attributes[i].name.toLowerCase()!=="class")return!0}}if(e.attributes&&e.attributes.length>0)switch(n){case"IMG":for(let i=0;i<e.attributes.length;i++){const s=e.attributes[i].name.toLowerCase();if(s!=="src"&&s!=="alt"&&s!=="title")return!0}return!1;case"A":for(let i=0;i<e.attributes.length;i++){const s=e.attributes[i].name.toLowerCase();if(s!=="href"&&s!=="title")return!0}return!1;case"CODE":const r=e.parentNode;if(r&&r.nodeName==="PRE"){for(let i=0;i<e.attributes.length;i++)if(e.attributes[i].name.toLowerCase()!=="class")return!0;return!1}default:return!0}return F.indexOf(n)===-1}forEach(e){for(let n=0;n<this.array.length;n++)e(this.array[n],n)}}function k(t,e,n){for(let r=0;r<t.length;r++){const i=t[r];if(G(i,e,n))return i}}function G(t,e,n){const r=t.filter;if(typeof r=="string"){if(r===e.nodeName.toLowerCase())return!0}else if(Array.isArray(r)){if(r.indexOf(e.nodeName.toLowerCase())>-1)return!0}else if(typeof r=="function"){if(r(e,n))return!0}else throw new TypeError("`filter` needs to be a string, array, or function");return!1}function K(t){const e=t.element,n=t.isBlock,r=t.isVoid,i=t.isPre||function(u){return u.nodeName==="PRE"};if(!e.firstChild||i(e))return;let s=null,a=!1,o=null,l=I(o,e,i);for(;l!==e;){if(l.nodeType===m.Text||l.nodeType===m.CDATASection){const c=l;let d=c.data.replace(/[ \r\n\t]+/g," ");if((!s||/ $/.test(s.data))&&!a&&d[0]===" "&&(d=d.substr(1)),!d){l=A(l);continue}c.data=d,s=c}else if(l.nodeType===m.Element)n(l)||l.nodeName==="BR"?(s&&(s.data=s.data.replace(/ $/,"")),s=null,a=!1):r(l)||i(l)?(s=null,a=!0):s&&(a=!1);else{l=A(l);continue}const u=I(o,l,i);o=l,l=u}s&&(s.data=s.data.replace(/ $/,""),s.data||A(s))}function A(t){const e=t.nextSibling??t.parentNode;return t.parentNode&&t.parentNode.removeChild(t),e}function I(t,e,n){return t&&t.parentNode===e||n(e)?e.nextSibling??e.parentNode:e.firstChild??e.nextSibling??e.parentNode}const y=typeof window<"u"?window:typeof globalThis<"u"?globalThis:{};function j(){const t=typeof y.DOMParser<"u"?y.DOMParser:void 0;let e=!1;if(!t)return!1;try{new t().parseFromString("","text/html")&&(e=!0)}catch{}return e}class B{parseFromString(e,n){throw new Error("Not implemented")}}function Y(){if(typeof window<"u"&&typeof document<"u"&&(typeof process>"u"||process.browser),typeof window<"u"){class t extends B{parseFromString(n,r){const i=document.implementation.createHTMLDocument("");return i.open(),i.write(n),i.close(),i}}return new t}else{const t=require("@mixmark-io/domino");class e extends B{parseFromString(r,i){return t.createDocument(r)}}return new e}}const q=()=>j()?new y.DOMParser:Y();function Q(t,{preformattedCode:e}){let n;return typeof t=="string"?n=J().parseFromString('<x-turnish id="turnish-root">'+t+"</x-turnish>","text/html").getElementById("turnish-root"):n=t.cloneNode(!0),K({element:n,isBlock:T,isVoid:O,isPre:e?Z:void 0}),n}let X;function J(){return X??=q()}function Z(t){return t.nodeName==="PRE"||t.nodeName==="CODE"}const ee=[[/\\/g,"\\\\"],[/\*/g,"\\*"],[/_/g,"\\_"],[/^-/g,"\\-"],[/^\+ /g,"\\+ "],[/^(=+)/g,"\\$1"],[/^(#{1,6}) /g,"\\$1 "],[/`/g,"\\`"],[/^~~~/g,"\\~~~"],[/\[/g,"\\["],[/\]/g,"\\]"],[/<([^>]*)>/g,"\\<$1\\>"],[/^>/g,"\\>"],[/^(\d+)\. /g,"$1\\. "]],te={rules:f,headingStyle:"atx",hr:"---",bulletListMarker:"-",codeBlockStyle:"fenced",fence:"```",emDelimiter:"*",strongDelimiter:"**",linkStyle:"inlined",linkReferenceStyle:"full",linkReferenceDeduplication:"full",br:" ",preformattedCode:!1,htmlRetentionMode:"standard",blankReplacement:(t,e)=>e.isBlock?`
50
+
51
+ `:"",keepReplacement:(t,e)=>e.isBlock?`
52
+
53
+ `+e.outerHTML+`
54
+
55
+ `:e.outerHTML,markdownIncludingHtmlReplacement:(t,e)=>{const n=e.nodeName.toLowerCase();let r="";if(e.attributes&&e.attributes.length>0){const l=[];for(let u=0;u<e.attributes.length;u++){const c=e.attributes[u];l.push(`${c.name}="${c.value}"`)}r=" "+l.join(" ")}r+=' markdown="1"';const i=`<${n}${r}>`,s=`</${n}>`,a=t.trim(),o=i+`
56
+ `+a+`
57
+ `+s;return e.isBlock?`
58
+
59
+ `+o+`
60
+
61
+ `:o},defaultReplacement:function(t,e){return e.isBlock?`
62
+
63
+ `+t+`
64
+
65
+ `:t}};class ne{options;rules;constructor(e){this.options=Object.assign({},te,e),this.rules=new W(this.options)}render(e){if(!re(e))throw new TypeError(e+" is not a string, or an element/document/fragment node.");if(e==="")return"";const n=this.process(Q(e,this.options));return this.postProcess(n)}use(e){if(Array.isArray(e))for(let n=0;n<e.length;n++)this.use(e[n]);else if(typeof e=="function")e(this);else throw new TypeError("plugin must be a Function or an Array of Functions");return this}addRule(e,n){return this.rules.add(e,n),this}keep(e){return this.rules.keep(e),this}remove(e){return this.rules.remove(e),this}escape(e){return ee.reduce(function(n,r){return n.replace(r[0],r[1])},e)}process(e){return Array.from(e.childNodes).reduce((n,r)=>{const i=p(r,this.options);let s="";if(i.nodeType===m.Text){const a=i.nodeValue??"";s=i.isCode?a:this.escape(a)}else i.nodeType===m.Element&&(s=this.replacementForNode(i));return P(n,s)},"")}postProcess(e){for(const n of this.rules.array)n.append&&(e=P(e,n.append(this.options)));return e.replace(/^[\t\r\n]+/,"").replace(/[\t\r\n\s]+$/,"")}replacementForNode(e){const n=this.rules.forNode(e);let r=this.process(e);const i=e.flankingWhitespace;return(i.leading||i.trailing)&&(r=r.trim()),i.leading+n.replacement(r,e,this.options)+i.trailing}}function P(t,e){const n=x(t),r=b(e),i=Math.max(t.length-n.length,e.length-r.length),s=`
66
+
67
+ `.substring(0,i);return n+s+r}function re(t){return t!=null&&(typeof t=="string"||t.nodeType&&(t.nodeType===1||t.nodeType===9||t.nodeType===11))}return ne}));
68
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/node.ts","../src/utilities.ts","../src/default-rules.ts","../src/rules.ts","../src/collapse-whitespace.ts","../src/html-parser.ts","../src/root-node.ts","../src/index.ts"],"sourcesContent":["import { isBlock, isVoid, hasVoid, isMeaningfulWhenBlank, hasMeaningfulWhenBlank } from '@/utilities'\n\ninterface Options {\n preformattedCode?: boolean;\n}\n\ninterface FlankingWhitespace {\n leading: string;\n trailing: string;\n}\n\ninterface EdgeWhitespace extends FlankingWhitespace {\n leadingAscii: string;\n leadingNonAscii: string;\n trailingNonAscii: string;\n trailingAscii: string;\n}\n\nexport interface ExtendedNode extends Element {\n isBlock: boolean;\n isCode: boolean;\n isBlank: boolean;\n flankingWhitespace: FlankingWhitespace;\n}\n\nexport function ExtendedNode(node: Node, options: Options): ExtendedNode {\n const extended = node as ExtendedNode;\n extended.isBlock = isBlock(extended);\n extended.isCode = extended.nodeName === 'CODE' || (extended.parentNode as ExtendedNode)?.isCode;\n extended.isBlank = isBlank(extended);\n extended.flankingWhitespace = flankingWhitespace(extended, options);\n return extended;\n}\n\nfunction isBlank(node: ExtendedNode): boolean {\n return (\n !isVoid(node) &&\n !isMeaningfulWhenBlank(node) &&\n /^\\s*$/i.test(node.textContent || '') &&\n !hasVoid(node) &&\n !hasMeaningfulWhenBlank(node)\n )\n}\n\nfunction flankingWhitespace(node: ExtendedNode, options: Options): FlankingWhitespace {\n const extendedNode = node as ExtendedNode;\n\n if (extendedNode.isBlock || (options.preformattedCode && extendedNode.isCode)) {\n return { leading: '', trailing: '' };\n }\n\n const edges = edgeWhitespace(node.textContent || '');\n\n // abandon leading ASCII WS if left-flanked by ASCII WS\n if (edges.leadingAscii && isFlankedByWhitespace('left', node, options)) {\n edges.leading = edges.leadingNonAscii;\n }\n\n // abandon trailing ASCII WS if right-flanked by ASCII WS\n if (edges.trailingAscii && isFlankedByWhitespace('right', node, options)) {\n edges.trailing = edges.trailingNonAscii;\n }\n\n return { leading: edges.leading, trailing: edges.trailing };\n}\n\nfunction edgeWhitespace(string: string): EdgeWhitespace {\n const m = string.match(/^(([ \\t\\r\\n]*)(\\s*))(?:(?=\\S)[\\s\\S]*\\S)?((\\s*?)([ \\t\\r\\n]*))$/);\n\n if (!m) {\n return {\n leading: '',\n leadingAscii: '',\n leadingNonAscii: '',\n trailing: '',\n trailingNonAscii: '',\n trailingAscii: ''\n };\n }\n\n return {\n leading: m[1], // whole string for whitespace-only strings\n leadingAscii: m[2],\n leadingNonAscii: m[3],\n trailing: m[4], // empty for whitespace-only strings\n trailingNonAscii: m[5],\n trailingAscii: m[6]\n };\n}\n\nfunction isFlankedByWhitespace(side: 'left' | 'right', node: Element, options: Options): boolean {\n let sibling: Element | null;\n let regExp: RegExp;\n let isFlanked: boolean | undefined;\n\n if (side === 'left') {\n sibling = node.previousElementSibling;\n regExp = / $/;\n } else {\n sibling = node.nextElementSibling;\n regExp = /^ /;\n }\n\n if (sibling) {\n if (sibling.nodeType === 3) {\n isFlanked = regExp.test(sibling.nodeValue || '');\n } else if (options.preformattedCode && sibling.nodeName === 'CODE') {\n isFlanked = false;\n } else if (sibling.nodeType === 1 && !isBlock(sibling)) {\n isFlanked = regExp.test(sibling.textContent || '');\n }\n }\n\n return isFlanked || false;\n}\n\nexport const NodeTypes = {\n Element: 1,\n Text: 3,\n CDATASection: 4,\n Comment: 8\n} as const;\n\nexport type NodeType = typeof NodeTypes[keyof typeof NodeTypes];\n","import { ExtendedNode, NodeTypes } from \"./node\";\n\nexport function repeat(character: string, count: number) {\n return Array(count + 1).join(character)\n}\n\nexport function trimLeadingNewlines(string: string) {\n return string.replace(/^\\n*/, '')\n}\n\nexport function trimTrailingNewlines(string: string) {\n // avoid match-at-end regexp bottleneck, see #370\n let indexEnd = string.length\n while (indexEnd > 0 && string[indexEnd - 1] === '\\n') indexEnd--\n return string.substring(0, indexEnd)\n}\n\nexport function trimNewlines(string: string) {\n return trimTrailingNewlines(trimLeadingNewlines(string))\n}\n\nexport const blockElements = [\n 'ADDRESS', 'ARTICLE', 'ASIDE', 'AUDIO', 'BLOCKQUOTE', 'BODY', 'CANVAS',\n 'CENTER', 'DD', 'DIR', 'DIV', 'DL', 'DT', 'FIELDSET', 'FIGCAPTION', 'FIGURE',\n 'FOOTER', 'FORM', 'FRAMESET', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEADER',\n 'HGROUP', 'HR', 'HTML', 'ISINDEX', 'LI', 'MAIN', 'MENU', 'NAV', 'NOFRAMES',\n 'NOSCRIPT', 'OL', 'OUTPUT', 'P', 'PRE', 'SECTION', 'TABLE', 'TBODY', 'TD',\n 'TFOOT', 'TH', 'THEAD', 'TR', 'UL'\n]\n\nexport function isBlock(node: Node) {\n return is(node, blockElements)\n}\n\nexport const voidElements = [\n 'AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT',\n 'KEYGEN', 'LINK', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR'\n]\n\nexport function isVoid(node: Node) {\n return is(node, voidElements)\n}\n\nexport function hasVoid(node: Node) {\n return has(node, voidElements)\n}\n\nconst meaningfulWhenBlankElements = [\n 'A', 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TH', 'TD', 'IFRAME', 'SCRIPT',\n 'AUDIO', 'VIDEO'\n]\n\nexport const standardMarkdownElements = [\n 'P', 'BR', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE',\n 'UL', 'OL', 'LI', 'PRE', 'CODE', 'HR', 'A', 'EM', 'I', 'STRONG',\n 'B', 'IMG', 'DIV', 'SPAN', 'TABLE', 'THEAD', 'TBODY', 'TR', 'TH', 'TD'\n]\n\nexport function isMeaningfulWhenBlank(node: Node) {\n return is(node, meaningfulWhenBlankElements)\n}\n\nexport function hasMeaningfulWhenBlank(node: Node) {\n return has(node, meaningfulWhenBlankElements)\n}\n\nfunction is(node: Node, tagNames: string[]) {\n return tagNames.indexOf(node.nodeName) >= 0\n}\n\nfunction has(node: Node, tagNames: string[]) {\n return (\n tagNames.some(function (tagName) {\n if (node.nodeType !== NodeTypes.Element) {\n return false;\n }\n return (node as Element).getElementsByTagName(tagName).length\n })\n )\n}\n\nexport function sanitizeWhitespace(string: string): string {\n return string ? string.replace(/(\\n+\\s*)+/g, '\\n') : '';\n}\n\nexport function sanitizedLinkContent(content: string): string {\n const sanitized = sanitizeWhitespace(content);\n return sanitized\n .replace(/[\\t\\r\\n]+/g, ' ')\n .replace(/ {2,}/g, ' ')\n .replace(/([()])/g, '\\\\$1')\n .trim();\n}\n\nexport function sanitizedLinkTitle(content: string): string {\n const sanitized = sanitizeWhitespace(content);\n return sanitized\n .replace(/[\\t\\r\\n]+/g, ' ');\n}\n\nexport type RequireOnly<T, K extends keyof T> =\n T & Required<Pick<T, K>>;\n","\nimport { Rule } from '@/rules';\nimport { TurnishOptions } from '@/index';\nimport { repeat, RequireOnly, sanitizedLinkContent, sanitizedLinkTitle, trimNewlines } from '@/utilities';\nimport { url } from 'inspector';\n\nexport const defaultRules: { [key: string]: Rule } = {}\n\ndefaultRules.paragraph = {\n filter: 'p',\n replacement: function (content: string): string {\n return '\\n\\n' + content + '\\n\\n';\n }\n};\n\ndefaultRules.lineBreak = {\n filter: 'br',\n replacement: function (_content: string, _node: Node, options: TurnishOptions): string {\n return options.br + '\\n';\n }\n};\n\ndefaultRules.heading = {\n filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],\n replacement: function (content: string, node: Node, options: TurnishOptions): string {\n const hLevel = Number(node.nodeName.charAt(1));\n if (options.headingStyle === 'setext' && hLevel < 3) {\n const underline = repeat((hLevel === 1 ? '=' : '-'), content.length);\n return (\n '\\n\\n' + content + '\\n' + underline + '\\n\\n'\n );\n } else {\n return '\\n\\n' + repeat('#', hLevel) + ' ' + content + '\\n\\n';\n }\n }\n};\n\ndefaultRules.blockquote = {\n filter: 'blockquote',\n replacement: function (content: string): string {\n content = trimNewlines(content).replace(/^/gm, '> ');\n return '\\n\\n' + content + '\\n\\n';\n }\n};\n\ndefaultRules.list = {\n filter: ['ul', 'ol'],\n replacement: function (content: string, node: Node): string {\n const parent = node.parentNode as Element;\n if (parent.nodeName === 'LI' && parent.lastElementChild === node) {\n return '\\n' + content;\n } else {\n return '\\n\\n' + content + '\\n\\n';\n }\n }\n};\n\ndefaultRules.listItem = {\n filter: 'li',\n replacement: function (content: string, node: Node, options: TurnishOptions): string {\n let prefix = options.bulletListMarker + ' ';\n const parent = node.parentNode as Element;\n if (parent.nodeName === 'OL') {\n const start = parent.getAttribute('start');\n const index = Array.prototype.indexOf.call(parent.children, node);\n prefix = (start ? Number(start) + index : index + 1) + '. ';\n }\n const isParagraph = /\\n$/.test(content);\n content = trimNewlines(content) + (isParagraph ? '\\n' : '');\n content = content.replace(/\\n/gm, '\\n' + ' '.repeat(prefix.length)); // indent\n return (\n prefix + content + (node.nextSibling ? '\\n' : '')\n );\n }\n};\n\ndefaultRules.indentedCodeBlock = {\n filter: function (node: Node, options: TurnishOptions): boolean {\n return !!(\n options &&\n options.codeBlockStyle === 'indented' &&\n node.nodeName === 'PRE' &&\n node.firstChild &&\n (node.firstChild as Element).nodeName === 'CODE'\n );\n },\n replacement: function (_content: string, node: Node): string {\n if (!node || !node.firstChild) return '';\n return (\n '\\n\\n ' +\n (node.firstChild as Element).textContent!.replace(/\\n/g, '\\n ') +\n '\\n\\n'\n );\n }\n};\n\ndefaultRules.fencedCodeBlock = {\n filter: function (node: Node, options: TurnishOptions): boolean {\n return !!(\n options &&\n options.codeBlockStyle === 'fenced' &&\n node.nodeName === 'PRE' &&\n node.firstChild &&\n (node.firstChild as Element).nodeName === 'CODE'\n );\n },\n replacement: function (_content: string, node: Node, options: TurnishOptions): string {\n if (!node.firstChild) {\n return '';\n }\n const codeElem = node.firstChild as Element;\n const className = codeElem.getAttribute('class') || '';\n const language = (className.match(/language-(\\S+)/) || [null, ''])[1];\n const code = codeElem.textContent || '';\n const fenceChar = options.fence?.charAt(0) || '`';\n let fenceSize = 3;\n const fenceInCodeRegex = new RegExp('^' + fenceChar + '{3,}', 'gm');\n let match;\n while ((match = fenceInCodeRegex.exec(code))) {\n if (match[0].length >= fenceSize) {\n fenceSize = match[0].length + 1;\n }\n }\n const fence = repeat(fenceChar, fenceSize);\n return (\n '\\n\\n' + fence + language + '\\n' +\n code.replace(/\\n$/, '') +\n '\\n' + fence + '\\n\\n'\n );\n }\n};\n\ndefaultRules.horizontalRule = {\n filter: 'hr',\n replacement: function (_content: string, _node: Node, options: TurnishOptions): string {\n return '\\n\\n' + options.hr + '\\n\\n';\n }\n};\n\ndefaultRules.inlineLink = {\n filter: function (node: Node, options: TurnishOptions): boolean {\n return !!(\n options?.linkStyle === 'inlined' &&\n node.nodeName === 'A' &&\n (node as Element).getAttribute('href')\n );\n },\n replacement: function (content: string, node: Node): string {\n const sanitizedContent = sanitizedLinkContent(content);\n let href = (node as Element)\n .getAttribute('href')\n ?.replace(/([()])/g, '\\\\$1');\n let title: string;\n const titleAttr = (node as Element).getAttribute('title');\n if (titleAttr) {\n const sanitizedTitle = sanitizedLinkTitle(titleAttr);\n title = ' \"' + sanitizedTitle.replace(/\"/g, '\\\\\"') + '\"';\n } else {\n title = '';\n }\n return '[' + sanitizedContent + '](' + href + title + ')';\n }\n};\n\nconst referenceLinkRule: RequireOnly<Rule, \"urlReferenceIdMap\" | \"references\"> = {\n filter: function (node: Node, options: TurnishOptions): boolean {\n return !!(\n options &&\n options.linkStyle === 'referenced' &&\n node.nodeName === 'A' &&\n (node as Element).getAttribute('href')\n );\n },\n replacement: function (content: string, node: Node, options: TurnishOptions): string {\n const self = referenceLinkRule;\n\n const href = (node as Element).getAttribute('href');\n let title: string;\n const titleAttr = (node as Element).getAttribute('title');\n if (titleAttr) {\n const sanitizedTitle = sanitizedLinkTitle(titleAttr);\n title = ' \"' + sanitizedTitle + '\"';\n } else {\n title = '';\n }\n const referenceKey = href + title;\n\n let replacement: string;\n let reference: string;\n switch (options.linkReferenceStyle) {\n case 'collapsed':\n replacement = '[' + content + '][]';\n reference = '[' + content + ']: ' + referenceKey;\n break;\n case 'shortcut':\n replacement = '[' + content + ']';\n reference = '[' + content + ']: ' + referenceKey;\n break;\n default: {\n let id: number;\n const existingKey = self.urlReferenceIdMap.get(referenceKey);\n if (options.linkReferenceDeduplication === 'full' && existingKey) {\n id = existingKey;\n reference = '[' + id + ']: ' + href + title;\n } else {\n id = self.references.length + 1;\n self.urlReferenceIdMap.set(referenceKey, id);\n reference = '[' + id + ']: ' + href + title;\n self.references.push(reference);\n }\n replacement = '[' + content + '][' + id + ']';\n break;\n }\n }\n\n if (options.linkReferenceStyle !== 'full') {\n // Check if we should deduplicate\n if (options.linkReferenceDeduplication === 'full') {\n if (!self.urlReferenceIdMap.has(referenceKey)) {\n self.urlReferenceIdMap.set(referenceKey, 1);\n self.references.push(reference);\n }\n } else {\n self.references.push(reference);\n }\n }\n return replacement;\n },\n references: [],\n urlReferenceIdMap: new Map<string, number>(),\n append: (): string => {\n const self = referenceLinkRule;\n let references = '';\n if (self.references && self.references.length) {\n references = '\\n\\n' + self.references.join('\\n') + '\\n\\n';\n self.references = [];\n self.urlReferenceIdMap = new Map();\n }\n return references;\n }\n};\n\ndefaultRules.referenceLink = referenceLinkRule;\n\ndefaultRules.emphasis = {\n filter: ['em', 'i'],\n replacement: (content: string, _node: Node, options: TurnishOptions): string => {\n content = content.trim();\n if (!content) { return ''; }\n return options.emDelimiter + content + options.emDelimiter;\n }\n};\n\ndefaultRules.strong = {\n filter: ['strong', 'b'],\n replacement: (content: string, _node: Node, options: TurnishOptions): string => {\n content = content.trim();\n if (!content) { return ''; }\n return options.strongDelimiter + content + options.strongDelimiter;\n }\n};\n\ndefaultRules.code = {\n filter: (node: Node): boolean => {\n const hasSiblings = node.previousSibling || node.nextSibling;\n const parent = node.parentNode as Element;\n const isCodeBlock = parent.nodeName === 'PRE' && !hasSiblings;\n return node.nodeName === 'CODE' && !isCodeBlock;\n },\n replacement: (content: string): string => {\n const trimmed = content.replace(/\\r?\\n|\\r/g, ' ');\n const extraSpace = /^`|^ .*?[^ ].* $|`$/.test(trimmed) ? ' ' : '';\n let delimiter = '`';\n const matches: string[] = trimmed.match(/`+/gm) || [];\n while (matches.includes(delimiter)) delimiter = delimiter + '`';\n return delimiter + extraSpace + trimmed + extraSpace + delimiter;\n }\n};\n\ndefaultRules.image = {\n filter: 'img',\n replacement: function (_content: string, node: Node): string {\n const altAttr = (node as Element).getAttribute('alt');\n const alt = altAttr ? sanitizedLinkTitle(altAttr) : '';\n const src = (node as Element).getAttribute('src') || '';\n const titleAttr = (node as Element).getAttribute('title');\n const title = titleAttr ? sanitizedLinkTitle(titleAttr) : '';\n const titlePart = title ? ' \"' + title + '\"' : '';\n return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : '';\n }\n};\n","/**\n * Manages a collection of rules used to convert HTML to Markdown\n */\nimport { ExtendedNode } from \"./node\";\nimport { TurnishOptions } from \"@/index\";\nimport { standardMarkdownElements } from \"./utilities\";\n\nexport type RuleFilterFunction = (node: ExtendedNode, options: TurnishOptions) => boolean;\nexport type RuleFilter = string | string[] | RuleFilterFunction;\n\ntype RuleReplacementFunction = (...args: any[]) => string;\n\nexport interface Rule {\n filter?: RuleFilter;\n replacement: RuleReplacementFunction | ((content: string, node: any, options: TurnishOptions, previousNode?: any) => string);\n references?: string[];\n /// Map of URL+title combinations to their reference IDs, used for link reference deduplication.\n /// When linkReferenceDeduplication is 'full', this tracks which URLs have already been assigned a reference number to avoid creating duplicate references.\n urlReferenceIdMap?: Map<string, number>;\n append?: (options: TurnishOptions) => string;\n}\n\nexport class Rules {\n options: TurnishOptions;\n private _keep: Rule[];\n private _remove: Rule[];\n blankRule: Rule;\n keepReplacement: RuleReplacementFunction;\n markdownIncludingHtmlReplacement: RuleReplacementFunction;\n defaultRule: Rule;\n array: Rule[];\n\n constructor(options: TurnishOptions) {\n this.options = options;\n this._keep = [];\n this._remove = [];\n\n this.blankRule = {\n replacement: options.blankReplacement\n };\n\n this.keepReplacement = options.keepReplacement;\n this.markdownIncludingHtmlReplacement = options.markdownIncludingHtmlReplacement;\n\n this.defaultRule = {\n replacement: options.defaultReplacement\n };\n\n this.array = [];\n for (const key in options.rules) {\n this.array.push(options.rules[key]);\n }\n }\n\n add(key: string, rule: Rule): void {\n this.array.unshift(rule);\n }\n\n keep(filter: RuleFilter): void {\n this._keep.unshift({\n filter: filter,\n replacement: this.keepReplacement\n });\n }\n\n remove(filter: RuleFilter): void {\n this._remove.unshift({\n filter: filter,\n replacement: function () {\n return '';\n }\n });\n }\n\n forNode(node: ExtendedNode): Rule {\n if (node.isBlank) {\n return this.blankRule;\n }\n if (this.options.htmlRetentionMode === 'preserveAll' && this.isUnsupportedElement(node)) {\n return {\n replacement: this.keepReplacement\n };\n }\n if (this.options.htmlRetentionMode === 'markdownIncludingHtml' && this.isUnsupportedElement(node)) {\n return {\n replacement: this.markdownIncludingHtmlReplacement\n };\n }\n\n let rule: Rule | undefined;\n if ((rule = findRule(this.array, node, this.options))) {\n return rule;\n }\n if ((rule = findRule(this._keep, node, this.options))) {\n return rule;\n }\n if ((rule = findRule(this._remove, node, this.options))) {\n return rule;\n }\n return this.defaultRule;\n }\n\n /// Check if an element is unsupported for Markdown conversion.\n private isUnsupportedElement(node: ExtendedNode): boolean {\n const nodeName = node.nodeName;\n\n if (nodeName === 'PRE' && node.firstChild && (node.firstChild as Element).nodeName === 'CODE') {\n const codeElem = node.firstChild as Element;\n if (codeElem.attributes && codeElem.attributes.length > 0) {\n for (let i = 0; i < codeElem.attributes.length; i++) {\n const attrName = codeElem.attributes[i].name.toLowerCase();\n if (attrName !== 'class') {\n return true;\n }\n }\n }\n }\n\n if (node.attributes && node.attributes.length > 0) {\n switch (nodeName) {\n case 'IMG':\n for (let i = 0; i < node.attributes.length; i++) {\n const attrName = node.attributes[i].name.toLowerCase();\n if (attrName !== 'src' && attrName !== 'alt' && attrName !== 'title') {\n return true;\n }\n }\n return false;\n case 'A':\n for (let i = 0; i < node.attributes.length; i++) {\n const attrName = node.attributes[i].name.toLowerCase();\n if (attrName !== 'href' && attrName !== 'title') {\n return true;\n }\n }\n return false;\n case 'CODE':\n const parent = node.parentNode as Element;\n if (parent && parent.nodeName === 'PRE') {\n for (let i = 0; i < node.attributes.length; i++) {\n const attrName = node.attributes[i].name.toLowerCase();\n if (attrName !== 'class') {\n return true;\n }\n }\n return false;\n }\n default:\n return true;\n }\n }\n // Elements that are not standard HTML elements are unsupported\n if (standardMarkdownElements.indexOf(nodeName) === -1) {\n return true;\n }\n return false;\n }\n\n forEach(fn: (rule: Rule, index: number) => void): void {\n for (let i = 0; i < this.array.length; i++) {\n fn(this.array[i], i);\n }\n }\n}\n\nfunction findRule(rules: Rule[], node: ExtendedNode, options: TurnishOptions): Rule | undefined {\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n if (filterValue(rule, node, options)) return rule;\n }\n return undefined;\n}\n\nfunction filterValue(rule: Rule, node: ExtendedNode, options: TurnishOptions): boolean {\n const filter = rule.filter;\n if (typeof filter === 'string') {\n if (filter === node.nodeName.toLowerCase()) {\n return true;\n }\n } else if (Array.isArray(filter)) {\n if (filter.indexOf(node.nodeName.toLowerCase()) > -1) {\n return true;\n }\n } else if (typeof filter === 'function') {\n if (filter(node, options)) {\n return true;\n }\n } else {\n throw new TypeError('`filter` needs to be a string, array, or function');\n }\n return false;\n}\n","/**\n * The collapseWhitespace function is adapted from collapse-whitespace\n * by Luc Thevenard.\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Luc Thevenard <lucthevenard@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport { NodeTypes } from \"./node\";\n\n/**\n * collapseWhitespace(options) removes extraneous whitespace from an the given element.\n *\n * @param {Object} options\n */\ninterface CollapseWhitespaceOptions {\n element: Node;\n isBlock: (node: Node) => boolean;\n isVoid: (node: Node) => boolean;\n isPre?: (node: Node) => boolean;\n}\n\nfunction collapseWhitespace(options: CollapseWhitespaceOptions): void {\n const element = options.element\n const isBlock = options.isBlock\n const isVoid = options.isVoid\n const isPre = options.isPre || function (node: Node): boolean {\n return node.nodeName === 'PRE';\n };\n\n if (!element.firstChild || isPre(element)) return\n\n let prevText: Text | null = null;\n let keepLeadingWs = false\n\n let prev: Node | null = null;\n let node: Node = next(prev, element, isPre);\n\n while (node !== element) {\n if (node.nodeType === NodeTypes.Text || node.nodeType === NodeTypes.CDATASection) {\n const textNode = node as Text;\n let text = textNode.data.replace(/[ \\r\\n\\t]+/g, ' ');\n\n if ((!prevText || / $/.test(prevText.data)) &&\n !keepLeadingWs && text[0] === ' ') {\n text = text.substr(1);\n }\n\n // `text` might be empty at this point.\n if (!text) {\n node = remove(node);\n continue;\n }\n\n textNode.data = text;\n\n prevText = textNode;\n } else if (node.nodeType === NodeTypes.Element) {\n if (isBlock(node) || node.nodeName === 'BR') {\n if (prevText) {\n prevText.data = prevText.data.replace(/ $/, '');\n }\n\n prevText = null;\n keepLeadingWs = false;\n } else if (isVoid(node) || isPre(node)) {\n // Avoid trimming space around non-block, non-BR void elements and inline PRE.\n prevText = null;\n keepLeadingWs = true;\n } else if (prevText) {\n // Drop protection if set previously.\n keepLeadingWs = false;\n }\n } else {\n node = remove(node);\n continue;\n }\n\n const nextNode = next(prev, node, isPre);\n prev = node;\n node = nextNode;\n }\n\n if (prevText) {\n prevText.data = prevText.data.replace(/ $/, '');\n if (!prevText.data) {\n remove(prevText);\n }\n }\n}\n\n/**\n * remove(node) removes the given node from the DOM and returns the\n * next node in the sequence.\n *\n * @param {Node} node\n * @return {Node} node\n */\nfunction remove(node: Node): Node {\n const nextNode: Node | null = node.nextSibling ?? node.parentNode;\n if (node.parentNode) {\n node.parentNode.removeChild(node);\n }\n return nextNode as Node;\n}\n\n/**\n * next(prev, current, isPre) returns the next node in the sequence, given the\n * current and previous nodes.\n *\n * @param {Node} prev\n * @param {Node} current\n * @param {Function} isPre\n * @return {Node}\n */\nfunction next(prev: Node | null, current: Node, isPre: (node: Node) => boolean): Node {\n if ((prev && prev.parentNode === current) || isPre(current)) {\n const nextNode: Node | null = current.nextSibling ?? current.parentNode;\n return nextNode as Node;\n }\n const nextNode: Node | null = current.firstChild ?? current.nextSibling ?? current.parentNode;\n return nextNode as Node;\n}\n\nexport default collapseWhitespace\n","/*\n * Set up window for Node.js\n */\n\nconst root: typeof globalThis = typeof window !== 'undefined' ? window : (typeof globalThis !== 'undefined' ? globalThis : {} as any)\n\n/*\n * Parsing HTML strings\n */\n\nfunction canParseHTMLNatively() {\n const Parser = typeof root.DOMParser !== 'undefined' ? root.DOMParser : undefined;\n let canParse = false;\n if (!Parser) return false;\n // Adapted from https://gist.github.com/1129031\n // Firefox/Opera/IE throw errors on unsupported types\n try {\n // WebKit returns null on unsupported types\n if (new Parser().parseFromString('', 'text/html')) {\n canParse = true;\n }\n } catch (e) { }\n return canParse;\n}\n\nexport class HTMLParser {\n // This will be assigned per environment below\n parseFromString(_input: string, _type?: string): Document {\n throw new Error('Not implemented')\n }\n}\n\nfunction createParser(): HTMLParser {\n const isBrowser =\n typeof window !== 'undefined' &&\n typeof document !== 'undefined' &&\n (typeof process === 'undefined' || (process as any).browser === true)\n\n if (typeof window !== 'undefined') {\n // Browser environment: use DOM API\n class HTMLParserBrowser extends HTMLParser {\n parseFromString(input: string, _type?: string): Document {\n const doc = document.implementation.createHTMLDocument('')\n doc.open()\n doc.write(input)\n doc.close()\n return doc\n }\n }\n return new HTMLParserBrowser()\n } else {\n const domino = require('@mixmark-io/domino') as {\n createDocument: (html: string) => Document\n }\n class HTMLParserNode extends HTMLParser {\n parseFromString(input: string, _type?: string): Document {\n return domino.createDocument(input);\n }\n }\n return new HTMLParserNode()\n }\n}\n\nexport const createHTMLParser = (): HTMLParser =>\n canParseHTMLNatively()\n ? new root.DOMParser()\n : createParser()\n","import collapseWhitespace from '@/collapse-whitespace'\nimport { createHTMLParser, HTMLParser } from '@/html-parser'\nimport { isBlock, isVoid } from '@/utilities'\n\ninterface RootNodeOptions {\n preformattedCode?: boolean\n}\n\nexport default function RootNode(\n input: string | Node,\n { preformattedCode }: RootNodeOptions\n): Element {\n let root: Element\n if (typeof input === 'string') {\n const doc = htmlParser().parseFromString(\n // DOM parsers arrange elements in the <head> and <body>.\n // Wrapping in a custom element ensures elements are reliably arranged in\n // a single element.\n '<x-turnish id=\"turnish-root\">' + input + '</x-turnish>',\n 'text/html'\n )\n root = doc.getElementById('turnish-root') as Element\n } else {\n root = input.cloneNode(true) as Element\n }\n collapseWhitespace({\n element: root,\n isBlock: isBlock,\n isVoid: isVoid,\n isPre: preformattedCode ? isPreOrCode : undefined\n })\n\n return root\n}\n\nlet _htmlParser: HTMLParser | undefined\nfunction htmlParser(): HTMLParser {\n return (_htmlParser ??= createHTMLParser())\n}\n\nfunction isPreOrCode(node: Node): boolean {\n return node.nodeName === 'PRE' || node.nodeName === 'CODE';\n}\n","import { defaultRules } from '@/default-rules'\nimport { Rules, Rule, RuleFilter } from '@/rules'\nimport { trimLeadingNewlines, trimTrailingNewlines } from '@/utilities'\nimport RootNode from '@/root-node'\nimport { ExtendedNode, NodeTypes } from '@/node';\nconst reduce = Array.prototype.reduce\n\ntype EscapeRule = [RegExp, string];\n\nconst escapes: EscapeRule[] = [\n [/\\\\/g, '\\\\\\\\'],\n [/\\*/g, '\\\\*'],\n [/_/g, '\\\\_'],\n [/^-/g, '\\\\-'],\n [/^\\+ /g, '\\\\+ '],\n [/^(=+)/g, '\\\\$1'],\n [/^(#{1,6}) /g, '\\\\$1 '],\n [/`/g, '\\\\`'],\n [/^~~~/g, '\\\\~~~'],\n [/\\[/g, '\\\\['],\n [/\\]/g, '\\\\]'],\n [/<([^>]*)>/g, '\\\\<$1\\\\>'],\n [/^>/g, '\\\\>'],\n [/^(\\d+)\\. /g, '$1\\\\. ']\n];\n\ntype Plugin = (service: Turnish) => void;\n\nexport interface TurnishOptions {\n rules?: { [key: string]: Rule };\n headingStyle?: 'setext' | 'atx';\n hr?: string;\n bulletListMarker?: '*' | '-' | '+';\n codeBlockStyle?: 'indented' | 'fenced';\n fence?: string;\n emDelimiter?: '_' | '*';\n strongDelimiter?: '**' | '__';\n linkStyle?: 'inlined' | 'referenced';\n linkReferenceStyle?: 'full' | 'collapsed' | 'shortcut';\n linkReferenceDeduplication?: 'none' | 'full';\n br?: string;\n preformattedCode?: boolean;\n htmlRetentionMode?: 'standard' | 'preserveAll' | 'markdownIncludingHtml';\n blankReplacement: (content: string, node: ExtendedNode) => string;\n keepReplacement: (content: string, node: ExtendedNode) => string;\n markdownIncludingHtmlReplacement: (content: string, node: ExtendedNode) => string;\n defaultReplacement: (content: string, node: ExtendedNode) => string;\n [key: string]: any;\n}\n\n\nconst defaultOptions: TurnishOptions = {\n rules: defaultRules,\n headingStyle: 'atx',\n hr: '---',\n bulletListMarker: '-',\n codeBlockStyle: 'fenced',\n fence: '```',\n emDelimiter: '*',\n strongDelimiter: '**',\n linkStyle: 'inlined',\n linkReferenceStyle: 'full',\n linkReferenceDeduplication: 'full',\n br: ' ',\n preformattedCode: false,\n htmlRetentionMode: 'standard',\n blankReplacement: (content: string, node: ExtendedNode): string => {\n return node.isBlock ? '\\n\\n' : '';\n },\n keepReplacement: (content: string, node: ExtendedNode): string => {\n return node.isBlock ? '\\n\\n' + node.outerHTML + '\\n\\n' : node.outerHTML;\n },\n markdownIncludingHtmlReplacement: (content: string, node: ExtendedNode): string => {\n const tagName = node.nodeName.toLowerCase();\n\n let attributes = '';\n if (node.attributes && node.attributes.length > 0) {\n const attrs: string[] = [];\n for (let i = 0; i < node.attributes.length; i++) {\n const attr = node.attributes[i];\n attrs.push(`${attr.name}=\"${attr.value}\"`);\n }\n attributes = ' ' + attrs.join(' ');\n }\n\n attributes += ' markdown=\"1\"';\n\n const openTag = `<${tagName}${attributes}>`;\n const closeTag = `</${tagName}>`;\n\n const trimmedContent = content.trim();\n const html = openTag + '\\n' + trimmedContent + '\\n' + closeTag;\n\n return node.isBlock ? '\\n\\n' + html + '\\n\\n' : html;\n },\n defaultReplacement: function (content: string, node: ExtendedNode): string {\n return node.isBlock ? '\\n\\n' + content + '\\n\\n' : content;\n }\n};\n\nexport default class Turnish {\n options: TurnishOptions;\n rules: Rules;\n\n constructor(options?: Partial<TurnishOptions>) {\n this.options = Object.assign({}, defaultOptions, options);\n this.rules = new Rules(this.options);\n }\n\n /**\n * The entry point for converting a string or DOM node to Markdown\n * @public\n * @param {InputType} input The string or DOM node to convert\n * @returns A Markdown representation of the input\n * @type string\n */\n render(input: InputType): string {\n if (!canConvert(input)) {\n throw new TypeError(\n input + ' is not a string, or an element/document/fragment node.'\n );\n }\n if (input === '') {\n return '';\n }\n const output = this.process(RootNode(input, this.options));\n return this.postProcess(output);\n }\n\n /**\n * Add one or more plugins\n * @public\n * @param {Plugin|Plugin[]} plugin The plugin or array of plugins to add\n * @returns The Turnish instance for chaining\n * @type Object\n */\n use(plugin: Plugin | Plugin[]): Turnish {\n if (Array.isArray(plugin)) {\n for (let i = 0; i < plugin.length; i++) this.use(plugin[i]);\n } else if (typeof plugin === 'function') {\n plugin(this);\n } else {\n throw new TypeError('plugin must be a Function or an Array of Functions');\n }\n return this;\n }\n\n /**\n * Adds a rule\n * @public\n * @param {string} key The unique key of the rule\n * @param {Object} rule The rule\n * @returns The Turnish instance for chaining\n * @type Object\n */\n addRule(key: string, rule: Rule): Turnish {\n this.rules.add(key, rule);\n return this;\n }\n\n /**\n * Keep a node (as HTML) that matches the filter\n * @public\n * @param {RuleFilter} filter The unique key of the rule\n * @returns The Turnish instance for chaining\n * @type Object\n */\n keep(filter: RuleFilter): Turnish {\n this.rules.keep(filter);\n return this;\n }\n\n /**\n * Remove a node that matches the filter\n * @public\n * @param {string|Array|Function} filter The unique key of the rule\n * @returns The Turnish instance for chaining\n * @type Object\n */\n remove(filter: RuleFilter): Turnish {\n this.rules.remove(filter);\n return this;\n }\n\n /**\n * Escapes Markdown syntax\n * @public\n * @param {string} string The string to escape\n * @returns A string with Markdown syntax escaped\n * @type string\n */\n escape(string: string): string {\n return escapes.reduce(function (accumulator: string, escape: EscapeRule) {\n return accumulator.replace(escape[0], escape[1]);\n }, string);\n }\n\n\n /**\n * Reduces a DOM node down to its Markdown string equivalent\n * @private\n * @param {HTMLElement} parentNode The node to convert\n * @returns A Markdown representation of the node\n * @type string\n */\n process(this: Turnish, parentNode: Node): string {\n return Array.from(parentNode.childNodes).reduce((output, node) => {\n const extended = ExtendedNode(node, this.options);\n let replacement = '';\n if (extended.nodeType === NodeTypes.Text) {\n const value = extended.nodeValue ?? ''; // ensure a string\n replacement = extended.isCode ? value : this.escape(value);\n } else if (extended.nodeType === NodeTypes.Element) {\n replacement = this.replacementForNode(extended);\n }\n return join(output, replacement);\n }, '');\n }\n\n /**\n * Appends strings as each rule requires and trims the output\n * @private\n * @param {string} output The conversion output\n * @returns A trimmed version of the ouput\n * @type string\n */\n postProcess(output: string): string {\n for (const rule of this.rules.array) {\n if (rule.append) {\n output = join(output, rule.append(this.options))\n }\n }\n return output\n .replace(/^[\\t\\r\\n]+/, '')\n .replace(/[\\t\\r\\n\\s]+$/, '')\n }\n\n\n /**\n * Converts an element node to its Markdown equivalent\n * @private\n * @param {ExtendedNode} node The node to convert\n * @returns A Markdown representation of the node\n * @type string\n */\n replacementForNode(node: ExtendedNode) {\n const rule = this.rules.forNode(node)\n let content = this.process(node)\n const whitespace = node.flankingWhitespace\n if (whitespace.leading || whitespace.trailing) {\n content = content.trim()\n }\n return (\n whitespace.leading +\n rule.replacement(content, node, this.options) +\n whitespace.trailing\n )\n }\n}\n\n/**\n * Joins replacement to the current output with appropriate number of new lines\n * @private\n * @param {string} output The current conversion output\n * @param {string} replacement The string to append to the output\n * @returns Joined output\n * @type string\n */\nfunction join(output: string, replacement: string): string {\n const s1 = trimTrailingNewlines(output)\n const s2 = trimLeadingNewlines(replacement)\n const nls = Math.max(output.length - s1.length, replacement.length - s2.length)\n const separator = '\\n\\n'.substring(0, nls)\n\n return s1 + separator + s2\n}\n\n/**\n * Determines whether an input can be converted\n * @private\n * @param {string|HTMLElement} input Describe this parameter\n * @returns Describe what it returns\n * @type string|Object|Array|Boolean|Number\n */\ntype InputType = string | HTMLElement | Document | DocumentFragment;\nfunction canConvert(input: any): input is InputType {\n return (\n input != null && (\n typeof input === 'string' ||\n (input.nodeType && (\n input.nodeType === 1 || input.nodeType === 9 || input.nodeType === 11\n ))\n )\n );\n}\n"],"names":["ExtendedNode","node","options","extended","isBlock","isBlank","flankingWhitespace","isVoid","isMeaningfulWhenBlank","hasVoid","hasMeaningfulWhenBlank","extendedNode","edges","edgeWhitespace","isFlankedByWhitespace","string","m","side","sibling","regExp","isFlanked","NodeTypes","repeat","character","count","trimLeadingNewlines","trimTrailingNewlines","indexEnd","trimNewlines","blockElements","is","voidElements","has","meaningfulWhenBlankElements","standardMarkdownElements","tagNames","tagName","sanitizeWhitespace","sanitizedLinkContent","content","sanitizedLinkTitle","defaultRules","_content","_node","hLevel","underline","parent","prefix","start","index","isParagraph","codeElem","language","code","fenceChar","fenceSize","fenceInCodeRegex","match","fence","sanitizedContent","href","title","titleAttr","referenceLinkRule","self","referenceKey","replacement","reference","id","existingKey","references","hasSiblings","isCodeBlock","trimmed","extraSpace","delimiter","matches","altAttr","alt","src","titlePart","Rules","key","rule","filter","findRule","nodeName","attrName","fn","i","rules","filterValue","collapseWhitespace","element","isPre","prevText","keepLeadingWs","prev","next","textNode","text","remove","nextNode","current","root","canParseHTMLNatively","Parser","canParse","HTMLParser","_input","_type","createParser","HTMLParserBrowser","input","doc","domino","HTMLParserNode","createHTMLParser","RootNode","preformattedCode","htmlParser","isPreOrCode","_htmlParser","escapes","defaultOptions","attributes","attrs","attr","openTag","closeTag","trimmedContent","html","Turnish","canConvert","output","plugin","accumulator","escape","parentNode","value","join","whitespace","s1","s2","nls","separator"],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The collapseWhitespace function is adapted from collapse-whitespace
3
+ * by Luc Thevenard.
4
+ *
5
+ * The MIT License (MIT)
6
+ *
7
+ * Copyright (c) 2014 Luc Thevenard <lucthevenard@gmail.com>
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ * of this software and associated documentation files (the "Software"), to deal
11
+ * in the Software without restriction, including without limitation the rights
12
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ * copies of the Software, and to permit persons to whom the Software is
14
+ * furnished to do so, subject to the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be included in
17
+ * all copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ * THE SOFTWARE.
26
+ */
27
+ /**
28
+ * collapseWhitespace(options) removes extraneous whitespace from an the given element.
29
+ *
30
+ * @param {Object} options
31
+ */
32
+ interface CollapseWhitespaceOptions {
33
+ element: Node;
34
+ isBlock: (node: Node) => boolean;
35
+ isVoid: (node: Node) => boolean;
36
+ isPre?: (node: Node) => boolean;
37
+ }
38
+ declare function collapseWhitespace(options: CollapseWhitespaceOptions): void;
39
+ export default collapseWhitespace;
@@ -0,0 +1,4 @@
1
+ import { Rule } from './rules';
2
+ export declare const defaultRules: {
3
+ [key: string]: Rule;
4
+ };
@@ -0,0 +1,4 @@
1
+ export declare class HTMLParser {
2
+ parseFromString(_input: string, _type?: string): Document;
3
+ }
4
+ export declare const createHTMLParser: () => HTMLParser;
@@ -0,0 +1,113 @@
1
+ import { Rules, Rule, RuleFilter } from './rules';
2
+ import { ExtendedNode } from './node';
3
+ type Plugin = (service: Turnish) => void;
4
+ export interface TurnishOptions {
5
+ rules?: {
6
+ [key: string]: Rule;
7
+ };
8
+ headingStyle?: 'setext' | 'atx';
9
+ hr?: string;
10
+ bulletListMarker?: '*' | '-' | '+';
11
+ codeBlockStyle?: 'indented' | 'fenced';
12
+ fence?: string;
13
+ emDelimiter?: '_' | '*';
14
+ strongDelimiter?: '**' | '__';
15
+ linkStyle?: 'inlined' | 'referenced';
16
+ linkReferenceStyle?: 'full' | 'collapsed' | 'shortcut';
17
+ linkReferenceDeduplication?: 'none' | 'full';
18
+ br?: string;
19
+ preformattedCode?: boolean;
20
+ htmlRetentionMode?: 'standard' | 'preserveAll' | 'markdownIncludingHtml';
21
+ blankReplacement: (content: string, node: ExtendedNode) => string;
22
+ keepReplacement: (content: string, node: ExtendedNode) => string;
23
+ markdownIncludingHtmlReplacement: (content: string, node: ExtendedNode) => string;
24
+ defaultReplacement: (content: string, node: ExtendedNode) => string;
25
+ [key: string]: any;
26
+ }
27
+ export default class Turnish {
28
+ options: TurnishOptions;
29
+ rules: Rules;
30
+ constructor(options?: Partial<TurnishOptions>);
31
+ /**
32
+ * The entry point for converting a string or DOM node to Markdown
33
+ * @public
34
+ * @param {InputType} input The string or DOM node to convert
35
+ * @returns A Markdown representation of the input
36
+ * @type string
37
+ */
38
+ render(input: InputType): string;
39
+ /**
40
+ * Add one or more plugins
41
+ * @public
42
+ * @param {Plugin|Plugin[]} plugin The plugin or array of plugins to add
43
+ * @returns The Turnish instance for chaining
44
+ * @type Object
45
+ */
46
+ use(plugin: Plugin | Plugin[]): Turnish;
47
+ /**
48
+ * Adds a rule
49
+ * @public
50
+ * @param {string} key The unique key of the rule
51
+ * @param {Object} rule The rule
52
+ * @returns The Turnish instance for chaining
53
+ * @type Object
54
+ */
55
+ addRule(key: string, rule: Rule): Turnish;
56
+ /**
57
+ * Keep a node (as HTML) that matches the filter
58
+ * @public
59
+ * @param {RuleFilter} filter The unique key of the rule
60
+ * @returns The Turnish instance for chaining
61
+ * @type Object
62
+ */
63
+ keep(filter: RuleFilter): Turnish;
64
+ /**
65
+ * Remove a node that matches the filter
66
+ * @public
67
+ * @param {string|Array|Function} filter The unique key of the rule
68
+ * @returns The Turnish instance for chaining
69
+ * @type Object
70
+ */
71
+ remove(filter: RuleFilter): Turnish;
72
+ /**
73
+ * Escapes Markdown syntax
74
+ * @public
75
+ * @param {string} string The string to escape
76
+ * @returns A string with Markdown syntax escaped
77
+ * @type string
78
+ */
79
+ escape(string: string): string;
80
+ /**
81
+ * Reduces a DOM node down to its Markdown string equivalent
82
+ * @private
83
+ * @param {HTMLElement} parentNode The node to convert
84
+ * @returns A Markdown representation of the node
85
+ * @type string
86
+ */
87
+ process(this: Turnish, parentNode: Node): string;
88
+ /**
89
+ * Appends strings as each rule requires and trims the output
90
+ * @private
91
+ * @param {string} output The conversion output
92
+ * @returns A trimmed version of the ouput
93
+ * @type string
94
+ */
95
+ postProcess(output: string): string;
96
+ /**
97
+ * Converts an element node to its Markdown equivalent
98
+ * @private
99
+ * @param {ExtendedNode} node The node to convert
100
+ * @returns A Markdown representation of the node
101
+ * @type string
102
+ */
103
+ replacementForNode(node: ExtendedNode): string;
104
+ }
105
+ /**
106
+ * Determines whether an input can be converted
107
+ * @private
108
+ * @param {string|HTMLElement} input Describe this parameter
109
+ * @returns Describe what it returns
110
+ * @type string|Object|Array|Boolean|Number
111
+ */
112
+ type InputType = string | HTMLElement | Document | DocumentFragment;
113
+ export {};
@@ -0,0 +1,22 @@
1
+ interface Options {
2
+ preformattedCode?: boolean;
3
+ }
4
+ interface FlankingWhitespace {
5
+ leading: string;
6
+ trailing: string;
7
+ }
8
+ export interface ExtendedNode extends Element {
9
+ isBlock: boolean;
10
+ isCode: boolean;
11
+ isBlank: boolean;
12
+ flankingWhitespace: FlankingWhitespace;
13
+ }
14
+ export declare function ExtendedNode(node: Node, options: Options): ExtendedNode;
15
+ export declare const NodeTypes: {
16
+ readonly Element: 1;
17
+ readonly Text: 3;
18
+ readonly CDATASection: 4;
19
+ readonly Comment: 8;
20
+ };
21
+ export type NodeType = typeof NodeTypes[keyof typeof NodeTypes];
22
+ export {};
@@ -0,0 +1,5 @@
1
+ interface RootNodeOptions {
2
+ preformattedCode?: boolean;
3
+ }
4
+ export default function RootNode(input: string | Node, { preformattedCode }: RootNodeOptions): Element;
5
+ export {};