← Back to MarkeMark

Changelog

The story of the app, version by version.

v2.1 — Build 9 May 13, 2026

Help → MarkeMark Tutorial now works from the launch picker. Before, clicking it on a fresh launch — when no document is open yet — was a silent no-op, and the first-launch auto-show never fired because it was gated on a document window appearing. Both paths now work.

  • Tutorial opens from anywhere. Help → MarkeMark Tutorial works whether you're in the launch picker, an open document, or with no windows visible
  • First-launch tutorial actually shows up. Auto-opens on the very first launch even if you dismiss the open panel without picking a file

Engineering note. The tutorial was wired via FocusedValue, which is nil while the system "open or new" panel is the only window in front — so the Help menu button was a silent no-op and the .onAppear-gated first-launch trigger never fired. Tutorial now lives in a free-standing NSWindow driven by a TutorialWindowController singleton; an NSApplicationDelegate handles the first-launch trigger. TutorialView gained an optional onDismiss callback so the AppKit host can close the window cleanly (\.dismiss is unreliable inside NSHostingController on macOS 13). All showTutorial FocusedValue plumbing removed from ContentView and markemarkApp.

v2.1 — Build 8 May 7, 2026

Find bar, rewritten. Cmd+F was technically working but didn't feel like a Mac app — flat single-match treatment, results going stale on edit, no live highlighting in the rendered preview, no Cmd+G. Build 8 rebuilds it from the ground up with the visual language Safari and Xcode use, drives both panes from a single source of truth, and adds the missing keyboard verbs.

  • Every match highlights — instantly. Type and yellow appears across the whole document; the match you're parked on glows orange with a ring, the way Safari does. Both the source pane and the rendered preview light up in lock-step
  • The bar is fast. Cmd+F focuses the field the same instant the bar slides in. Cmd+F a second time re-selects the existing query so you can overtype
  • Edits don't stale the matches. Type into the editor with the bar open and matches recompute live; your "current" pointer snaps to the closest surviving match
  • ⌘G / ⇧⌘G cycle matches. Plus Return / Shift+Return do the same. Wrap-around triggers the system beep, the way every Mac app from 1984 does it
  • Esc lands you on the current match. Restores focus to the editor at where you were parked, and persists the query to the system find pasteboard so the next Cmd+F (in this app or any other) starts with it pre-filled

