dsh-better-display 0.1.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 (300) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/DESIGN.md +72 -0
  3. package/LICENSE +24 -0
  4. package/README.en.md +41 -0
  5. package/README.md +41 -0
  6. package/THIRD_PARTY_NOTICES.md +65 -0
  7. package/cordis.patch.yml +5 -0
  8. package/cordis.yml +4 -0
  9. package/dshx.yml +5 -0
  10. package/lib/client.js +49923 -0
  11. package/lib/client.js.map +1 -0
  12. package/lib/dsh-better-display.js +256 -0
  13. package/lib/types/client/Blocks.d.ts +45 -0
  14. package/lib/types/client/Blocks.d.ts.map +1 -0
  15. package/lib/types/client/Blocks.js +136 -0
  16. package/lib/types/client/Blocks.js.map +1 -0
  17. package/lib/types/client/ChoreographedFlow.d.ts +22 -0
  18. package/lib/types/client/ChoreographedFlow.d.ts.map +1 -0
  19. package/lib/types/client/ChoreographedFlow.js +170 -0
  20. package/lib/types/client/ChoreographedFlow.js.map +1 -0
  21. package/lib/types/client/ClosedProcessSummary.d.ts +9 -0
  22. package/lib/types/client/ClosedProcessSummary.d.ts.map +1 -0
  23. package/lib/types/client/ClosedProcessSummary.js +15 -0
  24. package/lib/types/client/ClosedProcessSummary.js.map +1 -0
  25. package/lib/types/client/LiveFold.d.ts +10 -0
  26. package/lib/types/client/LiveFold.d.ts.map +1 -0
  27. package/lib/types/client/LiveFold.js +39 -0
  28. package/lib/types/client/LiveFold.js.map +1 -0
  29. package/lib/types/client/McpAppFrame.d.ts +32 -0
  30. package/lib/types/client/McpAppFrame.d.ts.map +1 -0
  31. package/lib/types/client/McpAppFrame.js +193 -0
  32. package/lib/types/client/McpAppFrame.js.map +1 -0
  33. package/lib/types/client/Reader.d.ts +3 -0
  34. package/lib/types/client/Reader.d.ts.map +1 -0
  35. package/lib/types/client/Reader.js +537 -0
  36. package/lib/types/client/Reader.js.map +1 -0
  37. package/lib/types/client/ReasoningCard.d.ts +11 -0
  38. package/lib/types/client/ReasoningCard.d.ts.map +1 -0
  39. package/lib/types/client/ReasoningCard.js +301 -0
  40. package/lib/types/client/ReasoningCard.js.map +1 -0
  41. package/lib/types/client/StickyLane.d.ts +8 -0
  42. package/lib/types/client/StickyLane.d.ts.map +1 -0
  43. package/lib/types/client/StickyLane.js +28 -0
  44. package/lib/types/client/StickyLane.js.map +1 -0
  45. package/lib/types/client/TimelineRail.d.ts +10 -0
  46. package/lib/types/client/TimelineRail.d.ts.map +1 -0
  47. package/lib/types/client/TimelineRail.js +168 -0
  48. package/lib/types/client/TimelineRail.js.map +1 -0
  49. package/lib/types/client/ToolActivity.d.ts +17 -0
  50. package/lib/types/client/ToolActivity.d.ts.map +1 -0
  51. package/lib/types/client/ToolActivity.js +192 -0
  52. package/lib/types/client/ToolActivity.js.map +1 -0
  53. package/lib/types/client/TurnMetrics.d.ts +11 -0
  54. package/lib/types/client/TurnMetrics.d.ts.map +1 -0
  55. package/lib/types/client/TurnMetrics.js +44 -0
  56. package/lib/types/client/TurnMetrics.js.map +1 -0
  57. package/lib/types/client/WaitingStatus.d.ts +6 -0
  58. package/lib/types/client/WaitingStatus.d.ts.map +1 -0
  59. package/lib/types/client/WaitingStatus.js +19 -0
  60. package/lib/types/client/WaitingStatus.js.map +1 -0
  61. package/lib/types/client/conversation-scroll.d.ts +19 -0
  62. package/lib/types/client/conversation-scroll.d.ts.map +1 -0
  63. package/lib/types/client/conversation-scroll.js +25 -0
  64. package/lib/types/client/conversation-scroll.js.map +1 -0
  65. package/lib/types/client/deliverables.d.ts +24 -0
  66. package/lib/types/client/deliverables.d.ts.map +1 -0
  67. package/lib/types/client/deliverables.js +104 -0
  68. package/lib/types/client/deliverables.js.map +1 -0
  69. package/lib/types/client/entry-policy.d.ts +10 -0
  70. package/lib/types/client/entry-policy.d.ts.map +1 -0
  71. package/lib/types/client/entry-policy.js +24 -0
  72. package/lib/types/client/entry-policy.js.map +1 -0
  73. package/lib/types/client/entry.d.ts +4 -0
  74. package/lib/types/client/entry.d.ts.map +1 -0
  75. package/lib/types/client/entry.js +34 -0
  76. package/lib/types/client/entry.js.map +1 -0
  77. package/lib/types/client/fold-choreography.d.ts +28 -0
  78. package/lib/types/client/fold-choreography.d.ts.map +1 -0
  79. package/lib/types/client/fold-choreography.js +31 -0
  80. package/lib/types/client/fold-choreography.js.map +1 -0
  81. package/lib/types/client/index.d.ts +7 -0
  82. package/lib/types/client/index.d.ts.map +1 -0
  83. package/lib/types/client/index.js +153 -0
  84. package/lib/types/client/index.js.map +1 -0
  85. package/lib/types/client/live-turn.d.ts +58 -0
  86. package/lib/types/client/live-turn.d.ts.map +1 -0
  87. package/lib/types/client/live-turn.js +144 -0
  88. package/lib/types/client/live-turn.js.map +1 -0
  89. package/lib/types/client/markdown/MarkdownText.d.ts +39 -0
  90. package/lib/types/client/markdown/MarkdownText.d.ts.map +1 -0
  91. package/lib/types/client/markdown/MarkdownText.js +171 -0
  92. package/lib/types/client/markdown/MarkdownText.js.map +1 -0
  93. package/lib/types/client/markdown/cjkFriendlyStrong.d.ts +9 -0
  94. package/lib/types/client/markdown/cjkFriendlyStrong.d.ts.map +1 -0
  95. package/lib/types/client/markdown/cjkFriendlyStrong.js +73 -0
  96. package/lib/types/client/markdown/cjkFriendlyStrong.js.map +1 -0
  97. package/lib/types/client/markdown/incremental.d.ts +69 -0
  98. package/lib/types/client/markdown/incremental.d.ts.map +1 -0
  99. package/lib/types/client/markdown/incremental.js +108 -0
  100. package/lib/types/client/markdown/incremental.js.map +1 -0
  101. package/lib/types/client/markdown/katex.d.ts +27 -0
  102. package/lib/types/client/markdown/katex.d.ts.map +1 -0
  103. package/lib/types/client/markdown/katex.js +88 -0
  104. package/lib/types/client/markdown/katex.js.map +1 -0
  105. package/lib/types/client/markdown/mathCompatibility.d.ts +11 -0
  106. package/lib/types/client/markdown/mathCompatibility.d.ts.map +1 -0
  107. package/lib/types/client/markdown/mathCompatibility.js +293 -0
  108. package/lib/types/client/markdown/mathCompatibility.js.map +1 -0
  109. package/lib/types/client/markdown/parse.d.ts +25 -0
  110. package/lib/types/client/markdown/parse.d.ts.map +1 -0
  111. package/lib/types/client/markdown/parse.js +42 -0
  112. package/lib/types/client/markdown/parse.js.map +1 -0
  113. package/lib/types/client/markdown/render.d.ts +119 -0
  114. package/lib/types/client/markdown/render.d.ts.map +1 -0
  115. package/lib/types/client/markdown/render.js +435 -0
  116. package/lib/types/client/markdown/render.js.map +1 -0
  117. package/lib/types/client/mcp-app.d.ts +50 -0
  118. package/lib/types/client/mcp-app.d.ts.map +1 -0
  119. package/lib/types/client/mcp-app.js +328 -0
  120. package/lib/types/client/mcp-app.js.map +1 -0
  121. package/lib/types/client/message-chrome.d.ts +19 -0
  122. package/lib/types/client/message-chrome.d.ts.map +1 -0
  123. package/lib/types/client/message-chrome.js +42 -0
  124. package/lib/types/client/message-chrome.js.map +1 -0
  125. package/lib/types/client/motion.d.ts +38 -0
  126. package/lib/types/client/motion.d.ts.map +1 -0
  127. package/lib/types/client/motion.js +367 -0
  128. package/lib/types/client/motion.js.map +1 -0
  129. package/lib/types/client/native/ContextBody.d.ts +130 -0
  130. package/lib/types/client/native/ContextBody.d.ts.map +1 -0
  131. package/lib/types/client/native/ContextBody.js +398 -0
  132. package/lib/types/client/native/ContextBody.js.map +1 -0
  133. package/lib/types/client/native/ContextInjectionRow.d.ts +26 -0
  134. package/lib/types/client/native/ContextInjectionRow.d.ts.map +1 -0
  135. package/lib/types/client/native/ContextInjectionRow.js +27 -0
  136. package/lib/types/client/native/ContextInjectionRow.js.map +1 -0
  137. package/lib/types/client/native/ReferenceIcon.d.ts +16 -0
  138. package/lib/types/client/native/ReferenceIcon.d.ts.map +1 -0
  139. package/lib/types/client/native/ReferenceIcon.js +16 -0
  140. package/lib/types/client/native/ReferenceIcon.js.map +1 -0
  141. package/lib/types/client/native/tool-call-model.d.ts +58 -0
  142. package/lib/types/client/native/tool-call-model.d.ts.map +1 -0
  143. package/lib/types/client/native/tool-call-model.js +219 -0
  144. package/lib/types/client/native/tool-call-model.js.map +1 -0
  145. package/lib/types/client/open-file.d.ts +24 -0
  146. package/lib/types/client/primitive-labels.d.ts +10 -0
  147. package/lib/types/client/primitive-labels.d.ts.map +1 -0
  148. package/lib/types/client/primitive-labels.js +37 -0
  149. package/lib/types/client/primitive-labels.js.map +1 -0
  150. package/lib/types/client/projection.d.ts +41 -0
  151. package/lib/types/client/projection.d.ts.map +1 -0
  152. package/lib/types/client/projection.js +112 -0
  153. package/lib/types/client/projection.js.map +1 -0
  154. package/lib/types/client/reasoning-follow.d.ts +6 -0
  155. package/lib/types/client/reasoning-follow.d.ts.map +1 -0
  156. package/lib/types/client/reasoning-follow.js +12 -0
  157. package/lib/types/client/reasoning-follow.js.map +1 -0
  158. package/lib/types/client/settings-copy.d.ts +6 -0
  159. package/lib/types/client/settings-slots.d.ts +16 -0
  160. package/lib/types/client/store.d.ts +17 -0
  161. package/lib/types/client/store.d.ts.map +1 -0
  162. package/lib/types/client/store.js +13 -0
  163. package/lib/types/client/store.js.map +1 -0
  164. package/lib/types/client/stream-buffer.d.ts +29 -0
  165. package/lib/types/client/stream-buffer.d.ts.map +1 -0
  166. package/lib/types/client/stream-buffer.js +113 -0
  167. package/lib/types/client/stream-buffer.js.map +1 -0
  168. package/lib/types/client/streaming.d.ts +18 -0
  169. package/lib/types/client/streaming.d.ts.map +1 -0
  170. package/lib/types/client/streaming.js +77 -0
  171. package/lib/types/client/streaming.js.map +1 -0
  172. package/lib/types/client/timeline.d.ts +26 -0
  173. package/lib/types/client/timeline.d.ts.map +1 -0
  174. package/lib/types/client/timeline.js +48 -0
  175. package/lib/types/client/timeline.js.map +1 -0
  176. package/lib/types/client/tool-activity.d.ts +52 -0
  177. package/lib/types/client/tool-activity.d.ts.map +1 -0
  178. package/lib/types/client/tool-activity.js +178 -0
  179. package/lib/types/client/tool-activity.js.map +1 -0
  180. package/lib/types/client/types.d.ts +66 -0
  181. package/lib/types/client/types.d.ts.map +1 -0
  182. package/lib/types/client/types.js +2 -0
  183. package/lib/types/client/types.js.map +1 -0
  184. package/lib/types/client/waiting-clock.d.ts +17 -0
  185. package/lib/types/client/waiting-clock.d.ts.map +1 -0
  186. package/lib/types/client/waiting-clock.js +24 -0
  187. package/lib/types/client/waiting-clock.js.map +1 -0
  188. package/lib/types/client/word-motion.d.ts +16 -0
  189. package/lib/types/client/word-motion.d.ts.map +1 -0
  190. package/lib/types/client/word-motion.js +89 -0
  191. package/lib/types/client/word-motion.js.map +1 -0
  192. package/lib/types/client/word-timeline.d.ts +28 -0
  193. package/lib/types/client/word-timeline.d.ts.map +1 -0
  194. package/lib/types/client/word-timeline.js +100 -0
  195. package/lib/types/client/word-timeline.js.map +1 -0
  196. package/lib/types/dsh-better-display.d.ts +17 -0
  197. package/lib/types/dsh-better-display.d.ts.map +1 -0
  198. package/lib/types/dsh-better-display.js +53 -0
  199. package/lib/types/dsh-better-display.js.map +1 -0
  200. package/package.json +121 -0
  201. package/scripts/build-motion-fixture.mjs +26 -0
  202. package/scripts/link-harness-dependencies.mjs +51 -0
  203. package/skills/generative-mcpapps/SKILL.md +47 -0
  204. package/skills/generative-mcpapps/examples/interactive_quiz.html +153 -0
  205. package/skills/generative-mcpapps/references/html_boilerplate.md +122 -0
  206. package/skills/generative-mcpapps/references/sep1865_protocol.md +54 -0
  207. package/src/client/Blocks.tsx +205 -0
  208. package/src/client/ChoreographedFlow.tsx +182 -0
  209. package/src/client/ClosedProcessSummary.tsx +19 -0
  210. package/src/client/LiveFold.tsx +43 -0
  211. package/src/client/McpAppFrame.module.css +210 -0
  212. package/src/client/McpAppFrame.tsx +317 -0
  213. package/src/client/Reader.module.css +329 -0
  214. package/src/client/Reader.tsx +814 -0
  215. package/src/client/ReasoningCard.tsx +285 -0
  216. package/src/client/SettingsSection.module.css +147 -0
  217. package/src/client/SettingsSection.tsx +117 -0
  218. package/src/client/StickyLane.tsx +24 -0
  219. package/src/client/TimelineRail.module.css +170 -0
  220. package/src/client/TimelineRail.tsx +262 -0
  221. package/src/client/ToolActivity.tsx +214 -0
  222. package/src/client/TurnMetrics.module.css +139 -0
  223. package/src/client/TurnMetrics.tsx +160 -0
  224. package/src/client/WaitingStatus.tsx +22 -0
  225. package/src/client/conversation-scroll.ts +28 -0
  226. package/src/client/deliverables.ts +122 -0
  227. package/src/client/entry-policy.ts +20 -0
  228. package/src/client/entry.tsx +40 -0
  229. package/src/client/fold-choreography.ts +38 -0
  230. package/src/client/index.tsx +198 -0
  231. package/src/client/live-turn.ts +155 -0
  232. package/src/client/markdown/MarkdownText.module.css +304 -0
  233. package/src/client/markdown/MarkdownText.tsx +187 -0
  234. package/src/client/markdown/cjkFriendlyStrong.ts +84 -0
  235. package/src/client/markdown/incremental.ts +131 -0
  236. package/src/client/markdown/katex.tsx +91 -0
  237. package/src/client/markdown/mathCompatibility.ts +350 -0
  238. package/src/client/markdown/parse.ts +45 -0
  239. package/src/client/markdown/render.tsx +630 -0
  240. package/src/client/markdown/upstream.json +14 -0
  241. package/src/client/mcp-app.ts +323 -0
  242. package/src/client/message-chrome.ts +47 -0
  243. package/src/client/motion.tsx +338 -0
  244. package/src/client/native/ContextBody.module.css +161 -0
  245. package/src/client/native/ContextBody.tsx +591 -0
  246. package/src/client/native/ContextInjectionRow.module.css +62 -0
  247. package/src/client/native/ContextInjectionRow.tsx +72 -0
  248. package/src/client/native/ReferenceIcon.tsx +35 -0
  249. package/src/client/native/tool-call-model.ts +248 -0
  250. package/src/client/native/upstream.json +41 -0
  251. package/src/client/open-file.ts +94 -0
  252. package/src/client/pending-submission.ts +49 -0
  253. package/src/client/primitive-labels.ts +53 -0
  254. package/src/client/projection.ts +118 -0
  255. package/src/client/reasoning-follow.ts +12 -0
  256. package/src/client/settings-copy.ts +53 -0
  257. package/src/client/settings-slots.ts +20 -0
  258. package/src/client/settings.tsx +73 -0
  259. package/src/client/skill-status.ts +78 -0
  260. package/src/client/store.ts +30 -0
  261. package/src/client/stream-buffer.ts +100 -0
  262. package/src/client/streaming.tsx +62 -0
  263. package/src/client/style.d.ts +4 -0
  264. package/src/client/timeline.ts +77 -0
  265. package/src/client/tool-activity.ts +152 -0
  266. package/src/client/types.ts +66 -0
  267. package/src/client/waiting-clock.ts +25 -0
  268. package/src/client/word-motion.tsx +91 -0
  269. package/src/client/word-timeline.ts +96 -0
  270. package/src/dsh-better-display.ts +108 -0
  271. package/src/skill-roots.ts +138 -0
  272. package/src/skill-status.ts +81 -0
  273. package/tests/browser-closed-gap.tsx +20 -0
  274. package/tests/browser-motion.tsx +65 -0
  275. package/tests/browser-sticky-lanes.tsx +22 -0
  276. package/tests/browser-waiting-clock.tsx +14 -0
  277. package/tests/chat-flow-hook.test.ts +66 -0
  278. package/tests/cloud-gate.test.ts +34 -0
  279. package/tests/conversation-scroll.test.ts +47 -0
  280. package/tests/deliverables.test.ts +128 -0
  281. package/tests/entry.test.ts +42 -0
  282. package/tests/fixtures/maid-composer-hide.html +31 -0
  283. package/tests/fold-choreography.test.ts +38 -0
  284. package/tests/history-word-regression.test.ts +16 -0
  285. package/tests/live-turn.test.ts +218 -0
  286. package/tests/mcp-apps.test.ts +157 -0
  287. package/tests/message-chrome.test.ts +29 -0
  288. package/tests/open-file.test.ts +103 -0
  289. package/tests/pending-submission.test.ts +45 -0
  290. package/tests/projection.test.ts +184 -0
  291. package/tests/reasoning-follow.test.ts +34 -0
  292. package/tests/settings-copy.test.ts +63 -0
  293. package/tests/skill-status.test.ts +137 -0
  294. package/tests/stock-install.test.ts +50 -0
  295. package/tests/stream-buffer.test.ts +97 -0
  296. package/tests/timeline.test.ts +59 -0
  297. package/tests/waiting-clock.test.ts +24 -0
  298. package/tests/word-timeline.test.ts +136 -0
  299. package/tsconfig.json +11 -0
  300. package/tsdown.config.ts +49 -0
