tempest-react-sdk 0.83.0 → 0.85.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.
Files changed (70) hide show
  1. package/README.md +1 -0
  2. package/dist/auth/create-tempest-auth.cjs +1 -1
  3. package/dist/auth/create-tempest-auth.cjs.map +1 -1
  4. package/dist/auth/create-tempest-auth.js +294 -178
  5. package/dist/auth/create-tempest-auth.js.map +1 -1
  6. package/dist/components/Markdown/Markdown.cjs +1 -1
  7. package/dist/components/Markdown/Markdown.cjs.map +1 -1
  8. package/dist/components/Markdown/Markdown.js +29 -28
  9. package/dist/components/Markdown/Markdown.js.map +1 -1
  10. package/dist/components/Markdown/markdown-parse.cjs +6 -5
  11. package/dist/components/Markdown/markdown-parse.cjs.map +1 -1
  12. package/dist/components/Markdown/markdown-parse.js +195 -160
  13. package/dist/components/Markdown/markdown-parse.js.map +1 -1
  14. package/dist/http/resumable-upload.cjs +1 -1
  15. package/dist/http/resumable-upload.cjs.map +1 -1
  16. package/dist/http/resumable-upload.js +1 -1
  17. package/dist/http/resumable-upload.js.map +1 -1
  18. package/dist/http/upload-with-progress.cjs +1 -1
  19. package/dist/http/upload-with-progress.cjs.map +1 -1
  20. package/dist/http/upload-with-progress.js +47 -39
  21. package/dist/http/upload-with-progress.js.map +1 -1
  22. package/dist/payments/PixCheckout.cjs +2 -0
  23. package/dist/payments/PixCheckout.cjs.map +1 -0
  24. package/dist/payments/PixCheckout.js +171 -0
  25. package/dist/payments/PixCheckout.js.map +1 -0
  26. package/dist/payments/PixCheckout.module.cjs +3 -0
  27. package/dist/payments/PixCheckout.module.cjs.map +1 -0
  28. package/dist/payments/PixCheckout.module.js +22 -0
  29. package/dist/payments/PixCheckout.module.js.map +1 -0
  30. package/dist/payments/format.cjs +2 -0
  31. package/dist/payments/format.cjs.map +1 -0
  32. package/dist/payments/format.js +9 -0
  33. package/dist/payments/format.js.map +1 -0
  34. package/dist/payments/mercado-pago.cjs +2 -0
  35. package/dist/payments/mercado-pago.cjs.map +1 -0
  36. package/dist/payments/mercado-pago.js +27 -0
  37. package/dist/payments/mercado-pago.js.map +1 -0
  38. package/dist/payments/outcome.cjs +2 -0
  39. package/dist/payments/outcome.cjs.map +1 -0
  40. package/dist/payments/outcome.js +111 -0
  41. package/dist/payments/outcome.js.map +1 -0
  42. package/dist/payments/types.cjs +2 -0
  43. package/dist/payments/types.cjs.map +1 -0
  44. package/dist/payments/types.js +16 -0
  45. package/dist/payments/types.js.map +1 -0
  46. package/dist/payments/use-mercado-pago-card.cjs +2 -0
  47. package/dist/payments/use-mercado-pago-card.cjs.map +1 -0
  48. package/dist/payments/use-mercado-pago-card.js +128 -0
  49. package/dist/payments/use-mercado-pago-card.js.map +1 -0
  50. package/dist/payments/use-pix-charge.cjs +2 -0
  51. package/dist/payments/use-pix-charge.cjs.map +1 -0
  52. package/dist/payments/use-pix-charge.js +71 -0
  53. package/dist/payments/use-pix-charge.js.map +1 -0
  54. package/dist/query/offline-persistence.cjs +1 -1
  55. package/dist/query/offline-persistence.cjs.map +1 -1
  56. package/dist/query/offline-persistence.js +100 -54
  57. package/dist/query/offline-persistence.js.map +1 -1
  58. package/dist/styles/PixCheckout.css +2 -0
  59. package/dist/styles/component/PixCheckout.css +18 -0
  60. package/dist/styles/manifest.json +6 -0
  61. package/dist/styles/payments.css +18 -0
  62. package/dist/styles.css +1 -1
  63. package/dist/sw/cache.cjs +1 -1
  64. package/dist/sw/cache.cjs.map +1 -1
  65. package/dist/sw/cache.js +1 -1
  66. package/dist/sw/cache.js.map +1 -1
  67. package/dist/tempest-react-sdk.cjs +1 -1
  68. package/dist/tempest-react-sdk.d.ts +913 -29
  69. package/dist/tempest-react-sdk.js +104 -97
  70. package/package.json +1 -1
@@ -6,25 +6,31 @@ import i from "./Markdown.module.js";
6
6
  import { Fragment as a, useMemo as o, useRef as s } from "react";
7
7
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
8
8
  //#region src/components/Markdown/Markdown.tsx
9
- function u(e) {
10
- return e.map((e, t) => {
11
- let n = t;
9
+ function u(e, t) {
10
+ return e.map((e, n) => {
11
+ let r = n;
12
12
  switch (e.type) {
13
- case "text": return /* @__PURE__ */ c(a, { children: e.value }, n);
14
- case "strong": return /* @__PURE__ */ c("strong", { children: u(e.children) }, n);
15
- case "em": return /* @__PURE__ */ c("em", { children: u(e.children) }, n);
16
- case "del": return /* @__PURE__ */ c("del", { children: u(e.children) }, n);
13
+ case "text": return /* @__PURE__ */ c(a, { children: e.value }, r);
14
+ case "strong": return /* @__PURE__ */ c("strong", { children: u(e.children, t) }, r);
15
+ case "em": return /* @__PURE__ */ c("em", { children: u(e.children, t) }, r);
16
+ case "del": return /* @__PURE__ */ c("del", { children: u(e.children, t) }, r);
17
+ case "link": return /* @__PURE__ */ c("a", {
18
+ className: i.link,
19
+ href: e.href,
20
+ ...t,
21
+ children: u(e.children, t)
22
+ }, r);
17
23
  case "code": return /* @__PURE__ */ c("code", {
18
24
  className: i.inlineCode,
19
25
  children: e.value
20
- }, n);
26
+ }, r);
21
27
  case "image": return /* @__PURE__ */ c("img", {
22
28
  className: i.image,
23
29
  src: e.src,
24
30
  alt: e.alt
25
- }, n);
26
- case "break": return /* @__PURE__ */ c("br", {}, n);
27
- default: return null;
31
+ }, r);
32
+ case "break": return /* @__PURE__ */ c("br", {}, r);
33
+ default: return e;
28
34
  }
29
35
  });
30
36
  }
@@ -45,36 +51,31 @@ function f({ source: t, headingOffset: n = 2, highlightCode: a = !0, showLineNum
45
51
  }, t))
46
52
  });
47
53
  }
