@joinezco/codeblock 0.0.8 → 0.0.9
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/dist/assets/fs.worker-DfanUHpQ.js +21 -0
- package/dist/assets/{index-MGle_v2x.js → index-BAnLzvMk.js} +1 -1
- package/dist/assets/{index-as7ELo0J.js → index-BBC9WDX6.js} +1 -1
- package/dist/assets/{index-Dx_VuNNd.js → index-BEXYxRro.js} +1 -1
- package/dist/assets/{index-pGm0qkrJ.js → index-BfYmUKH9.js} +1 -1
- package/dist/assets/{index-CXFONXS8.js → index-BhaTNAWE.js} +1 -1
- package/dist/assets/{index-D5Z27j1C.js → index-CCbYDSng.js} +1 -1
- package/dist/assets/{index-Dvu-FFzd.js → index-CIi8tLT6.js} +1 -1
- package/dist/assets/{index-C-QhPFHP.js → index-CaANcgI2.js} +1 -1
- package/dist/assets/index-CkWzFNzm.js +208 -0
- package/dist/assets/{index-N-GE7HTU.js → index-D_XGv9QZ.js} +1 -1
- package/dist/assets/{index-DWOBdRjn.js → index-DkmiPfkD.js} +1 -1
- package/dist/assets/{index-CGx5MZO7.js → index-DmNlLMQ4.js} +1 -1
- package/dist/assets/{index-I0dlv-r3.js → index-DmX_vI7D.js} +1 -1
- package/dist/assets/{index-9HdhmM_Y.js → index-DogEEevD.js} +1 -1
- package/dist/assets/{index-aEsF5o-7.js → index-DsDl5qZV.js} +1 -1
- package/dist/assets/{index-gUUzXNuP.js → index-gAy5mDg-.js} +1 -1
- package/dist/assets/{index-CIuq3uTk.js → index-i5qJLB2h.js} +1 -1
- package/dist/assets/javascript.worker-ClsyHOLi.js +552 -0
- package/dist/e2e/editor.spec.d.ts +1 -0
- package/dist/e2e/editor.spec.js +309 -0
- package/dist/editor.d.ts +9 -3
- package/dist/editor.js +83 -15
- package/dist/index.d.ts +3 -0
- package/dist/index.html +2 -3
- package/dist/index.js +3 -0
- package/dist/lsps/typescript.d.ts +3 -1
- package/dist/lsps/typescript.js +8 -17
- package/dist/panels/footer.d.ts +16 -0
- package/dist/panels/footer.js +258 -0
- package/dist/panels/toolbar.d.ts +15 -2
- package/dist/panels/toolbar.js +528 -115
- package/dist/panels/toolbar.test.js +20 -14
- package/dist/rpc/transport.d.ts +2 -11
- package/dist/rpc/transport.js +19 -35
- package/dist/themes/index.js +181 -14
- package/dist/themes/vscode.js +3 -2
- package/dist/utils/fs.d.ts +15 -3
- package/dist/utils/fs.js +85 -6
- package/dist/utils/lsp.d.ts +26 -15
- package/dist/utils/lsp.js +79 -44
- package/dist/utils/search.d.ts +2 -0
- package/dist/utils/search.js +13 -4
- package/dist/utils/typescript-defaults.d.ts +57 -0
- package/dist/utils/typescript-defaults.js +208 -0
- package/dist/utils/typescript-defaults.test.d.ts +1 -0
- package/dist/utils/typescript-defaults.test.js +197 -0
- package/dist/workers/fs.worker.js +14 -18
- package/dist/workers/javascript.worker.js +11 -9
- package/package.json +4 -3
- package/dist/assets/fs.worker-BwEqZcql.ts +0 -109
- package/dist/assets/index-C3BnE2cG.js +0 -222
- package/dist/assets/javascript.worker-C1zGArKk.js +0 -527
- package/dist/snapshot.bin +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { EditorView } from "@codemirror/view";
|
|
2
|
+
import { StateEffect, StateField } from "@codemirror/state";
|
|
3
|
+
import { setThemeEffect, lineWrappingCompartment } from "../editor";
|
|
4
|
+
const defaultSettings = {
|
|
5
|
+
theme: 'system',
|
|
6
|
+
fontSize: 16,
|
|
7
|
+
fontFamily: '',
|
|
8
|
+
autosave: true,
|
|
9
|
+
lineWrap: false,
|
|
10
|
+
lspLogEnabled: false,
|
|
11
|
+
agentUrl: '',
|
|
12
|
+
terminalEnabled: false,
|
|
13
|
+
};
|
|
14
|
+
export const updateSettingsEffect = StateEffect.define();
|
|
15
|
+
export const settingsField = StateField.define({
|
|
16
|
+
create() {
|
|
17
|
+
return { ...defaultSettings };
|
|
18
|
+
},
|
|
19
|
+
update(value, tr) {
|
|
20
|
+
for (const e of tr.effects) {
|
|
21
|
+
if (e.is(updateSettingsEffect)) {
|
|
22
|
+
return { ...value, ...e.value };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
export function resolveThemeDark(theme) {
|
|
29
|
+
if (theme === 'system') {
|
|
30
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
31
|
+
}
|
|
32
|
+
return theme === 'dark';
|
|
33
|
+
}
|
|
34
|
+
const themeIcons = {
|
|
35
|
+
light: '☀️',
|
|
36
|
+
dark: '🌙',
|
|
37
|
+
system: '🌓',
|
|
38
|
+
};
|
|
39
|
+
// Settings overlay component (no header — toolbar shows "settings.json" and cog becomes ✕)
|
|
40
|
+
export function createSettingsOverlay(view) {
|
|
41
|
+
const settings = view.state.field(settingsField);
|
|
42
|
+
const overlay = document.createElement("div");
|
|
43
|
+
overlay.className = "cm-settings-overlay";
|
|
44
|
+
// Theme section
|
|
45
|
+
const themeSection = document.createElement("div");
|
|
46
|
+
themeSection.className = "cm-settings-section";
|
|
47
|
+
const themeTitle = document.createElement("div");
|
|
48
|
+
themeTitle.className = "cm-settings-section-title";
|
|
49
|
+
themeTitle.textContent = "Theme";
|
|
50
|
+
themeSection.appendChild(themeTitle);
|
|
51
|
+
// Font size
|
|
52
|
+
const fontSizeRow = document.createElement("div");
|
|
53
|
+
fontSizeRow.className = "cm-settings-row";
|
|
54
|
+
const fontSizeLabel = document.createElement("label");
|
|
55
|
+
fontSizeLabel.textContent = "Font size";
|
|
56
|
+
const fontSizeControl = document.createElement("div");
|
|
57
|
+
fontSizeControl.className = "cm-settings-control";
|
|
58
|
+
const fontSizeRange = document.createElement("input");
|
|
59
|
+
fontSizeRange.type = "range";
|
|
60
|
+
fontSizeRange.className = "cm-settings-font-size-range";
|
|
61
|
+
fontSizeRange.min = "8";
|
|
62
|
+
fontSizeRange.max = "48";
|
|
63
|
+
fontSizeRange.step = "1";
|
|
64
|
+
fontSizeRange.value = String(settings.fontSize);
|
|
65
|
+
const fontSizeInput = document.createElement("input");
|
|
66
|
+
fontSizeInput.type = "number";
|
|
67
|
+
fontSizeInput.className = "cm-settings-font-size-input";
|
|
68
|
+
fontSizeInput.min = "1";
|
|
69
|
+
fontSizeInput.max = "128";
|
|
70
|
+
fontSizeInput.value = String(settings.fontSize);
|
|
71
|
+
const fontSizePx = document.createElement("span");
|
|
72
|
+
fontSizePx.textContent = "px";
|
|
73
|
+
// Use 'change' on the range (fires on mouseup) to avoid feedback loop:
|
|
74
|
+
// dragging changes font size → overlay relayouts → slider thumb shifts
|
|
75
|
+
// relative to pointer → triggers another input event → runaway resizing.
|
|
76
|
+
fontSizeRange.addEventListener("change", () => {
|
|
77
|
+
const size = Number(fontSizeRange.value);
|
|
78
|
+
fontSizeInput.value = String(size);
|
|
79
|
+
view.dispatch({ effects: updateSettingsEffect.of({ fontSize: size }) });
|
|
80
|
+
});
|
|
81
|
+
fontSizeInput.addEventListener("input", () => {
|
|
82
|
+
let size = Number(fontSizeInput.value);
|
|
83
|
+
if (isNaN(size) || size < 1)
|
|
84
|
+
return;
|
|
85
|
+
size = Math.min(128, size);
|
|
86
|
+
fontSizeRange.value = String(size);
|
|
87
|
+
view.dispatch({ effects: updateSettingsEffect.of({ fontSize: size }) });
|
|
88
|
+
});
|
|
89
|
+
fontSizeControl.appendChild(fontSizeRange);
|
|
90
|
+
fontSizeControl.appendChild(fontSizeInput);
|
|
91
|
+
fontSizeControl.appendChild(fontSizePx);
|
|
92
|
+
fontSizeRow.appendChild(fontSizeLabel);
|
|
93
|
+
fontSizeRow.appendChild(fontSizeControl);
|
|
94
|
+
themeSection.appendChild(fontSizeRow);
|
|
95
|
+
// Font family
|
|
96
|
+
const fontFamilyRow = document.createElement("div");
|
|
97
|
+
fontFamilyRow.className = "cm-settings-row";
|
|
98
|
+
const fontFamilyLabel = document.createElement("label");
|
|
99
|
+
fontFamilyLabel.textContent = "Font family";
|
|
100
|
+
const fontFamilySelect = document.createElement("select");
|
|
101
|
+
fontFamilySelect.className = "cm-settings-select";
|
|
102
|
+
const fontOptions = [
|
|
103
|
+
{ label: "System default", value: "" },
|
|
104
|
+
{ label: "UbuntuMono Nerd Font", value: '"UbuntuMono NF", monospace' },
|
|
105
|
+
];
|
|
106
|
+
for (const opt of fontOptions) {
|
|
107
|
+
const option = document.createElement("option");
|
|
108
|
+
option.value = opt.value;
|
|
109
|
+
option.textContent = opt.label;
|
|
110
|
+
if (settings.fontFamily === opt.value)
|
|
111
|
+
option.selected = true;
|
|
112
|
+
fontFamilySelect.appendChild(option);
|
|
113
|
+
}
|
|
114
|
+
fontFamilySelect.addEventListener("change", () => {
|
|
115
|
+
view.dispatch({ effects: updateSettingsEffect.of({ fontFamily: fontFamilySelect.value }) });
|
|
116
|
+
});
|
|
117
|
+
fontFamilyRow.appendChild(fontFamilyLabel);
|
|
118
|
+
fontFamilyRow.appendChild(fontFamilySelect);
|
|
119
|
+
themeSection.appendChild(fontFamilyRow);
|
|
120
|
+
// Color theme radio — with emoji icons
|
|
121
|
+
const colorThemeRow = document.createElement("div");
|
|
122
|
+
colorThemeRow.className = "cm-settings-row";
|
|
123
|
+
const colorThemeLabel = document.createElement("label");
|
|
124
|
+
colorThemeLabel.textContent = "Color theme";
|
|
125
|
+
const radioGroup = document.createElement("div");
|
|
126
|
+
radioGroup.className = "cm-settings-radio-group";
|
|
127
|
+
for (const t of ['light', 'dark', 'system']) {
|
|
128
|
+
const radio = document.createElement("input");
|
|
129
|
+
radio.type = "radio";
|
|
130
|
+
radio.name = "cm-color-theme";
|
|
131
|
+
radio.value = t;
|
|
132
|
+
radio.id = `cm-theme-${t}`;
|
|
133
|
+
if (settings.theme === t)
|
|
134
|
+
radio.checked = true;
|
|
135
|
+
radio.addEventListener("change", () => {
|
|
136
|
+
if (radio.checked) {
|
|
137
|
+
view.dispatch({
|
|
138
|
+
effects: [
|
|
139
|
+
updateSettingsEffect.of({ theme: t }),
|
|
140
|
+
setThemeEffect.of({ dark: resolveThemeDark(t) }),
|
|
141
|
+
]
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
const radioLabel = document.createElement("label");
|
|
146
|
+
radioLabel.htmlFor = `cm-theme-${t}`;
|
|
147
|
+
radioLabel.textContent = themeIcons[t];
|
|
148
|
+
radioLabel.title = t.charAt(0).toUpperCase() + t.slice(1);
|
|
149
|
+
radioGroup.appendChild(radio);
|
|
150
|
+
radioGroup.appendChild(radioLabel);
|
|
151
|
+
}
|
|
152
|
+
colorThemeRow.appendChild(colorThemeLabel);
|
|
153
|
+
colorThemeRow.appendChild(radioGroup);
|
|
154
|
+
themeSection.appendChild(colorThemeRow);
|
|
155
|
+
overlay.appendChild(themeSection);
|
|
156
|
+
// Editor section
|
|
157
|
+
const editorSection = document.createElement("div");
|
|
158
|
+
editorSection.className = "cm-settings-section";
|
|
159
|
+
const editorTitle = document.createElement("div");
|
|
160
|
+
editorTitle.className = "cm-settings-section-title";
|
|
161
|
+
editorTitle.textContent = "Editor";
|
|
162
|
+
editorSection.appendChild(editorTitle);
|
|
163
|
+
const autosaveRow = document.createElement("div");
|
|
164
|
+
autosaveRow.className = "cm-settings-row";
|
|
165
|
+
const autosaveLabel = document.createElement("label");
|
|
166
|
+
autosaveLabel.textContent = "Autosave";
|
|
167
|
+
autosaveLabel.htmlFor = "cm-autosave";
|
|
168
|
+
const autosaveCheckbox = document.createElement("input");
|
|
169
|
+
autosaveCheckbox.type = "checkbox";
|
|
170
|
+
autosaveCheckbox.id = "cm-autosave";
|
|
171
|
+
autosaveCheckbox.checked = settings.autosave;
|
|
172
|
+
autosaveCheckbox.addEventListener("change", () => {
|
|
173
|
+
view.dispatch({ effects: updateSettingsEffect.of({ autosave: autosaveCheckbox.checked }) });
|
|
174
|
+
});
|
|
175
|
+
autosaveRow.appendChild(autosaveLabel);
|
|
176
|
+
autosaveRow.appendChild(autosaveCheckbox);
|
|
177
|
+
editorSection.appendChild(autosaveRow);
|
|
178
|
+
// Line wrap toggle
|
|
179
|
+
const lineWrapRow = document.createElement("div");
|
|
180
|
+
lineWrapRow.className = "cm-settings-row";
|
|
181
|
+
const lineWrapLabel = document.createElement("label");
|
|
182
|
+
lineWrapLabel.textContent = "Line wrap";
|
|
183
|
+
lineWrapLabel.htmlFor = "cm-line-wrap";
|
|
184
|
+
const lineWrapCheckbox = document.createElement("input");
|
|
185
|
+
lineWrapCheckbox.type = "checkbox";
|
|
186
|
+
lineWrapCheckbox.id = "cm-line-wrap";
|
|
187
|
+
lineWrapCheckbox.checked = settings.lineWrap;
|
|
188
|
+
lineWrapCheckbox.addEventListener("change", () => {
|
|
189
|
+
view.dispatch({
|
|
190
|
+
effects: [
|
|
191
|
+
updateSettingsEffect.of({ lineWrap: lineWrapCheckbox.checked }),
|
|
192
|
+
lineWrappingCompartment.reconfigure(lineWrapCheckbox.checked ? EditorView.lineWrapping : []),
|
|
193
|
+
]
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
lineWrapRow.appendChild(lineWrapLabel);
|
|
197
|
+
lineWrapRow.appendChild(lineWrapCheckbox);
|
|
198
|
+
editorSection.appendChild(lineWrapRow);
|
|
199
|
+
// LSP log toggle
|
|
200
|
+
const lspLogRow = document.createElement("div");
|
|
201
|
+
lspLogRow.className = "cm-settings-row";
|
|
202
|
+
const lspLogLabel = document.createElement("label");
|
|
203
|
+
lspLogLabel.textContent = "LSP server log";
|
|
204
|
+
lspLogLabel.htmlFor = "cm-lsp-log";
|
|
205
|
+
const lspLogCheckbox = document.createElement("input");
|
|
206
|
+
lspLogCheckbox.type = "checkbox";
|
|
207
|
+
lspLogCheckbox.id = "cm-lsp-log";
|
|
208
|
+
lspLogCheckbox.checked = settings.lspLogEnabled;
|
|
209
|
+
lspLogCheckbox.addEventListener("change", () => {
|
|
210
|
+
view.dispatch({ effects: updateSettingsEffect.of({ lspLogEnabled: lspLogCheckbox.checked }) });
|
|
211
|
+
});
|
|
212
|
+
lspLogRow.appendChild(lspLogLabel);
|
|
213
|
+
lspLogRow.appendChild(lspLogCheckbox);
|
|
214
|
+
editorSection.appendChild(lspLogRow);
|
|
215
|
+
overlay.appendChild(editorSection);
|
|
216
|
+
// AI Agent section
|
|
217
|
+
const aiSection = document.createElement("div");
|
|
218
|
+
aiSection.className = "cm-settings-section";
|
|
219
|
+
const aiTitle = document.createElement("div");
|
|
220
|
+
aiTitle.className = "cm-settings-section-title";
|
|
221
|
+
aiTitle.textContent = "AI Agent";
|
|
222
|
+
aiSection.appendChild(aiTitle);
|
|
223
|
+
const agentRow = document.createElement("div");
|
|
224
|
+
agentRow.className = "cm-settings-row";
|
|
225
|
+
const agentLabel = document.createElement("label");
|
|
226
|
+
agentLabel.textContent = "Agent URL";
|
|
227
|
+
const agentInput = document.createElement("input");
|
|
228
|
+
agentInput.type = "text";
|
|
229
|
+
agentInput.className = "cm-settings-input";
|
|
230
|
+
agentInput.placeholder = "OpenAPI-compatible endpoint";
|
|
231
|
+
agentInput.value = settings.agentUrl;
|
|
232
|
+
agentInput.addEventListener("change", () => {
|
|
233
|
+
view.dispatch({ effects: updateSettingsEffect.of({ agentUrl: agentInput.value }) });
|
|
234
|
+
});
|
|
235
|
+
agentRow.appendChild(agentLabel);
|
|
236
|
+
agentRow.appendChild(agentInput);
|
|
237
|
+
aiSection.appendChild(agentRow);
|
|
238
|
+
// TODO: integrate via @marimo-team/codemirror-ai
|
|
239
|
+
overlay.appendChild(aiSection);
|
|
240
|
+
// Terminal section
|
|
241
|
+
const termSection = document.createElement("div");
|
|
242
|
+
termSection.className = "cm-settings-section";
|
|
243
|
+
const termTitle = document.createElement("div");
|
|
244
|
+
termTitle.className = "cm-settings-section-title";
|
|
245
|
+
termTitle.textContent = "Terminal";
|
|
246
|
+
termSection.appendChild(termTitle);
|
|
247
|
+
const termRow = document.createElement("div");
|
|
248
|
+
termRow.className = "cm-settings-row";
|
|
249
|
+
const termBtn = document.createElement("button");
|
|
250
|
+
termBtn.className = "cm-settings-button cm-settings-button-disabled";
|
|
251
|
+
termBtn.textContent = "Terminal (coming soon)";
|
|
252
|
+
termBtn.disabled = true;
|
|
253
|
+
termRow.appendChild(termBtn);
|
|
254
|
+
termSection.appendChild(termRow);
|
|
255
|
+
// TODO: ghostty-web + wanix integration
|
|
256
|
+
overlay.appendChild(termSection);
|
|
257
|
+
return overlay;
|
|
258
|
+
}
|
package/dist/panels/toolbar.d.ts
CHANGED
|
@@ -3,18 +3,31 @@ import { StateField } from "@codemirror/state";
|
|
|
3
3
|
import { HighlightedSearch } from "../utils/search";
|
|
4
4
|
export interface CommandResult {
|
|
5
5
|
id: string;
|
|
6
|
-
type: 'create-file' | 'rename-file';
|
|
6
|
+
type: 'create-file' | 'rename-file' | 'import-local-files' | 'import-local-folder' | 'open-file';
|
|
7
7
|
icon: string;
|
|
8
|
+
iconColor?: string;
|
|
8
9
|
query: string;
|
|
9
10
|
requiresInput?: boolean;
|
|
10
11
|
}
|
|
11
|
-
export
|
|
12
|
+
export interface BrowseEntry {
|
|
13
|
+
id: string;
|
|
14
|
+
type: 'browse-directory' | 'browse-file' | 'browse-parent';
|
|
15
|
+
icon: string;
|
|
16
|
+
iconColor?: string;
|
|
17
|
+
fullPath: string;
|
|
18
|
+
}
|
|
19
|
+
export type SearchResult = HighlightedSearch | CommandResult | BrowseEntry;
|
|
12
20
|
export interface NamingMode {
|
|
13
21
|
active: boolean;
|
|
14
22
|
type: 'create-file' | 'rename-file';
|
|
15
23
|
originalQuery: string;
|
|
16
24
|
languageExtension?: string;
|
|
17
25
|
}
|
|
26
|
+
export interface BrowseMode {
|
|
27
|
+
active: boolean;
|
|
28
|
+
currentPath: string;
|
|
29
|
+
filter: string;
|
|
30
|
+
}
|
|
18
31
|
export declare const setSearchResults: import("@codemirror/state").StateEffectType<SearchResult[]>;
|
|
19
32
|
export declare const searchResultsField: StateField<SearchResult[]>;
|
|
20
33
|
export declare const toolbarPanel: (view: EditorView) => Panel;
|