@temelj/mdx 0.14.0 → 0.16.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 (381) hide show
  1. package/README.md +470 -82
  2. package/dist/character-entities.d.mts +4 -0
  3. package/dist/character-entities.d.mts.map +1 -0
  4. package/dist/character-entities.mjs +2132 -0
  5. package/dist/character-entities.mjs.map +1 -0
  6. package/dist/character-reference.d.mts +6 -0
  7. package/dist/character-reference.d.mts.map +1 -0
  8. package/dist/character-reference.mjs +18 -0
  9. package/dist/character-reference.mjs.map +1 -0
  10. package/dist/compile-analysis.d.mts +28 -0
  11. package/dist/compile-analysis.d.mts.map +1 -0
  12. package/dist/compile-analysis.mjs +74 -0
  13. package/dist/compile-analysis.mjs.map +1 -0
  14. package/dist/compile-emit.d.mts +9 -0
  15. package/dist/compile-emit.d.mts.map +1 -0
  16. package/dist/compile-emit.mjs +187 -0
  17. package/dist/compile-emit.mjs.map +1 -0
  18. package/dist/compile-esm.d.mts +34 -0
  19. package/dist/compile-esm.d.mts.map +1 -0
  20. package/dist/compile-esm.mjs +187 -0
  21. package/dist/compile-esm.mjs.map +1 -0
  22. package/dist/compile-names.d.mts +13 -0
  23. package/dist/compile-names.d.mts.map +1 -0
  24. package/dist/compile-names.mjs +32 -0
  25. package/dist/compile-names.mjs.map +1 -0
  26. package/dist/compiler.d.mts +69 -85
  27. package/dist/compiler.d.mts.map +1 -1
  28. package/dist/compiler.mjs +167 -420
  29. package/dist/compiler.mjs.map +1 -1
  30. package/dist/diagnostics.d.mts +37 -0
  31. package/dist/diagnostics.d.mts.map +1 -0
  32. package/dist/diagnostics.mjs +57 -0
  33. package/dist/diagnostics.mjs.map +1 -0
  34. package/dist/errors.d.mts +157 -0
  35. package/dist/errors.d.mts.map +1 -0
  36. package/dist/errors.mjs +263 -0
  37. package/dist/errors.mjs.map +1 -0
  38. package/dist/footnote-numbering.d.mts +27 -0
  39. package/dist/footnote-numbering.d.mts.map +1 -0
  40. package/dist/footnote-numbering.mjs +49 -0
  41. package/dist/footnote-numbering.mjs.map +1 -0
  42. package/dist/format-context.d.mts +46 -0
  43. package/dist/format-context.d.mts.map +1 -0
  44. package/dist/format-context.mjs +26 -0
  45. package/dist/format-context.mjs.map +1 -0
  46. package/dist/format-directive.d.mts +9 -0
  47. package/dist/format-directive.d.mts.map +1 -0
  48. package/dist/format-directive.mjs +99 -0
  49. package/dist/format-directive.mjs.map +1 -0
  50. package/dist/format-jsx.d.mts +8 -0
  51. package/dist/format-jsx.d.mts.map +1 -0
  52. package/dist/format-jsx.mjs +47 -0
  53. package/dist/format-jsx.mjs.map +1 -0
  54. package/dist/format-math.d.mts +9 -0
  55. package/dist/format-math.d.mts.map +1 -0
  56. package/dist/format-math.mjs +79 -0
  57. package/dist/format-math.mjs.map +1 -0
  58. package/dist/format-safe.d.mts +25 -0
  59. package/dist/format-safe.d.mts.map +1 -0
  60. package/dist/format-safe.mjs +366 -0
  61. package/dist/format-safe.mjs.map +1 -0
  62. package/dist/format-table.d.mts +8 -0
  63. package/dist/format-table.d.mts.map +1 -0
  64. package/dist/format-table.mjs +55 -0
  65. package/dist/format-table.mjs.map +1 -0
  66. package/dist/format-track.d.mts +18 -0
  67. package/dist/format-track.d.mts.map +1 -0
  68. package/dist/format-track.mjs +34 -0
  69. package/dist/format-track.mjs.map +1 -0
  70. package/dist/format.d.mts +7 -0
  71. package/dist/format.d.mts.map +1 -0
  72. package/dist/format.mjs +549 -0
  73. package/dist/format.mjs.map +1 -0
  74. package/dist/frontmatter-decode.d.mts +15 -0
  75. package/dist/frontmatter-decode.d.mts.map +1 -0
  76. package/dist/frontmatter-decode.mjs +187 -0
  77. package/dist/frontmatter-decode.mjs.map +1 -0
  78. package/dist/frontmatter-schema.d.mts +8 -0
  79. package/dist/frontmatter-schema.d.mts.map +1 -0
  80. package/dist/frontmatter-schema.mjs +28 -0
  81. package/dist/frontmatter-schema.mjs.map +1 -0
  82. package/dist/frontmatter.d.mts +40 -0
  83. package/dist/frontmatter.d.mts.map +1 -0
  84. package/dist/frontmatter.mjs +109 -0
  85. package/dist/frontmatter.mjs.map +1 -0
  86. package/dist/heading.d.mts +6 -0
  87. package/dist/heading.d.mts.map +1 -0
  88. package/dist/heading.mjs +19 -0
  89. package/dist/heading.mjs.map +1 -0
  90. package/dist/html-format.d.mts +32 -0
  91. package/dist/html-format.d.mts.map +1 -0
  92. package/dist/html-format.mjs +127 -0
  93. package/dist/html-format.mjs.map +1 -0
  94. package/dist/html-lower.d.mts +78 -0
  95. package/dist/html-lower.d.mts.map +1 -0
  96. package/dist/html-lower.mjs +583 -0
  97. package/dist/html-lower.mjs.map +1 -0
  98. package/dist/html-stream.d.mts +13 -0
  99. package/dist/html-stream.d.mts.map +1 -0
  100. package/dist/html-stream.mjs +32 -0
  101. package/dist/html-stream.mjs.map +1 -0
  102. package/dist/html.d.mts +120 -0
  103. package/dist/html.d.mts.map +1 -0
  104. package/dist/html.mjs +77 -0
  105. package/dist/html.mjs.map +1 -0
  106. package/dist/identifier.d.mts +4 -0
  107. package/dist/identifier.d.mts.map +1 -0
  108. package/dist/identifier.mjs +8 -0
  109. package/dist/identifier.mjs.map +1 -0
  110. package/dist/javascript-ast.d.mts +16 -0
  111. package/dist/javascript-ast.d.mts.map +1 -0
  112. package/dist/javascript-ast.mjs +39 -0
  113. package/dist/javascript-ast.mjs.map +1 -0
  114. package/dist/javascript-jsx.d.mts +24 -0
  115. package/dist/javascript-jsx.d.mts.map +1 -0
  116. package/dist/javascript-jsx.mjs +189 -0
  117. package/dist/javascript-jsx.mjs.map +1 -0
  118. package/dist/javascript.d.mts +9 -0
  119. package/dist/javascript.d.mts.map +1 -0
  120. package/dist/javascript.mjs +31 -0
  121. package/dist/javascript.mjs.map +1 -0
  122. package/dist/jsx-reference.d.mts +15 -0
  123. package/dist/jsx-reference.d.mts.map +1 -0
  124. package/dist/jsx-reference.mjs +31 -0
  125. package/dist/jsx-reference.mjs.map +1 -0
  126. package/dist/mod.d.mts +26 -9
  127. package/dist/mod.mjs +20 -8
  128. package/dist/model.d.mts +196 -0
  129. package/dist/model.d.mts.map +1 -0
  130. package/dist/model.mjs +113 -0
  131. package/dist/model.mjs.map +1 -0
  132. package/dist/parser/block-container-recognizers.d.mts +40 -0
  133. package/dist/parser/block-container-recognizers.d.mts.map +1 -0
  134. package/dist/parser/block-container-recognizers.mjs +90 -0
  135. package/dist/parser/block-container-recognizers.mjs.map +1 -0
  136. package/dist/parser/block-directive-recognizers.d.mts +22 -0
  137. package/dist/parser/block-directive-recognizers.d.mts.map +1 -0
  138. package/dist/parser/block-directive-recognizers.mjs +77 -0
  139. package/dist/parser/block-directive-recognizers.mjs.map +1 -0
  140. package/dist/parser/block-leaf-recognizers.d.mts +53 -0
  141. package/dist/parser/block-leaf-recognizers.d.mts.map +1 -0
  142. package/dist/parser/block-leaf-recognizers.mjs +386 -0
  143. package/dist/parser/block-leaf-recognizers.mjs.map +1 -0
  144. package/dist/parser/block-parser.d.mts +38 -0
  145. package/dist/parser/block-parser.d.mts.map +1 -0
  146. package/dist/parser/block-parser.mjs +895 -0
  147. package/dist/parser/block-parser.mjs.map +1 -0
  148. package/dist/parser/block-syntax.d.mts +240 -0
  149. package/dist/parser/block-syntax.d.mts.map +1 -0
  150. package/dist/parser/characters.d.mts +19 -0
  151. package/dist/parser/characters.d.mts.map +1 -0
  152. package/dist/parser/characters.mjs +52 -0
  153. package/dist/parser/characters.mjs.map +1 -0
  154. package/dist/parser/config.d.mts +16 -0
  155. package/dist/parser/config.d.mts.map +1 -0
  156. package/dist/parser/config.mjs +25 -0
  157. package/dist/parser/config.mjs.map +1 -0
  158. package/dist/parser/directive-attributes.d.mts +9 -0
  159. package/dist/parser/directive-attributes.d.mts.map +1 -0
  160. package/dist/parser/directive-attributes.mjs +24 -0
  161. package/dist/parser/directive-attributes.mjs.map +1 -0
  162. package/dist/parser/embedded-scanner.d.mts +18 -0
  163. package/dist/parser/embedded-scanner.d.mts.map +1 -0
  164. package/dist/parser/embedded-scanner.mjs +199 -0
  165. package/dist/parser/embedded-scanner.mjs.map +1 -0
  166. package/dist/parser/inline-autolink.d.mts +7 -0
  167. package/dist/parser/inline-autolink.d.mts.map +1 -0
  168. package/dist/parser/inline-autolink.mjs +42 -0
  169. package/dist/parser/inline-autolink.mjs.map +1 -0
  170. package/dist/parser/inline-character-reference.d.mts +7 -0
  171. package/dist/parser/inline-character-reference.d.mts.map +1 -0
  172. package/dist/parser/inline-character-reference.mjs +22 -0
  173. package/dist/parser/inline-character-reference.mjs.map +1 -0
  174. package/dist/parser/inline-code.d.mts +7 -0
  175. package/dist/parser/inline-code.d.mts.map +1 -0
  176. package/dist/parser/inline-code.mjs +29 -0
  177. package/dist/parser/inline-code.mjs.map +1 -0
  178. package/dist/parser/inline-directive.d.mts +9 -0
  179. package/dist/parser/inline-directive.d.mts.map +1 -0
  180. package/dist/parser/inline-directive.mjs +45 -0
  181. package/dist/parser/inline-directive.mjs.map +1 -0
  182. package/dist/parser/inline-embedded.d.mts +19 -0
  183. package/dist/parser/inline-embedded.d.mts.map +1 -0
  184. package/dist/parser/inline-embedded.mjs +92 -0
  185. package/dist/parser/inline-embedded.mjs.map +1 -0
  186. package/dist/parser/inline-emphasis.d.mts +11 -0
  187. package/dist/parser/inline-emphasis.d.mts.map +1 -0
  188. package/dist/parser/inline-emphasis.mjs +79 -0
  189. package/dist/parser/inline-emphasis.mjs.map +1 -0
  190. package/dist/parser/inline-input.d.mts +46 -0
  191. package/dist/parser/inline-input.d.mts.map +1 -0
  192. package/dist/parser/inline-input.mjs +137 -0
  193. package/dist/parser/inline-input.mjs.map +1 -0
  194. package/dist/parser/inline-link.d.mts +12 -0
  195. package/dist/parser/inline-link.d.mts.map +1 -0
  196. package/dist/parser/inline-link.mjs +187 -0
  197. package/dist/parser/inline-link.mjs.map +1 -0
  198. package/dist/parser/inline-math.d.mts +10 -0
  199. package/dist/parser/inline-math.d.mts.map +1 -0
  200. package/dist/parser/inline-math.mjs +46 -0
  201. package/dist/parser/inline-math.mjs.map +1 -0
  202. package/dist/parser/inline-output.d.mts +34 -0
  203. package/dist/parser/inline-output.d.mts.map +1 -0
  204. package/dist/parser/inline-output.mjs +62 -0
  205. package/dist/parser/inline-output.mjs.map +1 -0
  206. package/dist/parser/inline-parser.d.mts +14 -0
  207. package/dist/parser/inline-parser.d.mts.map +1 -0
  208. package/dist/parser/inline-parser.mjs +328 -0
  209. package/dist/parser/inline-parser.mjs.map +1 -0
  210. package/dist/parser/inline-pending.d.mts +23 -0
  211. package/dist/parser/inline-pending.d.mts.map +1 -0
  212. package/dist/parser/inline-pending.mjs +100 -0
  213. package/dist/parser/inline-pending.mjs.map +1 -0
  214. package/dist/parser/inline-syntax.d.mts +118 -0
  215. package/dist/parser/inline-syntax.d.mts.map +1 -0
  216. package/dist/parser/inline-syntax.mjs +1 -0
  217. package/dist/parser/javascript-boundary.d.mts +16 -0
  218. package/dist/parser/javascript-boundary.d.mts.map +1 -0
  219. package/dist/parser/javascript-boundary.mjs +42 -0
  220. package/dist/parser/javascript-boundary.mjs.map +1 -0
  221. package/dist/parser/javascript-scanner.d.mts +22 -0
  222. package/dist/parser/javascript-scanner.d.mts.map +1 -0
  223. package/dist/parser/javascript-scanner.mjs +122 -0
  224. package/dist/parser/javascript-scanner.mjs.map +1 -0
  225. package/dist/parser/materialize-cache.d.mts +34 -0
  226. package/dist/parser/materialize-cache.d.mts.map +1 -0
  227. package/dist/parser/materialize-cache.mjs +12 -0
  228. package/dist/parser/materialize-cache.mjs.map +1 -0
  229. package/dist/parser/materialize-jsx.d.mts +14 -0
  230. package/dist/parser/materialize-jsx.d.mts.map +1 -0
  231. package/dist/parser/materialize-jsx.mjs +76 -0
  232. package/dist/parser/materialize-jsx.mjs.map +1 -0
  233. package/dist/parser/materialize.d.mts +61 -0
  234. package/dist/parser/materialize.d.mts.map +1 -0
  235. package/dist/parser/materialize.mjs +736 -0
  236. package/dist/parser/materialize.mjs.map +1 -0
  237. package/dist/parser/recognizer.d.mts +20 -0
  238. package/dist/parser/recognizer.d.mts.map +1 -0
  239. package/dist/parser/recognizer.mjs +24 -0
  240. package/dist/parser/recognizer.mjs.map +1 -0
  241. package/dist/parser/session.d.mts +42 -0
  242. package/dist/parser/session.d.mts.map +1 -0
  243. package/dist/parser/session.mjs +89 -0
  244. package/dist/parser/session.mjs.map +1 -0
  245. package/dist/parser.d.mts +25 -0
  246. package/dist/parser.d.mts.map +1 -0
  247. package/dist/parser.mjs +37 -0
  248. package/dist/parser.mjs.map +1 -0
  249. package/dist/plugin-internal.d.mts +25 -0
  250. package/dist/plugin-internal.d.mts.map +1 -0
  251. package/dist/plugin-internal.mjs +99 -0
  252. package/dist/plugin-internal.mjs.map +1 -0
  253. package/dist/plugin.d.mts +37 -0
  254. package/dist/plugin.d.mts.map +1 -0
  255. package/dist/plugin.mjs +1 -0
  256. package/dist/plugins/code-block-metadata.d.mts +42 -0
  257. package/dist/plugins/code-block-metadata.d.mts.map +1 -0
  258. package/dist/plugins/code-block-metadata.mjs +133 -0
  259. package/dist/plugins/code-block-metadata.mjs.map +1 -0
  260. package/dist/plugins/heading-id.d.mts +15 -0
  261. package/dist/plugins/heading-id.d.mts.map +1 -0
  262. package/dist/plugins/heading-id.mjs +45 -0
  263. package/dist/plugins/heading-id.mjs.map +1 -0
  264. package/dist/plugins/lower-heading.d.mts +16 -0
  265. package/dist/plugins/lower-heading.d.mts.map +1 -0
  266. package/dist/plugins/lower-heading.mjs +28 -0
  267. package/dist/plugins/lower-heading.mjs.map +1 -0
  268. package/dist/plugins/math-render.d.mts +26 -0
  269. package/dist/plugins/math-render.d.mts.map +1 -0
  270. package/dist/plugins/math-render.mjs +51 -0
  271. package/dist/plugins/math-render.mjs.map +1 -0
  272. package/dist/plugins/mod.d.mts +9 -6
  273. package/dist/plugins/mod.mjs +8 -6
  274. package/dist/plugins/remove-esm.d.mts +10 -0
  275. package/dist/plugins/remove-esm.d.mts.map +1 -0
  276. package/dist/plugins/remove-esm.mjs +12 -0
  277. package/dist/plugins/remove-esm.mjs.map +1 -0
  278. package/dist/plugins/shiki.d.mts +21 -0
  279. package/dist/plugins/shiki.d.mts.map +1 -0
  280. package/dist/plugins/shiki.mjs +144 -0
  281. package/dist/plugins/shiki.mjs.map +1 -0
  282. package/dist/plugins/syntax-highlight.d.mts +38 -0
  283. package/dist/plugins/syntax-highlight.d.mts.map +1 -0
  284. package/dist/plugins/syntax-highlight.mjs +106 -0
  285. package/dist/plugins/syntax-highlight.mjs.map +1 -0
  286. package/dist/processor.d.mts +60 -0
  287. package/dist/processor.d.mts.map +1 -0
  288. package/dist/processor.mjs +106 -0
  289. package/dist/processor.mjs.map +1 -0
  290. package/dist/ranges.d.mts +10 -0
  291. package/dist/ranges.d.mts.map +1 -0
  292. package/dist/ranges.mjs +22 -0
  293. package/dist/ranges.mjs.map +1 -0
  294. package/dist/source-map.d.mts +28 -0
  295. package/dist/source-map.d.mts.map +1 -0
  296. package/dist/source-map.mjs +90 -0
  297. package/dist/source-map.mjs.map +1 -0
  298. package/dist/source-text.d.mts +35 -0
  299. package/dist/source-text.d.mts.map +1 -0
  300. package/dist/source-text.mjs +136 -0
  301. package/dist/source-text.mjs.map +1 -0
  302. package/dist/source.d.mts +86 -0
  303. package/dist/source.d.mts.map +1 -0
  304. package/dist/source.mjs +264 -0
  305. package/dist/source.mjs.map +1 -0
  306. package/dist/stream-events.d.mts +59 -0
  307. package/dist/stream-events.d.mts.map +1 -0
  308. package/dist/stream-events.mjs +115 -0
  309. package/dist/stream-events.mjs.map +1 -0
  310. package/dist/stream-session.d.mts +79 -0
  311. package/dist/stream-session.d.mts.map +1 -0
  312. package/dist/stream-session.mjs +904 -0
  313. package/dist/stream-session.mjs.map +1 -0
  314. package/dist/stream-tail.d.mts +84 -0
  315. package/dist/stream-tail.d.mts.map +1 -0
  316. package/dist/stream-tail.mjs +359 -0
  317. package/dist/stream-tail.mjs.map +1 -0
  318. package/dist/stream-types.d.mts +89 -0
  319. package/dist/stream-types.d.mts.map +1 -0
  320. package/dist/stream-types.mjs +1 -0
  321. package/dist/stream.d.mts +28 -0
  322. package/dist/stream.d.mts.map +1 -0
  323. package/dist/stream.mjs +68 -0
  324. package/dist/stream.mjs.map +1 -0
  325. package/dist/syntax-options.d.mts +21 -0
  326. package/dist/syntax-options.d.mts.map +1 -0
  327. package/dist/syntax-options.mjs +26 -0
  328. package/dist/syntax-options.mjs.map +1 -0
  329. package/dist/traversal.d.mts +25 -0
  330. package/dist/traversal.d.mts.map +1 -0
  331. package/dist/traversal.mjs +136 -0
  332. package/dist/traversal.mjs.map +1 -0
  333. package/dist/tree.d.mts +18 -0
  334. package/dist/tree.d.mts.map +1 -0
  335. package/dist/tree.mjs +43 -0
  336. package/dist/tree.mjs.map +1 -0
  337. package/dist/unified/adapter.d.mts +24 -0
  338. package/dist/unified/adapter.d.mts.map +1 -0
  339. package/dist/unified/adapter.mjs +44 -0
  340. package/dist/unified/adapter.mjs.map +1 -0
  341. package/dist/unified/mod.d.mts +2 -0
  342. package/dist/unified/mod.mjs +1 -0
  343. package/dist/unified/runtime.d.mts +10 -0
  344. package/dist/unified/runtime.d.mts.map +1 -0
  345. package/dist/unified/runtime.mjs +115 -0
  346. package/dist/unified/runtime.mjs.map +1 -0
  347. package/dist/unified/tree-bridge.d.mts +63 -0
  348. package/dist/unified/tree-bridge.d.mts.map +1 -0
  349. package/dist/unified/tree-bridge.mjs +876 -0
  350. package/dist/unified/tree-bridge.mjs.map +1 -0
  351. package/dist/uri.d.mts +5 -0
  352. package/dist/uri.d.mts.map +1 -0
  353. package/dist/uri.mjs +32 -0
  354. package/dist/uri.mjs.map +1 -0
  355. package/package.json +56 -30
  356. package/dist/plugins/heading-id/plugin.d.mts +0 -17
  357. package/dist/plugins/heading-id/plugin.d.mts.map +0 -1
  358. package/dist/plugins/heading-id/plugin.mjs +0 -23
  359. package/dist/plugins/heading-id/plugin.mjs.map +0 -1
  360. package/dist/plugins/katex/plugin.d.mts +0 -39
  361. package/dist/plugins/katex/plugin.d.mts.map +0 -1
  362. package/dist/plugins/katex/plugin.mjs +0 -107
  363. package/dist/plugins/katex/plugin.mjs.map +0 -1
  364. package/dist/plugins/remove-imports-exports.d.mts +0 -10
  365. package/dist/plugins/remove-imports-exports.d.mts.map +0 -1
  366. package/dist/plugins/remove-imports-exports.mjs +0 -15
  367. package/dist/plugins/remove-imports-exports.mjs.map +0 -1
  368. package/dist/plugins/syntax-highlight/code-meta.d.mts +0 -22
  369. package/dist/plugins/syntax-highlight/code-meta.d.mts.map +0 -1
  370. package/dist/plugins/syntax-highlight/code-meta.mjs +0 -38
  371. package/dist/plugins/syntax-highlight/code-meta.mjs.map +0 -1
  372. package/dist/plugins/syntax-highlight/plugin.d.mts +0 -57
  373. package/dist/plugins/syntax-highlight/plugin.d.mts.map +0 -1
  374. package/dist/plugins/syntax-highlight/plugin.mjs +0 -93
  375. package/dist/plugins/syntax-highlight/plugin.mjs.map +0 -1
  376. package/dist/plugins/tree-processor/plugin.d.mts +0 -19
  377. package/dist/plugins/tree-processor/plugin.d.mts.map +0 -1
  378. package/dist/plugins/tree-processor/plugin.mjs +0 -21
  379. package/dist/plugins/tree-processor/plugin.mjs.map +0 -1
  380. package/dist/types.d.mts +0 -2
  381. /package/dist/{types.mjs → parser/block-syntax.mjs} +0 -0
