@intlayer/core 9.4.4 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +0 -2
  2. package/dist/cjs/dictionaryManipulator/qualifiedDictionary.cjs.map +1 -1
  3. package/dist/cjs/index.cjs +5 -8
  4. package/dist/cjs/interpreter/getPlural.cjs.map +1 -1
  5. package/dist/cjs/markdown/compiler.cjs +437 -209
  6. package/dist/cjs/markdown/compiler.cjs.map +1 -1
  7. package/dist/cjs/markdown/constants.cjs +32 -50
  8. package/dist/cjs/markdown/constants.cjs.map +1 -1
  9. package/dist/cjs/markdown/elementScanner.cjs +191 -0
  10. package/dist/cjs/markdown/elementScanner.cjs.map +1 -0
  11. package/dist/cjs/markdown/index.cjs +5 -8
  12. package/dist/cjs/markdown/parser.cjs +90 -48
  13. package/dist/cjs/markdown/parser.cjs.map +1 -1
  14. package/dist/cjs/markdown/renderer.cjs +14 -11
  15. package/dist/cjs/markdown/renderer.cjs.map +1 -1
  16. package/dist/cjs/markdown/utils.cjs +123 -34
  17. package/dist/cjs/markdown/utils.cjs.map +1 -1
  18. package/dist/esm/dictionaryManipulator/qualifiedDictionary.mjs.map +1 -1
  19. package/dist/esm/index.mjs +3 -3
  20. package/dist/esm/interpreter/getPlural.mjs.map +1 -1
  21. package/dist/esm/markdown/compiler.mjs +438 -211
  22. package/dist/esm/markdown/compiler.mjs.map +1 -1
  23. package/dist/esm/markdown/constants.mjs +29 -43
  24. package/dist/esm/markdown/constants.mjs.map +1 -1
  25. package/dist/esm/markdown/elementScanner.mjs +183 -0
  26. package/dist/esm/markdown/elementScanner.mjs.map +1 -0
  27. package/dist/esm/markdown/index.mjs +3 -3
  28. package/dist/esm/markdown/parser.mjs +90 -48
  29. package/dist/esm/markdown/parser.mjs.map +1 -1
  30. package/dist/esm/markdown/renderer.mjs +14 -11
  31. package/dist/esm/markdown/renderer.mjs.map +1 -1
  32. package/dist/esm/markdown/utils.mjs +124 -35
  33. package/dist/esm/markdown/utils.mjs.map +1 -1
  34. package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts +3 -3
  35. package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts.map +1 -1
  36. package/dist/types/index.d.ts +4 -4
  37. package/dist/types/interpreter/getPlural.d.ts +3 -3
  38. package/dist/types/interpreter/getPlural.d.ts.map +1 -1
  39. package/dist/types/markdown/compiler.d.ts +43 -0
  40. package/dist/types/markdown/compiler.d.ts.map +1 -1
  41. package/dist/types/markdown/constants.d.ts +26 -17
  42. package/dist/types/markdown/constants.d.ts.map +1 -1
  43. package/dist/types/markdown/elementScanner.d.ts +14 -0
  44. package/dist/types/markdown/elementScanner.d.ts.map +1 -0
  45. package/dist/types/markdown/index.d.ts +4 -4
  46. package/dist/types/markdown/parser.d.ts +0 -5
  47. package/dist/types/markdown/parser.d.ts.map +1 -1
  48. package/dist/types/markdown/renderer.d.ts +0 -4
  49. package/dist/types/markdown/renderer.d.ts.map +1 -1
  50. package/dist/types/markdown/types.d.ts +13 -0
  51. package/dist/types/markdown/types.d.ts.map +1 -1
  52. package/dist/types/markdown/utils.d.ts +7 -2
  53. package/dist/types/markdown/utils.d.ts.map +1 -1
  54. package/package.json +7 -7
  55. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +0 -1
  56. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +0 -1
  57. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +0 -1
  58. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +0 -1
  59. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +0 -1
  60. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +0 -1
  61. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +0 -1
  62. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +0 -7
  63. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +0 -1
  64. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +0 -2
  65. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +0 -1
  66. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +0 -1
  67. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +0 -1
  68. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +0 -1
  69. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +0 -1
  70. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +0 -1
  71. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +0 -1
  72. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +0 -1
  73. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +0 -1
  74. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +0 -7
  75. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +0 -1
  76. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +0 -6
  77. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +0 -2
  78. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +0 -1
  79. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +0 -1
  80. package/dist/types/@intlayer/core/dist/types/dictionaryManipulator/plainDynamicLoader.d.ts +0 -2
  81. package/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +0 -2
  82. package/dist/types/@intlayer/core/dist/types/formatters/compact.d.ts +0 -1
  83. package/dist/types/@intlayer/core/dist/types/formatters/currency.d.ts +0 -1
  84. package/dist/types/@intlayer/core/dist/types/formatters/date.d.ts +0 -1
  85. package/dist/types/@intlayer/core/dist/types/formatters/index.d.ts +0 -9
  86. package/dist/types/@intlayer/core/dist/types/formatters/list.d.ts +0 -1
  87. package/dist/types/@intlayer/core/dist/types/formatters/number.d.ts +0 -1
  88. package/dist/types/@intlayer/core/dist/types/formatters/percentage.d.ts +0 -1
  89. package/dist/types/@intlayer/core/dist/types/formatters/relativeTime.d.ts +0 -1
  90. package/dist/types/@intlayer/core/dist/types/formatters/units.d.ts +0 -1
  91. package/dist/types/@intlayer/core/dist/types/interpreter/dictionaryTransformCache.d.ts +0 -4
  92. package/dist/types/@intlayer/core/dist/types/interpreter/getCondition.d.ts +0 -2
  93. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/deepTransform.d.ts +0 -1
  94. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/getContent.d.ts +0 -3
  95. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/index.d.ts +0 -3
  96. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/plugins.d.ts +0 -7
  97. package/dist/types/@intlayer/core/dist/types/interpreter/getDictionary.d.ts +0 -4
  98. package/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +0 -6
  99. package/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +0 -2
  100. package/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +0 -2
  101. package/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +0 -2
  102. package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayer.d.ts +0 -4
  103. package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayerAsync.d.ts +0 -4
  104. package/dist/types/@intlayer/core/dist/types/interpreter/getNesting.d.ts +0 -6
  105. package/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +0 -3
  106. package/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +0 -2
  107. package/dist/types/@intlayer/core/dist/types/interpreter/getTranslation.d.ts +0 -1
  108. package/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +0 -18
  109. package/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +0 -2
  110. package/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +0 -6
  111. package/dist/types/@intlayer/core/dist/types/localization/comparePaths.d.ts +0 -1
  112. package/dist/types/@intlayer/core/dist/types/localization/domainUtils.d.ts +0 -2
  113. package/dist/types/@intlayer/core/dist/types/localization/generateSitemap.d.ts +0 -2
  114. package/dist/types/@intlayer/core/dist/types/localization/getBrowserLocale.d.ts +0 -1
  115. package/dist/types/@intlayer/core/dist/types/localization/getCanonicalPath.d.ts +0 -2
  116. package/dist/types/@intlayer/core/dist/types/localization/getHTMLTextDir.d.ts +0 -1
  117. package/dist/types/@intlayer/core/dist/types/localization/getLocale.d.ts +0 -1
  118. package/dist/types/@intlayer/core/dist/types/localization/getLocaleFromPath.d.ts +0 -2
  119. package/dist/types/@intlayer/core/dist/types/localization/getLocaleLang.d.ts +0 -1
  120. package/dist/types/@intlayer/core/dist/types/localization/getLocaleName.d.ts +0 -1
  121. package/dist/types/@intlayer/core/dist/types/localization/getLocalizedPath.d.ts +0 -2
  122. package/dist/types/@intlayer/core/dist/types/localization/getLocalizedUrl.d.ts +0 -2
  123. package/dist/types/@intlayer/core/dist/types/localization/getMultilingualUrls.d.ts +0 -2
  124. package/dist/types/@intlayer/core/dist/types/localization/getPathWithoutLocale.d.ts +0 -1
  125. package/dist/types/@intlayer/core/dist/types/localization/getPrefix.d.ts +0 -2
  126. package/dist/types/@intlayer/core/dist/types/localization/index.d.ts +0 -22
  127. package/dist/types/@intlayer/core/dist/types/localization/localeDetector.d.ts +0 -2
  128. package/dist/types/@intlayer/core/dist/types/localization/localeMapper.d.ts +0 -1
  129. package/dist/types/@intlayer/core/dist/types/localization/localeResolver.d.ts +0 -1
  130. package/dist/types/@intlayer/core/dist/types/localization/resolveBrowserLocale.d.ts +0 -2
  131. package/dist/types/@intlayer/core/dist/types/localization/rewriteMatch.d.ts +0 -1
  132. package/dist/types/@intlayer/core/dist/types/localization/rewriteUtils.d.ts +0 -2
  133. package/dist/types/@intlayer/core/dist/types/localization/validatePrefix.d.ts +0 -2
  134. package/dist/types/@intlayer/core/dist/types/markdown/index.d.ts +0 -2
  135. package/dist/types/@intlayer/core/dist/types/transpiler/condition/condition.d.ts +0 -1
  136. package/dist/types/@intlayer/core/dist/types/transpiler/condition/index.d.ts +0 -1
  137. package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/enumeration.d.ts +0 -1
  138. package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/index.d.ts +0 -1
  139. package/dist/types/@intlayer/core/dist/types/transpiler/file/file.d.ts +0 -1
  140. package/dist/types/@intlayer/core/dist/types/transpiler/file/index.d.ts +0 -1
  141. package/dist/types/@intlayer/core/dist/types/transpiler/gender/gender.d.ts +0 -1
  142. package/dist/types/@intlayer/core/dist/types/transpiler/gender/index.d.ts +0 -1
  143. package/dist/types/@intlayer/core/dist/types/transpiler/html/html.d.ts +0 -1
  144. package/dist/types/@intlayer/core/dist/types/transpiler/html/index.d.ts +0 -1
  145. package/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +0 -22
  146. package/dist/types/@intlayer/core/dist/types/transpiler/insertion/index.d.ts +0 -1
  147. package/dist/types/@intlayer/core/dist/types/transpiler/insertion/insertion.d.ts +0 -1
  148. package/dist/types/@intlayer/core/dist/types/transpiler/markdown/index.d.ts +0 -1
  149. package/dist/types/@intlayer/core/dist/types/transpiler/markdown/markdown.d.ts +0 -1
  150. package/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +0 -1
  151. package/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +0 -4
  152. package/dist/types/@intlayer/core/dist/types/transpiler/plural/index.d.ts +0 -1
  153. package/dist/types/@intlayer/core/dist/types/transpiler/plural/plural.d.ts +0 -1
  154. package/dist/types/@intlayer/core/dist/types/transpiler/select/index.d.ts +0 -1
  155. package/dist/types/@intlayer/core/dist/types/transpiler/select/select.d.ts +0 -1
  156. package/dist/types/@intlayer/core/dist/types/transpiler/translation/index.d.ts +0 -1
  157. package/dist/types/@intlayer/core/dist/types/transpiler/translation/translation.d.ts +0 -2
  158. package/dist/types/@intlayer/core/dist/types/utils/index.d.ts +0 -3
  159. package/dist/types/@intlayer/core/dist/types/utils/intl.d.ts +0 -1
  160. package/dist/types/@intlayer/core/dist/types/utils/isSameKeyPath.d.ts +0 -1
  161. package/dist/types/@intlayer/core/dist/types/utils/localeStorage.d.ts +0 -2
  162. package/dist/types/intlayer/dist/types/index.d.ts +0 -14
