diff --git a/README.md b/README.md index 9682158..01b7141 100644 --- a/README.md +++ b/README.md @@ -257,4 +257,4 @@ Amit Haridas (amit.wh@gmail.com) ## Version -v4.9.4 +v4.9.5 diff --git a/UPDATES.md b/UPDATES.md index 766490b..4be42af 100644 --- a/UPDATES.md +++ b/UPDATES.md @@ -1,5 +1,21 @@ # PanConverter - Updates & Changelog +## Version 4.9.5 (2026-09-14) + +### Fixes +- **Flowchart Panel — rendered Mermaid SVG invisible at runtime**: v4.9.4 shipped with three interaction bugs that combined to make the Flow Chart panel look broken even though all the wiring was correct: + 1. **Render target had zero height.** `.flowchart-preview-render` only had `flex: 1; padding: 8px; overflow: auto;` — no `min-height`. When the parent flex column shrank (collapsed sidebar, normal sidebar width before the user clicks Maximize), the target collapsed to 0 height and the Mermaid-rendered SVG, though attached to the DOM, was clipped to nothing. + 2. **Dark-on-dark surfaces.** The canvas host and preview host inherited the project's `body.theme-concreteinfo` dark theme. Mermaid's `dark` theme was selected automatically in `src/renderer.js` based on the body class, producing near-black SVG fills on a near-black background. Node labels "Node" were barely legible. + 3. **Selection highlight invisible.** `.flowchart-node.selected` only set `stroke: var(--accent); stroke-width: 2;` against the rect's existing near-black fill — a thin accent stroke on a dark fill is effectively invisible at small sizes. + + Fix in three places: + - `src/styles-sidebar.css` — gave `.flowchart-preview-render` a `min-height: 120px` so the Mermaid SVG always has room to lay out. Added a `!important` light background (`#fafafa` / `#1f2328` text) to `.flowchart-canvas-host` and `.flowchart-preview-host` so the flowchart surface is readable regardless of the project's body theme. Forced explicit fills and strokes on `.flowchart-node rect` / `.flowchart-node polygon` / `.flowchart-node text` / `.flowchart-edge` (white fill, dark stroke, dark text). Selection now also changes the fill (`#e3f0ff`) and bumps `stroke-width` to 3 on both nodes and edges — the highlight is unmissable. + - `src/renderer.js:2443-2450` — the inline `renderFlowChartMermaid` now always initializes Mermaid with `theme: 'default'` (light) regardless of body class. Keeping this in sync with the CSS rule above is load-bearing: both are needed for the panel to be visible in any theme. +- **Tradeoff accepted**: the flowchart surface is now always light — diverges from the project's body theme. The user has been explicit that visibility and a working editor are the priority; theme consistency within this focused panel is sacrificed to guarantee the panel reads. + +### Tests +- `tests/flowchart-panel.test.js` — new `describe('flowchart-panel: render target sizing (v4.9.5 regression)')` block (3 tests) reading the shipped CSS to assert: (a) `.flowchart-preview-render` has a non-zero `min-height`, (b) `.flowchart-canvas-host` / `.flowchart-preview-host` carry a forced background declaration with `!important`, (c) `.flowchart-node.selected rect/polygon` carry an explicit fill and `stroke-width >= 3`. Reading the stylesheet directly mirrors what the runtime loads via `` and sidesteps jsdom's incomplete layout engine. + ## Version 4.9.4 (2026-09-14) ### Fixes diff --git a/package.json b/package.json index ab2f111..b6ab2ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "markdown-converter", - "version": "4.9.4", + "version": "4.9.5", "description": "Professional Markdown editor and universal file converter with PDF editing, batch processing, and syntax highlighting", "main": "src/main.js", "scripts": { diff --git a/src/renderer.js b/src/renderer.js index 54fd0dd..0f95043 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -2440,7 +2440,15 @@ document.addEventListener('DOMContentLoaded', async () => { const mermaidModule = require('mermaid'); window.mermaid = mermaidModule.default || mermaidModule; } - const theme = document.body.className.includes('theme-dark') ? 'dark' : 'default'; + // v4.9.5 — force the Mermaid theme to 'default' (light) regardless of the + // project's . The flowchart preview lives next to + // the editor inside a sidebar that we deliberately render on a forced + // light surface (see .flowchart-canvas-host / .flowchart-preview-host in + // src/styles-sidebar.css). Mermaid's `dark` theme produces near-black + // SVG fills, which against a near-white background are unreadable and + // against a dark background completely invisible. Keep this in sync with + // the CSS rule above — both are needed. + const theme = 'default'; window.mermaid.initialize({ startOnLoad: false, theme, securityLevel: 'loose' }); window.mermaid .run({ nodes: [div] }) diff --git a/src/styles-sidebar.css b/src/styles-sidebar.css index f8a194e..e1b8b31 100644 --- a/src/styles-sidebar.css +++ b/src/styles-sidebar.css @@ -1089,19 +1089,55 @@ body[class*='dark'] .preview-content a.wiki-link { } .flowchart-preview-render { flex: 1; + /* Non-zero CSS height guarantees the Mermaid-rendered SVG has room to lay + * out — without this, flex children in a collapsed parent can compute to 0 + * height and mermaid's ends up invisible even though it parsed and + * attached to the DOM. */ + min-height: 120px; padding: 8px; overflow: auto; } +/* v4.9.5 — force light, readable surfaces inside the flowchart canvas and + * preview regardless of the project's theme class on . The flowchart + * is a focused editor surface (similar to the PDF viewer) and the previous + * "inherit body theme" approach left users with dark-on-dark rectangles and + * dark-on-dark Mermaid SVG output, both effectively invisible. Keeping this + * surface light trades theme consistency for guaranteed visibility — the + * user has been explicit that WORKING > consistent with body theme. */ +.flowchart-canvas-host, +.flowchart-preview-host { + background: #fafafa !important; + color: #1f2328 !important; +} +.flowchart-node rect, +.flowchart-node polygon { + fill: #ffffff !important; + stroke: #1f2328 !important; + stroke-width: 1.25; +} +.flowchart-node text { + fill: #1f2328 !important; +} +.flowchart-edge { + stroke: #1f2328 !important; + stroke-width: 1.25; +} .flowchart-node { cursor: grab; } +/* v4.9.5 — selection highlight: prior to this rule set, `.selected` only + * painted a 2px stroke on a near-black fill — barely visible against the + * dark canvas. Add a fill change AND bump stroke-width so the highlight is + * unmissable. Same logic for edges. */ .flowchart-node.selected rect, .flowchart-node.selected polygon { - stroke: var(--accent, #4a9eff); - stroke-width: 2; + fill: #e3f0ff !important; + stroke: #4a9eff !important; + stroke-width: 3; } .flowchart-edge.selected { - stroke: var(--accent, #4a9eff); + stroke: #4a9eff !important; + stroke-width: 3; } .flowchart-label-input { font-size: 13px; diff --git a/tests/flowchart-panel.test.js b/tests/flowchart-panel.test.js index 3063845..cd176c5 100644 --- a/tests/flowchart-panel.test.js +++ b/tests/flowchart-panel.test.js @@ -422,6 +422,70 @@ describe('flowchart-panel: selection wiring (canvas click → panel state + SVG }); }); +describe('flowchart-panel: render target sizing (v4.9.5 regression)', () => { + // Regression: v4.9.4 left the rendered Mermaid SVG invisible at runtime. + // The panel rendered the SVG into `.flowchart-preview-render` correctly, + // but the element had no `min-height`, so when the parent flex column + // shrank (sidebar collapsed, takeover not active) the render target + // collapsed to 0 height and the SVG — though attached — was invisible. + // jsdom doesn't compute layout, but it does let us read the CSS rules + // we ship and confirm the fix is in the stylesheet. + function findCssRules() { + // jsdom doesn't expose document.styleSheets[].cssRules reliably across + // versions, so grep the file directly. That matches what the user will + // actually load at runtime via . + const fs = require('fs'); + const path = require('path'); + const cssPath = path.join(__dirname, '..', 'src', 'styles-sidebar.css'); + const css = fs.readFileSync(cssPath, 'utf8'); + return css; + } + + test('stylesheet defines a non-zero min-height on .flowchart-preview-render', () => { + const css = findCssRules(); + // Pull out the rule block for `.flowchart-preview-render { … }` and + // assert it contains a `min-height` declaration with a non-zero value. + const re = /\.flowchart-preview-render\s*\{([^}]*)\}/; + const match = css.match(re); + expect(match).not.toBeNull(); + const body = match[1]; + const mh = body.match(/min-height\s*:\s*(\d+)\s*px/); + expect(mh).not.toBeNull(); + expect(parseInt(mh[1], 10)).toBeGreaterThan(0); + }); + + test('stylesheet forces light backgrounds on canvas + preview hosts', () => { + // Regression: v4.9.4 left the canvas and preview hosts with the body's + // theme color (dark), which produced dark-on-dark nodes that were + // effectively invisible. The v4.9.5 fix forces a light background + // on both surfaces regardless of the body's theme class. + const css = findCssRules(); + const hostsRule = /\.flowchart-canvas-host\s*,\s*\.flowchart-preview-host\s*\{([^}]*)\}/; + const match = css.match(hostsRule); + expect(match).not.toBeNull(); + expect(match[1]).toMatch(/background\s*:\s*#[a-f0-9]+/i); + expect(match[1]).toMatch(/!important/); + }); + + test('stylesheet defines a fill + thicker stroke on .flowchart-node.selected', () => { + // Regression: v4.9.4 painted selection as a 2px stroke on the rect's + // existing (dark) fill, which was invisible against the dark canvas. + // v4.9.5 changes the fill to a soft accent and bumps stroke-width to 3. + const css = findCssRules(); + const re = + /\.flowchart-node\.selected\s+rect,\s*\.flowchart-node\.selected\s+polygon\s*\{([^}]*)\}/; + const match = css.match(re); + expect(match).not.toBeNull(); + const body = match[1]; + // Fill must be explicitly set (not just a stroke change). + expect(body).toMatch(/fill\s*:\s*[^;]+/); + // Stroke must be at least 3px so the highlight is unmissable. + const sw = body.match(/stroke-width\s*:\s*(\d+)/); + expect(sw).not.toBeNull(); + expect(parseInt(sw[1], 10)).toBeGreaterThanOrEqual(3); + }); +}); + describe('flowchart-panel: maximize / takeover', () => { // Wrap the panel container in a fake `.main-content` so the takeover's // findMainContent() walker can locate it. Mirrors the real DOM layout in