@pyreon/code 0.10.0 → 0.11.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.
- package/lib/analysis/index.js.html +1 -1
- package/lib/{dist-qTrOe7xY.js → dist-5FA-omYL.js} +4 -4
- package/lib/dist-5FA-omYL.js.map +1 -0
- package/lib/{dist-CTPisNZp.js → dist-BisvZuec.js} +4 -4
- package/lib/dist-BisvZuec.js.map +1 -0
- package/lib/{dist-BAfzu5eu.js → dist-BrE8YJpx.js} +6 -6
- package/lib/dist-BrE8YJpx.js.map +1 -0
- package/lib/{dist-Dej_yf3k.js → dist-BxzbGcJt.js} +4 -4
- package/lib/dist-BxzbGcJt.js.map +1 -0
- package/lib/{dist-Ce2tvOxv.js → dist-CXUY-Nzh.js} +4 -4
- package/lib/dist-CXUY-Nzh.js.map +1 -0
- package/lib/{dist-B5vB-rif.js → dist-CfapY6Xm.js} +4 -4
- package/lib/dist-CfapY6Xm.js.map +1 -0
- package/lib/{dist-BLlV_D16.js → dist-CkzBqhDP.js} +30 -30
- package/lib/dist-CkzBqhDP.js.map +1 -0
- package/lib/{dist-BZtTlC1J.js → dist-DGt-lmGy.js} +3 -3
- package/lib/dist-DGt-lmGy.js.map +1 -0
- package/lib/{dist-DUNx9ldu.js → dist-DqTrMnaP.js} +4 -4
- package/lib/dist-DqTrMnaP.js.map +1 -0
- package/lib/{dist-CttF0OTv.js → dist-DwKx52QE.js} +5 -5
- package/lib/dist-DwKx52QE.js.map +1 -0
- package/lib/{dist-BNmKLTu8.js → dist-Oei2Buyd.js} +5 -5
- package/lib/dist-Oei2Buyd.js.map +1 -0
- package/lib/{dist-DS2tluW9.js → dist-TrbJHyZy.js} +4 -4
- package/lib/dist-TrbJHyZy.js.map +1 -0
- package/lib/{dist-DshStUxU.js → dist-jF2joTkO.js} +4 -4
- package/lib/dist-jF2joTkO.js.map +1 -0
- package/lib/{dist-CTDqGIAf.js → dist-pDxtX_z4.js} +4 -4
- package/lib/dist-pDxtX_z4.js.map +1 -0
- package/lib/{dist-v09vikKr.js → dist-sGMMCnKq.js} +5 -5
- package/lib/dist-sGMMCnKq.js.map +1 -0
- package/lib/index.js +20 -20
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts +4 -4
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +14 -7
- package/src/components/code-editor.tsx +4 -8
- package/src/components/diff-editor.tsx +16 -22
- package/src/components/tabbed-editor.tsx +8 -11
- package/src/editor.ts +44 -67
- package/src/index.ts +8 -8
- package/src/languages.ts +20 -28
- package/src/minimap.ts +21 -31
- package/src/tabbed-editor.ts +24 -38
- package/src/tests/code.test.ts +193 -199
- package/src/themes.ts +48 -48
- package/src/types.ts +27 -27
- package/lib/dist-B5vB-rif.js.map +0 -1
- package/lib/dist-BAfzu5eu.js.map +0 -1
- package/lib/dist-BLlV_D16.js.map +0 -1
- package/lib/dist-BNmKLTu8.js.map +0 -1
- package/lib/dist-BZtTlC1J.js.map +0 -1
- package/lib/dist-CTDqGIAf.js.map +0 -1
- package/lib/dist-CTPisNZp.js.map +0 -1
- package/lib/dist-Ce2tvOxv.js.map +0 -1
- package/lib/dist-CttF0OTv.js.map +0 -1
- package/lib/dist-DS2tluW9.js.map +0 -1
- package/lib/dist-DUNx9ldu.js.map +0 -1
- package/lib/dist-Dej_yf3k.js.map +0 -1
- package/lib/dist-DshStUxU.js.map +0 -1
- package/lib/dist-qTrOe7xY.js.map +0 -1
- package/lib/dist-v09vikKr.js.map +0 -1
package/src/tests/code.test.ts
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
import { effect } from
|
|
2
|
-
import { describe, expect, it } from
|
|
3
|
-
import { createEditor } from
|
|
4
|
-
import { getAvailableLanguages } from
|
|
5
|
-
import { createTabbedEditor } from
|
|
6
|
-
|
|
7
|
-
describe(
|
|
8
|
-
describe(
|
|
9
|
-
it(
|
|
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(
|
|
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(
|
|
19
|
-
const editor = createEditor({ value:
|
|
20
|
-
expect(editor.value()).toBe(
|
|
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(
|
|
24
|
-
const editor = createEditor({ language:
|
|
25
|
-
expect(editor.language()).toBe(
|
|
23
|
+
it("creates with language", () => {
|
|
24
|
+
const editor = createEditor({ language: "typescript" })
|
|
25
|
+
expect(editor.language()).toBe("typescript")
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
it(
|
|
29
|
-
const editor = createEditor({ theme:
|
|
30
|
-
expect(editor.theme()).toBe(
|
|
28
|
+
it("creates with theme", () => {
|
|
29
|
+
const editor = createEditor({ theme: "dark" })
|
|
30
|
+
expect(editor.theme()).toBe("dark")
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
it(
|
|
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(
|
|
38
|
+
it("stores config", () => {
|
|
39
39
|
const config = {
|
|
40
|
-
value:
|
|
41
|
-
language:
|
|
42
|
-
theme:
|
|
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(
|
|
52
|
-
it(
|
|
53
|
-
const editor = createEditor({ value:
|
|
54
|
-
expect(editor.value()).toBe(
|
|
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(
|
|
57
|
-
expect(editor.value()).toBe(
|
|
56
|
+
editor.value.set("updated")
|
|
57
|
+
expect(editor.value()).toBe("updated")
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
it(
|
|
61
|
-
const editor = createEditor({ language:
|
|
62
|
-
editor.language.set(
|
|
63
|
-
expect(editor.language()).toBe(
|
|
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(
|
|
67
|
-
const editor = createEditor({ theme:
|
|
68
|
-
editor.theme.set(
|
|
69
|
-
expect(editor.theme()).toBe(
|
|
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(
|
|
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(
|
|
79
|
-
const editor = createEditor({ value:
|
|
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(
|
|
87
|
-
editor.value.set(
|
|
86
|
+
editor.value.set("b")
|
|
87
|
+
editor.value.set("c")
|
|
88
88
|
|
|
89
|
-
expect(values).toEqual([
|
|
89
|
+
expect(values).toEqual(["a", "b", "c"])
|
|
90
90
|
})
|
|
91
91
|
})
|
|
92
92
|
|
|
93
|
-
describe(
|
|
94
|
-
it(
|
|
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(
|
|
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(
|
|
105
|
-
const editor = createEditor({ value:
|
|
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(
|
|
110
|
-
const editor = createEditor({ value:
|
|
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(
|
|
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(
|
|
121
|
-
it(
|
|
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(
|
|
126
|
+
it("insert does not throw before mount", () => {
|
|
127
127
|
const editor = createEditor()
|
|
128
|
-
expect(() => editor.insert(
|
|
128
|
+
expect(() => editor.insert("text")).not.toThrow()
|
|
129
129
|
})
|
|
130
130
|
|
|
131
|
-
it(
|
|
131
|
+
it("replaceSelection does not throw before mount", () => {
|
|
132
132
|
const editor = createEditor()
|
|
133
|
-
expect(() => editor.replaceSelection(
|
|
133
|
+
expect(() => editor.replaceSelection("text")).not.toThrow()
|
|
134
134
|
})
|
|
135
135
|
|
|
136
|
-
it(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
168
|
-
it(
|
|
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(
|
|
178
|
-
it(
|
|
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(
|
|
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(
|
|
190
|
+
it("highlightLine does not throw before mount", () => {
|
|
193
191
|
const editor = createEditor()
|
|
194
|
-
expect(() => editor.highlightLine(1,
|
|
192
|
+
expect(() => editor.highlightLine(1, "error-line")).not.toThrow()
|
|
195
193
|
})
|
|
196
194
|
|
|
197
|
-
it(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
238
|
-
it(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
252
|
+
it("all config options are stored", () => {
|
|
259
253
|
const editor = createEditor({
|
|
260
|
-
value:
|
|
261
|
-
language:
|
|
262
|
-
theme:
|
|
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:
|
|
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(
|
|
271
|
+
expect(editor.config.placeholder).toBe("Type here...")
|
|
278
272
|
})
|
|
279
273
|
})
|
|
280
274
|
})
|
|
281
275
|
|
|
282
|
-
describe(
|
|
283
|
-
it(
|
|
276
|
+
describe("createTabbedEditor", () => {
|
|
277
|
+
it("creates with initial tabs", () => {
|
|
284
278
|
const te = createTabbedEditor({
|
|
285
279
|
tabs: [
|
|
286
|
-
{ name:
|
|
287
|
-
{ name:
|
|
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(
|
|
292
|
-
expect(te.activeTab()?.name).toBe(
|
|
293
|
-
expect(te.editor.value()).toBe(
|
|
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(
|
|
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(
|
|
297
|
+
it("switchTab changes active tab and editor content", () => {
|
|
304
298
|
const te = createTabbedEditor({
|
|
305
299
|
tabs: [
|
|
306
|
-
{ name:
|
|
307
|
-
{ name:
|
|
300
|
+
{ name: "a.ts", value: "aaa" },
|
|
301
|
+
{ name: "b.ts", value: "bbb" },
|
|
308
302
|
],
|
|
309
303
|
})
|
|
310
|
-
expect(te.editor.value()).toBe(
|
|
304
|
+
expect(te.editor.value()).toBe("aaa")
|
|
311
305
|
|
|
312
|
-
te.switchTab(
|
|
313
|
-
expect(te.activeTabId()).toBe(
|
|
314
|
-
expect(te.editor.value()).toBe(
|
|
306
|
+
te.switchTab("b.ts")
|
|
307
|
+
expect(te.activeTabId()).toBe("b.ts")
|
|
308
|
+
expect(te.editor.value()).toBe("bbb")
|
|
315
309
|
|
|
316
|
-
te.switchTab(
|
|
317
|
-
expect(te.editor.value()).toBe(
|
|
310
|
+
te.switchTab("a.ts")
|
|
311
|
+
expect(te.editor.value()).toBe("aaa")
|
|
318
312
|
})
|
|
319
313
|
|
|
320
|
-
it(
|
|
314
|
+
it("openTab adds and switches to new tab", () => {
|
|
321
315
|
const te = createTabbedEditor({
|
|
322
|
-
tabs: [{ name:
|
|
316
|
+
tabs: [{ name: "a.ts", value: "aaa" }],
|
|
323
317
|
})
|
|
324
318
|
|
|
325
|
-
te.openTab({ name:
|
|
319
|
+
te.openTab({ name: "b.ts", language: "typescript", value: "bbb" })
|
|
326
320
|
expect(te.tabs()).toHaveLength(2)
|
|
327
|
-
expect(te.activeTabId()).toBe(
|
|
328
|
-
expect(te.editor.value()).toBe(
|
|
321
|
+
expect(te.activeTabId()).toBe("b.ts")
|
|
322
|
+
expect(te.editor.value()).toBe("bbb")
|
|
329
323
|
})
|
|
330
324
|
|
|
331
|
-
it(
|
|
325
|
+
it("openTab switches to existing tab", () => {
|
|
332
326
|
const te = createTabbedEditor({
|
|
333
327
|
tabs: [
|
|
334
|
-
{ name:
|
|
335
|
-
{ name:
|
|
328
|
+
{ name: "a.ts", value: "aaa" },
|
|
329
|
+
{ name: "b.ts", value: "bbb" },
|
|
336
330
|
],
|
|
337
331
|
})
|
|
338
332
|
|
|
339
|
-
te.openTab({ name:
|
|
333
|
+
te.openTab({ name: "b.ts", value: "bbb" })
|
|
340
334
|
expect(te.tabs()).toHaveLength(2) // not duplicated
|
|
341
|
-
expect(te.activeTabId()).toBe(
|
|
335
|
+
expect(te.activeTabId()).toBe("b.ts")
|
|
342
336
|
})
|
|
343
337
|
|
|
344
|
-
it(
|
|
338
|
+
it("closeTab removes tab", () => {
|
|
345
339
|
const te = createTabbedEditor({
|
|
346
340
|
tabs: [
|
|
347
|
-
{ name:
|
|
348
|
-
{ name:
|
|
341
|
+
{ name: "a.ts", value: "aaa" },
|
|
342
|
+
{ name: "b.ts", value: "bbb" },
|
|
349
343
|
],
|
|
350
344
|
})
|
|
351
345
|
|
|
352
|
-
te.closeTab(
|
|
346
|
+
te.closeTab("b.ts")
|
|
353
347
|
expect(te.tabs()).toHaveLength(1)
|
|
354
|
-
expect(te.tabs()[0]!.name).toBe(
|
|
348
|
+
expect(te.tabs()[0]!.name).toBe("a.ts")
|
|
355
349
|
})
|
|
356
350
|
|
|
357
|
-
it(
|
|
351
|
+
it("closeTab switches to adjacent when closing active", () => {
|
|
358
352
|
const te = createTabbedEditor({
|
|
359
353
|
tabs: [
|
|
360
|
-
{ name:
|
|
361
|
-
{ name:
|
|
362
|
-
{ name:
|
|
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(
|
|
367
|
-
te.closeTab(
|
|
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(
|
|
363
|
+
expect(te.activeTabId()).not.toBe("b.ts")
|
|
370
364
|
expect(te.tabs()).toHaveLength(2)
|
|
371
365
|
})
|
|
372
366
|
|
|
373
|
-
it(
|
|
367
|
+
it("closeTab respects closable: false", () => {
|
|
374
368
|
const te = createTabbedEditor({
|
|
375
|
-
tabs: [{ name:
|
|
369
|
+
tabs: [{ name: "main.ts", value: "main", closable: false }],
|
|
376
370
|
})
|
|
377
371
|
|
|
378
|
-
te.closeTab(
|
|
372
|
+
te.closeTab("main.ts")
|
|
379
373
|
expect(te.tabs()).toHaveLength(1) // not closed
|
|
380
374
|
})
|
|
381
375
|
|
|
382
|
-
it(
|
|
376
|
+
it("renameTab changes tab name", () => {
|
|
383
377
|
const te = createTabbedEditor({
|
|
384
|
-
tabs: [{ name:
|
|
378
|
+
tabs: [{ name: "old.ts", value: "" }],
|
|
385
379
|
})
|
|
386
380
|
|
|
387
|
-
te.renameTab(
|
|
388
|
-
expect(te.tabs()[0]!.name).toBe(
|
|
381
|
+
te.renameTab("old.ts", "new.ts")
|
|
382
|
+
expect(te.tabs()[0]!.name).toBe("new.ts")
|
|
389
383
|
})
|
|
390
384
|
|
|
391
|
-
it(
|
|
385
|
+
it("setModified marks tab", () => {
|
|
392
386
|
const te = createTabbedEditor({
|
|
393
|
-
tabs: [{ name:
|
|
387
|
+
tabs: [{ name: "a.ts", value: "" }],
|
|
394
388
|
})
|
|
395
389
|
|
|
396
|
-
te.setModified(
|
|
390
|
+
te.setModified("a.ts", true)
|
|
397
391
|
expect(te.tabs()[0]!.modified).toBe(true)
|
|
398
392
|
|
|
399
|
-
te.setModified(
|
|
393
|
+
te.setModified("a.ts", false)
|
|
400
394
|
expect(te.tabs()[0]!.modified).toBe(false)
|
|
401
395
|
})
|
|
402
396
|
|
|
403
|
-
it(
|
|
397
|
+
it("moveTab reorders tabs", () => {
|
|
404
398
|
const te = createTabbedEditor({
|
|
405
399
|
tabs: [
|
|
406
|
-
{ name:
|
|
407
|
-
{ name:
|
|
408
|
-
{ name:
|
|
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([
|
|
407
|
+
expect(te.tabs().map((t: any) => t.name)).toEqual(["b.ts", "c.ts", "a.ts"])
|
|
414
408
|
})
|
|
415
409
|
|
|
416
|
-
it(
|
|
410
|
+
it("getTab returns tab by id", () => {
|
|
417
411
|
const te = createTabbedEditor({
|
|
418
|
-
tabs: [{ name:
|
|
412
|
+
tabs: [{ name: "a.ts", value: "content" }],
|
|
419
413
|
})
|
|
420
414
|
|
|
421
|
-
expect(te.getTab(
|
|
422
|
-
expect(te.getTab(
|
|
415
|
+
expect(te.getTab("a.ts")?.value).toBe("content")
|
|
416
|
+
expect(te.getTab("missing")).toBeUndefined()
|
|
423
417
|
})
|
|
424
418
|
|
|
425
|
-
it(
|
|
419
|
+
it("closeAll closes all closable tabs", () => {
|
|
426
420
|
const te = createTabbedEditor({
|
|
427
421
|
tabs: [
|
|
428
|
-
{ name:
|
|
429
|
-
{ name:
|
|
430
|
-
{ name:
|
|
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(
|
|
430
|
+
expect(te.tabs()[0]!.name).toBe("a.ts")
|
|
437
431
|
})
|
|
438
432
|
|
|
439
|
-
it(
|
|
433
|
+
it("closeOthers closes all except specified", () => {
|
|
440
434
|
const te = createTabbedEditor({
|
|
441
435
|
tabs: [
|
|
442
|
-
{ name:
|
|
443
|
-
{ name:
|
|
444
|
-
{ name:
|
|
436
|
+
{ name: "a.ts", value: "" },
|
|
437
|
+
{ name: "b.ts", value: "" },
|
|
438
|
+
{ name: "c.ts", value: "" },
|
|
445
439
|
],
|
|
446
440
|
})
|
|
447
441
|
|
|
448
|
-
te.closeOthers(
|
|
442
|
+
te.closeOthers("b.ts")
|
|
449
443
|
expect(te.tabs()).toHaveLength(1)
|
|
450
|
-
expect(te.tabs()[0]!.name).toBe(
|
|
444
|
+
expect(te.tabs()[0]!.name).toBe("b.ts")
|
|
451
445
|
})
|
|
452
446
|
|
|
453
|
-
it(
|
|
447
|
+
it("preserves content when switching tabs", () => {
|
|
454
448
|
const te = createTabbedEditor({
|
|
455
449
|
tabs: [
|
|
456
|
-
{ name:
|
|
457
|
-
{ name:
|
|
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(
|
|
456
|
+
te.editor.value.set("modified-a")
|
|
463
457
|
|
|
464
458
|
// Switch to b.ts
|
|
465
|
-
te.switchTab(
|
|
466
|
-
expect(te.editor.value()).toBe(
|
|
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(
|
|
470
|
-
expect(te.editor.value()).toBe(
|
|
463
|
+
te.switchTab("a.ts")
|
|
464
|
+
expect(te.editor.value()).toBe("modified-a")
|
|
471
465
|
})
|
|
472
466
|
|
|
473
|
-
it(
|
|
467
|
+
it("dispose cleans up", () => {
|
|
474
468
|
const te = createTabbedEditor({
|
|
475
|
-
tabs: [{ name:
|
|
469
|
+
tabs: [{ name: "a.ts", value: "" }],
|
|
476
470
|
})
|
|
477
471
|
expect(() => te.dispose()).not.toThrow()
|
|
478
472
|
})
|
|
479
473
|
|
|
480
|
-
it(
|
|
474
|
+
it("close last tab clears editor", () => {
|
|
481
475
|
const te = createTabbedEditor({
|
|
482
|
-
tabs: [{ name:
|
|
476
|
+
tabs: [{ name: "a.ts", value: "content" }],
|
|
483
477
|
})
|
|
484
478
|
|
|
485
|
-
te.closeTab(
|
|
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(
|
|
493
|
-
it(
|
|
486
|
+
describe("getAvailableLanguages", () => {
|
|
487
|
+
it("returns all supported languages", () => {
|
|
494
488
|
const langs = getAvailableLanguages()
|
|
495
|
-
expect(langs).toContain(
|
|
496
|
-
expect(langs).toContain(
|
|
497
|
-
expect(langs).toContain(
|
|
498
|
-
expect(langs).toContain(
|
|
499
|
-
expect(langs).toContain(
|
|
500
|
-
expect(langs).toContain(
|
|
501
|
-
expect(langs).toContain(
|
|
502
|
-
expect(langs).toContain(
|
|
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
|
})
|