comark-ui 0.7.4 → 0.7.5

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.
package/dist/html.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as criticCss, n as Preset, r as PresetOptions } from "./index-BUDHsvnm.mjs";
1
+ import { a as criticCss, n as Preset, r as PresetOptions } from "./index-Dbqxt4Qg.mjs";
2
2
  import { NodeHandler } from "comark";
3
3
  //#region src/html.d.ts
4
4
  /**
@@ -8,6 +8,7 @@ import { ReadingTimeOptions } from "comark-reading-time";
8
8
  import { XrefOptions } from "comark-xref";
9
9
  import { ComarkPlugin } from "comark";
10
10
  import { BadgeOptions } from "comark-badge";
11
+ import { AnnotateOptions } from "comark-annotate";
11
12
  import { CastOptions } from "comark-cast";
12
13
  import { ChartsOptions } from "comark-charts";
13
14
  import { ChipsOptions } from "comark-chips";
@@ -43,7 +44,7 @@ type PresetOptions = {
43
44
  /** Pastes files into the Markdown before the other plugins read it. Off, since it reads from disk by default. */
44
45
  include?: IncludeOptions | boolean;
45
46
  /** HTML only: Vue, React, and Svelte have no annotate components. */
46
- annotate?: boolean;
47
+ annotate?: AnnotateOptions | boolean;
47
48
  carousel?: boolean;
48
49
  /** Reads no cast files unless you pass `{ root }` or `{ read }`; inline casts render either way. */
49
50
  cast?: CastOptions | boolean;
@@ -122,7 +123,7 @@ type Part<C, O = void> = {
122
123
  };
123
124
  /** One renderer's entry of each package with components, by the option that turns it on. */
124
125
  type Renderer<C> = {
125
- annotate?: Part<C>;
126
+ annotate?: Part<C, AnnotateOptions>;
126
127
  carousel: Part<C>;
127
128
  cast: Part<C, CastOptions>;
128
129
  charts: Part<C, ChartsOptions>;
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { t as typesetCss } from "./typeset-css-DdOGL7WF.mjs";
2
- import { a as criticCss, c as typeset, i as Renderer, n as Preset, o as preset, r as PresetOptions, s as TYPESET_TAG, t as AnyPlugin } from "./index-BUDHsvnm.mjs";
2
+ import { a as criticCss, c as typeset, i as Renderer, n as Preset, o as preset, r as PresetOptions, s as TYPESET_TAG, t as AnyPlugin } from "./index-Dbqxt4Qg.mjs";
3
3
  export { AnyPlugin, Preset, PresetOptions, Renderer, TYPESET_TAG, criticCss, preset, typeset, typesetCss };
package/dist/react.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as criticCss, n as Preset, r as PresetOptions } from "./index-BUDHsvnm.mjs";
1
+ import { a as criticCss, n as Preset, r as PresetOptions } from "./index-Dbqxt4Qg.mjs";
2
2
  import { ComponentType } from "react";
3
3
  //#region src/react.d.ts
4
4
  type AnyComponent = ComponentType<any>;
@@ -64,4 +64,4 @@ vp exec comark-annotate render report.md -o report.html
64
64
  ## Register
65
65
 
66
66
  - In `comark-ui`: on, in `comark-ui/html` only.
67
- - Alone: `pnpm add comark @comark/html comark-annotate`, then `createHtmlRenderer({ plugins: [annotate()], components })` with both from `comark-annotate/html`. It renders only to HTML and takes no options. Each document inlines the styles once, with style attributes for positions, so a strict Content Security Policy needs `style-src 'unsafe-inline'`.
67
+ - Alone: `pnpm add comark @comark/html comark-annotate`, then `createHtmlRenderer({ plugins: [annotate()], components })` with both from `comark-annotate/html`. It renders only to HTML. Screenshots reserve their `viewport`, or dimensions from a data URI. `annotate({ size: true })` also fetches remote screenshots at render time; enable it only for trusted documents, since requests follow redirects and can reach private networks. `annotate({ size: false })` disables measurement while retaining authored viewports. In `comark-ui`, put these options under `annotate`. Each document inlines the styles once, with style attributes for positions, so a strict Content Security Policy needs `style-src 'unsafe-inline'`.
@@ -12,7 +12,7 @@ The spinner now stops once the build finishes:
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. Other props, such as `width` or 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. 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.
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
@@ -25,5 +25,5 @@ The spinner now stops once the build finishes:
25
25
 
26
26
  ## Register
27
27
 
28
- - In `comark-ui`: on. `media: { controls: "native" }` keeps the browser's own controls and leaves the script out.
28
+ - In `comark-ui`: on. `media: { controls: "native" }` keeps the browser's own controls and leaves the script out. Measurement reads only data URIs by default. `media: { size: true }` also measures remote videos while parsing; use it only for trusted documents, since requests follow redirects and can reach private networks. `media: { size: false }` disables measurement. Authored dimensions work with any setting. Alone, pass the same options to `media()`.
29
29
  - Alone: `pnpm add comark @comark/html comark-media`, then `createHtmlRenderer({ plugins: [media()], components })` with both from `comark-media/html`. `comark-media/vue`, `/react`, and `/svelte` render it too. Its place in `plugins` doesn't matter. It reads the tokens before any plugin sees the tree, so comark-zoom never zooms a video and comark-chips never turns an attachment link into a chip. The HTML renderer inlines the players' script once per document, and the browser's own controls show until it runs and whenever a file can't play.
