@opencode-ai/ui 1.18.12 → 1.18.14

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 (93) hide show
  1. package/dist/context/i18n.d.ts +10 -1
  2. package/dist/context/marked-parser.d.ts +2 -0
  3. package/dist/context/marked-theme-register.d.ts +1 -0
  4. package/dist/context/marked-theme.d.ts +2 -0
  5. package/dist/context/marked.d.ts +2 -9
  6. package/dist/i18n/ar.d.ts +38 -0
  7. package/dist/i18n/az.d.ts +1 -0
  8. package/dist/i18n/br.d.ts +26 -0
  9. package/dist/i18n/bs.d.ts +26 -0
  10. package/dist/i18n/da.d.ts +22 -0
  11. package/dist/i18n/de.d.ts +22 -0
  12. package/dist/i18n/es.d.ts +26 -0
  13. package/dist/i18n/fi.d.ts +1 -0
  14. package/dist/i18n/fr.d.ts +26 -0
  15. package/dist/i18n/hi.d.ts +1 -0
  16. package/dist/i18n/id.d.ts +1 -0
  17. package/dist/i18n/it.d.ts +1 -0
  18. package/dist/i18n/ja.d.ts +22 -0
  19. package/dist/i18n/ko.d.ts +22 -0
  20. package/dist/i18n/nl.d.ts +1 -0
  21. package/dist/i18n/pa.d.ts +1 -0
  22. package/dist/i18n/pl.d.ts +30 -0
  23. package/dist/i18n/ru.d.ts +30 -0
  24. package/dist/i18n/sv.d.ts +1 -0
  25. package/dist/i18n/th.d.ts +22 -0
  26. package/dist/i18n/tr.d.ts +22 -0
  27. package/dist/i18n/ur.d.ts +1 -0
  28. package/dist/i18n/vi.d.ts +1 -0
  29. package/dist/i18n/zh.d.ts +22 -0
  30. package/dist/i18n/zht.d.ts +22 -0
  31. package/package.json +2 -3
  32. package/src/components/diff-changes.css +2 -0
  33. package/src/components/dropdown-menu.css +2 -2
  34. package/src/components/icon.css +5 -0
  35. package/src/components/icon.tsx +12 -1
  36. package/src/components/resize-handle.css +14 -2
  37. package/src/components/resize-handle.tsx +5 -1
  38. package/src/components/scroll-view.css +1 -1
  39. package/src/components/select.css +5 -3
  40. package/src/components/switch.css +4 -0
  41. package/src/components/tabs.css +54 -26
  42. package/src/components/tabs.tsx +1 -0
  43. package/src/components/text-field.css +2 -2
  44. package/src/components/toast.css +1 -1
  45. package/src/context/i18n.tsx +38 -2
  46. package/src/context/marked-parser.tsx +68 -0
  47. package/src/context/marked-theme-register.tsx +10 -0
  48. package/src/context/marked-theme.tsx +372 -0
  49. package/src/context/marked.tsx +20 -562
  50. package/src/i18n/ar.ts +62 -22
  51. package/src/i18n/az.ts +197 -0
  52. package/src/i18n/br.ts +34 -6
  53. package/src/i18n/bs.ts +51 -23
  54. package/src/i18n/da.ts +36 -12
  55. package/src/i18n/de.ts +58 -36
  56. package/src/i18n/en.ts +24 -0
  57. package/src/i18n/es.ts +45 -17
  58. package/src/i18n/fi.ts +197 -0
  59. package/src/i18n/fr.ts +51 -21
  60. package/src/i18n/hi.ts +199 -0
  61. package/src/i18n/id.ts +219 -0
  62. package/src/i18n/it.ts +202 -0
  63. package/src/i18n/ja.ts +29 -5
  64. package/src/i18n/ko.ts +36 -12
  65. package/src/i18n/nl.ts +197 -0
  66. package/src/i18n/no.ts +47 -23
  67. package/src/i18n/pa.ts +198 -0
  68. package/src/i18n/pl.ts +57 -24
  69. package/src/i18n/ru.ts +55 -23
  70. package/src/i18n/sv.ts +197 -0
  71. package/src/i18n/th.ts +44 -21
  72. package/src/i18n/tr.ts +49 -25
  73. package/src/i18n/uk.ts +47 -15
  74. package/src/i18n/ur.ts +198 -0
  75. package/src/i18n/vi.ts +197 -0
  76. package/src/i18n/zh.ts +52 -29
  77. package/src/i18n/zht.ts +45 -22
  78. package/src/v2/components/dialog-v2.css +2 -2
  79. package/src/v2/components/dialog-v2.tsx +3 -1
  80. package/src/v2/components/diff-changes-v2.css +2 -0
  81. package/src/v2/components/file-tree-v2.css +6 -2
  82. package/src/v2/components/inline-input-v2.tsx +3 -1
  83. package/src/v2/components/line-comment-v2.css +1 -1
  84. package/src/v2/components/line-comment-v2.tsx +6 -4
  85. package/src/v2/components/select-v2.css +16 -5
  86. package/src/v2/components/switch-v2.css +8 -0
  87. package/src/v2/components/tabs-v2.css +4 -4
  88. package/src/v2/components/tabs-v2.tsx +4 -2
  89. package/src/v2/components/text-input-v2.css +7 -5
  90. package/src/v2/components/text-input-v2.tsx +7 -1
  91. package/src/v2/components/toast-v2.tsx +8 -4
  92. package/dist/context/marked-code-span.d.ts +0 -10
  93. package/src/context/marked-code-span.ts +0 -17
