comark-ui 0.8.0 → 0.8.2
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/README.md +4 -2
- package/dist/{client-BhzMlpun.mjs → client-kUEiRbtp.mjs} +11 -4
- package/dist/client.d.mts +2 -2
- package/dist/client.mjs +3 -3
- package/dist/{editor-ASZBrUYa.mjs → editor-9IcfELjG.mjs} +98 -5
- package/dist/editor-vue.d.mts +1 -1
- package/dist/editor-vue.mjs +2 -5
- package/dist/{editor-KD97dL_1.d.mts → editor-yoVL7Ajq.d.mts} +27 -3
- package/dist/editor.d.mts +2 -2
- package/dist/editor.mjs +1 -1
- package/dist/html.d.mts +2 -2
- package/dist/html.mjs +4 -4
- package/dist/{index-DVGSDzBS.d.mts → index-BTyvRIPX.d.mts} +27 -5
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -3
- package/dist/nodes-CwDBFXnO.mjs +5 -0
- package/dist/react.d.mts +2 -2
- package/dist/react.mjs +4 -4
- package/dist/skills/comark-ui/SKILL.md +2 -0
- package/dist/skills/comark-ui/references/media.md +2 -2
- package/dist/skills/comark-ui/references/remark-to-comark.md +29 -0
- package/dist/skills.mjs +7 -3
- package/dist/{src-PkmYCSNu.mjs → src-Baygj6ZQ.mjs} +101 -3
- package/dist/svelte/index.d.ts +1 -1
- package/dist/svelte/index.js +1 -1
- package/dist/{typeset-css-5aJ7cSmh.mjs → typeset-css-BYvWbqWz.mjs} +22 -7
- package/dist/{typeset-css-DdOGL7WF.d.mts → typeset-css-DtOLAa1Z.d.mts} +7 -1
- package/dist/typeset.css +1 -0
- package/dist/vue.d.mts +2 -2
- package/dist/vue.mjs +4 -4
- package/package.json +50 -47
package/README.md
CHANGED
|
@@ -29,7 +29,9 @@ comarkUi({
|
|
|
29
29
|
});
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
`include` is off because it reads files from disk; turn it on to paste files into a document. `cast`, `table`, and `tests` are on but read no files until you pass `{ root }` or `{ read }`. When you parse in a browser, pass `chips: { download: false }`, since a browser may not download another site's images. comark-critic has no component for its styles, so put the exported `criticCss` in the page. The text around the blocks (headings, paragraphs, lists, tables, code, and quotes) is styled too, from shadcn/typeset on the same tokens and scoped to the document; pass `typeset: false` when your site already styles Markdown. See [Typeset](https://comark-ui.onmax.me/guide/typeset/).
|
|
32
|
+
`include` is off because it reads files from disk; turn it on to paste files into a document. `cast`, `table`, and `tests` are on but read no files until you pass `{ root }` or `{ read }`. When you parse in a browser, pass `chips: { download: false }`, since a browser may not download another site's images. comark-critic has no component for its styles, so put the exported `criticCss` in the page. The text around the blocks (headings, paragraphs, lists, tables, code, and quotes) is styled too, from shadcn/typeset on the same tokens and scoped to the document; pass `typeset: false` when your site already styles Markdown. For content outside a document, such as an editor, import `comark-ui/typeset.css` and add the `comark-typeset` class. See [Typeset](https://comark-ui.onmax.me/guide/typeset/).
|
|
33
|
+
|
|
34
|
+
It also returns `tags` and `blocks`. `tags` is every element a parsed document can hold besides the components; with the components' names, it's the allowlist for Comark's `security` plugin. `blocks` are the blocks the plugins replace while parsing, such as `::code-group`, which a linter needs beside the components' names.
|
|
33
35
|
|
|
34
36
|
## Renderers
|
|
35
37
|
|
|
@@ -54,7 +56,7 @@ Vue, React, and Svelte leave out annotate and diff, which render only to HTML.
|
|
|
54
56
|
| `fromMarkdown`, `toMarkdown` | Convert between Markdown and the editor's JSON with Comark's own parser and writer. Front matter stays beside the document. |
|
|
55
57
|
| `checkMarkdown(markdown, { plugins })` | Whether the editor can save the document without changing what readers see, judged with the plugins the page renders with. A document it can't keep opens read-only. |
|
|
56
58
|
| `Upload` | Uploads pasted and dropped files. Each shows a placeholder with its progress until `upload(file, progress)` returns its URL. |
|
|
57
|
-
| `createEditorCodec({ plugins })` | `{ extensions, fromMarkdown, toMarkdown, verify }` for a collaborative room, such as ViteHub Realtime's `editor` option. |
|
|
59
|
+
| `createEditorCodec({ plugins })` | `{ extensions, split, join, fromMarkdown, toMarkdown, verify }` for a collaborative room, such as ViteHub Realtime's `editor` option. A room keeps the body as the editor's document and the frontmatter as its fields, so a text edit never overwrites the metadata. |
|
|
58
60
|
|
|
59
61
|
`comark-ui/editor/vue` binds the editor to a Markdown string with `useComarkEditor(markdown)` or `<ComarkEditor v-model="markdown" />`. Run `pnpm playground` in this package to try it.
|
|
60
62
|
|
|
@@ -178,8 +178,6 @@ function addStyles(name, css) {
|
|
|
178
178
|
style.textContent = css;
|
|
179
179
|
document.head.append(style);
|
|
180
180
|
}
|
|
181
|
-
//#endregion
|
|
182
|
-
//#region src/client.ts
|
|
183
181
|
/**
|
|
184
182
|
* comark-pele's diagrams on the shared `--comark-*` tokens, on a card like comark-diagrams'. Pele paints with its
|
|
185
183
|
* `--pele-*` variables, so setting them on the wrapper themes every diagram, light and dark, without drawing it
|
|
@@ -187,8 +185,17 @@ function addStyles(name, css) {
|
|
|
187
185
|
*/
|
|
188
186
|
const mermaidCss = `@layer comark{${[
|
|
189
187
|
theme(".cmm,.pele-diagram"),
|
|
190
|
-
theme(":root", "status"),
|
|
191
|
-
`:where(:root){--pele-bg:var(--_comark-background);--pele-fg:var(--_comark-foreground);--pele-muted:var(--_comark-muted);--pele-line:var(--_comark-muted);--pele-surface:var(--_comark-accent);--pele-surface-alt:color-mix(in srgb,var(--_comark-accent),var(--_comark-foreground) 6%);--pele-border:var(--_comark-border);--pele-accent:var(--
|
|
188
|
+
theme(":root", "status", "primary"),
|
|
189
|
+
`:where(:root){--pele-bg:var(--_comark-background);--pele-fg:var(--_comark-foreground);--pele-muted:var(--_comark-muted);--pele-line:var(--_comark-muted);--pele-surface:var(--_comark-accent);--pele-surface-alt:color-mix(in srgb,var(--_comark-accent),var(--_comark-foreground) 6%);--pele-border:var(--_comark-border);--pele-accent:var(--_comark-primary);--pele-critical:var(--_comark-danger);--pele-error:var(--_comark-danger);--pele-font:var(--_comark-font);--pele-radius:calc(var(--_comark-radius) - 4px);${[
|
|
190
|
+
"#3b82f6",
|
|
191
|
+
"#f97316",
|
|
192
|
+
"#10b981",
|
|
193
|
+
"#a855f7",
|
|
194
|
+
"#f43f5e",
|
|
195
|
+
"#eab308",
|
|
196
|
+
"#06b6d4",
|
|
197
|
+
"#ec4899"
|
|
198
|
+
].map((hex, index) => `--pele-series-${index + 1}:var(--comark-chart-${index + 1},var(--ui-chart-${index + 1},var(--chart-${index + 1},${hex})))`).join(";")}}`,
|
|
192
199
|
".pele-diagram{box-sizing:border-box;margin-block:1.5rem;padding:1rem;overflow-x:auto;border:1px solid var(--_comark-border);border-radius:var(--_comark-radius);background:var(--_comark-background);color:var(--_comark-foreground);text-align:center}",
|
|
193
200
|
".pele-diagram>svg{min-width:min(28rem,var(--cmm-svg,28rem))}",
|
|
194
201
|
".pele-source{margin:0;color:var(--_comark-muted);text-align:left}",
|
package/dist/client.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as typesetCss } from "./typeset-css-
|
|
1
|
+
import { n as typesetStylesheet, t as typesetCss } from "./typeset-css-DtOLAa1Z.mjs";
|
|
2
2
|
//#region src/client.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* comark-pele's diagrams on the shared `--comark-*` tokens, on a card like comark-diagrams'. Pele paints with its
|
|
@@ -19,4 +19,4 @@ export declare function mermaidBar(): string;
|
|
|
19
19
|
*/
|
|
20
20
|
export declare function startMermaid(): () => void;
|
|
21
21
|
//#endregion
|
|
22
|
-
export { typesetCss };
|
|
22
|
+
export { typesetCss, typesetStylesheet };
|
package/dist/client.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as typesetCss } from "./typeset-css-
|
|
2
|
-
import { i as startMermaid, n as mermaidBar, r as mermaidCss, t as addMermaidStyles } from "./client-
|
|
3
|
-
export { addMermaidStyles, mermaidBar, mermaidCss, startMermaid, typesetCss };
|
|
1
|
+
import { n as typesetStylesheet, t as typesetCss } from "./typeset-css-BYvWbqWz.mjs";
|
|
2
|
+
import { i as startMermaid, n as mermaidBar, r as mermaidCss, t as addMermaidStyles } from "./client-kUEiRbtp.mjs";
|
|
3
|
+
export { addMermaidStyles, mermaidBar, mermaidCss, startMermaid, typesetCss, typesetStylesheet };
|
|
@@ -9,7 +9,8 @@ import Image from "@tiptap/extension-image";
|
|
|
9
9
|
import { TaskItem, TaskList } from "@tiptap/extension-list";
|
|
10
10
|
import { TableKit } from "@tiptap/extension-table";
|
|
11
11
|
import StarterKit from "@tiptap/starter-kit";
|
|
12
|
-
import {
|
|
12
|
+
import { parseFrontmatter } from "comark/parse";
|
|
13
|
+
import { renderFrontmatter, renderMarkdown } from "comark/render";
|
|
13
14
|
import { indent, textContent } from "comark/utils";
|
|
14
15
|
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
15
16
|
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
@@ -1054,16 +1055,90 @@ async function fromMarkdown(markdown) {
|
|
|
1054
1055
|
async function toMarkdown(doc, options = {}) {
|
|
1055
1056
|
const markdown = await renderMarkdown({
|
|
1056
1057
|
nodes: writeBlocks(doc.content),
|
|
1057
|
-
frontmatter:
|
|
1058
|
+
frontmatter: {},
|
|
1058
1059
|
meta: {}
|
|
1059
1060
|
}, writeOptions);
|
|
1060
|
-
return markdown.trim() ? `${markdown.trimEnd()}\n` : "";
|
|
1061
|
+
return withFrontmatter(markdown.trim() ? `${markdown.trimEnd()}\n` : "", options.frontmatter);
|
|
1062
|
+
}
|
|
1063
|
+
/** Finds the frontmatter block where Comark does, and says why a save wouldn't write it back. */
|
|
1064
|
+
function readFrontmatter(markdown) {
|
|
1065
|
+
if (!markdown.startsWith("---") || !markdown.includes("\n---")) return { kind: "none" };
|
|
1066
|
+
let read;
|
|
1067
|
+
try {
|
|
1068
|
+
read = parseFrontmatter(markdown);
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
return {
|
|
1071
|
+
kind: "lost",
|
|
1072
|
+
problem: `The frontmatter isn't valid YAML (${String(error instanceof Error && "reason" in error ? error.reason : error)}); fix it to edit the document.`,
|
|
1073
|
+
body: markdown.slice(markdown.indexOf("\n---") + 4).replace(/^(?:\r?\n)+/, "")
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
const { data, frontmatterText: yaml } = read;
|
|
1077
|
+
const value = data;
|
|
1078
|
+
if (!(value instanceof Object) || Array.isArray(value)) return {
|
|
1079
|
+
kind: "lost",
|
|
1080
|
+
problem: `The frontmatter is a YAML ${Array.isArray(value) ? "list" : "scalar"}, which a save would rewrite; turn it into \`key: value\` lines to edit the document.`
|
|
1081
|
+
};
|
|
1082
|
+
const comments = hasComment(yaml);
|
|
1083
|
+
if (!Object.keys(data).length) return {
|
|
1084
|
+
kind: "lost",
|
|
1085
|
+
problem: comments ? "The frontmatter holds only YAML comments, which a save would drop; delete them or move them into the text to edit the document." : "The frontmatter block is empty, so a save wouldn't write it back; delete its `---` lines or add a `key: value` line to edit the document."
|
|
1086
|
+
};
|
|
1087
|
+
if (comments) return {
|
|
1088
|
+
kind: "lost",
|
|
1089
|
+
problem: "The frontmatter has YAML comments, which a save would drop; delete them or move them into the text to edit the document."
|
|
1090
|
+
};
|
|
1091
|
+
if (hasProtoKey(data)) return {
|
|
1092
|
+
kind: "lost",
|
|
1093
|
+
problem: "The frontmatter has a `__proto__` key, which the room's fields would drop on save; rename it to edit the document."
|
|
1094
|
+
};
|
|
1095
|
+
return {
|
|
1096
|
+
kind: "kept",
|
|
1097
|
+
body: read.content.replace(/^(?:\r?\n)+/, ""),
|
|
1098
|
+
fields: data
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
function hasProtoKey(value, seen = /* @__PURE__ */ new Set()) {
|
|
1102
|
+
if (!(value instanceof Object) || seen.has(value)) return false;
|
|
1103
|
+
seen.add(value);
|
|
1104
|
+
return Object.hasOwn(value, "__proto__") || Object.values(value).some((child) => hasProtoKey(child, seen));
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Whether the YAML has a comment. A `#` after a space may sit inside a quoted value, so each candidate counts only when
|
|
1108
|
+
* cutting the line there leaves the same data.
|
|
1109
|
+
*/
|
|
1110
|
+
function hasComment(yaml) {
|
|
1111
|
+
const lines = yaml.split("\n");
|
|
1112
|
+
const data = (text) => {
|
|
1113
|
+
try {
|
|
1114
|
+
return { value: parseFrontmatter(`---\n${text}\n---\n`).data };
|
|
1115
|
+
} catch {
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
const original = data(yaml);
|
|
1120
|
+
return lines.some((line, index) => [...line.matchAll(/(?:^|\s)#/g)].some((match) => {
|
|
1121
|
+
const cut = [...lines];
|
|
1122
|
+
cut[index] = line.slice(0, match.index);
|
|
1123
|
+
const read = data(cut.join("\n"));
|
|
1124
|
+
return read !== void 0 && equal(read.value, original?.value);
|
|
1125
|
+
}));
|
|
1126
|
+
}
|
|
1127
|
+
/** Writes the frontmatter above the body. Comark's own writer leaves out the `---` lines when the body is empty. */
|
|
1128
|
+
function withFrontmatter(body, frontmatter = {}) {
|
|
1129
|
+
if (!Object.keys(frontmatter).length) return body;
|
|
1130
|
+
return `---\n${renderFrontmatter(frontmatter, "")}\n---\n${body ? `\n${body}` : ""}`;
|
|
1061
1131
|
}
|
|
1062
1132
|
/**
|
|
1063
1133
|
* Whether the editor can open this Markdown and save it without changing what readers see. Pass the parse plugins the
|
|
1064
1134
|
* page renders with, so syntax only they read, such as footnote definitions, counts too.
|
|
1065
1135
|
*/
|
|
1066
1136
|
async function checkMarkdown(markdown, options = {}) {
|
|
1137
|
+
const frontmatter = readFrontmatter(markdown);
|
|
1138
|
+
if (frontmatter.kind === "lost") return {
|
|
1139
|
+
editable: false,
|
|
1140
|
+
reason: frontmatter.problem
|
|
1141
|
+
};
|
|
1067
1142
|
const first = await fromMarkdown(markdown);
|
|
1068
1143
|
if (first.lossy) return { editable: false };
|
|
1069
1144
|
const written = await toMarkdown(first.doc, first);
|
|
@@ -1272,10 +1347,28 @@ function createEditorCodec(options = {}) {
|
|
|
1272
1347
|
});
|
|
1273
1348
|
return {
|
|
1274
1349
|
extensions: () => [kit],
|
|
1275
|
-
|
|
1350
|
+
async fromMarkdown(markdown) {
|
|
1351
|
+
const frontmatter = readFrontmatter(markdown);
|
|
1352
|
+
return (await fromMarkdown(frontmatter.kind === "lost" ? frontmatter.body ?? markdown : markdown)).doc;
|
|
1353
|
+
},
|
|
1276
1354
|
toMarkdown: (doc) => toMarkdown(doc),
|
|
1355
|
+
split(markdown) {
|
|
1356
|
+
const frontmatter = readFrontmatter(markdown);
|
|
1357
|
+
return frontmatter.kind === "kept" ? {
|
|
1358
|
+
body: frontmatter.body,
|
|
1359
|
+
fields: frontmatter.fields
|
|
1360
|
+
} : {
|
|
1361
|
+
body: markdown,
|
|
1362
|
+
fields: {}
|
|
1363
|
+
};
|
|
1364
|
+
},
|
|
1365
|
+
join: ({ body, fields }) => withFrontmatter(body, fields),
|
|
1277
1366
|
async verify(markdown) {
|
|
1278
|
-
|
|
1367
|
+
const frontmatter = readFrontmatter(markdown);
|
|
1368
|
+
if (frontmatter.kind !== "none") return {
|
|
1369
|
+
writable: false,
|
|
1370
|
+
issues: [{ message: frontmatter.kind === "lost" ? frontmatter.problem : "The frontmatter is in the room's body, where a save would drop it; open the room with the codec's `split()` so it stays in the room's fields." }]
|
|
1371
|
+
};
|
|
1279
1372
|
const check = await checkMarkdown(markdown, { plugins: options.plugins });
|
|
1280
1373
|
return check.editable ? {
|
|
1281
1374
|
writable: true,
|
package/dist/editor-vue.d.mts
CHANGED
package/dist/editor-vue.mjs
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as isElement, t as childrenOf } from "./nodes-CwDBFXnO.mjs";
|
|
2
|
+
import { c as fromMarkdown, l as toMarkdown, m as ComarkKit, s as checkMarkdown } from "./editor-9IcfELjG.mjs";
|
|
2
3
|
import { Editor, EditorContent } from "@tiptap/vue-3";
|
|
3
4
|
import { rowsOf } from "comark-properties";
|
|
4
5
|
import { Properties } from "comark-properties/vue";
|
|
5
6
|
import { defineComponent, h, onScopeDispose, ref, shallowRef, watch } from "vue";
|
|
6
|
-
//#region ../../shared/nodes.ts
|
|
7
|
-
const isElement = (node) => Array.isArray(node) && node[0] !== null;
|
|
8
|
-
const childrenOf = ([, , ...rest]) => rest;
|
|
9
|
-
//#endregion
|
|
10
7
|
//#region src/editor-vue.ts
|
|
11
8
|
/**
|
|
12
9
|
* A Tiptap editor bound to a Markdown string: an edit writes the Markdown back, and a change from outside reloads the
|
|
@@ -50,7 +50,7 @@ declare const ComarkKit: Extension<ComarkKitOptions, any>;
|
|
|
50
50
|
interface EditorDocument {
|
|
51
51
|
/** The document as Tiptap JSON, for `setContent` or a collaborative room. */
|
|
52
52
|
doc: JSONContent;
|
|
53
|
-
/** The front matter, which stays outside the editor
|
|
53
|
+
/** The front matter, which stays outside the editor. A collaborative room keeps it beside the body, in its fields. */
|
|
54
54
|
frontmatter: Record<string, unknown>;
|
|
55
55
|
/** The Markdown holds something the editor can't keep, so writing it back would change more than the edit. */
|
|
56
56
|
lossy: boolean;
|
|
@@ -61,11 +61,17 @@ declare function fromMarkdown(markdown: string): Promise<EditorDocument>;
|
|
|
61
61
|
declare function toMarkdown(doc: JSONContent, options?: {
|
|
62
62
|
frontmatter?: Record<string, unknown>;
|
|
63
63
|
}): Promise<string>;
|
|
64
|
+
/** A Markdown file as a collaborative room holds it: the body the editor shows, and the frontmatter beside it. */
|
|
65
|
+
interface SplitMarkdown {
|
|
66
|
+
body: string;
|
|
67
|
+
fields: Record<string, unknown>;
|
|
68
|
+
}
|
|
64
69
|
type MarkdownCheck = {
|
|
65
70
|
editable: true;
|
|
66
71
|
/** The Markdown as the editor writes it, which the first save produces. */ markdown: string;
|
|
67
72
|
} | {
|
|
68
73
|
editable: false;
|
|
74
|
+
/** Why, when it's the frontmatter the editor can't keep. */ reason?: string;
|
|
69
75
|
};
|
|
70
76
|
/**
|
|
71
77
|
* Whether the editor can open this Markdown and save it without changing what readers see. Pass the parse plugins the
|
|
@@ -128,15 +134,33 @@ declare const Upload: Extension<UploadOptions, any>;
|
|
|
128
134
|
* A schema and Markdown codec that a server and its browsers share, as a collaborative room needs: the server converts
|
|
129
135
|
* the stored Markdown with it, and every editor that joins builds the same schema from `extensions()`. ViteHub
|
|
130
136
|
* Realtime's `editor` option takes it as it is.
|
|
137
|
+
*
|
|
138
|
+
* A room holds the body as the editor's document and the frontmatter as its fields, a map of one value per key, so an
|
|
139
|
+
* edit to the text never writes over the metadata. `split()` and `join()` convert between a stored file and the two.
|
|
131
140
|
*/
|
|
132
141
|
interface EditorCodec {
|
|
133
142
|
extensions(): AnyExtension[];
|
|
143
|
+
/** Reads a room's body, without frontmatter. */
|
|
134
144
|
fromMarkdown(markdown: string): Promise<JSONContent>;
|
|
145
|
+
/** Writes a room's body, without frontmatter. */
|
|
135
146
|
toMarkdown(doc: JSONContent): Promise<string>;
|
|
136
|
-
/**
|
|
147
|
+
/**
|
|
148
|
+
* Splits a stored file into the room's body and fields. Frontmatter a save couldn't write back stays in the body,
|
|
149
|
+
* where `verify()` says why the room can't save it.
|
|
150
|
+
*/
|
|
151
|
+
split(markdown: string): SplitMarkdown;
|
|
152
|
+
/** Joins a room's body and fields into the file to store. */
|
|
153
|
+
join(document: SplitMarkdown): string;
|
|
154
|
+
/**
|
|
155
|
+
* Whether the room may save this body. `canonical` is what the first save writes for it unchanged, and `issues` says
|
|
156
|
+
* why a body that still holds frontmatter can't be saved. The fields need no check: every JSON value survives YAML.
|
|
157
|
+
*/
|
|
137
158
|
verify(markdown: string): Promise<{
|
|
138
159
|
writable: boolean;
|
|
139
160
|
canonical?: string;
|
|
161
|
+
issues?: {
|
|
162
|
+
message: string;
|
|
163
|
+
}[];
|
|
140
164
|
}>;
|
|
141
165
|
}
|
|
142
166
|
interface EditorCodecOptions {
|
|
@@ -146,4 +170,4 @@ interface EditorCodecOptions {
|
|
|
146
170
|
}
|
|
147
171
|
declare function createEditorCodec(options?: EditorCodecOptions): EditorCodec;
|
|
148
172
|
//#endregion
|
|
149
|
-
export {
|
|
173
|
+
export { DefinitionTerm as A, ComarkSlot as C, CriticInsertion as D, CriticHighlight as E, FootnoteReference as M, InlineFootnote as N, DefinitionDescription as O, ComarkKitOptions as S, CriticDeletion as T, ComarkBlock as _, Upload as a, ComarkInline as b, startUploads as c, EditorDocument as d, MarkdownCheck as f, toMarkdown as g, fromMarkdown as h, PendingUpload as i, FootnoteDefinition as j, DefinitionList as k, uploadKey as l, checkMarkdown as m, EditorCodecOptions as n, UploadOptions as o, SplitMarkdown as p, createEditorCodec as r, findUpload as s, EditorCodec as t, uploadPlugin as u, ComarkComment as v, CriticComment as w, ComarkKit as x, ComarkImage as y };
|
package/dist/editor.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
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 };
|
|
1
|
+
import { A as DefinitionTerm, C as ComarkSlot, D as CriticInsertion, E as CriticHighlight, M as FootnoteReference, N as InlineFootnote, O as DefinitionDescription, S as ComarkKitOptions, T as CriticDeletion, _ as ComarkBlock, a as Upload, b as ComarkInline, c as startUploads, d as EditorDocument, f as MarkdownCheck, g as toMarkdown, h as fromMarkdown, i as PendingUpload, j as FootnoteDefinition, k as DefinitionList, l as uploadKey, m as checkMarkdown, n as EditorCodecOptions, o as UploadOptions, p as SplitMarkdown, r as createEditorCodec, s as findUpload, t as EditorCodec, u as uploadPlugin, v as ComarkComment, w as CriticComment, x as ComarkKit, y as ComarkImage } from "./editor-yoVL7Ajq.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, type SplitMarkdown, 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, 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-
|
|
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-9IcfELjG.mjs";
|
package/dist/html.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as commentsCss, n as Preset, o as criticCss, r as PresetOptions } from "./index-BTyvRIPX.mjs";
|
|
2
2
|
import { NodeHandler } from "comark";
|
|
3
3
|
//#region src/html.d.ts
|
|
4
4
|
/**
|
|
@@ -10,4 +10,4 @@ export declare const mermaidScript: string;
|
|
|
10
10
|
/** Every plugin for `@comark/html`, with the `components` to render them. */
|
|
11
11
|
declare const _default: (options?: PresetOptions) => Preset<NodeHandler>;
|
|
12
12
|
//#endregion
|
|
13
|
-
export { type PresetOptions, criticCss, _default as default };
|
|
13
|
+
export { type PresetOptions, commentsCss, criticCss, _default as default };
|
package/dist/html.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
import { a as start, n as mermaidBar, r as mermaidCss } from "./client-
|
|
1
|
+
import { n as criticCss, r as preset, t as commentsCss } from "./src-Baygj6ZQ.mjs";
|
|
2
|
+
import { t as typesetCss } from "./typeset-css-BYvWbqWz.mjs";
|
|
3
|
+
import { a as start, n as mermaidBar, r as mermaidCss } from "./client-kUEiRbtp.mjs";
|
|
4
4
|
import { t as rawText } from "./text-D8j9clg3.mjs";
|
|
5
5
|
import { escapeHtml } from "comark/utils";
|
|
6
6
|
import * as annotate from "comark-annotate/html";
|
|
@@ -111,4 +111,4 @@ var html_default = (options) => preset({
|
|
|
111
111
|
zoom
|
|
112
112
|
}, options);
|
|
113
113
|
//#endregion
|
|
114
|
-
export { criticCss, html_default as default, mermaidScript };
|
|
114
|
+
export { commentsCss, criticCss, html_default as default, mermaidScript };
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { CriticOptions, css as criticCss } from "comark-critic";
|
|
2
2
|
import { FigureOptions } from "comark-figure";
|
|
3
3
|
import { FootnotesOptions } from "comark-footnotes";
|
|
4
|
+
import { CalloutsOptions, ReferencesOptions } from "comark-github";
|
|
4
5
|
import { IconOptions, Icons } from "comark-icon";
|
|
5
6
|
import { IncludeOptions } from "comark-include";
|
|
6
7
|
import { KeysOptions } from "comark-keys";
|
|
7
8
|
import { ReadingTimeOptions } from "comark-reading-time";
|
|
8
9
|
import { XrefOptions } from "comark-xref";
|
|
9
10
|
import { ComarkPlugin } from "comark";
|
|
11
|
+
import { CommentsOptions, css as commentsCss } from "comark-comments";
|
|
10
12
|
import { PropertiesOptions } from "comark-properties";
|
|
11
13
|
import { BadgeOptions } from "comark-badge";
|
|
12
14
|
import { AnnotateOptions } from "comark-annotate";
|
|
@@ -14,11 +16,9 @@ import { CastOptions } from "comark-cast";
|
|
|
14
16
|
import { ChartsOptions } from "comark-charts";
|
|
15
17
|
import { ChipsOptions } from "comark-chips";
|
|
16
18
|
import { CodeOptions } from "comark-code";
|
|
17
|
-
import { CommentsOptions } from "comark-comments";
|
|
18
19
|
import { DetailsOptions } from "comark-details";
|
|
19
20
|
import { DiagramsOptions } from "comark-diagrams";
|
|
20
21
|
import { FileTreeOptions } from "comark-file-tree";
|
|
21
|
-
import { CalloutsOptions, ReferencesOptions } from "comark-github";
|
|
22
22
|
import { AnchorsOptions, ExternalOptions } from "comark-links";
|
|
23
23
|
import { MathOptions } from "comark-mathml";
|
|
24
24
|
import { MediaOptions } from "comark-media";
|
|
@@ -29,6 +29,14 @@ import { TableOptions } from "comark-table";
|
|
|
29
29
|
import { TabsOptions } from "comark-tabs";
|
|
30
30
|
import { TestsOptions } from "comark-tests";
|
|
31
31
|
import { ZoomOptions } from "comark-zoom";
|
|
32
|
+
//#region src/mermaid-limits.d.ts
|
|
33
|
+
type MermaidOptions = PeleConfig & {
|
|
34
|
+
/** How many diagrams a document draws. The ones after show their source as a code block. */
|
|
35
|
+
maxDiagrams?: number;
|
|
36
|
+
/** How many characters of Mermaid source a document draws, over all its diagrams. A diagram past it shows its source. */
|
|
37
|
+
maxSource?: number;
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
32
40
|
//#region src/typeset.d.ts
|
|
33
41
|
/** The node that adds the styles. The plugin adds one at the end of every document. */
|
|
34
42
|
declare const TYPESET_TAG = "typeset-styles";
|
|
@@ -63,8 +71,11 @@ type PresetOptions = {
|
|
|
63
71
|
comments?: CommentsOptions | boolean;
|
|
64
72
|
/** Sends each diagram's source to `https://kroki.io` unless you pass your own `server`, or `{ draw: false }`. */
|
|
65
73
|
diagrams?: DiagramsOptions | boolean;
|
|
66
|
-
/**
|
|
67
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Draws `mermaid` fences with comark-pele, on the server and offline. A host that renders documents it didn't write
|
|
76
|
+
* can pass `{ maxDiagrams, maxSource }`: the diagrams past either limit show their source as code, each with an issue.
|
|
77
|
+
*/
|
|
78
|
+
mermaid?: MermaidOptions | boolean;
|
|
68
79
|
/** HTML only: Vue, React, and Svelte have no diff components. */
|
|
69
80
|
diff?: boolean;
|
|
70
81
|
embed?: boolean;
|
|
@@ -176,8 +187,19 @@ type Renderer<C> = {
|
|
|
176
187
|
type Preset<C> = {
|
|
177
188
|
plugins: AnyPlugin[];
|
|
178
189
|
components: Record<string, C>;
|
|
190
|
+
/**
|
|
191
|
+
* Every tag but `components`' that a document parsed with `plugins` can hold: Markdown's own, the raw HTML that
|
|
192
|
+
* GitHub's `html` plugin keeps, and the plain elements the plugins draw with. With `components`' names, it's the
|
|
193
|
+
* allowlist a host that sanitizes the tree needs. With GitHub's `html` off, raw HTML is left to the host.
|
|
194
|
+
*/
|
|
195
|
+
tags: string[];
|
|
196
|
+
/**
|
|
197
|
+
* The blocks a document may write that the plugins turn into other nodes while parsing, such as `::code-group`. A
|
|
198
|
+
* linter that reports unknown components needs them beside `components`' names.
|
|
199
|
+
*/
|
|
200
|
+
blocks: string[];
|
|
179
201
|
};
|
|
180
202
|
/** Builds a renderer's preset. Use the one from `comark-ui/html`, `/vue`, `/react`, or `/svelte`. */
|
|
181
203
|
declare function preset<C>(renderer: Renderer<C>, options?: PresetOptions): Preset<C>;
|
|
182
204
|
//#endregion
|
|
183
|
-
export {
|
|
205
|
+
export { commentsCss as a, TYPESET_TAG as c, Renderer as i, typeset as l, Preset as n, criticCss as o, PresetOptions as r, preset as s, AnyPlugin as t, MermaidOptions as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as typesetCss } from "./typeset-css-
|
|
2
|
-
import { a as
|
|
3
|
-
export { AnyPlugin, Preset, PresetOptions, Renderer, TYPESET_TAG, criticCss, preset, typeset, typesetCss };
|
|
1
|
+
import { n as typesetStylesheet, t as typesetCss } from "./typeset-css-DtOLAa1Z.mjs";
|
|
2
|
+
import { a as commentsCss, c as TYPESET_TAG, i as Renderer, l as typeset, n as Preset, o as criticCss, r as PresetOptions, s as preset, t as AnyPlugin, u as MermaidOptions } from "./index-BTyvRIPX.mjs";
|
|
3
|
+
export { AnyPlugin, type MermaidOptions, Preset, PresetOptions, Renderer, TYPESET_TAG, commentsCss, criticCss, preset, typeset, typesetCss, typesetStylesheet };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
export { TYPESET_TAG, criticCss, preset, typeset, typesetCss };
|
|
1
|
+
import { a as typeset, i as TYPESET_TAG, n as criticCss, r as preset, t as commentsCss } from "./src-Baygj6ZQ.mjs";
|
|
2
|
+
import { n as typesetStylesheet, t as typesetCss } from "./typeset-css-BYvWbqWz.mjs";
|
|
3
|
+
export { TYPESET_TAG, commentsCss, criticCss, preset, typeset, typesetCss, typesetStylesheet };
|
package/dist/react.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as commentsCss, n as Preset, o as criticCss, r as PresetOptions } from "./index-BTyvRIPX.mjs";
|
|
2
2
|
import { ComponentType } from "react";
|
|
3
3
|
//#region src/react.d.ts
|
|
4
4
|
type AnyComponent = ComponentType<any>;
|
|
5
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
|
-
export { type PresetOptions, criticCss, _default as default };
|
|
8
|
+
export { type PresetOptions, commentsCss, criticCss, _default as default };
|
package/dist/react.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
import { i as startMermaid, n as mermaidBar, t as addMermaidStyles } from "./client-
|
|
1
|
+
import { n as criticCss, r as preset, t as commentsCss } from "./src-Baygj6ZQ.mjs";
|
|
2
|
+
import { t as typesetCss } from "./typeset-css-BYvWbqWz.mjs";
|
|
3
|
+
import { i as startMermaid, n as mermaidBar, t as addMermaidStyles } from "./client-kUEiRbtp.mjs";
|
|
4
4
|
import { createElement, useEffect } from "react";
|
|
5
5
|
import * as badge from "comark-badge/react";
|
|
6
6
|
import * as cards from "comark-cards/react";
|
|
@@ -94,4 +94,4 @@ var react_default = (options) => preset({
|
|
|
94
94
|
zoom
|
|
95
95
|
}, options);
|
|
96
96
|
//#endregion
|
|
97
|
-
export { criticCss, react_default as default };
|
|
97
|
+
export { commentsCss, criticCss, react_default as default };
|
|
@@ -45,6 +45,8 @@ Either way, the HTML renderer inlines the styles once per document, and the Vue,
|
|
|
45
45
|
|
|
46
46
|
The `--comark-*` tokens theme every plugin at once; https://comark-ui.onmax.me/guide/theming/ lists them. In a Nuxt UI app the plugins follow its `--ui-*` variables with no setup. For a page rendered outside the app, such as review evidence, put the CSS from `nuxtUiTheme({ colors: appConfig.ui?.colors, css: mainCss })` (from `comark-ui/nuxt-ui`) in a `<style>`, so the page matches the app.
|
|
47
47
|
|
|
48
|
+
A project that renders Markdown with remark moves to Comark with `remark-to-comark`; the [remark-to-comark reference](references/remark-to-comark.md) walks through it.
|
|
49
|
+
|
|
48
50
|
Problems land in `meta.issues` after `parseMarkdown`, one sentence each, and a host can refuse a document while any remain. For untrusted input, add Comark's `security` plugin with `blockedTags` such as `script`, `style`, and `iframe`; it cleans the Markdown inside blocks too.
|
|
49
51
|
|
|
50
52
|
## Shape the document
|
|
@@ -7,12 +7,12 @@ comark-media plays an image that points at a video or a sound file, and a GitHub
|
|
|
7
7
|
```md
|
|
8
8
|
The spinner now stops once the build finishes:
|
|
9
9
|
|
|
10
|
-
{loop muted}
|
|
10
|
+
{loop muted width=1280 height=720}
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
- A `src` that ends in `.mp4`, `.webm`, `.mov`, or `.m4v`, before any `?` or `#`, plays as a video, and one in `.mp3`, `.wav`, `.ogg`, or `.m4a` as audio. Every other image stays an image.
|
|
14
14
|
- The alt text is required. It names the player for screen readers, and it's the text of a link to the file where the browser can't play it.
|
|
15
|
-
- `autoplay`, `loop`, and `muted` are off by default. Browsers start a file by itself only when it's muted, so `autoplay` needs `muted`. `poster="frame.png"` shows an image before a video plays; audio takes none. `{loop=false}` turns a prop off.
|
|
15
|
+
- `autoplay`, `loop`, and `muted` are off by default. Browsers start a file by itself only when it's muted, so `autoplay` needs `muted`. `poster="frame.png"` shows an image before a video plays; audio takes none. `{loop=false}` turns a prop off. Give every video its `width` and `height`, paired whole pixel dimensions like `{width=1280 height=720}`, so the page keeps its room before the file loads; read them with `ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 clip.mp4`. Audio takes neither. Other props, such as a class, are dropped and reported.
|
|
16
16
|
- A GitHub attachment link, `https://github.com/user-attachments/assets/<id>`, plays as a video when the bare URL sits alone in its paragraph, as on GitHub. With text of its own, or inside a sentence, it stays a link.
|
|
17
17
|
|
|
18
18
|
## Record the evidence
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Moving a project from remark
|
|
2
|
+
|
|
3
|
+
remark-to-comark moves a project that renders Markdown with remark, rehype, unified, or react-markdown to Comark. It reports what it finds as diagnostics, `RTC0101` to `RTC0303`, each with a fix and a link to https://comark-ui.onmax.me/remark-to-comark/diagnostics/.
|
|
4
|
+
|
|
5
|
+
## Run it
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
vp exec remark-to-comark check . --json
|
|
9
|
+
vp exec remark-to-comark content "**/*.{md,mdx}" --write
|
|
10
|
+
vp exec remark-to-comark rewrite . --write
|
|
11
|
+
vp exec remark-to-comark check . --json
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- `check` lists the remark setups it finds and what each plugin becomes, the unified chains `rewrite` can replace and why the others stay, the Markdown files `content` would change, and the MDX it leaves alone. `--json` prints each finding with its code, file, line, fix, and docs link.
|
|
15
|
+
- `rewrite` replaces a chain like `unified().use(remarkParse).use(remarkRehype).use(rehypeStringify).process(markdown)` with `renderHtml(markdown, comarkOptions({ … }))`, importing `comarkOptions` from `remark-to-comark/setup`. Install what the new code imports: `comark`, `@comark/html`, and `remark-to-comark`.
|
|
16
|
+
- `content` escapes `{`, `[`, and `:name` that Comark would read as attributes, spans, or components, so remark still renders every file byte for byte as before. It parses with the project's syntax plugins, so `$x_{i}$` stays math. Run it before `rewrite`, which removes the remark code it reads them from.
|
|
17
|
+
- Run `check` again at the end. What's left is work for you: framework configs (RTC0101), the project's own plugins (RTC0105), chains it couldn't rewrite (RTC0201), MDX (RTC0301), and blocks left as written (RTC0303).
|
|
18
|
+
|
|
19
|
+
## What it leaves to you
|
|
20
|
+
|
|
21
|
+
- A framework config, such as Astro's `markdown.remarkPlugins` or Docusaurus' `remarkPlugins`, stays as it is: the framework calls remark. Render with `renderHtml(markdown, comarkOptions())` where the framework lets you, such as a content loader or a route.
|
|
22
|
+
- react-markdown becomes `<Markdown value={markdown} options={…} plugins={[…]} />` from `@comark/react`, with the plugins the findings name.
|
|
23
|
+
- A plugin a comark-ui package replaces is reported with that package (RTC0102); its markup differs from the remark plugin's, so check pages that style it.
|
|
24
|
+
- MDX stays MDX. Convert a page by hand only when its JSX just passes props: rename it to `.md`, run `content` on the prose, then write the components as Comark blocks. `content` escapes Comark syntax, so don't run it after you add them.
|
|
25
|
+
|
|
26
|
+
## Register
|
|
27
|
+
|
|
28
|
+
- In `comark-ui`: not included. Install it beside the preset for the migration.
|
|
29
|
+
- Alone: `pnpm add -D remark-to-comark`. It installs the command `remark-to-comark`, the library `remark-to-comark`, the Comark setup `remark-to-comark/setup` (add it to your runtime dependencies when rewritten code imports it), the ports `remark-to-comark/plugins`, and the Vite Doctor extension `remark-to-comark/doctor`.
|
package/dist/skills.mjs
CHANGED
|
@@ -42,7 +42,7 @@ const skills = [
|
|
|
42
42
|
"files": [
|
|
43
43
|
{
|
|
44
44
|
"path": "SKILL.md",
|
|
45
|
-
"text": "---\nname: comark-ui\ndescription: Writes PR evidence, explanations of how something works, and docs pages in Markdown with comark-ui. Use when a document needs an annotated screenshot, a before/after, a chart, a diagram, a code change, or another comark block, or when setting up comark-ui or a comark-* package.\n---\n\n# comark-ui\n\nYou write Markdown, and the comark plugins render it as static HTML. The reader sees only what you measured and wrote down, so measure every mark from the page, take every number from the data, and check the render before you hand it over.\n\n## Install\n\nInstall `comark-ui` by default. It holds every plugin and registers them in the order they need:\n\n```sh\npnpm add comark @comark/html comark-ui\n```\n\nRun 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.\n\n```ts\nimport { createHtmlRenderer } from \"@comark/html\";\nimport comarkUi from \"comark-ui/html\";\n\nconst render = createHtmlRenderer(comarkUi());\n```\n\nEvery plugin is on except `include`. The [comark-ui reference](references/ui.md) covers its options, the plugins that read files or use the network, and its Vue, React, and Svelte entries.\n\nTo use only some plugins, install those packages and register each plugin with its components:\n\n```sh\npnpm add comark @comark/html comark-annotate\n```\n\n```ts\nimport { createHtmlRenderer } from \"@comark/html\";\nimport annotate, { components } from \"comark-annotate/html\";\n\nconst render = createHtmlRenderer({ plugins: [annotate()], components });\n```\n\nEach reference ends with a Register section that says how its package registers alone and which options it needs.\n\nEither way, the HTML renderer inlines the styles once per document, and the Vue, React, and Svelte components add them on mount. On a server-rendered page, import each package's `style.css`, such as `comark-cards/style.css`, so the page doesn't shift.\n\nThe `--comark-*` tokens theme every plugin at once; https://comark-ui.onmax.me/guide/theming/ lists them. In a Nuxt UI app the plugins follow its `--ui-*` variables with no setup. For a page rendered outside the app, such as review evidence, put the CSS from `nuxtUiTheme({ colors: appConfig.ui?.colors, css: mainCss })` (from `comark-ui/nuxt-ui`) in a `<style>`, so the page matches the app.\n\nProblems 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.\n\n## Shape the document\n\nThis skill teaches the blocks. Four sibling skills teach a whole document, what goes in it and in what order: `before-after-evidence`, `review-document`, `visual-explanation`, and `teach-lesson`. When the user asks for one of those and it isn't installed, suggest `vp dlx skills add onmax/comark-ui` and picking it from the list.\n\n## Pick the blocks\n\nRead the reference for each block you use before you write it. Mix the blocks freely with ordinary Markdown, such as headings, tables, and lists.\n\n### Review blocks\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| One state of a screen, with marks, numbered notes, or arrows | `::screenshot` | [annotate](references/annotate.md) |\n| A change on screen, before and after | `::compare` | [annotate](references/annotate.md) |\n| A command's output, such as a test run or a build, as colored text | `::cast` | [cast](references/cast.md) |\n| Numbers, such as sizes, timings, before/after metrics, a trend, or a timeline | `::chart` | [charts](references/charts.md) |\n| A flow, a sequence, an architecture, or a schema as a diagram | a `mermaid`, `d2`, `dot`, `plantuml`, `dbml`, `goat`, or `svgbob` fence | [diagrams](references/diagrams.md) |\n| Links and `@mentions` with the site's favicon or the person's avatar | links, `@user`, `:chip` | [chips](references/chips.md) |\n| Colors, such as design tokens before and after, or a palette | a color in inline code, `::palette` | [colors](references/colors.md) |\n| A suggested change to one file, before and after | `::diff` | [diff](references/diff.md) |\n| 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) |\n| A video, a design file, or a live reproduction from its link | `::embed` | [embed](references/embed.md) |\n| A screen recording or a sound that a screenshot can't show | `` | [media](references/media.md) |\n| A number before and after, a table of befores and afters, or progress | `:delta`, `::stats`, `:progress` | [metrics](references/metrics.md) |\n| Data from a CSV, TSV, or JSON fence or file, as a table that copies and sorts | `::table`, a `csv` fence | [table](references/table.md) |\n| A test run's passed, failed, and skipped counts and its failures, from a JUnit report | `::tests` | [tests](references/tests.md) |\n| A note, tip, or warning box, or long output folded away, as on GitHub | `> [!NOTE]`, `<details>` | [github](references/github.md) |\n| The review's status, pull request, author, date, and tags in a box | frontmatter, `::properties` | [properties](references/properties.md) |\n| Claims backed by links, with numbered citations | `:cite`, `::sources` | [sources](references/sources.md) |\n| An icon in a sentence or a table cell, such as a logo or a status | `:icon` | [icon](references/icon.md) |\n| A preview link a reviewer can scan with a phone | `:qr` | [qr](references/qr.md) |\n| Why a line of code is there, as numbered notes under it | `// <1>` and a numbered list | [code-notes](references/code-notes.md) |\n\n### Page behavior\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| A stable link to a section, or a link that opens a new tab | `{#id}`, `{target=\"_blank\"}` | [links](references/links.md) |\n| A table, code block, or diagram too small to read in place | `::zoom` | [zoom](references/zoom.md) |\n| A sequence to page through in one place, such as the screens of a flow | `::carousel` | [carousel](references/carousel.md) |\n| Versions of one thing where each reader needs only one, such as an OS or a package manager | `::tabs`, `::code-group`, `pm` | [tabs](references/tabs.md) |\n| Code with lines marked added, removed, or highlighted, or a pasted `git diff` | `ins={4}` after a fence's language, `diff lang=\"ts\"` | [code](references/code.md) |\n\n### Docs blocks\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| Content a reader may skip, such as a long log, behind a summary | `::details`, `::accordion`, `::collapsible` | [details](references/details.md) |\n| Folders and files, with what a change added, removed, or changed | `::file-tree` | [file-tree](references/file-tree.md) |\n| A component's props or a function's options, with types and defaults | `::field` | [fields](references/fields.md) |\n| A version, status, or deprecation tag in a heading or a sentence | `:badge` | [badge](references/badge.md) |\n| Links to the next pages as cards, or blocks side by side | `::card-group`, `::columns` | [cards](references/cards.md) |\n| Instructions the reader follows in order, such as repro or setup steps | `::steps` | [steps](references/steps.md) |\n| Code that changes over several steps, such as a refactor told one move at a time | `::magic-move` | [magic-move](references/magic-move.md) |\n| An interactive lesson question, poll, or recall card | `::question`, `::poll`, `::recall` | [quiz](references/quiz.md) |\n\n### Markdown syntax\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| Bold or italics in Chinese, Japanese, or Korean text | `**…**`, `*…*` | [cjk](references/cjk.md) |\n| An image with a caption under it | `` | [figure](references/figure.md) |\n| A highlighted phrase or a superscript | `==text==`, `^2^` | [mark](references/mark.md) |\n| A suggested edit or a comment inside the text | `{++ ++}`, `{-- --}`, `{~~ ~> ~~}`, `{== ==}`, `{>> <<}` | [critic](references/critic.md) |\n| Terms and their definitions, such as a glossary | `Term`, then `: definition` | [deflist](references/deflist.md) |\n| A numbered note at the end of the page, such as a source or a caveat | `[^label]`, `^[note]` | [footnotes](references/footnotes.md) |\n| A formula, such as a complexity bound or how a number was computed | `$…$`, `$$…$$` | [math](references/math.md) |\n| A keyboard shortcut | `++ctrl+k++` | [keys](references/keys.md) |\n\n### Authoring tools\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| A shared section, or real source lines, pasted from a file | `:include{src}` | [include](references/include.md) |\n| A table of contents of the page's headings | `::toc` | [outline](references/outline.md) |\n| Figures and tables numbered and referred to by number | `{#fig-name}`, `:ref{#fig-name}` | [xref](references/xref.md) |\n| Word count and reading time, for the page's layout | nothing; it writes `meta.readingTime` | [reading-time](references/reading-time.md) |\n\n### Chat\n\n| To show | Use | Reference |\n| --- | --- | --- |\n| An AI SDK chat message, with its reasoning, tool calls, sources, and files | `MessageParts` from `comark-chat` | [chat](references/chat.md) |\n\n## Marks\n\nScreenshots and charts draw the same marks. Each `::annotation` is one mark and its note, written in Markdown.\n\n- `mark` is `box` (default), `circle`, `underline`, `line`, `highlight`, `bracket`, `cross`, `check`, or `none`, which draws nothing, so its note needs a `side` and the arrow alone points.\n- `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.\n- `side` is `top`, `bottom`, `left`, or `right`, and puts the note in that margin with an arrow to its mark. Notes without one are numbered in a list under the figure.\n\nMark only what your text talks about. Write each note in the words the screen or table shows, saying what changed or what is wrong, so the reader can check it against the figure. Leave out a value the figure doesn't show.\n\n## Check the result\n\n1. Lint the file with `vp exec comark-lint report.md`, in a project with `comark-linter` and the plugins installed (`comark-ui` counts as every plugin). It prints one line per problem with its line, its rule, and the fix, and exits with 1 while any remain. Fix every problem and run it again until it exits with 0. The [lint reference](references/lint.md) covers the flags, the config file, the library, ESLint, and Vite Doctor.\n2. Render the document as the block's reference says, open it in a browser, and take a screenshot. Each mark must sit on its target, each number must match its note, and each chart must say what your text says. Name anything you couldn't verify when you hand the document over.\n"
|
|
45
|
+
"text": "---\nname: comark-ui\ndescription: Writes PR evidence, explanations of how something works, and docs pages in Markdown with comark-ui. Use when a document needs an annotated screenshot, a before/after, a chart, a diagram, a code change, or another comark block, or when setting up comark-ui or a comark-* package.\n---\n\n# comark-ui\n\nYou write Markdown, and the comark plugins render it as static HTML. The reader sees only what you measured and wrote down, so measure every mark from the page, take every number from the data, and check the render before you hand it over.\n\n## Install\n\nInstall `comark-ui` by default. It holds every plugin and registers them in the order they need:\n\n```sh\npnpm add comark @comark/html comark-ui\n```\n\nRun 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.\n\n```ts\nimport { createHtmlRenderer } from \"@comark/html\";\nimport comarkUi from \"comark-ui/html\";\n\nconst render = createHtmlRenderer(comarkUi());\n```\n\nEvery plugin is on except `include`. The [comark-ui reference](references/ui.md) covers its options, the plugins that read files or use the network, and its Vue, React, and Svelte entries.\n\nTo use only some plugins, install those packages and register each plugin with its components:\n\n```sh\npnpm add comark @comark/html comark-annotate\n```\n\n```ts\nimport { createHtmlRenderer } from \"@comark/html\";\nimport annotate, { components } from \"comark-annotate/html\";\n\nconst render = createHtmlRenderer({ plugins: [annotate()], components });\n```\n\nEach reference ends with a Register section that says how its package registers alone and which options it needs.\n\nEither way, the HTML renderer inlines the styles once per document, and the Vue, React, and Svelte components add them on mount. On a server-rendered page, import each package's `style.css`, such as `comark-cards/style.css`, so the page doesn't shift.\n\nThe `--comark-*` tokens theme every plugin at once; https://comark-ui.onmax.me/guide/theming/ lists them. In a Nuxt UI app the plugins follow its `--ui-*` variables with no setup. For a page rendered outside the app, such as review evidence, put the CSS from `nuxtUiTheme({ colors: appConfig.ui?.colors, css: mainCss })` (from `comark-ui/nuxt-ui`) in a `<style>`, so the page matches the app.\n\nA project that renders Markdown with remark moves to Comark with `remark-to-comark`; the [remark-to-comark reference](references/remark-to-comark.md) walks through it.\n\nProblems 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.\n\n## Shape the document\n\nThis skill teaches the blocks. Four sibling skills teach a whole document, what goes in it and in what order: `before-after-evidence`, `review-document`, `visual-explanation`, and `teach-lesson`. When the user asks for one of those and it isn't installed, suggest `vp dlx skills add onmax/comark-ui` and picking it from the list.\n\n## Pick the blocks\n\nRead the reference for each block you use before you write it. Mix the blocks freely with ordinary Markdown, such as headings, tables, and lists.\n\n### Review blocks\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| One state of a screen, with marks, numbered notes, or arrows | `::screenshot` | [annotate](references/annotate.md) |\n| A change on screen, before and after | `::compare` | [annotate](references/annotate.md) |\n| A command's output, such as a test run or a build, as colored text | `::cast` | [cast](references/cast.md) |\n| Numbers, such as sizes, timings, before/after metrics, a trend, or a timeline | `::chart` | [charts](references/charts.md) |\n| A flow, a sequence, an architecture, or a schema as a diagram | a `mermaid`, `d2`, `dot`, `plantuml`, `dbml`, `goat`, or `svgbob` fence | [diagrams](references/diagrams.md) |\n| Links and `@mentions` with the site's favicon or the person's avatar | links, `@user`, `:chip` | [chips](references/chips.md) |\n| Colors, such as design tokens before and after, or a palette | a color in inline code, `::palette` | [colors](references/colors.md) |\n| A suggested change to one file, before and after | `::diff` | [diff](references/diff.md) |\n| 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) |\n| A video, a design file, or a live reproduction from its link | `::embed` | [embed](references/embed.md) |\n| A screen recording or a sound that a screenshot can't show | `` | [media](references/media.md) |\n| A number before and after, a table of befores and afters, or progress | `:delta`, `::stats`, `:progress` | [metrics](references/metrics.md) |\n| Data from a CSV, TSV, or JSON fence or file, as a table that copies and sorts | `::table`, a `csv` fence | [table](references/table.md) |\n| A test run's passed, failed, and skipped counts and its failures, from a JUnit report | `::tests` | [tests](references/tests.md) |\n| A note, tip, or warning box, or long output folded away, as on GitHub | `> [!NOTE]`, `<details>` | [github](references/github.md) |\n| The review's status, pull request, author, date, and tags in a box | frontmatter, `::properties` | [properties](references/properties.md) |\n| Claims backed by links, with numbered citations | `:cite`, `::sources` | [sources](references/sources.md) |\n| An icon in a sentence or a table cell, such as a logo or a status | `:icon` | [icon](references/icon.md) |\n| A preview link a reviewer can scan with a phone | `:qr` | [qr](references/qr.md) |\n| Why a line of code is there, as numbered notes under it | `// <1>` and a numbered list | [code-notes](references/code-notes.md) |\n\n### Page behavior\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| A stable link to a section, or a link that opens a new tab | `{#id}`, `{target=\"_blank\"}` | [links](references/links.md) |\n| A table, code block, or diagram too small to read in place | `::zoom` | [zoom](references/zoom.md) |\n| A sequence to page through in one place, such as the screens of a flow | `::carousel` | [carousel](references/carousel.md) |\n| Versions of one thing where each reader needs only one, such as an OS or a package manager | `::tabs`, `::code-group`, `pm` | [tabs](references/tabs.md) |\n| Code with lines marked added, removed, or highlighted, or a pasted `git diff` | `ins={4}` after a fence's language, `diff lang=\"ts\"` | [code](references/code.md) |\n\n### Docs blocks\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| Content a reader may skip, such as a long log, behind a summary | `::details`, `::accordion`, `::collapsible` | [details](references/details.md) |\n| Folders and files, with what a change added, removed, or changed | `::file-tree` | [file-tree](references/file-tree.md) |\n| A component's props or a function's options, with types and defaults | `::field` | [fields](references/fields.md) |\n| A version, status, or deprecation tag in a heading or a sentence | `:badge` | [badge](references/badge.md) |\n| Links to the next pages as cards, or blocks side by side | `::card-group`, `::columns` | [cards](references/cards.md) |\n| Instructions the reader follows in order, such as repro or setup steps | `::steps` | [steps](references/steps.md) |\n| Code that changes over several steps, such as a refactor told one move at a time | `::magic-move` | [magic-move](references/magic-move.md) |\n| An interactive lesson question, poll, or recall card | `::question`, `::poll`, `::recall` | [quiz](references/quiz.md) |\n\n### Markdown syntax\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| Bold or italics in Chinese, Japanese, or Korean text | `**…**`, `*…*` | [cjk](references/cjk.md) |\n| An image with a caption under it | `` | [figure](references/figure.md) |\n| A highlighted phrase or a superscript | `==text==`, `^2^` | [mark](references/mark.md) |\n| A suggested edit or a comment inside the text | `{++ ++}`, `{-- --}`, `{~~ ~> ~~}`, `{== ==}`, `{>> <<}` | [critic](references/critic.md) |\n| Terms and their definitions, such as a glossary | `Term`, then `: definition` | [deflist](references/deflist.md) |\n| A numbered note at the end of the page, such as a source or a caveat | `[^label]`, `^[note]` | [footnotes](references/footnotes.md) |\n| A formula, such as a complexity bound or how a number was computed | `$…$`, `$$…$$` | [math](references/math.md) |\n| A keyboard shortcut | `++ctrl+k++` | [keys](references/keys.md) |\n\n### Authoring tools\n\n| To show | Write | Reference |\n| --- | --- | --- |\n| A shared section, or real source lines, pasted from a file | `:include{src}` | [include](references/include.md) |\n| A table of contents of the page's headings | `::toc` | [outline](references/outline.md) |\n| Figures and tables numbered and referred to by number | `{#fig-name}`, `:ref{#fig-name}` | [xref](references/xref.md) |\n| Word count and reading time, for the page's layout | nothing; it writes `meta.readingTime` | [reading-time](references/reading-time.md) |\n\n### Chat\n\n| To show | Use | Reference |\n| --- | --- | --- |\n| An AI SDK chat message, with its reasoning, tool calls, sources, and files | `MessageParts` from `comark-chat` | [chat](references/chat.md) |\n\n## Marks\n\nScreenshots and charts draw the same marks. Each `::annotation` is one mark and its note, written in Markdown.\n\n- `mark` is `box` (default), `circle`, `underline`, `line`, `highlight`, `bracket`, `cross`, `check`, or `none`, which draws nothing, so its note needs a `side` and the arrow alone points.\n- `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.\n- `side` is `top`, `bottom`, `left`, or `right`, and puts the note in that margin with an arrow to its mark. Notes without one are numbered in a list under the figure.\n\nMark only what your text talks about. Write each note in the words the screen or table shows, saying what changed or what is wrong, so the reader can check it against the figure. Leave out a value the figure doesn't show.\n\n## Check the result\n\n1. Lint the file with `vp exec comark-lint report.md`, in a project with `comark-linter` and the plugins installed (`comark-ui` counts as every plugin). It prints one line per problem with its line, its rule, and the fix, and exits with 1 while any remain. Fix every problem and run it again until it exits with 0. The [lint reference](references/lint.md) covers the flags, the config file, the library, ESLint, and Vite Doctor.\n2. Render the document as the block's reference says, open it in a browser, and take a screenshot. Each mark must sit on its target, each number must match its note, and each chart must say what your text says. Name anything you couldn't verify when you hand the document over.\n"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"path": "agents/openai.yaml",
|
|
@@ -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{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.
|
|
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{loop muted width=1280 height=720}\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. Give every video its `width` and `height`, paired whole pixel dimensions like `{width=1280 height=720}`, so the page keeps its room before the file loads; read them with `ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 clip.mp4`. Audio takes neither. Other props, such as a class, are dropped and reported.\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",
|
|
@@ -204,6 +204,10 @@ const skills = [
|
|
|
204
204
|
"path": "references/reading-time.md",
|
|
205
205
|
"text": "# Reading time\n\ncomark-reading-time counts a document's words while parsing and writes them to `meta.readingTime` as `{ words, minutes }`. It has no syntax and draws nothing. The host's layout shows the numbers, such as \"7 min read\" under the title.\n\n## What it counts\n\n- The text a reader reads. It leaves out code blocks, frontmatter, and comments, and counts inline code.\n- Each Chinese, Japanese, or Korean character counts as a word, since those languages put no spaces between words.\n- `minutes` is `words` over `wordsPerMinute`, rounded up, so any text takes at least a minute. It is 0 only for a document with no words.\n- `countWords(text)`, also exported, counts any string the same way, such as an excerpt.\n\n## Show it\n\nWith `@comark/html`, parse once, read the meta, and render that document:\n\n```ts\nimport { renderHtmlFromDocument } from \"@comark/html\";\nimport { parseMarkdown } from \"comark\";\nimport comarkUi from \"comark-ui/html\";\n\nconst { plugins, components } = comarkUi();\nconst document = await parseMarkdown(markdown, { plugins });\nconst body = await renderHtmlFromDocument(document, { components });\nconst html = `<p class=\"byline\">${document.meta.readingTime.minutes} min read</p>${body}`;\n```\n\nWith `@comark/vue` or `@comark/react`, read `meta.readingTime` from the parsed document you pass to `MarkdownDocument`.\n\n## Register\n\n- In `comark-ui`: on in every entry. `readingTime: { wordsPerMinute: 230 }` sets the speed; 0 or less counts at 200. The default, 200, is a cautious pace for technical prose; 230 to 250 suits light reading, and a site mostly in CJK may want more.\n- Alone: `pnpm add comark comark-reading-time`, then `parseMarkdown(markdown, { plugins: [readingTime()] })` with `readingTime` from `comark-reading-time`. It has no components, so it works with any renderer.\n"
|
|
206
206
|
},
|
|
207
|
+
{
|
|
208
|
+
"path": "references/remark-to-comark.md",
|
|
209
|
+
"text": "# Moving a project from remark\n\nremark-to-comark moves a project that renders Markdown with remark, rehype, unified, or react-markdown to Comark. It reports what it finds as diagnostics, `RTC0101` to `RTC0303`, each with a fix and a link to https://comark-ui.onmax.me/remark-to-comark/diagnostics/.\n\n## Run it\n\n```sh\nvp exec remark-to-comark check . --json\nvp exec remark-to-comark content \"**/*.{md,mdx}\" --write\nvp exec remark-to-comark rewrite . --write\nvp exec remark-to-comark check . --json\n```\n\n- `check` lists the remark setups it finds and what each plugin becomes, the unified chains `rewrite` can replace and why the others stay, the Markdown files `content` would change, and the MDX it leaves alone. `--json` prints each finding with its code, file, line, fix, and docs link.\n- `rewrite` replaces a chain like `unified().use(remarkParse).use(remarkRehype).use(rehypeStringify).process(markdown)` with `renderHtml(markdown, comarkOptions({ … }))`, importing `comarkOptions` from `remark-to-comark/setup`. Install what the new code imports: `comark`, `@comark/html`, and `remark-to-comark`.\n- `content` escapes `{`, `[`, and `:name` that Comark would read as attributes, spans, or components, so remark still renders every file byte for byte as before. It parses with the project's syntax plugins, so `$x_{i}$` stays math. Run it before `rewrite`, which removes the remark code it reads them from.\n- Run `check` again at the end. What's left is work for you: framework configs (RTC0101), the project's own plugins (RTC0105), chains it couldn't rewrite (RTC0201), MDX (RTC0301), and blocks left as written (RTC0303).\n\n## What it leaves to you\n\n- A framework config, such as Astro's `markdown.remarkPlugins` or Docusaurus' `remarkPlugins`, stays as it is: the framework calls remark. Render with `renderHtml(markdown, comarkOptions())` where the framework lets you, such as a content loader or a route.\n- react-markdown becomes `<Markdown value={markdown} options={…} plugins={[…]} />` from `@comark/react`, with the plugins the findings name.\n- A plugin a comark-ui package replaces is reported with that package (RTC0102); its markup differs from the remark plugin's, so check pages that style it.\n- MDX stays MDX. Convert a page by hand only when its JSX just passes props: rename it to `.md`, run `content` on the prose, then write the components as Comark blocks. `content` escapes Comark syntax, so don't run it after you add them.\n\n## Register\n\n- In `comark-ui`: not included. Install it beside the preset for the migration.\n- Alone: `pnpm add -D remark-to-comark`. It installs the command `remark-to-comark`, the library `remark-to-comark`, the Comark setup `remark-to-comark/setup` (add it to your runtime dependencies when rewritten code imports it), the ports `remark-to-comark/plugins`, and the Vite Doctor extension `remark-to-comark/doctor`.\n"
|
|
210
|
+
},
|
|
207
211
|
{
|
|
208
212
|
"path": "references/sources.md",
|
|
209
213
|
"text": "# Citations and sources\n\ncomark-sources turns `:cite[n]` into a numbered link to the nth source in the document's `::sources` list, and gives each source a link back to every citation of it. Use it when the claims in a document rest on links, such as the research behind a change.\n\n## Syntax\n\n```md\nPigeons find home by the sun and by the earth's magnetic field :cite[1], and some by smell too :cite[2,3].\n\n::sources\n1. [Magnetoreception in homing pigeons](https://en.wikipedia.org/wiki/Magnetoreception)\n2. [Olfactory navigation](https://en.wikipedia.org/wiki/Pigeon_intelligence), on smell\n3. [How do homing pigeons navigate?](https://www.sciencefocus.com/nature/how-do-homing-pigeons-navigate)\n::\n```\n\n- `:cite[2]` cites the second source, and `:cite[1,3]` several. Each becomes a superscript `[1]` that links to its source. Hovering or focusing it shows a card with the source's title, its site, and the icon the list shows for it, a globe when there's none. Put a space before `:cite`, which the plugin removes; `word:cite[1]` stays text, and nothing reports it.\n- `::sources` holds one numbered list with one source per item, each with its link. Sources count by their place in the list. Text after the link, such as `, on smell`, stays in the item. `title` names the list, \"Sources\" by default. The plugin drops anything beside the list and reports it.\n- A document has one `::sources`, anywhere in it, and citations before and after it both count. A citation of a number the list doesn't have, a source with no link, and a second list are reported.\n\n## Register\n\n- In `comark-ui`: on. It takes no options.\n- Alone: `pnpm add comark @comark/html comark-sources`, then `createHtmlRenderer({ plugins: [sources()], components })` with both from `comark-sources/html`. `comark-sources/vue`, `/react`, and `/svelte` render it too. Citations are plain `sup` links that work in any renderer, and the `sources` component draws the list and carries the styles for both. It has no options. The HTML renderer inlines the card's script once per document, and the components start it when they mount.\n"
|
|
@@ -321,6 +325,6 @@ const skills = [
|
|
|
321
325
|
}
|
|
322
326
|
];
|
|
323
327
|
/** The comark-ui version the skills come from, for a host's cache key or a digest. */
|
|
324
|
-
const version = "0.8.
|
|
328
|
+
const version = "0.8.2";
|
|
325
329
|
//#endregion
|
|
326
330
|
export { skills, version };
|
|
@@ -1,14 +1,61 @@
|
|
|
1
|
+
import { n as isElement, t as childrenOf } from "./nodes-CwDBFXnO.mjs";
|
|
1
2
|
import cjk from "comark-cjk";
|
|
2
3
|
import critic, { css as criticCss } from "comark-critic";
|
|
3
4
|
import deflist from "comark-deflist";
|
|
4
5
|
import figure from "comark-figure";
|
|
5
6
|
import footnotes from "comark-footnotes";
|
|
7
|
+
import { HTML_TAGS } from "comark-github";
|
|
6
8
|
import { createIcons } from "comark-icon";
|
|
7
9
|
import include from "comark-include";
|
|
8
10
|
import keys from "comark-keys";
|
|
9
11
|
import readingTime from "comark-reading-time";
|
|
10
12
|
import xref from "comark-xref";
|
|
11
13
|
import { defineComarkPlugin } from "comark";
|
|
14
|
+
import { css as commentsCss } from "comark-comments";
|
|
15
|
+
//#region src/mermaid-limits.ts
|
|
16
|
+
function diagramsOf(nodes, found = []) {
|
|
17
|
+
for (const node of nodes) {
|
|
18
|
+
if (!isElement(node)) continue;
|
|
19
|
+
if (node[0] === "pele") found.push(node);
|
|
20
|
+
else diagramsOf(childrenOf(node), found);
|
|
21
|
+
}
|
|
22
|
+
return found;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Turns the diagrams past a document's limits back into code blocks, before comark-code reads them, so a host that
|
|
26
|
+
* renders other people's documents bounds the time Pele spends drawing. Each one it turns back is a `meta.issues` entry.
|
|
27
|
+
*/
|
|
28
|
+
var mermaid_limits_default = defineComarkPlugin(({ maxDiagrams = Infinity, maxSource = Infinity } = {}) => ({
|
|
29
|
+
name: "comark-ui-mermaid-limits",
|
|
30
|
+
post({ tree }) {
|
|
31
|
+
const issues = [];
|
|
32
|
+
let drawn = 0;
|
|
33
|
+
let source = 0;
|
|
34
|
+
for (const [n, node] of diagramsOf(tree.nodes).entries()) {
|
|
35
|
+
const content = node[1].content;
|
|
36
|
+
const why = drawn >= maxDiagrams ? ["comark/mermaid/too-many-diagrams", `a document draws at most ${maxDiagrams} Mermaid diagrams. Move it to another document`] : source + content.length > maxSource ? ["comark/mermaid/source-too-long", `a document draws at most ${maxSource} characters of Mermaid. Shorten it or move it to another document`] : void 0;
|
|
37
|
+
if (!why) {
|
|
38
|
+
drawn++;
|
|
39
|
+
source += content.length;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const language = node[1].language ?? "mermaid";
|
|
43
|
+
node.splice(0, node.length, "pre", { language }, [
|
|
44
|
+
"code",
|
|
45
|
+
{ class: `language-${language}` },
|
|
46
|
+
content.replace(/\n$/, "")
|
|
47
|
+
]);
|
|
48
|
+
issues.push([why[0], `Mermaid diagram ${n + 1} shows its source as code, because ${why[1]}.`]);
|
|
49
|
+
}
|
|
50
|
+
if (!issues.length) return;
|
|
51
|
+
tree.meta.issues = [...tree.meta.issues ?? [], ...issues.map(([, message]) => message)];
|
|
52
|
+
tree.meta.issueRules = {
|
|
53
|
+
...tree.meta.issueRules,
|
|
54
|
+
...Object.fromEntries(issues.map(([rule, message]) => [message, rule]))
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}));
|
|
58
|
+
//#endregion
|
|
12
59
|
//#region src/typeset.ts
|
|
13
60
|
/** The node that adds the styles. The plugin adds one at the end of every document. */
|
|
14
61
|
const TYPESET_TAG = "typeset-styles";
|
|
@@ -21,6 +68,34 @@ const typeset = defineComarkPlugin(() => ({
|
|
|
21
68
|
}));
|
|
22
69
|
//#endregion
|
|
23
70
|
//#region src/index.ts
|
|
71
|
+
const words = (text) => text.split(" ");
|
|
72
|
+
const MARKDOWN_TAGS = words("a blockquote br code del em h1 h2 h3 h4 h5 h6 hr img input li ol p pre span strong table tbody td th thead tr ul");
|
|
73
|
+
const TAGS = [
|
|
74
|
+
["carousel", words("div")],
|
|
75
|
+
["codeNotes", words("div span")],
|
|
76
|
+
["critic", words("del ins mark")],
|
|
77
|
+
["deflist", words("dd dl dt")],
|
|
78
|
+
["figure", words("figcaption figure")],
|
|
79
|
+
["footnotes", words("section sup")],
|
|
80
|
+
["keys", words("kbd")],
|
|
81
|
+
["mark", words("mark sup")],
|
|
82
|
+
["metrics", words("dd div dt")],
|
|
83
|
+
["outline", words("a div li ul")],
|
|
84
|
+
["properties", words("dd div dt time")],
|
|
85
|
+
["quiz", words("div quiz-after quiz-answer quiz-explain quiz-hint quiz-label quiz-option quiz-options quiz-prompt quiz-rationale")],
|
|
86
|
+
["sources", words("ol sup")],
|
|
87
|
+
["table", words("button div span")],
|
|
88
|
+
["tabs", words("div tabs-item")],
|
|
89
|
+
["tests", words("details div summary")],
|
|
90
|
+
["xref", words("caption figcaption figure")]
|
|
91
|
+
];
|
|
92
|
+
const BLOCKS = [
|
|
93
|
+
["details", words("accordion-item collapsible details")],
|
|
94
|
+
["metrics", words("progress stats")],
|
|
95
|
+
["table", words("table")],
|
|
96
|
+
["tabs", words("code-group tabs-item")],
|
|
97
|
+
["xref", words("ref")]
|
|
98
|
+
];
|
|
24
99
|
const on = (value, fallback = true) => value === void 0 ? fallback : value !== false;
|
|
25
100
|
const optionsOf = (value) => value === true || value === false ? void 0 : value;
|
|
26
101
|
const noFiles = { read: () => void 0 };
|
|
@@ -49,7 +124,14 @@ function preset(renderer, options = {}) {
|
|
|
49
124
|
add(renderer.chips, options.chips);
|
|
50
125
|
add(renderer.colors, options.colors);
|
|
51
126
|
add(renderer.diagrams, options.diagrams);
|
|
52
|
-
|
|
127
|
+
if (on(options.mermaid)) {
|
|
128
|
+
const { maxDiagrams, maxSource, ...pele } = optionsOf(options.mermaid) ?? {};
|
|
129
|
+
add(renderer.mermaid, true, pele);
|
|
130
|
+
if (maxDiagrams !== void 0 || maxSource !== void 0) plugins.push(mermaid_limits_default({
|
|
131
|
+
maxDiagrams,
|
|
132
|
+
maxSource
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
53
135
|
add(renderer.diff, options.diff);
|
|
54
136
|
add(renderer.embed, options.embed);
|
|
55
137
|
parse(footnotes, options.footnotes);
|
|
@@ -111,10 +193,26 @@ function preset(renderer, options = {}) {
|
|
|
111
193
|
plugins.push(typeset());
|
|
112
194
|
components[TYPESET_TAG] = renderer.typeset;
|
|
113
195
|
}
|
|
196
|
+
const { annotate, comments, diff, quiz } = renderer;
|
|
197
|
+
const absent = Object.entries({
|
|
198
|
+
annotate,
|
|
199
|
+
comments,
|
|
200
|
+
diff,
|
|
201
|
+
quiz
|
|
202
|
+
}).flatMap(([key, part]) => part ? [] : [key]);
|
|
203
|
+
const enabled = (key) => on(options[key], key !== "include") && !absent.includes(key);
|
|
204
|
+
const tags = /* @__PURE__ */ new Set([
|
|
205
|
+
...MARKDOWN_TAGS,
|
|
206
|
+
...on(options.github) && on(optionsOf(options.github)?.html) ? HTML_TAGS : [],
|
|
207
|
+
...TAGS.flatMap(([key, list]) => enabled(key) ? list : [])
|
|
208
|
+
]);
|
|
209
|
+
const blocks = BLOCKS.flatMap(([key, list]) => enabled(key) ? list : []);
|
|
114
210
|
return {
|
|
115
211
|
plugins,
|
|
116
|
-
components
|
|
212
|
+
components,
|
|
213
|
+
tags: [...tags],
|
|
214
|
+
blocks
|
|
117
215
|
};
|
|
118
216
|
}
|
|
119
217
|
//#endregion
|
|
120
|
-
export { typeset as i,
|
|
218
|
+
export { typeset as a, TYPESET_TAG as i, criticCss as n, preset as r, commentsCss as t };
|
package/dist/svelte/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Component } from "svelte";
|
|
2
2
|
import type { Preset, PresetOptions } from "comark-ui";
|
|
3
3
|
|
|
4
|
-
export { criticCss } from "comark-ui";
|
|
4
|
+
export { commentsCss, criticCss } from "comark-ui";
|
|
5
5
|
export type { PresetOptions } from "comark-ui";
|
|
6
6
|
|
|
7
7
|
/** Every plugin with components for `@comark/svelte`, which leaves out annotate, comments, diff, and quiz. */
|
package/dist/svelte/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import * as zoom from "comark-zoom/svelte";
|
|
|
35
35
|
import Mermaid from "./Mermaid.svelte";
|
|
36
36
|
import typeset from "./Typeset.svelte";
|
|
37
37
|
|
|
38
|
-
export { criticCss } from "comark-ui";
|
|
38
|
+
export { commentsCss, criticCss } from "comark-ui";
|
|
39
39
|
|
|
40
40
|
const mermaid = { default: pele, components: { pele: Mermaid } };
|
|
41
41
|
|
|
@@ -89,7 +89,7 @@ const rules = `
|
|
|
89
89
|
&:where(ul > li, ol > li)::marker { color: var(--_ty-muted); }
|
|
90
90
|
&:where(ul.contains-task-list) { list-style-type: none; padding-inline-start: 0.25em; }
|
|
91
91
|
&:where(li.task-list-item > input[type="checkbox"]) {
|
|
92
|
-
margin-inline-end: 0.5em; vertical-align: -0.1em; accent-color: var(--
|
|
92
|
+
margin-inline-end: 0.5em; vertical-align: -0.1em; accent-color: var(--_comark-primary);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
&:where(details) { margin-block: var(--_ty-flow) 0; }
|
|
@@ -137,7 +137,8 @@ const rules = `
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
&:where(img, video) { border-radius: var(--_ty-radius); max-width: 100%; height: auto; margin-block: var(--_ty-flow) 0; }
|
|
140
|
-
|
|
140
|
+
/* An image in a line of text sits on the text; a block's top margin would push it below. */
|
|
141
|
+
&:where(:is(p, li, td, th, a) img) { margin-block-start: 0; }
|
|
141
142
|
&:where(figure) { margin-block: var(--_ty-flow) 0; margin-inline: 0; }
|
|
142
143
|
&:where(figcaption, caption) {
|
|
143
144
|
color: var(--_ty-muted); font-size: 0.875em; text-align: center; margin-block-start: calc(0.75em / 0.875);
|
|
@@ -175,10 +176,18 @@ const rules = `
|
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
/* Code highlighted with a light and a dark theme follows the page into dark mode, as the tokens do: a .dark class
|
|
178
|
-
above it, or the system's dark mode on a page with no .light class.
|
|
179
|
-
.shiki:where(.dark *) span
|
|
179
|
+
above it, or the system's dark mode on a page with no .light class. A span switches what it has a dark value for. */
|
|
180
|
+
.shiki:where(.dark *) span {
|
|
181
|
+
&[style*="--shiki-dark:"] { color: var(--shiki-dark) !important; }
|
|
182
|
+
&[style*="--shiki-dark-font-style:"] { font-style: var(--shiki-dark-font-style) !important; }
|
|
183
|
+
&[style*="--shiki-dark-font-weight:"] { font-weight: var(--shiki-dark-font-weight) !important; }
|
|
184
|
+
}
|
|
180
185
|
@media (prefers-color-scheme: dark) {
|
|
181
|
-
.shiki:not(:where(.light *)) span
|
|
186
|
+
.shiki:not(:where(.light *)) span {
|
|
187
|
+
&[style*="--shiki-dark:"] { color: var(--shiki-dark) !important; }
|
|
188
|
+
&[style*="--shiki-dark-font-style:"] { font-style: var(--shiki-dark-font-style) !important; }
|
|
189
|
+
&[style*="--shiki-dark-font-weight:"] { font-weight: var(--shiki-dark-font-weight) !important; }
|
|
190
|
+
}
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
/* A block marked data-wide, such as a before/after comparison or a diagram wider than the text, grows past the column
|
|
@@ -211,6 +220,12 @@ const rules = `
|
|
|
211
220
|
* page alone. The `typeset` layer sits inside `comark`, so every block's own rules win over it, and any plain rule of
|
|
212
221
|
* the page wins over both.
|
|
213
222
|
*/
|
|
214
|
-
const typesetCss = `@layer comark{@layer typeset{@scope{${theme(":scope")}${rules}}}}`.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").replace(/ ?([{};,>(]) ?/g, "$1").replace(/: /g, ":").trim();
|
|
223
|
+
const typesetCss = `@layer comark{@layer typeset{@scope{${theme(":scope", "primary")}${rules}}}}`.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").replace(/ ?([{};,>(]) ?/g, "$1").replace(/: /g, ":").trim();
|
|
224
|
+
/**
|
|
225
|
+
* The same styles for a page's own stylesheet, scoped to every element that matches `selector`, for Comark content
|
|
226
|
+
* that isn't a rendered document, such as a rich-text editor. `comark-ui/typeset.css` is this with `.comark-typeset`.
|
|
227
|
+
* The rules are the same string as `typesetCss`, so the two can't drift.
|
|
228
|
+
*/
|
|
229
|
+
const typesetStylesheet = (selector = ".comark-typeset") => typesetCss.replace("@scope{", `@scope (${selector}){`);
|
|
215
230
|
//#endregion
|
|
216
|
-
export { typesetCss as t };
|
|
231
|
+
export { typesetStylesheet as n, typesetCss as t };
|
|
@@ -6,5 +6,11 @@
|
|
|
6
6
|
* the page wins over both.
|
|
7
7
|
*/
|
|
8
8
|
declare const typesetCss: string;
|
|
9
|
+
/**
|
|
10
|
+
* The same styles for a page's own stylesheet, scoped to every element that matches `selector`, for Comark content
|
|
11
|
+
* that isn't a rendered document, such as a rich-text editor. `comark-ui/typeset.css` is this with `.comark-typeset`.
|
|
12
|
+
* The rules are the same string as `typesetCss`, so the two can't drift.
|
|
13
|
+
*/
|
|
14
|
+
declare const typesetStylesheet: (selector?: string) => string;
|
|
9
15
|
//#endregion
|
|
10
|
-
export { typesetCss as t };
|
|
16
|
+
export { typesetStylesheet as n, typesetCss as t };
|
package/dist/typeset.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer comark{@layer typeset{@scope (.comark-typeset){:where(:scope){--_comark-background:var(--comark-background,var(--ui-bg,var(--background,#fff)));--_comark-foreground:var(--comark-foreground,var(--ui-text-highlighted,var(--foreground,#0a0a0a)));--_comark-muted:var(--comark-muted,var(--ui-text-muted,var(--muted-foreground,#737373)));--_comark-border:var(--comark-border,var(--ui-border,var(--border,#e5e5e5)));--_comark-accent:var(--comark-accent,var(--ui-bg-elevated,var(--accent,#f5f5f5)));--_comark-ring:var(--comark-ring,var(--ui-primary,var(--ring,#a1a1a1)));--_comark-primary:var(--comark-primary,var(--ui-primary,var(--primary,var(--_comark-foreground))));--_comark-primary-foreground:var(--comark-primary-foreground,var(--ui-text-inverted,var(--primary-foreground,var(--_comark-background))));--_comark-secondary:var(--comark-secondary,var(--ui-secondary,var(--_comark-muted)));--_comark-radius:var(--comark-radius,calc(var(--ui-radius,calc(var(--radius,.625rem)/2))*2));--_comark-font:var(--comark-font,var(--font-sans,ui-sans-serif,system-ui,sans-serif))}@media(prefers-color-scheme:dark){:where(:scope){--_comark-background:var(--comark-background,var(--ui-bg,var(--background,#0a0a0a)));--_comark-foreground:var(--comark-foreground,var(--ui-text-highlighted,var(--foreground,#fafafa)));--_comark-muted:var(--comark-muted,var(--ui-text-muted,var(--muted-foreground,#a1a1a1)));--_comark-border:var(--comark-border,var(--ui-border,var(--border,rgb(255 255 255/.1))));--_comark-accent:var(--comark-accent,var(--ui-bg-elevated,var(--accent,#262626)));--_comark-ring:var(--comark-ring,var(--ui-primary,var(--ring,#737373)));--_comark-primary:var(--comark-primary,var(--ui-primary,var(--primary,var(--_comark-foreground))));--_comark-primary-foreground:var(--comark-primary-foreground,var(--ui-text-inverted,var(--primary-foreground,var(--_comark-background))));--_comark-secondary:var(--comark-secondary,var(--ui-secondary,var(--_comark-muted)))}}:scope{--_ty-flow:var(--typeset-flow,1.25em);--_ty-muted:var(--_comark-muted);--_ty-rule:var(--_comark-border);--_ty-surface:var(--_comark-accent);--_ty-radius:calc(var(--_comark-radius) * 0.8);--_ty-mono:var(--comark-font-mono,var(--font-mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace));font-family:var(--_comark-font);font-size:calc(var(--typeset-size,1em) * 1.125);line-height:var(--typeset-leading,1.75);color:var(--_comark-foreground);overflow-wrap:break-word;background-image:var(--comark-grain,url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E"));background-repeat:repeat;background-size:var(--comark-grain-size,256px 256px);@media(min-width:48rem),print{font-size:var(--typeset-size,1em);}}:scope *:not(:where(.not-typeset,[data-not-typeset],.not-typeset *,[data-not-typeset] *)){&:where(p){margin-block:var(--_ty-flow) 0;}&:where(h1,h2,h3,h4,h5,h6){color:var(--_comark-foreground);font-family:var(--comark-font-heading,var(--font-heading,inherit));font-weight:600;margin-block-end:0;}&:where(h1){font-size:1.75em;line-height:1.3;margin-block-start:var(--_ty-flow);}&:where(h2){font-size:1.25em;line-height:1.4;margin-block-start:calc(var(--_ty-flow) * 1.4);}&:where(h3){font-size:1.125em;line-height:1.45;margin-block-start:var(--_ty-flow);}&:where(h4){font-size:1em;line-height:1.5;margin-block-start:var(--_ty-flow);}&:where(h5){font-size:0.875em;line-height:1.5;font-weight:500;color:var(--_ty-muted);margin-block-start:calc(var(--_ty-flow) / 0.875);}&:where(h6){font-size:0.8125em;line-height:1.5;font-weight:500;letter-spacing:0.08em;text-transform:uppercase;color:var(--_ty-muted);margin-block-start:calc(var(--_ty-flow) / 0.8125);}&:where([id]){scroll-margin-block-start:var(--_ty-flow);}&:where(h1 + *,h2 + *,h3 + *,h4 + *,h5 + *,h6 + *){margin-block-start:1em;}&:where(:is(h1,h2,h3,h4) code){font-size:0.9em;}&:where(a){color:inherit;font-weight:500;text-decoration-line:underline;text-decoration-color:color-mix(in oklab,currentColor 30%,transparent);}&:where(a:hover){text-decoration-color:currentColor;}&:where(a:focus-visible){outline:2px solid var(--_comark-ring);outline-offset:2px;border-radius:0.125em;}&:where(:is(h1,h2,h3,h4,h5,h6) a){font-weight:inherit;}&:where(strong,b){font-weight:600;}&:where(mark){background-color:color-mix(in oklab,oklch(0.86 0.17 95) 40%,transparent);color:inherit;padding:0.05em 0.15em;border-radius:0.2em;}&:where(abbr[title]){text-decoration-line:underline;text-decoration-style:dotted;text-underline-offset:0.2em;cursor:help;}&:where(del,s){color:var(--_ty-muted);text-decoration-line:line-through;}&:where(sup,sub){font-size:0.75em;line-height:0;position:relative;vertical-align:baseline;}&:where(sup){top:-0.5em;}&:where(sub){bottom:-0.25em;}&:where(sup a){text-decoration-line:none;font-weight:500;}&:where(ul){list-style-type:disc;}&:where(ol){list-style-type:decimal;}&:where(ul ul){list-style-type:circle;}&:where(ul ul ul){list-style-type:square;}&:where(ol[type="a" i]){list-style-type:lower-alpha;}&:where(ol[type="i" i]){list-style-type:lower-roman;}&:where(ol[type="A" s]){list-style-type:upper-alpha;}&:where(ol[type="I" s]){list-style-type:upper-roman;}&:where(ul,ol){margin-block:var(--_ty-flow) 0;padding-inline-start:1.5em;}&:where(li){margin-block-start:0.5em;padding-inline-start:0.4em;}&:where(li>p,li>ul,li>ol){margin-block-start:0.5em;}&:where(ul>li,ol>li)::marker{color:var(--_ty-muted);}&:where(ul.contains-task-list){list-style-type:none;padding-inline-start:0.25em;}&:where(li.task-list-item>input[type="checkbox"]){margin-inline-end:0.5em;vertical-align:-0.1em;accent-color:var(--_comark-primary);}&:where(details){margin-block:var(--_ty-flow) 0;}&:where(summary){cursor:pointer;font-weight:500;}&:where(summary)::marker{color:var(--_ty-muted);}&:where(kbd){font-family:inherit;font-size:0.85em;font-weight:500;border:1px solid var(--_ty-rule);border-block-end-width:2px;border-radius:0.35em;padding:0.0625em 0.35em;}&:where(dl){margin-block:var(--_ty-flow) 0;}&:where(dt){font-weight:500;margin-block-start:1em;}&:where(dt + dt){margin-block-start:0.25em;}&:where(dd){margin-block-start:0.25em;margin-inline-start:0;padding-inline-start:1em;color:var(--_ty-muted);}&:where(:not(pre)>code){background-color:var(--_ty-surface);font-family:var(--_ty-mono);font-size:0.85em;border-radius:0.35em;padding:0.125em 0.3em;}&:where(pre){background-color:var(--_ty-surface);font-family:var(--_ty-mono);font-size:0.875em;line-height:1.5;tab-size:2;direction:ltr;border-radius:var(--_ty-radius);padding:0.75em 1em;overflow-x:auto;margin-block:calc(var(--_ty-flow) / 0.875) 0;}&:where(pre code){background-color:transparent;font-family:inherit;font-size:inherit;padding:0;border-radius:0;}&:where(blockquote){border-inline-start:2px solid var(--_ty-rule);padding-inline-start:1em;margin-block:var(--_ty-flow) 0;margin-inline:0;}&:where(hr){border:0;border-block-start:1px solid var(--_ty-rule);margin-block:calc(var(--_ty-flow) * 2.4) 0;}&:where(hr + h1,hr + h2,hr + h3,hr + h4){margin-block-start:var(--_ty-flow);}&:where(.footnotes,[data-footnotes]){margin-block-start:calc(var(--_ty-flow) * 2);font-size:0.875em;color:var(--_ty-muted);}&:where(.footnotes>hr:first-child){margin-block-start:0;}&:where(.footnote-ref a,.footnote-backref){text-decoration-line:none;}&:where(math[display="block"]){margin-block:var(--_ty-flow) 0;overflow-x:auto;overflow-y:hidden;padding-block:0.25em;}&:where(img,video){border-radius:var(--_ty-radius);max-width:100%;height:auto;margin-block:var(--_ty-flow) 0;}&:where(:is(p,li,td,th,a) img){margin-block-start:0;}&:where(figure){margin-block:var(--_ty-flow) 0;margin-inline:0;}&:where(figcaption,caption){color:var(--_ty-muted);font-size:0.875em;text-align:center;margin-block-start:calc(0.75em / 0.875);}&:where(caption){caption-side:bottom;}&:where(table){display:block;width:max-content;max-width:100%;overflow-x:auto;font-size:1em;line-height:1.5;font-variant-numeric:tabular-nums;border-collapse:separate;border-spacing:0;border-block-end:1px solid var(--_ty-rule);margin-block:var(--_ty-flow) 0;}&:where(thead th){font-weight:500;text-align:start;padding:0.65em 1em;}&:where(:is(tbody,tfoot) :is(td,th)){padding:0.75em 1em;text-align:start;vertical-align:top;border-block-start:1px solid var(--_ty-rule);}&:where(tbody th,tfoot th){font-weight:500;}&:where(th:first-child,td:first-child){padding-inline-start:0;}&:where(th[align="center"],td[align="center"]){text-align:center;}&:where(th[align="right"],td[align="right"]){text-align:end;}&:where(li>blockquote,li>table,li>figure){margin-block-start:0.5em;}&:where(li>pre){margin-block-start:calc(0.5em / 0.875);}@media print{&:where(pre,table,blockquote,figure){break-inside:avoid;}&:where(h1,h2,h3,h4){break-after:avoid;}}@media(forced-colors:active){&:where(:not(pre)>code){border:1px solid;}}}.shiki:where(.dark *) span{&[style*="--shiki-dark:"]{color:var(--shiki-dark) !important;}&[style*="--shiki-dark-font-style:"]{font-style:var(--shiki-dark-font-style) !important;}&[style*="--shiki-dark-font-weight:"]{font-weight:var(--shiki-dark-font-weight) !important;}}@media(prefers-color-scheme:dark){.shiki:not(:where(.light *)) span{&[style*="--shiki-dark:"]{color:var(--shiki-dark) !important;}&[style*="--shiki-dark-font-style:"]{font-style:var(--shiki-dark-font-style) !important;}&[style*="--shiki-dark-font-weight:"]{font-weight:var(--shiki-dark-font-weight) !important;}}}:scope>[data-wide]{--_ty-start:max(0px,var(--comark-wide-start,0px));--_ty-end:max(0px,var(--comark-wide-end,0px));--_ty-wide:max(100%,min(var(--comark-wide-width,100vw),var(--comark-wide-max,72rem),100% + var(--_ty-start) + var(--_ty-end)));width:var(--_ty-wide);margin-inline:clamp(-1 * var(--_ty-start),(100% - var(--_ty-wide)) / 2,100% + var(--_ty-end) - var(--_ty-wide)) 0;}:scope>:where(:first-child):not(:where(.not-typeset,[data-not-typeset],.not-typeset *,[data-not-typeset] *)),:scope>:where(:first-child)>:where(:first-child):not(:where(.not-typeset,[data-not-typeset],.not-typeset *,[data-not-typeset] *)),:scope :where(li>:first-child,blockquote>:first-child,td>:first-child,th>:first-child,dd>:first-child,figure>:first-child,figure>picture>img ):not(:where(.not-typeset,[data-not-typeset],.not-typeset *,[data-not-typeset] *)){margin-block-start:0;}}}}
|
package/dist/vue.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as commentsCss, n as Preset, o as criticCss, r as PresetOptions } from "./index-BTyvRIPX.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. */
|
|
5
5
|
declare const _default: (options?: PresetOptions) => Preset<Component>;
|
|
6
6
|
//#endregion
|
|
7
|
-
export { type PresetOptions, criticCss, _default as default };
|
|
7
|
+
export { type PresetOptions, commentsCss, criticCss, _default as default };
|
package/dist/vue.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
import { i as startMermaid, n as mermaidBar, t as addMermaidStyles } from "./client-
|
|
1
|
+
import { n as criticCss, r as preset, t as commentsCss } from "./src-Baygj6ZQ.mjs";
|
|
2
|
+
import { t as typesetCss } from "./typeset-css-BYvWbqWz.mjs";
|
|
3
|
+
import { i as startMermaid, n as mermaidBar, t as addMermaidStyles } from "./client-kUEiRbtp.mjs";
|
|
4
4
|
import * as properties from "comark-properties/vue";
|
|
5
5
|
import { defineComponent, h, onBeforeUnmount, onMounted } from "vue";
|
|
6
6
|
import * as badge from "comark-badge/vue";
|
|
@@ -110,4 +110,4 @@ var vue_default = (options) => preset({
|
|
|
110
110
|
zoom
|
|
111
111
|
}, options);
|
|
112
112
|
//#endregion
|
|
113
|
-
export { criticCss, vue_default as default };
|
|
113
|
+
export { commentsCss, criticCss, vue_default as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comark-ui",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
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",
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"type": "module",
|
|
26
|
-
"sideEffects":
|
|
26
|
+
"sideEffects": [
|
|
27
|
+
"*.css"
|
|
28
|
+
],
|
|
27
29
|
"exports": {
|
|
28
30
|
".": "./dist/index.mjs",
|
|
29
31
|
"./client": "./dist/client.mjs",
|
|
@@ -40,7 +42,8 @@
|
|
|
40
42
|
"./vue": "./dist/vue.mjs",
|
|
41
43
|
"./package.json": "./package.json",
|
|
42
44
|
"./skills": "./dist/skills.mjs",
|
|
43
|
-
"./skills/*": "./dist/skills/*"
|
|
45
|
+
"./skills/*": "./dist/skills/*",
|
|
46
|
+
"./typeset.css": "./dist/typeset.css"
|
|
44
47
|
},
|
|
45
48
|
"publishConfig": {
|
|
46
49
|
"access": "public",
|
|
@@ -48,50 +51,50 @@
|
|
|
48
51
|
},
|
|
49
52
|
"dependencies": {
|
|
50
53
|
"comark-pele": "^1.1.0",
|
|
51
|
-
"comark-annotate": "^0.8.
|
|
52
|
-
"comark-
|
|
53
|
-
"comark-
|
|
54
|
-
"comark-
|
|
55
|
-
"comark-
|
|
56
|
-
"comark-badge": "^0.8.
|
|
57
|
-
"comark-chips": "^0.8.
|
|
58
|
-
"comark-
|
|
59
|
-
"comark-
|
|
60
|
-
"comark-colors": "^0.8.
|
|
61
|
-
"comark-
|
|
62
|
-
"comark-
|
|
63
|
-
"comark-deflist": "^0.8.
|
|
64
|
-
"comark-
|
|
65
|
-
"comark-
|
|
66
|
-
"comark-
|
|
67
|
-
"comark-embed": "^0.8.
|
|
68
|
-
"comark-
|
|
69
|
-
"comark-
|
|
70
|
-
"comark-
|
|
71
|
-
"comark-
|
|
72
|
-
"comark-
|
|
73
|
-
"comark-
|
|
74
|
-
"comark-
|
|
75
|
-
"comark-
|
|
76
|
-
"comark-
|
|
77
|
-
"comark-
|
|
78
|
-
"comark-
|
|
79
|
-
"comark-
|
|
80
|
-
"comark-
|
|
81
|
-
"comark-
|
|
82
|
-
"comark-
|
|
83
|
-
"comark-
|
|
84
|
-
"comark-
|
|
85
|
-
"comark-
|
|
86
|
-
"comark-
|
|
87
|
-
"comark-
|
|
88
|
-
"comark-
|
|
89
|
-
"comark-
|
|
90
|
-
"comark-tabs": "^0.8.
|
|
91
|
-
"comark-
|
|
92
|
-
"comark-
|
|
93
|
-
"comark-
|
|
94
|
-
"comark-
|
|
54
|
+
"comark-annotate": "^0.8.2",
|
|
55
|
+
"comark-cast": "^0.8.2",
|
|
56
|
+
"comark-cards": "^0.8.2",
|
|
57
|
+
"comark-charts": "^0.8.2",
|
|
58
|
+
"comark-carousel": "^0.8.2",
|
|
59
|
+
"comark-badge": "^0.8.2",
|
|
60
|
+
"comark-chips": "^0.8.2",
|
|
61
|
+
"comark-cjk": "^0.8.2",
|
|
62
|
+
"comark-code": "^0.8.2",
|
|
63
|
+
"comark-colors": "^0.8.2",
|
|
64
|
+
"comark-critic": "^0.8.2",
|
|
65
|
+
"comark-details": "^0.8.2",
|
|
66
|
+
"comark-deflist": "^0.8.2",
|
|
67
|
+
"comark-comments": "^0.8.2",
|
|
68
|
+
"comark-diagrams": "^0.8.2",
|
|
69
|
+
"comark-code-notes": "^0.8.2",
|
|
70
|
+
"comark-embed": "^0.8.2",
|
|
71
|
+
"comark-diff": "^0.8.2",
|
|
72
|
+
"comark-fields": "^0.8.2",
|
|
73
|
+
"comark-figure": "^0.8.2",
|
|
74
|
+
"comark-file-tree": "^0.8.2",
|
|
75
|
+
"comark-include": "^0.8.2",
|
|
76
|
+
"comark-icon": "^0.8.2",
|
|
77
|
+
"comark-keys": "^0.8.2",
|
|
78
|
+
"comark-links": "^0.8.2",
|
|
79
|
+
"comark-mathml": "^0.8.2",
|
|
80
|
+
"comark-footnotes": "^0.8.2",
|
|
81
|
+
"comark-mark": "^0.8.2",
|
|
82
|
+
"comark-github": "^0.8.2",
|
|
83
|
+
"comark-magic-move": "^0.8.2",
|
|
84
|
+
"comark-metrics": "^0.8.2",
|
|
85
|
+
"comark-media": "^0.8.2",
|
|
86
|
+
"comark-outline": "^0.8.2",
|
|
87
|
+
"comark-quiz": "^0.8.2",
|
|
88
|
+
"comark-reading-time": "^0.8.2",
|
|
89
|
+
"comark-steps": "^0.8.2",
|
|
90
|
+
"comark-properties": "^0.8.2",
|
|
91
|
+
"comark-table": "^0.8.2",
|
|
92
|
+
"comark-tests": "^0.8.2",
|
|
93
|
+
"comark-tabs": "^0.8.2",
|
|
94
|
+
"comark-xref": "^0.8.2",
|
|
95
|
+
"comark-qr": "^0.8.2",
|
|
96
|
+
"comark-zoom": "^0.8.2",
|
|
97
|
+
"comark-sources": "^0.8.2"
|
|
95
98
|
},
|
|
96
99
|
"devDependencies": {
|
|
97
100
|
"@comark/html": "^0.8.1",
|