Engineering note. Three new files: FindController.swift (single source of truth — query, options, match arrays, current index, recomputes on every input change including doc edit, snaps current-match pointer to the nearest surviving range across edits), EditorMatchHighlighter.swift (paints via NSLayoutManager.addTemporaryAttribute so highlights don't enter the undo stack and clear when storage edits — yellow .backgroundColor for every match plus orange + thick underline + the system showFindIndicator pulse on the current one), and a rewritten FindBarView.swift with an NSSearchField-backed NSViewRepresentable that bypasses the SwiftUI mount race by deferring makeFirstResponder one runloop hop. Preview side gets a CSS mark.find-match / mark.find-match-current rule pair (light + dark + system variants) and a JS DOM-walker using TreeWalker to wrap text-node matches without touching links, images, or code blocks; applyMarkdown re-applies decorations after every re-render so editor edits don't silently strip preview highlights mid-search.

v2.1 — Build 7 Apr 29, 2026

Builds 5 and 6 didn't pan out — Build 5's bidirectional-editing fidelity changes had subtler regressions than the Quick Look break that Build 6 was meant to fix, and the test loop wasn't tight enough to catch them before shipping. Build 7 walks the editor, renderer, and preview-pane code back to Build 4's known-good state. Quick Look stays at the data-based path that worked through Build 4.

  • Stable rendering and editing. Back to the Build 4 markdown pipeline and bidirectional sync — no new behavior, but no surprises either
  • Quick Look unchanged from Build 6. Spacebar-preview a .md file in Finder renders cleanly. Text selection in the QL panel will return via a different approach in a future build
Engineering note: Content-only walk-back. CURRENT_PROJECT_VERSION bumps 6 → 7; preview.css, MarkdownRenderer.swift, EditorView.swift, and PreviewView.swift are restored to commit 892cd2c (Build 4). The Build 5 list-continuation, checkbox-toggle, <hr>*** round-trip, and caret-after-checkbox fixes are gone — they'll be ported back on top of Build 4 once each can be validated against a fixture before shipping. New repo-root test-ql.sh is the QL test loop that should have existed before Build 5.
v2.1 — Build 6 Apr 29, 2026

Reverts the Build 5 Quick Look change. Switching the QL extension to a view-based WKWebView to gain text selection broke QL preview in Finder — pulling the change back to the data-based path that worked through Build 4. The bidirectional-editing fixes from Build 5 all stay.

  • Quick Look works again. Spacebar-preview a .md file in Finder renders cleanly. Text selection in the QL panel will return in a future build via a different approach
  • All bidirectional editing fixes from Build 5 remain (checkbox toggle, Enter list continuation, *** round-trip, caret position after Enter, no bullet next to checkboxes)
v2.1 — Build 5 Apr 29, 2026

A round-trip-fidelity pass on the bidirectional preview pane plus a Quick Look quality-of-life win. Edits in the rendered pane (toggle a checkbox, hit Enter inside a list) used to corrupt the markdown source in subtle ways; this build closes the loop. And spacebar-preview a .md file in Finder — you can finally select and copy text out of it.

  • Quick Look text is selectable. Highlight and copy from the QL panel like any other text preview
  • Enter continues lists in both panes. - [ ] foo, Enter → - [ ] on the next line. Same for -, *, +, and 1. / 1) lists. Empty item, Enter → exits list mode
  • Toggling a checkbox no longer rewrites the line. Just that one [ ][x] flips in the source, instead of round-tripping the entire HTML and occasionally leaving a raw <input> tag behind
  • Bullet next to checkboxes — gone. Task-list items render with the checkbox alone, no leading dot
  • Horizontal rules round-trip as ***. --- collides with YAML frontmatter at line 1; *** is valid CommonMark and doesn't collide
  • Caret lands to the right of the checkbox after Enter inside a checkbox list, and exiting an empty checkbox mid-list drops you in a paragraph between the items instead of jumping to the bottom
Engineering note: Five wedge fixes plus one architectural change. The HTML→MD checkbox regex used attribute-order-agnostic lookaheads to handle WebKit's alphabetical attribute serialization. EditorView.swift gained a textView(_:doCommandBy:) intercept of insertNewline: plus a new ListContinuation enum. The preview-pane keydown handler in PreviewView.swift continues task-list items on Enter and splits the list when exiting an empty middle item; each new <li> is padded with a non-breaking space to dodge a WebKit caret-after-void-element bug, and the HTML→MD path strips that nbsp back to a regular space. The QL extension migrated from the data-based QLPreviewReply API to a view-based QLPreviewingController hosting a WKWebView — same HTML, but selectable.
v2.1 Apr 28, 2026

The whole markdown rendering pipeline got rebuilt around markdown-it — a real CommonMark + GFM library, in place of the in-house regex passes that kept growing edge cases. The headline win: single newlines now render as line breaks, matching Obsidian's default and the way most people actually write. Schedules, todo lists, and any block where you wrote one item per line stop collapsing into a paragraph. The print preview also got a meaningful upgrade — adjustable margins, a finer font slider, and a two-row toolbar so the action buttons stop getting clipped in portrait.

  • Line breaks render correctly. Type one item per line and you get one line per item — in the live preview, in PDF/HTML export, in print, and in Finder Quick Look. Same rendering everywhere
  • Print preview formatting matches the live preview. The Cmd+P sheet now uses the same renderer, so what you see in the editor is what you'll print
  • Quick Look preview formatting matches too. Space-bar a .md file in Finder and it renders the same way the app does
  • Adjustable print margin. New slider in the print preview sheet — drag from 0.1″ to 1.0″ in 0.05″ steps, persists across sessions. The system print dialog clamps further at print time per printer
  • Two-row print toolbar. Controls (font / margin / columns / orientation) live on row 1; Cancel / Save as PDF / Print on row 2 — fixes the truncated buttons in portrait (Ca… / Sav… / Pri…)
  • Finer print-preview font slider. Step granularity dropped from 0.1 pt to 0.05 pt. Numeric readout removed — drag against the live preview; the ± buttons (and ⌘− / ⌘=) still nudge by 0.1 pt one click at a time