48
- function p({ block: e, headingOffset: t, highlightCode: r, showLineNumbers: o, linkProps: s }) {
49
- let l = (e) => e.map((e, n) => /* @__PURE__ */ c(p, {
54
+ function p({ block: e, headingOffset: t, highlightCode: r, showLineNumbers: a, linkProps: o }) {
55
+ let s = (e) => e.map((e, n) => /* @__PURE__ */ c(p, {
50
56
  block: e,
51
57
  headingOffset: t,
52
58
  highlightCode: r,
53
- showLineNumbers: o,
54
- linkProps: s
55
- }, n)), d = (e) => e.map((e, t) => e.type === "link" ? /* @__PURE__ */ c("a", {
56
- className: i.link,
57
- href: e.href,
58
- ...s,
59
- children: u(e.children)
60
- }, t) : /* @__PURE__ */ c(a, { children: u([e]) }, t));
59
+ showLineNumbers: a,
60
+ linkProps: o
61
+ }, n)), l = (e) => u(e, o);
61
62
  switch (e.type) {
62
63
  case "heading": {
63
64
  let n = Math.min(6, Math.max(1, e.level + t - 1)), r = `h${n}`;
64
65
  return /* @__PURE__ */ c(r, {
65
66
  className: i[`h${n}`],
66
- children: d(e.children)
67
+ children: l(e.children)
67
68
  });
68
69
  }
69
- case "paragraph": return /* @__PURE__ */ c("p", { children: d(e.children) });
70
+ case "paragraph": return /* @__PURE__ */ c("p", { children: l(e.children) });
70
71
  case "code": return r ? /* @__PURE__ */ c(n, {
71
72
  code: e.value,
72
73
  language: e.language ?? void 0,
73
- showLineNumbers: o
74
+ showLineNumbers: a
74
75
  }) : /* @__PURE__ */ c("pre", { children: /* @__PURE__ */ c("code", { children: e.value }) });
75
76
  case "quote": return /* @__PURE__ */ c("blockquote", {
76
77
  className: i.quote,
77
- children: l(e.children)
78
+ children: s(e.children)
78
79
  });
79
80
  case "rule": return /* @__PURE__ */ c("hr", { className: i.rule });
80
81
  case "list": return e.ordered ? /* @__PURE__ */ c("ol", {
@@ -82,18 +83,18 @@ function p({ block: e, headingOffset: t, highlightCode: r, showLineNumbers: o, l
82
83
  start: e.start === 1 ? void 0 : e.start,
83
84
  children: e.items.map((e, t) => /* @__PURE__ */ c("li", {
84
85
  className: i.item,
85
- children: l(e)
86
+ children: s(e)
86
87
  }, t))
87
88
  }) : /* @__PURE__ */ c("ul", {
88
89
  className: i.list,
89
90
  children: e.items.map((e, t) => /* @__PURE__ */ c("li", {
90
91
  className: i.item,
91
- children: l(e)
92
+ children: s(e)
92
93
  }, t))
93
94
  });
94
95
  case "table": return /* @__PURE__ */ c(m, {
95
96
  block: e,
96
- inline: d
97
+ inline: l
97
98
  });
98
99
  default: return null;
99
100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.js","names":["styles","Markdown_module_default","renderInline","nodes","key","index","node","Fragment","alignOf","align","Markdown","rest","blocks","useMemo","parseMarkdown","source","cn","className","Block","children","child","inline","linkProps","block","level","headingOffset","Tag","highlightCode","CodeBlock","item","Table","scroll","useRef","overflowing","useScrollOverflow","cell","row","cellIndex","rowIndex"],"sources":["../../../src/components/Markdown/Markdown.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines — the renderer maps every block and inline node the\n * parser can emit to an element, and the length is that mapping — one arm per node\n * kind, no branching to extract.\n */\nimport { Fragment, useMemo, useRef, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport { useScrollOverflow } from \"@/hooks/use-scroll-overflow\";\nimport { cn } from \"@/utils/cn\";\n\nimport { CodeBlock } from \"../CodeBlock\";\nimport {\n parseMarkdown,\n type MarkdownAlign,\n type MarkdownBlock,\n type MarkdownInline,\n} from \"./markdown-parse\";\nimport styles from \"./Markdown.module.css\";\n\n/** DOM attributes this component redefines. */\ntype OverriddenDomProps = \"children\";\n\nexport interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps> {\n /** The Markdown source. */\n source: string;\n /**\n * Heading level the document's `#` maps to. Default 2.\n *\n * A comment body rendered inside a page whose `<h1>` is the page title must not\n * emit a second `<h1>`; shifting the whole scale keeps the outline valid.\n */\n headingOffset?: number;\n /** Render fenced code with `CodeBlock` (copy button, line numbers). Default `true`. */\n highlightCode?: boolean;\n /** Show line numbers in fenced code. Default `false`. */\n showLineNumbers?: boolean;\n /** Extra props for every link — `target=\"_blank\"`, an analytics handler. */\n linkProps?: HTMLAttributes<HTMLAnchorElement> & { target?: string; rel?: string };\n}\n\n/** Render inline nodes. */\nfunction renderInline(nodes: readonly MarkdownInline[]): ReactNode {\n return nodes.map((node, index) => {\n const key = index;\n switch (node.type) {\n case \"text\":\n return <Fragment key={key}>{node.value}</Fragment>;\n case \"strong\":\n return <strong key={key}>{renderInline(node.children)}</strong>;\n case \"em\":\n return <em key={key}>{renderInline(node.children)}</em>;\n case \"del\":\n return <del key={key}>{renderInline(node.children)}</del>;\n case \"code\":\n return (\n <code key={key} className={styles.inlineCode}>\n {node.value}\n </code>\n );\n case \"image\":\n return <img key={key} className={styles.image} src={node.src} alt={node.alt} />;\n case \"break\":\n return <br key={key} />;\n default:\n return null;\n }\n });\n}\n\n/** CSS `text-align` for a table column. */\nfunction alignOf(align: MarkdownAlign): { textAlign: \"left\" | \"center\" | \"right\" } | undefined {\n return align ? { textAlign: align } : undefined;\n}\n\n/**\n * Rendered Markdown, from a node tree — never from an HTML string.\n *\n * `dangerouslySetInnerHTML` appears nowhere in this component. That is what makes\n * rendering somebody else's Markdown safe by construction rather than by a promise\n * about escaping: a `<script>` in a comment is four characters of text, because text\n * is all a React child can be.\n *\n * Link and image URLs go through a scheme **allowlist** (`http`, `https`, `mailto`,\n * `tel`, `sms`, plus relative), so `[click](javascript:alert(1))` renders as plain\n * text. A blocklist would have to enumerate every spelling of `javascript:` and\n * would miss one.\n *\n * @example\n * <Markdown source={comentario.corpo} linkProps={{ target: \"_blank\", rel: \"noreferrer\" }} />\n */\nexport function Markdown({\n source,\n headingOffset = 2,\n highlightCode = true,\n showLineNumbers = false,\n linkProps,\n className,\n ...rest\n}: MarkdownProps) {\n const blocks = useMemo(() => parseMarkdown(source), [source]);\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {blocks.map((block, index) => (\n <Block\n key={index}\n block={block}\n headingOffset={headingOffset}\n highlightCode={highlightCode}\n showLineNumbers={showLineNumbers}\n linkProps={linkProps}\n />\n ))}\n </div>\n );\n}\n\ninterface BlockProps {\n block: MarkdownBlock;\n headingOffset: number;\n highlightCode: boolean;\n showLineNumbers: boolean;\n linkProps?: MarkdownProps[\"linkProps\"];\n}\n\n/** One block, and its children. */\nfunction Block({ block, headingOffset, highlightCode, showLineNumbers, linkProps }: BlockProps) {\n const children = (nodes: readonly MarkdownBlock[]): ReactNode =>\n nodes.map((child, index) => (\n <Block\n key={index}\n block={child}\n headingOffset={headingOffset}\n highlightCode={highlightCode}\n showLineNumbers={showLineNumbers}\n linkProps={linkProps}\n />\n ));\n\n const inline = (nodes: readonly MarkdownInline[]): ReactNode =>\n nodes.map((node, index) =>\n node.type === \"link\" ? (\n <a key={index} className={styles.link} href={node.href} {...linkProps}>\n {renderInline(node.children)}\n </a>\n ) : (\n <Fragment key={index}>{renderInline([node])}</Fragment>\n ),\n );\n\n switch (block.type) {\n case \"heading\": {\n const level = Math.min(6, Math.max(1, block.level + headingOffset - 1));\n const Tag = `h${level}` as \"h1\";\n return (\n <Tag className={styles[`h${level}` as keyof typeof styles]}>\n {inline(block.children)}\n </Tag>\n );\n }\n case \"paragraph\":\n return <p>{inline(block.children)}</p>;\n case \"code\":\n return highlightCode ? (\n <CodeBlock\n code={block.value}\n language={block.language ?? undefined}\n showLineNumbers={showLineNumbers}\n />\n ) : (\n <pre>\n <code>{block.value}</code>\n </pre>\n );\n case \"quote\":\n return <blockquote className={styles.quote}>{children(block.children)}</blockquote>;\n case \"rule\":\n return <hr className={styles.rule} />;\n case \"list\":\n return block.ordered ? (\n <ol className={styles.list} start={block.start === 1 ? undefined : block.start}>\n {block.items.map((item, index) => (\n <li key={index} className={styles.item}>\n {children(item)}\n </li>\n ))}\n </ol>\n ) : (\n <ul className={styles.list}>\n {block.items.map((item, index) => (\n <li key={index} className={styles.item}>\n {children(item)}\n </li>\n ))}\n </ul>\n );\n case \"table\":\n return <Table block={block} inline={inline} />;\n default:\n return null;\n }\n}\n\n/**\n * A table, in its own scroll box.\n *\n * The box only becomes a tab stop while it actually overflows: a scroll container\n * with nothing focusable inside cannot be reached by keyboard, and adding the stop\n * unconditionally would pollute the tab order with one entry per table on the page.\n */\nfunction Table({\n block,\n inline,\n}: {\n block: Extract<MarkdownBlock, { type: \"table\" }>;\n inline: (nodes: readonly MarkdownInline[]) => ReactNode;\n}) {\n const scroll = useRef<HTMLDivElement | null>(null);\n const overflowing = useScrollOverflow(scroll, \"horizontal\");\n\n return (\n <div\n ref={scroll}\n className={styles.tableScroll}\n tabIndex={overflowing ? 0 : undefined}\n role={overflowing ? \"region\" : undefined}\n aria-label={overflowing ? \"Tabela rolável\" : undefined}\n >\n <table className={styles.table}>\n <thead>\n <tr>\n {block.head.map((cell, index) => (\n <th key={index} style={alignOf(block.align[index] ?? null)}>\n {inline(cell)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {block.rows.map((row, rowIndex) => (\n <tr key={rowIndex}>\n {row.map((cell, cellIndex) => (\n <td key={cellIndex} style={alignOf(block.align[cellIndex] ?? null)}>\n {inline(cell)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAyCA,SAASE,EAAa,GAA6C;CAC/D,OAAOC,EAAM,KAAK,GAAM,MAAU;EAC9B,IAAMC,IAAMC;EACZ,QAAQC,EAAK,MAAb;GACI,KAAK,QACD,OAAO,kBAACC,GAAD,EAAA,UAAqBD,EAAK,MAAgB,GAA3BF,CAA2B;GACrD,KAAK,UACD,OAAO,kBAAC,UAAD,EAAA,UAAmBF,EAAaI,EAAK,QAAQ,EAAU,GAA1CF,CAA0C;GAClE,KAAK,MACD,OAAO,kBAAC,MAAD,EAAA,UAAeF,EAAaI,EAAK,QAAQ,EAAM,GAAtCF,CAAsC;GAC1D,KAAK,OACD,OAAO,kBAAC,OAAD,EAAA,UAAgBF,EAAaI,EAAK,QAAQ,EAAO,GAAvCF,CAAuC;GAC5D,KAAK,QACD,OACI,kBAAC,QAAD;IAAgB,WAAWJ,EAAO;IAC7B,UAAAM,EAAK;GACJ,GAFKF,CAEL;GAEd,KAAK,SACD,OAAO,kBAAC,OAAD;IAAe,WAAWJ,EAAO;IAAO,KAAKM,EAAK;IAAK,KAAKA,EAAK;GAAM,GAA7DF,CAA6D;GAClF,KAAK,SACD,OAAO,kBAAC,MAAD,CAAe,GAANA,CAAM;GAC1B,SACI,OAAO;EACf;CACJ,CAAC;AACL;AAGA,SAASI,EAAQ,GAA8E;CAC3F,OAAOC,IAAQ,EAAE,WAAWA,EAAM,IAAI,KAAA;AAC1C;AAkBA,SAAgBC,EAAS,EACrB,WACA,mBAAgB,GAChB,mBAAgB,IAChB,qBAAkB,IAClB,cACA,cACA,GAAGC,KACW;CACd,IAAMC,IAASC,QAAcC,EAAcC,CAAM,GAAG,CAACA,CAAM,CAAC;CAE5D,OACI,kBAAC,OAAD;EAAK,WAAWC,EAAGhB,EAAO,MAAMiB,CAAS;EAAG,GAAIN;EAC3C,UAAAC,EAAO,KAAK,GAAO,MAChB,kBAACM,GAAD;GAEW;GACQ;GACA;GACE;GACN;EACd,GANQb,CAMR,CACJ;CACA,CAAA;AAEb;AAWA,SAASa,EAAM,EAAE,UAAO,kBAAe,kBAAe,oBAAiB,gBAAyB;CAC5F,IAAMC,KAAY,MACdhB,EAAM,KAAK,GAAO,MACd,kBAACe,GAAD;EAEI,OAAOE;EACQ;EACA;EACE;EACN;CACd,GANQf,CAMR,CACJ,GAECgB,KAAU,MACZlB,EAAM,KAAK,GAAM,MACbG,EAAK,SAAS,SACV,kBAAC,KAAD;EAAe,WAAWN,EAAO;EAAM,MAAMM,EAAK;EAAM,GAAIgB;EACvD,UAAApB,EAAaI,EAAK,QAAQ;CAC5B,GAFKD,CAEL,IAEH,kBAACE,GAAD,EAAA,UAAuBL,EAAa,CAACI,CAAI,CAAC,EAAY,GAAvCD,CAAuC,CAE9D;CAEJ,QAAQkB,EAAM,MAAd;EACI,KAAK,WAAW;GACZ,IAAMC,IAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGD,EAAM,QAAQE,IAAgB,CAAC,CAAC,GAChEC,IAAM,IAAIF;GAChB,OACI,kBAACE,GAAD;IAAK,WAAW1B,EAAO,IAAIwB;IACtB,UAAAH,EAAOE,EAAM,QAAQ;GACrB,CAAA;EAEb;EACA,KAAK,aACD,OAAO,kBAAC,KAAD,EAAA,UAAIF,EAAOE,EAAM,QAAQ,EAAK,CAAA;EACzC,KAAK,QACD,OAAOI,IACH,kBAACC,GAAD;GACI,MAAML,EAAM;GACZ,UAAUA,EAAM,YAAY,KAAA;GACX;EACpB,CAAA,IAED,kBAAC,OAAD,EAAA,UACI,kBAAC,QAAD,EAAA,UAAOA,EAAM,MAAY,CAAA,EACxB,CAAA;EAEb,KAAK,SACD,OAAO,kBAAC,cAAD;GAAY,WAAWvB,EAAO;GAAQ,UAAAmB,EAASI,EAAM,QAAQ;EAAc,CAAA;EACtF,KAAK,QACD,OAAO,kBAAC,MAAD,EAAI,WAAWvB,EAAO,KAAO,CAAA;EACxC,KAAK,QACD,OAAOuB,EAAM,UACT,kBAAC,MAAD;GAAI,WAAWvB,EAAO;GAAM,OAAOuB,EAAM,UAAU,IAAI,KAAA,IAAYA,EAAM;GACpE,UAAAA,EAAM,MAAM,KAAK,GAAM,MACpB,kBAAC,MAAD;IAAgB,WAAWvB,EAAO;IAC7B,UAAAmB,EAASU,CAAI;GACd,GAFKxB,CAEL,CACP;EACD,CAAA,IAEJ,kBAAC,MAAD;GAAI,WAAWL,EAAO;GACjB,UAAAuB,EAAM,MAAM,KAAK,GAAM,MACpB,kBAAC,MAAD;IAAgB,WAAWvB,EAAO;IAC7B,UAAAmB,EAASU,CAAI;GACd,GAFKxB,CAEL,CACP;EACD,CAAA;EAEZ,KAAK,SACD,OAAO,kBAACyB,GAAD;GAAc;GAAe;EAAS,CAAA;EACjD,SACI,OAAO;CACf;AACJ;AASA,SAASA,EAAM,EACX,UACA,aAID;CACC,IAAMC,IAASC,EAA8B,IAAI,GAC3CC,IAAcC,EAAkBH,GAAQ,YAAY;CAE1D,OACI,kBAAC,OAAD;EACI,KAAKA;EACL,WAAW/B,EAAO;EAClB,UAAUiC,IAAc,IAAI,KAAA;EAC5B,MAAMA,IAAc,WAAW,KAAA;EAC/B,cAAYA,IAAc,mBAAmB,KAAA;EAE7C,UAAA,kBAAC,SAAD;GAAO,WAAWjC,EAAO;GAAzB,UAAA,CACI,kBAAC,SAAD,EAAA,UACI,kBAAC,MAAD,EAAA,UACKuB,EAAM,KAAK,KAAK,GAAM,MACnB,kBAAC,MAAD;IAAgB,OAAOf,EAAQe,EAAM,MAAMlB,MAAU,IAAI;IACpD,UAAAgB,EAAOc,CAAI;GACZ,GAFK9B,CAEL,CACP,EACD,CAAA,EACD,CAAA,GACP,kBAAC,SAAD,EAAA,UACKkB,EAAM,KAAK,KAAK,GAAK,MAClB,kBAAC,MAAD,EAAA,UACKa,EAAI,KAAK,GAAM,MACZ,kBAAC,MAAD;IAAoB,OAAO5B,EAAQe,EAAM,MAAMc,MAAc,IAAI;IAC5D,UAAAhB,EAAOc,CAAI;GACZ,GAFKE,CAEL,CACP,EACD,GANKC,CAML,CACP,EACE,CAAA,CACJ;;CACN,CAAA;AAEb"}
1
+ {"version":3,"file":"Markdown.js","names":["styles","unhandled","Markdown_module_default","renderInline","nodes","key","index","node","Fragment","linkProps","alignOf","align","Markdown","rest","blocks","useMemo","parseMarkdown","source","cn","className","Block","children","child","inline","block","level","headingOffset","Tag","highlightCode","CodeBlock","item","Table","scroll","useRef","overflowing","useScrollOverflow","cell","row","cellIndex","rowIndex"],"sources":["../../../src/components/Markdown/Markdown.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines — the renderer maps every block and inline node the\n * parser can emit to an element, and the length is that mapping — one arm per node\n * kind, no branching to extract.\n */\nimport { Fragment, useMemo, useRef, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport { useScrollOverflow } from \"@/hooks/use-scroll-overflow\";\nimport { cn } from \"@/utils/cn\";\n\nimport { CodeBlock } from \"../CodeBlock\";\nimport {\n parseMarkdown,\n type MarkdownAlign,\n type MarkdownBlock,\n type MarkdownInline,\n} from \"./markdown-parse\";\nimport styles from \"./Markdown.module.css\";\n\n/** DOM attributes this component redefines. */\ntype OverriddenDomProps = \"children\";\n\nexport interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps> {\n /** The Markdown source. */\n source: string;\n /**\n * Heading level the document's `#` maps to. Default 2.\n *\n * A comment body rendered inside a page whose `<h1>` is the page title must not\n * emit a second `<h1>`; shifting the whole scale keeps the outline valid.\n */\n headingOffset?: number;\n /** Render fenced code with `CodeBlock` (copy button, line numbers). Default `true`. */\n highlightCode?: boolean;\n /** Show line numbers in fenced code. Default `false`. */\n showLineNumbers?: boolean;\n /** Extra props for every link — `target=\"_blank\"`, an analytics handler. */\n linkProps?: HTMLAttributes<HTMLAnchorElement> & { target?: string; rel?: string };\n}\n\n/**\n * Render inline nodes, at any depth.\n *\n * Every node kind has its arm here, the link included, because a link is as\n * likely to sit inside `**…**` as at the top of a paragraph. The link used to be\n * handled only by the block renderer's top-level pass, so this function hit its\n * `default` for a link nested in emphasis and returned `null`: `**[texto](url)**`\n * rendered an empty `<strong>` and the words were gone (#599). The `never` check\n * in the `default` arm makes a node kind without a renderer a type error instead\n * of silently missing text.\n *\n * @param nodes - Inline nodes from the parser.\n * @param linkProps - Extra props for every link, however deep.\n * @returns The React children.\n */\nfunction renderInline(\n nodes: readonly MarkdownInline[],\n linkProps: MarkdownProps[\"linkProps\"],\n): ReactNode {\n return nodes.map((node, index) => {\n const key = index;\n switch (node.type) {\n case \"text\":\n return <Fragment key={key}>{node.value}</Fragment>;\n case \"strong\":\n return <strong key={key}>{renderInline(node.children, linkProps)}</strong>;\n case \"em\":\n return <em key={key}>{renderInline(node.children, linkProps)}</em>;\n case \"del\":\n return <del key={key}>{renderInline(node.children, linkProps)}</del>;\n case \"link\":\n return (\n <a key={key} className={styles.link} href={node.href} {...linkProps}>\n {renderInline(node.children, linkProps)}\n </a>\n );\n case \"code\":\n return (\n <code key={key} className={styles.inlineCode}>\n {node.value}\n </code>\n );\n case \"image\":\n return <img key={key} className={styles.image} src={node.src} alt={node.alt} />;\n case \"break\":\n return <br key={key} />;\n default: {\n const unhandled: never = node;\n return unhandled;\n }\n }\n });\n}\n\n/** CSS `text-align` for a table column. */\nfunction alignOf(align: MarkdownAlign): { textAlign: \"left\" | \"center\" | \"right\" } | undefined {\n return align ? { textAlign: align } : undefined;\n}\n\n/**\n * Rendered Markdown, from a node tree — never from an HTML string.\n *\n * `dangerouslySetInnerHTML` appears nowhere in this component. That is what makes\n * rendering somebody else's Markdown safe by construction rather than by a promise\n * about escaping: a `<script>` in a comment is four characters of text, because text\n * is all a React child can be.\n *\n * Link and image URLs go through a scheme **allowlist** (`http`, `https`, `mailto`,\n * `tel`, `sms`, plus relative), so `[click](javascript:alert(1))` renders as plain\n * text. A blocklist would have to enumerate every spelling of `javascript:` and\n * would miss one.\n *\n * @example\n * <Markdown source={comentario.corpo} linkProps={{ target: \"_blank\", rel: \"noreferrer\" }} />\n */\nexport function Markdown({\n source,\n headingOffset = 2,\n highlightCode = true,\n showLineNumbers = false,\n linkProps,\n className,\n ...rest\n}: MarkdownProps) {\n const blocks = useMemo(() => parseMarkdown(source), [source]);\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {blocks.map((block, index) => (\n <Block\n key={index}\n block={block}\n headingOffset={headingOffset}\n highlightCode={highlightCode}\n showLineNumbers={showLineNumbers}\n linkProps={linkProps}\n />\n ))}\n </div>\n );\n}\n\ninterface BlockProps {\n block: MarkdownBlock;\n headingOffset: number;\n highlightCode: boolean;\n showLineNumbers: boolean;\n linkProps?: MarkdownProps[\"linkProps\"];\n}\n\n/** One block, and its children. */\nfunction Block({ block, headingOffset, highlightCode, showLineNumbers, linkProps }: BlockProps) {\n const children = (nodes: readonly MarkdownBlock[]): ReactNode =>\n nodes.map((child, index) => (\n <Block\n key={index}\n block={child}\n headingOffset={headingOffset}\n highlightCode={highlightCode}\n showLineNumbers={showLineNumbers}\n linkProps={linkProps}\n />\n ));\n\n const inline = (nodes: readonly MarkdownInline[]): ReactNode => renderInline(nodes, linkProps);\n\n switch (block.type) {\n case \"heading\": {\n const level = Math.min(6, Math.max(1, block.level + headingOffset - 1));\n const Tag = `h${level}` as \"h1\";\n return (\n <Tag className={styles[`h${level}` as keyof typeof styles]}>\n {inline(block.children)}\n </Tag>\n );\n }\n case \"paragraph\":\n return <p>{inline(block.children)}</p>;\n case \"code\":\n return highlightCode ? (\n <CodeBlock\n code={block.value}\n language={block.language ?? undefined}\n showLineNumbers={showLineNumbers}\n />\n ) : (\n <pre>\n <code>{block.value}</code>\n </pre>\n );\n case \"quote\":\n return <blockquote className={styles.quote}>{children(block.children)}</blockquote>;\n case \"rule\":\n return <hr className={styles.rule} />;\n case \"list\":\n return block.ordered ? (\n <ol className={styles.list} start={block.start === 1 ? undefined : block.start}>\n {block.items.map((item, index) => (\n <li key={index} className={styles.item}>\n {children(item)}\n </li>\n ))}\n </ol>\n ) : (\n <ul className={styles.list}>\n {block.items.map((item, index) => (\n <li key={index} className={styles.item}>\n {children(item)}\n </li>\n ))}\n </ul>\n );\n case \"table\":\n return <Table block={block} inline={inline} />;\n default:\n return null;\n }\n}\n\n/**\n * A table, in its own scroll box.\n *\n * The box only becomes a tab stop while it actually overflows: a scroll container\n * with nothing focusable inside cannot be reached by keyboard, and adding the stop\n * unconditionally would pollute the tab order with one entry per table on the page.\n */\nfunction Table({\n block,\n inline,\n}: {\n block: Extract<MarkdownBlock, { type: \"table\" }>;\n inline: (nodes: readonly MarkdownInline[]) => ReactNode;\n}) {\n const scroll = useRef<HTMLDivElement | null>(null);\n const overflowing = useScrollOverflow(scroll, \"horizontal\");\n\n return (\n <div\n ref={scroll}\n className={styles.tableScroll}\n tabIndex={overflowing ? 0 : undefined}\n role={overflowing ? \"region\" : undefined}\n aria-label={overflowing ? \"Tabela rolável\" : undefined}\n >\n <table className={styles.table}>\n <thead>\n <tr>\n {block.head.map((cell, index) => (\n <th key={index} style={alignOf(block.align[index] ?? null)}>\n {inline(cell)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {block.rows.map((row, rowIndex) => (\n <tr key={rowIndex}>\n {row.map((cell, cellIndex) => (\n <td key={cellIndex} style={alignOf(block.align[cellIndex] ?? null)}>\n {inline(cell)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  const e=require("../../utils/safe-url.cjs");var t=/^\s{0,3}(`{3,}|~{3,})\s*([\w+-]*)$/,n=/^\s{0,3}(#{1,6})\s+/,r=/^\s{0,3}([-*_])\s*(?:\1\s*){2,}$/,i=/^\s{0,3}>\s?(.*)$/,a=/^([^\S\n\r]*)([-*+])[^\S\n\r]+/,o=/^([^\S\n\r]*)(\d{1,9})[.)][^\S\n\r]+/;function s(e,t){let n=e.exec(t);if(!n)return null;let r=t.slice(n[0].length);return r.includes(`\u2028`)||r.includes(`\u2029`)?null:{indent:n[1],marker:n[2],content:r}}function c(e){return s(a,e)}function l(e){return s(o,e)}var u=/^\s{0,3}\|[\s|:-]*$|^\s{0,3}:?-+:?(\s*\|\s*:?-+:?)+\s*\|?$/,d=32;function f(e){let t=n.exec(e);if(!t)return null;let r=e.slice(t[0].length).trimEnd(),i=r.length;for(;i>0&&r[i-1]===`#`;)--i;return r=r.slice(0,i).trimEnd(),{level:t[1].length,text:r}}function p(e){return e.endsWith(` `)}function m(e){return h(e.replace(/\r\n?/g,`
2
2
  `).split(`
3
3
  `),0)}function h(e,n){if(n>=d){let t=e.map(e=>e.trim()).filter(Boolean).join(`
4
- `);return t?[{type:`paragraph`,children:S(t)}]:[]}let a=[],o=0;for(;o<e.length;){let s=e[o];if(s.trim()===``){o+=1;continue}let d=t.exec(s.trimEnd());if(d){let t=d[1][0],n=[];for(o+=1;o<e.length&&!RegExp(`^\\s{0,3}${t}{3,}\\s*$`).test(e[o]);)n.push(e[o]),o+=1;o+=1,a.push({type:`code`,language:d[2]||null,value:n.join(`
5
- `)});continue}let m=f(s);if(m){a.push({type:`heading`,level:m.level,children:S(m.text)}),o+=1;continue}if(r.test(s)){a.push({type:`rule`}),o+=1;continue}if(i.test(s)){let t=[];for(;o<e.length;){let n=i.exec(e[o]);if(n)t.push(n[1]),o+=1;else{if(e[o].trim()===``)break;t.push(e[o]),o+=1}}a.push({type:`quote`,children:h(t,n+1)});continue}if(c(s)||l(s)){let[t,r]=_(e,o,n);a.push(t),o=r;continue}if(o+1<e.length&&s.includes(`|`)&&u.test(e[o+1].trimEnd())){let[t,n]=y(e,o);a.push(t),o=n;continue}let v=[],b=[];for(;o<e.length&&e[o].trim()!==``;){let n=e[o];if(f(n)||r.test(n)||t.test(n.trimEnd())||i.test(n)||c(n)||l(n))break;v.push(n.trim()),b.push(p(n)),o+=1}v.length>0&&a.push({type:`paragraph`,children:S(g(v,b))})}return a}function g(e,t){return e.map((n,r)=>t[r]&&r<e.length-1?`${n} `:n).join(`
6
- `)}function _(e,t,n){let r=c(e[t]),i=l(e[t]),a=i!==null,o=(i??r)?.indent.length??0,s=a?Number(i?.marker??1):1,u=[],d=[],f=t,p=()=>{d.length!==0&&(u.push(h(d,n+1)),d=[])};for(;f<e.length;){let t=e[f];if(t.trim()===``){if(f+1<e.length&&e[f+1].trim()!==``){d.push(``),f+=1;continue}break}let n=c(t),r=l(t),i=n??r;if(i&&i.indent.length<=o){if(!(a?r:n))break;p(),d.push(i.content),f+=1}else if(i)d.push(t.slice(o)),f+=1;else if(t.search(/\S/)>o)d.push(t.trim()),f+=1;else break}return p(),[{type:`list`,ordered:a,start:s,items:u},f]}function v(e){let t=e.trim().replace(/^\|/,``).replace(/\|$/,``),n=[],r=``;for(let e=0;e<t.length;e+=1)t[e]===`\\`&&t[e+1]===`|`?(r+=`|`,e+=1):t[e]===`|`?(n.push(r),r=``):r+=t[e];return n.push(r),n.map(e=>e.trim())}function y(e,t){let n=v(e[t]),r=v(e[t+1]).map(e=>{let t=e.startsWith(`:`),n=e.endsWith(`:`);return t&&n?`center`:n?`right`:t?`left`:null}),i=[],a=t+2;for(;a<e.length&&e[a].trim()!==``&&e[a].includes(`|`);)i.push(v(e[a]).map(S)),a+=1;return[{type:`table`,align:r,head:n.map(S),rows:i},a]}var b=[{guard:{kind:`link`,opener:`![`},first:`!`,pattern:/^!\[([^\]]*)\]\(((?:[^()\s]|\([^()\s]*\))+)(?:\s+"[^"]*")?\)/,build:t=>{let n=e.safeImageUrl(t[2]);return n?{type:`image`,src:n,alt:t[1]}:{type:`text`,value:t[1]}}},{guard:{kind:`link`,opener:`[`},first:`[`,pattern:/^\[([^\]]*)\]\(((?:[^()\s]|\([^()\s]*\))+)(?:\s+"[^"]*")?\)/,build:t=>{let n=e.safeLinkUrl(t[2]),r=S(t[1]);return n?{type:`link`,href:n,children:r}:{type:`text`,value:t[1]}}},{first:"`",pattern:/^`([^`]+)`/,build:e=>({type:`code`,value:e[1]})},{first:`*`,pattern:/^\*\*([\s\S]+?)\*\*/,build:e=>({type:`strong`,children:S(e[1])})},{first:`_`,pattern:/^__([\s\S]+?)__/,build:e=>({type:`strong`,children:S(e[1])})},{first:`~`,pattern:/^~~([\s\S]+?)~~/,build:e=>({type:`del`,children:S(e[1])})},{first:`*`,pattern:/^\*([^*\n]+)\*/,build:e=>({type:`em`,children:S(e[1])})},{first:`_`,pattern:/^_([^_\n]+)_/,build:e=>({type:`em`,children:S(e[1])})},{guard:{kind:`autolink`,opener:`<`},first:`<`,pattern:/^<((?:https?:\/\/|mailto:)[^>\s]+)>/,build:t=>{let n=e.safeLinkUrl(t[1]);return n?{type:`link`,href:n,children:[{type:`text`,value:t[1]}]}:{type:`text`,value:t[1]}}},{first:`\\`,pattern:/^\\\n/,build:()=>({type:`break`})}],x=new Set(b.map(e=>e.first));function S(e){let t=[],n=``,r=0,i=-1,a=-1,o=-1,s=/[>\s]/g,c=()=>{n&&t.push({type:`text`,value:n}),n=``},l=t=>{if(i<t){let n=e.indexOf(`]`,t);i=n===-1?e.length:n}return i},u=t=>(o<t&&(s.lastIndex=t,o=s.exec(e)?.index??e.length),o),d=t=>{if(!t)return!0;if(!e.startsWith(t.opener,r))return!1;if(t.kind===`autolink`)return e[u(r+1)]===`>`;let n=l(r+t.opener.length);return e[n+1]===`(`&&n!==a};for(;r<e.length;){if(e[r]===`\\`&&r+1<e.length&&e[r+1]!==`
7
- `){n+=e[r+1],r+=2;continue}if(e[r]===` `){let i=r;for(;e[i]===` `;)i+=1;i-r>=2&&e[i]===`
8
- `?(c(),t.push({type:`break`}),r=i+1):(n+=e.slice(r,i),r=i);continue}if(!x.has(e[r])){n+=e[r],r+=1;continue}let i=e.slice(r),o=!1;for(let n of b){if(n.first!==e[r]||!d(n.guard))continue;let s=n.pattern.exec(i);if(!s){n.guard?.kind===`link`&&(a=l(r+n.guard.opener.length));continue}let u=n.build(s);if(u){c(),t.push(u),r+=s[0].length,o=!0;break}}o||(n+=e[r],r+=1)}return c(),t}exports.parseInline=S,exports.parseMarkdown=m;
4
+ `);return t?[{type:`paragraph`,children:E(t)}]:[]}let a=[],o=0;for(;o<e.length;){let s=e[o];if(s.trim()===``){o+=1;continue}let d=t.exec(s.trimEnd());if(d){let t=d[1][0],n=[];for(o+=1;o<e.length&&!RegExp(`^\\s{0,3}${t}{3,}\\s*$`).test(e[o]);)n.push(e[o]),o+=1;o+=1,a.push({type:`code`,language:d[2]||null,value:n.join(`
5
+ `)});continue}let m=f(s);if(m){a.push({type:`heading`,level:m.level,children:E(m.text)}),o+=1;continue}if(r.test(s)){a.push({type:`rule`}),o+=1;continue}if(i.test(s)){let t=[];for(;o<e.length;){let n=i.exec(e[o]);if(n)t.push(n[1]),o+=1;else{if(e[o].trim()===``)break;t.push(e[o]),o+=1}}a.push({type:`quote`,children:h(t,n+1)});continue}if(c(s)||l(s)){let[t,r]=_(e,o,n);a.push(t),o=r;continue}if(o+1<e.length&&s.includes(`|`)&&u.test(e[o+1].trimEnd())){let[t,n]=y(e,o);a.push(t),o=n;continue}let v=[],b=[];for(;o<e.length&&e[o].trim()!==``;){let n=e[o];if(f(n)||r.test(n)||t.test(n.trimEnd())||i.test(n)||c(n)||l(n))break;v.push(n.trim()),b.push(p(n)),o+=1}v.length>0&&a.push({type:`paragraph`,children:E(g(v,b))})}return a}function g(e,t){return e.map((n,r)=>t[r]&&r<e.length-1?`${n} `:n).join(`
6
+ `)}function _(e,t,n){let r=c(e[t]),i=l(e[t]),a=i!==null,o=(i??r)?.indent.length??0,s=a?Number(i?.marker??1):1,u=[],d=[],f=t,p=()=>{d.length!==0&&(u.push(h(d,n+1)),d=[])};for(;f<e.length;){let t=e[f];if(t.trim()===``){if(f+1<e.length&&e[f+1].trim()!==``){d.push(``),f+=1;continue}break}let n=c(t),r=l(t),i=n??r;if(i&&i.indent.length<=o){if(!(a?r:n))break;p(),d.push(i.content),f+=1}else if(i)d.push(t.slice(o)),f+=1;else if(t.search(/\S/)>o)d.push(t.trim()),f+=1;else break}return p(),[{type:`list`,ordered:a,start:s,items:u},f]}function v(e){let t=e.trim().replace(/^\|/,``).replace(/\|$/,``),n=[],r=``;for(let e=0;e<t.length;e+=1)t[e]===`\\`&&t[e+1]===`|`?(r+=`|`,e+=1):t[e]===`|`?(n.push(r),r=``):r+=t[e];return n.push(r),n.map(e=>e.trim())}function y(e,t){let n=v(e[t]),r=v(e[t+1]).map(e=>{let t=e.startsWith(`:`),n=e.endsWith(`:`);return t&&n?`center`:n?`right`:t?`left`:null}),i=[],a=t+2;for(;a<e.length&&e[a].trim()!==``&&e[a].includes(`|`);)i.push(v(e[a]).map(E)),a+=1;return[{type:`table`,align:r,head:n.map(E),rows:i},a]}var b=/\]\(((?:[^()\s]|\([^()\s]*\))+)(?:\s+"[^"]*")?\)/y,x=/https?:\/\/|mailto:/y,S=new Set(["`",`[`,`!`,`<`]),C=new Set([`*`,`_`,`~`]);function w(e,t){let n=new Int32Array(e.length+1);n[e.length]=e.length;for(let r=e.length-1;r>=0;--r)n[r]=t(e[r])?r:n[r+1];return n}function T(e,t,n){return e===`~`?{type:`del`,children:n}:t===1?{type:`em`,children:n}:t===2?{type:`strong`,children:n}:{type:`em`,children:[{type:`strong`,children:n}]}}function E(t){let n=t.length,r=null,i=null,a=null,o=new Map,s=new Map,c=e=>(o.has(e)||(b.lastIndex=e,o.set(e,b.exec(t))),o.get(e)??null),l=(e,n)=>{let r=e;for(;r<n&&t[r]===t[e];)r+=1;return r-e},u=i=>{let a=t[i]===`!`;if(a&&t[i+1]!==`[`)return null;let o=i+(a?2:1);r??=w(t,e=>e===`]`);let s=r[o];if(s>=n)return null;let l=c(s);return l?{end:s+l[0].length,build:()=>{let n=t.slice(o,s);if(a){let t=e.safeImageUrl(l[1]);return t?{type:`image`,src:t,alt:n}:{type:`text`,value:n}}let r=e.safeLinkUrl(l[1]);return r?{type:`link`,href:r,children:m(o,s,!0)}:{type:`text`,value:n}}}:null},d=r=>{let o=t[r];if(o==="`"){i??=w(t,e=>e==="`");let e=i[r+1];return e>=n||e===r+1?null:{end:e+1,build:()=>({type:`code`,value:t.slice(r+1,e)})}}if(o===`<`){a??=w(t,e=>e===`>`||/\s/.test(e));let n=a[r+1];if(t[n]!==`>`)return null;x.lastIndex=r+1;let i=x.exec(t);return!i||r+1+i[0].length>=n?null:{end:n+1,build:i=>{if(i)return{type:`text`,value:t.slice(r,n+1)};let a=t.slice(r+1,n),o=e.safeLinkUrl(a),s={type:`text`,value:a};return o?{type:`link`,href:o,children:[s]}:s}}}return u(r)},f=(e,n)=>{if(!S.has(t[e]))return null;s.has(e)||s.set(e,d(e));let r=s.get(e)??null;return r&&r.end<=n?r:null},p=(e,n,r,i)=>{let a=r;for(;a<i;){let r=t[a];if(r===`\\`){a+=2;continue}if(r===`
7
+ `&&n===1)return{close:-1,stop:a};if(r===e){let t=l(a,i);if(t===n)return{close:a,stop:a};if(t===3&&e!==`~`)return{close:a+3-n,stop:a};a+=t;continue}let o=f(a,i);a=o?o.end:a+1}return{close:-1,stop:i}};function m(e,n,r){let i=[],a=new Map,o=``,s=e,c=e=>{e.type===`text`?o+=e.value:(o&&i.push({type:`text`,value:o}),o=``,i.push(e))},u=e=>{let i=t[e],o=l(e,n);if(!(i===`~`?o===2:o<=3))return{node:null,end:e+o};let s=`${i}${o}`,c=a.get(s)??-1,u=-1;if(e>=c){let t=p(i,o,e+o,n);u=t.close,u===-1&&a.set(s,t.stop)}return u===-1?{node:null,end:i===`~`?e+o:e+1}:{node:T(i,o,m(e+o,u,r)),end:u+o}};for(;s<n;){let e=t[s];if(e===`\\`&&s+1<n){t[s+1]===`
8
+ `?c({type:`break`}):o+=t[s+1],s+=2;continue}if(e===` `){let e=s;for(;e<n&&t[e]===` `;)e+=1;e-s>=2&&e<n&&t[e]===`
9
+ `?(c({type:`break`}),s=e+1):(o+=t.slice(s,e),s=e);continue}if(C.has(e)){let e=u(s);e.node?c(e.node):o+=t.slice(s,e.end),s=e.end;continue}let i=f(s,n);i?(c(i.build(r)),s=i.end):(o+=e,s+=1)}return o&&i.push({type:`text`,value:o}),i}return m(0,n,!1)}exports.parseInline=E,exports.parseMarkdown=m;
9
10
  //# sourceMappingURL=markdown-parse.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-parse.cjs","names":["safeImageUrl","safeLinkUrl","require_safe_url","FENCE","HEADING_OPEN","RULE","QUOTE","BULLET_OPENER","ORDERED_OPENER","matchListOpener","match","pattern","line","content","matchBullet","matchOrdered","TABLE_DELIMITER","MAX_NESTING_DEPTH","matchHeading","open","text","end","endsWithHardBreak","parseMarkdown","parseBlocks","source","depth","lines","parseInline","blocks","i","fence","marker","body","heading","inner","list","next","parseList","table","parseTable","paragraph","hardBreaks","current","joinParagraph","index","bulletStart","start","orderedStart","ordered","baseIndent","startNumber","items","buffer","flush","bullet","numbered","splitRow","trimmed","cells","cell","head","align","left","right","rows","INLINE_RULES","src","href","children","INLINE_FIRST","rule","nodes","bracketAt","deadTailAt","stopAt","stops","closingBracket","from","found","autolinkStop","allowed","guard","close","rest","matched","node"],"sources":["../../../src/components/Markdown/markdown-parse.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines, function-lines — a Markdown block parser is a state\n * machine over line kinds: paragraph, heading, fence, list, quote, table and\n * thematic break each need to see the lines around them to know where they end.\n * parseBlocks is that loop, and cutting it into per-kind functions would hand each\n * one the same lookahead cursor.\n */\n// A small Markdown parser for the subset an app actually renders from untrusted\n// text: comments, ticket bodies, release notes, a product description.\n//\n// It produces a node tree, never an HTML string, and the renderer turns that into\n// React elements. No `dangerouslySetInnerHTML` exists anywhere in this component —\n// which is the property that makes rendering somebody else's Markdown safe, and it\n// is structural rather than a promise about escaping.\n//\n// Raw HTML in the input is therefore not \"sanitized\", it is **text**: `<script>` in\n// a comment renders as the four characters somebody typed. That is the whole point,\n// and it is also the documented limit — this is not a CommonMark implementation and\n// does not try to be.\n\nimport { safeImageUrl, safeLinkUrl } from \"@/utils/safe-url\";\n\n/** Inline content. */\nexport type MarkdownInline =\n | { type: \"text\"; value: string }\n | { type: \"strong\"; children: MarkdownInline[] }\n | { type: \"em\"; children: MarkdownInline[] }\n | { type: \"del\"; children: MarkdownInline[] }\n | { type: \"code\"; value: string }\n | { type: \"link\"; href: string; children: MarkdownInline[] }\n | { type: \"image\"; src: string; alt: string }\n | { type: \"break\" };\n\n/** Column alignment of a table, from the delimiter row. */\nexport type MarkdownAlign = \"left\" | \"center\" | \"right\" | null;\n\n/** Block content. */\nexport type MarkdownBlock =\n | { type: \"heading\"; level: number; children: MarkdownInline[] }\n | { type: \"paragraph\"; children: MarkdownInline[] }\n | { type: \"code\"; language: string | null; value: string }\n | { type: \"quote\"; children: MarkdownBlock[] }\n | { type: \"list\"; ordered: boolean; start: number; items: MarkdownBlock[][] }\n | {\n type: \"table\";\n align: MarkdownAlign[];\n head: MarkdownInline[][];\n rows: MarkdownInline[][][];\n }\n | { type: \"rule\" };\n\n/**\n * A fence opener, matched against the line **after** `trimEnd()`.\n *\n * The trailing `\\s*` lives in the `trimEnd()` rather than in the pattern: with it,\n * `\\s*([\\w+-]*)\\s*$` is two whitespace quantifiers separated by one that may be\n * empty, and a fence followed by 20 000 spaces and a stray `!` took 0.36 s (#437).\n */\nconst FENCE = /^\\s{0,3}(`{3,}|~{3,})\\s*([\\w+-]*)$/;\n/**\n * The opening marker of an ATX heading. The text and the optional closing `#` run\n * are cut by {@link matchHeading} with string operations, not by this pattern.\n */\nconst HEADING_OPEN = /^\\s{0,3}(#{1,6})\\s+/;\nconst RULE = /^\\s{0,3}([-*_])\\s*(?:\\1\\s*){2,}$/;\nconst QUOTE = /^\\s{0,3}>\\s?(.*)$/;\n/**\n * The opener of a list item: indentation, marker and the whitespace that\n * separates the marker from the content.\n *\n * The content is sliced off with a string operation rather than captured,\n * because it may not hold U+2028/U+2029. Those are line terminators the old\n * `(.*)$` could not cross, so a line with one after the marker was a paragraph\n * and has to stay one. Capturing the content with a regex that stops at them (a\n * `[^\\u2028\\u2029]*`) would put the separator and the content back to racing for\n * a run of spaces — quadratic, 3.6 s for a bullet padded with 80 000 spaces\n * (#478). Matching only the opener and slicing sidesteps that entirely.\n *\n * The separator is `[^\\S\\n\\r]`: every whitespace character except CR and LF,\n * which a line never contains. That keeps a separator a person pastes from Word\n * or Docs — NBSP, a form feed, a leading BOM — reading as a list, exactly as the\n * old `\\s+` did, instead of silently turning the line into a paragraph.\n */\nconst BULLET_OPENER = /^([^\\S\\n\\r]*)([-*+])[^\\S\\n\\r]+/;\nconst ORDERED_OPENER = /^([^\\S\\n\\r]*)(\\d{1,9})[.)][^\\S\\n\\r]+/;\n\n/** A list item's opener: how far it is indented, its marker and its content. */\ninterface ListOpener {\n indent: string;\n marker: string;\n content: string;\n}\n\n/**\n * Read a list item's opener, or `null` when the line is not one.\n *\n * A line whose content holds U+2028/U+2029 is not a list item: the old `(.*)$`\n * stopped at the separator, never reached `$`, and left the line a paragraph,\n * and {@link parseMarkdown} still splits only on `\\n` and `\\r`. Keeping that\n * here is what lets the opener stay a plain pattern with no `.*` to race.\n *\n * @param pattern - {@link BULLET_OPENER} or {@link ORDERED_OPENER}.\n * @param line - One source line.\n * @returns The opener, or `null` when the line is not a list item.\n */\nfunction matchListOpener(pattern: RegExp, line: string): ListOpener | null {\n const match = pattern.exec(line);\n if (!match) return null;\n const content = line.slice(match[0].length);\n if (content.includes(\"\\u2028\") || content.includes(\"\\u2029\")) return null;\n return { indent: match[1], marker: match[2], content };\n}\n\n/** {@link matchListOpener} for a bullet. */\nfunction matchBullet(line: string): ListOpener | null {\n return matchListOpener(BULLET_OPENER, line);\n}\n\n/** {@link matchListOpener} for an ordered marker. */\nfunction matchOrdered(line: string): ListOpener | null {\n return matchListOpener(ORDERED_OPENER, line);\n}\n/**\n * A table's delimiter row, matched against the line **after** `trimEnd()`.\n *\n * The `|` is required somewhere in the line, and that is what tells a one-column\n * table (`| --- |`) apart from a thematic break (`---`) — a single column is a\n * legitimate table, and the first version of this regex demanded two. The trailing\n * whitespace is trimmed before the test for the same reason as {@link FENCE}: a\n * `\\s*\\|?\\s*$` tail backtracked quadratically on `- |` plus 50 000 spaces (#437).\n */\nconst TABLE_DELIMITER = /^\\s{0,3}\\|[\\s|:-]*$|^\\s{0,3}:?-+:?(\\s*\\|\\s*:?-+:?)+\\s*\\|?$/;\n\n/**\n * How deep quotes and lists may nest before the rest is read as a paragraph.\n *\n * Each level is one recursive {@link parseBlocks} call and one nested element in\n * the render, so `\"- \".repeat(20000)` used to throw `RangeError: Maximum call stack\n * size exceeded` out of the component (#437). Real documents stop at a handful of\n * levels; past this cap the words are kept, only the nesting is dropped.\n */\nconst MAX_NESTING_DEPTH = 32;\n\n/**\n * Match an ATX heading in linear time.\n *\n * The regex this replaces, `/^\\s{0,3}(#{1,6})\\s+(.*?)\\s*#*\\s*$/`, let a lazy `.*?`\n * and two `\\s*` race for the same run of spaces: `\"# a\" + \" \".repeat(4000) + \"b\"`\n * took about 4.7 s, cubic in the run (#437). Only the opening marker is a regex\n * now. The text is the rest of the line minus the longest suffix shaped like\n * `\\s*#*\\s*` — exactly what the lazy group left behind, so `# título #`,\n * `# título#` and `# #` read as before.\n *\n * @param line - One source line.\n * @returns The level and raw text, or `null` when the line is not a heading.\n */\nfunction matchHeading(line: string): { level: number; text: string } | null {\n const open = HEADING_OPEN.exec(line);\n if (!open) return null;\n let text = line.slice(open[0].length).trimEnd();\n let end = text.length;\n while (end > 0 && text[end - 1] === \"#\") end -= 1;\n text = text.slice(0, end).trimEnd();\n return { level: open[1].length, text };\n}\n\n/**\n * Whether a paragraph line ends in a hard break: two or more trailing spaces.\n *\n * `/ {2,}$/` was quadratic on a line with a long inner run of spaces — it retried\n * the run from every space and failed at the next word each time (0.57 s for\n * 50 000 spaces, #437).\n */\nfunction endsWithHardBreak(line: string): boolean {\n return line.endsWith(\" \");\n}\n\n/**\n * Parse a Markdown document into blocks.\n *\n * @param source - Raw Markdown.\n * @returns Block nodes in document order.\n */\nexport function parseMarkdown(source: string): MarkdownBlock[] {\n const lines = source.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n return parseBlocks(lines, 0);\n}\n\n/**\n * Parse a run of lines into blocks.\n *\n * @param lines - The lines of this container.\n * @param depth - How many quotes and lists enclose them. At\n * {@link MAX_NESTING_DEPTH} the lines become one paragraph instead of more\n * containers, so a hostile document cannot exhaust the stack.\n * @returns The blocks.\n */\nfunction parseBlocks(lines: string[], depth: number): MarkdownBlock[] {\n if (depth >= MAX_NESTING_DEPTH) {\n const source = lines\n .map((line) => line.trim())\n .filter(Boolean)\n .join(\"\\n\");\n return source ? [{ type: \"paragraph\", children: parseInline(source) }] : [];\n }\n const blocks: MarkdownBlock[] = [];\n let i = 0;\n\n while (i < lines.length) {\n const line = lines[i];\n\n if (line.trim() === \"\") {\n i += 1;\n continue;\n }\n\n const fence = FENCE.exec(line.trimEnd());\n if (fence) {\n const marker = fence[1][0];\n const body: string[] = [];\n i += 1;\n while (i < lines.length && !new RegExp(`^\\\\s{0,3}${marker}{3,}\\\\s*$`).test(lines[i])) {\n body.push(lines[i]);\n i += 1;\n }\n // An unterminated fence still yields a code block: the alternative is to\n // render the rest of the document as prose full of backticks.\n i += 1;\n blocks.push({ type: \"code\", language: fence[2] || null, value: body.join(\"\\n\") });\n continue;\n }\n\n const heading = matchHeading(line);\n if (heading) {\n blocks.push({\n type: \"heading\",\n level: heading.level,\n children: parseInline(heading.text),\n });\n i += 1;\n continue;\n }\n\n if (RULE.test(line)) {\n blocks.push({ type: \"rule\" });\n i += 1;\n continue;\n }\n\n if (QUOTE.test(line)) {\n const inner: string[] = [];\n while (i < lines.length) {\n const match = QUOTE.exec(lines[i]);\n if (match) {\n inner.push(match[1]);\n i += 1;\n continue;\n }\n // A blank line ends the quote; a plain line continues it (lazy\n // continuation), which is how people actually write quotes.\n if (lines[i].trim() === \"\") break;\n inner.push(lines[i]);\n i += 1;\n }\n blocks.push({ type: \"quote\", children: parseBlocks(inner, depth + 1) });\n continue;\n }\n\n if (matchBullet(line) || matchOrdered(line)) {\n const [list, next] = parseList(lines, i, depth);\n blocks.push(list);\n i = next;\n continue;\n }\n\n if (\n i + 1 < lines.length &&\n line.includes(\"|\") &&\n TABLE_DELIMITER.test(lines[i + 1].trimEnd())\n ) {\n const [table, next] = parseTable(lines, i);\n blocks.push(table);\n i = next;\n continue;\n }\n\n const paragraph: string[] = [];\n const hardBreaks: boolean[] = [];\n while (i < lines.length && lines[i].trim() !== \"\") {\n const current = lines[i];\n if (\n matchHeading(current) ||\n RULE.test(current) ||\n FENCE.test(current.trimEnd()) ||\n QUOTE.test(current) ||\n matchBullet(current) ||\n matchOrdered(current)\n ) {\n break;\n }\n paragraph.push(current.trim());\n hardBreaks.push(endsWithHardBreak(current));\n i += 1;\n }\n if (paragraph.length > 0) {\n blocks.push({\n type: \"paragraph\",\n children: parseInline(joinParagraph(paragraph, hardBreaks)),\n });\n }\n }\n\n return blocks;\n}\n\n/**\n * Re-join the lines of a paragraph, keeping the two-space hard break.\n *\n * Every line is trimmed before it is parsed, because leading indentation is not\n * content and a trailing space is invisible noise in almost every line. The one\n * exception is the CommonMark hard break: two or more trailing spaces mean\n * \"break the line here\", so trimming first would delete the only mark that says\n * so and the ` \\n` inline rule could never match. The flag is recorded before\n * the trim and the marker put back here, on every line but the last — a break\n * after the final line of a paragraph would break into nothing.\n *\n * @param lines - The trimmed lines, in order.\n * @param hardBreaks - Whether each line ended in two or more spaces.\n * @returns The paragraph source the inline parser reads.\n */\nfunction joinParagraph(lines: readonly string[], hardBreaks: readonly boolean[]): string {\n return lines\n .map((line, index) => (hardBreaks[index] && index < lines.length - 1 ? `${line} ` : line))\n .join(\"\\n\");\n}\n\n/**\n * Parse a list, including nested lists and multi-line items.\n *\n * Nesting is decided by indentation relative to the **first** item's marker, so a\n * list indented inside a quote or another list still reads correctly.\n *\n * @param lines - The lines of the enclosing container.\n * @param start - Index of the first item's line.\n * @param depth - Nesting depth of the enclosing container.\n * @returns The list node and the index of the first line after it.\n */\nfunction parseList(lines: string[], start: number, depth: number): [MarkdownBlock, number] {\n const bulletStart = matchBullet(lines[start]);\n const orderedStart = matchOrdered(lines[start]);\n // The two markers are mutually exclusive — `-*+` versus digits — so whichever\n // matched decides the list kind.\n const ordered = orderedStart !== null;\n const first = orderedStart ?? bulletStart;\n const baseIndent = first?.indent.length ?? 0;\n const startNumber = ordered ? Number(orderedStart?.marker ?? 1) : 1;\n\n const items: MarkdownBlock[][] = [];\n let buffer: string[] = [];\n let i = start;\n\n const flush = (): void => {\n if (buffer.length === 0) return;\n items.push(parseBlocks(buffer, depth + 1));\n buffer = [];\n };\n\n while (i < lines.length) {\n const line = lines[i];\n if (line.trim() === \"\") {\n // A single blank line inside a list is a loose item, not the end. Two in\n // a row end it, which is what a blank-then-paragraph document means.\n if (i + 1 < lines.length && lines[i + 1].trim() !== \"\") {\n buffer.push(\"\");\n i += 1;\n continue;\n }\n break;\n }\n const bullet = matchBullet(line);\n const numbered = matchOrdered(line);\n const match = bullet ?? numbered;\n\n if (match && match.indent.length <= baseIndent) {\n const sameKind = ordered ? Boolean(numbered) : Boolean(bullet);\n if (!sameKind) break;\n flush();\n buffer.push(match.content);\n i += 1;\n continue;\n }\n if (match) {\n // Deeper marker: keep the indentation so the recursive call sees a list.\n buffer.push(line.slice(baseIndent));\n i += 1;\n continue;\n }\n if (line.search(/\\S/) > baseIndent) {\n buffer.push(line.trim());\n i += 1;\n continue;\n }\n break;\n }\n flush();\n\n return [{ type: \"list\", ordered, start: startNumber, items }, i];\n}\n\n/** Split a table row on unescaped pipes. */\nfunction splitRow(line: string): string[] {\n const trimmed = line.trim().replace(/^\\|/, \"\").replace(/\\|$/, \"\");\n const cells: string[] = [];\n let current = \"\";\n for (let i = 0; i < trimmed.length; i += 1) {\n if (trimmed[i] === \"\\\\\" && trimmed[i + 1] === \"|\") {\n current += \"|\";\n i += 1;\n continue;\n }\n if (trimmed[i] === \"|\") {\n cells.push(current);\n current = \"\";\n continue;\n }\n current += trimmed[i];\n }\n cells.push(current);\n return cells.map((cell) => cell.trim());\n}\n\n/**\n * Parse a GFM pipe table.\n *\n * @returns The table node and the index of the first line after it.\n */\nfunction parseTable(lines: string[], start: number): [MarkdownBlock, number] {\n const head = splitRow(lines[start]);\n const align: MarkdownAlign[] = splitRow(lines[start + 1]).map((cell) => {\n const left = cell.startsWith(\":\");\n const right = cell.endsWith(\":\");\n if (left && right) return \"center\";\n if (right) return \"right\";\n if (left) return \"left\";\n return null;\n });\n\n const rows: MarkdownInline[][][] = [];\n let i = start + 2;\n while (i < lines.length && lines[i].trim() !== \"\" && lines[i].includes(\"|\")) {\n rows.push(splitRow(lines[i]).map(parseInline));\n i += 1;\n }\n\n return [{ type: \"table\", align, head: head.map(parseInline), rows }, i];\n}\n\n/**\n * The precheck a rule needs before its pattern may run, keyed by the opener the\n * pattern starts with.\n *\n * `link` covers links and images, whose label ends at the first `]`; `autolink`\n * covers `<scheme:...>`, which ends at the first `>` or whitespace. Without the\n * precheck each pattern scanned to the end of the text from every opener, and\n * `\"[\".repeat(50000)` took 0.6 s (#437).\n */\ntype InlineGuard = { kind: \"link\"; opener: \"[\" | \"![\" } | { kind: \"autolink\"; opener: \"<\" };\n\n/** Inline delimiters, longest marker first so `**` wins over `*`. */\nconst INLINE_RULES: Array<{\n first: string;\n pattern: RegExp;\n guard?: InlineGuard;\n build: (match: RegExpExecArray) => MarkdownInline | null;\n}> = [\n {\n guard: { kind: \"link\", opener: \"![\" },\n first: \"!\",\n pattern: /^!\\[([^\\]]*)\\]\\(((?:[^()\\s]|\\([^()\\s]*\\))+)(?:\\s+\"[^\"]*\")?\\)/,\n build: (match) => {\n const src = safeImageUrl(match[2]);\n return src ? { type: \"image\", src, alt: match[1] } : { type: \"text\", value: match[1] };\n },\n },\n {\n guard: { kind: \"link\", opener: \"[\" },\n first: \"[\",\n pattern: /^\\[([^\\]]*)\\]\\(((?:[^()\\s]|\\([^()\\s]*\\))+)(?:\\s+\"[^\"]*\")?\\)/,\n build: (match) => {\n const href = safeLinkUrl(match[2]);\n const children = parseInline(match[1]);\n // A rejected URL keeps the label as plain text: dropping the text too\n // would silently delete words somebody wrote.\n return href ? { type: \"link\", href, children } : { type: \"text\", value: match[1] };\n },\n },\n { first: \"`\", pattern: /^`([^`]+)`/, build: (match) => ({ type: \"code\", value: match[1] }) },\n {\n first: \"*\",\n pattern: /^\\*\\*([\\s\\S]+?)\\*\\*/,\n build: (match) => ({ type: \"strong\", children: parseInline(match[1]) }),\n },\n {\n first: \"_\",\n pattern: /^__([\\s\\S]+?)__/,\n build: (match) => ({ type: \"strong\", children: parseInline(match[1]) }),\n },\n {\n first: \"~\",\n pattern: /^~~([\\s\\S]+?)~~/,\n build: (match) => ({ type: \"del\", children: parseInline(match[1]) }),\n },\n {\n first: \"*\",\n pattern: /^\\*([^*\\n]+)\\*/,\n build: (match) => ({ type: \"em\", children: parseInline(match[1]) }),\n },\n {\n first: \"_\",\n pattern: /^_([^_\\n]+)_/,\n build: (match) => ({ type: \"em\", children: parseInline(match[1]) }),\n },\n {\n guard: { kind: \"autolink\", opener: \"<\" },\n first: \"<\",\n pattern: /^<((?:https?:\\/\\/|mailto:)[^>\\s]+)>/,\n build: (match) => {\n const href = safeLinkUrl(match[1]);\n return href\n ? { type: \"link\", href, children: [{ type: \"text\", value: match[1] }] }\n : { type: \"text\", value: match[1] };\n },\n },\n { first: \"\\\\\", pattern: /^\\\\\\n/, build: () => ({ type: \"break\" }) },\n];\n\n/** Characters some inline rule can start with; any other character is text. */\nconst INLINE_FIRST = new Set(INLINE_RULES.map((rule) => rule.first));\n\n/**\n * Parse inline Markdown.\n *\n * A backslash escapes the next character, so `\\*not italic\\*` renders with the\n * asterisks. Anything that matches no rule is text — an unclosed `**` is two\n * asterisks, not a bold run to the end of the paragraph.\n *\n * The parse is linear in the text, which matters because the text is somebody\n * else's (#437):\n *\n * - A run of spaces is consumed whole: it is a hard break when two or more of them\n * end at a newline, and text otherwise. Matching `^ {2,}\\n` from every space\n * rescanned the run each time.\n * - A link or image label ends at the first `]` after the opener, so every opener\n * before the same `]` shares the same `](...)` tail. The position of that `]` is\n * cached, an opener whose `]` is not followed by `(` is skipped without running\n * the pattern, and once a tail has failed no later opener retries it.\n * - An autolink ends at the first `>` or whitespace, also cached; when that stop\n * is not `>` the pattern cannot match and is not run.\n * - A rule runs only at its own first character, so a run of `[` costs one set\n * lookup per character instead of every pattern in the table.\n *\n * @param source - One block's text.\n * @returns Inline nodes.\n */\nexport function parseInline(source: string): MarkdownInline[] {\n const nodes: MarkdownInline[] = [];\n let text = \"\";\n let i = 0;\n\n let bracketAt = -1;\n let deadTailAt = -1;\n let stopAt = -1;\n const stops = /[>\\s]/g;\n\n const flush = (): void => {\n if (text) nodes.push({ type: \"text\", value: text });\n text = \"\";\n };\n\n const closingBracket = (from: number): number => {\n if (bracketAt < from) {\n const found = source.indexOf(\"]\", from);\n bracketAt = found === -1 ? source.length : found;\n }\n return bracketAt;\n };\n\n const autolinkStop = (from: number): number => {\n if (stopAt < from) {\n stops.lastIndex = from;\n stopAt = stops.exec(source)?.index ?? source.length;\n }\n return stopAt;\n };\n\n const allowed = (guard: InlineGuard | undefined): boolean => {\n if (!guard) return true;\n if (!source.startsWith(guard.opener, i)) return false;\n if (guard.kind === \"autolink\") return source[autolinkStop(i + 1)] === \">\";\n const close = closingBracket(i + guard.opener.length);\n return source[close + 1] === \"(\" && close !== deadTailAt;\n };\n\n while (i < source.length) {\n if (source[i] === \"\\\\\" && i + 1 < source.length && source[i + 1] !== \"\\n\") {\n text += source[i + 1];\n i += 2;\n continue;\n }\n\n if (source[i] === \" \") {\n let end = i;\n while (source[end] === \" \") end += 1;\n if (end - i >= 2 && source[end] === \"\\n\") {\n flush();\n nodes.push({ type: \"break\" });\n i = end + 1;\n } else {\n text += source.slice(i, end);\n i = end;\n }\n continue;\n }\n\n if (!INLINE_FIRST.has(source[i])) {\n text += source[i];\n i += 1;\n continue;\n }\n\n const rest = source.slice(i);\n let matched = false;\n for (const rule of INLINE_RULES) {\n if (rule.first !== source[i] || !allowed(rule.guard)) continue;\n const match = rule.pattern.exec(rest);\n if (!match) {\n if (rule.guard?.kind === \"link\") {\n deadTailAt = closingBracket(i + rule.guard.opener.length);\n }\n continue;\n }\n const node = rule.build(match);\n if (!node) continue;\n flush();\n nodes.push(node);\n i += match[0].length;\n matched = true;\n break;\n }\n if (matched) continue;\n\n text += source[i];\n i += 1;\n }\n\n flush();\n return nodes;\n}\n"],"mappings":"A,4CA0DA,IAAMG,EAAQ,qCAKRC,EAAe,sBACfC,EAAO,mCACPC,EAAQ,oBAkBRC,EAAgB,iCAChBC,EAAiB,uCAqBvB,SAASC,EAAgB,EAAiB,EAAiC,CACvE,IAAMC,EAAQC,EAAQ,KAAKC,CAAI,EAC/B,GAAI,CAACF,EAAO,OAAO,KACnB,IAAMG,EAAUD,EAAK,MAAMF,EAAM,EAAE,CAAC,MAAM,EAE1C,OADIG,EAAQ,SAAS,QAAQ,GAAKA,EAAQ,SAAS,QAAQ,EAAU,KAC9D,CAAE,OAAQH,EAAM,GAAI,OAAQA,EAAM,GAAI,SAAQ,CACzD,CAGA,SAASI,EAAY,EAAiC,CAClD,OAAOL,EAAgBF,EAAeK,CAAI,CAC9C,CAGA,SAASG,EAAa,EAAiC,CACnD,OAAON,EAAgBD,EAAgBI,CAAI,CAC/C,CAUA,IAAMI,EAAkB,6DAUlBC,EAAoB,GAe1B,SAASC,EAAa,EAAsD,CACxE,IAAMC,EAAOf,EAAa,KAAKQ,CAAI,EACnC,GAAI,CAACO,EAAM,OAAO,KAClB,IAAIC,EAAOR,EAAK,MAAMO,EAAK,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,EAC1CE,EAAMD,EAAK,OACf,KAAOC,EAAM,GAAKD,EAAKC,EAAM,KAAO,KAAK,IAEzC,MADA,GAAOD,EAAK,MAAM,EAAGC,CAAG,CAAC,CAAC,QAAQ,EAC3B,CAAE,MAAOF,EAAK,EAAE,CAAC,OAAQ,MAAK,CACzC,CASA,SAASG,EAAkB,EAAuB,CAC9C,OAAOV,EAAK,SAAS,IAAI,CAC7B,CAQA,SAAgBW,EAAc,EAAiC,CAE3D,OAAOC,EADOC,EAAO,QAAQ,SAAU;CAAI,CAAC,CAAC,MAAM;CAChC,EAAO,CAAC,CAC/B,CAWA,SAASD,EAAY,EAAiB,EAAgC,CAClE,GAAIE,GAAST,EAAmB,CAC5B,IAAMQ,EAASE,EACV,IAAK,GAASf,EAAK,KAAK,CAAC,CAAC,CAC1B,OAAO,OAAO,CAAC,CACf,KAAK;CAAI,EACd,OAAOa,EAAS,CAAC,CAAE,KAAM,YAAa,SAAUG,EAAYH,CAAM,CAAE,CAAC,EAAI,CAAC,CAC9E,CACA,IAAMI,EAA0B,CAAC,EAC7BC,EAAI,EAER,KAAOA,EAAIH,EAAM,QAAQ,CACrB,IAAMf,EAAOe,EAAMG,GAEnB,GAAIlB,EAAK,KAAK,IAAM,GAAI,CACpB,GAAK,EACL,QACJ,CAEA,IAAMmB,EAAQ5B,EAAM,KAAKS,EAAK,QAAQ,CAAC,EACvC,GAAImB,EAAO,CACP,IAAMC,EAASD,EAAM,EAAE,CAAC,GAClBE,EAAiB,CAAC,EAExB,IADA,GAAK,EACEH,EAAIH,EAAM,QAAU,CAAK,OAAO,YAAYK,EAAO,UAAU,CAAC,CAAC,KAAKL,EAAMG,EAAE,GAC/EG,EAAK,KAAKN,EAAMG,EAAE,EAClB,GAAK,EAIT,GAAK,EACLD,EAAO,KAAK,CAAE,KAAM,OAAQ,SAAUE,EAAM,IAAM,KAAM,MAAOE,EAAK,KAAK;CAAI,CAAE,CAAC,EAChF,QACJ,CAEA,IAAMC,EAAUhB,EAAaN,CAAI,EACjC,GAAIsB,EAAS,CACTL,EAAO,KAAK,CACR,KAAM,UACN,MAAOK,EAAQ,MACf,SAAUN,EAAYM,EAAQ,IAAI,CACtC,CAAC,EACD,GAAK,EACL,QACJ,CAEA,GAAI7B,EAAK,KAAKO,CAAI,EAAG,CACjBiB,EAAO,KAAK,CAAE,KAAM,MAAO,CAAC,EAC5B,GAAK,EACL,QACJ,CAEA,GAAIvB,EAAM,KAAKM,CAAI,EAAG,CAClB,IAAMuB,EAAkB,CAAC,EACzB,KAAOL,EAAIH,EAAM,QAAQ,CACrB,IAAMjB,EAAQJ,EAAM,KAAKqB,EAAMG,EAAE,EACjC,GAAIpB,EACAyB,EAAM,KAAKzB,EAAM,EAAE,EACnB,GAAK,MAKT,IAAIiB,EAAMG,EAAE,CAAC,KAAK,IAAM,GAAI,MAC5BK,EAAM,KAAKR,EAAMG,EAAE,EACnB,GAAK,CAFuB,CAGhC,CACAD,EAAO,KAAK,CAAE,KAAM,QAAS,SAAUL,EAAYW,EAAOT,EAAQ,CAAC,CAAE,CAAC,EACtE,QACJ,CAEA,GAAIZ,EAAYF,CAAI,GAAKG,EAAaH,CAAI,EAAG,CACzC,GAAM,CAACwB,EAAMC,GAAQC,EAAUX,EAAOG,EAAGJ,CAAK,EAC9CG,EAAO,KAAKO,CAAI,EAChB,EAAIC,EACJ,QACJ,CAEA,GACIP,EAAI,EAAIH,EAAM,QACdf,EAAK,SAAS,GAAG,GACjBI,EAAgB,KAAKW,EAAMG,EAAI,EAAE,CAAC,QAAQ,CAAC,EAC7C,CACE,GAAM,CAACS,EAAOF,GAAQG,EAAWb,EAAOG,CAAC,EACzCD,EAAO,KAAKU,CAAK,EACjB,EAAIF,EACJ,QACJ,CAEA,IAAMI,EAAsB,CAAC,EACvBC,EAAwB,CAAC,EAC/B,KAAOZ,EAAIH,EAAM,QAAUA,EAAMG,EAAE,CAAC,KAAK,IAAM,IAAI,CAC/C,IAAMa,EAAUhB,EAAMG,GACtB,GACIZ,EAAayB,CAAO,GACpBtC,EAAK,KAAKsC,CAAO,GACjBxC,EAAM,KAAKwC,EAAQ,QAAQ,CAAC,GAC5BrC,EAAM,KAAKqC,CAAO,GAClB7B,EAAY6B,CAAO,GACnB5B,EAAa4B,CAAO,EAEpB,MAEJF,EAAU,KAAKE,EAAQ,KAAK,CAAC,EAC7BD,EAAW,KAAKpB,EAAkBqB,CAAO,CAAC,EAC1C,GAAK,CACT,CACIF,EAAU,OAAS,GACnBZ,EAAO,KAAK,CACR,KAAM,YACN,SAAUD,EAAYgB,EAAcH,EAAWC,CAAU,CAAC,CAC9D,CAAC,CAET,CAEA,OAAOb,CACX,CAiBA,SAASe,EAAc,EAA0B,EAAwC,CACrF,OAAOjB,EACF,KAAK,EAAM,IAAWe,EAAWG,IAAUA,EAAQlB,EAAM,OAAS,EAAI,GAAGf,EAAK,IAAMA,CAAK,CAAC,CAC1F,KAAK;CAAI,CAClB,CAaA,SAAS0B,EAAU,EAAiB,EAAe,EAAwC,CACvF,IAAMQ,EAAchC,EAAYa,EAAMoB,EAAM,EACtCC,EAAejC,EAAaY,EAAMoB,EAAM,EAGxCE,EAAUD,IAAiB,KAE3BE,GADQF,GAAgBF,EAAA,EACJ,OAAO,QAAU,EACrCK,EAAcF,EAAU,OAAOD,GAAc,QAAU,CAAC,EAAI,EAE5DI,EAA2B,CAAC,EAC9BC,EAAmB,CAAC,EACpBvB,EAAIiB,EAEFO,MAAoB,CAClBD,EAAO,SAAW,IACtBD,EAAM,KAAK5B,EAAY6B,EAAQ3B,EAAQ,CAAC,CAAC,EACzC,EAAS,CAAC,EACd,EAEA,KAAOI,EAAIH,EAAM,QAAQ,CACrB,IAAMf,EAAOe,EAAMG,GACnB,GAAIlB,EAAK,KAAK,IAAM,GAAI,CAGpB,GAAIkB,EAAI,EAAIH,EAAM,QAAUA,EAAMG,EAAI,EAAE,CAAC,KAAK,IAAM,GAAI,CACpDuB,EAAO,KAAK,EAAE,EACd,GAAK,EACL,QACJ,CACA,KACJ,CACA,IAAME,EAASzC,EAAYF,CAAI,EACzB4C,EAAWzC,EAAaH,CAAI,EAC5BF,EAAQ6C,GAAUC,EAExB,GAAI9C,GAASA,EAAM,OAAO,QAAUwC,EAAY,CAE5C,GAAI,EADaD,EAAkBO,EAAoBD,GACxC,MACfD,EAAM,EACND,EAAO,KAAK3C,EAAM,OAAO,EACzB,GAAK,CAET,MACA,GAAIA,EAEA2C,EAAO,KAAKzC,EAAK,MAAMsC,CAAU,CAAC,EAClC,GAAK,OAGT,GAAItC,EAAK,OAAO,IAAI,EAAIsC,EACpBG,EAAO,KAAKzC,EAAK,KAAK,CAAC,EACvB,GAAK,OAGT,KACJ,CAGA,OAFA0C,EAAM,EAEC,CAAC,CAAE,KAAM,OAAQ,UAAS,MAAOH,EAAa,OAAM,EAAGrB,CAAC,CACnE,CAGA,SAAS2B,EAAS,EAAwB,CACtC,IAAMC,EAAU9C,EAAK,KAAK,CAAC,CAAC,QAAQ,MAAO,EAAE,CAAC,CAAC,QAAQ,MAAO,EAAE,EAC1D+C,EAAkB,CAAC,EACrBhB,EAAU,GACd,IAAK,IAAIb,EAAI,EAAGA,EAAI4B,EAAQ,OAAQ,GAAK,EACjCA,EAAQ5B,KAAO,MAAQ4B,EAAQ5B,EAAI,KAAO,KAC1C,GAAW,IACX,GAAK,GAGL4B,EAAQ5B,KAAO,KACf6B,EAAM,KAAKhB,CAAO,EAClB,EAAU,IAGd,GAAWe,EAAQ5B,GAGvB,OADA6B,EAAM,KAAKhB,CAAO,EACXgB,EAAM,IAAK,GAASC,EAAK,KAAK,CAAC,CAC1C,CAOA,SAASpB,EAAW,EAAiB,EAAwC,CACzE,IAAMqB,EAAOJ,EAAS9B,EAAMoB,EAAM,EAC5Be,EAAyBL,EAAS9B,EAAMoB,EAAQ,EAAE,CAAC,CAAC,IAAK,GAAS,CACpE,IAAMgB,EAAOH,EAAK,WAAW,GAAG,EAC1BI,EAAQJ,EAAK,SAAS,GAAG,EAI/B,OAHIG,GAAQC,EAAc,SACtBA,EAAc,QACdD,EAAa,OACV,IACX,CAAC,EAEKE,EAA6B,CAAC,EAChCnC,EAAIiB,EAAQ,EAChB,KAAOjB,EAAIH,EAAM,QAAUA,EAAMG,EAAE,CAAC,KAAK,IAAM,IAAMH,EAAMG,EAAE,CAAC,SAAS,GAAG,GACtEmC,EAAK,KAAKR,EAAS9B,EAAMG,EAAE,CAAC,CAAC,IAAIF,CAAW,CAAC,EAC7C,GAAK,EAGT,MAAO,CAAC,CAAE,KAAM,QAAS,QAAO,KAAMiC,EAAK,IAAIjC,CAAW,EAAG,MAAK,EAAGE,CAAC,CAC1E,CAcA,IAAMoC,EAKD,CACD,CACI,MAAO,CAAE,KAAM,OAAQ,OAAQ,IAAK,EACpC,MAAO,IACP,QAAS,+DACT,MAAQ,GAAU,CACd,IAAMC,EAAMnE,EAAAA,aAAaU,EAAM,EAAE,EACjC,OAAOyD,EAAM,CAAE,KAAM,QAAS,MAAK,IAAKzD,EAAM,EAAG,EAAI,CAAE,KAAM,OAAQ,MAAOA,EAAM,EAAG,CACzF,CACJ,EACA,CACI,MAAO,CAAE,KAAM,OAAQ,OAAQ,GAAI,EACnC,MAAO,IACP,QAAS,8DACT,MAAQ,GAAU,CACd,IAAM0D,EAAOnE,EAAAA,YAAYS,EAAM,EAAE,EAC3B2D,EAAWzC,EAAYlB,EAAM,EAAE,EAGrC,OAAO0D,EAAO,CAAE,KAAM,OAAQ,OAAM,UAAS,EAAI,CAAE,KAAM,OAAQ,MAAO1D,EAAM,EAAG,CACrF,CACJ,EACA,CAAE,MAAO,IAAK,QAAS,aAAc,MAAQ,IAAW,CAAE,KAAM,OAAQ,MAAOA,EAAM,EAAG,EAAG,EAC3F,CACI,MAAO,IACP,QAAS,sBACT,MAAQ,IAAW,CAAE,KAAM,SAAU,SAAUkB,EAAYlB,EAAM,EAAE,CAAE,EACzE,EACA,CACI,MAAO,IACP,QAAS,kBACT,MAAQ,IAAW,CAAE,KAAM,SAAU,SAAUkB,EAAYlB,EAAM,EAAE,CAAE,EACzE,EACA,CACI,MAAO,IACP,QAAS,kBACT,MAAQ,IAAW,CAAE,KAAM,MAAO,SAAUkB,EAAYlB,EAAM,EAAE,CAAE,EACtE,EACA,CACI,MAAO,IACP,QAAS,iBACT,MAAQ,IAAW,CAAE,KAAM,KAAM,SAAUkB,EAAYlB,EAAM,EAAE,CAAE,EACrE,EACA,CACI,MAAO,IACP,QAAS,eACT,MAAQ,IAAW,CAAE,KAAM,KAAM,SAAUkB,EAAYlB,EAAM,EAAE,CAAE,EACrE,EACA,CACI,MAAO,CAAE,KAAM,WAAY,OAAQ,GAAI,EACvC,MAAO,IACP,QAAS,sCACT,MAAQ,GAAU,CACd,IAAM0D,EAAOnE,EAAAA,YAAYS,EAAM,EAAE,EACjC,OAAO0D,EACD,CAAE,KAAM,OAAQ,OAAM,SAAU,CAAC,CAAE,KAAM,OAAQ,MAAO1D,EAAM,EAAG,CAAC,CAAE,EACpE,CAAE,KAAM,OAAQ,MAAOA,EAAM,EAAG,CAC1C,CACJ,EACA,CAAE,MAAO,KAAM,QAAS,QAAS,WAAc,CAAE,KAAM,OAAQ,EAAG,CACtE,EAGM4D,EAAe,IAAI,IAAIJ,EAAa,IAAK,GAASK,EAAK,KAAK,CAAC,EA2BnE,SAAgB3C,EAAY,EAAkC,CAC1D,IAAM4C,EAA0B,CAAC,EAC7BpD,EAAO,GACPU,EAAI,EAEJ2C,EAAY,GACZC,EAAa,GACbC,EAAS,GACPC,EAAQ,SAERtB,MAAoB,CAClBlC,GAAMoD,EAAM,KAAK,CAAE,KAAM,OAAQ,MAAOpD,CAAK,CAAC,EAClD,EAAO,EACX,EAEMyD,EAAkB,GAAyB,CAC7C,GAAIJ,EAAYK,EAAM,CAClB,IAAMC,EAAQtD,EAAO,QAAQ,IAAKqD,CAAI,EACtC,EAAYC,IAAU,GAAKtD,EAAO,OAASsD,CAC/C,CACA,OAAON,CACX,EAEMO,EAAgB,IACdL,EAASG,IACT,EAAM,UAAYA,EAClB,EAASF,EAAM,KAAKnD,CAAM,CAAC,EAAE,OAASA,EAAO,QAE1CkD,GAGLM,EAAW,GAA4C,CACzD,GAAI,CAACC,EAAO,MAAO,GACnB,GAAI,CAACzD,EAAO,WAAWyD,EAAM,OAAQpD,CAAC,EAAG,MAAO,GAChD,GAAIoD,EAAM,OAAS,WAAY,OAAOzD,EAAOuD,EAAalD,EAAI,CAAC,KAAO,IACtE,IAAMqD,EAAQN,EAAe/C,EAAIoD,EAAM,OAAO,MAAM,EACpD,OAAOzD,EAAO0D,EAAQ,KAAO,KAAOA,IAAUT,CAClD,EAEA,KAAO5C,EAAIL,EAAO,QAAQ,CACtB,GAAIA,EAAOK,KAAO,MAAQA,EAAI,EAAIL,EAAO,QAAUA,EAAOK,EAAI,KAAO;EAAM,CACvE,GAAQL,EAAOK,EAAI,GACnB,GAAK,EACL,QACJ,CAEA,GAAIL,EAAOK,KAAO,IAAK,CACnB,IAAIT,EAAMS,EACV,KAAOL,EAAOJ,KAAS,KAAK,GAAO,EAC/BA,EAAMS,GAAK,GAAKL,EAAOJ,KAAS;GAChCiC,EAAM,EACNkB,EAAM,KAAK,CAAE,KAAM,OAAQ,CAAC,EAC5B,EAAInD,EAAM,IAEV,GAAQI,EAAO,MAAMK,EAAGT,CAAG,EAC3B,EAAIA,GAER,QACJ,CAEA,GAAI,CAACiD,EAAa,IAAI7C,EAAOK,EAAE,EAAG,CAC9B,GAAQL,EAAOK,GACf,GAAK,EACL,QACJ,CAEA,IAAMsD,EAAO3D,EAAO,MAAMK,CAAC,EACvBuD,EAAU,GACd,IAAK,IAAMd,KAAQL,EAAc,CAC7B,GAAIK,EAAK,QAAU9C,EAAOK,IAAM,CAACmD,EAAQV,EAAK,KAAK,EAAG,SACtD,IAAM7D,EAAQ6D,EAAK,QAAQ,KAAKa,CAAI,EACpC,GAAI,CAAC1E,EAAO,CACJ6D,EAAK,OAAO,OAAS,SACrB,EAAaM,EAAe/C,EAAIyC,EAAK,MAAM,OAAO,MAAM,GAE5D,QACJ,CACA,IAAMe,EAAOf,EAAK,MAAM7D,CAAK,EAC7B,GAAK4E,EACL,GAAM,EACNd,EAAM,KAAKc,CAAI,EACf,GAAK5E,EAAM,EAAE,CAAC,OACd,EAAU,GACV,KAJM,CAKV,CACI2E,IAEJ,GAAQ5D,EAAOK,GACf,GAAK,EACT,CAGA,OADAwB,EAAM,EACCkB,CACX,C"}
1
+ {"version":3,"file":"markdown-parse.cjs","names":["safeImageUrl","safeLinkUrl","require_safe_url","FENCE","HEADING_OPEN","RULE","QUOTE","BULLET_OPENER","ORDERED_OPENER","matchListOpener","match","pattern","line","content","matchBullet","matchOrdered","TABLE_DELIMITER","MAX_NESTING_DEPTH","matchHeading","open","text","end","endsWithHardBreak","parseMarkdown","parseBlocks","source","depth","lines","parseInline","blocks","i","fence","marker","body","heading","inner","list","next","parseList","table","parseTable","paragraph","hardBreaks","current","joinParagraph","index","bulletStart","start","orderedStart","ordered","baseIndent","startNumber","items","buffer","flush","bullet","numbered","splitRow","trimmed","cells","cell","head","align","left","right","rows","LINK_TAIL","AUTOLINK_SCHEME","ATOM_FIRST","EMPHASIS","nextIndexTable","matches","emphasisNode","length","brackets","backticks","autolinkStops","tails","atoms","tailAt","close","runLength","to","from","readLink","image","labelStart","char","tail","label","src","href","parseRange","readAtom","stop","scheme","inLink","url","atomAt","atom","findCloser","size","run","nodes","failed","push","node","emphasisAt","at","kind","deadUntil","scan","span"],"sources":["../../../src/components/Markdown/markdown-parse.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines, function-lines — a Markdown block parser is a state\n * machine over line kinds: paragraph, heading, fence, list, quote, table and\n * thematic break each need to see the lines around them to know where they end.\n * parseBlocks is that loop, and cutting it into per-kind functions would hand each\n * one the same lookahead cursor.\n */\n// A small Markdown parser for the subset an app actually renders from untrusted\n// text: comments, ticket bodies, release notes, a product description.\n//\n// It produces a node tree, never an HTML string, and the renderer turns that into\n// React elements. No `dangerouslySetInnerHTML` exists anywhere in this component —\n// which is the property that makes rendering somebody else's Markdown safe, and it\n// is structural rather than a promise about escaping.\n//\n// Raw HTML in the input is therefore not \"sanitized\", it is **text**: `<script>` in\n// a comment renders as the four characters somebody typed. That is the whole point,\n// and it is also the documented limit — this is not a CommonMark implementation and\n// does not try to be.\n\nimport { safeImageUrl, safeLinkUrl } from \"@/utils/safe-url\";\n\n/** Inline content. */\nexport type MarkdownInline =\n | { type: \"text\"; value: string }\n | { type: \"strong\"; children: MarkdownInline[] }\n | { type: \"em\"; children: MarkdownInline[] }\n | { type: \"del\"; children: MarkdownInline[] }\n | { type: \"code\"; value: string }\n | { type: \"link\"; href: string; children: MarkdownInline[] }\n | { type: \"image\"; src: string; alt: string }\n | { type: \"break\" };\n\n/** Column alignment of a table, from the delimiter row. */\nexport type MarkdownAlign = \"left\" | \"center\" | \"right\" | null;\n\n/** Block content. */\nexport type MarkdownBlock =\n | { type: \"heading\"; level: number; children: MarkdownInline[] }\n | { type: \"paragraph\"; children: MarkdownInline[] }\n | { type: \"code\"; language: string | null; value: string }\n | { type: \"quote\"; children: MarkdownBlock[] }\n | { type: \"list\"; ordered: boolean; start: number; items: MarkdownBlock[][] }\n | {\n type: \"table\";\n align: MarkdownAlign[];\n head: MarkdownInline[][];\n rows: MarkdownInline[][][];\n }\n | { type: \"rule\" };\n\n/**\n * A fence opener, matched against the line **after** `trimEnd()`.\n *\n * The trailing `\\s*` lives in the `trimEnd()` rather than in the pattern: with it,\n * `\\s*([\\w+-]*)\\s*$` is two whitespace quantifiers separated by one that may be\n * empty, and a fence followed by 20 000 spaces and a stray `!` took 0.36 s (#437).\n */\nconst FENCE = /^\\s{0,3}(`{3,}|~{3,})\\s*([\\w+-]*)$/;\n/**\n * The opening marker of an ATX heading. The text and the optional closing `#` run\n * are cut by {@link matchHeading} with string operations, not by this pattern.\n */\nconst HEADING_OPEN = /^\\s{0,3}(#{1,6})\\s+/;\nconst RULE = /^\\s{0,3}([-*_])\\s*(?:\\1\\s*){2,}$/;\nconst QUOTE = /^\\s{0,3}>\\s?(.*)$/;\n/**\n * The opener of a list item: indentation, marker and the whitespace that\n * separates the marker from the content.\n *\n * The content is sliced off with a string operation rather than captured,\n * because it may not hold U+2028/U+2029. Those are line terminators the old\n * `(.*)$` could not cross, so a line with one after the marker was a paragraph\n * and has to stay one. Capturing the content with a regex that stops at them (a\n * `[^\\u2028\\u2029]*`) would put the separator and the content back to racing for\n * a run of spaces — quadratic, 3.6 s for a bullet padded with 80 000 spaces\n * (#478). Matching only the opener and slicing sidesteps that entirely.\n *\n * The separator is `[^\\S\\n\\r]`: every whitespace character except CR and LF,\n * which a line never contains. That keeps a separator a person pastes from Word\n * or Docs — NBSP, a form feed, a leading BOM — reading as a list, exactly as the\n * old `\\s+` did, instead of silently turning the line into a paragraph.\n */\nconst BULLET_OPENER = /^([^\\S\\n\\r]*)([-*+])[^\\S\\n\\r]+/;\nconst ORDERED_OPENER = /^([^\\S\\n\\r]*)(\\d{1,9})[.)][^\\S\\n\\r]+/;\n\n/** A list item's opener: how far it is indented, its marker and its content. */\ninterface ListOpener {\n indent: string;\n marker: string;\n content: string;\n}\n\n/**\n * Read a list item's opener, or `null` when the line is not one.\n *\n * A line whose content holds U+2028/U+2029 is not a list item: the old `(.*)$`\n * stopped at the separator, never reached `$`, and left the line a paragraph,\n * and {@link parseMarkdown} still splits only on `\\n` and `\\r`. Keeping that\n * here is what lets the opener stay a plain pattern with no `.*` to race.\n *\n * @param pattern - {@link BULLET_OPENER} or {@link ORDERED_OPENER}.\n * @param line - One source line.\n * @returns The opener, or `null` when the line is not a list item.\n */\nfunction matchListOpener(pattern: RegExp, line: string): ListOpener | null {\n const match = pattern.exec(line);\n if (!match) return null;\n const content = line.slice(match[0].length);\n if (content.includes(\"\\u2028\") || content.includes(\"\\u2029\")) return null;\n return { indent: match[1], marker: match[2], content };\n}\n\n/** {@link matchListOpener} for a bullet. */\nfunction matchBullet(line: string): ListOpener | null {\n return matchListOpener(BULLET_OPENER, line);\n}\n\n/** {@link matchListOpener} for an ordered marker. */\nfunction matchOrdered(line: string): ListOpener | null {\n return matchListOpener(ORDERED_OPENER, line);\n}\n/**\n * A table's delimiter row, matched against the line **after** `trimEnd()`.\n *\n * The `|` is required somewhere in the line, and that is what tells a one-column\n * table (`| --- |`) apart from a thematic break (`---`) — a single column is a\n * legitimate table, and the first version of this regex demanded two. The trailing\n * whitespace is trimmed before the test for the same reason as {@link FENCE}: a\n * `\\s*\\|?\\s*$` tail backtracked quadratically on `- |` plus 50 000 spaces (#437).\n */\nconst TABLE_DELIMITER = /^\\s{0,3}\\|[\\s|:-]*$|^\\s{0,3}:?-+:?(\\s*\\|\\s*:?-+:?)+\\s*\\|?$/;\n\n/**\n * How deep quotes and lists may nest before the rest is read as a paragraph.\n *\n * Each level is one recursive {@link parseBlocks} call and one nested element in\n * the render, so `\"- \".repeat(20000)` used to throw `RangeError: Maximum call stack\n * size exceeded` out of the component (#437). Real documents stop at a handful of\n * levels; past this cap the words are kept, only the nesting is dropped.\n */\nconst MAX_NESTING_DEPTH = 32;\n\n/**\n * Match an ATX heading in linear time.\n *\n * The regex this replaces, `/^\\s{0,3}(#{1,6})\\s+(.*?)\\s*#*\\s*$/`, let a lazy `.*?`\n * and two `\\s*` race for the same run of spaces: `\"# a\" + \" \".repeat(4000) + \"b\"`\n * took about 4.7 s, cubic in the run (#437). Only the opening marker is a regex\n * now. The text is the rest of the line minus the longest suffix shaped like\n * `\\s*#*\\s*` — exactly what the lazy group left behind, so `# título #`,\n * `# título#` and `# #` read as before.\n *\n * @param line - One source line.\n * @returns The level and raw text, or `null` when the line is not a heading.\n */\nfunction matchHeading(line: string): { level: number; text: string } | null {\n const open = HEADING_OPEN.exec(line);\n if (!open) return null;\n let text = line.slice(open[0].length).trimEnd();\n let end = text.length;\n while (end > 0 && text[end - 1] === \"#\") end -= 1;\n text = text.slice(0, end).trimEnd();\n return { level: open[1].length, text };\n}\n\n/**\n * Whether a paragraph line ends in a hard break: two or more trailing spaces.\n *\n * `/ {2,}$/` was quadratic on a line with a long inner run of spaces — it retried\n * the run from every space and failed at the next word each time (0.57 s for\n * 50 000 spaces, #437).\n */\nfunction endsWithHardBreak(line: string): boolean {\n return line.endsWith(\" \");\n}\n\n/**\n * Parse a Markdown document into blocks.\n *\n * @param source - Raw Markdown.\n * @returns Block nodes in document order.\n */\nexport function parseMarkdown(source: string): MarkdownBlock[] {\n const lines = source.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n return parseBlocks(lines, 0);\n}\n\n/**\n * Parse a run of lines into blocks.\n *\n * @param lines - The lines of this container.\n * @param depth - How many quotes and lists enclose them. At\n * {@link MAX_NESTING_DEPTH} the lines become one paragraph instead of more\n * containers, so a hostile document cannot exhaust the stack.\n * @returns The blocks.\n */\nfunction parseBlocks(lines: string[], depth: number): MarkdownBlock[] {\n if (depth >= MAX_NESTING_DEPTH) {\n const source = lines\n .map((line) => line.trim())\n .filter(Boolean)\n .join(\"\\n\");\n return source ? [{ type: \"paragraph\", children: parseInline(source) }] : [];\n }\n const blocks: MarkdownBlock[] = [];\n let i = 0;\n\n while (i < lines.length) {\n const line = lines[i];\n\n if (line.trim() === \"\") {\n i += 1;\n continue;\n }\n\n const fence = FENCE.exec(line.trimEnd());\n if (fence) {\n const marker = fence[1][0];\n const body: string[] = [];\n i += 1;\n while (i < lines.length && !new RegExp(`^\\\\s{0,3}${marker}{3,}\\\\s*$`).test(lines[i])) {\n body.push(lines[i]);\n i += 1;\n }\n // An unterminated fence still yields a code block: the alternative is to\n // render the rest of the document as prose full of backticks.\n i += 1;\n blocks.push({ type: \"code\", language: fence[2] || null, value: body.join(\"\\n\") });\n continue;\n }\n\n const heading = matchHeading(line);\n if (heading) {\n blocks.push({\n type: \"heading\",\n level: heading.level,\n children: parseInline(heading.text),\n });\n i += 1;\n continue;\n }\n\n if (RULE.test(line)) {\n blocks.push({ type: \"rule\" });\n i += 1;\n continue;\n }\n\n if (QUOTE.test(line)) {\n const inner: string[] = [];\n while (i < lines.length) {\n const match = QUOTE.exec(lines[i]);\n if (match) {\n inner.push(match[1]);\n i += 1;\n continue;\n }\n // A blank line ends the quote; a plain line continues it (lazy\n // continuation), which is how people actually write quotes.\n if (lines[i].trim() === \"\") break;\n inner.push(lines[i]);\n i += 1;\n }\n blocks.push({ type: \"quote\", children: parseBlocks(inner, depth + 1) });\n continue;\n }\n\n if (matchBullet(line) || matchOrdered(line)) {\n const [list, next] = parseList(lines, i, depth);\n blocks.push(list);\n i = next;\n continue;\n }\n\n if (\n i + 1 < lines.length &&\n line.includes(\"|\") &&\n TABLE_DELIMITER.test(lines[i + 1].trimEnd())\n ) {\n const [table, next] = parseTable(lines, i);\n blocks.push(table);\n i = next;\n continue;\n }\n\n const paragraph: string[] = [];\n const hardBreaks: boolean[] = [];\n while (i < lines.length && lines[i].trim() !== \"\") {\n const current = lines[i];\n if (\n matchHeading(current) ||\n RULE.test(current) ||\n FENCE.test(current.trimEnd()) ||\n QUOTE.test(current) ||\n matchBullet(current) ||\n matchOrdered(current)\n ) {\n break;\n }\n paragraph.push(current.trim());\n hardBreaks.push(endsWithHardBreak(current));\n i += 1;\n }\n if (paragraph.length > 0) {\n blocks.push({\n type: \"paragraph\",\n children: parseInline(joinParagraph(paragraph, hardBreaks)),\n });\n }\n }\n\n return blocks;\n}\n\n/**\n * Re-join the lines of a paragraph, keeping the two-space hard break.\n *\n * Every line is trimmed before it is parsed, because leading indentation is not\n * content and a trailing space is invisible noise in almost every line. The one\n * exception is the CommonMark hard break: two or more trailing spaces mean\n * \"break the line here\", so trimming first would delete the only mark that says\n * so and the ` \\n` inline rule could never match. The flag is recorded before\n * the trim and the marker put back here, on every line but the last — a break\n * after the final line of a paragraph would break into nothing.\n *\n * @param lines - The trimmed lines, in order.\n * @param hardBreaks - Whether each line ended in two or more spaces.\n * @returns The paragraph source the inline parser reads.\n */\nfunction joinParagraph(lines: readonly string[], hardBreaks: readonly boolean[]): string {\n return lines\n .map((line, index) => (hardBreaks[index] && index < lines.length - 1 ? `${line} ` : line))\n .join(\"\\n\");\n}\n\n/**\n * Parse a list, including nested lists and multi-line items.\n *\n * Nesting is decided by indentation relative to the **first** item's marker, so a\n * list indented inside a quote or another list still reads correctly.\n *\n * @param lines - The lines of the enclosing container.\n * @param start - Index of the first item's line.\n * @param depth - Nesting depth of the enclosing container.\n * @returns The list node and the index of the first line after it.\n */\nfunction parseList(lines: string[], start: number, depth: number): [MarkdownBlock, number] {\n const bulletStart = matchBullet(lines[start]);\n const orderedStart = matchOrdered(lines[start]);\n // The two markers are mutually exclusive — `-*+` versus digits — so whichever\n // matched decides the list kind.\n const ordered = orderedStart !== null;\n const first = orderedStart ?? bulletStart;\n const baseIndent = first?.indent.length ?? 0;\n const startNumber = ordered ? Number(orderedStart?.marker ?? 1) : 1;\n\n const items: MarkdownBlock[][] = [];\n let buffer: string[] = [];\n let i = start;\n\n const flush = (): void => {\n if (buffer.length === 0) return;\n items.push(parseBlocks(buffer, depth + 1));\n buffer = [];\n };\n\n while (i < lines.length) {\n const line = lines[i];\n if (line.trim() === \"\") {\n // A single blank line inside a list is a loose item, not the end. Two in\n // a row end it, which is what a blank-then-paragraph document means.\n if (i + 1 < lines.length && lines[i + 1].trim() !== \"\") {\n buffer.push(\"\");\n i += 1;\n continue;\n }\n break;\n }\n const bullet = matchBullet(line);\n const numbered = matchOrdered(line);\n const match = bullet ?? numbered;\n\n if (match && match.indent.length <= baseIndent) {\n const sameKind = ordered ? Boolean(numbered) : Boolean(bullet);\n if (!sameKind) break;\n flush();\n buffer.push(match.content);\n i += 1;\n continue;\n }\n if (match) {\n // Deeper marker: keep the indentation so the recursive call sees a list.\n buffer.push(line.slice(baseIndent));\n i += 1;\n continue;\n }\n if (line.search(/\\S/) > baseIndent) {\n buffer.push(line.trim());\n i += 1;\n continue;\n }\n break;\n }\n flush();\n\n return [{ type: \"list\", ordered, start: startNumber, items }, i];\n}\n\n/** Split a table row on unescaped pipes. */\nfunction splitRow(line: string): string[] {\n const trimmed = line.trim().replace(/^\\|/, \"\").replace(/\\|$/, \"\");\n const cells: string[] = [];\n let current = \"\";\n for (let i = 0; i < trimmed.length; i += 1) {\n if (trimmed[i] === \"\\\\\" && trimmed[i + 1] === \"|\") {\n current += \"|\";\n i += 1;\n continue;\n }\n if (trimmed[i] === \"|\") {\n cells.push(current);\n current = \"\";\n continue;\n }\n current += trimmed[i];\n }\n cells.push(current);\n return cells.map((cell) => cell.trim());\n}\n\n/**\n * Parse a GFM pipe table.\n *\n * @returns The table node and the index of the first line after it.\n */\nfunction parseTable(lines: string[], start: number): [MarkdownBlock, number] {\n const head = splitRow(lines[start]);\n const align: MarkdownAlign[] = splitRow(lines[start + 1]).map((cell) => {\n const left = cell.startsWith(\":\");\n const right = cell.endsWith(\":\");\n if (left && right) return \"center\";\n if (right) return \"right\";\n if (left) return \"left\";\n return null;\n });\n\n const rows: MarkdownInline[][][] = [];\n let i = start + 2;\n while (i < lines.length && lines[i].trim() !== \"\" && lines[i].includes(\"|\")) {\n rows.push(splitRow(lines[i]).map(parseInline));\n i += 1;\n }\n\n return [{ type: \"table\", align, head: head.map(parseInline), rows }, i];\n}\n\n/**\n * The tail of a link or image, read from the label's closing `]`: the\n * destination and an optional quoted title. Sticky, so it runs at a position of\n * the whole source instead of on a slice.\n */\nconst LINK_TAIL = /\\]\\(((?:[^()\\s]|\\([^()\\s]*\\))+)(?:\\s+\"[^\"]*\")?\\)/y;\n\n/**\n * The scheme an autolink must open with, right after its `<`. Sticky, like\n * {@link LINK_TAIL}.\n *\n * Only the scheme is a regex. The rest of `<https://…>` is the run up to the\n * first `>` or whitespace, which a table already knows: the pattern this\n * replaces, `/<((?:https?:\\/\\/|mailto:)[^>\\s]+)>/y`, rescanned that run from\n * every `<` inside it, quadratic for `[` plus 10 000 `<https://` plus `](u)>`.\n */\nconst AUTOLINK_SCHEME = /https?:\\/\\/|mailto:/y;\n\n/** Characters an atom can start with: code span, link, image, autolink. */\nconst ATOM_FIRST = new Set([\"`\", \"[\", \"!\", \"<\"]);\n\n/** Characters an emphasis run is made of. */\nconst EMPHASIS = new Set([\"*\", \"_\", \"~\"]);\n\n/** A parsed inline construct and the index right after it. */\ninterface InlineSpan {\n /** The node, or `null` when the source up to `end` is plain text. */\n node: MarkdownInline | null;\n end: number;\n}\n\n/**\n * An atom read at one position: where it ends, and how to build its node.\n *\n * The node is built only when the atom is accepted, because most atoms never\n * are: every `[` before one `]` reads a link ending at the same tail, the first\n * one is kept, and every later one overruns the label it sits in. Building\n * eagerly parsed each of those labels recursively — one stack frame per opener,\n * so `\"[\".repeat(5000) + \"a](u)\"` threw `RangeError: Maximum call stack size\n * exceeded`, and below the stack limit the work was quadratic.\n *\n * `build` is told whether the atom sits in a link label: an autolink there is\n * kept as text, since an `<a>` inside an `<a>` is invalid HTML and the browser\n * splits it.\n */\ninterface InlineAtom {\n end: number;\n build: (inLink: boolean) => MarkdownInline;\n}\n\n/** Where an emphasis closer search ended: the closer, or `-1` and where it gave up. */\ninterface CloserScan {\n close: number;\n stop: number;\n}\n\n/**\n * For every index of `source`, the first index at or after it holding a\n * character `matches` accepts, or `source.length` when none does.\n *\n * One backward pass, so every later lookup is O(1) wherever it starts — a cursor\n * that only moves forward would go stale as soon as the emphasis scan looked\n * ahead of the main loop.\n *\n * @param source - The text being parsed.\n * @param matches - Which characters to index.\n * @returns The lookup table, `source.length + 1` long.\n */\nfunction nextIndexTable(source: string, matches: (char: string) => boolean): Int32Array {\n const table = new Int32Array(source.length + 1);\n table[source.length] = source.length;\n for (let index = source.length - 1; index >= 0; index -= 1) {\n table[index] = matches(source[index]) ? index : table[index + 1];\n }\n return table;\n}\n\n/**\n * Wrap emphasis content in the node its marker run means.\n *\n * @param marker - `*`, `_` or `~`.\n * @param length - The run length: 1 is italic, 2 bold (strikethrough for `~`),\n * 3 italic around bold.\n * @param children - The parsed content.\n * @returns The emphasis node.\n */\nfunction emphasisNode(marker: string, length: number, children: MarkdownInline[]): MarkdownInline {\n if (marker === \"~\") return { type: \"del\", children };\n if (length === 1) return { type: \"em\", children };\n if (length === 2) return { type: \"strong\", children };\n return { type: \"em\", children: [{ type: \"strong\", children }] };\n}\n\n/**\n * Parse inline Markdown.\n *\n * A backslash escapes the next character, so `\\*not italic\\*` renders with the\n * asterisks. Anything that matches no construct is text — an unclosed `**` is two\n * asterisks, not a bold run to the end of the paragraph.\n *\n * Code spans, links, images and autolinks are **atoms**: read whole wherever they\n * start, and stepped over whole by the search for an emphasis closer. So the\n * content of `**…**`, `*…*`, `_…_` and `~~…~~` goes through this same parser —\n * `**[texto](url)**` is bold around a link — and a marker inside an atom never\n * closes the emphasis around it: the `_` in `_veja [doc](https://x.com/a_b)_` is\n * part of the URL (#599).\n *\n * Emphasis is a run of one marker character. A run of 1 is italic, of 2 bold\n * (strikethrough for `~~`), of 3 italic around bold. The closer is the next run\n * of the same character and the same length, or a run of 3, which closes the\n * outer emphasis and leaves the rest of its markers to the content: `*a **b***`\n * is italic around `a` and bold `b`. A run of another length is stepped over,\n * which is what lets `*a **b** c*` keep its bold inside the italic. Italic does\n * not cross a line break; bold and strikethrough do. A run that finds no closer\n * gives up one marker as text and the rest is tried again, so `**a*` is a literal\n * `*` before italic `a`.\n *\n * The parse is linear in the text, which matters because the text is somebody\n * else's (#437):\n *\n * - A run of spaces is consumed whole: it is a hard break when two or more of them\n * end at a newline, and text otherwise.\n * - A link or image label ends at the first `]` after the opener, read from a\n * table built once per call, and the `](…)` tail after a given `]` is matched\n * once and remembered: every opener before that `]` shares it.\n * - An autolink ends at the first `>` or whitespace, also from a table; only its\n * scheme is matched by a pattern, so no `<` rescans the run after it.\n * - An atom is read once per position and remembered, and reading it only finds\n * where it ends: its node, and so the parse of a link label, is built when the\n * atom is accepted. An opener that overruns the range it sits in costs O(1),\n * which is every `[` after the first before a shared `]`.\n * - Nesting is bounded by the grammar, not by the input. A label ends at the\n * first `]`, so an accepted link never holds another link, and an autolink in a\n * label stays text; no emphasis kind nests itself. So at most one link and the\n * seven emphasis kinds on each side of it stack up, whatever the text — no stack\n * overflow, and no depth cap to tune.\n * - A closer search for one marker and length that fails proves no later opener\n * of the same kind closes either, since that opener would itself have been the\n * closer; so each kind fails at most once per line. A matched emphasis cannot\n * nest its own kind (the inner one's closer would have closed the outer), so\n * the content is re-read at most once per kind — a constant factor.\n *\n * @param source - One block's text.\n * @returns Inline nodes.\n */\nexport function parseInline(source: string): MarkdownInline[] {\n const length = source.length;\n let brackets: Int32Array | null = null;\n let backticks: Int32Array | null = null;\n let autolinkStops: Int32Array | null = null;\n const tails = new Map<number, RegExpExecArray | null>();\n const atoms = new Map<number, InlineAtom | null>();\n\n const tailAt = (close: number): RegExpExecArray | null => {\n if (!tails.has(close)) {\n LINK_TAIL.lastIndex = close;\n tails.set(close, LINK_TAIL.exec(source));\n }\n return tails.get(close) ?? null;\n };\n\n const runLength = (from: number, end: number): number => {\n let to = from;\n while (to < end && source[to] === source[from]) to += 1;\n return to - from;\n };\n\n const readLink = (start: number): InlineAtom | null => {\n const image = source[start] === \"!\";\n if (image && source[start + 1] !== \"[\") return null;\n const labelStart = start + (image ? 2 : 1);\n brackets ??= nextIndexTable(source, (char) => char === \"]\");\n const close = brackets[labelStart];\n if (close >= length) return null;\n const tail = tailAt(close);\n if (!tail) return null;\n const build = (): MarkdownInline => {\n const label = source.slice(labelStart, close);\n if (image) {\n const src = safeImageUrl(tail[1]);\n return src ? { type: \"image\", src, alt: label } : { type: \"text\", value: label };\n }\n const href = safeLinkUrl(tail[1]);\n return href\n ? { type: \"link\", href, children: parseRange(labelStart, close, true) }\n : { type: \"text\", value: label };\n };\n return { end: close + tail[0].length, build };\n };\n\n const readAtom = (start: number): InlineAtom | null => {\n const char = source[start];\n if (char === \"`\") {\n backticks ??= nextIndexTable(source, (next) => next === \"`\");\n const close = backticks[start + 1];\n if (close >= length || close === start + 1) return null;\n return {\n end: close + 1,\n build: () => ({ type: \"code\", value: source.slice(start + 1, close) }),\n };\n }\n if (char === \"<\") {\n autolinkStops ??= nextIndexTable(source, (next) => next === \">\" || /\\s/.test(next));\n const stop = autolinkStops[start + 1];\n if (source[stop] !== \">\") return null;\n AUTOLINK_SCHEME.lastIndex = start + 1;\n const scheme = AUTOLINK_SCHEME.exec(source);\n if (!scheme || start + 1 + scheme[0].length >= stop) return null;\n const build = (inLink: boolean): MarkdownInline => {\n if (inLink) return { type: \"text\", value: source.slice(start, stop + 1) };\n const url = source.slice(start + 1, stop);\n const href = safeLinkUrl(url);\n const text: MarkdownInline = { type: \"text\", value: url };\n return href ? { type: \"link\", href, children: [text] } : text;\n };\n return { end: stop + 1, build };\n }\n return readLink(start);\n };\n\n const atomAt = (start: number, end: number): InlineAtom | null => {\n if (!ATOM_FIRST.has(source[start])) return null;\n if (!atoms.has(start)) atoms.set(start, readAtom(start));\n const atom = atoms.get(start) ?? null;\n return atom && atom.end <= end ? atom : null;\n };\n\n const findCloser = (marker: string, size: number, from: number, end: number): CloserScan => {\n let index = from;\n while (index < end) {\n const char = source[index];\n if (char === \"\\\\\") {\n index += 2;\n continue;\n }\n if (char === \"\\n\" && size === 1) return { close: -1, stop: index };\n if (char === marker) {\n const run = runLength(index, end);\n if (run === size) return { close: index, stop: index };\n if (run === 3 && marker !== \"~\") {\n return { close: index + 3 - size, stop: index };\n }\n index += run;\n continue;\n }\n const atom = atomAt(index, end);\n index = atom ? atom.end : index + 1;\n }\n return { close: -1, stop: end };\n };\n\n function parseRange(start: number, end: number, inLink: boolean): MarkdownInline[] {\n const nodes: MarkdownInline[] = [];\n const failed = new Map<string, number>();\n let text = \"\";\n let index = start;\n\n const push = (node: MarkdownInline): void => {\n if (node.type === \"text\") {\n text += node.value;\n return;\n }\n if (text) nodes.push({ type: \"text\", value: text });\n text = \"\";\n nodes.push(node);\n };\n\n const emphasisAt = (at: number): InlineSpan => {\n const marker = source[at];\n const size = runLength(at, end);\n const usable = marker === \"~\" ? size === 2 : size <= 3;\n if (!usable) return { node: null, end: at + size };\n const kind = `${marker}${size}`;\n const deadUntil = failed.get(kind) ?? -1;\n let close = -1;\n if (at >= deadUntil) {\n const scan = findCloser(marker, size, at + size, end);\n close = scan.close;\n if (close === -1) failed.set(kind, scan.stop);\n }\n if (close === -1) return { node: null, end: marker === \"~\" ? at + size : at + 1 };\n return {\n node: emphasisNode(marker, size, parseRange(at + size, close, inLink)),\n end: close + size,\n };\n };\n\n while (index < end) {\n const char = source[index];\n\n if (char === \"\\\\\" && index + 1 < end) {\n if (source[index + 1] === \"\\n\") push({ type: \"break\" });\n else text += source[index + 1];\n index += 2;\n continue;\n }\n\n if (char === \" \") {\n let stop = index;\n while (stop < end && source[stop] === \" \") stop += 1;\n if (stop - index >= 2 && stop < end && source[stop] === \"\\n\") {\n push({ type: \"break\" });\n index = stop + 1;\n } else {\n text += source.slice(index, stop);\n index = stop;\n }\n continue;\n }\n\n if (EMPHASIS.has(char)) {\n const span = emphasisAt(index);\n if (span.node) push(span.node);\n else text += source.slice(index, span.end);\n index = span.end;\n continue;\n }\n\n const atom = atomAt(index, end);\n if (atom) {\n push(atom.build(inLink));\n index = atom.end;\n continue;\n }\n text += char;\n index += 1;\n }\n\n if (text) nodes.push({ type: \"text\", value: text });\n return nodes;\n }\n\n return parseRange(0, length, false);\n}\n"],"mappings":"A,4CA0DA,IAAMG,EAAQ,qCAKRC,EAAe,sBACfC,EAAO,mCACPC,EAAQ,oBAkBRC,EAAgB,iCAChBC,EAAiB,uCAqBvB,SAASC,EAAgB,EAAiB,EAAiC,CACvE,IAAMC,EAAQC,EAAQ,KAAKC,CAAI,EAC/B,GAAI,CAACF,EAAO,OAAO,KACnB,IAAMG,EAAUD,EAAK,MAAMF,EAAM,EAAE,CAAC,MAAM,EAE1C,OADIG,EAAQ,SAAS,QAAQ,GAAKA,EAAQ,SAAS,QAAQ,EAAU,KAC9D,CAAE,OAAQH,EAAM,GAAI,OAAQA,EAAM,GAAI,SAAQ,CACzD,CAGA,SAASI,EAAY,EAAiC,CAClD,OAAOL,EAAgBF,EAAeK,CAAI,CAC9C,CAGA,SAASG,EAAa,EAAiC,CACnD,OAAON,EAAgBD,EAAgBI,CAAI,CAC/C,CAUA,IAAMI,EAAkB,6DAUlBC,EAAoB,GAe1B,SAASC,EAAa,EAAsD,CACxE,IAAMC,EAAOf,EAAa,KAAKQ,CAAI,EACnC,GAAI,CAACO,EAAM,OAAO,KAClB,IAAIC,EAAOR,EAAK,MAAMO,EAAK,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,EAC1CE,EAAMD,EAAK,OACf,KAAOC,EAAM,GAAKD,EAAKC,EAAM,KAAO,KAAK,IAEzC,MADA,GAAOD,EAAK,MAAM,EAAGC,CAAG,CAAC,CAAC,QAAQ,EAC3B,CAAE,MAAOF,EAAK,EAAE,CAAC,OAAQ,MAAK,CACzC,CASA,SAASG,EAAkB,EAAuB,CAC9C,OAAOV,EAAK,SAAS,IAAI,CAC7B,CAQA,SAAgBW,EAAc,EAAiC,CAE3D,OAAOC,EADOC,EAAO,QAAQ,SAAU;CAAI,CAAC,CAAC,MAAM;CAChC,EAAO,CAAC,CAC/B,CAWA,SAASD,EAAY,EAAiB,EAAgC,CAClE,GAAIE,GAAST,EAAmB,CAC5B,IAAMQ,EAASE,EACV,IAAK,GAASf,EAAK,KAAK,CAAC,CAAC,CAC1B,OAAO,OAAO,CAAC,CACf,KAAK;CAAI,EACd,OAAOa,EAAS,CAAC,CAAE,KAAM,YAAa,SAAUG,EAAYH,CAAM,CAAE,CAAC,EAAI,CAAC,CAC9E,CACA,IAAMI,EAA0B,CAAC,EAC7BC,EAAI,EAER,KAAOA,EAAIH,EAAM,QAAQ,CACrB,IAAMf,EAAOe,EAAMG,GAEnB,GAAIlB,EAAK,KAAK,IAAM,GAAI,CACpB,GAAK,EACL,QACJ,CAEA,IAAMmB,EAAQ5B,EAAM,KAAKS,EAAK,QAAQ,CAAC,EACvC,GAAImB,EAAO,CACP,IAAMC,EAASD,EAAM,EAAE,CAAC,GAClBE,EAAiB,CAAC,EAExB,IADA,GAAK,EACEH,EAAIH,EAAM,QAAU,CAAK,OAAO,YAAYK,EAAO,UAAU,CAAC,CAAC,KAAKL,EAAMG,EAAE,GAC/EG,EAAK,KAAKN,EAAMG,EAAE,EAClB,GAAK,EAIT,GAAK,EACLD,EAAO,KAAK,CAAE,KAAM,OAAQ,SAAUE,EAAM,IAAM,KAAM,MAAOE,EAAK,KAAK;CAAI,CAAE,CAAC,EAChF,QACJ,CAEA,IAAMC,EAAUhB,EAAaN,CAAI,EACjC,GAAIsB,EAAS,CACTL,EAAO,KAAK,CACR,KAAM,UACN,MAAOK,EAAQ,MACf,SAAUN,EAAYM,EAAQ,IAAI,CACtC,CAAC,EACD,GAAK,EACL,QACJ,CAEA,GAAI7B,EAAK,KAAKO,CAAI,EAAG,CACjBiB,EAAO,KAAK,CAAE,KAAM,MAAO,CAAC,EAC5B,GAAK,EACL,QACJ,CAEA,GAAIvB,EAAM,KAAKM,CAAI,EAAG,CAClB,IAAMuB,EAAkB,CAAC,EACzB,KAAOL,EAAIH,EAAM,QAAQ,CACrB,IAAMjB,EAAQJ,EAAM,KAAKqB,EAAMG,EAAE,EACjC,GAAIpB,EACAyB,EAAM,KAAKzB,EAAM,EAAE,EACnB,GAAK,MAKT,IAAIiB,EAAMG,EAAE,CAAC,KAAK,IAAM,GAAI,MAC5BK,EAAM,KAAKR,EAAMG,EAAE,EACnB,GAAK,CAFuB,CAGhC,CACAD,EAAO,KAAK,CAAE,KAAM,QAAS,SAAUL,EAAYW,EAAOT,EAAQ,CAAC,CAAE,CAAC,EACtE,QACJ,CAEA,GAAIZ,EAAYF,CAAI,GAAKG,EAAaH,CAAI,EAAG,CACzC,GAAM,CAACwB,EAAMC,GAAQC,EAAUX,EAAOG,EAAGJ,CAAK,EAC9CG,EAAO,KAAKO,CAAI,EAChB,EAAIC,EACJ,QACJ,CAEA,GACIP,EAAI,EAAIH,EAAM,QACdf,EAAK,SAAS,GAAG,GACjBI,EAAgB,KAAKW,EAAMG,EAAI,EAAE,CAAC,QAAQ,CAAC,EAC7C,CACE,GAAM,CAACS,EAAOF,GAAQG,EAAWb,EAAOG,CAAC,EACzCD,EAAO,KAAKU,CAAK,EACjB,EAAIF,EACJ,QACJ,CAEA,IAAMI,EAAsB,CAAC,EACvBC,EAAwB,CAAC,EAC/B,KAAOZ,EAAIH,EAAM,QAAUA,EAAMG,EAAE,CAAC,KAAK,IAAM,IAAI,CAC/C,IAAMa,EAAUhB,EAAMG,GACtB,GACIZ,EAAayB,CAAO,GACpBtC,EAAK,KAAKsC,CAAO,GACjBxC,EAAM,KAAKwC,EAAQ,QAAQ,CAAC,GAC5BrC,EAAM,KAAKqC,CAAO,GAClB7B,EAAY6B,CAAO,GACnB5B,EAAa4B,CAAO,EAEpB,MAEJF,EAAU,KAAKE,EAAQ,KAAK,CAAC,EAC7BD,EAAW,KAAKpB,EAAkBqB,CAAO,CAAC,EAC1C,GAAK,CACT,CACIF,EAAU,OAAS,GACnBZ,EAAO,KAAK,CACR,KAAM,YACN,SAAUD,EAAYgB,EAAcH,EAAWC,CAAU,CAAC,CAC9D,CAAC,CAET,CAEA,OAAOb,CACX,CAiBA,SAASe,EAAc,EAA0B,EAAwC,CACrF,OAAOjB,EACF,KAAK,EAAM,IAAWe,EAAWG,IAAUA,EAAQlB,EAAM,OAAS,EAAI,GAAGf,EAAK,IAAMA,CAAK,CAAC,CAC1F,KAAK;CAAI,CAClB,CAaA,SAAS0B,EAAU,EAAiB,EAAe,EAAwC,CACvF,IAAMQ,EAAchC,EAAYa,EAAMoB,EAAM,EACtCC,EAAejC,EAAaY,EAAMoB,EAAM,EAGxCE,EAAUD,IAAiB,KAE3BE,GADQF,GAAgBF,EAAA,EACJ,OAAO,QAAU,EACrCK,EAAcF,EAAU,OAAOD,GAAc,QAAU,CAAC,EAAI,EAE5DI,EAA2B,CAAC,EAC9BC,EAAmB,CAAC,EACpBvB,EAAIiB,EAEFO,MAAoB,CAClBD,EAAO,SAAW,IACtBD,EAAM,KAAK5B,EAAY6B,EAAQ3B,EAAQ,CAAC,CAAC,EACzC,EAAS,CAAC,EACd,EAEA,KAAOI,EAAIH,EAAM,QAAQ,CACrB,IAAMf,EAAOe,EAAMG,GACnB,GAAIlB,EAAK,KAAK,IAAM,GAAI,CAGpB,GAAIkB,EAAI,EAAIH,EAAM,QAAUA,EAAMG,EAAI,EAAE,CAAC,KAAK,IAAM,GAAI,CACpDuB,EAAO,KAAK,EAAE,EACd,GAAK,EACL,QACJ,CACA,KACJ,CACA,IAAME,EAASzC,EAAYF,CAAI,EACzB4C,EAAWzC,EAAaH,CAAI,EAC5BF,EAAQ6C,GAAUC,EAExB,GAAI9C,GAASA,EAAM,OAAO,QAAUwC,EAAY,CAE5C,GAAI,EADaD,EAAkBO,EAAoBD,GACxC,MACfD,EAAM,EACND,EAAO,KAAK3C,EAAM,OAAO,EACzB,GAAK,CAET,MACA,GAAIA,EAEA2C,EAAO,KAAKzC,EAAK,MAAMsC,CAAU,CAAC,EAClC,GAAK,OAGT,GAAItC,EAAK,OAAO,IAAI,EAAIsC,EACpBG,EAAO,KAAKzC,EAAK,KAAK,CAAC,EACvB,GAAK,OAGT,KACJ,CAGA,OAFA0C,EAAM,EAEC,CAAC,CAAE,KAAM,OAAQ,UAAS,MAAOH,EAAa,OAAM,EAAGrB,CAAC,CACnE,CAGA,SAAS2B,EAAS,EAAwB,CACtC,IAAMC,EAAU9C,EAAK,KAAK,CAAC,CAAC,QAAQ,MAAO,EAAE,CAAC,CAAC,QAAQ,MAAO,EAAE,EAC1D+C,EAAkB,CAAC,EACrBhB,EAAU,GACd,IAAK,IAAIb,EAAI,EAAGA,EAAI4B,EAAQ,OAAQ,GAAK,EACjCA,EAAQ5B,KAAO,MAAQ4B,EAAQ5B,EAAI,KAAO,KAC1C,GAAW,IACX,GAAK,GAGL4B,EAAQ5B,KAAO,KACf6B,EAAM,KAAKhB,CAAO,EAClB,EAAU,IAGd,GAAWe,EAAQ5B,GAGvB,OADA6B,EAAM,KAAKhB,CAAO,EACXgB,EAAM,IAAK,GAASC,EAAK,KAAK,CAAC,CAC1C,CAOA,SAASpB,EAAW,EAAiB,EAAwC,CACzE,IAAMqB,EAAOJ,EAAS9B,EAAMoB,EAAM,EAC5Be,EAAyBL,EAAS9B,EAAMoB,EAAQ,EAAE,CAAC,CAAC,IAAK,GAAS,CACpE,IAAMgB,EAAOH,EAAK,WAAW,GAAG,EAC1BI,EAAQJ,EAAK,SAAS,GAAG,EAI/B,OAHIG,GAAQC,EAAc,SACtBA,EAAc,QACdD,EAAa,OACV,IACX,CAAC,EAEKE,EAA6B,CAAC,EAChCnC,EAAIiB,EAAQ,EAChB,KAAOjB,EAAIH,EAAM,QAAUA,EAAMG,EAAE,CAAC,KAAK,IAAM,IAAMH,EAAMG,EAAE,CAAC,SAAS,GAAG,GACtEmC,EAAK,KAAKR,EAAS9B,EAAMG,EAAE,CAAC,CAAC,IAAIF,CAAW,CAAC,EAC7C,GAAK,EAGT,MAAO,CAAC,CAAE,KAAM,QAAS,QAAO,KAAMiC,EAAK,IAAIjC,CAAW,EAAG,MAAK,EAAGE,CAAC,CAC1E,CAOA,IAAMoC,EAAY,oDAWZC,EAAkB,uBAGlBC,EAAa,IAAI,IAAI,CAAC,IAAK,IAAK,IAAK,GAAG,CAAC,EAGzCC,EAAW,IAAI,IAAI,CAAC,IAAK,IAAK,GAAG,CAAC,EA8CxC,SAASC,EAAe,EAAgB,EAAgD,CACpF,IAAM/B,EAAQ,IAAI,WAAWd,EAAO,OAAS,CAAC,EAC9C,EAAMA,EAAO,QAAUA,EAAO,OAC9B,IAAK,IAAIoB,EAAQpB,EAAO,OAAS,EAAGoB,GAAS,EAAG,IAC5C,EAAMA,GAAS0B,EAAQ9C,EAAOoB,EAAM,EAAIA,EAAQN,EAAMM,EAAQ,GAElE,OAAON,CACX,CAWA,SAASiC,EAAa,EAAgB,EAAgB,EAA4C,CAI9F,OAHIxC,IAAW,IAAY,CAAE,KAAM,MAAO,UAAS,EAC/CyC,IAAW,EAAU,CAAE,KAAM,KAAM,UAAS,EAC5CA,IAAW,EAAU,CAAE,KAAM,SAAU,UAAS,EAC7C,CAAE,KAAM,KAAM,SAAU,CAAC,CAAE,KAAM,SAAU,UAAS,CAAC,CAAE,CAClE,CAsDA,SAAgB7C,EAAY,EAAkC,CAC1D,IAAM6C,EAAShD,EAAO,OAClBiD,EAA8B,KAC9BC,EAA+B,KAC/BC,EAAmC,KACjCC,EAAQ,IAAI,IACZC,EAAQ,IAAI,IAEZC,EAAU,IACPF,EAAM,IAAIG,CAAK,IAChB,EAAU,UAAYA,EACtBH,EAAM,IAAIG,EAAOd,EAAU,KAAKzC,CAAM,CAAC,GAEpCoD,EAAM,IAAIG,CAAK,GAAK,MAGzBC,GAAa,EAAc,IAAwB,CACrD,IAAIC,EAAKC,EACT,KAAOD,EAAK7D,GAAOI,EAAOyD,KAAQzD,EAAO0D,IAAO,GAAM,EACtD,OAAOD,EAAKC,CAChB,EAEMC,EAAY,GAAqC,CACnD,IAAMC,EAAQ5D,EAAOsB,KAAW,IAChC,GAAIsC,GAAS5D,EAAOsB,EAAQ,KAAO,IAAK,OAAO,KAC/C,IAAMuC,EAAavC,GAASsC,EAAQ,EAAI,GACxC,IAAaf,EAAe7C,EAAS,GAAS8D,IAAS,GAAG,EAC1D,IAAMP,EAAQN,EAASY,GACvB,GAAIN,GAASP,EAAQ,OAAO,KAC5B,IAAMe,EAAOT,EAAOC,CAAK,EAazB,OAZKQ,EAYE,CAAE,IAAKR,EAAQQ,EAAK,EAAE,CAAC,OAAQ,UAXF,CAChC,IAAMC,EAAQhE,EAAO,MAAM6D,EAAYN,CAAK,EAC5C,GAAIK,EAAO,CACP,IAAMK,EAAM1F,EAAAA,aAAawF,EAAK,EAAE,EAChC,OAAOE,EAAM,CAAE,KAAM,QAAS,MAAK,IAAKD,CAAM,EAAI,CAAE,KAAM,OAAQ,MAAOA,CAAM,CACnF,CACA,IAAME,EAAO1F,EAAAA,YAAYuF,EAAK,EAAE,EAChC,OAAOG,EACD,CAAE,KAAM,OAAQ,OAAM,SAAUC,EAAWN,EAAYN,EAAO,EAAI,CAAE,EACpE,CAAE,KAAM,OAAQ,MAAOS,CAAM,CACvC,CAC4C,EAZ1B,IAatB,EAEMI,EAAY,GAAqC,CACnD,IAAMN,EAAO9D,EAAOsB,GACpB,GAAIwC,IAAS,IAAK,CACd,IAAcjB,EAAe7C,EAAS,GAASY,IAAS,GAAG,EAC3D,IAAM2C,EAAQL,EAAU5B,EAAQ,GAEhC,OADIiC,GAASP,GAAUO,IAAUjC,EAAQ,EAAU,KAC5C,CACH,IAAKiC,EAAQ,EACb,WAAc,CAAE,KAAM,OAAQ,MAAOvD,EAAO,MAAMsB,EAAQ,EAAGiC,CAAK,CAAE,EACxE,CACJ,CACA,GAAIO,IAAS,IAAK,CACd,IAAkBjB,EAAe7C,EAAS,GAASY,IAAS,KAAO,KAAK,KAAKA,CAAI,CAAC,EAClF,IAAMyD,EAAOlB,EAAc7B,EAAQ,GACnC,GAAItB,EAAOqE,KAAU,IAAK,OAAO,KACjC,EAAgB,UAAY/C,EAAQ,EACpC,IAAMgD,EAAS5B,EAAgB,KAAK1C,CAAM,EAS1C,MARI,CAACsE,GAAUhD,EAAQ,EAAIgD,EAAO,EAAE,CAAC,QAAUD,EAAa,KAQrD,CAAE,IAAKA,EAAO,EAAG,MAPT,GAAoC,CAC/C,GAAIE,EAAQ,MAAO,CAAE,KAAM,OAAQ,MAAOvE,EAAO,MAAMsB,EAAO+C,EAAO,CAAC,CAAE,EACxE,IAAMG,EAAMxE,EAAO,MAAMsB,EAAQ,EAAG+C,CAAI,EAClCH,EAAO1F,EAAAA,YAAYgG,CAAG,EACtB7E,EAAuB,CAAE,KAAM,OAAQ,MAAO6E,CAAI,EACxD,OAAON,EAAO,CAAE,KAAM,OAAQ,OAAM,SAAU,CAACvE,CAAI,CAAE,EAAIA,CAC7D,CAC8B,CAClC,CACA,OAAOgE,EAASrC,CAAK,CACzB,EAEMmD,GAAU,EAAe,IAAmC,CAC9D,GAAI,CAAC9B,EAAW,IAAI3C,EAAOsB,EAAM,EAAG,OAAO,KACtC+B,EAAM,IAAI/B,CAAK,GAAG+B,EAAM,IAAI/B,EAAO8C,EAAS9C,CAAK,CAAC,EACvD,IAAMoD,EAAOrB,EAAM,IAAI/B,CAAK,GAAK,KACjC,OAAOoD,GAAQA,EAAK,KAAO9E,EAAM8E,EAAO,IAC5C,EAEMC,GAAc,EAAgB,EAAc,EAAc,IAA4B,CACxF,IAAIvD,EAAQsC,EACZ,KAAOtC,EAAQxB,GAAK,CAChB,IAAMkE,EAAO9D,EAAOoB,GACpB,GAAI0C,IAAS,KAAM,CACf,GAAS,EACT,QACJ,CACA,GAAIA,IAAS;GAAQc,IAAS,EAAG,MAAO,CAAE,MAAO,GAAI,KAAMxD,CAAM,EACjE,GAAI0C,IAASvD,EAAQ,CACjB,IAAMsE,EAAMrB,EAAUpC,EAAOxB,CAAG,EAChC,GAAIiF,IAAQD,EAAM,MAAO,CAAE,MAAOxD,EAAO,KAAMA,CAAM,EACrD,GAAIyD,IAAQ,GAAKtE,IAAW,IACxB,MAAO,CAAE,MAAOa,EAAQ,EAAIwD,EAAM,KAAMxD,CAAM,EAElD,GAASyD,EACT,QACJ,CACA,IAAMH,EAAOD,EAAOrD,EAAOxB,CAAG,EAC9B,EAAQ8E,EAAOA,EAAK,IAAMtD,EAAQ,CACtC,CACA,MAAO,CAAE,MAAO,GAAI,KAAMxB,CAAI,CAClC,EAEA,SAASuE,EAAW,EAAe,EAAa,EAAmC,CAC/E,IAAMW,EAA0B,CAAC,EAC3BC,EAAS,IAAI,IACfpF,EAAO,GACPyB,EAAQE,EAEN0D,EAAQ,GAA+B,CACrCC,EAAK,OAAS,OACd,GAAQA,EAAK,OAGbtF,GAAMmF,EAAM,KAAK,CAAE,KAAM,OAAQ,MAAOnF,CAAK,CAAC,EAClD,EAAO,GACPmF,EAAM,KAAKG,CAAI,EACnB,EAEMC,EAAc,GAA2B,CAC3C,IAAM3E,EAASP,EAAOmF,GAChBP,EAAOpB,EAAU2B,EAAIvF,CAAG,EAE9B,GAAI,EADWW,IAAW,IAAMqE,IAAS,EAAIA,GAAQ,GACxC,MAAO,CAAE,KAAM,KAAM,IAAKO,EAAKP,CAAK,EACjD,IAAMQ,EAAO,GAAG7E,IAASqE,IACnBS,EAAYN,EAAO,IAAIK,CAAI,GAAK,GAClC7B,EAAQ,GACZ,GAAI4B,GAAME,EAAW,CACjB,IAAMC,EAAOX,EAAWpE,EAAQqE,EAAMO,EAAKP,EAAMhF,CAAG,EACpD,EAAQ0F,EAAK,MACT/B,IAAU,IAAIwB,EAAO,IAAIK,EAAME,EAAK,IAAI,CAChD,CAEA,OADI/B,IAAU,GAAW,CAAE,KAAM,KAAM,IAAKhD,IAAW,IAAM4E,EAAKP,EAAOO,EAAK,CAAE,EACzE,CACH,KAAMpC,EAAaxC,EAAQqE,EAAMT,EAAWgB,EAAKP,EAAMrB,EAAOgB,CAAM,CAAC,EACrE,IAAKhB,EAAQqB,CACjB,CACJ,EAEA,KAAOxD,EAAQxB,GAAK,CAChB,IAAMkE,EAAO9D,EAAOoB,GAEpB,GAAI0C,IAAS,MAAQ1C,EAAQ,EAAIxB,EAAK,CAC9BI,EAAOoB,EAAQ,KAAO;EAAM4D,EAAK,CAAE,KAAM,OAAQ,CAAC,EACjD,GAAQhF,EAAOoB,EAAQ,GAC5B,GAAS,EACT,QACJ,CAEA,GAAI0C,IAAS,IAAK,CACd,IAAIO,EAAOjD,EACX,KAAOiD,EAAOzE,GAAOI,EAAOqE,KAAU,KAAK,GAAQ,EAC/CA,EAAOjD,GAAS,GAAKiD,EAAOzE,GAAOI,EAAOqE,KAAU;GACpDW,EAAK,CAAE,KAAM,OAAQ,CAAC,EACtB,EAAQX,EAAO,IAEf,GAAQrE,EAAO,MAAMoB,EAAOiD,CAAI,EAChC,EAAQA,GAEZ,QACJ,CAEA,GAAIzB,EAAS,IAAIkB,CAAI,EAAG,CACpB,IAAMyB,EAAOL,EAAW9D,CAAK,EACzBmE,EAAK,KAAMP,EAAKO,EAAK,IAAI,EACxB,GAAQvF,EAAO,MAAMoB,EAAOmE,EAAK,GAAG,EACzC,EAAQA,EAAK,IACb,QACJ,CAEA,IAAMb,EAAOD,EAAOrD,EAAOxB,CAAG,EAC1B8E,GACAM,EAAKN,EAAK,MAAMH,CAAM,CAAC,EACvB,EAAQG,EAAK,MAGjB,GAAQZ,EACR,GAAS,EACb,CAGA,OADInE,GAAMmF,EAAM,KAAK,CAAE,KAAM,OAAQ,MAAOnF,CAAK,CAAC,EAC3CmF,CACX,CAEA,OAAOX,EAAW,EAAGnB,EAAQ,EAAK,CACtC,C"}