comark-ui 0.7.2 → 0.7.4

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 (45) hide show
  1. package/README.md +2 -2
  2. package/dist/{editor-BAdok66p.mjs → editor-DmxNPK7K.mjs} +522 -68
  3. package/dist/{editor-CNivEuMH.d.mts → editor-KD97dL_1.d.mts} +21 -3
  4. package/dist/editor-vue.d.mts +1 -1
  5. package/dist/editor-vue.mjs +1 -1
  6. package/dist/editor.d.mts +2 -2
  7. package/dist/editor.mjs +1 -1
  8. package/dist/html.d.mts +1 -1
  9. package/dist/html.mjs +3 -1
  10. package/dist/{index-jkwx6SyG.d.mts → index-BUDHsvnm.d.mts} +7 -0
  11. package/dist/index.d.mts +1 -1
  12. package/dist/index.mjs +1 -1
  13. package/dist/react.d.mts +2 -2
  14. package/dist/react.mjs +2 -2
  15. package/dist/skills/before-after-evidence/SKILL.md +72 -0
  16. package/dist/skills/before-after-evidence/agents/openai.yaml +3 -0
  17. package/dist/skills/before-after-evidence/references/blocks.md +54 -0
  18. package/dist/skills/before-after-evidence/references/example.md +37 -0
  19. package/dist/skills/before-after-evidence/references/measuring.md +50 -0
  20. package/dist/skills/comark-ui/SKILL.md +8 -1
  21. package/dist/skills/comark-ui/references/annotate.md +4 -2
  22. package/dist/skills/comark-ui/references/comments.md +43 -0
  23. package/dist/skills/comark-ui/references/lint.md +1 -1
  24. package/dist/skills/comark-ui/references/quiz.md +1 -1
  25. package/dist/skills/comark-ui/references/ui.md +1 -1
  26. package/dist/skills/review-document/SKILL.md +64 -0
  27. package/dist/skills/review-document/agents/openai.yaml +3 -0
  28. package/dist/skills/review-document/references/blocks.md +69 -0
  29. package/dist/skills/review-document/references/example.md +51 -0
  30. package/dist/skills/teach-lesson/SKILL.md +78 -0
  31. package/dist/skills/teach-lesson/agents/openai.yaml +3 -0
  32. package/dist/skills/teach-lesson/references/blocks.md +91 -0
  33. package/dist/skills/teach-lesson/references/example.md +70 -0
  34. package/dist/skills/visual-explanation/SKILL.md +67 -0
  35. package/dist/skills/visual-explanation/agents/openai.yaml +3 -0
  36. package/dist/skills/visual-explanation/references/blocks.md +89 -0
  37. package/dist/skills/visual-explanation/references/example.md +25 -0
  38. package/dist/skills.d.mts +18 -0
  39. package/dist/skills.mjs +326 -0
  40. package/dist/{src-DROB05U6.mjs → src-PkmYCSNu.mjs} +1 -0
  41. package/dist/svelte/index.d.ts +1 -1
  42. package/dist/svelte/index.js +1 -1
  43. package/dist/vue.d.mts +2 -2
  44. package/dist/vue.mjs +2 -2
  45. package/package.json +46 -44
@@ -1,5 +1,5 @@
1
1
  import { ComarkPlugin } from "comark";
2
- import { AnyExtension, Extension, JSONContent, Node } from "@tiptap/core";
2
+ import { AnyExtension, Extension, JSONContent, Mark, Node } from "@tiptap/core";
3
3
  import { StarterKitOptions } from "@tiptap/starter-kit";
4
4
  import { EditorState, Plugin, PluginKey, Transaction } from "@tiptap/pm/state";
5
5
  import { DecorationSet } from "@tiptap/pm/view";
@@ -21,9 +21,27 @@ declare const ComarkSlot: Node<any, any>;
21
21
  declare const ComarkInline: Node<any, any>;
22
22
  /** An HTML comment between blocks. */
23
23
  declare const ComarkComment: Node<any, any>;
24
+ /** A footnote reference, `[^label]`. */
25
+ declare const FootnoteReference: Node<any, any>;
26
+ /** A note written where it applies, `^[text]`. */
27
+ declare const InlineFootnote: Node<any, any>;
28
+ /** A footnote's text, `[^label]: text`, with the blocks indented under it. */
29
+ declare const FootnoteDefinition: Node<any, any>;
30
+ /** A definition list, `Term` then `: Definition`. */
31
+ declare const DefinitionList: Node<any, any>;
32
+ declare const DefinitionTerm: Node<any, any>;
33
+ declare const DefinitionDescription: Node<any, any>;
34
+ /** CriticMarkup's suggested insertion, `{++text++}`. */
35
+ declare const CriticInsertion: Mark<any, any>;
36
+ /** CriticMarkup's suggested deletion, `{--text--}`. */
37
+ declare const CriticDeletion: Mark<any, any>;
38
+ /** CriticMarkup's highlight, `{==text==}`. */
39
+ declare const CriticHighlight: Mark<any, any>;
40
+ /** CriticMarkup's comment, `{>>text<<}`. */
41
+ declare const CriticComment: Node<any, any>;
24
42
  /**
25
43
  * The schema `fromMarkdown` and `toMarkdown` read and write: StarterKit's nodes and marks, task lists, inline images,
26
- * tables, and Comark's components, slots, and comments. It needs no DOM, so a server can load it to convert a document
44
+ * tables, footnotes, definition lists, CriticMarkup, and Comark's components, slots, and comments. It needs no DOM, so a server can load it to convert a document
27
45
  * for a collaborative room.
28
46
  */
