Repository navigation
Releases
MD Viewer v0.6.0
Release v0.6.0 — A Window Without a Frame
The window lost its OS title bar. The toolbar is the title bar now: one band of chrome
instead of two, about 30px more text at every window size, and a window whose edges belong
to the app rather than to Windows.
🚀 Key Improvements
🪟 The Window Is Frameless
- The toolbar became the title bar.
decorationsis off, and the 48px row that was already there now does the caption's job: it drags the window, maximizes on a double-click, and carries minimize / maximize-restore / close at its right edge, with Windows' own close-red hover. - The document's name came back to the bar. With no caption above it, a single open document had nowhere to be named — the tab strip only appears at two. The name shows at the left while one document is open, and hands over to the tabs at two.
- The maximize glyph follows the window, not the click.
Win+↑, a double-click on the bar and the button itself all keep the restore glyph honest, because the state is read back from the window. - Snapping and resizing are untouched. The drag is still
WM_NCLBUTTONDOWN(HTCAPTION), and Tauri keepsWS_CAPTIONandWS_THICKFRAMEon the window rather than stripping them, so drag-to-edge snapping,Win+arrow and edge-resizing behave exactly as they did under a real caption. - About 30px more text, at every window size: one 48px band where a ~32px caption used to be stacked on a 48px toolbar.
📜 The Reading Surface Scrolls
- The scrollbar starts below the toolbar. It used to run the full height of the window beside the bar, because the bar was a sticky element inside the page. The page no longer scrolls; the reading surface does.
- The window buttons are flush with the window edge. The bar spans the full width now, instead of stopping short of the scrollbar's gutter.
- Nothing else moved. Reading position, the pinned section bar, the progress bar, find-scroll and
J/Kmeasure the same things they did — only the surface they measure changed.
🛠️ Under the Hood
- Four window permissions, no more. Dragging the bar and the three buttons need
start-dragging,minimize,toggle-maximizeandclose;is-maximizedandinternal-toggle-maximizewere already in the default set. The webview still cannot do anything else. - The front-end suite grew from 76 checks to 91: the drag region, the name at one document and its hand-over to the strip at two, each window button reaching the window API, the glyph following the window, and the controls staying
<button>s — which is what keeps the band draggable. - The size budget moved 112/66 → 118/70 KB to pay for the title bar.
src/is 112.4 KB of 118 andapp.js66.5 KB of 70. - The toolbar is a solid colour. It was translucent with a backdrop blur, which was worth having while the document scrolled under it; now that nothing does, the filter had nothing to blur.
⚠️ One Known Limitation
- The Windows 11 snap-layouts flyout does not appear when you hover the maximize button. The OS draws it around the caption button a custom title bar does not have; restoring it would need
HTMAXBUTTONfromWM_NCHITTEST. Development happens on Windows 10, so this is unverified rather than known-broken — snapping itself is unaffected.
📅 Recent Version History
- v0.6.0: A frameless window whose toolbar is the title bar, and a reading surface that scrolls.
- v0.5.0: One band of chrome, Ctrl+wheel zoom, and the heading
#removed. - v0.4.0: Keyboard-driven tabs, session restore, front-end tests and a fmt/clippy gate.
- v0.3.4: Markdown files get a document icon of their own.
- v0.3.3: Settings panel, two-button toolbar, scroll and shift fixes.
- v0.3.2: Pinned section title, image lightbox, remembered window size and position.
Full Changelog: CHANGELOG.md
MD Viewer v0.5.0
Release v0.5.0 — A Quieter Top of the Window
The reader got quieter. The window used to stack three bands of chrome above the text and
say the same things in each of them; now it is one row, and the second band only appears
when it has something to say.
🚀 Key Improvements
🧹 One Band Instead of Three
- The tab strip moved into the toolbar. A window with tabs open used to reserve 108px above the text — a toolbar, a tab strip and a pinned section bar, stacked. It now reserves 48px: the tabs sit in the toolbar row next to the buttons, and nothing docks below it.
- The toolbar stopped repeating itself. The document name was in the title bar, again in the toolbar and again in the active tab; the folder path was in the toolbar and again in the footer; the word count was in both places too. What is left is the tab strip and two buttons — the name lives in the title bar and the tab, the path and the word count in the footer.
- The app mark is gone from the toolbar. It duplicated the window icon two inches to its left.
- The pinned section bar now earns its place. It used to sit under the toolbar naming the very heading you were already reading; it appears only once that heading has scrolled out of view, and disappears again at the top of a document.
- The footer carries the reading stats together: words, reading time, path and timestamp.
⌨️ Ctrl + Wheel Zooms
- The gesture every reader has.
Ctrl(orCmd) plus the wheel scales the article on the same 80–160% scale asCtrl+/-/0, with smaller steps because a wheel repeats faster than a key. The event is intercepted, so the webview does not page-zoom instead.
🖱️ The Heading # Is Gone
- The small
#that appeared beside a heading on hover, and copied a link to that section, has been removed — from the markup, the styles and the click handler. - Heading ids stay, so the outline and in-document links (
[text](#heading)) behave exactly as before.
🛠️ Under the Hood
- One layout variable fewer.
--tabs-hexisted to keep everything docked below the tab strip in step; with the strip inside the toolbar, headings' scroll margin, the outline drawer and the pinned bar all key off--topbar-halone. - The front-end suite grew from 68 checks to 76: the sticky bar's show/hide rule, the toolbar carrying no duplicates, and four checks for the wheel zoom (a plain wheel must not zoom, Ctrl+wheel in, out, and settling at the clamp).
- Still three static files, and the size budget did not have to move:
src/is 106.5 KB of its 112 KB,app.js63.9 KB of 66 KB — the removals paid for the addition.
📦 Beyond the App
- The repository is now n4od/md-viewer (from a name that began with a dot).
- Contributing is easier from any machine: the UI runs with nothing but Node (
node scripts/dev-server.js), the Rust side is verified on Ubuntu as well as Windows in CI, and the docs no longer assume this maintainer's PC. CONTRIBUTING.md,SECURITY.md,CODE_OF_CONDUCT.mdand issue/PR templates landed since 0.4.0.
📅 Recent Version History
- v0.5.0: One band of chrome, Ctrl+wheel zoom, and the heading
#removed. - v0.4.0: Keyboard-driven tabs, session restore, front-end tests and a fmt/clippy gate.
- v0.3.4: Markdown files get a document icon of their own.
- v0.3.3: Settings panel, two-button toolbar, scroll and shift fixes.
- v0.3.2: Pinned section title, image lightbox, remembered window size and position.
- v0.3.1: Tabs — several documents at once in one window.
Full Changelog: CHANGELOG.md
MD Viewer v0.4.0
Release v0.4.0 — Tabs, Finished
Tabs arrived in 0.3.1, but only for the mouse, and a session came back as a single
document. This release finishes both: the strip behaves like a real tablist, and the
documents you had open are still there next time.
🚀 Key Improvements
⌨️ The Tab Strip, From the Keyboard
Ctrl+Tab/Ctrl+Shift+Tabwalk the strip and wrap around;Ctrl+Wcloses the document you are reading; a middle-click closes the tab under the pointer.- Left/right and Home/End move within the strip and activate as they go, because the document is the point of the tab.
- A real tablist, not a row of links: each tab reports whether it is selected, and the strip is a single tab stop, so a screen reader announces a tab set and Tab does not walk through every close button before reaching the page.
- Focus stays where you left it. The strip is rebuilt whenever the tab set changes, and focus used to fall back to the page on that rebuild — which made the strip un-navigable after the first switch. Closing a tab now hands focus to its neighbour, and closing down to one document hands it back to the article.
🔁 The Documents You Had Open Come Back
- Turn on Reopen the documents I had open and a fresh launch rebuilds the strip, with the document you were reading in front. Twelve tabs at most.
- Only the document on screen is read at start-up. The other tabs are placeholders that load the first time you switch to them, so restoring five tabs costs one render rather than five.
- Tabs whose file has moved or been deleted are pruned before the strip is rebuilt, instead of failing one by one when you click them.
- A file opened from Explorer still wins. The stored session is only used when nothing was named on the command line, so double-clicking a file never gets overridden by what was open last time.
🧪 A Test Suite That Runs Itself
- 68 checks in a real browser, driving the actual frontend inside the preview harness: the render path, the lightbox, the settings dialog, progressive rendering — and now the tab keyboard model, focus retention, middle-click, persistence and session restore.
- CI runs it on every push, in a headless browser, and fails the build when a check fails. No test framework, no bundler, nothing added to the size budget.
- The formatter and the linter are gates now (
cargo fmt --check,cargo clippy -D warnings), after the one-time formatting pass the roadmap had been carrying since the first release.
🛠️ Under the Hood
- The session lives in
localStoragebeside the other preferences and is capped at twelve entries, so a stray list cannot turn start-up into a stampede of file reads. - The strip is a
divwithrole="tablist"rather than a<nav>: the role replaces the navigation landmark, and a tab is a wrapper around two sibling buttons because a button may not contain another button. - The frontend stays three static files. The size budget moved from 108/62 KB to 112/66 KB to pay for the keyboard model and restore, and is enforced in CI.
📅 Recent Version History
- v0.4.0: Keyboard-driven tabs, session restore, front-end tests and a fmt/clippy gate.
- v0.3.4: Markdown files get a document icon of their own.
- v0.3.3: Settings panel, two-button toolbar, scroll and shift fixes.
- v0.3.2: Pinned section title, image lightbox, remembered window size and position.
- v0.3.1: Tabs — several documents at once in one window.
- v0.3.0: Syntax highlighting for fenced code, reopen-the-last-document, print styles removed.
Full Changelog: CHANGELOG.md
MD Viewer v0.3.4
Release v0.3.4 — Markdown Files Get Their Own Icon
Markdown files no longer wear the app's tile in Explorer. They get a page of their own,
in the same palette and with the same mark.
🚀 Key Improvements
🎨 A File Icon, Not an App Icon
- Documents look like documents: a page with a folded corner, the app's serif "M" and its teal caret. A folder of notes now reads as notes, and sits clearly apart from the app tile instead of being a copy of it.
- Drawn for the sizes Explorer actually uses: 16px in list and detail views, 32px in tiles. The mark and the folded corner are chosen to survive that scale-down, where a detailed app tile turns to mush.
- The "Open with" entry keeps the app icon, deliberately: that row represents the app in the picker, not the document.
🛠️ Under the Hood
- The artwork travels inside the binary and is written out beside the theme, recent files and window geometry when the association is registered — so a portable copy gets the file icon too, with no second file to ship and nothing extra to clean up on uninstall.
- A fresh install is corrected on first launch, quietly, and the shell is told — so the new icon appears without restarting Explorer.
- Still no new dependencies: the icon comes from the project's own icon script, and a test pins the embedded bytes and the registry value's shape, so a silent fallback to the app tile cannot slip through unnoticed.
📅 Recent Version History
- v0.3.4: Markdown files get a document icon of their own.
- v0.3.3: Settings panel, two-button toolbar, scroll and shift fixes.
- v0.3.2: Pinned section title, image lightbox, remembered window size and position.
- v0.3.1: Tabs — several documents at once in one window.
- v0.3.0: Syntax highlighting for fenced code, reopen-the-last-document, print styles removed.
Full Changelog: CHANGELOG.md
MD Viewer v0.3.3
Release v0.3.3 — Settings, and a Smaller Toolbar
Every preference the app had been keeping to itself now has a home, the toolbar is down
to two buttons, and the reading pane holds still.
🚀 Key Improvements
⚙️ Settings
- One panel for every preference: theme, text size (until now keyboard-only), reading width, whether the reading position is remembered, whether the last document reopens at start, the default find options, the recent list, the file types the app claims along with the default-app action, remembered window size and position, and an About line with the running version.
- "Reopen the last document at start" is now a real setting. It had been left as a one-shot offer on the welcome screen, because a persisted switch with no way to turn it off would have been a trap — the panel is a permanent home for it.
- It behaves the way a dialog should: Esc closes it, focus returns to the gear that opened it, and a click outside dismisses it.
🎨 A Smaller Toolbar
- Two buttons instead of four: contents and settings. The theme button went with the setting it duplicated (
Ctrl+Shift+Lstill cycles the theme), and the open-file button went becauseCtrl+O, drag and drop, the welcome screen and Explorer already cover opening a file.
🐛 Fixes
- The reading pane no longer shifts sideways when the scrollbar appears or disappears. Opening the settings dialog caused it every time; the same jump happened whenever a short document followed a long one.
- The settings dialog no longer scrolls the page behind it, and a click outside dismisses it, as Esc and the close button already did.
🛠️ Developer / Core
- The size budget was raised deliberately, to 108/62 KB. The panel is the largest single frontend change so far, and the guard exists to keep the frontend three dependency-free files — it is still far below what a bundler or framework would cost.
- Still no new dependencies: the panel is plain HTML, CSS and JavaScript, the preferences are the same
localStoragekeys the app already used, and the only new Rust is a version command and a flag for remembering the window.
📅 Recent Version History
- v0.3.3: Settings panel, two-button toolbar, scroll and shift fixes.
- v0.3.2: Pinned section title, image lightbox, remembered window size and position.
- v0.3.1: Tabs — several documents at once in one window.
- v0.3.0: Syntax highlighting for fenced code, reopen-the-last-document, print styles removed.
- v0.2.0: Progressive rendering for large files, section links, image sizing, find toggles, reading position.
Full Changelog: CHANGELOG.md
MD Viewer v0.3.2
Release v0.3.2 — Pinned Section, Image Zoom & Window Memory
Three small things: the section you are reading stays visible, screenshots open at
full size, and the window reopens exactly where you left it.
🚀 Key Improvements
🎨 Reading
- The current section stays in view: a slim bar under the toolbar shows the section you are in, updated as you scroll. In a long document you no longer have to scroll back up to remember where you are, and it shows the document name until a section has been picked.
- Click an image to see it full size: images in a note are capped at the article's width, which makes a screenshot unreadable. Clicking one now opens it over a dimmed backdrop. Esc, the close button or a click on the backdrop dismisses it, and clicking an image that is also a link opens the picture rather than navigating away.
- Anchors still land correctly: the pinned bar is part of the stack docked below the toolbar, alongside tabs, and the scroll offsets account for both — so a heading you jump to is never hidden underneath them.
🛠️ Windows and Core
- The window reopens where you left it: size and position are saved when the window closes and restored on the next launch, so the app stops snapping back to its default box. Stored in logical pixels, so a change of display scaling does not resize it.
- No stranded windows: a saved position that no longer lands on a connected monitor is ignored rather than honoured, so unplugging a display cannot leave the window off-screen. The size is still applied.
- Nothing extra to install: the geometry lives in a small
window.jsonnext to the WebView2 profile, which the uninstaller already removes. - A deliberate size-budget raise: the frontend ceiling moves from 88/52 KB to 96/56 KB, because these three features took it past the old one. That guard exists to keep the frontend three dependency-free files; it is still far below what a bundler or framework would cost.
📅 Recent Version History
- v0.3.2: Pinned section title, image lightbox, remembered window size and position.
- v0.3.1: Tabs — several documents at once in one window.
- v0.3.0: Syntax highlighting for fenced code, reopen-the-last-document, print styles removed.
- v0.2.0: Progressive rendering for large files, section links, image sizing, find toggles, reading position.
- v0.1.1: Retry on a failed reload, recent-list housekeeping,
--version/--help/--register-defaultflags. - v0.1.0: First release — a read-only, single-window Markdown viewer with Windows file association.
Full Changelog: CHANGELOG.md
MD Viewer v0.3.1
Release v0.3.1 — Tabs for Multiple Documents
More than one document can be open at once, as tabs in the same window. The strip
stays out of the way until you actually have a second document, and each tab
remembers where you were.
🚀 Key Improvements
🚀 Tabs
- Several documents at once: open, close and switch between them in the one window, instead of opening a second file replacing what was on screen.
- The strip only appears when it earns its place: with a single document there is no tab strip at all, so ordinary reading looks exactly as it did before. The second document is what brings it in.
- Opening a file that is already open activates it: double-click the same
.mdin Explorer twice and the second click brings its tab forward rather than opening a duplicate. - Each tab remembers where you were: switching returns to that document's own scroll position and section, and its own find query travels with it — search for something in one tab, switch away, and it is still there when you come back.
- Everything opens into a tab: the recent list, document links, drag and drop, the open dialog and a second double-click all land in the strip.
🛠️ Developer / Core
- No second window, no second WebView2 tree: a window costs a whole WebView2 process tree (measured at ~320 MB working set), so multiple windows would multiply memory for the same feature. Tabs share the window and cost nothing beyond the documents themselves.
- No new Rust state: the renderer already tracked exactly one active document, and switching a tab is simply
load_path— which re-points the file watcher, the asset scope and the window title. A background tab is re-read when you return to it, so it is never stale. - Still three static frontend files: the whole feature is frontend state plus about 20 lines of CSS, and every existing render path — progressive rendering, section links, syntax highlighting, reading position — is untouched.
📅 Recent Version History
- v0.3.1: Tabs — several documents at once in one window.
- v0.3.0: Syntax highlighting for fenced code, reopen-the-last-document, print styles removed.
- v0.2.0: Progressive rendering for large files, section links, image sizing, find toggles, reading position.
- v0.1.1: Retry on a failed reload, recent-list housekeeping,
--version/--help/--register-defaultflags. - v0.1.0: First release — a read-only, single-window Markdown viewer with Windows file association.
Full Changelog: CHANGELOG.md
MD Viewer v0.3.0
Release v0.3.0 — Syntax Highlighting & Session Continuity
Fenced code is now coloured — in ten-plus languages, with no highlighter bundle and
no client-side JavaScript — and the welcome screen leads with the document you were
last reading, so picking up where you left off is one click.
🚀 Key Improvements
🚀 Syntax Highlighting
- Ten-plus languages out of the box: Rust, JavaScript and TypeScript, Python, JSON, shell, PowerShell, SQL, YAML and TOML, CSS, HTML/XML and the C family (which covers C, C++, Java, C#, Go, Swift and Kotlin fences).
- Nothing added to the frontend: tokenising happens in Rust on the render path, so
app.jsis unchanged — no highlighter bundle, no client-side work, and the "three static files" promise is intact. - Sanitiser still has the last word: spans are produced before the allow-list runs, so a highlighted block cannot introduce anything the sanitised renderer would have rejected. Markup inside a string stays text.
- Colours that pass AA: every token colour measures at least 4.5:1 against the code background in both themes (worst case 4.90 light, 4.66 dark).
- Tolerant by design: a language the highlighter does not know, or a fence with no language tag, renders exactly as it did before. Only the interesting tokens get a span, so plain identifiers and punctuation keep the normal code colour and the payload stays lean.
✨ Resuming Work
- Reopen the last document: starting with no file on the command line, the welcome screen now leads with "Reopen
<name>" for the document that was last on screen. It is one click instead of finding it in the recent list. - Nothing to switch off: the last document is simply the top of the recent list, so there is no autostart setting and no way to get stuck with one you cannot turn off.
🧹 Removed
- Print styles: MD Viewer is a reader and exposes no print action, so the
@media printrules shipped in 0.2.0 were removed rather than left in the stylesheet unreachable. The stylesheet is now screen-only and about 2.3 KB lighter.
🛠️ Developer / Core
- The cost is measured, not guessed: on a deliberately code-heavy document (600 Rust blocks), 124 KiB of Markdown now renders to 357 KiB of HTML in ~94 ms — about +26% render time and +15% payload against the same document before highlighting.
- No new dependencies: the highlighter is a small tokeniser in
main.rswith a table per language, and it is covered by tests alongside the rest of the render path. - CI budget raised deliberately: the frontend ceiling moves from 80/46 KB to 88/52 KB after the 0.2.0 batch reached the old one. The guard still rules out a bundler or a framework.
📅 Recent Version History
- v0.3.0: Syntax highlighting for fenced code, reopen-the-last-document, print styles removed.
- v0.2.0: Progressive rendering for large files, section links, image sizing, find toggles, reading position, print fixes.
- v0.1.1: Retry on a failed reload, recent-list housekeeping,
--version/--help/--register-defaultflags. - v0.1.0: First release — a read-only, single-window Markdown viewer with Windows file association.
Full Changelog: CHANGELOG.md
MD Viewer v0.2.0
Release v0.2.0 — Large Files, Section Links & Print Fixes
This release makes MD Viewer comfortable with documents it used to choke on —
multi-megabyte notes now paint in a fraction of a second — and adds the small
things you reach for while reading: links to a section, find toggles that stick,
a reading position that survives closing the window, and a print stylesheet that
actually works.
🚀 Key Improvements
🚀 New Features
- Progressive rendering for large files: Documents above 1 MiB of rendered HTML are now attached 128 KiB at a time instead of in one go, so the top of the file appears while the rest is still being built. A document that took ~2.4 s to show anything now paints its first chunk in ~70 ms.
- Same document, same DOM: Chunking is provably lossless — the chunks rejoin byte-for-byte and produce an identical DOM to a single insert, so nothing about the rendered result changes.
- Safe to interrupt: Opening a new file mid-render cancels the old one cleanly; a superseded chunk pump stops on its next step rather than appending pieces of the previous document.
- Section links: Hover a heading (or Tab to it) and a
#appears; clicking it copies a link to that section as the file path plus the anchor, e.g.C:\notes\a.md#setup. It copies rather than navigates, so it never scrolls you away from where you are. - Image placeholders: Local images now carry their real pixel dimensions, read from the file header, so the page reserves the correct box before the image loads and the text below no longer jumps.
- Find toggles: Match-case and whole-word switches in the find bar (also
Alt+C/Alt+W), remembered across sessions. - Find counting that stays honest: The counter reports every occurrence; only the first 1500 become highlight ranges, so a document with thousands of hits stays responsive while the number stays truthful.
- Reading position: Reopening a long document returns to where you stopped. The position is written on the leading edge of a scroll burst — so closing the window right after scrolling cannot lose it — with a trailing debounce for the resting position, capped at 60 documents.
⚡ Performance
- Outline scroll-spy: Heading offsets were re-measured for every heading on every scroll frame, so the cost grew with document size. They are now measured once per layout and binary-searched: on 500 headings the per-tick cost fell from 0.75 ms to about 0.0004 ms.
- Cheaper document open: An ASCII fast path in
slugify(the Unicode property escapes were re-run for every heading) and one delegated outline listener instead of one per link cut a 500-section document's open from 67 ms to 42 ms plain, and 131 ms to 75 ms with tables and code. - Instant first paint on large files: The first chunk of a big document is on screen in ~70 ms, where previously the whole document had to be parsed, enhanced and laid out before anything appeared.
- Profile first, then optimise: Laying out a 1.2 MB document turned out to be ~1.9 s of the ~2 s open, against ~130 ms of parsing — which is why the fix attaches the document in pieces rather than shortening the Markdown render.
♿ Accessibility
- AA contrast in both themes: The faintest text token now measures 4.65:1 on the light theme and 5.97:1 on dark, past WCAG AA.
- Skip to content: A skip link lets keyboard users jump past the toolbar straight into the article.
- Focus that goes somewhere and comes back: The outline and the find bar move focus in when opened and hand it back to where it came from when closed.
- States that are announced: The outline toggle reports
aria-expanded, the current sectionaria-current, the find match count is a live region, and the theme button names the active mode. - Keyboard guards: Plain
j/kno longer scroll the page while you are typing in the find field. - Clean heading names: Section anchors are built so a screen reader announces the heading text, not the copy-link control attached to it.
🐛 Bug Fixes
- Printing in dark mode: The print styles now force the light palette, so a reader in dark mode no longer prints near-white text on white paper.
- No clipped content on paper: Wide tables and long code lines scroll sideways on screen, which meant they were simply cut off when printed. They now wrap, and tables drop to 9pt with cell wrapping.
- Page breaks that respect content: Table header rows repeat on every page a table spans, and breaks are avoided inside code blocks, tables, rows and images.
- Predictable page margins: A
@pagerule sets a 16 mm × 18 mm margin instead of relying on the dialog default.
🛠️ Developer / Core
- Frontend size budget in CI: The build fails if
src/exceeds 80 KB orapp.jsexceeds 46 KB, so "three static files, no framework" is enforced by the pipeline rather than remembered. - Dead ends recorded in the code: Staging the document off-DOM before attaching it, and delegating the code-copy buttons, were both measured and rejected — the numbers are kept in the source so they are not retried.
- Image dimensions without a dependency: PNG, JPEG, GIF and WebP sizes are read from the file header only (never decoded), from the first 64 KiB, and cached per render.
- Still zero dependencies: Every feature above ships in the same three static frontend files and the same single Rust binary — no new runtime, no web fonts, no network calls.
📅 Recent Version History
- v0.2.0: Progressive rendering for large files, section links, image sizing, find toggles, reading position, and print fixes.
- v0.1.1: Retry on a failed reload, recent-list housekeeping, and the
--version/--help/--register-defaultcommand-line flags. - v0.1.0: First release — a read-only, single-window Markdown viewer with first-class Windows file association.
Full Changelog: CHANGELOG.md
MD Viewer 0.1.1
A maintenance release: three things you can feel, and one build warning that went away.
What's new
Retry when a file disappears. If an editor deletes and rewrites a file mid-save, the viewer now keeps the document on screen, names the file it could not read, and offers Retry — instead of blanking the reading pane and leaving you to reopen it.
Recent files that stay honest. Entries whose file no longer exists are pruned at start-up, and the "Recently opened" list has a Clear action. The existence check runs in Rust (filter_existing), so a moved or deleted file simply disappears rather than failing when you click it.
Command line flags. Both the installed and portable executables accept:
| Flag | Effect |
|---|---|
--version, -V |
prints mdviewer 0.1.1 |
--help, -h |
prints usage |
--register-default |
registers that executable as a .md handler and refreshes the shell — no window, no dialog |
--register-default is the one to call from a script: a Windows Sandbox .wsb logon command, a CI smoke test, or an unattended setup. Exit code 0 on success, 1 on failure, and the output appears even though the app ships without a console window.
& "$env:LOCALAPPDATA\MD Viewer\mdviewer.exe" --register-default
if ($LASTEXITCODE -ne 0) { throw 'association registration failed' }Identifier cleanup. The bundle identifier is now mdviewer (was dev.mdviewer.app), removing the build warning about the .app suffix colliding with macOS bundles. Side effect worth knowing: WebView2's data directory moves to %LOCALAPPDATA%\mdviewer, so the stored theme and recent-files list reset once on the next run.
Install
Per-user, no admin:
MD.Viewer_0.1.1_x64-setup.exe— installs to%LOCALAPPDATA%\MD Viewer, registers the Markdown associations and adds a Start-menu entry.MD.Viewer_0.1.1_x64-portable.exe— run it from anywhere; register it from the empty state (Set as default for .md files) if you want the association.
Requirements and limits:
- Windows 10/11 x64, with the WebView2 runtime (preinstalled on Windows 11; the installer fetches it when missing).
- If another app already owns
.md, confirm MD Viewer once: right-click a.mdfile → Open with → Choose another app → MD Viewer → Always. Windows keeps that final choice; nothing can set it silently. - Read-only by design, and files larger than 16 MB are truncated with a notice.
Verify what you downloaded against SHA256SUMS-v0.1.1.txt:
Get-FileHash ".\MD.Viewer_0.1.1_x64-setup.exe" -Algorithm SHA256Full details in CHANGELOG.md; planned work in ROADMAP.md.