comark-ui 0.7.6 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +3 -3
  2. package/dist/{client-Bjd6VcGQ.mjs → client-kUEiRbtp.mjs} +25 -8
  3. package/dist/client.mjs +2 -2
  4. package/dist/{editor-DmxNPK7K.mjs → editor-9IcfELjG.mjs} +108 -16
  5. package/dist/editor-vue.d.mts +21 -5
  6. package/dist/editor-vue.mjs +40 -9
  7. package/dist/{editor-KD97dL_1.d.mts → editor-yoVL7Ajq.d.mts} +27 -3
  8. package/dist/editor.d.mts +2 -2
  9. package/dist/editor.mjs +1 -1
  10. package/dist/html.d.mts +1 -1
  11. package/dist/html.mjs +7 -3
  12. package/dist/{index-Dbqxt4Qg.d.mts → index-DVGSDzBS.d.mts} +1 -1
  13. package/dist/index.d.mts +1 -1
  14. package/dist/index.mjs +1 -1
  15. package/dist/react.d.mts +1 -1
  16. package/dist/react.mjs +2 -2
  17. package/dist/skills/before-after-evidence/SKILL.md +11 -13
  18. package/dist/skills/before-after-evidence/references/blocks.md +1 -1
  19. package/dist/skills/comark-ui/SKILL.md +13 -9
  20. package/dist/skills/comark-ui/references/annotate.md +1 -1
  21. package/dist/skills/comark-ui/references/badge.md +1 -1
  22. package/dist/skills/comark-ui/references/cards.md +2 -1
  23. package/dist/skills/comark-ui/references/code-notes.md +1 -1
  24. package/dist/skills/comark-ui/references/code.md +3 -3
  25. package/dist/skills/comark-ui/references/comments.md +3 -3
  26. package/dist/skills/comark-ui/references/embed.md +3 -2
  27. package/dist/skills/comark-ui/references/keys.md +1 -1
  28. package/dist/skills/comark-ui/references/links.md +1 -1
  29. package/dist/skills/comark-ui/references/lint.md +21 -12
  30. package/dist/skills/comark-ui/references/magic-move.md +1 -1
  31. package/dist/skills/comark-ui/references/media.md +2 -2
  32. package/dist/skills/comark-ui/references/metrics.md +1 -0
  33. package/dist/skills/comark-ui/references/outline.md +2 -2
  34. package/dist/skills/comark-ui/references/properties.md +1 -1
  35. package/dist/skills/comark-ui/references/quiz.md +15 -3
  36. package/dist/skills/comark-ui/references/reading-time.md +1 -1
  37. package/dist/skills/comark-ui/references/remark-to-comark.md +29 -0
  38. package/dist/skills/comark-ui/references/steps.md +1 -1
  39. package/dist/skills/comark-ui/references/table.md +1 -0
  40. package/dist/skills/comark-ui/references/tabs.md +2 -2
  41. package/dist/skills/comark-ui/references/tests.md +1 -1
  42. package/dist/skills/comark-ui/references/ui.md +7 -6
  43. package/dist/skills/teach-lesson/SKILL.md +4 -4
  44. package/dist/skills/teach-lesson/references/blocks.md +6 -6
  45. package/dist/skills.mjs +34 -30
  46. package/dist/text-D8j9clg3.mjs +19 -0
  47. package/dist/{typeset-css-5aJ7cSmh.mjs → typeset-css-blSNpFNK.mjs} +2 -2
  48. package/dist/vue.d.mts +1 -1
  49. package/dist/vue.mjs +3 -3
  50. package/package.json +45 -45
@@ -6,25 +6,25 @@ license: MIT
6
6
 
7
7
  # Before/after evidence
8
8
 
9
- A before/after is evidence when a reviewer can check every claim against the two images and nothing else. Three things make it so, and the reader can't repair any of them: two captures of the same view, marks that sit on what changed, and notes in the words the screen shows.
9
+ A before/after is evidence when a reviewer can check every claim against the two images and nothing else. The reader can't repair a bad pair, so get three things right: two captures of the same view, marks on what changed, and notes in the words the screen shows.
10
10
 
11
- This skill writes the document. Where it's published, and who can open it, is up to your host.
11
+ This skill writes the document. Your host decides where it's published and who can open it.
12
12
 
13
13
  ## 1. Capture a comparable pair
14
14
 
15
- Take **after** from the branch or its preview, and **before** from a deployment or commit that still behaves the old way. Capture both with the same viewport, zoom, theme, data, scroll position, and open menus, so the change is the only difference.
15
+ Take the after capture from the branch or its preview, and the before capture from a deployment or commit that still behaves the old way. Capture both with the same viewport, zoom, theme, data, scroll position, and open menus, so the change is the only difference.
16
16
 
17
17
  - Set up the state that shows the change before you capture: the long name that wrapped, the error that stayed hidden, the empty list.
18
18
  - Clip both captures to one region around the change, the same rectangle on each side. A `::compare` gives each image under half the page width, where a full-page capture's text is too small to read.
19
- - Pin anything that moves the layout between the two states, such as a dialog centered vertically that grows by one line, so the same element sits at the same place in both.
19
+ - Pin anything that moves the layout between the two states, such as a vertically centered dialog that grows by one line, so the same element sits at the same place in both.
20
20
 
21
- If one side can't be captured comparably, stop and say what blocked you. A description in place of a screenshot, or one side alone, isn't before/after evidence.
21
+ If you can't capture one side comparably, stop and say what blocked you. A description in place of a screenshot, or one side alone, isn't before/after evidence.
22
22
 
23
23
  Done when both images exist, have the same size, and differ only where the change is.
24
24
 
25
25
  ## 2. Measure every mark
26
26
 
27
- Marks take `x`, `y`, `w`, and `h` as percentages of the image. Measure them: an estimate drifts a few percent, and on a half-width image that's the neighbouring button.
27
+ Marks take `x`, `y`, `w`, and `h` as percentages of the image. Measure them. An estimate drifts a few percent, which on a half-width image lands on the neighbouring button.
28
28
 
29
29
  - **A page you captured:** read the element's box in the same browser, viewport, and state, minus the clip's offset. [references/measuring.md](references/measuring.md) has the snippet.
30
30
  - **A still you didn't capture**, such as a frame from a screen recording, a design export, or an image attached to a bug report: there is no DOM to ask. Measure in image pixels and divide by the image's natural width and height. Confirm each box by cropping the image to it and looking at the crop, as the same reference shows.
@@ -42,7 +42,7 @@ Start from [references/example.md](references/example.md) and keep its shape:
42
42
  3. The `::compare`, each note a few words in the screen's own words. A value the screenshot doesn't show stays out of its note.
43
43
  4. A `::diff` of the line that caused it, only when the reader would otherwise ask.
44
44
 
45
- The images carry the evidence, so the text only points into them. How the work went (the checks you ran, retries, CI) goes in your report to the user, not in the document. [references/blocks.md](references/blocks.md) has the syntax of each block.
45
+ The images carry the evidence, so the text only points into them. Put how the work went (checks, retries, CI) in your report to the user, not in the document. [references/blocks.md](references/blocks.md) has the syntax of each block.
46
46
 
47
47
  Image `src` must be a URL the renderer can reach: a path next to the document, or an https URL your host gives you for the upload.
48
48
 
@@ -56,17 +56,15 @@ Image `src` must be a URL the renderer can reach: a path next to the document, o
56
56
 
