Commit Graph
349 Commits
Author SHA1 Message Date
Amit Haridas de7ebecad4 feat(quick-switcher): pure fuzzy matcher + ranker
Tiered scoring (exact 1.0 / stem 1.0 / prefix 0.8 / subseq 0.5+bonuses
capped 0.79) with leftmost+rightmost greedy alignment — rightmost wins
for extension/suffix queries ('md' against 'readme.md'), leftmost wins
for prefix queries ('re' against 'readme.md'). Boost-aware rankResults
applies recency x2 and open-tabs x1.5 multiplicatively; empty query
falls back to boosts alone.

Pure module, no DOM/IPC/Node — runs in renderer or main. 22 new tests.

Amit Haridas
2026-09-30 19:53:44 +05:30
amitwh 23046967c3 feat(flowchart): discoverable connect form + per-node color + save-to-file export; v4.12.0
User feedback on v4.11.0: the Add Connection form was buried below the
node/edge lists and they couldn't find it; they also asked for per-node
color and Save to File export. v4.12.0 reorganises the #fc-nodelist panel
to put the connect form right after the Add Node buttons, adds a native
<input type="color"> per node row that drives a new store.setNodeColor
mutator (with serialize/deserialize round-trip), and wires a Save to File
button that pops a system save dialog via a new 'save-text-file' IPC
channel.

- src/flowchart-generator.html — panel order is now Add Node /
  Add Connection / Nodes / Edges / Export (Insert · Save · Reset).
  Removed the legacy top toolbar; status moved into the panel.
  Added .fc-help, per-node color-picker CSS, .fc-toolbar-row.
- src/flowchart/flowchart-shapes.js — shapeSvg() accepts an optional
  6th 'color' arg; emits fill=... on rects and polygons. Falls back to
  #ffffff for empty/null/undefined so old callers keep working.
- src/flowchart/flowchart-store.js — setNodeColor(id, color) mutator
  with snapshot/emit, normalizeColor() helper (hex validation),
  addNode accepts color, deserialize normalises missing color.
- src/renderer/flowchart-bundle.js — mirrors all of the above inline
  (the bundle is loaded as a single <script>), wires fc-btn-save to
  api.saveFile, passes node.color to shapeSvg in the canvas render,
  and renders <input type='color'> per node row.
- src/main.js — new ipcMain.handle('save-text-file', ...) using a
  system Save dialog (mirrors the ascii:save handler shape).
- src/preload.js — added 'save-text-file' to ALLOWED_SEND_CHANNELS
  and a saveFile(content, defaultName) helper on the flowchart bridge.

Tests: 92/92 suites, 1165/1165 tests pass on this run
- +9 store tests (color defaults, setNodeColor, undo, hex validation,
  round-trip, deserialize normalisation)