@@ -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// 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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"}
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// RULE SCOPE CONSTANTS\n// ============================================================================\n\n/**\n * Parsing scope for markdown rules.\n * Bitmask representation for fast bitwise checking and bundle minification.\n * - BLOCK (1): evaluated only when !state.inline && !state.simple\n * - INLINE (2): evaluated only when state.inline || state.simple\n * - BOTH (3): evaluated in both scopes (default)\n */\nexport const RuleScope = {\n BLOCK: 1,\n INLINE: 2,\n BOTH: 3,\n} as const;\n\nexport const SCOPE_BLOCK = RuleScope.BLOCK;\nexport const SCOPE_INLINE = RuleScope.INLINE;\nexport const SCOPE_BOTH = RuleScope.BOTH;\n\nexport type RuleScopeValue =\n | (typeof RuleScope)[keyof typeof RuleScope]\n | 'block'\n | 'inline'\n | 'both';\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,}))\\1\\n/;\nexport const BREAK_THEMATIC_R = /^(?:([-*_])( *\\1){2,}) *(?:\\n *)+\\n/;\n\n/** Code block patterns */\n// The body is consumed a whole line at a time rather than character by\n// character: a closing fence only ever starts a line, so the backreference is\n// tested once per line instead of once per character. The trailing `$` branch\n// inside the loop keeps an unterminated fence that ends without a newline.\nexport const CODE_BLOCK_FENCED_R =\n /^(?: {1,3})?(`{3,}|~{3,}) *(\\S+)? *([^\\n]*?)?\\n((?:[^\\n]*(?:\\n|$))*?)(?:\\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\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_.-]*$/;\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/**\n * Table patterns.\n *\n * The row scans spell \"any character but a newline\" as `[^\\n]` rather than `.`:\n * `.` is a four-range exclusion, and matching it over rows this wide costs a\n * third more than the single-range class. It is also the more faithful reading\n * — only `\\n` ends a line here, and `\\r` is normalized away before parsing.\n */\nexport const NP_TABLE_R =\n /^(\\|[^\\n]*)\\n(?: *(\\|? *[-:]+ *\\|[-| :]*)\\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/** Tabs, which `normalizeWhitespace` widens to four spaces. */\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 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;\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 // The body advances a line at a time rather than a character at a time: a\n // list can only end at a line boundary, so the terminator — the expensive\n // half, with its two nested lookaheads — is tried once per line instead of\n // once per character. The step swallows the newline that used to open the\n // terminator, which is why it now reads `\\n+` and not `\\n{2,}`, and the\n // leading lookahead keeps a source with nothing left after the bullet from\n // matching through a zero-width step.\n '(?=[\\\\s\\\\S])(?:[^\\\\n]*(?:\\\\n|$))+?' +\n '(?:\\\\n+(?! )' +\n '(?!\\\\1' +\n bullet +\n ' (?!' +\n bullet +\n ' ))\\\\n*' +\n // `\\s` already covers `\\n`, so the trailing `\\n*` the pattern used to\n // carry could only ever match empty — and paying for it at every step of\n // the lazy scan cost a third of the whole match.\n '|\\\\s*$)'\n );\n};\n\nexport const ORDERED_LIST_R = generateListRegex(ORDERED);\nexport const UNORDERED_LIST_R = generateListRegex(UNORDERED);\n"],"mappings":"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"}
@@ -0,0 +1,191 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ //#region src/markdown/elementScanner.ts
3
+ /**
4
+ * Lean, non-backtracking element scanner for HTML blocks, custom components, and self-closing tags.
5
+ */
6
+ const findTagEnd = (source, from) => {
7
+ const len = source.length;
8
+ let pos = from;
9
+ while (pos < len) {
10
+ const code = source.charCodeAt(pos);
11
+ if (code === 62) return pos;
12
+ if (code === 34 || code === 39) {
13
+ let cur = pos + 1;
14
+ while (cur < len && source.charCodeAt(cur) !== code && source.charCodeAt(cur) !== 10) cur++;
15
+ pos = source.charCodeAt(cur) === code ? cur + 1 : pos + 1;
16
+ continue;
17
+ }
18
+ pos++;
19
+ }
20
+ return -1;
21
+ };
22
+ /** Fold an ASCII upper-case letter to lower case, leaving anything else alone. */
23
+ const foldAscii = (code) => code >= 65 && code <= 90 ? code + 32 : code;
24
+ /**
25
+ * Compare `needle` against `source` at `at`, ignoring ASCII case.
26
+ *
27
+ * HTML tag names are case-insensitive, and the scanner asks this question once
28
+ * per `<` it walks past — so it must not allocate. Slicing the candidate out and
29
+ * lower-casing it built two strings per question, which is what made the tag
30
+ * walk the most expensive frame in an element-heavy document.
31
+ */
32
+ const matchesFolded = (source, needle, at) => {
33
+ for (let index = 0; index < needle.length; index++) if (foldAscii(source.charCodeAt(at + index)) !== foldAscii(needle.charCodeAt(index))) return false;
34
+ return true;
35
+ };
36
+ /**
37
+ * Index of the next `needle` tag at or after `from`, or -1 when there is none
38
+ * starting before `limit`.
39
+ *
40
+ * `limit` is what keeps the nesting walk linear: an opening tag only matters
41
+ * when it precedes the closing one, so searching past the closing tag walks the
42
+ * rest of the document — once per element — for an answer that is thrown away.
43
+ */
44
+ const findTag = (source, needle, from, caseInsensitive, limit) => {
45
+ if (!caseInsensitive) {
46
+ const idx = source.indexOf(needle, from);
47
+ return idx === -1 || idx >= limit ? -1 : idx;
48
+ }
49
+ const max = Math.min(limit, source.length - needle.length + 1);
50
+ let pos = from;
51
+ while (pos < max) {
52
+ const idx = source.indexOf("<", pos);
53
+ if (idx === -1 || idx >= max) return -1;
54
+ if (matchesFolded(source, needle, idx)) return idx;
55
+ pos = idx + 1;
56
+ }
57
+ return -1;
58
+ };
59
+ const makeMatch = (source, end, tagName, attrs, content) => {
60
+ const result = [
61
+ source.slice(0, end),
62
+ tagName,
63
+ attrs,
64
+ content
65
+ ];
66
+ result.index = 0;
67
+ result.input = source;
68
+ return result;
69
+ };
70
+ /** ASCII letter or digit — the characters a tag name is built from. */
71
+ const isNameChar = (code) => code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57;
72
+ const skipLeadingSpaces = (source) => {
73
+ let i = 0;
74
+ while (source.charCodeAt(i) === 32) i++;
75
+ return source.charCodeAt(i) === 60 ? i : -1;
76
+ };
77
+ const matchElement = (source, customComponent) => {
78
+ const bracket = skipLeadingSpaces(source);
79
+ if (bracket === -1) return null;
80
+ const nameStart = bracket + 1;
81
+ let nameEnd = nameStart;
82
+ const first = source.charCodeAt(nameStart);
83
+ if (customComponent) {
84
+ if (first < 65 || first > 90) return null;
85
+ while (nameEnd < source.length && isNameChar(source.charCodeAt(nameEnd))) nameEnd++;
86
+ } else {
87
+ if (!(first >= 65 && first <= 90 || first >= 97 && first <= 122)) return null;
88
+ while (nameEnd < source.length) {
89
+ const c = source.charCodeAt(nameEnd);
90
+ if (c === 32 || c === 9 || c === 10 || c === 13 || c === 62 || c === 47) break;
91
+ nameEnd++;
92
+ }
93
+ }
94
+ const tagName = source.slice(nameStart, nameEnd);
95
+ const openTagEnd = findTagEnd(source, nameEnd);
96
+ if (openTagEnd === -1) return null;
97
+ if (!customComponent && source.charCodeAt(openTagEnd - 1) === 47) return null;
98
+ let contentStart = openTagEnd + 1;
99
+ if (source.charCodeAt(contentStart) === 10) contentStart++;
100
+ const openTag = `<${tagName}`;
101
+ const closeTag = `</${tagName}`;
102
+ let depth = 1;
103
+ let cursor = contentStart;
104
+ const len = source.length;
105
+ let contentEnd = -1;
106
+ let end = -1;
107
+ while (cursor < len) {
108
+ const closeIdx = findTag(source, closeTag, cursor, !customComponent, len);
109
+ if (closeIdx === -1) return null;
110
+ const openIdx = findTag(source, openTag, cursor, !customComponent, closeIdx);
111
+ if (openIdx !== -1) {
112
+ const next = source.charCodeAt(openIdx + openTag.length);
113
+ if (next === 32 || next === 9 || next === 10 || next === 13 || next === 62 || next === 47) {
114
+ const nestedEnd = findTagEnd(source, openIdx + openTag.length);
115
+ if (nestedEnd === -1) return null;
116
+ depth++;
117
+ cursor = nestedEnd + 1;
118
+ } else cursor = openIdx + 1;
119
+ continue;
120
+ }
121
+ if (source.charCodeAt(closeIdx + closeTag.length) !== 62) {
122
+ cursor = closeIdx + 1;
123
+ continue;
124
+ }
125
+ const closeTagEnd = closeIdx + closeTag.length + 1;
126
+ depth--;
127
+ if (depth > 0) {
128
+ cursor = closeTagEnd;
129
+ continue;
130
+ }
131
+ if (findTag(source, closeTag, closeTagEnd, !customComponent, len) === closeTagEnd && source.charCodeAt(closeTagEnd + closeTag.length) === 62) {
132
+ depth = 1;
133
+ cursor = closeTagEnd;
134
+ continue;
135
+ }
136
+ contentEnd = closeIdx;
137
+ end = closeTagEnd;
138
+ break;
139
+ }
140
+ if (end === -1) return null;
141
+ while (source.charCodeAt(end) === 10) end++;
142
+ return makeMatch(source, end, tagName, source.slice(nameEnd, openTagEnd), source.slice(contentStart, contentEnd));
143
+ };
144
+ const matchSelfClosingElement = (source) => {
145
+ const bracket = skipLeadingSpaces(source);
146
+ if (bracket === -1) return null;
147
+ const nameStart = bracket + 1;
148
+ const first = source.charCodeAt(nameStart);
149
+ if (!(first >= 65 && first <= 90 || first >= 97 && first <= 122)) return null;
150
+ let nameEnd = nameStart + 1;
151
+ while (nameEnd < source.length && (isNameChar(source.charCodeAt(nameEnd)) || source.charCodeAt(nameEnd) === 58)) nameEnd++;
152
+ const c = source.charCodeAt(nameEnd);
153
+ const hasAttrs = c === 32 || c === 9 || c === 10 || c === 13;
154
+ let tagEnd;
155
+ if (hasAttrs) {
156
+ tagEnd = findTagEnd(source, nameEnd);
157
+ if (tagEnd === -1) return null;
158
+ } else {
159
+ tagEnd = source.charCodeAt(nameEnd) === 47 ? nameEnd + 1 : nameEnd;
160
+ if (source.charCodeAt(tagEnd) !== 62) return null;
161
+ }
162
+ const tagName = source.slice(nameStart, nameEnd);
163
+ const tailStart = tagEnd + 1;
164
+ if (source.charCodeAt(tailStart) === 60 && source.charCodeAt(tailStart + 1) === 47 && matchesFolded(source, tagName, tailStart + 2) && source.charCodeAt(tailStart + 2 + tagName.length) === 62) return null;
165
+ let end = tailStart;
166
+ let scan = tailStart;
167
+ while (scan < source.length) {
168
+ const sc = source.charCodeAt(scan);
169
+ if (sc !== 32 && sc !== 9 && sc !== 10 && sc !== 13) break;
170
+ scan++;
171
+ if (source.charCodeAt(scan - 1) === 10) end = scan;
172
+ }
173
+ return makeMatch(source, end, tagName, hasAttrs ? source.slice(nameEnd + 1, tagEnd) : void 0, end > tailStart ? source.slice(tailStart, end) : void 0);
174
+ };
175
+ const matchHtmlBlockElement = (source) => matchElement(source, false);
176
+ const matchCustomComponent = (source) => matchElement(source, true);
177
+ const startsWithHtmlBlockElement = (source) => matchHtmlBlockElement(source) !== null;
178
+ const startsWithSelfClosingElement = (source) => matchSelfClosingElement(source) !== null;
179
+ const startsWithCustomComponent = (source) => matchCustomComponent(source) !== null;
180
+ const startsWithElement = (source) => startsWithHtmlBlockElement(source) || startsWithSelfClosingElement(source);
181
+
182
+ //#endregion
183
+ exports.matchCustomComponent = matchCustomComponent;
184
+ exports.matchElement = matchElement;
185
+ exports.matchHtmlBlockElement = matchHtmlBlockElement;
186
+ exports.matchSelfClosingElement = matchSelfClosingElement;
187
+ exports.startsWithCustomComponent = startsWithCustomComponent;
188
+ exports.startsWithElement = startsWithElement;
189
+ exports.startsWithHtmlBlockElement = startsWithHtmlBlockElement;
190
+ exports.startsWithSelfClosingElement = startsWithSelfClosingElement;
191
+ //# sourceMappingURL=elementScanner.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementScanner.cjs","names":[],"sources":["../../../src/markdown/elementScanner.ts"],"sourcesContent":["/**\n * Lean, non-backtracking element scanner for HTML blocks, custom components, and self-closing tags.\n */\n\nconst findTagEnd = (source: string, from: number): number => {\n const len = source.length;\n let pos = from;\n while (pos < len) {\n const code = source.charCodeAt(pos);\n if (code === 62) return pos; // '>'\n if (code === 34 || code === 39) {\n // '\"' or \"'\"\n let cur = pos + 1;\n while (\n cur < len &&\n source.charCodeAt(cur) !== code &&\n source.charCodeAt(cur) !== 10\n )\n cur++;\n pos = source.charCodeAt(cur) === code ? cur + 1 : pos + 1;\n continue;\n }\n pos++;\n }\n return -1;\n};\n\n/** Fold an ASCII upper-case letter to lower case, leaving anything else alone. */\nconst foldAscii = (code: number): number =>\n code >= 65 && code <= 90 ? code + 32 : code;\n\n/**\n * Compare `needle` against `source` at `at`, ignoring ASCII case.\n *\n * HTML tag names are case-insensitive, and the scanner asks this question once\n * per `<` it walks past — so it must not allocate. Slicing the candidate out and\n * lower-casing it built two strings per question, which is what made the tag\n * walk the most expensive frame in an element-heavy document.\n */\nconst matchesFolded = (source: string, needle: string, at: number): boolean => {\n for (let index = 0; index < needle.length; index++) {\n if (\n foldAscii(source.charCodeAt(at + index)) !==\n foldAscii(needle.charCodeAt(index))\n ) {\n return false;\n }\n }\n return true;\n};\n\n/**\n * Index of the next `needle` tag at or after `from`, or -1 when there is none\n * starting before `limit`.\n *\n * `limit` is what keeps the nesting walk linear: an opening tag only matters\n * when it precedes the closing one, so searching past the closing tag walks the\n * rest of the document — once per element — for an answer that is thrown away.\n */\nconst findTag = (\n source: string,\n needle: string,\n from: number,\n caseInsensitive: boolean,\n limit: number\n): number => {\n if (!caseInsensitive) {\n const idx = source.indexOf(needle, from);\n return idx === -1 || idx >= limit ? -1 : idx;\n }\n const max = Math.min(limit, source.length - needle.length + 1);\n let pos = from;\n while (pos < max) {\n const idx = source.indexOf('<', pos);\n if (idx === -1 || idx >= max) return -1;\n if (matchesFolded(source, needle, idx)) return idx;\n pos = idx + 1;\n }\n return -1;\n};\n\nconst makeMatch = (\n source: string,\n end: number,\n tagName: string,\n attrs?: string,\n content?: string\n): RegExpMatchArray => {\n const result = [\n source.slice(0, end),\n tagName,\n attrs,\n content,\n ] as unknown as RegExpMatchArray;\n result.index = 0;\n result.input = source;\n return result;\n};\n\n/** ASCII letter or digit — the characters a tag name is built from. */\nconst isNameChar = (code: number): boolean =>\n (code >= 97 && code <= 122) ||\n (code >= 65 && code <= 90) ||\n (code >= 48 && code <= 57);\n\nconst skipLeadingSpaces = (source: string): number => {\n let i = 0;\n while (source.charCodeAt(i) === 32) i++;\n return source.charCodeAt(i) === 60 ? i : -1;\n};\n\nexport const matchElement = (\n source: string,\n customComponent: boolean\n): RegExpMatchArray | null => {\n const bracket = skipLeadingSpaces(source);\n if (bracket === -1) return null;\n\n const nameStart = bracket + 1;\n let nameEnd = nameStart;\n const first = source.charCodeAt(nameStart);\n\n if (customComponent) {\n if (first < 65 || first > 90) return null; // [A-Z]\n while (nameEnd < source.length && isNameChar(source.charCodeAt(nameEnd)))\n nameEnd++;\n } else {\n if (!((first >= 65 && first <= 90) || (first >= 97 && first <= 122)))\n return null;\n while (nameEnd < source.length) {\n const c = source.charCodeAt(nameEnd);\n if (c === 32 || c === 9 || c === 10 || c === 13 || c === 62 || c === 47)\n break;\n nameEnd++;\n }\n }\n\n const tagName = source.slice(nameStart, nameEnd);\n const openTagEnd = findTagEnd(source, nameEnd);\n if (openTagEnd === -1) return null;\n if (!customComponent && source.charCodeAt(openTagEnd - 1) === 47) return null;\n\n let contentStart = openTagEnd + 1;\n if (source.charCodeAt(contentStart) === 10) contentStart++;\n\n const openTag = `<${tagName}`;\n const closeTag = `</${tagName}`;\n\n let depth = 1;\n let cursor = contentStart;\n const len = source.length;\n let contentEnd = -1;\n let end = -1;\n\n while (cursor < len) {\n const closeIdx = findTag(source, closeTag, cursor, !customComponent, len);\n\n if (closeIdx === -1) return null;\n\n const openIdx = findTag(\n source,\n openTag,\n cursor,\n !customComponent,\n closeIdx\n );\n\n if (openIdx !== -1) {\n const next = source.charCodeAt(openIdx + openTag.length);\n if (\n next === 32 ||\n next === 9 ||\n next === 10 ||\n next === 13 ||\n next === 62 ||\n next === 47\n ) {\n const nestedEnd = findTagEnd(source, openIdx + openTag.length);\n if (nestedEnd === -1) return null;\n depth++;\n cursor = nestedEnd + 1;\n } else {\n cursor = openIdx + 1;\n }\n continue;\n }\n\n if (source.charCodeAt(closeIdx + closeTag.length) !== 62) {\n cursor = closeIdx + 1;\n continue;\n }\n\n const closeTagEnd = closeIdx + closeTag.length + 1;\n depth--;\n\n if (depth > 0) {\n cursor = closeTagEnd;\n continue;\n }\n\n // (?!</\\1>)\n if (\n findTag(source, closeTag, closeTagEnd, !customComponent, len) ===\n closeTagEnd &&\n source.charCodeAt(closeTagEnd + closeTag.length) === 62\n ) {\n depth = 1;\n cursor = closeTagEnd;\n continue;\n }\n\n contentEnd = closeIdx;\n end = closeTagEnd;\n break;\n }\n\n if (end === -1) return null;\n while (source.charCodeAt(end) === 10) end++;\n\n return makeMatch(\n source,\n end,\n tagName,\n source.slice(nameEnd, openTagEnd),\n source.slice(contentStart, contentEnd)\n );\n};\n\nexport const matchSelfClosingElement = (\n source: string\n): RegExpMatchArray | null => {\n const bracket = skipLeadingSpaces(source);\n if (bracket === -1) return null;\n\n const nameStart = bracket + 1;\n const first = source.charCodeAt(nameStart);\n if (!((first >= 65 && first <= 90) || (first >= 97 && first <= 122)))\n return null;\n\n let nameEnd = nameStart + 1;\n while (\n nameEnd < source.length &&\n (isNameChar(source.charCodeAt(nameEnd)) ||\n source.charCodeAt(nameEnd) === 58) /* : */\n )\n nameEnd++;\n\n const c = source.charCodeAt(nameEnd);\n const hasAttrs = c === 32 || c === 9 || c === 10 || c === 13;\n let tagEnd: number;\n\n if (hasAttrs) {\n tagEnd = findTagEnd(source, nameEnd);\n if (tagEnd === -1) return null;\n } else {\n tagEnd = source.charCodeAt(nameEnd) === 47 ? nameEnd + 1 : nameEnd;\n if (source.charCodeAt(tagEnd) !== 62) return null;\n }\n\n const tagName = source.slice(nameStart, nameEnd);\n const tailStart = tagEnd + 1;\n\n // `<tag/></tag>` is a paired element written oddly, not a self-closing one.\n if (\n source.charCodeAt(tailStart) === 60 /* < */ &&\n source.charCodeAt(tailStart + 1) === 47 /* / */ &&\n matchesFolded(source, tagName, tailStart + 2) &&\n source.charCodeAt(tailStart + 2 + tagName.length) === 62 /* > */\n ) {\n return null;\n }\n\n let end = tailStart;\n let scan = tailStart;\n while (scan < source.length) {\n const sc = source.charCodeAt(scan);\n if (sc !== 32 && sc !== 9 && sc !== 10 && sc !== 13) break;\n scan++;\n if (source.charCodeAt(scan - 1) === 10) end = scan;\n }\n\n return makeMatch(\n source,\n end,\n tagName,\n hasAttrs ? source.slice(nameEnd + 1, tagEnd) : undefined,\n end > tailStart ? source.slice(tailStart, end) : undefined\n );\n};\n\nexport const matchHtmlBlockElement = (source: string) =>\n matchElement(source, false);\nexport const matchCustomComponent = (source: string) =>\n matchElement(source, true);\nexport const startsWithHtmlBlockElement = (source: string) =>\n matchHtmlBlockElement(source) !== null;\nexport const startsWithSelfClosingElement = (source: string) =>\n matchSelfClosingElement(source) !== null;\nexport const startsWithCustomComponent = (source: string) =>\n matchCustomComponent(source) !== null;\nexport const startsWithElement = (source: string) =>\n startsWithHtmlBlockElement(source) || startsWithSelfClosingElement(source);\n"],"mappings":"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"}
@@ -23,8 +23,6 @@ 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;
27
- exports.CUSTOM_COMPONENT_R = require_markdown_constants.CUSTOM_COMPONENT_R;
28
26
  exports.DO_NOT_PROCESS_HTML_ELEMENTS = require_markdown_constants.DO_NOT_PROCESS_HTML_ELEMENTS;
