@localix-ai/flowdown 0.0.0-stage → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -2
  3. package/dist/browser/file-actions.js +80 -0
  4. package/dist/browser/file-actions.js.map +1 -0
  5. package/dist/core/block-facts.js +72 -0
  6. package/dist/core/block-facts.js.map +1 -0
  7. package/dist/core/blocks.d.ts +25 -0
  8. package/dist/core/blocks.js +464 -0
  9. package/dist/core/blocks.js.map +1 -0
  10. package/dist/core/bounded-cache.js +42 -0
  11. package/dist/core/bounded-cache.js.map +1 -0
  12. package/dist/core/continues.js +15 -0
  13. package/dist/core/continues.js.map +1 -0
  14. package/dist/core/dollars.d.ts +12 -0
  15. package/dist/core/dollars.js +88 -0
  16. package/dist/core/dollars.js.map +1 -0
  17. package/dist/core/fence-scan.js +62 -0
  18. package/dist/core/fence-scan.js.map +1 -0
  19. package/dist/core/file-tree-parse.d.ts +26 -0
  20. package/dist/core/file-tree-parse.js +51 -0
  21. package/dist/core/file-tree-parse.js.map +1 -0
  22. package/dist/core/forms-html.js +63 -0
  23. package/dist/core/forms-html.js.map +1 -0
  24. package/dist/core/forms.d.ts +28 -0
  25. package/dist/core/forms.js +23 -0
  26. package/dist/core/forms.js.map +1 -0
  27. package/dist/core/headings.d.ts +11 -0
  28. package/dist/core/headings.js +74 -0
  29. package/dist/core/headings.js.map +1 -0
  30. package/dist/core/heal.d.ts +11 -0
  31. package/dist/core/heal.js +220 -0
  32. package/dist/core/heal.js.map +1 -0
  33. package/dist/core/load-once.js +23 -0
  34. package/dist/core/load-once.js.map +1 -0
  35. package/dist/core/math-delimiters.js +33 -0
  36. package/dist/core/math-delimiters.js.map +1 -0
  37. package/dist/core/math-syntax.js +56 -0
  38. package/dist/core/math-syntax.js.map +1 -0
  39. package/dist/core/prose.d.ts +10 -0
  40. package/dist/core/prose.js +77 -0
  41. package/dist/core/prose.js.map +1 -0
  42. package/dist/core/remark-answer-blocks.d.ts +5 -0
  43. package/dist/core/remark-answer-blocks.js +172 -0
  44. package/dist/core/remark-answer-blocks.js.map +1 -0
  45. package/dist/core/remark-answer-containers.js +299 -0
  46. package/dist/core/remark-answer-containers.js.map +1 -0
  47. package/dist/core/sanitize-schema.d.ts +18 -0
  48. package/dist/core/sanitize-schema.js +62 -0
  49. package/dist/core/sanitize-schema.js.map +1 -0
  50. package/dist/core/syntax.d.ts +8 -0
  51. package/dist/core/syntax.js +32 -0
  52. package/dist/core/syntax.js.map +1 -0
  53. package/dist/dialect.d.ts +92 -0
  54. package/dist/dialect.js +176 -0
  55. package/dist/dialect.js.map +1 -0
  56. package/dist/document/fence.d.ts +25 -0
  57. package/dist/document/fence.js +102 -0
  58. package/dist/document/fence.js.map +1 -0
  59. package/dist/document/index.d.ts +46 -0
  60. package/dist/document/index.js +66 -0
  61. package/dist/document/index.js.map +1 -0
  62. package/dist/document/table.d.ts +11 -0
  63. package/dist/document/table.js +35 -0
  64. package/dist/document/table.js.map +1 -0
  65. package/dist/dom/index.d.ts +21 -0
  66. package/dist/dom/index.js +141 -0
  67. package/dist/dom/index.js.map +1 -0
  68. package/dist/dom/patch.js +104 -0
  69. package/dist/dom/patch.js.map +1 -0
  70. package/dist/element/index.d.ts +35 -0
  71. package/dist/element/index.js +64 -0
  72. package/dist/element/index.js.map +1 -0
  73. package/dist/engine/blocks.js +785 -0
  74. package/dist/engine/blocks.js.map +1 -0
  75. package/dist/engine/entities.js +83 -0
  76. package/dist/engine/entities.js.map +1 -0
  77. package/dist/engine/entity-core.js +9 -0
  78. package/dist/engine/entity-core.js.map +1 -0
  79. package/dist/engine/entity-table.js +9 -0
  80. package/dist/engine/entity-table.js.map +1 -0
  81. package/dist/engine/html.d.ts +7 -0
  82. package/dist/engine/html.js +207 -0
  83. package/dist/engine/html.js.map +1 -0
  84. package/dist/engine/index.d.ts +7 -0
  85. package/dist/engine/index.js +74 -0
  86. package/dist/engine/index.js.map +1 -0
  87. package/dist/engine/inlines.js +887 -0
  88. package/dist/engine/inlines.js.map +1 -0
  89. package/dist/engine/types.d.ts +109 -0
  90. package/dist/engine/url.d.ts +11 -0
  91. package/dist/engine/url.js +16 -0
  92. package/dist/engine/url.js.map +1 -0
  93. package/dist/engine/visit.d.ts +10 -0
  94. package/dist/engine/visit.js +29 -0
  95. package/dist/engine/visit.js.map +1 -0
  96. package/dist/highlight/highlight.d.ts +4 -0
  97. package/dist/highlight/highlight.js +144 -0
  98. package/dist/highlight/highlight.js.map +1 -0
  99. package/dist/highlight/index.d.ts +4 -0
  100. package/dist/highlight/index.js +18 -0
  101. package/dist/highlight/index.js.map +1 -0
  102. package/dist/html/index.d.ts +4 -0
  103. package/dist/html/index.js +544 -0
  104. package/dist/html/index.js.map +1 -0
  105. package/dist/index.d.ts +27 -0
  106. package/dist/index.js +13 -0
  107. package/dist/math/index.d.ts +17 -0
  108. package/dist/math/index.js +20 -0
  109. package/dist/math/index.js.map +1 -0
  110. package/dist/math/typeset.d.ts +12 -0
  111. package/dist/math/typeset.js +74 -0
  112. package/dist/math/typeset.js.map +1 -0
  113. package/dist/mermaid/diagram.d.ts +8 -0
  114. package/dist/mermaid/diagram.js +114 -0
  115. package/dist/mermaid/diagram.js.map +1 -0
  116. package/dist/mermaid/drawing.js +139 -0
  117. package/dist/mermaid/drawing.js.map +1 -0
  118. package/dist/mermaid/icons.js +16 -0
  119. package/dist/mermaid/icons.js.map +1 -0
  120. package/dist/mermaid/index.d.ts +13 -0
  121. package/dist/mermaid/index.js +3 -0
  122. package/dist/mermaid/loader.d.ts +5 -0
  123. package/dist/mermaid/loader.js +18 -0
  124. package/dist/mermaid/loader.js.map +1 -0
  125. package/dist/mermaid/look.d.ts +16 -0
  126. package/dist/mermaid/look.js +167 -0
  127. package/dist/mermaid/look.js.map +1 -0
  128. package/dist/mermaid/normalize-svg.js +44 -0
  129. package/dist/mermaid/normalize-svg.js.map +1 -0
  130. package/dist/mermaid/renderer.d.ts +22 -0
  131. package/dist/mermaid/renderer.js +132 -0
  132. package/dist/mermaid/renderer.js.map +1 -0
  133. package/dist/mermaid/viewer.js +309 -0
  134. package/dist/mermaid/viewer.js.map +1 -0
  135. package/dist/prompt/index.d.ts +19 -0
  136. package/dist/prompt/index.js +54 -0
  137. package/dist/prompt/index.js.map +1 -0
  138. package/dist/react/callout.d.ts +9 -0
  139. package/dist/react/callout.js +12 -0
  140. package/dist/react/callout.js.map +1 -0
  141. package/dist/react/code-block.d.ts +18 -0
  142. package/dist/react/code-block.js +94 -0
  143. package/dist/react/code-block.js.map +1 -0
  144. package/dist/react/context.d.ts +18 -0
  145. package/dist/react/context.js +17 -0
  146. package/dist/react/context.js.map +1 -0
  147. package/dist/react/draw.d.ts +2 -0
  148. package/dist/react/draw.js +17 -0
  149. package/dist/react/draw.js.map +1 -0
  150. package/dist/react/file-tree.d.ts +16 -0
  151. package/dist/react/file-tree.js +69 -0
  152. package/dist/react/file-tree.js.map +1 -0
  153. package/dist/react/growing-code.js +36 -0
  154. package/dist/react/growing-code.js.map +1 -0
  155. package/dist/react/helpers.d.ts +6 -0
  156. package/dist/react/helpers.js +17 -0
  157. package/dist/react/helpers.js.map +1 -0
  158. package/dist/react/icons.js +23 -0
  159. package/dist/react/icons.js.map +1 -0
  160. package/dist/react/labels.js +9 -0
  161. package/dist/react/labels.js.map +1 -0
  162. package/dist/react/markdown.d.ts +78 -0
  163. package/dist/react/markdown.js +206 -0
  164. package/dist/react/markdown.js.map +1 -0
  165. package/dist/react/render.d.ts +8 -0
  166. package/dist/react/render.js +41 -0
  167. package/dist/react/render.js.map +1 -0
  168. package/dist/react/scrolls.js +62 -0
  169. package/dist/react/scrolls.js.map +1 -0
  170. package/dist/react/table-rows.js +66 -0
  171. package/dist/react/table-rows.js.map +1 -0
  172. package/dist/react/table.js +22 -0
  173. package/dist/react/table.js.map +1 -0
  174. package/dist/react/tabs.d.ts +25 -0
  175. package/dist/react/tabs.js +58 -0
  176. package/dist/react/tabs.js.map +1 -0
  177. package/dist/react/use-smooth-text.d.ts +6 -0
  178. package/dist/react/use-smooth-text.js +157 -0
  179. package/dist/react/use-smooth-text.js.map +1 -0
  180. package/dist/react/use-stage.d.ts +9 -0
  181. package/dist/react/use-stage.js +57 -0
  182. package/dist/react/use-stage.js.map +1 -0
  183. package/dist/remark.d.ts +20 -0
  184. package/dist/remark.js +10 -0
  185. package/dist/render/factory.d.ts +15 -0
  186. package/dist/render/labels.d.ts +46 -0
  187. package/dist/render/labels.js +46 -0
  188. package/dist/render/labels.js.map +1 -0
  189. package/dist/render/tree.js +314 -0
  190. package/dist/render/tree.js.map +1 -0
  191. package/dist/render/view.d.ts +58 -0
  192. package/dist/render/view.js +306 -0
  193. package/dist/render/view.js.map +1 -0
  194. package/dist/render/views.d.ts +16 -0
  195. package/dist/render/views.js +261 -0
  196. package/dist/render/views.js.map +1 -0
  197. package/dist/render/vnode.d.ts +21 -0
  198. package/dist/render/vnode.js +194 -0
  199. package/dist/render/vnode.js.map +1 -0
  200. package/dist/static/index.d.ts +28 -0
  201. package/dist/static/index.js +27 -0
  202. package/dist/static/index.js.map +1 -0
  203. package/dist/stream.d.ts +12 -0
  204. package/dist/stream.js +3 -0
  205. package/dist/styles.css +1362 -0
  206. package/dist/tui/code.d.ts +5 -0
  207. package/dist/tui/code.js +240 -0
  208. package/dist/tui/code.js.map +1 -0
  209. package/dist/tui/index.d.ts +54 -0
  210. package/dist/tui/index.js +99 -0
  211. package/dist/tui/index.js.map +1 -0
  212. package/dist/tui/math.js +242 -0
  213. package/dist/tui/math.js.map +1 -0
  214. package/dist/tui/printable.d.ts +12 -0
  215. package/dist/tui/printable.js +31 -0
  216. package/dist/tui/printable.js.map +1 -0
  217. package/dist/tui/render.d.ts +12 -0
  218. package/dist/tui/render.js +524 -0
  219. package/dist/tui/render.js.map +1 -0
  220. package/dist/tui/style.d.ts +35 -0
  221. package/dist/tui/style.js +77 -0
  222. package/dist/tui/style.js.map +1 -0
  223. package/dist/tui/table.js +73 -0
  224. package/dist/tui/table.js.map +1 -0
  225. package/dist/tui/width.d.ts +2 -0
  226. package/dist/tui/width.js +133 -0
  227. package/dist/tui/width.js.map +1 -0
  228. package/dist/tui/wrap.d.ts +8 -0
  229. package/dist/tui/wrap.js +191 -0
  230. package/dist/tui/wrap.js.map +1 -0
  231. package/package.json +128 -4