29
47
  declare const ComarkKit: Extension<ComarkKitOptions, any>;
@@ -128,4 +146,4 @@ interface EditorCodecOptions {
128
146
  }
129
147
  declare function createEditorCodec(options?: EditorCodecOptions): EditorCodec;
130
148
  //#endregion
131
- export { ComarkSlot as S, ComarkComment as _, Upload as a, ComarkKit as b, startUploads as c, EditorDocument as d, MarkdownCheck as f, ComarkBlock as g, toMarkdown as h, PendingUpload as i, uploadKey as l, fromMarkdown as m, EditorCodecOptions as n, UploadOptions as o, checkMarkdown as p, createEditorCodec as r, findUpload as s, EditorCodec as t, uploadPlugin as u, ComarkImage as v, ComarkKitOptions as x, ComarkInline as y };
149
+ export { FootnoteDefinition as A, CriticComment as C, DefinitionDescription as D, CriticInsertion as E, InlineFootnote as M, DefinitionList as O, ComarkSlot as S, CriticHighlight as T, ComarkComment as _, Upload as a, ComarkKit as b, startUploads as c, EditorDocument as d, MarkdownCheck as f, ComarkBlock as g, toMarkdown as h, PendingUpload as i, FootnoteReference as j, DefinitionTerm as k, uploadKey as l, fromMarkdown as m, EditorCodecOptions as n, UploadOptions as o, checkMarkdown as p, createEditorCodec as r, findUpload as s, EditorCodec as t, uploadPlugin as u, ComarkImage as v, CriticDeletion as w, ComarkKitOptions as x, ComarkInline as y };
@@ -1,4 +1,4 @@
1
- import { x as ComarkKitOptions } from "./editor-CNivEuMH.mjs";
1
+ import { x as ComarkKitOptions } from "./editor-KD97dL_1.mjs";
2
2
  import { ComarkPlugin } from "comark";
3
3
  import { AnyExtension } from "@tiptap/core";
4
4
  import { Editor } from "@tiptap/vue-3";
@@ -1,4 +1,4 @@
1
- import { c as fromMarkdown, l as toMarkdown, m as ComarkKit, s as checkMarkdown } from "./editor-BAdok66p.mjs";
1
+ import { c as fromMarkdown, l as toMarkdown, m as ComarkKit, s as checkMarkdown } from "./editor-DmxNPK7K.mjs";
2
2
  import { Editor, EditorContent } from "@tiptap/vue-3";
3
3
  import { defineComponent, h, onScopeDispose, ref, shallowRef, watch } from "vue";
4
4
  //#region src/editor-vue.ts
package/dist/editor.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { S as ComarkSlot, _ as ComarkComment, a as Upload, b as ComarkKit, c as startUploads, d as EditorDocument, f as MarkdownCheck, g as ComarkBlock, h as toMarkdown, i as PendingUpload, l as uploadKey, m as fromMarkdown, n as EditorCodecOptions, o as UploadOptions, p as checkMarkdown, r as createEditorCodec, s as findUpload, t as EditorCodec, u as uploadPlugin, v as ComarkImage, x as ComarkKitOptions, y as ComarkInline } from "./editor-CNivEuMH.mjs";
2
- export { ComarkBlock, ComarkComment, ComarkImage, ComarkInline, ComarkKit, type ComarkKitOptions, ComarkSlot, type EditorCodec, type EditorCodecOptions, type EditorDocument, type MarkdownCheck, type PendingUpload, Upload, type UploadOptions, checkMarkdown, createEditorCodec, findUpload, fromMarkdown, startUploads, toMarkdown, uploadKey, uploadPlugin };
1
+ import { A as FootnoteDefinition, C as CriticComment, D as DefinitionDescription, E as CriticInsertion, M as InlineFootnote, O as DefinitionList, S as ComarkSlot, T as CriticHighlight, _ as ComarkComment, a as Upload, b as ComarkKit, c as startUploads, d as EditorDocument, f as MarkdownCheck, g as ComarkBlock, h as toMarkdown, i as PendingUpload, j as FootnoteReference, k as DefinitionTerm, l as uploadKey, m as fromMarkdown, n as EditorCodecOptions, o as UploadOptions, p as checkMarkdown, r as createEditorCodec, s as findUpload, t as EditorCodec, u as uploadPlugin, v as ComarkImage, w as CriticDeletion, x as ComarkKitOptions, y as ComarkInline } from "./editor-KD97dL_1.mjs";
2
+ export { ComarkBlock, ComarkComment, ComarkImage, ComarkInline, ComarkKit, type ComarkKitOptions, ComarkSlot, CriticComment, CriticDeletion, CriticHighlight, CriticInsertion, DefinitionDescription, DefinitionList, DefinitionTerm, type EditorCodec, type EditorCodecOptions, type EditorDocument, FootnoteDefinition, FootnoteReference, InlineFootnote, type MarkdownCheck, type PendingUpload, Upload, type UploadOptions, checkMarkdown, createEditorCodec, findUpload, fromMarkdown, startUploads, toMarkdown, uploadKey, uploadPlugin };
package/dist/editor.mjs CHANGED
@@ -1 +1 @@
1
- export { u as ComarkBlock, d as ComarkComment, f as ComarkImage, p as ComarkInline, m as ComarkKit, h as ComarkSlot, n as Upload, s as checkMarkdown, t as createEditorCodec, r as findUpload, c as fromMarkdown, i as startUploads, l as toMarkdown, a as uploadKey, o as uploadPlugin } from "./editor-BAdok66p.mjs";
1
+ export { u as ComarkBlock, d as ComarkComment, f as ComarkImage, p as ComarkInline, m as ComarkKit, h as ComarkSlot, g as CriticComment, _ as CriticDeletion, v as CriticHighlight, y as CriticInsertion, b as DefinitionDescription, x as DefinitionList, S as DefinitionTerm, C as FootnoteDefinition, w as FootnoteReference, T as InlineFootnote, n as Upload, s as checkMarkdown, t as createEditorCodec, r as findUpload, c as fromMarkdown, i as startUploads, l as toMarkdown, a as uploadKey, o as uploadPlugin } from "./editor-DmxNPK7K.mjs";
package/dist/html.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as criticCss, n as Preset, r as PresetOptions } from "./index-jkwx6SyG.mjs";
1
+ import { a as criticCss, n as Preset, r as PresetOptions } from "./index-BUDHsvnm.mjs";
2
2
  import { NodeHandler } from "comark";