29
27
  exports.FENCE_DELIMITER_R = require_markdown_constants.FENCE_DELIMITER_R;
30
28
  exports.FOOTNOTE_R = require_markdown_constants.FOOTNOTE_R;
@@ -35,21 +33,16 @@ exports.GFM_TASK_R = require_markdown_constants.GFM_TASK_R;
35
33
  exports.HEADING_ATX_COMPLIANT_R = require_markdown_constants.HEADING_ATX_COMPLIANT_R;
36
34
  exports.HEADING_R = require_markdown_constants.HEADING_R;
37
35
  exports.HEADING_SETEXT_R = require_markdown_constants.HEADING_SETEXT_R;
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;
40
36
  exports.HTML_CHAR_CODE_R = require_markdown_constants.HTML_CHAR_CODE_R;
41
37
  exports.HTML_COMMENT_R = require_markdown_constants.HTML_COMMENT_R;
42
38
  exports.HTML_CUSTOM_ATTR_R = require_markdown_constants.HTML_CUSTOM_ATTR_R;
43
39
  exports.HTML_LEFT_TRIM_AMOUNT_R = require_markdown_constants.HTML_LEFT_TRIM_AMOUNT_R;
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;
46
40
  exports.INLINE_SKIP_R = require_markdown_constants.INLINE_SKIP_R;
