From 42bdc6ad9826cc96b49157ba214f7e0fb468300a Mon Sep 17 00:00:00 2001 From: mwiegand Date: Sun, 17 May 2026 02:08:42 +0200 Subject: [PATCH] feat(editor-v2): files-overlay reads/writes via window.__filesEditor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Routes 8 call sites through the cm6 controller alias: - 5 reads (byte-count, save POST, dirty checks at 306, 481, 496, 511, 528) → getEditorValue() helper, falling back to editorEls.contentBox.value if window.__filesEditor isn't mounted (no-JS / pre-mount path). - 3 writes (clear, "Loading…" placeholder, fetched body content at 362, 395, 402) → setEditorValue() helper with the same fallback. The two helpers live inline next to editorEls so the rest of the module's call sites stay close to existing style. Known regressions (out of scope for v2, candidate follow-ups): - Byte-count badge updates only on file-open / setContent calls, not live on every keystroke. Needs a controller.onChange(cb) hook. - Ctrl+S inside cm6 doesn't trigger the modal Save. cm6 owns the keymap in its editing surface; users can still click the Save button. Adding a custom cm6 keymap entry would restore the shortcut. Co-Authored-By: Claude Opus 4.7 (1M context) --- l4d2web/l4d2web/static/js/files-overlay.js | 33 ++++++++++++++++------ 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/l4d2web/l4d2web/static/js/files-overlay.js b/l4d2web/l4d2web/static/js/files-overlay.js index cffc9fe..27ccb88 100644 --- a/l4d2web/l4d2web/static/js/files-overlay.js +++ b/l4d2web/l4d2web/static/js/files-overlay.js @@ -281,12 +281,29 @@ saveBtn: editorDialog.querySelector(".files-editor-save"), }; + // Bridge to the CodeMirror 6 controller, set up by static/js/editor.js + // on the .files-editor-content textarea. Falls back to the textarea + // directly if the bundle didn't load (no-JS fallback / file open + // before the controller has been mounted). + function getEditorValue() { + return (window.__filesEditor && window.__filesEditor.getValue) + ? window.__filesEditor.getValue() + : editorEls.contentBox.value; + } + function setEditorValue(text) { + if (window.__filesEditor && window.__filesEditor.setContent) { + window.__filesEditor.setContent(text); + } else { + editorEls.contentBox.value = text; + } + } + function setEditorTitle(text) { editorEls.title.textContent = text; } function updateByteCount() { - const bytes = new TextEncoder().encode(editorEls.contentBox.value).length; + const bytes = new TextEncoder().encode(getEditorValue()).length; editorEls.byteCount.textContent = `UTF-8 · ${bytes} bytes`; } @@ -342,7 +359,7 @@ setEditorTitle(`${folder ? folder + "/" : ""}…new file`); editorEls.filename.value = ""; editorEls.filename.disabled = false; - editorEls.contentBox.value = ""; + setEditorValue(""); editorEls.contentBox.disabled = false; editorEls.renameHint.hidden = true; editorEls.textPanel.hidden = false; @@ -375,14 +392,14 @@ editor.mode = "text"; editorEls.textPanel.hidden = false; editorEls.binaryPanel.hidden = true; - editorEls.contentBox.value = "Loading…"; + setEditorValue("Loading…"); editorEls.contentBox.disabled = true; const r = await fetchJson( `${baseUrl}/files/content?path=${encodeURIComponent(path)}` ); if (r.ok && r.body) { - editorEls.contentBox.value = r.body.content; + setEditorValue(r.body.content); editorEls.contentBox.disabled = false; updateByteCount(); updateSaveEnabled(); @@ -461,7 +478,7 @@ // Text-flavor create → /save with no new_path. const r = await postJson(`${baseUrl}/files/save`, { path: newRel, - content: editorEls.contentBox.value, + content: getEditorValue(), }); if (r.ok) { editorDialog.close(); @@ -476,7 +493,7 @@ // For files, a plain /save overwrite is fine. const r2 = await postJson(`${baseUrl}/files/save`, { path: newRel, - content: editorEls.contentBox.value, + content: getEditorValue(), }); if (r2.ok) { editorDialog.close(); @@ -491,7 +508,7 @@ const altered = withCollisionSuffix(newRel); const r2 = await postJson(`${baseUrl}/files/save`, { path: altered, - content: editorEls.contentBox.value, + content: getEditorValue(), }); if (r2.ok) { editorDialog.close(); @@ -508,7 +525,7 @@ if (editor.mode === "text") { const payload = { path: editor.originalPath, - content: editorEls.contentBox.value, + content: getEditorValue(), }; if (renaming) payload.new_path = newRel; const r = await postJson(`${baseUrl}/files/save`, payload);