Repository navigation
Releases: carlosboeing/penmark
Release list
Penmark v0.6.0
Raw-text elements pass through the inline render path
- The preview now shows the authored value of a self-closing raw-text element such as
<textarea/>. markdown-it has no HTML parser, so that spelling used the inline path. The per-text-node source-offset spans then appeared inside the element's value as literal text. - A new inline rule turns a raw-text open tag and everything up to its end tag into a single token. It covers
script,style,textarea,title,xmp,noembed,noframesandiframe. An element with no end tag continues to the end of the block, matching browser display. - The renderer still stamps ordinary inline text with source offsets, and comment highlighting is unchanged.
Markdown links open in a Penmark tab; frontmatter card keeps its state
- Relative links to markdown files now open in a new Penmark preview tab. The opener is
vscode.openWithonpenmark.previewEditor, withvscode.openas fallback. Extensionless wiki-links resolve via an existence probe:.mdsuffix first, then the workspace root. mailto:andftp:links open in the system handler.file:URIs open inside the IDE. Neither is resolved as a relative file path. Untitled and remote documents skip existence probing, since there is no local directory to probe.- The frontmatter card keeps its collapse state across preview re-renders and tab switches. Persistence is
getState/setStatewhile the tab is open. Cards with more than three keys still start collapsed. Version 0.6.0.
OSS repository safeguards
- CI now uses immutable action and browser-container references, explicit least-privilege permissions, timeouts, pull-request run cancellation, and a stable
requiredaggregate check while preserving the full operating-system and VS Code-version matrix. - Release verification now runs under
bashwithsafe.directory,--shm-size=2g, and built-in Node ZIP manifest extraction inside the pinned Playwright container, accepts only three-component version tags, repeats the complete suite on the tagged commit, checks VSIX contents and version coherence, writes a checksum, creates an artifact build-provenance attestation (actions/attest-build-provenance), and smoke-tests the downloaded release asset; manual dispatch remains verification-only. - Added public runtime dependency notices and removed internal path examples from public artifacts.
Dependabot can read the lockfile again
package-lock.jsonheld conflict markers inside the innerpackages[""]version hunk. Every Dependabot update job stopped withdependency_file_not_parseable, so no dependency update reached a pull request.- The hunk now resolves to 0.6.0, which matches
package.jsonand the lockfile's own top-level version.
Agent-authored character entities render as punctuation
Agent-generated review comments can encode punctuation as decimal HTML character references, such as - for a hyphen. Penmark decoded only its own paired-hyphen storage sentinel (--), so a single reference reached the drawer and popover as visible source text. Penmark now renders any valid decimal reference as the character it denotes, using markdown-it's own validity rule so surrogates, NUL, control characters and noncharacters stay literal rather than becoming ill-formed text a save could write into the file.
This rendering is a presentation pass, applied where a note is handed to the preview and where one is exported for an agent. An entry's quote is exempt: it stays byte-faithful all the way to the drawer, which renders it at the point of display. Re-anchor re-adds the same quote at a new location, so a rendered quote would be stored and could never match the document again, and the next anchor loss would orphan a comment that would otherwise recover. It is deliberately not part of the storage codec. Decoding at parse time instead would have broken two things: quote recovery matches an entry's quote against raw document bytes, so a quoted passage that itself contains a reference would stop matching and the comment would orphan; and because the writer escapes only --, each read-and-save cycle would strip one more level from text the user never edited. Keeping the pass at the display seam leaves the spec's round-trip guarantee intact for every string. The validity rule is written out rather than imported: pulling markdown-it's helper into the eager extension entry took dist/extension.js from 53 KB to 136 KB, against a sub-50 ms activation budget. A test pins the copy to markdown-it across every code point. Format spec §6 gains a non-normative reader-side rule; regression tests cover the sentinel, standalone references, each rejected range, and the three consumers that need raw bytes.
Commenting no longer breaks the formatting it wraps
Commenting a bullet that opens in bold left the asterisks showing in the preview: **Subscription-billed.** rendered literally instead of bold. Reported from a real review session.
- An anchor at the start of a line no longer starts an HTML block — CommonMark treats any line beginning with
<!--as raw HTML through the closing-->, so the whole line skipped inline parsing. This was never specific to bold: inline code, links and italics on that line all rendered as source. It fired wherever inline-safety snapping pushed a span opener to the start of a block's content — bullets and ordered items (including nested ones), paragraphs, blockquotes, a paragraph's continuation line, and a closer landing at a line start. The renderer now declines the HTML-block rule for a line that leads with a pmk anchor and still carries content, so those lines take the inline path where the marker passes through verbatim at the exact extent (ADR 0006). Lines holding nothing but a marker keep the old behaviour, becausepmk:bandpmk:ranchors own their line by design (§4.2), and a hand-written<!-- note -->still behaves as stock CommonMark. - A highlight spanning list items stays visible past the first one — a bullet list is one block, so commenting three of five bullets is a span, not a range. The single
<mark>wrapped</li><li>, which is invalid nesting; because<mark>is not an HTML formatting element the browser closes it at</li>and discards the stray closer, silently dropping the highlight from every item after the first. The extent is now split into one<mark>per inline run, all sharing the comment id. An extent inside a single block still produces exactly one<mark>, byte-for-byte as before. - The split reads as one control — the fragments of a split highlight would otherwise each become a tab stop announcing the same comment. Only the first carries the keyboard affordance and the gutter dot; clicking any fragment still opens the popover, and all fragments light up together when the comment is active.
- Tests cover the boundary cases the fixtures missed — the anchored-doc fixture had no line-start anchor, so no snapshot could have caught this. New tests pin each block context that broke, both marker-only-line behaviours, a non-pmk comment at a line start, and the cross-block split down to whitespace handling.
Multi-block selections were already correct and are unchanged: a heading, paragraph, fenced code and list selected together still become one range wrapper with their formatting intact.
What's Changed
- fix(comments): keep markdown formatting intact around inline anchors by @carlosboeing in #50
- chore(git): add the private-workbench pre-commit guard by @carlosboeing in #53
- chore: gitignore local git worktrees by @carlosboeing in #54
- docs: scope worktrees to implementation work by @carlosboeing in #56
- docs: stop instructing agents to cite private design docs in public by @carlosboeing in #57
- Decode agent-authored decimal character references by @carlosboeing in #59
- chore(governance): align repository with OSS house standard by @carlosboeing in #61
- chore(governance): add SUPPORT.md to house standard by @carlosboeing in #62
- feat(preview): open markdown links in new tab and persist frontmatter state by @carlosboeing in #44
- fix(deps): remove merge markers from package-lock.json by @carlosboeing in #63
- chore(deps): bump dompurify from 3.4.11 to 3.4.14 by @dependabot[bot] in #48
- chore(deps-dev): bump undici from 7.28.0 to 7.29.0 by @dependabot[bot] in #45
- chore(deps-dev): bump fast-uri from 3.1.2 to 3.1.6 by @dependabot[bot] in #46
- chore(deps-dev): bump postcss from 8.5.16 to 8.5.26 by @dependabot[bot] in #52
- chore(deps-dev): bump js-yaml from 4.2.0 to 4.3.2 by @dependabot[bot] in #60
- chore(deps): bump mermaid from 11.16.0 to 11.16.1 by @dependabot[bot] in #47
- chore(deps-dev): bump brace-expansion from 2.1.1 to 2.1.4 by @dependabot[bot] in #66
- chore(deps): bump Playwright to 1.62.1 with container image by @carlosboeing in #67
- chore(deps): bump the minor-and-patch group across 1 directory with 13 updates by @dependabot[bot] in #68
- fix(render): keep raw-text elements whole on the inline path by @carlosboeing in #69
- docs(changelog): record raw-text in...
Penmark v0.5.3
What's Changed
- chore: ignore .workbench/ and genericize private-repo refs in CLAUDE.md by @carlosboeing in #4
- chore(git): add Playwright temporary directories to gitignore by @carlosboeing in #5
- feat(custom-editor): support custom text editors in Penmark by @carlosboeing in #6
- feat(custom-editor): add direct context menu option to open with Penmark by @carlosboeing in #8
- feat(v1-polish): implement v1.0 polish features by @carlosboeing in #10
- feat(ui-ux): audit and implement premium webview UI/UX polish by @carlosboeing in #12
- feat(export): add HTML and PDF export by @carlosboeing in #22
- chore(deps): bump js-yaml and markdownlint-cli2 by @dependabot[bot] in #23
- ci(deps): bump actions/checkout from 6 to 7 by @dependabot[bot] in #15
- chore(deps-dev): bump @types/node from 25.9.3 to 26.1.0 by @dependabot[bot] in #17
- chore(deps): bump dompurify from 3.4.10 to 3.4.11 by @dependabot[bot] in #14
- chore(deps): bump undici from 7.27.2 to 7.28.0 by @dependabot[bot] in #13
- chore(deps-dev): bump form-data from 4.0.5 to 4.0.6 by @dependabot[bot] in #7
- chore(deps): bump the minor-and-patch group across 1 directory with 8 updates by @dependabot[bot] in #26
- chore(deps-dev): bump vitest + @vitest/coverage-v8 to 4.1.10 by @carlosboeing in #27
- feat(ui): ship adaptive review surface by @carlosboeing in #32
- feat(find): add in-preview search fallback by @carlosboeing in #35
- fix(find): restore matching for longer queries, clear search on close by @carlosboeing in #36
- docs(changelog): mark the find fixes as shipped by @carlosboeing in #37
- fix(ui): panel, search and typography bug bash by @carlosboeing in #38
- fix(comments): keep comments readable after a format-on-save by @carlosboeing in #41
- docs(roadmap): add comment deep links to future considerations by @carlosboeing in #42
- feat(webview): type-aware frontmatter card lists, status borders, and path links by @carlosboeing in #43
New Contributors
- @carlosboeing made their first contribution in #4
- @dependabot[bot] made their first contribution in #23
Full Changelog: v0.1.0...v0.5.3
Penmark v0.5.0 — Review MVP
Penmark v0.5.0 — the Review MVP. Penmark now does its differentiating thing: Google-Docs-style inline review comments on rendered markdown, stored in the document itself, built for reviewing AI-authored design docs / plans / research in the IDE.
Local-first: download the VSIX below and sideload into VS Code / Cursor / Antigravity (--install-extension penmark-markdown-review-0.5.0.vsix or Extensions → Install from VSIX…). Compatibility floor engines.vscode ^1.105.0.
Highlights
- Inline comments — select rendered prose, add a comment; stored as invisible
pmk:s/b/ranchors + a single trailingpmk:reviewblock per the frozen public format (spec/penmark-format.md, agent contract inAGENTS-GUIDE.md). - Highlights, gutter dots, resolve popover — theme-aware, intensity-configurable; blue (human) / purple (agent) authorship.
- Comments drawer + needs-attention bucket + attention chip — orphaned / content-removed / degraded comments surfaced by the §8 reconcile degradation ladder, with re-anchor and delete.
- Add / resolve as one undo step (single
WorkspaceEdit), author identity, reconcile on open/change (corruption flagged, never silently swallowed). - Export review as an agent-ready prompt for handoff to a coding agent.
- Release-blocking acceptance gate — golden suite over the §8 desync states + real
git merge-fileconcurrent-merge scenarios, proving the single-file format survives 3-way merges.
Core VSIX 581 KiB (mermaid chunk excluded, lazy-loaded), under the 1 MiB budget.
Known limitation
Resolving a 3-way merge by keeping two pmk:review blocks surfaces the non-EOF block's comments via the corruption flag only, not yet in needs-attention (§8.5, tracked post-v0.5). No data loss; the union resolution is fully lossless.
Verification
CI is billing-blocked, so this release was verified locally per plan D16: build, typecheck, eslint, vitest run --coverage (717 passed; src/core/comments ≥95%), Docker Playwright goldens, and the VSIX size gate. The manual cross-IDE smoke (docs/guides/release-smoke-checklist-v0.5.md) is the remaining human step.
Full notes: CHANGELOG.
🤖 Generated with Claude Code
Penmark v0.1.0
What's Changed
- P0.1: anchor torture-test spike — verdict GO by @carlosboeing in #1
- P0.2: repo scaffold — TS strict, esbuild dual entry, ESLint core boundary by @carlosboeing in #2
- P0.3: 4-layer test harness with enforced coverage gates by @carlosboeing in #4
- P0.6: format spec v1 frozen-draft + AGENTS-GUIDE by @carlosboeing in #3
- P0.4: CI workflows + VSIX size gate by @carlosboeing in #5
- T1: render pipeline core — markdown-it GFM + frontmatter strip by @carlosboeing in #6
- T2: data-pmk-offset source positions (ADR 0005) by @carlosboeing in #7
- T3: DOMPurify sanitization of rendered HTML by @carlosboeing in #8
- T4: webview preview panel (nonce CSP, debounced re-render) by @carlosboeing in #9
- T5: webview client — protocol, morphdom render, links, sanitize by @carlosboeing in #10
- T6: GitHub light/dark/auto themes + v0.1 settings by @carlosboeing in #11
- T7: lazy highlight.js (common-language subset) by @carlosboeing in #12
- T8: copy buttons on code blocks by @carlosboeing in #13
- T9: lazy mermaid rendering + pan/zoom lightbox by @carlosboeing in #14
- T10: bidirectional scroll sync via offset map by @carlosboeing in #15
- T11: formatter golden matrix over anchored conformance corpus by @carlosboeing in #16
- T12: v0.1 performance budget gates (design §8 exit criteria) by @carlosboeing in #17
- T13: ship v0.1.0 — Reading MVP by @carlosboeing in #18
New Contributors
- @carlosboeing made their first contribution in #1
Full Changelog: https://github.com/carlosboeing/penmark/commits/v0.1.0