47
41
  exports.INTERPOLATION_R = require_markdown_constants.INTERPOLATION_R;
48
42
  exports.LINK_AUTOLINK_BARE_URL_R = require_markdown_constants.LINK_AUTOLINK_BARE_URL_R;
49
43
  exports.LINK_AUTOLINK_R = require_markdown_constants.LINK_AUTOLINK_R;
50
44
  exports.LOOKAHEAD = require_markdown_constants.LOOKAHEAD;
51
45
  exports.NAMED_CODES_TO_UNICODE = require_markdown_constants.NAMED_CODES_TO_UNICODE;
52
- exports.NORMALIZE_WHITESPACE_R = require_markdown_constants.NORMALIZE_WHITESPACE_R;
53
46
  exports.NP_TABLE_R = require_markdown_constants.NP_TABLE_R;
54
47
  exports.ORDERED = require_markdown_constants.ORDERED;
55
48
  exports.ORDERED_LIST_BULLET = require_markdown_constants.ORDERED_LIST_BULLET;
@@ -62,7 +55,11 @@ exports.Priority = require_markdown_constants.Priority;
62
55
  exports.REFERENCE_IMAGE_OR_LINK = require_markdown_constants.REFERENCE_IMAGE_OR_LINK;
63
56
  exports.REFERENCE_IMAGE_R = require_markdown_constants.REFERENCE_IMAGE_R;