3
3
  //#region src/html.d.ts
4
4
  /**
package/dist/html.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as typesetCss } from "./typeset-css-5aJ7cSmh.mjs";
2
- import { n as preset, t as criticCss } from "./src-DROB05U6.mjs";
2
+ import { n as preset, t as criticCss } from "./src-PkmYCSNu.mjs";
3
3
  import { a as start, n as mermaidBar, r as mermaidCss } from "./client-Bjd6VcGQ.mjs";
4
4
  import { escapeHtml } from "comark/utils";
5
5
  import * as annotate from "comark-annotate/html";
@@ -12,6 +12,7 @@ import * as chips from "comark-chips/html";
12
12
  import * as code from "comark-code/html";
13
13
  import * as codeNotes from "comark-code-notes/html";
14
14
  import * as colors from "comark-colors/html";
15
+ import * as comments from "comark-comments/html";
15
16
  import * as details from "comark-details/html";
16
17
  import * as diagrams from "comark-diagrams/html";
17
18
  import * as diff from "comark-diff/html";
@@ -77,6 +78,7 @@ var html_default = (options) => preset({
77
78
  code,
78
79
  codeNotes,
79
80
  colors,
81
+ comments,
80
82
  details,
81
83
  diagrams,
82
84
  diff,
@@ -12,6 +12,7 @@ import { CastOptions } from "comark-cast";
12
12
  import { ChartsOptions } from "comark-charts";
13
13
  import { ChipsOptions } from "comark-chips";
14
14
  import { CodeOptions } from "comark-code";
15
+ import { CommentsOptions } from "comark-comments";
15
16
  import { DetailsOptions } from "comark-details";
16
17
  import { DiagramsOptions } from "comark-diagrams";
17
18
  import { FileTreeOptions } from "comark-file-tree";
@@ -54,6 +55,11 @@ type PresetOptions = {
54
55
  /** Pass `{ download: false }` when parsing in a browser, which may not download another site's images. */
55
56
  chips?: ChipsOptions | boolean;
56
57
  colors?: boolean;
58
+ /**
59
+ * HTML only: Vue, React, and Svelte have no comments components. `{ mark: "pen" }` draws suggestions with a
60
+ * hand-drawn pen unless one sets its own `mark`.
61
+ */
62
+ comments?: CommentsOptions | boolean;
57
63
  /** Sends each diagram's source to `https://kroki.io` unless you pass your own `server`, or `{ draw: false }`. */
58
64
  diagrams?: DiagramsOptions | boolean;
59
65
  /** Draws `mermaid` fences with comark-pele, on the server and offline. */
@@ -122,6 +128,7 @@ type Renderer<C> = {
122
128
  charts: Part<C, ChartsOptions>;
123
129
  chips: Part<C, ChipsOptions>;
124
130
  colors: Part<C>;
131
+ comments?: Part<C, CommentsOptions>;
125
132
  diagrams: Part<C, DiagramsOptions>;
126
133
  mermaid: Part<C, PeleConfig>;
127
134
  diff?: Part<C>;
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-jkwx6SyG.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";
3
3
  export { AnyPlugin, Preset, PresetOptions, Renderer, TYPESET_TAG, criticCss, preset, typeset, typesetCss };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  import { t as typesetCss } from "./typeset-css-5aJ7cSmh.mjs";
2
- import { i as typeset, n as preset, r as TYPESET_TAG, t as criticCss } from "./src-DROB05U6.mjs";
2
+ import { i as typeset, n as preset, r as TYPESET_TAG, t as criticCss } from "./src-PkmYCSNu.mjs";
3
3
  export { TYPESET_TAG, criticCss, preset, typeset, typesetCss };
package/dist/react.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import { a as criticCss, n as Preset, r as PresetOptions } from "./index-jkwx6SyG.mjs";
1
+ import { a as criticCss, n as Preset, r as PresetOptions } from "./index-BUDHsvnm.mjs";
2
2
  import { ComponentType } from "react";
3
3
  //#region src/react.d.ts
4
4
  type AnyComponent = ComponentType<any>;
5
- /** Every plugin with components for `@comark/react`, which leaves out annotate, diff, and quiz. */
5
+ /** Every plugin with components for `@comark/react`, which leaves out annotate, comments, diff, and quiz. */
6
6
  declare const _default: (options?: PresetOptions) => Preset<AnyComponent>;
7
7
  //#endregion
8
8
  export { type PresetOptions, criticCss, _default as default };
package/dist/react.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as typesetCss } from "./typeset-css-5aJ7cSmh.mjs";
2
- import { n as preset, t as criticCss } from "./src-DROB05U6.mjs";
2
+ import { n as preset, t as criticCss } from "./src-PkmYCSNu.mjs";
3
3
  import { i as startMermaid, n as mermaidBar, t as addMermaidStyles } from "./client-Bjd6VcGQ.mjs";
