Skip to content

0.1.25 - 2026-06-19

Choose a tag to compare

@github-actions github-actions released this 19 Jun 06:20
eae235a

Release Notes

Added

  • Inline & page comments — review documentation directly in the browser: select text to anchor a comment to a passage, or comment on the page as a whole. Threads support replies, resolve/reopen, and a "Show resolved" disclosure with a count badge. Comments persist in .rw/comments/sqlite.db (versioned schema with idempotent forward migrations) and survive re-renders via multi-selector anchoring (TextQuoteSelector + TextPositionSelector); when the original passage changes, the viewer falls back to fuzzy re-anchoring (diff-match-patch) and marks the comment "re-anchored" with a dashed underline. Anchors that would land on short or ambiguous text drop to the page timeline with their original quote instead of jumping to an unrelated occurrence, and highlights stack progressively darker where comments overlap.
    • Authorship — every comment carries an author ({ id, name, avatarUrl? }); local:human renders a person avatar, local:ai a sparkles avatar (recommended for LLM agents), others fall back to name initials. rw serve stamps browser-created comments as "You".
    • Markdown bodies — comment bodies render a safe, restricted CommonMark+GFM subset (paragraphs, bold/italic/strikethrough, lists, blockquotes, inline and fenced code, http/https/mailto links). Raw HTML, images, tables, headings, and unsafe link schemes are neutralized; the rendered HTML ships in an additive bodyHtml field alongside the raw body.
    • Deep links — every thread has a shareable #comment-<id> URL with a "Copy link" button; opening one scrolls to and reveals the thread (auto-expanding the resolved disclosure when needed). Inbound deep-linking works when embedded; the copy button is hidden there since the host owns the URL.
    • Keyboard navigation — press n/p to step between comments in document order, wrapping at the ends; each jump scrolls into view, opens inline threads in the margin, and is announced to screen readers. Keys are ignored while typing, and modifier combos pass through to the browser.
    • Live refresh — comments added, edited, or resolved by the rw comment CLI or another browser tab appear without a manual reload, via a best-effort token-authenticated notify (using .rw/server.json) re-broadcast over the existing live-reload WebSocket. In-progress drafts are preserved, and the CLI stays decoupled — if no server is running, the comment is still written.
    • Delete replies — replies can be soft-deleted (kept visible, muted and struck-through, with a Restore button so a misclick is reversible in-session); top-level comments use Resolve instead. Deletes are non-destructive (deletedAt on the row) and hidden on the next refetch.
    • REST API & CLI/_api/comments (create, list, update, and DELETE /_api/comments/{id} with a deletedAt field plus canDelete/canRestore flags) and an rw comment CLI (list, show, add, reply, resolve) for scripting and LLM agents. The CLI reads and writes the SQLite store directly whether or not rw serve is running, takes identity from RW_COMMENT_AUTHOR_ID/RW_COMMENT_AUTHOR_NAME or --author-* flags, and anchors inline comments with --quote (rejecting ambiguous or missing matches).
    • @rwdocs/core exports renderCommentBody(markdown) so hosts that store their own comments (e.g. a Backstage backend plugin) can render bodies to the same safe bodyHtml. Returns a Promise<string>.
  • Status badges — :status[Label]{color=NAME} renders an inline colored pill label (grey, red, yellow, green, blue, purple). Publishing to Confluence emits the native status macro, so badges stay editable and on-style. Color is case-insensitive and optional; unknown or omitted colors fall back to grey.
  • Custom section namespaces — sections can declare a namespace in meta.yaml or frontmatter (e.g. namespace: payments), producing section refs of the form kind:namespace/name that map to Backstage catalog entities outside the default namespace. The field inherits down the directory tree and a subtree can override it; invalid values fail the site load with an error naming the offending file. Wikilinks that omit the namespace resolve within the current page's namespace.
  • Named metadata sidecar files — place <name>.meta.yaml (e.g. payments.meta.yaml) directly in a directory to declare a page or content-less catalog entity at that path, instead of creating a <name>/meta.yaml subfolder. Works as a sidecar for an existing <name>.md or stand-alone to register Backstage components/systems that exist only to build relations. The suffix follows the configured metadata filename. Named sidecars are leaf-only (no vars cascade), and a directory meta.yaml wins if both resolve to the same page.
  • rw confluence render <markdown_file> --out <dir|-> — renders markdown to a Confluence-publishable bundle (page.xhtml plus one PNG per diagram). Stdin optionally accepts the current page's storage XHTML body to preserve inline-comment markers; without it, the command renders as a fresh page. --out - writes the body XHTML to stdout (erroring with exit 3 only if the render produced PNG attachments); --strict exits non-zero on any warning or unmatched comment.
  • rw backstage publish now surfaces diagram-processing warnings — broken or cyclic PlantUML !include paths — in yellow on stderr instead of silently discarding them. Pass --strict to fail the publish when any warning was emitted; bundles still upload either way, so warnings can be fixed in a follow-up commit and republished.
  • RW_DIAGRAMS_KROKI_URL environment variable — supplies diagrams.kroki_url for projects without an rw.toml (or one that omits the field). Precedence is CLI flag > rw.toml > env var, so explicit project config still wins. Lets teams roll rw out across many repos that share a single Kroki server by exporting the variable once.
  • rw serve writes a .rw/server.json runtime-info file on startup (host, port, pid, version, start time, and a reserved secret token) and removes it on graceful shutdown — including on SIGTERM (docker stop, systemd), not just Ctrl-C. The file is written atomically with 0600 permissions in the gitignored .rw/ directory, so the token never lands in version control. It lets other tooling discover a running server for the project.