@@ -0,0 +1,79 @@
1
+ import { isUnicodePunctuation, isUnicodeWhitespace } from "./characters.mjs";
2
+ import { bracketText, delimiterText, isBracket, isDelimiter, mergeText } from "./inline-output.mjs";
3
+ //#region src/parser/inline-emphasis.ts
4
+ function createDelimiter(value, start, end, marker) {
5
+ const before = value.char(start - 1);
6
+ const after = value.char(end);
7
+ const beforeWhitespace = before === void 0 || isUnicodeWhitespace(before);
8
+ const afterWhitespace = after === void 0 || isUnicodeWhitespace(after);
9
+ const beforePunctuation = before !== void 0 && isUnicodePunctuation(before);
10
+ const afterPunctuation = after !== void 0 && isUnicodePunctuation(after);
11
+ const leftFlanking = !afterWhitespace && (!afterPunctuation || beforeWhitespace || beforePunctuation);
12
+ const rightFlanking = !beforeWhitespace && (!beforePunctuation || afterWhitespace || afterPunctuation);
13
+ return {
14
+ marker,
15
+ length: end - start,
16
+ originalLength: end - start,
17
+ start,
18
+ canOpen: marker === "_" ? leftFlanking && (!rightFlanking || beforePunctuation) : leftFlanking,
19
+ canClose: marker === "_" ? rightFlanking && (!leftFlanking || afterPunctuation) : rightFlanking
20
+ };
21
+ }
22
+ function resolveCloser(input, output, delimiters, closer, syntax, after = -1) {
23
+ if (!closer.canClose) return;
24
+ while (closer.length > 0) {
25
+ const closerIndex = delimiters.lastIndexOf(closer);
26
+ let openerIndex = -1;
27
+ for (let index = closerIndex - 1; index >= 0; index--) {
28
+ const candidate = delimiters[index];
29
+ if (candidate.start <= after) break;
30
+ if (candidate.marker === closer.marker && candidate.canOpen && !violatesRuleOfThree(candidate, closer)) {
31
+ openerIndex = index;
32
+ break;
33
+ }
34
+ }
35
+ const opener = delimiters[openerIndex];
36
+ if (opener === void 0) return;
37
+ const use = closer.marker === "~" ? opener.length >= 2 && closer.length >= 2 ? 2 : syntax.singleTilde ? 1 : 2 : opener.length >= 2 && closer.length >= 2 ? 2 : 1;
38
+ if (opener.length < use || closer.length < use) return;
39
+ const closerOutput = output.lastIndexOf(closer);
40
+ const openerOutput = closerOutput === -1 ? -1 : output.lastIndexOf(opener, closerOutput - 1);
41
+ if (openerOutput === -1 || closerOutput === -1 || openerOutput >= closerOutput) throw new Error("Delimiter stack diverged from inline output");
42
+ const children = output.slice(openerOutput + 1, closerOutput).map((entry) => isDelimiter(entry) ? delimiterText(input, entry) : isBracket(entry) ? bracketText(input, entry) : entry);
43
+ opener.length -= use;
44
+ const nodeStart = opener.start + opener.length;
45
+ const nodeEnd = closer.start + use;
46
+ closer.start += use;
47
+ closer.length -= use;
48
+ const node = {
49
+ kind: closer.marker === "~" ? "delete" : use === 2 ? "strong" : "emphasis",
50
+ range: input.sourceRange(nodeStart, nodeEnd),
51
+ children: mergeText(children)
52
+ };
53
+ output.splice(openerOutput + 1, closerOutput - openerOutput - 1, node);
54
+ delimiters.splice(openerIndex + 1, closerIndex - openerIndex - 1);
55
+ let closerAt = openerOutput + 2;
56
+ if (opener.length === 0) {
57
+ output.splice(openerOutput, 1);
58
+ delimiters.splice(openerIndex, 1);
59
+ closerAt--;
60
+ }
61
+ if (closer.length === 0) {
62
+ output.splice(closerAt, 1);
63
+ delimiters.splice(delimiters.lastIndexOf(closer), 1);
64
+ return;
65
+ }
66
+ }
67
+ }
68
+ /** Resolves closers that were held behind a bracket boundary. */
69
+ function resolveDelimiters(input, output, delimiters, syntax, after = -1) {
70
+ const closers = delimiters.slice();
71
+ for (const closer of closers) if (closer.start > after && delimiters.includes(closer)) resolveCloser(input, output, delimiters, closer, syntax, after);
72
+ }
73
+ function violatesRuleOfThree(opener, closer) {
74
+ return (opener.canClose || closer.canOpen) && (opener.originalLength + closer.originalLength) % 3 === 0 && (opener.originalLength % 3 !== 0 || closer.originalLength % 3 !== 0);
75
+ }
76
+ //#endregion
77
+ export { createDelimiter, resolveCloser, resolveDelimiters };
78
+
79
+ //# sourceMappingURL=inline-emphasis.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-emphasis.mjs","names":[],"sources":["../../src/parser/inline-emphasis.ts"],"sourcesContent":["import type { SourceText } from \"../source-text.ts\";\nimport type { ResolvedSyntaxOptions } from \"../syntax-options.ts\";\nimport type { InlineInput } from \"./inline-input.ts\";\nimport type { Delimiter, Output } from \"./inline-output.ts\";\nimport type { InlineSyntax } from \"./inline-syntax.ts\";\n\nimport { isUnicodePunctuation, isUnicodeWhitespace } from \"./characters.ts\";\nimport { bracketText, delimiterText, isBracket, isDelimiter, mergeText } from \"./inline-output.ts\";\n\n// Emphasis, strong, and strikethrough from delimiter runs, resolved as closers arrive.\n\nexport function createDelimiter(\n value: SourceText,\n start: number,\n end: number,\n marker: Delimiter[\"marker\"],\n): Delimiter {\n const before = value.char(start - 1);\n const after = value.char(end);\n const beforeWhitespace = before === undefined || isUnicodeWhitespace(before);\n const afterWhitespace = after === undefined || isUnicodeWhitespace(after);\n const beforePunctuation = before !== undefined && isUnicodePunctuation(before);\n const afterPunctuation = after !== undefined && isUnicodePunctuation(after);\n\n const leftFlanking =\n !afterWhitespace && (!afterPunctuation || beforeWhitespace || beforePunctuation);\n\n const rightFlanking =\n !beforeWhitespace && (!beforePunctuation || afterWhitespace || afterPunctuation);\n\n return {\n marker,\n length: end - start,\n originalLength: end - start,\n start,\n canOpen: marker === \"_\" ? leftFlanking && (!rightFlanking || beforePunctuation) : leftFlanking,\n canClose: marker === \"_\" ? rightFlanking && (!leftFlanking || afterPunctuation) : rightFlanking,\n };\n}\n\nexport function resolveCloser(\n input: InlineInput,\n output: Output[],\n delimiters: Delimiter[],\n closer: Delimiter,\n syntax: ResolvedSyntaxOptions,\n after = -1,\n): void {\n if (!closer.canClose) {\n return;\n }\n\n while (closer.length > 0) {\n const closerIndex = delimiters.lastIndexOf(closer);\n let openerIndex = -1;\n\n for (let index = closerIndex - 1; index >= 0; index--) {\n const candidate = delimiters[index];\n\n if (candidate.start <= after) {\n break;\n }\n\n if (\n candidate.marker === closer.marker &&\n candidate.canOpen &&\n !violatesRuleOfThree(candidate, closer)\n ) {\n openerIndex = index;\n break;\n }\n }\n\n const opener = delimiters[openerIndex];\n\n if (opener === undefined) {\n return;\n }\n\n const use =\n closer.marker === \"~\"\n ? opener.length >= 2 && closer.length >= 2\n ? 2\n : syntax.singleTilde\n ? 1\n : 2\n : opener.length >= 2 && closer.length >= 2\n ? 2\n : 1;\n\n if (opener.length < use || closer.length < use) {\n return;\n }\n\n // The closer was just pushed and the opener precedes it, so both are found from the end.\n const closerOutput = output.lastIndexOf(closer);\n const openerOutput = closerOutput === -1 ? -1 : output.lastIndexOf(opener, closerOutput - 1);\n\n if (openerOutput === -1 || closerOutput === -1 || openerOutput >= closerOutput) {\n throw new Error(\"Delimiter stack diverged from inline output\");\n }\n\n const children = output\n .slice(openerOutput + 1, closerOutput)\n .map((entry) =>\n isDelimiter(entry)\n ? delimiterText(input, entry)\n : isBracket(entry)\n ? bracketText(input, entry)\n : entry,\n );\n\n opener.length -= use;\n const nodeStart = opener.start + opener.length;\n const nodeEnd = closer.start + use;\n closer.start += use;\n closer.length -= use;\n\n const node: InlineSyntax = {\n kind: closer.marker === \"~\" ? \"delete\" : use === 2 ? \"strong\" : \"emphasis\",\n range: input.sourceRange(nodeStart, nodeEnd),\n children: mergeText(children),\n };\n\n output.splice(openerOutput + 1, closerOutput - openerOutput - 1, node);\n // Delimiters between the pair are now inside the node.\n delimiters.splice(openerIndex + 1, closerIndex - openerIndex - 1);\n let closerAt = openerOutput + 2;\n\n if (opener.length === 0) {\n output.splice(openerOutput, 1);\n delimiters.splice(openerIndex, 1);\n closerAt--;\n }\n\n if (closer.length === 0) {\n output.splice(closerAt, 1);\n delimiters.splice(delimiters.lastIndexOf(closer), 1);\n\n return;\n }\n }\n}\n\n/** Resolves closers that were held behind a bracket boundary. */\nexport function resolveDelimiters(\n input: InlineInput,\n output: Output[],\n delimiters: Delimiter[],\n syntax: ResolvedSyntaxOptions,\n after = -1,\n): void {\n // Resolving one closer removes entries from the stack.\n const closers = delimiters.slice();\n\n for (const closer of closers) {\n if (closer.start > after && delimiters.includes(closer)) {\n resolveCloser(input, output, delimiters, closer, syntax, after);\n }\n }\n}\n\nfunction violatesRuleOfThree(opener: Delimiter, closer: Delimiter): boolean {\n return (\n (opener.canClose || closer.canOpen) &&\n (opener.originalLength + closer.originalLength) % 3 === 0 &&\n (opener.originalLength % 3 !== 0 || closer.originalLength % 3 !== 0)\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { SourceRange } from "../ranges.mjs";
2
+ import { SourceText } from "../source-text.mjs";
3
+ import { SourceFile } from "../source.mjs";
4
+ //#region src/parser/inline-input.d.ts
5
+ export interface SourceInlineSegment {
6
+ readonly kind: "source";
7
+ readonly range: SourceRange;
8
+ }
9
+ export interface VirtualSpaceInlineSegment {
10
+ readonly kind: "virtualSpace";
11
+ readonly offset: number;
12
+ readonly columns: number;
13
+ }
14
+ export type InlineSegment = SourceInlineSegment | VirtualSpaceInlineSegment;
15
+ /**
16
+ * Source-backed block content with explicit virtual indentation. Text is built
17
+ * once; segment boundaries map characters back to their source offsets.
18
+ */
19
+ export declare class InlineInput {
20
+ #private;
21
+ readonly file: SourceFile;
22
+ /**
23
+ * `base` is an earlier input of the same growing text, such as the open
24
+ * paragraph before an append. When this input only adds text after it, the
25
+ * base's decoded text and segment boundaries are shared; only new text is decoded.
26
+ */
27
+ constructor(file: SourceFile, segments: readonly InlineSegment[], base?: InlineInput);
28
+ get length(): number;
29
+ sourceRange(start?: number, end?: number): SourceRange;
30
+ /** Source segments are contiguous; virtual indentation maps to one authored tab. */
31
+ private sourceOffset;
32
+ toString(): string;
33
+ /** The text in chunks, which an extended input shares instead of copying. */
34
+ text(): SourceText;
35
+ /** Whether this input was built by extending `other`, so it starts with the same text. */
36
+ extends(other: InlineInput): boolean;
37
+ /**
38
+ * The shared storage, when `segments` extend this input's: every segment is
39
+ * the same object except the last, which may only have grown at its end.
40
+ */
41
+ private extendable;
42
+ /** Decodes segments from `from` into the storage after `length` characters of `text`. */
43
+ private append;
44
+ }
45
+ //#endregion
46
+ //# sourceMappingURL=inline-input.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-input.d.mts","names":[],"sources":["../../src/parser/inline-input.ts"],"mappings":";;;;iBAMiB;WACN;WACA,OAAO;;iBAGD;WACN;WACA;WACA;;YAGC,gBAAgB,sBAAsB;;;;;qBAmBrC;;WAGK,MAAM;;;;;;EAOtB,YAAmB,MAAM,YAAY,mBAAmB,iBAAiB,OAAO;MA6BrE;EAIJ,YAAY,gBAAW,eAAoB;;UAqB1C;EAsBD;;EAKA,QAAQ;;EAKR,QAAQ,OAAO;;;;;UAQd;;UAgCA"}
@@ -0,0 +1,137 @@
1
+ import { sourceRange } from "../ranges.mjs";
2
+ import { SourceText } from "../source-text.mjs";
3
+ //#region src/parser/inline-input.ts
4
+ /**
5
+ * Segments that successive inputs of one growing text share. Each
6
+ * input reads its own prefix; only the newest input may extend the storage, and
7
+ * it only ever writes past every existing input's end.
8
+ */
9
+ var InputStorage = class {
10
+ /** The segments as given, compared by identity when a later input extends this one. */
11
+ inputs = [];
12
+ /** Text length after each segment. */
13
+ ends = [];
14
+ tip;
15
+ };
16
+ /**
17
+ * Source-backed block content with explicit virtual indentation. Text is built
18
+ * once; segment boundaries map characters back to their source offsets.
19
+ */
20
+ var InlineInput = class {
21
+ #storage;
22
+ #text;
23
+ file;
24
+ /**
25
+ * `base` is an earlier input of the same growing text, such as the open
26
+ * paragraph before an append. When this input only adds text after it, the
27
+ * base's decoded text and segment boundaries are shared; only new text is decoded.
28
+ */
29
+ constructor(file, segments, base) {
30
+ this.file = file;
31
+ const storage = base === void 0 ? void 0 : base.extendable(file, segments);
32
+ if (base === void 0 || storage === void 0) {
33
+ this.#storage = new InputStorage();
34
+ this.#text = this.append(segments, 0, 0, SourceText.of(""));
35
+ } else {
36
+ this.#storage = storage;
37
+ const last = segments.length === 0 ? -1 : storage.inputs.length - 1;
38
+ const grown = segments[last];
39
+ const previous = storage.inputs[last];
40
+ let text = base.#text;
41
+ if (grown?.kind === "source" && previous?.kind === "source" && grown !== previous) {
42
+ const start = previous.range.end;
43
+ const part = file.semanticSlice({
44
+ start,
45
+ end: grown.range.end
46
+ });
47
+ text = text.append(part);
48
+ storage.inputs[last] = grown;
49
+ storage.ends[last] = text.length;
50
+ }
51
+ this.#text = this.append(segments, last + 1, text.length, text);
52
+ }
53
+ this.#storage.tip = this;
54
+ }
55
+ get length() {
56
+ return this.#text.length;
57
+ }
58
+ sourceRange(start = 0, end = this.length) {
59
+ if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || end < start) throw new RangeError(`Invalid inline range ${start}..${end}`);
60
+ if (end > this.length) throw new RangeError(`Inline range ${start}..${end} exceeds input length ${this.length}`);
61
+ if (start === this.length) {
62
+ const offset = this.length === 0 ? 0 : this.sourceOffset(this.length - 1);
63
+ return sourceRange(offset, offset);
64
+ }
65
+ const first = this.sourceOffset(start);
66
+ return sourceRange(first, (end === 0 ? first : this.sourceOffset(end - 1)) + 1);
67
+ }
68
+ /** Source segments are contiguous; virtual indentation maps to one authored tab. */
69
+ sourceOffset(offset) {
70
+ const { inputs, ends } = this.#storage;
71
+ let low = 0;
72
+ let high = inputs.length - 1;
73
+ while (low < high) {
74
+ const middle = low + high >> 1;
75
+ if (offset < ends[middle]) high = middle;
76
+ else low = middle + 1;
77
+ }
78
+ const segment = inputs[low];
79
+ return segment.kind === "virtualSpace" ? segment.offset : segment.range.start + offset - (low === 0 ? 0 : ends[low - 1]);
80
+ }
81
+ toString() {
82
+ return this.#text.toString();
83
+ }
84
+ /** The text in chunks, which an extended input shares instead of copying. */
85
+ text() {
86
+ return this.#text;
87
+ }
88
+ /** Whether this input was built by extending `other`, so it starts with the same text. */
89
+ extends(other) {
90
+ return this.#storage === other.#storage && this.length >= other.length;
91
+ }
92
+ /**
93
+ * The shared storage, when `segments` extend this input's: every segment is
94
+ * the same object except the last, which may only have grown at its end.
95
+ */
96
+ extendable(file, segments) {
97
+ const storage = this.#storage;
98
+ const count = storage.inputs.length;
99
+ if (storage.tip !== this || !this.file.isPrefixOf(file) || segments.length < count) return;
100
+ for (let index = Math.max(0, count - 3); index < count - 1; index++) if (!sameSegment(storage.inputs[index], segments[index])) return;
101
+ const previous = storage.inputs[count - 1];
102
+ const next = segments[count - 1];
103
+ return (previous === next || previous?.kind === "source" && next?.kind === "source" && next.range.start === previous.range.start && next.range.end >= previous.range.end) && count > 0 ? storage : void 0;
104
+ }
105
+ /** Decodes segments from `from` into the storage after `length` characters of `text`. */
106
+ append(segments, from, length, text) {
107
+ const storage = this.#storage;
108
+ const parts = [];
109
+ let index = length;
110
+ for (let position = from; position < segments.length; position++) {
111
+ const segment = validateSegment(segments[position]);
112
+ const part = segment.kind === "source" ? this.file.semanticSlice(segment.range) : " ".repeat(segment.columns);
113
+ index += part.length;
114
+ parts.push(part);
115
+ storage.inputs[position] = segments[position];
116
+ storage.ends[position] = index;
117
+ }
118
+ return text.length === 0 ? SourceText.of(parts.join("")) : parts.reduce((result, part) => result.append(part), text);
119
+ }
120
+ };
121
+ function sameSegment(left, right) {
122
+ if (left === right) return true;
123
+ if (left?.kind === "source" && right?.kind === "source") return left.range.start === right.range.start && left.range.end === right.range.end;
124
+ return left?.kind === "virtualSpace" && right?.kind === "virtualSpace" && left.offset === right.offset && left.columns === right.columns;
125
+ }
126
+ function validateSegment(segment) {
127
+ if (segment.kind === "source") return {
128
+ kind: "source",
129
+ range: sourceRange(segment.range.start, segment.range.end)
130
+ };
131
+ if (!Number.isSafeInteger(segment.offset) || !Number.isSafeInteger(segment.columns) || segment.offset < 0 || segment.columns < 1) throw new RangeError("Invalid virtual inline indentation");
132
+ return { ...segment };
133
+ }
134
+ //#endregion
135
+ export { InlineInput };
136
+
137
+ //# sourceMappingURL=inline-input.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-input.mjs","names":[],"sources":["../../src/parser/inline-input.ts"],"sourcesContent":["import type { SourceRange } from \"../ranges.ts\";\nimport type { SourceFile } from \"../source.ts\";\n\nimport { sourceRange } from \"../ranges.ts\";\nimport { SourceText } from \"../source-text.ts\";\n\nexport interface SourceInlineSegment {\n readonly kind: \"source\";\n readonly range: SourceRange;\n}\n\nexport interface VirtualSpaceInlineSegment {\n readonly kind: \"virtualSpace\";\n readonly offset: number;\n readonly columns: number;\n}\n\nexport type InlineSegment = SourceInlineSegment | VirtualSpaceInlineSegment;\n\n/**\n * Segments that successive inputs of one growing text share. Each\n * input reads its own prefix; only the newest input may extend the storage, and\n * it only ever writes past every existing input's end.\n */\nclass InputStorage {\n /** The segments as given, compared by identity when a later input extends this one. */\n readonly inputs: InlineSegment[] = [];\n /** Text length after each segment. */\n readonly ends: number[] = [];\n tip: InlineInput | undefined;\n}\n\n/**\n * Source-backed block content with explicit virtual indentation. Text is built\n * once; segment boundaries map characters back to their source offsets.\n */\nexport class InlineInput {\n readonly #storage: InputStorage;\n readonly #text: SourceText;\n public readonly file: SourceFile;\n\n /**\n * `base` is an earlier input of the same growing text, such as the open\n * paragraph before an append. When this input only adds text after it, the\n * base's decoded text and segment boundaries are shared; only new text is decoded.\n */\n public constructor(file: SourceFile, segments: readonly InlineSegment[], base?: InlineInput) {\n this.file = file;\n const storage = base === undefined ? undefined : base.extendable(file, segments);\n\n if (base === undefined || storage === undefined) {\n this.#storage = new InputStorage();\n this.#text = this.append(segments, 0, 0, SourceText.of(\"\"));\n } else {\n this.#storage = storage;\n // The base's last segment may have grown on the same line, so it is decoded past its old end.\n const last = segments.length === 0 ? -1 : storage.inputs.length - 1;\n const grown = segments[last];\n const previous = storage.inputs[last];\n let text = base.#text;\n\n if (grown?.kind === \"source\" && previous?.kind === \"source\" && grown !== previous) {\n const start = previous.range.end;\n const part = file.semanticSlice({ start, end: grown.range.end });\n text = text.append(part);\n storage.inputs[last] = grown;\n storage.ends[last] = text.length;\n }\n\n this.#text = this.append(segments, last + 1, text.length, text);\n }\n\n this.#storage.tip = this;\n }\n\n public get length(): number {\n return this.#text.length;\n }\n\n public sourceRange(start = 0, end = this.length): SourceRange {\n if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || end < start) {\n throw new RangeError(`Invalid inline range ${start}..${end}`);\n }\n\n if (end > this.length) {\n throw new RangeError(`Inline range ${start}..${end} exceeds input length ${this.length}`);\n }\n\n if (start === this.length) {\n const offset = this.length === 0 ? 0 : this.sourceOffset(this.length - 1);\n\n return sourceRange(offset, offset);\n }\n\n const first = this.sourceOffset(start);\n\n return sourceRange(first, (end === 0 ? first : this.sourceOffset(end - 1)) + 1);\n }\n\n /** Source segments are contiguous; virtual indentation maps to one authored tab. */\n private sourceOffset(offset: number): number {\n const { inputs, ends } = this.#storage;\n let low = 0;\n let high = inputs.length - 1;\n\n while (low < high) {\n const middle = (low + high) >> 1;\n\n if (offset < ends[middle]) {\n high = middle;\n } else {\n low = middle + 1;\n }\n }\n\n const segment = inputs[low];\n\n return segment.kind === \"virtualSpace\"\n ? segment.offset\n : segment.range.start + offset - (low === 0 ? 0 : ends[low - 1]);\n }\n\n public toString(): string {\n return this.#text.toString();\n }\n\n /** The text in chunks, which an extended input shares instead of copying. */\n public text(): SourceText {\n return this.#text;\n }\n\n /** Whether this input was built by extending `other`, so it starts with the same text. */\n public extends(other: InlineInput): boolean {\n return this.#storage === other.#storage && this.length >= other.length;\n }\n\n /**\n * The shared storage, when `segments` extend this input's: every segment is\n * the same object except the last, which may only have grown at its end.\n */\n private extendable(\n file: SourceFile,\n segments: readonly InlineSegment[],\n ): InputStorage | undefined {\n const storage = this.#storage;\n const count = storage.inputs.length;\n\n if (storage.tip !== this || !this.file.isPrefixOf(file) || segments.length < count) {\n return undefined;\n }\n\n // The file only grew, so complete lines keep their segments; the open line can be rebuilt.\n for (let index = Math.max(0, count - 3); index < count - 1; index++) {\n if (!sameSegment(storage.inputs[index], segments[index])) {\n return undefined;\n }\n }\n\n const previous = storage.inputs[count - 1];\n const next = segments[count - 1];\n\n const grows =\n previous === next ||\n (previous?.kind === \"source\" &&\n next?.kind === \"source\" &&\n next.range.start === previous.range.start &&\n next.range.end >= previous.range.end);\n\n return grows && count > 0 ? storage : undefined;\n }\n\n /** Decodes segments from `from` into the storage after `length` characters of `text`. */\n private append(\n segments: readonly InlineSegment[],\n from: number,\n length: number,\n text: SourceText,\n ): SourceText {\n const storage = this.#storage;\n const parts: string[] = [];\n let index = length;\n\n for (let position = from; position < segments.length; position++) {\n const segment = validateSegment(segments[position]);\n\n const part =\n segment.kind === \"source\"\n ? this.file.semanticSlice(segment.range)\n : \" \".repeat(segment.columns);\n\n index += part.length;\n parts.push(part);\n storage.inputs[position] = segments[position];\n storage.ends[position] = index;\n }\n\n // A fresh input joins its parts once; an extension appends the few new ones.\n return text.length === 0\n ? SourceText.of(parts.join(\"\"))\n : parts.reduce((result, part) => result.append(part), text);\n }\n}\n\nfunction sameSegment(left: InlineSegment | undefined, right: InlineSegment | undefined): boolean {\n if (left === right) {\n return true;\n }\n\n if (left?.kind === \"source\" && right?.kind === \"source\") {\n return left.range.start === right.range.start && left.range.end === right.range.end;\n }\n\n return (\n left?.kind === \"virtualSpace\" &&\n right?.kind === \"virtualSpace\" &&\n left.offset === right.offset &&\n left.columns === right.columns\n );\n}\n\nfunction validateSegment(segment: InlineSegment): InlineSegment {\n if (segment.kind === \"source\") {\n return {\n kind: \"source\",\n range: sourceRange(segment.range.start, segment.range.end),\n };\n }\n\n if (\n !Number.isSafeInteger(segment.offset) ||\n !Number.isSafeInteger(segment.columns) ||\n segment.offset < 0 ||\n segment.columns < 1\n ) {\n throw new RangeError(\"Invalid virtual inline indentation\");\n }\n\n return { ...segment };\n}\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { ResolvedSyntaxOptions } from "../syntax-options.mjs";
2
+ import { SourceText } from "../source-text.mjs";
3
+ import { InlineInput } from "./inline-input.mjs";
4
+ import { DefinitionLookup } from "./inline-syntax.mjs";
5
+ import { Bracket, Delimiter, Output } from "./inline-output.mjs";
6
+ //#region src/parser/inline-link.d.ts
7
+ export declare function resolveBracket(input: InlineInput, value: SourceText, close: number, bracket: Bracket, output: Output[], delimiters: Delimiter[], syntax: ResolvedSyntaxOptions, definitions: DefinitionLookup, references: Set<string>, nested: boolean): Readonly<{
8
+ end: number;
9
+ link: boolean;
10
+ }> | undefined;
11
+ //#endregion
12
+ //# sourceMappingURL=inline-link.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-link.d.mts","names":[],"sources":["../../src/parser/inline-link.ts"],"mappings":";;;;;;wBAgCgB,eACd,OAAO,aACP,OAAO,YACP,eACA,SAAS,SACT,QAAQ,UACR,YAAY,aACZ,QAAQ,uBACR,aAAa,kBACb,YAAY,aACZ,kBACC;EAAW;EAAa"}
@@ -0,0 +1,187 @@
1
+ import { decodeNamedCharacterReference, decodeNumericCharacterReference } from "../character-reference.mjs";
2
+ import { normalizeIdentifier } from "../identifier.mjs";
3
+ import { isUnicodeWhitespace } from "./characters.mjs";
4
+ import { InlineInput } from "./inline-input.mjs";
5
+ import { bracketText, delimiterText, escapedAt, findUnescapedInline, isBracket, isDelimiter, mergeText, textNode } from "./inline-output.mjs";
6
+ import { matchLiteralAutolink } from "./inline-autolink.mjs";
7
+ import { resolveDelimiters } from "./inline-emphasis.mjs";
8
+ //#region src/parser/inline-link.ts
9
+ function resolveBracket(input, value, close, bracket, output, delimiters, syntax, definitions, references, nested) {
10
+ const outputIndex = output.lastIndexOf(bracket);
11
+ if (outputIndex === -1) throw new Error("Bracket stack diverged from inline output");
12
+ if (!bracket.active) {
13
+ output[outputIndex] = bracketText(input, bracket);
14
+ return;
15
+ }
16
+ const labelStart = bracket.start + (bracket.image ? 2 : 1);
17
+ const label = value.slice(labelStart, close);
18
+ if (!bracket.image && label.startsWith("^") && !label.slice(1).includes("[") && !label.slice(1).includes("]")) {
19
+ output.splice(outputIndex, output.length - outputIndex, {
20
+ kind: "footnoteReference",
21
+ range: input.sourceRange(bracket.start, close + 1),
22
+ identifier: normalizeIdentifier(label.slice(1))
23
+ });
24
+ removeDetachedDelimiters(delimiters, bracket);
25
+ return {
26
+ end: close + 1,
27
+ link: true
28
+ };
29
+ }
30
+ const inline = value.char(close + 1) === "(" ? linkDestination(value, close + 2) : void 0;
31
+ const reference = inline === void 0 ? referenceSuffix(value, close + 1) : void 0;
32
+ const identifier = normalizeIdentifier(reference?.label || label);
33
+ const defined = definitions.has(identifier);
34
+ if (inline === void 0) {
35
+ if (identifier !== "" && (nested || /(?:https?:\/\/|www\.|@)/iu.test(label))) references.add(identifier);
36
+ if (identifier === "" || nested && !defined) {
37
+ output[outputIndex] = bracketText(input, bracket);
38
+ return;
39
+ }
40
+ }
41
+ resolveDelimiters(input, output, delimiters, syntax, bracket.start);
42
+ const children = output.slice(outputIndex + 1).map((entry) => isDelimiter(entry) ? delimiterText(input, entry) : isBracket(entry) ? bracketText(input, entry) : entry);
43
+ if (inline !== void 0) {
44
+ const destination = decodeLinkString(inline.destination);
45
+ const node = bracket.image ? {
46
+ kind: "image",
47
+ range: input.sourceRange(bracket.start, inline.end),
48
+ destination,
49
+ title: inline.title === void 0 ? void 0 : decodeLinkString(inline.title),
50
+ alt: inlinePlainText(children)
51
+ } : {
52
+ kind: "link",
53
+ range: input.sourceRange(bracket.start, inline.end),
54
+ destination,
55
+ title: inline.title === void 0 ? void 0 : decodeLinkString(inline.title),
56
+ children: mergeText(children)
57
+ };
58
+ output.splice(outputIndex, output.length - outputIndex, node);
59
+ removeDetachedDelimiters(delimiters, bracket);
60
+ return {
61
+ end: inline.end,
62
+ link: !bracket.image
63
+ };
64
+ }
65
+ const end = reference?.end ?? close + 1;
66
+ const autolinks = !defined && !bracket.image ? fallbackAutolinks(input, children) : void 0;
67
+ if (autolinks !== void 0) output.splice(outputIndex, output.length - outputIndex, bracketText(input, bracket), ...autolinks, textNode(input, value, close, end));
68
+ else output.splice(outputIndex, output.length - outputIndex, {
69
+ kind: "reference",
70
+ range: input.sourceRange(bracket.start, end),
71
+ identifier,
72
+ referenceKind: reference === void 0 ? "shortcut" : reference.label === "" ? "collapsed" : "full",
73
+ image: bracket.image,
74
+ children: mergeText(children)
75
+ });
76
+ removeDetachedDelimiters(delimiters, bracket);
77
+ return {
78
+ end,
79
+ link: defined && !bracket.image
80
+ };
81
+ }
82
+ /** Literal labels resume normal autolinking when no reference definition exists. */
83
+ function fallbackAutolinks(input, children) {
84
+ const output = [];
85
+ let changed = false;
86
+ for (const child of children) {
87
+ if (child.kind !== "text" || !/(?:https?:\/\/|www\.|@)/iu.test(child.value)) {
88
+ output.push(child);
89
+ continue;
90
+ }
91
+ const part = new InlineInput(input.file, [{
92
+ kind: "source",
93
+ range: child.range
94
+ }]);
95
+ const value = part.text();
96
+ if (value.toString() !== child.value) {
97
+ output.push(child);
98
+ continue;
99
+ }
100
+ let start = 0;
101
+ for (let offset = 0; offset < value.length; offset++) {
102
+ const match = matchLiteralAutolink(part, value, offset);
103
+ if (match === void 0) continue;
104
+ if (start < offset) output.push(textNode(part, value, start, offset));
105
+ output.push(match.node);
106
+ offset = match.end - 1;
107
+ start = match.end;
108
+ changed = true;
109
+ }
110
+ if (start < value.length) output.push(textNode(part, value, start, value.length));
111
+ }
112
+ return changed ? output : void 0;
113
+ }
114
+ function linkDestination(value, start) {
115
+ let cursor = start;
116
+ while (value.char(cursor) === " " || value.char(cursor) === " " || value.char(cursor) === "\n") cursor++;
117
+ let destination = "";
118
+ if (value.char(cursor) === "<") {
119
+ const end = findUnescapedInline(value, ">", cursor + 1);
120
+ if (end === void 0 || /[\r\n<]/u.test(value.slice(cursor + 1, end))) return;
121
+ destination = value.slice(cursor + 1, end);
122
+ cursor = end + 1;
123
+ } else {
124
+ const destinationStart = cursor;
125
+ let depth = 0;
126
+ while (cursor < value.length) {
127
+ const character = value.char(cursor);
128
+ if (isUnicodeWhitespace(character ?? "")) break;
129
+ if (character === "(" && !escapedAt(value, cursor, destinationStart)) {
130
+ if (++depth > 32) return;
131
+ } else if (character === ")" && !escapedAt(value, cursor, destinationStart)) {
132
+ if (depth === 0) break;
133
+ depth--;
134
+ }
135
+ cursor++;
136
+ }
137
+ if (depth !== 0) return;
138
+ destination = value.slice(destinationStart, cursor);
139
+ }
140
+ const beforeWhitespace = cursor;
141
+ while (isUnicodeWhitespace(value.char(cursor) ?? "")) cursor++;
142
+ let title;
143
+ if (cursor !== beforeWhitespace && value.char(cursor) !== ")") {
144
+ const opener = value.char(cursor);
145
+ const closer = opener === "(" ? ")" : opener === "'" ? "'" : opener === "\"" ? "\"" : void 0;
146
+ if (closer === void 0) return;
147
+ const titleEnd = findUnescapedInline(value, closer, cursor + 1);
148
+ if (titleEnd === void 0) return;
149
+ title = value.slice(cursor + 1, titleEnd);
150
+ cursor = titleEnd + 1;
151
+ while (isUnicodeWhitespace(value.char(cursor) ?? "")) cursor++;
152
+ }
153
+ return value.char(cursor) === ")" ? {
154
+ destination,
155
+ end: cursor + 1,
156
+ title
157
+ } : void 0;
158
+ }
159
+ function referenceSuffix(value, start) {
160
+ if (value.char(start) !== "[") return;
161
+ const end = findUnescapedInline(value, "]", start + 1);
162
+ if (end === void 0 || end - start > 1e3 || value.slice(start + 1, end).includes("[")) return;
163
+ return {
164
+ end: end + 1,
165
+ label: value.slice(start + 1, end)
166
+ };
167
+ }
168
+ function decodeLinkString(value) {
169
+ return value.replace(/\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|[xX][\dA-Fa-f]{1,6})|[A-Za-z][\dA-Za-z]{1,30});/gu, (match, escaped, reference) => {
170
+ if (escaped !== void 0) return escaped;
171
+ if (reference === void 0) return match;
172
+ if (!reference.startsWith("#")) return decodeNamedCharacterReference(reference) ?? match;
173
+ const hexadecimal = reference[1] === "x" || reference[1] === "X";
174
+ return decodeNumericCharacterReference(reference.slice(hexadecimal ? 2 : 1), hexadecimal ? 16 : 10);
175
+ });
176
+ }
177
+ function inlinePlainText(nodes) {
178
+ return nodes.map((node) => node.kind === "text" || node.kind === "code" || node.kind === "rawHtml" ? node.value : "children" in node ? inlinePlainText(node.children) : "").join("");
179
+ }
180
+ /** Delimiters after a resolved bracket are inside its node. */
181
+ function removeDetachedDelimiters(delimiters, bracket) {
182
+ while ((delimiters.at(-1)?.start ?? -1) > bracket.start) delimiters.pop();
183
+ }
184
+ //#endregion
185
+ export { resolveBracket };
186
+
187
+ //# sourceMappingURL=inline-link.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-link.mjs","names":[],"sources":["../../src/parser/inline-link.ts"],"sourcesContent":["import type { SourceText } from \"../source-text.ts\";\nimport type { ResolvedSyntaxOptions } from \"../syntax-options.ts\";\nimport type { Bracket, Delimiter, Output } from \"./inline-output.ts\";\nimport type { DefinitionLookup, InlineSyntax } from \"./inline-syntax.ts\";\n\nimport {\n decodeNamedCharacterReference,\n decodeNumericCharacterReference,\n} from \"../character-reference.ts\";\nimport { normalizeIdentifier } from \"../identifier.ts\";\nimport { isUnicodeWhitespace } from \"./characters.ts\";\nimport { matchLiteralAutolink } from \"./inline-autolink.ts\";\nimport { resolveDelimiters } from \"./inline-emphasis.ts\";\nimport { InlineInput } from \"./inline-input.ts\";\nimport {\n bracketText,\n delimiterText,\n escapedAt,\n findUnescapedInline,\n isBracket,\n isDelimiter,\n mergeText,\n textNode,\n} from \"./inline-output.ts\";\n\n// Links, images, references, and footnote references, resolved at a closing bracket.\n\ninterface ReferenceSuffix {\n readonly end: number;\n readonly label: string;\n}\n\nexport function resolveBracket(\n input: InlineInput,\n value: SourceText,\n close: number,\n bracket: Bracket,\n output: Output[],\n delimiters: Delimiter[],\n syntax: ResolvedSyntaxOptions,\n definitions: DefinitionLookup,\n references: Set<string>,\n nested: boolean,\n): Readonly<{ end: number; link: boolean }> | undefined {\n const outputIndex = output.lastIndexOf(bracket);\n\n if (outputIndex === -1) {\n throw new Error(\"Bracket stack diverged from inline output\");\n }\n\n if (!bracket.active) {\n output[outputIndex] = bracketText(input, bracket);\n\n return;\n }\n\n const labelStart = bracket.start + (bracket.image ? 2 : 1);\n const label = value.slice(labelStart, close);\n\n if (\n !bracket.image &&\n label.startsWith(\"^\") &&\n !label.slice(1).includes(\"[\") &&\n !label.slice(1).includes(\"]\")\n ) {\n output.splice(outputIndex, output.length - outputIndex, {\n kind: \"footnoteReference\",\n range: input.sourceRange(bracket.start, close + 1),\n identifier: normalizeIdentifier(label.slice(1)),\n });\n removeDetachedDelimiters(delimiters, bracket);\n\n return { end: close + 1, link: true };\n }\n\n const inline = value.char(close + 1) === \"(\" ? linkDestination(value, close + 2) : undefined;\n const reference = inline === undefined ? referenceSuffix(value, close + 1) : undefined;\n const identifier = normalizeIdentifier(reference?.label || label);\n const defined = definitions.has(identifier);\n\n if (inline === undefined) {\n if (identifier !== \"\" && (nested || /(?:https?:\\/\\/|www\\.|@)/iu.test(label))) {\n references.add(identifier);\n }\n\n // Missing inner references remain label text. A later definition reparses their dependents.\n if (identifier === \"\" || (nested && !defined)) {\n output[outputIndex] = bracketText(input, bracket);\n\n return;\n }\n }\n\n resolveDelimiters(input, output, delimiters, syntax, bracket.start);\n\n const children = output\n .slice(outputIndex + 1)\n .map((entry) =>\n isDelimiter(entry)\n ? delimiterText(input, entry)\n : isBracket(entry)\n ? bracketText(input, entry)\n : entry,\n );\n\n if (inline !== undefined) {\n const destination = decodeLinkString(inline.destination);\n\n const node: InlineSyntax = bracket.image\n ? {\n kind: \"image\",\n range: input.sourceRange(bracket.start, inline.end),\n destination,\n title: inline.title === undefined ? undefined : decodeLinkString(inline.title),\n alt: inlinePlainText(children),\n }\n : {\n kind: \"link\",\n range: input.sourceRange(bracket.start, inline.end),\n destination,\n title: inline.title === undefined ? undefined : decodeLinkString(inline.title),\n children: mergeText(children),\n };\n\n output.splice(outputIndex, output.length - outputIndex, node);\n removeDetachedDelimiters(delimiters, bracket);\n\n return { end: inline.end, link: !bracket.image };\n }\n\n const end = reference?.end ?? close + 1;\n const autolinks = !defined && !bracket.image ? fallbackAutolinks(input, children) : undefined;\n\n if (autolinks !== undefined) {\n output.splice(\n outputIndex,\n output.length - outputIndex,\n bracketText(input, bracket),\n ...autolinks,\n textNode(input, value, close, end),\n );\n } else {\n output.splice(outputIndex, output.length - outputIndex, {\n kind: \"reference\",\n range: input.sourceRange(bracket.start, end),\n identifier,\n referenceKind:\n reference === undefined ? \"shortcut\" : reference.label === \"\" ? \"collapsed\" : \"full\",\n image: bracket.image,\n children: mergeText(children),\n });\n }\n\n removeDetachedDelimiters(delimiters, bracket);\n\n return { end, link: defined && !bracket.image };\n}\n\n/** Literal labels resume normal autolinking when no reference definition exists. */\nfunction fallbackAutolinks(\n input: InlineInput,\n children: readonly InlineSyntax[],\n): InlineSyntax[] | undefined {\n const output: InlineSyntax[] = [];\n let changed = false;\n\n for (const child of children) {\n if (child.kind !== \"text\" || !/(?:https?:\\/\\/|www\\.|@)/iu.test(child.value)) {\n output.push(child);\n continue;\n }\n\n const part = new InlineInput(input.file, [{ kind: \"source\", range: child.range }]);\n const value = part.text();\n\n if (value.toString() !== child.value) {\n output.push(child);\n continue;\n }\n\n let start = 0;\n\n for (let offset = 0; offset < value.length; offset++) {\n const match = matchLiteralAutolink(part, value, offset);\n\n if (match === undefined) {\n continue;\n }\n\n if (start < offset) {\n output.push(textNode(part, value, start, offset));\n }\n\n output.push(match.node);\n offset = match.end - 1;\n start = match.end;\n changed = true;\n }\n\n if (start < value.length) {\n output.push(textNode(part, value, start, value.length));\n }\n }\n\n return changed ? output : undefined;\n}\n\ninterface LinkDestinationResult {\n readonly destination: string;\n readonly end: number;\n readonly title: string | undefined;\n}\n\nfunction linkDestination(value: SourceText, start: number): LinkDestinationResult | undefined {\n let cursor = start;\n\n while (value.char(cursor) === \" \" || value.char(cursor) === \"\\t\" || value.char(cursor) === \"\\n\") {\n cursor++;\n }\n\n let destination = \"\";\n\n if (value.char(cursor) === \"<\") {\n const end = findUnescapedInline(value, \">\", cursor + 1);\n\n if (end === undefined || /[\\r\\n<]/u.test(value.slice(cursor + 1, end))) {\n return;\n }\n\n destination = value.slice(cursor + 1, end);\n cursor = end + 1;\n } else {\n const destinationStart = cursor;\n let depth = 0;\n\n while (cursor < value.length) {\n const character = value.char(cursor);\n\n if (isUnicodeWhitespace(character ?? \"\")) {\n break;\n }\n\n if (character === \"(\" && !escapedAt(value, cursor, destinationStart)) {\n if (++depth > 32) {\n return;\n }\n } else if (character === \")\" && !escapedAt(value, cursor, destinationStart)) {\n if (depth === 0) {\n break;\n }\n\n depth--;\n }\n\n cursor++;\n }\n\n if (depth !== 0) {\n return;\n }\n\n destination = value.slice(destinationStart, cursor);\n }\n\n const beforeWhitespace = cursor;\n\n while (isUnicodeWhitespace(value.char(cursor) ?? \"\")) {\n cursor++;\n }\n\n let title: string | undefined;\n\n if (cursor !== beforeWhitespace && value.char(cursor) !== \")\") {\n const opener = value.char(cursor);\n const closer = opener === \"(\" ? \")\" : opener === \"'\" ? \"'\" : opener === '\"' ? '\"' : undefined;\n\n if (closer === undefined) {\n return;\n }\n\n const titleEnd = findUnescapedInline(value, closer, cursor + 1);\n\n if (titleEnd === undefined) {\n return;\n }\n\n title = value.slice(cursor + 1, titleEnd);\n cursor = titleEnd + 1;\n\n while (isUnicodeWhitespace(value.char(cursor) ?? \"\")) {\n cursor++;\n }\n }\n\n return value.char(cursor) === \")\" ? { destination, end: cursor + 1, title } : undefined;\n}\n\nfunction referenceSuffix(value: SourceText, start: number): ReferenceSuffix | undefined {\n if (value.char(start) !== \"[\") {\n return;\n }\n\n const end = findUnescapedInline(value, \"]\", start + 1);\n\n if (end === undefined || end - start > 1000 || value.slice(start + 1, end).includes(\"[\")) {\n return;\n }\n\n return { end: end + 1, label: value.slice(start + 1, end) };\n}\n\nfunction decodeLinkString(value: string): string {\n return value.replace(\n /\\\\([!-/:-@[-`{-~])|&(#(?:\\d{1,7}|[xX][\\dA-Fa-f]{1,6})|[A-Za-z][\\dA-Za-z]{1,30});/gu,\n (match, escaped: string | undefined, reference: string | undefined) => {\n if (escaped !== undefined) {\n return escaped;\n }\n\n if (reference === undefined) {\n return match;\n }\n\n if (!reference.startsWith(\"#\")) {\n return decodeNamedCharacterReference(reference) ?? match;\n }\n\n const hexadecimal = reference[1] === \"x\" || reference[1] === \"X\";\n\n return decodeNumericCharacterReference(\n reference.slice(hexadecimal ? 2 : 1),\n hexadecimal ? 16 : 10,\n );\n },\n );\n}\n\nfunction inlinePlainText(nodes: readonly InlineSyntax[]): string {\n return nodes\n .map((node) =>\n node.kind === \"text\" || node.kind === \"code\" || node.kind === \"rawHtml\"\n ? node.value\n : \"children\" in node\n ? inlinePlainText(node.children)\n : \"\",\n )\n .join(\"\");\n}\n\n/** Delimiters after a resolved bracket are inside its node. */\nfunction removeDetachedDelimiters(delimiters: Delimiter[], bracket: Bracket): void {\n while ((delimiters.at(-1)?.start ?? -1) > bracket.start) {\n delimiters.pop();\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { SourceText } from "../source-text.mjs";
2
+ import { InlineInput } from "./inline-input.mjs";
3
+ import { InlineMatch } from "./inline-output.mjs";
4
+ //#region src/parser/inline-math.d.ts
5
+ export declare function texMath(input: InlineInput, value: SourceText, start: number): InlineMatch | undefined;
6
+ export declare function dollarMath(input: InlineInput, value: SourceText, start: number): InlineMatch | undefined;
7
+ /** An opening dollar that later input could still close. */
8
+ export declare function dollarUnclosed(value: SourceText, start: number): boolean;
9
+ //#endregion
10
+ //# sourceMappingURL=inline-math.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-math.d.mts","names":[],"sources":["../../src/parser/inline-math.ts"],"mappings":";;;;wBASgB,QACd,OAAO,aACP,OAAO,YACP,gBACC;wBAwBa,WACd,OAAO,aACP,OAAO,YACP,gBACC;;wBA6Ba,eAAe,OAAO,YAAY"}
@@ -0,0 +1,46 @@
1
+ import { isUnicodeWhitespace } from "./characters.mjs";
2
+ import { escapedAt } from "./inline-output.mjs";
3
+ //#region src/parser/inline-math.ts
4
+ function texMath(input, value, start) {
5
+ let close = value.indexOf("\\)", start + 2);
6
+ while (close !== -1 && escapedAt(value, close, start + 2)) close = value.indexOf("\\)", close + 2);
7
+ if (close === -1) return;
8
+ const end = close + 2;
9
+ return {
10
+ end,
11
+ node: {
12
+ kind: "math",
13
+ range: input.sourceRange(start, end),
14
+ value: value.slice(start + 2, close),
15
+ format: "tex"
16
+ }
17
+ };
18
+ }
19
+ function dollarMath(input, value, start) {
20
+ if (value.char(start + 1) === void 0 || isUnicodeWhitespace(value.char(start + 1) ?? "")) return;
21
+ let close = value.indexOf("$", start + 1);
22
+ while (close !== -1 && escapedAt(value, close, start + 1)) close = value.indexOf("$", close + 1);
23
+ if (close === -1 || close === start + 1 || isUnicodeWhitespace(value.char(close - 1) ?? "")) return;
24
+ const end = close + 1;
25
+ return {
26
+ end,
27
+ node: {
28
+ kind: "math",
29
+ range: input.sourceRange(start, end),
30
+ value: value.slice(start + 1, close),
31
+ format: "dollar"
32
+ }
33
+ };
34
+ }
35
+ /** An opening dollar that later input could still close. */
36
+ function dollarUnclosed(value, start) {
37
+ if (value.char(start + 1) === void 0) return true;
38
+ if (isUnicodeWhitespace(value.char(start + 1) ?? "")) return false;
39
+ let close = value.indexOf("$", start + 1);
40
+ while (close !== -1 && escapedAt(value, close, start + 1)) close = value.indexOf("$", close + 1);
41
+ return close === -1;
42
+ }
43
+ //#endregion
44
+ export { dollarMath, dollarUnclosed, texMath };
45
+
46
+ //# sourceMappingURL=inline-math.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-math.mjs","names":[],"sources":["../../src/parser/inline-math.ts"],"sourcesContent":["import type { SourceText } from \"../source-text.ts\";\nimport type { InlineInput } from \"./inline-input.ts\";\nimport type { InlineMatch } from \"./inline-output.ts\";\n\nimport { isUnicodeWhitespace } from \"./characters.ts\";\nimport { escapedAt } from \"./inline-output.ts\";\n\n// Inline TeX and dollar math.\n\nexport function texMath(\n input: InlineInput,\n value: SourceText,\n start: number,\n): InlineMatch | undefined {\n let close = value.indexOf(\"\\\\)\", start + 2);\n\n while (close !== -1 && escapedAt(value, close, start + 2)) {\n close = value.indexOf(\"\\\\)\", close + 2);\n }\n\n if (close === -1) {\n return;\n }\n\n const end = close + 2;\n\n return {\n end,\n node: {\n kind: \"math\",\n range: input.sourceRange(start, end),\n value: value.slice(start + 2, close),\n format: \"tex\",\n },\n };\n}\n\nexport function dollarMath(\n input: InlineInput,\n value: SourceText,\n start: number,\n): InlineMatch | undefined {\n if (value.char(start + 1) === undefined || isUnicodeWhitespace(value.char(start + 1) ?? \"\")) {\n return;\n }\n\n let close = value.indexOf(\"$\", start + 1);\n\n while (close !== -1 && escapedAt(value, close, start + 1)) {\n close = value.indexOf(\"$\", close + 1);\n }\n\n if (close === -1 || close === start + 1 || isUnicodeWhitespace(value.char(close - 1) ?? \"\")) {\n return;\n }\n\n const end = close + 1;\n\n return {\n end,\n node: {\n kind: \"math\",\n range: input.sourceRange(start, end),\n value: value.slice(start + 1, close),\n format: \"dollar\",\n },\n };\n}\n\n/** An opening dollar that later input could still close. */\nexport function dollarUnclosed(value: SourceText, start: number): boolean {\n if (value.char(start + 1) === undefined) {\n return true;\n }\n\n if (isUnicodeWhitespace(value.char(start + 1) ?? \"\")) {\n return false;\n }\n\n let close = value.indexOf(\"$\", start + 1);\n\n while (close !== -1 && escapedAt(value, close, start + 1)) {\n close = value.indexOf(\"$\", close + 1);\n }\n\n return close === -1;\n}\n"],"mappings":";;;AASA,SAAgB,QACd,OACA,OACA,OACyB;CACzB,IAAI,QAAQ,MAAM,QAAQ,OAAO,QAAQ,CAAC;CAE1C,OAAO,UAAU,MAAM,UAAU,OAAO,OAAO,QAAQ,CAAC,GACtD,QAAQ,MAAM,QAAQ,OAAO,QAAQ,CAAC;CAGxC,IAAI,UAAU,IACZ;CAGF,MAAM,MAAM,QAAQ;CAEpB,OAAO;EACL;EACA,MAAM;GACJ,MAAM;GACN,OAAO,MAAM,YAAY,OAAO,GAAG;GACnC,OAAO,MAAM,MAAM,QAAQ,GAAG,KAAK;GACnC,QAAQ;EACV;CACF;AACF;AAEA,SAAgB,WACd,OACA,OACA,OACyB;CACzB,IAAI,MAAM,KAAK,QAAQ,CAAC,MAAM,KAAA,KAAa,oBAAoB,MAAM,KAAK,QAAQ,CAAC,KAAK,EAAE,GACxF;CAGF,IAAI,QAAQ,MAAM,QAAQ,KAAK,QAAQ,CAAC;CAExC,OAAO,UAAU,MAAM,UAAU,OAAO,OAAO,QAAQ,CAAC,GACtD,QAAQ,MAAM,QAAQ,KAAK,QAAQ,CAAC;CAGtC,IAAI,UAAU,MAAM,UAAU,QAAQ,KAAK,oBAAoB,MAAM,KAAK,QAAQ,CAAC,KAAK,EAAE,GACxF;CAGF,MAAM,MAAM,QAAQ;CAEpB,OAAO;EACL;EACA,MAAM;GACJ,MAAM;GACN,OAAO,MAAM,YAAY,OAAO,GAAG;GACnC,OAAO,MAAM,MAAM,QAAQ,GAAG,KAAK;GACnC,QAAQ;EACV;CACF;AACF;;AAGA,SAAgB,eAAe,OAAmB,OAAwB;CACxE,IAAI,MAAM,KAAK,QAAQ,CAAC,MAAM,KAAA,GAC5B,OAAO;CAGT,IAAI,oBAAoB,MAAM,KAAK,QAAQ,CAAC,KAAK,EAAE,GACjD,OAAO;CAGT,IAAI,QAAQ,MAAM,QAAQ,KAAK,QAAQ,CAAC;CAExC,OAAO,UAAU,MAAM,UAAU,OAAO,OAAO,QAAQ,CAAC,GACtD,QAAQ,MAAM,QAAQ,KAAK,QAAQ,CAAC;CAGtC,OAAO,UAAU;AACnB"}