Cditor-inspired: WYSIWYG polish, tables, windowed rendering, block reorder#52
Merged
Conversation
…gh text Cditor-inspired (issue #16 probe): the task box grows to 0.9em, a done box fills with the accent color under a white check, and a checked item's text renders struck through + muted — in BOTH views (reader draws the same box the WYSIWYG paints). Reveal-on-caret still shows plain source.
Cditor-inspired: gpui-component's Scrollbar overlaid on the feed and page scroll containers (full-inset overlay, its own helper's pattern — a right-anchored zero-width box gives the thumb no bounds). Fades in on scroll/hover per the theme's show mode.
…ews) Cditor-inspired: every fenced block gets top-right chrome. Reader: a hover-revealed language tag + Copy (writes the raw code). WYSIWYG: the same chip painted on the card — Copy writes the block body via the clipboard writer; the language tag opens a scrollable picker of the host's grammars (set_code_languages, new pub API) and selecting one rewrites the opening fence as one undo step. Zorite passes its compiled tree-sitter set plus text/mermaid (highlight::LANGUAGES).
Pre-existing since 1e0ffe6: `(a < b).then_some(a - start..)` evaluates its argument eagerly, so a token wholly before the current line underflows `b - start` (panic with overflow checks on — debug builds). First reachable on a multi-line highlighted block; surfaced by the new language picker. `then` (lazy) instead.
…iet gutter Follow-ups to the code-card chrome from user testing: - chips are hover-revealed (full-card hover tracking, the heading-chevron pattern), on an opaque popover-surface pill, at 13px - a fence reveals only with the caret/selection on its own line — editing inside the block no longer shows the fence markers (their language now lives in the chip); dead code_regions removed - picking a language parks the caret on the body's first line, not the fence (which would reveal it) - vertical caret movement skips zero-height (collapsed) rows in the travel direction, and end-of-document clamps to the last visible line — arrows can't land on (and reveal) either fence - the line-number gutter paints nothing for zero-height rows (the hidden fence got a number inside the card's pad gap)
Cditor-inspired restyle of the `/` menu (issue #16): - rows show a boxed glyph + title + one-line description; capped at 7 tall rows. The other completions (`[[`, `#`, `\`, `{{`) stay compact. - categories (Markdown, Templates) open a submenu that flies out beside the main panel instead of replacing the list; hover / arrow / Enter to focus it, Esc steps back, hover the main list to return. Positioning polish (the hard part): - the flyout is an ABSOLUTE child of the main panel, so it never inflates the anchored element — gpui always snaps an overflowing anchored box into the window, which was yanking the whole menu up as you hovered. With only the stable main panel anchored, it sits cleanly below the caret and doesn't move when the flyout shows/hides. - the flyout doesn't auto-open on a fresh `/` (a `flyout_shown` flag, set only on deliberate hover / arrow / Enter). - the flyout shifts up when it would overflow the window bottom (the caller replicates where snap lands the main panel, then offsets). - a transparent backdrop under the menu dismisses it on an outside click (on_mouse_down_out fires in capture phase against only the main panel's bounds, so it would have closed on flyout-row clicks).
The rest of the menu-family restyle (issue #16): - the shared page menu (sidebar rows, All Pages, search, backlinks) and the tab menu get Lucide icons per row and a RED "Delete page" (label + trash icon in the theme's danger color); the sidebar's "New page" and the formula/Edit right-click menu get icons too - selection right-click grows an inline-format bar across its top: B / I / U / S / <> toggle bold, italic, underline, strikethrough, and inline code on the selection (the editor's toggle-wrap, so a second press un-wraps); spell suggestions + clipboard verbs sit below - NEW: underline (cmd-u) via the <u> tag — markdown has none — honored in BOTH views like <mark>: WYSIWYG hides the tags and underlines the body (toggle_wrap generalized to open/close pairs), the reader underlines the wrapped runs; "Underline" joins the slash palette; NEW: strikethrough action (cmd-shift-x) - every menu (app + all five in-editor popups) carries the same drop shadow, so the family reads as one system - six Lucide faces newly embedded for release builds: trash-2, app-window, file-text, file-down, align-center, align-right
…eletes The table-interaction pass (issue #16): the right-click table menu becomes grouped Cditor-style rows (glyph column, checkmarks, shadow) and grows real new verbs: - Duplicate row (duplicate_table_row — header duplicates as the first body row; caret lands in the copy, same cell + offset) - table styles in the menu (set_table_style rewrites the <!-- table:STYLE --> marker as one undo step, caret stays put) with the current style checked — previously pickable only at creation - Copy as Markdown (copy_table — grid + style marker via the clipboard writer) - alignment rows check the cell's current alignment - the delete group (row / column / table) renders red via the new SyntaxStyle::popover_danger (host-themed; zorite passes a Radix red) API.md documents the three new methods + field.
…r pills The hovered row/column now reads by BORDER, not fill (issue #16, Cditor's look): a thin accent outline around it, plus a small accent capsule sitting ON the table border — "+" / "−" halves with a hairline divider — replacing the old outside strips and gutter handles. Row pill on the left border (insert below / delete row); column pill on the top border (insert right / delete column) — column inserts now land right of the HOVERED column, not the last. Hover the last row/column to append. The caret's cell carries a quieter accent outline, and the column highlight yields while the pointer is on the row's pill.
Cditor's column resizing, zorite-style (issue #16): each column's right border becomes a grab band (resize cursor, accent line when hovered) and dragging resizes the column LIVE; release persists every column's width into the table's marker comment — <!-- table:grid cols=142,96,210 --> — so it's plain markdown both views honor and other viewers ignore. One undo step per drag; the style menu and resize preserve each other's marker attributes. Cells word-wrap once a drag narrows a column under its content: the row grows to the tallest cell's wrap rows, the caret seats on the correct wrap row, and clicks hit-test in 2-D inside the cell (alignment applies only to unwrapped cells). While the pointer is on a resize band — or a drag is live — the row/column outlines + pills yield to it. Recognition consolidates in gpui-markdown's syntax module (the sanctioned direction): the shared TableStyle replaces gpui-editor's duplicate, and table_col_widths / table_marker_text parse + write the cols= attribute, with tests.
…IWYG Bold/italic (* and _), strike, inline code, <mark>, and <u> markers now NEVER show in WYSIWYG — not under the caret (the old per-construct reveal) and not under a selection (the old whole-line raw reveal). The styling is the feedback; the toggles (⌘B/I/U/⇧X/E, the selection format bar) edit it — the model Cditor gets by converting typed markers to styled spans. Structural constructs (links, wiki links, headings, math) keep reveal-on-caret: their raw text is the only way to edit them. An unclosed pair still shows while you type it. Caret movement is by VISIBLE position now: left/right (and shift-select) extend their grapheme step while the display column is unchanged, so the zero-width marker bytes never cost extra keypresses. Selected lines keep the hidden view with correctly mapped highlight geometry. New always_hide span flag + fmt_marker() in the scanner; tests updated to the new contract plus a never-reveal matrix.
Backspace / forward delete now remove the adjacent VISIBLE character — at a construct's edge the invisible marker bytes are skipped, so a hidden ** / ~~ / ` / <u> / <mark> is never half-eaten into revealed junk. Deleting a construct's last character collapses the construct: the now-empty marker pair goes with it as one edit (one undo step), matching deleting the last char of a bold run in Cditor. fmt_marker_pairs (new, tested) returns the opening/closing marker pair per construct — pairing is per-construct so a delete between two adjacent constructs can't fuse one's closer with the other's opener — and fmt_delete_range plans the edit (skip → visible grapheme → pair collapse), bowing out inside code fences and across line joins.
…ectors JYChen-8866 forked gpui-whiteboard as Cditor's `ding-board` and built on it; this brings his work home (issue #16). New with this adoption: - mind-map tool: seeded root+branches with per-node metadata, auto layout, sides/direction, straight/bezier/orthogonal connectors, and "+" add-node buttons on the selection - flowchart tool: seeded Start/Process/Decision/Yes/No/End scaffold - shape-bound connectors: line/arrow endpoints snap to shapes' connector points and FOLLOW them through move/resize/rotate (SegmentAnchor; detach on moving the segment); dashed segment style - alignment guides + snapping while dragging elements - perf: viewport culling (render_perf's WorldViewport) and cached text/label layouts — his fork's answer to our "defer until measured" - read-only mode, BoardEmbedView (embedded board + host-driven Edit button), BoardThumbnailView + LocalThumbnailSnapshot (static previews) - font: system CJK fallback face behind the bundled JetBrains Mono All new scene fields are serde-defaulted, so existing boards load unchanged. Zorite-side: importers/tests gain the new fields; UI strings localized from Chinese; his additions brought up to the clippy gate. README adopted; API.md documents the new surface. His tests (a superset of ours) ride along.
table_cells / table_cell_ranges split blindly on '|', so a cell holding an escaped pipe miscounted against the reader's GFM parse (grid, caret, and click hit-tests disagreed with the rendered table) — and rewrite_table_columns' split+rejoin then CORRUPTED the row on any column insert/delete (the cell became two, shifting every later column). Splitting now skips pipes preceded by an odd backslash run; cells stay VERBATIM source (the escape visible in the grid), so ranges/caret math keep their exact source mapping and rewrites round-trip. Found auditing against Cditor's table.rs, which unescapes+re-escapes.
Two paste bugs from the Cditor audit: - a Windows/browser clipboard carries \r\n (or bare \r); pasting put literal \r bytes into the buffer — garbled rendering and desynced \n-based row/column math. Normalize to \n on paste. - pasting text with newlines/pipes inside a table cell split the `| … |` row markup, though Enter is carefully guarded there. Flatten newlines to spaces and escape pipes (unescape-first so an existing \| doesn't double), keeping the paste one cell's content — consistent with the new escape-aware cell splitting.
Two reader/editor divergences from the Cditor audit: - inline code now matches backtick RUNS: an opening run of N backticks closes at the next run of exactly N, so ``a`b`` keeps its inner backtick as body; a run with no matching closer is skipped whole (one token, CommonMark) instead of re-matching a shorter span inside itself. - backslash escapes are honored for * (bold + italic), ~~, the backtick opener, and every [ construct (links, wiki links, footnotes): \*text\* now stays literal in WYSIWYG exactly as the reader shows it, and an escaped closer no longer closes. Shared is_backslash_escaped (from the \| table fix) + _unescaped find variants; `_` already checked.
A backslash escape's `\` now renders as a hidden marker (reveal-on- caret), so `\*text\*` displays *text* and `\**bold**` displays exactly what the reader renders (literal star, italic body, literal star) instead of leaving the backslashes visible. The escaped character stays literal content — no construct can open on it — and `\\` shows a single backslash. Follow-up to the escape-honoring scanner fix, verified against the reader's GFM parse.
…vely The last reader/editor divergence from the Cditor audit's bug list: scan_line consumed a construct wholesale, so **bold *italic* bold** rendered its inner markers as literal text with only the outer style. The inline loop is now scan_inline, recursive: a formatting construct's body (bold/italic both forms, strike, <mark>, <u>) re-scans with the construct's style layered as the base (Style::over — booleans OR, options prefer the inner construct's), the gaps between inner constructs fill with the body style, and depth caps at 3. Inline code, links, wiki links, tags, and bare URLs inherit the enclosing style without recursing (code bodies stay literal per CommonMark). Marker pairing moves from adjacency to shared pair_ids stamped on each construct's opener+closer, so fmt_marker_pairs — and the Cditor-style delete collapse built on it — survives nested constructs between a pair's markers.
Three audit items in one pass: - the measure pass memoizes its full shape_document output (ShapeMemo, RefCell — the closure only holds a read borrow) and prepaint consumes it when the wrap width / caret / selection / font size match — the whole document was being shaped TWICE per frame with identical inputs. Taken-once semantics: the memo can never go stale across frames, and a key mismatch just falls back to shaping. - UTF-8↔UTF-16 conversions resume from an anchor of the last converted offset (valid per content generation) instead of scanning from byte 0 — IME composition fires these many times per keystroke, so CJK composition latency no longer grows with note size. The new content_gen counter (bumped in record_edit + the three bypasses: set_text, undo/redo restore, IME replace_and_mark) is also the staleness key a future cross-frame shape cache needs. - bounds_for_range spans the whole marked range when it sits on one wrap row, so the IME candidate window anchors under the composing text instead of a zero-width bar at its start.
shape_document re-derived every structural scan on each call — table regions, ordered-list numbering, mermaid blocks, math regions, property runs, foldable callouts — all O(document) walks that ran on every frame (twice, before the shape memo). They now live in ScanData, cached on EditorState keyed by content_gen, rebuilt only when the content changes. The same scan feeds the caret-driven table ops (align/menu/duplicate/ style/resize used to call table_regions on every click) and the fenced- code parity guard: apply_auto_replace re-scanned every line above the caret on each boundary keystroke, and fmt_delete_range on each delete — both now read the scan's per-line fence_odd.
…'t jump Cditor's anchor-restore, adapted (its AnchorFrame::restore_once): a math/mermaid/image raster arriving collapses raw source lines into a rendered block, shifting every line below — including whatever the user was reading. The measure pass now detects it (same content_gen as the last paint but different line tops ⇒ the height change was async, not an edit), and when the first changed row sits above the window viewport it hands the delta to a host hook (set_scroll_compensator, new pub API) BEFORE the scroll container places its children — the feed/page scroll offset absorbs the shift in the same frame. Edits never trigger it, and a width change (resize reflow) is excluded. Both hosts wired; API.md documents the hook.
The audit's cross-frame item, right-sized: gpui's own LineLayoutCache already retains glyph shaping across frames, so the residual per-frame cost was rebuilding every markdown line's display string + run list (hidden_runs) on every repaint — caret blinks, hovers, and any edit in ANOTHER feed editor re-derived every visible day's every line. Each line's built (display, runs, map) is now cached across frames, keyed by a hash of the line bytes, its reveal state (caret column, prefix reveal/hide, selection reveal), its diagnostics, and a font+ palette epoch — with the source line verified on hit, so collisions can't render the wrong text. Edits re-key only the lines they change; theme/font switches miss wholesale via the epoch. Capacity-capped so retired keys from typing can't accumulate. (A full WrappedLine-level cache needs Clone that gpui's WrappedLine doesn't have — this captures the same win without the ownership refactor.)
…ames table_column_widths shaped every cell of every table per shape_document call, and table_row_wrap_rows re-shaped each drag-narrowed row's cells per frame. Bundle the editor's shaping caches into one ShapeCaches struct (line runs + a keyed region_cols entry + a per-row wrap-count memo); rebuilt only when the tables' source, the wrap width, the font epoch, or a live column drag changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…menu Cditor-style: hovering a new "Turn into" row opens a kind-list flyout (Text / H1-H3 / bulleted / numbered / to-do / quote / callout / code / math) with the caret block's current kind checked. Flat-markdown conversions — a line-prefix rewrite in one undo step; quote runs and fenced code/math blocks convert whole, and fenced targets seat the caret inside the body so the markers stay hidden. The flyout floats as an absolute sibling of the clipped menu box so it can't inflate the anchored bounds (the slash-flyout lesson). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ws span A body row with more cells than the header used to hide the excess (and a caret seated there could panic on a col_widths slice). Reader parity instead: the grid's column count is the max cell count across the region's rows, and a short row's last cell spans the remaining columns with no divider — paint, caret math, click hit-testing, and the caret-cell outline all follow the span via cell_span_width. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
In reader mode every loaded day rebuilt its full MarkdownView element tree per frame, making feed scrolling slow. The feed column now tracks each day section's bounds (a second ScrollHandle that never scrolls), and days more than a viewport-height offscreen render as fixed-height spacers using their last measured height, so the scroll geometry is preserved. Fully rendered days refresh their recorded height each frame; a width change clears the cache. WYSIWYG days (one cached editor element each) and feed-find sessions (which need every day's blocks painted) always render fully. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…aint The document-scale half of the Cditor audit's L item, without the estimated-heights machinery (heights stay exact, so no convergence jumps; the honest ceiling is that a document's FIRST shape is still O(doc), cached thereafter): - Geometry reads a new per-line wrap-row count (ShapedLines + committed EditorState/PrepaintState vecs) instead of wrap_boundaries(), so a line's layout no longer needs its shaped text. - Paint culls lines outside the window viewport (nesting-guide bookkeeping still walks offscreen ancestors' marks). - shape_document takes a quantized viewport band (published one frame stale from prepaint so measure + prepaint always agree and the ShapeMemo keeps hitting): plain markdown lines wholly outside it skip run-building and shaping, reusing exactly-cached (row height, wrap rows). Caret/selection lines, code, tables, math, images, embeds, and folds always shape fully. Also two scroll-anchoring fixes this surfaced (sandbox-reproduced: the "stuck feed at a narrow window" bug): the compensator now only reacts to measures at the real final width — taffy's intrinsic-width passes produced multi-thousand-px bogus deltas that yanked the feed offset and fought the user's scrolling (and broke drag-and-drop mid-yank) — and a once-per-paint latch stops one async raster arrival from compensating once per measure call. ZORITE_WINDOW_DEBUG=1 logs compensator events. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cditor/Notion-style: hovering a line reveals a six-dot grip in the left margin (left of the line-number rail when it's up — the host pads for it via set_grip_inset); dragging it moves the line's whole block, with an accent bar marking the drop boundary. Blocks travel as units: fenced code, tables + their style marker, math/mermaid regions, property panels, quote/callout runs, and list items with their deeper-indented children. Drops snap out of rendered-region interiors, and the move is ONE undoable splice of the span between block and target. The grip lives OUTSIDE the editor div's bounds, so the press, the drag tracking, the drop, and hover-row repaints all run through window-level mouse listeners gated on painted rects — the div's own listeners never see gutter events (and its hitboxes report unhovered out there). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A viewport-sized hitbox inserted above the editor's own keeps the grab cursor while the pointer crosses text (which would flip it to I-beam). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Natural content-fit columns always (the scale-to-fit pass is gone); a table wider than the viewport scrolls in place — horizontal wheel/ trackpad over it moves it (vertical still scrolls the page), a slim thumb under the last row shows the position, and rows paint shifted under a per-row content mask (the outer Grid border gets its own full-height mask). All x hit-testing — cell clicks, hover pills, resize bands, the caret and selection — applies the same offset. Table source lines now shape unwrapped: their raw `| … |` text is hidden, and a wrapped source would multiply the row's height. Matches the reader, which already scrolls over-wide tables in their row. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two caret leaks flashed the raw `<!-- table:… -->` marker: the drag's commit re-seated a caret that wasn't in the table into a fabricated "cell" on row 0 (the marker line) — it now stays where it was, shifted by the edit's byte delta — and a band press right after a document loads focused the editor with the caret still parked at offset 0 on the marker line — it now seats into the header cell before the drag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Table selection quads now paint one full-height band per row: wrapped cells highlight every wrap row, and vacant trailing cells highlight to the table's edge (endpoints inside a cell keep the exact caret x; an empty cell the shaper can't position falls back to the edge). Collapsed rows (the |---| separator, hidden marker/fence lines, folds) paint no quad — they used to smear a base-height band over their neighbors — and a wide scrolled table's bands clamp to its visible area. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same bug tables had: a long `{width=N}` source wrapping at a
narrow window multiplied the image row's height by its wrap count.
Widget lines now shape unwrapped; revealed-on-caret lines still wrap.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two ultrareview findings on PR #52: - The gutter grip's window-level press listener gated on a bare rect, so a drag could start THROUGH a dialog/menu/popover covering the gutter. It now gates on the grip hitbox's is_hovered, which respects gpui occlusion (BlockMouse hitboxes above it win). - Turn-into's hand-rolled prefix grammar diverged from the renderer's: `* [ ]`/`+ [ ]` tasks classified as bullets, `1)` lists and indented items inconsistently, any `[!garbage` counted as a callout, and the strip/detect/render grammars could triple-drift. block_kind_at, strip_block_prefix, and the quote-run walks now compose the renderer's own recognizers (task_prefix/list_prefix/heading_level/ blockquote_prefix/alert_kind) — one grammar, three consumers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The invariant, enforced once: set_text — the only PASSIVE caret-parking path — steps a caret landing on a `<!-- table/math:… -->` marker line to the table's header (or past the math block), so every focus-without-caret-move affordance (pills, delete handles, code Copy, fold chevrons, image grips, resize bands) is safe by construction. Deliberate navigation onto a marker still reveals it for editing. The resize-band point patch this replaces is deleted. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A persisted light/dark choice still wins; unknown persisted values now fall back to Auto too. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI caught what the local gate missed: running `cargo check -p` before `cargo clippy` can reuse the check fingerprint and skip lints, so the gate printed clean while CI's fresh clippy failed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Five of the six ultrareview dedup findings: - table_left(): THE single source for a (possibly scrolled) table's content-left, replacing six hand-built `bounds.left + GUTTER - sx` sites including paint's inline clamp fork (the cloned sx map is gone). - fence_block_rows() + quote_run_rows(): one fence walk and one quote run walk, replacing three copies of each across turn_into, drag_block_rows, snap_drop_boundary, and block_kind_at. - grip_left(): the grip x formula shared by prepaint and the event-time hover mirror, so the two can't drift. - is_escaped deleted — is_backslash_escaped is the one escape predicate. - menu_turn_into moved into DiagMenu, so the flyout flag dies with the menu instead of leaking across opens. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Named per-line channels instead of positional .0-.8 access, and ONE push_placeholder method replaces the seven hand-replicated empty-placeholder blobs (mermaid/math/embed/fold/props arms + the windowed skip path) — the parallel-vec lockstep invariant now lives in the type. Last of the six ultrareview dedup findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Hover listener: none for raw editors, O(1) x/y bail via a read-only check before any entity update (was: N editor updates + full line scans per pointer move across the feed). - on_scroll_wheel bails on dx == 0 before the O(lines) row walk. - line_runs cache payloads are SharedString/Rc — a hit is three refcount bumps, not three deep clones per visible line per frame; the maps channel shares the same allocation, inline math/image calls are span-gated, and the display string feeds shape_runs directly. - region_cols keys on the scan generation (no per-frame rehash of all table text) and stores Rc (hit = pointer bump). - Per-row content-key memo: steady-state frames hash three u64s per line instead of every line's bytes for the run/height cache keys; diagnostics changes invalidate explicitly. - Slash flyout rows cached per (level, title) instead of rebuilt every frame and twice per arrow key. ScanData carries its generation; ShapedDoc.maps is Rc-shared. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A selection with both ends inside the same wrapped cell now paints one band per wrap row (start x → cell edge, full-width middles, cell edge → end x) instead of a single band that covered only part of the text. Cross-cell and full-row selections keep the full-height row band. Also the type_complexity lints CI caught: RowKeys/RegionCols/FlyoutCache aliases. Root cause of the recurring local-pass/CI-fail gap found: the local gate ran clippy WITHOUT `-- -D warnings`, so default-warn lints printed as warnings the error grep ignored — the gate now mirrors CI exactly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
The full port of what we liked from JYChen-8866's Cditor (issue #16) into zorite's flat-markdown engines, plus the follow-on audit fixes. 41 commits:
Features
<>)<!-- table:STYLE cols=… -->, and wide tables scroll horizontally in place (natural column widths, masked paint, slim thumb) instead of scaling downPerformance (from the Cditor audit)
Fixes
\|handling through cell split/rewrite, CRLF paste normalization, double-backtick spans, nested inline emphasis, ragged-table grid widening with row spans, selection-highlight bands (full-height rows, no phantom stripes), table style-marker reveal leaks, unwrapped hidden sources for table/widget rows🤖 Generated with Claude Code
Credits
Huge thanks to @JYChen-8866 (jychen), who wrote Cditor specifically to contribute its editor to Zorite (#16). This PR ports its best ideas into Zorite's flat-markdown engines — the table interactions, marker-hiding behavior, menus, code cards, and drag-reorder are all his designs — and the whiteboard improvements are his ding-board fork adopted wholesale. The multi-window virtual-rendering architecture in Cditor also directly informed the windowed-rendering work here.