Feat/split view - #3
Merged
Merged
Conversation
Dropping one or more files onto the page opens each in a new tab, or — if a tab already has that file open — activates the existing tab instead of creating a duplicate. "Same file" is decided by FileSystemFileHandle identity (isSameEntry) when the browser exposes a handle, falling back to file name. Files open in the focused split pane; the editor is focused afterwards. - FileActions.openDropped() + _findOpenDoc() + _readFile() reuse the existing size-guard / EOL / BOM / disk-baseline logic. - App wires capture-phase dragover/drop guarded to file drags (stopPropagation) so file drops never reach CodeMirror's text-drop handling, while dragging selected text within the editor still works. - CHANGELOG: note under 0.3.0 Added. Tests: file-actions.test.ts (+4: new tab, activate by handle identity, distinct entry same name, activate by name); drag-drop.spec.ts e2e (+2). 644 unit + 185 e2e pass; typecheck and lint clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a Notepad++-style Plugins system where plugin code is NEVER bundled into editor.js — it loads on demand (dynamic import → separate webpack chunk) only when the user enables it, keeping startup fast. Plugin system (Phase A): - plugin-api.ts: Plugin + PluginContext (store, focused view/controller, dockManager, namespaced storage, menu contribution). - registry.ts: lazy enable/disable via dynamic-import loaders; enabled ids persisted and re-activated AFTER app-ready (never blocks first paint). - New "Plugins" top-level menu (between Macro and Help) + Plugin Manager modal (Enable/Disable with a Loading… state). - Wired through app.ts (menu render + refresh) and editor-page.ts (registry construction + post-appReady restore). MarkdownViewer++ (Phase B): - Docked live preview: CommonMark + GFM (tables, task lists, strikethrough) via marked, sanitized with DOMPurify, rendered in a shadow root so custom CSS is isolated. Auto-refresh (debounced) + synced scroll + Ctrl+Shift+M toggle. - Options (custom CSS, persisted), Export HTML; PDF via browser Print. - marked + dompurify live only in the plugin chunk (verified: 0 DOMPurify refs in editor.js; they're in the on-demand 214.js chunk). Tests: registry (lazy-load, persistence, disable, failure, namespacing); markdownToHtml (GFM); e2e markdown-viewer.spec.ts (enable→lazy-load→preview, auto-refresh, real-browser XSS sanitization). Menu-count tests updated to 10. 653 unit + e2e pass; typecheck, lint, build clean. Docs: docs/plugins/README.md, docs/plugins/markdown-viewer.md (user flows). ComparePlus (Phase C) and CHANGELOG/perf finalize (Phase D) still to come. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A persisted dock layout restores the Markdown Preview panel on reload BEFORE the lazily-loaded plugin re-registers its renderer, so the panel mounted as a blank fallback with no content. On activate, close any such stale restored instance so togglePreview() re-mounts it with the real renderer. Adds an e2e regression test: enable → reload → preview still renders. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ports the browser-feasible subset of Notepad++ ComparePlus, lazy-loaded like MarkdownViewer++ (jsdiff lives only in the plugin chunk, never in editor.js). - diff-engine.ts (pure, tested): line diff with change-pairing + inline char diff, ignore whitespace/case/empty-lines, heuristic move detection, and a set-based "find unique lines" mode. - Renders into a generic always-present overlay decoration slot (src/editor/plugin-overlay.ts) added to both editor panes — avoids appending a StateField to a freshly-created split pane (which doesn't render reliably). Decorations are painted after a layout frame so the new pane is sized. - Uses the split view (new SplitApi on PluginContext / App.getSplitApi): left = previous tab, right = active tab. Modes: Compare, vs Clipboard, vs Last Save, Find Unique Lines. Next/Prev/First/Last diff navigation. Clear Results. Settings dialog for the ignore/move/char options. - Git/SVN diff and Compare Selections are disabled (not feasible / not yet). Also: CHANGELOG entry for the plugins feature; docs/plugins/compareplus.md (user flows). Perf verified: editor.js has 0 refs to jsdiff/DOMPurify. Tests: diff-engine unit tests (add/remove/change/char/ignore/moves/unique); compare-plus.spec.ts e2e (split + diff highlights, Clear Results). 660 unit + 192 e2e pass; typecheck, lint, build clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oll rebind ComparePlus: the two panes now align line-by-line. The diff engine emits filler "gaps" for lines present on only one side; those render as block-widget spacers so matching lines stay horizontally aligned, and the panes scroll in lockstep. MarkdownViewer++: the synced-scroll listener now rebinds to the focused editor pane on tab/pane changes (previously bound once at mount), so scrolling follows the active document. (Content already tracked the active tab — verified via switch/close/reload/split e2e.) Tests: engine gap tests; compare-plus alignment e2e (spacer present + equal pane heights). 662 unit + 193 e2e pass; typecheck, lint, build clean. CHANGELOG updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
In split view: - Dropping a file lands in the pane the cursor is over (not just the focused pane); if that file is already open in the other pane, its tab is moved across rather than duplicated. - A tab can be dragged from one pane's strip onto the other to move it there. - FileActions.openDropped now delegates placement to a callback so the app can target a specific pane; App.openDocInView moves/creates + shows a doc in a given pane (falls back to primary when the pane doesn't exist). - The drop handler derives the target pane from the drop's element (guarded against non-Element targets like document, which previously threw). - TabBar tabs are draggable and each strip is a drop target (custom application/x-notepad-tab payload), wired to App.openDocInView. Tests: split-drag-drop.spec.ts e2e (drop into pane, move-across, tab drag). 662 unit + 196 e2e pass; typecheck, lint, build clean. CHANGELOG updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Improve tab strip overflow handling by: - Updating the overflow algorithm to always keep the active tab visible (never hidden in overflow), using a greedy left-to-right approach instead of checking if tabs extend past the cutoff - Actually hiding overflowed tabs with display: none to prevent them from occupying layout space and pushing the >> button off-screen - Resetting display state before each measurement to account for previously hidden tabs - Fixing the shell's grid layout with minmax(0, 1fr) and min-width: 0 to clip content to viewport instead of expanding the grid Adds regression tests for narrow viewport behavior and tab activation from overflow menu.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Checklist
-sflag on all commits)npm run lintpassesnpm run typecheckpassesnpm testpasses// SPDX-License-Identifier: GPL-3.0-or-later