Removed

  • Breaking: rw confluence update and rw confluence generate-tokens are removed. rw no longer talks to the Confluence REST API; the [confluence] section in rw.toml is no longer recognized (stale sections are silently ignored, not rejected). Use rw confluence render <md> --out <dir> to produce a publish-ready bundle (XHTML body + diagram PNGs), then publish it with a tool of your choice. Comment preservation continues to work: pipe the current page's storage XHTML body into stdin and rw carries <ac:inline-comment-marker> tags through to the new XHTML.

Changed

  • Breaking: the HTTP API served by rw serve moved from /api/* to the reserved /_api/* prefix (e.g. /_api/navigation, /_api/pages/..., /_api/comments), freeing the /api/* URL space for documentation pages. The bundled viewer moves in lockstep; only external callers hitting rw serve's HTTP endpoints directly need to update.
  • Breaking: heading anchor IDs for headings containing [[wikilink]] syntax now include the wikilink's resolved display text — ## See [[overview]] (resolver returning "Overview") now produces <h2 id="see-overview"> instead of <h2 id="see">. The TOC entry title changes correspondingly. In-page anchor links targeting the old slugs need updating.
  • Block directives (:::tab/:::note containers and ::leaf directives) are now parsed with awareness of markdown structure: they must be blank-line separated (each delimiter on its own paragraph), delimiters inside code or fenced blocks stay literal so directive syntax can be shown as an example, and directives now work inside blockquotes and loose list items. Standard blank-line-separated :::tab blocks are unaffected; any that relied on the old no-blank-line form now render as literal text until separated.
  • Single-page sites (only index.md, or a README.md homepage) no longer show an empty navigation sidebar — the desktop sidebar, mobile hamburger, and mobile drawer are all hidden, leaving a clean centered article. Sites with a "back to home" link keep their sidebar.
  • Page modification times (lastModified) now reflect the git commit time instead of the filesystem mtime, so timestamps stay stable across git checkout, pull, and branch switching. S3-published bundles now carry these times in the manifest too (previously always epoch zero for Backstage-served pages).
  • Page outline (TOC) sidebar widened from 240px to 320px so opening a comment no longer narrows the article; it now appears at viewport widths ≥ 1304px (was ≥ 1224px), with the floating "On this page" popover below that.
  • @rwdocs/viewer now requires Node.js >=22.12.0 (was >=20) — Vite 8 needs Node 20.19+/22.12+, and Node 20 reached end-of-life on 2026-04-30; 22.12.0 is the first release where require(esm) works without a flag.
  • Minimum supported Rust version raised to 1.96 — building rw from source now needs a 1.96+ toolchain.

Fixed

  • rw serve no longer fails to start when a project has a README.md but no docs/ directory; the README is served as the homepage and live reload picks up a docs/ directory created afterwards without a restart.
  • Requesting a page that exists in the navigation tree but whose markdown source is missing from storage now returns 404 Not Found instead of 500 Internal Server Error.
  • Documentation pages whose URL begins with /api/ (e.g. docs/api/usage.md) no longer return 404 when opened directly or refreshed.
  • Pages that reference other pages — via [[wikilinks]], cross-section links, or C4 diagram entity includes — no longer keep showing stale content after the referenced page changes. The rendered-page cache key now incorporates a fingerprint of cross-page inputs.
  • A transient panic inside rw serve (most realistically inside storage.scan() during a reload) no longer permanently bricks the server by poisoning the internal reload lock. Reads resume on the previous snapshot and the next reload trigger is honored; the storage layers and file-watcher debouncer got the same hardening.
  • rw serve no longer keeps serving stale page content after a file change that lands while a previous reload's storage scan is still running — validity is now derived from a monotonic generation stamp, so a change can't be swallowed by an in-flight reload.
  • New files created under docs/ while rw serve is running now reliably appear in the navigation sidebar without a manual refresh (the live-reload Created handler no longer races its own invalidation).
  • S3 (and other remote storage) outages no longer become "soft outages" where every read serializes on a mutex and re-calls the unreachable backend; a failed background reload keeps serving the stale snapshot and retries only on the next explicit signal.
  • Heading anchor IDs are now guaranteed unique within a page (previously a slug colliding with another heading's auto-numbered suffix could emit duplicate ids, and a heading with no slug characters produced an empty id="").
  • An image inside a heading (e.g. # ![](icon.png) Project Name) now renders inside the <h*> element instead of escaping before it, fixing the document outline, TOC, and SEO for icon-led titles.
  • Formatted image alt text (![**Logo**](...), ![Press `Enter`](...)) no longer leaks empty inline tags next to the <img>, and inline code inside alt text now contributes to the rendered alt attribute instead of disappearing.
  • Long URLs and other unbreakable tokens (UUIDs, hash digests, file paths) in tables, paragraphs, and list items now wrap instead of forcing horizontal scrolling on narrow viewports.
  • Directives with non-ASCII characters in their attribute braces (e.g. :foo[bar]{цвет}, {🎉}) no longer panic the renderer; valid uses such as {.заголовок}, {#заголовок}, and {цвет=зелёный} were already safe and remain unchanged.
  • Inline directive syntax (:name[…]) inside an inline code span, indented code block, or raw inline HTML is no longer expanded, so documentation can demonstrate :status[…] and other directives as code.
  • Inline directives following a non-directive colon on the same line (e.g. Note: press :kbd[Ctrl+C], See https://example.com then run :cmd[deploy]) are no longer silently dropped — the renderer skips past punctuation colons, URL schemes, and times and continues scanning for the real directive.
  • YAML frontmatter values containing :name[...]-shaped text (e.g. description: 'See :status[Done] for details') no longer trigger spurious "unknown inline directive" warnings or invoke directive handlers.

Install rw 0.1.25

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/rwdocs/rw/releases/download/v0.1.25/rw-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/rwdocs/rw/releases/download/v0.1.25/rw-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install rwdocs/tap/rw

Download rw 0.1.25

File Platform Checksum
rw-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
rw-x86_64-apple-darwin.tar.xz Intel macOS checksum
rw-x86_64-pc-windows-msvc.zip x64 Windows checksum
rw-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
rw-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
rw-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum