Friday, 10 July 2026
CodePanel — a CodeMirror-based code editor panel with a central file-editor registry that routes files to the right panel by suffix.
A new src/editor/FileEditorRegistry.ts class that maps file
suffixes to editor panel tags. It holds a default in-memory list and
optionally loads a project-level override from
workspace/editor/file-editors.json inside the open project.
Matching is pure suffix comparison — filename.endsWith('.' + suffix)
— so special.html beats html when it appears
earlier in the list. The project list is checked first entry-by-entry;
only when no match is found there does it fall through to the defaults.
Unknown extensions fire an onFileTypeUnknown event instead
of opening anything.
Editor.openDocument now loads the registry (once, lazily)
before fetching file content. It resolves an editorTag and
includes it in the DocumentOpenedEvent. If no tag is found
it dispatches the new onFileTypeUnknown event and returns
early without fetching the file.
HtmlEditorPanel was updated to ignore events where
editorTag !== 'html-editor-panel'.
TabContainer's dirty and saved listeners were simplified
to match any panel by currentPath rather than hard-coding
panelType === 'html-editor'.
A new code-panel custom element backed by CodeMirror 5.
Toolbar matches html-editor-panel: Pin, Undo, Redo, Save.
Undo and Redo delegate directly to cm.undo() /
cm.redo(); button enable-states are refreshed from
cm.historySize() on every CM change event.
Language mode is resolved from the file extension
(js/ts/json → javascript,
css → css, xml/svg → xml,
md → markdown, others → plain text).
A custom cp-dark CodeMirror theme matches the editor's
colour palette (background #0f1117, Material-style token
colours).
The file tree was updated so all files are clickable (not just HTML); clicking an unsupported extension shows a 3-second red banner ("Can't open extension .xyz") at the top of the tree.
Editors could declare their own patterns at import time, but that makes overriding them require touching editor source. A central list stored as data (JSON) lets a project prepend custom mappings without modifying any editor code. The project file is optional; when absent, in-memory defaults apply.
When a project provides file-editors.json, only the suffixes
it declares are overridden. Everything else falls through to the defaults.
This means a project only needs to list custom formats, not restate all
standard ones.
Glob matching requires a library or a non-trivial implementation.
Stripping the leading *. and using
endsWith('.' + suffix) is sufficient for all real cases
(including compound extensions like special.html) and
needs no dependency.
CodeMirror 6 requires a bundler or complex import maps to use without
a build step. CM5 ships a single-file UMD build that works as a plain
<script> tag, matching the existing pattern
(markdown-it). The core and five language modes were
downloaded from cdnjs and placed in public/vendor/,
keeping the setup self-hosted and version-locked.
src/editor/FileEditorRegistry.ts — new: suffix-to-editor registry with project override
src/editor/Editor.ts — added fileEditorRegistry, editorTag in event, onFileTypeUnknown
src/components/html-editor-panel/html-editor-panel.ts — filters onDocumentOpened by editorTag
src/components/file-tree-panel/file-tree-panel.ts — all files clickable, _showTypeError for unknown extensions
public/components/file-tree-panel/file-tree-panel.css — all files get hover/active styles, added .ftp-type-error
src/components/code-panel/code-panel.ts — new: CodeMirror 5 editor panel
public/components/code-panel/code-panel.css — new: panel layout + cp-dark CM theme
public/vendor/codemirror.min.js — new (CM5 core)
public/vendor/codemirror.min.css — new (CM5 base CSS)
public/vendor/cm-mode-xml.min.js — new
public/vendor/cm-mode-javascript.min.js — new
public/vendor/cm-mode-css.min.js — new
public/vendor/cm-mode-htmlmixed.min.js — new
public/vendor/cm-mode-markdown.min.js — new
public/editor.html — added CM vendor scripts, code-panel CSS and module script
src/components/tab-container/tab-container.ts — added Code Editor to menu, panel-agnostic dirty tracking
src/components/editor-shell/editor-shell.ts — awaits code-panel definition