@@ -1,570 +1,28 @@
1
- import { marked, type MarkedExtension, type Tokens } from "marked"
2
- import markedShiki from "marked-shiki"
3
- import katex from "katex"
1
+ import { getSharedHighlighter } from "@pierre/diffs"
4
2
  import { bundledLanguages, type BundledLanguage } from "shiki"
5
3
  import { createSimpleContext } from "./helper"
6
- import { markedCodeSpanBoundary } from "./marked-code-span"
7
- import { getSharedHighlighter, registerCustomTheme, ThemeRegistrationResolved } from "@pierre/diffs"
4
+ import { createMarkdownParser } from "./marked-parser"
5
+ import { registerOpenCodeTheme } from "./marked-theme-register"
8
6
 
9
- export const OpenCodeTheme = {
10
- name: "OpenCode",
11
- bg: "var(--color-background-stronger)",
12
- fg: "var(--text-base)",
13
- colors: {
14
- "editor.background": "var(--color-background-stronger)",
15
- "editor.foreground": "var(--text-base)",
16
- "gitDecoration.addedResourceForeground": "var(--syntax-diff-add)",
17
- "gitDecoration.deletedResourceForeground": "var(--syntax-diff-delete)",
18
- "gitDecoration.modifiedResourceForeground": "var(--syntax-diff-unknown)",
19
- // "gitDecoration.conflictingResourceForeground": "#ffca00",
20
- // "gitDecoration.modifiedResourceForeground": "#1a76d4",
21
- // "gitDecoration.untrackedResourceForeground": "#00cab1",
22
- // "gitDecoration.ignoredResourceForeground": "#84848A",
23
- // "terminal.titleForeground": "#adadb1",
24
- // "terminal.titleInactiveForeground": "#84848A",
25
- // "terminal.background": "#141415",
26
- // "terminal.foreground": "#adadb1",
27
- // "terminal.ansiBlack": "#141415",
28
- // "terminal.ansiRed": "#ff2e3f",
29
- // "terminal.ansiGreen": "#0dbe4e",
30
- // "terminal.ansiYellow": "#ffca00",
31
- // "terminal.ansiBlue": "#008cff",
32
- // "terminal.ansiMagenta": "#c635e4",
33
- // "terminal.ansiCyan": "#08c0ef",
34
- // "terminal.ansiWhite": "#c6c6c8",
35
- // "terminal.ansiBrightBlack": "#141415",
36
- // "terminal.ansiBrightRed": "#ff2e3f",
37
- // "terminal.ansiBrightGreen": "#0dbe4e",
38
- // "terminal.ansiBrightYellow": "#ffca00",
39
- // "terminal.ansiBrightBlue": "#008cff",
40
- // "terminal.ansiBrightMagenta": "#c635e4",
41
- // "terminal.ansiBrightCyan": "#08c0ef",
42
- // "terminal.ansiBrightWhite": "#c6c6c8",
43
- },
44
- tokenColors: [
45
- {
46
- scope: ["comment", "punctuation.definition.comment", "string.comment"],
47
- settings: {
48
- foreground: "var(--syntax-comment)",
49
- },
50
- },
51
- {
52
- scope: ["entity.other.attribute-name"],
53
- settings: {
54
- foreground: "var(--syntax-property)", // maybe attribute
55
- },
56
- },
57
- {
58
- scope: ["constant", "entity.name.constant", "variable.other.constant", "variable.language", "entity"],
59
- settings: {
60
- foreground: "var(--syntax-constant)",
61
- },
62
- },
63
- {
64
- scope: ["entity.name", "meta.export.default", "meta.definition.variable"],
65
- settings: {
66
- foreground: "var(--syntax-type)",
67
- },
68
- },
69
- {
70
- scope: ["meta.object.member"],
71
- settings: {
72
- foreground: "var(--syntax-primitive)",
73
- },
74
- },
75
- {
76
- scope: [
77
- "variable.parameter.function",
78
- "meta.jsx.children",
79
- "meta.block",
80
- "meta.tag.attributes",
81
- "entity.name.constant",
82
- "meta.embedded.expression",
83
- "meta.template.expression",
84
- "string.other.begin.yaml",
85
- "string.other.end.yaml",
86
- ],
87
- settings: {
88
- foreground: "var(--syntax-punctuation)",
89
- },
90
- },
91
- {
92
- scope: ["entity.name.function", "support.type.primitive"],
93
- settings: {
94
- foreground: "var(--syntax-primitive)",
95
- },
96
- },
97
- {
98
- scope: ["support.class.component"],
99
- settings: {
100
- foreground: "var(--syntax-type)",
101
- },
102
- },
103
- {
104
- scope: "keyword",
105
- settings: {
106
- foreground: "var(--syntax-keyword)",
107
- },
108
- },
109
- {
110
- scope: [
111
- "keyword.operator",
112
- "storage.type.function.arrow",
113
- "punctuation.separator.key-value.css",
114
- "entity.name.tag.yaml",
115
- "punctuation.separator.key-value.mapping.yaml",
116
- ],
117
- settings: {
118
- foreground: "var(--syntax-operator)",
119
- },
120
- },
121
- {
122
- scope: ["storage", "storage.type"],
123
- settings: {
124
- foreground: "var(--syntax-keyword)",
125
- },
126
- },
127
- {
128
- scope: ["storage.modifier.package", "storage.modifier.import", "storage.type.java"],
129
- settings: {
130
- foreground: "var(--syntax-primitive)",
131
- },
132
- },
133
- {
134
- scope: [
135
- "string",
136
- "punctuation.definition.string",
137
- "string punctuation.section.embedded source",
138
- "entity.name.tag",
139
- ],
140
- settings: {
141
- foreground: "var(--syntax-string)",
142
- },
143
- },
144
- {
145
- scope: "support",
146
- settings: {
147
- foreground: "var(--syntax-primitive)",
148
- },
149
- },
150
- {
151
- scope: ["support.type.object.module", "variable.other.object", "support.type.property-name.css"],
152
- settings: {
153
- foreground: "var(--syntax-object)",
154
- },
155
- },
156
- {
157
- scope: "meta.property-name",
158
- settings: {
159
- foreground: "var(--syntax-property)",
160
- },
161
- },
162
- {
163
- scope: "variable",
164
- settings: {
165
- foreground: "var(--syntax-variable)",
166
- },
167
- },
168
- {
169
- scope: "variable.other",
170
- settings: {
171
- foreground: "var(--syntax-variable)",
172
- },
173
- },
174
- {
175
- scope: [
176
- "invalid.broken",
177
- "invalid.illegal",
178
- "invalid.unimplemented",
179
- "invalid.deprecated",
180
- "message.error",
181
- "markup.deleted",
182
- "meta.diff.header.from-file",
183
- "punctuation.definition.deleted",
184
- "brackethighlighter.unmatched",
185
- "token.error-token",
186
- ],
187
- settings: {
188
- foreground: "var(--syntax-critical)",
189
- },
190
- },
191
- {
192
- scope: "carriage-return",
193
- settings: {
194
- foreground: "var(--syntax-keyword)",
195
- },
196
- },
197
- {
198
- scope: "string source",
199
- settings: {
200
- foreground: "var(--syntax-variable)",
201
- },
202
- },
203
- {
204
- scope: "string variable",
205
- settings: {
206
- foreground: "var(--syntax-constant)",
207
- },
208
- },
209
- {
210
- scope: [
211
- "source.regexp",
212
- "string.regexp",
213
- "string.regexp.character-class",
214
- "string.regexp constant.character.escape",
215
- "string.regexp source.ruby.embedded",
216
- "string.regexp string.regexp.arbitrary-repitition",
217
- "string.regexp constant.character.escape",
218
- ],
219
- settings: {
220
- foreground: "var(--syntax-regexp)",
221
- },
222
- },
223
- {
224
- scope: "support.constant",
225
- settings: {
226
- foreground: "var(--syntax-primitive)",
227
- },
228
- },
229
- {
230
- scope: "support.variable",
231
- settings: {
232
- foreground: "var(--syntax-variable)",
233
- },
234
- },
235
- {
236
- scope: "meta.module-reference",
237
- settings: {
238
- foreground: "var(--syntax-info)",
239
- },
240
- },
241
- {
242
- scope: "punctuation.definition.list.begin.markdown",
243
- settings: {
244
- foreground: "var(--syntax-punctuation)",
245
- },
246
- },
247
- {
248
- scope: ["markup.heading", "markup.heading entity.name"],
249
- settings: {
250
- fontStyle: "bold",
251
- foreground: "var(--syntax-info)",
252
- },
253
- },
254
- {
255
- scope: "markup.quote",
256
- settings: {
257
- foreground: "var(--syntax-info)",
258
- },
259
- },
260
- {
261
- scope: "markup.italic",
262
- settings: {
263
- fontStyle: "italic",
264
- // foreground: "",
265
- },
266
- },
267
- {
268
- scope: "markup.bold",
269
- settings: {
270
- fontStyle: "bold",
271
- foreground: "var(--text-strong)",
272
- },
273
- },
274
- {
275
- scope: [
276
- "markup.raw",
277
- "markup.inserted",
278
- "meta.diff.header.to-file",
279
- "punctuation.definition.inserted",
280
- "markup.changed",
281
- "punctuation.definition.changed",
282
- "markup.ignored",
283
- "markup.untracked",
284
- ],
285
- settings: {
286
- foreground: "var(--text-base)",
287
- },
288
- },
289
- {
290
- scope: "meta.diff.range",
291
- settings: {
292
- fontStyle: "bold",
293
- foreground: "var(--syntax-unknown)",
294
- },
295
- },
296
- {
297
- scope: "meta.diff.header",
298
- settings: {
299
- foreground: "var(--syntax-unknown)",
300
- },
301
- },
302
- {
303
- scope: "meta.separator",
304
- settings: {
305
- fontStyle: "bold",
306
- foreground: "var(--syntax-unknown)",
307
- },
308
- },
309
- {
310
- scope: "meta.output",
311
- settings: {
312
- foreground: "var(--syntax-unknown)",
313
- },
314
- },
315
- {
316
- scope: "meta.export.default",
317
- settings: {
318
- foreground: "var(--syntax-unknown)",
319
- },
320
- },
321
- {
322
- scope: [
323
- "brackethighlighter.tag",
324
- "brackethighlighter.curly",
325
- "brackethighlighter.round",
326
- "brackethighlighter.square",
327
- "brackethighlighter.angle",
328
- "brackethighlighter.quote",
329
- ],
330
- settings: {
331
- foreground: "var(--syntax-unknown)",
332
- },
333
- },
334
- {
335
- scope: ["constant.other.reference.link", "string.other.link"],
336
- settings: {
337
- fontStyle: "underline",
338
- foreground: "var(--syntax-unknown)",
339
- },
340
- },
341
- {
342
- scope: "token.info-token",
343
- settings: {
344
- foreground: "var(--syntax-info)",
345
- },
346
- },
347
- {
348
- scope: "token.warn-token",
349
- settings: {
350
- foreground: "var(--syntax-warning)",
351
- },
352
- },
353
- {
354
- scope: "token.debug-token",
355
- settings: {
356
- foreground: "var(--syntax-info)",
357
- },
358
- },
359
- ],
360
- semanticTokenColors: {
361
- comment: "var(--syntax-comment)",
362
- string: "var(--syntax-string)",
363
- number: "var(--syntax-constant)",
364
- regexp: "var(--syntax-regexp)",
365
- keyword: "var(--syntax-keyword)",
366
- variable: "var(--syntax-variable)",
367
- parameter: "var(--syntax-variable)",
368
- property: "var(--syntax-property)",
369
- function: "var(--syntax-primitive)",
370
- method: "var(--syntax-primitive)",
371
- type: "var(--syntax-type)",
372
- class: "var(--syntax-type)",
373
- namespace: "var(--syntax-type)",
374
- enumMember: "var(--syntax-primitive)",
375
- "variable.constant": "var(--syntax-constant)",
376
- "variable.defaultLibrary": "var(--syntax-unknown)",
377
- },
378
- } as unknown as ThemeRegistrationResolved
7
+ export { OpenCodeTheme } from "./marked-theme"
379
8
 
