comark-cards 0.7.6 → 0.8.0
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 +1 -1
- package/dist/{client-C5acm8_C.mjs → client-DsO8I6Oo.mjs} +69 -12
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +1 -1
- package/dist/html.mjs +6 -3
- package/dist/index.mjs +1 -211
- package/dist/react.mjs +2 -2
- package/dist/src-BsKBRfFx.mjs +232 -0
- package/dist/style.css +1 -1
- package/dist/vue.mjs +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ The plugin adds every problem to `meta.issues`, so a host can reject a document
|
|
|
44
44
|
|
|
45
45
|
| Renderer | Import |
|
|
46
46
|
| --- | --- |
|
|
47
|
-
| `@comark/html` | `comark-cards/html`: the styles are inlined
|
|
47
|
+
| `@comark/html` | `comark-cards/html`: the styles are inlined |
|
|
48
48
|
| `@comark/vue` | `comark-cards/vue` |
|
|
49
49
|
| `@comark/react` | `comark-cards/react` |
|
|
50
50
|
| `@comark/svelte` | `comark-cards/svelte` |
|
|
@@ -43,16 +43,66 @@ const tokens = [
|
|
|
43
43
|
"#737373"
|
|
44
44
|
]
|
|
45
45
|
];
|
|
46
|
-
const
|
|
46
|
+
const groups = {
|
|
47
|
+
status: Object.values({
|
|
48
|
+
success: [
|
|
49
|
+
"success",
|
|
50
|
+
"ui-success",
|
|
51
|
+
"success",
|
|
52
|
+
"#259f56",
|
|
53
|
+
"#59d38c"
|
|
54
|
+
],
|
|
55
|
+
danger: [
|
|
56
|
+
"danger",
|
|
57
|
+
"ui-error",
|
|
58
|
+
"destructive",
|
|
59
|
+
"#ee3533",
|
|
60
|
+
"#fd736d"
|
|
61
|
+
],
|
|
62
|
+
warning: [
|
|
63
|
+
"warning",
|
|
64
|
+
"ui-warning",
|
|
65
|
+
"",
|
|
66
|
+
"#d97706",
|
|
67
|
+
"#fbbf24"
|
|
68
|
+
],
|
|
69
|
+
info: [
|
|
70
|
+
"info",
|
|
71
|
+
"ui-info",
|
|
72
|
+
"",
|
|
73
|
+
"#2563eb",
|
|
74
|
+
"#60a5fa"
|
|
75
|
+
]
|
|
76
|
+
}),
|
|
77
|
+
shadow: [[
|
|
78
|
+
"shadow",
|
|
79
|
+
"",
|
|
80
|
+
"",
|
|
81
|
+
"0 4px 12px rgb(0 0 0/.12)",
|
|
82
|
+
"0 4px 12px rgb(0 0 0/.5)"
|
|
83
|
+
]]
|
|
84
|
+
};
|
|
85
|
+
const chain = (token, scheme) => {
|
|
86
|
+
const shadcn = token[2] ? `var(--${token[2]},${token[scheme]})` : token[scheme];
|
|
87
|
+
const nuxt = token[1] ? `var(--${token[1]},${shadcn})` : shadcn;
|
|
88
|
+
return `var(--comark-${token[0]},${nuxt})`;
|
|
89
|
+
};
|
|
90
|
+
const resolve = (list, scheme) => list.map((token) => `--_comark-${token[0]}:${chain(token, scheme)}`).join(";");
|
|
47
91
|
/**
|
|
48
92
|
* Resolves the `--comark-*` tokens on `selector`, falling back to Nuxt UI's variables, then shadcn/ui's, then shadcn's
|
|
49
93
|
* neutral theme. Nuxt UI's corners are twice its `--ui-radius`, so the radius halves shadcn's to double it back.
|
|
50
94
|
* They resolve on the component rather than `:root`, so a `.dark` class anywhere above it switches the theme, and a
|
|
51
95
|
* `--comark-*` set on any ancestor still inherits down. `:where()` keeps them at zero specificity.
|
|
96
|
+
*
|
|
97
|
+
* Every block gets the core tokens. Name `"status"` for `--comark-success`, `-danger`, `-warning`, and `-info`, and
|
|
98
|
+
* `"shadow"` for `--comark-shadow`, so a block that never draws them doesn't carry them.
|
|
52
99
|
*/
|
|
53
|
-
function theme(selector) {
|
|
100
|
+
function theme(selector, ...extras) {
|
|
54
101
|
const where = `:where(${selector})`;
|
|
55
|
-
|
|
102
|
+
const added = extras.flatMap((name) => groups[name]);
|
|
103
|
+
const list = [...tokens, ...added];
|
|
104
|
+
const classes = added.length ? `:where(.light,.light *)${where}{${resolve(added, 3)}}:where(.dark,.dark *)${where}{${resolve(added, 4)}}` : "";
|
|
105
|
+
return `${where}{${resolve(list, 3)};--_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}{${resolve(list, 4)}}}` + classes;
|
|
56
106
|
}
|
|
57
107
|
//#endregion
|
|
58
108
|
//#region src/styles.ts
|
|
@@ -65,9 +115,8 @@ function theme(selector) {
|
|
|
65
115
|
* primary then to the foreground, so a card is neutral like the other plugins until the page has a brand color. The rules sit in the `comark` layer, so any unlayered rule of the host's wins.
|
|
66
116
|
*/
|
|
67
117
|
const css = `@layer comark{${[
|
|
68
|
-
theme(".ccr,.ccr-group,.ccr-columns"),
|
|
69
|
-
":where(.ccr){--ccr-primary:var(--ui-primary,var(--primary,var(--_comark-foreground)));--ccr-secondary:var(--ui-secondary
|
|
70
|
-
"@media (prefers-color-scheme:dark){:where(.ccr){--ccr-secondary:var(--ui-secondary,#60a5fa);--ccr-success:var(--ui-success,#4ade80);--ccr-info:var(--ui-info,#60a5fa);--ccr-warning:var(--ui-warning,#facc15);--ccr-error:var(--ui-error,var(--destructive,#f87171))}}",
|
|
118
|
+
theme(".ccr,.ccr-group,.ccr-columns", "status"),
|
|
119
|
+
":where(.ccr){--ccr-primary:var(--ui-primary,var(--primary,var(--_comark-foreground)));--ccr-secondary:var(--ui-secondary,var(--_comark-info));--ccr-success:var(--_comark-success);--ccr-info:var(--_comark-info);--ccr-warning:var(--_comark-warning);--ccr-error:var(--_comark-danger);--ccr-neutral:var(--_comark-foreground)}",
|
|
71
120
|
".ccr-group,.ccr-columns{display:grid;gap:1rem;margin:1.5rem 0;container-type:inline-size}",
|
|
72
121
|
".ccr-group{grid-template-columns:repeat(2,minmax(0,1fr))}",
|
|
73
122
|
...[
|
|
@@ -81,7 +130,7 @@ const css = `@layer comark{${[
|
|
|
81
130
|
".ccr-group>.ccr{margin:0}",
|
|
82
131
|
".ccr-column>:first-child{margin-top:0}",
|
|
83
132
|
".ccr-column>:last-child{margin-bottom:0}",
|
|
84
|
-
".ccr{--ccr:var(--ccr-primary);position:relative;margin:1.5rem 0;padding:1.25rem;border:1px solid var(--_comark-border);border-radius:calc(var(--_comark-radius) + 2px);background:var(--_comark-background);
|
|
133
|
+
".ccr{--ccr:var(--ccr-primary);position:relative;margin:1.5rem 0;padding:1.25rem;border:1px solid var(--_comark-border);border-radius:calc(var(--_comark-radius) + 2px);background:var(--_comark-background);color:var(--_comark-muted);font:400 .875rem/1.375rem var(--_comark-font);transition:background-color .15s,border-color .15s}",
|
|
85
134
|
...[
|
|
86
135
|
"secondary",
|
|
87
136
|
"success",
|
|
@@ -109,15 +158,23 @@ const css = `@layer comark{${[
|
|
|
109
158
|
"@media print{.ccr{break-inside:avoid}.ccr-external{display:none}}"
|
|
110
159
|
].join("")}}`;
|
|
111
160
|
//#endregion
|
|
112
|
-
//#region
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
161
|
+
//#region ../../shared/styles.ts
|
|
162
|
+
/**
|
|
163
|
+
* Adds a package's styles to the page once, unless the page already carries them as a `style` or a `link` with
|
|
164
|
+
* `data-comark-<name>`, which is how the HTML renderer inlines them and how an app that imports `style.css` marks them.
|
|
165
|
+
*/
|
|
166
|
+
function addStyles$1(name, css) {
|
|
167
|
+
const attribute = `data-comark-${name}`;
|
|
168
|
+
if (document.querySelector(`style[${attribute}],link[${attribute}]`)) return;
|
|
116
169
|
const style = document.createElement("style");
|
|
117
|
-
style.
|
|
170
|
+
style.setAttribute(attribute, "");
|
|
118
171
|
style.textContent = css;
|
|
119
172
|
document.head.append(style);
|
|
120
173
|
}
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/client.ts
|
|
176
|
+
/** Adds the card styles to the page once. The Vue, React, and Svelte components call it when they mount. */
|
|
177
|
+
const addStyles = () => addStyles$1("cards", css);
|
|
121
178
|
/** Lucide's arrow-up-right (ISC), drawn in the corner of a card that opens in a new tab. */
|
|
122
179
|
const external = "M7 7h10v10M7 17 17 7";
|
|
123
180
|
/** Returns whether a card URL is safe to place in an href. */
|
package/dist/client.d.mts
CHANGED
|
@@ -11,7 +11,7 @@ export declare const css: string;
|
|
|
11
11
|
//#endregion
|
|
12
12
|
//#region src/client.d.ts
|
|
13
13
|
/** Adds the card styles to the page once. The Vue, React, and Svelte components call it when they mount. */
|
|
14
|
-
export declare
|
|
14
|
+
export declare const addStyles: () => void;
|
|
15
15
|
/** Lucide's arrow-up-right (ISC), drawn in the corner of a card that opens in a new tab. */
|
|
16
16
|
export declare const external = "M7 7h10v10M7 17 17 7";
|
|
17
17
|
/** Returns whether a card URL is safe to place in an href. */
|
package/dist/client.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as addStyles, o as css, n as external, r as isExternalHref, i as isSafeHref, a as rel } from "./client-
|
|
1
|
+
export { t as addStyles, o as css, n as external, r as isExternalHref, i as isSafeHref, a as rel } from "./client-DsO8I6Oo.mjs";
|
package/dist/html.mjs
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { a as rel, n as external, o as css } from "./client-
|
|
2
|
-
import
|
|
1
|
+
import { a as rel, n as external, o as css } from "./client-DsO8I6Oo.mjs";
|
|
2
|
+
import { i as rawText, n as src_default, r as variants, t as colors } from "./src-BsKBRfFx.mjs";
|
|
3
3
|
import { escapeHtml } from "comark/utils";
|
|
4
4
|
import { iconHtml, iconStyles } from "comark-icon/html";
|
|
5
|
+
//#region ../../shared/html.ts
|
|
6
|
+
/** A value as the inside of a double-quoted HTML attribute. */
|
|
7
|
+
const attr = (value) => escapeHtml(rawText(value), { "\"": """ });
|
|
8
|
+
//#endregion
|
|
5
9
|
//#region src/html.ts
|
|
6
10
|
const styled = /* @__PURE__ */ new WeakSet();
|
|
7
|
-
const attr = (value) => escapeHtml(String(value), { "\"": """ });
|
|
8
11
|
const styles = (state) => {
|
|
9
12
|
if (styled.has(state.context)) return "";
|
|
10
13
|
styled.add(state.context);
|
package/dist/index.mjs
CHANGED
|
@@ -1,211 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { defineComarkPlugin } from "comark";
|
|
3
|
-
import { resolveAttributes } from "comark/render";
|
|
4
|
-
import { textContent } from "comark/utils";
|
|
5
|
-
import { createIcons, describeIconProblem, iconProblemRule } from "comark-icon";
|
|
6
|
-
//#region src/index.ts
|
|
7
|
-
/** Nuxt UI's colors, which tint a card's icon and border, and its background with a `variant`. */
|
|
8
|
-
const colors = [
|
|
9
|
-
"primary",
|
|
10
|
-
"secondary",
|
|
11
|
-
"success",
|
|
12
|
-
"info",
|
|
13
|
-
"warning",
|
|
14
|
-
"error",
|
|
15
|
-
"neutral"
|
|
16
|
-
];
|
|
17
|
-
/**
|
|
18
|
-
* Nuxt UI's card variants that a document block needs: `outline`, the default, keeps the plain card, `soft` washes it
|
|
19
|
-
* in its color, and `subtle` washes it and draws its border in the color too.
|
|
20
|
-
*/
|
|
21
|
-
const variants = [
|
|
22
|
-
"outline",
|
|
23
|
-
"soft",
|
|
24
|
-
"subtle"
|
|
25
|
-
];
|
|
26
|
-
const isElement = (node) => Array.isArray(node) && node[0] !== null;
|
|
27
|
-
const isContent = (node) => Array.isArray(node) ? node[0] !== null : node.trim() !== "";
|
|
28
|
-
const childrenOf = (node) => node.slice(2);
|
|
29
|
-
const text = (value) => value === void 0 || value === null || value instanceof Object ? "" : String(value).trim();
|
|
30
|
-
const clip = (value) => {
|
|
31
|
-
const words = value.trim().replace(/\s+/g, " ");
|
|
32
|
-
return words.length > 40 ? `${words.slice(0, 39)}…` : words;
|
|
33
|
-
};
|
|
34
|
-
const isColor = (value) => colors.some((color) => color === value);
|
|
35
|
-
const isVariant = (value) => variants.some((variant) => variant === value);
|
|
36
|
-
const isTemplate = (node, name) => isElement(node) && node[0] === "template" && node[1].name === name;
|
|
37
|
-
const unwrap = (nodes) => nodes.filter(isContent).flatMap((node) => isElement(node) && node[0] === "p" ? childrenOf(node) : [node]);
|
|
38
|
-
const resolve = (node, walk) => resolveAttributes(node[1], walk.data, { parseJson: true });
|
|
39
|
-
const CARD_PROPS = [
|
|
40
|
-
"title",
|
|
41
|
-
"description",
|
|
42
|
-
"icon",
|
|
43
|
-
"to",
|
|
44
|
-
"href",
|
|
45
|
-
"target",
|
|
46
|
-
"color",
|
|
47
|
-
"variant"
|
|
48
|
-
];
|
|
49
|
-
function unknownProps(node, name, block, props, walk) {
|
|
50
|
-
const known = props.flatMap((prop) => prop === "href" ? [] : [`\`${prop}\``]);
|
|
51
|
-
const list = known.length > 1 ? `${known.slice(0, -1).join(", ")}, or ${known.at(-1)}` : known[0];
|
|
52
|
-
for (const key of Object.keys(node[1])) {
|
|
53
|
-
const prop = key.replace(/^:/, "");
|
|
54
|
-
if (!props.includes(prop) && prop !== "id" && prop !== "class") walk.issues.push({
|
|
55
|
-
rule: "comark/cards/unknown-prop",
|
|
56
|
-
message: `${name}: \`${prop}\` isn't a prop of \`${block}\`, so it's ignored. Use ${list}.`
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function card(node, walk) {
|
|
61
|
-
const attrs = resolve(node, walk);
|
|
62
|
-
const children = childrenOf(node);
|
|
63
|
-
const slot = children.find((child) => isTemplate(child, "title"));
|
|
64
|
-
const content = children.flatMap((child) => child === slot ? [] : isTemplate(child, "default") ? childrenOf(child) : [child]);
|
|
65
|
-
const title = slot ? unwrap(childrenOf(slot)) : text(attrs.title) ? [text(attrs.title)] : [];
|
|
66
|
-
const words = clip(textContent([
|
|
67
|
-
"p",
|
|
68
|
-
{},
|
|
69
|
-
...title
|
|
70
|
-
]));
|
|
71
|
-
const name = `\`::card\` ${++walk.cards}${words ? ` ("${words}")` : ""}`;
|
|
72
|
-
unknownProps(node, name, "::card", CARD_PROPS, walk);
|
|
73
|
-
const description = text(attrs.description);
|
|
74
|
-
if (!content.some(isContent) && description) content.push([
|
|
75
|
-
"p",
|
|
76
|
-
{},
|
|
77
|
-
description
|
|
78
|
-
]);
|
|
79
|
-
const written = text(attrs.color);
|
|
80
|
-
const result = {};
|
|
81
|
-
result.color = isColor(written) ? written : "primary";
|
|
82
|
-
if (written && !isColor(written)) walk.issues.push({
|
|
83
|
-
rule: "comark/cards/invalid-color",
|
|
84
|
-
message: `${name}: \`color\` is "${clip(written)}", so it shows as primary. Write one of ${colors.join(", ")}.`
|
|
85
|
-
});
|
|
86
|
-
const variant = text(attrs.variant);
|
|
87
|
-
if (isVariant(variant)) {
|
|
88
|
-
if (variant !== "outline") result.variant = variant;
|
|
89
|
-
} else if (variant) walk.issues.push({
|
|
90
|
-
rule: "comark/cards/invalid-variant",
|
|
91
|
-
message: `${name}: \`variant\` is "${clip(variant)}", so it shows as outline. Write one of ${variants.join(", ")}.`
|
|
92
|
-
});
|
|
93
|
-
let to = text(attrs.to);
|
|
94
|
-
const href = text(attrs.href);
|
|
95
|
-
if (href && !to) {
|
|
96
|
-
walk.issues.push({
|
|
97
|
-
rule: "comark/cards/href-instead-of-to",
|
|
98
|
-
message: `${name}: Nuxt UI links a card with \`to\`, so it ignores \`href\`. Write \`to="${clip(href)}"\` instead.`
|
|
99
|
-
});
|
|
100
|
-
to = href;
|
|
101
|
-
}
|
|
102
|
-
if (to && !isSafeHref(to)) {
|
|
103
|
-
walk.issues.push({
|
|
104
|
-
rule: "comark/cards/unsafe-link",
|
|
105
|
-
message: `${name}: \`to\` must be a page or a web address, so it isn't a link.`
|
|
106
|
-
});
|
|
107
|
-
to = "";
|
|
108
|
-
}
|
|
109
|
-
if (to) {
|
|
110
|
-
result.to = to;
|
|
111
|
-
const target = text(attrs.target) || (isExternalHref(to) ? "_blank" : "");
|
|
112
|
-
if (target) result.target = target;
|
|
113
|
-
if (target === "_blank") result.external = "true";
|
|
114
|
-
result.label = words || "Card link";
|
|
115
|
-
}
|
|
116
|
-
const icon = text(attrs.icon);
|
|
117
|
-
if (icon) walk.icons.push({
|
|
118
|
-
card: node,
|
|
119
|
-
value: icon,
|
|
120
|
-
name
|
|
121
|
-
});
|
|
122
|
-
node[1] = result;
|
|
123
|
-
const head = title.length ? [[
|
|
124
|
-
"card-title",
|
|
125
|
-
{},
|
|
126
|
-
...title
|
|
127
|
-
]] : [];
|
|
128
|
-
node.splice(2, node.length - 2, ...head, ...content);
|
|
129
|
-
}
|
|
130
|
-
function columns(node, walk) {
|
|
131
|
-
const name = `\`::columns\` ${++walk.columns}`;
|
|
132
|
-
unknownProps(node, name, "::columns", ["cols"], walk);
|
|
133
|
-
const written = text(resolve(node, walk).cols);
|
|
134
|
-
let cols = "2";
|
|
135
|
-
if (/^[1-6]$/.test(written)) cols = written;
|
|
136
|
-
else if (written) walk.issues.push({
|
|
137
|
-
rule: "comark/cards/invalid-cols",
|
|
138
|
-
message: `${name}: \`cols\` is "${clip(written)}", so it shows 2 columns. Write a number from 1 to 6.`
|
|
139
|
-
});
|
|
140
|
-
const cells = childrenOf(node).filter(isContent).map((child) => isElement(child) && child[0] === "column" ? [
|
|
141
|
-
"column",
|
|
142
|
-
{},
|
|
143
|
-
...childrenOf(child)
|
|
144
|
-
] : [
|
|
145
|
-
"column",
|
|
146
|
-
{},
|
|
147
|
-
child
|
|
148
|
-
]);
|
|
149
|
-
if (!cells.length) walk.issues.push({
|
|
150
|
-
rule: "comark/cards/empty-columns",
|
|
151
|
-
message: `${name} is empty. Put a block inside for each column, or remove it.`
|
|
152
|
-
});
|
|
153
|
-
node[1] = { cols };
|
|
154
|
-
node.splice(2, node.length - 2, ...cells);
|
|
155
|
-
}
|
|
156
|
-
function transform(nodes, walk) {
|
|
157
|
-
for (const node of nodes) {
|
|
158
|
-
if (!isElement(node)) continue;
|
|
159
|
-
if (node[0] === "card") card(node, walk);
|
|
160
|
-
else if (node[0] === "columns") columns(node, walk);
|
|
161
|
-
else if (node[0] === "card-group") node[1] = {};
|
|
162
|
-
transform(childrenOf(node), walk);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
async function addIcons(walk, resolver) {
|
|
166
|
-
if (!walk.icons.length) return;
|
|
167
|
-
const resolved = await resolver.resolve(walk.icons.map(({ value }) => value));
|
|
168
|
-
for (const { card: node, value, name } of walk.icons) {
|
|
169
|
-
const icon = resolved.get(value);
|
|
170
|
-
if (!icon) continue;
|
|
171
|
-
if ("problem" in icon) walk.issues.push({
|
|
172
|
-
rule: iconProblemRule(icon),
|
|
173
|
-
message: `${name}, icon "${clip(value)}": ${describeIconProblem(value, icon)}`
|
|
174
|
-
});
|
|
175
|
-
else node[1].icon = icon;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Turns `::card-group` and `::card{title description icon to target color variant}` into cards, link cards when they
|
|
180
|
-
* have `to`, and `::columns{cols}` into a grid with a cell per block. Problems are added to `meta.issues`.
|
|
181
|
-
*/
|
|
182
|
-
var src_default = defineComarkPlugin((options = {}) => {
|
|
183
|
-
const resolver = options.iconResolver ?? createIcons();
|
|
184
|
-
return {
|
|
185
|
-
name: "comark-cards",
|
|
186
|
-
async post(state) {
|
|
187
|
-
const { tree } = state;
|
|
188
|
-
const walk = {
|
|
189
|
-
data: {
|
|
190
|
-
frontmatter: tree.frontmatter,
|
|
191
|
-
meta: tree.meta,
|
|
192
|
-
data: {},
|
|
193
|
-
props: {}
|
|
194
|
-
},
|
|
195
|
-
issues: [],
|
|
196
|
-
icons: [],
|
|
197
|
-
cards: 0,
|
|
198
|
-
columns: 0
|
|
199
|
-
};
|
|
200
|
-
transform(tree.nodes, walk);
|
|
201
|
-
await addIcons(walk, resolver);
|
|
202
|
-
tree.meta.issues = [...tree.meta.issues ?? [], ...walk.issues.map((issue) => issue.message)];
|
|
203
|
-
tree.meta.issueRules = {
|
|
204
|
-
...tree.meta.issueRules,
|
|
205
|
-
...Object.fromEntries(walk.issues.map((issue) => [issue.message, issue.rule]))
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
});
|
|
210
|
-
//#endregion
|
|
211
|
-
export { colors, src_default as default, variants };
|
|
1
|
+
export { t as colors, n as default, r as variants } from "./src-BsKBRfFx.mjs";
|
package/dist/react.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as rel, i as isSafeHref, n as external, r as isExternalHref, t as addStyles } from "./client-
|
|
2
|
-
import src_default,
|
|
1
|
+
import { a as rel, i as isSafeHref, n as external, r as isExternalHref, t as addStyles } from "./client-DsO8I6Oo.mjs";
|
|
2
|
+
import { n as src_default, r as variants, t as colors } from "./src-BsKBRfFx.mjs";
|
|
3
3
|
import { Icon } from "comark-icon/react";
|
|
4
4
|
import { createElement, useEffect } from "react";
|
|
5
5
|
//#region src/react.ts
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { i as isSafeHref, r as isExternalHref } from "./client-DsO8I6Oo.mjs";
|
|
2
|
+
import { defineComarkPlugin } from "comark";
|
|
3
|
+
import { resolveAttributes } from "comark/render";
|
|
4
|
+
import { textContent } from "comark/utils";
|
|
5
|
+
import { createIcons, describeIconProblem, iconProblemRule } from "comark-icon";
|
|
6
|
+
//#region ../../shared/text.ts
|
|
7
|
+
/**
|
|
8
|
+
* A prop value as text. Comark writes strings, numbers, and booleans, so an object, array, function, or missing value
|
|
9
|
+
* is no text. The `typeof` check, unlike `instanceof`, can't throw on a revoked proxy.
|
|
10
|
+
*/
|
|
11
|
+
function scalar(value) {
|
|
12
|
+
switch (typeof value) {
|
|
13
|
+
case "string": return value;
|
|
14
|
+
case "number":
|
|
15
|
+
case "boolean":
|
|
16
|
+
case "bigint":
|
|
17
|
+
case "symbol": return String(value);
|
|
18
|
+
default: return;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** A prop value as text, without its surrounding whitespace, or empty when it has none. */
|
|
22
|
+
const text = (value) => scalar(value)?.trim() ?? "";
|
|
23
|
+
/** A prop value as text exactly as written, or empty when it has none. */
|
|
24
|
+
const rawText = (value) => scalar(value) ?? "";
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region ../../shared/nodes.ts
|
|
27
|
+
const isElement = (node) => Array.isArray(node) && node[0] !== null;
|
|
28
|
+
const childrenOf = ([, , ...rest]) => rest;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/index.ts
|
|
31
|
+
/** Nuxt UI's colors, which tint a card's icon and border, and its background with a `variant`. */
|
|
32
|
+
const colors = [
|
|
33
|
+
"primary",
|
|
34
|
+
"secondary",
|
|
35
|
+
"success",
|
|
36
|
+
"info",
|
|
37
|
+
"warning",
|
|
38
|
+
"error",
|
|
39
|
+
"neutral"
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* Nuxt UI's card variants that a document block needs: `outline`, the default, keeps the plain card, `soft` washes it
|
|
43
|
+
* in its color, and `subtle` washes it and draws its border in the color too.
|
|
44
|
+
*/
|
|
45
|
+
const variants = [
|
|
46
|
+
"outline",
|
|
47
|
+
"soft",
|
|
48
|
+
"subtle"
|
|
49
|
+
];
|
|
50
|
+
const isContent = (node) => Array.isArray(node) ? node[0] !== null : node.trim() !== "";
|
|
51
|
+
const clip = (value) => {
|
|
52
|
+
const words = value.trim().replace(/\s+/g, " ");
|
|
53
|
+
return words.length > 40 ? `${words.slice(0, 39)}…` : words;
|
|
54
|
+
};
|
|
55
|
+
const isColor = (value) => colors.some((color) => color === value);
|
|
56
|
+
const isVariant = (value) => variants.some((variant) => variant === value);
|
|
57
|
+
const isTemplate = (node, name) => isElement(node) && node[0] === "template" && node[1].name === name;
|
|
58
|
+
const unwrap = (nodes) => nodes.filter(isContent).flatMap((node) => isElement(node) && node[0] === "p" ? childrenOf(node) : [node]);
|
|
59
|
+
const resolve = (node, walk) => resolveAttributes(node[1], walk.data, { parseJson: true });
|
|
60
|
+
const CARD_PROPS = [
|
|
61
|
+
"title",
|
|
62
|
+
"description",
|
|
63
|
+
"icon",
|
|
64
|
+
"to",
|
|
65
|
+
"href",
|
|
66
|
+
"target",
|
|
67
|
+
"color",
|
|
68
|
+
"variant"
|
|
69
|
+
];
|
|
70
|
+
function unknownProps(node, name, block, props, walk) {
|
|
71
|
+
const known = props.flatMap((prop) => prop === "href" ? [] : [`\`${prop}\``]);
|
|
72
|
+
const list = known.length > 1 ? `${known.slice(0, -1).join(", ")}, or ${known.at(-1)}` : known[0];
|
|
73
|
+
for (const key of Object.keys(node[1])) {
|
|
74
|
+
const prop = key.replace(/^:/, "");
|
|
75
|
+
if (!props.includes(prop) && prop !== "id" && prop !== "class") walk.issues.push({
|
|
76
|
+
rule: "comark/cards/unknown-prop",
|
|
77
|
+
message: `${name}: \`${prop}\` isn't a prop of \`${block}\`, so it's ignored. Use ${list}.`
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function card(node, walk) {
|
|
82
|
+
const attrs = resolve(node, walk);
|
|
83
|
+
const children = childrenOf(node);
|
|
84
|
+
const slot = children.find((child) => isTemplate(child, "title"));
|
|
85
|
+
const content = children.flatMap((child) => child === slot ? [] : isTemplate(child, "default") ? childrenOf(child) : [child]);
|
|
86
|
+
const title = slot ? unwrap(childrenOf(slot)) : text(attrs.title) ? [text(attrs.title)] : [];
|
|
87
|
+
const words = clip(textContent([
|
|
88
|
+
"p",
|
|
89
|
+
{},
|
|
90
|
+
...title
|
|
91
|
+
]));
|
|
92
|
+
const name = `\`::card\` ${++walk.cards}${words ? ` ("${words}")` : ""}`;
|
|
93
|
+
unknownProps(node, name, "::card", CARD_PROPS, walk);
|
|
94
|
+
const description = text(attrs.description);
|
|
95
|
+
if (!content.some(isContent) && description) content.push([
|
|
96
|
+
"p",
|
|
97
|
+
{},
|
|
98
|
+
description
|
|
99
|
+
]);
|
|
100
|
+
const written = text(attrs.color);
|
|
101
|
+
const result = {};
|
|
102
|
+
result.color = isColor(written) ? written : "primary";
|
|
103
|
+
if (written && !isColor(written)) walk.issues.push({
|
|
104
|
+
rule: "comark/cards/invalid-color",
|
|
105
|
+
message: `${name}: \`color\` is "${clip(written)}", so it shows as primary. Write one of ${colors.join(", ")}.`
|
|
106
|
+
});
|
|
107
|
+
const variant = text(attrs.variant);
|
|
108
|
+
if (isVariant(variant)) {
|
|
109
|
+
if (variant !== "outline") result.variant = variant;
|
|
110
|
+
} else if (variant) walk.issues.push({
|
|
111
|
+
rule: "comark/cards/invalid-variant",
|
|
112
|
+
message: `${name}: \`variant\` is "${clip(variant)}", so it shows as outline. Write one of ${variants.join(", ")}.`
|
|
113
|
+
});
|
|
114
|
+
let to = text(attrs.to);
|
|
115
|
+
const href = text(attrs.href);
|
|
116
|
+
if (href && !to) {
|
|
117
|
+
walk.issues.push({
|
|
118
|
+
rule: "comark/cards/href-instead-of-to",
|
|
119
|
+
message: `${name}: Nuxt UI links a card with \`to\`, so it ignores \`href\`. Write \`to="${clip(href)}"\` instead.`
|
|
120
|
+
});
|
|
121
|
+
to = href;
|
|
122
|
+
}
|
|
123
|
+
if (to && !isSafeHref(to)) {
|
|
124
|
+
walk.issues.push({
|
|
125
|
+
rule: "comark/cards/unsafe-link",
|
|
126
|
+
message: `${name}: \`to\` must be a page or a web address, so it isn't a link.`
|
|
127
|
+
});
|
|
128
|
+
to = "";
|
|
129
|
+
}
|
|
130
|
+
if (to) {
|
|
131
|
+
result.to = to;
|
|
132
|
+
const target = text(attrs.target) || (isExternalHref(to) ? "_blank" : "");
|
|
133
|
+
if (target) result.target = target;
|
|
134
|
+
if (target === "_blank") result.external = "true";
|
|
135
|
+
result.label = words || "Card link";
|
|
136
|
+
}
|
|
137
|
+
const icon = text(attrs.icon);
|
|
138
|
+
if (icon) walk.icons.push({
|
|
139
|
+
card: node,
|
|
140
|
+
value: icon,
|
|
141
|
+
name
|
|
142
|
+
});
|
|
143
|
+
node[1] = result;
|
|
144
|
+
const head = title.length ? [[
|
|
145
|
+
"card-title",
|
|
146
|
+
{},
|
|
147
|
+
...title
|
|
148
|
+
]] : [];
|
|
149
|
+
node.splice(2, node.length - 2, ...head, ...content);
|
|
150
|
+
}
|
|
151
|
+
function columns(node, walk) {
|
|
152
|
+
const name = `\`::columns\` ${++walk.columns}`;
|
|
153
|
+
unknownProps(node, name, "::columns", ["cols"], walk);
|
|
154
|
+
const written = text(resolve(node, walk).cols);
|
|
155
|
+
let cols = "2";
|
|
156
|
+
if (/^[1-6]$/.test(written)) cols = written;
|
|
157
|
+
else if (written) walk.issues.push({
|
|
158
|
+
rule: "comark/cards/invalid-cols",
|
|
159
|
+
message: `${name}: \`cols\` is "${clip(written)}", so it shows 2 columns. Write a number from 1 to 6.`
|
|
160
|
+
});
|
|
161
|
+
const cells = childrenOf(node).filter(isContent).map((child) => isElement(child) && child[0] === "column" ? [
|
|
162
|
+
"column",
|
|
163
|
+
{},
|
|
164
|
+
...childrenOf(child)
|
|
165
|
+
] : [
|
|
166
|
+
"column",
|
|
167
|
+
{},
|
|
168
|
+
child
|
|
169
|
+
]);
|
|
170
|
+
if (!cells.length) walk.issues.push({
|
|
171
|
+
rule: "comark/cards/empty-columns",
|
|
172
|
+
message: `${name} is empty. Put a block inside for each column, or remove it.`
|
|
173
|
+
});
|
|
174
|
+
node[1] = { cols };
|
|
175
|
+
node.splice(2, node.length - 2, ...cells);
|
|
176
|
+
}
|
|
177
|
+
function transform(nodes, walk) {
|
|
178
|
+
for (const node of nodes) {
|
|
179
|
+
if (!isElement(node)) continue;
|
|
180
|
+
if (node[0] === "card") card(node, walk);
|
|
181
|
+
else if (node[0] === "columns") columns(node, walk);
|
|
182
|
+
else if (node[0] === "card-group") node[1] = {};
|
|
183
|
+
transform(childrenOf(node), walk);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async function addIcons(walk, resolver) {
|
|
187
|
+
if (!walk.icons.length) return;
|
|
188
|
+
const resolved = await resolver.resolve(walk.icons.map(({ value }) => value));
|
|
189
|
+
for (const { card: node, value, name } of walk.icons) {
|
|
190
|
+
const icon = resolved.get(value);
|
|
191
|
+
if (!icon) continue;
|
|
192
|
+
if ("problem" in icon) walk.issues.push({
|
|
193
|
+
rule: iconProblemRule(icon),
|
|
194
|
+
message: `${name}, icon "${clip(value)}": ${describeIconProblem(value, icon)}`
|
|
195
|
+
});
|
|
196
|
+
else node[1].icon = icon;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Turns `::card-group` and `::card{title description icon to target color variant}` into cards, link cards when they
|
|
201
|
+
* have `to`, and `::columns{cols}` into a grid with a cell per block. Problems are added to `meta.issues`.
|
|
202
|
+
*/
|
|
203
|
+
var src_default = defineComarkPlugin((options = {}) => {
|
|
204
|
+
const resolver = options.iconResolver ?? createIcons();
|
|
205
|
+
return {
|
|
206
|
+
name: "comark-cards",
|
|
207
|
+
async post(state) {
|
|
208
|
+
const { tree } = state;
|
|
209
|
+
const walk = {
|
|
210
|
+
data: {
|
|
211
|
+
frontmatter: tree.frontmatter,
|
|
212
|
+
meta: tree.meta,
|
|
213
|
+
data: {},
|
|
214
|
+
props: {}
|
|
215
|
+
},
|
|
216
|
+
issues: [],
|
|
217
|
+
icons: [],
|
|
218
|
+
cards: 0,
|
|
219
|
+
columns: 0
|
|
220
|
+
};
|
|
221
|
+
transform(tree.nodes, walk);
|
|
222
|
+
await addIcons(walk, resolver);
|
|
223
|
+
tree.meta.issues = [...tree.meta.issues ?? [], ...walk.issues.map((issue) => issue.message)];
|
|
224
|
+
tree.meta.issueRules = {
|
|
225
|
+
...tree.meta.issueRules,
|
|
226
|
+
...Object.fromEntries(walk.issues.map((issue) => [issue.message, issue.rule]))
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
//#endregion
|
|
232
|
+
export { rawText as i, src_default as n, variants as r, colors as t };
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer comark{:where(.ccr,.ccr-group,.ccr-columns){--_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-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(.ccr,.ccr-group,.ccr-columns){--_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)))}}:where(.ccr){--
|
|
1
|
+
@layer comark{:where(.ccr,.ccr-group,.ccr-columns){--_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-success:var(--comark-success,var(--ui-success,var(--success,#259f56)));--_comark-danger:var(--comark-danger,var(--ui-error,var(--destructive,#ee3533)));--_comark-warning:var(--comark-warning,var(--ui-warning,#d97706));--_comark-info:var(--comark-info,var(--ui-info,#2563eb));--_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(.ccr,.ccr-group,.ccr-columns){--_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-success:var(--comark-success,var(--ui-success,var(--success,#59d38c)));--_comark-danger:var(--comark-danger,var(--ui-error,var(--destructive,#fd736d)));--_comark-warning:var(--comark-warning,var(--ui-warning,#fbbf24));--_comark-info:var(--comark-info,var(--ui-info,#60a5fa))}}:where(.light,.light *):where(.ccr,.ccr-group,.ccr-columns){--_comark-success:var(--comark-success,var(--ui-success,var(--success,#259f56)));--_comark-danger:var(--comark-danger,var(--ui-error,var(--destructive,#ee3533)));--_comark-warning:var(--comark-warning,var(--ui-warning,#d97706));--_comark-info:var(--comark-info,var(--ui-info,#2563eb))}:where(.dark,.dark *):where(.ccr,.ccr-group,.ccr-columns){--_comark-success:var(--comark-success,var(--ui-success,var(--success,#59d38c)));--_comark-danger:var(--comark-danger,var(--ui-error,var(--destructive,#fd736d)));--_comark-warning:var(--comark-warning,var(--ui-warning,#fbbf24));--_comark-info:var(--comark-info,var(--ui-info,#60a5fa))}:where(.ccr){--ccr-primary:var(--ui-primary,var(--primary,var(--_comark-foreground)));--ccr-secondary:var(--ui-secondary,var(--_comark-info));--ccr-success:var(--_comark-success);--ccr-info:var(--_comark-info);--ccr-warning:var(--_comark-warning);--ccr-error:var(--_comark-danger);--ccr-neutral:var(--_comark-foreground)}.ccr-group,.ccr-columns{display:grid;gap:1rem;margin:1.5rem 0;container-type:inline-size}.ccr-group{grid-template-columns:repeat(2,minmax(0,1fr))}.ccr-columns[data-cols='2']{grid-template-columns:repeat(2,minmax(0,1fr))}.ccr-columns[data-cols='3']{grid-template-columns:repeat(3,minmax(0,1fr))}.ccr-columns[data-cols='4']{grid-template-columns:repeat(4,minmax(0,1fr))}.ccr-columns[data-cols='5']{grid-template-columns:repeat(5,minmax(0,1fr))}.ccr-columns[data-cols='6']{grid-template-columns:repeat(6,minmax(0,1fr))}@container (width<36rem){.ccr-group>*,.ccr-columns>*{grid-column:1/-1}}.ccr-group>.ccr{margin:0}.ccr-column>:first-child{margin-top:0}.ccr-column>:last-child{margin-bottom:0}.ccr{--ccr:var(--ccr-primary);position:relative;margin:1.5rem 0;padding:1.25rem;border:1px solid var(--_comark-border);border-radius:calc(var(--_comark-radius) + 2px);background:var(--_comark-background);color:var(--_comark-muted);font:400 .875rem/1.375rem var(--_comark-font);transition:background-color .15s,border-color .15s}.ccr[data-color='secondary']{--ccr:var(--ccr-secondary)}.ccr[data-color='success']{--ccr:var(--ccr-success)}.ccr[data-color='info']{--ccr:var(--ccr-info)}.ccr[data-color='warning']{--ccr:var(--ccr-warning)}.ccr[data-color='error']{--ccr:var(--ccr-error)}.ccr[data-color='neutral']{--ccr:var(--ccr-neutral)}.ccr[data-variant='soft'],.ccr[data-variant='subtle']{background:color-mix(in srgb,var(--ccr) 10%,var(--_comark-background))}.ccr[data-variant='soft']{border-color:transparent}.ccr[data-variant='subtle']{border-color:color-mix(in srgb,var(--ccr) 30%,var(--_comark-background))}.ccr>:last-child{margin-bottom:0}.ccr>.ci{--comark-icon-size:1.25rem;display:block;margin-bottom:.75rem;color:var(--ccr)}.ccr-title{margin:0 0 .25rem;color:var(--_comark-foreground);font-size:.9375rem;font-weight:600;line-height:1.375rem;text-wrap:balance}.ccr-title+*{margin-top:0}.ccr-link{position:absolute;inset:0;z-index:0;border-radius:inherit}.ccr-link:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--_comark-ring) 50%,transparent)}.ccr :is(a,button):not(.ccr-link){position:relative;z-index:1}.ccr:has(>.ccr-link):hover{border-color:color-mix(in srgb,var(--ccr) 50%,var(--_comark-border));background:color-mix(in srgb,var(--_comark-accent) 50%,var(--_comark-background))}.ccr[data-variant='soft']:has(>.ccr-link):hover{border-color:transparent}.ccr[data-variant='subtle']:has(>.ccr-link):hover{border-color:color-mix(in srgb,var(--ccr) 30%,var(--_comark-background))}.ccr[data-variant='soft']:has(>.ccr-link):hover,.ccr[data-variant='subtle']:has(>.ccr-link):hover{background:color-mix(in srgb,var(--ccr) 16%,var(--_comark-background))}.ccr-external{position:absolute;top:1rem;inset-inline-end:1rem;width:1rem;height:1rem;color:var(--_comark-muted)}.ccr:dir(rtl) .ccr-external{scale:-1 1}@media print{.ccr{break-inside:avoid}.ccr-external{display:none}}}
|
package/dist/vue.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as rel, i as isSafeHref, n as external, r as isExternalHref, t as addStyles } from "./client-
|
|
2
|
-
import src_default,
|
|
1
|
+
import { a as rel, i as isSafeHref, n as external, r as isExternalHref, t as addStyles } from "./client-DsO8I6Oo.mjs";
|
|
2
|
+
import { n as src_default, r as variants, t as colors } from "./src-BsKBRfFx.mjs";
|
|
3
3
|
import { defineComponent, h, onMounted } from "vue";
|
|
4
4
|
import { Icon } from "comark-icon/vue";
|
|
5
5
|
//#region src/vue.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comark-cards",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Cards, link cards, and columns in Nuxt UI's syntax, with no script. A Comark plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"card",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"provenance": true
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"comark-icon": "^0.
|
|
49
|
+
"comark-icon": "^0.8.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@comark/html": "^0.8.1",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"react-dom": "^19.3.1",
|
|
60
60
|
"svelte": "^5.57.2",
|
|
61
61
|
"vue": "^3.5.44",
|
|
62
|
-
"comark-zoom": "0.
|
|
62
|
+
"comark-zoom": "0.8.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@comark/html": "^0.8.0",
|