@opencode/ui 2.1.2 → 2.1.4

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.
@@ -0,0 +1,68 @@
1
+ export declare const OpenCodeTheme: {
2
+ name: string;
3
+ appearance: "dark";
4
+ cssVariables: {
5
+ prefix: string;
6
+ };
7
+ style: {
8
+ "editor.background": string;
9
+ "editor.foreground": string;
10
+ created: string;
11
+ deleted: string;
12
+ modified: string;
13
+ syntax: {
14
+ attribute: string;
15
+ background: string;
16
+ boolean: string;
17
+ comment: string;
18
+ constant: string;
19
+ constructor: string;
20
+ "diff.minus": string;
21
+ "diff.plus": string;
22
+ embedded: string;
23
+ emphasis: string;
24
+ enum: string;
25
+ foreground: string;
26
+ function: string;
27
+ hint: string;
28
+ keyword: string;
29
+ "keyword.operator": string;
30
+ label: string;
31
+ link_text: string;
32
+ link_uri: string;
33
+ namespace: string;
34
+ number: string;
35
+ operator: string;
36
+ predictive: {
37
+ color: string;
38
+ font_style: "italic";
39
+ };
40
+ preproc: string;
41
+ primary: string;
42
+ property: string;
43
+ punctuation: string;
44
+ "punctuation.special": string;
45
+ selector: string;
46
+ "selector.class": string;
47
+ "selector.id": string;
48
+ "selector.pseudo": string;
49
+ string: string;
50
+ "string.escape": string;
51
+ "string.regex": string;
52
+ "string.special": string;
53
+ tag: string;
54
+ "tag.component.jsx": string;
55
+ text: string;
56
+ "text.literal": string;
57
+ title: {
58
+ color: string;
59
+ font_weight: 700;
60
+ };
61
+ type: string;
62
+ variable: string;
63
+ "variable.parameter": string;
64
+ "variable.special": string;
65
+ variant: string;
66
+ };
67
+ };
68
+ };
@@ -1,3 +1,3 @@
1
1
  import type { MarkedExtension } from "marked";
2
- export declare function createMarkdownParser(highlight: (code: string, language: string) => string | Promise<string>): import("marked").Marked<string, string>;
2
+ export declare function createMarkdownParser(): import("marked").Marked<string, string>;
3
3
  export declare const markdownMath: MarkedExtension;
@@ -1,21 +1,24 @@
1
1
  import type { DesktopTheme } from "./types";
2
2
  export type ColorScheme = "light" | "dark" | "system";
3
- export declare const useTheme: () => {
4
- themeId: () => string;
5
- colorScheme: () => ColorScheme;
6
- mode: () => "dark" | "light";
7
- ids: () => string[];
8
- name: (id: string) => string;
9
- loadThemes: () => Promise<Record<string, DesktopTheme>>;
10
- themes: () => Record<string, DesktopTheme>;
11
- setTheme: (id: string) => void;
12
- setColorScheme: (scheme: ColorScheme) => void;
13
- registerTheme: (theme: DesktopTheme) => void;
14
- previewTheme: (id: string) => void;
15
- previewColorScheme: (scheme: ColorScheme) => void;
16
- commitPreview: () => void;
17
- cancelPreview: () => void;
18
- }, ThemeProvider: (props: import("solid-js").ParentProps<{
19
- defaultTheme?: string;
20
- onThemeApplied?: (theme: DesktopTheme, mode: "light" | "dark", scheme: ColorScheme) => void;
21
- }>) => import("solid-js").JSX.Element;
3
+ export declare const { use: useTheme, provider: ThemeProvider }: {
4
+ provider: (props: import("solid-js").ParentProps<{
5
+ defaultTheme?: string;
6
+ onThemeApplied?: (theme: DesktopTheme, mode: "light" | "dark", scheme: ColorScheme) => void;
7
+ }>) => import("solid-js").JSX.Element;
8
+ use(): {
9
+ themeId: () => string;
10
+ colorScheme: () => ColorScheme;
11
+ mode: () => "dark" | "light";
12
+ ids: () => string[];
13
+ name: (id: string) => string;
14
+ loadThemes: () => Promise<Record<string, DesktopTheme>>;
15
+ themes: () => Record<string, DesktopTheme>;
16
+ setTheme: (id: string) => void;
17
+ setColorScheme: (scheme: ColorScheme) => void;
18
+ registerTheme: (theme: DesktopTheme) => void;
19
+ previewTheme: (id: string) => void;
20
+ previewColorScheme: (scheme: ColorScheme) => void;
21
+ commitPreview: () => void;
22
+ cancelPreview: () => void;
23
+ };
24
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencode/ui",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -226,7 +226,8 @@
226
226
  },
