comark-ui 0.0.0 → 0.7.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 (76) hide show
  1. package/LICENSE +69 -0
  2. package/README.md +69 -1
  3. package/dist/client.d.mts +12 -0
  4. package/dist/client.mjs +26 -0
  5. package/dist/editor-BAdok66p.mjs +835 -0
  6. package/dist/editor-CNivEuMH.d.mts +131 -0
  7. package/dist/editor-vue.d.mts +57 -0
  8. package/dist/editor-vue.mjs +85 -0
  9. package/dist/editor.d.mts +2 -0
  10. package/dist/editor.mjs +1 -0
  11. package/dist/html.d.mts +7 -0
  12. package/dist/html.mjs +90 -0
  13. package/dist/index-B0YvApci.d.mts +173 -0
  14. package/dist/index.d.mts +3 -0
  15. package/dist/index.mjs +3 -0
  16. package/dist/nuxt-ui.d.mts +17 -0
  17. package/dist/nuxt-ui.mjs +488 -0
  18. package/dist/react.d.mts +8 -0
  19. package/dist/react.mjs +83 -0
  20. package/dist/skills/comark-ui/SKILL.md +138 -0
  21. package/dist/skills/comark-ui/agents/openai.yaml +3 -0
  22. package/dist/skills/comark-ui/references/annotate.md +65 -0
  23. package/dist/skills/comark-ui/references/badge.md +52 -0
  24. package/dist/skills/comark-ui/references/cards.md +57 -0
  25. package/dist/skills/comark-ui/references/carousel.md +31 -0
  26. package/dist/skills/comark-ui/references/cast.md +48 -0
  27. package/dist/skills/comark-ui/references/charts.md +80 -0
  28. package/dist/skills/comark-ui/references/chat.md +25 -0
  29. package/dist/skills/comark-ui/references/chips.md +33 -0
  30. package/dist/skills/comark-ui/references/cjk.md +23 -0
  31. package/dist/skills/comark-ui/references/code-notes.md +34 -0
  32. package/dist/skills/comark-ui/references/code.md +84 -0
  33. package/dist/skills/comark-ui/references/colors.md +33 -0
  34. package/dist/skills/comark-ui/references/critic.md +30 -0
  35. package/dist/skills/comark-ui/references/deflist.md +38 -0
  36. package/dist/skills/comark-ui/references/details.md +49 -0
  37. package/dist/skills/comark-ui/references/diagrams.md +45 -0
  38. package/dist/skills/comark-ui/references/diff.md +43 -0
  39. package/dist/skills/comark-ui/references/embed.md +40 -0
  40. package/dist/skills/comark-ui/references/fields.md +48 -0
  41. package/dist/skills/comark-ui/references/figure.md +25 -0
  42. package/dist/skills/comark-ui/references/file-tree.md +42 -0
  43. package/dist/skills/comark-ui/references/footnotes.md +26 -0
  44. package/dist/skills/comark-ui/references/github.md +44 -0
  45. package/dist/skills/comark-ui/references/icon.md +28 -0
  46. package/dist/skills/comark-ui/references/include.md +44 -0
  47. package/dist/skills/comark-ui/references/keys.md +28 -0
  48. package/dist/skills/comark-ui/references/links.md +43 -0
  49. package/dist/skills/comark-ui/references/lint.md +96 -0
  50. package/dist/skills/comark-ui/references/magic-move.md +34 -0
  51. package/dist/skills/comark-ui/references/mark.md +22 -0
  52. package/dist/skills/comark-ui/references/math.md +25 -0
  53. package/dist/skills/comark-ui/references/media.md +29 -0
  54. package/dist/skills/comark-ui/references/metrics.md +34 -0
  55. package/dist/skills/comark-ui/references/outline.md +36 -0
  56. package/dist/skills/comark-ui/references/properties.md +32 -0
  57. package/dist/skills/comark-ui/references/qr.md +20 -0
  58. package/dist/skills/comark-ui/references/quiz.md +45 -0
  59. package/dist/skills/comark-ui/references/reading-time.md +32 -0
  60. package/dist/skills/comark-ui/references/sources.md +24 -0
  61. package/dist/skills/comark-ui/references/steps.md +34 -0
  62. package/dist/skills/comark-ui/references/table.md +48 -0
  63. package/dist/skills/comark-ui/references/tabs.md +46 -0
  64. package/dist/skills/comark-ui/references/tests.md +59 -0
  65. package/dist/skills/comark-ui/references/ui.md +54 -0
  66. package/dist/skills/comark-ui/references/xref.md +48 -0
  67. package/dist/skills/comark-ui/references/zoom.md +35 -0
  68. package/dist/src-DROB05U6.mjs +119 -0
  69. package/dist/svelte/Typeset.svelte +7 -0
  70. package/dist/svelte/index.d.ts +9 -0
  71. package/dist/svelte/index.js +84 -0
  72. package/dist/typeset-css-DPB0S1bV.mjs +202 -0
  73. package/dist/typeset-css-DdOGL7WF.d.mts +10 -0
  74. package/dist/vue.d.mts +7 -0
  75. package/dist/vue.mjs +86 -0
  76. package/package.json +170 -4