380
- registerCustomTheme("OpenCode", () => Promise.resolve(OpenCodeTheme))
381
-
382
- function renderMathInText(text: string): string {
383
- let result = text
384
-
385
- // Display math: $$...$$
386
- const displayMathRegex = /\$\$([\s\S]*?)\$\$/g
387
- result = result.replace(displayMathRegex, (_, math) => {
388
- try {
389
- return katex.renderToString(math, {
390
- displayMode: true,
391
- throwOnError: false,
392
- })
393
- } catch {
394
- return `$$${math}$$`
395
- }
396
- })
397
-
398
- // Inline math: \(...\)
399
- const inlineMathRegex = /\\\(((?:\\.|[^\\\n])*?)\\\)/g
400
- result = result.replace(inlineMathRegex, (_, math) => {
401
- try {
402
- return katex.renderToString(math, {
403
- displayMode: false,
404
- throwOnError: false,
405
- })
406
- } catch {
407
- return `\\(${math}\\)`
408
- }
409
- })
410
-
411
- return result
412
- }
413
-
414
- const inlineMathRegex = /^\\\(((?:\\.|[^\\\n])*?)\\\)/
415
- const blockMathRegex = /^\$\$\n([\s\S]+?)\n\$\$(?:\n|$)/
416
-
417
- const katexExtension: MarkedExtension = {
418
- extensions: [
419
- {
420
- name: "inlineKatex",
421
- level: "inline",
422
- start(src) {
423
- const index = src.indexOf("\\(")
424
- if (index === -1) return
425
- return index
426
- },
427
- tokenizer(src) {
428
- const match = src.match(inlineMathRegex)
429
- if (!match) return
430
- return {
431
- type: "inlineKatex",
432
- raw: match[0],
433
- text: match[1].trim(),
434
- displayMode: false,
435
- }
436
- },
437
- renderer: renderKatexToken,
438
- },
439
- {
440
- name: "blockKatex",
441
- level: "block",
442
- tokenizer(src) {
443
- const match = src.match(blockMathRegex)
444
- if (!match) return
445
- return {
446
- type: "blockKatex",
447
- raw: match[0],
448
- text: match[1].trim(),
449
- displayMode: true,
450
- }
451
- },
452
- renderer: renderKatexToken,
453
- },
454
- ],
455
- }
456
-
457
- function renderKatexToken(token: Tokens.Generic) {
458
- return katex.renderToString(typeof token.text === "string" ? token.text : "", {
459
- displayMode: token.displayMode === true,
460
- throwOnError: false,
461
- })
462
- }
463
-
464
- function renderMathExpressions(html: string): string {
465
- // Split on code/pre/kbd tags to avoid processing their contents
466
- const codeBlockPattern = /(<(?:pre|code|kbd)[^>]*>[\s\S]*?<\/(?:pre|code|kbd)>)/gi
467
- const parts = html.split(codeBlockPattern)
468
-
469
- return parts
470
- .map((part, i) => {
471
- // Odd indices are the captured code blocks - leave them alone
472
- if (i % 2 === 1) return part
473
- // Process math only in non-code parts
474
- return renderMathInText(part)
475
- })
476
- .join("")
477
- }
478
-
479
- async function highlightCodeBlocks(html: string): Promise<string> {
480
- const codeBlockRegex = /<pre><code(?:\s+class="language-([^"]*)")?>([\s\S]*?)<\/code><\/pre>/g
481
- const matches = [...html.matchAll(codeBlockRegex)]
482
- if (matches.length === 0) return html
483
-
484
- const highlighter = await getSharedHighlighter({
485
- themes: ["OpenCode"],
486
- langs: [],
487
- preferredHighlighter: "shiki-wasm",
488
- })
489
-
490
- let result = html
491
- for (const match of matches) {
492
- const [fullMatch, lang, escapedCode] = match
493
- const code = escapedCode
494
- .replace(/&lt;/g, "<")
495
- .replace(/&gt;/g, ">")
496
- .replace(/&amp;/g, "&")
497
- .replace(/&quot;/g, '"')
498
- .replace(/&#39;/g, "'")
499
-
500
- let language = lang || "text"
501
- if (!(language in bundledLanguages)) {
502
- language = "text"
503
- }
504
- if (!highlighter.getLoadedLanguages().includes(language)) {
505
- await highlighter.loadLanguage(language as BundledLanguage)
506
- }
507
-
508
- const highlighted = highlighter.codeToHtml(code, {
509
- lang: language,
510
- theme: "OpenCode",
511
- tabindex: false,
512
- })
513
- result = result.replace(fullMatch, () => highlighted)
514
- }
515
-
516
- return result
517
- }
518
-
519
- export type NativeMarkdownParser = (markdown: string) => Promise<string>
9
+ registerOpenCodeTheme()
520
10
 
