@opencode/ui 0.0.0-dev-20725 → 0.0.0-dev-20731

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.
@@ -1,3 +1,3 @@
1
1
  import type { MarkedExtension } from "marked";
2
2
  export declare function createMarkdownParser(highlight: (code: string, language: string) => string | Promise<string>): import("marked").Marked<string, string>;
3
- export declare const markdownMath: MarkedExtension[];
3
+ export declare const markdownMath: MarkedExtension;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencode/ui",
3
- "version": "0.0.0-dev-20725",
3
+ "version": "0.0.0-dev-20731",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -252,7 +252,6 @@
252
252
  "fuzzysort": "3.1.0",
253
253
  "katex": "0.16.47",
254
254
  "marked": "18.0.11",
255
- "marked-katex-extension": "5.1.13",
256
255
  "marked-shiki": "1.2.1",
257
256
  "motion": "12.34.5",
258
257
  "remeda": "2.26.0",
@@ -1,45 +1,97 @@
1
1
  import katex from "katex"
2
2
  import type { MarkedExtension, Tokens } from "marked"
3
- import markedKatex from "marked-katex-extension"
4
3
  import markedShiki from "marked-shiki"
5
4
  import { createMarkdownBase } from "./marked-base"
6
5
 
7
6
  export function createMarkdownParser(highlight: (code: string, language: string) => string | Promise<string>) {
8
- return createMarkdownBase().use(...markdownMath, markedShiki({ highlight }))
7
+ return createMarkdownBase().use(markdownMath, markedShiki({ highlight }))
9
8
  }
10
9
 
10
+ // `$$...$$` renders as display math anywhere in a line.
11
+ // `$...$` follows Pandoc's boundaries so prices and shell variables stay text: the opening `$` needs a non-space
12
+ // after it, the closing `$` needs a non-space before it and no letter, digit, or underscore after it.
13
+ // Neither form spans a newline, and `$...$` cannot contain an unescaped `$`, so a failed `$...$` attempt stops at
14
+ // the next `$` and a failed `$$...$$` attempt stops at the end of the line.
15
+ const inlineDollarMathRegex =
16
+ /\$\$(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n$]))\$\$|\$(?=[^\s$])((?:\\.|[^\\\n$])*?(?:\\\S|[^\s\\$]))\$(?!\w)/y
17
+
11
18
  const inlineParenMathRegex = /^\\\(((?:\\.|[^\\\n])*?)\\\)/
12
19
 
13
- // marked-katex-extension handles `$...$`, `$$...$$`, and `$$` fenced blocks; it has no `\(...\)` syntax.
14
- export const markdownMath: MarkedExtension[] = [
15
- markedKatex({ throwOnError: false }),
16
- {
17
- extensions: [
18
- {
19
- name: "inlineParenKatex",
20
- level: "inline",
21
- start(src) {
22
- const index = src.indexOf("\\(")
23
-
24
- if (index === -1) return
25
-
26
- return index
27
- },
28
- tokenizer(src) {
29
- const match = src.match(inlineParenMathRegex)
30
-
31
- if (!match) return
32
-
33
- return {
34
- type: "inlineParenKatex",
35
- raw: match[0],
36
- text: match[1].trim(),
37
- }
38
- },
39
- renderer(token: Tokens.Generic) {
40
- return katex.renderToString(token.text, { throwOnError: false })
41
- },
20
+ const blockMathRegex = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/
21
+
22
+ function renderMath(token: Tokens.Generic) {
23
+ return katex.renderToString(token.text, { throwOnError: false, displayMode: token.displayMode })
24
+ }
25
+
26
+ export const markdownMath: MarkedExtension = {
27
+ extensions: [
28
+ {
29
+ name: "inlineDollarKatex",
30
+ level: "inline",
31
+ // marked calls `start` again for every text token with the rest of the paragraph, so it must not try the
32
+ // regex at each `$`; a `$` that fails the tokenizer just stays in the merged text.
33
+ start(src) {
34
+ const index = src.indexOf("$")
35
+
36
+ if (index === -1) return
37
+
38
+ return index
42
39
  },
43
- ],
44
- },
45
- ]
40
+ tokenizer(src) {
41
+ inlineDollarMathRegex.lastIndex = 0
42
+ const match = inlineDollarMathRegex.exec(src)
43
+
44
+ if (!match) return
45
+
46
+ return {
47
+ type: "inlineDollarKatex",
48
+ raw: match[0],
49
+ text: (match[1] ?? match[2]).trim(),
50
+ displayMode: match[1] !== undefined,
51
+ }
52
+ },
53
+ renderer: renderMath,
54
+ },
55
+ {
56
+ name: "inlineParenKatex",
57
+ level: "inline",
58
+ start(src) {
59
+ const index = src.indexOf("\\(")
60
+
61
+ if (index === -1) return
62
+
63
+ return index
64
+ },
65
+ tokenizer(src) {
66
+ const match = src.match(inlineParenMathRegex)
67
+
68
+ if (!match) return
69
+
70
+ return {
71
+ type: "inlineParenKatex",
72
+ raw: match[0],
73
+ text: match[1].trim(),
74
+ displayMode: false,
75
+ }
76
+ },
77
+ renderer: renderMath,
78
+ },
79
+ {
80
+ name: "blockKatex",
81
+ level: "block",
82
+ tokenizer(src) {
83
+ const match = src.match(blockMathRegex)
84
+
85
+ if (!match) return
86
+
87
+ return {
88
+ type: "blockKatex",
89
+ raw: match[0],
90
+ text: match[2].trim(),
91
+ displayMode: match[1].length === 2,
92
+ }
93
+ },
94
+ renderer: (token) => renderMath(token) + "\n",
95
+ },
96
+ ],
97
+ }