4
4
  import { createElement, useEffect } from "react";
5
5
  import * as badge from "comark-badge/react";
@@ -57,7 +57,7 @@ const typeset = () => createElement("style", {
57
57
  "data-comark-typeset": "",
58
58
  dangerouslySetInnerHTML: { __html: typesetCss }
59
59
  });
60
- /** Every plugin with components for `@comark/react`, which leaves out annotate, diff, and quiz. */
60
+ /** Every plugin with components for `@comark/react`, which leaves out annotate, comments, diff, and quiz. */
61
61
  var react_default = (options) => preset({
62
62
  badge,
63
63
  cards,
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: before-after-evidence
3
+ description: Shows a visible change as two comparable screenshots, before and after, with marks measured from the source and checked in the rendered page. Use when a pull request, bug fix, or design change alters what people see, or when someone asks for before/after screenshots or visual evidence.
4
+ license: MIT
5
+ ---
6
+
7
+ # Before/after evidence
8
+
9
+ A before/after is evidence when a reviewer can check every claim against the two images and nothing else. Three things make it so, and the reader can't repair any of them: two captures of the same view, marks that sit on what changed, and notes in the words the screen shows.
10
+
11
+ This skill writes the document. Where it's published, and who can open it, is up to your host.
12
+
13
+ ## 1. Capture a comparable pair
14
+
15
+ Take **after** from the branch or its preview, and **before** from a deployment or commit that still behaves the old way. Capture both with the same viewport, zoom, theme, data, scroll position, and open menus, so the change is the only difference.
16
+
17
+ - Set up the state that shows the change before you capture: the long name that wrapped, the error that stayed hidden, the empty list.
18
+ - Clip both captures to one region around the change, the same rectangle on each side. A `::compare` gives each image under half the page width, where a full-page capture's text is too small to read.
19
+ - Pin anything that moves the layout between the two states, such as a dialog centered vertically that grows by one line, so the same element sits at the same place in both.
20
+
21
+ If one side can't be captured comparably, stop and say what blocked you. A description in place of a screenshot, or one side alone, isn't before/after evidence.
22
+
23
+ Done when both images exist, have the same size, and differ only where the change is.
24
+
25
+ ## 2. Measure every mark
26
+
27
+ Marks take `x`, `y`, `w`, and `h` as percentages of the image. Measure them: an estimate drifts a few percent, and on a half-width image that's the neighbouring button.
28
+
29
+ - **A page you captured:** read the element's box in the same browser, viewport, and state, minus the clip's offset. [references/measuring.md](references/measuring.md) has the snippet.
30
+ - **A still you didn't capture**, such as a frame from a screen recording, a design export, or an image attached to a bug report: there is no DOM to ask. Measure in image pixels and divide by the image's natural width and height. Confirm each box by cropping the image to it and looking at the crop, as the same reference shows.
31
+
32
+ Mark the change at its own size: the field, the label, the button. Use `red` on the before side for the problem and `green` on the after side for the fix, and leave what stayed the same unmarked. Two or three marks a side usually tell the whole story.
33
+
34
+ Done when every mark has numbers you measured, and you can name the element or the pixel rectangle each came from.
35
+
36
+ ## 3. Write the document
37
+
38
+ Start from [references/example.md](references/example.md) and keep its shape:
39
+
40
+ 1. One sentence: what changed, and for whom.
41
+ 2. One line of steps to reach the screen, so a reviewer can reproduce it.
42
+ 3. The `::compare`, each note a few words in the screen's own words. A value the screenshot doesn't show stays out of its note.
43
+ 4. A `::diff` of the line that caused it, only when the reader would otherwise ask.
44
+
45
+ The images carry the evidence, so the text only points into them. How the work went (the checks you ran, retries, CI) goes in your report to the user, not in the document. [references/blocks.md](references/blocks.md) has the syntax of each block.
46
+
47
+ Image `src` must be a URL the renderer can reach: a path next to the document, or an https URL your host gives you for the upload.
48
+
49
+ ## 4. Check the render
50
+
51
+ 1. Lint it, and fix until it reports no problems:
52
+
53
+ ```sh
54
+ vp dlx --package comark-linter --package comark-ui lint-comark evidence.md
55
+ ```
56
+
57
+ These commands use the [global Vite+ CLI](https://viteplus.dev/guide/global-cli). Without it, `pnpm dlx` takes the same arguments.
58
+
59
+ 2. Open the page where it will be read and take a screenshot of it. For a local screenshot-only check, copy the complete `::compare` block, including its nested screenshots and annotations, into `evidence-screenshots.md` beside `evidence.md`.
60
+
61
+ Ensure comark-annotate is a direct dependency of this workspace package. If it is only transitive, read the installed Comark UI version and add that exact version with the project's package manager: for pnpm, `pnpm add -D comark-annotate@<version>`, substituting that version. Add `-w` when installing at the workspace root. With no Comark UI packages installed, omit `@<version>`. This links the executable without fetching a different renderer release via `@latest`. Then run:
62
+
63
+ ```sh
64
+ vp exec comark-annotate render evidence-screenshots.md -o evidence-screenshots.html
65
+ ```
66
+
67
+ Without Vite+, use `pnpm exec` with the same arguments.
68
+
69
+ Open `evidence-screenshots.html` and take a screenshot of it. This CLI renders annotate, carousel, and zoom only; check any `::diff` or other blocks in the host's full Comark UI preview.
70
+ 3. Check that each mark sits on its target and each note matches what its side shows. Measure a mark that misses again, from the source, since a box moved by eye stays a guess.
71
+
72
+ Done when you've looked at the rendered page and every mark lands. Name any mark or block you couldn't check in your report.
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "Before/after evidence"
3
+ short_description: "Show a visible change with comparable, measured screenshots"
@@ -0,0 +1,54 @@
1
+ # Blocks for before/after evidence
2
+
3
+ These blocks come with `comark-ui`, or alone with `comark-annotate` and `comark-diff`. The comark-ui skill (`vp dlx skills add onmax/comark-ui`) documents every block in full.
4
+
5
+ ## `::compare`
6
+
7
+ Two `:::screenshot` blocks inside, before then after. They're titled Before and After unless they set `title`, and their notes are numbered across both.
8
+
9
+ | Prop | What it does |
10
+ | --- | --- |
11
+ | `title` | Names the comparison for screen readers. |
12
+ | `mode` | `columns` (default) side by side, or `slider`: one full-width image with a divider to drag. Use `slider` when the change is small and in the same spot, such as one label. |
13
+
14
+ ## `:::screenshot`
15
+
16
+ | Prop | What it does |
17
+ | --- | --- |
18
+ | `src` | Required. The image URL. |
19
+ | `alt` | Required. What the image shows, in one phrase. |
20
+ | `viewport` | The capture's size, like `640x420`. Set the same on both sides; a compare reports a mismatch. |
21
+ | `href` | The page you captured, such as the preview deployment, linked by its host above the image. |
22
+ | `title` | A heading above the image, in place of Before or After. |
23
+
24
+ Other Markdown inside the block, after its annotations, becomes the caption.
25
+
26
+ ## `::::annotation`
27
+
28
+ A direct child of a screenshot. Its content is the note, in Markdown.
29
+
30
+ | Prop | What it does |
31
+ | --- | --- |
32
+ | `x` `y` `w` `h` | Required. The marked rectangle as percentages of the image, without `%`. |
33
+ | `mark` | `box` (default), `circle`, `underline`, `highlight`, `bracket`, `cross`, `check`, or `none`. |
34
+ | `color` | `red` for a problem, `green` for the fix, `amber` for a warning, `violet` (default) to point something out, `gray`, or a hex color. |
35
+ | `side` | `top` or `bottom` moves the note into the margin with an arrow; in a side-by-side compare, `left` and `right` notes join the numbered list. |
36
+
37
+ Notes without a `side` are numbered under their image, which is the clearest default in a compare.
38
+
39
+ ## `::diff`
40
+
41
+ Two fenced blocks inside, the file before and after, starting at the same line.
42
+
43
+ ````md
44
+ ::diff{line=42 label="The change"}
45
+ ```tsx [src/members/InviteDialog.tsx]
46
+ <button onClick={send}>Send invite</button>
47
+ ```
48
+ ```tsx
49
+ <button onClick={send} disabled={invalid}>Send invite</button>
50
+ ```
51
+ ::
52
+ ````
53
+
54
+ `line` is the file's line number of the first line in both blocks. Keep a diff to the few lines that caused the change; the pull request has the rest.
@@ -0,0 +1,37 @@
1
+ The invite dialog now says what's wrong with an address, and waits for a valid one before it sends.
2
+
3
+ Open **Settings › Members**, select **Invite**, type `maria@acme`, and press Tab.
4
+
5
+ ::compare{title="Invite dialog with an incomplete address"}
6
+ :::screenshot{src="https://comark-ui.onmax.me/skill-invite-before.png" alt="Invite dialog with a red email field and no message" viewport="640x420"}
7
+ ::::annotation{x=8.3 y=42.9 w=60.6 h=12.8 color="red"}
8
+ Only the border turns red. Nothing says what to fix.
9
+ ::::
10
+
11
+ ::::annotation{x=72 y=63.5 w=19.7 h=11.5 color="red"}
12
+ **Send invite** still sends to `maria@acme`.
13
+ ::::
14
+ :::
15
+
16
+ :::screenshot{src="https://comark-ui.onmax.me/skill-invite-after.png" alt="Invite dialog with an error under the email field and a disabled Send invite button" viewport="640x420" href="https://pr-218.preview.acme.example/settings/members"}
17
+ ::::annotation{x=8.3 y=58.3 w=49 h=5.8 mark="underline" color="green"}
18
+ "Add the domain, like maria@acme.com"
19
+ ::::
20
+
21
+ ::::annotation{x=72 y=71.8 w=19.7 h=11.5 color="green"}
22
+ **Send invite** waits for a valid address.
23
+ ::::
24
+ :::
25
+ ::
26
+
27
+ ::diff{line=42 label="The change"}
28
+ ```tsx [src/members/InviteDialog.tsx]
29
+ <input id="email" aria-invalid={invalid} value={email} onChange={edit} />
30
+ <button className="primary" onClick={send}>Send invite</button>
31
+ ```
32
+ ```tsx
33
+ <input id="email" aria-invalid={invalid} aria-describedby="email-error" value={email} onChange={edit} />
34
+ {invalid && <p id="email-error" className="error">Add the domain, like {suggestion}</p>}
35
+ <button className="primary" onClick={send} disabled={invalid}>Send invite</button>
36
+ ```
37
+ ::
@@ -0,0 +1,50 @@
1
+ # Measuring marks
2
+
3
+ Every mark is `x y w h`, each a percentage of the image from 0 to 100. Measure in the same coordinates the image was captured in.
4
+
5
+ ## A page you captured
6
+
7
+ Capture both states with one clip, then read each element's box in the same page, before anything moves:
8
+
9
+ ```js
10
+ // Playwright: one clip for both sides, so the same element sits at the same place.
11
+ const clip = { x: 56, y: 12, width: 528, height: 312 };
12
+ await page.screenshot({ path: "after.png", clip });
13
+
14
+ const box = await page.$eval("#email", (el, clip) => {
15
+ const r = el.getBoundingClientRect();
16
+ return [
17
+ ((r.x - clip.x) / clip.width) * 100,
18
+ ((r.y - clip.y) / clip.height) * 100,
19
+ (r.width / clip.width) * 100,
20
+ (r.height / clip.height) * 100,
21
+ ].map((v) => +v.toFixed(1));
22
+ }, clip);
23
+ // box is [x, y, w, h] for the annotation.
24
+ ```
25
+
26
+ - Without a clip, divide by `innerWidth` and `innerHeight` and subtract nothing.
27
+ - For a full-page capture, add `scrollX` and `scrollY` to the box and divide by `document.documentElement.scrollWidth` and `scrollHeight`.
28
+ - An element that spans its container, such as a block paragraph, measures as wide as the container. Measure the text instead: give it `width: fit-content` while you capture, or measure a `Range` around its text.
29
+ - If an element crosses the clip's edge, cut its box at the edge, so every value stays between 0 and 100.
30
+
31
+ ## A still you didn't capture
32
+
33
+ A frame from a screen recording, a design export, or an image attached to an issue has no DOM. Measure in pixels:
34
+
35
+ 1. Read the image's natural size, such as with `magick identify frame.png` or `file frame.png`.
36
+ 2. Find the target's rectangle in pixels in an image viewer that shows the pointer's coordinates.
37
+ 3. Divide: `x = left / width * 100`, `y = top / height * 100`, `w = boxWidth / width * 100`, `h = boxHeight / height * 100`.
38
+ 4. Crop the image to that rectangle and look at the crop. It should show the target and little else:
39
+
40
+ ```sh
41
+ magick frame.png -crop 320x38+44+134 +repage crop.png
42
+ ```
43
+
44
+ With Python and Pillow, `Image.open("frame.png").crop((44, 134, 364, 172)).save("crop.png")` does the same.
45
+
46
+ For a pair of video frames, take both at the same playback size and use the same crop for both, as you would clip two page captures.
47
+
48
+ ## In the render
49
+
50
+ The rendered page is the last check. A mark that misses there has the wrong numbers: measure it again from the source.
@@ -15,6 +15,8 @@ Prefer `comark-ui`, every plugin in one install, registered in the order they ne
15
15
  pnpm add comark @comark/html comark-ui
16
16
  ```
17
17
 
18
+ Run the comark CLIs with the [global Vite+ CLI](https://viteplus.dev/guide/global-cli): `vp dlx` for a package the project doesn't install, `vp exec` for one it does. Without Vite+, `pnpm dlx` and `pnpm exec` take the same arguments.
19
+
18
20
  ```ts
19
21
  import { createHtmlRenderer } from "@comark/html";
20
22
  import comarkUi from "comark-ui/html";
@@ -43,6 +45,10 @@ Either way, the HTML renderer inlines the styles once per document, and the Vue,
43
45
 
44
46
  Problems land in `meta.issues` after `parseMarkdown`, one sentence each, and a host can refuse a document while any remain. For untrusted input, add Comark's `security` plugin with `blockedTags` such as `script`, `style`, and `iframe`; it cleans the Markdown inside blocks too.
45
47
 
48
+ ## Shape the document
49
+
50
+ This skill teaches the blocks. Four sibling skills teach a whole document, what goes in it and in what order: `before-after-evidence`, `review-document`, `visual-explanation`, and `teach-lesson`. When the user asks for one of those and the skill isn't installed, suggest `vp dlx skills add onmax/comark-ui` and picking it from the list.
51
+
46
52
  ## Pick the blocks
47
53
 
48
54
  Read the reference for each block you use before you write it. Mix the blocks freely with ordinary Markdown, such as headings, tables, and lists.
@@ -59,6 +65,7 @@ Read the reference for each block you use before you write it. Mix the blocks fr
59
65
  | Links and `@mentions` with the site's favicon or the person's avatar | links, `@user`, `:chip` | [chips](references/chips.md) |
60
66
  | Colors, such as design tokens before and after, or a palette | a color in inline code, `::palette` | [colors](references/colors.md) |
61
67
  | A suggested change to one file, before and after | `::diff` | [diff](references/diff.md) |
68
+ | Suggested edits and comment threads on prose, such as a copy review, each note in a card in the margin | `:suggestion`, `:comment` | [comments](references/comments.md) |
62
69
  | A video, a design file, or a live reproduction from its link | `::embed` | [embed](references/embed.md) |
63
70
  | A screen recording or a sound that a screenshot can't show | `![alt](clip.mp4)` | [media](references/media.md) |
64
71
  | A number before and after, a table of befores and afters, or progress | `:delta`, `::stats`, `:progress` | [metrics](references/metrics.md) |
@@ -134,5 +141,5 @@ Mark only what your text talks about. Each note says what changed or what is wro
134
141
 
135
142
  ## Check the result
136
143
 
137
- 1. Lint the file: `npx lint-comark report.md`, in a project with `comark-linter` and the plugins installed, where `comark-ui` counts as every plugin. It prints one line per problem with its line, its rule, and how to fix it, and exits with 1 while any remain. Fix every one, and run it again until it exits with 0. The [lint reference](references/lint.md) covers its flags, its config file, the library, ESLint, and Vite Doctor.
144
+ 1. Lint the file: `vp exec lint-comark report.md`, in a project with `comark-linter` and the plugins installed, where `comark-ui` counts as every plugin. It prints one line per problem with its line, its rule, and how to fix it, and exits with 1 while any remain. Fix every one, and run it again until it exits with 0. The [lint reference](references/lint.md) covers its flags, its config file, the library, ESLint, and Vite Doctor.
138
145
  2. Look at the render, made as the block's reference says. Open it in a browser and take a screenshot: each mark sits on its target, each number matches its note, and each chart says what your text says. If you can't verify something, say so when you hand the document over instead of guessing.
@@ -53,11 +53,13 @@ For a clipped capture, `getBoundingClientRect()` and Playwright's main-frame `cl
53
53
 
54
54
  ## Preview
55
55
 
56
+ Ensure comark-annotate is a direct dependency of the workspace package where you run the CLI. If it is only transitive, read the installed Comark UI version and add that exact version with the project's package manager: for pnpm, `pnpm add -D comark-annotate@<version>`, substituting that version. Add `-w` when installing at the workspace root. With no Comark UI packages installed, omit `@<version>`. This links the executable without fetching a different renderer release via `@latest`.
57
+
56
58
  ```sh
57
- npx comark-annotate render report.md -o report.html
59
+ vp exec comark-annotate render report.md -o report.html
58
60
  ```
59
61
 
60
- `render` writes a standalone page of the screenshots and compares, and relative `src` paths resolve next to it. Without comark-linter, `npx 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.
62
+ `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.
61
63
 
62
64
  ## Register
63
65
 
@@ -0,0 +1,43 @@
1
+ # Suggestions and comments
2
+
3
+ comark-comments draws suggested edits and comments on a span of prose, each with its note in a card in the margin beside its line, as in a Google Docs or Word review. Use it to review copy or a docs page, where each change needs a reason and a comment can get a reply. For marks with no notes or margin, which a host can also accept or reject, use [critic](critic.md). For a change to code, write a `::diff`.
4
+
5
+ ## Syntax
6
+
7
+ ```md
8
+ To :suggestion[sign in]{from="log in" by="Claude" note="The button says Sign in."}, enter your email.
9
+
10
+ :suggestion[]{from="simply" by="Claude" note="“Simply” tells a stuck reader it should have been easy."} Enter the email you signed up with.
11
+
12
+ The link expires after :comment[15 minutes]{#ttl by="@onmax" note="Is 15 minutes enough when email is slow?"}.
13
+
14
+ :comment{reply="ttl" by="Claude" note="Keeping 15. The email has a resend button."}
15
+ ```
16
+
17
+ | Write | Is |
18
+ | --- | --- |
19
+ | `:suggestion[new]{from="old"}` | A replacement: `old` struck, `new` inserted |
20
+ | `:suggestion[]{from="old"}` or `:suggestion{from="old"}` | A deletion |
21
+ | `:suggestion[new]` | An insertion |
22
+ | `:comment[words]{note="…"}` | A comment on `words` |
23
+ | `:comment{reply="id" note="…"}` | A reply to the comment or suggestion with `#id` |
24
+
25
+ | Prop | On | What it does |
26
+ | --- | --- | --- |
27
+ | `from` | suggestion | The text it replaces or deletes. Plain text. |
28
+ | `by` | both, reply | The author, shown as written; a leading `@` is dropped. The avatar is the name's initial. |
29
+ | `note` | both, reply | The card's text. Plain text. A suggestion with no note and no replies is only a redline, with no card. |
30
+ | `mark` | suggestion | `track` (default): red strike, green insert. `pen`: a hand-drawn strike with the new words handwritten above. |
31
+ | `#id` | both | The id a reply points at. Comments and suggestions share one id space. |
32
+ | `reply` | reply | The `#id` of the thread it joins. |
33
+
34
+ - A reply can sit anywhere in the document; it moves into its thread, and the paragraph it leaves empty is dropped. Put replies after the paragraph, or at the end.
35
+ - Pen fits short changes only: both sides 24 characters or fewer, on one line, and plain text. Anything else draws as `track`, with no issue.
36
+ - Write suggestions and comments in paragraphs and list items. In a heading or a table cell, and inside another one, they draw without a card, and the linter reports them.
37
+ - On a page 50rem wide or more, each card sits in the right margin level with its line. On a narrow page the reader clicks a bubble to open its card under the line.
38
+ - Don't overlap two anchors. Mark the words once, and reply to the thread.
39
+
40
+ ## Register
41
+
42
+ - In `comark-ui`: on, as `comments`, in `comark-ui/html` only. `comments: { mark: "pen" }` draws every suggestion with the pen unless it sets its own `mark`.
43
+ - Alone: `pnpm add comark @comark/html comark-comments`, then `createHtmlRenderer({ plugins: [comments()], components })` with `comments, { components }` from `comark-comments/html`. There are no Vue, React, or Svelte entries.
@@ -5,7 +5,7 @@ comark-linter reports what Comark forgives, such as a `::` block never closed, a
5
5
  ## Run the command
6
6
 
7
7
  ```sh
8
- npx lint-comark "docs/**/*.md" --format json --check-urls
8
+ vp exec lint-comark "docs/**/*.md" --format json --check-urls
9
9
  ```
10
10
 
11
11
  - Pass files or globs. Quote a glob so the shell passes it as written; lint-comark expands it and skips `node_modules` and `dist`.
@@ -37,7 +37,7 @@ Promise callbacks are microtasks, and a timer's callback is a task.
37
37
 
38
38
  A question uses radios when one option is marked `[x]`; `multiple` makes it a checkbox question. Options are shuffled deterministically unless `shuffle="false"`. Questions and recall cards share numbering, while polls are not numbered. A missing id is derived from the block content. Use `#hint` and `#explain` on questions, and `#answer` on recall cards. Polls accept `multiple` and a date in `closes`.
39
39
 
40
- The HTML renderer inlines the quiz script and styles. Hosts can listen for `comark-quiz:answer` and `comark-quiz:ready`, and restore answers or results with `comark-quiz:state`; see the package [getting started guide](../../packages/quiz/docs/getting-started.md) for the event shapes and storage behavior.
40
+ The HTML renderer inlines the quiz script and styles. Hosts can listen for `comark-quiz:answer` and `comark-quiz:ready`, and restore answers or results with `comark-quiz:state`; see [Saving answers](https://comark-ui.onmax.me/quiz/#saving-answers) on its page for the event shapes and storage behavior.
41
41
 
42
42
  ## Register
43
43
 
@@ -36,7 +36,7 @@ comarkUi({
36
36
  | `@comark/react` | `comark-ui/react` |
37
37
  | `@comark/svelte` | `comark-ui/svelte` |
38
38
 
39
- The Vue, React, and Svelte entries leave out annotate and diff, which render only to HTML. Screenshots, compares, diffs, and the marks on charts need `comark-ui/html`.
39
+ The 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`.
40
40
 
41
41
  To 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.
42
42
 
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: review-document
3
+ description: Turns a review's findings into one short Markdown document a reader can act on, with the verdict first and each finding ranked, located, backed by evidence, and paired with its fix. Use when writing up a code review, a design or QA review, an audit, or any report whose reader must decide what to do next.
4
+ license: MIT
5
+ ---
6
+
7
+ # Review document
8
+
9
+ A review's reader has one question: what do I do now? Answer it in the first two lines, then give each finding just enough evidence that the reader trusts it without redoing your work. This skill organizes findings you already have; finding them is the review itself.
10
+
11
+ Length is the usual failure. A reader who has to dig through praise, process, and restated findings misses the one that blocks the merge. Every line below the verdict either supports a finding or says what you didn't check.
12
+
13
+ ## 1. Decide the verdict
14
+
15
+ Pick one: **approve**, **approve with changes**, **request changes**, or **blocked** on a named thing. Under it, write the reason in one sentence that names the finding behind it.
16
+
17
+ Done when someone who reads only the verdict knows what to do.
18
+
19
+ ## 2. Keep the findings that change the decision
20
+
21
+ - Keep a finding when fixing it, or not, changes what the reader should do.
22
+ - Merge findings with one root cause into one, and list every place it appears.
23
+ - Rank each one: **blocking** (wrong results, lost data, a security hole, broken for users), **should fix** (a real cost that can wait), or **nit**, only when the reader asked for them.
24
+
25
+ Order them blocking first. Done when every finding has a rank and no two share a cause.
26
+
27
+ ## 3. Back each finding
28
+
29
+ Each finding is four parts, in this order:
30
+
31
+ 1. **A title that states the consequence**, for whom: "Small avatars load the 512px image", not "Cache key issue".
32
+ 2. **Where**: the file and line, linked when there's a URL.
33
+ 3. **Evidence**, the strongest you have: a failing test or command you ran (`::tests`, a fenced block of output), a screenshot of the wrong state (measured as the before-after-evidence skill describes), the lines that cause it (a fence with the line highlighted), then reasoning. Say which it is: a finding you reproduced reads differently from one you read in the code.
34
+ 4. **The fix**: a `::diff` of the smallest change, or one sentence when the fix is a decision for the reader.
35
+
36
+ Done when every blocking finding has evidence you ran or captured, or says plainly that it comes from reading the code.
37
+
38
+ ## 4. Say what you checked
39
+
40
+ End with two short lists: what you checked and how, and what you didn't check. A review that implies more coverage than it had loses the reader's trust in the parts that were real.
41
+
42
+ ## 5. Write it
43
+
44
+ Follow [references/example.md](references/example.md):
45
+
46
+ - The verdict in a callout: `> [!CAUTION]` for request changes or blocked, `> [!WARNING]` for approve with changes, `> [!TIP]` for approve.
47
+ - One `##` heading per finding, numbered, with its rank in the heading. About a dozen lines each, evidence included.
48
+ - No summary that repeats the findings, no section for an empty rank, no list of what's good unless the reader asked.
49
+
50
+ [references/blocks.md](references/blocks.md) has the syntax for the callout, `::tests`, `::diff`, and highlighted lines.
51
+
52
+ ## 6. Check the render
53
+
54
+ 1. Lint it, and fix until it reports no problems:
55
+
56
+ ```sh
57
+ vp dlx --package comark-linter --package comark-ui lint-comark review.md
58
+ ```
59
+
60
+ These commands use the [global Vite+ CLI](https://viteplus.dev/guide/global-cli). Without it, `pnpm dlx` takes the same arguments.
61
+
62
+ 2. Open the rendered page where it will be read and read it top to bottom as the reader would. Each finding's evidence should be visible without expanding anything except a long log, and each `::diff` should start at the line its finding names.
63
+
64
+ Done when the page renders without problems and you've read it once as the reader.
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "Review document"
3
+ short_description: "Write findings as a verdict, evidence, and fixes"