@@ -0,0 +1,242 @@
1
+ // src/tui/math.ts
2
+ /**
3
+ * A formula as a terminal can write it: its LaTeX read into Unicode.
4
+ *
5
+ * A terminal has one size of letter on one line, so a formula is not typeset; it is written the
6
+ * way one is typed in plain text: `\frac{1}{k} \sum_{i=1}^{k} r_i` is `1/k ∑ᵢ₌₁ᵏ rᵢ`. A command
7
+ * with a symbol becomes the symbol, a fraction a slash, a script the small letters Unicode has
8
+ * (`x^2` is `x²`) or, where it has none, the script as written (`e^(iπ)`). A command this does
9
+ * not know stays as it was written: a formula is never shorter than what it says.
10
+ *
11
+ * It reads any text and never throws: a reply is not obliged to hold LaTeX that is right.
12
+ */
13
+ /** Pairs of a command's name and what it is written as. */
14
+ const NAMED = `alpha α beta β gamma γ delta δ epsilon ϵ varepsilon ε zeta ζ eta η theta θ vartheta ϑ
15
+ iota ι kappa κ lambda λ mu μ nu ν xi ξ pi π varpi ϖ rho ρ varrho ϱ sigma σ varsigma ς tau τ
16
+ upsilon υ phi ϕ varphi φ chi χ psi ψ omega ω Gamma Γ Delta Δ Theta Θ Lambda Λ Xi Ξ Pi Π Sigma Σ
17
+ Upsilon Υ Phi Φ Psi Ψ Omega Ω sum ∑ prod ∏ coprod ∐ int ∫ iint ∬ iiint ∭ oint ∮ infty ∞
18
+ partial ∂ nabla ∇ times × cdot · div ÷ pm ± mp ∓ le ≤ leq ≤ ge ≥ geq ≥ ne ≠ neq ≠ ll ≪ gg ≫
19
+ approx ≈ equiv ≡ sim ∼ simeq ≃ cong ≅ propto ∝ to → rightarrow → gets ← leftarrow ←
20
+ leftrightarrow ↔ Rightarrow ⇒ Leftarrow ⇐ Leftrightarrow ⇔ implies ⇒ iff ⇔ mapsto ↦ uparrow ↑
21
+ downarrow ↓ in ∈ notin ∉ ni ∋ subset ⊂ subseteq ⊆ supset ⊃ supseteq ⊇ cup ∪ cap ∩ setminus ∖
22
+ emptyset ∅ varnothing ∅ forall ∀ exists ∃ nexists ∄ neg ¬ lnot ¬ land ∧ wedge ∧ lor ∨ vee ∨
23
+ oplus ⊕ otimes ⊗ odot ⊙ cdots ⋯ ldots … dots … vdots ⋮ ddots ⋱ angle ∠ perp ⊥ parallel ∥ mid ∣
24
+ circ ∘ bullet • star ⋆ ast ∗ dagger † langle ⟨ rangle ⟩ lfloor ⌊ rfloor ⌋ lceil ⌈ rceil ⌉
25
+ lvert | rvert | vert | lVert ‖ rVert ‖ Vert ‖ ell ℓ hbar ℏ Re ℜ Im ℑ aleph ℵ prime ′ degree °
26
+ top ⊤ bot ⊥ vdash ⊢ models ⊨ therefore ∴ because ∵ triangle △ square □ checkmark ✓ lbrace {
27
+ rbrace } colon :`;
28
+ const SYMBOLS = /* @__PURE__ */ new Map();
29
+ {
30
+ const words = NAMED.split(/\s+/);
31
+ for (let at = 0; at + 1 < words.length; at += 2) SYMBOLS.set(words[at], words[at + 1]);
32
+ }
33
+ /** Names that are written upright, as themselves. */
34
+ const FUNCTIONS = new Set("sin cos tan cot sec csc arcsin arccos arctan sinh cosh tanh log ln lg exp lim limsup liminf max min sup inf det dim ker gcd deg arg Pr hom mod bmod".split(" "));
35
+ /** A mark over or under a letter, as the combining character that draws it. */
36
+ const ACCENTS = {
37
+ bar: 772,
38
+ overline: 773,
39
+ hat: 770,
40
+ widehat: 770,
41
+ tilde: 771,
42
+ widetilde: 771,
43
+ vec: 8407,
44
+ overrightarrow: 8407,
45
+ dot: 775,
46
+ ddot: 776,
47
+ underline: 818
48
+ };
49
+ /** Commands that change how their argument looks and not what it says. */
50
+ const TRANSPARENT = new Set("text textrm textit textbf textsf texttt mathrm mathit mathbf mathsf mathtt mathcal mathfrak mathscr boldsymbol bm mbox operatorname boxed underbrace overbrace substack".split(" "));
51
+ /** Commands about size and placement, which a terminal has one of. */
52
+ const DROPPED = new Set("left right big Big bigg Bigg bigl bigr Bigl Bigr biggl biggr middle displaystyle textstyle scriptstyle limits nolimits nonumber notag".split(" "));
53
+ /** Pairs of a character and its small form, as a table. */
54
+ const small = (pairs) => {
55
+ const chars = [...pairs];
56
+ const table = /* @__PURE__ */ new Map();
57
+ for (let at = 0; at + 1 < chars.length; at += 2) table.set(chars[at], chars[at + 1]);
58
+ return table;
59
+ };
60
+ const SUPER = small("0⁰1¹2²3³4⁴5⁵6⁶7⁷8⁸9⁹+⁺-⁻−⁻=⁼(⁽)⁾aᵃbᵇcᶜdᵈeᵉfᶠgᵍhʰiⁱjʲkᵏlˡmᵐnⁿoᵒpᵖrʳsˢtᵗuᵘvᵛwʷxˣyʸzᶻAᴬBᴮDᴰEᴱGᴳHᴴIᴵJᴶKᴷLᴸMᴹNᴺOᴼPᴾRᴿTᵀUᵁVⱽWᵂ∘°′′");
61
+ const SUB = small("0₀1₁2₂3₃4₄5₅6₆7₇8₈9₉+₊-₋−₋=₌(₍)₎aₐeₑhₕiᵢjⱼkₖlₗmₘnₙoₒpₚrᵣsₛtₜuᵤvᵥxₓβᵦγᵧρᵨφᵩχᵪ");
62
+ /** The sets of numbers, the letters `\mathbb` is asked for that every font has. */
63
+ const DOUBLE = small("CℂHℍNℕPℙQℚRℝZℤ");
64
+ /** A script in the small letters of `table`; where one is missing, as written after `mark`. */
65
+ function script(text, table, mark) {
66
+ const body = text.replace(/\s+/g, " ").trim();
67
+ if (body === "") return "";
68
+ let out = "";
69
+ for (const char of body) {
70
+ if (char === " ") continue;
71
+ const to = table.get(char);
72
+ if (to === void 0) return mark + ([...body].length === 1 ? body : `(${body})`);
73
+ out += to;
74
+ }
75
+ return out;
76
+ }
77
+ /**
78
+ * What needs no brackets to stand over or under a slash: a word (letters, digits, their marks),
79
+ * with a root or a `∂` before it and one bracketed group after it, as in `√π`, `∂x`, `P(B)`.
80
+ */
81
+ const WORD = /^[√∂∇]?[\p{L}\p{N}\p{M}.′']*(?:\([^()]*\))?$/u;
82
+ const MARK = /\p{M}/u;
83
+ /** `text` as one thing: itself when it is a word, bracketed when it is more. */
84
+ const atom = (text) => {
85
+ const body = text.trim().replace(/^([∂∇]) +/, "$1");
86
+ return WORD.test(body) ? body : `(${body})`;
87
+ };
88
+ function accented(text, code) {
89
+ const mark = String.fromCharCode(code);
90
+ let out = "";
91
+ for (const char of text.trim()) out += char === " " || MARK.test(char) ? char : char + mark;
92
+ return out;
93
+ }
94
+ /** Groups and arguments nested deeper than this are read as text: no formula is, and no stack is that deep. */
95
+ const MAX_DEPTH = 16;
96
+ const LETTERS = /[a-zA-Z]+/y;
97
+ var Reader = class {
98
+ text;
99
+ at = 0;
100
+ depth = 0;
101
+ /** The environments this is inside, innermost last. */
102
+ inside = [];
103
+ constructor(text) {
104
+ this.text = text;
105
+ }
106
+ /** Everything up to the end, or inside a group up to the `}` that closes it. */
107
+ run(grouped = false) {
108
+ let out = "";
109
+ while (this.at < this.text.length) {
110
+ if (grouped && this.text[this.at] === "}") break;
111
+ out += this.piece();
112
+ }
113
+ return out;
114
+ }
115
+ /** The next thing, with what it takes. Always moves on. */
116
+ piece() {
117
+ const char = String.fromCodePoint(this.text.codePointAt(this.at));
118
+ this.at += char.length;
119
+ switch (char) {
120
+ case "\\": return this.command();
121
+ case "{": return this.group();
122
+ case "^": return script(this.argument(), SUPER, "^");
123
+ case "_": return script(this.argument(), SUB, "_");
124
+ case "&": return this.inside.at(-1) === "cases" ? ", " : "";
125
+ case "~": return " ";
126
+ default: return char === "\n" || char === "\r" || char === " " ? " " : char;
127
+ }
128
+ }
129
+ /** The group whose `{` was just read. */
130
+ group() {
131
+ if (this.depth >= MAX_DEPTH) return "{";
132
+ this.depth++;
133
+ const inside = this.run(true);
134
+ this.depth--;
135
+ if (this.text[this.at] === "}") this.at++;
136
+ return inside;
137
+ }
138
+ /** What a command or a script takes: a group, or the one thing that comes next. */
139
+ argument() {
140
+ while (this.text[this.at] === " ") this.at++;
141
+ const next = this.text[this.at];
142
+ if (next === void 0 || next === "}" || this.depth >= MAX_DEPTH) return "";
143
+ if (next === "{") {
144
+ this.at++;
145
+ return this.group();
146
+ }
147
+ this.depth++;
148
+ const one = this.piece();
149
+ this.depth--;
150
+ return one;
151
+ }
152
+ /** The `[n]` of a root, when it has one. */
153
+ index() {
154
+ if (this.text[this.at] !== "[" || this.depth >= MAX_DEPTH) return "";
155
+ this.at++;
156
+ this.depth++;
157
+ let out = "";
158
+ while (this.at < this.text.length && this.text[this.at] !== "]" && this.text[this.at] !== "}") out += this.piece();
159
+ this.depth--;
160
+ if (this.text[this.at] === "]") this.at++;
161
+ return out;
162
+ }
163
+ /** The `{name}` of an environment, read past. */
164
+ name() {
165
+ if (this.text[this.at] !== "{") return "";
166
+ const from = this.at + 1;
167
+ const close = this.text.indexOf("}", from);
168
+ this.at = close === -1 ? this.text.length : close + 1;
169
+ return this.text.slice(from, close === -1 ? void 0 : close).trim();
170
+ }
171
+ /** The command whose backslash was just read. */
172
+ command() {
173
+ LETTERS.lastIndex = this.at;
174
+ const name = LETTERS.exec(this.text)?.[0];
175
+ if (name === void 0) return this.escaped();
176
+ this.at += name.length;
177
+ const symbol = SYMBOLS.get(name);
178
+ if (symbol !== void 0) return symbol;
179
+ if (FUNCTIONS.has(name)) return name;
180
+ const accent = ACCENTS[name];
181
+ if (accent !== void 0) return accented(this.argument(), accent);
182
+ if (TRANSPARENT.has(name)) return this.argument();
183
+ if (DROPPED.has(name)) {
184
+ if ((name === "left" || name === "right") && this.text[this.at] === ".") this.at++;
185
+ return "";
186
+ }
187
+ switch (name) {
188
+ case "frac":
189
+ case "dfrac":
190
+ case "tfrac":
191
+ case "cfrac": return `${atom(this.argument())}/${atom(this.argument())}`;
192
+ case "binom":
193
+ case "dbinom":
194
+ case "tbinom": return `C(${this.argument().trim()}, ${this.argument().trim()})`;
195
+ case "sqrt": return `${script(this.index(), SUPER, "")}√${atom(this.argument())}`;
196
+ case "mathbb": return [...this.argument()].map((char) => DOUBLE.get(char) ?? char).join("");
197
+ case "not": return `${this.argument()}̸`;
198
+ case "tag": return `(${this.argument().trim()})`;
199
+ case "pmod": return ` (mod ${this.argument().trim()})`;
200
+ case "begin": {
201
+ const environment = this.name();
202
+ this.inside.push(environment);
203
+ return environment === "cases" ? " { " : " ";
204
+ }
205
+ case "end":
206
+ this.name();
207
+ this.inside.pop();
208
+ return " ";
209
+ case "quad":
210
+ case "qquad": return " ";
211
+ }
212
+ let out = `\\${name}`;
213
+ while (this.text[this.at] === "{" && this.depth < MAX_DEPTH) {
214
+ this.at++;
215
+ out += `{${this.group()}}`;
216
+ }
217
+ return out;
218
+ }
219
+ /** A backslash before something that is not a letter. */
220
+ escaped() {
221
+ const char = this.text[this.at];
222
+ if (char === void 0) return "\\";
223
+ this.at++;
224
+ if (char === "\\") return "\n";
225
+ if (char === "," || char === ";" || char === ":" || char === " ") return " ";
226
+ if (char === "!") return "";
227
+ if (char === "|") return "‖";
228
+ if ("{}%$&_#".includes(char)) return char;
229
+ return `\\${char}`;
230
+ }
231
+ };
232
+ /** A row with its spaces as a reader writes them: one between things, none inside a bracket. */
233
+ const tidy = (row) => row.replace(/\s+/g, " ").replace(/([([⟨⌊⌈]) /g, "$1").replace(/ ([)\]⟩⌋⌉,])/g, "$1").trim().normalize("NFC");
234
+ /** The rows of a formula: one, unless the formula breaks its own (`\\`). */
235
+ function mathRows(source) {
236
+ return new Reader(source).run().split("\n").map(tidy).filter(Boolean);
237
+ }
238
+ /** A formula on one row, as it is written inside a sentence. */
239
+ const mathText = (source) => mathRows(source).join(" ");
240
+ export { mathRows, mathText };
241
+
242
+ //# sourceMappingURL=math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.js","names":[],"sources":["../../src/tui/math.ts"],"sourcesContent":["/**\n * A formula as a terminal can write it: its LaTeX read into Unicode.\n *\n * A terminal has one size of letter on one line, so a formula is not typeset; it is written the\n * way one is typed in plain text: `\\frac{1}{k} \\sum_{i=1}^{k} r_i` is `1/k ∑ᵢ₌₁ᵏ rᵢ`. A command\n * with a symbol becomes the symbol, a fraction a slash, a script the small letters Unicode has\n * (`x^2` is `x²`) or, where it has none, the script as written (`e^(iπ)`). A command this does\n * not know stays as it was written: a formula is never shorter than what it says.\n *\n * It reads any text and never throws: a reply is not obliged to hold LaTeX that is right.\n */\n\n/** Pairs of a command's name and what it is written as. */\nconst NAMED = `alpha α beta β gamma γ delta δ epsilon ϵ varepsilon ε zeta ζ eta η theta θ vartheta ϑ\niota ι kappa κ lambda λ mu μ nu ν xi ξ pi π varpi ϖ rho ρ varrho ϱ sigma σ varsigma ς tau τ\nupsilon υ phi ϕ varphi φ chi χ psi ψ omega ω Gamma Γ Delta Δ Theta Θ Lambda Λ Xi Ξ Pi Π Sigma Σ\nUpsilon Υ Phi Φ Psi Ψ Omega Ω sum ∑ prod ∏ coprod ∐ int ∫ iint ∬ iiint ∭ oint ∮ infty ∞\npartial ∂ nabla ∇ times × cdot · div ÷ pm ± mp ∓ le ≤ leq ≤ ge ≥ geq ≥ ne ≠ neq ≠ ll ≪ gg ≫\napprox ≈ equiv ≡ sim ∼ simeq ≃ cong ≅ propto ∝ to → rightarrow → gets ← leftarrow ←\nleftrightarrow ↔ Rightarrow ⇒ Leftarrow ⇐ Leftrightarrow ⇔ implies ⇒ iff ⇔ mapsto ↦ uparrow ↑\ndownarrow ↓ in ∈ notin ∉ ni ∋ subset ⊂ subseteq ⊆ supset ⊃ supseteq ⊇ cup ∪ cap ∩ setminus ∖\nemptyset ∅ varnothing ∅ forall ∀ exists ∃ nexists ∄ neg ¬ lnot ¬ land ∧ wedge ∧ lor ∨ vee ∨\noplus ⊕ otimes ⊗ odot ⊙ cdots ⋯ ldots … dots … vdots ⋮ ddots ⋱ angle ∠ perp ⊥ parallel ∥ mid ∣\ncirc ∘ bullet • star ⋆ ast ∗ dagger † langle ⟨ rangle ⟩ lfloor ⌊ rfloor ⌋ lceil ⌈ rceil ⌉\nlvert | rvert | vert | lVert ‖ rVert ‖ Vert ‖ ell ℓ hbar ℏ Re ℜ Im ℑ aleph ℵ prime ′ degree °\ntop ⊤ bot ⊥ vdash ⊢ models ⊨ therefore ∴ because ∵ triangle △ square □ checkmark ✓ lbrace {\nrbrace } colon :`\n\nconst SYMBOLS = new Map<string, string>()\n{\n const words = NAMED.split(/\\s+/)\n for (let at = 0; at + 1 < words.length; at += 2) SYMBOLS.set(words[at]!, words[at + 1]!)\n}\n\n/** Names that are written upright, as themselves. */\nconst FUNCTIONS = new Set(\n 'sin cos tan cot sec csc arcsin arccos arctan sinh cosh tanh log ln lg exp lim limsup liminf max min sup inf det dim ker gcd deg arg Pr hom mod bmod'.split(\n ' ',\n ),\n)\n\n/** A mark over or under a letter, as the combining character that draws it. */\nconst ACCENTS: Record<string, number> = {\n bar: 0x304,\n overline: 0x305,\n hat: 0x302,\n widehat: 0x302,\n tilde: 0x303,\n widetilde: 0x303,\n vec: 0x20d7,\n overrightarrow: 0x20d7,\n dot: 0x307,\n ddot: 0x308,\n underline: 0x332,\n}\n\n/** Commands that change how their argument looks and not what it says. */\nconst TRANSPARENT = new Set(\n 'text textrm textit textbf textsf texttt mathrm mathit mathbf mathsf mathtt mathcal mathfrak mathscr boldsymbol bm mbox operatorname boxed underbrace overbrace substack'.split(\n ' ',\n ),\n)\n\n/** Commands about size and placement, which a terminal has one of. */\nconst DROPPED = new Set(\n 'left right big Big bigg Bigg bigl bigr Bigl Bigr biggl biggr middle displaystyle textstyle scriptstyle limits nolimits nonumber notag'.split(\n ' ',\n ),\n)\n\n/** Pairs of a character and its small form, as a table. */\nconst small = (pairs: string): Map<string, string> => {\n const chars = [...pairs]\n const table = new Map<string, string>()\n for (let at = 0; at + 1 < chars.length; at += 2) table.set(chars[at]!, chars[at + 1]!)\n return table\n}\n\nconst SUPER = small(\n '0⁰1¹2²3³4⁴5⁵6⁶7⁷8⁸9⁹+⁺-⁻−⁻=⁼(⁽)⁾aᵃbᵇcᶜdᵈeᵉfᶠgᵍhʰiⁱjʲkᵏlˡmᵐnⁿoᵒpᵖrʳsˢtᵗuᵘvᵛwʷxˣyʸzᶻAᴬBᴮDᴰEᴱGᴳHᴴIᴵJᴶKᴷLᴸMᴹNᴺOᴼPᴾRᴿTᵀUᵁVⱽWᵂ∘°′′',\n)\nconst SUB = small('0₀1₁2₂3₃4₄5₅6₆7₇8₈9₉+₊-₋−₋=₌(₍)₎aₐeₑhₕiᵢjⱼkₖlₗmₘnₙoₒpₚrᵣsₛtₜuᵤvᵥxₓβᵦγᵧρᵨφᵩχᵪ')\n\n/** The sets of numbers, the letters `\\mathbb` is asked for that every font has. */\nconst DOUBLE = small('CℂHℍNℕPℙQℚRℝZℤ')\n\n/** A script in the small letters of `table`; where one is missing, as written after `mark`. */\nfunction script(text: string, table: Map<string, string>, mark: string): string {\n const body = text.replace(/\\s+/g, ' ').trim()\n if (body === '') return ''\n let out = ''\n for (const char of body) {\n if (char === ' ') continue\n const to = table.get(char)\n if (to === undefined) return mark + ([...body].length === 1 ? body : `(${body})`)\n out += to\n }\n return out\n}\n\n/**\n * What needs no brackets to stand over or under a slash: a word (letters, digits, their marks),\n * with a root or a `∂` before it and one bracketed group after it, as in `√π`, `∂x`, `P(B)`.\n */\nconst WORD = /^[√∂∇]?[\\p{L}\\p{N}\\p{M}.′']*(?:\\([^()]*\\))?$/u\nconst MARK = /\\p{M}/u\n\n/** `text` as one thing: itself when it is a word, bracketed when it is more. */\nconst atom = (text: string): string => {\n const body = text.trim().replace(/^([∂∇]) +/, '$1')\n return WORD.test(body) ? body : `(${body})`\n}\n\nfunction accented(text: string, code: number): string {\n const mark = String.fromCharCode(code)\n let out = ''\n for (const char of text.trim()) out += char === ' ' || MARK.test(char) ? char : char + mark\n return out\n}\n\n/** Groups and arguments nested deeper than this are read as text: no formula is, and no stack is that deep. */\nconst MAX_DEPTH = 16\n\nconst LETTERS = /[a-zA-Z]+/y\n\nclass Reader {\n private at = 0\n private depth = 0\n /** The environments this is inside, innermost last. */\n private readonly inside: string[] = []\n\n constructor(private readonly text: string) {}\n\n /** Everything up to the end, or inside a group up to the `}` that closes it. */\n run(grouped = false): string {\n let out = ''\n while (this.at < this.text.length) {\n if (grouped && this.text[this.at] === '}') break\n out += this.piece()\n }\n return out\n }\n\n /** The next thing, with what it takes. Always moves on. */\n private piece(): string {\n const char = String.fromCodePoint(this.text.codePointAt(this.at)!)\n this.at += char.length\n switch (char) {\n case '\\\\':\n return this.command()\n case '{':\n return this.group()\n case '^':\n return script(this.argument(), SUPER, '^')\n case '_':\n return script(this.argument(), SUB, '_')\n // A column: of cases, the condition after its value; of an alignment, nothing to write.\n case '&':\n return this.inside.at(-1) === 'cases' ? ', ' : ''\n case '~':\n return ' '\n default:\n // A line ending of the source is a space: only `\\\\` ends a row.\n return char === '\\n' || char === '\\r' || char === '\\t' ? ' ' : char\n }\n }\n\n /** The group whose `{` was just read. */\n private group(): string {\n if (this.depth >= MAX_DEPTH) return '{'\n this.depth++\n const inside = this.run(true)\n this.depth--\n if (this.text[this.at] === '}') this.at++\n return inside\n }\n\n /** What a command or a script takes: a group, or the one thing that comes next. */\n private argument(): string {\n while (this.text[this.at] === ' ') this.at++\n const next = this.text[this.at]\n if (next === undefined || next === '}' || this.depth >= MAX_DEPTH) return ''\n if (next === '{') {\n this.at++\n return this.group()\n }\n this.depth++\n const one = this.piece()\n this.depth--\n return one\n }\n\n /** The `[n]` of a root, when it has one. */\n private index(): string {\n if (this.text[this.at] !== '[' || this.depth >= MAX_DEPTH) return ''\n this.at++\n this.depth++\n let out = ''\n while (this.at < this.text.length && this.text[this.at] !== ']' && this.text[this.at] !== '}')\n out += this.piece()\n this.depth--\n if (this.text[this.at] === ']') this.at++\n return out\n }\n\n /** The `{name}` of an environment, read past. */\n private name(): string {\n if (this.text[this.at] !== '{') return ''\n const from = this.at + 1\n const close = this.text.indexOf('}', from)\n this.at = close === -1 ? this.text.length : close + 1\n return this.text.slice(from, close === -1 ? undefined : close).trim()\n }\n\n /** The command whose backslash was just read. */\n private command(): string {\n LETTERS.lastIndex = this.at\n const name = LETTERS.exec(this.text)?.[0]\n if (name === undefined) return this.escaped()\n this.at += name.length\n const symbol = SYMBOLS.get(name)\n if (symbol !== undefined) return symbol\n if (FUNCTIONS.has(name)) return name\n const accent = ACCENTS[name]\n if (accent !== undefined) return accented(this.argument(), accent)\n if (TRANSPARENT.has(name)) return this.argument()\n if (DROPPED.has(name)) {\n // `\\left.` and `\\right.` are the side of a pair that is not drawn.\n if ((name === 'left' || name === 'right') && this.text[this.at] === '.') this.at++\n return ''\n }\n switch (name) {\n case 'frac':\n case 'dfrac':\n case 'tfrac':\n case 'cfrac': {\n const over = atom(this.argument())\n return `${over}/${atom(this.argument())}`\n }\n case 'binom':\n case 'dbinom':\n case 'tbinom': {\n const from = this.argument().trim()\n return `C(${from}, ${this.argument().trim()})`\n }\n case 'sqrt': {\n const index = this.index()\n return `${script(index, SUPER, '')}√${atom(this.argument())}`\n }\n case 'mathbb':\n return [...this.argument()].map((char) => DOUBLE.get(char) ?? char).join('')\n case 'not':\n return `${this.argument()}̸`\n case 'tag':\n return `(${this.argument().trim()})`\n case 'pmod':\n return ` (mod ${this.argument().trim()})`\n case 'begin': {\n const environment = this.name()\n this.inside.push(environment)\n return environment === 'cases' ? ' { ' : ' '\n }\n case 'end':\n this.name()\n this.inside.pop()\n return ' '\n case 'quad':\n case 'qquad':\n return ' '\n }\n // Not known: as it was written, with what it took.\n let out = `\\\\${name}`\n while (this.text[this.at] === '{' && this.depth < MAX_DEPTH) {\n this.at++\n out += `{${this.group()}}`\n }\n return out\n }\n\n /** A backslash before something that is not a letter. */\n private escaped(): string {\n const char = this.text[this.at]\n if (char === undefined) return '\\\\'\n this.at++\n // `\\\\` ends a row of the formula.\n if (char === '\\\\') return '\\n'\n if (char === ',' || char === ';' || char === ':' || char === ' ') return ' '\n if (char === '!') return ''\n if (char === '|') return '‖'\n if ('{}%$&_#'.includes(char)) return char\n return `\\\\${char}`\n }\n}\n\n/** A row with its spaces as a reader writes them: one between things, none inside a bracket. */\nconst tidy = (row: string): string =>\n row\n .replace(/\\s+/g, ' ')\n .replace(/([([⟨⌊⌈]) /g, '$1')\n .replace(/ ([)\\]⟩⌋⌉,])/g, '$1')\n .trim()\n // A letter with its mark as one character where there is one: fonts draw `ŷ` better than `y` and a hat.\n .normalize('NFC')\n\n/** The rows of a formula: one, unless the formula breaks its own (`\\\\`). */\nexport function mathRows(source: string): string[] {\n return new Reader(source).run().split('\\n').map(tidy).filter(Boolean)\n}\n\n/** A formula on one row, as it is written inside a sentence. */\nexport const mathText = (source: string): string => mathRows(source).join(' ')\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Text made safe to print. A reply is a model's words, and a model can be made to write anything:
3
+ * an escape sequence that clears the screen, retitles the window or rewrites a row already read,
4
+ * a direction override that shows `exe.txt` for `txt.exe`. Every character that is an instruction
5
+ * to the terminal and not a letter is written out as what it is (`\u{1b}`), so it is seen and
6
+ * does nothing.
7
+ *
8
+ * Every piece of text a row is made of passes through here; the escape sequences in the output
9
+ * are the renderer's own (`style.ts`) and no others.
10
+ */
11
+ /** `text` with every character a terminal would act on written out as its escape. */
12
+ export declare const printable: (text: string) => string;
@@ -0,0 +1,31 @@
1
+ // src/tui/printable.ts
2
+ /**
3
+ * Text made safe to print. A reply is a model's words, and a model can be made to write anything:
4
+ * an escape sequence that clears the screen, retitles the window or rewrites a row already read,
5
+ * a direction override that shows `exe.txt` for `txt.exe`. Every character that is an instruction
6
+ * to the terminal and not a letter is written out as what it is (`\u{1b}`), so it is seen and
7
+ * does nothing.
8
+ *
9
+ * Every piece of text a row is made of passes through here; the escape sequences in the output
10
+ * are the renderer's own (`style.ts`) and no others.
11
+ */
12
+ const RANGES = [
13
+ [0, 31],
14
+ [127, 159],
15
+ [8206, 8207],
16
+ [8232, 8233],
17
+ [8234, 8238],
18
+ [8294, 8297]
19
+ ];
20
+ const hex = (code) => `\\u{${code.toString(16)}}`;
21
+ const UNSAFE = new RegExp(`[${RANGES.map(([from, to]) => `${hex(from)}-${hex(to)}`).join("")}]`, "gu");
22
+ const NAMED = {
23
+ " ": "\\t",
24
+ "\n": "\\n",
25
+ "\r": "\\r"
26
+ };
27
+ /** `text` with every character a terminal would act on written out as its escape. */
28
+ const printable = (text) => text.replace(UNSAFE, (c) => NAMED[c] ?? `\\u{${c.codePointAt(0).toString(16)}}`);
29
+ export { printable };
30
+
31
+ //# sourceMappingURL=printable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"printable.js","names":[],"sources":["../../src/tui/printable.ts"],"sourcesContent":["/**\n * Text made safe to print. A reply is a model's words, and a model can be made to write anything:\n * an escape sequence that clears the screen, retitles the window or rewrites a row already read,\n * a direction override that shows `exe.txt` for `txt.exe`. Every character that is an instruction\n * to the terminal and not a letter is written out as what it is (`\\u{1b}`), so it is seen and\n * does nothing.\n *\n * Every piece of text a row is made of passes through here; the escape sequences in the output\n * are the renderer's own (`style.ts`) and no others.\n */\n\n// C0 and C1 controls and DEL; the marks that reorder what is shown (bidi marks, embeddings,\n// overrides and isolates); and the separators a terminal may take for the end of a row. Written\n// as numbers: a character of this set typed into the source would be invisible, or end the line.\nconst RANGES: ReadonlyArray<readonly [number, number]> = [\n [0x00, 0x1f],\n [0x7f, 0x9f],\n [0x200e, 0x200f],\n [0x2028, 0x2029],\n [0x202a, 0x202e],\n [0x2066, 0x2069],\n]\nconst hex = (code: number): string => `\\\\u{${code.toString(16)}}`\nconst UNSAFE = new RegExp(\n `[${RANGES.map(([from, to]) => `${hex(from)}-${hex(to)}`).join('')}]`,\n 'gu',\n)\n\nconst NAMED: Record<string, string> = { '\\t': '\\\\t', '\\n': '\\\\n', '\\r': '\\\\r' }\n\n/** `text` with every character a terminal would act on written out as its escape. */\nexport const printable = (text: string): string =>\n text.replace(UNSAFE, (c) => NAMED[c] ?? `\\\\u{${c.codePointAt(0)!.toString(16)}}`)\n"],"mappings":";;;;;;;;;;;AAcA,MAAM,SAAmD;CACvD,CAAC,GAAM,EAAI;CACX,CAAC,KAAM,GAAI;CACX,CAAC,MAAQ,IAAM;CACf,CAAC,MAAQ,IAAM;CACf,CAAC,MAAQ,IAAM;CACf,CAAC,MAAQ,IAAM;AACjB;AACA,MAAM,OAAO,SAAyB,OAAO,KAAK,SAAS,EAAE,EAAE;AAC/D,MAAM,SAAS,IAAI,OACjB,IAAI,OAAO,KAAK,CAAC,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,IACnE,IACF;AAEA,MAAM,QAAgC;CAAE,KAAM;CAAO,MAAM;CAAO,MAAM;AAAM;;AAG9E,MAAa,aAAa,SACxB,KAAK,QAAQ,SAAS,MAAM,MAAM,MAAM,OAAO,EAAE,YAAY,CAAC,CAAC,CAAE,SAAS,EAAE,EAAE,EAAE"}
@@ -0,0 +1,12 @@
1
+ import { CalloutKind } from "../dialect.js";
2
+ /** The words the renderer adds, for a terminal in another language. */
3
+ export interface TerminalLabels {
4
+ callouts: Record<CalloutKind, string>;
5
+ /** What a `[!DETAILS]` form with no title of its own is called. */
6
+ details: string;
7
+ /** What stands over a diagram's source, which a terminal cannot draw. */
8
+ diagram: string;
9
+ }
10
+ export declare const DEFAULT_LABELS: TerminalLabels;
11
+ /** The narrowest a terminal is drawn for: under it, rows are as wide as this. */
12
+ export declare const MIN_WIDTH = 8;