64
57
  exports.REFERENCE_LINK_R = require_markdown_constants.REFERENCE_LINK_R;
58
+ exports.RuleScope = require_markdown_constants.RuleScope;
65
59
  exports.RuleType = require_markdown_constants.RuleType;
60
+ exports.SCOPE_BLOCK = require_markdown_constants.SCOPE_BLOCK;
61
+ exports.SCOPE_BOTH = require_markdown_constants.SCOPE_BOTH;
62
+ exports.SCOPE_INLINE = require_markdown_constants.SCOPE_INLINE;
66
63
  exports.SHORTCODE_R = require_markdown_constants.SHORTCODE_R;
67
64
  exports.SHOULD_RENDER_AS_BLOCK_R = require_markdown_constants.SHOULD_RENDER_AS_BLOCK_R;
68
65
  exports.TABLE_CENTER_ALIGN = require_markdown_constants.TABLE_CENTER_ALIGN;
@@ -74,7 +71,6 @@ exports.TEXT_BOLD_R = require_markdown_constants.TEXT_BOLD_R;
74
71
  exports.TEXT_EMPHASIZED_R = require_markdown_constants.TEXT_EMPHASIZED_R;
75
72
  exports.TEXT_ESCAPED_R = require_markdown_constants.TEXT_ESCAPED_R;
