@mrsf/markdown-it-mrsf
v0.4.8
Published
markdown-it plugin for rendering Sidemark/MRSF (Markdown Review Sidecar Format) review comments
Maintainers
Readme
@mrsf/markdown-it-mrsf
A markdown-it plugin for rendering MRSF (Sidemark) review comments directly into HTML output.
Renders badges, line highlights, inline text highlights, and tooltips — no client-side JavaScript required for static use. An optional interactive mode adds action buttons for host applications to hook into.
Install
npm install @mrsf/markdown-it-mrsfBrowser & Bundler Support
The plugin works seamlessly in both Node.js and browser environments. When bundled with tools like Vite, webpack, or esbuild, the "browser" export condition in package.json automatically resolves to a browser-safe entry point — no special imports required.
// Works everywhere — Node.js, Vite, webpack, etc.
import { mrsfPlugin } from "@mrsf/markdown-it-mrsf";In browser environments, only the comments and loader options are available (no file-system access). The sidecarPath and documentPath options require Node.js.
Usage
Inline data (recommended for testing and custom pipelines)
import MarkdownIt from "markdown-it";
import { mrsfPlugin } from "@mrsf/markdown-it-mrsf";
const md = new MarkdownIt();
md.use(mrsfPlugin, {
comments: {
mrsf_version: "1.0",
document: "guide.md",
comments: [
{
id: "c1",
author: "Jane",
timestamp: "2026-01-01T00:00:00Z",
text: "Can you clarify this section?",
resolved: false,
line: 3,
},
],
},
});
const html = md.render(markdownSource);Auto-discover from disk
md.use(mrsfPlugin, {
documentPath: "docs/guide.md",
});The plugin looks for docs/guide.md.review.yaml (or .review.json) next to the document.
Explicit sidecar path
md.use(mrsfPlugin, {
sidecarPath: ".reviews/docs/guide.md.review.yaml",
});Custom loader function
md.use(mrsfPlugin, {
loader: () => {
// Load sidecar data however you like — from a database, API, in-memory store, etc.
return {
mrsf_version: "1.0",
document: "guide.md",
comments: [/* ... */],
};
},
});Stylesheet
Include the default CSS for badges, tooltips, and highlights:
import "@mrsf/markdown-it-mrsf/style.css";Or link directly in HTML:
<link rel="stylesheet" href="node_modules/@mrsf/markdown-it-mrsf/dist/style.css">Customise with CSS custom properties:
:root {
--mrsf-accent: #3794ff;
--mrsf-badge-bg: #007acc;
--mrsf-badge-fg: #fff;
--mrsf-tooltip-bg: #252526;
--mrsf-tooltip-fg: #cccccc;
--mrsf-highlight-bg: rgba(255, 213, 79, 0.25);
}Interactive Mode
Enable interactive: true to add action buttons inside tooltips, plus:
- Gutter “Add comment” buttons for each line badge
- An inline “Add comment” floater that appears when users select text
Buttons render as <button data-mrsf-action="..." data-mrsf-comment-id="..."> elements — inert without JavaScript.
md.use(mrsfPlugin, {
comments: sidecarData,
interactive: true,
});Controller
Include the optional controller to wire up the inline and gutter actions. By default it shows built-in dialogs for add, reply, edit, resolve, unresolve, and delete, then dispatches events you can persist through your own API:
import { refreshAll } from "@mrsf/markdown-it-mrsf/controller";
document.addEventListener("mrsf:submit", async (e) => {
// { action, commentId, text?, line?, end_line?, start_column?, end_column?, selection_text? }
await saveComment(e.detail);
});
await mermaid.run();
refreshAll();Events fired after user confirmation: mrsf:add, mrsf:reply, mrsf:edit, mrsf:resolve, mrsf:unresolve, mrsf:delete, mrsf:navigate, plus mrsf:submit with the full payload.
Set window.mrsfDisableBuiltinUi = true before loading the controller if you want to render your own UI and only consume the events.
The controller also auto-refreshes gutter positions on DOM mutations inside the rendered container, which covers common async renderers such as Mermaid. Call refreshAll() after third-party rendering when you need a deterministic reposition step.
Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| comments | MrsfDocument | — | Pre-loaded sidecar data (highest priority) |
| loader | () => MrsfDocument \| null | — | Custom loader function for sidecar data |
| documentPath | string | — | Path to Markdown file for auto-discovery |
| sidecarPath | string | — | Explicit path to sidecar file |
| showResolved | boolean | true | Whether to show resolved comments |
| interactive | boolean | false | Add action buttons for host JS integration |
| gutterPosition | 'left' \| 'right' | 'right' | Badge position: left margin gutter or floated right |
| gutterForInline | boolean | true | Show gutter badge for comments that also have inline highlights |
| inlineHighlights | boolean | true | Render inline text highlights for selected_text |
| lineHighlight | boolean | false | Add background tint on commented lines |
| theme | 'light' \| 'dark' \| 'auto' | 'auto' | Color scheme hint |
| cwd | string | process.cwd() | Working directory for file resolution |
Display Modes
The plugin supports several display modes that can be combined:
- Gutter + inline (default): Badges appear in the gutter,
selected_textis highlighted inline with hover tooltips on both. - Gutter only (
inlineHighlights: false): Only gutter badges shown, no inline highlights. - Inline only (
gutterForInline: false): Lines with inline-highlighted comments show only the highlight (with tooltip) — no gutter badge. Lines withoutselected_textstill show badges.
DOM Contract
All rendered elements follow a strict data-attribute contract:
data-mrsf-line— source line number (1-based)data-mrsf-comment-id— comment identifierdata-mrsf-action— action type (add,resolve,unresolve,reply,edit,delete,navigate)data-mrsf-start-line,data-mrsf-end-line,data-mrsf-start-column,data-mrsf-end-column— optional selection anchors when present