521
11
  export const { use: useMarked, provider: MarkedProvider } = createSimpleContext({
522
12
  name: "Marked",
523
- init: (props: { nativeParser?: NativeMarkdownParser }) => {
524
- const jsParser = marked.use(
525
- markedCodeSpanBoundary,
526
- {
527
- renderer: {
528
- link({ href, title, text }) {
529
- const titleAttr = title ? ` title="${title}"` : ""
530
- return `<a href="${href}"${titleAttr} class="external-link" target="_blank" rel="noopener noreferrer">${text}</a>`
531
- },
532
- },
533
- },
534
- katexExtension,
535
- markedShiki({
536
- async highlight(code, lang) {
537
- const highlighter = await getSharedHighlighter({
538
- themes: ["OpenCode"],
539
- langs: [],
540
- preferredHighlighter: "shiki-wasm",
541
- })
542
- if (!(lang in bundledLanguages)) {
543
- lang = "text"
544
- }
545
- if (!highlighter.getLoadedLanguages().includes(lang)) {
546
- await highlighter.loadLanguage(lang as BundledLanguage)
547
- }
548
- return highlighter.codeToHtml(code, {
549
- lang: lang || "text",
550
- theme: "OpenCode",
551
- tabindex: false,
552
- })
553
- },
554
- }),
555
- )
556
-
557
- if (props.nativeParser) {
558
- const nativeParser = props.nativeParser
559
- return {
560
- async parse(markdown: string): Promise<string> {
561
- const html = await nativeParser(markdown)
562
- const withMath = renderMathExpressions(html)
563
- return highlightCodeBlocks(withMath)
564
- },
565
- }
566
- }
567
-
568
- return jsParser
569
- },
13
+ init: () =>
14
+ createMarkdownParser(async (code, language) => {
15
+ const highlighter = await getSharedHighlighter({
16
+ themes: ["OpenCode"],
17
+ langs: [],
18
+ preferredHighlighter: "shiki-wasm",
19
+ })
20
+ const name = language in bundledLanguages ? language : "text"
21
+ if (!highlighter.getLoadedLanguages().includes(name)) await highlighter.loadLanguage(name as BundledLanguage)
22
+ return highlighter.codeToHtml(code, {
23
+ lang: name,
24
+ theme: "OpenCode",
25
+ tabindex: false,
26
+ })
27
+ }),
570
28
  })