@pyreon/code 0.10.0 → 0.11.0

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 (62) hide show
  1. package/lib/analysis/index.js.html +1 -1
  2. package/lib/{dist-qTrOe7xY.js → dist-5FA-omYL.js} +4 -4
  3. package/lib/dist-5FA-omYL.js.map +1 -0
  4. package/lib/{dist-CTPisNZp.js → dist-BisvZuec.js} +4 -4
  5. package/lib/dist-BisvZuec.js.map +1 -0
  6. package/lib/{dist-BAfzu5eu.js → dist-BrE8YJpx.js} +6 -6
  7. package/lib/dist-BrE8YJpx.js.map +1 -0
  8. package/lib/{dist-Dej_yf3k.js → dist-BxzbGcJt.js} +4 -4
  9. package/lib/dist-BxzbGcJt.js.map +1 -0
  10. package/lib/{dist-Ce2tvOxv.js → dist-CXUY-Nzh.js} +4 -4
  11. package/lib/dist-CXUY-Nzh.js.map +1 -0
  12. package/lib/{dist-B5vB-rif.js → dist-CfapY6Xm.js} +4 -4
  13. package/lib/dist-CfapY6Xm.js.map +1 -0
  14. package/lib/{dist-BLlV_D16.js → dist-CkzBqhDP.js} +30 -30
  15. package/lib/dist-CkzBqhDP.js.map +1 -0
  16. package/lib/{dist-BZtTlC1J.js → dist-DGt-lmGy.js} +3 -3
  17. package/lib/dist-DGt-lmGy.js.map +1 -0
  18. package/lib/{dist-DUNx9ldu.js → dist-DqTrMnaP.js} +4 -4
  19. package/lib/dist-DqTrMnaP.js.map +1 -0
  20. package/lib/{dist-CttF0OTv.js → dist-DwKx52QE.js} +5 -5
  21. package/lib/dist-DwKx52QE.js.map +1 -0
  22. package/lib/{dist-BNmKLTu8.js → dist-Oei2Buyd.js} +5 -5
  23. package/lib/dist-Oei2Buyd.js.map +1 -0
  24. package/lib/{dist-DS2tluW9.js → dist-TrbJHyZy.js} +4 -4
  25. package/lib/dist-TrbJHyZy.js.map +1 -0
  26. package/lib/{dist-DshStUxU.js → dist-jF2joTkO.js} +4 -4
  27. package/lib/dist-jF2joTkO.js.map +1 -0
  28. package/lib/{dist-CTDqGIAf.js → dist-pDxtX_z4.js} +4 -4
  29. package/lib/dist-pDxtX_z4.js.map +1 -0
  30. package/lib/{dist-v09vikKr.js → dist-sGMMCnKq.js} +5 -5
  31. package/lib/dist-sGMMCnKq.js.map +1 -0
  32. package/lib/index.js +20 -20
  33. package/lib/index.js.map +1 -1
  34. package/lib/types/index.d.ts +4 -4
  35. package/lib/types/index.d.ts.map +1 -1
  36. package/package.json +14 -7
  37. package/src/components/code-editor.tsx +4 -8
  38. package/src/components/diff-editor.tsx +16 -22
  39. package/src/components/tabbed-editor.tsx +8 -11
  40. package/src/editor.ts +44 -67
  41. package/src/index.ts +8 -8
  42. package/src/languages.ts +20 -28
  43. package/src/minimap.ts +21 -31
  44. package/src/tabbed-editor.ts +24 -38
  45. package/src/tests/code.test.ts +193 -199
  46. package/src/themes.ts +48 -48
  47. package/src/types.ts +27 -27
  48. package/lib/dist-B5vB-rif.js.map +0 -1
  49. package/lib/dist-BAfzu5eu.js.map +0 -1
  50. package/lib/dist-BLlV_D16.js.map +0 -1
  51. package/lib/dist-BNmKLTu8.js.map +0 -1
  52. package/lib/dist-BZtTlC1J.js.map +0 -1
  53. package/lib/dist-CTDqGIAf.js.map +0 -1
  54. package/lib/dist-CTPisNZp.js.map +0 -1
  55. package/lib/dist-Ce2tvOxv.js.map +0 -1
  56. package/lib/dist-CttF0OTv.js.map +0 -1
  57. package/lib/dist-DS2tluW9.js.map +0 -1
  58. package/lib/dist-DUNx9ldu.js.map +0 -1
  59. package/lib/dist-Dej_yf3k.js.map +0 -1
  60. package/lib/dist-DshStUxU.js.map +0 -1
  61. package/lib/dist-qTrOe7xY.js.map +0 -1
  62. package/lib/dist-v09vikKr.js.map +0 -1
