@localix-ai/flowdown 0.0.0-stage → 0.5.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.
- package/LICENSE +21 -0
- package/README.md +101 -2
- package/dist/browser/file-actions.js +80 -0
- package/dist/browser/file-actions.js.map +1 -0
- package/dist/core/block-facts.js +72 -0
- package/dist/core/block-facts.js.map +1 -0
- package/dist/core/blocks.d.ts +25 -0
- package/dist/core/blocks.js +463 -0
- package/dist/core/blocks.js.map +1 -0
- package/dist/core/bounded-cache.js +42 -0
- package/dist/core/bounded-cache.js.map +1 -0
- package/dist/core/dollars.d.ts +12 -0
- package/dist/core/dollars.js +88 -0
- package/dist/core/dollars.js.map +1 -0
- package/dist/core/fence-scan.js +53 -0
- package/dist/core/fence-scan.js.map +1 -0
- package/dist/core/file-tree-parse.d.ts +26 -0
- package/dist/core/file-tree-parse.js +51 -0
- package/dist/core/file-tree-parse.js.map +1 -0
- package/dist/core/forms-html.js +63 -0
- package/dist/core/forms-html.js.map +1 -0
- package/dist/core/forms.d.ts +28 -0
- package/dist/core/forms.js +23 -0
- package/dist/core/forms.js.map +1 -0
- package/dist/core/headings.d.ts +11 -0
- package/dist/core/headings.js +74 -0
- package/dist/core/headings.js.map +1 -0
- package/dist/core/heal.d.ts +11 -0
- package/dist/core/heal.js +220 -0
- package/dist/core/heal.js.map +1 -0
- package/dist/core/load-once.js +23 -0
- package/dist/core/load-once.js.map +1 -0
- package/dist/core/math-delimiters.js +33 -0
- package/dist/core/math-delimiters.js.map +1 -0
- package/dist/core/math-syntax.js +56 -0
- package/dist/core/math-syntax.js.map +1 -0
- package/dist/core/prose.d.ts +10 -0
- package/dist/core/prose.js +77 -0
- package/dist/core/prose.js.map +1 -0
- package/dist/core/remark-answer-blocks.d.ts +5 -0
- package/dist/core/remark-answer-blocks.js +172 -0
- package/dist/core/remark-answer-blocks.js.map +1 -0
- package/dist/core/remark-answer-containers.js +299 -0
- package/dist/core/remark-answer-containers.js.map +1 -0
- package/dist/core/sanitize-schema.d.ts +18 -0
- package/dist/core/sanitize-schema.js +62 -0
- package/dist/core/sanitize-schema.js.map +1 -0
- package/dist/core/syntax.d.ts +8 -0
- package/dist/core/syntax.js +32 -0
- package/dist/core/syntax.js.map +1 -0
- package/dist/dialect.d.ts +92 -0
- package/dist/dialect.js +176 -0
- package/dist/dialect.js.map +1 -0
- package/dist/document/fence.d.ts +25 -0
- package/dist/document/fence.js +101 -0
- package/dist/document/fence.js.map +1 -0
- package/dist/document/index.d.ts +46 -0
- package/dist/document/index.js +66 -0
- package/dist/document/index.js.map +1 -0
- package/dist/document/table.d.ts +11 -0
- package/dist/document/table.js +35 -0
- package/dist/document/table.js.map +1 -0
- package/dist/dom/index.d.ts +21 -0
- package/dist/dom/index.js +123 -0
- package/dist/dom/index.js.map +1 -0
- package/dist/dom/patch.js +104 -0
- package/dist/dom/patch.js.map +1 -0
- package/dist/element/index.d.ts +29 -0
- package/dist/element/index.js +64 -0
- package/dist/element/index.js.map +1 -0
- package/dist/engine/blocks.js +774 -0
- package/dist/engine/blocks.js.map +1 -0
- package/dist/engine/entities.js +83 -0
- package/dist/engine/entities.js.map +1 -0
- package/dist/engine/entity-core.js +9 -0
- package/dist/engine/entity-core.js.map +1 -0
- package/dist/engine/entity-table.js +9 -0
- package/dist/engine/entity-table.js.map +1 -0
- package/dist/engine/html.d.ts +7 -0
- package/dist/engine/html.js +207 -0
- package/dist/engine/html.js.map +1 -0
- package/dist/engine/index.d.ts +7 -0
- package/dist/engine/index.js +74 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/inlines.js +852 -0
- package/dist/engine/inlines.js.map +1 -0
- package/dist/engine/types.d.ts +109 -0
- package/dist/engine/url.d.ts +11 -0
- package/dist/engine/url.js +16 -0
- package/dist/engine/url.js.map +1 -0
- package/dist/engine/visit.d.ts +10 -0
- package/dist/engine/visit.js +29 -0
- package/dist/engine/visit.js.map +1 -0
- package/dist/highlight/highlight.d.ts +4 -0
- package/dist/highlight/highlight.js +144 -0
- package/dist/highlight/highlight.js.map +1 -0
- package/dist/highlight/index.d.ts +4 -0
- package/dist/highlight/index.js +18 -0
- package/dist/highlight/index.js.map +1 -0
- package/dist/html/index.d.ts +4 -0
- package/dist/html/index.js +544 -0
- package/dist/html/index.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +13 -0
- package/dist/math/index.d.ts +17 -0
- package/dist/math/index.js +20 -0
- package/dist/math/index.js.map +1 -0
- package/dist/math/typeset.d.ts +12 -0
- package/dist/math/typeset.js +74 -0
- package/dist/math/typeset.js.map +1 -0
- package/dist/mermaid/diagram.d.ts +8 -0
- package/dist/mermaid/diagram.js +114 -0
- package/dist/mermaid/diagram.js.map +1 -0
- package/dist/mermaid/drawing.js +139 -0
- package/dist/mermaid/drawing.js.map +1 -0
- package/dist/mermaid/icons.js +16 -0
- package/dist/mermaid/icons.js.map +1 -0
- package/dist/mermaid/index.d.ts +13 -0
- package/dist/mermaid/index.js +3 -0
- package/dist/mermaid/loader.d.ts +5 -0
- package/dist/mermaid/loader.js +18 -0
- package/dist/mermaid/loader.js.map +1 -0
- package/dist/mermaid/look.d.ts +16 -0
- package/dist/mermaid/look.js +167 -0
- package/dist/mermaid/look.js.map +1 -0
- package/dist/mermaid/normalize-svg.js +44 -0
- package/dist/mermaid/normalize-svg.js.map +1 -0
- package/dist/mermaid/renderer.d.ts +22 -0
- package/dist/mermaid/renderer.js +132 -0
- package/dist/mermaid/renderer.js.map +1 -0
- package/dist/mermaid/viewer.js +309 -0
- package/dist/mermaid/viewer.js.map +1 -0
- package/dist/prompt/index.d.ts +19 -0
- package/dist/prompt/index.js +54 -0
- package/dist/prompt/index.js.map +1 -0
- package/dist/react/callout.d.ts +9 -0
- package/dist/react/callout.js +12 -0
- package/dist/react/callout.js.map +1 -0
- package/dist/react/code-block.d.ts +18 -0
- package/dist/react/code-block.js +81 -0
- package/dist/react/code-block.js.map +1 -0
- package/dist/react/context.d.ts +18 -0
- package/dist/react/context.js +17 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/draw.d.ts +2 -0
- package/dist/react/draw.js +16 -0
- package/dist/react/draw.js.map +1 -0
- package/dist/react/file-tree.d.ts +16 -0
- package/dist/react/file-tree.js +69 -0
- package/dist/react/file-tree.js.map +1 -0
- package/dist/react/growing-code.js +36 -0
- package/dist/react/growing-code.js.map +1 -0
- package/dist/react/helpers.d.ts +6 -0
- package/dist/react/helpers.js +17 -0
- package/dist/react/helpers.js.map +1 -0
- package/dist/react/icons.js +23 -0
- package/dist/react/icons.js.map +1 -0
- package/dist/react/labels.js +9 -0
- package/dist/react/labels.js.map +1 -0
- package/dist/react/markdown.d.ts +78 -0
- package/dist/react/markdown.js +204 -0
- package/dist/react/markdown.js.map +1 -0
- package/dist/react/render.d.ts +8 -0
- package/dist/react/render.js +41 -0
- package/dist/react/render.js.map +1 -0
- package/dist/react/table-rows.js +66 -0
- package/dist/react/table-rows.js.map +1 -0
- package/dist/react/table.js +36 -0
- package/dist/react/table.js.map +1 -0
- package/dist/react/tabs.d.ts +25 -0
- package/dist/react/tabs.js +58 -0
- package/dist/react/tabs.js.map +1 -0
- package/dist/react/use-smooth-text.d.ts +6 -0
- package/dist/react/use-smooth-text.js +156 -0
- package/dist/react/use-smooth-text.js.map +1 -0
- package/dist/react/use-stage.d.ts +9 -0
- package/dist/react/use-stage.js +57 -0
- package/dist/react/use-stage.js.map +1 -0
- package/dist/remark.d.ts +20 -0
- package/dist/remark.js +10 -0
- package/dist/render/factory.d.ts +15 -0
- package/dist/render/labels.d.ts +41 -0
- package/dist/render/labels.js +43 -0
- package/dist/render/labels.js.map +1 -0
- package/dist/render/tree.js +312 -0
- package/dist/render/tree.js.map +1 -0
- package/dist/render/view.d.ts +55 -0
- package/dist/render/view.js +302 -0
- package/dist/render/view.js.map +1 -0
- package/dist/render/views.d.ts +16 -0
- package/dist/render/views.js +261 -0
- package/dist/render/views.js.map +1 -0
- package/dist/render/vnode.d.ts +21 -0
- package/dist/render/vnode.js +194 -0
- package/dist/render/vnode.js.map +1 -0
- package/dist/static/index.d.ts +28 -0
- package/dist/static/index.js +27 -0
- package/dist/static/index.js.map +1 -0
- package/dist/stream.d.ts +12 -0
- package/dist/stream.js +3 -0
- package/dist/styles.css +1351 -0
- package/dist/tui/code.d.ts +5 -0
- package/dist/tui/code.js +240 -0
- package/dist/tui/code.js.map +1 -0
- package/dist/tui/index.d.ts +54 -0
- package/dist/tui/index.js +99 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/math.js +242 -0
- package/dist/tui/math.js.map +1 -0
- package/dist/tui/printable.d.ts +12 -0
- package/dist/tui/printable.js +31 -0
- package/dist/tui/printable.js.map +1 -0
- package/dist/tui/render.d.ts +12 -0
- package/dist/tui/render.js +524 -0
- package/dist/tui/render.js.map +1 -0
- package/dist/tui/style.d.ts +35 -0
- package/dist/tui/style.js +77 -0
- package/dist/tui/style.js.map +1 -0
- package/dist/tui/table.js +73 -0
- package/dist/tui/table.js.map +1 -0
- package/dist/tui/width.d.ts +2 -0
- package/dist/tui/width.js +133 -0
- package/dist/tui/width.js.map +1 -0
- package/dist/tui/wrap.d.ts +8 -0
- package/dist/tui/wrap.js +190 -0
- package/dist/tui/wrap.js.map +1 -0
- package/package.json +127 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inlines.js","names":[],"sources":["../../src/engine/inlines.ts"],"sourcesContent":["/**\n * The inline pass: the text of one block read into emphasis, links, code spans and the rest, by\n * the algorithm in the CommonMark spec (a delimiter stack for emphasis, a bracket stack for\n * links). One pass over the text; the parser's state lives in the module, since a block's text\n * is read from start to end before the next one begins.\n */\nimport { decodeEntity, ENTITY, isEscapable, normalizeUri, unescapeString } from './entities'\nimport type { InlineRule, InlineState, Node, Reference } from './types'\n\nexport interface InlineContext {\n refs: Map<string, Reference>\n /** The footnotes the document defines: normalized label to the label as written. */\n footnotes: Map<string, string>\n /** How many times each footnote has been referred to so far, in the order first referred to. */\n footnoteUses: Map<string, number>\n gfm: boolean\n /** Whether `$$` alone on a line fences a display formula. */\n math: boolean\n /** Extension rules by the ASCII code of the character that starts them. */\n rules: (InlineRule['parse'][] | undefined)[]\n /** 1 for every ASCII character that can start something other than plain text. */\n special: Uint8Array\n}\n\n/** A node while its block is read: linked to its siblings, so emphasis can wrap a run of them. */\ninterface Inl {\n type: string\n value: string\n parent: Inl | null\n prev: Inl | null\n next: Inl | null\n first: Inl | null\n last: Inl | null\n url: string\n title: string\n /** The finished node of an extension's construct. */\n node: Node | null\n}\n\ninterface Delimiter {\n cc: number\n num: number\n orig: number\n node: Inl\n prev: Delimiter | null\n next: Delimiter | null\n canOpen: boolean\n canClose: boolean\n}\n\ninterface Bracket {\n node: Inl\n prev: Bracket | null\n prevDelimiter: Delimiter | null\n index: number\n image: boolean\n active: boolean\n bracketAfter: boolean\n}\n\n/** A bare address found in the text: where it is and where it leads. */\ninterface Span {\n start: number\n end: number\n url: string\n}\n\nconst C_NEWLINE = 10\nconst C_SPACE = 32\nconst C_BANG = 33\nconst C_AMPERSAND = 38\nconst C_OPEN_PAREN = 40\nconst C_CLOSE_PAREN = 41\nconst C_ASTERISK = 42\nconst C_COLON = 58\nconst C_LESSTHAN = 60\nconst C_OPEN_BRACKET = 91\nconst C_BACKSLASH = 92\nconst C_CLOSE_BRACKET = 93\nconst C_CARET = 94\nconst C_UNDERSCORE = 95\nconst C_BACKTICK = 96\nconst C_TILDE = 126\n\nconst TAGNAME = '[A-Za-z][A-Za-z0-9-]*'\nconst ATTRIBUTENAME = '[a-zA-Z_:][a-zA-Z0-9:._-]*'\nconst ATTRIBUTEVALUE = '(?:[^\"\\'=<>`\\\\x00-\\\\x20]+|\\'[^\\']*\\'|\"[^\"]*\")'\nconst ATTRIBUTE = `(?:\\\\s+${ATTRIBUTENAME}(?:\\\\s*=\\\\s*${ATTRIBUTEVALUE})?)`\nexport const OPENTAG = `<${TAGNAME}${ATTRIBUTE}*\\\\s*/?>`\nexport const CLOSETAG = `</${TAGNAME}\\\\s*[>]`\nconst HTMLTAG = `(?:${OPENTAG}|${CLOSETAG}|<!-->|<!--->|<!--[\\\\s\\\\S]*?-->|[<][?][\\\\s\\\\S]*?[?][>]|<![A-Za-z]+[^>]*>|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>)`\n\nconst reHtmlTag = new RegExp(HTMLTAG, 'y')\nconst reEntity = new RegExp(ENTITY, 'iy')\n// The specification's own character classes name control characters.\n// oxlint-disable-next-line no-control-regex\nconst reAutolink = /<([A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\\x00-\\x20]*)>/y\nconst reEmailAutolink =\n /<([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])?)*)>/y\nconst reLinkLabel = /\\[(?:[^\\\\[\\]]|\\\\[\\s\\S]){0,1000}\\]/y\n// oxlint-disable-next-line no-control-regex\nconst reLinkDestinationBraces = /<(?:[^<>\\n\\\\\\x00]|\\\\.)*>/y\nconst reLinkTitle = /\"(?:\\\\[\\s\\S]|[^\"\\\\])*\"|'(?:\\\\[\\s\\S]|[^'\\\\])*'|\\((?:\\\\[\\s\\S]|[^()\\\\])*\\)/y\nconst reSpaceAtEndOfLine = /[ \\t]*(?:\\n|$)/y\nconst reFootnoteReference = /\\[\\^([^\\]\\s]+)\\]/y\nconst reUnicodeSpace = /\\p{Zs}/u\nconst reUnicodePunctuation = /[\\p{P}\\p{S}]/u\n/** Bare addresses: a URL with a scheme, one that starts `www.`, or an email address. */\nconst reBareLink =\n /(?:(?:https?|ftp):\\/\\/|www\\.)[^\\s<]*|(mailto:|xmpp:)?[A-Za-z0-9._+-]+@[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)+(\\/[A-Za-z0-9@.]+)?/g\n\n/** Whether the text may hold a bare address: three searches for a few characters, no regex. */\nconst mayHoldBareLink = (text: string): boolean =>\n text.indexOf('@') !== -1 || text.indexOf('://') !== -1 || text.indexOf('www.') !== -1\n\nlet subject = ''\nlet pos = 0\nlet end = 0\nlet ctx: InlineContext\nlet root: Inl\nlet delimiters: Delimiter | null = null\nlet brackets: Bracket | null = null\n/** Whether the text may hold a bare address (`www.`, `://`, `@`) to turn into a link. */\nlet bareLinks = false\n/** Lengths of backtick runs known to have no closing run in the rest of the text. */\nlet noBacktickCloser: Set<number> | null = null\n\nconst inl = (type: string, value = ''): Inl => ({\n type,\n value,\n parent: null,\n prev: null,\n next: null,\n first: null,\n last: null,\n url: '',\n title: '',\n node: null,\n})\n\nconst append = (parent: Inl, child: Inl): void => {\n child.parent = parent\n child.prev = parent.last\n child.next = null\n if (parent.last) parent.last.next = child\n else parent.first = child\n parent.last = child\n}\n\nconst unlink = (node: Inl): void => {\n if (node.prev) node.prev.next = node.next\n else if (node.parent) node.parent.first = node.next\n if (node.next) node.next.prev = node.prev\n else if (node.parent) node.parent.last = node.prev\n node.parent = node.prev = node.next = null\n}\n\nconst insertAfter = (node: Inl, sibling: Inl): void => {\n sibling.parent = node.parent\n sibling.prev = node\n sibling.next = node.next\n if (node.next) node.next.prev = sibling\n else if (node.parent) node.parent.last = sibling\n node.next = sibling\n}\n\nconst text = (value: string): Inl => {\n const node = inl('text', value)\n append(root, node)\n return node\n}\n\n/** Runs a sticky expression at the current place; the match, with the place moved past it. */\nconst match = (re: RegExp): string | null => {\n re.lastIndex = pos\n const found = re.exec(subject)\n if (found === null) return null\n pos = re.lastIndex\n return found[0]\n}\n\n/** Skips spaces, tabs and at most one line ending. */\nconst spnl = (): void => {\n let code = subject.charCodeAt(pos)\n while (code === C_SPACE || code === 9) code = subject.charCodeAt(++pos)\n if (code === C_NEWLINE) {\n code = subject.charCodeAt(++pos)\n while (code === C_SPACE || code === 9) code = subject.charCodeAt(++pos)\n }\n}\n\nconst isWhitespace = (code: number): boolean =>\n code === 32 ||\n code === 10 ||\n code === 9 ||\n code === 13 ||\n code === 12 ||\n (code >= 128 && reUnicodeSpace.test(String.fromCodePoint(code)))\n\nconst isPunctuation = (code: number): boolean =>\n code < 128 ? isEscapable(code) : reUnicodePunctuation.test(String.fromCodePoint(code))\n\nconst parseNewline = (): void => {\n pos++\n const last = root.last\n if (\n last !== null &&\n last.type === 'text' &&\n last.value.charCodeAt(last.value.length - 1) === 32\n ) {\n const hard = last.value.charCodeAt(last.value.length - 2) === 32\n last.value = last.value.replace(/ +$/, '')\n append(root, inl(hard ? 'break' : 'softbreak'))\n } else append(root, inl('softbreak'))\n while (subject.charCodeAt(pos) === C_SPACE) pos++\n}\n\nconst parseBackslash = (): void => {\n pos++\n const code = subject.charCodeAt(pos)\n if (code === C_NEWLINE) {\n pos++\n append(root, inl('break'))\n while (subject.charCodeAt(pos) === C_SPACE) pos++\n } else if (isEscapable(code)) {\n text(subject.charAt(pos))\n pos++\n } else text('\\\\')\n}\n\nconst parseBackticks = (): void => {\n const start = pos\n while (subject.charCodeAt(pos) === C_BACKTICK) pos++\n const length = pos - start\n const after = pos\n if (noBacktickCloser === null || !noBacktickCloser.has(length)) {\n let from = after\n for (;;) {\n const open = subject.indexOf('`', from)\n if (open === -1) break\n let close = open + 1\n while (subject.charCodeAt(close) === C_BACKTICK) close++\n if (close - open === length) {\n let content = subject.slice(after, open)\n if (content.indexOf('\\n') !== -1) content = content.replace(/\\n/g, ' ')\n if (\n content.charCodeAt(0) === 32 &&\n content.charCodeAt(content.length - 1) === 32 &&\n /[^ ]/.test(content)\n )\n content = content.slice(1, -1)\n append(root, inl('inlineCode', content))\n pos = close\n return\n }\n from = close\n }\n ;(noBacktickCloser ??= new Set()).add(length)\n }\n pos = after\n text(subject.slice(start, after))\n}\n\nconst parseDelimiters = (cc: number): void => {\n const start = pos\n while (subject.charCodeAt(pos) === cc) pos++\n const num = pos - start\n // Strikethrough is one tilde or two; a longer run is text.\n if (cc === C_TILDE && num > 2) {\n text(subject.slice(start, pos))\n return\n }\n let before = C_NEWLINE\n if (start > 0) {\n before = subject.charCodeAt(start - 1)\n if (before >= 0xdc00 && before <= 0xdfff && start > 1)\n before = subject.codePointAt(start - 2) ?? before\n }\n const after = pos < end ? (subject.codePointAt(pos) ?? C_NEWLINE) : C_NEWLINE\n const afterIsWhitespace = isWhitespace(after)\n const afterIsPunctuation = isPunctuation(after)\n const beforeIsWhitespace = isWhitespace(before)\n const beforeIsPunctuation = isPunctuation(before)\n const leftFlanking =\n !afterIsWhitespace && (!afterIsPunctuation || beforeIsWhitespace || beforeIsPunctuation)\n const rightFlanking =\n !beforeIsWhitespace && (!beforeIsPunctuation || afterIsWhitespace || afterIsPunctuation)\n const canOpen =\n cc === C_UNDERSCORE ? leftFlanking && (!rightFlanking || beforeIsPunctuation) : leftFlanking\n const canClose =\n cc === C_UNDERSCORE ? rightFlanking && (!leftFlanking || afterIsPunctuation) : rightFlanking\n const node = text(subject.slice(start, pos))\n if (!canOpen && !canClose) return\n const delimiter: Delimiter = {\n cc,\n num,\n orig: num,\n node,\n prev: delimiters,\n next: null,\n canOpen,\n canClose,\n }\n if (delimiters !== null) delimiters.next = delimiter\n delimiters = delimiter\n}\n\nconst removeDelimiter = (delimiter: Delimiter): void => {\n if (delimiter.prev !== null) delimiter.prev.next = delimiter.next\n if (delimiter.next === null) delimiters = delimiter.prev\n else delimiter.next.prev = delimiter.prev\n}\n\n/** Turns matching delimiter runs above `bottom` into emphasis, strong and strikethrough. */\nconst processEmphasis = (bottom: Delimiter | null): void => {\n // The lowest opener worth looking at, by what kind of closer is asking: `_` and `*` by whether\n // the closer can open and its length modulo three, `~` by its length.\n const bottoms: (Delimiter | null)[] = [\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n bottom,\n ]\n let closer = delimiters\n while (closer !== null && closer.prev !== bottom) closer = closer.prev\n while (closer !== null) {\n if (!closer.canClose) {\n closer = closer.next\n continue\n }\n const cc = closer.cc\n const key =\n cc === C_TILDE\n ? 11 + closer.orig\n : (cc === C_UNDERSCORE ? 0 : 6) + (closer.canOpen ? 3 : 0) + (closer.orig % 3)\n let opener = closer.prev\n let found = false\n while (opener !== null && opener !== bottom && opener !== bottoms[key]) {\n if (opener.cc === cc && opener.canOpen) {\n if (cc === C_TILDE) found = opener.orig === closer.orig\n else\n found = !(\n (closer.canOpen || opener.canClose) &&\n closer.orig % 3 !== 0 &&\n (opener.orig + closer.orig) % 3 === 0\n )\n if (found) break\n }\n opener = opener.prev\n }\n const old: Delimiter = closer\n if (found && opener !== null) {\n const use = cc === C_TILDE ? closer.num : closer.num >= 2 && opener.num >= 2 ? 2 : 1\n opener.num -= use\n closer.num -= use\n opener.node.value = opener.node.value.slice(use)\n closer.node.value = closer.node.value.slice(use)\n const wrapper = inl(cc === C_TILDE ? 'delete' : use === 1 ? 'emphasis' : 'strong')\n let between = opener.node.next\n while (between !== null && between !== closer.node) {\n const next: Inl | null = between.next\n unlink(between)\n append(wrapper, between)\n between = next\n }\n insertAfter(opener.node, wrapper)\n // Delimiters between the two can no longer match anything.\n if (opener.next !== closer) {\n opener.next = closer\n closer.prev = opener\n }\n if (opener.num === 0) {\n unlink(opener.node)\n removeDelimiter(opener)\n }\n if (closer.num === 0) {\n unlink(closer.node)\n const next: Delimiter | null = closer.next\n removeDelimiter(closer)\n closer = next\n }\n } else {\n closer = old.next\n bottoms[key] = old.prev\n if (!old.canOpen) removeDelimiter(old)\n }\n }\n // `removeDelimiter` moves `delimiters` down the stack.\n // oxlint-disable-next-line no-unmodified-loop-condition\n while (delimiters !== null && delimiters !== bottom) removeDelimiter(delimiters)\n}\n\nconst addBracket = (node: Inl, index: number, image: boolean): void => {\n if (brackets !== null) brackets.bracketAfter = true\n brackets = {\n node,\n prev: brackets,\n prevDelimiter: delimiters,\n index,\n image,\n active: true,\n bracketAfter: false,\n }\n}\n\n/** A link destination at the current place, or null. */\nconst parseLinkDestination = (): string | null => {\n const braced = match(reLinkDestinationBraces)\n if (braced !== null) return normalizeUri(unescapeString(braced.slice(1, -1)))\n if (subject.charCodeAt(pos) === C_LESSTHAN) return null\n const start = pos\n let depth = 0\n let code = 0\n while (pos < end) {\n code = subject.charCodeAt(pos)\n if (code === C_BACKSLASH && isEscapable(subject.charCodeAt(pos + 1))) pos += 2\n else if (code === C_OPEN_PAREN) {\n pos++\n depth++\n } else if (code === C_CLOSE_PAREN) {\n if (depth < 1) break\n pos++\n depth--\n } else if (code <= 32 || code === 127) break\n else pos++\n }\n if (pos === start && code !== C_CLOSE_PAREN) return null\n if (depth !== 0) return null\n return normalizeUri(unescapeString(subject.slice(start, pos)))\n}\n\nconst parseLinkTitle = (): string | null => {\n const title = match(reLinkTitle)\n return title === null ? null : unescapeString(title.slice(1, -1))\n}\n\n/** The length of a link label (`[…]`) at the current place, with the place moved past it; or 0. */\nconst parseLinkLabel = (): number => {\n const label = match(reLinkLabel)\n return label === null || label.length > 1001 ? 0 : label.length\n}\n\n/** A reference label as it is matched: without case, with its whitespace collapsed. */\nexport const normalizeLabel = (label: string): string =>\n label\n .slice(1, -1)\n .trim()\n .replace(/[ \\t\\r\\n]+/g, ' ')\n .toLowerCase()\n .toUpperCase()\n\nconst parseCloseBracket = (): void => {\n const start = pos\n pos++\n const opener = brackets\n if (opener === null) {\n text(']')\n return\n }\n if (!opener.active) {\n text(']')\n brackets = opener.prev\n return\n }\n const image = opener.image\n const savepos = pos\n let url = ''\n let title = ''\n let matched = false\n\n // An inline link: `[text](destination \"title\")`.\n if (subject.charCodeAt(pos) === C_OPEN_PAREN) {\n pos++\n spnl()\n const destination = parseLinkDestination()\n if (destination !== null) {\n const beforeTitle = pos\n spnl()\n let found: string | null = null\n // A title needs whitespace before it.\n if (pos !== beforeTitle) found = parseLinkTitle()\n spnl()\n if (subject.charCodeAt(pos) === C_CLOSE_PAREN) {\n pos++\n url = destination\n title = found ?? ''\n matched = true\n }\n }\n if (!matched) pos = savepos\n }\n\n // A reference link: `[text][label]`, `[label][]` or `[label]`.\n if (!matched) {\n const beforeLabel = pos\n const length = parseLinkLabel()\n let label = ''\n if (length > 2) label = subject.slice(beforeLabel, beforeLabel + length)\n else if (!opener.bracketAfter) label = subject.slice(opener.index, start + 1)\n if (length === 0) pos = savepos\n if (label !== '') {\n const reference = ctx.refs.get(normalizeLabel(label))\n if (reference !== undefined) {\n url = reference.url\n title = reference.title\n matched = true\n }\n }\n }\n\n if (!matched) {\n brackets = opener.prev\n pos = start + 1\n text(']')\n return\n }\n\n const node = inl(image ? 'image' : 'link')\n node.url = url\n node.title = title\n let inside = opener.node.next\n while (inside !== null) {\n const next: Inl | null = inside.next\n unlink(inside)\n append(node, inside)\n inside = next\n }\n append(root, node)\n processEmphasis(opener.prevDelimiter)\n brackets = opener.prev\n unlink(opener.node)\n if (!image) {\n // A link cannot hold a link: the brackets opened before this one can no longer open any.\n for (let bracket = brackets; bracket !== null; bracket = bracket.prev)\n if (!bracket.image) bracket.active = false\n }\n}\n\nconst parseOpenBracket = (): void => {\n if (ctx.footnotes.size > 0 && subject.charCodeAt(pos + 1) === C_CARET) {\n reFootnoteReference.lastIndex = pos\n const found = reFootnoteReference.exec(subject)\n const key = found === null ? '' : normalizeLabel(`[${found[1]}]`)\n const label = ctx.footnotes.get(key)\n if (label !== undefined) {\n const uses = (ctx.footnoteUses.get(key) ?? 0) + 1\n ctx.footnoteUses.set(key, uses)\n // A footnote's number is its place among the footnotes referred to so far.\n let index = 0\n for (const used of ctx.footnoteUses.keys()) {\n index++\n if (used === key) break\n }\n state.push({\n type: 'footnoteReference',\n identifier: key.toLowerCase(),\n label,\n index,\n occurrence: uses,\n })\n pos = reFootnoteReference.lastIndex\n return\n }\n }\n const start = pos\n pos++\n addBracket(text('['), start, false)\n}\n\nconst parseBang = (): void => {\n const start = pos\n pos++\n if (\n subject.charCodeAt(pos) === C_OPEN_BRACKET &&\n // `![^1]` is an exclamation mark and a footnote, not an image.\n !(ctx.footnotes.size > 0 && subject.charCodeAt(pos + 1) === C_CARET)\n ) {\n pos++\n addBracket(text('!['), start + 1, true)\n } else text('!')\n}\n\nconst parseLessThan = (): void => {\n reEmailAutolink.lastIndex = pos\n let found = reEmailAutolink.exec(subject)\n if (found !== null) {\n const address = found[1] ?? ''\n const node = inl('link')\n node.url = normalizeUri(`mailto:${address}`)\n append(node, inl('text', address))\n append(root, node)\n pos = reEmailAutolink.lastIndex\n return\n }\n reAutolink.lastIndex = pos\n found = reAutolink.exec(subject)\n if (found !== null) {\n const address = found[1] ?? ''\n const node = inl('link')\n node.url = normalizeUri(address)\n append(node, inl('text', address))\n append(root, node)\n pos = reAutolink.lastIndex\n return\n }\n const tag = match(reHtmlTag)\n if (tag !== null) append(root, inl('html', tag))\n else {\n pos++\n text('<')\n }\n}\n\nconst parseEntity = (): void => {\n reEntity.lastIndex = pos\n const found = reEntity.exec(subject)\n const decoded = found === null ? null : decodeEntity(found[0])\n if (decoded === null) {\n pos++\n text('&')\n } else {\n pos = reEntity.lastIndex\n text(decoded)\n }\n}\n\nconst isAlphanumeric = (code: number): boolean =>\n (code >= 48 && code <= 57) || (code >= 65 && code <= 90) || (code >= 97 && code <= 122)\n\n/** Where a bare URL ends, by GitHub's rules for what trails a link without being part of it. */\nconst trimBareLink = (link: string): string => {\n let length = link.length\n for (;;) {\n const last = link.charCodeAt(length - 1)\n if ('?!.,:*_~\\'\"'.indexOf(link.charAt(length - 1)) !== -1 && length > 0) length--\n else if (last === C_CLOSE_PAREN) {\n let balance = 0\n for (let index = 0; index < length; index++) {\n const code = link.charCodeAt(index)\n if (code === C_OPEN_PAREN) balance++\n else if (code === C_CLOSE_PAREN) balance--\n }\n if (balance >= 0) break\n length--\n } else if (last === 59 /* ; */) {\n let start = length - 2\n while (start >= 0 && isAlphanumeric(link.charCodeAt(start))) start--\n if (start >= 0 && start < length - 2 && link.charCodeAt(start) === C_AMPERSAND) length = start\n else length--\n } else break\n }\n return link.slice(0, length)\n}\n\n/** The bare addresses in a run of text, in order. */\nconst findBareLinks = (run: string): Span[] => {\n const found: Span[] = []\n reBareLink.lastIndex = 0\n for (let hit = reBareLink.exec(run); hit !== null; hit = reBareLink.exec(run)) {\n let start = hit.index\n let link = hit[0]\n const first = link.charCodeAt(0)\n if (link.indexOf('@') !== -1 && !/^(?:https?:|ftp:|www\\.)/.test(link)) {\n let scheme = hit[1] ?? ''\n // `mailto:` and `xmpp:` are part of the link only as a word of their own.\n if (scheme !== '' && start > 0 && isAlphanumeric(run.charCodeAt(start - 1))) {\n start += scheme.length\n link = link.slice(scheme.length)\n scheme = ''\n }\n // Only an XMPP address takes a resource after a slash.\n if (hit[2] !== undefined && scheme !== 'xmpp:') link = link.slice(0, -hit[2].length)\n while (link.charCodeAt(link.length - 1) === 46 /* . */) link = link.slice(0, -1)\n // An address ends in a letter or a digit.\n if (!isAlphanumeric(link.charCodeAt(link.length - 1))) {\n reBareLink.lastIndex = start + link.length\n continue\n }\n found.push({ start, end: start + link.length, url: scheme === '' ? `mailto:${link}` : link })\n reBareLink.lastIndex = start + link.length\n continue\n }\n const www = first === 119 /* w */\n if (start > 0) {\n const before = run.charCodeAt(start - 1)\n // A URL with a scheme starts where its scheme does; `www.` starts a word.\n if (\n www\n ? !isWhitespace(before) &&\n before !== C_ASTERISK &&\n before !== C_UNDERSCORE &&\n before !== C_TILDE &&\n before !== C_OPEN_PAREN\n : (before >= 65 && before <= 90) ||\n (before >= 97 && before <= 122) ||\n before === 60 /* < */\n )\n continue\n }\n const host = www ? 0 : link.indexOf('://') + 3\n let hostEnd = host\n while (hostEnd < link.length) {\n const code = link.charCodeAt(hostEnd)\n if (\n code < 128 &&\n !isAlphanumeric(code) &&\n code !== 45 &&\n code !== 46 &&\n code !== C_UNDERSCORE\n )\n break\n hostEnd++\n }\n const segments = link.slice(host, hostEnd).split('.')\n if (hostEnd === host || (www && (segments.length < 2 || link.length < 5))) continue\n // The last two parts of a domain hold no underscore.\n if (segments.slice(-2).some((segment) => segment.indexOf('_') !== -1)) continue\n link = trimBareLink(link)\n if (link.length <= host) continue\n found.push({ start, end: start + link.length, url: www ? `http://${link}` : link })\n reBareLink.lastIndex = start + link.length\n }\n return found\n}\n\n/** The plain text of a run of nodes: what an image's `alt` holds. */\nconst plainText = (nodes: Node[]): string => {\n let out = ''\n for (const node of nodes) {\n if (node.type === 'image') out += node.alt ?? ''\n else if (node.children) out += plainText(node.children)\n else if (node.type === 'break') out += '\\n'\n else out += node.value ?? ''\n }\n return out\n}\n\n/** A run of finished nodes with the bare addresses in its text made into links. */\nconst linkify = (nodes: Node[]): Node[] => {\n let out: Node[] | null = null\n for (let index = 0; index < nodes.length; index++) {\n const node = nodes[index] as Node\n const value = node.type === 'text' ? (node.value ?? '') : ''\n const found = value !== '' && mayHoldBareLink(value) ? findBareLinks(value) : null\n if (found === null || found.length === 0) {\n if (out !== null) out.push(node)\n continue\n }\n out ??= nodes.slice(0, index)\n let from = 0\n for (const span of found) {\n if (span.start > from) out.push({ type: 'text', value: value.slice(from, span.start) })\n out.push({\n type: 'link',\n url: normalizeUri(span.url),\n title: '',\n children: [{ type: 'text', value: value.slice(span.start, span.end) }],\n })\n from = span.end\n }\n if (from < value.length) out.push({ type: 'text', value: value.slice(from) })\n }\n return out ?? nodes\n}\n\n/**\n * The finished nodes under a parent, with text that ended up side by side joined. `links` is\n * whether bare addresses in the text become links: not inside a link, which cannot hold another.\n */\nconst finish = (parent: Inl, links: boolean): Node[] => {\n const out: Node[] = []\n let last: Node | undefined\n for (let node = parent.first; node !== null; node = node.next) {\n let made: Node\n switch (node.type) {\n case 'text':\n if (node.value === '') continue\n if (last !== undefined && last.type === 'text') {\n last.value += node.value\n continue\n }\n made = { type: 'text', value: node.value }\n break\n case 'link':\n made = { type: 'link', url: node.url, title: node.title, children: finish(node, false) }\n break\n case 'image': {\n const children = finish(node, false)\n made = { type: 'image', url: node.url, title: node.title, alt: plainText(children) }\n break\n }\n case 'emphasis':\n case 'strong':\n case 'delete':\n made = { type: node.type, children: finish(node, links) }\n break\n case 'softbreak':\n // A line ending inside a paragraph is part of its text, as in mdast.\n if (last !== undefined && last.type === 'text') {\n last.value += '\\n'\n continue\n }\n made = { type: 'text', value: '\\n' }\n break\n case 'break':\n made = { type: 'break' }\n break\n case 'node':\n if (node.node === null) continue\n made = node.node\n break\n default:\n made = { type: node.type, value: node.value }\n }\n out.push(made)\n last = made\n }\n return links ? linkify(out) : out\n}\n\n/**\n * Runs one parse of a document and puts back what the inline parser was reading before it. The\n * parser keeps its place in this module, which is what makes it fast; an extension's rule that\n * parses a text of its own (a caption, a cell) starts a second parse in the middle of the first,\n * and the first one goes on from where it was.\n */\nexport const isolated = <T>(run: () => T): T => {\n const held = [subject, pos, end, ctx, root, delimiters, brackets, bareLinks, noBacktickCloser]\n const heldText = state.text\n const heldPos = state.pos\n try {\n return run()\n } finally {\n ;[subject, pos, end, ctx, root, delimiters, brackets, bareLinks, noBacktickCloser] = held as [\n string,\n number,\n number,\n InlineContext,\n Inl,\n typeof delimiters,\n typeof brackets,\n boolean,\n typeof noBacktickCloser,\n ]\n state.text = heldText\n state.pos = heldPos\n }\n}\n\nconst state: InlineState = {\n text: '',\n pos: 0,\n push: (node) => {\n const wrapper = inl('node')\n wrapper.node = node\n append(root, wrapper)\n },\n}\n\n/** Reads the inline text of one block into nodes. */\nexport const parseInlines = (source: string, context: InlineContext): Node[] => {\n // The text of a block ends where its last line does: trailing whitespace is not content.\n let length = source.length\n while (length > 0) {\n const code = source.charCodeAt(length - 1)\n if (code !== 32 && code !== 10 && code !== 9) break\n length--\n }\n subject = length === source.length ? source : source.slice(0, length)\n pos = 0\n end = length\n ctx = context\n root = inl('root')\n delimiters = null\n brackets = null\n noBacktickCloser = null\n bareLinks = context.gfm && mayHoldBareLink(subject)\n const special = context.special\n const rules = context.rules\n\n while (pos < end) {\n const code = subject.charCodeAt(pos)\n const own = code < 128 ? rules[code] : undefined\n if (own !== undefined) {\n state.text = subject\n state.pos = pos\n let handled = false\n for (const rule of own) {\n if (rule(state)) {\n handled = true\n break\n }\n }\n if (handled) {\n pos = state.pos\n continue\n }\n }\n switch (code) {\n case C_NEWLINE:\n parseNewline()\n break\n case C_BACKSLASH:\n parseBackslash()\n break\n case C_BACKTICK:\n parseBackticks()\n break\n case C_ASTERISK:\n case C_UNDERSCORE:\n parseDelimiters(code)\n break\n case C_TILDE:\n if (context.gfm) parseDelimiters(code)\n else {\n pos++\n text('~')\n }\n break\n case C_OPEN_BRACKET:\n parseOpenBracket()\n break\n case C_BANG:\n parseBang()\n break\n case C_CLOSE_BRACKET:\n parseCloseBracket()\n break\n case C_LESSTHAN:\n parseLessThan()\n break\n case C_AMPERSAND:\n parseEntity()\n break\n default: {\n // A run of plain text, up to the next character that can start something.\n const start = pos\n pos++\n while (pos < end) {\n const next = subject.charCodeAt(pos)\n if (next < 128 && special[next] === 1) break\n pos++\n }\n text(subject.slice(start, pos))\n }\n }\n }\n processEmphasis(null)\n const nodes = finish(root, bareLinks)\n subject = ''\n return nodes\n}\n\n/**\n * Reads one link reference definition from the start of a paragraph's text into `refs`. Returns\n * how many characters it took, or 0 when the text does not start with a definition.\n */\nexport const parseReference = (source: string, refs: Map<string, Reference>): number => {\n subject = source\n pos = 0\n end = source.length\n const labelLength = parseLinkLabel()\n if (labelLength === 0) return 0\n const label = source.slice(0, labelLength)\n if (source.charCodeAt(pos) !== C_COLON) return 0\n pos++\n spnl()\n const destination = parseLinkDestination()\n if (destination === null) return 0\n const beforeTitle = pos\n spnl()\n let title: string | null = null\n if (pos !== beforeTitle) title = parseLinkTitle()\n if (title === null) pos = beforeTitle\n let atLineEnd = match(reSpaceAtEndOfLine) !== null\n if (!atLineEnd && title !== null) {\n // What follows the title is not the end of the line: the definition is the part before it.\n title = null\n pos = beforeTitle\n atLineEnd = match(reSpaceAtEndOfLine) !== null\n }\n if (!atLineEnd) return 0\n const normalized = normalizeLabel(label)\n if (normalized === '') return 0\n if (!refs.has(normalized)) refs.set(normalized, { url: destination, title: title ?? '' })\n return pos\n}\n\n/** The characters that start an inline construct, as a table by ASCII code. */\nexport const specialCharacters = (extra: string): Uint8Array => {\n const table = new Uint8Array(128)\n for (const char of `\\n\\\\\\`*_~[]!<&${extra}`) table[char.charCodeAt(0)] = 1\n return table\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tree the engine parses Markdown into. One node shape for every kind, so the parser and the
|
|
3
|
+
* renderers stay monomorphic: a kind uses the fields it needs and leaves the rest unset.
|
|
4
|
+
*/
|
|
5
|
+
/** A place in the text: line and column from 1, offset from 0. */
|
|
6
|
+
export interface Point {
|
|
7
|
+
line: number;
|
|
8
|
+
column: number;
|
|
9
|
+
offset: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Position {
|
|
12
|
+
start: Point;
|
|
13
|
+
end: Point;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Any Markdown tree: the engine's own, or the mdast one a unified pipeline hands a plugin. The
|
|
17
|
+
* dialect's passes read and write the fields the two share.
|
|
18
|
+
*/
|
|
19
|
+
export interface Tree {
|
|
20
|
+
type: string;
|
|
21
|
+
children?: unknown[];
|
|
22
|
+
}
|
|
23
|
+
export type Align = 'left' | 'right' | 'center' | null;
|
|
24
|
+
export type NodeType = 'root' | 'paragraph' | 'heading' | 'thematicBreak' | 'blockquote' | 'list' | 'listItem' | 'code' | 'html' | 'table' | 'tableRow' | 'tableCell' | 'footnoteDefinition' | 'footnotes' | 'text' | 'break' | 'emphasis' | 'strong' | 'delete' | 'inlineCode' | 'link' | 'image' | 'footnoteReference' | 'math' | 'inlineMath' | 'element' | (string & {});
|
|
25
|
+
export interface Node {
|
|
26
|
+
type: NodeType;
|
|
27
|
+
children?: Node[];
|
|
28
|
+
/** The text of a `text`, `inlineCode`, `code` or `html` node. A line ending in a paragraph is `\n` in its text. */
|
|
29
|
+
value?: string;
|
|
30
|
+
/** A heading's level, 1 to 6. */
|
|
31
|
+
depth?: number;
|
|
32
|
+
/** A list: numbered or bulleted, its first number, and whether blank lines part its items. */
|
|
33
|
+
ordered?: boolean;
|
|
34
|
+
start?: number;
|
|
35
|
+
spread?: boolean;
|
|
36
|
+
/** A task list item: checked, unchecked, or (unset) not a task. */
|
|
37
|
+
checked?: boolean;
|
|
38
|
+
/** A code block's info string: its first word, and the rest. */
|
|
39
|
+
lang?: string;
|
|
40
|
+
meta?: string;
|
|
41
|
+
/** A link's or image's destination and title. */
|
|
42
|
+
url?: string;
|
|
43
|
+
title?: string;
|
|
44
|
+
/** An image's description, as plain text. */
|
|
45
|
+
alt?: string;
|
|
46
|
+
/** A table's column alignments; a cell's own alignment and whether it is a header cell. */
|
|
47
|
+
align?: Align[];
|
|
48
|
+
cellAlign?: Align;
|
|
49
|
+
header?: boolean;
|
|
50
|
+
/** A footnote's label as its definition writes it, the same folded for matching, and its number. */
|
|
51
|
+
label?: string;
|
|
52
|
+
identifier?: string;
|
|
53
|
+
index?: number;
|
|
54
|
+
/** A footnote reference: which reference to its footnote this is, from 1. */
|
|
55
|
+
occurrence?: number;
|
|
56
|
+
/** A footnote definition: how many references lead to it. */
|
|
57
|
+
count?: number;
|
|
58
|
+
/** Where a block sits in the text it was parsed from. */
|
|
59
|
+
position?: Position;
|
|
60
|
+
/** Whatever an extension keeps on its node. */
|
|
61
|
+
data?: Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
/** A link reference definition: `[label]: url "title"`. */
|
|
64
|
+
export interface Reference {
|
|
65
|
+
url: string;
|
|
66
|
+
title: string;
|
|
67
|
+
}
|
|
68
|
+
/** What one inline rule sees: the text being read and where the parser is in it. */
|
|
69
|
+
export interface InlineState {
|
|
70
|
+
/** The inline text of one block. */
|
|
71
|
+
text: string;
|
|
72
|
+
/** Where the parser is. A rule that matches moves it past what it read. */
|
|
73
|
+
pos: number;
|
|
74
|
+
/** Adds a node at the current place. */
|
|
75
|
+
push: (node: Node) => void;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* An inline construct: the characters it can start with, and a function that reads it. The
|
|
79
|
+
* function returns false when the text at `state.pos` is not its construct, leaving `pos` alone.
|
|
80
|
+
*/
|
|
81
|
+
export interface InlineRule {
|
|
82
|
+
chars: string;
|
|
83
|
+
parse: (state: InlineState) => boolean;
|
|
84
|
+
}
|
|
85
|
+
/** A fenced block an extension draws its own way: ```` ```tree ````, ```` ```mermaid ````. */
|
|
86
|
+
export type FenceRule = (node: Node) => Node | null | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* An extension to the syntax. Everything past CommonMark is one: GFM, and each form of the
|
|
89
|
+
* flowdown dialect.
|
|
90
|
+
*/
|
|
91
|
+
export interface Extension {
|
|
92
|
+
name: string;
|
|
93
|
+
/** Inline constructs, tried when the parser meets one of their characters. */
|
|
94
|
+
inline?: InlineRule[];
|
|
95
|
+
/** Reads a `$$` line as the fence of a display formula: a `math` node with the lines between. */
|
|
96
|
+
mathFences?: boolean;
|
|
97
|
+
/** Fenced blocks by language: the rule gets the `code` node and returns what replaces it. */
|
|
98
|
+
fences?: Record<string, FenceRule>;
|
|
99
|
+
/**
|
|
100
|
+
* Rewrites the finished tree: how a blockquote becomes a callout, a list becomes steps. `source`
|
|
101
|
+
* is the text the tree was read from, the one every node's position counts in.
|
|
102
|
+
*/
|
|
103
|
+
transform?: (root: Node, source: string) => void;
|
|
104
|
+
}
|
|
105
|
+
export interface ParseOptions {
|
|
106
|
+
/** GitHub's extensions: tables, strikethrough, task lists, bare links, footnotes. On by default. */
|
|
107
|
+
gfm?: boolean;
|
|
108
|
+
extensions?: Extension[];
|
|
109
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Node } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Rewrites or refuses a URL: `key` is the attribute it is for (`href`, `src`), `node` the link or
|
|
4
|
+
* image. An empty string leaves the attribute empty.
|
|
5
|
+
*/
|
|
6
|
+
export type UrlTransform = (url: string, key: string, node: Node) => string | null | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* The default for a URL: relative ones and `http`, `https`, `mailto`, `irc`, `ircs` and `xmpp`
|
|
9
|
+
* pass, and everything else (`javascript:`, `data:`, `tel:`) is emptied.
|
|
10
|
+
*/
|
|
11
|
+
export declare const defaultUrlTransform: (url: string) => string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/engine/url.ts
|
|
2
|
+
const SAFE_PROTOCOL = /^(?:https?|ircs?|mailto|xmpp)$/i;
|
|
3
|
+
/**
|
|
4
|
+
* The default for a URL: relative ones and `http`, `https`, `mailto`, `irc`, `ircs` and `xmpp`
|
|
5
|
+
* pass, and everything else (`javascript:`, `data:`, `tel:`) is emptied.
|
|
6
|
+
*/
|
|
7
|
+
const defaultUrlTransform = (url) => {
|
|
8
|
+
const colon = url.indexOf(":");
|
|
9
|
+
const question = url.indexOf("?");
|
|
10
|
+
const hash = url.indexOf("#");
|
|
11
|
+
const slash = url.indexOf("/");
|
|
12
|
+
return colon === -1 || slash !== -1 && colon > slash || question !== -1 && colon > question || hash !== -1 && colon > hash || SAFE_PROTOCOL.test(url.slice(0, colon)) ? url : "";
|
|
13
|
+
};
|
|
14
|
+
export { defaultUrlTransform };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.js","names":[],"sources":["../../src/engine/url.ts"],"sourcesContent":["import type { Node } from './types'\n\n/**\n * Rewrites or refuses a URL: `key` is the attribute it is for (`href`, `src`), `node` the link or\n * image. An empty string leaves the attribute empty.\n */\nexport type UrlTransform = (url: string, key: string, node: Node) => string | null | undefined\n\nconst SAFE_PROTOCOL = /^(?:https?|ircs?|mailto|xmpp)$/i\n\n/**\n * The default for a URL: relative ones and `http`, `https`, `mailto`, `irc`, `ircs` and `xmpp`\n * pass, and everything else (`javascript:`, `data:`, `tel:`) is emptied.\n */\nexport const defaultUrlTransform = (url: string): string => {\n const colon = url.indexOf(':')\n const question = url.indexOf('?')\n const hash = url.indexOf('#')\n const slash = url.indexOf('/')\n return colon === -1 ||\n (slash !== -1 && colon > slash) ||\n (question !== -1 && colon > question) ||\n (hash !== -1 && colon > hash) ||\n SAFE_PROTOCOL.test(url.slice(0, colon))\n ? url\n : ''\n}\n"],"mappings":";AAQA,MAAM,gBAAgB;;;;;AAMtB,MAAa,uBAAuB,QAAwB;CAC1D,MAAM,QAAQ,IAAI,QAAQ,GAAG;CAC7B,MAAM,WAAW,IAAI,QAAQ,GAAG;CAChC,MAAM,OAAO,IAAI,QAAQ,GAAG;CAC5B,MAAM,QAAQ,IAAI,QAAQ,GAAG;CAC7B,OAAO,UAAU,MACd,UAAU,MAAM,QAAQ,SACxB,aAAa,MAAM,QAAQ,YAC3B,SAAS,MAAM,QAAQ,QACxB,cAAc,KAAK,IAAI,MAAM,GAAG,KAAK,CAAC,IACpC,MACA;AACN"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Node } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Calls `visitor` on every node of a tree, parents before their children. A visitor that returns
|
|
4
|
+
* a number moves the walk to that place among the node's siblings: how a pass that replaces or
|
|
5
|
+
* removes nodes says where to go on from. Returning `false` leaves the node's children unread.
|
|
6
|
+
*/
|
|
7
|
+
export type Visitor = (node: Node, index: number | undefined, parent: Node | undefined) => number | boolean | void;
|
|
8
|
+
export declare const visit: (tree: Node, visitor: Visitor) => void;
|
|
9
|
+
/** The text of a node and everything under it; an image gives its description. */
|
|
10
|
+
export declare const toText: (node: Node) => string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/engine/visit.ts
|
|
2
|
+
const visit = (tree, visitor) => {
|
|
3
|
+
const walk = (node, index, parent) => {
|
|
4
|
+
const result = visitor(node, index, parent);
|
|
5
|
+
if (result !== false) {
|
|
6
|
+
const children = node.children;
|
|
7
|
+
if (children !== void 0) {
|
|
8
|
+
let at = 0;
|
|
9
|
+
while (at < children.length) {
|
|
10
|
+
const next = walk(children[at], at, node);
|
|
11
|
+
at = typeof next === "number" ? next : at + 1;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (typeof result === "number") return result;
|
|
16
|
+
};
|
|
17
|
+
walk(tree, void 0, void 0);
|
|
18
|
+
};
|
|
19
|
+
/** The text of a node and everything under it; an image gives its description. */
|
|
20
|
+
const toText = (node) => {
|
|
21
|
+
if (node.value !== void 0) return node.value;
|
|
22
|
+
if (node.type === "image") return node.alt ?? "";
|
|
23
|
+
let out = "";
|
|
24
|
+
if (node.children) for (const child of node.children) out += toText(child);
|
|
25
|
+
return out;
|
|
26
|
+
};
|
|
27
|
+
export { toText, visit };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=visit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visit.js","names":[],"sources":["../../src/engine/visit.ts"],"sourcesContent":["import type { Node } from './types'\n\n/**\n * Calls `visitor` on every node of a tree, parents before their children. A visitor that returns\n * a number moves the walk to that place among the node's siblings: how a pass that replaces or\n * removes nodes says where to go on from. Returning `false` leaves the node's children unread.\n */\nexport type Visitor = (\n node: Node,\n index: number | undefined,\n parent: Node | undefined,\n) => number | boolean | void\n\nexport const visit = (tree: Node, visitor: Visitor): void => {\n const walk = (node: Node, index: number | undefined, parent: Node | undefined): number | void => {\n const result = visitor(node, index, parent)\n if (result !== false) {\n const children = node.children\n if (children !== undefined) {\n let at = 0\n while (at < children.length) {\n const next = walk(children[at] as Node, at, node)\n at = typeof next === 'number' ? next : at + 1\n }\n }\n }\n if (typeof result === 'number') return result\n }\n walk(tree, undefined, undefined)\n}\n\n/** The text of a node and everything under it; an image gives its description. */\nexport const toText = (node: Node): string => {\n if (node.value !== undefined) return node.value\n if (node.type === 'image') return node.alt ?? ''\n let out = ''\n if (node.children) for (const child of node.children) out += toText(child)\n return out\n}\n"],"mappings":";AAaA,MAAa,SAAS,MAAY,YAA2B;CAC3D,MAAM,QAAQ,MAAY,OAA2B,WAA4C;EAC/F,MAAM,SAAS,QAAQ,MAAM,OAAO,MAAM;EAC1C,IAAI,WAAW,OAAO;GACpB,MAAM,WAAW,KAAK;GACtB,IAAI,aAAa,KAAA,GAAW;IAC1B,IAAI,KAAK;IACT,OAAO,KAAK,SAAS,QAAQ;KAC3B,MAAM,OAAO,KAAK,SAAS,KAAa,IAAI,IAAI;KAChD,KAAK,OAAO,SAAS,WAAW,OAAO,KAAK;IAC9C;GACF;EACF;EACA,IAAI,OAAO,WAAW,UAAU,OAAO;CACzC;CACA,KAAK,MAAM,KAAA,GAAW,KAAA,CAAS;AACjC;;AAGA,MAAa,UAAU,SAAuB;CAC5C,IAAI,KAAK,UAAU,KAAA,GAAW,OAAO,KAAK;CAC1C,IAAI,KAAK,SAAS,SAAS,OAAO,KAAK,OAAO;CAC9C,IAAI,MAAM;CACV,IAAI,KAAK,UAAU,KAAK,MAAM,SAAS,KAAK,UAAU,OAAO,OAAO,KAAK;CACzE,OAAO;AACT"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import hljs from "highlight.js/lib/core";
|
|
2
|
+
import bash from "highlight.js/lib/languages/bash";
|
|
3
|
+
import c from "highlight.js/lib/languages/c";
|
|
4
|
+
import cpp from "highlight.js/lib/languages/cpp";
|
|
5
|
+
import csharp from "highlight.js/lib/languages/csharp";
|
|
6
|
+
import css from "highlight.js/lib/languages/css";
|
|
7
|
+
import diff from "highlight.js/lib/languages/diff";
|
|
8
|
+
import dockerfile from "highlight.js/lib/languages/dockerfile";
|
|
9
|
+
import go from "highlight.js/lib/languages/go";
|
|
10
|
+
import ini from "highlight.js/lib/languages/ini";
|
|
11
|
+
import java from "highlight.js/lib/languages/java";
|
|
12
|
+
import javascript from "highlight.js/lib/languages/javascript";
|
|
13
|
+
import json from "highlight.js/lib/languages/json";
|
|
14
|
+
import kotlin from "highlight.js/lib/languages/kotlin";
|
|
15
|
+
import markdown from "highlight.js/lib/languages/markdown";
|
|
16
|
+
import php from "highlight.js/lib/languages/php";
|
|
17
|
+
import python from "highlight.js/lib/languages/python";
|
|
18
|
+
import ruby from "highlight.js/lib/languages/ruby";
|
|
19
|
+
import rust from "highlight.js/lib/languages/rust";
|
|
20
|
+
import sql from "highlight.js/lib/languages/sql";
|
|
21
|
+
import swift from "highlight.js/lib/languages/swift";
|
|
22
|
+
import typescript from "highlight.js/lib/languages/typescript";
|
|
23
|
+
import xml from "highlight.js/lib/languages/xml";
|
|
24
|
+
import yaml from "highlight.js/lib/languages/yaml";
|
|
25
|
+
// src/highlight/highlight.ts
|
|
26
|
+
/**
|
|
27
|
+
* highlight.js's Bash knows the shell's own words (`cd`, `echo`, `export`), strings, variables and
|
|
28
|
+
* comments, but not the programs a line runs: `bun add @localix-ai/flowdown --dev`, the line a README is
|
|
29
|
+
* made of, came out in one colour. These modes add what Shiki's grammar shows: the command, the
|
|
30
|
+
* first word after a line's start (or a `$ ` prompt), a `|`, `&&`, `;`, `(` or a `then`/`do`; its
|
|
31
|
+
* flags; and bare numbers. An assignment before a command (`NODE_ENV=production bun test`) is not
|
|
32
|
+
* the command, and a keyword stays a keyword. The shell's own words are coloured only where a
|
|
33
|
+
* command stands, so the `test` of `bun test` is an argument, not the `test` built-in.
|
|
34
|
+
*/
|
|
35
|
+
const SHELL_COMMAND = {
|
|
36
|
+
scope: "built_in",
|
|
37
|
+
match: new RegExp(`(?<=(?:^[ \\t]*(?:\\$[ \\t]+)?|[|&;(][ \\t]*|\\b(?:then|do|else|time)[ \\t]+)(?:[A-Za-z_]\\w*=[^ \\t]*[ \\t]+)*)(?!(?:if|then|else|elif|fi|for|while|until|in|do|done|case|esac|function|select|time)(?![\\w.-]))(?![\\w./-]*=)[A-Za-z_./][\\w./-]*`)
|
|
38
|
+
};
|
|
39
|
+
const SHELL_FLAG = {
|
|
40
|
+
scope: "attr",
|
|
41
|
+
match: /(?<=[ \t])--?[A-Za-z][\w-]*/
|
|
42
|
+
};
|
|
43
|
+
const SHELL_NUMBER = {
|
|
44
|
+
scope: "number",
|
|
45
|
+
match: /(?<=[ \t=])\d+(?:\.\d+)*(?![\w./-])/
|
|
46
|
+
};
|
|
47
|
+
const shell = (api) => {
|
|
48
|
+
const grammar = bash(api);
|
|
49
|
+
const keywords = typeof grammar.keywords === "object" ? grammar.keywords : {};
|
|
50
|
+
return {
|
|
51
|
+
...grammar,
|
|
52
|
+
keywords: {
|
|
53
|
+
...keywords,
|
|
54
|
+
built_in: []
|
|
55
|
+
},
|
|
56
|
+
contains: [
|
|
57
|
+
SHELL_COMMAND,
|
|
58
|
+
SHELL_FLAG,
|
|
59
|
+
SHELL_NUMBER,
|
|
60
|
+
...grammar.contains ?? []
|
|
61
|
+
]
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
const highlighter = hljs.newInstance();
|
|
65
|
+
for (const [name, grammar] of Object.entries({
|
|
66
|
+
bash: shell,
|
|
67
|
+
c,
|
|
68
|
+
cpp,
|
|
69
|
+
csharp,
|
|
70
|
+
css,
|
|
71
|
+
diff,
|
|
72
|
+
dockerfile,
|
|
73
|
+
go,
|
|
74
|
+
ini,
|
|
75
|
+
java,
|
|
76
|
+
javascript,
|
|
77
|
+
json,
|
|
78
|
+
kotlin,
|
|
79
|
+
markdown,
|
|
80
|
+
php,
|
|
81
|
+
python,
|
|
82
|
+
ruby,
|
|
83
|
+
rust,
|
|
84
|
+
sql,
|
|
85
|
+
swift,
|
|
86
|
+
typescript,
|
|
87
|
+
xml,
|
|
88
|
+
yaml
|
|
89
|
+
})) highlighter.registerLanguage(name, grammar);
|
|
90
|
+
const aliases = {
|
|
91
|
+
sh: "bash",
|
|
92
|
+
shell: "bash",
|
|
93
|
+
zsh: "bash",
|
|
94
|
+
js: "javascript",
|
|
95
|
+
jsx: "javascript",
|
|
96
|
+
mjs: "javascript",
|
|
97
|
+
cjs: "javascript",
|
|
98
|
+
ts: "typescript",
|
|
99
|
+
tsx: "typescript",
|
|
100
|
+
html: "xml",
|
|
101
|
+
svg: "xml",
|
|
102
|
+
md: "markdown",
|
|
103
|
+
patch: "diff",
|
|
104
|
+
yml: "yaml",
|
|
105
|
+
py: "python",
|
|
106
|
+
golang: "go",
|
|
107
|
+
rs: "rust",
|
|
108
|
+
rb: "ruby",
|
|
109
|
+
kt: "kotlin",
|
|
110
|
+
cs: "csharp",
|
|
111
|
+
"c#": "csharp",
|
|
112
|
+
"c++": "cpp",
|
|
113
|
+
h: "c",
|
|
114
|
+
hpp: "cpp",
|
|
115
|
+
toml: "ini",
|
|
116
|
+
docker: "dockerfile"
|
|
117
|
+
};
|
|
118
|
+
function escapeHtml(source) {
|
|
119
|
+
return source.replace(/[&<>"']/g, (character) => {
|
|
120
|
+
return {
|
|
121
|
+
"&": "&",
|
|
122
|
+
"<": "<",
|
|
123
|
+
">": ">",
|
|
124
|
+
"\"": """,
|
|
125
|
+
"'": "'"
|
|
126
|
+
}[character];
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Highlighted HTML for the fence's language. Only a language the fence names is highlighted, never
|
|
131
|
+
* a guessed one: an unknown or plain-text fence comes back escaped (or null, when asked).
|
|
132
|
+
*/
|
|
133
|
+
function highlightCode(source, fenceLanguage = "text", options) {
|
|
134
|
+
const normalized = fenceLanguage.toLowerCase();
|
|
135
|
+
const language = aliases[normalized] ?? normalized;
|
|
136
|
+
if (!highlighter.getLanguage(language)) return options ? null : escapeHtml(source);
|
|
137
|
+
return highlighter.highlight(source, {
|
|
138
|
+
language,
|
|
139
|
+
ignoreIllegals: true
|
|
140
|
+
}).value;
|
|
141
|
+
}
|
|
142
|
+
export { highlightCode };
|
|
143
|
+
|
|
144
|
+
//# sourceMappingURL=highlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.js","names":[],"sources":["../../src/highlight/highlight.ts"],"sourcesContent":["import type { LanguageFn, Mode } from 'highlight.js'\nimport hljs from 'highlight.js/lib/core'\nimport bash from 'highlight.js/lib/languages/bash'\nimport c from 'highlight.js/lib/languages/c'\nimport cpp from 'highlight.js/lib/languages/cpp'\nimport csharp from 'highlight.js/lib/languages/csharp'\nimport css from 'highlight.js/lib/languages/css'\nimport diff from 'highlight.js/lib/languages/diff'\nimport dockerfile from 'highlight.js/lib/languages/dockerfile'\nimport go from 'highlight.js/lib/languages/go'\nimport ini from 'highlight.js/lib/languages/ini'\nimport java from 'highlight.js/lib/languages/java'\nimport javascript from 'highlight.js/lib/languages/javascript'\nimport json from 'highlight.js/lib/languages/json'\nimport kotlin from 'highlight.js/lib/languages/kotlin'\nimport markdown from 'highlight.js/lib/languages/markdown'\nimport php from 'highlight.js/lib/languages/php'\nimport python from 'highlight.js/lib/languages/python'\nimport ruby from 'highlight.js/lib/languages/ruby'\nimport rust from 'highlight.js/lib/languages/rust'\nimport sql from 'highlight.js/lib/languages/sql'\nimport swift from 'highlight.js/lib/languages/swift'\nimport typescript from 'highlight.js/lib/languages/typescript'\nimport xml from 'highlight.js/lib/languages/xml'\nimport yaml from 'highlight.js/lib/languages/yaml'\n\n/** Words that open or close a shell construct: never a command's name. */\nconst SHELL_KEYWORDS =\n 'if|then|else|elif|fi|for|while|until|in|do|done|case|esac|function|select|time'\n\n/**\n * highlight.js's Bash knows the shell's own words (`cd`, `echo`, `export`), strings, variables and\n * comments, but not the programs a line runs: `bun add @localix-ai/flowdown --dev`, the line a README is\n * made of, came out in one colour. These modes add what Shiki's grammar shows: the command, the\n * first word after a line's start (or a `$ ` prompt), a `|`, `&&`, `;`, `(` or a `then`/`do`; its\n * flags; and bare numbers. An assignment before a command (`NODE_ENV=production bun test`) is not\n * the command, and a keyword stays a keyword. The shell's own words are coloured only where a\n * command stands, so the `test` of `bun test` is an argument, not the `test` built-in.\n */\nconst SHELL_COMMAND: Mode = {\n scope: 'built_in',\n match: new RegExp(\n `(?<=(?:^[ \\\\t]*(?:\\\\$[ \\\\t]+)?|[|&;(][ \\\\t]*|\\\\b(?:then|do|else|time)[ \\\\t]+)(?:[A-Za-z_]\\\\w*=[^ \\\\t]*[ \\\\t]+)*)` +\n `(?!(?:${SHELL_KEYWORDS})(?![\\\\w.-]))(?![\\\\w./-]*=)[A-Za-z_./][\\\\w./-]*`,\n ),\n}\nconst SHELL_FLAG: Mode = { scope: 'attr', match: /(?<=[ \\t])--?[A-Za-z][\\w-]*/ }\nconst SHELL_NUMBER: Mode = { scope: 'number', match: /(?<=[ \\t=])\\d+(?:\\.\\d+)*(?![\\w./-])/ }\n\nconst shell: LanguageFn = (api) => {\n const grammar = bash(api)\n const keywords = typeof grammar.keywords === 'object' ? grammar.keywords : {}\n return {\n ...grammar,\n keywords: { ...keywords, built_in: [] },\n contains: [SHELL_COMMAND, SHELL_FLAG, SHELL_NUMBER, ...(grammar.contains ?? [])],\n }\n}\n\nconst highlighter = hljs.newInstance()\nfor (const [name, grammar] of Object.entries({\n bash: shell,\n c,\n cpp,\n csharp,\n css,\n diff,\n dockerfile,\n go,\n ini,\n java,\n javascript,\n json,\n kotlin,\n markdown,\n php,\n python,\n ruby,\n rust,\n sql,\n swift,\n typescript,\n xml,\n yaml,\n})) {\n highlighter.registerLanguage(name, grammar)\n}\n\nconst aliases: Record<string, string> = {\n sh: 'bash',\n shell: 'bash',\n zsh: 'bash',\n js: 'javascript',\n jsx: 'javascript',\n mjs: 'javascript',\n cjs: 'javascript',\n ts: 'typescript',\n tsx: 'typescript',\n html: 'xml',\n svg: 'xml',\n md: 'markdown',\n patch: 'diff',\n yml: 'yaml',\n py: 'python',\n golang: 'go',\n rs: 'rust',\n rb: 'ruby',\n kt: 'kotlin',\n cs: 'csharp',\n 'c#': 'csharp',\n 'c++': 'cpp',\n h: 'c',\n hpp: 'cpp',\n toml: 'ini',\n docker: 'dockerfile',\n}\n\nfunction escapeHtml(source: string): string {\n return source.replace(/[&<>\"']/g, (character) => {\n return { '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' }[character]!\n })\n}\n\nexport function highlightCode(source: string, fenceLanguage?: string): string\nexport function highlightCode(\n source: string,\n fenceLanguage: string | undefined,\n options: { unknown: 'null' },\n): string | null\n/**\n * Highlighted HTML for the fence's language. Only a language the fence names is highlighted, never\n * a guessed one: an unknown or plain-text fence comes back escaped (or null, when asked).\n */\nexport function highlightCode(\n source: string,\n fenceLanguage = 'text',\n options?: { unknown: 'null' },\n): string | null {\n const normalized = fenceLanguage.toLowerCase()\n const language = aliases[normalized] ?? normalized\n if (!highlighter.getLanguage(language)) return options ? null : escapeHtml(source)\n return highlighter.highlight(source, { language, ignoreIllegals: true }).value\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,MAAM,gBAAsB;CAC1B,OAAO;CACP,OAAO,IAAI,OACT,qPAEF;AACF;AACA,MAAM,aAAmB;CAAE,OAAO;CAAQ,OAAO;AAA8B;AAC/E,MAAM,eAAqB;CAAE,OAAO;CAAU,OAAO;AAAsC;AAE3F,MAAM,SAAqB,QAAQ;CACjC,MAAM,UAAU,KAAK,GAAG;CACxB,MAAM,WAAW,OAAO,QAAQ,aAAa,WAAW,QAAQ,WAAW,CAAC;CAC5E,OAAO;EACL,GAAG;EACH,UAAU;GAAE,GAAG;GAAU,UAAU,CAAC;EAAE;EACtC,UAAU;GAAC;GAAe;GAAY;GAAc,GAAI,QAAQ,YAAY,CAAC;EAAE;CACjF;AACF;AAEA,MAAM,cAAc,KAAK,YAAY;AACrC,KAAK,MAAM,CAAC,MAAM,YAAY,OAAO,QAAQ;CAC3C,MAAM;CACN;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,GACC,YAAY,iBAAiB,MAAM,OAAO;AAG5C,MAAM,UAAkC;CACtC,IAAI;CACJ,OAAO;CACP,KAAK;CACL,IAAI;CACJ,KAAK;CACL,KAAK;CACL,KAAK;CACL,IAAI;CACJ,KAAK;CACL,MAAM;CACN,KAAK;CACL,IAAI;CACJ,OAAO;CACP,KAAK;CACL,IAAI;CACJ,QAAQ;CACR,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACN,OAAO;CACP,GAAG;CACH,KAAK;CACL,MAAM;CACN,QAAQ;AACV;AAEA,SAAS,WAAW,QAAwB;CAC1C,OAAO,OAAO,QAAQ,aAAa,cAAc;EAC/C,OAAO;GAAE,KAAK;GAAS,KAAK;GAAQ,KAAK;GAAQ,MAAK;GAAU,KAAK;EAAQ,EAAE;CACjF,CAAC;AACH;;;;;AAYA,SAAgB,cACd,QACA,gBAAgB,QAChB,SACe;CACf,MAAM,aAAa,cAAc,YAAY;CAC7C,MAAM,WAAW,QAAQ,eAAe;CACxC,IAAI,CAAC,YAAY,YAAY,QAAQ,GAAG,OAAO,UAAU,OAAO,WAAW,MAAM;CACjF,OAAO,YAAY,UAAU,QAAQ;EAAE;EAAU,gBAAgB;CAAK,CAAC,CAAC,CAAC;AAC3E"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { highlightCode } from "./highlight.js";
|
|
2
|
+
/** The `Highlighter` shape: highlighted HTML, or null for a language it does not know. */
|
|
3
|
+
export declare function highlight(code: string, language: string): string | null;
|
|
4
|
+
export { highlight as default, highlightCode };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { highlightCode } from "./highlight.js";
|
|
2
|
+
// src/highlight/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* `@localix-ai/flowdown/highlight`: a highlighter for `<Markdown highlight={…}>`, built on highlight.js
|
|
5
|
+
* with the languages replies and READMEs mostly hold and their usual aliases: shell, JavaScript and
|
|
6
|
+
* TypeScript, Python, Go, Rust, Java, Kotlin, Swift, C, C++, C#, PHP, Ruby, SQL, JSON, YAML, TOML,
|
|
7
|
+
* Dockerfile, CSS, HTML, Markdown and diffs.
|
|
8
|
+
*
|
|
9
|
+
* It is its own entry, and highlight.js an optional peer, so a page that highlights with Shiki or
|
|
10
|
+
* not at all bundles none of it. Colours come from the `--fd-code-*` tokens in `styles.css`.
|
|
11
|
+
*/
|
|
12
|
+
/** The `Highlighter` shape: highlighted HTML, or null for a language it does not know. */
|
|
13
|
+
function highlight(code, language) {
|
|
14
|
+
return highlightCode(code, language, { unknown: "null" });
|
|
15
|
+
}
|
|
16
|
+
export { highlight as default, highlight, highlightCode };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/highlight/index.ts"],"sourcesContent":["/**\n * `@localix-ai/flowdown/highlight`: a highlighter for `<Markdown highlight={…}>`, built on highlight.js\n * with the languages replies and READMEs mostly hold and their usual aliases: shell, JavaScript and\n * TypeScript, Python, Go, Rust, Java, Kotlin, Swift, C, C++, C#, PHP, Ruby, SQL, JSON, YAML, TOML,\n * Dockerfile, CSS, HTML, Markdown and diffs.\n *\n * It is its own entry, and highlight.js an optional peer, so a page that highlights with Shiki or\n * not at all bundles none of it. Colours come from the `--fd-code-*` tokens in `styles.css`.\n */\nimport { highlightCode } from './highlight'\n\nexport { highlightCode } from './highlight'\n\n/** The `Highlighter` shape: highlighted HTML, or null for a language it does not know. */\nexport function highlight(code: string, language: string): string | null {\n return highlightCode(code, language, { unknown: 'null' })\n}\n\nexport default highlight\n"],"mappings":";;;;;;;;;;;;AAcA,SAAgB,UAAU,MAAc,UAAiC;CACvE,OAAO,cAAc,MAAM,UAAU,EAAE,SAAS,OAAO,CAAC;AAC1D"}
|