@intlayer/core 9.4.0 → 9.4.2

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 (72) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/index.cjs +8 -4
  3. package/dist/cjs/localization/getCanonicalPath.cjs +52 -0
  4. package/dist/cjs/localization/getCanonicalPath.cjs.map +1 -0
  5. package/dist/cjs/localization/getCanonicalPath.test-d.cjs +12 -0
  6. package/dist/cjs/localization/getCanonicalPath.test-d.cjs.map +1 -0
  7. package/dist/cjs/localization/getLocalizedPath.cjs +4 -2
  8. package/dist/cjs/localization/getLocalizedPath.cjs.map +1 -1
  9. package/dist/cjs/localization/index.cjs +4 -2
  10. package/dist/cjs/localization/rewriteMatch.cjs +52 -0
  11. package/dist/cjs/localization/rewriteMatch.cjs.map +1 -0
  12. package/dist/cjs/localization/rewriteUtils.cjs +6 -68
  13. package/dist/cjs/localization/rewriteUtils.cjs.map +1 -1
  14. package/dist/cjs/localization/rewriteUtils.test-d.cjs +0 -5
  15. package/dist/cjs/localization/rewriteUtils.test-d.cjs.map +1 -1
  16. package/dist/cjs/markdown/compiler.cjs +100 -75
  17. package/dist/cjs/markdown/compiler.cjs.map +1 -1
  18. package/dist/cjs/markdown/constants.cjs +14 -5
  19. package/dist/cjs/markdown/constants.cjs.map +1 -1
  20. package/dist/cjs/markdown/index.cjs +4 -2
  21. package/dist/cjs/markdown/parser.cjs +70 -44
  22. package/dist/cjs/markdown/parser.cjs.map +1 -1
  23. package/dist/cjs/markdown/renderer.cjs +7 -19
  24. package/dist/cjs/markdown/renderer.cjs.map +1 -1
  25. package/dist/cjs/markdown/utils.cjs +33 -37
  26. package/dist/cjs/markdown/utils.cjs.map +1 -1
  27. package/dist/esm/index.mjs +5 -3
  28. package/dist/esm/localization/getCanonicalPath.mjs +51 -0
  29. package/dist/esm/localization/getCanonicalPath.mjs.map +1 -0
  30. package/dist/esm/localization/getCanonicalPath.test-d.mjs +12 -0
  31. package/dist/esm/localization/getCanonicalPath.test-d.mjs.map +1 -0
  32. package/dist/esm/localization/getLocalizedPath.mjs +3 -1
  33. package/dist/esm/localization/getLocalizedPath.mjs.map +1 -1
  34. package/dist/esm/localization/index.mjs +3 -1
  35. package/dist/esm/localization/rewriteMatch.mjs +49 -0
  36. package/dist/esm/localization/rewriteMatch.mjs.map +1 -0
  37. package/dist/esm/localization/rewriteUtils.mjs +3 -63
  38. package/dist/esm/localization/rewriteUtils.mjs.map +1 -1
  39. package/dist/esm/localization/rewriteUtils.test-d.mjs +1 -6
  40. package/dist/esm/localization/rewriteUtils.test-d.mjs.map +1 -1
  41. package/dist/esm/markdown/compiler.mjs +101 -55
  42. package/dist/esm/markdown/compiler.mjs.map +1 -1
  43. package/dist/esm/markdown/constants.mjs +11 -4
  44. package/dist/esm/markdown/constants.mjs.map +1 -1
  45. package/dist/esm/markdown/index.mjs +2 -2
  46. package/dist/esm/markdown/parser.mjs +70 -44
  47. package/dist/esm/markdown/parser.mjs.map +1 -1
  48. package/dist/esm/markdown/renderer.mjs +7 -19
  49. package/dist/esm/markdown/renderer.mjs.map +1 -1
  50. package/dist/esm/markdown/utils.mjs +34 -38
  51. package/dist/esm/markdown/utils.mjs.map +1 -1
  52. package/dist/types/index.d.ts +5 -3
  53. package/dist/types/localization/getCanonicalPath.d.ts +19 -0
  54. package/dist/types/localization/getCanonicalPath.d.ts.map +1 -0
  55. package/dist/types/localization/getCanonicalPath.test-d.d.ts +1 -0
  56. package/dist/types/localization/getLocalizedPath.d.ts.map +1 -1
  57. package/dist/types/localization/index.d.ts +3 -1
  58. package/dist/types/localization/rewriteMatch.d.ts +20 -0
  59. package/dist/types/localization/rewriteMatch.d.ts.map +1 -0
  60. package/dist/types/localization/rewriteUtils.d.ts +2 -14
  61. package/dist/types/localization/rewriteUtils.d.ts.map +1 -1
  62. package/dist/types/markdown/compiler.d.ts.map +1 -1
  63. package/dist/types/markdown/constants.d.ts +11 -4
  64. package/dist/types/markdown/constants.d.ts.map +1 -1
  65. package/dist/types/markdown/index.d.ts +2 -2
  66. package/dist/types/markdown/parser.d.ts.map +1 -1
  67. package/dist/types/markdown/renderer.d.ts.map +1 -1
  68. package/dist/types/markdown/types.d.ts +8 -2
  69. package/dist/types/markdown/types.d.ts.map +1 -1
  70. package/dist/types/markdown/utils.d.ts +0 -4
  71. package/dist/types/markdown/utils.d.ts.map +1 -1
  72. package/package.json +7 -7
@@ -63,8 +63,6 @@ const Priority = {
63
63
  /** bare text and stuff that is considered leftovers */
64
64
  MIN: 4
65
65
  };
66
- /** Threshold for performance logging (in milliseconds) */
67
- const DURATION_DELAY_TRIGGER = 20;
68
66
  /**
69
67
  * Map of HTML attributes to their JSX prop equivalents.
70
68
  * Some renderers use camelCase for certain attributes.
@@ -222,14 +220,23 @@ const PARAGRAPH_R = /^[^\n]+(?: {2}\n|\n{2,})/;
222
220
  const REFERENCE_IMAGE_OR_LINK = /^\[([^\]]*)\]:\s+<?([^\s>]+)>?\s*("([^"]*)")?/;
223
221
  const REFERENCE_IMAGE_R = /^!\[([^\]]*)\] ?\[([^\]]*)\]/;
224
222
  const REFERENCE_LINK_R = /^\[([^\]]*)\] ?\[([^\]]*)\]/;
223
+ /**
224
+ * Cheap prefix probes used to reject a rule before its full (and far more
225
+ * expensive) block regex runs. Kept as module constants so the parser's inner
226
+ * loop never allocates a `RegExp` per candidate position.
227
+ */
228
+ const HTML_BLOCK_OPENING_TAG_R = /^ *<([a-z][a-z0-9:-]*)\b/i;
229
+ const HTML_SELF_CLOSING_OPENING_TAG_R = /^ *<([a-zA-Z][a-zA-Z0-9:]*)[\s>/]/;
230
+ const CUSTOM_COMPONENT_OPENING_TAG_R = /^ *<([A-Z][a-zA-Z0-9]*)/;
225
231
  /** Block detection */
