@intlayer/core 9.4.4 → 9.5.1

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 (171) 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/localization/getPrefix.cjs +6 -6
  6. package/dist/cjs/localization/getPrefix.cjs.map +1 -1
  7. package/dist/cjs/markdown/compiler.cjs +437 -209
  8. package/dist/cjs/markdown/compiler.cjs.map +1 -1
  9. package/dist/cjs/markdown/constants.cjs +32 -50
  10. package/dist/cjs/markdown/constants.cjs.map +1 -1
  11. package/dist/cjs/markdown/elementScanner.cjs +191 -0
  12. package/dist/cjs/markdown/elementScanner.cjs.map +1 -0
  13. package/dist/cjs/markdown/index.cjs +5 -8
  14. package/dist/cjs/markdown/parser.cjs +90 -48
  15. package/dist/cjs/markdown/parser.cjs.map +1 -1
  16. package/dist/cjs/markdown/renderer.cjs +14 -11
  17. package/dist/cjs/markdown/renderer.cjs.map +1 -1
  18. package/dist/cjs/markdown/utils.cjs +123 -34
  19. package/dist/cjs/markdown/utils.cjs.map +1 -1
  20. package/dist/cjs/utils/getCookie.cjs +1 -1
  21. package/dist/cjs/utils/getCookie.cjs.map +1 -1
  22. package/dist/esm/dictionaryManipulator/qualifiedDictionary.mjs.map +1 -1
  23. package/dist/esm/index.mjs +3 -3
  24. package/dist/esm/interpreter/getPlural.mjs.map +1 -1
  25. package/dist/esm/localization/getPrefix.mjs +6 -6
  26. package/dist/esm/localization/getPrefix.mjs.map +1 -1
  27. package/dist/esm/markdown/compiler.mjs +438 -211
  28. package/dist/esm/markdown/compiler.mjs.map +1 -1
  29. package/dist/esm/markdown/constants.mjs +29 -43
  30. package/dist/esm/markdown/constants.mjs.map +1 -1
  31. package/dist/esm/markdown/elementScanner.mjs +183 -0
  32. package/dist/esm/markdown/elementScanner.mjs.map +1 -0
  33. package/dist/esm/markdown/index.mjs +3 -3
  34. package/dist/esm/markdown/parser.mjs +90 -48
  35. package/dist/esm/markdown/parser.mjs.map +1 -1
  36. package/dist/esm/markdown/renderer.mjs +14 -11
  37. package/dist/esm/markdown/renderer.mjs.map +1 -1
  38. package/dist/esm/markdown/utils.mjs +124 -35
  39. package/dist/esm/markdown/utils.mjs.map +1 -1
  40. package/dist/esm/utils/getCookie.mjs +1 -1
  41. package/dist/esm/utils/getCookie.mjs.map +1 -1
  42. package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts +3 -3
  43. package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts.map +1 -1
  44. package/dist/types/index.d.ts +4 -4
  45. package/dist/types/interpreter/getPlural.d.ts +3 -3
  46. package/dist/types/interpreter/getPlural.d.ts.map +1 -1
  47. package/dist/types/localization/getPrefix.d.ts.map +1 -1
  48. package/dist/types/markdown/compiler.d.ts +43 -0
  49. package/dist/types/markdown/compiler.d.ts.map +1 -1
  50. package/dist/types/markdown/constants.d.ts +26 -17
  51. package/dist/types/markdown/constants.d.ts.map +1 -1
  52. package/dist/types/markdown/elementScanner.d.ts +14 -0
  53. package/dist/types/markdown/elementScanner.d.ts.map +1 -0
  54. package/dist/types/markdown/index.d.ts +4 -4
  55. package/dist/types/markdown/parser.d.ts +0 -5
  56. package/dist/types/markdown/parser.d.ts.map +1 -1
  57. package/dist/types/markdown/renderer.d.ts +0 -4
  58. package/dist/types/markdown/renderer.d.ts.map +1 -1
  59. package/dist/types/markdown/types.d.ts +13 -0
  60. package/dist/types/markdown/types.d.ts.map +1 -1
  61. package/dist/types/markdown/utils.d.ts +7 -2
  62. package/dist/types/markdown/utils.d.ts.map +1 -1
  63. package/package.json +7 -7
  64. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +0 -1
  65. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +0 -1
  66. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +0 -1
  67. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +0 -1
  68. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +0 -1
  69. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +0 -1
  70. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +0 -1
  71. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +0 -7
  72. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +0 -1
  73. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +0 -2
  74. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +0 -1
  75. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +0 -1
  76. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +0 -1
  77. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +0 -1
  78. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +0 -1
  79. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +0 -1
  80. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +0 -1
  81. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +0 -1
  82. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +0 -1
  83. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +0 -7
  84. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +0 -1
  85. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +0 -6
  86. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +0 -2
  87. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +0 -1
  88. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +0 -1
  89. package/dist/types/@intlayer/core/dist/types/dictionaryManipulator/plainDynamicLoader.d.ts +0 -2
  90. package/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +0 -2
  91. package/dist/types/@intlayer/core/dist/types/formatters/compact.d.ts +0 -1
  92. package/dist/types/@intlayer/core/dist/types/formatters/currency.d.ts +0 -1
  93. package/dist/types/@intlayer/core/dist/types/formatters/date.d.ts +0 -1
  94. package/dist/types/@intlayer/core/dist/types/formatters/index.d.ts +0 -9
  95. package/dist/types/@intlayer/core/dist/types/formatters/list.d.ts +0 -1
  96. package/dist/types/@intlayer/core/dist/types/formatters/number.d.ts +0 -1
  97. package/dist/types/@intlayer/core/dist/types/formatters/percentage.d.ts +0 -1
  98. package/dist/types/@intlayer/core/dist/types/formatters/relativeTime.d.ts +0 -1
  99. package/dist/types/@intlayer/core/dist/types/formatters/units.d.ts +0 -1
  100. package/dist/types/@intlayer/core/dist/types/interpreter/dictionaryTransformCache.d.ts +0 -4
  101. package/dist/types/@intlayer/core/dist/types/interpreter/getCondition.d.ts +0 -2
  102. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/deepTransform.d.ts +0 -1
  103. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/getContent.d.ts +0 -3
  104. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/index.d.ts +0 -3
  105. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/plugins.d.ts +0 -7
  106. package/dist/types/@intlayer/core/dist/types/interpreter/getDictionary.d.ts +0 -4
  107. package/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +0 -6
  108. package/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +0 -2
  109. package/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +0 -2
  110. package/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +0 -2
  111. package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayer.d.ts +0 -4
  112. package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayerAsync.d.ts +0 -4
  113. package/dist/types/@intlayer/core/dist/types/interpreter/getNesting.d.ts +0 -6
  114. package/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +0 -3
  115. package/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +0 -2
  116. package/dist/types/@intlayer/core/dist/types/interpreter/getTranslation.d.ts +0 -1
  117. package/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +0 -18
  118. package/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +0 -2
  119. package/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +0 -6
  120. package/dist/types/@intlayer/core/dist/types/localization/comparePaths.d.ts +0 -1
  121. package/dist/types/@intlayer/core/dist/types/localization/domainUtils.d.ts +0 -2
  122. package/dist/types/@intlayer/core/dist/types/localization/generateSitemap.d.ts +0 -2
  123. package/dist/types/@intlayer/core/dist/types/localization/getBrowserLocale.d.ts +0 -1
  124. package/dist/types/@intlayer/core/dist/types/localization/getCanonicalPath.d.ts +0 -2
  125. package/dist/types/@intlayer/core/dist/types/localization/getHTMLTextDir.d.ts +0 -1
  126. package/dist/types/@intlayer/core/dist/types/localization/getLocale.d.ts +0 -1
  127. package/dist/types/@intlayer/core/dist/types/localization/getLocaleFromPath.d.ts +0 -2
  128. package/dist/types/@intlayer/core/dist/types/localization/getLocaleLang.d.ts +0 -1
  129. package/dist/types/@intlayer/core/dist/types/localization/getLocaleName.d.ts +0 -1
  130. package/dist/types/@intlayer/core/dist/types/localization/getLocalizedPath.d.ts +0 -2
  131. package/dist/types/@intlayer/core/dist/types/localization/getLocalizedUrl.d.ts +0 -2
  132. package/dist/types/@intlayer/core/dist/types/localization/getMultilingualUrls.d.ts +0 -2
  133. package/dist/types/@intlayer/core/dist/types/localization/getPathWithoutLocale.d.ts +0 -1
  134. package/dist/types/@intlayer/core/dist/types/localization/getPrefix.d.ts +0 -2
  135. package/dist/types/@intlayer/core/dist/types/localization/index.d.ts +0 -22
  136. package/dist/types/@intlayer/core/dist/types/localization/localeDetector.d.ts +0 -2
  137. package/dist/types/@intlayer/core/dist/types/localization/localeMapper.d.ts +0 -1
  138. package/dist/types/@intlayer/core/dist/types/localization/localeResolver.d.ts +0 -1
  139. package/dist/types/@intlayer/core/dist/types/localization/resolveBrowserLocale.d.ts +0 -2
  140. package/dist/types/@intlayer/core/dist/types/localization/rewriteMatch.d.ts +0 -1
  141. package/dist/types/@intlayer/core/dist/types/localization/rewriteUtils.d.ts +0 -2
  142. package/dist/types/@intlayer/core/dist/types/localization/validatePrefix.d.ts +0 -2
  143. package/dist/types/@intlayer/core/dist/types/markdown/index.d.ts +0 -2
  144. package/dist/types/@intlayer/core/dist/types/transpiler/condition/condition.d.ts +0 -1
  145. package/dist/types/@intlayer/core/dist/types/transpiler/condition/index.d.ts +0 -1
  146. package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/enumeration.d.ts +0 -1
  147. package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/index.d.ts +0 -1
  148. package/dist/types/@intlayer/core/dist/types/transpiler/file/file.d.ts +0 -1
  149. package/dist/types/@intlayer/core/dist/types/transpiler/file/index.d.ts +0 -1
  150. package/dist/types/@intlayer/core/dist/types/transpiler/gender/gender.d.ts +0 -1
  151. package/dist/types/@intlayer/core/dist/types/transpiler/gender/index.d.ts +0 -1
  152. package/dist/types/@intlayer/core/dist/types/transpiler/html/html.d.ts +0 -1
  153. package/dist/types/@intlayer/core/dist/types/transpiler/html/index.d.ts +0 -1
  154. package/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +0 -22
  155. package/dist/types/@intlayer/core/dist/types/transpiler/insertion/index.d.ts +0 -1
  156. package/dist/types/@intlayer/core/dist/types/transpiler/insertion/insertion.d.ts +0 -1
  157. package/dist/types/@intlayer/core/dist/types/transpiler/markdown/index.d.ts +0 -1
  158. package/dist/types/@intlayer/core/dist/types/transpiler/markdown/markdown.d.ts +0 -1
  159. package/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +0 -1
  160. package/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +0 -4
  161. package/dist/types/@intlayer/core/dist/types/transpiler/plural/index.d.ts +0 -1
  162. package/dist/types/@intlayer/core/dist/types/transpiler/plural/plural.d.ts +0 -1
  163. package/dist/types/@intlayer/core/dist/types/transpiler/select/index.d.ts +0 -1
  164. package/dist/types/@intlayer/core/dist/types/transpiler/select/select.d.ts +0 -1
  165. package/dist/types/@intlayer/core/dist/types/transpiler/translation/index.d.ts +0 -1
  166. package/dist/types/@intlayer/core/dist/types/transpiler/translation/translation.d.ts +0 -2
  167. package/dist/types/@intlayer/core/dist/types/utils/index.d.ts +0 -3
  168. package/dist/types/@intlayer/core/dist/types/utils/intl.d.ts +0 -1
  169. package/dist/types/@intlayer/core/dist/types/utils/isSameKeyPath.d.ts +0 -1
  170. package/dist/types/@intlayer/core/dist/types/utils/localeStorage.d.ts +0 -2
  171. package/dist/types/intlayer/dist/types/index.d.ts +0 -14
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_markdown_constants = require('./constants.cjs');
3
+ const require_markdown_elementScanner = require('./elementScanner.cjs');
3
4
  const require_markdown_utils = require('./utils.cjs');