Engineering note: New MarkdownItBridge.swift runs markdown-it.min.js in-process via JavaScriptCore so PDF export, HTML export, and the print-preview sheet share the same renderer the live preview uses. The preview pane runs the same library inside its WKWebView and exchanges raw markdown + an image-placeholder tag table with Swift, so local images stay inlined as base64 data URLs (placeholderize → md.render → JS-side restoration). The Quick Look extension got the same treatment via MarkdownItBridgeQL.swift. Config: breaks:true linkify:true typographer:true plus markdown-it-task-lists for checkboxes. Print margin is threaded as marginInches through the print-preview sheet → PDFExporter.printHTMLPDFExporter.export / exportDocumentPrintService.print; the value drives body { padding } (which is what WKPDFConfiguration.createPDF actually honors) and is clamped 0.1–1.0″.

Known small regressions landing in 2.1.1: wiki-links [[Foo]], Obsidian highlights ==text==, and footnote syntax [^id] render as literal text — markdown-it doesn't ship with these by default. Each is a small plugin away.

v2.0.1 Apr 25, 2026

A small polish pass on top of v2.0. Nothing dramatic — every change just makes the app sit a little more naturally next to native macOS chrome.

  • Cleaner toolbar. The hairline under the toolbar is gone; buttons sit cleanly on the window background
  • Unified icon palette. View-mode buttons in the toolbar and the divider lock now share the same gray ramp macOS uses for native toolbar items
  • Smoother divider. Wider grab zone, refined scroll-lock pill, and a generous hover handoff so the cursor flips back to the standard arrow before you reach the lock
  • App icon refreshed — Bebas Neue # on the site's slate brand, cleaner output across every size
  • Social card. Links to markemark.app now render as a full-card preview on iMessage, Slack, X, and LinkedIn
v2.0 Apr 24, 2026

