UNPKG

mermaid

Version:

Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.

4 lines 212 kB
{ "version": 3, "sources": ["../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/icon/defaults.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/customisations/defaults.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/icon/name.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/icon/transformations.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/icon/merge.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/icon-set/tree.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/icon-set/get-icon.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/svg/size.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/svg/defs.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/svg/build.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/svg/id.js", "../../../../../node_modules/.pnpm/@iconify+utils@3.0.2/node_modules/@iconify/utils/lib/svg/html.js", "../../../src/rendering-util/icons.ts", "../../../../../node_modules/.pnpm/ts-dedent@2.2.0/node_modules/ts-dedent/src/index.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/defaults.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/rules.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/helpers.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/Tokenizer.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/Lexer.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/Renderer.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/TextRenderer.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/Parser.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/Hooks.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/Instance.ts", "../../../../../node_modules/.pnpm/marked@16.3.0/node_modules/marked/src/marked.ts", "../../../src/rendering-util/handle-markdown-text.ts", "../../../src/rendering-util/splitText.ts", "../../../src/rendering-util/createText.ts"], "sourcesContent": ["/**\n* Default values for dimensions\n*/\nconst defaultIconDimensions = Object.freeze({\n\tleft: 0,\n\ttop: 0,\n\twidth: 16,\n\theight: 16\n});\n/**\n* Default values for transformations\n*/\nconst defaultIconTransformations = Object.freeze({\n\trotate: 0,\n\tvFlip: false,\n\thFlip: false\n});\n/**\n* Default values for all optional IconifyIcon properties\n*/\nconst defaultIconProps = Object.freeze({\n\t...defaultIconDimensions,\n\t...defaultIconTransformations\n});\n/**\n* Default values for all properties used in ExtendedIconifyIcon\n*/\nconst defaultExtendedIconProps = Object.freeze({\n\t...defaultIconProps,\n\tbody: \"\",\n\thidden: false\n});\n\nexport { defaultExtendedIconProps, defaultIconDimensions, defaultIconProps, defaultIconTransformations };", "import { defaultIconTransformations } from \"../icon/defaults.js\";\n\n/**\n* Default icon customisations values\n*/\nconst defaultIconSizeCustomisations = Object.freeze({\n\twidth: null,\n\theight: null\n});\nconst defaultIconCustomisations = Object.freeze({\n\t...defaultIconSizeCustomisations,\n\t...defaultIconTransformations\n});\n\nexport { defaultIconCustomisations, defaultIconSizeCustomisations };", "/**\n* Expression to test part of icon name.\n*\n* Used when loading icons from Iconify API due to project naming convension.\n* Ignored when using custom icon sets - convension does not apply.\n*/\nconst matchIconName = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n/**\n* Convert string icon name to IconifyIconName object.\n*/\nconst stringToIcon = (value, validate, allowSimpleName, provider = \"\") => {\n\tconst colonSeparated = value.split(\":\");\n\tif (value.slice(0, 1) === \"@\") {\n\t\tif (colonSeparated.length < 2 || colonSeparated.length > 3) return null;\n\t\tprovider = colonSeparated.shift().slice(1);\n\t}\n\tif (colonSeparated.length > 3 || !colonSeparated.length) return null;\n\tif (colonSeparated.length > 1) {\n\t\tconst name$1 = colonSeparated.pop();\n\t\tconst prefix = colonSeparated.pop();\n\t\tconst result = {\n\t\t\tprovider: colonSeparated.length > 0 ? colonSeparated[0] : provider,\n\t\t\tprefix,\n\t\t\tname: name$1\n\t\t};\n\t\treturn validate && !validateIconName(result) ? null : result;\n\t}\n\tconst name = colonSeparated[0];\n\tconst dashSeparated = name.split(\"-\");\n\tif (dashSeparated.length > 1) {\n\t\tconst result = {\n\t\t\tprovider,\n\t\t\tprefix: dashSeparated.shift(),\n\t\t\tname: dashSeparated.join(\"-\")\n\t\t};\n\t\treturn validate && !validateIconName(result) ? null : result;\n\t}\n\tif (allowSimpleName && provider === \"\") {\n\t\tconst result = {\n\t\t\tprovider,\n\t\t\tprefix: \"\",\n\t\t\tname\n\t\t};\n\t\treturn validate && !validateIconName(result, allowSimpleName) ? null : result;\n\t}\n\treturn null;\n};\n/**\n* Check if icon is valid.\n*\n* This function is not part of stringToIcon because validation is not needed for most code.\n*/\nconst validateIconName = (icon, allowSimpleName) => {\n\tif (!icon) return false;\n\treturn !!((allowSimpleName && icon.prefix === \"\" || !!icon.prefix) && !!icon.name);\n};\n\nexport { matchIconName, stringToIcon, validateIconName };", "/**\n* Merge transformations\n*/\nfunction mergeIconTransformations(obj1, obj2) {\n\tconst result = {};\n\tif (!obj1.hFlip !== !obj2.hFlip) result.hFlip = true;\n\tif (!obj1.vFlip !== !obj2.vFlip) result.vFlip = true;\n\tconst rotate = ((obj1.rotate || 0) + (obj2.rotate || 0)) % 4;\n\tif (rotate) result.rotate = rotate;\n\treturn result;\n}\n\nexport { mergeIconTransformations };", "import { defaultExtendedIconProps, defaultIconTransformations } from \"./defaults.js\";\nimport { mergeIconTransformations } from \"./transformations.js\";\n\n/**\n* Merge icon and alias\n*\n* Can also be used to merge default values and icon\n*/\nfunction mergeIconData(parent, child) {\n\tconst result = mergeIconTransformations(parent, child);\n\tfor (const key in defaultExtendedIconProps) if (key in defaultIconTransformations) {\n\t\tif (key in parent && !(key in result)) result[key] = defaultIconTransformations[key];\n\t} else if (key in child) result[key] = child[key];\n\telse if (key in parent) result[key] = parent[key];\n\treturn result;\n}\n\nexport { mergeIconData };", "/**\n* Resolve icon set icons\n*\n* Returns parent icon for each icon\n*/\nfunction getIconsTree(data, names) {\n\tconst icons = data.icons;\n\tconst aliases = data.aliases || Object.create(null);\n\tconst resolved = Object.create(null);\n\tfunction resolve(name) {\n\t\tif (icons[name]) return resolved[name] = [];\n\t\tif (!(name in resolved)) {\n\t\t\tresolved[name] = null;\n\t\t\tconst parent = aliases[name] && aliases[name].parent;\n\t\t\tconst value = parent && resolve(parent);\n\t\t\tif (value) resolved[name] = [parent].concat(value);\n\t\t}\n\t\treturn resolved[name];\n\t}\n\t(names || Object.keys(icons).concat(Object.keys(aliases))).forEach(resolve);\n\treturn resolved;\n}\n\nexport { getIconsTree };", "import { mergeIconData } from \"../icon/merge.js\";\nimport { getIconsTree } from \"./tree.js\";\n\n/**\n* Get icon data, using prepared aliases tree\n*/\nfunction internalGetIconData(data, name, tree) {\n\tconst icons = data.icons;\n\tconst aliases = data.aliases || Object.create(null);\n\tlet currentProps = {};\n\tfunction parse(name$1) {\n\t\tcurrentProps = mergeIconData(icons[name$1] || aliases[name$1], currentProps);\n\t}\n\tparse(name);\n\ttree.forEach(parse);\n\treturn mergeIconData(data, currentProps);\n}\n/**\n* Get data for icon\n*/\nfunction getIconData(data, name) {\n\tif (data.icons[name]) return internalGetIconData(data, name, []);\n\tconst tree = getIconsTree(data, [name])[name];\n\treturn tree ? internalGetIconData(data, name, tree) : null;\n}\n\nexport { getIconData, internalGetIconData };", "/**\n* Regular expressions for calculating dimensions\n*/\nconst unitsSplit = /(-?[0-9.]*[0-9]+[0-9.]*)/g;\nconst unitsTest = /^-?[0-9.]*[0-9]+[0-9.]*$/g;\nfunction calculateSize(size, ratio, precision) {\n\tif (ratio === 1) return size;\n\tprecision = precision || 100;\n\tif (typeof size === \"number\") return Math.ceil(size * ratio * precision) / precision;\n\tif (typeof size !== \"string\") return size;\n\tconst oldParts = size.split(unitsSplit);\n\tif (oldParts === null || !oldParts.length) return size;\n\tconst newParts = [];\n\tlet code = oldParts.shift();\n\tlet isNumber = unitsTest.test(code);\n\twhile (true) {\n\t\tif (isNumber) {\n\t\t\tconst num = parseFloat(code);\n\t\t\tif (isNaN(num)) newParts.push(code);\n\t\t\telse newParts.push(Math.ceil(num * ratio * precision) / precision);\n\t\t} else newParts.push(code);\n\t\tcode = oldParts.shift();\n\t\tif (code === void 0) return newParts.join(\"\");\n\t\tisNumber = !isNumber;\n\t}\n}\n\nexport { calculateSize };", "function splitSVGDefs(content, tag = \"defs\") {\n\tlet defs = \"\";\n\tconst index = content.indexOf(\"<\" + tag);\n\twhile (index >= 0) {\n\t\tconst start = content.indexOf(\">\", index);\n\t\tconst end = content.indexOf(\"</\" + tag);\n\t\tif (start === -1 || end === -1) break;\n\t\tconst endEnd = content.indexOf(\">\", end);\n\t\tif (endEnd === -1) break;\n\t\tdefs += content.slice(start + 1, end).trim();\n\t\tcontent = content.slice(0, index).trim() + content.slice(endEnd + 1);\n\t}\n\treturn {\n\t\tdefs,\n\t\tcontent\n\t};\n}\n/**\n* Merge defs and content\n*/\nfunction mergeDefsAndContent(defs, content) {\n\treturn defs ? \"<defs>\" + defs + \"</defs>\" + content : content;\n}\n/**\n* Wrap SVG content, without wrapping definitions\n*/\nfunction wrapSVGContent(body, start, end) {\n\tconst split = splitSVGDefs(body);\n\treturn mergeDefsAndContent(split.defs, start + split.content + end);\n}\n\nexport { mergeDefsAndContent, splitSVGDefs, wrapSVGContent };", "import { defaultIconProps } from \"../icon/defaults.js\";\nimport { defaultIconCustomisations } from \"../customisations/defaults.js\";\nimport { calculateSize } from \"./size.js\";\nimport { wrapSVGContent } from \"./defs.js\";\n\n/**\n* Check if value should be unset. Allows multiple keywords\n*/\nconst isUnsetKeyword = (value) => value === \"unset\" || value === \"undefined\" || value === \"none\";\n/**\n* Get SVG attributes and content from icon + customisations\n*\n* Does not generate style to make it compatible with frameworks that use objects for style, such as React.\n* Instead, it generates 'inline' value. If true, rendering engine should add verticalAlign: -0.125em to icon.\n*\n* Customisations should be normalised by platform specific parser.\n* Result should be converted to <svg> by platform specific parser.\n* Use replaceIDs to generate unique IDs for body.\n*/\nfunction iconToSVG(icon, customisations) {\n\tconst fullIcon = {\n\t\t...defaultIconProps,\n\t\t...icon\n\t};\n\tconst fullCustomisations = {\n\t\t...defaultIconCustomisations,\n\t\t...customisations\n\t};\n\tconst box = {\n\t\tleft: fullIcon.left,\n\t\ttop: fullIcon.top,\n\t\twidth: fullIcon.width,\n\t\theight: fullIcon.height\n\t};\n\tlet body = fullIcon.body;\n\t[fullIcon, fullCustomisations].forEach((props) => {\n\t\tconst transformations = [];\n\t\tconst hFlip = props.hFlip;\n\t\tconst vFlip = props.vFlip;\n\t\tlet rotation = props.rotate;\n\t\tif (hFlip) if (vFlip) rotation += 2;\n\t\telse {\n\t\t\ttransformations.push(\"translate(\" + (box.width + box.left).toString() + \" \" + (0 - box.top).toString() + \")\");\n\t\t\ttransformations.push(\"scale(-1 1)\");\n\t\t\tbox.top = box.left = 0;\n\t\t}\n\t\telse if (vFlip) {\n\t\t\ttransformations.push(\"translate(\" + (0 - box.left).toString() + \" \" + (box.height + box.top).toString() + \")\");\n\t\t\ttransformations.push(\"scale(1 -1)\");\n\t\t\tbox.top = box.left = 0;\n\t\t}\n\t\tlet tempValue;\n\t\tif (rotation < 0) rotation -= Math.floor(rotation / 4) * 4;\n\t\trotation = rotation % 4;\n\t\tswitch (rotation) {\n\t\t\tcase 1:\n\t\t\t\ttempValue = box.height / 2 + box.top;\n\t\t\t\ttransformations.unshift(\"rotate(90 \" + tempValue.toString() + \" \" + tempValue.toString() + \")\");\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\ttransformations.unshift(\"rotate(180 \" + (box.width / 2 + box.left).toString() + \" \" + (box.height / 2 + box.top).toString() + \")\");\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\ttempValue = box.width / 2 + box.left;\n\t\t\t\ttransformations.unshift(\"rotate(-90 \" + tempValue.toString() + \" \" + tempValue.toString() + \")\");\n\t\t\t\tbreak;\n\t\t}\n\t\tif (rotation % 2 === 1) {\n\t\t\tif (box.left !== box.top) {\n\t\t\t\ttempValue = box.left;\n\t\t\t\tbox.left = box.top;\n\t\t\t\tbox.top = tempValue;\n\t\t\t}\n\t\t\tif (box.width !== box.height) {\n\t\t\t\ttempValue = box.width;\n\t\t\t\tbox.width = box.height;\n\t\t\t\tbox.height = tempValue;\n\t\t\t}\n\t\t}\n\t\tif (transformations.length) body = wrapSVGContent(body, \"<g transform=\\\"\" + transformations.join(\" \") + \"\\\">\", \"</g>\");\n\t});\n\tconst customisationsWidth = fullCustomisations.width;\n\tconst customisationsHeight = fullCustomisations.height;\n\tconst boxWidth = box.width;\n\tconst boxHeight = box.height;\n\tlet width;\n\tlet height;\n\tif (customisationsWidth === null) {\n\t\theight = customisationsHeight === null ? \"1em\" : customisationsHeight === \"auto\" ? boxHeight : customisationsHeight;\n\t\twidth = calculateSize(height, boxWidth / boxHeight);\n\t} else {\n\t\twidth = customisationsWidth === \"auto\" ? boxWidth : customisationsWidth;\n\t\theight = customisationsHeight === null ? calculateSize(width, boxHeight / boxWidth) : customisationsHeight === \"auto\" ? boxHeight : customisationsHeight;\n\t}\n\tconst attributes = {};\n\tconst setAttr = (prop, value) => {\n\t\tif (!isUnsetKeyword(value)) attributes[prop] = value.toString();\n\t};\n\tsetAttr(\"width\", width);\n\tsetAttr(\"height\", height);\n\tconst viewBox = [\n\t\tbox.left,\n\t\tbox.top,\n\t\tboxWidth,\n\t\tboxHeight\n\t];\n\tattributes.viewBox = viewBox.join(\" \");\n\treturn {\n\t\tattributes,\n\t\tviewBox,\n\t\tbody\n\t};\n}\n\nexport { iconToSVG, isUnsetKeyword };", "/**\n* IDs usage:\n*\n* id=\"{id}\"\n* xlink:href=\"#{id}\"\n* url(#{id})\n*\n* From SVG animations:\n*\n* begin=\"0;{id}.end\"\n* begin=\"{id}.end\"\n* begin=\"{id}.click\"\n*/\n/**\n* Regular expression for finding ids\n*/\nconst regex = /\\sid=\"(\\S+)\"/g;\n/**\n* New random-ish prefix for ids\n*\n* Do not use dash, it cannot be used in SVG 2 animations\n*/\nconst randomPrefix = \"IconifyId\" + Date.now().toString(16) + (Math.random() * 16777216 | 0).toString(16);\n/**\n* Counter for ids, increasing with every replacement\n*/\nlet counter = 0;\n/**\n* Replace IDs in SVG output with unique IDs\n*/\nfunction replaceIDs(body, prefix = randomPrefix) {\n\tconst ids = [];\n\tlet match;\n\twhile (match = regex.exec(body)) ids.push(match[1]);\n\tif (!ids.length) return body;\n\tconst suffix = \"suffix\" + (Math.random() * 16777216 | Date.now()).toString(16);\n\tids.forEach((id) => {\n\t\tconst newID = typeof prefix === \"function\" ? prefix(id) : prefix + (counter++).toString();\n\t\tconst escapedID = id.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\t\tbody = body.replace(new RegExp(\"([#;\\\"])(\" + escapedID + \")([\\\")]|\\\\.[a-z])\", \"g\"), \"$1\" + newID + suffix + \"$3\");\n\t});\n\tbody = body.replace(new RegExp(suffix, \"g\"), \"\");\n\treturn body;\n}\n\nexport { replaceIDs };", "/**\n* Generate <svg>\n*/\nfunction iconToHTML(body, attributes) {\n\tlet renderAttribsHTML = body.indexOf(\"xlink:\") === -1 ? \"\" : \" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\";\n\tfor (const attr in attributes) renderAttribsHTML += \" \" + attr + \"=\\\"\" + attributes[attr] + \"\\\"\";\n\treturn \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\"\" + renderAttribsHTML + \">\" + body + \"</svg>\";\n}\n\nexport { iconToHTML };", "import type { ExtendedIconifyIcon, IconifyIcon, IconifyJSON } from '@iconify/types';\nimport type { IconifyIconCustomisations } from '@iconify/utils';\nimport { getIconData, iconToHTML, iconToSVG, replaceIDs, stringToIcon } from '@iconify/utils';\nimport { getConfig } from '../config.js';\nimport { sanitizeText } from '../diagrams/common/common.js';\nimport { log } from '../logger.js';\n\nexport interface AsyncIconLoader {\n name: string;\n loader: () => Promise<IconifyJSON>;\n}\n\nexport interface SyncIconLoader {\n name: string;\n icons: IconifyJSON;\n}\n\nexport type IconLoader = AsyncIconLoader | SyncIconLoader;\n\nexport const unknownIcon: IconifyIcon = {\n body: '<g><rect width=\"80\" height=\"80\" style=\"fill: #087ebf; stroke-width: 0px;\"/><text transform=\"translate(21.16 64.67)\" style=\"fill: #fff; font-family: ArialMT, Arial; font-size: 67.75px;\"><tspan x=\"0\" y=\"0\">?</tspan></text></g>',\n height: 80,\n width: 80,\n};\n\nconst iconsStore = new Map<string, IconifyJSON>();\nconst loaderStore = new Map<string, AsyncIconLoader['loader']>();\n\nexport const registerIconPacks = (iconLoaders: IconLoader[]) => {\n for (const iconLoader of iconLoaders) {\n if (!iconLoader.name) {\n throw new Error(\n 'Invalid icon loader. Must have a \"name\" property with non-empty string value.'\n );\n }\n log.debug('Registering icon pack:', iconLoader.name);\n if ('loader' in iconLoader) {\n loaderStore.set(iconLoader.name, iconLoader.loader);\n } else if ('icons' in iconLoader) {\n iconsStore.set(iconLoader.name, iconLoader.icons);\n } else {\n log.error('Invalid icon loader:', iconLoader);\n throw new Error('Invalid icon loader. Must have either \"icons\" or \"loader\" property.');\n }\n }\n};\n\nconst getRegisteredIconData = async (iconName: string, fallbackPrefix?: string) => {\n const data = stringToIcon(iconName, true, fallbackPrefix !== undefined);\n if (!data) {\n throw new Error(`Invalid icon name: ${iconName}`);\n }\n const prefix = data.prefix || fallbackPrefix;\n if (!prefix) {\n throw new Error(`Icon name must contain a prefix: ${iconName}`);\n }\n let icons = iconsStore.get(prefix);\n if (!icons) {\n const loader = loaderStore.get(prefix);\n if (!loader) {\n throw new Error(`Icon set not found: ${data.prefix}`);\n }\n try {\n const loaded = await loader();\n icons = { ...loaded, prefix };\n iconsStore.set(prefix, icons);\n } catch (e) {\n log.error(e);\n throw new Error(`Failed to load icon set: ${data.prefix}`);\n }\n }\n const iconData = getIconData(icons, data.name);\n if (!iconData) {\n throw new Error(`Icon not found: ${iconName}`);\n }\n return iconData;\n};\n\nexport const isIconAvailable = async (iconName: string) => {\n try {\n await getRegisteredIconData(iconName);\n return true;\n } catch {\n return false;\n }\n};\n\nexport const getIconSVG = async (\n iconName: string,\n customisations?: IconifyIconCustomisations & { fallbackPrefix?: string },\n extraAttributes?: Record<string, string>\n) => {\n let iconData: ExtendedIconifyIcon;\n try {\n iconData = await getRegisteredIconData(iconName, customisations?.fallbackPrefix);\n } catch (e) {\n log.error(e);\n iconData = unknownIcon;\n }\n const renderData = iconToSVG(iconData, customisations);\n const svg = iconToHTML(replaceIDs(renderData.body), {\n ...renderData.attributes,\n ...extraAttributes,\n });\n return sanitizeText(svg, getConfig());\n};\n", "export function dedent(\n templ: TemplateStringsArray | string,\n ...values: unknown[]\n): string {\n let strings = Array.from(typeof templ === 'string' ? [templ] : templ);\n\n // 1. Remove trailing whitespace.\n strings[strings.length - 1] = strings[strings.length - 1].replace(\n /\\r?\\n([\\t ]*)$/,\n '',\n );\n\n // 2. Find all line breaks to determine the highest common indentation level.\n const indentLengths = strings.reduce((arr, str) => {\n const matches = str.match(/\\n([\\t ]+|(?!\\s).)/g);\n if (matches) {\n return arr.concat(\n matches.map((match) => match.match(/[\\t ]/g)?.length ?? 0),\n );\n }\n return arr;\n }, <number[]>[]);\n\n // 3. Remove the common indentation from all strings.\n if (indentLengths.length) {\n const pattern = new RegExp(`\\n[\\t ]{${Math.min(...indentLengths)}}`, 'g');\n\n strings = strings.map((str) => str.replace(pattern, '\\n'));\n }\n\n // 4. Remove leading whitespace.\n strings[0] = strings[0].replace(/^\\r?\\n/, '');\n\n // 5. Perform interpolation.\n let string = strings[0];\n\n values.forEach((value, i) => {\n // 5.1 Read current indentation level\n const endentations = string.match(/(?:^|\\n)( *)$/)\n const endentation = endentations ? endentations[1] : ''\n let indentedValue = value\n // 5.2 Add indentation to values with multiline strings\n if (typeof value === 'string' && value.includes('\\n')) {\n indentedValue = String(value)\n .split('\\n')\n .map((str, i) => {\n return i === 0 ? str : `${endentation}${str}`\n })\n .join('\\n');\n }\n\n string += indentedValue + strings[i + 1];\n });\n\n return string;\n}\n\nexport default dedent;\n", "import type { MarkedOptions } from './MarkedOptions.ts';\n\n/**\n * Gets the original marked default options.\n */\nexport function _getDefaults<ParserOutput = string, RendererOutput = string>(): MarkedOptions<ParserOutput, RendererOutput> {\n return {\n async: false,\n breaks: false,\n extensions: null,\n gfm: true,\n hooks: null,\n pedantic: false,\n renderer: null,\n silent: false,\n tokenizer: null,\n walkTokens: null,\n };\n}\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport let _defaults: MarkedOptions<any, any> = _getDefaults();\n\nexport function changeDefaults<ParserOutput = string, RendererOutput = string>(newDefaults: MarkedOptions<ParserOutput, RendererOutput>) {\n _defaults = newDefaults;\n}\n", "const noopTest = { exec: () => null } as unknown as RegExp;\n\nfunction edit(regex: string | RegExp, opt = '') {\n let source = typeof regex === 'string' ? regex : regex.source;\n const obj = {\n replace: (name: string | RegExp, val: string | RegExp) => {\n let valSource = typeof val === 'string' ? val : val.source;\n valSource = valSource.replace(other.caret, '$1');\n source = source.replace(name, valSource);\n return obj;\n },\n getRegex: () => {\n return new RegExp(source, opt);\n },\n };\n return obj;\n}\n\nexport const other = {\n codeRemoveIndent: /^(?: {1,4}| {0,3}\\t)/gm,\n outputLinkReplace: /\\\\([\\[\\]])/g,\n indentCodeCompensation: /^(\\s+)(?:```)/,\n beginningSpace: /^\\s+/,\n endingHash: /#$/,\n startingSpaceChar: /^ /,\n endingSpaceChar: / $/,\n nonSpaceChar: /[^ ]/,\n newLineCharGlobal: /\\n/g,\n tabCharGlobal: /\\t/g,\n multipleSpaceGlobal: /\\s+/g,\n blankLine: /^[ \\t]*$/,\n doubleBlankLine: /\\n[ \\t]*\\n[ \\t]*$/,\n blockquoteStart: /^ {0,3}>/,\n blockquoteSetextReplace: /\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,\n blockquoteSetextReplace2: /^ {0,3}>[ \\t]?/gm,\n listReplaceTabs: /^\\t+/,\n listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,\n listIsTask: /^\\[[ xX]\\] /,\n listReplaceTask: /^\\[[ xX]\\] +/,\n anyLine: /\\n.*\\n/,\n hrefBrackets: /^<(.*)>$/,\n tableDelimiter: /[:|]/,\n tableAlignChars: /^\\||\\| *$/g,\n tableRowBlankLine: /\\n[ \\t]*$/,\n tableAlignRight: /^ *-+: *$/,\n tableAlignCenter: /^ *:-+: *$/,\n tableAlignLeft: /^ *:-+ *$/,\n startATag: /^<a /i,\n endATag: /^<\\/a>/i,\n startPreScriptTag: /^<(pre|code|kbd|script)(\\s|>)/i,\n endPreScriptTag: /^<\\/(pre|code|kbd|script)(\\s|>)/i,\n startAngleBracket: /^</,\n endAngleBracket: />$/,\n pedanticHrefTitle: /^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/,\n unicodeAlphaNumeric: /[\\p{L}\\p{N}]/u,\n escapeTest: /[&<>\"']/,\n escapeReplace: /[&<>\"']/g,\n escapeTestNoEncode: /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,\n escapeReplaceNoEncode: /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,\n unescapeTest: /&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/ig,\n caret: /(^|[^\\[])\\^/g,\n percentDecode: /%25/g,\n findPipe: /\\|/g,\n splitPipe: / \\|/,\n slashPipe: /\\\\\\|/g,\n carriageReturn: /\\r\\n|\\r/g,\n spaceLine: /^ +$/gm,\n notSpaceStart: /^\\S*/,\n endingNewline: /\\n$/,\n listItemRegex: (bull: string) => new RegExp(`^( {0,3}${bull})((?:[\\t ][^\\\\n]*)?(?:\\\\n|$))`),\n nextBulletRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ \\t][^\\\\n]*)?(?:\\\\n|$))`),\n hrRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`),\n fencesBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\\`\\`\\`|~~~)`),\n headingBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),\n htmlBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'),\n};\n\n/**\n * Block-Level Grammar\n */\n\nconst newline = /^(?:[ \\t]*(?:\\n|$))+/;\nconst blockCode = /^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/;\nconst fences = /^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/;\nconst hr = /^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/;\nconst heading = /^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/;\nconst bullet = /(?:[*+-]|\\d{1,9}[.)])/;\nconst lheadingCore = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/;\nconst lheading = edit(lheadingCore)\n .replace(/bull/g, bullet) // lists can interrupt\n .replace(/blockCode/g, /(?: {4}| {0,3}\\t)/) // indented code blocks can interrupt\n .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt\n .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt\n .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt\n .replace(/html/g, / {0,3}<[^\\n>]+>\\n/) // block html can interrupt\n .replace(/\\|table/g, '') // table not in commonmark\n .getRegex();\nconst lheadingGfm = edit(lheadingCore)\n .replace(/bull/g, bullet) // lists can interrupt\n .replace(/blockCode/g, /(?: {4}| {0,3}\\t)/) // indented code blocks can interrupt\n .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt\n .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt\n .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt\n .replace(/html/g, / {0,3}<[^\\n>]+>\\n/) // block html can interrupt\n .replace(/table/g, / {0,3}\\|?(?:[:\\- ]*\\|)+[\\:\\- ]*\\n/) // table can interrupt\n .getRegex();\nconst _paragraph = /^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\\n)[^\\n]+)*)/;\nconst blockText = /^[^\\n]+/;\nconst _blockLabel = /(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/;\nconst def = edit(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/)\n .replace('label', _blockLabel)\n .replace('title', /(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/)\n .getRegex();\n\nconst list = edit(/^( {0,3}bull)([ \\t][^\\n]+?)?(?:\\n|$)/)\n .replace(/bull/g, bullet)\n .getRegex();\n\nconst _tag = 'address|article|aside|base|basefont|blockquote|body|caption'\n + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'\n + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'\n + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'\n + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title'\n + '|tr|track|ul';\nconst _comment = /<!--(?:-?>|[\\s\\S]*?(?:-->|$))/;\nconst html = edit(\n '^ {0,3}(?:' // optional indentation\n+ '<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:</\\\\1>[^\\\\n]*\\\\n+|$)' // (1)\n+ '|comment[^\\\\n]*(\\\\n+|$)' // (2)\n+ '|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>\\\\n*|$)' // (3)\n+ '|<![A-Z][\\\\s\\\\S]*?(?:>\\\\n*|$)' // (4)\n+ '|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?(?:\\\\]\\\\]>\\\\n*|$)' // (5)\n+ '|</?(tag)(?: +|\\\\n|/?>)[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (6)\n+ '|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (7) open tag\n+ '|</(?!script|pre|style|textarea)[a-z][\\\\w-]*\\\\s*>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (7) closing tag\n+ ')', 'i')\n .replace('comment', _comment)\n .replace('tag', _tag)\n .replace('attribute', / +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/)\n .getRegex();\n\nconst paragraph = edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n .replace('|table', '')\n .replace('blockquote', ' {0,3}>')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', '</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n .getRegex();\n\nconst blockquote = edit(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/)\n .replace('paragraph', paragraph)\n .getRegex();\n\n/**\n * Normal Block Grammar\n */\n\nconst blockNormal = {\n blockquote,\n code: blockCode,\n def,\n fences,\n heading,\n hr,\n html,\n lheading,\n list,\n newline,\n paragraph,\n table: noopTest,\n text: blockText,\n};\n\ntype BlockKeys = keyof typeof blockNormal;\n\n/**\n * GFM Block Grammar\n */\n\nconst gfmTable = edit(\n '^ *([^\\\\n ].*)\\\\n' // Header\n+ ' {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)' // Align\n+ '(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)') // Cells\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('blockquote', ' {0,3}>')\n .replace('code', '(?: {4}| {0,3}\\t)[^\\\\n]')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', '</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // tables can be interrupted by type (6) html blocks\n .getRegex();\n\nconst blockGfm: Record<BlockKeys, RegExp> = {\n ...blockNormal,\n lheading: lheadingGfm,\n table: gfmTable,\n paragraph: edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n .replace('table', gfmTable) // interrupt paragraphs with table\n .replace('blockquote', ' {0,3}>')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', '</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n .getRegex(),\n};\n\n/**\n * Pedantic grammar (original John Gruber's loose markdown specification)\n */\n\nconst blockPedantic: Record<BlockKeys, RegExp> = {\n ...blockNormal,\n html: edit(\n '^ *(?:comment *(?:\\\\n|\\\\s*$)'\n + '|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)' // closed tag\n + '|<tag(?:\"[^\"]*\"|\\'[^\\']*\\'|\\\\s[^\\'\"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))')\n .replace('comment', _comment)\n .replace(/tag/g, '(?!(?:'\n + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'\n + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'\n + '\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b')\n .getRegex(),\n def: /^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/,\n heading: /^(#{1,6})(.*)(?:\\n+|$)/,\n fences: noopTest, // fences not supported\n lheading: /^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,\n paragraph: edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' *#{1,6} *[^\\n]')\n .replace('lheading', lheading)\n .replace('|table', '')\n .replace('blockquote', ' {0,3}>')\n .replace('|fences', '')\n .replace('|list', '')\n .replace('|html', '')\n .replace('|tag', '')\n .getRegex(),\n};\n\n/**\n * Inline-Level Grammar\n */\n\nconst escape = /^\\\\([!\"#$%&'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/;\nconst inlineCode = /^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/;\nconst br = /^( {2,}|\\\\)\\n(?!\\s*$)/;\nconst inlineText = /^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/;\n\n// list of unicode punctuation marks, plus any missing characters from CommonMark spec\nconst _punctuation = /[\\p{P}\\p{S}]/u;\nconst _punctuationOrSpace = /[\\s\\p{P}\\p{S}]/u;\nconst _notPunctuationOrSpace = /[^\\s\\p{P}\\p{S}]/u;\nconst punctuation = edit(/^((?![*_])punctSpace)/, 'u')\n .replace(/punctSpace/g, _punctuationOrSpace).getRegex();\n\n// GFM allows ~ inside strong and em for strikethrough\nconst _punctuationGfmStrongEm = /(?!~)[\\p{P}\\p{S}]/u;\nconst _punctuationOrSpaceGfmStrongEm = /(?!~)[\\s\\p{P}\\p{S}]/u;\nconst _notPunctuationOrSpaceGfmStrongEm = /(?:[^\\s\\p{P}\\p{S}]|~)/u;\n\n// sequences em should skip over [title](link), `code`, <html>\nconst blockSkip = /\\[[^\\[\\]]*?\\]\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)]|\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)])*\\))*\\)|`[^`]*?`|<(?! )[^<>]*?>/g;\n\nconst emStrongLDelimCore = /^(?:\\*+(?:((?!\\*)punct)|[^\\s*]))|^_+(?:((?!_)punct)|([^\\s_]))/;\n\nconst emStrongLDelim = edit(emStrongLDelimCore, 'u')\n .replace(/punct/g, _punctuation)\n .getRegex();\n\nconst emStrongLDelimGfm = edit(emStrongLDelimCore, 'u')\n .replace(/punct/g, _punctuationGfmStrongEm)\n .getRegex();\n\nconst emStrongRDelimAstCore =\n '^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)' // Skip orphan inside strong\n+ '|[^*]+(?=[^*])' // Consume to delim\n+ '|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)' // (1) #*** can only be a Right Delimiter\n+ '|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter\n+ '|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter\n+ '|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)' // (4) ***# can only be Left Delimiter\n+ '|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter\n+ '|notPunctSpace(\\\\*+)(?=notPunctSpace)'; // (6) a***a can be either Left or Right Delimiter\n\nconst emStrongRDelimAst = edit(emStrongRDelimAstCore, 'gu')\n .replace(/notPunctSpace/g, _notPunctuationOrSpace)\n .replace(/punctSpace/g, _punctuationOrSpace)\n .replace(/punct/g, _punctuation)\n .getRegex();\n\nconst emStrongRDelimAstGfm = edit(emStrongRDelimAstCore, 'gu')\n .replace(/notPunctSpace/g, _notPunctuationOrSpaceGfmStrongEm)\n .replace(/punctSpace/g, _punctuationOrSpaceGfmStrongEm)\n .replace(/punct/g, _punctuationGfmStrongEm)\n .getRegex();\n\n// (6) Not allowed for _\nconst emStrongRDelimUnd = edit(\n '^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)' // Skip orphan inside strong\n+ '|[^_]+(?=[^_])' // Consume to delim\n+ '|(?!_)punct(_+)(?=[\\\\s]|$)' // (1) #___ can only be a Right Delimiter\n+ '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter\n+ '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter\n+ '|[\\\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter\n+ '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter\n .replace(/notPunctSpace/g, _notPunctuationOrSpace)\n .replace(/punctSpace/g, _punctuationOrSpace)\n .replace(/punct/g, _punctuation)\n .getRegex();\n\nconst anyPunctuation = edit(/\\\\(punct)/, 'gu')\n .replace(/punct/g, _punctuation)\n .getRegex();\n\nconst autolink = edit(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/)\n .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/)\n .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/)\n .getRegex();\n\nconst _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex();\nconst tag = edit(\n '^comment'\n + '|^</[a-zA-Z][\\\\w:-]*\\\\s*>' // self-closing tag\n + '|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>' // open tag\n + '|^<\\\\?[\\\\s\\\\S]*?\\\\?>' // processing instruction, e.g. <?php ?>\n + '|^<![a-zA-Z]+\\\\s[\\\\s\\\\S]*?>' // declaration, e.g. <!DOCTYPE html>\n + '|^<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>') // CDATA section\n .replace('comment', _inlineComment)\n .replace('attribute', /\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/)\n .getRegex();\n\nconst _inlineLabel = /(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`[^`]*`|[^\\[\\]\\\\`])*?/;\n\nconst link = edit(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]*(?:\\n[ \\t]*)?)(title))?\\s*\\)/)\n .replace('label', _inlineLabel)\n .replace('href', /<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]*/)\n .replace('title', /\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/)\n .getRegex();\n\nconst reflink = edit(/^!?\\[(label)\\]\\[(ref)\\]/)\n .replace('label', _inlineLabel)\n .replace('ref', _blockLabel)\n .getRegex();\n\nconst nolink = edit(/^!?\\[(ref)\\](?:\\[\\])?/)\n .replace('ref', _blockLabel)\n .getRegex();\n\nconst reflinkSearch = edit('reflink|nolink(?!\\\\()', 'g')\n .replace('reflink', reflink)\n .replace('nolink', nolink)\n .getRegex();\n\n/**\n * Normal Inline Grammar\n */\n\nconst inlineNormal = {\n _backpedal: noopTest, // only used for GFM url\n anyPunctuation,\n autolink,\n blockSkip,\n br,\n code: inlineCode,\n del: noopTest,\n emStrongLDelim,\n emStrongRDelimAst,\n emStrongRDelimUnd,\n escape,\n link,\n nolink,\n punctuation,\n reflink,\n reflinkSearch,\n tag,\n text: inlineText,\n url: noopTest,\n};\n\ntype InlineKeys = keyof typeof inlineNormal;\n\n/**\n * Pedantic Inline Grammar\n */\n\nconst inlinePedantic: Record<InlineKeys, RegExp> = {\n ...inlineNormal,\n link: edit(/^!?\\[(label)\\]\\((.*?)\\)/)\n .replace('label', _inlineLabel)\n .getRegex(),\n reflink: edit(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/)\n .replace('label', _inlineLabel)\n .getRegex(),\n};\n\n/**\n * GFM Inline Grammar\n */\n\nconst inlineGfm: Record<InlineKeys, RegExp> = {\n ...inlineNormal,\n emStrongRDelimAst: emStrongRDelimAstGfm,\n emStrongLDelim: emStrongLDelimGfm,\n url: edit(/^((?:ftp|https?):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/, 'i')\n .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/)\n .getRegex(),\n _backpedal: /(?:[^?!.,:;*_'\"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'\"~)]+(?!$))+/,\n del: /^(~~?)(?=[^\\s~])((?:\\\\[\\s\\S]|[^\\\\])*?(?:\\\\[\\s\\S]|[^\\s~\\\\]))\\1(?=[^~]|$)/,\n text: /^([`~]+|[^`~])(?:(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|https?:\\/\\/|ftp:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)))/,\n};\n\n/**\n * GFM + Line Breaks Inline Grammar\n */\n\nconst inlineBreaks: Record<InlineKeys, RegExp> = {\n ...inlineGfm,\n br: edit(br).replace('{2,}', '*').getRegex(),\n text: edit(inlineGfm.text)\n .replace('\\\\b_', '\\\\b_| {2,}\\\\n')\n .replace(/\\{2,\\}/g, '*')\n .getRegex(),\n};\n\n/**\n * exports\n */\n\nexport const block = {\n normal: blockNormal,\n gfm: blockGfm,\n pedantic: blockPedantic,\n};\n\nexport const inline = {\n normal: inlineNormal,\n gfm: inlineGfm,\n breaks: inlineBreaks,\n pedantic: inlinePedantic,\n};\n\nexport interface Rules {\n other: typeof other\n block: Record<BlockKeys, RegExp>\n inline: Record<InlineKeys, RegExp>\n}\n", "import { other } from './rules.ts';\n\n/**\n * Helpers\n */\nconst escapeReplacements: { [index: string]: string } = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n};\nconst getEscapeReplacement = (ch: string) => escapeReplacements[ch];\n\nexport function escape(html: string, encode?: boolean) {\n if (encode) {\n if (other.escapeTest.test(html)) {\n return html.replace(other.escapeReplace, getEscapeReplacement);\n }\n } else {\n if (other.escapeTestNoEncode.test(html)) {\n return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement);\n }\n }\n\n return html;\n}\n\nexport function unescape(html: string) {\n // explicitly match decimal, hex, and named HTML entities\n return html.replace(other.unescapeTest, (_, n) => {\n n = n.toLowerCase();\n if (n === 'colon') return ':';\n if (n.charAt(0) === '#') {\n return n.charAt(1) === 'x'\n ? String.fromCharCode(parseInt(n.substring(2), 16))\n : String.fromCharCode(+n.substring(1));\n }\n return '';\n });\n}\n\nexport function cleanUrl(href: string) {\n try {\n href = encodeURI(href).replace(other.percentDecode, '%');\n } catch {\n return null;\n }\n return href;\n}\n\nexport function splitCells(tableRow: string, count?: number) {\n // ensure that every cell-delimiting pipe has a space\n // before it to distinguish it from an escaped pipe\n const row = tableRow.replace(other.findPipe, (match, offset, str) => {\n let escaped = false;\n let curr = offset;\n while (--curr >= 0 && str[curr] === '\\\\') escaped = !escaped;\n if (escaped) {\n // odd number of slashes means | is escaped\n // so we leave it alone\n return '|';\n } else {\n // add space before unescaped |\n return ' |';\n }\n }),\n cells = row.split(other.splitPipe);\n let i = 0;\n\n // First/last cell in a row cannot be empty if it has no leading/trailing pipe\n if (!cells[0].trim()) {\n cells.shift();\n }\n if (cells.length > 0 && !cells.at(-1)?.trim()) {\n cells.pop();\n }\n\n if (count) {\n if (cells.length > count) {\n cells.splice(count);\n } else {\n while (cells.length < count) cells.push('');\n }\n }\n\n for (; i < cells.length; i++) {\n // leading or trailing whitespace is ignored per the gfm spec\n cells[i] = cells[i].trim().replace(other.slashPipe, '|');\n }\n return cells;\n}\n\n/**\n * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').\n * /c*$/ is vulnerable to REDOS.\n *\n * @param str\n * @param c\n * @param invert Remove suffix of non-c chars instead. Default falsey.\n */\nexport function rtrim(str: string, c: string, invert?: boolean) {\n const l = str.length;\n if (l === 0) {\n return '';\n }\n\n // Length of suffix matching the invert condition.\n let suffLen = 0;\n\n // Step left until we fail to match the invert condition.\n while (suffLen < l) {\n const currChar = str.charAt(l - suffLen - 1);\n if (currChar === c && !invert) {\n suffLen++;\n } else if (currChar !== c && invert) {\n suffLen++;\n } else {\n break;\n }\n }\n\n return str.slice(0, l - suffLen);\n}\n\nexport function findClosingBracket(str: string, b: string) {\n if (str.indexOf(b[1]) === -1) {\n return -1;\n }\n\n let level = 0;\n for (let i = 0; i < str.length; i++) {\n if (str[i] === '\\\\') {\n i++;\n } else if (str[i] === b[0]) {\n level++;\n } else if (str[i] === b[1]) {\n level--;\n if (level < 0) {\n return i;\n }\n }\n }\n if (level > 0) {\n return -2;\n }\n\n return -1;\n}\n", "import { _defaults } from './defaults.ts';\nimport {\n rtrim,\n splitCells,\n findClosingBracket,\n} from './helpers.ts';\nimport type { Rules } from './rules.ts';\nimport type { _Lexer } from './Lexer.ts';\nimport type { Links, Tokens, Token } from './Tokens.ts';\nimport type { MarkedOptions } from './MarkedOptions.ts';\n\nfunction outputLink(cap: string[], link: Pick<Tokens.Link, 'href' | 'title'>, raw: string, lexer: _Lexer, rules: Rules): Tokens.Link | Tokens.Image {\n const href = link.href;\n const title = link.title || null;\n const text = cap[1].replace(rules.other.outputLinkReplace, '$1');\n\n lexer.state.inLink = true;\n const token: Tokens.Link | Tokens.Image = {\n type: cap[0].charAt(0) === '!' ? 'image' : 'link',\n raw,\n href,\n title,\n text,\n tokens: lexer.inlineTokens(text),\n };\n lexer.state.inLink = false;\n return token;\n}\n\nfunction indentCodeCompensation(raw: string, text: string, rules: Rules) {\n const matchIndentToCode = raw.match(rules.other.indentCodeCompensation);\n\n if (matchIndentToCode === null) {\n return text;\n }\n\n const indentToCode = matchIndentToCode[1];\n\n return text\n .split('\\n')\n .map(node => {\n const matchIndentInNode = node.match(rules.other.beginningSpace);\n if (matchIndentInNode === null) {\n return node;\n }\n\n const [indentInNode] = matchIndentInNode;\n\n if (indentInNode.length >= indentToCode.length) {\n return node.slice(indentToCode.length);\n }\n\n return node;\n })\n .join('\\n');\n}\n\n/**\n * Tokenizer\n */\nexport class _Tokenizer<ParserOutput = string, RendererOutput = string> {\n options: MarkedOptions<ParserOutput, RendererOutput>;\n rules!: Rules; // set by the lexer\n lexer!: _Lexer<ParserOutput, RendererOutput>; // set by the lexer\n\n constructor(options?: MarkedOptions<ParserOutput, RendererOutput>) {\n this.options = options || _defaults;\n }\n\n space(src: string): Tokens.Space | undefined {\n const cap = this.rules.block.newline.exec(src);\n if (cap && cap[0].length > 0) {\n return {\n type: 'space',\n raw: cap[0],\n };\n }\n }\n\n code(src: string): Tokens.Code | undefined {\n const cap = this.rules.block.code.exec(src);\n if (cap) {\n const text = cap[0].replace(this.rules.other.codeRemoveIndent, '');\n return {\n type: 'code',\n raw: cap[0],\n codeBlockStyle: 'indented',\n text: !this.options.pedantic\n ? rtrim(text, '\\n')\n : text,\n };\n }\n }\n\n fences(src: string): Tokens.Code | undefined {\n const cap = this.rules.block.fences.exec(src);\n if (cap) {\n const raw = cap[0];\n const text = indentCodeCompensation(raw, cap[3] || '', this.rules);\n\n return {\n type: 'code',\n raw,\n lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2],\n text,\n };\n }\n }\n\n heading(src: string): Tokens.Heading | undefined {\n const cap = this.rules.block.heading.exec(src);\n if (cap) {\n let text = cap[2].trim();\n\n // remove trailing #s\n if (this.rules.other.endingHash.test(text)) {\n const trimmed = rtrim(text, '#');\n if (this.options.pedantic) {\n text = trimmed.trim();\n } else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) {\n // CommonMark requires space before trailing #s\n text = trimmed.trim();\n }\n }\n\n return {\n type: 'heading',\n raw: cap[0],\n depth: cap[1].length,\n text,\n tokens: this.lexer.inline(text),\n };\n }\n }\n\n hr(src: string): Tokens.Hr | undefined {\n const cap = this.rules.block.hr.exec(src);\n if (cap) {\n return {\n type: 'hr',\n raw: rtrim(cap[0], '\\n'),\n };\n }\n }\n\n blockquote(src: string): Tokens.Blockquote | undefined {\n const cap = this.rules.block.blockquote.exec(src);\n if (cap) {\n let lines = rtrim(cap[0], '\\n').split('\\n');\n let raw = '';\n let text = '';\n const tokens: Token[] = [];\n\n while (lines.length > 0) {\n let inBlockquote = false;\n const currentLines = [];\n\n let i;\n for (i = 0; i < lines.length; i++) {\n // get lines up to a continuation\n if (this.rules.other.blockquoteStart.test(lines[i])) {\n currentLines.push(lines[i]);\n inBlockquote = true;\n } else if (!inBlockquote) {\n currentLines.push(lines[i]);\n } else {\n break;\n }\n }\n lines = lines.slice(i);\n\n const currentRaw = currentLines.join('\\n');\n const currentText = currentRaw\n // precede setext continuation with 4 spaces so it isn't a setext\n .replace(this.rules.other.blockquoteSetextReplace, '\\n $1')\n .replace(this.rules.other.blockquoteSetextReplace2, '');\n raw = raw ? `${raw}\\n${currentRaw}` : currentRaw;\n text = text ? `${text}\\n${currentText}` : currentText;\n\n // parse blockquote lines as top level tokens\n // merge paragraphs if this is a continuation\n const top = this.lexer.state.top;\n this.lexer.state.top = true;\n this.lexer.blockTokens(currentText, tokens, true);\n this.lexer.state.top = top;\n\n // if there is no continuation then we are done\n if (lines.length === 0) {\n break;\n }\n\n const lastToken = tokens.at(-1);\n\n if (lastToken?.type === 'code') {\n // blockquote continuation cannot be preceded by a code block\n break;\n } else if (lastToken?.type ==