76
73
  exports.TEXT_MARKED_R = require_markdown_constants.TEXT_MARKED_R;
77
- exports.TEXT_PLAIN_R = require_markdown_constants.TEXT_PLAIN_R;
78
74
  exports.TEXT_STRIKETHROUGHED_R = require_markdown_constants.TEXT_STRIKETHROUGHED_R;
79
75
  exports.TRIM_STARTING_NEWLINES = require_markdown_constants.TRIM_STARTING_NEWLINES;
80
76
  exports.UNESCAPE_R = require_markdown_constants.UNESCAPE_R;
@@ -100,6 +96,7 @@ exports.generateListItemRegex = require_markdown_constants.generateListItemRegex
100
96
  exports.generateListRegex = require_markdown_constants.generateListRegex;
101
97
  exports.get = require_markdown_utils.get;
102
98
  exports.getMarkdownMetadata = require_transpiler_markdown_getMarkdownMetadata.getMarkdownMetadata;
99
+ exports.getRuleSet = require_markdown_compiler.getRuleSet;
103
100
  exports.inlineRegex = require_markdown_utils.inlineRegex;
104
101
  exports.md = require_transpiler_markdown_markdown.md;
105
102
  exports.normalizeAttributeKey = require_markdown_utils.normalizeAttributeKey;
@@ -1,30 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_markdown_constants = require('./constants.cjs');
2
3
  const require_markdown_utils = require('./utils.cjs');
3
4
 
4
5
  //#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
6
  /**
29
7
  * Advance the incremental lookbehind carried on the parse state.
30
8
  *
@@ -35,10 +13,14 @@ const orderRules = (names, rules) => {
35
13
  * rescanning — the whole document, which made parsing quadratic.
36
14
  */
37
15
  const advanceLookbehind = (state, capture) => {
16
+ const lastCode = capture.charCodeAt(capture.length - 1);
17
+ if (state.prevCaptureHasBlankLine !== true) state.prevCaptureHasBlankLine = capture.indexOf("\n\n") !== -1 || state.prevCaptureHasBlankLine !== void 0 && capture.charCodeAt(0) === 10 && state.prevCaptureIndent === "";
18
+ if (lastCode !== 32 && lastCode !== 10) {
19
+ state.prevCaptureIndent = void 0;
20
+ return;
21
+ }
38
22
  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);