@@ -0,0 +1,350 @@
1
+ // Adapted from DeepSeek Harness b150a551b8d465e31e418e1b2eaf5e79bbb7d28e (MIT). See THIRD_PARTY_NOTICES.md.
2
+ /** Extend upstream dollar-only math syntax with TeX delimiters while reusing its token vocabulary. */
3
+
4
+ import { factorySpace } from 'micromark-factory-space'
5
+ import type {} from 'micromark-extension-math'
6
+ import { markdownLineEnding } from 'micromark-util-character'
7
+ import { codes, constants, types } from 'micromark-util-symbol'
8
+ import type { Construct, Extension, Previous, State, Tokenizer } from 'micromark-util-types'
9
+
10
+ // oxlint-disable typescript/no-this-alias -- micromark binds tokenizer context only on the outer callback.
11
+
12
+ const previousBackslash: Previous = function (code) {
13
+ if (code !== codes.backslash) return true
14
+ const tail = this.events.at(-1)
15
+ /* v8 ignore next -- a previous code necessarily has a preceding event. */
16
+ if (tail === undefined) return false
17
+ return tail[1].type === types.characterEscape
18
+ }
19
+
20
+ const tokenizeBackslashMathText: Tokenizer = function (effects, ok, nok) {
21
+ return start
22
+
23
+ function start(code: number | null): State | undefined {
24
+ /* v8 ignore next -- the text construct is dispatched only for a backslash. */
25
+ if (code !== codes.backslash) return nok(code)
26
+ effects.enter('mathText')
27
+ effects.enter('mathTextSequence')
28
+ effects.consume(code)
29
+ return open
30
+ }
31
+
32
+ function open(code: number | null): State | undefined {
33
+ if (code !== codes.leftParenthesis) return nok(code)
34
+ effects.consume(code)
35
+ effects.exit('mathTextSequence')
36
+ return between
37
+ }
38
+
39
+ function between(code: number | null): State | undefined {
40
+ if (code === codes.eof) return nok(code)
41
+ if (code === codes.backslash) {
42
+ return effects.attempt({ partial: true, tokenize: tokenizeClose }, close, afterCloseAttempt)(code)
43
+ }
44
+ if (markdownLineEnding(code)) {
45
+ effects.enter(types.lineEnding)
46
+ effects.consume(code)
47
+ effects.exit(types.lineEnding)
48
+ return between
49
+ }
50
+ return dataStart(code)
51
+ }
52
+
53
+ function afterCloseAttempt(code: number | null): State | undefined {
54
+ return effects.check({ partial: true, tokenize: tokenizeOpen }, nok, dataStart)(code)
55
+ }
56
+
57
+ function dataStart(code: number | null): State | undefined {
58
+ effects.enter('mathTextData')
59
+ effects.consume(code)
60
+ return code === codes.backslash ? afterDataBackslash : data
61
+ }
62
+
63
+ function afterDataBackslash(code: number | null): State | undefined {
64
+ if (code === codes.backslash) {
65
+ effects.consume(code)
66
+ return data
67
+ }
68
+ return data(code)
69
+ }
70
+
71
+ function data(code: number | null): State | undefined {
72
+ if (code === codes.eof || code === codes.backslash || markdownLineEnding(code)) {
73
+ effects.exit('mathTextData')
74
+ return between(code)
75
+ }
76
+ effects.consume(code)
77
+ return data
78
+ }
79
+
80
+ function close(code: number | null): State | undefined {
81
+ effects.exit('mathText')
82
+ return ok(code)
83
+ }
84
+
85
+ function tokenizeClose(closeEffects: Parameters<Tokenizer>[0], closeOk: State, closeNok: State): State {
86
+ return slash
87
+
88
+ function slash(code: number | null): State | undefined {
89
+ /* v8 ignore next -- this partial construct is attempted only at a backslash. */
90
+ if (code !== codes.backslash) return closeNok(code)
91
+ closeEffects.enter('mathTextSequence')
92
+ closeEffects.consume(code)
93
+ return parenthesis
94
+ }
95
+
96
+ function parenthesis(code: number | null): State | undefined {
97
+ if (code !== codes.rightParenthesis) return closeNok(code)
98
+ closeEffects.consume(code)
99
+ closeEffects.exit('mathTextSequence')
100
+ return closeOk
101
+ }
102
+ }
103
+
104
+ function tokenizeOpen(openEffects: Parameters<Tokenizer>[0], openOk: State, openNok: State): State {
105
+ return slash
106
+
107
+ function slash(code: number | null): State | undefined {
108
+ /* v8 ignore next -- the opening check follows a failed close attempt at a backslash. */
109
+ if (code !== codes.backslash) return openNok(code)
110
+ openEffects.enter(types.chunkString)
111
+ openEffects.consume(code)
112
+ return parenthesis
113
+ }
114
+
115
+ function parenthesis(code: number | null): State | undefined {
116
+ if (code !== codes.leftParenthesis) return openNok(code)
117
+ openEffects.consume(code)
118
+ openEffects.exit(types.chunkString)
119
+ return openOk
120
+ }
121
+ }
122
+ }
123
+
124
+ function createMathFlow(marker: number, openMarker: number, closeMarker: number, multiline: boolean): Construct {
125
+ const tokenize: Tokenizer = function (effects, ok, nok) {
126
+ const self = this
127
+ let oddBackslashRun = false
128
+ const tail = self.events.at(-1)
129
+ const initialSize = tail?.[1].type === types.linePrefix
130
+ ? tail[2].sliceSerialize(tail[1], true).length
131
+ : 0
132
+
133
+ return start
134
+
135
+ function start(code: number | null): State | undefined {
136
+ /* v8 ignore next -- the flow construct is dispatched only for its marker. */
137
+ if (code !== marker) return nok(code)
138
+ effects.enter('mathFlow')
139
+ effects.enter('mathFlowFence')
140
+ effects.enter('mathFlowFenceSequence')
141
+ effects.consume(code)
142
+ return open
143
+ }
144
+
145
+ function open(code: number | null): State | undefined {
146
+ if (code !== openMarker) return nok(code)
147
+ effects.consume(code)
148
+ effects.exit('mathFlowFenceSequence')
149
+ effects.exit('mathFlowFence')
150
+ return marker === codes.dollarSign ? afterDollarOpen : content
151
+ }
152
+
153
+ function afterDollarOpen(code: number | null): State | undefined {
154
+ return code === codes.dollarSign ? nok(code) : content(code)
155
+ }
156
+
157
+ function content(code: number | null): State | undefined {
158
+ if (code === codes.eof) return nok(code)
159
+ if (code === marker && (marker !== codes.dollarSign || !oddBackslashRun)) {
160
+ return effects.attempt(
161
+ { partial: true, tokenize: tokenizeClosingFence },
162
+ closed,
163
+ afterClosingFenceAttempt,
164
+ )(code)
165
+ }
166
+ if (markdownLineEnding(code)) {
167
+ return multiline
168
+ ? effects.attempt(nonLazyContinuation, afterContinuation, nok)(code)
169
+ : nok(code)
170
+ }
171
+ return valueStart(code)
172
+ }
173
+
174
+ function afterClosingFenceAttempt(code: number | null): State | undefined {
175
+ return marker === codes.backslash
176
+ ? effects.check({ partial: true, tokenize: tokenizeOpeningFence }, nok, markerValueStart)(code)
177
+ : markerValueStart(code)
178
+ }
179
+
180
+ function afterContinuation(code: number | null): State | undefined {
181
+ return effects.attempt(
182
+ { partial: true, tokenize: tokenizeClosingFence },
183
+ closed,
184
+ initialSize
185
+ ? factorySpace(effects, content, types.linePrefix, initialSize + 1)
186
+ : content,
187
+ )(code)
188
+ }
189
+
190
+ function valueStart(code: number | null): State | undefined {
191
+ effects.enter('mathFlowValue')
192
+ oddBackslashRun = code === codes.backslash
193
+ effects.consume(code)
194
+ return value
195
+ }
196
+
197
+ function markerValueStart(code: number | null): State | undefined {
198
+ effects.enter('mathFlowValue')
199
+ oddBackslashRun = false
200
+ effects.consume(code)
201
+ return valueAfterMarker
202
+ }
203
+
204
+ function valueAfterMarker(code: number | null): State | undefined {
205
+ if (code === marker) {
206
+ effects.consume(code)
207
+ return value
208
+ }
209
+ return value(code)
210
+ }
211
+
212
+ function value(code: number | null): State | undefined {
213
+ if (code === codes.eof || code === marker || markdownLineEnding(code)) {
214
+ effects.exit('mathFlowValue')
215
+ return content(code)
216
+ }
217
+ oddBackslashRun = code === codes.backslash ? !oddBackslashRun : false
218
+ effects.consume(code)
219
+ return value
220
+ }
221
+
222
+ function closed(code: number | null): State | undefined {
223
+ effects.exit('mathFlow')
224
+ return ok(code)
225
+ }
226
+
227
+ function tokenizeClosingFence(
228
+ closeEffects: Parameters<Tokenizer>[0],
229
+ closeOk: State,
230
+ closeNok: State,
231
+ ): State {
232
+ return factorySpace(closeEffects, sequenceStart, types.linePrefix, constants.tabSize)
233
+
234
+ function sequenceStart(code: number | null): State | undefined {
235
+ if (code !== marker) return closeNok(code)
236
+ closeEffects.enter('mathFlowFence')
237
+ closeEffects.enter('mathFlowFenceSequence')
238
+ closeEffects.consume(code)
239
+ return sequenceEnd
240
+ }
241
+
242
+ function sequenceEnd(code: number | null): State | undefined {
243
+ if (code !== closeMarker) return closeNok(code)
244
+ closeEffects.consume(code)
245
+ closeEffects.exit('mathFlowFenceSequence')
246
+ return factorySpace(closeEffects, after, types.whitespace)
247
+ }
248
+
249
+ function after(code: number | null): State | undefined {
250
+ if (code !== codes.eof && !markdownLineEnding(code)) return closeNok(code)
251
+ closeEffects.exit('mathFlowFence')
252
+ return closeOk(code)
253
+ }
254
+ }
255
+
256
+ function tokenizeOpeningFence(
257
+ openEffects: Parameters<Tokenizer>[0],
258
+ openOk: State,
259
+ openNok: State,
260
+ ): State {
261
+ return sequenceStart
262
+
263
+ function sequenceStart(code: number | null): State | undefined {
264
+ /* v8 ignore next -- the opening check follows a failed close attempt at the marker. */
265
+ if (code !== marker) return openNok(code)
266
+ openEffects.enter(types.chunkString)
267
+ openEffects.consume(code)
268
+ return sequenceEnd
269
+ }
270
+
271
+ function sequenceEnd(code: number | null): State | undefined {
272
+ if (code !== openMarker) return openNok(code)
273
+ openEffects.consume(code)
274
+ openEffects.exit(types.chunkString)
275
+ return openOk
276
+ }
277
+ }
278
+ }
279
+
280
+ return {
281
+ concrete: true,
282
+ name: marker === codes.dollarSign ? 'sameLineDollarMathFlow' : 'backslashMathFlow',
283
+ tokenize,
284
+ }
285
+ }
286
+
287
+ const tokenizeNonLazyContinuation: Tokenizer = function (effects, ok, nok) {
288
+ const self = this
289
+
290
+ return start
291
+
292
+ function start(code: number | null): State | undefined {
293
+ /* v8 ignore next -- continuation constructs are attempted only after a line ending. */
294
+ if (code === codes.eof) return ok(code)
295
+ /* v8 ignore next -- continuation constructs are attempted only after a line ending. */
296
+ if (!markdownLineEnding(code)) return nok(code)
297
+ effects.enter(types.lineEnding)
298
+ effects.consume(code)
299
+ effects.exit(types.lineEnding)
300
+ return lineStart
301
+ }
302
+
303
+ function lineStart(code: number | null): State | undefined {
304
+ return self.parser.lazy[self.now().line] ? nok(code) : ok(code)
305
+ }
306
+ }
307
+
308
+ const nonLazyContinuation: Construct = {
309
+ partial: true,
310
+ tokenize: tokenizeNonLazyContinuation,
311
+ }
312
+
313
+ const backslashMathText: Construct = {
314
+ name: 'backslashMathText',
315
+ previous: previousBackslash,
316
+ tokenize: tokenizeBackslashMathText,
317
+ }
318
+
319
+ const backslashMathFlow = createMathFlow(
320
+ codes.backslash,
321
+ codes.leftSquareBracket,
322
+ codes.rightSquareBracket,
323
+ true,
324
+ )
325
+
326
+ const sameLineDollarMathFlow = createMathFlow(
327
+ codes.dollarSign,
328
+ codes.dollarSign,
329
+ codes.dollarSign,
330
+ false,
331
+ )
332
+
333
+ const backslashMath: Extension = {
334
+ flow: {
335
+ [codes.backslash]: backslashMathFlow,
336
+ [codes.dollarSign]: sameLineDollarMathFlow,
337
+ },
338
+ text: { [codes.backslash]: backslashMathText },
339
+ }
340
+
341
+ /**
342
+ * TeX backslash delimiters and same-line display-dollar blocks as a micromark
343
+ * syntax extension reusing `micromark-extension-math`'s token vocabulary; the
344
+ * caller must also register `math()` on the same parse so the emitted tokens
345
+ * compile to standard math nodes.
346
+ * @returns The micromark syntax extension.
347
+ */
348
+ export function mathCompatibility(): Extension {
349
+ return backslashMath
350
+ }
@@ -0,0 +1,45 @@
1
+ // Adapted from DeepSeek Harness b150a551b8d465e31e418e1b2eaf5e79bbb7d28e (MIT). See THIRD_PARTY_NOTICES.md.
2
+ /**
3
+ * The markdown renderer's two mdast grammars, one per rendering arm. Each
4
+ * arm is internally consistent — the incremental tail parses, the one-shot
5
+ * parses, and the plain-text projection of a given grammar always agree on
6
+ * where blocks start and end — and the settled grammar is the streaming one
7
+ * plus the math extensions, so the arms differ only where TeX delimiters
8
+ * begin a math construct (a `$$` block is a paragraph while streaming and a
9
+ * math block once settled, by design).
10
+ */
11
+
12
+ import type { Root } from 'mdast'
13
+ import { fromMarkdown } from 'mdast-util-from-markdown'
14
+ import { gfmFromMarkdown } from 'mdast-util-gfm'
15
+ import { mathFromMarkdown } from 'mdast-util-math'
16
+ import { gfm } from 'micromark-extension-gfm'
17
+ import { math } from 'micromark-extension-math'
18
+ import { cjkFriendlyStrong } from './cjkFriendlyStrong.js'
19
+ import { mathCompatibility } from './mathCompatibility.js'
20
+
21
+ /**
22
+ * Parse GFM markdown (the streaming arm's grammar: no math, so incomplete
23
+ * TeX never flashes KaTeX errors mid-stream).
24
+ * @param text - Markdown source.
25
+ * @returns The mdast root.
26
+ */
27
+ export function parseGfm(text: string): Root {
28
+ return fromMarkdown(text, {
29
+ extensions: [gfm(), cjkFriendlyStrong()],
30
+ mdastExtensions: [gfmFromMarkdown()],
31
+ })
32
+ }
33
+
34
+ /**
35
+ * Parse GFM markdown plus TeX math with the compatibility delimiters
36
+ * (the settled arm's grammar).
37
+ * @param text - Markdown source.
38
+ * @returns The mdast root.
39
+ */
40
+ export function parseGfmWithMath(text: string): Root {
41
+ return fromMarkdown(text, {
42
+ extensions: [gfm(), cjkFriendlyStrong(), mathCompatibility(), math()],
43
+ mdastExtensions: [gfmFromMarkdown(), mathFromMarkdown()],
44
+ })
45
+ }