All notable changes to Quoll are documented here.
- The copy button on a code block no longer hangs over the block's top edge and its rounded corner. It sat too high on blocks without a language tag, and on code blocks nested inside a quote, whenever the cursor was outside the block.
- Dragging to select text in a table now keeps the selection when you release the mouse outside the table, and when the document scrolls mid-drag. Previously either case dropped what you had selected and left a plain cursor behind.
- Internal hardening of the table cell's text-mapping code, plus test coverage around it. Nothing changes in how the editor looks or behaves.
- Dragging to select text inside a table cell that contains formatting — bold, a link, inline code, an escaped character — now selects exactly the characters you dragged over. Previously any such cell selected as a whole the moment you dragged inside it.
- Rewrote the Marketplace page: what Quoll does is now shown in short animations (live Markdown reveal, task checkboxes, table editing, the document outline), and the formatting shortcuts and editor settings that were missing from it are documented. The editor itself is unchanged.
- Internal robustness work in the image, table and task-checkbox blocks. Nothing changes in how the editor looks or behaves.
- Dragging across text in a table now keeps your selection when the raw Markdown appears — previously the selection collapsed to a single cursor the moment the table opened for editing.
- Clicking a same-document link like
[intro](#getting-started)now scrolls to the heading it names, instead of doing nothing.
- A relative link Quoll refuses to open because its target falls outside both the workspace and the document's own folder now shows a message explaining why, instead of the click silently doing nothing.
- A single broken inline decoration (heading, emphasis, link, table, or image) can no longer take every other inline decoration in the editor down with it — previously one bad decoration reverted the whole document to raw Markdown until you reloaded the window.
- Links that Quoll can't actually open (protocol-relative destinations, disallowed schemes, oversized addresses) no longer show a pointer cursor, so they no longer look clickable.
- If pasting an image fails while inserting its link, Quoll now cleans up after itself instead of leaving a stray file in your workspace with no link — retrying the paste no longer looks like a duplicate.
- "Quoll: Format Document" now tells you to open a Markdown file in the Quoll editor when none is active, instead of appearing to do nothing.
- The Command Palette no longer lists "Quoll: Format Selection", which could never do anything from there. The formatting shortcuts inside the editor (bold, italic, code, strikethrough, link) are unchanged.
- Quoted text in the light theme now meets accessibility contrast guidelines, including nested blockquotes and callouts that were still too faint at deeper nesting levels.
- Format Document now gives your bullet lists one consistent marker, rewriting
*and+items to-. Lists where that change would alter how the document reads — merging with a neighbouring list, or turning an item into a horizontal rule — are left exactly as you wrote them.
- Pasting plain Markdown you copied from somewhere else — a checklist, a list, a heading — now lands exactly as you copied it, instead of arriving with a backslash in front of every
-,[, and]and its blank lines squashed away. Pasting genuinely formatted text (bold, links, headings, tables) is unchanged: stray Markdown characters inside it are still neutralised so they stay literal. - Converted rich paste no longer merges separate lines together: content laid out as separate blocks stays on separate lines, and a blank line between them survives instead of turning into a stray
\. - Switching back to a Quoll tab no longer occasionally lands you at the wrong scroll position when the editor was resized while hidden — for example with the outline pinned open. Your place is now restored once the layout has settled, including when it settles late.
- Typing a lone
-/=under a paragraph no longer shrinks that paragraph to the default font size when a non-default font-size preset is active.
- The stale-fold clamp (from 0.1.61–0.1.63) now reliably kicks in right after an external change, instead of occasionally missing on the very next update while the document was still being re-parsed.
- A collapsed list no longer hides a list item that an external change (a formatter, git, or another editor) inserts into it. As with headings, the fold now shrinks back to its own item, so the newly-added sibling stays visible instead of being concealed until you unfold.
- A collapsed section no longer hides a heading that an external change (a formatter, git, or another editor) inserts inside it. The fold now shrinks back to its own section, so the newly-added section stays visible instead of being concealed until you unfold.
- Collapsed sections no longer spring open when the file is changed outside the editor (by a formatter, git, or another editor). Your folds stay put; only a fold that directly overlaps the external change is affected.
- Pasting images into a single document is now capped at a generous total size per editing session, guarding against runaway disk use from a misbehaving source. The limit is far above any normal paste workflow; if it is ever reached, further image pastes are declined with a one-time notice and resume when you reopen the document.
- Links with percent-encoded characters now open correctly: a relative link like
[notes](my%20notes.md)opens the space-named file, and external links containing%2For+(GitLab-style API URLs, search queries) reach your browser unchanged instead of being silently altered.
- Format Document now leaves a table whose delimiter row omits its outer pipes (e.g.
:-- | --:) byte-untouched, matching how it already treats pipe-less header and body rows, instead of rewriting just that row's outer pipes. - When a file is changed on disk while you have unsaved edits, the reload-or-keep prompt now only fires for the document you're actually looking at, and a file that isn't valid UTF-8 no longer triggers a spurious conflict — closing edge cases that could otherwise discard your in-editor changes.
- When a document becomes read-only, the metadata (frontmatter) block no longer tells screen-reader users they can move the caret in to edit it — that hint now disappears in step with the document's writability instead of lingering as a dead-end affordance.
- Inside a table cell,
[a](x\ y)now renders as literal text instead of a link, matching how the same text renders everywhere else. Only proper backslash escapes (like\)) still keep a link intact. - Links inside table cells now go through Quoll's link-safety check consistently no matter how you open them — middle-click and the right-click "Open Link" menu can no longer bypass the validation that a normal click already went through.
- Pasting rich text where a bold or italic span has whitespace at its edge (a space, or a line break, just inside the bold) now renders as emphasis instead of showing the literal
**/*markers. - Pasting a numbered list that starts at an unusual value (a negative or very large
start) now produces a valid numbered list instead of degrading to plain paragraphs. - Clicking a code reference like
`src/foo.ts`in a document that lives outside every open workspace folder now opens the file next to the document, instead of guessing a same-named file under an unrelated workspace root. - A lint rule with a very long message (for example one quoting a long duplicate heading) no longer blanks out the whole Problems list for the document — the message is trimmed and the other problems still show.
- Keyboard focus in the outline is now preserved when a section collapses or the outline rebuilds after an edit, instead of dropping back to the top of the page.
- Reaching for the outline sidebar's resize handle no longer causes the hover-opened sidebar to close mid-reach.
- The
Cmd/Ctrl+.lint autofix no longer deletes the blank line above when the caret is resting at the start of the following (clean) line — it now only acts when the caret is actually on the flagged line.
- Screen readers now announce when the outline's active section changes as the caret moves through the document, not just when you navigate the outline tree directly.
- Enter now behaves correctly in a few list and blockquote edge cases (non-sequential ordered lists, a blockquote nested in a list, a fenced code block opened right after a
>or list marker) where it previously produced the wrong result. - Pasting rich text (e.g. from a webpage) while the caret is inside a fenced code block no longer corrupts the fence — it now pastes as plain text instead.
- Closed a gap where some auto-linked URLs (like a bare
xmpp:address) could skip Quoll's link-safety check before being saved to disk. - Switching to the text editor while an edit is blocked by the safety check no longer risks closing the Quoll tab and losing your unsaved draft, and the resulting warning now explains why.
- Fixed rare cases where typing quickly right after an edit settled, or while an external file change was still coalescing, could visibly rewind or drop your latest keystrokes.
- Fixed a rare case on documents with Windows-style line endings (CRLF) where a queued edit could be silently dropped instead of applied.
- Workspace code references like
`src/foo.ts:42`in inline code are now clickable — and openable from the keyboard withCmd/Ctrl+Enter— opening the file in a text editor at the referenced line and column. - Pasting rich text copied from a web page, Google Docs, or a chat window now converts it to Markdown — headings, bold/italic, links, nested lists, code blocks, blockquotes, and tables all survive — instead of landing as plain text. Anything that can't be converted safely falls back to the usual plain-text paste.
- Pasting a Markdown list into an existing list now re-bases the pasted items' indentation to the caret's nesting level, keeping the fragment's inner structure intact.
- A new "Quoll: Format Document" command applies a conservative Markdown clean-up on demand — it runs only when you invoke it, never on save.
- Task checkboxes can now be toggled from the keyboard: press
Cmd/Ctrl+Lwith the caret on a task line.
-
correct stale comments across host, webview, and build config (#349)
-
Accessibility polish across the outline sidebar and editor chrome: the outline settings popover now behaves as a proper dialog for assistive tech, the hover outline overlay closes when keyboard focus leaves it, the outline tree announces the document's title, the pinned outline's resize divider is keyboard-operable, and the frontmatter metadata text now meets WCAG AA contrast.
- Table cells now render
~~strikethrough~~and==highlight==marks, matching how they already render everywhere else in the document.
- Fixed a rare case where switching away from a document right after typing quickly could visibly erase the last keystroke.
- Obsidian-style
==highlight==marks are now recognized: type==text==to highlight it, styled to match your light/dark/high-contrast theme. - A new status bar slot shows word count, character count, and estimated reading time for the active document (frontmatter and fenced code blocks are excluded from the word count and reading time).
- The outline sidebar now supports full keyboard navigation: Up/Down/Home/End move between headings, Left/Right collapse or expand a heading (or jump to its parent/child), and Enter jumps to that heading in the document.
- Fenced code blocks with a recognized language now show a header bar with the language name and a copy button, similar to ChatGPT's code block style. The header hides while you're editing the block so it doesn't duplicate the raw ```lang line.
- Fenced code blocks now show syntax highlighting (keywords, strings, comments, numbers, types) for blocks with a recognized language.
- Fenced code blocks now have a language picker, so you can set or change a block's language directly in the editor.
- High-Contrast themes are now recognized separately from Light, so High Contrast Black no longer risks falling back to the light color palette.
- Tab and Shift-Tab in lists now perform structural moves instead of shifting whitespace: Shift-Tab out of a bullet into a numbered list adopts that list's numbering and renumbers it, and Tab nests a bullet under a numbered item to the correct content column — even healing a list that was already mis-nested too shallowly.
- Pressing Enter then Shift-Tab on an empty list item now adopts the destination list's shape (bullet, checkbox, or number) instead of keeping the wrong marker.
- Nesting an ordered list item that starts a new sub-list now restarts the sub-list at "1." and renumbers the outer list to close the gap, matching how Notion handles the same move.
- Screen readers now present the document outline as a tree — announcing each heading's depth in the hierarchy, your current position, and whether a section is expanded or collapsed — instead of a flat list of buttons.
- Screen readers now announce "Copied" (or "Copy failed") when you use a fenced code block's copy button, so the result is confirmed aloud instead of only changing the button's icon.
- Keyboard users arrowing through the outline panel's font/size/line-height/width segments, or focusing a heading's expand/collapse twistie, now see a visible focus ring — previously neither control showed any focus indicator.
- With the outline panel pinned, switching away from and back to a Quoll tab (including the Cmd+Option+K context hand-off) no longer leaves the editor blank or partially blank until you scroll — the editor now restores your position and redraws the text immediately.
- With the document outline pinned, pressing Cmd+Option+K (hand the selection to Claude Code) no longer squeezes the editor into a one-character-wide column. The reading column now keeps its width through the hand-off.
- The cat title-bar button on a Markdown text tab now swaps that tab to the Quoll editor in place, instead of leaving the text tab open and adding a second Quoll tab. It mirrors the file-code button's Quoll→text swap, so switching either direction keeps you on a single tab.
- Blockquotes and callouts now keep a small vertical gap from the block directly above and below them, even when no blank line separates them in the source. A panel that immediately follows a list item or paragraph no longer renders flush against that line's bottom edge, while nested quotes stay visually joined to their parent.
- Fenced code blocks now keep that same vertical gap from the block directly above and below them. A code block that immediately follows a list item or paragraph no longer renders flush against that line, and a long block's "Show more" / "Show less" collapse bar keeps the gap at the panel's true bottom without opening a gap mid-panel. A code block nested inside a blockquote stays visually joined to its parent.
- Two fenced code blocks written back-to-back with no blank line between them now sit a single small gap apart, matching the spacing used everywhere else, instead of a doubled gap.
- Collapse and expand individual headings in the document outline: any heading that has sub-headings now shows a chevron — like the Explorer file tree — that folds just that heading's children (mouse or keyboard). Leaf headings stay aligned without one.
- Opt-in advisory prose lint rules: flags passive voice, filler/hedge words, and sentences over 30 words as info-level hints in paragraphs. Off by default — enable with the
quoll.lint.prose.enabledsetting.
- The outline's "OUTLINE" header is now a plain label; folding happens per heading instead of collapsing the whole panel.
- Editor settings popover in the outline sidebar: choose the font (Default / Serif / Sans), font size, line height, and reading-column width. Open it from the gear button in the sidebar footer; choices are saved to your settings and apply to every open Quoll editor.
- Add title-bar buttons to switch between Quoll and the built-in text editor from either side: a cat icon on a Markdown text editor opens it in Quoll, and a file-code icon on a Quoll editor reopens it as text.
- Polish the document outline sidebar to match VS Code's native side panels: the corner toggle and pin button use proper icons, the "OUTLINE" header now reads and behaves like the built-in EXPLORER section (including a chevron to collapse/expand it), and row alignment sits under the header label.
- Switch the toolbar's "open in text editor" icon to better match what it does.
- Refresh the hero image used on the Marketplace page.
- Smart list continuation: pressing Enter at the end of a list item now continues the list (adding the next bullet, or the next number for ordered lists) instead of just inserting a blank line, and pressing Enter on an empty list item exits the list instead of leaving a dangling empty marker. Deleting or reordering items in an ordered list renumbers the remaining items to stay sequential.
- Refresh the Marketplace branding: a new extension icon, updated hero and editor-overview images, and a tidied README header.
Combined patch-release notes, newest first. Releases after 0.1.36 get their own per-version sections above.
- Make the document outline sidebar read like a native VS Code side panel, and let you resize it. The header now puts the pin button at the right edge with a thin rounded border so it reads as a button rather than a bare icon, the "OUTLINE" label matches VS Code's side-panel section-header type (size/weight/colour via the side-bar section-header theme token), and the panel background uses VS Code's own side-panel background so it matches the built-in panels instead of the editor surface. The panel is now horizontally resizable: drag the divider on its right edge to widen or narrow it (both while hovering and while pinned), and the width you choose is remembered across reloads. A minimum/maximum keeps the editor column from being squeezed out. Colours still track dark, light, and high-contrast themes, and it stays display-only — the Markdown round-trips byte-for-byte.
- Add keyboard shortcuts for inline formatting. With the Quoll editor focused,
Cmd/Ctrl+B,Cmd/Ctrl+I,Cmd/Ctrl+E, andCmd/Ctrl+Shift+Xnow toggle the selection's Markdown bold (**…**), italic (*…*), inline code (`…`), and strikethrough (~~…~~); pressing the same chord again on the wrapped text unwraps it back to the original, so a shortcut round-trips. With no selection, the chord inserts an empty marker pair and drops the caret between the markers ready to type.Cmd/Ctrl+Kwraps the selection as a link —[text](…)— placing the caret in the empty URL slot to type or paste the address (with nothing selected it inserts[](…)with the caret in the text slot). The bindings are scoped to the active Quoll editor, so they override VS Code's defaults (toggle sidebar, open Extensions) only while you're editing there and leave those defaults untouched everywhere else; a read-only document ignores them. Every change flows through the normal save path, so the Markdown round-trips byte-for-byte. - Wrap a selection as a Markdown link when you paste a URL over it. Selecting text and pasting a single
http(s)URL now replaces the selection with[selection](url)in one undo step — the Notion/Obsidian behaviour — so linking a phrase is a select-and-paste instead of typing the brackets by hand. Detection is deliberately strict: the clipboard must be exactly one URL token (a URL followed by trailing text, a non-http(s)scheme likemailto:, or a multi-line selection all fall through to a normal plain paste), and it reuses the same URL-safety allowlist as the rest of the editor. This replaces CodeMirror's looser built-in URL-paste, which wrapped a URL-plus-trailing-text and accepted schemes outside the allowlist. Pasting with no selection, and every non-URL paste, is unchanged; a read-only document ignores it. The inserted link flows through the normal save path and round-trips byte-for-byte. - Add a Getting Started walkthrough (Command Palette → "Welcome: Open Walkthrough..." → Quoll, or the Welcome page) covering the five things that aren't obvious from just opening a
.mdfile: opening it in Quoll, the caret-driven live-reveal of Markdown syntax, toggling to the built-in text editor and back, the built-in Outline view, and thequoll.lint.*/quoll.editor.spellchecksettings. Purely additive Marketplace/editor-chrome content — no runtime behaviour change. - Add GitHub issue templates (bug report, feature request) and a link from the README to the Issues page, so bug reports and feature requests arrive with the fields Quoll actually needs (VS Code/Quoll version, a repro snippet, expected vs actual). No code or editor-behaviour change.
- Consolidate the webview's ~9 near-identical "post a message to the host, log and swallow a transport throw" blocks (edit, lint-diagnostics, caret-report, context-handoff, codex-context-handoff, switch-to-text, open-external, link-open, image-write) into one shared helper. Purely internal — the log text and every post-failure fallback behave exactly as before.
- Remember which editor surface you last used for each file, within a session. If you switch a
.mdto the built-in text editor (or open it in Quoll), Quoll now reopens that file in the same surface next time you open it this session — so a file you were reading in Quoll comes back in Quoll instead of dropping to plain text. It's session-only and lives entirely in memory: a full VS Code restart deliberately forgets, and nothing is written to disk or your settings. Because VS Code decides the initial editor before an extension can intervene, a file briefly opens in the default surface and is then swapped to the remembered one; the swap never saves or discards your work, and it closes the extra tab so only one surface stays open (a file with unsaved changes is left in both rather than saved). Explicitly opening a file in Quoll is always honoured — it's never bounced back to text. - Add a document outline sidebar. Hovering the top-left corner button now slides in a left-edge panel listing every heading in the document, indented by level; clicking a heading moves the caret there (a selection-only jump — nothing is edited) and closes the sidebar. A pin button in its header switches it from a hover-close overlay to a pinned, always-open 2-column layout that sits beside the editor instead of floating over it, for a keep-it-open browsing session;
Mod-Alt-otoggles it from the keyboard, and a settings-gear footer is reserved for future outline options. The list only rebuilds while the sidebar is open — a full parse once on deliberate open, then a debounced incremental rebuild as you keep typing — so the keystroke path pays nothing while it's closed. Colours track dark, light, and high-contrast themes. Display-only — it never touches the document, and the Markdown round-trips byte-for-byte. - Fix
⌘⌥Eleaving both the Quoll and text-editor tabs open instead of swapping in place. Toggling the editor surface used to open the target editor as a new tab alongside the source, so after a few toggles you'd accumulate duplicate tabs for the same file; the command now closes the source tab once the target is open (saving first if it was dirty), so the toggle always leaves exactly one surface open, in both directions. It's safe under an in-progress edit or a failed save (the close is skipped rather than risking data loss), and toggling from a non-active split only closes that split's own tab, leaving other splits of the same file untouched. The caret still carries across the swap as before. - Refresh the Marketplace positioning copy to lean on Obsidian rather than Notion — the README and description now describe Quoll as an Obsidian-style Markdown editor — and add an MEO keyword for discoverability. "Notion" is kept as a search keyword/topic so users looking for a Notion-style editor still find Quoll. No code or editor-behaviour change.
- Bring back the status bar while a Quoll editor is active. Because a Quoll editor isn't a plain text editor, VS Code hid its whole built-in status bar (cursor position, line ending, and so on) whenever a
.mdfile was open in Quoll. The useful part is back: a status-bar readout now shows the live cursor position (Ln X, Col Y, updating as you move the caret), the file's line ending (LF/CRLF), and aMarkdownindicator. It appears only while the Quoll editor is the active tab and disappears when you switch away. Encoding and indentation are intentionally left out — VS Code exposes no public way to read them for a custom editor. Display-only — it never touches the document, and the Markdown round-trips byte-for-byte. - Show the selected character count in that status-bar cursor readout, matching VS Code's native text editor. Selecting text now appends the count —
Ln 29, Col 1552 (147 selected)— and it disappears the moment the selection collapses back to a plain cursor. It counts the primary selection (a multi-cursor sum is a follow-up). Display-only — it never touches the document. - Remove the per-document reading stats readout. The bottom-right words/characters/reading-time overlay added in the previous release has been taken out; the editor surface is unchanged otherwise and the Markdown still round-trips byte-for-byte.
- Stop losing unsaved text-editor edits when you close the text tab of a file you're also viewing in Quoll — the mirror of the fix below. If a
.mdfile had unsaved changes in the built-in text editor and you also had it open in Quoll (both tabs open), closing the text tab and answering "Don't Save" used to silently discard those edits: VS Code reverts the shared document when a text editor closes over a custom editor, and the still-open Quoll editor then reseeded to the on-disk content. Quoll now detects that close-triggered revert while it stays open and restores the unsaved bytes, so your work survives. An explicit "Revert File" is still honoured — it has no accompanying tab close, so Quoll reseeds to disk as before (an external revert wins). No effect on saving, and the Markdown round-trips byte-for-byte. - Stop losing unsaved edits when you close Quoll over a file you're also editing as text. If a
.mdfile had unsaved changes in the built-in text editor and you opened the same file in Quoll (both tabs open), closing the Quoll tab and answering "Don't Save" used to silently discard those text-editor edits — VS Code reverts the shared document when a custom editor closes, even though another editor still holds it. Quoll now detects that case on close and restores the unsaved bytes to the still-open editor, so your work survives. A genuine discard is still honoured: if Quoll was the only editor holding the file, "Don't Save" throws the changes away as before. No effect on saving, and the Markdown round-trips byte-for-byte. - Fix the vertical scrollbar sitting ~20px inside the editor pane's right edge, with a matching dead strip on the left. VS Code injects its default webview stylesheet —
body { padding: 0 20px }— as an unlayered rule, and per CSS cascade layers an unlayered declaration beats every layered one regardless of source order or specificity; Quoll's ownbodyreset lived inside@layer reset, so VS Code's 20px padding quietly won and inset the whole editor (scrollbar included) from the pane edges. The reset is now an unlayeredhtml bodyrule whose higher specificity beats VS Code's barebodyorder-independently, so the scrollbar sits flush against the pane's right edge. The centred reading column is unchanged —.cm-contentowns its own measure and inset — so only the outer whitespace shifts. Display-only. - Tighten the gap between the fold/unfold chevron in the gutter and the line it belongs to. The chevron sat noticeably far from the content column; it now slides closer so the caret↔content spacing is about two-thirds of what it was, while still stopping short of the text (no overlap, still clickable in both the collapsed and expanded states) and leaving the centred reading column and both themes unchanged. Display-only.
- Convert a pasted HTML table into a Markdown table. Copying a table from a web page, a spreadsheet, or a document and pasting it into Quoll now inserts an equivalent GFM table — header row, alignment delimiter, and body rows — instead of the raw HTML or a wall of tab-separated text, placed on its own blank-line-separated block. Cell text is escaped so pipes, backslashes, and Markdown link/code/emphasis characters survive as literal text; a
<br>or newline inside a cell collapses to a space; merged cells (colspan/rowspan) spread into empty placeholders so the columns stay aligned rather than shifting; and a link or image inside a cell drops to its visible text (an<img>cell becomes empty), so no pasted URL ever enters the document as a live link. Every other paste is unchanged — plain text, a URL dropped over a selection, and image files all behave exactly as before — and a read-only document ignores the paste. The generated Markdown flows through the same save path as ordinary typing (an over-large paste surfaces the usual "too large to save" banner), and it round-trips byte-for-byte thereafter. - Show per-document reading stats. A small, unobtrusive readout in the bottom-right corner of the editor now reports the current document's word count, character count, and estimated reading time, with the heading and link counts in its tooltip. Frontmatter and fenced code blocks are excluded from the word and character counts, and CJK text is counted per character (matching how it carries no spaces between words). The readout is dim at rest and brightens when you hover over the editor, slides away with the other floating controls as you scroll down, and refreshes a moment after you stop typing so it never interrupts your flow. Display-only — it never touches the document, and the Markdown round-trips byte-for-byte.
- Make relative Markdown links click-to-open (page-to-page navigation). Clicking a link whose target is a relative
.mdfile —[notes](./other.md),[up](../index.md)— now opens that file in Quoll, so you can move between notes the way you would in Notion or Obsidian. External links (http/https/mailto) still open in your browser/mail client exactly as before, and a fragment, an image, or any non-.mdrelative link is unaffected (the click reveals its source for editing). The target is resolved and validated entirely on the extension side against the current document's location and kept within your workspace — the webview only ever hands over the link text, never a filesystem path — and a link that points outside the workspace is refused. Display-only for the source document — the Markdown round-trips byte-for-byte. (Phase 1 of the feature; author-side autocomplete for link targets is a separate follow-up.) - Ship a root
NOTICEin the packaged extension. The distributed bundle inlines several MIT-licensed CodeMirror and Lezer packages, whose licence requires their copyright and permission notice to travel with the code; the.vsixnow carries aNOTICEreproducing them. A build-time test asserts every third-party package actually bundled intodist/is named inNOTICE, so a future dependency can't ship unattributed. No user-facing behaviour change. - Add a setting to toggle the editor's native spellchecker.
quoll.editor.spellcheck(default on) drives thespellcheckattribute on the editing surface, so the platform's built-in spell suggestions (the red squiggly underlines) appear as you write and turn off cleanly when you disable the setting. Like the lint-gutter setting, the change is pushed to every open Quoll editor immediately — no reload — and it never touches the document, so the Markdown round-trips byte-for-byte. - Restyle unordered-list bullets and task checkboxes. The marker now sits a touch further from its text — bullets and checkboxes share the same wider gap — the top-level bullet is a slightly larger filled dot, and nested bullets now vary by depth: a filled dot at level 1, a hollow dot at level 2, and a short dash at level 3 and deeper (an Obsidian-style depth cue). Ordered-list numbers and the checkbox glyph are unchanged, wrapped continuation lines stay aligned under the item text at every depth even at the wider gap, and it works in both dark and light themes. Display-only — the Markdown round-trips byte-for-byte.
- Add an opt-in autofix to the "multiple consecutive blank lines" lint. Quoll already flagged a run of two or more blank lines in the Problems panel (and the opt-in gutter), but there was nothing to apply — the finding had no fix. Pressing
Cmd/Ctrl+.on a flagged run now collapses it to a single blank line, deleting the excess blank line(s) including their terminators (correct at the start/end of the file and under CRLF). The fix runs only through that explicit keypress, never on save, so a document you never touch still round-trips byte-for-byte; the finding stays decoration-free in the editor (a filled whole-line underline would read as a phantom blockquote). - Give every list item the same vertical breathing room so bullet, ordered, and task lists no longer read cramped. Previously only loose list items (separated by a blank line) and a list's first item after prose were spaced, while consecutive tight items — nested
Done when:-style sub-bullets, a checkbox list continued with Enter — packed together with no gap; now every list-item line carries a uniform ~0.5em top gap (a loose item still reads a little more open because its blank source line adds its own height on top). The marker column, hang-indent, and soft-wrapped continuation alignment are unchanged, both themes are unaffected, and the fold chevron stays centred on each item's row. Display-only — the Markdown round-trips byte-for-byte. - Fix content-less list items rendering wrong in two ways that shared one root cause. An empty task checkbox —
- [ ]with nothing typed after the marker — showed the raw bullet and literal[ ]text instead of the interactive checkbox: the GFM parser only emits a task node once the marker is followed by content (a trailing space or text), and Quoll keyed the checkbox on that node, so a bare- [ ]got none until you typed a character. Separately, an empty nested sub-bullet (-with no text) rendered shallower — further left — than a content-bearing sibling at the same source indent, because the list hang-indent skipped its alignment metric for an item with no content. Quoll now recognises a bare[ ]/[x]first-line marker as a checkbox (toggling works, identical to one with text) and gives an empty item the same implied-single-space hang as a filled sibling, so both align — including an empty item nested under a checkbox. Content-bearing checkboxes and bullets, multi-level nesting, and a stray[ ]written lower in the same item (which is not a checkbox) are all unaffected, and the Markdown round-trips byte-for-byte. - Fix a paragraph ballooning into a heading when you type a lone
-on the line below it to start a bullet list. In CommonMark a paragraph line immediately followed by a line of one-or-more-(or=) is a setext heading, with that dash/equals line as the underline — so the instant you typed the-, Quoll styled the paragraph above as a big heading, exactly when you meant to start a list. Quoll now treats a lone single-/=underline as a nascent list marker and renders the paragraph as plain text, so the surprise heading never appears; a real multi-character underline (---/===) still renders as a heading as before. The de-style is caret-independent — it doesn't flicker back to a heading when you click away — and the Markdown round-trips byte-for-byte. - Finish demoting that nascent lone
-/=setext so it sheds every heading affordance, not just the big font. The paragraph above the lone underline still got a heading's extra top spacing and a fold chevron in the gutter — both keyed off the raw heading node type the font de-style didn't touch — so it read as plain text yet sat and folded like a heading. All three now consult one shared rule, so a nascent list gets no heading spacing and no chevron; a real multi-character---/===heading keeps all of them, unchanged. - Keep a formatted paragraph's inline styling when a lone
-/=under it makes it a nascent setext. De-styling that heading back to plain text used to flatten the paragraph's own emphasis along with it — bold went un-bold and a link lost its colour (Foo **bar** [x](url)above a lone dash rendered uniformly plain) — because Quoll reset the whole line and CodeMirror paints the heading and inline-emphasis styling on the same span. The bold, link colour, italic, and inline-code styling of the text are now preserved while only the heading look (big navy font) is dropped; a real---/===heading is unchanged, and the Markdown round-trips byte-for-byte. - Fix a nested list item's wrapped continuation lines staying mis-aligned after a live change to the editor's body font. Quoll measures the rendered width of one space in your proportional body font to size a list's hang-indent so wrapped lines line up under the item's text — but it only re-measured on mount, resize, and zoom, all of which CodeMirror signals through a geometry change. A font swap that keeps the line height constant raises no such signal: a dynamic
--vscode-font-familychange (which CodeMirror never observes) or a late-loading webfont with different metrics left the hang-indent on the old measurement until you reloaded the tab. Quoll now watches the measuring probe's own width with aResizeObserver, so any font change that shifts the space advance re-aligns the wrapped lines immediately, no reload. Display-only — the Markdown round-trips byte-for-byte. - Fix a thematic break nested as a list-item child (
- itemthen an indented---below it) rendering as a rule flush against the document's left margin instead of aligned under the item. Quoll draws a---line as a horizontal rule and, for an indented break, folds the leading indent into the full-width rule — correct for a top-level---, but the same folding pulled a list-continuation break out to the margin even though the item's other nested content (a paragraph under the item) sits at the item's content column. The rule now insets to that same content column when the break is a list-item child, matching its sibling content; a top-level indented---still renders flush-left, and a blockquote break (> ---) still renders inside its quote. Display-only — the Markdown round-trips byte-for-byte. - Fix the save-policy banner rendering beside the editor instead of above it. When Quoll refuses to save a document (an edit that would write unsafe Markdown), it shows a warning strip — but the editor shell was a horizontal flex row, so that strip appeared as a narrow column squeezed to the left of the editor rather than as a full-width bar across the top. The shell now stacks vertically: the banner is a full-width strip above the editor, and the editor fills the remaining height below it. The editor's internal scrolling (and the scroll-to-hide of the floating toolbar) is unchanged.
- Fix keyboard focus being stranded on a task-list checkbox when a Space/Enter toggle can't complete. Pressing Space or Enter on a focused checkbox consumes the keystroke, then hands focus back to the editor so you can keep typing — but that focus return only ran when the toggle actually succeeded. If the toggle aborted (its source marker had shifted out from under the cursor, the document was read-only, or the view was tearing down), focus stayed on the about-to-be-replaced checkbox and your next keystroke went nowhere. Focus now returns to the editor regardless of whether the toggle applied. Mouse clicks still deliberately leave focus alone. No change to the successful-toggle path or the Markdown.
- Recognise a callout marker written with a TAB after the
>(>\t[!NOTE]), matching the space-separated form. Quoll only accepted spaces between the quote marker and the[!TYPE]token, so a tab-indented marker rendered as a plain blockquote — no accent colour, no marker-row concealment. It now walks the quote prefix in columns with CommonMark's 4-column tab stops, so>\t[!NOTE]is a callout, a tab between nested markers (>\t> [!NOTE]) still opens a nested callout, while a deeper tab indent that forms an indented code block (e.g.>\t\t[!NOTE], or>\t[!NOTE]where the tab reaches column 4) correctly is not — staying in lockstep with how the parser reads the line. Display-only — the Markdown round-trips byte-for-byte. - Stop the fenced-code copy button re-serialising a code block's entire body on every keystroke typed inside it. Each visible block's copy button used to stash a fresh copy of the whole code body — rebuilt by concatenating the block's text on every edit, viewport shift, or re-parse — so typing inside a large (hundreds-of-KB) fenced block allocated that whole string once per keystroke, adding avoidable GC pressure for a value only needed at click time. The button now keeps just the block's open-line offset and computes the body lazily when you actually click Copy, reading the current document — so it copies exactly what's there after your edits, with no per-keystroke allocation. Purely internal — the button copies the same text as before.
- Stop rebuilding the advisory-lint underline set on every keystroke. Between the debounced lint passes, each character you type used to re-create every diagnostic's underline range from scratch and re-sort them into a fresh decoration set — cheap for a handful of findings, but O(number of findings) per keystroke, which only bites on a pathologically messy paste (tens of thousands of findings). Quoll now holds the underline set as a mapped structure and shifts it through each edit in proportion to the change size, matching CodeMirror's own lint layer; the raw findings are still kept for the hover tooltip, the Problems mirror, and the opt-in gutter. Purely internal — the underlines, gutter dots, and hover behave exactly as before.
- Bound the caret-position reports Quoll streams to the extension host as you move the cursor. Dragging out a selection (or holding an arrow key) fires a cursor-move event on every tick, and Quoll used to post each one to the host — which only ever keeps the latest, for the editor-switch handoff. It now coalesces them to a single report ~100ms after the cursor settles, and still flushes the final position immediately before you switch to the built-in text editor or close the tab, so the caret you land on after a switch is always the one you left. Purely internal — no visible change.
- Fix Enter stalling briefly on every keystroke right after opening a large document. The auto-close-fence handler (which turns Enter on an unclosed
```opener into a matching closing fence) ran on every Enter and, before doing any fence check, forced the Markdown parser all the way to end-of-document — so pressing Enter in a plain paragraph near the top of a big, freshly-opened file could hang for up to ~50ms until that parse converged. It now parses only up to the caret line: a plain-paragraph Enter resolves cheaply and never touches the rest of the file, while a caret on a real fence opener still parses far enough to close the block correctly (for an already-closed fence it stops at the closer, not the document end). Fence auto-close behaviour is unchanged. - Fix a document with pathologically nested emphasis inside a GFM table cell (
| *a *b *c …* |) or image alt () failing to open in Quoll at all. The inline tree builder and its two walkers (cell renderer, alt-text extractor) all recurse once per emphasis nesting level, so a deeply nested run could overflow the JavaScript call stack; because the throw was uncaught outside the URL gate, it propagated through the editor mount and Quoll reported "webview failed to start". The tree builder is now iterative; the tree walkers cap recursion at 100 levels (real Markdown nests at most ~3) and emit the raw source literal for anything deeper; and both entry points are wrapped in fail-closed catches as defence in depth. Normal documents are unaffected. - Harden the protocol validator for image paste/drop results so a success and a failure are discriminated on
ok: a success must carry a document-relative path and a failure must not. The shapes were previously checked independently, allowing an incoherent object to pass boundary validation; the webview already treated a missing path as failure, so there is no user-visible change. - Tighten the webview's script/style URL guards to reject
&, matching the guard already applied to the image resource-base URL. The extension builds its<script>/<link>source URLs from its own install path, then validates them before writing them into the page — but that check allowed&, which an HTML parser can read as the start of a numeric character reference (e.g."→") and use to break out of the attribute. Not an exploitable gap (these URLs always derive from the extension's own trusted install path, which the platform percent-encodes), just a consistency fix so all three URL guards fail closed the same way. No user-facing behaviour change. - Route a table cell's link opens through the same host security check as every other link in Quoll. Opening a link inside a rendered table (Cmd/Ctrl-click) used to hand the URL straight to VS Code's built-in link handler, skipping the allowlist re-check Quoll re-applies host-side to every other link open — a redundant safety layer rather than an exploitable gap, since the URL is already validated when the cell renders and VS Code itself refuses non-
http(s)/mailtoschemes. Both paths now go through the same host check, so the defence is consistent. A pathologically long in-cell link (over 8 KB) now reveals its source for editing instead of doing nothing, matching how oversize inline links already behave. Everyday links open exactly as before, and the Markdown round-trips byte-for-byte. - Fix a thematic break written inside a blockquote (
> ---) rendering as a rule that jumped out of its quote. Quoll draws a---line as a horizontal rule, and when the caret is off that line it hid the whole line behind the rule widget — but for> ---"the whole line" includes the>quote marker, so the rule appeared at the document's left margin instead of inside the blockquote, and its concealed span even overlapped the blockquote's own marker-hiding. The rule now keeps the container prefix: a leading indent (---) is still absorbed as before, but a quote marker is preserved so the rule renders inside the quote.- ---is unaffected — it is a genuine thematic break whose-is a rule glyph, not a list bullet, so the whole line is still concealed. Display-only — the Markdown round-trips byte-for-byte. - Fix the Claude Code (
⌘⌥K) handoff over-reporting the selected line range by one when the selection ends exactly at the start of a line. Selecting a whole line including its trailing newline lands the caret at the start of the next line, and the handoff used to count that empty next line — so selecting just line 1 handed Claude#L1-2. It now anchors the end to the last character you actually selected, so the reference covers only the lines you touched; a caret with no selection still hands off the whole file as before. - Fix Select-All then typing (or Delete) doing nothing when a document leads with collapsed YAML frontmatter. The frontmatter renders as a read-only metadata card, and its guard vetoed any edit touching that region — but Select-All puts the whole document in one selection, so the veto silently dropped the entire keystroke, leaving even the body unchanged with no feedback. A Select-All (or any selection that spans the whole frontmatter block and extends into the body) followed by typing or Delete now replaces the document as expected — the frontmatter is overwritten cleanly along with the body, never left half-corrupt. The boundary guard is otherwise unchanged: a stray keystroke, a Backspace at the fence, or a partial selection inside the block is still refused so the
---fences can't be corrupted. - Surface link-open failures to the user. Clicking an external link (
http/https/mailto) hands it to the OS, which can silently fail — no application registered for the scheme, or the launch itself rejected — and Quoll used to swallow that outcome, so a dead click gave zero feedback. It now shows an error toast ("couldn't open the link") on every failure mode: a "no handler" result, an async rejection, and a synchronous throw. The specific cause still goes to the extension host log. Purely additive — a link that opens successfully behaves exactly as before. - Add in-editor find & replace. Press
Cmd/Ctrl+Fto open a find panel over the document's raw Markdown; typing highlights every match,Enter/Shift+Entercycle to the next / previous one, and the panel's replace toggle exposes replace-one and replace-all. Because search runs over the text layer, it finds source that the rich rendering hides — a heading's#, a link's URL, a table cell, or fenced-code text — that VS Code's DOM-based find would miss. Replacements go through the same save path as ordinary typing (so one that would produce unsafe Markdown is refused with the usual banner, your typed bytes kept), round-trip byte-for-byte, and re-render tables, images, and the frontmatter card from the new text; in a read-only document the panel omits its replace controls. The panel is styled to match your VS Code theme in both dark and light modes. - Fix a callout's
[!TYPE]marker line occasionally staying hidden (or failing to hide) after an edit that restructures the document from outside the callout. Quoll conceals the> [!NOTE]marker row while your caret is outside the callout, and — like the fold gutter — it only re-scans the block you're typing in, which assumes an edit can't reshape blocks elsewhere. But Markdown structure isn't that local: opening an unclosed ``` fence (or a<script>/`<!DOCTYPE` opener) in a paragraph above a callout pulls the callout into a code/HTML block, so it stops being a callout — yet the marker row could stay concealed, leaving the literal `[!TYPE]` bytes hidden until your next keystroke inside that block. Quoll now detects these structure-changing edits and rebuilds the callout conceal for them (the same guard the fold gutter uses), so the marker row is always correct; ordinary prose typing still takes the fast per-block path. Display-only — the Markdown round-trips byte-for-byte. - Fix the fold chevron occasionally landing on the wrong line, or disappearing, after an edit that restructures the document from outside the edited paragraph. Quoll only re-scans the block you're typing in for fold markers, which assumes an edit can't change the shape of blocks elsewhere — but Markdown structure isn't that local: typing an unclosed ``` fence (or a
<script>/`<!DOCTYPE` opener) above a heading pulls it into a code/HTML block, un-bulleting a list item promotes a heading nested under it, and some multi-line edits flip a distant heading in or out of a list. In those cases the gutter could keep a stale chevron or drop one until your next keystroke in the affected block. Quoll now detects these structure-changing edits and rebuilds the whole gutter for them, so the chevrons are always correct; ordinary prose typing still takes the fast per-block path. Display-only — the Markdown round-trips byte-for-byte. - Coalesce a burst of external edits to the open file into a single re-render. When another tool rewrites the file you're viewing — a formatter,
git checkout, or an AI assistant like Claude Code writing many changes in a rapid burst — Quoll used to rebuild the whole document once per change event, re-parsing and re-linting the entire file every time. It now waits ~100ms for the burst to settle and re-renders once with the final content. Edits that land while Quoll is mid-save are still applied immediately and in order (nothing is dropped or reordered), and a lone external edit still propagates promptly. Purely internal — the content shown is always the live file. - Stop the editor re-rendering a table, image, task checkbox, or fenced-code copy button on every keystroke typed in a paragraph above it. Editing above one of these blocks shifts its position in the document, which previously made Quoll rebuild the whole block — re-tokenizing every table cell, recreating the
<img>, or redrawing the checkbox/button — once per keystroke. Quoll now reuses the already-rendered block and only re-points its tracked source offsets, so typing above a block no longer churns it (less work, no flicker). Purely internal — the blocks look identical, the Markdown round-trips byte-for-byte, and clicking a cell, image, or checkbox after the shift still lands the caret on the right source line. - Fix the lint layer flagging a document's leading YAML frontmatter as if it were Markdown. A
# keyline inside the frontmatter used to be read as a heading — colliding with a real body heading of the same text (a spurious "duplicate heading" warning) and skewing heading-level checks — while trailing spaces and double blank lines inside the block drew their own warnings. These false positives were hidden in the editor (the frontmatter renders as a metadata card) but still showed up in the Problems panel. Quoll now excludes the leading frontmatter block from linting entirely, matching the common Markdown-linter default, so only the document body is checked. - Add a lint that flags a GFM table row whose cell count differs from the table's delimiter row. Quoll renders each table row's cells as-is, so a row written with too few pipes just leaves its trailing columns blank and looks plausibly correct even though it is ragged in source (a row with too many pipes instead extends the grid with extra columns). Quoll now flags each mismatched row on its own line in the Problems panel (advisory only — it never blocks a save and offers no autofix). A well-formed table raises nothing.
- Add a lint that flags problems inside a document's leading YAML frontmatter that the editor otherwise hides. Because Quoll renders the frontmatter as a metadata card, a duplicated top-level key (where the second silently overrides the first) or a structurally broken line — one that is neither a
key: value, a nested/indented value, nor a-list item, includingkey:valuewritten with no space after the colon, which YAML reads as plain text rather than a field — never surfaces visually, so these defects can quietly corrupt your metadata. Quoll now flags each on its own line in the Problems panel (advisory only — it never blocks a save and offers no autofix). A well-formed block, or a document with no frontmatter, raises nothing. - Fix the Claude Code (
⌘⌥K), Codex (⌘J), and text-editor (⌘⌥E) handoffs still able to race ahead of the edit they just flushed. Flushing posts your latest keystrokes to the host first, but VS Code applies that edit asynchronously — so a handoff fired in the same instant could still read the document before the edit landed, pointing Claude at stale line numbers, handing Codex a pre-edit file, or reopening the text editor without your last change. The host now holds the handoff (and the Quoll→text-editor switch) until the edit has finished applying, so it always sees what you just typed; if that save fails, the handoff is dropped rather than sent with stale content. - Fix the Claude Code (
⌘⌥K) and Codex (⌘J) context handoffs referencing stale content when fired right after typing. Outbound edits are debounced by ~300ms, so a handoff invoked mid-window used to point Claude at line references the host hadn't caught up to, and hand Codex the whole file without your latest keystrokes; both handoffs now flush the pending edit to the host first (respecting the in-flight single-write guard, since the editor stays open) so the reference always reflects what you just typed. - Warn when a file with unsaved Quoll edits is changed on disk by another tool. Previously a tab with unsaved edits kept showing the old content when, say, the Claude Code CLI rewrote the same file (VS Code deliberately does not auto-reload an edited tab, to protect your unsaved work). Quoll now watches the open file and, when the on-disk content diverges from your unsaved edits, offers a choice — Reload from disk (discards your edits and shows the on-disk version) or Keep my edits (leaves your work untouched; the usual save-conflict prompt still appears when you save). Clean tabs with no unsaved edits keep updating automatically as before.
- Fix very large documents (over ~4 million characters) silently failing to save. Such a file still opens and stays editable, but each edit exceeded the host's size limit and was dropped with no visible sign — typing kept piling up while nothing reached disk. Editing an over-limit document now surfaces a "document is too large to save" banner (the same banner other unsaved-change errors use) instead of dropping the edit in silence.
- Fix a rejected edit's draft being wiped when the file is saved. If Quoll refuses an edit that would write unsafe Markdown (keeping your typed bytes on screen with the reject banner), a following save — or a continuous autosave tick — no longer reseeds the editor and destroys that draft. A save fires a change event carrying no new content, and the host now ignores those version-identical events instead of re-posting the document; genuine external edits (which advance the version) still resync as before.
- Round the frontmatter metadata card's corners to match the other block panels: it now shares the editor's block-radius (8px) instead of its own one-off 4px, so the frontmatter card, fenced-code panel, and blockquote read as one radius family. Its neutral fill is kept on purpose — it stays a quiet read-only metadata card, distinct from the tinted content surfaces. Purely visual — no behaviour or Markdown changes.
- Unify the resting look of the editor's four hover-revealed floating controls — the outline and switch-editor corner buttons, the fenced-code copy button, and the code-block collapse toggle. They previously dimmed to three different opacities (0.5 / 0.6 / 0.85) and faded at two different speeds; all four now share one resting dim and one fade duration, so hovering any of them behaves identically. The collapse toggle, which previously snapped, now fades like the rest. Purely visual — no behaviour or Markdown changes.
- Lighten GFM table borders from a full four-edge grid to horizontal rules only (a Notion-style look): each row now draws a single hairline rule with no vertical column edges, and the header row carries a stronger 2px rule so it reads as the table's spine. Cell padding and the table's outer alignment are unchanged, and it still round-trips byte-for-byte.
- Give inline code a little breathing room: the navy pill now shows a ~2px visual inset around the text so glyphs no longer sit flush against its edge. It is painted with a shadow ring in the same fill colour rather than padding, so it adds no layout shift and leaves caret and click positions exactly as before. Inside fenced code blocks the ring matches the line background, so it stays seamless there.
- Add generous vertical space above headings so documents breathe like Notion and Obsidian instead of reading cramped. Each heading level gets a proportional gap above it — largest for H1, tapering down through H2, H3, and a shared smaller gap for H4–H6 — and the space scales with the body font. The very first line of a document and headings nested inside a blockquote or callout are left alone (they already have their own spacing). The fold chevron stays centred on the heading text, clicking into the new space lands the caret on the heading, and the Markdown round-trips byte-for-byte (display-only).
- Double the per-level indent of nested bullet lists so each level steps about 14px (a Notion/Obsidian feel) instead of the previous ~7px, which read too tight. The extra step applies to a bullet nested under a plain bullet — plain and task children step together, so mixed bullet/task sibling items stay left-aligned — while ordered lists, nesting under a task item, and blockquoted lists keep their existing spacing. Display-only: the raw Markdown is untouched and still round-trips byte-for-byte.
- Fix three block widgets — GFM tables, images, and the frontmatter metadata block — plus the bullet-list dot bleeding a few pixels past the paragraph text column. They now line up flush with body text on both edges: the table and image reserve the same text-column inset the blockquote and code panels already use, the frontmatter card is nudged in to match, and the bullet dot sits at the column edge. Display-only — the Markdown round-trips unchanged.
- Fix the caret not appearing in Quoll after switching from VS Code's built-in text editor. Moving the caret in the text editor and switching back to the Quoll tab now lands the cursor at the same position and shows it — the position was already carried across, but the cursor was never drawn because the rich editor had not taken focus. Selecting a range in the text editor transfers as a collapsed caret at the selection's head; the switch carries a single caret position in both directions by design.
- Fix the floating toolbar (outline and switch-editor buttons) not hiding on scroll. The toolbar animation was wired but had no visible effect — the element that actually scrolled was not
.cm-scrollerbecause the height chain above it was not bounded, so the scroll listener never fired. The editor is now bound to the viewport so.cm-scrolleris the real scroller and the toolbar hides on scroll-down and returns on scroll-up as designed. - Clarify and cover the external on-disk edit path with a regression test. A clean Quoll tab (no unsaved edits) correctly auto-updates when another tool — such as the Claude Code CLI — writes the file directly; the new test pins this
fs.writeFile→ VS Code watcher → auto-revert → reseed path end-to-end. A tab with unsaved edits does not auto-update: VS Code intentionally skips reverting dirty models to protect unsaved work. Workaround: save the tab first (or enablefiles.autoSave) so VS Code reconciles the external write. - Publish to the Marketplace stable channel. Earlier 0.1.x builds shipped on the pre-release channel (the publish workflow, deploy script, and
pnpm packageall passed--pre-release); that flag has been removed everywhere, so releases now install as ordinary stable updates for everyone instead of only pre-release opt-ins. - Fix
⌘⌥E(Ctrl+Alt+E) not switching from Quoll to the built-in text editor on macOS. On a Mac, Option+E is the acute-accent dead key, so the keydown never matched the editor'sMod-Alt-echord; it now matches on the physical key — the same way VS Code matches the reverse text→Quoll direction — so both directions are symmetric. The top-right button and the Command Palette toggle were unaffected and still work. - Fix the fold/unfold chevron alignment on list items. On a bullet, ordered, or task list item the chevron sat slightly above the item's first line — it didn't account for the vertical gap between list items — and now sits centred on that line at every nesting level and in both themes. Heading-fold chevrons are unchanged.
- Align the soft-wrapped continuation lines of bullet and ordered list items under the first line's text — they previously hung a few pixels to its left because the marker was approximated as a single space. The marker glyph column is now sized to closely match its rendered width, so wrapped lines land on the content column (bullet task items were already aligned and are unchanged; ordered task items are handled in a later entry below). The bullet dot also gains a slightly wider gap before the text.
- Fix a stray fold/unfold chevron appearing on GFM table rows. A table renders as a display-only block widget, not a foldable construct, so it now offers no fold affordance — top-level or nested inside a list item. Heading folds and genuine list folds are unaffected.
- Render thematic breaks (
---,***,___) as a horizontal rule; move the caret onto the line to edit the raw source. Frontmatter fences and setext heading underlines are left untouched, and the bytes round-trip unchanged. - Callouts read as a clean titled panel: a thin per-type accent bar plus the weighted
[!TYPE]marker line convey the type, and the marker line is tucked away whenever your caret is outside the callout — the editable> [!TYPE]source reappears the moment you move into it. (No emoji badge — the accent bar and marker typography carry the type on their own.) - Fix GFM tables nested inside a list item so they render as the editable grid instead of raw
| … |source. A table indented as list-continuation content is now recognised (the same fix also covers top-level tables indented 1–3 spaces and tab-indented tables), and it still round-trips byte-for-byte. - Make the fenced-code copy button icon-only at rest: drop the resting boxed background so it reads as a bare icon; the boxed hover/focus affordance and the copied/failed states are unchanged.
- Remove the leftover raised-key edge from the fenced-code copy button at rest: the native
<button>bevel and any injected border/shadow are now explicitly neutralised, so the resting button is a truly flat bare icon. Hover, focus, copied, and failed states are unchanged. - Restyle task-list checkboxes so open work leads the eye: incomplete items now show a green rounded ring, while completed items recede — a muted-grey filled box with a cut-out checkmark, and their text is dimmed (no strikethrough). The checkmark is re-centred, and in the light theme the todo ring uses a brighter green.
- Add a top-right button and an
Ctrl/Cmd+Alt+Ekeybinding to switch the current.mdbetween Quoll and VS Code's built-in text editor; the caret position is preserved across the switch (via the button and the chord; the reverse text→Quoll direction preserves it too). - Tighten the task-list checkbox corner radius from 6px to 5px for a slightly crisper box.
- Make the floating outline and switch-editor buttons behave like a mobile-app toolbar: scrolling down slides them off the top edge, scrolling up brings them back, and they stay visible at the very top of the document. An open outline panel rides along so nothing is left floating, and the slide honours your "reduce motion" setting (it snaps instead). While hidden the toolbar is also kept out of the keyboard tab order for the whole slide, so focus can never land on an off-screen button.
- Align the soft-wrapped continuation lines of ordered task items (
1. [x] …) under the first line's text. Their visibleN.prefix was still sized as plain spaces, so wrapped lines hung a couple of pixels to the left (worse for multi-digit numbers); the number-and-dot glyph run is now sized to its rendered width like plain ordered lists. Bullet tasks (- [ ], whose marker folds into the checkbox) are unchanged. - Fix a stray fold/unfold chevron on a list item whose GFM table starts on the same physical line as the list marker (
- | a | b |). The table renders as a block widget that covers the marker line, leaving the chevron nowhere sensible to sit, so it is now suppressed for that shape only. Genuine list folds — including a table on a later continuation line and plain multi-line items — and heading folds are unaffected. Cmd+Option+K(Ctrl+Alt+K) now auto-inserts the@file#Lx-yreference into the Claude Code you're actually using: the extension's composer when its sidebar or panel is visible, otherwise the CLI session connected via/ide. A text editor briefly flashes in place of Quoll (same pane, no layout shift) while the handoff is delivered, and the reference is also copied to the clipboard as insurance. When Claude Code isn't installed, the previous behaviour remains: copy to clipboard, surface Claude Code, and toast to paste.
Quoll opens Markdown files in a Notion- and Obsidian-style WYSIWYG editor, right inside VS Code. Raw Markdown stays the single source of truth — every construct round-trips byte-for-byte — while the editor renders it live.
Highlights:
- Live Markdown rendering with reveal-on-caret: headings, blockquotes, inline emphasis, links, and code render in place; move the caret onto a construct to edit its raw source.
- Fenced code blocks on a rounded, syntax-aware panel with a copy-to-clipboard button, auto-closing fences on Enter, and automatic collapse for long blocks.
- Blockquote callouts with GitHub/Obsidian admonition types (
[!NOTE],[!TIP],[!IMPORTANT],[!WARNING],[!CAUTION]) and nested-quote tinting. - GFM tables rendered as editable grids: click a cell to edit in place, keyboard navigation, and structural row/column edits, with full IME support.
- Task lists with interactive checkboxes, and clean outline indentation for nested bullet, ordered, and task lists.
- Standalone images render inline; paste or drop an image to save it under
./assets/and insert a relative link. - YAML frontmatter renders as a quiet metadata block — click or arrow into it to edit the source.
- Document outline / heading navigator.
- Advisory Markdown lint surfaced as in-editor underlines, with an optional Problems-panel mirror, an opt-in gutter, and an opt-in trailing-whitespace quick fix. Lint is advisory only — it never blocks a save or rewrites bytes.
- Caret position carries across switching between Quoll and the default text editor; one-key handoff of the current file or selection to Claude Code or Codex.
- Theme-aware styling for light, dark, and high-contrast themes.
Security: a host-side write gate validates every save (URL allowlist,
frontmatter round-trip), and image and link destinations are gated so rendering
and writing stay in lockstep. The editor webview runs under a default-deny CSP
(base-uri/form-action locked down), and relative image paths that traverse
above the document's folder — standalone or inside a table cell — render as an
inert placeholder.