23
+ const tail = newlineIndex === -1 ? state.prevCaptureIndent === void 0 ? void 0 : state.prevCaptureIndent === "" ? capture : state.prevCaptureIndent + capture : capture.slice(newlineIndex + 1);
42
24
  if (tail === void 0 || tail === "") {
43
25
  state.prevCaptureIndent = tail;
44
26
  return;
@@ -52,45 +34,105 @@ const advanceLookbehind = (state, capture) => {
52
34
  /**
53
35
  * Creates a parser for a given set of rules, with the precedence
54
36
  * specified as a list of rules.
55
- *
56
- * @param rules - An object containing rule type -> {match, order, parse} objects
57
- * (lower order is higher precedence)
58
- *
59
- * @returns The resulting parse function
60
37
  */
61
38
  const parserFor = (rules) => {
62
- const ruleList = Object.keys(rules);
63
- if (process.env.NODE_ENV !== "production") ruleList.forEach((type) => {
64
- const order = rules[type]?._order;
65
- if (typeof order !== "number" || !Number.isFinite(order)) console.warn(`intlayer: Invalid order for rule \`${type}\`: ${order}`);
66
- });
67
- const order = orderRules(ruleList, rules);
39
+ const order = Object.keys(rules).sort((a, b) => rules[a]._order - rules[b]._order || +a - +b);
68
40
  const ruleCount = order.length;
69
41
  const qualifiers = new Array(ruleCount);
70
42
  const matchers = new Array(ruleCount);
71
43
  const parsers = new Array(ruleCount);
44
+ const ruleFirstChars = new Array(ruleCount);
45
+ const ruleIsBlock = new Array(ruleCount);
46
+ const ruleIsInline = new Array(ruleCount);
47
+ const blockDefaultCandidates = [];
48
+ const inlineDefaultCandidates = [];
72
49
  for (let i = 0; i < ruleCount; i++) {
73
50
  const rule = rules[order[i]];
74
- qualifiers[i] = rule._qualify;
51
+ let q = rule._qualify;
75
52
  matchers[i] = rule._match;
76
53
  parsers[i] = rule._parse;
54
+ const rawScope = rule._scope;
55
+ const isBlock = rawScope !== require_markdown_constants.SCOPE_INLINE;
56
+ const isInline = rawScope !== require_markdown_constants.SCOPE_BLOCK;
57
+ ruleIsBlock[i] = isBlock;
58
+ ruleIsInline[i] = isInline;
59
+ if (rule._firstChars && rule._firstChars.length > 0) ruleFirstChars[i] = rule._firstChars;
60
+ else if (Array.isArray(q) && q.length > 0 && q.every((p) => p.length > 0)) {
61
+ ruleFirstChars[i] = q.map((p) => p.charCodeAt(0));
62
+ if (q.every((p) => p.length === 1)) q = void 0;
63
+ } else {
64
+ ruleFirstChars[i] = null;
65
+ if (isBlock) blockDefaultCandidates.push(i);
66
+ if (isInline) inlineDefaultCandidates.push(i);
67
+ }
68
+ qualifiers[i] = q;
69
+ }
70
+ const blockAsciiCandidates = new Array(128);
71
+ const inlineAsciiCandidates = new Array(128);
72
+ for (let code = 0; code < 128; code++) {
73
+ const bList = [];
74
+ const iList = [];
75
+ for (let i = 0; i < ruleCount; i++) {
76
+ const isBlock = ruleIsBlock[i];
77
+ const isInline = ruleIsInline[i];
78
+ const chars = ruleFirstChars[i];
79
+ if (isBlock && (!chars || chars.includes(code))) bList.push(i);
80
+ if (isInline && (!chars || chars.includes(code))) iList.push(i);
81
+ }
82
+ blockAsciiCandidates[code] = bList;
83
+ inlineAsciiCandidates[code] = iList;
77
84
  }
78
85
  const nestedParse = (source, state = {}) => {
79
86
  const result = [];
87
+ const isInline = Boolean(state.inline || state.simple);
80
88
  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);
89
+ let hasContent = false;
90
+ for (let j = 0; j < source.length; j++) {
91
+ const c = source.charCodeAt(j);
92
+ if (c !== 32 && c !== 9 && c !== 10 && c !== 13) {
93
+ hasContent = true;
91
94
  break;
92
95
  }
93
96
  }
97
+ if (hasContent) {
98
+ const asciiCandidates = isInline ? inlineAsciiCandidates : blockAsciiCandidates;
99
+ const defaultCandidates = isInline ? inlineDefaultCandidates : blockDefaultCandidates;
100
+ while (source) {
101
+ const code = source.charCodeAt(0);
102
+ const candidates = code < 128 ? asciiCandidates[code] : defaultCandidates;
103
+ const candidateCount = candidates.length;
104
+ let matched = false;
105
+ for (let c = 0; c < candidateCount; c++) {
106
+ const i = candidates[c];
107
+ const qualify = qualifiers[i];
108
+ if (qualify && !require_markdown_utils.qualifies(source, state, qualify)) continue;
109
+ const capture = matchers[i](source, state);
110
+ if (capture?.[0]) {
111
+ source = source.slice(capture[0].length);
112
+ const parsed = parsers[i](capture, nestedParse, state);
113
+ advanceLookbehind(state, capture[0]);
114
+ const nodeType = parsed.type || order[i];
115
+ parsed.type = nodeType;
116
+ const len = result.length;
117
+ if (nodeType === require_markdown_constants.RuleType.text) {
118
+ if (!parsed.text) {
119
+ matched = true;
120
+ break;
121
+ }
122
+ if (len > 0 && result[len - 1].type === require_markdown_constants.RuleType.text) {
123
+ result[len - 1].text += parsed.text;
124
+ matched = true;
125
+ break;
126
+ }
127
+ }
128
+ result.push(parsed);
129
+ matched = true;
130
+ break;
131
+ }
132
+ }
133
+ if (!matched) break;
134
+ }
135
+ }
94
136
  return result;
95
137
  };
96
138
  return (source, state) => nestedParse(require_markdown_utils.normalizeWhitespace(source), state);
@@ -1 +1 @@
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
+ {"version":3,"file":"parser.cjs","names":["SCOPE_INLINE","SCOPE_BLOCK","qualifies","RuleType","normalizeWhitespace"],"sources":["../../../src/markdown/parser.ts"],"sourcesContent":["import { RuleType, SCOPE_BLOCK, SCOPE_INLINE } from './constants';\nimport type {\n NestedParser,\n ParserResult,\n ParseState,\n Rule,\n Rules,\n} from './types';\nimport { normalizeWhitespace, qualifies } from './utils';\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 lastCode = capture.charCodeAt(capture.length - 1);\n\n if (state.prevCaptureHasBlankLine !== true) {\n state.prevCaptureHasBlankLine =\n capture.indexOf('\\n\\n') !== -1 ||\n (state.prevCaptureHasBlankLine !== undefined &&\n capture.charCodeAt(0) === 10 &&\n state.prevCaptureIndent === '');\n }\n\n // A capture whose last character is neither a space nor a newline cannot\n // leave an all-space tail behind it, whatever it contains — so the common\n // case never pays for the backwards `lastIndexOf` scan.\n if (lastCode !== 32 /* space */ && lastCode !== 10 /* \\n */) {\n state.prevCaptureIndent = undefined;\n return;\n }\n\n const newlineIndex = capture.lastIndexOf('\\n');\n\n const tail =\n newlineIndex === -1\n ? state.prevCaptureIndent === undefined\n ? undefined\n : state.prevCaptureIndent === ''\n ? capture\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) {\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 */\nexport const parserFor = (\n rules: Rules\n): ((source: string, state: ParseState) => ParserResult[]) => {\n const order = Object.keys(rules).sort(\n (a, b) => rules[a]!._order - rules[b]!._order || +a - +b\n );\n const ruleCount = order.length;\n\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 const ruleFirstChars: (number[] | null)[] = new Array(ruleCount);\n const ruleIsBlock: boolean[] = new Array(ruleCount);\n const ruleIsInline: boolean[] = new Array(ruleCount);\n const blockDefaultCandidates: number[] = [];\n const inlineDefaultCandidates: number[] = [];\n\n for (let i = 0; i < ruleCount; i++) {\n const rule = rules[order[i]!]!;\n let q = rule._qualify;\n matchers[i] = rule._match;\n parsers[i] = rule._parse;\n\n const rawScope = rule._scope;\n const isBlock = rawScope !== SCOPE_INLINE;\n const isInline = rawScope !== SCOPE_BLOCK;\n\n ruleIsBlock[i] = isBlock;\n ruleIsInline[i] = isInline;\n\n if (rule._firstChars && rule._firstChars.length > 0) {\n ruleFirstChars[i] = rule._firstChars;\n } else if (\n Array.isArray(q) &&\n q.length > 0 &&\n q.every((p) => p.length > 0)\n ) {\n ruleFirstChars[i] = q.map((p) => p.charCodeAt(0));\n if (q.every((p) => p.length === 1)) q = undefined;\n } else {\n ruleFirstChars[i] = null;\n if (isBlock) blockDefaultCandidates.push(i);\n if (isInline) inlineDefaultCandidates.push(i);\n }\n qualifiers[i] = q;\n }\n\n const blockAsciiCandidates: number[][] = new Array(128);\n const inlineAsciiCandidates: number[][] = new Array(128);\n for (let code = 0; code < 128; code++) {\n const bList: number[] = [];\n const iList: number[] = [];\n for (let i = 0; i < ruleCount; i++) {\n const isBlock = ruleIsBlock[i]!;\n const isInline = ruleIsInline[i]!;\n const chars = ruleFirstChars[i];\n\n if (isBlock && (!chars || chars.includes(code))) {\n bList.push(i);\n }\n if (isInline && (!chars || chars.includes(code))) {\n iList.push(i);\n }\n }\n blockAsciiCandidates[code] = bList;\n inlineAsciiCandidates[code] = iList;\n }\n\n const nestedParse: NestedParser = (\n source: string,\n state: ParseState = {}\n ): ParserResult[] => {\n const result: ParserResult[] = [];\n const isInline = Boolean(state.inline || state.simple);\n\n if (state.prevCaptureHasBlankLine === undefined) {\n state.prevCaptureIndent = '';\n }\n\n // Quick non-allocating whitespace check\n let hasContent = false;\n for (let j = 0; j < source.length; j++) {\n const c = source.charCodeAt(j);\n if (c !== 32 && c !== 9 && c !== 10 && c !== 13) {\n hasContent = true;\n break;\n }\n }\n\n if (hasContent) {\n const asciiCandidates = isInline\n ? inlineAsciiCandidates\n : blockAsciiCandidates;\n const defaultCandidates = isInline\n ? inlineDefaultCandidates\n : blockDefaultCandidates;\n\n while (source) {\n const code = source.charCodeAt(0);\n const candidates =\n code < 128 ? asciiCandidates[code]! : defaultCandidates;\n const candidateCount = candidates.length;\n let matched = false;\n\n for (let c = 0; c < candidateCount; c++) {\n const i = candidates[c]!;\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.slice(capture[0].length);\n\n const parsed: any = parsers[i]!(capture, nestedParse, state);\n\n advanceLookbehind(state, capture[0]);\n\n const nodeType = parsed.type || order[i];\n parsed.type = nodeType;\n\n const len = result.length;\n if (nodeType === RuleType.text) {\n if (!parsed.text) {\n matched = true;\n break;\n }\n if (len > 0 && result[len - 1]!.type === RuleType.text) {\n (result[len - 1] as any).text += parsed.text;\n matched = true;\n break;\n }\n }\n\n result.push(parsed as ParserResult);\n matched = true;\n break;\n }\n }\n\n if (!matched) break;\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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"}
@@ -15,10 +15,9 @@ const renderFor = (render) => {
15
15
  let lastWasString = false;
16
16
  let renderedIndex = 0;
17
17
  for (let i = 0; i < ast.length; i++) {
18
- const nodeOut = emit(ast[i], {
19
- ...state,
20
- key: renderedIndex
21
- });
18
+ state.key = renderedIndex;
19
+ const node = ast[i];
20
+ const nodeOut = Array.isArray(node) ? emit(node, state) : render(node, emit, state);
22
21
  const isString = typeof nodeOut === "string";
23
22
  if (isString && lastWasString) result[result.length - 1] = result[result.length - 1] + nodeOut;
24
23
  else if (nodeOut !== null) {
@@ -34,14 +33,18 @@ const renderFor = (render) => {
34
33
  };
35
34
  /**
36
35
  * Creates a renderer from rules with optional custom render hook.
37
- *
38
- * @param rules - The rules object containing _render functions
39
- * @param userRender - Optional custom render hook for full control
40
- * @returns A render function for AST nodes
41
36
  */
42
- const createRenderer = (rules, userRender) => (ast, render, state) => {
43
- const renderer = rules[ast.type]?._render;
44
- return userRender ? userRender(() => renderer?.(ast, render, state), ast, render, state) : renderer?.(ast, render, state);
37
+ const createRenderer = (rules, userRender) => {
38
+ const renderers = {};
39
+ for (const type in rules) renderers[type] = rules[type]?._render;
40
+ if (!userRender) return (ast, render, state) => {
41
+ const r = renderers[ast.type];
42
+ return r ? r(ast, render, state) : void 0;
43
+ };
44
+ return (ast, render, state) => {
45
+ const renderer = renderers[ast.type];
46
+ return userRender(() => renderer?.(ast, render, state), ast, render, state);
47
+ };
45
48
  };
46
49
 
47
50
  //#endregion