- Rename `resolveTableIndex` useMemo value to `currentTableIndex` in Table.tsx
so the name reflects a computed value rather than an action; update all
references (callbacks, dependency arrays, JSDoc comment)
- Fix `escapeCell` in markdown-table.ts: replace the single-char lookbehind
regex `(?<!\\)|` with a character loop that counts consecutive backslashes
before each pipe and only inserts an escape when the count is even, mirroring
the parser logic and correctly handling sequences like `\\|`
- Remove redundant `as ColumnAlignment` type assertion in `createEmptyTable`;
TypeScript infers `\"none\"` correctly via contextual typing from the return type
- Add regression test for the `\\|` round-trip case in markdown-table.test.ts
Hoist `findAllTables(memo.content)` into a shared `useMemo` so the
markdown AST is parsed exactly once per `memo.content` change.
Both `resolveTableIndex` and `handleEditClick` now reference the same
cached `tables` array, keeping the lookup and edit paths in sync and
eliminating the duplicate parse that previously occurred on every edit
click.
- Replace regex-based TABLE_LINE scan in findAllTables with a proper
GFM markdown AST lookup using mdast-util-from-markdown + mdast-util-gfm
+ micromark-extension-gfm + unist-util-visit (all already in deps).
Tables without leading/trailing pipes (e.g. 'A | B\n--- | ---\n1 | 2')
are now correctly detected via node.position.start/end.offset.
- Add regression test asserting pipe-less GFM table is found with correct
start/end offsets.
- Fix parseMarkdownTable to split on unescaped pipes only (lookbehind).
- Fix import order in Table.tsx (Biome organizeImports).
- Fix useless escape \- → - in TableEditorDialog.tsx sort regex.
- Reformat long normalize/compareFn lines to satisfy Biome formatter.
Bugs:
- Fix replaceNthTable off-by-one: findAllTables now uses truly exclusive
end index (start + text.length) so content.slice(start, end) === text
- Replace fragile DOM-based table index resolution with AST-based approach
using node.position.start.offset from hast ReactMarkdownProps
Architecture:
- Unify TableEditorDialog instances: InsertMenu no longer manages its own
dialog, instead calls onOpenTableEditor from parent MemoEditor which
owns the single shared dialog instance
- Remove onInsertText prop chain (InsertMenu → EditorToolbar → MemoEditor)
replaced by onOpenTableEditor
Other improvements:
- Add i18n: all hardcoded English strings now use useTranslate()/t() with
new editor.table.* keys in en.json
- Fix useCallback [props] dependency that defeated memoization (removed
with dialog unification)
- Use stable row IDs (monotonic counter) as React keys instead of array
indices in TableEditorDialog
- Replace hardcoded MONO_FONT constant with Tailwind font-mono class
(maps to project's --font-mono CSS variable)
- Add 28 vitest tests for markdown-table.ts covering parse, serialize,
findAllTables, replaceNthTable, createEmptyTable with edge cases
- Add vitest dev dependency with test/test:watch scripts
Add a dialog-based table editor to create and edit markdown tables via a
visual grid instead of raw pipe-delimited text.
Features:
- Visual grid with inputs for headers and cells; add/remove rows and columns
- Sort columns (asc/desc, text and numeric); tab navigation (new row at end)
- Insert column/row between columns/rows via hover zones and + buttons with
blue highlight lines clipped to table bounds
- Sticky header with solid background; square headers; monospace cell font
- Row numbers with insert zones; delete row at row end; delete column with
spacing from insert button; Add row/Add column in footer and below table
- Delete table button on rendered tables (with confirm); edit pencil opens
dialog with parsed data; always-visible sort/delete at 40% opacity
- Fixed-size dialog (56rem x 44rem); /table slash command and Table in
InsertMenu open dialog; Command.action support for dialog-based commands
New: TableEditorDialog.tsx, utils/markdown-table.ts. Integration in
SlashCommands, EditorContent, InsertMenu, MemoContent Table.
Made-with: Cursor
Replace the standalone SSE dot above UserMenu with a small badge
overlaid on the bottom-right of the user avatar. Only visible when
status is connecting (yellow) or disconnected (red) — invisible in the
normal connected state, removing constant visual noise.
Add a comment preview section below memo cards in list view, displaying
up to 3 comment snippets with a "View all" link. Removes the old comment
count icon from the memo header in favor of this richer inline display.
Comment preview is hidden in memo detail view.
- Reduce themes from 6 to 4: system, light, dark, paper
- Remove midnight (too similar to dark) and whitewall (too similar to light)
- Drop all unused tokens: chart-*, sidebar-primary, sidebar-border,
sidebar-ring, shadow-2xs, tracking-normal, spacing
- Remove redundant @theme inline blocks from dynamic theme files
(Tailwind only processes them at compile time, not at runtime)
- Move shared tokens (fonts, radius) to default.css only
- Polish dark mode color palette
- Consistent cool-slate hue (h265) across all surfaces
- Proper surface layering: sidebar(0.07) → bg(0.09) → card(0.13) →
popover(0.17) → secondary(0.19) → muted(0.21) → accent(0.22)
- Foreground softened to 0.82 (from 0.9) — comfortable off-white
- Accent more chromatic than muted (0.012 vs 0.008) — hover feels interactive
- Popover elevated above card (0.17 vs 0.13) — floating elements visible
- Destructive more vivid (0.62/c0.20) — clearly red on dark surfaces
- Input border (0.25) more distinct than layout border (0.21)
- Sidebar foreground (0.68) dimmer than content foreground (0.82)
- Fix inline code background invisible in dark mode (#5674)
- Muted was same lightness as card — increased to 0.21 for clear contrast
Align header padding, text color, background tokens, and item row styles
across CodeBlock, AttachmentList, RelationList, and LocationDisplay so all
metadata panels follow the same visual pattern.
The explore page sidebar was showing tags from the current user's private
memos because the default ListMemos query applies a server-side OR filter
(creator_id == X || visibility in [...]), mixing private content in.
Fix by using a visibility-scoped ListMemos request in the explore context
so private memos are always excluded via the AND'd server auth filter.
Also consolidate two always-firing useMemos calls into one context-aware
query, unify activity stats computation with countBy across all branches,
and extract a toDateString helper to remove duplicated formatting logic.