- +7 shapes tests (fill color on all 5 kinds, fallback to #ffffff)
- +6 controller tests (color picker wires setNodeColor, canvas rect
  reflects color, Save to File calls api.saveFile with the fenced
  Mermaid source and 'flowchart.mmd', cancel + error paths surface in
  status)

Verification:
- npm run lint          clean
- npm run format:check  clean
- npm test              92/92 suites, 1165/1165 tests pass

Amit Haridas
2026-09-15 09:23:58 +05:30
amitwh e87e301b0f chore: remove stale debug-copy + drop placeholder string-split hack; v4.11.1
- Remove untracked root-level flowchart-bundle.js (older v4.10.0 copy
  that had drifted from src/renderer/flowchart-bundle.js; never loaded
  by Electron, just repo noise).
- In src/renderer/flowchart-bundle.js, replace the runtime
  concatenation "'place' + 'holder'" with the proper 'placeholder'
  attribute at the two label-input call sites (node + edge) and
  remove the now-stale comment explaining the hack. No functional
  change.
- Bump version 4.11.0 -> 4.11.1 in package.json and README.md and add
  the matching UPDATES.md entry.

Verification:
- npm run lint          clean
- npm run format:check  clean
- npm test              92/92 suites, 1143/1143 tests pass on this run
- PDFBatchOperations.test.js passes 21/21 in isolation
  (the occasional failure seen in the v4.11.0 run was a parallel-test
  file-IO race, not introduced by these changes)

Amit Haridas
2026-09-15 08:10:35 +05:30
amitwh 075e407f3f feat(flowchart): button-based UI replaces click-canvas interaction; v4.11.0
Replaced the v4.10.0 floating selection toolbar (which relied on
SVG click hit-testing inside #canvas-host and was unreliable in the
user's Electron runtime) with a button-driven node-list panel
(#fc-nodelist) below the canvas. Every mutation now flows through
explicit controls: 5 Add Node buttons, per-node kind-select +
label-input + delete ×, per-edge kind-select + label-input + delete
×, and a Connect form (From/To selects + Edge button + Refresh).

The canvas is purely visual now: no more #fc-selection-toolbar, no
controller-level _selectedId/_selectedKind state, no keyboard
Delete/Backspace selection handler. Canvas click callbacks
(onNodeClick, onEdgeClick, onShapeMenu) are no-ops. The 5-shape /
3-edge-kind / label-input / delete-button surface is unchanged in
spirit — it just lives in the panel instead of floating over the
canvas.

Files:
- src/flowchart-generator.html: added #fc-nodelist between canvas and
  preview (wrapped in new .fc-left column), removed fc-selection-toolbar,
  bumped header hint.
- src/renderer/flowchart-bundle.js: removed SHAPE_BUTTONS/EDGE_BUTTONS,
  setSelection, renderSelectionToolbar, appendLabelInput,
  appendDeleteButton, the keyboard Delete handler, and the
  controller-level selection state. Added rerenderNodeList +
  shapeLabel/edgeLabel, wired all panel buttons (add-row, per-node
  selects/inputs/deletes, per-edge selects/inputs/deletes, connect
  form). Subscribe now calls rerenderNodeList instead of the old
  renderSelectionToolbar.
- tests/flowchart-controller.test.js: replaced 6 v4.10.0 selection
  toolbar tests with 11 v4.11.0 button-driven panel tests.
- package.json: 4.10.0 -> 4.11.0.
- README.md: version line bumped to v4.11.0.
- UPDATES.md: added v4.11.0 changelog entry.

Test summary: 92 suites, 1143 tests pass (was 1138 — +5 net).
Lint + prettier clean.

Amit Haridas
2026-09-15 01:33:17 +05:30
amitwh b81119026e feat(flowchart): visible selection toolbar + console-log diagnostics; v4.10.0
Even after the v4.9.9 inline-modal fix the user kept reporting 'no fix still'
because hidden right-click context menus and window.prompt calls remain
unreliable in Electron renderer contexts. This release ships a *visible*
floating selection toolbar inside the canvas panel so the primary
interactions are not hidden behind modals or context menus.

- New <div id="fc-selection-toolbar"> inside #canvas-host, hidden until a
  node or edge is selected. Renders:
    * 5 shape buttons (Process / Decision / Terminator / Subroutine /
      Document) when a node is selected, calling store.setNodeKind on
      click. The active shape is highlighted.
    * 3 edge-kind buttons (Solid / Dotted / Thick) when an edge is
      selected, calling store.setEdgeKind.
    * An always-visible label input that mirrors the selected item's
      label and writes back via store.setNodeLabel / store.setEdgeLabel
      with a 100ms debounce.
    * A red Delete button calling store.removeNode / store.disconnect.
- Selection state now tracked at the controller level (_selectedId +
  _selectedKind) and exposed via window.FlowchartController so the
  keyboard Delete/Backspace shortcut and the toolbar share one source
  of truth.
- Console-log instrumentation on every canvas event (pointerdown with
  altKey, pointerup with drag result, dblclick, contextmenu, selection
  changes, and every bootstrap phase) so the user can open DevTools
  (Ctrl+Shift+I) and verify Alt+drag and double-click actually fire.
- promptInline / confirmInline kept as advanced fallback for the
  right-click 'change shape' path; the toolbar is now the primary
  interaction surface.
- Preview-render pane now shows a static info card explaining that the
  canvas on the left is the rendered chart (previously blank).
- 6 new tests in tests/flowchart-controller.test.js — toolbar hidden
  by default, selecting a node populates shape buttons + label input +
  Delete, clicking a shape button updates the kind, label input is
  debounced, edge selection populates edge-kind buttons, Delete button
  removes the selected node.

Total tests: 1127 passing (was 1121; +6 new). The 11 pre-existing
PDFOperations failures are unrelated to this change.
2026-09-15 00:40:01 +05:30
amitwh 81e8561403 fix(flowchart): replace window.prompt/confirm with inline modal in standalone window; v4.9.9
Electron renderer contexts return undefined from window.prompt/window.confirm,
so shape change, edge kind, edge label, and reset confirmation did nothing.
Bundle now ships promptInline/confirmInline (custom DOM overlay modals) and
uses them in onEdgeClick / onShapeMenu / reset handler. Exposed as
window.FlowchartModals for jsdom tests.

Amit Haridas
2026-09-15 00:27:24 +05:30
amitwh ca5983e9ff fix(flowchart): bundle pure modules into single file for standalone window; v4.9.8
Amit Haridas
2026-09-15 00:09:57 +05:30
amitwh 86d4c0d23a fix(flowchart): expose pure modules as window globals for standalone window; v4.9.7
Each pure module's UMD wrapper assigned window.FlowchartXxx only in the else branch — when 'module' was undefined. But the renderer runs with nodeIntegration:true, so 'module' is always truthy and the else branch never ran. The standalone Flowchart Generator window then aborted with 'Flowchart pure modules not loaded'.

Fix: append 'if (typeof window !== undefined) window.FlowchartXxx = exported;' after the CommonJS branch in all 4 pure modules (store, shapes, mermaid, canvas). Both branches can run now; the legacy sidebar panel still loads them via require() and the renderer unconditionally exposes the global.

Regression guard: 4 new source-grep tests in tests/flowchart-controller.test.js assert each module's source contains the 'window.FlowchartXxx = exported' assignment.

Attribution: Amit Haridas
2026-09-14 23:59:50 +05:30
amitwh 5f846d1e5f refactor(flowchart): standalone window (Cmd+Alt+F) replaces sidebar panel; v4.9.6
Five fix rounds (v4.9.1 → v4.9.5) couldn't make the sidebar flowchart
panel feel right — at 280 px sidebar with canvas + preview cramped to
~175 px each, plus the editor-container hide/show dance the
maximize/restore toggle required, the panel kept presenting as
cramped and unreliable at runtime. Strategy pivot: the flowchart
editor now lives in its own BrowserWindow, matching the ASCII Art
Generator pattern.

- src/flowchart-generator.html — new standalone HTML with header,
  toolbar (Insert at Cursor / Reset), canvas host, and preview host.
  Stylesheet hrefs are src/-relative (no ../). Forced light surface
  via background/color !important rules — mirrors the v4.9.5 CSS fix.
- src/renderer/flowchart-controller.js — pure browser IIFE. Hydrates
  from <userData>/flowchart-session.json once on mount, persists on
  every mutation with 500 ms debounce. Insert at Cursor wraps the
  generated Mermaid source in a fenced ```mermaid block and sends
  it through the existing insert-content IPC.
- src/main.js — openFlowchartGenerator() launches the standalone
  BrowserWindow (1100×720, contextIsolation:true, nodeIntegration:false).
  Tools menu entry 'Flowchart Generator' with Cmd/Ctrl+Alt+F.
- src/preload.js — new window.electronAPI.flowchart.* namespace with
  getUserDataPath/readFile/writeFile/insertAtCursor, reusing the
  existing thin text-file IPC handlers.
- The four pure modules (flowchart-shapes.js, flowchart-mermaid.js,
  flowchart-store.js, flowchart-canvas.js) gained a tiny UMD wrapper
  so they work both as CommonJS (legacy sidebar) and as browser
  globals (standalone window). No behavioural change to the 73
  flowchart unit tests in tests/flowchart-*.test.js.
- src/renderer.js — sidebar registerPanel('flowchart', ...) and the
  commandPalette entry are now commented out. Legacy panel file
  (src/sidebar/flowchart-panel.js) preserved for rollback.

Tests:
- tests/flowchart-controller.test.js — 10 new tests covering
  stylesheet paths (no ../ escape), bootstrap wiring
  (getUserDataPath once, reads flowchart-session.json), hydration
  from a saved session, Insert-at-Cursor fenced block format,
  Reset (with and without confirm), and two regression tests that
  src/renderer.js no longer has a live sidebar registration.

All 1122 tests pass; lint + format clean.

Amit Haridas
2026-09-14 23:50:25 +05:30
amitwh 9557c0af4d fix(flowchart): ensure rendered SVG + selection visibility; force light theme in canvas; v4.9.5
v4.9.4 shipped three interaction bugs in the Flow Chart panel that combined to make it look broken at runtime: (1) .flowchart-preview-render had no min-height, so the Mermaid SVG clipped to 0 when the sidebar flex column shrank; (2) the canvas + preview hosts inherited the body.theme-concreteinfo dark theme, producing dark-on-dark nodes; (3) .flowchart-node.selected only set a 2px stroke on the rect's existing dark fill, which was effectively invisible.

Fix: styles-sidebar.css adds min-height: 120px on .flowchart-preview-render; forces a light background on .flowchart-canvas-host / .flowchart-preview-host with !important so theme inheritance cannot override it; forces explicit white fills and dark strokes on .flowchart-node rect/polygon/text and .flowchart-edge so labels read against any background; selection now changes fill (#e3f0ff) AND bumps stroke-width to 3 on both nodes and edges. renderer.js renderFlowChartMermaid now always initializes Mermaid with theme: 'default' regardless of body class — keeps the Mermaid SVG light to match the CSS-forced canvas surface.

Three new CSS regression tests in tests/flowchart-panel.test.js read the shipped stylesheet and assert the three structural invariants (non-zero min-height on render target, !important light background on canvas+preview hosts, fill + stroke-width >= 3 on .flowchart-node.selected).

Tradeoff: the flowchart surface is now always light, diverging from body theme. Visibility of a working editor is the priority per user direction.

Amit Haridas
2026-09-14 23:09:23 +05:30
amitwh d31ed86fab fix(flowchart): wire selection + layout precedence; v4.9.4
- Add opts.onNodeClick + surgical applySelectionHighlight() so node/edge clicks immediately paint .selected and mirror id into panel state (Delete/Backspace works on freshly-clicked node).
- Add Maximize/Restore button to flowchart toolbar: toggles .main-content.flowchart-takeover which hides .editor-container and lets the canvas + preview split the full window width instead of the 280px sidebar.
- destroy() clears the takeover class so the editor stays usable after leaving the panel.
- 8 new tests in tests/flowchart-panel.test.js for selection wiring and takeover.

Amit Haridas
2026-09-14 23:00:47 +05:30
amitwh e0945b427d fix(flowchart): prevent preview-source duplication; v4.9.3
The flowchart preview pane accumulated raw Mermaid source when the user
fired several addNode mutations within the 250ms debounce window —
mermaid.run({nodes:[div]}) is async, so the previous render's
<div class="mermaid"> (still carrying the source text) sat in
.flowchart-preview-render when the next render cleared the target. The
first render's eventual element.innerHTML=svg landed on a detached node,
but the visible preview pane had a stack of stale <div class="mermaid">
elements carrying the source.

Fixed by switching renderFlowChartMermaid (src/renderer.js) to
replaceChildren() and adding a per-target WeakSet in-flight tracker so
the new render always starts from a clean slate and the previous render's
eventual innerHTML=svg is harmless on a detached node.

Added a second regression test that fires 7 mutations inside the debounce
with a renderMermaid mock that mimics mermaid.run's async innerHTML=svg
closure.

Amit Haridas
2026-09-14 22:52:13 +05:30
amitwh ac31162d3b fix(ascii-art): wire Box/Templates mode + correct standalone <link href>; v4.9.2
- src/ascii-generator.html line 7: ../fonts.css -> fonts.css (src/-relative;
  fixes silent stylesheet miss — same class as the v4.9.0->v4.9.1 script-tag fix)
- src/renderer/ascii-controller.js: wire all 3 mode tabs, 18 template
  buttons, and the 3 box form fields. setMode() toggles .active on tabs
  and matching .mode-section. Templates route through the orchestrator's
  template:<id> font namespace. Box mode renders text with single/double/
  rounded/bold/ascii borders via a pure renderBox() helper. All 11 T9
  behaviours preserved.
- tests/ascii-controller.test.js: 6 tests covering stylesheet path,
  pure box renderer, mode-tab switching, and template button wiring.
- package.json 4.9.1 -> 4.9.2; README + UPDATES updated.

Amit Haridas
2026-09-14 22:37:02 +05:30
amitwh 8c708b7abb fix(flowchart): pre-await getUserDataPath to fix persistence; bump v4.9.0 → v4.9.1
Amit Haridas
2026-09-14 22:24:27 +05:30
amitwh 58aa4da00f chore(release): bump v4.8.0 → v4.9.0 — visual flow chart, ASCII art upgrade, 12 new themes
Amit Haridas
2026-09-14 22:19:33 +05:30
amitwh b28d11035b docs(readme): drop undocumented Add Flow Chart Node Insert shortcut
The flowchart panel keyboard handler in src/sidebar/flowchart-panel.js only
handles Ctrl+Z, Ctrl+Shift+Z, Delete, and Backspace. There is no Insert-key
branch, so the README row documenting it was a lie. Remove the row until the
behaviour is actually implemented.

Amit Haridas
2026-09-14 22:06:25 +05:30
amitwh bf0ed6857d fix(sidebar): register Ctrl+Alt+F to toggle flow chart panel
The rail button tooltip advertised the shortcut, but commandPalette.register
was missing for 'Toggle Sidebar: Flow Chart'. Wire it up next to the other
sidebar toggles (Explorer/Git/Outline) so the advertised shortcut works.

Amit Haridas
2026-09-14 22:06:20 +05:30
amitwh aee30a2a9c docs(readme): visual flow chart editor feature + panel-scoped shortcuts
Amit Haridas
2026-09-14 21:55:48 +05:30
amitwh b0dcf57daf feat(sidebar): register flowchart panel + rail button + thin fs IPC
- Add data-panel=flowchart rail button in src/index.html after daily-notes

- Append .flowchart-* panel CSS selectors to src/styles-sidebar.css

- Add flowchartIO IPC bridge and registerPanel('flowchart') in src/renderer.js

- Add get-user-data-path / read-text-file / write-text-file IPC in src/main.js

- Path validation: sandbox inside app.getPath('userData')

- read-text-file returns null on ENOENT (file doesn't exist)

Amit Haridas
2026-09-14 21:52:32 +05:30
amitwh a6dc54cedc fix(sidebar): clean up listeners + timers + store subscription on panel destroy
destroy() previously only called canvas.destroy(), leaking:
- the container keydown listener
- the insertBtn click listener
- the debouncedPreview setTimeout handle (could write to a detached <pre>)
- the debouncedPersist setTimeout handle (could writeFile after unmount)
- the store.subscribe listener (store kept a stale closure)

Also compute the persistence path once on mount instead of invoking
getUserDataPath() three times per panel lifecycle.

Inline debouncedPreview / debouncedPersist so their timer handles are
reachable from destroy(). Capture store.subscribe's unsubscribe.
destroy() order: clear timers, unsubscribe store, remove listeners,
then canvas.destroy().

Amit Haridas
2026-09-14 21:49:49 +05:30
amitwh 59ee9c609e feat(sidebar): flowchart-panel — canvas + preview + persistence + insert
Amit Haridas
2026-09-14 21:45:47 +05:30
amitwh 0331a08207 feat(flowchart): SVG canvas with drag, double-click label edit, context menu hook
- Adds flowchart-canvas.js with createCanvas(container, store, opts) -> { destroy, getSvg }
- Consumes T1 store (subscribe/moveNode/connect/addNode) and T2 shapeSvg for 5 node kinds
- All 3 edge kinds render: solid (default), dotted (stroke-dasharray 4,4), thick (stroke-width 3)
- Pointer events: drag moves nodes; Alt+drag creates solid edges between nodes
- onEdgeClick fires on edge click; onShapeMenu fires on contextmenu
- Double-click opens inline <input> overlay for label editing
- destroy() unsubscribes from store and removes all listeners/SVG

Tests: 9 new (rendering 5, pointer events 2, subscribe 1, destroy 1) @jest-environment jsdom
Full suite: 89 suites / 1083 tests pass; lint clean; prettier clean.

Amit Haridas
2026-09-14 21:41:58 +05:30
amitwh 216e0ecf51 feat(flowchart): mermaid translator (flowchart TD, all 5 shapes, 3 edge kinds)
Pure Mermaid translator: graph (nodes + edges) -> flowchart TD source.
5 node kinds (process/decision/terminator/subroutine/document) ->
Mermaid syntax ([..], {..}, ([..]), [[..]], [/../]).
3 edge kinds (solid/dotted/thick) -> Mermaid arrows (-->, -.->, ==>).
Label escaping: double quotes become #quot;, newlines become literal \n.

Also moves tests/fixtures per-test dirs to fixtures-epub / fixtures-css
so the shared tests/fixtures/ stays available for snapshot fixtures.

Amit Haridas
2026-09-14 21:36:02 +05:30
amitwh 4a36b7db76 feat(flowchart): 5 SVG shape templates (process/decision/terminator/subroutine/document)
Amit Haridas
2026-09-14 21:25:38 +05:30
amitwh 7869be0ff9 feat(flowchart): pure graph store with undo/redo + injectable IO
Amit Haridas
2026-09-14 21:23:03 +05:30
amitwh 2ca543de35 fix(ascii-art): correct controller script tag path (drop ../)
Amit Haridas
2026-09-14 21:19:37 +05:30
Amit Haridas 02c9250c0d docs(readme): ASCII Art Generator now 17 hand-coded + 400+ FIGlet fonts; insert/copy/save
Amit Haridas
2026-09-14 21:14:36 +05:30
amitwh ab50183dc0 refactor(ascii-art): delete in-app modal #ascii-art-dialog, controller, dead preload channels
Amit Haridas
2026-09-14 21:06:28 +05:30
amitwh 8c162c1714 feat(ascii-art): standalone window uses controller + searchable picker + copy/save/insert
Amit Haridas
2026-09-14 21:05:24 +05:30
amitwh 38bc2b2bc5 feat(ascii-art): renderer controller for standalone window (font picker + copy/save/insert)
Amit Haridas
2026-09-14 20:58:46 +05:30
amitwh 1d68fc132f test(preload): ascii channel allow-list assertions + extend existing security test
Amit Haridas
2026-09-14 20:55:58 +05:30
amitwh fecd23d35e feat(ascii-art): preload allow-list + ascii namespace
Amit Haridas
2026-09-14 20:54:23 +05:30
amitwh f089f60d70 feat(ascii-art): wire IPC handlers for generate/list-fonts/save/copy/last-font
Amit Haridas
2026-09-14 20:50:37 +05:30
amitwh 9751bbc6df feat(ascii-art): pure AsciiArt module with generate/listFonts/getFontMeta
Amit Haridas
2026-09-14 20:46:49 +05:30
amitwh 57fee91e32 feat(ascii-art): pure AsciiArt module with generate/listFonts/getFontMeta
Pure CommonJS orchestrator that unifies hand-coded fonts, figlet adapter,
and templates behind a single public API. Wired to main.js via ipcMain.handle.

Public API:
  - generate({ text, font, options }) - resolves 'template:<name>' /
    'figlet:<font>' / bare id, falls back to standard for unknown fonts.
  - listFonts() - hand-coded first (17), then figlet, then templates (19).
  - getFontMeta(id) - null for unknown id, full meta for hand-coded,
    { kind } for figlet/templates.

Amit Haridas
2026-09-14 20:45:05 +05:30
amitwh fba848ef16 feat(ascii-art): figlet adapter with lazy load, font cache, structured error 2026-09-14 20:40:55 +05:30
amitwh bb99a5c5ee feat(ascii-art): 19 named ASCII art templates with snapshot tests
Per Task 3 of the 2026-09-14 ASCII art upgrade plan.

- New module: src/main/AsciiArt.templates.js exporting ASCII_TEMPLATES
  (19 entries) and getTemplate(name) accessor (returns '' for unknown).
- New test: tests/main/ascii-art.templates.test.js with 19 per-template
  snapshots + unknown-name + keys-match assertions (21 tests total).
- 17 templates verbatim from src/ascii-generator.html:596-626
  (arrow-right, arrow-down, decision, process, flowchart, sequence,
  network, hierarchy, header, note, warning, info, divider, separator,
  banner, checklist + the brief's own TEMPLATE_NAMES order).
- 2 templates verbatim from src/renderer.js:6542-6697
  (progress-bar, table-simple).
- 1 newly authored: arrow-up (completes the arrow triplet; does not
  exist in either source).

Amit Haridas
2026-09-14 20:35:39 +05:30
amitwh f71aa2b097 feat(ascii-art): 17 hand-coded font tables (5 existing + 12 new) with snapshot tests
Widen height bound to 3-12 so the spec-named figlet fonts fit:
- Isometric1, Isometric2, Isometric3, Isometric4 (h=11)
- Calvin S (h=3)

Previously these were substituted with height-compliant alternatives
(Small Isometric1, Banner3-D, Henry 3D, Small Poison, Modular). Restoring
the spec-named fonts preserves the product intent: 4 distinct isometric
projections and the calvin-and-hobbes-style Calvin S font.

Amit Haridas
2026-09-14 20:30:04 +05:30
amitwh 5385e159ed feat(ascii-art): 17 hand-coded font tables (5 existing + 12 new) with snapshot tests
Amit Haridas
2026-09-14 20:27:03 +05:30
amitwh 3fbb47000e chore(deps): add figlet ^1.8.0 for ASCII art generator 2026-09-14 20:21:14 +05:30
amitwh 66def72f3e docs(readme): list all 37 themes by category
Amit Haridas
2026-09-14 20:19:26 +05:30
amitwh c1c9ab4a4c feat(themes): add 12 new themes (Catppuccin, One Light, Tokyo Night Storm, Synthwave, Outrun, Winter, Solarized HC, Spring)
Amit Haridas
2026-09-14 20:16:08 +05:30
amitwh 0bc50c7d54 feat(renderer): toggle <link disabled> on theme-changed instead of page reload
Replace the page-reload IPC handling in the theme-changed listener with an
in-place toggle of the preloaded <link id="theme-*"> tags. The helper scans
for a matching link first and only mutates disabled states when one exists,
so an unknown id (or main-process miss) short-circuits and preserves the
currently active theme. body.className is always set to the requested id so
legacy selectors keep matching.

Add tests/theme-renderer-apply.test.js with three cases covering: switching
to a fresh theme, idempotent re-switch, and the unknown-id short-circuit.
The test's local helper mirrors the renderer implementation so future drift
is caught at test time.

Amit Haridas
2026-09-14 20:11:44 +05:30
amitwh ceeda453be feat(index): preload 37 disabled theme <link> tags for renderer toggle
Preload one disabled <link id="theme-<id>"> per registered theme
between the structural CSS block and the KaTeX link. The renderer
will toggle the disabled attribute on the active link when the theme
changes. The 12 new-theme CSS files (catppuccin-*, one-light,
tokyo-night-storm, synthwave-84, outrun, winter-is-coming-*, solarized-dark-hc,
spring-light) are created in the next task; until then those 12 links
are inert (disabled) and 404 is harmless.

Amit Haridas
2026-09-14 20:03:39 +05:30
amitwh 311304f365 refactor(styles): extract 25 existing themes into per-theme CSS files 2026-09-14 19:58:56 +05:30
amitwh 8392e33f5b refactor(main): drive View → Theme submenu from ThemeRegistry
Wires the three registry-layer modules into src/main.js:

- Require ThemeRegistry + buildThemeMenu + the bootstrap side-effect
  module at the top of the file so the registry is populated before
  the menu is built.
- Replace the 109-line hardcoded View → Theme submenu block with a
  buildThemeMenu({ setTheme, getCurrentThemeId }) call — themes are
  now driven entirely from ThemeRegistry.list() / categories().
- Harden setTheme() to validate the incoming id against the registry
  and fall back to 'atomonelight' if the stored id no longer exists
  (e.g. after a downgrade or theme rename), with a console.warn so the
  fallback is observable.

Pure wiring — no new behaviour, no unrelated edits. All 79 test suites
/ 931 tests remain green; lint and prettier checks clean.

Amit Haridas
2026-09-14 19:49:17 +05:30
amitwh a2b4a856f3 feat(theme-registry): buildThemeMenu converts registry → Electron MenuItem[]
Adds src/main/themeMenuBuilder.js — a pure module that consumes
ThemeRegistry.list() + ThemeRegistry.categories() and the injected
setTheme/getCurrentThemeId callbacks to produce the View → Theme
submenu's MenuItemTemplate[] in the same shape as the previous
hardcoded block in src/main.js:1137-1245.

- Radio-style items with checked=true on the active theme id
- Grouped by category in registry order with separators between
  non-empty categories
- No Electron / electron-store imports — keeps the module pure and
  unit-testable under @jest-environment node
- Tests use jest.resetModules() + per-test require to avoid the
  module-cache leakage the bootstrap test surfaced in T2

Amit Haridas
2026-09-14 19:46:15 +05:30
amitwh eaad62d02e feat(theme-registry): bootstrap with 25 existing + 12 new themes
Registers all 37 editor themes at startup via ThemeRegistry.bootstrap.js.
Side-effect module: requiring it populates the registry from a static
THEMES array (25 existing menu themes refactored into the registry +
12 new: Catppuccin x4, one-light, tokyo-night-storm, synthwave-84,
outrun, winter-is-coming x2, solarized-dark-hc, spring-light).

Categories split: 13 light / 22 dark / 1 high-contrast / 1 seasonal
(spring-light per spec).

Snapshot test asserts exact id order, shape validity, and category
counts. Tests use jest.resetModules() + per-test requires so the
bootstrap module re-evaluates its registration loop each run.

Amit Haridas
2026-09-14 19:43:48 +05:30
Amit Haridas 1e7e332c24 feat(theme-registry): pure ThemeRegistry module with full API
- 8 exports: register/unregister/list/get/categories/lightThemes/darkThemes/clear
- kebab-case id validator; category whitelist (light/dark/high-contrast/seasonal)
- duplicate-id and shape errors with descriptive messages
- pure CommonJS, no IO, no Electron deps — T2 bootstrap will register all 37 themes
- 10 Jest tests covering register/unregister/get/categories/light+dark filters
- full suite: 77 suites, 924 tests passing; lint + Prettier clean

Amit Haridas
2026-09-14 19:39:52 +05:30
amitwh b8c772269c docs(plans): add ascii-art-upgrade implementation plan
12-task TDD plan for the full-fledged ASCII Art Generator upgrade:

* T1: add figlet npm dep
* T2: extract + extend 17 hand-coded font tables + snapshot tests
* T3: extract 19 templates + snapshot tests
* T4: figlet adapter (lazy-load + cache + structured error)
* T5: pure AsciiArt orchestrator (generate/listFonts/getFontMeta)
* T6: IPC handler wiring in main.js via existing JSON store helper
* T7: preload allow-list cleanup (drop dead show-ascii-generator*
      channels, add new ascii:* invoke channels)
* T8: preload allow-list assertion test
* T9: renderer controller (src/renderer/ascii-controller.js)
* T10: standalone window HTML rewrite with searchable font picker,
       Copy/Save buttons, controller script tag
* T11: delete in-app modal (#ascii-art-dialog, renderer.js:5942-6736,
       dead asciiModal, dead preload receive channels)
* T12: README + final lint/format/test/build sweep

Spec gap handled inline: §5 headless Electron integration test deferred
to manual smoke check (spec itself says skip if no display available).

Amit Haridas
2026-09-14 19:14:30 +05:30