4
5
  const require_markdown_parser = require('./parser.cjs');
5
6
  const require_markdown_renderer = require('./renderer.cjs');
@@ -14,14 +15,6 @@ const LINK_R = new RegExp(`^\\[((?:\\[[^\\[\\]]*(?:\\[[^\\[\\]]*\\][^\\[\\]]*)*\
14
15
  * lowercase the whole remaining document to look its closing tag up — copying
15
16
  * the rest of the file on each probe.
16
17
  */
17
- const closingTagRegexCache = /* @__PURE__ */ new Map();
18
- const getClosingTagRegex = (tag) => {
19
- const cached = closingTagRegexCache.get(tag);
20
- if (cached) return cached;
21
- const regex = new RegExp(`</${tag}>`, "i");
22
- closingTagRegexCache.set(tag, regex);
23
- return regex;
24
- };
25
18
  /**
26
19
  * Builds a tag -> component resolver for one set of overrides.
27
20
  *
@@ -30,10 +23,17 @@ const getClosingTagRegex = (tag) => {
30
23
  */
31
24
  const createTagResolver = (components) => {
32
25
  let lowercaseKeys = null;
26
+ if (Object.keys(components).length === 0) return (tag) => tag;
27
+ const resolved = /* @__PURE__ */ new Map();
33
28
  return (tag) => {
34
29
  if (typeof tag !== "string") return tag;
30
+ const memoized = resolved.get(tag);
31
+ if (memoized !== void 0) return memoized;
35
32
  const override = require_markdown_utils.get(components, tag);
36
- if (override) return override;
33
+ if (override) {
34
+ resolved.set(tag, override);
35
+ return override;
36
+ }
37
37
  if (!lowercaseKeys) {
38
38
  lowercaseKeys = /* @__PURE__ */ new Map();
39
39
  for (const key of Object.keys(components)) {
@@ -42,7 +42,9 @@ const createTagResolver = (components) => {
42
42
  }
43
43
  }
44
44
  const key = lowercaseKeys.get(tag.toLowerCase());
45
- return (key ? require_markdown_utils.get(components, key) : void 0) || tag;
45
+ const result = (key ? require_markdown_utils.get(components, key) : void 0) || tag;
46
+ resolved.set(tag, result);
47
+ return result;
46
48
  };
47
49
  };
48
50
  /** Resolves the slugifier for a context, falling back to the built-in one. */
@@ -50,7 +52,7 @@ const createSlugger = (ctx) => (input) => ctx.slugify ? ctx.slugify(input, requi
50
52
  const createElementFactory = (ctx, options) => {
51
53
  const { runtime, components = {} } = ctx;
52
54
  const resolveTag = createTagResolver(components);
53
- const filteredTags = options.tagfilter ? [
55
+ const filteredTags = options.tagfilter ? /* @__PURE__ */ new Set([
54
56
  "title",
55
57
  "textarea",
56
58
  "style",
@@ -60,59 +62,211 @@ const createElementFactory = (ctx, options) => {
60
62
  "noframes",
61
63
  "script",
62
64
  "plaintext"
63
- ] : [];
65
+ ]) : null;
66
+ /**
67
+ * True when `props` can be handed to the runtime untouched: no `class`
68
+ * alias to fold into `className`, and no empty value to drop. Rules build a
69
+ * fresh literal for every element, so reusing it is safe, and it saves an
70
+ * object per element — the single largest allocation in the render phase.
71
+ */
72
+ const needsPropsRewrite = (props) => {
73
+ if ("class" in props) return true;
74
+ for (const key in props) {
75
+ const value = props[key];
76
+ if (value === void 0 || value === null) return true;
77
+ }
78
+ return false;
79
+ };
64
80
  return (tag, props, ...children) => {
65
- if (typeof tag === "string" && filteredTags.includes(tag.toLowerCase())) return null;
66
81
  const isStringTag = typeof tag === "string";
67
- const className = require_markdown_utils.cx(props?.className, props?.class);
68
- const mergedProps = {};
69
- let classNameHandled = false;
70
- if (props) for (const key in props) {
71
- const value = props[key];
72
- if (value === void 0 || value === null) continue;
73
- if (key === "className" || key === "class") {
74
- if (!classNameHandled) {
75
- if (className) mergedProps.className = className;
76
- classNameHandled = true;
77
- }
78
- } else mergedProps[key] = value;
82
+ if (filteredTags && isStringTag && (filteredTags.has(tag) || filteredTags.has(tag.toLowerCase()))) return null;
83
+ let finalProps;
84
+ if (!props) finalProps = {};
85
+ else if (!needsPropsRewrite(props)) finalProps = props;
86
+ else {
87
+ const className = require_markdown_utils.cx(props.className, props.class);
88
+ const mergedProps = {};
89
+ let classNameHandled = false;
90
+ for (const key in props) {
91
+ const value = props[key];
92
+ if (value === void 0 || value === null) continue;
93
+ if (key === "className" || key === "class") {
94
+ if (!classNameHandled) {
95
+ if (className) mergedProps.className = className;
96
+ classNameHandled = true;
97
+ }
98
+ } else mergedProps[key] = value;
99
+ }
100
+ if (!classNameHandled && className) mergedProps.className = className;
101
+ finalProps = mergedProps;
79
102
  }
80
- if (!classNameHandled && className) mergedProps.className = className;
81
- let finalProps = mergedProps;
82
- if (runtime.normalizeProps && isStringTag) finalProps = runtime.normalizeProps(tag, mergedProps);
103
+ if (runtime.normalizeProps && isStringTag) finalProps = runtime.normalizeProps(tag, finalProps);
83
104
  const component = resolveTag(tag);
84
- return runtime.createElement(component, finalProps, ...children.length === 1 ? [children[0]] : children);
105
+ return runtime.createElement(component, finalProps, ...children);
106
+ };
107
+ };
108
+ const createDocumentScope = () => ({
109
+ footnotes: [],
110
+ references: {}
111
+ });
112
+ /**
113
+ * Small enough to scan linearly, large enough that an app mixing a few option
114
+ * sets — say prose and a dictionary rendered with different components — keeps
115
+ * hitting it.
116
+ */
117
+ const RULE_SET_CACHE_LIMIT = 8;
118
+ const ruleSetCache = [];
119
+ /**
120
+ * Every input that changes how rules are built. Compared directly rather than
121
+ * through a signature array, which would allocate on every compile.
122
+ */
123
+ const builtFromSame = (entry, ctx, options, parseOnly) => entry.parseOnly === parseOnly && entry.ctx.runtime === ctx.runtime && entry.ctx.components === ctx.components && entry.ctx.namedCodesToUnicode === ctx.namedCodesToUnicode && entry.ctx.sanitizer === ctx.sanitizer && entry.ctx.slugify === ctx.slugify && entry.options.disableAutoLink === options.disableAutoLink && entry.options.disableParsingRawHTML === options.disableParsingRawHTML && entry.options.enforceAtxHeadings === options.enforceAtxHeadings && entry.options.tagfilter === options.tagfilter && entry.options.renderRule === options.renderRule;
124
+ /**
125
+ * Returns the rule set for these options, building it only when no cached set
126
+ * was made from the same inputs.
127
+ */
128
+ const getRuleSet = (ctx, options, parseOnly) => {
129
+ for (let index = 0; index < ruleSetCache.length; index++) {
130
+ const entry = ruleSetCache[index];
131
+ if (!builtFromSame(entry, ctx, options, parseOnly)) continue;
132
+ if (index > 0) {
133
+ ruleSetCache.splice(index, 1);
134
+ ruleSetCache.unshift(entry);
135
+ }
136
+ return entry;
137
+ }
138
+ const scope = { current: createDocumentScope() };
139
+ const createElement = parseOnly ? noopCreateElement : createElementFactory(ctx, options);
140
+ const rules = createDocumentRules(createElement, ctx, options, scope);
141
+ const entry = {
142
+ ctx,
143
+ options,
144
+ parseOnly,
145
+ createElement,
146
+ scope,
147
+ parse: require_markdown_parser.parserFor(rules),
148
+ emit: require_markdown_renderer.renderFor(require_markdown_renderer.createRenderer(rules, options.renderRule))
85
149
  };
150
+ ruleSetCache.unshift(entry);
151
+ if (ruleSetCache.length > RULE_SET_CACHE_LIMIT) ruleSetCache.pop();
152
+ return entry;
86
153
  };
87
- const createRules = (createElement, ctx, options, footnotes, refs, attrStringToMap, containsBlockSyntax, nonParagraphBlockSyntaxes) => {
154
+ /**
155
+ * Runs `operation` with `scope` installed as the current document, restoring
156
+ * whatever was there before. The save/restore keeps a nested compile — a custom
157
+ * component that renders markdown of its own — from clobbering its caller.
158
+ */
159
+ const withDocumentScope = (ref, scope, operation) => {
160
+ const previous = ref.current;
161
+ ref.current = scope;
162
+ try {
163
+ return operation();
164
+ } finally {
165
+ ref.current = previous;
166
+ }
167
+ };
168
+ const createRules = (createElement, ctx, options, scope, attrStringToMap, containsBlockSyntax, nonParagraphBlockSyntaxes) => {
88
169
  const slug = createSlugger(ctx);
89
170
  const sanitize = ctx.sanitizer ?? require_markdown_utils.sanitizer;
90
171
  const namedCodesToUnicode = ctx.namedCodesToUnicode ? {
91
172
  ...require_markdown_constants.NAMED_CODES_TO_UNICODE,
92
173
  ...ctx.namedCodesToUnicode
93
174
  } : require_markdown_constants.NAMED_CODES_TO_UNICODE;
175
+ /**
176
+ * Raw HTML blocks and custom components differ only in how their tag is
177
+ * spelled: both trim the captured content, decide block or inline parsing
178
+ * from it, and render the tag with its attributes. `rawHtml` adds the two
179
+ * things only real HTML needs — the never-parse element list, and tracking
180
+ * whether we are inside an anchor.
181
+ */
182
+ const pairedElementRule = (match, order, rawHtml, scope = require_markdown_constants.SCOPE_BOTH) => ({
183
+ _scope: scope,
184
+ _qualify: ["<"],
185
+ _match: require_markdown_utils.anyScopeRegex(match),
186
+ _order: order,
187
+ _parse(capture, parse, state) {
188
+ const content = capture[3] ?? "";
189
+ const whitespace = content.match(require_markdown_constants.HTML_LEFT_TRIM_AMOUNT_R)?.[1] ?? "";
190
+ const trimmed = require_markdown_utils.trimLeadingWhitespaceOutsideFences(content, whitespace);
191
+ const parseFunc = containsBlockSyntax(trimmed) ? require_markdown_utils.parseBlock : require_markdown_utils.parseInline;
192
+ const tagName = (capture[1] ?? "").trim();
193
+ const lowercased = tagName.toLowerCase();
194
+ const noInnerParse = rawHtml && require_markdown_constants.DO_NOT_PROCESS_HTML_ELEMENTS.indexOf(lowercased) !== -1;
195
+ const tag = noInnerParse ? lowercased : tagName;
196
+ const ast = {
197
+ attrs: attrStringToMap(tag, capture[2] ?? ""),
198
+ noInnerParse,
199
+ tag
200
+ };
201
+ if (rawHtml) state.inAnchor = state.inAnchor || lowercased === "a";
202
+ if (noInnerParse) ast.text = content;
203
+ else {
204
+ const prevInHTML = state.inHTML;
205
+ state.inHTML = true;
206
+ ast.children = parseFunc(parse, trimmed, state);
207
+ state.inHTML = prevInHTML;
208
+ }
209
+ if (rawHtml) state.inAnchor = false;
210
+ return ast;
211
+ },
212
+ _render(node, output, state = {}) {
213
+ return createElement(node.tag, {
214
+ key: state.key,
215
+ ...node.attrs ?? {}
216
+ }, node.text ?? (node.children ? output(node.children, state) : ""));
217
+ }
218
+ });
94
219
  const generateListRule = (type) => {
95
220
  const ordered = type === 1;
96
221
  const LIST_R = ordered ? require_markdown_constants.ORDERED_LIST_R : require_markdown_constants.UNORDERED_LIST_R;
97
222
  const LIST_ITEM_R = ordered ? require_markdown_constants.ORDERED_LIST_ITEM_R : require_markdown_constants.UNORDERED_LIST_ITEM_R;
98
223
  const LIST_ITEM_PREFIX_R = ordered ? require_markdown_constants.ORDERED_LIST_ITEM_PREFIX_R : require_markdown_constants.UNORDERED_LIST_ITEM_PREFIX_R;
99
224
  return {
100
- _qualify: (source) => LIST_ITEM_PREFIX_R.test(source),
225
+ _scope: require_markdown_constants.SCOPE_BOTH,
226
+ _firstChars: ordered ? [
227
+ 32,
228
+ 9,
229
+ 48,
230
+ 49,
231
+ 50,
232
+ 51,
233
+ 52,
234
+ 53,
235
+ 54,
236
+ 55,
237
+ 56,
238
+ 57
239
+ ] : [
240
+ 32,
241
+ 9,
242
+ 42,
243
+ 43,
244
+ 45
245
+ ],
246
+ _qualify: (source, state) => state.prevCaptureIndent !== void 0 && Boolean(state.list ?? (!state.inline && !state.simple)) && LIST_ITEM_PREFIX_R.test(source),
101
247
  _match: require_markdown_utils.allowInline((source, state) => {
102
248
  const lineIndent = state.prevCaptureIndent;
103
249
  const isStartOfLine = lineIndent !== void 0;
104
250
  const isListAllowed = state.list ?? (!state.inline && !state.simple);
105
251
  if (isStartOfLine && isListAllowed) {
106
252
  const matchSource = lineIndent ? lineIndent + source : source;
107
- return LIST_R.exec(matchSource);
253
+ const match = LIST_R.exec(matchSource);
254
+ if (!match) return null;
255
+ if (lineIndent && match[0].startsWith(lineIndent)) {
256
+ const adjusted = [...match];
257
+ adjusted[0] = match[0].slice(lineIndent.length);
258
+ adjusted.fullMatch = match[0];
259
+ return adjusted;
260
+ }
261
+ return match;
108
262
  }
109
263
  return null;
110
264
  }),
111
265
  _order: require_markdown_constants.Priority.HIGH,
112
266
  _parse(capture, parse, state) {
113
- const bullet = capture[2];
267
+ const bullet = capture[2] ?? "";
114
268
  const startValue = ordered ? +bullet.slice(0, -1) : void 0;
115
- const items = capture[0].replace(require_markdown_constants.BLOCK_END_R, "\n").match(LIST_ITEM_R);
269
+ const items = (capture.fullMatch ?? capture[0] ?? "").replace(require_markdown_constants.BLOCK_END_R, "\n").match(LIST_ITEM_R);
116
270
  if (!items) return {
117
271
  items: [],
118
272
  ordered,
@@ -123,8 +277,8 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
123
277
  items: items.map((item, i) => {
124
278
  const prefixCapture = LIST_ITEM_PREFIX_R.exec(item);
125
279
  const space = prefixCapture ? prefixCapture[0].length : 0;
126
- const spaceRegex = new RegExp(`^ {1,${space}}`, "gm");
127
- const content = item.replace(spaceRegex, "").replace(LIST_ITEM_PREFIX_R, "");
280
+ const spaceRegex = space <= 8 ? STRIP_INDENT_REGEXES[space] : new RegExp(`^ {1,${space}}`, "gm");
281
+ const content = item.slice(space).replace(spaceRegex, "");
128
282
  const isLastItem = i === items.length - 1;
129
283
  const thisItemIsAParagraph = content.indexOf("\n\n") !== -1 || isLastItem && lastItemWasAParagraph;
130
284
  lastItemWasAParagraph = thisItemIsAParagraph;
@@ -149,21 +303,33 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
149
303
  };
150
304
  },
151
305
  _render(node, output, state = {}) {
152
- const Tag = node.ordered ? "ol" : "ul";
153
- const props = { key: state.key };
154
- if (node.ordered && node.start != null) props.start = node.start;
155
- return createElement(Tag, props, ...node.items.map((item, i) => createElement("li", { key: i }, output(item, state))));
306
+ return createElement(ordered ? "ol" : "ul", {
307
+ key: state.key,
308
+ start: node.start
309
+ }, ...node.items.map((item, i) => createElement("li", { key: i }, output(item, state))));
156
310
  }
157
311
  };
158
312
  };
159
313
  const matchParagraph = (source, state) => {
160
314
  if (state.inline || state.simple || state.inHTML && source.indexOf("\n\n") === -1 && !state.prevCaptureHasBlankLine) return null;
161
315
  let start = 0;
162
- while (true) {
316
+ const srcLen = source.length;
317
+ while (start < srcLen) {
163
318
  const newlineIndex = source.indexOf("\n", start);
164
- const line = source.slice(start, newlineIndex === -1 ? void 0 : newlineIndex + 1);
165
- if (require_markdown_utils.some(nonParagraphBlockSyntaxes, line)) break;
166
- if (newlineIndex === -1 || !line.trim()) break;
319
+ const lineEnd = newlineIndex === -1 ? srcLen : newlineIndex;
320
+ let p = start;
321
+ while (p < lineEnd && (source.charCodeAt(p) === 32 || source.charCodeAt(p) === 9)) p++;
322
+ if (p >= lineEnd) break;
323
+ if (p - start >= 4 || source.charCodeAt(start) === 9) break;
324
+ const ch = source.charCodeAt(p);
325
+ if (ch === 62 || ch === 96 || ch === 126 || ch === 35 || ch === 124 || ch === 42 || ch === 43 || ch === 45 || ch === 61 || ch === 60 || ch >= 48 && ch <= 57) {
326
+ const line = source.slice(start, newlineIndex === -1 ? void 0 : newlineIndex + 1);
327
+ if (require_markdown_utils.some(nonParagraphBlockSyntaxes, line)) break;
328
+ }
329
+ if (newlineIndex === -1) {
330
+ start = srcLen;
331
+ break;
332
+ }
167
333
  start = newlineIndex + 1;
168
334
  }
169
335
  const match = source.slice(0, start);
@@ -178,11 +344,12 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
178
344
  };
179
345
  return {
180
346
  [require_markdown_constants.RuleType.blockQuote]: {
347
+ _scope: require_markdown_constants.SCOPE_BLOCK,
181
348
  _qualify: [">"],
182
349
  _match: require_markdown_utils.blockRegex(require_markdown_constants.BLOCKQUOTE_R),
183
350
  _order: require_markdown_constants.Priority.HIGH,
184
351
  _parse(capture, parse, state) {
185
- const matchAlert = capture[0].replace(require_markdown_constants.BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, "").match(require_markdown_constants.BLOCKQUOTE_ALERT_R);
352
+ const matchAlert = (capture[0] ?? "").replace(require_markdown_constants.BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, "").match(require_markdown_constants.BLOCKQUOTE_ALERT_R);
186
353
  const alert = matchAlert?.[1];
187
354
  const content = matchAlert?.[2] ?? "";
188
355
  return {
@@ -209,6 +376,7 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
209
376
  }
210
377
  },
211
378
  [require_markdown_constants.RuleType.breakLine]: {
379
+ _scope: require_markdown_constants.SCOPE_BOTH,
212
380
  _qualify: [" "],
213
381
  _match: require_markdown_utils.anyScopeRegex(require_markdown_constants.BREAK_LINE_R),
214
382
  _order: require_markdown_constants.Priority.HIGH,
@@ -218,6 +386,7 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
218
386
  }
219
387
  },
220
388
  [require_markdown_constants.RuleType.breakThematic]: {
389
+ _scope: require_markdown_constants.SCOPE_BLOCK,
221
390
  _qualify: [
222
391
  "--",
223
392
  "__",
@@ -234,6 +403,7 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
234
403
  }
235
404
  },
236
405
  [require_markdown_constants.RuleType.codeBlock]: {
406
+ _scope: require_markdown_constants.SCOPE_BLOCK,
237
407
  _qualify: [" "],
238
408
  _match: require_markdown_utils.blockRegex(require_markdown_constants.CODE_BLOCK_R),
239
409
  _order: require_markdown_constants.Priority.MAX,
@@ -241,7 +411,7 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
241
411
  return {
242
412
  type: require_markdown_constants.RuleType.codeBlock,
243
413
  lang: void 0,
244
- text: require_markdown_utils.unescapeString(require_markdown_utils.trimEnd(capture[0].replace(/^ {4}/gm, "")))
414
+ text: require_markdown_utils.unescapeString(require_markdown_utils.trimEnd((capture[0] ?? "").replace(/^ {4}/gm, "")))
245
415
  };
246
416
  },
247
417
  _render(node, _, state = {}) {
@@ -252,6 +422,7 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
252
422
  }
253
423
  },
254
424
  [require_markdown_constants.RuleType.codeFenced]: {
425
+ _scope: require_markdown_constants.SCOPE_BLOCK,
255
426
  _qualify: ["```", "~~~"],
256
427
  _match: require_markdown_utils.blockRegex(require_markdown_constants.CODE_BLOCK_FENCED_R),
257
428
  _order: require_markdown_constants.Priority.MAX,
@@ -259,43 +430,48 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
259
430
  return {
260
431
  attrs: attrStringToMap("code", capture[3] ?? ""),
261
432
  lang: capture[2] || void 0,
262
- text: capture[4],
433
+ text: capture[4] ?? "",
263
434
  type: require_markdown_constants.RuleType.codeBlock
264
435
  };
265
436
  }