v2.0 is everything since the first public release folded into one headline: press Space on any .md file in Finder and see it rendered — with inline images, syntax highlighting, and dark mode. That gesture was always the product; 2.0 is when it actually works end-to-end. Plus a new home at markemark.app with a redesign that finally does the app justice.

  • Quick Look, for real. Spacebar on any .md or .markdown file shows a fully rendered preview — headings, code, tables, checklists, inline images. Open a folder once in the app, every file inside previews cleanly after that
  • Inline images everywhere. Obsidian-style embeds (![[screenshot.png]]) and relative paths (![alt](refs/foo.png)) render in the editor's preview, in Quick Look, in HTML export, and in printed PDF. Your .md stays plain text on disk; images stay as files next to them
  • Obsidian-style wiki links. [[page]], [[page|alias]], and [[page#section|alias]] render as subtle dark-purple underlined text across preview, HTML, PDF, print, and Quick Look. Edit the displayed text in the preview pane and it round-trips back as an alias
  • Pane sync that stays out of the way. Scroll the editor, the preview follows the same proportion of the document. A sync caret tracks your cursor. Toggle sync off with ⇧⌘Y when a tall image pushes one pane ahead of the other
  • Preview-pane shortcuts. Cmd+B/I/K, undo/redo, and friends work in whichever pane has focus — not just the editor
  • ~3× faster keystroke-to-preview latency (550 ms → 200 ms). Native AppKit pane divider, layer-backed editor scroll, syntax highlighting that skips unchanged code blocks, and a Combine-driven render pipeline that keeps heavy work off the main thread
  • New site, new home. markemark.app is the canonical URL. Real product screenshots, auto dark mode, and a scroll-scrubbed Quick Look preview in the hero
v1.5 Apr 22, 2026

Native printing and the foundations of pane sync. The two big things people wanted from a markdown editor that takes itself seriously.

  • Print & PDF with 1–9 column reflow. Cmd+P opens a live preview with a column stepper, portrait/landscape toggle, and a zoom slider that reflows text across the page. Checklists, weekly schedules, and reference cards finally fit on one page
  • Pane sync. Scroll the editor, the preview follows. Scroll the preview, the editor follows. Both stay aligned to the block you're looking at, with a sync caret tracking your cursor within a paragraph
  • Round-trip fidelity. Code-block language tags, footnotes, and bare URLs all survive editing in the preview pane intact — no more silent rewrites of your markdown
  • Wiki links render in Quick Look too, matching the main app
Engineering note: Six different print-code paths (WKWebView, PDFDocument, custom NSView, in-memory and disk round-trips) all failed with the same generic "This application does not support printing" error. The culprit turned out to be a missing com.apple.security.print sandbox entitlement — the sandbox was silently blocking every print IPC call regardless of API surface. The print implementation itself was fine the whole time.
v1.4 Feb 27, 2026

Format shortcuts finally work where you'd expect them — in whichever pane has focus.

  • Cmd+B/I/K, Cmd+Shift+X, and friends now work in the preview pane as well as the editor
  • Strikethrough round-trips cleanly through preview edits
  • Interactive tutorial replaces the old welcome screen
v1.3.1 Feb 27, 2026

The app can now tell you when a new version is available.

  • Auto-checks for updates on launch (once per day, fails silently offline)
  • "Check for Updates…" menu item for manual checks
  • Automated release pipeline — build, sign, notarize, package DMG, and generate version manifest in one command
v1.3 Feb 24, 2026

The first public release. Getting a macOS app from "works on my machine" to "works on anyone's machine" turned out to be its own project.

  • Website launch and notarized DMG distribution
  • Quick Look extension for previewing .md files in Finder
  • Table rendering and clickable task-list checkboxes
  • Bundled highlight.js locally for fully offline syntax highlighting
v1.2 Feb 12, 2026

The release where MarkeMark went from a working prototype to something you'd want to use daily.

  • Full GFM rendering: tables, task lists, nested lists, footnotes, highlights, auto-links
  • Syntax highlighting with highlight.js (auto-detects language)
  • Find bar (Cmd+F) with real-time match counting, next/previous, case sensitivity
  • Export as HTML — self-contained file with all CSS and JavaScript inlined
  • Undo/redo from either pane
The Great Simplification Feb 13, 2026

After several sessions and roughly 1,100 lines of code spent trying to mirror selections and cursors between panes, the root design flaw became clear: two independent algorithms that had to agree on block counts, but couldn't — the markdown renderer and the DOM structure used fundamentally different counting. Every fix introduced a new edge case.

The solution was to delete all of it. Sync cursors, selection highlighting, source-line annotation — all removed. Sometimes the best code is code you delete. (Pane sync came back later in v1.5, with a much simpler approach.)

v1.1 Feb 6, 2026

Focused on making the editor feel responsive rather than adding new features.

  • 250 ms debounced editor-to-preview sync — no more per-keystroke re-renders
  • Incremental DOM updates that preserve scroll position instead of reloading the whole page
  • View mode switching: Cmd+1 (preview only), Cmd+2 (editor only), Cmd+3 (split)
  • PDF export
  • Modern paste handler using the Selection API
v1.0 Feb 6, 2026

The starting point. One question: what if you could edit either side of a markdown editor?

  • Split-pane layout with resizable divider
  • Bidirectional editing — write markdown on the left, or edit the rendered preview on the right, and changes sync both ways
  • Custom markdown renderer and HTML-to-markdown converter
  • Dark mode in both panes
  • Open and save .md, .markdown, and .txt files
Engineering note: The entire app — SwiftUI interface, markdown rendering, bidirectional editing, and this website — was built with Claude Code.