@@ -22,7 +22,8 @@ comarkUi({
22
22
 
23
23
  - Every plugin except `include`, which reads files from disk. `include: { root, base }` turns it on, or `{ read }` in a browser or an edge runtime. `include: true` reads under the working directory.
24
24
  - `cast`, `table`, and `tests` get a reader that finds no file. Inline casts, CSV fences, and pasted JUnit reports render, and a `src` file doesn't load until you pass `{ root }` or `{ read }`. Any other options object replaces that reader too, so the plugin reads under the working directory.
25
- - Three plugins use the network while parsing: `chips` downloads favicons and avatars, `icon` fetches icon sets from the Iconify API, and `diagrams` sends each diagram's source to `https://kroki.io`. In a browser, pass `chips: { download: false }`, since a browser may not download another site's images. To parse offline, also pass `icon: { fetch: false }` with your icon sets in `collections`, and `diagrams: { draw: false }`. To keep diagram sources private, pass your own Kroki `server`.
25
+ - By default, three plugins use the network while parsing: `chips` downloads favicons and avatars, `icon` fetches icon sets from the Iconify API, and `diagrams` sends each diagram's source to `https://kroki.io`. In a browser, pass `chips: { download: false }`, since a browser may not download another site's images. To parse offline, also pass `icon: { fetch: false }` with your icon sets in `collections`, and `diagrams: { draw: false }`. To keep diagram sources private, pass your own Kroki `server`.
26
+ - Media sizing reads only data URIs by default. `zoom: { size: true }` and `media: { size: true }` also fetch remote files while parsing; `annotate: { size: true }` does so at HTML render time. Enable these only for trusted documents, since requests follow redirects and can reach private networks. `{ size: false }` disables measurement for each plugin; authored dimensions and screenshot viewports still work.
26
27
  - `icon`'s options apply to every icon the preset draws, in cards, details, file trees, tabs, and code actions too.
27
28
  - comark-critic has no component to add its styles, so put `criticCss`, which every entry exports, in the page.
28
29
  - The text around the blocks is styled by default, scoped to the element the document renders into, on the same `--comark-*` tokens. Pass `typeset: false` when the site already styles Markdown, such as with Tailwind Typography's `prose`.
@@ -31,5 +31,5 @@ The zoomed view fires `comark-zoom:open`, `comark-zoom:change`, and `comark-zoom
31
31
 
32
32
  ## Register
33
33
 
34
- - In `comark-ui`: on, as `zoom`. `zoom: { images: false }` leaves images alone, so only `::zoom` blocks and elements marked `{data-zoom}` zoom.
34
+ - In `comark-ui`: on, as `zoom`. `zoom: { images: false }` leaves images alone, so only `::zoom` blocks and elements marked `{data-zoom}` zoom. Data URI images get dimensions by default; one authored pixel side gets the other at the file's ratio. Images with both sides or a side such as `50%` keep them. `zoom: { size: true }` also measures remote images while parsing; use it only for trusted documents, since requests follow redirects and can reach private networks. `zoom: { size: false }` disables measurement. Alone, pass the same options to `zoom()`.
35
35
  - Alone: `pnpm add comark @comark/html comark-zoom`, then `createHtmlRenderer({ plugins: [zoom()], components })` with both from `comark-zoom/html`. `comark-zoom/vue`, `/react`, and `/svelte` export the same pair for those renderers. The plugin adds a node that starts the script, so pass the components even when only images zoom. A page with no renderer calls `start()` from `comark-zoom/client` once. comark-annotate and comark-carousel zoom their own blocks without it, so register `zoom()` for images and `::zoom`.
package/dist/skills.mjs CHANGED
@@ -50,7 +50,7 @@ const skills = [
50
50
  },
51
51
  {
52
52
  "path": "references/annotate.md",
53
- "text": "# Screenshots and compares\n\ncomark-annotate draws `::screenshot` and `::compare`. Their marks take the values under Marks in SKILL.md.\n\n## Choose the layout\n\nPick what explains the change best:\n\n- One `::screenshot` with marks, when a single state shows the point.\n- A `::compare` of two screenshots, when the change is the point. Capture both at the same viewport, zoom, scroll, and page state, and set the same `viewport` on both. Each image gets under half the page width, where the text of a full-page capture is too small to read, so clip both captures to the same region around the change, such as Playwright's `screenshot({ clip })`.\n- `::compare{mode=\"slider\"}` instead, when both screenshots show the same spot and the change is small, such as a number or a label at the same place. The reader drags a divider across one full-width image instead of reading two half-width ones. Side notes become numbered notes there, so skip `side`.\n- A side note for the two or three points that matter most. With `mark=\"none\"` and `to` on the exact spot, the arrow alone points and nothing covers the screen, which reads cleanest. Other notes stay numbered in the list under the image. In a side-by-side compare only `top` and `bottom` keep their arrows; left and right notes join the list.\n\nFor a review the reader should follow without a key, write it the way a designer marks up a board: the default ink with no `color`, every note a side note in the margin nearest its point, set off with `at` so its arrow sweeps in, and a `bracket` where a note covers a run of rows. Write the notes of a compare as a pair that argue the change: \"The type gets the headline…\" on the before, \"The message becomes the starting point.\" on the after.\n\nMark the change at its own size: the bar, field, or label that changed. What stayed the same goes unmarked, or in one sentence above the screenshots. Keep it to about six marks per screenshot, fewer in a compare.\n\n## Syntax\n\n```md\n::compare\n:::screenshot{src=\"before.png\" alt=\"Filter toolbar wrapping onto a second row\" viewport=\"1440x900\" href=\"https://pr12.preview.example.com/correlations\"}\n::::annotation{x=3.6 y=20.6 w=92.9 h=31.4 color=\"red\"}\nMoon phase and vibes don't fit, so the toolbar wraps and pushes the table down.\n::::\n:::\n\n:::screenshot{src=\"after.png\" alt=\"Filter toolbar on one row\" viewport=\"1440x900\"}\n::::annotation{x=87.6 y=24.2 w=7.4 h=9.9 mark=\"check\" color=\"green\"}\n**Apply** lines up with the chips.\n::::\n:::\n::\n```\n\n- `::compare`: `title` is optional and names the comparison for screen readers. `mode` is `columns` (default, side by side) or `slider`. `ink` colors every annotation in both screenshots that doesn't set its own `color`. Its two screenshots are titled Before and After unless they set their own.\n- `::screenshot`: `src` and `alt` are required; `title` (the heading above the image), `href` (the captured page, linked by its host), `viewport` (like `1440x900`), and `ink` are optional. Other content becomes the caption.\n- `::annotation`: `x y w h` are required percentages of the image, numbers from 0 to 100 without `%`. `mark` is `box` (default), `circle`, `underline`, `line` (straight through the middle, along the longer side), `highlight`, `bracket`, `cross`, `check`, or `none`, which needs a `side`. `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. `side` is `top`, `bottom`, `left`, or `right`; keep top or bottom notes at least a quarter of the image apart and left or right notes an eighth apart.\n- `at` moves a side note along its margin, as a percentage of the image (across for top and bottom, down for left and right). A note set off from its point reads away from it, so put it on the side with room: a top note at `at=40` pointing left of 40 reads to the right. `to=\"x,y\"` is the point the arrow lands on, measured like the box; without it the arrow meets the middle of the mark's facing edge. Both need a `side`.\n- Annotations must be direct children of a screenshot.\n\n## Measure every mark\n\nTake each mark's coordinates from the page, in the browser you captured. Measure the element and divide by the viewport:\n\n```js\nconst r = document.querySelector(\"SELECTOR\").getBoundingClientRect();\n[(r.x / innerWidth) * 100, (r.y / innerHeight) * 100, (r.width / innerWidth) * 100, (r.height / innerHeight) * 100].map((v) => +v.toFixed(1));\n```\n\nFor a full-page screenshot, add `scrollX`/`scrollY` and divide by `document.documentElement.scrollWidth` and `scrollHeight` instead.\nFor a clipped capture, `getBoundingClientRect()` and Playwright's main-frame `clip` both use viewport-relative coordinates, so the formula takes no scroll offsets. Make sure the clip fully contains every marked element. Subtract the clip's `x` and `y` and divide by its `width` and `height`; if an element crosses the clip edge, intersect its measured rectangle with the clip before normalizing so every value stays between 0 and 100. If the clip is in document coordinates, convert it to viewport coordinates before subtracting.\n\n## Preview\n\nEnsure 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`.\n\n```sh\nvp exec comark-annotate render report.md -o report.html\n```\n\n`render` writes a standalone page of the screenshots and compares, and relative `src` paths resolve next to it. Without comark-linter, `vp exec comark-annotate check report.md` lists these blocks' problems on its own. It names each one like `screenshot \"after.png\", annotation 2`, counting annotations within their screenshot, and exits with 1 while any remain.\n\n## Register\n\n- In `comark-ui`: on, in `comark-ui/html` only.\n- Alone: `pnpm add comark @comark/html comark-annotate`, then `createHtmlRenderer({ plugins: [annotate()], components })` with both from `comark-annotate/html`. It renders only to HTML and takes no options. Each document inlines the styles once, with style attributes for positions, so a strict Content Security Policy needs `style-src 'unsafe-inline'`.\n"
53
+ "text": "# Screenshots and compares\n\ncomark-annotate draws `::screenshot` and `::compare`. Their marks take the values under Marks in SKILL.md.\n\n## Choose the layout\n\nPick what explains the change best:\n\n- One `::screenshot` with marks, when a single state shows the point.\n- A `::compare` of two screenshots, when the change is the point. Capture both at the same viewport, zoom, scroll, and page state, and set the same `viewport` on both. Each image gets under half the page width, where the text of a full-page capture is too small to read, so clip both captures to the same region around the change, such as Playwright's `screenshot({ clip })`.\n- `::compare{mode=\"slider\"}` instead, when both screenshots show the same spot and the change is small, such as a number or a label at the same place. The reader drags a divider across one full-width image instead of reading two half-width ones. Side notes become numbered notes there, so skip `side`.\n- A side note for the two or three points that matter most. With `mark=\"none\"` and `to` on the exact spot, the arrow alone points and nothing covers the screen, which reads cleanest. Other notes stay numbered in the list under the image. In a side-by-side compare only `top` and `bottom` keep their arrows; left and right notes join the list.\n\nFor a review the reader should follow without a key, write it the way a designer marks up a board: the default ink with no `color`, every note a side note in the margin nearest its point, set off with `at` so its arrow sweeps in, and a `bracket` where a note covers a run of rows. Write the notes of a compare as a pair that argue the change: \"The type gets the headline…\" on the before, \"The message becomes the starting point.\" on the after.\n\nMark the change at its own size: the bar, field, or label that changed. What stayed the same goes unmarked, or in one sentence above the screenshots. Keep it to about six marks per screenshot, fewer in a compare.\n\n## Syntax\n\n```md\n::compare\n:::screenshot{src=\"before.png\" alt=\"Filter toolbar wrapping onto a second row\" viewport=\"1440x900\" href=\"https://pr12.preview.example.com/correlations\"}\n::::annotation{x=3.6 y=20.6 w=92.9 h=31.4 color=\"red\"}\nMoon phase and vibes don't fit, so the toolbar wraps and pushes the table down.\n::::\n:::\n\n:::screenshot{src=\"after.png\" alt=\"Filter toolbar on one row\" viewport=\"1440x900\"}\n::::annotation{x=87.6 y=24.2 w=7.4 h=9.9 mark=\"check\" color=\"green\"}\n**Apply** lines up with the chips.\n::::\n:::\n::\n```\n\n- `::compare`: `title` is optional and names the comparison for screen readers. `mode` is `columns` (default, side by side) or `slider`. `ink` colors every annotation in both screenshots that doesn't set its own `color`. Its two screenshots are titled Before and After unless they set their own.\n- `::screenshot`: `src` and `alt` are required; `title` (the heading above the image), `href` (the captured page, linked by its host), `viewport` (like `1440x900`), and `ink` are optional. Other content becomes the caption.\n- `::annotation`: `x y w h` are required percentages of the image, numbers from 0 to 100 without `%`. `mark` is `box` (default), `circle`, `underline`, `line` (straight through the middle, along the longer side), `highlight`, `bracket`, `cross`, `check`, or `none`, which needs a `side`. `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. `side` is `top`, `bottom`, `left`, or `right`; keep top or bottom notes at least a quarter of the image apart and left or right notes an eighth apart.\n- `at` moves a side note along its margin, as a percentage of the image (across for top and bottom, down for left and right). A note set off from its point reads away from it, so put it on the side with room: a top note at `at=40` pointing left of 40 reads to the right. `to=\"x,y\"` is the point the arrow lands on, measured like the box; without it the arrow meets the middle of the mark's facing edge. Both need a `side`.\n- Annotations must be direct children of a screenshot.\n\n## Measure every mark\n\nTake each mark's coordinates from the page, in the browser you captured. Measure the element and divide by the viewport:\n\n```js\nconst r = document.querySelector(\"SELECTOR\").getBoundingClientRect();\n[(r.x / innerWidth) * 100, (r.y / innerHeight) * 100, (r.width / innerWidth) * 100, (r.height / innerHeight) * 100].map((v) => +v.toFixed(1));\n```\n\nFor a full-page screenshot, add `scrollX`/`scrollY` and divide by `document.documentElement.scrollWidth` and `scrollHeight` instead.\nFor a clipped capture, `getBoundingClientRect()` and Playwright's main-frame `clip` both use viewport-relative coordinates, so the formula takes no scroll offsets. Make sure the clip fully contains every marked element. Subtract the clip's `x` and `y` and divide by its `width` and `height`; if an element crosses the clip edge, intersect its measured rectangle with the clip before normalizing so every value stays between 0 and 100. If the clip is in document coordinates, convert it to viewport coordinates before subtracting.\n\n## Preview\n\nEnsure 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`.\n\n```sh\nvp exec comark-annotate render report.md -o report.html\n```\n\n`render` writes a standalone page of the screenshots and compares, and relative `src` paths resolve next to it. Without comark-linter, `vp exec comark-annotate check report.md` lists these blocks' problems on its own. It names each one like `screenshot \"after.png\", annotation 2`, counting annotations within their screenshot, and exits with 1 while any remain.\n\n## Register\n\n- In `comark-ui`: on, in `comark-ui/html` only.\n- Alone: `pnpm add comark @comark/html comark-annotate`, then `createHtmlRenderer({ plugins: [annotate()], components })` with both from `comark-annotate/html`. It renders only to HTML. Screenshots reserve their `viewport`, or dimensions from a data URI. `annotate({ size: true })` also fetches remote screenshots at render time; enable it only for trusted documents, since requests follow redirects and can reach private networks. `annotate({ size: false })` disables measurement while retaining authored viewports. In `comark-ui`, put these options under `annotate`. Each document inlines the styles once, with style attributes for positions, so a strict Content Security Policy needs `style-src 'unsafe-inline'`.\n"
54
54
  },
55
55
  {
56
56
  "path": "references/badge.md",
@@ -178,7 +178,7 @@ const skills = [
178
178
  },
179
179
  {
180
180
  "path": "references/media.md",
181
- "text": "# Videos and audio\n\ncomark-media plays an image that points at a video or a sound file, and a GitHub attachment link alone on its line, with the alt text as the player's label. Use it for a screen recording in PR evidence: a transition, a loading state, or a sound, which a screenshot can't show.\n\n## Syntax\n\n```md\nThe spinner now stops once the build finishes:\n\n![The build spinner stops and the Deploy button turns green](./recordings/build.mp4){loop muted}\n```\n\n- 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.\n- 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.\n- `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. Other props, such as `width` or a class, are dropped and reported.\n- 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.\n\n## Record the evidence\n\n- Record only the part of the screen that changes, for a few seconds.\n- Encode it as H.264 `.mp4` for every browser, or `.webm` for a smaller file. A `.mov` from macOS doesn't always play in Firefox.\n- Say what happens in the alt text, so a reader who can't play the file still learns what it shows.\n- Add `loop muted` to a clip of one motion, so it reads like an animated screenshot once played.\n- A GitHub attachment from a private repository plays only for readers signed in with access to it. For a page that others read, download the file and serve it with the page.\n\n## Register\n\n- In `comark-ui`: on. `media: { controls: \"native\" }` keeps the browser's own controls and leaves the script out.\n- Alone: `pnpm add comark @comark/html comark-media`, then `createHtmlRenderer({ plugins: [media()], components })` with both from `comark-media/html`. `comark-media/vue`, `/react`, and `/svelte` render it too. Its place in `plugins` doesn't matter. It reads the tokens before any plugin sees the tree, so comark-zoom never zooms a video and comark-chips never turns an attachment link into a chip. The HTML renderer inlines the players' script once per document, and the browser's own controls show until it runs and whenever a file can't play.\n"
181
+ "text": "# Videos and audio\n\ncomark-media plays an image that points at a video or a sound file, and a GitHub attachment link alone on its line, with the alt text as the player's label. Use it for a screen recording in PR evidence: a transition, a loading state, or a sound, which a screenshot can't show.\n\n## Syntax\n\n```md\nThe spinner now stops once the build finishes:\n\n![The build spinner stops and the Deploy button turns green](./recordings/build.mp4){loop muted}\n```\n\n- 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.\n- 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.\n- `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.\n- 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.\n\n## Record the evidence\n\n- Record only the part of the screen that changes, for a few seconds.\n- Encode it as H.264 `.mp4` for every browser, or `.webm` for a smaller file. A `.mov` from macOS doesn't always play in Firefox.\n- Say what happens in the alt text, so a reader who can't play the file still learns what it shows.\n- Add `loop muted` to a clip of one motion, so it reads like an animated screenshot once played.\n- A GitHub attachment from a private repository plays only for readers signed in with access to it. For a page that others read, download the file and serve it with the page.\n\n## Register\n\n- In `comark-ui`: on. `media: { controls: \"native\" }` keeps the browser's own controls and leaves the script out. Measurement reads only data URIs by default. `media: { size: true }` also measures remote videos while parsing; use it only for trusted documents, since requests follow redirects and can reach private networks. `media: { size: false }` disables measurement. Authored dimensions work with any setting. Alone, pass the same options to `media()`.\n- Alone: `pnpm add comark @comark/html comark-media`, then `createHtmlRenderer({ plugins: [media()], components })` with both from `comark-media/html`. `comark-media/vue`, `/react`, and `/svelte` render it too. Its place in `plugins` doesn't matter. It reads the tokens before any plugin sees the tree, so comark-zoom never zooms a video and comark-chips never turns an attachment link into a chip. The HTML renderer inlines the players' script once per document, and the browser's own controls show until it runs and whenever a file can't play.\n"
182
182
  },
183
183
  {
184
184
  "path": "references/metrics.md",
@@ -226,7 +226,7 @@ const skills = [
226
226
  },
227
227
  {
228
228
  "path": "references/ui.md",
229
- "text": "# Every plugin in one install\n\ncomark-ui registers every comark-ui package for one renderer, in the order they need, with one icon resolver shared by `:icon`, cards, details, file trees, tabs, and code actions. Install in SKILL.md shows its basic use. This page covers its options, what it turns on, its other renderers, and how the linter uses it.\n\n## Options\n\n`comarkUi(options)` returns `{ plugins, components }`. Each key is a package's name without `comark-`, in camelCase, such as `fileTree`, `codeNotes`, or `readingTime`. `false` turns a plugin off along with its components, and an object turns it on with those options. `true` turns on `include` and leaves the others as they are:\n\n```ts\ncomarkUi({\n zoom: false,\n code: { actions: [{ id: \"run\", label: \"Run\" }] },\n github: { callouts: false, references: { repo: \"owner/name\" } },\n table: { root: \"data\" },\n include: { root: \"content\", base: \"guide\" },\n});\n```\n\n`github` takes its three plugins by name, `callouts`, `references`, and `html`, and `links` takes `external` and `anchors`. Each package's reference lists its own options. The order stays fixed whatever you pass. `include` runs first, so the others read what it pastes, and `code` and `codeNotes` run last, after every plugin that writes code blocks.\n\n## What it turns on\n\n- Every plugin except `include`, which reads files from disk. `include: { root, base }` turns it on, or `{ read }` in a browser or an edge runtime. `include: true` reads under the working directory.\n- `cast`, `table`, and `tests` get a reader that finds no file. Inline casts, CSV fences, and pasted JUnit reports render, and a `src` file doesn't load until you pass `{ root }` or `{ read }`. Any other options object replaces that reader too, so the plugin reads under the working directory.\n- Three plugins use the network while parsing: `chips` downloads favicons and avatars, `icon` fetches icon sets from the Iconify API, and `diagrams` sends each diagram's source to `https://kroki.io`. In a browser, pass `chips: { download: false }`, since a browser may not download another site's images. To parse offline, also pass `icon: { fetch: false }` with your icon sets in `collections`, and `diagrams: { draw: false }`. To keep diagram sources private, pass your own Kroki `server`.\n- `icon`'s options apply to every icon the preset draws, in cards, details, file trees, tabs, and code actions too.\n- comark-critic has no component to add its styles, so put `criticCss`, which every entry exports, in the page.\n- The text around the blocks is styled by default, scoped to the element the document renders into, on the same `--comark-*` tokens. Pass `typeset: false` when the site already styles Markdown, such as with Tailwind Typography's `prose`.\n\n## Renderers\n\n| Renderer | Entry |\n| --- | --- |\n| `@comark/html` | `comark-ui/html` |\n| `@comark/vue` | `comark-ui/vue` |\n| `@comark/react` | `comark-ui/react` |\n| `@comark/svelte` | `comark-ui/svelte` |\n\nThe Vue, React, and Svelte entries leave out annotate, comments, diff, and quiz, which render only to HTML. Screenshots, compares, diffs, suggestions and comments, and the marks on charts need `comark-ui/html`.\n\nTo use another renderer, install it in place of `@comark/html`, such as `pnpm add comark @comark/vue comark-ui`, and pass it `plugins` and `components` as you would one package's. The preset needs Vue 3.5, React 18, or Svelte 5.20 or later. Every entry exports the `PresetOptions` type, and `comark-ui` itself exports `preset(renderer, options)`, which builds the same pair from renderer entries you pass.\n\n## In the linter\n\ncomark-linter imports `comark-ui/html` when the project has it, and lints with all its plugins and components, ahead of any comark package installed on its own, so none runs twice. It calls `comarkUi()` with options of its own, so the app's options don't reach it:\n\n- It draws no chart or diagram, and downloads no chip image.\n- `::cast`, `::table`, and `::tests` read their `src` files from the working directory.\n- `include` stays off until a lint config adds it, as [include](include.md) says.\n\n## Register\n\n- In `comark-ui`: this is the preset itself, registered as Install in SKILL.md shows.\n- Alone: each plugin is its own package, registered as its reference says. The preset ships in lockstep with them, so `comark-ui@X` holds every plugin at version `X`.\n"
229
+ "text": "# Every plugin in one install\n\ncomark-ui registers every comark-ui package for one renderer, in the order they need, with one icon resolver shared by `:icon`, cards, details, file trees, tabs, and code actions. Install in SKILL.md shows its basic use. This page covers its options, what it turns on, its other renderers, and how the linter uses it.\n\n## Options\n\n`comarkUi(options)` returns `{ plugins, components }`. Each key is a package's name without `comark-`, in camelCase, such as `fileTree`, `codeNotes`, or `readingTime`. `false` turns a plugin off along with its components, and an object turns it on with those options. `true` turns on `include` and leaves the others as they are:\n\n```ts\ncomarkUi({\n zoom: false,\n code: { actions: [{ id: \"run\", label: \"Run\" }] },\n github: { callouts: false, references: { repo: \"owner/name\" } },\n table: { root: \"data\" },\n include: { root: \"content\", base: \"guide\" },\n});\n```\n\n`github` takes its three plugins by name, `callouts`, `references`, and `html`, and `links` takes `external` and `anchors`. Each package's reference lists its own options. The order stays fixed whatever you pass. `include` runs first, so the others read what it pastes, and `code` and `codeNotes` run last, after every plugin that writes code blocks.\n\n## What it turns on\n\n- Every plugin except `include`, which reads files from disk. `include: { root, base }` turns it on, or `{ read }` in a browser or an edge runtime. `include: true` reads under the working directory.\n- `cast`, `table`, and `tests` get a reader that finds no file. Inline casts, CSV fences, and pasted JUnit reports render, and a `src` file doesn't load until you pass `{ root }` or `{ read }`. Any other options object replaces that reader too, so the plugin reads under the working directory.\n- By default, three plugins use the network while parsing: `chips` downloads favicons and avatars, `icon` fetches icon sets from the Iconify API, and `diagrams` sends each diagram's source to `https://kroki.io`. In a browser, pass `chips: { download: false }`, since a browser may not download another site's images. To parse offline, also pass `icon: { fetch: false }` with your icon sets in `collections`, and `diagrams: { draw: false }`. To keep diagram sources private, pass your own Kroki `server`.\n- Media sizing reads only data URIs by default. `zoom: { size: true }` and `media: { size: true }` also fetch remote files while parsing; `annotate: { size: true }` does so at HTML render time. Enable these only for trusted documents, since requests follow redirects and can reach private networks. `{ size: false }` disables measurement for each plugin; authored dimensions and screenshot viewports still work.\n- `icon`'s options apply to every icon the preset draws, in cards, details, file trees, tabs, and code actions too.\n- comark-critic has no component to add its styles, so put `criticCss`, which every entry exports, in the page.\n- The text around the blocks is styled by default, scoped to the element the document renders into, on the same `--comark-*` tokens. Pass `typeset: false` when the site already styles Markdown, such as with Tailwind Typography's `prose`.\n\n## Renderers\n\n| Renderer | Entry |\n| --- | --- |\n| `@comark/html` | `comark-ui/html` |\n| `@comark/vue` | `comark-ui/vue` |\n| `@comark/react` | `comark-ui/react` |\n| `@comark/svelte` | `comark-ui/svelte` |\n\nThe Vue, React, and Svelte entries leave out annotate, comments, diff, and quiz, which render only to HTML. Screenshots, compares, diffs, suggestions and comments, and the marks on charts need `comark-ui/html`.\n\nTo use another renderer, install it in place of `@comark/html`, such as `pnpm add comark @comark/vue comark-ui`, and pass it `plugins` and `components` as you would one package's. The preset needs Vue 3.5, React 18, or Svelte 5.20 or later. Every entry exports the `PresetOptions` type, and `comark-ui` itself exports `preset(renderer, options)`, which builds the same pair from renderer entries you pass.\n\n## In the linter\n\ncomark-linter imports `comark-ui/html` when the project has it, and lints with all its plugins and components, ahead of any comark package installed on its own, so none runs twice. It calls `comarkUi()` with options of its own, so the app's options don't reach it:\n\n- It draws no chart or diagram, and downloads no chip image.\n- `::cast`, `::table`, and `::tests` read their `src` files from the working directory.\n- `include` stays off until a lint config adds it, as [include](include.md) says.\n\n## Register\n\n- In `comark-ui`: this is the preset itself, registered as Install in SKILL.md shows.\n- Alone: each plugin is its own package, registered as its reference says. The preset ships in lockstep with them, so `comark-ui@X` holds every plugin at version `X`.\n"
230
230
  },
231
231
  {
232
232
  "path": "references/xref.md",
@@ -234,7 +234,7 @@ const skills = [
234
234
  },
235
235
  {
236
236
  "path": "references/zoom.md",
237
- "text": "# Zoom\n\ncomark-zoom lets the reader click an image or a `::zoom` block to see it large, and closes it with Escape, Back, or a click around it. Images zoom with no markup. Wrap a table, code block, or diagram in `::zoom` when it's too small to read in place.\n\n## Syntax\n\n```md\n::zoom{title=\"Deploy retry policy\"}\n| Attempt | Wait before it |\n| --- | --- |\n| 1 | 1 s |\n| 2 | 4 s |\n| 3 | 16 s |\n::\n```\n\n- `::zoom` zooms everything inside it as one item. `title` heads the zoomed view. Items with the same `group` page through one zoomed view, with a strip of them below. `#id` and `.class` go on the block.\n- Every content image zooms on its own, with its alt text as the zoomed view's heading. It grows no larger than its file, so give a small image a larger file to open with `{data-zoom-src=\"dashboard@2x.png\"}`.\n- An image inside a link keeps its link and doesn't zoom. Images inside `::zoom`, `::carousel`, `::screenshot`, or `::compare` zoom with their block.\n- `{zoom=false}` keeps an image from zooming, and `{data-zoom}` makes any element zoom on its own.\n\ncomark-zoom reports no problems, so a misspelled prop such as `titel` is dropped silently and passes the linter. Spell `title` and `group` as written here.\n\n## Group or carousel\n\nA `group` leaves each item in its place in the text and pages through them only once one is zoomed. Use it for screenshots that sit apart, each next to the paragraph about it. A `::carousel` puts the items in one place with arrows instead. An item hidden when the view opens, such as one in a closed tab, stays out of its group.\n\n## In the page\n\nThe zoomed view fires `comark-zoom:open`, `comark-zoom:change`, and `comark-zoom:close` on the item, and they bubble. The `detail` of `open` and `change` holds the dialog's `header` and `footer`, a `layer` over the zoomed content where a host draws its own pins, and `copyOf(element)` and `originalOf(element)` to map between the page and the zoomed copy. `data-zoom-aside`, a selector, shows a caption beside the zoomed item at its own size, as annotate does with a screenshot's notes.\n\n## Register\n\n- In `comark-ui`: on, as `zoom`. `zoom: { images: false }` leaves images alone, so only `::zoom` blocks and elements marked `{data-zoom}` zoom.\n- Alone: `pnpm add comark @comark/html comark-zoom`, then `createHtmlRenderer({ plugins: [zoom()], components })` with both from `comark-zoom/html`. `comark-zoom/vue`, `/react`, and `/svelte` export the same pair for those renderers. The plugin adds a node that starts the script, so pass the components even when only images zoom. A page with no renderer calls `start()` from `comark-zoom/client` once. comark-annotate and comark-carousel zoom their own blocks without it, so register `zoom()` for images and `::zoom`.\n"
237
+ "text": "# Zoom\n\ncomark-zoom lets the reader click an image or a `::zoom` block to see it large, and closes it with Escape, Back, or a click around it. Images zoom with no markup. Wrap a table, code block, or diagram in `::zoom` when it's too small to read in place.\n\n## Syntax\n\n```md\n::zoom{title=\"Deploy retry policy\"}\n| Attempt | Wait before it |\n| --- | --- |\n| 1 | 1 s |\n| 2 | 4 s |\n| 3 | 16 s |\n::\n```\n\n- `::zoom` zooms everything inside it as one item. `title` heads the zoomed view. Items with the same `group` page through one zoomed view, with a strip of them below. `#id` and `.class` go on the block.\n- Every content image zooms on its own, with its alt text as the zoomed view's heading. It grows no larger than its file, so give a small image a larger file to open with `{data-zoom-src=\"dashboard@2x.png\"}`.\n- An image inside a link keeps its link and doesn't zoom. Images inside `::zoom`, `::carousel`, `::screenshot`, or `::compare` zoom with their block.\n- `{zoom=false}` keeps an image from zooming, and `{data-zoom}` makes any element zoom on its own.\n\ncomark-zoom reports no problems, so a misspelled prop such as `titel` is dropped silently and passes the linter. Spell `title` and `group` as written here.\n\n## Group or carousel\n\nA `group` leaves each item in its place in the text and pages through them only once one is zoomed. Use it for screenshots that sit apart, each next to the paragraph about it. A `::carousel` puts the items in one place with arrows instead. An item hidden when the view opens, such as one in a closed tab, stays out of its group.\n\n## In the page\n\nThe zoomed view fires `comark-zoom:open`, `comark-zoom:change`, and `comark-zoom:close` on the item, and they bubble. The `detail` of `open` and `change` holds the dialog's `header` and `footer`, a `layer` over the zoomed content where a host draws its own pins, and `copyOf(element)` and `originalOf(element)` to map between the page and the zoomed copy. `data-zoom-aside`, a selector, shows a caption beside the zoomed item at its own size, as annotate does with a screenshot's notes.\n\n## Register\n\n- In `comark-ui`: on, as `zoom`. `zoom: { images: false }` leaves images alone, so only `::zoom` blocks and elements marked `{data-zoom}` zoom. Data URI images get dimensions by default; one authored pixel side gets the other at the file's ratio. Images with both sides or a side such as `50%` keep them. `zoom: { size: true }` also measures remote images while parsing; use it only for trusted documents, since requests follow redirects and can reach private networks. `zoom: { size: false }` disables measurement. Alone, pass the same options to `zoom()`.\n- Alone: `pnpm add comark @comark/html comark-zoom`, then `createHtmlRenderer({ plugins: [zoom()], components })` with both from `comark-zoom/html`. `comark-zoom/vue`, `/react`, and `/svelte` export the same pair for those renderers. The plugin adds a node that starts the script, so pass the components even when only images zoom. A page with no renderer calls `start()` from `comark-zoom/client` once. comark-annotate and comark-carousel zoom their own blocks without it, so register `zoom()` for images and `::zoom`.\n"
238
238
  }
239
239
  ]
240
240
  },
@@ -321,6 +321,6 @@ const skills = [
321
321
  }
322
322
  ];
323
323
  /** The comark-ui version the skills come from, for a host's cache key or a digest. */
324
- const version = "0.7.4";
324
+ const version = "0.7.5";
325
325
  //#endregion
326
326
  export { skills, version };
package/dist/vue.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as criticCss, n as Preset, r as PresetOptions } from "./index-BUDHsvnm.mjs";
1
+ import { a as criticCss, n as Preset, r as PresetOptions } from "./index-Dbqxt4Qg.mjs";
2
2
  import { Component } from "vue";
3
3
  //#region src/vue.d.ts
4
4
  /** Every plugin with components for `@comark/vue`, which leaves out annotate, comments, diff, and quiz. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comark-ui",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "Every comark-ui block in one install: annotated screenshots, charts, diffs, tabs, zoom, and more, registered in the order they need with shared icons. Turn any of them off or pass its options.",
5
5
  "keywords": [
6
6
  "comark",
@@ -48,50 +48,50 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "comark-pele": "^1.1.0",
51
- "comark-annotate": "^0.7.4",
52
- "comark-cards": "^0.7.4",
53
- "comark-carousel": "^0.7.4",
54
- "comark-badge": "^0.7.4",
55
- "comark-cast": "^0.7.4",
56
- "comark-charts": "^0.7.4",
57
- "comark-chips": "^0.7.4",
58
- "comark-cjk": "^0.7.4",
59
- "comark-code": "^0.7.4",
60
- "comark-colors": "^0.7.4",
61
- "comark-code-notes": "^0.7.4",
62
- "comark-deflist": "^0.7.4",
63
- "comark-critic": "^0.7.4",
64
- "comark-details": "^0.7.4",
65
- "comark-comments": "^0.7.4",
66
- "comark-diagrams": "^0.7.4",
67
- "comark-embed": "^0.7.4",
68
- "comark-fields": "^0.7.4",
69
- "comark-figure": "^0.7.4",
70
- "comark-diff": "^0.7.4",
71
- "comark-file-tree": "^0.7.4",
72
- "comark-footnotes": "^0.7.4",
73
- "comark-github": "^0.7.4",
74
- "comark-keys": "^0.7.4",
75
- "comark-include": "^0.7.4",
76
- "comark-icon": "^0.7.4",
77
- "comark-mathml": "^0.7.4",
78
- "comark-mark": "^0.7.4",
79
- "comark-magic-move": "^0.7.4",
80
- "comark-links": "^0.7.4",
81
- "comark-media": "^0.7.4",
82
- "comark-metrics": "^0.7.4",
83
- "comark-outline": "^0.7.4",
84
- "comark-properties": "^0.7.4",
85
- "comark-sources": "^0.7.4",
86
- "comark-quiz": "^0.7.4",
87
- "comark-qr": "^0.7.4",
88
- "comark-table": "^0.7.4",
89
- "comark-steps": "^0.7.4",
90
- "comark-reading-time": "^0.7.4",
91
- "comark-tabs": "^0.7.4",
92
- "comark-xref": "^0.7.4",
93
- "comark-tests": "^0.7.4",
94
- "comark-zoom": "^0.7.4"
51
+ "comark-annotate": "^0.7.5",
52
+ "comark-badge": "^0.7.5",
53
+ "comark-cards": "^0.7.5",
54
+ "comark-cast": "^0.7.5",
55
+ "comark-carousel": "^0.7.5",
56
+ "comark-charts": "^0.7.5",
57
+ "comark-chips": "^0.7.5",
58
+ "comark-cjk": "^0.7.5",
59
+ "comark-code": "^0.7.5",
60
+ "comark-colors": "^0.7.5",
61
+ "comark-comments": "^0.7.5",
62
+ "comark-code-notes": "^0.7.5",
63
+ "comark-critic": "^0.7.5",
64
+ "comark-details": "^0.7.5",
65
+ "comark-deflist": "^0.7.5",
66
+ "comark-diagrams": "^0.7.5",
67
+ "comark-diff": "^0.7.5",
68
+ "comark-embed": "^0.7.5",
69
+ "comark-figure": "^0.7.5",
70
+ "comark-file-tree": "^0.7.5",
71
+ "comark-fields": "^0.7.5",
72
+ "comark-footnotes": "^0.7.5",
73
+ "comark-github": "^0.7.5",
74
+ "comark-icon": "^0.7.5",
75
+ "comark-include": "^0.7.5",
76
+ "comark-keys": "^0.7.5",
77
+ "comark-links": "^0.7.5",
78
+ "comark-magic-move": "^0.7.5",
79
+ "comark-mark": "^0.7.5",
80
+ "comark-metrics": "^0.7.5",
81
+ "comark-properties": "^0.7.5",
82
+ "comark-mathml": "^0.7.5",
83
+ "comark-qr": "^0.7.5",
84
+ "comark-quiz": "^0.7.5",
85
+ "comark-outline": "^0.7.5",
86
+ "comark-sources": "^0.7.5",
87
+ "comark-media": "^0.7.5",
88
+ "comark-reading-time": "^0.7.5",
89
+ "comark-table": "^0.7.5",
90
+ "comark-steps": "^0.7.5",
91
+ "comark-tabs": "^0.7.5",
92
+ "comark-xref": "^0.7.5",
93
+ "comark-tests": "^0.7.5",
94
+ "comark-zoom": "^0.7.5"
95
95
  },
96
96
  "devDependencies": {
97
97
  "@comark/html": "^0.8.1",