266
437
  },
267
438
  [require_markdown_constants.RuleType.codeInline]: {
268
- _qualify: ["`"],
439
+ _scope: require_markdown_constants.SCOPE_INLINE,
440
+ _firstChars: [96],
441
+ _qualify: (source) => source.charCodeAt(0) === 96 && source.indexOf("`", 1) !== -1,
269
442
  _match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.CODE_INLINE_R),
270
443
  _order: require_markdown_constants.Priority.LOW,
271
444
  _parse(capture) {
272
- return { text: require_markdown_utils.unescapeString(capture[2]) };
445
+ return { text: require_markdown_utils.unescapeString(capture[2] ?? "") };
273
446
  },
274
447
  _render(node, _, state = {}) {
275
448
  return createElement("code", { key: state.key }, node.text);
276
449
  }
277
450
  },
278
451
  [require_markdown_constants.RuleType.footnote]: {
452
+ _scope: require_markdown_constants.SCOPE_INLINE,
279
453
  _qualify: ["[^"],
280
454
  _match: require_markdown_utils.blockRegex(require_markdown_constants.FOOTNOTE_R),
281
455
  _order: require_markdown_constants.Priority.MAX,
282
456
  _parse(capture) {
283
- footnotes.push({
284
- footnote: capture[2],
285
- identifier: capture[1]
457
+ scope.current.footnotes.push({
458
+ footnote: capture[2] ?? "",
459
+ identifier: capture[1] ?? ""
286
460
  });
287
461
  return {};
288
462
  },
289
463
  _render: require_markdown_utils.renderNothing
290
464
  },
291
465
  [require_markdown_constants.RuleType.footnoteReference]: {
466
+ _scope: require_markdown_constants.SCOPE_INLINE,
292
467
  _qualify: ["[^"],
293
468
  _match: require_markdown_utils.inlineRegex(require_markdown_constants.FOOTNOTE_REFERENCE_R),
294
469
  _order: require_markdown_constants.Priority.HIGH,
295
470
  _parse(capture) {
471
+ const text = capture[1] ?? "";
296
472
  return {
297
- target: `#${slug(capture[1])}`,
298
- text: capture[1]
473
+ target: `#${slug(text)}`,
474
+ text
299
475
  };
300
476
  },
301
477
  _render(node, _, state = {}) {
@@ -306,11 +482,12 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
306
482
  }
307
483
  },
308
484
  [require_markdown_constants.RuleType.gfmTask]: {
485
+ _scope: require_markdown_constants.SCOPE_INLINE,
309
486
  _qualify: ["[ ]", "[x]"],
310
487
  _match: require_markdown_utils.inlineRegex(require_markdown_constants.GFM_TASK_R),
311
488
  _order: require_markdown_constants.Priority.HIGH,
312
489
  _parse(capture) {
313
- return { completed: capture[1].toLowerCase() === "x" };
490
+ return { completed: (capture[1] ?? "").toLowerCase() === "x" };
314
491
  },
315
492
  _render(node, _, state = {}) {
316
493
  return createElement("input", {
@@ -322,14 +499,16 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
322
499
  }
323
500
  },
324
501
  [require_markdown_constants.RuleType.heading]: {
502
+ _scope: require_markdown_constants.SCOPE_BLOCK,
325
503
  _qualify: ["#"],
326
504
  _match: require_markdown_utils.blockRegex(options.enforceAtxHeadings ? require_markdown_constants.HEADING_ATX_COMPLIANT_R : require_markdown_constants.HEADING_R),
327
505
  _order: require_markdown_constants.Priority.HIGH,
328
506
  _parse(capture, parse, state) {
507
+ const text = capture[2] ?? "";
329
508
  return {
330
- children: require_markdown_utils.parseInline(parse, capture[2], state),
331
- id: slug(capture[2]),
332
- level: capture[1].length
509
+ children: require_markdown_utils.parseInline(parse, text, state),
510
+ id: slug(text),
511
+ level: capture[1]?.length ?? 1
333
512
  };
334
513
  },
335
514
  _render(node, output, state = {}) {
@@ -340,7 +519,9 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
340
519
  }
341
520
  },
342
521
  [require_markdown_constants.RuleType.headingSetext]: {
343
- _qualify: (source) => {
522
+ _scope: require_markdown_constants.SCOPE_BLOCK,
523
+ _qualify: (source, state) => {
524
+ if (state.prevCaptureIndent === void 0 || state.inline || state.simple) return false;
344
525
  const nlIndex = source.indexOf("\n");
345
526
  return nlIndex > 0 && nlIndex < source.length - 1 && (source[nlIndex + 1] === "=" || source[nlIndex + 1] === "-");
346
527
  },
@@ -348,52 +529,15 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
348
529
  _order: require_markdown_constants.Priority.MAX,
349
530
  _parse(capture, parse, state) {
350
531
  return {
351
- children: require_markdown_utils.parseInline(parse, capture[1], state),
532
+ children: require_markdown_utils.parseInline(parse, capture[1] ?? "", state),
352
533
  level: capture[2] === "=" ? 1 : 2,
353
534
  type: require_markdown_constants.RuleType.heading
354
535
  };
355
536
  }
356
537
  },
357
- [require_markdown_constants.RuleType.htmlBlock]: {
358
- _qualify: (source) => {
359
- if (options.disableParsingRawHTML) return false;
360
- const match = require_markdown_constants.HTML_BLOCK_OPENING_TAG_R.exec(source);
361
- if (!match) return false;
362
- return getClosingTagRegex(match[1]).test(source);
363
- },
364
- _match: require_markdown_utils.anyScopeRegex(require_markdown_constants.HTML_BLOCK_ELEMENT_R),
365
- _order: require_markdown_constants.Priority.HIGH,
366
- _parse(capture, parse, state) {
367
- const whitespace = capture[3].match(require_markdown_constants.HTML_LEFT_TRIM_AMOUNT_R)?.[1] ?? "";
368
- const trimmed = require_markdown_utils.trimLeadingWhitespaceOutsideFences(capture[3], whitespace);
369
- const parseFunc = containsBlockSyntax(trimmed) ? require_markdown_utils.parseBlock : require_markdown_utils.parseInline;
370
- const tagName = capture[1].trim();
371
- const noInnerParse = require_markdown_constants.DO_NOT_PROCESS_HTML_ELEMENTS.indexOf(tagName.toLowerCase()) !== -1;
372
- const tag = noInnerParse ? tagName.toLowerCase() : tagName;
373
- const ast = {
374
- attrs: attrStringToMap(tag, capture[2] ?? ""),
375
- noInnerParse,
376
- tag
377
- };
378
- state.inAnchor = state.inAnchor || tagName.toLowerCase() === "a";
379
- if (noInnerParse) ast.text = capture[3];
380
- else {
381
- const prevInHTML = state.inHTML;
382
- state.inHTML = true;
383
- ast.children = parseFunc(parse, trimmed, state);
384
- state.inHTML = prevInHTML;
385
- }
386
- state.inAnchor = false;
387
- return ast;
388
- },
389
- _render(node, output, state = {}) {
390
- return createElement(node.tag, {
391
- key: state.key,
392
- ...node.attrs ?? {}
393
- }, node.text ?? (node.children ? output(node.children, state) : ""));
394
- }
395
- },
538
+ [require_markdown_constants.RuleType.htmlBlock]: pairedElementRule(require_markdown_elementScanner.matchHtmlBlockElement, require_markdown_constants.Priority.HIGH, true, require_markdown_constants.SCOPE_BOTH),
396
539
  [require_markdown_constants.RuleType.htmlComment]: {
540
+ _scope: require_markdown_constants.SCOPE_BOTH,
397
541
  _qualify: ["<!"],
398
542
  _match: require_markdown_utils.anyScopeRegex(require_markdown_constants.HTML_COMMENT_R),
399
543
  _order: require_markdown_constants.Priority.HIGH,
@@ -401,14 +545,12 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
401
545
  _render: require_markdown_utils.renderNothing
402
546
  },
403
547
  [require_markdown_constants.RuleType.htmlSelfClosing]: {
404
- _qualify: (source) => {
405
- if (options.disableParsingRawHTML) return false;
406
- return require_markdown_constants.HTML_SELF_CLOSING_OPENING_TAG_R.test(source);
407
- },
408
- _match: require_markdown_utils.anyScopeRegex(require_markdown_constants.HTML_SELF_CLOSING_ELEMENT_R),
548
+ _scope: require_markdown_constants.SCOPE_BOTH,
549
+ _qualify: ["<"],
550
+ _match: require_markdown_utils.anyScopeRegex(require_markdown_elementScanner.matchSelfClosingElement),
409
551
  _order: require_markdown_constants.Priority.HIGH,
410
552
  _parse(capture) {
411
- const tag = capture[1].trim();
553
+ const tag = (capture[1] ?? "").trim();
412
554
  return {
413
555
  attrs: attrStringToMap(tag, capture[2] || ""),
414
556
  tag
@@ -421,34 +563,10 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
421
563
  });
422
564
  }
423
565
  },
424
- [require_markdown_constants.RuleType.customComponent]: {
425
- _qualify: (source) => require_markdown_constants.CUSTOM_COMPONENT_OPENING_TAG_R.test(source),
426
- _match: require_markdown_utils.anyScopeRegex(require_markdown_constants.CUSTOM_COMPONENT_R),
427
- _order: require_markdown_constants.Priority.MAX,
428
- _parse(capture, parse, state) {
429
- const whitespace = capture[3].match(require_markdown_constants.HTML_LEFT_TRIM_AMOUNT_R)?.[1] ?? "";
430
- const trimmed = require_markdown_utils.trimLeadingWhitespaceOutsideFences(capture[3], whitespace);
431
- const parseFunc = containsBlockSyntax(trimmed) ? require_markdown_utils.parseBlock : require_markdown_utils.parseInline;
432
- const tag = capture[1].trim();
433
- const ast = {
434
- attrs: attrStringToMap(tag, capture[2] ?? ""),
435
- noInnerParse: false,
436
- tag
437
- };
438
- const prevInHTML = state.inHTML;
439
- state.inHTML = true;
440
- ast.children = parseFunc(parse, trimmed, state);
441
- state.inHTML = prevInHTML;
442
- return ast;
443
- },
444
- _render(node, output, state = {}) {
445
- return createElement(node.tag, {
446
- key: state.key,
447
- ...node.attrs ?? {}
448
- }, node.text ?? (node.children ? output(node.children, state) : ""));
449
- }
450
- },
566
+ [require_markdown_constants.RuleType.customComponent]: pairedElementRule(require_markdown_elementScanner.matchCustomComponent, require_markdown_constants.Priority.MAX, false, require_markdown_constants.SCOPE_BOTH),
451
567
  [require_markdown_constants.RuleType.paragraph]: {
568
+ _scope: require_markdown_constants.SCOPE_BLOCK,
569
+ _qualify: (_source, state) => !state.inline && !state.simple,
452
570
  _match: matchParagraph,
453
571
  _order: require_markdown_constants.Priority.LOW,
454
572
  _parse: require_markdown_utils.parseCaptureInline,
@@ -457,14 +575,16 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
457
575
  }
458
576
  },
459
577
  [require_markdown_constants.RuleType.image]: {
460
- _qualify: ["!["],
578
+ _scope: require_markdown_constants.SCOPE_INLINE,
579
+ _firstChars: [33],
580
+ _qualify: (source) => source.startsWith("![") && source.indexOf("](") !== -1,
461
581
  _match: require_markdown_utils.simpleInlineRegex(IMAGE_R),
462
582
  _order: require_markdown_constants.Priority.HIGH,
463
583
  _parse(capture) {
464
584
  return {
465
- alt: require_markdown_utils.unescapeString(capture[1]),
466
- target: require_markdown_utils.unescapeString(capture[2]),
467
- title: require_markdown_utils.unescapeString(capture[3])
585
+ alt: require_markdown_utils.unescapeString(capture[1] ?? ""),
586
+ target: require_markdown_utils.unescapeString(capture[2] ?? ""),
587
+ title: capture[3] ? require_markdown_utils.unescapeString(capture[3]) : void 0
468
588
  };
469
589
  },
470
590
  _render(node, _, state = {}) {
@@ -477,14 +597,16 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
477
597
  }
478
598
  },
479
599
  [require_markdown_constants.RuleType.link]: {
480
- _qualify: ["["],
600
+ _scope: require_markdown_constants.SCOPE_INLINE,
601
+ _firstChars: [91],
602
+ _qualify: (source) => source.charCodeAt(0) === 91 && source.indexOf("](") !== -1,
481
603
  _match: require_markdown_utils.inlineRegex(LINK_R),
482
604
  _order: require_markdown_constants.Priority.LOW,
483
605
  _parse(capture, parse, state) {
484
606
  return {
485
- children: require_markdown_utils.parseSimpleInline(parse, capture[1], state),
486
- target: require_markdown_utils.unescapeString(capture[2]),
487
- title: require_markdown_utils.unescapeString(capture[3])
607
+ children: require_markdown_utils.parseSimpleInline(parse, capture[1] ?? "", state),
608
+ target: require_markdown_utils.unescapeString(capture[2] ?? ""),
609
+ title: capture[3] ? require_markdown_utils.unescapeString(capture[3]) : void 0
488
610
  };
489
611
  },
490
612
  _render(node, output, state = {}) {
@@ -497,11 +619,12 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
497
619
  }
498
620
  },
499
621
  [require_markdown_constants.RuleType.linkAngleBraceStyleDetector]: {
622
+ _scope: require_markdown_constants.SCOPE_INLINE,
500
623
  _qualify: ["<"],
501
624
  _match: require_markdown_utils.inlineRegex(require_markdown_constants.LINK_AUTOLINK_R),
502
625
  _order: require_markdown_constants.Priority.MAX,
503
626
  _parse(capture) {
504
- let target = capture[1];
627
+ let target = capture[1] ?? "";
505
628
  let isEmail = false;
506
629
  if (target.indexOf("@") !== -1 && target.indexOf("//") === -1) {
507
630
  isEmail = true;
@@ -518,21 +641,26 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
518
641
  }
519
642
  },
520
643
  [require_markdown_constants.RuleType.linkBareUrlDetector]: {
521
- _qualify: (source, state) => !!(state.inline && !state.inAnchor && !options.disableAutoLink && (require_markdown_utils.startsWith(source, "http://") || require_markdown_utils.startsWith(source, "https://"))),
644
+ _scope: require_markdown_constants.SCOPE_INLINE,
645
+ _firstChars: [104],
646
+ _qualify: (source, state) => Boolean(state.inline && !state.inAnchor && !options.disableAutoLink && (require_markdown_utils.startsWith(source, "http://") || require_markdown_utils.startsWith(source, "https://"))),
522
647
  _match: require_markdown_utils.inlineRegex(require_markdown_constants.LINK_AUTOLINK_BARE_URL_R),
523
648
  _order: require_markdown_constants.Priority.MAX,
524
649
  _parse(capture) {
650
+ const url = capture[1] ?? "";
525
651
  return {
526
652
  children: [{
527
- text: capture[1],
653
+ text: url,
528
654
  type: require_markdown_constants.RuleType.text
529
655
  }],
530
- target: capture[1],
656
+ target: url,
531
657
  type: require_markdown_constants.RuleType.link
532
658
  };
533
659
  }
534
660
  },
535
661
  [require_markdown_constants.RuleType.newlineCoalescer]: {
662
+ _scope: require_markdown_constants.SCOPE_BOTH,
663
+ _qualify: ["\n"],
536
664
  _match: require_markdown_utils.blockRegex(require_markdown_constants.CONSECUTIVE_NEWLINE_R),
537
665
  _order: require_markdown_constants.Priority.LOW,
538
666
  _parse: require_markdown_utils.captureNothing,
@@ -543,12 +671,14 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
543
671
  [require_markdown_constants.RuleType.orderedList]: generateListRule(1),
544
672
  [require_markdown_constants.RuleType.unorderedList]: generateListRule(2),
545
673
  [require_markdown_constants.RuleType.ref]: {
674
+ _scope: require_markdown_constants.SCOPE_BOTH,
546
675
  _qualify: ["["],
547
676
  _match: require_markdown_utils.anyScopeRegex(require_markdown_constants.REFERENCE_IMAGE_OR_LINK),
548
677
  _order: require_markdown_constants.Priority.MAX,
549
678
  _parse(capture) {
550
- refs[capture[1]] = {
551
- target: capture[2],
679
+ const identifier = capture[1];
680
+ if (identifier !== void 0) scope.current.references[identifier] = {
681
+ target: capture[2] ?? "",
552
682
  title: capture[4]
553
683
  };
554
684
  return {};
@@ -556,17 +686,19 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
556
686
  _render: require_markdown_utils.renderNothing
557
687
  },
558
688
  [require_markdown_constants.RuleType.refImage]: {
559
- _qualify: ["!["],
689
+ _scope: require_markdown_constants.SCOPE_INLINE,
690
+ _firstChars: [33],
691
+ _qualify: (source) => source.startsWith("![") && source.indexOf("](") === -1,
560
692
  _match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.REFERENCE_IMAGE_R),
561
693
  _order: require_markdown_constants.Priority.MAX,
562
694
  _parse(capture) {
563
695
  return {
564
696
  alt: capture[1] ? require_markdown_utils.unescapeString(capture[1]) : void 0,
565
- ref: capture[2]
697
+ ref: capture[2] ?? ""
566
698
  };
567
699
  },
568
700
  _render(node, _, state = {}) {
569
- const ref = refs[node.ref];
701
+ const ref = scope.current.references[node.ref];
570
702
  if (!ref) return null;
571
703
  return createElement("img", {
572
704
  key: state.key,
@@ -577,18 +709,20 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
577
709
  }
578
710
  },
579
711
  [require_markdown_constants.RuleType.refLink]: {
580
- _qualify: (source) => source[0] === "[" && source.indexOf("](") === -1,
712
+ _scope: require_markdown_constants.SCOPE_INLINE,
713
+ _firstChars: [91],
714
+ _qualify: (source) => source.indexOf("](") === -1,
581
715
  _match: require_markdown_utils.inlineRegex(require_markdown_constants.REFERENCE_LINK_R),
582
716
  _order: require_markdown_constants.Priority.MAX,
583
717
  _parse(capture, parse, state) {
584
718
  return {
585
- children: require_markdown_utils.parseSimpleInline(parse, capture[1], state),
586
- fallbackChildren: capture[0],
587
- ref: capture[2]
719
+ children: require_markdown_utils.parseSimpleInline(parse, capture[1] ?? "", state),
720
+ fallbackChildren: capture[0] ?? "",
721
+ ref: capture[2] ?? ""
588
722
  };
589
723
  },
590
724
  _render(node, output, state = {}) {
591
- const ref = refs[node.ref];
725
+ const ref = scope.current.references[node.ref];
592
726
  if (!ref) return createElement("span", { key: state.key }, node.fallbackChildren);
593
727
  return createElement("a", {
594
728
  key: state.key,
@@ -598,6 +732,7 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
598
732
  }
599
733
  },
600
734
  [require_markdown_constants.RuleType.table]: {
735
+ _scope: require_markdown_constants.SCOPE_BLOCK,
601
736
  _qualify: ["|"],
602
737
  _match: require_markdown_utils.blockRegex(require_markdown_constants.NP_TABLE_R),
603
738
  _order: require_markdown_constants.Priority.HIGH,
@@ -605,7 +740,7 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
605
740
  state.inline = true;
606
741
  const align = capture[2] ? require_markdown_utils.parseTableAlign(capture[2]) : [];
607
742
  const cells = capture[3] ? require_markdown_utils.parseTableCells(capture[3], parse, state) : [];
608
- const header = require_markdown_utils.parseTableRow(capture[1], parse, state, !!cells.length);
743
+ const header = require_markdown_utils.parseTableRow(capture[1] ?? "", parse, state, !!cells.length);
609
744
  state.inline = false;
610
745
  return cells.length ? {
611
746
  align,
@@ -620,17 +755,19 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
620
755
  _render(node, output, state = {}) {
621
756
  const table = node;
622
757
  const getStyle = (i) => table.align[i] && table.align[i] !== "left" ? { textAlign: table.align[i] } : {};
623
- return createElement("table", { key: state.key }, createElement("thead", null, createElement("tr", null, ...table.header.map((c, i) => createElement("th", {
758
+ return createElement("table", { key: state.key }, createElement("thead", { key: "thead" }, createElement("tr", null, ...table.header.map((c, i) => createElement("th", {
624
759
  key: i,
625
760
  style: getStyle(i)
626
- }, output(c, state))))), createElement("tbody", null, ...table.cells.map((row, i) => createElement("tr", { key: i }, ...row.map((c, j) => createElement("td", {
761
+ }, output(c, state))))), createElement("tbody", { key: "tbody" }, ...table.cells.map((row, i) => createElement("tr", { key: i }, ...row.map((c, j) => createElement("td", {
627
762
  key: j,
628
763
  style: getStyle(j)
629
764
  }, output(c, state)))))));
630
765
  }
631
766
  },
632
767
  [require_markdown_constants.RuleType.tableSeparator]: {
633
- _match: (source, state) => state.inTable && source[0] === "|" ? /^\|/.exec(source) : null,
768
+ _scope: require_markdown_constants.SCOPE_INLINE,
769
+ _qualify: ["|"],
770
+ _match: (source, state) => state.inTable ? /^\|/.exec(source) : null,
634
771
  _order: require_markdown_constants.Priority.HIGH,
635
772
  _parse() {
636
773
  return { type: require_markdown_constants.RuleType.tableSeparator };
@@ -640,90 +777,180 @@ const createRules = (createElement, ctx, options, footnotes, refs, attrStringToM
640
777
  }
641
778
  },
642
779
  [require_markdown_constants.RuleType.text]: {
780
+ _scope: require_markdown_constants.SCOPE_INLINE,
643
781
  _match: require_markdown_utils.allowInline((source, _state) => {
644
- const shortMatch = require_markdown_constants.SHORTCODE_R.exec(source);
645
- if (shortMatch) return shortMatch;
646
- return require_markdown_constants.TEXT_PLAIN_R.exec(source) || /^[\s\S]/.exec(source);
782
+ const len = source.length;
783
+ if (source.charCodeAt(0) === 10) {
784
+ let j = 1;
785
+ while (j < len && source.charCodeAt(j) === 32) j++;
786
+ if (j < len && (source.charCodeAt(j) === 42 || source.charCodeAt(j) === 43 || source.charCodeAt(j) === 45 || source.charCodeAt(j) >= 48 && source.charCodeAt(j) <= 57)) return [source.slice(0, j)];
787
+ return ["\n"];
788
+ }
789
+ if (source.charCodeAt(0) === 58) {
790
+ const shortMatch = require_markdown_constants.SHORTCODE_R.exec(source);
791
+ if (shortMatch) return shortMatch;
792
+ }
793
+ TEXT_RUN_R.lastIndex = 1;
794
+ TEXT_RUN_R.test(source);
795
+ TEXT_CAPTURE[0] = source.slice(0, trimHardBreak(source, TEXT_RUN_R.lastIndex));
796
+ return TEXT_CAPTURE;
647
797
  }),
648
798
  _order: require_markdown_constants.Priority.MIN,
649
799
  _parse(capture) {
650
- const text = capture[0];
651
- return { text: text.indexOf("&") === -1 ? text : text.replace(require_markdown_constants.HTML_CHAR_CODE_R, (f, i) => {
652
- if (i.startsWith("#x")) return String.fromCharCode(parseInt(i.slice(2), 16));
653
- if (i.startsWith("#")) return String.fromCharCode(parseInt(i.slice(1), 10));
654
- return namedCodesToUnicode[i] || f;
655
- }) };
800
+ const text = capture[0] ?? "";
801
+ return {
802
+ type: require_markdown_constants.RuleType.text,
803
+ text: text.charCodeAt(0) !== 38 ? text : text.replace(require_markdown_constants.HTML_CHAR_CODE_R, (f, i) => {
804
+ if (i.startsWith("#x")) return String.fromCharCode(parseInt(i.slice(2), 16));
805
+ if (i.startsWith("#")) return String.fromCharCode(parseInt(i.slice(1), 10));
806
+ return namedCodesToUnicode[i] || f;
807
+ })
808
+ };
656
809
  },
657
810
  _render(node) {
658
811
  return node.text;
659
812
  }
660
813
  },
661
814
  [require_markdown_constants.RuleType.textBolded]: {
662
- _qualify: ["**", "__"],
815
+ _scope: require_markdown_constants.SCOPE_INLINE,
816
+ _firstChars: [42, 95],
817
+ _qualify: (source) => {
818
+ const c = source.charCodeAt(0);
819
+ if (c === 42) {
820
+ const next = source.charCodeAt(2);
821
+ if (next === 32 || next === 10 || next === 9) return false;
822
+ return source.charCodeAt(1) === 42 && source.indexOf("**", 2) !== -1;
823
+ }
824
+ if (c === 95) {
825
+ const next = source.charCodeAt(2);
826
+ if (next === 32 || next === 10 || next === 9) return false;
827
+ return source.charCodeAt(1) === 95 && source.indexOf("__", 2) !== -1;
828
+ }
829
+ return false;
830
+ },
663
831
  _match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_BOLD_R),
664
832
  _order: require_markdown_constants.Priority.MED,
665
833
  _parse(capture, parse, state) {
666
- return { children: parse(capture[2], state) };
834
+ return { children: parse(capture[2] ?? "", state) };
667
835
  },
668
836
  _render(node, output, state = {}) {
669
837
  return createElement("strong", { key: state.key }, output(node.children, state));
670
838
  }
671
839
  },
672
840
  [require_markdown_constants.RuleType.textEmphasized]: {
673
- _qualify: ["*", "_"],
841
+ _scope: require_markdown_constants.SCOPE_INLINE,
842
+ _firstChars: [42, 95],
843
+ _qualify: (source) => {
844
+ const c = source.charCodeAt(0);
845
+ const next = source.charCodeAt(1);
846
+ if (next === 32 || next === 10 || next === 9) return false;
847
+ return c === 42 && source.indexOf("*", 1) !== -1 || c === 95 && source.indexOf("_", 1) !== -1;
848
+ },
674
849
  _match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_EMPHASIZED_R),
675
850
  _order: require_markdown_constants.Priority.LOW,
676
851
  _parse(capture, parse, state) {
677
- return { children: parse(capture[2], state) };
852
+ return { children: parse(capture[2] ?? "", state) };
678
853
  },
679
854
  _render(node, output, state = {}) {
680
855
  return createElement("em", { key: state.key }, output(node.children, state));
681
856
  }
682
857
  },
683
858
  [require_markdown_constants.RuleType.textEscaped]: {
859
+ _scope: require_markdown_constants.SCOPE_INLINE,
684
860
  _qualify: ["\\"],
685
861
  _match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_ESCAPED_R),
686
862
  _order: require_markdown_constants.Priority.HIGH,
687
863
  _parse(capture) {
688
864
  return {
689
- text: capture[1],
865
+ text: capture[1] ?? "",
690
866
  type: require_markdown_constants.RuleType.text
691
867
  };
692
868
  }
693
869
  },
694
870
  [require_markdown_constants.RuleType.textMarked]: {
695
- _qualify: ["=="],
871
+ _scope: require_markdown_constants.SCOPE_INLINE,
872
+ _firstChars: [61],
873
+ _qualify: (source) => {
874
+ const next = source.charCodeAt(2);
875
+ if (next === 32 || next === 10 || next === 9) return false;
876
+ return source.charCodeAt(1) === 61 && source.indexOf("==", 2) !== -1;
877
+ },
696
878
  _match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_MARKED_R),
697
879
  _order: require_markdown_constants.Priority.LOW,
698
- _parse: require_markdown_utils.parseCaptureInline,
880
+ _parse(capture, parse, state) {
881
+ return { children: require_markdown_utils.parseCaptureInline(capture, parse, state).children };
882
+ },
699
883
  _render(node, output, state = {}) {
700
884
  return createElement("mark", { key: state.key }, output(node.children, state));
701
885
  }
702
886
  },
703
887
  [require_markdown_constants.RuleType.textStrikethroughed]: {
704
- _qualify: ["~~"],
888
+ _scope: require_markdown_constants.SCOPE_INLINE,
889
+ _firstChars: [126],
890
+ _qualify: (source) => {
891
+ const next = source.charCodeAt(2);
892
+ if (next === 32 || next === 10 || next === 9) return false;
893
+ return source.charCodeAt(1) === 126 && source.indexOf("~~", 2) !== -1;
894
+ },
705
895
  _match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_STRIKETHROUGHED_R),
706
896
  _order: require_markdown_constants.Priority.LOW,
707
- _parse: require_markdown_utils.parseCaptureInline,
897
+ _parse(capture, parse, state) {
898
+ return { children: require_markdown_utils.parseCaptureInline(capture, parse, state).children };
899
+ },
708
900
  _render(node, output, state = {}) {
709
901
  return createElement("del", { key: state.key }, output(node.children, state));
710
902
  }
711
903
  }
712
904
  };
713
905
  };
906
+ const STRIP_INDENT_REGEXES = [
907
+ null,
908
+ /^ {1,1}/gm,
909
+ /^ {1,2}/gm,
910
+ /^ {1,3}/gm,
911
+ /^ {1,4}/gm,
912
+ /^ {1,5}/gm,
913
+ /^ {1,6}/gm,
914
+ /^ {1,7}/gm,
915
+ /^ {1,8}/gm
916
+ ];
917
+ /** Scratch capture reused by the text rule; see its `_match`. */
918
+ const TEXT_CAPTURE = [""];
714
919
  /**
715
- * `createElement` is only ever reached from a rule's `_render`, so a parse-only
716
- * caller can hand over this stub instead of building an element factory.
920
+ * Consumes a run of plain text, stopping before the next character that could
921
+ * open another inline rule or a bare URL. Anchored so `test` leaves the stop
922
+ * offset in `lastIndex` without allocating a match array, and so the scan
923
+ * itself runs in the regex engine.
924
+ *
925
+ * The bare-URL guard is an alternation branch rather than a per-character
926
+ * lookahead, because a lookahead is re-evaluated at every offset while this
927
+ * branch is only reached on an `h`. `&` stops a run purely so that an HTML
928
+ * entity can only ever sit at offset 0 of a text node; adjacent text nodes are
929
+ * merged by the parser, so the tree is unchanged.
717
930
  */
718
- const noopCreateElement = () => null;
931
+ const TEXT_RUN_R = /(?:[^\n&h!*:<=[\\_`~]+|h(?!ttp))*/y;
932
+ /**
933
+ * Pull a run's stop offset back before a hard line break it just swallowed.
934
+ *
935
+ * A run never contains a newline, so ` \n` can only sit immediately before the
936
+ * stop offset — which makes this O(1) check equivalent to the per-character
937
+ * `(?! {2}\n)` lookahead the run scanner used to carry.
938
+ */
939
+ const trimHardBreak = (source, end) => end >= 3 && source.charCodeAt(end) === 10 && source.charCodeAt(end - 1) === 32 && source.charCodeAt(end - 2) === 32 ? end - 2 : end;
940
+ const noopCreateElement = (type, props, ...children) => ({
941
+ children,
942
+ props,
943
+ type
944
+ });
719
945
  /**
720
946
  * Builds the rule set backing one document.
721
947
  *
722
- * Rules close over the document's footnote and reference tables, so they cannot
723
- * be shared across documents — but a single document's parse and render phases
724
- * can share one set, which is what `compile` does.
948
+ * Rules read the document's footnote and reference tables through `scope`
949
+ * rather than closing over them, so one set serves every document sharing the
950
+ * same options. Building this graph dominated the cost of compiling the many
951
+ * short strings a dictionary holds; `getRuleSet` caches it.
725
952
  */
726
- const createDocumentRules = (createElement, ctx, options, footnotes, refs) => {
953
+ const createDocumentRules = (createElement, ctx, options, scope) => {
727
954
  const attrStringToMap = (tag, str) => {
728
955
  if (!str?.trim()) return null;
729
956
  const attributes = str.match(require_markdown_constants.ATTR_EXTRACTOR_R);
@@ -736,7 +963,7 @@ const createDocumentRules = (createElement, ctx, options, footnotes, refs) => {
736
963
  const mappedKey = require_markdown_constants.ATTRIBUTE_TO_NODE_PROP_MAP[key] ?? key;
737
964
  if (mappedKey === "ref") return map;
738
965
  map[mappedKey] = require_markdown_utils.attributeValueToNodePropValue(tag, key, value, ctx.sanitizer ?? require_markdown_utils.sanitizer);
739
- if (typeof map[mappedKey] === "string" && (require_markdown_constants.HTML_BLOCK_ELEMENT_R.test(map[mappedKey]) || require_markdown_constants.HTML_SELF_CLOSING_ELEMENT_R.test(map[mappedKey]))) map[mappedKey] = parseMarkdown(map[mappedKey].trim(), ctx, options).ast;
966
+ if (typeof map[mappedKey] === "string" && require_markdown_elementScanner.startsWithElement(map[mappedKey])) map[mappedKey] = parseMarkdown(map[mappedKey].trim(), ctx, options).ast;
740
967
  } else if (raw !== "style") map[require_markdown_constants.ATTRIBUTE_TO_NODE_PROP_MAP[raw] ?? raw] = true;
741
968
  return map;
742
969
  }, {});
@@ -746,19 +973,18 @@ const createDocumentRules = (createElement, ctx, options, footnotes, refs) => {
746
973
  require_markdown_constants.CODE_BLOCK_FENCED_R,
747
974
  require_markdown_constants.CODE_BLOCK_R,
748
975
  options.enforceAtxHeadings ? require_markdown_constants.HEADING_ATX_COMPLIANT_R : require_markdown_constants.HEADING_R,
749
- require_markdown_constants.HEADING_SETEXT_R,
750
976
  require_markdown_constants.NP_TABLE_R,
751
977
  require_markdown_constants.ORDERED_LIST_R,
752
978
  require_markdown_constants.UNORDERED_LIST_R,
753
- require_markdown_constants.CUSTOM_COMPONENT_R
979
+ require_markdown_elementScanner.startsWithCustomComponent
754
980
  ];
755
981
  const blockSyntaxes = options.disableParsingRawHTML ? nonParagraphBlockSyntaxes : [
756
982
  ...nonParagraphBlockSyntaxes,
757
983
  require_markdown_constants.PARAGRAPH_R,
758
- require_markdown_constants.HTML_BLOCK_ELEMENT_R,
984
+ require_markdown_elementScanner.startsWithHtmlBlockElement,
759
985
  require_markdown_constants.HTML_COMMENT_R,
760
- require_markdown_constants.HTML_SELF_CLOSING_ELEMENT_R,
761
- require_markdown_constants.CUSTOM_COMPONENT_R
986
+ require_markdown_elementScanner.startsWithSelfClosingElement,
987
+ require_markdown_elementScanner.startsWithCustomComponent
762
988
  ];
763
989
  const containsBlockSyntax = (input) => {
764
990
  const cleaned = input.replace(require_markdown_constants.TRIM_STARTING_NEWLINES, "");
@@ -766,17 +992,16 @@ const createDocumentRules = (createElement, ctx, options, footnotes, refs) => {
766
992
  if (slice.indexOf("\n\n") !== -1) return true;
767
993
  return require_markdown_utils.some(blockSyntaxes, slice);
768
994
  };
769
- const baseRules = createRules(createElement, ctx, options, footnotes, refs, attrStringToMap, containsBlockSyntax, nonParagraphBlockSyntaxes);
995
+ const baseRules = createRules(createElement, ctx, options, scope, attrStringToMap, containsBlockSyntax, nonParagraphBlockSyntaxes);
770
996
  return options.disableParsingRawHTML ? Object.keys(baseRules).reduce((acc, key) => {
771
997
  if (key !== require_markdown_constants.RuleType.htmlBlock && key !== require_markdown_constants.RuleType.htmlSelfClosing) acc[key] = baseRules[key];
772
998
  return acc;
773
999
  }, {}) : baseRules;
774
1000
  };
775
1001
  /** Runs the parse phase against an already-built rule set. */
776
- const parseWithRules = (markdown, options, rules, footnotes, refs) => {
777
- const parser = require_markdown_parser.parserFor(rules);
778
- const result = options.preserveFrontmatter ? markdown : markdown.replace(require_markdown_constants.FRONT_MATTER_R, "");
779
- const trimmedStart = result.replace(require_markdown_constants.TRIM_STARTING_NEWLINES, "");
1002
+ const parseWithRules = (markdown, options, parser, footnotes, refs) => {
1003
+ const result = !options.preserveFrontmatter && markdown.charCodeAt(0) === 45 ? markdown.replace(require_markdown_constants.FRONT_MATTER_R, "") : markdown;
1004
+ const trimmedStart = result.charCodeAt(0) === 10 ? result.replace(require_markdown_constants.TRIM_STARTING_NEWLINES, "") : result;
780
1005
  const inline = options.forceInline || !options.forceBlock && require_markdown_constants.SHOULD_RENDER_AS_BLOCK_R.test(trimmedStart) === false;
781
1006
  const ast = parser(inline ? result : `${require_markdown_utils.trimEnd(trimmedStart)}\n\n`, { inline });
782
1007
  if (footnotes.length > 0) for (const def of footnotes) def.parsedAst = parser(def.footnote, { inline: true });
@@ -788,11 +1013,10 @@ const parseWithRules = (markdown, options, rules, footnotes, refs) => {
788
1013
  };
789
1014
  };
790
1015
  /** Runs the render phase against an already-built rule set. */
791
- const renderWithRules = (parsed, ctx, options, rules, createElement) => {
1016
+ const renderWithRules = (parsed, ctx, options, emitter, createElement) => {
792
1017
  const components = ctx.components ?? {};
793
1018
  const slug = createSlugger(ctx);
794
1019
  const footnotes = parsed.footnotes || [];
795
- const emitter = require_markdown_renderer.renderFor(require_markdown_renderer.createRenderer(rules, options.renderRule));
796
1020
  const inline = parsed.inline;
797
1021
  const arr = emitter(parsed.ast, { inline });
798
1022
  while (typeof arr[arr.length - 1] === "string" && !arr[arr.length - 1].trim()) arr.pop();
@@ -802,6 +1026,7 @@ const renderWithRules = (parsed, ctx, options, rules, createElement) => {
802
1026
  if (arr.length > 1 || options.forceWrapper) return createElement(wrapper, { key: "outer" }, arr);
803
1027
  if (arr.length === 1) {
804
1028
  const node = arr[0];
1029
+ if (Array.isArray(node)) return createElement(wrapper, { key: "outer" }, node);
805
1030
  if (typeof node === "string") {
806
1031
  const spanProps = { key: "outer" };
807
1032
  if (!inline && components) {
@@ -827,27 +1052,29 @@ const renderWithRules = (parsed, ctx, options, rules, createElement) => {
827
1052
  }, def.identifier, emitter(def.parsedAst || def.footnote, { inline: true }))))) : node;
828
1053
  };
829
1054
  const parseMarkdown = (markdown = "", ctx, options = {}) => {
830
- const footnotes = [];
831
- const refs = {};
832
- const rules = createDocumentRules(noopCreateElement, ctx, options, footnotes, refs);
833
- return parseWithRules(markdown, options, rules, footnotes, refs);
1055
+ const { parse, scope } = getRuleSet(ctx, options, true);
1056
+ const documentScope = createDocumentScope();
1057
+ return withDocumentScope(scope, documentScope, () => parseWithRules(markdown, options, parse, documentScope.footnotes, documentScope.references));
834
1058
  };
835
1059
  const renderMarkdownAst = (parsed, ctx, options = {}) => {
836
- const createElement = createElementFactory(ctx, options);
837
- const rules = createDocumentRules(createElement, ctx, options, parsed.footnotes ?? [], parsed.references ?? {});
838
- return renderWithRules(parsed, ctx, options, rules, createElement);
1060
+ const { emit, createElement, scope } = getRuleSet(ctx, options, false);
1061
+ const documentScope = {
1062
+ footnotes: parsed.footnotes ?? [],
1063
+ references: parsed.references ?? {}
1064
+ };
1065
+ return withDocumentScope(scope, documentScope, () => renderWithRules(parsed, ctx, options, emit, createElement));
839
1066
  };
840
1067
  const compile = (markdown = "", ctx, options = {}) => {
841
1068
  if (typeof markdown !== "string") {
842
1069
  if (process.env.NODE_ENV !== "production") console.error("intlayer: the first argument must be a string. Received", typeof markdown);
843
1070
  throw new Error("intlayer: the first argument must be a string");
844
1071
  }
845
- const footnotes = [];
846
- const refs = {};
847
- const createElement = createElementFactory(ctx, options);
848
- const rules = createDocumentRules(createElement, ctx, options, footnotes, refs);
849
- const parsed = parseWithRules(markdown, options, rules, footnotes, refs);
850
- return renderWithRules(parsed, ctx, options, rules, createElement);
1072
+ const { parse, emit, createElement, scope } = getRuleSet(ctx, options, false);
1073
+ const documentScope = createDocumentScope();
1074
+ return withDocumentScope(scope, documentScope, () => {
1075
+ const parsed = parseWithRules(markdown, options, parse, documentScope.footnotes, documentScope.references);
1076
+ return renderWithRules(parsed, ctx, options, emit, createElement);
1077
+ });
851
1078
  };
852
1079
  const createCompiler = (ctx) => (markdown, options) => compile(markdown, ctx, options);
853
1080
  const compileWithOptions = (markdown, runtime, options = {}) => {
@@ -865,6 +1092,7 @@ const compileWithOptions = (markdown, runtime, options = {}) => {
865
1092
  exports.compile = compile;
866
1093
  exports.compileWithOptions = compileWithOptions;
867
1094
  exports.createCompiler = createCompiler;
1095
+ exports.getRuleSet = getRuleSet;
868
1096
  exports.parseMarkdown = parseMarkdown;
869
1097
  exports.renderMarkdownAst = renderMarkdownAst;
870
1098
  //# sourceMappingURL=compiler.cjs.map