@@ -0,0 +1,84 @@
1
+ # Code blocks
2
+
3
+ comark-code puts Copy and Wrap on every code block. It also reads options after a fence's language, written the way Expressive Code writes them. They mark lines as added, deleted, or worth a look, fold lines away, number them, and frame shell sessions as a terminal. Use the markers to point at the lines your text talks about, such as the fix in a pull request.
4
+
5
+ ## Syntax
6
+
7
+ ````md
8
+ ```ts title="src/zoom.ts" del={3} ins={4} mark={1}
9
+ function close() {
10
+ dialog.close();
11
+ history.back();
12
+ if (opened) history.back();
13
+ }
14
+ ```
15
+ ````
16
+
17
+ | Option | What it does |
18
+ | --- | --- |
19
+ | `ins={4}` | Marks lines as added, in green with a `+`. |
20
+ | `del={3}` | Marks lines as deleted, in red with a `−`. Copy leaves them out, so the block copies as the code after the change. |
21
+ | `mark={1}` | Highlights lines to look at, like Comark's own `{1}`. |
22
+ | `collapse={2-7}` | Folds lines behind a row that counts them. A click opens them. |
23
+ | `showLineNumbers` | Numbers the lines. |
24
+ | `startLineNumber=120` | Numbers the lines from 120, and turns numbers on. |
25
+ | `title="src/zoom.ts"` | Titles the block, like Comark's `[src/zoom.ts]`. A block without one shows its language. |
26
+ | `frame="terminal"` | Draws a terminal window. `frame="code"` or `frame="none"` draws a plain block. |
27
+ | `wrap` | Starts the block with Wrap on. |
28
+
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
+
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.
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.
34
+
35
+ ## Show a change
36
+
37
+ - Mark a change of a few lines with `ins` and `del` on the code you write out.
38
+ - Paste `git diff` output into a `diff` fence with `lang`, as below. The code highlights as that language, each leading `+` or `-` becomes `ins` or `del`, and the `@@` hunk headers and the file headers above them go away. Without `lang`, the fence stays a plain diff.
39
+ - For a suggested change, the way a pull request review shows one, write comark-diff's `::diff` with the code before and after.
40
+ - `mark` the lines your text names, and `collapse` the imports and setup the reader can skip.
41
+
42
+ ````md
43
+ ```diff lang="ts"
44
+ @@ -12,4 +12,4 @@ export function close() {
45
+ function close() {
46
+ dialog.close();
47
+ - history.back();
48
+ + if (opened) history.back();
49
+ }
50
+ ```
51
+ ````
52
+
53
+ A range that lands on the wrong line inside the block isn't reported, so count the lines before you mark them.
54
+
55
+ ## Add buttons
56
+
57
+ `code({ actions })` adds the host's own buttons before Wrap and Copy, on the blocks in each action's `languages`, or on every block when it lists none. A button shows a `label`, an `icon`, or both. The icon is an Iconify name, such as `lucide:play`, or an image URL, and an icon-only button needs a `title` for its tooltip and screen readers.
58
+
59
+ ```ts
60
+ code({ actions: [{ id: "run", label: "Run", icon: "lucide:play", languages: ["sh", "bash"] }] });
61
+ ```
62
+
63
+ The page decides what a click does. `onCodeAction()` from `comark-code/client` calls your function with the block's code and language, and returns a function that stops listening:
64
+
65
+ ```ts
66
+ import { onCodeAction } from "comark-code/client";
67
+
68
+ const stop = onCodeAction("run", ({ code, language }) => terminal.run(code));
69
+ ```
70
+
71
+ A click sends a bubbling `comark-code-action` event with `{ action, code, language }` as its `detail`, so one listener on the page can handle every action. Icons resolve while parsing, through the `iconResolver` option, a `createIcons()` from comark-icon, or from the Iconify API without one. An icon that can't be drawn is reported, and its button shows its title instead.
72
+
73
+ ## Register
74
+
75
+ - In `comark-ui`: on, as `code`. Pass `code: { actions }` for buttons of your own, and the preset's `icon` options resolve their icons. The preset leaves Shiki out. To add it, put it right before comark-code, which keeps it after comark-tabs:
76
+
77
+ ```ts
78
+ import shiki from "comark/plugins/shiki";
79
+
80
+ const { plugins, components } = comarkUi();
81
+ plugins.splice(plugins.findIndex((plugin) => plugin.name === "comark-code"), 0, shiki());
82
+ ```
83
+
84
+ - Alone: `pnpm add comark @comark/html comark-code`, then `createHtmlRenderer({ plugins: [code()], components })` with both from `comark-code/html`. `comark-code/vue`, `/react`, and `/svelte` (Svelte 5.20 or later) export the same pair for those renderers. With Shiki, list `shiki()` before `code()`. Shiki redraws every block, so comark-code listed first loses its markers, numbers, and folds, and reports it. Without Shiki, comark-code splits the lines itself.
@@ -0,0 +1,33 @@
1
+ # Color swatches
2
+
3
+ comark-colors puts a swatch before inline code that holds one color, and draws a `::palette` of named colors as a grid of tiles. Use it when a change touches colors, such as design tokens or a theme, so the reviewer sees each value.
4
+
5
+ ## Syntax
6
+
7
+ ```md
8
+ | Token | Before | After |
9
+ | --- | --- | --- |
10
+ | `--primary` | `#3b82f6` | `oklch(0.55 0.2 264)` |
11
+ | `--ring` | `#93c5fd` | `oklch(0.7 0.12 260)` |
12
+
13
+ ::palette
14
+ - Background: `#fafaf9`
15
+ - Foreground: `#1c1917`
16
+ - Primary: `oklch(0.55 0.2 264)`
17
+ - Overlay: `rgb(0 0 0 / 40%)`
18
+ ::
19
+ ```
20
+
21
+ - Inline code that holds one color and nothing else gets a swatch, in text, a table, or a list. A translucent color sits on a checkerboard.
22
+ - It reads hex colors of 3, 4, 6, or 8 digits and the CSS functions `rgb()`, `rgba()`, `hsl()`, `hsla()`, `hwb()`, `lab()`, `lch()`, `oklab()`, and `oklch()`, alpha included.
23
+ - `::palette` holds a list, bulleted or numbered, of `name: color` lines, with the color in inline code or not. Each line becomes a tile with its name and value. It takes no props.
24
+ - `meta.issues` reports a palette with no list, a line with no name or color, a color it can't draw, and content beside the list. The palette leaves out that line and drops that content.
25
+
26
+ ## Show a color change
27
+
28
+ Put the old and new values side by side in a table, one token per row, as above, and give each theme its own `::palette` to show the whole set. Write each color as hex or one of the functions above, alone in its code span. In inline code, anything else stays plain code and nothing reports it: a named color such as `red`, `var(--primary)`, `color-mix()`, or a span with more in it, such as `` `color: #fff` ``. Code blocks never get swatches.
29
+
30
+ ## Register
31
+
32
+ - In `comark-ui`: on. It takes no options.
33
+ - Alone: `pnpm add comark @comark/html comark-colors`, then `createHtmlRenderer({ plugins: [colors()], components })` with both from `comark-colors/html`. `comark-colors/vue`, `/react`, and `/svelte` render it too. Every entry exports `isColor(value)`, the test the plugin runs on inline code.
@@ -0,0 +1,30 @@
1
+ # Suggested edits
2
+
3
+ comark-critic reads CriticMarkup: insertions, deletions, substitutions, highlights, and comments written inside the text. Use it to review prose in place, such as a docs page or a changelog, where the reader should see each change in its sentence. For a change to code, write a `::diff` instead.
4
+
5
+ ## Syntax
6
+
7
+ ```md
8
+ The deploy waits when more than {--twelve--}{++fifteen++} pigeons sit on the roof.
9
+
10
+ Count them {~~after~>before~~} the stand-up, from the {==east window==}{>>The west one faces the parking lot.<<}.
11
+ ```
12
+
13
+ | Mark | Write | Shows as |
14
+ | --- | --- | --- |
15
+ | Insertion | `{++added++}` | `<ins>`, tinted green |
16
+ | Deletion | `{--removed--}` | `<del>`, struck through in red |
17
+ | Substitution | `{~~old~>new~~}` | the deletion, then the insertion |
18
+ | Highlight | `{==this==}` | `<mark>`, in amber |
19
+ | Comment | `{>>why<<}` | a muted chip where it sits |
20
+
21
+ - Put a comment right after the words it's about. After a highlight, it comments on the highlighted words, as above.
22
+ - Text inside a mark is Markdown, so it can hold `**bold**`, code, and links. A `{.class}` right after a mark adds that class beside the mark's own.
23
+ - Each mark opens and closes in one paragraph, so mark an edit that spans paragraphs once in each. A mark left open, or a substitution without `~>`, stays as written, and the linter reports it.
24
+ - A mark inside a code span stays as written. Write `\{++` to show the characters themselves.
25
+ - Leave the spaces around a deleted word as they are. `a {--big--} duck` accepts as `a duck`, and HTML shows the two spaces as one.
26
+
27
+ ## Register
28
+
29
+ - In `comark-ui`: on by default, in `view` mode, which shows every mark. `critic: { mode: "accept" }` renders the text with the changes made, and `mode: "reject"` renders it without them. Both drop the comments and show highlights as plain text. The plugin reports any other `mode` and shows the changes. To publish a reviewed draft, keep the marks in the source and parse it a second time in `accept` mode. No component adds the styles, so put `criticCss`, exported by every entry, in the page. Without it, the browser underlines `<ins>`, strikes `<del>`, paints `<mark>` yellow, and shows comments as plain text. `--ccm-ins`, `--ccm-del`, and `--ccm-mark` recolor the marks.
30
+ - Alone: `pnpm add comark comark-critic`, then `plugins: [critic()]` with `import critic from "comark-critic"`, and the same `mode` option. Load the styles with `import "comark-critic/style.css"`, or inline the `css` export. It has no components, so it works in any renderer and in streaming parses.
@@ -0,0 +1,38 @@
1
+ # Definition lists
2
+
3
+ comark-deflist renders a term followed by `: definition` lines as a native `<dl>`, `<dt>`, and `<dd>`. Use it for a glossary, or for options whose descriptions run past a line.
4
+
5
+ ## Syntax
6
+
7
+ ````md
8
+ Flaky test
9
+ : A test that passes and fails on the same code.
10
+
11
+ Rubber duck
12
+ : A listener who doesn't need to understand the bug.
13
+ : A bath toy.
14
+
15
+ Deploy freeze
16
+ : No deploys from Friday noon to Monday.
17
+
18
+ Hotfixes still ship, with two approvals:
19
+
20
+ ```sh
21
+ deploy --hotfix --approvers 2
22
+ ```
23
+ ````
24
+
25
+ - A term is one line of inline Markdown. Its definition starts on the next line, or after one blank line, with `:` or `~` and a space.
26
+ - Give a term several definitions with one marker line each. Leave a blank line before the next term, since a line right after a definition continues that definition.
27
+ - Indent lines past the marker to continue a definition with more paragraphs, a list, or code, with a blank line between its blocks. Start the definition with `:` and three spaces and indent the rest by four, so every block starts in the same column.
28
+ - A definition of one paragraph renders its text straight inside `<dd>`, and one of several blocks keeps a `<p>` for each.
29
+ - Write the space after the marker. Without it, the line joins the term's paragraph. `:3 to 1` stays text, and `:No deploys` becomes an empty inline component that drops the word `No`. The linter reports such a component only when its name isn't also an HTML tag, so it misses `:A test`.
30
+
31
+ ## Choose a list or a table
32
+
33
+ Use a definition list when a definition runs past a line or holds more than a paragraph, since a table cell holds neither a list nor code. For short values side by side, such as options and their defaults, a table scans faster.
34
+
35
+ ## Register
36
+
37
+ - In `comark-ui`: on by default. `deflist: false` turns it off; it takes no options.
38
+ - Alone: `pnpm add comark comark-deflist`, then `plugins: [deflist()]` with `import deflist from "comark-deflist"`. It has no components, classes, or styles, so every renderer draws `dl`, `dt`, and `dd` as they are, and the page's own CSS styles them. It works inside any `::component` and in streaming parses.
@@ -0,0 +1,49 @@
1
+ # Folded sections
2
+
3
+ comark-details folds content behind a summary: `::details` for one block, `::accordion` for a run of questions, and `::collapsible` for optional content. Each one renders as a native `<details>` with a real `<summary>`, so it opens with no script, the browser's search finds the text inside, and it prints.
4
+
5
+ ## Syntax
6
+
7
+ ````md
8
+ ::details{summary="Full build log"}
9
+ ```txt
10
+ vite v7.1.4 building for production...
11
+ ✓ 412 modules transformed.
12
+ dist/index.html 0.46 kB
13
+ ```
14
+ ::
15
+
16
+ ::accordion{type="single" :defaultValue='["0"]'}
17
+ :::accordion-item{label="Is it free?" icon="lucide:badge-dollar-sign"}
18
+ Yes. Every package is MIT licensed.
19
+ :::
20
+
21
+ :::accordion-item{label="Does it need a script?" description="No. Each item is a native details element."}
22
+ :::
23
+ ::
24
+
25
+ ::collapsible{name="options"}
26
+ - `level`: the heading level that starts each step.
27
+ - `start`: the number of the first step.
28
+ ::
29
+ ````
30
+
31
+ | Block | Props |
32
+ | --- | --- |
33
+ | `::details` | `summary` is the text shown while it's closed. Without one it reads "Details", and the plugin reports it. `open` starts it open, and `icon` puts an icon before the summary. |
34
+ | `::accordion` | `type` is `multiple` (default), where several items can be open at once, or `single`, where opening one closes the others. `defaultValue` lists the items that start open by position from 0, as `:defaultValue='["0", "2"]'` or `defaultValue="1"`. A `single` accordion opens only the first of them. |
35
+ | `:::accordion-item` | `label` is the summary, and it's required. `icon` puts an icon before it, and `description` is the text shown when the item has no content of its own. |
36
+ | `::collapsible` | `name` says what it hides, default `properties`, and the summary reads "Show properties" while closed and "Hide properties" while open. `openText` and `closeText` replace "Show" and "Hide", and `icon` puts an icon before the summary. |
37
+
38
+ On `::details`, a `#summary` slot replaces `summary` and can hold Markdown; write the body after `#default`. `icon` takes a name as in [icon](icon.md), such as `lucide:info`.
39
+
40
+ ## Choose the block
41
+
42
+ - `::details` for one thing a reader may skip, such as a long log, a stack trace, or the answer to one question.
43
+ - `::accordion` for several questions or sections in a row. Put every block inside an `:::accordion-item`, since content between items doesn't render, and an item outside `::accordion` renders on its own.
44
+ - `::collapsible` for optional content under a heading or a field, such as the rarely used options in a list of props.
45
+
46
+ ## Register
47
+
48
+ - In `comark-ui`: on, under the key `details`. Its icons come from the preset's shared resolver, so `icon: { collections }` applies to them.
49
+ - Alone: `pnpm add comark @comark/html comark-details`, then `createHtmlRenderer({ plugins: [details()], components })` with both from `comark-details/html`. By default icons come from the Iconify API while parsing. To share one resolver with the page's other plugins, add `comark-icon`, make one with `createIcons()`, and pass it as `details({ iconResolver })`. The output needs no script. `comark-details/vue`, `/react`, and `/svelte` render it too.
@@ -0,0 +1,45 @@
1
+ # Diagrams
2
+
3
+ comark-diagrams draws PlantUML, Graphviz, D2, DBML, GoAT, and Svgbob fences as SVG while parsing, through a Kroki server, and puts the drawing in the page with no script. Use it when a flow or a schema shows a change faster than prose.
4
+
5
+ ## Syntax
6
+
7
+ ````md
8
+ ```d2 [How a sighting reaches the map]
9
+ phone -> api: POST /sightings
10
+ api -> queue: dedupe
11
+ queue -> map: pigeon pin
12
+ ```
13
+ ````
14
+
15
+ | Fence | Draws |
16
+ | --- | --- |
17
+ | `plantuml` | UML: sequence, class, state, and other diagrams |
18
+ | `graphviz` or `dot` | Graphs in the DOT language |
19
+ | `d2` | Boxes and arrows in D2's short syntax |
20
+ | `dbml` | Database tables and their relations |
21
+ | `goat` or `svgbob` | ASCII art, as lines and arrows |
22
+
23
+ - The title in brackets after the language goes under the diagram and names it for screen readers. Give every diagram one.
24
+ - Every other fence stays code, `mermaid` included, so draw flows in `d2` or `dot`.
25
+ - A diagram Kroki can't draw stays code, and `meta.issues` quotes the tool's error. So does one drawn while the server can't be reached; the next parse tries again.
26
+ - The plugin drops anything that could run from the SVG: scripts, event handlers, embedded HTML, and animations. Write labels as plain text. A D2 Markdown label (`|md … |`) is embedded HTML, so it comes out empty, and nothing reports it.
27
+
28
+ ## Check each diagram
29
+
30
+ Send an internal architecture or a schema with sensitive names only to the host's own Kroki server. With the default `server`, each diagram's source goes to `https://kroki.io`, a public service.
31
+
32
+ The linter sends nothing, so it can't tell whether a diagram draws. Render the document, or post the source to the same Kroki server and read the answer:
33
+
34
+ ```sh
35
+ curl -s -H "Content-Type: text/plain" --data-binary @flow.d2 https://kroki.io/d2/svg
36
+ ```
37
+
38
+ An SVG means it draws; any other answer is the tool's error.
39
+
40
+ ## Register
41
+
42
+ - In `comark-ui`: on, with the options below under `diagrams`.
43
+ - Alone: `pnpm add comark @comark/html comark-diagrams`, then `createHtmlRenderer({ plugins: [diagrams()], components })` with both from `comark-diagrams/html`. `comark-diagrams/vue`, `/react`, and `/svelte` render it too.
44
+
45
+ `server` is the Kroki server, `https://kroki.io` by default. `docker run -d -p 8000:8000 yuzutech/kroki` runs your own, which draws every fence above, and `diagrams({ server: "http://localhost:8000" })` points at it. `draw: false` leaves every fence as code and sends nothing, for a lint step. The plugin draws each diagram once per process, and a failed one again on the next parse.
@@ -0,0 +1,43 @@
1
+ # Code changes
2
+
3
+ comark-diff draws a file's lines before and after as a suggested change, the way a pull request review shows one. Removed lines are red, added lines green, and the words that changed a shade deeper, under a header with the file and the count of lines added and removed. Use it to propose or explain an edit to one file.
4
+
5
+ ## Syntax
6
+
7
+ ````md
8
+ ::diff{line=212 label="Suggested change"}
9
+ ```ts [packages/zoom/src/client.ts]
10
+ function close() {
11
+ dialog.close();
12
+ history.back();
13
+ }
14
+ ```
15
+ ```ts
16
+ function close() {
17
+ dialog.close();
18
+ if (opened) history.back();
19
+ }
20
+ ```
21
+ ::
22
+ ````
23
+
24
+ Inside go two fenced blocks, before then after, in the file's language, and nothing else. Leave the first block empty for a new file, or the second for a deleted one.
25
+
26
+ | Prop | What it does |
27
+ | --- | --- |
28
+ | `file` | The file's path. Defaults to the name on the first block, like `` ```ts [src/a.ts] ``; one of the two is required. |
29
+ | `line` | The file's line number of the first line in both blocks, a whole number from 1. Without it, the diff has no line numbers. |
30
+ | `label` | A heading before the file name, such as "Suggested change". |
31
+
32
+ A line a block highlights, like `` ```ts {2} ``, stays highlighted. `meta.issues` reports an unknown prop, content beside the blocks, a count of blocks other than two, a `diff` or `patch` block, a missing file name, two different file names or languages, a `line` that isn't a whole number from 1, a block over 200 lines, and a diff with no change.
33
+
34
+ ## Keep it to the change
35
+
36
+ - Show one file per diff, with a few unchanged lines before and after the change. Split a change to two files into two diffs, and write explanations above or below the block.
37
+ - Copy both blocks from the file, and start them at the same line, since `line` numbers both from there. Take the number from the file; the plugin can't check it.
38
+ - For a change already written as a unified diff, such as `git diff` output, paste it into a `diff` fence outside `::diff`, as the [code reference](code.md) shows.
39
+
40
+ ## Register
41
+
42
+ - In `comark-ui`: on, in `comark-ui/html` only.
43
+ - Alone: `pnpm add comark @comark/html comark-diff`, then `createHtmlRenderer({ plugins: [diff()], components })` with both from `comark-diff/html`. It renders only to HTML, takes no options, and needs no script. Add Comark's `shiki` plugin, in any order, to keep the code's highlighting.
@@ -0,0 +1,40 @@
1
+ # Players and link cards
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.
4
+
5
+ ## Syntax
6
+
7
+ ```md
8
+ ::embed{url="https://youtu.be/KCrXgy8qtjM" title="Watch before standup: Vite in 100 Seconds" start=30}
9
+ ::
10
+ ```
11
+
12
+ | Prop | What it does |
13
+ | --- | --- |
14
+ | `url` | Required. An `https://` link; any other renders nothing. |
15
+ | `title` | Names the player for screen readers and is the text of the link under it. Without it, the link shows the host. |
16
+ | `start` | Whole seconds into a YouTube or Vimeo video. A YouTube link's own `t=`, like `t=1m30s`, works too. |
17
+
18
+ Close the block with `::` on the next line. It drops anything inside and reports it.
19
+
20
+ | Provider | Links it reads |
21
+ | --- | --- |
22
+ | YouTube | `youtube.com/watch?v=`, `youtu.be/`, `/shorts/` (drawn tall), `/embed/`, and `/live/`, played from `youtube-nocookie.com` |
23
+ | Vimeo | `vimeo.com/<number>`, an unlisted link with its hash, and `player.vimeo.com/video/`, played with `dnt=1` |
24
+ | Loom | `loom.com/share/<id>` |
25
+ | Spotify | `open.spotify.com` track, album, playlist, episode, show, and artist links; a track or an episode gets the compact player |
26
+ | CodePen | `codepen.io/<user>/pen/<id>` |
27
+ | StackBlitz | `stackblitz.com/edit/<project>` and `stackblitz.com/github/<owner>/<repo>`, keeping options such as `file` and `view` |
28
+ | Figma | `figma.com/design`, `file`, `proto`, `board`, `slides`, and `deck` links, keeping `node-id` |
29
+
30
+ 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
+ ## Pick what to embed
33
+
34
+ - Give every card a `title`. A card fetches nothing, so without one it shows only the host, and the plugin reports it.
35
+ - For a live reproduction, embed a StackBlitz project that runs in the browser alone, such as one from the `typescript` starter. A project that runs in WebContainers, such as a Node or Vite starter, needs a cross-origin-isolated page and a supported browser, and otherwise shows "Unable to run Embedded Project". Nothing reports it.
36
+
37
+ ## Register
38
+
39
+ - 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.
@@ -0,0 +1,48 @@
1
+ # Props and options
2
+
3
+ comark-fields lists a component's props or a function's options, each with its type, its default, and a required tag, and nests an object's properties under it. Use it in API docs, or in a review that adds or changes options.
4
+
5
+ ## Syntax
6
+
7
+ ```md
8
+ ::field-group
9
+ :::field{name="title" type="string" required}
10
+ The text above the card's content.
11
+ :::
12
+
13
+ :::field{name="options" type="object" default="{}"}
14
+ What the plugin takes.
15
+
16
+ ::::field{name="download" type="boolean" default="true"}
17
+ Inlines each image while parsing.
18
+ ::::
19
+ :::
20
+ ::
21
+ ```
22
+
23
+ | Prop | What it does |
24
+ | --- | --- |
25
+ | `name` | Required. The prop, option, or parameter, shown in code. |
26
+ | `type` | Its type, as you'd write it in TypeScript. |
27
+ | `required` | A bare `required` adds a required tag. `:required="false"` leaves it off. |
28
+ | `default` | Its default, shown in code. `:default="0"` and `:default='{"a":1}'` show as written. |
29
+ | `description` | The text shown when the field has no content of its own, or above its nested fields. On a field with text inside, the plugin ignores it and reports it. |
30
+
31
+ The text inside a field is its description. Fields inside a field describe an object's properties, with one more colon for each level. `::field-group` stacks fields with a line between them, and a field works on its own too. Nuxt UI's own field has no `default` and ignores it.
32
+
33
+ To fold rarely used options away, put their fields in a `::collapsible` from [details](details.md), as Nuxt UI's docs do:
34
+
35
+ ```md
36
+ ::field{name="options" type="object"}
37
+ :::collapsible{name="options"}
38
+ ::::field{name="sync" type="string"}
39
+ A key shared by blocks that switch together.
40
+ ::::
41
+ :::
42
+ ::
43
+ ```
44
+
45
+ ## Register
46
+
47
+ - In `comark-ui`: on, under the key `fields`, with no options.
48
+ - Alone: `pnpm add comark @comark/html comark-fields`, then `createHtmlRenderer({ plugins: [fields()], components })` with both from `comark-fields/html`. It takes no options and needs no script. `comark-fields/vue`, `/react`, and `/svelte` render it too.
@@ -0,0 +1,25 @@
1
+ # Image captions
2
+
3
+ comark-figure turns an image with a title, alone in its paragraph, into a native `<figure>` with the title as its `<figcaption>`. Use it when an image needs a sentence under it that says why it's there.
4
+
5
+ ## Syntax
6
+
7
+ ```md
8
+ ![Bar chart of deploys per day, highest on Tuesday](deploys.png "Most deploys land on Tuesday, after the Monday freeze")
9
+ ```
10
+
11
+ - The caption is the title, the quoted text after the URL. It is plain text, so Markdown in it shows as written.
12
+ - The alt text stays on the image for screen readers, who hear both. Make them say different things. The alt text says what the image shows, and the caption says why it's there.
13
+ - The image keeps its `src`, its alt text, and any `{attributes}`, and loses its `title`.
14
+ - Give the image a paragraph of its own, with a blank line before and after it. That works at the top level, in a list item, a blockquote, or a definition, and in a `::component` beside another block. An image inside a sentence keeps its title as a tooltip.
15
+ - When a `::component` holds nothing but the image, the plugin leaves the image as it is. Add another block to the component, or move the image out of it.
16
+ - A linked image becomes a figure too: `[![alt](src "Caption")](https://example.com)` keeps the link around the image, with the caption under it, outside the link. A title on the link, `[![alt](src)](url "Title")`, stays the link's tooltip.
17
+
18
+ ## Numbered figures
19
+
20
+ For a figure the text refers to by number, give the image comark-xref's `{#fig-…}` id and no title, and xref captions it with "Figure 1:" and its alt text. `comark-ui` runs both plugins, and there an image with both a title and a `fig-` id becomes an unnumbered figure. xref then reports it as sharing its paragraph with text, and every `:ref` to it as pointing at nothing.
21
+
22
+ ## Register
23
+
24
+ - In `comark-ui`: on by default. `figure: { unwrap: true }` also lifts every image alone in its paragraph out of the `<p>`, with a title or without, so the page's CSS can size those images apart from the ones inside a sentence. Comark's `autoUnwrap` does that only in list items and blockquotes.
25
+ - Alone: `pnpm add comark comark-figure`, then `plugins: [figure()]` with `import figure from "comark-figure"`, and the same `unwrap` option. It has no components, classes, or styles, so it works in any renderer. With comark-zoom, the image in a figure still zooms, in either plugin order. Browsers indent a figure by 40px on each side until the page's CSS sets its margin.
@@ -0,0 +1,42 @@
1
+ # File trees
2
+
3
+ comark-file-tree draws folders and files from a fenced block, marks entries added, removed, or changed, and puts a note on any line. Use it to show what a change adds, moves, or deletes, or how a project is laid out.
4
+
5
+ ## Syntax
6
+
7
+ ````md
8
+ ::file-tree
9
+ ```
10
+ packages/
11
+ steps/
12
+ + src/
13
+ + index.ts # the parse plugin
14
+ ~ package.json
15
+ - legacy.ts # folded into index.ts
16
+ ...
17
+ README.md
18
+ ```
19
+ ::
20
+ ````
21
+
22
+ Write one entry per line in one fenced block inside `::file-tree`, with any language or none. The block takes no props.
23
+
24
+ | Written | What it does |
25
+ | --- | --- |
26
+ | Two spaces before a name | Puts it inside the entry above that starts further left. Four spaces or tabs work the same. |
27
+ | `├──`, `└──`, and `│` | Output pasted from `tree`, in Unicode or ASCII. The plugin drops its `.` root and its `2 directories, 3 files` summary. |
28
+ | A trailing `/` | Makes a folder. An entry with entries under it is a folder too. |
29
+ | `+`, `-`, or `~` and a space before a name | Marks it added, removed, or changed, in a color, with the sign kept beside the name. |
30
+ | ` # note` after a name | A note, shown after the name in a lighter color. The `#` needs a space on each side, so `#notes.md` stays a name. |
31
+ | `...` | Stands for entries left out. |
32
+
33
+ ## Show a change
34
+
35
+ - Write the tree in a fence, even a short one. A Markdown list turns `__init__.py` bold and `[id].vue` into a span, so the plugin reports it and renders the list as written.
36
+ - List the folders on the path to each changed file, mark the files, and put `...` where unchanged entries sit. Give a file a note when the reason it changed fits in a few words.
37
+ - Write any explanation outside the block, since text beside the fence doesn't render.
38
+
39
+ ## Register
40
+
41
+ - In `comark-ui`: on, under the key `fileTree`. The preset passes its shared icon resolver, so every entry gets its file type's icon from Iconify's vscode-icons set, fetched from the Iconify API unless `icon: { collections }` holds `vscode-icons`. `fileTree: { icons }` adds icons of your own, as below.
42
+ - Alone: `pnpm add comark @comark/html comark-file-tree`, then `createHtmlRenderer({ plugins: [fileTree()], components })` with both from `comark-file-tree/html`. Without options, every folder and file gets the same plain glyph and nothing is fetched. Add `comark-icon` and pass `fileTree({ iconResolver: createIcons() })` to draw each file type's icon. `icons` maps a file name, an extension such as `.vue`, or `name/` for a folder to any icon name from [icon](icon.md), and its `folder` and `file` keys set the fallbacks. A name wins over an extension, and an icon that doesn't load leaves the plain glyph. The output needs no script. `comark-file-tree/vue`, `/react`, and `/svelte` render it too.
@@ -0,0 +1,26 @@
1
+ # Footnotes
2
+
3
+ comark-footnotes numbers notes in the order the text first references them and lists them in a section at the end of the page. Use a note for a source, a caveat, or a detail that would break the sentence, such as how you measured a number.
4
+
5
+ ## Syntax
6
+
7
+ ```md
8
+ The deploy waits when the roof holds more than 12 pigeons[^count], unless it's a hotfix^[Hotfixes need two approvals.].
9
+
10
+ [^count]: Counted once, from the window, at 9:00.
11
+
12
+ Pigeons that fly off mid-count still count.
13
+ ```
14
+
15
+ - `[^label]` marks where a note applies, and a line that starts with `[^label]:` defines it, anywhere in the document. The number comes from the order of first reference, so name the label after the note, such as `[^count]`.
16
+ - `^[text]` writes a note in place, with no label and no definition.
17
+ - Indent lines by four spaces to continue a definition with more paragraphs, a list, or code. A line that isn't indented continues the paragraph above it.
18
+ - Markdown in a note renders, and a note can reference another note. A note referenced twice links back to both places.
19
+ - The plugin draws the section, its `Footnotes` heading, and the rule above it, so the document holds only the definitions.
20
+
21
+ The linter reports a reference with no definition, a definition nothing references, and a label defined twice. Only the first of two definitions shows. It misses a label with a space. `[^my note]` shows as `^my note`, and its definition disappears, so join the words with hyphens: `[^my-note]`.
22
+
23
+ ## Register
24
+
25
+ - In `comark-ui`: on by default, in place of Comark's own footnotes plugin. `footnotes: { label: "Notes", hr: false, backRef: "↑" }` sets the section's heading (default `"Footnotes"`; `""` leaves it out), whether a rule comes before the section (default `true`), and the link from a note back to its reference (default `"↩"`).
26
+ - Alone: `pnpm add comark comark-footnotes`, then `plugins: [footnotes()]` with `import footnotes from "comark-footnotes"`, and the same options. It is named `footnotes`, and Comark keeps the first plugin of a name, so remove `comark/plugins/footnotes` from the list instead of adding this one after it. It has no components and writes the nodes and classes Comark's plugin writes, such as `footnote-ref` and `footnotes`, so styles made for it keep working.
@@ -0,0 +1,44 @@
1
+ # GitHub callouts, references, and HTML
2
+
3
+ comark-github renders three parts of GitHub's Markdown as GitHub does: `> [!NOTE]` alerts as callouts with an icon and a title, `@user` and `#123` as links, and raw HTML cut down to the tags GitHub allows. Use a callout for the one thing a reader must not miss, and write references and HTML as you would in a GitHub comment.
4
+
5
+ ## Syntax
6
+
7
+ ````md
8
+ > [!WARNING] Breaking change
9
+ > `render(markdown)` is gone. Create a renderer once with `createHtmlRenderer()` and reuse it.
10
+
11
+ Thanks @onmax: this fixes #51, and onmax/comark-ui#73 builds on it.
12
+
13
+ <details>
14
+ <summary>Test output</summary>
15
+
16
+ ```txt
17
+ ✓ test/callouts.test.ts (12 tests) 41ms
18
+ ```
19
+
20
+ </details>
21
+ ````
22
+
23
+ - Callouts: `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, or `[!CAUTION]` at the start of a quote's first line, in any case. Text after the marker on that line is the title, as plain text; without it the title is the type, such as Warning. The body is any Markdown on the quote's next lines, and a callout can sit in a list. Any other marker, such as `[!INFO]`, leaves a plain quote that shows the marker, and is reported.
24
+ - References: `@user` links to `https://github.com/user`, `owner/name#123` to that issue or pull request, and a bare `#123` into the host's `repo`. With no `repo`, `#123` stays text. A reference must stand alone, so `me@example.com`, `C#9`, `@comark/html`, and anything in a link or in code are never references.
25
+ - Raw HTML keeps GitHub's tags, such as `details`, `summary`, `kbd`, `sub`, `sup`, `img`, `picture`, and tables, and the attributes that set the layout or describe the content, such as `width`, `align`, `alt`, `title`, and `open`. `script` and `style` go with their content. Any other tag, such as `iframe`, `form`, or `video`, gives way to its content, so write a recording as an image for comark-media. `class`, `id`, `style`, and event handlers go. A URL must be relative, http, or https, or mailto in a link. Blocks written as Markdown, such as `::screenshot`, are untouched.
26
+
27
+ ## Choose the callout
28
+
29
+ | Type | Use it for |
30
+ | --- | --- |
31
+ | `NOTE` | Context the reader should know, even when skimming |
32
+ | `TIP` | A better or faster way to do something |
33
+ | `IMPORTANT` | Something the reader needs to succeed |
34
+ | `WARNING` | A risk that needs their attention now |
35
+ | `CAUTION` | An action with consequences they can't undo |
36
+
37
+ ## Collapse long output
38
+
39
+ Put a long log or a full test run in a `<details>`, with a `<summary>` that says what it holds, so the page stays short. Leave a blank line after `</summary>`, which GitHub needs to render the Markdown inside, and another before `</details>`. After a list, a `</details>` with no blank line before it joins the list, and the next block lands inside the details.
40
+
41
+ ## Register
42
+
43
+ - In `comark-ui`: all three are on. Pass `github: { references: { repo: "owner/name" } }` so a bare `#123` links. `github: { callouts: { titles: { note: "Nota" } } }` renames the default titles for a site in another language, and `github: { html: false }` renders raw HTML as written. comark-chips runs first there, so `@user` renders as its avatar chip.
44
+ - Alone: `pnpm add comark @comark/html comark-github`, then `createHtmlRenderer({ plugins: [callouts(), references({ repo: "owner/name" }), html()], components })` with all four from `comark-github/html`. It has no default export, so register the plugins you want, in any order; only callouts use `components`. `callouts()` takes the place of Comark's built-in alert plugin and `html()` of its html plugin, even under `registerDefaultPlugins: false`. `comark-github/vue`, `/react`, and `/svelte` render it too. A `repo` that isn't `owner/name` is reported, and `#123` stays text.
@@ -0,0 +1,28 @@
1
+ # Icons
2
+
3
+ comark-icon draws `:icon` with any of Iconify's 200,000 icons, such as a logo beside a name or a status in a table. It resolves each icon while parsing and writes it into the page as a CSS image, so the reader's browser fetches nothing and runs no script.
4
+
5
+ ## Syntax
6
+
7
+ ```md
8
+ | Check | Result |
9
+ | --- | --- |
10
+ | Unit tests | :icon{name="lucide:circle-check" label="Passed"} |
11
+ | Visual diff | :icon{name="lucide:circle-x" label="Failed"} |
12
+
13
+ Built with :icon{name="logos:vue"} Vue and :icon{name="logos:vitejs"} Vite.
14
+ ```
15
+
16
+ | Prop | What it does |
17
+ | --- | --- |
18
+ | `name` | Required. `set:name`, such as `lucide:apple`, from a set at https://icones.js.org. Nuxt UI's `i-lucide-apple` works too. A URL, or a path that starts with `/`, `./`, or `../`, draws that image instead. `:name="frontmatter.icon"` takes the name from the frontmatter. |
19
+ | `label` | What the icon means, for screen readers. Without one the icon is decoration, and they skip it. |
20
+
21
+ An icon is as tall as the text. One in a single color, such as Lucide's, paints in the color of the text around it. One with colors of its own, such as `logos:vue`, keeps them.
22
+
23
+ Give a `label` when the icon says something the words around it don't, such as a lone status in a table cell. Leave it out when a word beside the icon says the same. Copy each name from icones.js.org. The plugin leaves out an icon it can't draw, from a misspelled name, an unknown set, or a failed download, and reports it.
24
+
25
+ ## Register
26
+
27
+ - In `comark-ui`: on. Its `icon` option takes `collections` and `fetch`, as below, and its resolver also draws the icons of cards, details, file trees, tabs, and code actions.
28
+ - Alone: `pnpm add comark @comark/html comark-icon`, then `createHtmlRenderer({ plugins: [icon()], components })` with both from `comark-icon/html`. `comark-icon/vue`, `/react`, and `/svelte` render it too. With no options it downloads each icon from the Iconify API while parsing, once per process. To build offline, install the sets you use and pass them, as in `icon({ collections: { lucide }, fetch: false })` with `icons as lucide` from `@iconify-json/lucide`. A collection can also map names to SVG markup, for icons of your own, and `fetch` can be the URL of your own Iconify API. Plugins that draw icons take an `Icons` from `createIcons()`, so pass the same one to each and set the options once.