@@ -1,45 +1,45 @@
1
- import { effect } from '@pyreon/reactivity'
2
- import { describe, expect, it } from 'vitest'
3
- import { createEditor } from '../editor'
4
- import { getAvailableLanguages } from '../languages'
5
- import { createTabbedEditor } from '../tabbed-editor'
6
-
7
- describe('createEditor', () => {
8
- describe('initialization', () => {
9
- it('creates with default values', () => {
1
+ import { effect } from "@pyreon/reactivity"
2
+ import { describe, expect, it } from "vitest"
3
+ import { createEditor } from "../editor"
4
+ import { getAvailableLanguages } from "../languages"
5
+ import { createTabbedEditor } from "../tabbed-editor"
6
+
7
+ describe("createEditor", () => {
8
+ describe("initialization", () => {
9
+ it("creates with default values", () => {
10
10
  const editor = createEditor()
11
- expect(editor.value()).toBe('')
12
- expect(editor.language()).toBe('plain')
11
+ expect(editor.value()).toBe("")
12
+ expect(editor.language()).toBe("plain")
13
13
  expect(editor.readOnly()).toBe(false)
14
14
  expect(editor.focused()).toBe(false)
15
15
  expect(editor.view()).toBeNull()
16
16
  })
17
17
 
18
- it('creates with initial value', () => {
19
- const editor = createEditor({ value: 'hello world' })
20
- expect(editor.value()).toBe('hello world')
18
+ it("creates with initial value", () => {
19
+ const editor = createEditor({ value: "hello world" })
20
+ expect(editor.value()).toBe("hello world")
21
21
  })
22
22
 
23
- it('creates with language', () => {
24
- const editor = createEditor({ language: 'typescript' })
25
- expect(editor.language()).toBe('typescript')
23
+ it("creates with language", () => {
24
+ const editor = createEditor({ language: "typescript" })
25
+ expect(editor.language()).toBe("typescript")
26
26
  })
27
27
 
28
- it('creates with theme', () => {
29
- const editor = createEditor({ theme: 'dark' })
30
- expect(editor.theme()).toBe('dark')
28
+ it("creates with theme", () => {
29
+ const editor = createEditor({ theme: "dark" })
30
+ expect(editor.theme()).toBe("dark")
31
31
  })
32
32
 
33
- it('creates with readOnly', () => {
33
+ it("creates with readOnly", () => {
34
34
  const editor = createEditor({ readOnly: true })
35
35
  expect(editor.readOnly()).toBe(true)
36
36
  })
37
37
 
38
- it('stores config', () => {
38
+ it("stores config", () => {
39
39
  const config = {
40
- value: 'test',
41
- language: 'json' as const,
42
- theme: 'dark' as const,
40
+ value: "test",
41
+ language: "json" as const,
42
+ theme: "dark" as const,
43
43
  lineNumbers: true,
44
44
  tabSize: 4,
45
45
  }
@@ -48,124 +48,124 @@ describe('createEditor', () => {
48
48
  })
49
49
  })
50
50
 
51
- describe('signal reactivity', () => {
52
- it('value is a writable signal', () => {
53
- const editor = createEditor({ value: 'initial' })
54
- expect(editor.value()).toBe('initial')
51
+ describe("signal reactivity", () => {
52
+ it("value is a writable signal", () => {
53
+ const editor = createEditor({ value: "initial" })
54
+ expect(editor.value()).toBe("initial")
55
55
 
56
- editor.value.set('updated')
57
- expect(editor.value()).toBe('updated')
56
+ editor.value.set("updated")
57
+ expect(editor.value()).toBe("updated")
58
58
  })
59
59
 
60
- it('language is a writable signal', () => {
61
- const editor = createEditor({ language: 'javascript' })
62
- editor.language.set('python')
63
- expect(editor.language()).toBe('python')
60
+ it("language is a writable signal", () => {
61
+ const editor = createEditor({ language: "javascript" })
62
+ editor.language.set("python")
63
+ expect(editor.language()).toBe("python")
64
64
  })
65
65
 
66
- it('theme is a writable signal', () => {
67
- const editor = createEditor({ theme: 'light' })
68
- editor.theme.set('dark')
69
- expect(editor.theme()).toBe('dark')
66
+ it("theme is a writable signal", () => {
67
+ const editor = createEditor({ theme: "light" })
68
+ editor.theme.set("dark")
69
+ expect(editor.theme()).toBe("dark")
70
70
  })
71
71
 
72
- it('readOnly is a writable signal', () => {
72
+ it("readOnly is a writable signal", () => {
73
73
  const editor = createEditor({ readOnly: false })
74
74
  editor.readOnly.set(true)
75
75
  expect(editor.readOnly()).toBe(true)
76
76
  })
77
77
 
78
- it('value is reactive in effects', () => {
79
- const editor = createEditor({ value: 'a' })
78
+ it("value is reactive in effects", () => {
79
+ const editor = createEditor({ value: "a" })
80
80
  const values: string[] = []
81
81
 
82
82
  effect(() => {
83
83
  values.push(editor.value())
84
84
  })
85
85
 
86
- editor.value.set('b')
87
- editor.value.set('c')
86
+ editor.value.set("b")
87
+ editor.value.set("c")
88
88
 
89
- expect(values).toEqual(['a', 'b', 'c'])
89
+ expect(values).toEqual(["a", "b", "c"])
90
90
  })
91
91
  })
92
92
 
93
- describe('computed properties (before mount)', () => {
94
- it('cursor returns default before mount', () => {
93
+ describe("computed properties (before mount)", () => {
94
+ it("cursor returns default before mount", () => {
95
95
  const editor = createEditor()
96
96
  expect(editor.cursor()).toEqual({ line: 1, col: 1 })
97
97
  })
98
98
 
99
- it('selection returns default before mount', () => {
99
+ it("selection returns default before mount", () => {
100
100
  const editor = createEditor()
101
- expect(editor.selection()).toEqual({ from: 0, to: 0, text: '' })
101
+ expect(editor.selection()).toEqual({ from: 0, to: 0, text: "" })
102
102
  })
103
103
 
104
- it('lineCount returns initial line count', () => {
105
- const editor = createEditor({ value: 'line1\nline2\nline3' })
104
+ it("lineCount returns initial line count", () => {
105
+ const editor = createEditor({ value: "line1\nline2\nline3" })
106
106
  expect(editor.lineCount()).toBe(3)
107
107
  })
108
108
 
109
- it('lineCount for single line', () => {
110
- const editor = createEditor({ value: 'hello' })
109
+ it("lineCount for single line", () => {
110
+ const editor = createEditor({ value: "hello" })
111
111
  expect(editor.lineCount()).toBe(1)
112
112
  })
113
113
 
114
- it('lineCount for empty', () => {
115
- const editor = createEditor({ value: '' })
114
+ it("lineCount for empty", () => {
115
+ const editor = createEditor({ value: "" })
116
116
  expect(editor.lineCount()).toBe(1)
117
117
  })
118
118
  })
119
119
 
120
- describe('actions (before mount)', () => {
121
- it('focus does not throw before mount', () => {
120
+ describe("actions (before mount)", () => {
121
+ it("focus does not throw before mount", () => {
122
122
  const editor = createEditor()
123
123
  expect(() => editor.focus()).not.toThrow()
124
124
  })
125
125
 
126
- it('insert does not throw before mount', () => {
126
+ it("insert does not throw before mount", () => {
127
127
  const editor = createEditor()
128
- expect(() => editor.insert('text')).not.toThrow()
128
+ expect(() => editor.insert("text")).not.toThrow()
129
129
  })
130
130
 
131
- it('replaceSelection does not throw before mount', () => {
131
+ it("replaceSelection does not throw before mount", () => {
132
132
  const editor = createEditor()
133
- expect(() => editor.replaceSelection('text')).not.toThrow()
133
+ expect(() => editor.replaceSelection("text")).not.toThrow()
134
134
  })
135
135
 
136
- it('select does not throw before mount', () => {
136
+ it("select does not throw before mount", () => {
137
137
  const editor = createEditor()
138
138
  expect(() => editor.select(0, 5)).not.toThrow()
139
139
  })
140
140
 
141
- it('selectAll does not throw before mount', () => {
141
+ it("selectAll does not throw before mount", () => {
142
142
  const editor = createEditor()
143
143
  expect(() => editor.selectAll()).not.toThrow()
144
144
  })
145
145
 
146
- it('goToLine does not throw before mount', () => {
146
+ it("goToLine does not throw before mount", () => {
147
147
  const editor = createEditor()
148
148
  expect(() => editor.goToLine(5)).not.toThrow()
149
149
  })
150
150
 
151
- it('undo does not throw before mount', () => {
151
+ it("undo does not throw before mount", () => {
152
152
  const editor = createEditor()
153
153
  expect(() => editor.undo()).not.toThrow()
154
154
  })
155
155
 
156
- it('redo does not throw before mount', () => {
156
+ it("redo does not throw before mount", () => {
157
157
  const editor = createEditor()
158
158
  expect(() => editor.redo()).not.toThrow()
159
159
  })
160
160
 
161
- it('dispose does not throw before mount', () => {
161
+ it("dispose does not throw before mount", () => {
162
162
  const editor = createEditor()
163
163
  expect(() => editor.dispose()).not.toThrow()
164
164
  })
165
165
  })
166
166
 
167
- describe('onChange callback', () => {
168
- it('config stores onChange', () => {
167
+ describe("onChange callback", () => {
168
+ it("config stores onChange", () => {
169
169
  const onChange = () => {
170
170
  /* noop */
171
171
  }
@@ -174,92 +174,86 @@ describe('createEditor', () => {
174
174
  })
175
175
  })
176
176
 
177
- describe('new actions (before mount)', () => {
178
- it('setDiagnostics does not throw before mount', () => {
177
+ describe("new actions (before mount)", () => {
178
+ it("setDiagnostics does not throw before mount", () => {
179
179
  const editor = createEditor()
180
180
  expect(() =>
181
- editor.setDiagnostics([
182
- { from: 0, to: 5, severity: 'error', message: 'test' },
183
- ]),
181
+ editor.setDiagnostics([{ from: 0, to: 5, severity: "error", message: "test" }]),
184
182
  ).not.toThrow()
185
183
  })
186
184
 
187
- it('clearDiagnostics does not throw before mount', () => {
185
+ it("clearDiagnostics does not throw before mount", () => {
188
186
  const editor = createEditor()
189
187
  expect(() => editor.clearDiagnostics()).not.toThrow()
190
188
  })
191
189
 
192
- it('highlightLine does not throw before mount', () => {
190
+ it("highlightLine does not throw before mount", () => {
193
191
  const editor = createEditor()
194
- expect(() => editor.highlightLine(1, 'error-line')).not.toThrow()
192
+ expect(() => editor.highlightLine(1, "error-line")).not.toThrow()
195
193
  })
196
194
 
197
- it('clearLineHighlights does not throw before mount', () => {
195
+ it("clearLineHighlights does not throw before mount", () => {
198
196
  const editor = createEditor()
199
197
  expect(() => editor.clearLineHighlights()).not.toThrow()
200
198
  })
201
199
 
202
- it('setGutterMarker does not throw before mount', () => {
200
+ it("setGutterMarker does not throw before mount", () => {
203
201
  const editor = createEditor()
204
- expect(() =>
205
- editor.setGutterMarker(1, { text: '🔴', title: 'Breakpoint' }),
206
- ).not.toThrow()
202
+ expect(() => editor.setGutterMarker(1, { text: "🔴", title: "Breakpoint" })).not.toThrow()
207
203
  })
208
204
 
209
- it('clearGutterMarkers does not throw before mount', () => {
205
+ it("clearGutterMarkers does not throw before mount", () => {
210
206
  const editor = createEditor()
211
207
  expect(() => editor.clearGutterMarkers()).not.toThrow()
212
208
  })
213
209
 
214
- it('addKeybinding does not throw before mount', () => {
210
+ it("addKeybinding does not throw before mount", () => {
215
211
  const editor = createEditor()
216
- expect(() =>
217
- editor.addKeybinding('Ctrl-Shift-L', () => true),
218
- ).not.toThrow()
212
+ expect(() => editor.addKeybinding("Ctrl-Shift-L", () => true)).not.toThrow()
219
213
  })
220
214
 
221
- it('getLine returns empty string before mount', () => {
215
+ it("getLine returns empty string before mount", () => {
222
216
  const editor = createEditor()
223
- expect(editor.getLine(1)).toBe('')
217
+ expect(editor.getLine(1)).toBe("")
224
218
  })
225
219
 
226
- it('getWordAtCursor returns empty string before mount', () => {
220
+ it("getWordAtCursor returns empty string before mount", () => {
227
221
  const editor = createEditor()
228
- expect(editor.getWordAtCursor()).toBe('')
222
+ expect(editor.getWordAtCursor()).toBe("")
229
223
  })
230
224
 
231
- it('scrollTo does not throw before mount', () => {
225
+ it("scrollTo does not throw before mount", () => {
232
226
  const editor = createEditor()
233
227
  expect(() => editor.scrollTo(0)).not.toThrow()
234
228
  })
235
229
  })
236
230
 
237
- describe('config options', () => {
238
- it('highlightIndentGuides defaults to true', () => {
231
+ describe("config options", () => {
232
+ it("highlightIndentGuides defaults to true", () => {
239
233
  const editor = createEditor()
240
234
  expect(editor.config.highlightIndentGuides).toBeUndefined() // uses default
241
235
  })
242
236
 
243
- it('vim mode can be enabled', () => {
237
+ it("vim mode can be enabled", () => {
244
238
  const editor = createEditor({ vim: true })
245
239
  expect(editor.config.vim).toBe(true)
246
240
  })
247
241
 
248
- it('emacs mode can be enabled', () => {
242
+ it("emacs mode can be enabled", () => {
249
243
  const editor = createEditor({ emacs: true })
250
244
  expect(editor.config.emacs).toBe(true)
251
245
  })
252
246
 
253
- it('minimap can be enabled', () => {
247
+ it("minimap can be enabled", () => {
254
248
  const editor = createEditor({ minimap: true })
255
249
  expect(editor.config.minimap).toBe(true)
256
250
  })
257
251
 
258
- it('all config options are stored', () => {
252
+ it("all config options are stored", () => {
259
253
  const editor = createEditor({
260
- value: 'test',
261
- language: 'typescript',
262
- theme: 'dark',
254
+ value: "test",
255
+ language: "typescript",
256
+ theme: "dark",
263
257
  lineNumbers: false,
264
258
  readOnly: true,
265
259
  foldGutter: false,
@@ -270,236 +264,236 @@ describe('createEditor', () => {
270
264
  highlightIndentGuides: false,
271
265
  tabSize: 4,
272
266
  lineWrapping: true,
273
- placeholder: 'Type here...',
267
+ placeholder: "Type here...",
274
268
  })
275
269
  expect(editor.config.tabSize).toBe(4)
276
270
  expect(editor.config.lineWrapping).toBe(true)
277
- expect(editor.config.placeholder).toBe('Type here...')
271
+ expect(editor.config.placeholder).toBe("Type here...")
278
272
  })
279
273
  })
280
274
  })
281
275
 
282
- describe('createTabbedEditor', () => {
283
- it('creates with initial tabs', () => {
276
+ describe("createTabbedEditor", () => {
277
+ it("creates with initial tabs", () => {
284
278
  const te = createTabbedEditor({
285
279
  tabs: [
286
- { name: 'index.ts', language: 'typescript', value: 'const x = 1' },
287
- { name: 'style.css', language: 'css', value: '.app {}' },
280
+ { name: "index.ts", language: "typescript", value: "const x = 1" },
281
+ { name: "style.css", language: "css", value: ".app {}" },
288
282
  ],
289
283
  })
290
284
  expect(te.tabs()).toHaveLength(2)
291
- expect(te.activeTabId()).toBe('index.ts')
292
- expect(te.activeTab()?.name).toBe('index.ts')
293
- expect(te.editor.value()).toBe('const x = 1')
285
+ expect(te.activeTabId()).toBe("index.ts")
286
+ expect(te.activeTab()?.name).toBe("index.ts")
287
+ expect(te.editor.value()).toBe("const x = 1")
294
288
  })
295
289
 
296
- it('creates with no tabs', () => {
290
+ it("creates with no tabs", () => {
297
291
  const te = createTabbedEditor()
298
292
  expect(te.tabs()).toHaveLength(0)
299
- expect(te.activeTabId()).toBe('')
293
+ expect(te.activeTabId()).toBe("")
300
294
  expect(te.activeTab()).toBeNull()
301
295
  })
302
296
 
303
- it('switchTab changes active tab and editor content', () => {
297
+ it("switchTab changes active tab and editor content", () => {
304
298
  const te = createTabbedEditor({
305
299
  tabs: [
306
- { name: 'a.ts', value: 'aaa' },
307
- { name: 'b.ts', value: 'bbb' },
300
+ { name: "a.ts", value: "aaa" },
301
+ { name: "b.ts", value: "bbb" },
308
302
  ],
309
303
  })
310
- expect(te.editor.value()).toBe('aaa')
304
+ expect(te.editor.value()).toBe("aaa")
311
305
 
312
- te.switchTab('b.ts')
313
- expect(te.activeTabId()).toBe('b.ts')
314
- expect(te.editor.value()).toBe('bbb')
306
+ te.switchTab("b.ts")
307
+ expect(te.activeTabId()).toBe("b.ts")
308
+ expect(te.editor.value()).toBe("bbb")
315
309
 
316
- te.switchTab('a.ts')
317
- expect(te.editor.value()).toBe('aaa')
310
+ te.switchTab("a.ts")
311
+ expect(te.editor.value()).toBe("aaa")
318
312
  })
319
313
 
320
- it('openTab adds and switches to new tab', () => {
314
+ it("openTab adds and switches to new tab", () => {
321
315
  const te = createTabbedEditor({
322
- tabs: [{ name: 'a.ts', value: 'aaa' }],
316
+ tabs: [{ name: "a.ts", value: "aaa" }],
323
317
  })
324
318
 
325
- te.openTab({ name: 'b.ts', language: 'typescript', value: 'bbb' })
319
+ te.openTab({ name: "b.ts", language: "typescript", value: "bbb" })
326
320
  expect(te.tabs()).toHaveLength(2)
327
- expect(te.activeTabId()).toBe('b.ts')
328
- expect(te.editor.value()).toBe('bbb')
321
+ expect(te.activeTabId()).toBe("b.ts")
322
+ expect(te.editor.value()).toBe("bbb")
329
323
  })
330
324
 
331
- it('openTab switches to existing tab', () => {
325
+ it("openTab switches to existing tab", () => {
332
326
  const te = createTabbedEditor({
333
327
  tabs: [
334
- { name: 'a.ts', value: 'aaa' },
335
- { name: 'b.ts', value: 'bbb' },
328
+ { name: "a.ts", value: "aaa" },
329
+ { name: "b.ts", value: "bbb" },
336
330
  ],
337
331
  })
338
332
 
339
- te.openTab({ name: 'b.ts', value: 'bbb' })
333
+ te.openTab({ name: "b.ts", value: "bbb" })
340
334
  expect(te.tabs()).toHaveLength(2) // not duplicated
341
- expect(te.activeTabId()).toBe('b.ts')
335
+ expect(te.activeTabId()).toBe("b.ts")
342
336
  })
343
337
 
344
- it('closeTab removes tab', () => {
338
+ it("closeTab removes tab", () => {
345
339
  const te = createTabbedEditor({
346
340
  tabs: [
347
- { name: 'a.ts', value: 'aaa' },
348
- { name: 'b.ts', value: 'bbb' },
341
+ { name: "a.ts", value: "aaa" },
342
+ { name: "b.ts", value: "bbb" },
349
343
  ],
350
344
  })
351
345
 
352
- te.closeTab('b.ts')
346
+ te.closeTab("b.ts")
353
347
  expect(te.tabs()).toHaveLength(1)
354
- expect(te.tabs()[0]!.name).toBe('a.ts')
348
+ expect(te.tabs()[0]!.name).toBe("a.ts")
355
349
  })
356
350
 
357
- it('closeTab switches to adjacent when closing active', () => {
351
+ it("closeTab switches to adjacent when closing active", () => {
358
352
  const te = createTabbedEditor({
359
353
  tabs: [
360
- { name: 'a.ts', value: 'aaa' },
361
- { name: 'b.ts', value: 'bbb' },
362
- { name: 'c.ts', value: 'ccc' },
354
+ { name: "a.ts", value: "aaa" },
355
+ { name: "b.ts", value: "bbb" },
356
+ { name: "c.ts", value: "ccc" },
363
357
  ],
364
358
  })
365
359
 
366
- te.switchTab('b.ts')
367
- te.closeTab('b.ts')
360
+ te.switchTab("b.ts")
361
+ te.closeTab("b.ts")
368
362
  // Should switch to c.ts (next) or a.ts
369
- expect(te.activeTabId()).not.toBe('b.ts')
363
+ expect(te.activeTabId()).not.toBe("b.ts")
370
364
  expect(te.tabs()).toHaveLength(2)
371
365
  })
372
366
 
373
- it('closeTab respects closable: false', () => {
367
+ it("closeTab respects closable: false", () => {
374
368
  const te = createTabbedEditor({
375
- tabs: [{ name: 'main.ts', value: 'main', closable: false }],
369
+ tabs: [{ name: "main.ts", value: "main", closable: false }],
376
370
  })
377
371
 
378
- te.closeTab('main.ts')
372
+ te.closeTab("main.ts")
379
373
  expect(te.tabs()).toHaveLength(1) // not closed
380
374
  })
381
375
 
382
- it('renameTab changes tab name', () => {
376
+ it("renameTab changes tab name", () => {
383
377
  const te = createTabbedEditor({
384
- tabs: [{ name: 'old.ts', value: '' }],
378
+ tabs: [{ name: "old.ts", value: "" }],
385
379
  })
386
380
 
387
- te.renameTab('old.ts', 'new.ts')
388
- expect(te.tabs()[0]!.name).toBe('new.ts')
381
+ te.renameTab("old.ts", "new.ts")
382
+ expect(te.tabs()[0]!.name).toBe("new.ts")
389
383
  })
390
384
 
391
- it('setModified marks tab', () => {
385
+ it("setModified marks tab", () => {
392
386
  const te = createTabbedEditor({
393
- tabs: [{ name: 'a.ts', value: '' }],
387
+ tabs: [{ name: "a.ts", value: "" }],
394
388
  })
395
389
 
396
- te.setModified('a.ts', true)
390
+ te.setModified("a.ts", true)
397
391
  expect(te.tabs()[0]!.modified).toBe(true)
398
392
 
399
- te.setModified('a.ts', false)
393
+ te.setModified("a.ts", false)
400
394
  expect(te.tabs()[0]!.modified).toBe(false)
401
395
  })
402
396
 
403
- it('moveTab reorders tabs', () => {
397
+ it("moveTab reorders tabs", () => {
404
398
  const te = createTabbedEditor({
405
399
  tabs: [
406
- { name: 'a.ts', value: '' },
407
- { name: 'b.ts', value: '' },
408
- { name: 'c.ts', value: '' },
400
+ { name: "a.ts", value: "" },
401
+ { name: "b.ts", value: "" },
402
+ { name: "c.ts", value: "" },
409
403
  ],
410
404
  })
411
405
 
412
406
  te.moveTab(0, 2)
413
- expect(te.tabs().map((t: any) => t.name)).toEqual(['b.ts', 'c.ts', 'a.ts'])
407
+ expect(te.tabs().map((t: any) => t.name)).toEqual(["b.ts", "c.ts", "a.ts"])
414
408
  })
415
409
 
416
- it('getTab returns tab by id', () => {
410
+ it("getTab returns tab by id", () => {
417
411
  const te = createTabbedEditor({
418
- tabs: [{ name: 'a.ts', value: 'content' }],
412
+ tabs: [{ name: "a.ts", value: "content" }],
419
413
  })
420
414
 
421
- expect(te.getTab('a.ts')?.value).toBe('content')
422
- expect(te.getTab('missing')).toBeUndefined()
415
+ expect(te.getTab("a.ts")?.value).toBe("content")
416
+ expect(te.getTab("missing")).toBeUndefined()
423
417
  })
424
418
 
425
- it('closeAll closes all closable tabs', () => {
419
+ it("closeAll closes all closable tabs", () => {
426
420
  const te = createTabbedEditor({
427
421
  tabs: [
428
- { name: 'a.ts', value: '', closable: false },
429
- { name: 'b.ts', value: '' },
430
- { name: 'c.ts', value: '' },
422
+ { name: "a.ts", value: "", closable: false },
423
+ { name: "b.ts", value: "" },
424
+ { name: "c.ts", value: "" },
431
425
  ],
432
426
  })
433
427
 
434
428
  te.closeAll()
435
429
  expect(te.tabs()).toHaveLength(1)
436
- expect(te.tabs()[0]!.name).toBe('a.ts')
430
+ expect(te.tabs()[0]!.name).toBe("a.ts")
437
431
  })
438
432
 
439
- it('closeOthers closes all except specified', () => {
433
+ it("closeOthers closes all except specified", () => {
440
434
  const te = createTabbedEditor({
441
435
  tabs: [
442
- { name: 'a.ts', value: '' },
443
- { name: 'b.ts', value: '' },
444
- { name: 'c.ts', value: '' },
436
+ { name: "a.ts", value: "" },
437
+ { name: "b.ts", value: "" },
438
+ { name: "c.ts", value: "" },
445
439
  ],
446
440
  })
447
441
 
448
- te.closeOthers('b.ts')
442
+ te.closeOthers("b.ts")
449
443
  expect(te.tabs()).toHaveLength(1)
450
- expect(te.tabs()[0]!.name).toBe('b.ts')
444
+ expect(te.tabs()[0]!.name).toBe("b.ts")
451
445
  })
452
446
 
453
- it('preserves content when switching tabs', () => {
447
+ it("preserves content when switching tabs", () => {
454
448
  const te = createTabbedEditor({
455
449
  tabs: [
456
- { name: 'a.ts', value: 'original-a' },
457
- { name: 'b.ts', value: 'original-b' },
450
+ { name: "a.ts", value: "original-a" },
451
+ { name: "b.ts", value: "original-b" },
458
452
  ],
459
453
  })
460
454
 
461
455
  // Modify a.ts via signal
462
- te.editor.value.set('modified-a')
456
+ te.editor.value.set("modified-a")
463
457
 
464
458
  // Switch to b.ts
465
- te.switchTab('b.ts')
466
- expect(te.editor.value()).toBe('original-b')
459
+ te.switchTab("b.ts")
460
+ expect(te.editor.value()).toBe("original-b")
467
461
 
468
462
  // Switch back — should have the modified content
469
- te.switchTab('a.ts')
470
- expect(te.editor.value()).toBe('modified-a')
463
+ te.switchTab("a.ts")
464
+ expect(te.editor.value()).toBe("modified-a")
471
465
  })
472
466
 
473
- it('dispose cleans up', () => {
467
+ it("dispose cleans up", () => {
474
468
  const te = createTabbedEditor({
475
- tabs: [{ name: 'a.ts', value: '' }],
469
+ tabs: [{ name: "a.ts", value: "" }],
476
470
  })
477
471
  expect(() => te.dispose()).not.toThrow()
478
472
  })
479
473
 
480
- it('close last tab clears editor', () => {
474
+ it("close last tab clears editor", () => {
481
475
  const te = createTabbedEditor({
482
- tabs: [{ name: 'a.ts', value: 'content' }],
476
+ tabs: [{ name: "a.ts", value: "content" }],
483
477
  })
484
478
 
485
- te.closeTab('a.ts')
479
+ te.closeTab("a.ts")
486
480
  expect(te.tabs()).toHaveLength(0)
487
- expect(te.activeTabId()).toBe('')
488
- expect(te.editor.value()).toBe('')
481
+ expect(te.activeTabId()).toBe("")
482
+ expect(te.editor.value()).toBe("")
489
483
  })
490
484
  })
491
485
 
492
- describe('getAvailableLanguages', () => {
493
- it('returns all supported languages', () => {
486
+ describe("getAvailableLanguages", () => {
487
+ it("returns all supported languages", () => {
494
488
  const langs = getAvailableLanguages()
495
- expect(langs).toContain('javascript')
496
- expect(langs).toContain('typescript')
497
- expect(langs).toContain('html')
498
- expect(langs).toContain('css')
499
- expect(langs).toContain('json')
500
- expect(langs).toContain('python')
501
- expect(langs).toContain('markdown')
502
- expect(langs).toContain('plain')
489
+ expect(langs).toContain("javascript")
490
+ expect(langs).toContain("typescript")
491
+ expect(langs).toContain("html")
492
+ expect(langs).toContain("css")
493
+ expect(langs).toContain("json")
494
+ expect(langs).toContain("python")
495
+ expect(langs).toContain("markdown")
496
+ expect(langs).toContain("plain")
503
497
  expect(langs.length).toBeGreaterThanOrEqual(15)
504
498
  })
505
499
  })