57
57
  These commands use the [global Vite+ CLI](https://viteplus.dev/guide/global-cli). Without it, `pnpm dlx` takes the same arguments.
58
58
 
59
- 2. Open the page where it will be read and take a screenshot of it. For a local screenshot-only check, copy the complete `::compare` block, including its nested screenshots and annotations, into `evidence-screenshots.md` beside `evidence.md`.
59
+ 2. Open the page where it will be read and take a screenshot of it. To check the screenshots alone, copy the whole `::compare` block, nested screenshots and annotations included, into `evidence-screenshots.md` beside `evidence.md`.
60
60
 
61
- Ensure comark-annotate is a direct dependency of this workspace package. If it is only transitive, read the installed Comark UI version and add that exact version with the project's package manager: for pnpm, `pnpm add -D comark-annotate@<version>`, substituting that version. Add `-w` when installing at the workspace root. With no Comark UI packages installed, omit `@<version>`. This links the executable without fetching a different renderer release via `@latest`. Then run:
61
+ Make comark-annotate a direct dependency of this workspace package. A transitive one isn't linked, and `@latest` can run a different release from the project's renderers. Match the version of the installed Comark UI packages: `pnpm add -D comark-annotate@<version>`, with `-w` at the workspace root. With no Comark UI packages installed, omit `@<version>`. Then run:
62
62
 
63
63
  ```sh
64
64
  vp exec comark-annotate render evidence-screenshots.md -o evidence-screenshots.html
65
65
  ```
66
66
 
67
- Without Vite+, use `pnpm exec` with the same arguments.
68
-
69
- Open `evidence-screenshots.html` and take a screenshot of it. This CLI renders annotate, carousel, and zoom only; check any `::diff` or other blocks in the host's full Comark UI preview.
70
- 3. Check that each mark sits on its target and each note matches what its side shows. Measure a mark that misses again, from the source, since a box moved by eye stays a guess.
67
+ Without Vite+, use `pnpm exec` with the same arguments. Open `evidence-screenshots.html` and take a screenshot of it. This CLI renders annotate, carousel, and zoom only; check any `::diff` or other blocks in the host's full Comark UI preview.
68
+ 3. Check that each mark sits on its target and each note matches what its side shows. Measure a mark that misses again from the source; a box moved by eye stays a guess.
71
69
 
72
70
  Done when you've looked at the rendered page and every mark lands. Name any mark or block you couldn't check in your report.
@@ -30,7 +30,7 @@ A direct child of a screenshot. Its content is the note, in Markdown.
30
30
  | Prop | What it does |
31
31
  | --- | --- |
32
32
  | `x` `y` `w` `h` | Required. The marked rectangle as percentages of the image, without `%`. |
33
- | `mark` | `box` (default), `circle`, `underline`, `highlight`, `bracket`, `cross`, `check`, or `none`. |
33
+ | `mark` | `box` (default), `circle`, `underline`, `line`, `highlight`, `bracket`, `cross`, `check`, or `none`. |
34
34
  | `color` | `red` for a problem, `green` for the fix, `amber` for a warning, `violet` (default) to point something out, `gray`, or a hex color. |
35
35
  | `side` | `top` or `bottom` moves the note into the margin with an arrow; in a side-by-side compare, `left` and `right` notes join the numbered list. |
36
36
 
@@ -5,11 +5,11 @@ description: Writes PR evidence, explanations of how something works, and docs p
5
5
 
6
6
  # comark-ui
7
7
 
8
- You write Markdown; the comark plugins render it as static HTML, from marks on screenshots and charts drawn from tables to code changes, diagrams, and steps. The reader sees only what you measured and wrote down, so measure every mark from the page, take every number from the data, and check the render before you hand it over.
8
+ You write Markdown, and the comark plugins render it as static HTML. The reader sees only what you measured and wrote down, so measure every mark from the page, take every number from the data, and check the render before you hand it over.
9
9
 
10
10
  ## Install
11
11
 
12
- Prefer `comark-ui`, every plugin in one install, registered in the order they need:
12
+ Install `comark-ui` by default. It holds every plugin and registers them in the order they need:
13
13
 
14
14
  ```sh
15
15
  pnpm add comark @comark/html comark-ui
@@ -26,7 +26,7 @@ const render = createHtmlRenderer(comarkUi());
26
26
 
27
27
  Every plugin is on except `include`. The [comark-ui reference](references/ui.md) covers its options, the plugins that read files or use the network, and its Vue, React, and Svelte entries.
28
28
 
29
- When a project wants only some plugins, install those packages and register each plugin with its components:
29
+ To use only some plugins, install those packages and register each plugin with its components:
30
30
 
31
31
  ```sh
32
32
  pnpm add comark @comark/html comark-annotate
@@ -41,13 +41,17 @@ const render = createHtmlRenderer({ plugins: [annotate()], components });
41
41
 
42
42
  Each reference ends with a Register section that says how its package registers alone and which options it needs.
43
43
 
44
- Either way, the HTML renderer inlines the styles once per document, and the Vue, React, and Svelte components add them on mount. On a server-rendered page, import each package's `style.css`, such as `comark-cards/style.css`, so the page doesn't shift. The `--comark-*` tokens in https://comark-ui.onmax.me/guide/theming/ theme every plugin at once. In a Nuxt UI app the plugins follow its `--ui-*` variables with no setup; for a page rendered outside the app, such as review evidence, put the CSS from `nuxtUiTheme({ colors: appConfig.ui?.colors, css: mainCss })` in `comark-ui/nuxt-ui` in a `<style>`, so the page matches the app.
44
+ Either way, the HTML renderer inlines the styles once per document, and the Vue, React, and Svelte components add them on mount. On a server-rendered page, import each package's `style.css`, such as `comark-cards/style.css`, so the page doesn't shift.
45
+
46
+ The `--comark-*` tokens theme every plugin at once; https://comark-ui.onmax.me/guide/theming/ lists them. In a Nuxt UI app the plugins follow its `--ui-*` variables with no setup. For a page rendered outside the app, such as review evidence, put the CSS from `nuxtUiTheme({ colors: appConfig.ui?.colors, css: mainCss })` (from `comark-ui/nuxt-ui`) in a `<style>`, so the page matches the app.
47
+
48
+ A project that renders Markdown with remark moves to Comark with `remark-to-comark`; the [remark-to-comark reference](references/remark-to-comark.md) walks through it.
45
49
 
46
50
  Problems land in `meta.issues` after `parseMarkdown`, one sentence each, and a host can refuse a document while any remain. For untrusted input, add Comark's `security` plugin with `blockedTags` such as `script`, `style`, and `iframe`; it cleans the Markdown inside blocks too.
47
51
 
48
52
  ## Shape the document
49
53
 
50
- This skill teaches the blocks. Four sibling skills teach a whole document, what goes in it and in what order: `before-after-evidence`, `review-document`, `visual-explanation`, and `teach-lesson`. When the user asks for one of those and the skill isn't installed, suggest `vp dlx skills add onmax/comark-ui` and picking it from the list.
54
+ This skill teaches the blocks. Four sibling skills teach a whole document, what goes in it and in what order: `before-after-evidence`, `review-document`, `visual-explanation`, and `teach-lesson`. When the user asks for one of those and it isn't installed, suggest `vp dlx skills add onmax/comark-ui` and picking it from the list.
51
55
 
52
56
  ## Pick the blocks
53
57
 
@@ -133,13 +137,13 @@ Read the reference for each block you use before you write it. Mix the blocks fr
133
137
 
134
138
  Screenshots and charts draw the same marks. Each `::annotation` is one mark and its note, written in Markdown.
135
139
 
136
- - `mark` is `box` (default), `circle`, `underline`, `highlight`, `bracket`, `cross`, `check`, or `none`, which draws nothing, so its note needs a `side` and the arrow alone points.
140
+ - `mark` is `box` (default), `circle`, `underline`, `line`, `highlight`, `bracket`, `cross`, `check`, or `none`, which draws nothing, so its note needs a `side` and the arrow alone points.
137
141
  - `color` is `violet` (default) to point something out, `red` for a problem, `amber` for a warning, `green` for a fix, `blue` for a second voice, `gray` for neutral, or a 3- or 6-digit hex color.
138
142
  - `side` is `top`, `bottom`, `left`, or `right`, and puts the note in that margin with an arrow to its mark. Notes without one are numbered in a list under the figure.
139
143
 
140
- Mark only what your text talks about. Each note says what changed or what is wrong in the words the screen or the table shows, so the reader can check it against the figure; a value the figure doesn't show stays out of the note.
144
+ Mark only what your text talks about. Write each note in the words the screen or table shows, saying what changed or what is wrong, so the reader can check it against the figure. Leave out a value the figure doesn't show.
141
145
 
142
146
  ## Check the result
143
147
 
144
- 1. Lint the file: `vp exec comark-lint report.md`, in a project with `comark-linter` and the plugins installed, where `comark-ui` counts as every plugin. It prints one line per problem with its line, its rule, and how to fix it, and exits with 1 while any remain. Fix every one, and run it again until it exits with 0. The [lint reference](references/lint.md) covers its flags, its config file, the library, ESLint, and Vite Doctor.
145
- 2. Look at the render, made as the block's reference says. Open it in a browser and take a screenshot: each mark sits on its target, each number matches its note, and each chart says what your text says. If you can't verify something, say so when you hand the document over instead of guessing.
148
+ 1. Lint the file with `vp exec comark-lint report.md`, in a project with `comark-linter` and the plugins installed (`comark-ui` counts as every plugin). It prints one line per problem with its line, its rule, and the fix, and exits with 1 while any remain. Fix every problem and run it again until it exits with 0. The [lint reference](references/lint.md) covers the flags, the config file, the library, ESLint, and Vite Doctor.
149
+ 2. Render the document as the block's reference says, open it in a browser, and take a screenshot. Each mark must sit on its target, each number must match its note, and each chart must say what your text says. Name anything you couldn't verify when you hand the document over.
@@ -53,7 +53,7 @@ For a clipped capture, `getBoundingClientRect()` and Playwright's main-frame `cl
53
53
 
54
54
  ## Preview
55
55
 
56
- Ensure comark-annotate is a direct dependency of the workspace package where you run the CLI. If it is only transitive, read the installed Comark UI version and add that exact version with the project's package manager: for pnpm, `pnpm add -D comark-annotate@<version>`, substituting that version. Add `-w` when installing at the workspace root. With no Comark UI packages installed, omit `@<version>`. This links the executable without fetching a different renderer release via `@latest`.
56
+ Make comark-annotate a direct dependency of the workspace package where you run the CLI, so its executable links. If it is only transitive, read the installed Comark UI version and add that exact version, such as `pnpm add -D comark-annotate@<version>` (add `-w` at the workspace root), because `@latest` could fetch a different renderer release. With no Comark UI packages installed, omit `@<version>`.
57
57
 
58
58
  ```sh
59
59
  vp exec comark-annotate render report.md -o report.html
@@ -42,7 +42,7 @@ Use image mode for README-style label/value badges. Static images embed their SV
42
42
  - `style`: `shadcn` by default, `subtle`, or `solid`; `theme`: `auto` by default, following the page's light or dark theme (on GitHub too), or `light` or `dark`. `color` and `labelColor` accept semantic names or six-digit hex colors. In the default preset, shadcn draws an outline with neutral text; `labelColor` applies to subtle and solid backgrounds. CI chooses its own status color. Images embed colors and do not inherit the document's CSS.
43
43
  - `period`: `day`, `week`, or `month` for downloads. Hosted values cache for five minutes for versions, one hour for downloads, and one minute for CI. Failures display `unavailable` for 30 seconds. Downloaded SVGs are snapshots.
44
44
 
45
- The builder at `/badges/` lives in the docs layout, shares its configuration and export format in the query string, and exports Comark, Markdown, an image URL, and SVG. The image endpoint is `/badge.svg`, with the same props as query parameters. Preserve the existing prose syntax for inline tags that should follow the page's theme.
45
+ The builder at `/badges/` exports Comark, Markdown, an image URL, and SVG. The image endpoint is `/badge.svg`, with the same props as query parameters. For an inline tag that should follow the page's theme, keep the prose syntax above; an image embeds its own colors.
46
46
 
47
47
  ## Register
48
48
 
@@ -23,7 +23,8 @@ Read the code, or open an issue.
23
23
  | `icon` | An icon above the title, in the card's color, named as in [icon](icon.md), such as `lucide:rocket`. The plugin reports one it can't draw. |
24
24
  | `to` | Makes it a link card. One link covers the card and takes the title as its name, and links in the card's text still open on their own. A web address opens in a new tab with an arrow in the corner. |
25
25
  | `target` | Where the link opens, such as `_self` to keep a web address in the tab. |
26
- | `color` | Tints the icon and a hovered link card's border: `primary` (default), `secondary`, `success`, `info`, `warning`, `error`, or `neutral`. |
26
+ | `color` | Tints the icon and a hovered link card's border: `primary` (default), `secondary`, `success`, `info`, `warning`, `error`, or `neutral`. Any other value shows as `primary` and is reported. |
27
+ | `variant` | `outline` (default) keeps the plain card, `soft` washes it in its `color`, and `subtle` washes it and draws its border in the `color` too. |
27
28
 
28
29
  `::card-group` sets its cards in two columns, or one when the group is narrower than 36rem, so a group in a sidebar stacks too. A card works on its own as well.
29
30
 
@@ -30,5 +30,5 @@ Mark the lines a reviewer would ask about: the request that runs in parallel, th
30
30
 
31
31
  ## Register
32
32
 
33
- - In `comark-ui`: on as `codeNotes`, the last plugin. The preset leaves Shiki out; add it right before comark-code, as the [code reference](code.md) shows, which keeps it ahead of code notes.
33
+ - In `comark-ui`: on as `codeNotes`, listed after `code`. The preset leaves Shiki out; add it right before comark-code, as the [code reference](code.md) shows, which keeps it ahead of code notes.
34
34
  - Alone: `pnpm add comark @comark/html comark-code-notes`, then `createHtmlRenderer({ plugins: [shiki(), codeNotes()], components })` with `shiki` from `@comark/html/plugins/shiki`, and `codeNotes` and `components` from `comark-code-notes/html`. It goes after `shiki`; in the other order the code isn't highlighted and `meta.issues` says so. Without Shiki it draws the lines itself. It takes no options, and `comark-code-notes/vue`, `/react`, and `/svelte` render it too.
@@ -28,9 +28,9 @@ function close() {
28
28
 
29
29
  A range is one line, `{7}`, a run, `{3-4}`, or a list of both, `{1, 3-4}`, always in braces. Ranges count the block's own lines from 1, folded lines included, whatever `startLineNumber` says: `startLineNumber=120 ins={3}` marks the line numbered 122.
30
30
 
31
- `sh`, `bash`, `zsh`, `shell`, `console`, and `ansi` blocks draw as terminals unless their title is a file name, such as `install.sh`. A terminal's header shows its title but not its language. In a code group the tab names the block, so a terminal there draws no window.
31
+ `sh`, `bash`, `zsh`, `shell`, `shellscript`, `shellsession`, `console`, and `ansi` blocks draw as terminals unless their title is a file name, such as `install.sh`. A terminal's header shows its title but not its language. In a code group the tab names the block, so a terminal there draws no window.
32
32
 
33
- When the host runs Shiki's notation transformers, comments such as `// [!code ++]`, `// [!code --]`, `// [!code highlight]`, and `// [!code focus]` mark lines too, and comark-code styles them.
33
+ When the host runs Shiki's notation transformers, comments such as `// [!code ++]`, `// [!code --]`, `// [!code highlight]`, `// [!code focus]`, `// [!code error]`, and `// [!code warning]` mark lines too, and comark-code styles them.
34
34
 
35
35
  ## Show a change
36
36
 
@@ -50,7 +50,7 @@ When the host runs Shiki's notation transformers, comments such as `// [!code ++
50
50
  ```
51
51
  ````
52
52
 
53
- A range that lands on the wrong line inside the block isn't reported, so count the lines before you mark them.
53
+ A range past the block's last line is reported. One that lands on the wrong line inside the block isn't, so count the lines before you mark them.
54
54
 
55
55
  ## Add buttons
56
56
 
@@ -25,7 +25,7 @@ The link expires after :comment[15 minutes]{#ttl by="@onmax" note="Is 15 minutes
25
25
  | Prop | On | What it does |
26
26
  | --- | --- | --- |
27
27
  | `from` | suggestion | The text it replaces or deletes. Plain text. |
28
- | `by` | both, reply | The author, shown as written; a leading `@` is dropped. The avatar is the name's initial. |
28
+ | `by` | both, reply | The author, shown as written; a leading `@` is dropped. The avatar is the name's initial, or the image `avatars` gives that name. |
29
29
  | `note` | both, reply | The card's text. Plain text. A suggestion with no note and no replies is only a redline, with no card. |
30
30
  | `mark` | suggestion | `track` (default): red strike, green insert. `pen`: a hand-drawn strike with the new words handwritten above. |
31
31
  | `#id` | both | The id a reply points at. Comments and suggestions share one id space. |
@@ -39,5 +39,5 @@ The link expires after :comment[15 minutes]{#ttl by="@onmax" note="Is 15 minutes
39
39
 
40
40
  ## Register
41
41
 
42
- - In `comark-ui`: on, as `comments`, in `comark-ui/html` only. `comments: { mark: "pen" }` draws every suggestion with the pen unless it sets its own `mark`.
43
- - Alone: `pnpm add comark @comark/html comark-comments`, then `createHtmlRenderer({ plugins: [comments()], components })` with `comments, { components }` from `comark-comments/html`. There are no Vue, React, or Svelte entries.
42
+ - In `comark-ui`: on, as `comments`, in `comark-ui/html` only. `comments: { mark: "pen" }` draws every suggestion with the pen unless it sets its own `mark`. `comments: { avatars: { onmax: "https://github.com/onmax.png" } }` gives authors an image by the name in `by`, without `@`, in any case.
43
+ - Alone: `pnpm add comark @comark/html comark-comments`, then `createHtmlRenderer({ plugins: [comments()], components })` with `comments, { components }` from `comark-comments/html`, which takes the same `mark` and `avatars` options. There are no Vue, React, or Svelte entries.
@@ -1,6 +1,6 @@
1
1
  # Players and link cards
2
2
 
3
- comark-embed turns `::embed` into the provider's player, with the link under it, for YouTube, Vimeo, Loom, Spotify, CodePen, StackBlitz, and Figma, and into a link card for any other https page. It reads the player's address from the link alone and fetches nothing. Use it for a screen recording of a bug, a design file, or a live reproduction.
3
+ comark-embed turns `::embed` into the provider's player, with the link under it, for YouTube, Vimeo, Loom, Spotify, CodePen, StackBlitz, Figma, and X, and into a link card for any other https page. It reads the player's address from the link alone and fetches nothing. Use it for a screen recording of a bug, a design file, or a live reproduction.
4
4
 
5
5
  ## Syntax
6
6
 
@@ -26,6 +26,7 @@ Close the block with `::` on the next line. It drops anything inside and reports
26
26
  | CodePen | `codepen.io/<user>/pen/<id>` |
27
27
  | StackBlitz | `stackblitz.com/edit/<project>` and `stackblitz.com/github/<owner>/<repo>`, keeping options such as `file` and `view` |
28
28
  | Figma | `figma.com/design`, `file`, `proto`, `board`, `slides`, and `deck` links, keeping `node-id` |
29
+ | X | `x.com/<user>/status/<id>` and `twitter.com` links, `mobile.` ones too; the post grows to its own height |
29
30
 
30
31
  Any other `https://` link renders as a card with its `title` and host. A provider's link it can't read an ID from renders as a card too, and is reported. A link with a user name or password renders nothing.
31
32
 
@@ -37,4 +38,4 @@ Any other `https://` link renders as a card with its `title` and host. A provide
37
38
  ## Register
38
39
 
39
40
  - In `comark-ui`: on.
40
- - Alone: `pnpm add comark @comark/html comark-embed`, then `createHtmlRenderer({ plugins: [embed()], components })` with both from `comark-embed/html`. It takes no options and needs no script. `comark-embed/vue`, `/react`, and `/svelte` render it too.
41
+ - Alone: `pnpm add comark @comark/html comark-embed`, then `createHtmlRenderer({ plugins: [embed()], components })` with both from `comark-embed/html`. It takes no options. Only an X post needs a script, which the HTML renderer inlines and the components start on mount. `comark-embed/vue`, `/react`, and `/svelte` render it too.
@@ -11,7 +11,7 @@ Hold ++shift++ and press ++"Duck Button"++ to page the rubber duck.
11
11
  ```
12
12
 
13
13
  - Write the keys between `++` and `++`, joined by single `+` signs, with no spaces. Names aren't case sensitive.
14
- - Letters and digits render uppercase, `f1` to `f24` as F1 to F24, and these names as their usual labels:
14
+ - Full names (`control`, `command`, `escape`, `delete`, `arrow-up`) and pymdownx.keys' other aliases work too. Letters and digits render uppercase, `f1` to `f24` as F1 to F24, and these names as their usual labels:
15
15
  - Modifiers: `ctrl`, `alt`, `shift`, `cmd`, `opt`, `option`, `meta`, `super`, `win`, `fn`, `altgr`.
16
16
  - Editing: `enter`, `return`, `tab`, `esc`, `space`, `backspace`, `bksp`, `del`, `ins`, `caps-lock`.
17
17
  - Moving: `up`, `down`, `left`, `right`, `home`, `end`, `pg-up`, `pg-dn`, `page-up`, `page-down`.
@@ -15,7 +15,7 @@ Turn off the `new-checkout` flag in **Settings**, then redeploy.
15
15
  ```
16
16
 
17
17
  - A heading's `#` link uses its id. Comark makes the id from the heading's text, so write `{#rollout}` after a heading that other pages link to, and the link survives a reworded heading.
18
- - A link opens a new tab only when the host sets `target` or the link says `{target="_blank"}`. Leave both off, so the reader decides; add one only where leaving loses the reader's work, such as a page with a half-filled form. Any link that opens a new tab, on your site or another, gets `rel="noopener"`, a ↗, and "(opens in a new tab)" for screen readers, so leave that out of the link's text.
18
+ - A link opens a new tab only when the host sets `target` or the link says `{target="_blank"}`. Leave both off, so the reader decides; add one only where leaving loses the reader's work, such as a page with a half-filled form. Any link that opens a new tab, on your site or another, gets a ↗ and "(opens in a new tab)" for screen readers, so leave that out of the link's text. Any link with `target="_blank"` also gets `rel="noopener"`.
19
19
  - A link keeps the `target` and `rel` written on it, such as `{rel="me"}` on a profile link, or `{target="_self"}` to keep one link in the tab when the host opens the others in a new one.
20
20
 
21
21
  ## Options
@@ -1,6 +1,6 @@
1
1
  # Checking documents
2
2
 
3
- comark-linter reports what Comark forgives, such as a `::` block never closed, a misspelled component, or a link to a missing file. It also reports every problem a plugin puts in `meta.issues`, each under its own rule. Check the result in SKILL.md runs it on one file; this page covers its flags, its config file, the library, ESLint, and Vite Doctor.
3
+ comark-linter reports what Comark forgives, such as an unclosed `::` block, a misspelled component, or a link to a missing file. It also reports every problem a plugin puts in `meta.issues`, each under its own rule. SKILL.md's Check the result step runs it on one file. This page covers the flags, the config file, the library, ESLint, and Vite Doctor.
4
4
 
5
5
  ## Run the command
6
6
 
@@ -10,13 +10,22 @@ vp exec comark-lint "docs/**/*.md" --format json --check-urls
10
10
 
11
11
  - Pass files or globs. Quote a glob so the shell passes it as written; comark-lint expands it and skips `node_modules` and `dist`.
12
12
  - It prints `file:line:column rule message fix` for each problem, or `No problems.` when there are none. It exits with 0 when clean, 1 on any problem, and 2 when a file can't be read, a glob matches nothing, or the config fails to load.
13
- - `--format json` prints an array of `{ file, rule, line, column, message, fix }` instead.
14
- - `--check-urls` also requests every external URL, and reports one that answers 404 or 410, has no DNS record, or fails its TLS check. It caches answers for a day in `node_modules/.cache/comark-linter/urls.json`, except a 404, 410, 429, or 5xx, which it requests again on the next run.
13
+ - `--format json` prints an array of `{ file, rule, severity, line, column, message, fix }` instead. `severity` is `error` or `warn`; the exit code is 1 for either.
14
+ - `--check-urls` also requests every external URL and reports one that answers 404 or 410, has no DNS record, or fails its TLS check. It caches answers for a day in `node_modules/.cache/comark-linter/urls.json`, except a 404, 410, 429, or 5xx, which the next run requests again.
15
15
  - It loads `comark-lint.config.ts` (or `.mts`, `.mjs`, `.js`) from the working directory, or a `lint-comark.config` file there. `--config path/to/config.ts` loads another one instead.
16
16
 
17
- Run it from the project root. A relative link or image resolves from the document's folder, and a `/` path from the working directory. Each must point at a file that exists, so save the screenshots before you lint.
17
+ Run it from the project root. A relative link or image resolves from the document's folder, and a `/` path from the working directory. Each must point at an existing file, so save the screenshots before you lint.
18
18
 
19
- It lints with every comark-ui package installed, `comark-ui` first; the [comark-ui reference](ui.md) says what it turns on there. Besides each plugin's own rules, named `comark/<package>/<kind>`, it reports unclosed blocks, unknown components, an unclosed `{` or a key set twice, broken links and anchors, frontmatter that isn't valid YAML, `javascript:` and other unsafe URLs, duplicate ids, images without alt text unless `{alt=""}` marks them as decoration, and empty links. It also reports links that stop working for other readers: localhost, private network, and `file:` URLs, tunnels such as ngrok, and Vercel or Netlify deploy previews. In PR evidence, link the production page or the pull request, and write a local address as code, such as `` `localhost:3000` ``, since Comark links a bare URL.
19
+ It lints with every installed comark-ui package, `comark-ui` first; the [comark-ui reference](ui.md) says what it turns on there. Besides each plugin's own rules, named `comark/<package>/<kind>`, it reports:
20
+
21
+ - unclosed blocks, unknown components, an unclosed `{`, and a key set twice
22
+ - broken links and anchors, empty links, and duplicate ids
23
+ - frontmatter that isn't valid YAML
24
+ - `javascript:` and other unsafe URLs
25
+ - images without alt text, unless `{alt=""}` marks them as decoration
26
+ - links that stop working for other readers: localhost, private network, and `file:` URLs, tunnels such as ngrok, and Vercel or Netlify deploy previews
27
+
28
+ In PR evidence, link the production page or the pull request. Write a local address as code, such as `` `localhost:3000` ``, since Comark turns a bare URL into a link.
20
29
 
21
30
  ## Config file
22
31
 
@@ -32,8 +41,8 @@ export default defineConfig({
32
41
  });
33
42
  ```
34
43
 
35
- - `plugins` and `components` add to those of the installed packages. `components` takes names, or the components map you render with. Comark keeps the first plugin of each name and drops the rest, so a config can add plugins, such as your own or [include](include.md), and can't change the options of one an installed package registers.
36
- - It takes every library option below except `file`. Node reads a `.ts` config from 22.18 on; on older versions, write it as `.mjs`.
44
+ - `plugins` and `components` add to those of the installed packages. `components` takes names, or the components map you render with. Comark keeps the first plugin of each name, so a config can add plugins, such as your own or [include](include.md), but can't change the options of one an installed package registers.
45
+ - It takes every library option below except `file`. Node reads a `.ts` config from 22.18; on older versions, write `.mjs`.
37
46
 
38
47
  `links` sets how the linter checks links. It applies `skip`, `block`, and `allow` in that order, then checks the file or the URL:
39
48
 
@@ -57,8 +66,8 @@ const diagnostics = await lint(markdown, { plugins: [annotate()], components, fi
57
66
  const results = await lintFiles(["docs/index.md", "docs/setup.md"], await resolveConfig());
58
67
  ```
59
68
 
60
- - `lint(markdown, options)` returns `{ rule, line, column?, message, fix }[]` in source order and never throws. A rule that crashes reports one diagnostic saying so, and the others still run.
61
- - Pass `plugins` and `components`, the ones you render with; without `components`, it skips the unknown-component check. Pass `file`, the document's path, to check its links to files. `root` defaults to the working directory, and `read`, `exists`, and `list` replace node:fs, by absolute path. Pass `headingIds` if you render with it, so anchors match, and `links` as above.
69
+ - `lint(markdown, options)` returns `{ rule, severity, line, column?, message, fix }[]` in source order and never throws. A rule that crashes reports one diagnostic saying so, and the others still run.
70
+ - Pass the `plugins` and `components` you render with; without `components`, it skips the unknown-component check. Pass `file`, the document's path, to check its links to files. `root` defaults to the working directory, and `read`, `exists`, and `list` replace node:fs, by absolute path. Pass the `headingIds` you render with so anchors match, and `links` as above.
62
71
  - `lintFiles(paths, options)` parses each file once, checks links between them against each other's headings, and requests each URL once. It returns `{ file, text, diagnostics }` for each path, with no `text` when the file can't be read.
63
72
  - `resolveConfig(config)` returns the installed packages' plugins and components plus the config's, as the command uses them. `rules` maps every rule to its title.
64
73
 
@@ -71,9 +80,9 @@ import comark from "comark-linter/eslint";
71
80
  export default [comark.configs.recommended, { settings: { comark: { config: "comark-lint.config.mjs" } } }];
72
81
  ```
73
82
 
74
- Use a JavaScript ES module (`export default { ... }`) for the linter config across supported Node versions. A `.ts` config requires Node 22.18+ or `--experimental-strip-types` on Node 22.12–22.17, including in the editor. Restart ESLint after editing the config or its imports; they are cached for the process lifetime.
83
+ Write the linter config as a JavaScript ES module (`export default { ... }`) so it loads on every supported Node version. A `.ts` config needs Node 22.18+, or `--experimental-strip-types` on Node 22.12–22.17, in the editor too. Restart ESLint after you edit the config or its imports, since it caches them for the process.
75
84
 
76
- Install `eslint` (9.15 or later) and `@eslint/markdown` (8 or later). The recommended config lints `**/*.md` and `**/*.mdc` with `@eslint/markdown`'s `markdown/commonmark` language and YAML frontmatter, and turns on every rule but `comark/dead-url`, which requests every URL; turn that one on in `rules` to check them. Each rule has the name the command prints and is configured like any ESLint rule, `<!-- eslint-disable-next-line comark/unknown-component -->` included. ESLint prints the fix after the message. `settings.comark.config`, from the working directory, loads the same config file as `--config`. oxlint can't run it: its JS plugins don't lint `.md` files, so run `comark-lint` beside `oxlint`.
85
+ Install `eslint` (9.15 or later) and `@eslint/markdown` (8 or later). The recommended config lints `**/*.md` and `**/*.mdc` with `@eslint/markdown`'s `markdown/commonmark` language and YAML frontmatter. It turns on every rule but `comark/dead-url`, which requests every URL; turn that one on in `rules` to check them. Each rule has the name the command prints and is configured like any ESLint rule, `<!-- eslint-disable-next-line comark/unknown-component -->` included. ESLint prints the fix after the message. `settings.comark.config`, a path from the working directory, loads the same config file as `--config`. oxlint can't run it, because its JS plugins don't lint `.md` files; run `comark-lint` beside `oxlint`.
77
86
 
78
87
  ## Vite Doctor
79
88
 
@@ -93,4 +102,4 @@ Run `vite-doctor . --config doctor.config.ts --max-warnings 0`. The extension ta
93
102
  ## Register
94
103
 
95
104
  - In `comark-ui`: not included. Install it beside the preset, which it finds on its own.
96
- - Alone: `pnpm add -D comark-linter`. The command is `comark-lint`, also installed as `lint-comark`, the library `comark-linter`, the ESLint plugin `comark-linter/eslint`, and the extension `comark-linter/doctor`. npm refused `comark-lint` as too close to `remark-lint`, hence the name.
105
+ - Alone: `pnpm add -D comark-linter`. It installs the command `comark-lint` (also `lint-comark`), the library `comark-linter`, the ESLint plugin `comark-linter/eslint`, and the Vite Doctor extension `comark-linter/doctor`.
@@ -25,7 +25,7 @@ const total = price * rate
25
25
  ## Choose the steps
26
26
 
27
27
  - Change one thing per step. When most of the code moves at once, the reader can't follow any of it.
28
- - Keep the code that stays the same identical, spaces aside, so it moves rather than fading out and in.
28
+ - Keep the code that stays the same identical, so it moves rather than fading out and in.
29
29
  - For a change a reviewer approves, write `::diff`: it shows every removed and added line at once, which an animation can't.
30
30
 
31
31
  ## Register
@@ -7,12 +7,12 @@ comark-media plays an image that points at a video or a sound file, and a GitHub
7
7
  ```md
8
8
  The spinner now stops once the build finishes:
9
9
 
10
- ![The build spinner stops and the Deploy button turns green](./recordings/build.mp4){loop muted}
10
+ ![The build spinner stops and the Deploy button turns green](./recordings/build.mp4){loop muted width=1280 height=720}
11
11
  ```
12
12
 
13
13
  - A `src` that ends in `.mp4`, `.webm`, `.mov`, or `.m4v`, before any `?` or `#`, plays as a video, and one in `.mp3`, `.wav`, `.ogg`, or `.m4a` as audio. Every other image stays an image.
14
14
  - The alt text is required. It names the player for screen readers, and it's the text of a link to the file where the browser can't play it.
15
- - `autoplay`, `loop`, and `muted` are off by default. Browsers start a file by itself only when it's muted, so `autoplay` needs `muted`. `poster="frame.png"` shows an image before a video plays; audio takes none. `{loop=false}` turns a prop off. A video's `width` and `height` must be paired whole pixel dimensions, like `{width=1280 height=720}`, to reserve its room before loading. Audio takes neither. Other props, such as a class, are dropped and reported.
15
+ - `autoplay`, `loop`, and `muted` are off by default. Browsers start a file by itself only when it's muted, so `autoplay` needs `muted`. `poster="frame.png"` shows an image before a video plays; audio takes none. `{loop=false}` turns a prop off. Give every video its `width` and `height`, paired whole pixel dimensions like `{width=1280 height=720}`, so the page keeps its room before the file loads; read them with `ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 clip.mp4`. Audio takes neither. Other props, such as a class, are dropped and reported.
16
16
  - A GitHub attachment link, `https://github.com/user-attachments/assets/<id>`, plays as a video when the bare URL sits alone in its paragraph, as on GitHub. With text of its own, or inside a sentence, it stays a link.
17
17
 
18
18
  ## Record the evidence
@@ -20,6 +20,7 @@ Tests moved to Vitest: :progress{value=17 max=20 label="Migrated"}
20
20
 
21
21
  - `:delta` reads `412 kB → 388 kB ↓ 5.8%`. `from` and `to` are required numbers, and `unit`, such as `kB`, `s`, or `%`, goes after both. `better` is `lower` for sizes and durations or `higher` for scores. It colors the change green when it's better and red when it's worse; without it the change is gray. The percent is of `from`, to one decimal. From 0 there is no percent, so the change is the difference, such as `↑ 1.5 s`.
22
22
  - `::stats` holds one Markdown table of three columns: a name, the value before, and the value after, under any headers. A cell is a number, with commas if you like, and an optional unit after it, the same in both cells of a row. `better` applies to every row, and `unit` names a difference from 0 for cells written without one. The plugin drops anything else inside the block and reports it.
23
+ - Add `tiles` to `::stats` to show each row as a tile, with the name above the after value and the change below it. The table can then have two columns, a name and a value; a value with no before shows without a change. `better` and `unit` work as for the table.
23
24
  - `:progress` is a native `<progress>` with its percent after it. `value` is required: a fraction from 0 to 1, or a count up to `max`, which is 1 by default. `label` shows before the bar and names it for screen readers. The plugin clamps a `value` outside 0 to `max` and reports it.
24
25
 
25
26
  ## Write the numbers
@@ -36,9 +36,9 @@ The `rail` option adds an "On this page" outline beside the text of every docume
36
36
 
37
37
  - Options: `rail: true`, or `{ title, depth }` (default "On this page" and 3).
38
38
  - The page sets `--comark-inset-end` on `:root` for a panel that covers its right edge. While the outline keeps a column beside wide blocks, it sets `data-comark-rail` and `--comark-rail-width` on `<html>`, and the page shrinks `--comark-wide-end` by it, so wide blocks move toward the room before the text.
39
- - It hides where it doesn't fit, and rather than narrow a diagram.
39
+ - It hides where it doesn't fit, and hides rather than narrow a wide diagram.
40
40
 
41
41
  ## Register
42
42
 
43
43
  - In `comark-ui`: on in every entry; `outline: { rail: true }` adds the side outline.
44
- - Alone: `pnpm add comark @comark/html comark-outline`, then `createHtmlRenderer({ plugins: [outline()], components })` with both from `comark-outline/html`. `comark-outline/vue`, `/react`, and `/svelte` render it too. It reads the headings itself, so it works in any plugin order and without Comark's toc plugin, which only fills `meta.toc` for a sidebar. The npm name is `comark-outline` because npm refused `comark-toc`.
44
+ - Alone: `pnpm add comark @comark/html comark-outline`, then `createHtmlRenderer({ plugins: [outline()], components })` with both from `comark-outline/html`. `comark-outline/vue`, `/react`, and `/svelte` render it too. It reads the headings itself, so it works in any plugin order and without Comark's toc plugin, which only fills `meta.toc` for a sidebar.
@@ -24,7 +24,7 @@ The palette page now shows every token of the theme.
24
24
  - The box shows the host's `keys`, by default `status`, `pr`, `author`, `date`, and `tags`, in that order. A key that's missing or empty is skipped, and the rest of the frontmatter, such as a layout or a slug, stays off the page.
25
25
  - The box goes first in the document. To put it somewhere else, such as under the title, write `::properties` there and close it with `::` on the next line. It takes no props and no content; choosing keys is the host's job.
26
26
  - Text, a number, `true`, and `false` show as written, and so does a date such as `2026-10-23`. A GitHub or GitLab pull request, merge request, or issue link shows as `owner/repo#123`, any other http(s) link as its host and path, and a list as one badge per item. An object or a list of lists doesn't show, and is reported.
27
- - Each label is its key capitalized, with `pr` as PR, unless the host names it.
27
+ - Each label is its key capitalized, with dashes and underscores as spaces, `pr` as PR, and `url` as URL, unless the host names it.
28
28
 
29
29
  ## Register
30
30
 
@@ -1,6 +1,6 @@
1
1
  # Lessons and quizzes
2
2
 
3
- comark-quiz adds `::question`, `::poll`, and `::recall` blocks for interactive lessons. Questions check one or more answers and explain each option, polls collect votes, and recall cards reveal an answer for self-testing. Without its script, the prompt, options, and answer disclosure remain readable HTML.
3
+ comark-quiz adds `::question`, `::poll`, and `::recall` blocks for interactive lessons. A question checks one or more answers and explains each option, a poll collects votes, and a recall card hides an answer until the reader asks for it. Without the script, the prompt, options, and answer disclosure stay readable HTML.
4
4
 
5
5
  ## Syntax
6
6
 
@@ -35,11 +35,23 @@ Promise callbacks are microtasks, and a timer's callback is a task.
35
35
  ::
36
36
  ```
37
37
 
38
- A question uses radios when one option is marked `[x]`; `multiple` makes it a checkbox question. Options are shuffled deterministically unless `shuffle="false"`. Questions and recall cards share numbering, while polls are not numbered. A missing id is derived from the block content. Use `#hint` and `#explain` on questions, and `#answer` on recall cards. Polls accept `multiple` and a date in `closes`.
38
+ | Block | Props and slots |
39
+ | --- | --- |
40
+ | `::question` | `#id`, `multiple`, `shuffle="false"`, `number="false"`, slots `#hint` and `#explain`. |
41
+ | `::poll` | `#id`, `multiple`, `closes` (an ISO date; after it the poll shows as closed). Options are never shuffled. |
42
+ | `::recall` | `#id`, `number="false"`, and the required slot `#answer`. |
43
+
44
+ - Mark a right option `[x]` and a wrong one `[ ]`. One right option makes radios and several make checkboxes; `multiple` forces checkboxes even with one. Mark no option in a poll.
45
+ - Put a `>` line under an option to say why it is right or wrong. Give every wrong option a reason, since that is the lesson for a reader who picked it.
46
+ - Leave a blank line before `#hint` and `#explain`. Without it, the text above swallows the slot, and the plugin reports it.
47
+ - Give every block an `#id`. Hosts save answers by id. Without one the id derives from the prompt and options, changes when you reword them, and the plugin reports it. Keep the id when you reword the prompt.
48
+ - Questions and recall cards share one count, so a lesson numbers them 1, 2, 3 down the page. Polls are not numbered.
49
+ - Options are shuffled the same way for every reader, so do not write options that point at others by place, such as "All of the above" or "Both A and B". Keep the options about as long as each other, since a right option much longer than the rest is reported.
50
+ - Keep a block to six options or fewer. Mark at least one right option in a question, or ask it as a poll. Put no block inside another block's prompt, option, or slot.
39
51
 
40
52
  The HTML renderer inlines the quiz script and styles. Hosts can listen for `comark-quiz:answer` and `comark-quiz:ready`, and restore answers or results with `comark-quiz:state`; see [Saving answers](https://comark-ui.onmax.me/quiz/#saving-answers) on its page for the event shapes and storage behavior.
41
53
 
42
54
  ## Register
43
55
 
44
56
  - In `comark-ui`: on, as `quiz`, with optional `{ labels }` for translated UI text.
45
- - Alone: `pnpm add comark @comark/html comark-quiz`, then `createHtmlRenderer({ plugins: [quiz()], components })` with `quiz, { components }` from `comark-quiz/html`. The HTML renderer is required because the blocks need its inlined script; there are no Vue, React, or Svelte entries.
57
+ - Alone: `pnpm add comark @comark/html comark-quiz`, then `createHtmlRenderer({ plugins: [quiz()], components })` with `quiz, { components }` from `comark-quiz/html`. Use the HTML renderer, since the blocks need its inlined script; there are no Vue, React, or Svelte entries.
@@ -28,5 +28,5 @@ With `@comark/vue` or `@comark/react`, read `meta.readingTime` from the parsed d
28
28
 
29
29
  ## Register
30
30
 
31
- - In `comark-ui`: on in every entry. `readingTime: { wordsPerMinute: 230 }` sets the speed. The default, 200, is a cautious pace for technical prose; 230 to 250 suits light reading, and a site mostly in CJK may want more.
31
+ - In `comark-ui`: on in every entry. `readingTime: { wordsPerMinute: 230 }` sets the speed; 0 or less counts at 200. The default, 200, is a cautious pace for technical prose; 230 to 250 suits light reading, and a site mostly in CJK may want more.
32
32
  - Alone: `pnpm add comark comark-reading-time`, then `parseMarkdown(markdown, { plugins: [readingTime()] })` with `readingTime` from `comark-reading-time`. It has no components, so it works with any renderer.
@@ -0,0 +1,29 @@
1
+ # Moving a project from remark
2
+
3
+ remark-to-comark moves a project that renders Markdown with remark, rehype, unified, or react-markdown to Comark. It reports what it finds as diagnostics, `RTC0101` to `RTC0303`, each with a fix and a link to https://comark-ui.onmax.me/remark-to-comark/diagnostics/.
4
+
5
+ ## Run it
6
+
7
+ ```sh
8
+ vp exec remark-to-comark check . --json
9
+ vp exec remark-to-comark content "**/*.{md,mdx}" --write
10
+ vp exec remark-to-comark rewrite . --write
11
+ vp exec remark-to-comark check . --json
12
+ ```
13
+
14
+ - `check` lists the remark setups it finds and what each plugin becomes, the unified chains `rewrite` can replace and why the others stay, the Markdown files `content` would change, and the MDX it leaves alone. `--json` prints each finding with its code, file, line, fix, and docs link.
15
+ - `rewrite` replaces a chain like `unified().use(remarkParse).use(remarkRehype).use(rehypeStringify).process(markdown)` with `renderHtml(markdown, comarkOptions({ … }))`, importing `comarkOptions` from `remark-to-comark/setup`. Install what the new code imports: `comark`, `@comark/html`, and `remark-to-comark`.
16
+ - `content` escapes `{`, `[`, and `:name` that Comark would read as attributes, spans, or components, so remark still renders every file byte for byte as before. It parses with the project's syntax plugins, so `$x_{i}$` stays math. Run it before `rewrite`, which removes the remark code it reads them from.
17
+ - Run `check` again at the end. What's left is work for you: framework configs (RTC0101), the project's own plugins (RTC0105), chains it couldn't rewrite (RTC0201), MDX (RTC0301), and blocks left as written (RTC0303).
18
+
19
+ ## What it leaves to you
20
+
21
+ - A framework config, such as Astro's `markdown.remarkPlugins` or Docusaurus' `remarkPlugins`, stays as it is: the framework calls remark. Render with `renderHtml(markdown, comarkOptions())` where the framework lets you, such as a content loader or a route.
22
+ - react-markdown becomes `<Markdown value={markdown} options={…} plugins={[…]} />` from `@comark/react`, with the plugins the findings name.
23
+ - A plugin a comark-ui package replaces is reported with that package (RTC0102); its markup differs from the remark plugin's, so check pages that style it.
24
+ - MDX stays MDX. Convert a page by hand only when its JSX just passes props: rename it to `.md`, run `content` on the prose, then write the components as Comark blocks. `content` escapes Comark syntax, so don't run it after you add them.
25
+
26
+ ## Register
27
+
28
+ - In `comark-ui`: not included. Install it beside the preset for the migration.
29
+ - Alone: `pnpm add -D remark-to-comark`. It installs the command `remark-to-comark`, the library `remark-to-comark`, the Comark setup `remark-to-comark/setup` (add it to your runtime dependencies when rewritten code imports it), the ports `remark-to-comark/plugins`, and the Vite Doctor extension `remark-to-comark/doctor`.
@@ -18,7 +18,7 @@ At 1024 px wide, **Apply** drops under the filter chips.
18
18
  ```
19
19
 
20
20
  - Each `###` heading starts a step that holds everything up to the next one, code blocks and images included. The heading keeps its id, so a link to `#add-three-filters` and a table of contents still find it.
21
- - `level` is the level of the headings that start each step, from 2 to 6, default 3. Write `::steps{level="2"}` for `##` headings. Deeper headings stay inside their step.
21
+ - `level` is the level of the headings that start each step, from 2 to 6, default 3; any other value falls back to 3 and is reported. Write `::steps{level="2"}` for `##` headings. Deeper headings stay inside their step.
22
22
  - A block whose only content is one numbered list makes a step of each item, and a list that starts at 3 numbers its steps from 3. Use the list when every step fits on one line.
23
23
  - A `:::steps{level="4"}` inside a step keeps its own headings and numbers.
24
24
 
@@ -25,6 +25,7 @@ Or read the file the run wrote, and leave the block empty:
25
25
  - A ` ```json ` fence stays code unless it sits inside `::table`. It holds an array of objects, one per row. Every key becomes a column, in the order first seen, and a nested value shows as JSON.
26
26
  - `src` starts at the document's folder, or at the host's `root` when it starts with `/`. It can't leave `root` or be a URL, and the extension picks the format. The plugin drops content beside `src` and reports it.
27
27
  - A Markdown table inside `::table{sort}` or `::table{copy}` gets the Copy button. A `::table` with no props renders its Markdown table plain.
28
+ - To tint a cell by status, write the whole cell as `[text]{tone="success"}`, with `success`, `warning`, `error`, or `info`. A tone on the first cell tints the row. This works in Markdown, CSV, TSV, and JSON cells. A span that doesn't fill its cell, or another tone, leaves the cell uncolored and is reported.
28
29
 
29
30
  | Prop | What it does |
30
31
  | --- | --- |
@@ -28,9 +28,9 @@ Press **Ctrl+K** to find the pigeon data.
28
28
 
29
29
  - `::tabs`: each `:::tabs-item` inside is one tab. Content outside every tab doesn't render, and is reported.
30
30
  - `:::tabs-item`: `label` is required and must differ from the other labels in its block, since `sync` matches tabs by label. `icon` draws an Iconify name, such as `lucide:apple`, or an image URL before the label.
31
- - `::code-group`: only code blocks go inside. Name each one's tab in brackets after its language, as in `sh [pnpm]`, with an optional icon after it, as in `sh [pnpm] icon=logos:pnpm`. The tab replaces the block's own title, and comark-code's `title="pnpm"` names no tab.
31
+ - `::code-group`: only code blocks go inside. Name each one's tab in brackets after its language, as in `sh [pnpm]`, with an optional icon after it, as in `sh [pnpm] icon=logos:pnpm`. The tab replaces the block's own title. `title="pnpm"` names no tab, so a block without brackets is reported.
32
32
  - `sync`, on either block, is a key shared by blocks that switch together. Picking a tab picks the tab with the same label in every block with that key, and the next page that uses the key remembers it.
33
- - A code block marked `pm`, as in `sh pm`, holds package manager commands in any manager (npm, npx, pnpm, pnpx, yarn, bun, bunx, or deno) and becomes a code group with a tab each for npm, pnpm, yarn, and bun, synced as `pm`. The manager it's written in keeps its commands as written. It reads install, frozen install (`npm ci`), add with `-D`, `-E`, `-O`, `--save-peer`, or `-g`, remove, update, run, `npx`/`dlx`, create, and init. Only commands at the start of a line or after `&&`, `||`, or `;` change. Inside a `::code-group`, `pm` does nothing.
33
+ - A code block marked `pm`, as in `sh pm`, holds package manager commands in any manager (npm, npx, pnpm, pnpx, yarn, bun, bunx, or deno) and becomes a code group with a tab each for npm, pnpm, yarn, and bun, synced as `pm`. The manager it's written in keeps its commands as written. It reads install, frozen install (`npm ci`), add with `-D`, `-E`, `-O`, `--save-peer`, or `-g`, remove, run, `npx`/`dlx`, create, and init. An update or a `pnpm exec` stays only in its own manager's tab, and the others are left out and reported. Only commands at the start of a line or after `&&`, `||`, or `;` change. Inside a `::code-group`, `pm` does nothing.
34
34
 
35
35
  ## Choose the block
36
36
 
@@ -35,7 +35,7 @@ The block shows:
35
35
 
36
36
  - The counts of `<testcase>` elements. A case with `<skipped>` is skipped, one with `<failure>` or `<error>` failed, and the rest passed. Failed and skipped show only when there are any.
37
37
  - The duration, from the `time` of `<testsuites>`, else the sum of the suites' times, else the cases', written as `250 ms`, `4.2 s`, or `1 min 21 s`. A report without times shows none.
38
- - Each failure as a closed disclosure named `classname › name`, with its `message` and its stack in a code block. Failures print open.
38
+ - Each failure as a closed disclosure named `classname › name`, with its `message` and its stack in a code block. In print, every failure prints open.
39
39
 
40
40
  The root is `<testsuites>` or a single `<testsuite>`. A report with another root renders nothing, and so does malformed XML, which the plugin reports with its line.
41
41