227
227
  "scripts": {
228
228
  "build": "rm -rf dist && tsc -p tsconfig.build.json",
229
- "typecheck": "tsc --noEmit",
229
+ "typecheck": "bun check --no-script",
230
+ "typecheck:tsc": "tsc --noEmit",
230
231
  "test": "bun test src --only-failures",
231
232
  "dev": "vite",
232
233
  "generate:tailwind": "bun run script/tailwind.ts",
@@ -235,8 +236,8 @@
235
236
  "devDependencies": {
236
237
  "@solidjs/meta": "0.29.4",
237
238
  "@tsconfig/node22": "22.0.2",
238
- "@types/bun": "1.4.0",
239
- "@typescript/native": "npm:typescript@7.0.2",
239
+ "@types/bun": "1.4.3",
240
+ "@typescript/native": "npm:typescript@7.1.0-beta",
240
241
  "solid-js": "1.9.15",
241
242
  "tailwindcss": "4.1.11",
242
243
  "typescript": "npm:@typescript/typescript6@6.0.2",
@@ -247,16 +248,15 @@
247
248
  "dependencies": {
248
249
  "@kitlangton/solid-motion": "0.2.2",
249
250
  "@kobalte/core": "0.13.13",
250
- "@pierre/diffs": "1.5.1",
251
+ "@pierre/diffs": "1.6.1",
252
+ "@pierre/highlights": "0.2.0",
251
253
  "@solid-primitives/event-listener": "2.4.6",
252
254
  "@solid-primitives/resize-observer": "2.2.0",
253
255
  "fuzzysort": "3.1.0",
254
256
  "katex": "0.16.47",
255
257
  "marked": "18.0.11",
256
- "marked-shiki": "1.2.1",
257
258
  "motion": "12.34.5",
258
259
  "remeda": "2.26.0",
259
- "shiki": "4.4.3",
260
260
  "solid-list": "0.3.0",
261
261
  "solid-sonner": "0.3.1"
262
262
  },
@@ -0,0 +1,66 @@
1
+ import type { Theme } from "@pierre/highlights"
2
+
3
+ // A Highlights palette: each value names an app CSS variable without its `--`, so code follows the active app theme.
4
+ // Token types are grouped as in Pierre's own `pierre-dark` theme (for example, properties share the variable colour
5
+ // and all punctuation is one muted colour); each group uses the app syntax role with the same meaning.
6
+ // Token names fall back to their parent scope, so `keyword.control` uses `keyword`.
7
+ export const OpenCodeTheme = {
8
+ name: "OpenCode",
9
+ appearance: "dark",
10
+ cssVariables: { prefix: "--" },
11
+ style: {
12
+ "editor.background": "color-background-stronger",
13
+ "editor.foreground": "text-base",
14
+ created: "syntax-diff-add",
15
+ deleted: "syntax-diff-delete",
16
+ modified: "syntax-diff-unknown",
17
+ syntax: {
18
+ attribute: "syntax-property",
19
+ background: "color-background-stronger",
20
+ boolean: "syntax-constant",
21
+ comment: "syntax-comment",
22
+ constant: "syntax-constant",
23
+ constructor: "syntax-type",
24
+ "diff.minus": "syntax-diff-delete",
25
+ "diff.plus": "syntax-diff-add",
26
+ embedded: "text-base",
27
+ emphasis: "text-base",
28
+ enum: "syntax-type",
29
+ foreground: "text-base",
30
+ function: "syntax-primitive",
31
+ hint: "syntax-comment",
32
+ keyword: "syntax-keyword",
33
+ "keyword.operator": "syntax-operator",
34
+ label: "syntax-constant",
35
+ link_text: "syntax-info",
36
+ link_uri: "syntax-keyword",
37
+ namespace: "syntax-constant",
38
+ number: "syntax-constant",
39
+ operator: "syntax-operator",
40
+ predictive: { color: "syntax-comment", font_style: "italic" },
41
+ preproc: "syntax-keyword",
42
+ primary: "syntax-info",
43
+ property: "syntax-variable",
44
+ punctuation: "syntax-punctuation",
45
+ "punctuation.special": "syntax-keyword",
46
+ selector: "syntax-keyword",
47
+ "selector.class": "syntax-property",
48
+ "selector.id": "syntax-primitive",
49
+ "selector.pseudo": "syntax-operator",
50
+ string: "syntax-string",
51
+ "string.escape": "syntax-constant",
52
+ "string.regex": "syntax-regexp",
53
+ "string.special": "syntax-constant",
54
+ tag: "syntax-keyword",
55
+ "tag.component.jsx": "syntax-type",
56
+ text: "text-base",
57
+ "text.literal": "syntax-string",
58
+ title: { color: "syntax-keyword", font_weight: 700 },
59
+ type: "syntax-type",
60
+ variable: "syntax-variable",
61
+ "variable.parameter": "text-base",
62
+ "variable.special": "syntax-constant",
63
+ variant: "syntax-constant",
64
+ },
65
+ },
66
+ } satisfies Theme
@@ -1,10 +1,28 @@
1
+ import { codeToHtml, isSupportedLanguage } from "@pierre/highlights"
1
2
  import katex from "katex"
2
3
  import type { MarkedExtension, Tokens } from "marked"
3
- import markedShiki from "marked-shiki"
4
4
  import { createMarkdownBase } from "./marked-base"
5
+ import { OpenCodeTheme } from "./highlight-theme"
5
6
 
6
- export function createMarkdownParser(highlight: (code: string, language: string) => string | Promise<string>) {
7
- return createMarkdownBase().use(markdownMath, markedShiki({ highlight }))
7
+ export function createMarkdownParser() {
8
+ return createMarkdownBase().use(markdownMath, markdownCode)
9
+ }
10
+
11
+ const decoder = new TextDecoder()
12
+
13
+ // The class keeps the fence's own language, even one without a lexer, so the viewer can label it and render Mermaid.
14
+ const markdownCode: MarkedExtension = {
15
+ renderer: {
16
+ code(token) {
17
+ const language = (token.lang?.match(/^\S*/)?.[0] ?? "").toLowerCase().replace(/[^\w#+.-]/g, "") || "text"
18
+
19
+ const html = decoder.decode(
20
+ codeToHtml(token.text, { lang: isSupportedLanguage(language) ? language : "text", theme: OpenCodeTheme }),
21
+ )
22
+
23
+ return html.replace("<code>", `<code class="language-${language}">`) + "\n"
24
+ },
25
+ },
8
26
  }
9
27
 
10
28
  // `$$...$$` renders as display math anywhere in a line.
@@ -1 +0,0 @@
1
- export declare function registerOpenCodeTheme(): void;
@@ -1,2 +0,0 @@
1
- import type { ThemeRegistrationResolved } from "@pierre/diffs";
2
- export declare const OpenCodeTheme: ThemeRegistrationResolved;
@@ -1,2 +0,0 @@
1
- export { OpenCodeTheme } from "./marked-theme";
2
- export declare const useMarked: () => import("marked").Marked<string, string>, MarkedProvider: (props: import("solid-js").ParentProps<Record<string, any>>) => import("solid-js").JSX.Element;
@@ -1,10 +0,0 @@
1
- import { registerCustomTheme } from "@pierre/diffs"
2
- import { OpenCodeTheme } from "./marked-theme"
3
-
4
- let registered = false
5
-
6
- export function registerOpenCodeTheme() {
7
- if (registered) return
8
- registered = true
9
- registerCustomTheme("OpenCode", () => Promise.resolve(OpenCodeTheme))
10
- }
@@ -1,372 +0,0 @@
1
- import type { ThemeRegistrationResolved } from "@pierre/diffs"
2
-
3
- export const OpenCodeTheme = {
4
- name: "OpenCode",
5
- bg: "var(--color-background-stronger)",
6
- fg: "var(--text-base)",
7
- colors: {
8
- "editor.background": "var(--color-background-stronger)",
9
- "editor.foreground": "var(--text-base)",
10
- "gitDecoration.addedResourceForeground": "var(--syntax-diff-add)",
11
- "gitDecoration.deletedResourceForeground": "var(--syntax-diff-delete)",
12
- "gitDecoration.modifiedResourceForeground": "var(--syntax-diff-unknown)",
13
- // "gitDecoration.conflictingResourceForeground": "#ffca00",
14
- // "gitDecoration.modifiedResourceForeground": "#1a76d4",
15
- // "gitDecoration.untrackedResourceForeground": "#00cab1",
16
- // "gitDecoration.ignoredResourceForeground": "#84848A",
17
- // "terminal.titleForeground": "#adadb1",
18
- // "terminal.titleInactiveForeground": "#84848A",
19
- // "terminal.background": "#141415",
20
- // "terminal.foreground": "#adadb1",
21
- // "terminal.ansiBlack": "#141415",
22
- // "terminal.ansiRed": "#ff2e3f",
23
- // "terminal.ansiGreen": "#0dbe4e",
24
- // "terminal.ansiYellow": "#ffca00",
25
- // "terminal.ansiBlue": "#008cff",
26
- // "terminal.ansiMagenta": "#c635e4",
27
- // "terminal.ansiCyan": "#08c0ef",
28
- // "terminal.ansiWhite": "#c6c6c8",
29
- // "terminal.ansiBrightBlack": "#141415",
30
- // "terminal.ansiBrightRed": "#ff2e3f",
31
- // "terminal.ansiBrightGreen": "#0dbe4e",
32
- // "terminal.ansiBrightYellow": "#ffca00",
33
- // "terminal.ansiBrightBlue": "#008cff",
34
- // "terminal.ansiBrightMagenta": "#c635e4",
35
- // "terminal.ansiBrightCyan": "#08c0ef",
36
- // "terminal.ansiBrightWhite": "#c6c6c8",
37
- },
38
- tokenColors: [
39
- {
40
- scope: ["comment", "punctuation.definition.comment", "string.comment"],
41
- settings: {
42
- foreground: "var(--syntax-comment)",
43
- },
44
- },
45
- {
46
- scope: ["entity.other.attribute-name"],
47
- settings: {
48
- foreground: "var(--syntax-property)", // maybe attribute
49
- },
50
- },
51
- {
52
- scope: ["constant", "entity.name.constant", "variable.other.constant", "variable.language", "entity"],
53
- settings: {
54
- foreground: "var(--syntax-constant)",
55
- },
56
- },
57
- {
58
- scope: ["entity.name", "meta.export.default", "meta.definition.variable"],
59
- settings: {
60
- foreground: "var(--syntax-type)",
61
- },
62
- },
63
- {
64
- scope: ["meta.object.member"],
65
- settings: {
66
- foreground: "var(--syntax-primitive)",
67
- },
68
- },
69
- {
70
- scope: [
71
- "variable.parameter.function",
72
- "meta.jsx.children",
73
- "meta.block",
74
- "meta.tag.attributes",
75
- "entity.name.constant",
76
- "meta.embedded.expression",
77
- "meta.template.expression",
78
- "string.other.begin.yaml",
79
- "string.other.end.yaml",
80
- ],
81
- settings: {
82
- foreground: "var(--syntax-punctuation)",
83
- },
84
- },
85
- {
86
- scope: ["entity.name.function", "support.type.primitive"],
87
- settings: {
88
- foreground: "var(--syntax-primitive)",
89
- },
90
- },
91
- {
92
- scope: ["support.class.component"],
93
- settings: {
94
- foreground: "var(--syntax-type)",
95
- },
96
- },
97
- {
98
- scope: "keyword",
99
- settings: {
100
- foreground: "var(--syntax-keyword)",
101
- },
102
- },
103
- {
104
- scope: [
105
- "keyword.operator",
106
- "storage.type.function.arrow",
107
- "punctuation.separator.key-value.css",
108
- "entity.name.tag.yaml",
109
- "punctuation.separator.key-value.mapping.yaml",
110
- ],
111
- settings: {
112
- foreground: "var(--syntax-operator)",
113
- },
114
- },
115
- {
116
- scope: ["storage", "storage.type"],
117
- settings: {
118
- foreground: "var(--syntax-keyword)",
119
- },
120
- },
121
- {
122
- scope: ["storage.modifier.package", "storage.modifier.import", "storage.type.java"],
123
- settings: {
124
- foreground: "var(--syntax-primitive)",
125
- },
126
- },
127
- {
128
- scope: [
129
- "string",
130
- "punctuation.definition.string",
131
- "string punctuation.section.embedded source",
132
- "entity.name.tag",
133
- ],
134
- settings: {
135
- foreground: "var(--syntax-string)",
136
- },
137
- },
138
- {
139
- scope: "support",
140
- settings: {
141
- foreground: "var(--syntax-primitive)",
142
- },
143
- },
144
- {
145
- scope: ["support.type.object.module", "variable.other.object", "support.type.property-name.css"],
146
- settings: {
147
- foreground: "var(--syntax-object)",
148
- },
149
- },
150
- {
151
- scope: "meta.property-name",
152
- settings: {
153
- foreground: "var(--syntax-property)",
154
- },
155
- },
156
- {
157
- scope: "variable",
158
- settings: {
159
- foreground: "var(--syntax-variable)",
160
- },
161
- },
162
- {
163
- scope: "variable.other",
164
- settings: {
165
- foreground: "var(--syntax-variable)",
166
- },
167
- },
168
- {
169
- scope: [
170
- "invalid.broken",
171
- "invalid.illegal",
172
- "invalid.unimplemented",
173
- "invalid.deprecated",
174
- "message.error",
175
- "markup.deleted",
176
- "meta.diff.header.from-file",
177
- "punctuation.definition.deleted",
178
- "brackethighlighter.unmatched",
179
- "token.error-token",
180
- ],
181
- settings: {
182
- foreground: "var(--syntax-critical)",
183
- },
184
- },
185
- {
186
- scope: "carriage-return",
187
- settings: {
188
- foreground: "var(--syntax-keyword)",
189
- },
190
- },
191
- {
192
- scope: "string source",
193
- settings: {
194
- foreground: "var(--syntax-variable)",
195
- },
196
- },
197
- {
198
- scope: "string variable",
199
- settings: {
200
- foreground: "var(--syntax-constant)",
201
- },
202
- },
203
- {
204
- scope: [
205
- "source.regexp",
206
- "string.regexp",
207
- "string.regexp.character-class",
208
- "string.regexp constant.character.escape",
209
- "string.regexp source.ruby.embedded",
210
- "string.regexp string.regexp.arbitrary-repitition",
211
- "string.regexp constant.character.escape",
212
- ],
213
- settings: {
214
- foreground: "var(--syntax-regexp)",
215
- },
216
- },
217
- {
218
- scope: "support.constant",
219
- settings: {
220
- foreground: "var(--syntax-primitive)",
221
- },
222
- },
223
- {
224
- scope: "support.variable",
225
- settings: {
226
- foreground: "var(--syntax-variable)",
227
- },
228
- },
229
- {
230
- scope: "meta.module-reference",
231
- settings: {
232
- foreground: "var(--syntax-info)",
233
- },
234
- },
235
- {
236
- scope: "punctuation.definition.list.begin.markdown",
237
- settings: {
238
- foreground: "var(--syntax-punctuation)",
239
- },
240
- },
241
- {
242
- scope: ["markup.heading", "markup.heading entity.name"],
243
- settings: {
244
- fontStyle: "bold",
245
- foreground: "var(--syntax-info)",
246
- },
247
- },
248
- {
249
- scope: "markup.quote",
250
- settings: {
251
- foreground: "var(--syntax-info)",
252
- },
253
- },
254
- {
255
- scope: "markup.italic",
256
- settings: {
257
- fontStyle: "italic",
258
- // foreground: "",
259
- },
260
- },
261
- {
262
- scope: "markup.bold",
263
- settings: {
264
- fontStyle: "bold",
265
- foreground: "var(--text-strong)",
266
- },
267
- },
268
- {
269
- scope: [
270
- "markup.raw",
271
- "markup.inserted",
272
- "meta.diff.header.to-file",
273
- "punctuation.definition.inserted",
274
- "markup.changed",
275
- "punctuation.definition.changed",
276
- "markup.ignored",
277
- "markup.untracked",
278
- ],
279
- settings: {
280
- foreground: "var(--text-base)",
281
- },
282
- },
283
- {
284
- scope: "meta.diff.range",
285
- settings: {
286
- fontStyle: "bold",
287
- foreground: "var(--syntax-unknown)",
288
- },
289
- },
290
- {
291
- scope: "meta.diff.header",
292
- settings: {
293
- foreground: "var(--syntax-unknown)",
294
- },
295
- },
296
- {
297
- scope: "meta.separator",
298
- settings: {
299
- fontStyle: "bold",
300
- foreground: "var(--syntax-unknown)",
301
- },
302
- },
303
- {
304
- scope: "meta.output",
305
- settings: {
306
- foreground: "var(--syntax-unknown)",
307
- },
308
- },
309
- {
310
- scope: "meta.export.default",
311
- settings: {
312
- foreground: "var(--syntax-unknown)",
313
- },
314
- },
315
- {
316
- scope: [
317
- "brackethighlighter.tag",
318
- "brackethighlighter.curly",
319
- "brackethighlighter.round",
320
- "brackethighlighter.square",
321
- "brackethighlighter.angle",
322
- "brackethighlighter.quote",
323
- ],
324
- settings: {
325
- foreground: "var(--syntax-unknown)",
326
- },
327
- },
328
- {
329
- scope: ["constant.other.reference.link", "string.other.link"],
330
- settings: {
331
- fontStyle: "underline",
332
- foreground: "var(--syntax-unknown)",
333
- },
334
- },
335
- {
336
- scope: "token.info-token",
337
- settings: {
338
- foreground: "var(--syntax-info)",
339
- },
340
- },
341
- {
342
- scope: "token.warn-token",
343
- settings: {
344
- foreground: "var(--syntax-warning)",
345
- },
346
- },
347
- {
348
- scope: "token.debug-token",
349
- settings: {
350
- foreground: "var(--syntax-info)",
351
- },
352
- },
353
- ],
354
- semanticTokenColors: {
355
- comment: "var(--syntax-comment)",
356
- string: "var(--syntax-string)",
357
- number: "var(--syntax-constant)",
358
- regexp: "var(--syntax-regexp)",
359
- keyword: "var(--syntax-keyword)",
360
- variable: "var(--syntax-variable)",
361
- parameter: "var(--syntax-variable)",
362
- property: "var(--syntax-property)",
363
- function: "var(--syntax-primitive)",
364
- method: "var(--syntax-primitive)",
365
- type: "var(--syntax-type)",
366
- class: "var(--syntax-type)",
367
- namespace: "var(--syntax-type)",
368
- enumMember: "var(--syntax-primitive)",
369
- "variable.constant": "var(--syntax-constant)",
370
- "variable.defaultLibrary": "var(--syntax-unknown)",
371
- },
372
- } as unknown as ThemeRegistrationResolved
@@ -1,31 +0,0 @@
1
- import { getSharedHighlighter } from "@pierre/diffs"
2
- import { bundledLanguages, type BundledLanguage } from "shiki"
3
- import { createSimpleContext } from "./helper"
4
- import { createMarkdownParser } from "./marked-parser"
5
- import { registerOpenCodeTheme } from "./marked-theme-register"
6
-
7
- export { OpenCodeTheme } from "./marked-theme"
8
-
9
- registerOpenCodeTheme()
10
-
11
- export const { use: useMarked, provider: MarkedProvider } = createSimpleContext({
12
- name: "Marked",
13
- init: () =>
14
- createMarkdownParser(async (code, language) => {
15
- const highlighter = await getSharedHighlighter({
16
- themes: ["OpenCode"],
17
- langs: [],
18
- preferredHighlighter: "shiki-wasm",
19
- })
20
-
21
- const name = language in bundledLanguages ? language : "text"
22
-
23
- if (!highlighter.getLoadedLanguages().includes(name)) await highlighter.loadLanguage(name as BundledLanguage)
24
-
25
- return highlighter.codeToHtml(code, {
26
- lang: name,
27
- theme: "OpenCode",
28
- tabindex: false,
29
- })
30
- }),
31
- })