226
232
  const SHOULD_RENDER_AS_BLOCK_R = /(\n|^[-*]\s|^#|^ {2,}|^-{2,}|^>\s)/;
227
233
  /** Tab and whitespace */
228
234
  const TAB_R = /\t/g;
235
+ /** Every character `normalizeWhitespace` rewrites, so it needs a single pass. */
236
+ const NORMALIZE_WHITESPACE_R = /\r\n?|\f|\t/g;
229
237
  const TRIM_STARTING_NEWLINES = /^\n+/;
230
238
  const HTML_LEFT_TRIM_AMOUNT_R = /^\n*([ \t]*)/;
231
239
  /** List patterns */
232
- const LIST_LOOKBEHIND_R = /(?:^|\n)( *)$/;
233
240
  const ORDERED_LIST_BULLET = "(?:\\d+\\.)";
234
241
  const UNORDERED_LIST_BULLET = "(?:[*+-])";
235
242
  /** Text formatting patterns */
@@ -296,9 +303,9 @@ exports.CODE_BLOCK_R = CODE_BLOCK_R;
296
303
  exports.CODE_INLINE_R = CODE_INLINE_R;
297
304
  exports.CONSECUTIVE_NEWLINE_R = CONSECUTIVE_NEWLINE_R;
298
305
  exports.CR_NEWLINE_R = CR_NEWLINE_R;
306
+ exports.CUSTOM_COMPONENT_OPENING_TAG_R = CUSTOM_COMPONENT_OPENING_TAG_R;
299
307
  exports.CUSTOM_COMPONENT_R = CUSTOM_COMPONENT_R;
300
308
  exports.DO_NOT_PROCESS_HTML_ELEMENTS = DO_NOT_PROCESS_HTML_ELEMENTS;
301
- exports.DURATION_DELAY_TRIGGER = DURATION_DELAY_TRIGGER;
302
309
  exports.FENCE_DELIMITER_R = FENCE_DELIMITER_R;
303
310
  exports.FOOTNOTE_R = FOOTNOTE_R;
304
311
  exports.FOOTNOTE_REFERENCE_R = FOOTNOTE_REFERENCE_R;
@@ -309,18 +316,20 @@ exports.HEADING_ATX_COMPLIANT_R = HEADING_ATX_COMPLIANT_R;
309
316
  exports.HEADING_R = HEADING_R;
310
317
  exports.HEADING_SETEXT_R = HEADING_SETEXT_R;
311
318
  exports.HTML_BLOCK_ELEMENT_R = HTML_BLOCK_ELEMENT_R;
319
+ exports.HTML_BLOCK_OPENING_TAG_R = HTML_BLOCK_OPENING_TAG_R;
312
320
  exports.HTML_CHAR_CODE_R = HTML_CHAR_CODE_R;
313
321
  exports.HTML_COMMENT_R = HTML_COMMENT_R;
314
322
  exports.HTML_CUSTOM_ATTR_R = HTML_CUSTOM_ATTR_R;
315
323
  exports.HTML_LEFT_TRIM_AMOUNT_R = HTML_LEFT_TRIM_AMOUNT_R;
316
324
  exports.HTML_SELF_CLOSING_ELEMENT_R = HTML_SELF_CLOSING_ELEMENT_R;
325
+ exports.HTML_SELF_CLOSING_OPENING_TAG_R = HTML_SELF_CLOSING_OPENING_TAG_R;
317
326
  exports.INLINE_SKIP_R = INLINE_SKIP_R;
318
327
  exports.INTERPOLATION_R = INTERPOLATION_R;
319
328
  exports.LINK_AUTOLINK_BARE_URL_R = LINK_AUTOLINK_BARE_URL_R;
320
329
  exports.LINK_AUTOLINK_R = LINK_AUTOLINK_R;
321
- exports.LIST_LOOKBEHIND_R = LIST_LOOKBEHIND_R;
322
330
  exports.LOOKAHEAD = LOOKAHEAD;
323
331
  exports.NAMED_CODES_TO_UNICODE = NAMED_CODES_TO_UNICODE;
332
+ exports.NORMALIZE_WHITESPACE_R = NORMALIZE_WHITESPACE_R;
324
333
  exports.NP_TABLE_R = NP_TABLE_R;
325
334
  exports.ORDERED = ORDERED;
326
335
  exports.ORDERED_LIST_BULLET = ORDERED_LIST_BULLET;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.cjs","names":[],"sources":["../../../src/markdown/constants.ts"],"sourcesContent":["// ============================================================================\n// RULE TYPES\n// ============================================================================\n\n/**\n * Analogous to `node.type`. Please note that the values here may change at any time,\n * so do not hard code against the value directly.\n */\nexport const RuleType = {\n blockQuote: '0',\n breakLine: '1',\n breakThematic: '2',\n codeBlock: '3',\n codeFenced: '4',\n codeInline: '5',\n footnote: '6',\n footnoteReference: '7',\n gfmTask: '8',\n heading: '9',\n headingSetext: '10',\n /** only available if not `disableHTMLParsing` */\n htmlBlock: '11',\n htmlComment: '12',\n /** only available if not `disableHTMLParsing` */\n htmlSelfClosing: '13',\n /** Custom components like <Tabs>, <TabItem> */\n customComponent: '34',\n image: '14',\n link: '15',\n /** emits a `link` 'node', does not render directly */\n linkAngleBraceStyleDetector: '16',\n /** emits a `link` 'node', does not render directly */\n linkBareUrlDetector: '17',\n newlineCoalescer: '19',\n orderedList: '20',\n paragraph: '21',\n ref: '22',\n refImage: '23',\n refLink: '24',\n table: '25',\n tableSeparator: '26',\n text: '27',\n textBolded: '28',\n textEmphasized: '29',\n textEscaped: '30',\n textMarked: '31',\n textStrikethroughed: '32',\n unorderedList: '33',\n} as const;\n\n// In test environment, use human-readable keys for easier debugging\nif (process.env.NODE_ENV === 'test') {\n Object.keys(RuleType).forEach((key) => {\n (RuleType as any)[key] = key;\n });\n}\n\nexport type RuleTypeValue = (typeof RuleType)[keyof typeof RuleType];\n\n// ============================================================================\n// PRIORITY LEVELS\n// ============================================================================\n\n/**\n * Priority levels for rule ordering.\n */\nexport const Priority = {\n /** anything that must scan the tree before everything else */\n MAX: 0,\n /** scans for block-level constructs */\n HIGH: 1,\n /** inline w/ more priority than other inline */\n MED: 2,\n /** inline elements */\n LOW: 3,\n /** bare text and stuff that is considered leftovers */\n MIN: 4,\n} as const;\n\nexport type PriorityValue = (typeof Priority)[keyof typeof Priority];\n\n// ============================================================================\n// PERFORMANCE CONSTANTS\n// ============================================================================\n\n/** Threshold for performance logging (in milliseconds) */\nexport const DURATION_DELAY_TRIGGER = 20;\n\n// ============================================================================\n// ATTRIBUTE MAPPING\n// ============================================================================\n\n/**\n * Map of HTML attributes to their JSX prop equivalents.\n * Some renderers use camelCase for certain attributes.\n */\nexport const ATTRIBUTE_TO_NODE_PROP_MAP: Record<string, string> = [\n 'allowFullScreen',\n 'allowTransparency',\n 'autoComplete',\n 'autoFocus',\n 'autoPlay',\n 'cellPadding',\n 'cellSpacing',\n 'charSet',\n 'classId',\n 'colSpan',\n 'contentEditable',\n 'contextMenu',\n 'crossOrigin',\n 'encType',\n 'formAction',\n 'formEncType',\n 'formMethod',\n 'formNoValidate',\n 'formTarget',\n 'frameBorder',\n 'hrefLang',\n 'inputMode',\n 'keyParams',\n 'keyType',\n 'marginHeight',\n 'marginWidth',\n 'maxLength',\n 'mediaGroup',\n 'minLength',\n 'noValidate',\n 'radioGroup',\n 'readOnly',\n 'rowSpan',\n 'spellCheck',\n 'srcDoc',\n 'srcLang',\n 'srcSet',\n 'tabIndex',\n 'useMap',\n].reduce(\n (obj: Record<string, string>, x) => {\n obj[x.toLowerCase()] = x;\n return obj;\n },\n { class: 'className', for: 'htmlFor' }\n);\n\n// ============================================================================\n// NAMED CODES TO UNICODE\n// ============================================================================\n\n/**\n * Default HTML entity to unicode mappings.\n */\nexport const NAMED_CODES_TO_UNICODE: Record<string, string> = {\n amp: '\\u0026',\n apos: '\\u0027',\n gt: '\\u003e',\n lt: '\\u003c',\n nbsp: '\\u00a0',\n quot: '\\u201c',\n};\n\n// ============================================================================\n// SPECIAL ELEMENTS\n// ============================================================================\n\n/** HTML elements that should not have their content processed */\nexport const DO_NOT_PROCESS_HTML_ELEMENTS = ['style', 'script', 'pre'];\n\n/** Attributes that require URL sanitization */\nexport const ATTRIBUTES_TO_SANITIZE = [\n 'src',\n 'href',\n 'data',\n 'formAction',\n 'srcDoc',\n 'action',\n];\n\n// ============================================================================\n// REGEX PATTERNS\n// ============================================================================\n\n/** Attribute extractor regex */\nexport const ATTR_EXTRACTOR_R =\n /([-A-Z0-9_:]+)(?:\\s*=\\s*(?:(?:\"((?:\\\\.|[^\"])*)\")|(?:'((?:\\\\.|[^'])*)')|(?:\\{((?:\\\\.|{[^}]*?}|[^}])*)\\})))?/gi;\n\n/** Block end detection */\nexport const BLOCK_END_R = /\\n{2,}$/;\n\n/** Blockquote patterns */\nexport const BLOCKQUOTE_R = /^(\\s*>[\\s\\S]*?)(?=\\n\\n|$)/;\nexport const BLOCKQUOTE_TRIM_LEFT_MULTILINE_R = /^ *> ?/gm;\nexport const BLOCKQUOTE_ALERT_R = /^(?:\\[!([^\\]]*)\\]\\n)?([\\s\\S]*)/;\n\n/** Line break patterns */\nexport const BREAK_LINE_R = /^ {2,}\\n/;\nexport const BREAK_THEMATIC_R = /^(?:([-*_])( *\\1){2,}) *(?:\\n *)+\\n/;\n\n/** Code block patterns */\nexport const CODE_BLOCK_FENCED_R =\n /^(?: {1,3})?(`{3,}|~{3,}) *(\\S+)? *([^\\n]*?)?\\n([\\s\\S]*?)(?:\\1\\n?|$)/;\nexport const CODE_BLOCK_R = /^(?: {4}[^\\n]+\\n*)+(?:\\n *)+\\n?/;\n/** A single line opening or closing a fenced code block, with its indentation. */\nexport const FENCE_DELIMITER_R = /^([ \\t]*)(`{3,}|~{3,})/;\nexport const CODE_INLINE_R = /^(`+)((?:\\\\`|(?!\\1)`|[^`])+)\\1/;\n\n/** Newline patterns */\nexport const CONSECUTIVE_NEWLINE_R = /^(?:\\n *)*\\n/;\nexport const CR_NEWLINE_R = /\\r\\n?/g;\n\n/** Footnote patterns */\nexport const FOOTNOTE_R = /^\\[\\^([^\\]]+)](:(.*)((\\n+ {4,}.*)|(\\n(?!\\[\\^).+))*)/;\nexport const FOOTNOTE_REFERENCE_R = /^\\[\\^([^\\]]+)]/;\n\n/** Form feed */\nexport const FORMFEED_R = /\\f/g;\n\n/** Front matter */\nexport const FRONT_MATTER_R = /^---[ \\t]*\\n(.|\\n)*?\\n---[ \\t]*\\n/;\n\n/** GFM task */\nexport const GFM_TASK_R = /^\\s*?\\[(x|\\s)\\]/;\n\n/** Heading patterns */\nexport const HEADING_R = /^ *(#{1,6}) *([^\\n]+?)(?: +#*)?(?:\\n *)*(?:\\n|$)/;\nexport const HEADING_ATX_COMPLIANT_R =\n /^ *(#{1,6}) +([^\\n]+?)(?: +#*)?(?:\\n *)*(?:\\n|$)/;\nexport const HEADING_SETEXT_R = /^([^\\n]+)\\n *(=|-)\\2{2,} *\\n/;\n\n/** HTML patterns */\n\n/**\n * Run of characters carrying no meaning inside an opening tag: neither a quote\n * opening a value nor an angle bracket delimiting a tag.\n */\nconst TAG_PLAIN_RUN = `[^>\"'<]*`;\n\n/**\n * Quoted attribute value. It may hold an angle bracket —\n * `<Tab label='Intlayer >=9.4'>` — but not a line break, which keeps a tag that\n * turns out not to match from trying every later quote of the document as its\n * closing one.\n */\nconst TAG_QUOTED_VALUE = `\"[^\"\\\\n]*\"|'[^'\\\\n]*'`;\n\n/**\n * Attribute list of an opening tag, written as a plain run followed by\n * quote-or-bracket-led segments so that each character has a single way to be\n * read. A lone quote is allowed last so a tag holding an unbalanced one still\n * parses, as it did before quoted values were recognised.\n */\nconst TAG_ATTRIBUTES = `${TAG_PLAIN_RUN}(?:(?:${TAG_QUOTED_VALUE}|<.*?>|[\"'])${TAG_PLAIN_RUN})*`;\n\n/** Rejects the opening tag of a self-closing element, `<div class=\"a\"/>`. */\nconst NOT_SELF_CLOSING = `(?![^>]*/>)`;\n\n/**\n * Opening tag of a nested element bearing the same name as the outer one. This\n * one stays a plain scan up to the first `>`: it is tried at every character of\n * the element's content, and a richer pattern here costs an order of magnitude\n * on documents whose tag never closes.\n */\nconst NESTED_SAME_TAG_OPENING = `<\\\\1[^>]*?>`;\n\nexport const HTML_BLOCK_ELEMENT_R = new RegExp(\n `^ *(?!<[a-zA-Z][^ >/]* ?/>)<([a-zA-Z][^ >/]*) ?(${NOT_SELF_CLOSING}${TAG_ATTRIBUTES})>\\\\n?(\\\\s*(?:${NESTED_SAME_TAG_OPENING}[\\\\s\\\\S]*?</\\\\1>|(?!<\\\\1\\\\b)[\\\\s\\\\S])*?)</\\\\1>(?!</\\\\1>)\\\\n*`,\n 'i'\n);\nexport const HTML_CHAR_CODE_R =\n /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/gi;\nexport const HTML_COMMENT_R = /^<!--[\\s\\S]*?(?:-->)/;\nexport const HTML_CUSTOM_ATTR_R = /^(data|aria|x)-[a-z_][a-z\\d_.-]*$/;\nexport const HTML_SELF_CLOSING_ELEMENT_R = new RegExp(\n `^ *<([a-zA-Z][a-zA-Z0-9:]*)(?:\\\\s+(${TAG_ATTRIBUTES}))?/?>(?!</\\\\1>)(\\\\s*\\\\n)?`,\n 'i'\n);\n\n/** Custom component pattern */\nexport const CUSTOM_COMPONENT_R = new RegExp(\n `^ *<([A-Z][a-zA-Z0-9]*)(?:\\\\s+(${TAG_ATTRIBUTES}))?>\\\\n?(\\\\s*(?:${NESTED_SAME_TAG_OPENING}[\\\\s\\\\S]*?</\\\\1>|(?!<\\\\1\\\\b)[\\\\s\\\\S])*?)</\\\\1>(?!</\\\\1>)\\\\n*`\n);\n\n/** Interpolation */\nexport const INTERPOLATION_R = /^\\{.*\\}$/;\n\n/** Link patterns */\nexport const LINK_AUTOLINK_BARE_URL_R = /^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/;\nexport const LINK_AUTOLINK_R = /^<([^ >]+[:@/][^ >]+)>/;\nexport const CAPTURE_LETTER_AFTER_HYPHEN = /-([a-z])?/gi;\n\n/** Table patterns */\nexport const NP_TABLE_R =\n /^(\\|.*)\\n(?: *(\\|? *[-:]+ *\\|[-| :]*)\\n((?:.*\\|.*\\n)*))?\\n?/;\nexport const TABLE_TRIM_PIPES = /(^ *\\||\\| *$)/g;\nexport const TABLE_CENTER_ALIGN = /^ *:-+: *$/;\nexport const TABLE_LEFT_ALIGN = /^ *:-+ *$/;\nexport const TABLE_RIGHT_ALIGN = /^ *-+: *$/;\n\n/** Paragraph */\nexport const PARAGRAPH_R = /^[^\\n]+(?: {2}\\n|\\n{2,})/;\n\n/** Reference patterns */\nexport const REFERENCE_IMAGE_OR_LINK =\n /^\\[([^\\]]*)\\]:\\s+<?([^\\s>]+)>?\\s*(\"([^\"]*)\")?/;\nexport const REFERENCE_IMAGE_R = /^!\\[([^\\]]*)\\] ?\\[([^\\]]*)\\]/;\nexport const REFERENCE_LINK_R = /^\\[([^\\]]*)\\] ?\\[([^\\]]*)\\]/;\n\n/** Block detection */\nexport const SHOULD_RENDER_AS_BLOCK_R = /(\\n|^[-*]\\s|^#|^ {2,}|^-{2,}|^>\\s)/;\n\n/** Tab and whitespace */\nexport const TAB_R = /\\t/g;\nexport const TRIM_STARTING_NEWLINES = /^\\n+/;\nexport const HTML_LEFT_TRIM_AMOUNT_R = /^\\n*([ \\t]*)/;\n\n/** List patterns */\nexport const LIST_LOOKBEHIND_R = /(?:^|\\n)( *)$/;\nexport const ORDERED_LIST_BULLET = '(?:\\\\d+\\\\.)';\nexport const UNORDERED_LIST_BULLET = '(?:[*+-])';\n\n/** Text formatting patterns */\nexport const TEXT_ESCAPED_R = /^\\\\([^0-9A-Za-z\\s])/;\nexport const UNESCAPE_R = /\\\\([^0-9A-Za-z\\s])/g;\nexport const TEXT_PLAIN_R =\n /^[\\s\\S](?:(?! {2}\\n|[0-9]\\.|http)[^=*_~\\-\\n:<`\\\\[!])*/;\n\n/** Shortcode pattern */\nexport const SHORTCODE_R = /^(:[a-zA-Z0-9-_]+:)/;\n\n// ============================================================================\n// LIST TYPE CONSTANTS\n// ============================================================================\n\nexport type ListType = 1 | 2;\nexport const ORDERED: ListType = 1;\nexport const UNORDERED: ListType = 2;\n\n// ============================================================================\n// INLINE PATTERN HELPERS\n// ============================================================================\n\n/**\n * Ensure there's at least one more instance of the delimiter later\n * in the current sequence.\n */\nexport const LOOKAHEAD = (double: number): string =>\n `(?=[\\\\s\\\\S]+?\\\\1${double ? '\\\\1' : ''})`;\n\n/**\n * For inline formatting, this partial attempts to ignore characters that\n * may appear in nested formatting.\n */\nexport const INLINE_SKIP_R =\n '((?:\\\\[.*?\\\\][([].*?[)\\\\]]|<.*?>(?:.*?<.*?>)?|`.*?`|\\\\\\\\[^\\\\s]|[\\\\s\\\\S])+?)';\n\n/** Bold text pattern */\nexport const TEXT_BOLD_R = new RegExp(\n `^([*_])\\\\1${LOOKAHEAD(1)}${INLINE_SKIP_R}\\\\1\\\\1(?!\\\\1)`\n);\n\n/** Emphasized text pattern */\nexport const TEXT_EMPHASIZED_R = new RegExp(\n `^([*_])${LOOKAHEAD(0)}${INLINE_SKIP_R}\\\\1(?!\\\\1)`\n);\n\n/** Marked text pattern */\nexport const TEXT_MARKED_R = new RegExp(\n `^(==)${LOOKAHEAD(0)}${INLINE_SKIP_R}\\\\1`\n);\n\n/** Strikethrough text pattern */\nexport const TEXT_STRIKETHROUGHED_R = new RegExp(\n `^(~~)${LOOKAHEAD(0)}${INLINE_SKIP_R}\\\\1`\n);\n\n// ============================================================================\n// LIST REGEX GENERATORS\n// ============================================================================\n\nexport const generateListItemPrefix = (type: ListType): string => {\n return (\n '( *)(' +\n (type === ORDERED ? ORDERED_LIST_BULLET : UNORDERED_LIST_BULLET) +\n ') +'\n );\n};\n\nexport const ORDERED_LIST_ITEM_PREFIX = generateListItemPrefix(ORDERED);\nexport const UNORDERED_LIST_ITEM_PREFIX = generateListItemPrefix(UNORDERED);\n\nexport const generateListItemPrefixRegex = (type: ListType): RegExp => {\n return new RegExp(\n '^' +\n (type === ORDERED ? ORDERED_LIST_ITEM_PREFIX : UNORDERED_LIST_ITEM_PREFIX)\n );\n};\n\nexport const ORDERED_LIST_ITEM_PREFIX_R = generateListItemPrefixRegex(ORDERED);\nexport const UNORDERED_LIST_ITEM_PREFIX_R =\n generateListItemPrefixRegex(UNORDERED);\n\nexport const generateListItemRegex = (type: ListType): RegExp => {\n return new RegExp(\n '^' +\n (type === ORDERED\n ? ORDERED_LIST_ITEM_PREFIX\n : UNORDERED_LIST_ITEM_PREFIX) +\n '[^\\\\n]*(?:\\\\n' +\n '(?!\\\\1' +\n (type === ORDERED ? ORDERED_LIST_BULLET : UNORDERED_LIST_BULLET) +\n ' )[^\\\\n]*)*(\\\\n|$)',\n 'gm'\n );\n};\n\nexport const ORDERED_LIST_ITEM_R = generateListItemRegex(ORDERED);\nexport const UNORDERED_LIST_ITEM_R = generateListItemRegex(UNORDERED);\n\nexport const generateListRegex = (type: ListType): RegExp => {\n const bullet = type === ORDERED ? ORDERED_LIST_BULLET : UNORDERED_LIST_BULLET;\n\n return new RegExp(\n '^( *)(' +\n bullet +\n ') ' +\n '[\\\\s\\\\S]+?(?:\\\\n{2,}(?! )' +\n '(?!\\\\1' +\n bullet +\n ' (?!' +\n bullet +\n ' ))\\\\n*' +\n '|\\\\s*\\\\n*$)'\n );\n};\n\nexport const ORDERED_LIST_R = generateListRegex(ORDERED);\nexport const UNORDERED_LIST_R = generateListRegex(UNORDERED);\n"],"mappings":"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"}
1
+ {"version":3,"file":"constants.cjs","names":[],"sources":["../../../src/markdown/constants.ts"],"sourcesContent":["// ============================================================================\n// RULE TYPES\n// ============================================================================\n\n/**\n * Analogous to `node.type`. Please note that the values here may change at any time,\n * so do not hard code against the value directly.\n */\nexport const RuleType = {\n blockQuote: '0',\n breakLine: '1',\n breakThematic: '2',\n codeBlock: '3',\n codeFenced: '4',\n codeInline: '5',\n footnote: '6',\n footnoteReference: '7',\n gfmTask: '8',\n heading: '9',\n headingSetext: '10',\n /** only available if not `disableHTMLParsing` */\n htmlBlock: '11',\n htmlComment: '12',\n /** only available if not `disableHTMLParsing` */\n htmlSelfClosing: '13',\n /** Custom components like <Tabs>, <TabItem> */\n customComponent: '34',\n image: '14',\n link: '15',\n /** emits a `link` 'node', does not render directly */\n linkAngleBraceStyleDetector: '16',\n /** emits a `link` 'node', does not render directly */\n linkBareUrlDetector: '17',\n newlineCoalescer: '19',\n orderedList: '20',\n paragraph: '21',\n ref: '22',\n refImage: '23',\n refLink: '24',\n table: '25',\n tableSeparator: '26',\n text: '27',\n textBolded: '28',\n textEmphasized: '29',\n textEscaped: '30',\n textMarked: '31',\n textStrikethroughed: '32',\n unorderedList: '33',\n} as const;\n\n// In test environment, use human-readable keys for easier debugging\nif (process.env.NODE_ENV === 'test') {\n Object.keys(RuleType).forEach((key) => {\n (RuleType as any)[key] = key;\n });\n}\n\nexport type RuleTypeValue = (typeof RuleType)[keyof typeof RuleType];\n\n// ============================================================================\n// PRIORITY LEVELS\n// ============================================================================\n\n/**\n * Priority levels for rule ordering.\n */\nexport const Priority = {\n /** anything that must scan the tree before everything else */\n MAX: 0,\n /** scans for block-level constructs */\n HIGH: 1,\n /** inline w/ more priority than other inline */\n MED: 2,\n /** inline elements */\n LOW: 3,\n /** bare text and stuff that is considered leftovers */\n MIN: 4,\n} as const;\n\nexport type PriorityValue = (typeof Priority)[keyof typeof Priority];\n\n// ============================================================================\n// ATTRIBUTE MAPPING\n// ============================================================================\n\n/**\n * Map of HTML attributes to their JSX prop equivalents.\n * Some renderers use camelCase for certain attributes.\n */\nexport const ATTRIBUTE_TO_NODE_PROP_MAP: Record<string, string> = [\n 'allowFullScreen',\n 'allowTransparency',\n 'autoComplete',\n 'autoFocus',\n 'autoPlay',\n 'cellPadding',\n 'cellSpacing',\n 'charSet',\n 'classId',\n 'colSpan',\n 'contentEditable',\n 'contextMenu',\n 'crossOrigin',\n 'encType',\n 'formAction',\n 'formEncType',\n 'formMethod',\n 'formNoValidate',\n 'formTarget',\n 'frameBorder',\n 'hrefLang',\n 'inputMode',\n 'keyParams',\n 'keyType',\n 'marginHeight',\n 'marginWidth',\n 'maxLength',\n 'mediaGroup',\n 'minLength',\n 'noValidate',\n 'radioGroup',\n 'readOnly',\n 'rowSpan',\n 'spellCheck',\n 'srcDoc',\n 'srcLang',\n 'srcSet',\n 'tabIndex',\n 'useMap',\n].reduce(\n (obj: Record<string, string>, x) => {\n obj[x.toLowerCase()] = x;\n return obj;\n },\n { class: 'className', for: 'htmlFor' }\n);\n\n// ============================================================================\n// NAMED CODES TO UNICODE\n// ============================================================================\n\n/**\n * Default HTML entity to unicode mappings.\n */\nexport const NAMED_CODES_TO_UNICODE: Record<string, string> = {\n amp: '\\u0026',\n apos: '\\u0027',\n gt: '\\u003e',\n lt: '\\u003c',\n nbsp: '\\u00a0',\n quot: '\\u201c',\n};\n\n// ============================================================================\n// SPECIAL ELEMENTS\n// ============================================================================\n\n/** HTML elements that should not have their content processed */\nexport const DO_NOT_PROCESS_HTML_ELEMENTS = ['style', 'script', 'pre'];\n\n/** Attributes that require URL sanitization */\nexport const ATTRIBUTES_TO_SANITIZE = [\n 'src',\n 'href',\n 'data',\n 'formAction',\n 'srcDoc',\n 'action',\n];\n\n// ============================================================================\n// REGEX PATTERNS\n// ============================================================================\n\n/** Attribute extractor regex */\nexport const ATTR_EXTRACTOR_R =\n /([-A-Z0-9_:]+)(?:\\s*=\\s*(?:(?:\"((?:\\\\.|[^\"])*)\")|(?:'((?:\\\\.|[^'])*)')|(?:\\{((?:\\\\.|{[^}]*?}|[^}])*)\\})))?/gi;\n\n/** Block end detection */\nexport const BLOCK_END_R = /\\n{2,}$/;\n\n/** Blockquote patterns */\nexport const BLOCKQUOTE_R = /^(\\s*>[\\s\\S]*?)(?=\\n\\n|$)/;\nexport const BLOCKQUOTE_TRIM_LEFT_MULTILINE_R = /^ *> ?/gm;\nexport const BLOCKQUOTE_ALERT_R = /^(?:\\[!([^\\]]*)\\]\\n)?([\\s\\S]*)/;\n\n/** Line break patterns */\nexport const BREAK_LINE_R = /^ {2,}\\n/;\nexport const BREAK_THEMATIC_R = /^(?:([-*_])( *\\1){2,}) *(?:\\n *)+\\n/;\n\n/** Code block patterns */\nexport const CODE_BLOCK_FENCED_R =\n /^(?: {1,3})?(`{3,}|~{3,}) *(\\S+)? *([^\\n]*?)?\\n([\\s\\S]*?)(?:\\1\\n?|$)/;\nexport const CODE_BLOCK_R = /^(?: {4}[^\\n]+\\n*)+(?:\\n *)+\\n?/;\n/** A single line opening or closing a fenced code block, with its indentation. */\nexport const FENCE_DELIMITER_R = /^([ \\t]*)(`{3,}|~{3,})/;\nexport const CODE_INLINE_R = /^(`+)((?:\\\\`|(?!\\1)`|[^`])+)\\1/;\n\n/** Newline patterns */\nexport const CONSECUTIVE_NEWLINE_R = /^(?:\\n *)*\\n/;\nexport const CR_NEWLINE_R = /\\r\\n?/g;\n\n/** Footnote patterns */\nexport const FOOTNOTE_R = /^\\[\\^([^\\]]+)](:(.*)((\\n+ {4,}.*)|(\\n(?!\\[\\^).+))*)/;\nexport const FOOTNOTE_REFERENCE_R = /^\\[\\^([^\\]]+)]/;\n\n/** Form feed */\nexport const FORMFEED_R = /\\f/g;\n\n/** Front matter */\nexport const FRONT_MATTER_R = /^---[ \\t]*\\n(.|\\n)*?\\n---[ \\t]*\\n/;\n\n/** GFM task */\nexport const GFM_TASK_R = /^\\s*?\\[(x|\\s)\\]/;\n\n/** Heading patterns */\nexport const HEADING_R = /^ *(#{1,6}) *([^\\n]+?)(?: +#*)?(?:\\n *)*(?:\\n|$)/;\nexport const HEADING_ATX_COMPLIANT_R =\n /^ *(#{1,6}) +([^\\n]+?)(?: +#*)?(?:\\n *)*(?:\\n|$)/;\nexport const HEADING_SETEXT_R = /^([^\\n]+)\\n *(=|-)\\2{2,} *\\n/;\n\n/** HTML patterns */\n\n/**\n * Run of characters carrying no meaning inside an opening tag: neither a quote\n * opening a value nor an angle bracket delimiting a tag.\n */\nconst TAG_PLAIN_RUN = `[^>\"'<]*`;\n\n/**\n * Quoted attribute value. It may hold an angle bracket —\n * `<Tab label='Intlayer >=9.4'>` — but not a line break, which keeps a tag that\n * turns out not to match from trying every later quote of the document as its\n * closing one.\n */\nconst TAG_QUOTED_VALUE = `\"[^\"\\\\n]*\"|'[^'\\\\n]*'`;\n\n/**\n * Attribute list of an opening tag, written as a plain run followed by\n * quote-or-bracket-led segments so that each character has a single way to be\n * read. A lone quote is allowed last so a tag holding an unbalanced one still\n * parses, as it did before quoted values were recognised.\n */\nconst TAG_ATTRIBUTES = `${TAG_PLAIN_RUN}(?:(?:${TAG_QUOTED_VALUE}|<.*?>|[\"'])${TAG_PLAIN_RUN})*`;\n\n/** Rejects the opening tag of a self-closing element, `<div class=\"a\"/>`. */\nconst NOT_SELF_CLOSING = `(?![^>]*/>)`;\n\n/**\n * Opening tag of a nested element bearing the same name as the outer one. This\n * one stays a plain scan up to the first `>`: it is tried at every character of\n * the element's content, and a richer pattern here costs an order of magnitude\n * on documents whose tag never closes.\n */\nconst NESTED_SAME_TAG_OPENING = `<\\\\1[^>]*?>`;\n\nexport const HTML_BLOCK_ELEMENT_R = new RegExp(\n `^ *(?!<[a-zA-Z][^ >/]* ?/>)<([a-zA-Z][^ >/]*) ?(${NOT_SELF_CLOSING}${TAG_ATTRIBUTES})>\\\\n?(\\\\s*(?:${NESTED_SAME_TAG_OPENING}[\\\\s\\\\S]*?</\\\\1>|(?!<\\\\1\\\\b)[\\\\s\\\\S])*?)</\\\\1>(?!</\\\\1>)\\\\n*`,\n 'i'\n);\nexport const HTML_CHAR_CODE_R =\n /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/gi;\nexport const HTML_COMMENT_R = /^<!--[\\s\\S]*?(?:-->)/;\nexport const HTML_CUSTOM_ATTR_R = /^(data|aria|x)-[a-z_][a-z\\d_.-]*$/;\nexport const HTML_SELF_CLOSING_ELEMENT_R = new RegExp(\n `^ *<([a-zA-Z][a-zA-Z0-9:]*)(?:\\\\s+(${TAG_ATTRIBUTES}))?/?>(?!</\\\\1>)(\\\\s*\\\\n)?`,\n 'i'\n);\n\n/** Custom component pattern */\nexport const CUSTOM_COMPONENT_R = new RegExp(\n `^ *<([A-Z][a-zA-Z0-9]*)(?:\\\\s+(${TAG_ATTRIBUTES}))?>\\\\n?(\\\\s*(?:${NESTED_SAME_TAG_OPENING}[\\\\s\\\\S]*?</\\\\1>|(?!<\\\\1\\\\b)[\\\\s\\\\S])*?)</\\\\1>(?!</\\\\1>)\\\\n*`\n);\n\n/** Interpolation */\nexport const INTERPOLATION_R = /^\\{.*\\}$/;\n\n/** Link patterns */\nexport const LINK_AUTOLINK_BARE_URL_R = /^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/;\nexport const LINK_AUTOLINK_R = /^<([^ >]+[:@/][^ >]+)>/;\nexport const CAPTURE_LETTER_AFTER_HYPHEN = /-([a-z])?/gi;\n\n/** Table patterns */\nexport const NP_TABLE_R =\n /^(\\|.*)\\n(?: *(\\|? *[-:]+ *\\|[-| :]*)\\n((?:.*\\|.*\\n)*))?\\n?/;\nexport const TABLE_TRIM_PIPES = /(^ *\\||\\| *$)/g;\nexport const TABLE_CENTER_ALIGN = /^ *:-+: *$/;\nexport const TABLE_LEFT_ALIGN = /^ *:-+ *$/;\nexport const TABLE_RIGHT_ALIGN = /^ *-+: *$/;\n\n/** Paragraph */\nexport const PARAGRAPH_R = /^[^\\n]+(?: {2}\\n|\\n{2,})/;\n\n/** Reference patterns */\nexport const REFERENCE_IMAGE_OR_LINK =\n /^\\[([^\\]]*)\\]:\\s+<?([^\\s>]+)>?\\s*(\"([^\"]*)\")?/;\nexport const REFERENCE_IMAGE_R = /^!\\[([^\\]]*)\\] ?\\[([^\\]]*)\\]/;\nexport const REFERENCE_LINK_R = /^\\[([^\\]]*)\\] ?\\[([^\\]]*)\\]/;\n\n/**\n * Cheap prefix probes used to reject a rule before its full (and far more\n * expensive) block regex runs. Kept as module constants so the parser's inner\n * loop never allocates a `RegExp` per candidate position.\n */\nexport const HTML_BLOCK_OPENING_TAG_R = /^ *<([a-z][a-z0-9:-]*)\\b/i;\nexport const HTML_SELF_CLOSING_OPENING_TAG_R =\n /^ *<([a-zA-Z][a-zA-Z0-9:]*)[\\s>/]/;\nexport const CUSTOM_COMPONENT_OPENING_TAG_R = /^ *<([A-Z][a-zA-Z0-9]*)/;\n\n/** Block detection */\nexport const SHOULD_RENDER_AS_BLOCK_R = /(\\n|^[-*]\\s|^#|^ {2,}|^-{2,}|^>\\s)/;\n\n/** Tab and whitespace */\nexport const TAB_R = /\\t/g;\n/** Every character `normalizeWhitespace` rewrites, so it needs a single pass. */\nexport const NORMALIZE_WHITESPACE_R = /\\r\\n?|\\f|\\t/g;\nexport const TRIM_STARTING_NEWLINES = /^\\n+/;\nexport const HTML_LEFT_TRIM_AMOUNT_R = /^\\n*([ \\t]*)/;\n\n/** List patterns */\nexport const ORDERED_LIST_BULLET = '(?:\\\\d+\\\\.)';\nexport const UNORDERED_LIST_BULLET = '(?:[*+-])';\n\n/** Text formatting patterns */\nexport const TEXT_ESCAPED_R = /^\\\\([^0-9A-Za-z\\s])/;\nexport const UNESCAPE_R = /\\\\([^0-9A-Za-z\\s])/g;\nexport const TEXT_PLAIN_R =\n /^[\\s\\S](?:(?! {2}\\n|[0-9]\\.|http)[^=*_~\\-\\n:<`\\\\[!])*/;\n\n/** Shortcode pattern */\nexport const SHORTCODE_R = /^(:[a-zA-Z0-9-_]+:)/;\n\n// ============================================================================\n// LIST TYPE CONSTANTS\n// ============================================================================\n\nexport type ListType = 1 | 2;\nexport const ORDERED: ListType = 1;\nexport const UNORDERED: ListType = 2;\n\n// ============================================================================\n// INLINE PATTERN HELPERS\n// ============================================================================\n\n/**\n * Ensure there's at least one more instance of the delimiter later\n * in the current sequence.\n */\nexport const LOOKAHEAD = (double: number): string =>\n `(?=[\\\\s\\\\S]+?\\\\1${double ? '\\\\1' : ''})`;\n\n/**\n * For inline formatting, this partial attempts to ignore characters that\n * may appear in nested formatting.\n */\nexport const INLINE_SKIP_R =\n '((?:\\\\[.*?\\\\][([].*?[)\\\\]]|<.*?>(?:.*?<.*?>)?|`.*?`|\\\\\\\\[^\\\\s]|[\\\\s\\\\S])+?)';\n\n/** Bold text pattern */\nexport const TEXT_BOLD_R = new RegExp(\n `^([*_])\\\\1${LOOKAHEAD(1)}${INLINE_SKIP_R}\\\\1\\\\1(?!\\\\1)`\n);\n\n/** Emphasized text pattern */\nexport const TEXT_EMPHASIZED_R = new RegExp(\n `^([*_])${LOOKAHEAD(0)}${INLINE_SKIP_R}\\\\1(?!\\\\1)`\n);\n\n/** Marked text pattern */\nexport const TEXT_MARKED_R = new RegExp(\n `^(==)${LOOKAHEAD(0)}${INLINE_SKIP_R}\\\\1`\n);\n\n/** Strikethrough text pattern */\nexport const TEXT_STRIKETHROUGHED_R = new RegExp(\n `^(~~)${LOOKAHEAD(0)}${INLINE_SKIP_R}\\\\1`\n);\n\n// ============================================================================\n// LIST REGEX GENERATORS\n// ============================================================================\n\nexport const generateListItemPrefix = (type: ListType): string => {\n return (\n '( *)(' +\n (type === ORDERED ? ORDERED_LIST_BULLET : UNORDERED_LIST_BULLET) +\n ') +'\n );\n};\n\nexport const ORDERED_LIST_ITEM_PREFIX = generateListItemPrefix(ORDERED);\nexport const UNORDERED_LIST_ITEM_PREFIX = generateListItemPrefix(UNORDERED);\n\nexport const generateListItemPrefixRegex = (type: ListType): RegExp => {\n return new RegExp(\n '^' +\n (type === ORDERED ? ORDERED_LIST_ITEM_PREFIX : UNORDERED_LIST_ITEM_PREFIX)\n );\n};\n\nexport const ORDERED_LIST_ITEM_PREFIX_R = generateListItemPrefixRegex(ORDERED);\nexport const UNORDERED_LIST_ITEM_PREFIX_R =\n generateListItemPrefixRegex(UNORDERED);\n\nexport const generateListItemRegex = (type: ListType): RegExp => {\n return new RegExp(\n '^' +\n (type === ORDERED\n ? ORDERED_LIST_ITEM_PREFIX\n : UNORDERED_LIST_ITEM_PREFIX) +\n '[^\\\\n]*(?:\\\\n' +\n '(?!\\\\1' +\n (type === ORDERED ? ORDERED_LIST_BULLET : UNORDERED_LIST_BULLET) +\n ' )[^\\\\n]*)*(\\\\n|$)',\n 'gm'\n );\n};\n\nexport const ORDERED_LIST_ITEM_R = generateListItemRegex(ORDERED);\nexport const UNORDERED_LIST_ITEM_R = generateListItemRegex(UNORDERED);\n\nexport const generateListRegex = (type: ListType): RegExp => {\n const bullet = type === ORDERED ? ORDERED_LIST_BULLET : UNORDERED_LIST_BULLET;\n\n return new RegExp(\n '^( *)(' +\n bullet +\n ') ' +\n '[\\\\s\\\\S]+?(?:\\\\n{2,}(?! )' +\n '(?!\\\\1' +\n bullet +\n ' (?!' +\n bullet +\n ' ))\\\\n*' +\n '|\\\\s*\\\\n*$)'\n );\n};\n\nexport const ORDERED_LIST_R = generateListRegex(ORDERED);\nexport const UNORDERED_LIST_R = generateListRegex(UNORDERED);\n"],"mappings":"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"}
@@ -23,9 +23,9 @@ exports.CODE_BLOCK_R = require_markdown_constants.CODE_BLOCK_R;
23
23
  exports.CODE_INLINE_R = require_markdown_constants.CODE_INLINE_R;
24
24
  exports.CONSECUTIVE_NEWLINE_R = require_markdown_constants.CONSECUTIVE_NEWLINE_R;
25
25
  exports.CR_NEWLINE_R = require_markdown_constants.CR_NEWLINE_R;
26
+ exports.CUSTOM_COMPONENT_OPENING_TAG_R = require_markdown_constants.CUSTOM_COMPONENT_OPENING_TAG_R;
26
27
  exports.CUSTOM_COMPONENT_R = require_markdown_constants.CUSTOM_COMPONENT_R;
27
28
  exports.DO_NOT_PROCESS_HTML_ELEMENTS = require_markdown_constants.DO_NOT_PROCESS_HTML_ELEMENTS;
28
- exports.DURATION_DELAY_TRIGGER = require_markdown_constants.DURATION_DELAY_TRIGGER;
29
29
  exports.FENCE_DELIMITER_R = require_markdown_constants.FENCE_DELIMITER_R;
30
30
  exports.FOOTNOTE_R = require_markdown_constants.FOOTNOTE_R;
31
31
  exports.FOOTNOTE_REFERENCE_R = require_markdown_constants.FOOTNOTE_REFERENCE_R;
@@ -36,18 +36,20 @@ exports.HEADING_ATX_COMPLIANT_R = require_markdown_constants.HEADING_ATX_COMPLIA
36
36
  exports.HEADING_R = require_markdown_constants.HEADING_R;
37
37
  exports.HEADING_SETEXT_R = require_markdown_constants.HEADING_SETEXT_R;
38
38
  exports.HTML_BLOCK_ELEMENT_R = require_markdown_constants.HTML_BLOCK_ELEMENT_R;
39
+ exports.HTML_BLOCK_OPENING_TAG_R = require_markdown_constants.HTML_BLOCK_OPENING_TAG_R;
39
40
  exports.HTML_CHAR_CODE_R = require_markdown_constants.HTML_CHAR_CODE_R;
40
41
  exports.HTML_COMMENT_R = require_markdown_constants.HTML_COMMENT_R;
41
42
  exports.HTML_CUSTOM_ATTR_R = require_markdown_constants.HTML_CUSTOM_ATTR_R;
42
43
  exports.HTML_LEFT_TRIM_AMOUNT_R = require_markdown_constants.HTML_LEFT_TRIM_AMOUNT_R;
43
44
  exports.HTML_SELF_CLOSING_ELEMENT_R = require_markdown_constants.HTML_SELF_CLOSING_ELEMENT_R;
45
+ exports.HTML_SELF_CLOSING_OPENING_TAG_R = require_markdown_constants.HTML_SELF_CLOSING_OPENING_TAG_R;
44
46
  exports.INLINE_SKIP_R = require_markdown_constants.INLINE_SKIP_R;
45
47
  exports.INTERPOLATION_R = require_markdown_constants.INTERPOLATION_R;
46
48
  exports.LINK_AUTOLINK_BARE_URL_R = require_markdown_constants.LINK_AUTOLINK_BARE_URL_R;
47
49
  exports.LINK_AUTOLINK_R = require_markdown_constants.LINK_AUTOLINK_R;
48
- exports.LIST_LOOKBEHIND_R = require_markdown_constants.LIST_LOOKBEHIND_R;
49
50
  exports.LOOKAHEAD = require_markdown_constants.LOOKAHEAD;
50
51
  exports.NAMED_CODES_TO_UNICODE = require_markdown_constants.NAMED_CODES_TO_UNICODE;
52
+ exports.NORMALIZE_WHITESPACE_R = require_markdown_constants.NORMALIZE_WHITESPACE_R;
51
53
  exports.NP_TABLE_R = require_markdown_constants.NP_TABLE_R;
52
54
  exports.ORDERED = require_markdown_constants.ORDERED;
53
55
  exports.ORDERED_LIST_BULLET = require_markdown_constants.ORDERED_LIST_BULLET;
@@ -1,8 +1,54 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_markdown_constants = require('./constants.cjs');
3
2
  const require_markdown_utils = require('./utils.cjs');
4
3
 
5
4
  //#region src/markdown/parser.ts
5
+ const ruleOrderCache = /* @__PURE__ */ new Map();
6
+ const sameNames = (a, b) => {
7
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
8
+ return true;
9
+ };
10
+ /**
11
+ * Resolves `Object.keys(rules)` into precedence order, sorting only the first
12
+ * time a given rule set is seen.
13
+ */
14
+ const orderRules = (names, rules) => {
15
+ const candidates = ruleOrderCache.get(names.length);
16
+ if (candidates) {
17
+ for (let i = 0; i < candidates.length; i++) if (sameNames(names, candidates[i].names)) return candidates[i].order;
18
+ }
19
+ const order = names.slice().sort((a, b) => rules[a]._order - rules[b]._order || +a - +b);
20
+ const entry = {
21
+ names: names.slice(),
22
+ order
23
+ };
24
+ if (candidates) candidates.push(entry);
25
+ else ruleOrderCache.set(names.length, [entry]);
26
+ return order;
27
+ };
28
+ /**
29
+ * Advance the incremental lookbehind carried on the parse state.
30
+ *
31
+ * Rules only ever ask two questions about the source already consumed: how far
32
+ * the current line is indented (`prevCaptureIndent`) and whether a blank line
33
+ * has been seen (`prevCaptureHasBlankLine`). Both are maintained in time
34
+ * proportional to the capture rather than by concatenating — and later
35
+ * rescanning — the whole document, which made parsing quadratic.
36
+ */
37
+ const advanceLookbehind = (state, capture) => {
38
+ const newlineIndex = capture.lastIndexOf("\n");
39
+ const hasPrevCapture = state.prevCaptureHasBlankLine !== void 0;
40
+ if (state.prevCaptureHasBlankLine !== true) state.prevCaptureHasBlankLine = capture.indexOf("\n\n") !== -1 || hasPrevCapture && capture.charCodeAt(0) === 10 && state.prevCaptureIndent === "";
41
+ const tail = newlineIndex === -1 ? state.prevCaptureIndent === void 0 ? void 0 : state.prevCaptureIndent + capture : capture.slice(newlineIndex + 1);
42
+ if (tail === void 0 || tail === "") {
43
+ state.prevCaptureIndent = tail;
44
+ return;
45
+ }
46
+ for (let i = 0; i < tail.length; i++) if (tail.charCodeAt(i) !== 32) {
47
+ state.prevCaptureIndent = void 0;
48
+ return;
49
+ }
50
+ state.prevCaptureIndent = tail;
51
+ };
6
52
  /**
7
53
  * Creates a parser for a given set of rules, with the precedence
8
54
  * specified as a list of rules.
@@ -13,60 +59,40 @@ const require_markdown_utils = require('./utils.cjs');
13
59
  * @returns The resulting parse function
14
60
  */
15
61
  const parserFor = (rules) => {
16
- const start = performance.now();
17
62
  const ruleList = Object.keys(rules);
18
63
  if (process.env.NODE_ENV !== "production") ruleList.forEach((type) => {
19
64
  const order = rules[type]?._order;
20
65
  if (typeof order !== "number" || !Number.isFinite(order)) console.warn(`intlayer: Invalid order for rule \`${type}\`: ${order}`);
21
66
  });
22
- ruleList.sort((a, b) => {
23
- return rules[a]._order - rules[b]._order || +a - +b;
24
- });
67
+ const order = orderRules(ruleList, rules);
68
+ const ruleCount = order.length;
69
+ const qualifiers = new Array(ruleCount);
70
+ const matchers = new Array(ruleCount);
71
+ const parsers = new Array(ruleCount);
72
+ for (let i = 0; i < ruleCount; i++) {
73
+ const rule = rules[order[i]];
74
+ qualifiers[i] = rule._qualify;
75
+ matchers[i] = rule._match;
76
+ parsers[i] = rule._parse;
77
+ }
25
78
  const nestedParse = (source, state = {}) => {
26
- const parseStart = performance.now();
27
79
  const result = [];
28
- state.prevCapture = state.prevCapture || "";
29
- if (source.trim()) while (source) {
30
- let i = 0;
31
- while (i < ruleList.length) {
32
- const ruleType = ruleList[i];
33
- const rule = rules[ruleType];
34
- if (rule?._qualify && !require_markdown_utils.qualifies(source, state, rule._qualify)) {
35
- i++;
36
- continue;
37
- }
38
- const matchStart = performance.now();
39
- const capture = rule?._match(source, state);
40
- if (process.env.NODE_ENV !== "production") {
41
- const matchDuration = performance.now() - matchStart;
42
- if (matchDuration > 1) console.log(`${ruleType}._match: ${matchDuration.toFixed(3)}ms, source length: ${source.length}`);
43
- }
44
- if (capture?.[0]) {
45
- source = source.substring(capture[0].length);
46
- const ruleParseStart = performance.now();
47
- const parsedAny = rule?._parse(capture, nestedParse, state);
48
- if (process.env.NODE_ENV !== "production") {
49
- const ruleParseDuration = performance.now() - ruleParseStart;
50
- if (ruleParseDuration > 1) console.log(`${ruleType}._parse: ${ruleParseDuration.toFixed(3)}ms, capture length: ${capture[0].length}`);
51
- }
52
- state.prevCapture = (state.prevCapture || "") + capture[0];
53
- if (!parsedAny.type) parsedAny.type = ruleType;
54
- result.push(parsedAny);
55
- break;
56
- }
57
- i++;
80
+ if (state.prevCaptureHasBlankLine === void 0) state.prevCaptureIndent = "";
81
+ if (source.trim()) while (source) for (let i = 0; i < ruleCount; i++) {
82
+ const qualify = qualifiers[i];
83
+ if (qualify && !require_markdown_utils.qualifies(source, state, qualify)) continue;
84
+ const capture = matchers[i](source, state);
85
+ if (capture?.[0]) {
86
+ source = source.substring(capture[0].length);
87
+ const parsed = parsers[i](capture, nestedParse, state);
88
+ advanceLookbehind(state, capture[0]);
89
+ if (!parsed.type) parsed.type = order[i];
90
+ result.push(parsed);
91
+ break;
58
92
  }
59
93
  }
60
- if (process.env.NODE_ENV === "development") {
61
- const parseDuration = performance.now() - parseStart;
62
- if (parseDuration > 1) console.log(`nestedParse: ${parseDuration.toFixed(3)}ms, source length: ${source.length}, result count: ${result.length}`);
63
- }
64
94
  return result;
65
95
  };
66
- if (process.env.NODE_ENV === "development") {
67
- const duration = performance.now() - start;
68
- if (duration > 20) console.log(`parserFor: ${duration.toFixed(3)}ms, rules count: ${ruleList.length}`);
69
- }
70
96
  return (source, state) => nestedParse(require_markdown_utils.normalizeWhitespace(source), state);
71
97
  };
72
98
 
@@ -1 +1 @@
1
- {"version":3,"file":"parser.cjs","names":["qualifies","normalizeWhitespace"],"sources":["../../../src/markdown/parser.ts"],"sourcesContent":["import { DURATION_DELAY_TRIGGER } from './constants';\nimport type { NestedParser, ParserResult, ParseState, Rules } from './types';\nimport { normalizeWhitespace, qualifies } from './utils';\n\n/**\n * Creates a parser for a given set of rules, with the precedence\n * specified as a list of rules.\n *\n * @param rules - An object containing rule type -> {match, order, parse} objects\n * (lower order is higher precedence)\n *\n * @returns The resulting parse function\n */\nexport const parserFor = (\n rules: Rules\n): ((source: string, state: ParseState) => ParserResult[]) => {\n const start = performance.now();\n const ruleList = Object.keys(rules);\n\n if (process.env.NODE_ENV !== 'production') {\n ruleList.forEach((type) => {\n const order = rules[type]?._order;\n if (typeof order !== 'number' || !Number.isFinite(order)) {\n console.warn(`intlayer: Invalid order for rule \\`${type}\\`: ${order}`);\n }\n });\n }\n\n // Sorts rules in order of increasing order, then\n // ascending rule name (numeric) in case of ties.\n // RuleType keys are string numbers — use numeric comparison to preserve\n // intended ordering (e.g. codeFenced '4' must precede headingSetext '10').\n ruleList.sort((a, b) => {\n return rules[a]!._order - rules[b]!._order || +a - +b;\n });\n\n const nestedParse: NestedParser = (\n source: string,\n state: ParseState = {}\n ): ParserResult[] => {\n const parseStart = performance.now();\n const result: ParserResult[] = [];\n state.prevCapture = state.prevCapture || '';\n\n if (source.trim()) {\n while (source) {\n let i = 0;\n while (i < ruleList.length) {\n const ruleType = ruleList[i];\n const rule = rules[ruleType as keyof typeof rules];\n\n if (rule?._qualify && !qualifies(source, state, rule._qualify)) {\n i++;\n continue;\n }\n\n const matchStart = performance.now();\n const capture = rule?._match(source, state);\n\n if (process.env.NODE_ENV !== 'production') {\n const matchDuration = performance.now() - matchStart;\n if (matchDuration > 1) {\n console.log(\n `${ruleType}._match: ${matchDuration.toFixed(3)}ms, source length: ${source.length}`\n );\n }\n }\n\n if (capture?.[0]) {\n source = source.substring(capture[0].length);\n\n const ruleParseStart = performance.now();\n const parsedAny: any = rule?._parse(capture, nestedParse, state);\n\n if (process.env.NODE_ENV !== 'production') {\n const ruleParseDuration = performance.now() - ruleParseStart;\n if (ruleParseDuration > 1) {\n console.log(\n `${ruleType}._parse: ${ruleParseDuration.toFixed(3)}ms, capture length: ${capture[0].length}`\n );\n }\n }\n\n state.prevCapture = (state.prevCapture || '') + capture[0];\n\n if (!parsedAny.type) {\n parsedAny.type = ruleType;\n }\n result.push(parsedAny as ParserResult);\n break;\n }\n i++;\n }\n }\n }\n\n // Tree shakeable log for prod\n if (process.env.NODE_ENV === 'development') {\n const parseDuration = performance.now() - parseStart;\n if (parseDuration > 1) {\n console.log(\n `nestedParse: ${parseDuration.toFixed(3)}ms, source length: ${source.length}, result count: ${result.length}`\n );\n }\n }\n\n return result;\n };\n\n // Tree shakeable log for prod\n if (process.env.NODE_ENV === 'development') {\n const duration = performance.now() - start;\n\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parserFor: ${duration.toFixed(3)}ms, rules count: ${ruleList.length}`\n );\n }\n }\n\n return (source: string, state: ParseState) =>\n nestedParse(normalizeWhitespace(source), state);\n};\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,aACX,UAC4D;CAC5D,MAAM,QAAQ,YAAY,IAAI;CAC9B,MAAM,WAAW,OAAO,KAAK,KAAK;CAElC,IAAI,QAAQ,IAAI,aAAa,cAC3B,SAAS,SAAS,SAAS;EACzB,MAAM,QAAQ,MAAM,KAAK,EAAE;EAC3B,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,GACrD,QAAQ,KAAK,sCAAsC,KAAK,MAAM,OAAO;CAEzE,CAAC;CAOH,SAAS,MAAM,GAAG,MAAM;EACtB,OAAO,MAAM,EAAE,CAAE,SAAS,MAAM,EAAE,CAAE,UAAU,CAAC,IAAI,CAAC;CACtD,CAAC;CAED,MAAM,eACJ,QACA,QAAoB,CAAC,MACF;EACnB,MAAM,aAAa,YAAY,IAAI;EACnC,MAAM,SAAyB,CAAC;EAChC,MAAM,cAAc,MAAM,eAAe;EAEzC,IAAI,OAAO,KAAK,GACd,OAAO,QAAQ;GACb,IAAI,IAAI;GACR,OAAO,IAAI,SAAS,QAAQ;IAC1B,MAAM,WAAW,SAAS;IAC1B,MAAM,OAAO,MAAM;IAEnB,IAAI,MAAM,YAAY,CAACA,iCAAU,QAAQ,OAAO,KAAK,QAAQ,GAAG;KAC9D;KACA;IACF;IAEA,MAAM,aAAa,YAAY,IAAI;IACnC,MAAM,UAAU,MAAM,OAAO,QAAQ,KAAK;IAE1C,IAAI,QAAQ,IAAI,aAAa,cAAc;KACzC,MAAM,gBAAgB,YAAY,IAAI,IAAI;KAC1C,IAAI,gBAAgB,GAClB,QAAQ,IACN,GAAG,SAAS,WAAW,cAAc,QAAQ,CAAC,EAAE,qBAAqB,OAAO,QAC9E;IAEJ;IAEA,IAAI,UAAU,IAAI;KAChB,SAAS,OAAO,UAAU,QAAQ,EAAE,CAAC,MAAM;KAE3C,MAAM,iBAAiB,YAAY,IAAI;KACvC,MAAM,YAAiB,MAAM,OAAO,SAAS,aAAa,KAAK;KAE/D,IAAI,QAAQ,IAAI,aAAa,cAAc;MACzC,MAAM,oBAAoB,YAAY,IAAI,IAAI;MAC9C,IAAI,oBAAoB,GACtB,QAAQ,IACN,GAAG,SAAS,WAAW,kBAAkB,QAAQ,CAAC,EAAE,sBAAsB,QAAQ,EAAE,CAAC,QACvF;KAEJ;KAEA,MAAM,eAAe,MAAM,eAAe,MAAM,QAAQ;KAExD,IAAI,CAAC,UAAU,MACb,UAAU,OAAO;KAEnB,OAAO,KAAK,SAAyB;KACrC;IACF;IACA;GACF;EACF;EAIF,IAAI,QAAQ,IAAI,aAAa,eAAe;GAC1C,MAAM,gBAAgB,YAAY,IAAI,IAAI;GAC1C,IAAI,gBAAgB,GAClB,QAAQ,IACN,gBAAgB,cAAc,QAAQ,CAAC,EAAE,qBAAqB,OAAO,OAAO,kBAAkB,OAAO,QACvG;EAEJ;EAEA,OAAO;CACT;CAGA,IAAI,QAAQ,IAAI,aAAa,eAAe;EAC1C,MAAM,WAAW,YAAY,IAAI,IAAI;EAErC,IAAI,eACF,QAAQ,IACN,cAAc,SAAS,QAAQ,CAAC,EAAE,mBAAmB,SAAS,QAChE;CAEJ;CAEA,QAAQ,QAAgB,UACtB,YAAYC,2CAAoB,MAAM,GAAG,KAAK;AAClD"}
1
+ {"version":3,"file":"parser.cjs","names":["qualifies","normalizeWhitespace"],"sources":["../../../src/markdown/parser.ts"],"sourcesContent":["import type {\n NestedParser,\n ParserResult,\n ParseState,\n Rule,\n Rules,\n} from './types';\nimport { normalizeWhitespace, qualifies } from './utils';\n\n/**\n * Cached rule precedence, grouped by rule count.\n *\n * A rule's `_order` never varies, so the precedence a rule set sorts into is a\n * pure function of which rules it holds. Rules themselves are rebuilt per\n * document, so the cache is keyed by rule names rather than by object identity,\n * and grouped by count to keep the comparison short.\n */\ntype RuleOrderEntry = { names: string[]; order: string[] };\n\nconst ruleOrderCache = new Map<number, RuleOrderEntry[]>();\n\nconst sameNames = (a: string[], b: string[]): boolean => {\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n\n return true;\n};\n\n/**\n * Resolves `Object.keys(rules)` into precedence order, sorting only the first\n * time a given rule set is seen.\n */\nconst orderRules = (names: string[], rules: Rules): string[] => {\n const candidates = ruleOrderCache.get(names.length);\n\n if (candidates) {\n for (let i = 0; i < candidates.length; i++) {\n if (sameNames(names, candidates[i]!.names)) return candidates[i]!.order;\n }\n }\n\n // Sorts rules in order of increasing order, then\n // ascending rule name (numeric) in case of ties.\n // RuleType keys are string numbers — use numeric comparison to preserve\n // intended ordering (e.g. codeFenced '4' must precede headingSetext '10').\n const order = names\n .slice()\n .sort((a, b) => rules[a]!._order - rules[b]!._order || +a - +b);\n\n const entry: RuleOrderEntry = { names: names.slice(), order };\n\n if (candidates) candidates.push(entry);\n else ruleOrderCache.set(names.length, [entry]);\n\n return order;\n};\n\n/**\n * Advance the incremental lookbehind carried on the parse state.\n *\n * Rules only ever ask two questions about the source already consumed: how far\n * the current line is indented (`prevCaptureIndent`) and whether a blank line\n * has been seen (`prevCaptureHasBlankLine`). Both are maintained in time\n * proportional to the capture rather than by concatenating — and later\n * rescanning — the whole document, which made parsing quadratic.\n */\nconst advanceLookbehind = (state: ParseState, capture: string): void => {\n const newlineIndex = capture.lastIndexOf('\\n');\n // `undefined` marks a lookbehind nothing has been appended to yet, which is\n // the only way to tell an empty lookbehind from one ending on a line break.\n const hasPrevCapture = state.prevCaptureHasBlankLine !== undefined;\n\n if (state.prevCaptureHasBlankLine !== true) {\n state.prevCaptureHasBlankLine =\n capture.indexOf('\\n\\n') !== -1 ||\n // A capture opening on a line break closes a blank line when the\n // lookbehind already ended on one.\n (hasPrevCapture &&\n capture.charCodeAt(0) === 10 /* \\n */ &&\n state.prevCaptureIndent === '');\n }\n\n // Everything after the final newline forms the current line. With no newline\n // in the capture, the current line simply grew by `capture`.\n const tail =\n newlineIndex === -1\n ? state.prevCaptureIndent === undefined\n ? undefined\n : state.prevCaptureIndent + capture\n : capture.slice(newlineIndex + 1);\n\n if (tail === undefined || tail === '') {\n state.prevCaptureIndent = tail;\n return;\n }\n\n for (let i = 0; i < tail.length; i++) {\n if (tail.charCodeAt(i) !== 32 /* space */) {\n state.prevCaptureIndent = undefined;\n return;\n }\n }\n\n state.prevCaptureIndent = tail;\n};\n\n/**\n * Creates a parser for a given set of rules, with the precedence\n * specified as a list of rules.\n *\n * @param rules - An object containing rule type -> {match, order, parse} objects\n * (lower order is higher precedence)\n *\n * @returns The resulting parse function\n */\nexport const parserFor = (\n rules: Rules\n): ((source: string, state: ParseState) => ParserResult[]) => {\n const ruleList = Object.keys(rules);\n\n if (process.env.NODE_ENV !== 'production') {\n ruleList.forEach((type) => {\n const order = rules[type]?._order;\n if (typeof order !== 'number' || !Number.isFinite(order)) {\n console.warn(`intlayer: Invalid order for rule \\`${type}\\`: ${order}`);\n }\n });\n }\n\n const order = orderRules(ruleList, rules);\n const ruleCount = order.length;\n\n // Rule objects have heterogeneous shapes (`_qualify` and `_render` are both\n // optional), so their members are hoisted into parallel arrays: the hot loop\n // then reads monomorphic slots instead of polymorphic properties, and the\n // whole set costs three allocations rather than one wrapper per rule.\n const qualifiers: (Rule<any>['_qualify'] | undefined)[] = new Array(\n ruleCount\n );\n const matchers: Rule<any>['_match'][] = new Array(ruleCount);\n const parsers: Rule<any>['_parse'][] = new Array(ruleCount);\n\n for (let i = 0; i < ruleCount; i++) {\n const rule = rules[order[i]!]!;\n\n qualifiers[i] = rule._qualify;\n matchers[i] = rule._match;\n parsers[i] = rule._parse;\n }\n\n const nestedParse: NestedParser = (\n source: string,\n state: ParseState = {}\n ): ParserResult[] => {\n const result: ParserResult[] = [];\n\n if (state.prevCaptureHasBlankLine === undefined) {\n // Nothing consumed yet: an empty lookbehind sits at the start of a line.\n state.prevCaptureIndent = '';\n }\n\n if (source.trim()) {\n while (source) {\n for (let i = 0; i < ruleCount; i++) {\n const qualify = qualifiers[i];\n\n if (qualify && !qualifies(source, state, qualify)) continue;\n\n const capture = matchers[i]!(source, state);\n\n if (capture?.[0]) {\n source = source.substring(capture[0].length);\n\n const parsed: any = parsers[i]!(capture, nestedParse, state);\n\n advanceLookbehind(state, capture[0]);\n\n if (!parsed.type) {\n parsed.type = order[i];\n }\n\n result.push(parsed as ParserResult);\n break;\n }\n }\n }\n }\n\n return result;\n };\n\n return (source: string, state: ParseState) =>\n nestedParse(normalizeWhitespace(source), state);\n};\n"],"mappings":"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"}
@@ -1,6 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_markdown_constants = require('./constants.cjs');
3
-
4
2
  //#region src/markdown/renderer.ts
5
3
  /**
6
4
  * Creates a renderer for AST nodes.
@@ -9,16 +7,15 @@ const require_markdown_constants = require('./constants.cjs');
9
7
  * @param render - The render function to call for each node
10
8
  * @returns A function that renders AST to output
11
9
  */
12
- const renderFor = (render) => (ast, state = {}) => {
13
- const start = performance.now();
14
- const patchedRender = (ast, state = {}) => renderFor(render)(ast, state);
15
- if (Array.isArray(ast)) {
10
+ const renderFor = (render) => {
11
+ const emit = (ast, state = {}) => {
12
+ if (!Array.isArray(ast)) return render(ast, emit, state);
16
13
  const oldKey = state.key;
17
14
  const result = [];
18
15
  let lastWasString = false;
19
16
  let renderedIndex = 0;
20
17
  for (let i = 0; i < ast.length; i++) {
21
- const nodeOut = patchedRender(ast[i], {
18
+ const nodeOut = emit(ast[i], {
22
19
  ...state,
23
20
  key: renderedIndex
24
21
  });
@@ -31,14 +28,9 @@ const renderFor = (render) => (ast, state = {}) => {
31
28
  lastWasString = isString;
32
29
  }
33
30
  state.key = oldKey;
34
- const duration = performance.now() - start;
35
- if (duration > 20) console.log(`renderFor (array): ${duration.toFixed(3)}ms, ast length: ${ast.length}`);
36
31
  return result;
37
- }
38
- const result = render(ast, patchedRender, state);
39
- const duration = performance.now() - start;
40
- if (duration > 20) console.log(`renderFor (single): ${duration.toFixed(3)}ms, ast type: ${ast.type}`);
41
- return result;
32
+ };
33
+ return emit;
42
34
  };
43
35
  /**
44
36
  * Creates a renderer from rules with optional custom render hook.
@@ -48,12 +40,8 @@ const renderFor = (render) => (ast, state = {}) => {
48
40
  * @returns A render function for AST nodes
49
41
  */
50
42
  const createRenderer = (rules, userRender) => (ast, render, state) => {
51
- const start = performance.now();
52
43
  const renderer = rules[ast.type]?._render;
53
- const result = userRender ? userRender(() => renderer?.(ast, render, state), ast, render, state) : renderer?.(ast, render, state);
54
- const duration = performance.now() - start;
55
- if (duration > 20) console.log(`createRenderer: ${duration.toFixed(3)}ms, ast type: ${ast.type}, hasUserRender: ${!!userRender}`);
56
- return result;
44
+ return userRender ? userRender(() => renderer?.(ast, render, state), ast, render, state) : renderer?.(ast, render, state);
57
45
  };
58
46
 
59
47
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.cjs","names":[],"sources":["../../../src/markdown/renderer.ts"],"sourcesContent":["import { DURATION_DELAY_TRIGGER } from './constants';\nimport type {\n ParserResult,\n ParseState,\n RenderRuleHook,\n RuleOutput,\n Rules,\n} from './types';\n\n/**\n * Creates a renderer for AST nodes.\n * Renamed from `reactFor` to be framework-agnostic.\n *\n * @param render - The render function to call for each node\n * @returns A function that renders AST to output\n */\nexport const renderFor =\n (\n render: (\n ast: ParserResult,\n render: RuleOutput,\n state: ParseState\n ) => unknown\n ) =>\n (ast: ParserResult | ParserResult[], state: ParseState = {}): any => {\n const start = performance.now();\n\n const patchedRender = (\n ast: ParserResult | ParserResult[],\n state: ParseState = {}\n ): any => renderFor(render)(ast, state);\n\n if (Array.isArray(ast)) {\n const oldKey = state.key;\n const result: any[] = [];\n\n // map nestedOutput over the ast, except group any text\n // nodes together into a single string output.\n let lastWasString = false;\n let renderedIndex = 0;\n\n for (let i = 0; i < ast.length; i++) {\n // We clone the state to avoid side effects on other nodes in the same level\n // while ensuring each non-null rendered node gets a unique, sequential key.\n const nodeOut = patchedRender(ast[i], { ...state, key: renderedIndex });\n const isString = typeof nodeOut === 'string';\n\n if (isString && lastWasString) {\n result[result.length - 1] =\n (result[result.length - 1] as string) + nodeOut;\n } else if (nodeOut !== null) {\n result.push(nodeOut);\n renderedIndex++;\n }\n\n lastWasString = isString;\n }\n\n state.key = oldKey;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `renderFor (array): ${duration.toFixed(3)}ms, ast length: ${ast.length}`\n );\n }\n\n return result;\n }\n\n const result = render(ast, patchedRender as RuleOutput, state);\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `renderFor (single): ${duration.toFixed(3)}ms, ast type: ${(ast as ParserResult).type}`\n );\n }\n\n return result;\n };\n\n/**\n * Creates a renderer from rules with optional custom render hook.\n *\n * @param rules - The rules object containing _render functions\n * @param userRender - Optional custom render hook for full control\n * @returns A render function for AST nodes\n */\nexport const createRenderer =\n (rules: Rules, userRender?: RenderRuleHook) =>\n (ast: ParserResult, render: RuleOutput, state: ParseState): unknown => {\n const start = performance.now();\n const renderer = rules[ast.type]?._render;\n\n const result = userRender\n ? userRender(() => renderer?.(ast, render, state), ast, render, state)\n : renderer?.(ast, render, state);\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `createRenderer: ${duration.toFixed(3)}ms, ast type: ${ast.type}, hasUserRender: ${!!userRender}`\n );\n }\n\n return result;\n };\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,aAET,YAMD,KAAoC,QAAoB,CAAC,MAAW;CACnE,MAAM,QAAQ,YAAY,IAAI;CAE9B,MAAM,iBACJ,KACA,QAAoB,CAAC,MACb,UAAU,MAAM,CAAC,CAAC,KAAK,KAAK;CAEtC,IAAI,MAAM,QAAQ,GAAG,GAAG;EACtB,MAAM,SAAS,MAAM;EACrB,MAAM,SAAgB,CAAC;EAIvB,IAAI,gBAAgB;EACpB,IAAI,gBAAgB;EAEpB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;GAGnC,MAAM,UAAU,cAAc,IAAI,IAAI;IAAE,GAAG;IAAO,KAAK;GAAc,CAAC;GACtE,MAAM,WAAW,OAAO,YAAY;GAEpC,IAAI,YAAY,eACd,OAAO,OAAO,SAAS,KACpB,OAAO,OAAO,SAAS,KAAgB;QACrC,IAAI,YAAY,MAAM;IAC3B,OAAO,KAAK,OAAO;IACnB;GACF;GAEA,gBAAgB;EAClB;EAEA,MAAM,MAAM;EAEZ,MAAM,WAAW,YAAY,IAAI,IAAI;EACrC,IAAI,eACF,QAAQ,IACN,sBAAsB,SAAS,QAAQ,CAAC,EAAE,kBAAkB,IAAI,QAClE;EAGF,OAAO;CACT;CAEA,MAAM,SAAS,OAAO,KAAK,eAA6B,KAAK;CAE7D,MAAM,WAAW,YAAY,IAAI,IAAI;CACrC,IAAI,eACF,QAAQ,IACN,uBAAuB,SAAS,QAAQ,CAAC,EAAE,gBAAiB,IAAqB,MACnF;CAGF,OAAO;AACT;;;;;;;;AASF,MAAa,kBACV,OAAc,gBACd,KAAmB,QAAoB,UAA+B;CACrE,MAAM,QAAQ,YAAY,IAAI;CAC9B,MAAM,WAAW,MAAM,IAAI,KAAK,EAAE;CAElC,MAAM,SAAS,aACX,iBAAiB,WAAW,KAAK,QAAQ,KAAK,GAAG,KAAK,QAAQ,KAAK,IACnE,WAAW,KAAK,QAAQ,KAAK;CAEjC,MAAM,WAAW,YAAY,IAAI,IAAI;CACrC,IAAI,eACF,QAAQ,IACN,mBAAmB,SAAS,QAAQ,CAAC,EAAE,gBAAgB,IAAI,KAAK,mBAAmB,CAAC,CAAC,YACvF;CAGF,OAAO;AACT"}
1
+ {"version":3,"file":"renderer.cjs","names":[],"sources":["../../../src/markdown/renderer.ts"],"sourcesContent":["import type {\n ParserResult,\n ParseState,\n RenderRuleHook,\n RuleOutput,\n Rules,\n} from './types';\n\n/**\n * Creates a renderer for AST nodes.\n * Renamed from `reactFor` to be framework-agnostic.\n *\n * @param render - The render function to call for each node\n * @returns A function that renders AST to output\n */\nexport const renderFor = (\n render: (ast: ParserResult, render: RuleOutput, state: ParseState) => unknown\n) => {\n // Bound once instead of per node: rebuilding the recursive renderer on every\n // visit allocated a closure pair for each AST node.\n const emit = (\n ast: ParserResult | ParserResult[],\n state: ParseState = {}\n ): any => {\n if (!Array.isArray(ast)) {\n return render(ast, emit as RuleOutput, state);\n }\n\n const oldKey = state.key;\n const result: any[] = [];\n\n // map nestedOutput over the ast, except group any text\n // nodes together into a single string output.\n let lastWasString = false;\n let renderedIndex = 0;\n\n for (let i = 0; i < ast.length; i++) {\n // We clone the state to avoid side effects on other nodes in the same level\n // while ensuring each non-null rendered node gets a unique, sequential key.\n const nodeOut = emit(ast[i], { ...state, key: renderedIndex });\n const isString = typeof nodeOut === 'string';\n\n if (isString && lastWasString) {\n result[result.length - 1] =\n (result[result.length - 1] as string) + nodeOut;\n } else if (nodeOut !== null) {\n result.push(nodeOut);\n renderedIndex++;\n }\n\n lastWasString = isString;\n }\n\n state.key = oldKey;\n\n return result;\n };\n\n return emit;\n};\n\n/**\n * Creates a renderer from rules with optional custom render hook.\n *\n * @param rules - The rules object containing _render functions\n * @param userRender - Optional custom render hook for full control\n * @returns A render function for AST nodes\n */\nexport const createRenderer =\n (rules: Rules, userRender?: RenderRuleHook) =>\n (ast: ParserResult, render: RuleOutput, state: ParseState): unknown => {\n const renderer = rules[ast.type]?._render;\n\n return userRender\n ? userRender(() => renderer?.(ast, render, state), ast, render, state)\n : renderer?.(ast, render, state);\n };\n"],"mappings":";;;;;;;;;AAeA,MAAa,aACX,WACG;CAGH,MAAM,QACJ,KACA,QAAoB,CAAC,MACb;EACR,IAAI,CAAC,MAAM,QAAQ,GAAG,GACpB,OAAO,OAAO,KAAK,MAAoB,KAAK;EAG9C,MAAM,SAAS,MAAM;EACrB,MAAM,SAAgB,CAAC;EAIvB,IAAI,gBAAgB;EACpB,IAAI,gBAAgB;EAEpB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;GAGnC,MAAM,UAAU,KAAK,IAAI,IAAI;IAAE,GAAG;IAAO,KAAK;GAAc,CAAC;GAC7D,MAAM,WAAW,OAAO,YAAY;GAEpC,IAAI,YAAY,eACd,OAAO,OAAO,SAAS,KACpB,OAAO,OAAO,SAAS,KAAgB;QACrC,IAAI,YAAY,MAAM;IAC3B,OAAO,KAAK,OAAO;IACnB;GACF;GAEA,gBAAgB;EAClB;EAEA,MAAM,MAAM;EAEZ,OAAO;CACT;CAEA,OAAO;AACT;;;;;;;;AASA,MAAa,kBACV,OAAc,gBACd,KAAmB,QAAoB,UAA+B;CACrE,MAAM,WAAW,MAAM,IAAI,KAAK,EAAE;CAElC,OAAO,aACH,iBAAiB,WAAW,KAAK,QAAQ,KAAK,GAAG,KAAK,QAAQ,KAAK,IACnE,WAAW,KAAK,QAAQ,KAAK;AACnC"}