comark-colors 0.0.0 → 0.7.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/LICENSE +21 -0
- package/README.md +43 -1
- package/dist/client.d.mts +12 -0
- package/dist/client.mjs +12 -0
- package/dist/html.d.mts +7 -0
- package/dist/html.mjs +27 -0
- package/dist/index.d.mts +24 -0
- package/dist/index.mjs +100 -0
- package/dist/react.d.mts +20 -0
- package/dist/react.mjs +31 -0
- package/dist/style.css +1 -0
- package/dist/styles-gTSbKJ8j.mjs +79 -0
- package/dist/svelte/Color.svelte +14 -0
- package/dist/svelte/Palette.svelte +10 -0
- package/dist/svelte/index.d.ts +9 -0
- package/dist/svelte/index.js +7 -0
- package/dist/vue.d.mts +33 -0
- package/dist/vue.mjs +49 -0
- package/package.json +82 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 onmax
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,45 @@
|
|
|
1
1
|
# comark-colors
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://npmx.dev/package/comark-colors)
|
|
4
|
+
[](https://npmx.dev/package/comark-colors)
|
|
5
|
+
[](https://npmx.dev/package/comark-colors)
|
|
6
|
+
[](https://comark-ui.onmax.me/colors/)
|
|
7
|
+
|
|
8
|
+
A swatch before inline code that holds a color, as GitLab draws it, and `::palette` grids of named colors. A [Comark](https://comark.dev) plugin for HTML, Vue, React, and Svelte.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pnpm add comark comark-colors
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { createHtmlRenderer } from "@comark/html";
|
|
16
|
+
import colors, { components } from "comark-colors/html";
|
|
17
|
+
|
|
18
|
+
const render = createHtmlRenderer({ plugins: [colors()], components });
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```md
|
|
22
|
+
The button moves from `#3b82f6` to `oklch(0.55 0.2 264)`.
|
|
23
|
+
|
|
24
|
+
::palette
|
|
25
|
+
- Primary: `#3b82f6`
|
|
26
|
+
- Danger: #dc2626
|
|
27
|
+
::
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Inline code that holds one literal hex, `rgb()`, `hsl()`, `hwb()`, `lab()`, `lch()`, `oklab()`, or `oklch()` color gets a swatch, with no new syntax. Calculated components such as `calc()` are left as code. A `::palette` holds one list of `name: color` lines and draws a tile for each.
|
|
31
|
+
|
|
32
|
+
The plugin adds every problem with a palette to `meta.issues`: no list, content beside it, a line with no name or color, and a color it can't draw. Each issue names its palette and says how to fix it.
|
|
33
|
+
|
|
34
|
+
## Renderers
|
|
35
|
+
|
|
36
|
+
| Renderer | Import |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| `@comark/html` | `comark-colors/html`: the styles are inlined once per document |
|
|
39
|
+
| `@comark/vue` | `comark-colors/vue` |
|
|
40
|
+
| `@comark/react` | `comark-colors/react` |
|
|
41
|
+
| `@comark/svelte` | `comark-colors/svelte` |
|
|
42
|
+
|
|
43
|
+
Each entry exports the parse plugin as `default` and the renderer's `components`. The Vue, React, and Svelte components add the styles when they mount; import `comark-colors/style.css` with your styles so a server-rendered page doesn't shift.
|
|
44
|
+
|
|
45
|
+
The styles follow shadcn/ui: they read its CSS variables, such as `--background` and `--border`, when the page has them, and use its neutral theme otherwise. Set the shared `--comark-*` tokens to theme every plugin at once; the rules sit in a `comark` CSS layer, so any plain rule of your own wins.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/styles.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* A swatch inside inline code, and palettes as a grid of tiles in the style of shadcn/ui's Card, on the shared
|
|
4
|
+
* `--comark-*` tokens. Override `--cco-tile-width` and `--cco-tile-height` to size a palette's tiles. The rules sit in
|
|
5
|
+
* the `comark` layer, so any unlayered rule of the host's wins.
|
|
6
|
+
*/
|
|
7
|
+
export declare const css: string;
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/client.d.ts
|
|
10
|
+
/** Adds the colors styles to the page once. The Vue, React, and Svelte components call it when they mount. */
|
|
11
|
+
export declare function addStyles(): void;
|
|
12
|
+
//#endregion
|
package/dist/client.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as css } from "./styles-gTSbKJ8j.mjs";
|
|
2
|
+
//#region src/client.ts
|
|
3
|
+
/** Adds the colors styles to the page once. The Vue, React, and Svelte components call it when they mount. */
|
|
4
|
+
function addStyles() {
|
|
5
|
+
if (document.querySelector("style[data-comark-colors]")) return;
|
|
6
|
+
const style = document.createElement("style");
|
|
7
|
+
style.dataset.comarkColors = "";
|
|
8
|
+
style.textContent = css;
|
|
9
|
+
document.head.append(style);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { addStyles, css };
|
package/dist/html.d.mts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import _default, { ColorAttributes, ColorsMeta, isColor } from "./index.mjs";
|
|
2
|
+
import { NodeHandler } from "comark";
|
|
3
|
+
//#region src/html.d.ts
|
|
4
|
+
/** The HTML renderer for colors and `::palette`. Pass it as `components`; it inlines the styles once per document. */
|
|
5
|
+
export declare const components: Record<"color" | "palette", NodeHandler>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { type ColorAttributes, type ColorsMeta, _default as default, isColor };
|
package/dist/html.mjs
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import src_default, { isColor } from "./index.mjs";
|
|
2
|
+
import { t as css } from "./styles-gTSbKJ8j.mjs";
|
|
3
|
+
import { escapeHtml } from "comark/utils";
|
|
4
|
+
//#region src/html.ts
|
|
5
|
+
const styled = /* @__PURE__ */ new WeakSet();
|
|
6
|
+
const attr = (value) => escapeHtml(value, { "\"": """ });
|
|
7
|
+
const str = (value) => value === void 0 ? "" : String(value);
|
|
8
|
+
const styles = (state) => {
|
|
9
|
+
const tag = styled.has(state.context) ? "" : `<style data-comark-colors>${css}</style>`;
|
|
10
|
+
styled.add(state.context);
|
|
11
|
+
return tag;
|
|
12
|
+
};
|
|
13
|
+
const color = ([, attrs], state) => {
|
|
14
|
+
const value = str(attrs.value);
|
|
15
|
+
const name = str(attrs.name);
|
|
16
|
+
if (!value) return "";
|
|
17
|
+
if (name) return `<li><span class="cco-tile" style="--cco:${attr(value)}"></span><span class="cco-name">${attr(name)}</span><span class="cco-value">${attr(value)}</span></li>`;
|
|
18
|
+
return `${styles(state)}<code class="cco"><span class="cco-swatch" style="--cco:${attr(value)}" aria-hidden="true"></span>${attr(value)}</code>`;
|
|
19
|
+
};
|
|
20
|
+
const palette = async ([, , ...children], state) => `${styles(state)}<ul class="cco-palette">${(await Promise.all(children.map((child) => state.one(child, state)))).join("")}</ul>`;
|
|
21
|
+
/** The HTML renderer for colors and `::palette`. Pass it as `components`; it inlines the styles once per document. */
|
|
22
|
+
const components = {
|
|
23
|
+
color,
|
|
24
|
+
palette
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export { components, src_default as default, isColor };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/index.d.ts
|
|
2
|
+
export type ColorsMeta = {
|
|
3
|
+
/** One readable sentence per problem with a `::palette`. Empty when the document has none. Other plugins add theirs too. */
|
|
4
|
+
issues: string[];
|
|
5
|
+
/** The comark-linter rule of each issue, by its sentence, so the linter reports it under its own code. */
|
|
6
|
+
issueRules: Record<string, string>;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* What a color becomes, and all its renderers read. Inline code that holds a color has only `value`; a `::palette` line
|
|
10
|
+
* has its `name` too.
|
|
11
|
+
*/
|
|
12
|
+
export type ColorAttributes = {
|
|
13
|
+
value?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
};
|
|
16
|
+
/** Whether `value` is a hex, rgb(), hsl(), hwb(), lab(), lch(), oklab(), or oklch() color. */
|
|
17
|
+
export declare const isColor: (value: string) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Puts a swatch before inline code that holds a color, such as `#3b82f6` or `oklch(0.62 0.19 260)`, and turns a
|
|
20
|
+
* `::palette` of `name: color` lines into a grid of swatches. Problems are added to `meta.issues`.
|
|
21
|
+
*/
|
|
22
|
+
declare const _default: import("comark").ComarkPluginFactory<void, ColorsMeta, {}>;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { _default as default };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { defineComarkPlugin } from "comark";
|
|
2
|
+
import { textContent } from "comark/utils";
|
|
3
|
+
//#region src/index.ts
|
|
4
|
+
const NUMBER = String.raw`[+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?`;
|
|
5
|
+
const PERCENT = String.raw`${NUMBER}%`;
|
|
6
|
+
const ANGLE = String.raw`${NUMBER}(?:deg|grad|rad|turn)`;
|
|
7
|
+
const NONE = String.raw`none`;
|
|
8
|
+
const CSS_WS = String.raw`(?:[ \t\r\n\f]|/\*(?:[^"'<>]|\r?\n)*?\*/)`;
|
|
9
|
+
const ALPHA = String.raw`(?:${NUMBER}|${PERCENT}|${NONE})`;
|
|
10
|
+
const RGB_CHANNEL = String.raw`(?:${NUMBER}|${PERCENT}|${NONE})`;
|
|
11
|
+
const HSL_HUE = String.raw`(?:${NUMBER}|${ANGLE}|${NONE})`;
|
|
12
|
+
const HSL_PERCENT = String.raw`(?:${PERCENT}|${NONE})`;
|
|
13
|
+
const LAB_CHANNEL = String.raw`(?:${NUMBER}|${PERCENT}|${NONE})`;
|
|
14
|
+
const LEGACY_RGB = String.raw`(?:${NUMBER}${CSS_WS}*,${CSS_WS}*${NUMBER}${CSS_WS}*,${CSS_WS}*${NUMBER}|${PERCENT}${CSS_WS}*,${CSS_WS}*${PERCENT}${CSS_WS}*,${CSS_WS}*${PERCENT})(?:${CSS_WS}*,${CSS_WS}*(?:${NUMBER}|${PERCENT}))?`;
|
|
15
|
+
const LEGACY_HSL = String.raw`(?:${NUMBER}|${ANGLE})`;
|
|
16
|
+
const MODERN = (a, b, c) => String.raw`${a}${CSS_WS}+${b}${CSS_WS}+${c}(?:${CSS_WS}*/${CSS_WS}*${ALPHA})?`;
|
|
17
|
+
const COLOR = new RegExp(String.raw`^(?:#(?:[\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})|(?:rgb|rgba)\(${CSS_WS}*(?:${MODERN(RGB_CHANNEL, RGB_CHANNEL, RGB_CHANNEL)}|${LEGACY_RGB})${CSS_WS}*\)|(?:hsl|hsla)\(${CSS_WS}*(?:${MODERN(HSL_HUE, HSL_PERCENT, HSL_PERCENT)}|${LEGACY_HSL}${CSS_WS}*,${CSS_WS}*${PERCENT}${CSS_WS}*,${CSS_WS}*${PERCENT}(?:${CSS_WS}*,${CSS_WS}*(?:${NUMBER}|${PERCENT}))?)${CSS_WS}*\)|hwb\(${CSS_WS}*${MODERN(HSL_HUE, HSL_PERCENT, HSL_PERCENT)}${CSS_WS}*\)|lab\(${CSS_WS}*${MODERN(LAB_CHANNEL, LAB_CHANNEL, LAB_CHANNEL)}${CSS_WS}*\)|lch\(${CSS_WS}*${MODERN(LAB_CHANNEL, LAB_CHANNEL, HSL_HUE)}${CSS_WS}*\)|oklab\(${CSS_WS}*${MODERN(LAB_CHANNEL, LAB_CHANNEL, LAB_CHANNEL)}${CSS_WS}*\)|oklch\(${CSS_WS}*${MODERN(LAB_CHANNEL, LAB_CHANNEL, HSL_HUE)}${CSS_WS}*\))$`, "i");
|
|
18
|
+
const EXAMPLE = "`- Primary: #3b82f6`";
|
|
19
|
+
/** Whether `value` is a hex, rgb(), hsl(), hwb(), lab(), lch(), oklab(), or oklch() color. */
|
|
20
|
+
const isColor = (value) => COLOR.test(value);
|
|
21
|
+
const isElement = (node) => Array.isArray(node) && node[0] !== null;
|
|
22
|
+
const childrenOf = ([, , ...rest]) => rest;
|
|
23
|
+
const isContent = (node) => Array.isArray(node) ? node[0] !== null : node.trim() !== "";
|
|
24
|
+
function palette(node, number, issues) {
|
|
25
|
+
const name = `\`::palette\` ${number}`;
|
|
26
|
+
for (const key of Object.keys(node[1])) {
|
|
27
|
+
const prop = key.replace(/^:/, "");
|
|
28
|
+
if (prop !== "id" && prop !== "class") issues.push({
|
|
29
|
+
rule: "comark/colors/unknown-prop",
|
|
30
|
+
message: `${name}: \`${prop}\` isn't a prop of \`::palette\`, which has none, so it's ignored. Remove it.`
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const content = childrenOf(node).filter(isContent);
|
|
34
|
+
const lists = content.filter((child) => isElement(child) && (child[0] === "ul" || child[0] === "ol"));
|
|
35
|
+
if (!lists.length) {
|
|
36
|
+
issues.push({
|
|
37
|
+
rule: "comark/colors/missing-list",
|
|
38
|
+
message: `${name} needs a list of \`name: color\` lines, such as ${EXAMPLE}.`
|
|
39
|
+
});
|
|
40
|
+
return ["palette", {}];
|
|
41
|
+
}
|
|
42
|
+
if (lists.length < content.length) issues.push({
|
|
43
|
+
rule: "comark/colors/content-dropped",
|
|
44
|
+
message: `${name} drops everything but its list. Move the rest outside the block.`
|
|
45
|
+
});
|
|
46
|
+
const colors = [];
|
|
47
|
+
for (const item of lists.flatMap(childrenOf).filter(isElement)) {
|
|
48
|
+
const line = textContent(item).trim();
|
|
49
|
+
const [, label, value = ""] = /^(.*\S)\s*:\s*(\S.*)$/s.exec(line) ?? [];
|
|
50
|
+
if (!label) issues.push({
|
|
51
|
+
rule: "comark/colors/unreadable-line",
|
|
52
|
+
message: `${name}: "${line}" needs a name and a color, such as ${EXAMPLE}.`
|
|
53
|
+
});
|
|
54
|
+
else if (!isColor(value.trim())) issues.push({
|
|
55
|
+
rule: "comark/colors/invalid-color",
|
|
56
|
+
message: `${name}: "${value.trim()}" for ${label} isn't a color it can draw. Write a hex color or an rgb(), hsl(), hwb(), lab(), lch(), oklab(), or oklch() color.`
|
|
57
|
+
});
|
|
58
|
+
else colors.push(["color", {
|
|
59
|
+
name: label,
|
|
60
|
+
value: value.trim()
|
|
61
|
+
}]);
|
|
62
|
+
}
|
|
63
|
+
return [
|
|
64
|
+
"palette",
|
|
65
|
+
{},
|
|
66
|
+
...colors
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Puts a swatch before inline code that holds a color, such as `#3b82f6` or `oklch(0.62 0.19 260)`, and turns a
|
|
71
|
+
* `::palette` of `name: color` lines into a grid of swatches. Problems are added to `meta.issues`.
|
|
72
|
+
*/
|
|
73
|
+
var src_default = defineComarkPlugin(() => ({
|
|
74
|
+
name: "comark-colors",
|
|
75
|
+
post(state) {
|
|
76
|
+
const { tree } = state;
|
|
77
|
+
const issues = [];
|
|
78
|
+
let count = 0;
|
|
79
|
+
const walk = (nodes, start) => {
|
|
80
|
+
for (let index = start; index < nodes.length; index++) {
|
|
81
|
+
const node = nodes[index];
|
|
82
|
+
if (!node || !isElement(node) || node[0] === "pre") continue;
|
|
83
|
+
if (node[0] === "palette") nodes[index] = palette(node, ++count, issues);
|
|
84
|
+
else if (node[0] !== "code") walk(node, 2);
|
|
85
|
+
else {
|
|
86
|
+
const [value, ...rest] = childrenOf(node);
|
|
87
|
+
if (value !== void 0 && !Array.isArray(value) && !rest.length && isColor(value.trim())) nodes[index] = ["color", { value: value.trim() }];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
walk(tree.nodes, 0);
|
|
92
|
+
tree.meta.issues = [...tree.meta.issues ?? [], ...issues.map((issue) => issue.message)];
|
|
93
|
+
tree.meta.issueRules = {
|
|
94
|
+
...tree.meta.issueRules,
|
|
95
|
+
...Object.fromEntries(issues.map((issue) => [issue.message, issue.rule]))
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}));
|
|
99
|
+
//#endregion
|
|
100
|
+
export { src_default as default, isColor };
|
package/dist/react.d.mts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import _default, { ColorAttributes, ColorsMeta, isColor } from "./index.mjs";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/react.d.ts
|
|
4
|
+
/** A color in inline code, or a line of a `::palette`, for `@comark/react`. */
|
|
5
|
+
export declare function Color({ value, name }: ColorAttributes): import("react").DetailedReactHTMLElement<import("react").HTMLAttributes<HTMLElement>, HTMLElement> | import("react").DetailedReactHTMLElement<{
|
|
6
|
+
className: string;
|
|
7
|
+
}, HTMLElement> | null;
|
|
8
|
+
/** `::palette` for `@comark/react`. */
|
|
9
|
+
export declare function Palette({ children }: {
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
}): import("react").DetailedReactHTMLElement<{
|
|
12
|
+
className: string;
|
|
13
|
+
}, HTMLElement>;
|
|
14
|
+
/** Pass these as `components` to `@comark/react`. */
|
|
15
|
+
export declare const components: {
|
|
16
|
+
Color: typeof Color;
|
|
17
|
+
Palette: typeof Palette;
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { type ColorAttributes, type ColorsMeta, _default as default, isColor };
|
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import src_default, { isColor } from "./index.mjs";
|
|
2
|
+
import { addStyles } from "./client.mjs";
|
|
3
|
+
import { createElement, useEffect } from "react";
|
|
4
|
+
//#region src/react.ts
|
|
5
|
+
/** A color in inline code, or a line of a `::palette`, for `@comark/react`. */
|
|
6
|
+
function Color({ value, name }) {
|
|
7
|
+
useEffect(addStyles, []);
|
|
8
|
+
if (!value) return null;
|
|
9
|
+
const style = { "--cco": value };
|
|
10
|
+
if (name) return createElement("li", null, createElement("span", {
|
|
11
|
+
className: "cco-tile",
|
|
12
|
+
style
|
|
13
|
+
}), createElement("span", { className: "cco-name" }, name), createElement("span", { className: "cco-value" }, value));
|
|
14
|
+
return createElement("code", { className: "cco" }, createElement("span", {
|
|
15
|
+
className: "cco-swatch",
|
|
16
|
+
style,
|
|
17
|
+
"aria-hidden": true
|
|
18
|
+
}), value);
|
|
19
|
+
}
|
|
20
|
+
/** `::palette` for `@comark/react`. */
|
|
21
|
+
function Palette({ children }) {
|
|
22
|
+
useEffect(addStyles, []);
|
|
23
|
+
return createElement("ul", { className: "cco-palette" }, children);
|
|
24
|
+
}
|
|
25
|
+
/** Pass these as `components` to `@comark/react`. */
|
|
26
|
+
const components = {
|
|
27
|
+
Color,
|
|
28
|
+
Palette
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
export { Color, Palette, components, src_default as default, isColor };
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer comark{:where(.cco-palette,.cco){--_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(.cco-palette,.cco){--_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(.cco-palette){--cco-tile-width:9rem;--cco-tile-height:4rem}.cco-swatch{display:inline-block;box-sizing:border-box;width:.8em;height:.8em;margin-inline-end:.35em;vertical-align:-.05em;border:1px solid var(--_comark-border);border-radius:.2em;background:linear-gradient(var(--cco),var(--cco)),repeating-conic-gradient(color-mix(in srgb,var(--_comark-muted) 35%,var(--_comark-background)) 0 25%,var(--_comark-background) 0 50%) 0 0/8px 8px}.cco-palette{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--cco-tile-width),1fr));gap:.75rem;margin:1.5rem 0;padding:0;list-style:none;font-family:var(--_comark-font)}.cco-palette>li{margin:0!important;padding:0!important;overflow:hidden;border:1px solid var(--_comark-border);border-radius:var(--_comark-radius);background:var(--_comark-background);color:var(--_comark-foreground)}.cco-tile{display:block;height:var(--cco-tile-height);border-bottom:1px solid var(--_comark-border);background:linear-gradient(var(--cco),var(--cco)),repeating-conic-gradient(color-mix(in srgb,var(--_comark-muted) 35%,var(--_comark-background)) 0 25%,var(--_comark-background) 0 50%) 0 0/8px 8px}.cco-name,.cco-value{display:block;padding:0 .75rem;line-height:1.25rem;overflow-wrap:anywhere}.cco-name{padding-top:.5rem;font-size:.875rem;font-weight:500}.cco-value{padding-bottom:.5rem;color:var(--_comark-muted);font:.75rem/1.25rem ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.cco-swatch,.cco-tile{-webkit-print-color-adjust:exact;print-color-adjust:exact}@media print{.cco-palette>li{break-inside:avoid}}}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region ../zoom/dist/theme.mjs
|
|
2
|
+
const tokens = [
|
|
3
|
+
[
|
|
4
|
+
"background",
|
|
5
|
+
"ui-bg",
|
|
6
|
+
"background",
|
|
7
|
+
"#fff",
|
|
8
|
+
"#0a0a0a"
|
|
9
|
+
],
|
|
10
|
+
[
|
|
11
|
+
"foreground",
|
|
12
|
+
"ui-text-highlighted",
|
|
13
|
+
"foreground",
|
|
14
|
+
"#0a0a0a",
|
|
15
|
+
"#fafafa"
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
"muted",
|
|
19
|
+
"ui-text-muted",
|
|
20
|
+
"muted-foreground",
|
|
21
|
+
"#737373",
|
|
22
|
+
"#a1a1a1"
|
|
23
|
+
],
|
|
24
|
+
[
|
|
25
|
+
"border",
|
|
26
|
+
"ui-border",
|
|
27
|
+
"border",
|
|
28
|
+
"#e5e5e5",
|
|
29
|
+
"rgb(255 255 255/.1)"
|
|
30
|
+
],
|
|
31
|
+
[
|
|
32
|
+
"accent",
|
|
33
|
+
"ui-bg-elevated",
|
|
34
|
+
"accent",
|
|
35
|
+
"#f5f5f5",
|
|
36
|
+
"#262626"
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
"ring",
|
|
40
|
+
"ui-primary",
|
|
41
|
+
"ring",
|
|
42
|
+
"#a1a1a1",
|
|
43
|
+
"#737373"
|
|
44
|
+
]
|
|
45
|
+
];
|
|
46
|
+
const resolve = (scheme) => tokens.map((token) => `--_comark-${token[0]}:var(--comark-${token[0]},var(--${token[1]},var(--${token[2]},${token[scheme]})))`).join(";");
|
|
47
|
+
/**
|
|
48
|
+
* Resolves the `--comark-*` tokens on `selector`, falling back to Nuxt UI's variables, then shadcn/ui's, then shadcn's
|
|
49
|
+
* neutral theme. Nuxt UI's corners are twice its `--ui-radius`, so the radius halves shadcn's to double it back.
|
|
50
|
+
* They resolve on the component rather than `:root`, so a `.dark` class anywhere above it switches the theme, and a
|
|
51
|
+
* `--comark-*` set on any ancestor still inherits down. `:where()` keeps them at zero specificity.
|
|
52
|
+
*/
|
|
53
|
+
function theme(selector) {
|
|
54
|
+
const where = `:where(${selector})`;
|
|
55
|
+
return `${where}{${resolve(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(4)}}}`;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/styles.ts
|
|
59
|
+
const fill = "background:linear-gradient(var(--cco),var(--cco)),repeating-conic-gradient(color-mix(in srgb,var(--_comark-muted) 35%,var(--_comark-background)) 0 25%,var(--_comark-background) 0 50%) 0 0/8px 8px";
|
|
60
|
+
/**
|
|
61
|
+
* A swatch inside inline code, and palettes as a grid of tiles in the style of shadcn/ui's Card, on the shared
|
|
62
|
+
* `--comark-*` tokens. Override `--cco-tile-width` and `--cco-tile-height` to size a palette's tiles. The rules sit in
|
|
63
|
+
* the `comark` layer, so any unlayered rule of the host's wins.
|
|
64
|
+
*/
|
|
65
|
+
const css = `@layer comark{${[
|
|
66
|
+
theme(".cco-palette,.cco"),
|
|
67
|
+
":where(.cco-palette){--cco-tile-width:9rem;--cco-tile-height:4rem}",
|
|
68
|
+
`.cco-swatch{display:inline-block;box-sizing:border-box;width:.8em;height:.8em;margin-inline-end:.35em;vertical-align:-.05em;border:1px solid var(--_comark-border);border-radius:.2em;${fill}}`,
|
|
69
|
+
".cco-palette{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--cco-tile-width),1fr));gap:.75rem;margin:1.5rem 0;padding:0;list-style:none;font-family:var(--_comark-font)}",
|
|
70
|
+
".cco-palette>li{margin:0!important;padding:0!important;overflow:hidden;border:1px solid var(--_comark-border);border-radius:var(--_comark-radius);background:var(--_comark-background);color:var(--_comark-foreground)}",
|
|
71
|
+
`.cco-tile{display:block;height:var(--cco-tile-height);border-bottom:1px solid var(--_comark-border);${fill}}`,
|
|
72
|
+
".cco-name,.cco-value{display:block;padding:0 .75rem;line-height:1.25rem;overflow-wrap:anywhere}",
|
|
73
|
+
".cco-name{padding-top:.5rem;font-size:.875rem;font-weight:500}",
|
|
74
|
+
".cco-value{padding-bottom:.5rem;color:var(--_comark-muted);font:.75rem/1.25rem ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}",
|
|
75
|
+
".cco-swatch,.cco-tile{-webkit-print-color-adjust:exact;print-color-adjust:exact}",
|
|
76
|
+
"@media print{.cco-palette>li{break-inside:avoid}}"
|
|
77
|
+
].join("")}}`;
|
|
78
|
+
//#endregion
|
|
79
|
+
export { css as t };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!-- A color in inline code, or a line of a `::palette`, for `@comark/svelte`. -->
|
|
2
|
+
<script>
|
|
3
|
+
import { onMount } from "svelte";
|
|
4
|
+
import { addStyles } from "comark-colors/client";
|
|
5
|
+
|
|
6
|
+
let { value = undefined, name = undefined } = $props();
|
|
7
|
+
onMount(addStyles);
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
{#if value && name}
|
|
11
|
+
<li><span class="cco-tile" style:--cco={value}></span><span class="cco-name">{name}</span><span class="cco-value">{value}</span></li>
|
|
12
|
+
{:else if value}
|
|
13
|
+
<code class="cco"><span class="cco-swatch" style:--cco={value} aria-hidden="true"></span>{value}</code>
|
|
14
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<!-- `::palette` for `@comark/svelte`. -->
|
|
2
|
+
<script>
|
|
3
|
+
import { onMount } from "svelte";
|
|
4
|
+
import { addStyles } from "comark-colors/client";
|
|
5
|
+
|
|
6
|
+
let { children } = $props();
|
|
7
|
+
onMount(addStyles);
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<ul class="cco-palette">{@render children?.()}</ul>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Component, Snippet } from "svelte";
|
|
2
|
+
import type { ColorAttributes } from "comark-colors";
|
|
3
|
+
|
|
4
|
+
export { default, isColor } from "comark-colors";
|
|
5
|
+
export type { ColorAttributes, ColorsMeta } from "comark-colors";
|
|
6
|
+
|
|
7
|
+
export declare const Color: Component<ColorAttributes>;
|
|
8
|
+
export declare const Palette: Component<{ children?: Snippet }>;
|
|
9
|
+
export declare const components: { Color: typeof Color; Palette: typeof Palette };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Colors and `::palette` for `@comark/svelte`. Pass `components` to it; the parse plugin comes from `comark-colors`.
|
|
2
|
+
import Color from "./Color.svelte";
|
|
3
|
+
import Palette from "./Palette.svelte";
|
|
4
|
+
|
|
5
|
+
export { default, isColor } from "comark-colors";
|
|
6
|
+
export { Color, Palette };
|
|
7
|
+
export const components = { Color, Palette };
|
package/dist/vue.d.mts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import _default, { ColorAttributes, ColorsMeta, isColor } from "./index.mjs";
|
|
2
|
+
//#region src/vue.d.ts
|
|
3
|
+
/** A color in inline code, or a line of a `::palette`, for `@comark/vue`. */
|
|
4
|
+
export declare const Color: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
5
|
+
value: StringConstructor;
|
|
6
|
+
name: StringConstructor;
|
|
7
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
10
|
+
value: StringConstructor;
|
|
11
|
+
name: StringConstructor;
|
|
12
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
13
|
+
/** `::palette` for `@comark/vue`. */
|
|
14
|
+
export declare const Palette: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
15
|
+
[key: string]: any;
|
|
16
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
17
|
+
/** Pass these as `components` to `@comark/vue`. */
|
|
18
|
+
export declare const components: {
|
|
19
|
+
Color: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
20
|
+
value: StringConstructor;
|
|
21
|
+
name: StringConstructor;
|
|
22
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
}> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
25
|
+
value: StringConstructor;
|
|
26
|
+
name: StringConstructor;
|
|
27
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
28
|
+
Palette: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { type ColorAttributes, type ColorsMeta, _default as default, isColor };
|
package/dist/vue.mjs
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import src_default, { isColor } from "./index.mjs";
|
|
2
|
+
import { addStyles } from "./client.mjs";
|
|
3
|
+
import { defineComponent, h, onMounted } from "vue";
|
|
4
|
+
//#region src/vue.ts
|
|
5
|
+
/** A color in inline code, or a line of a `::palette`, for `@comark/vue`. */
|
|
6
|
+
const Color = defineComponent({
|
|
7
|
+
name: "Color",
|
|
8
|
+
inheritAttrs: false,
|
|
9
|
+
props: {
|
|
10
|
+
value: String,
|
|
11
|
+
name: String
|
|
12
|
+
},
|
|
13
|
+
setup(props) {
|
|
14
|
+
onMounted(addStyles);
|
|
15
|
+
return () => {
|
|
16
|
+
if (!props.value) return null;
|
|
17
|
+
const style = { "--cco": props.value };
|
|
18
|
+
if (props.name) return h("li", [
|
|
19
|
+
h("span", {
|
|
20
|
+
class: "cco-tile",
|
|
21
|
+
style
|
|
22
|
+
}),
|
|
23
|
+
h("span", { class: "cco-name" }, props.name),
|
|
24
|
+
h("span", { class: "cco-value" }, props.value)
|
|
25
|
+
]);
|
|
26
|
+
return h("code", { class: "cco" }, [h("span", {
|
|
27
|
+
class: "cco-swatch",
|
|
28
|
+
style,
|
|
29
|
+
"aria-hidden": "true"
|
|
30
|
+
}), props.value]);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
/** `::palette` for `@comark/vue`. */
|
|
35
|
+
const Palette = defineComponent({
|
|
36
|
+
name: "Palette",
|
|
37
|
+
inheritAttrs: false,
|
|
38
|
+
setup(_, { slots }) {
|
|
39
|
+
onMounted(addStyles);
|
|
40
|
+
return () => h("ul", { class: "cco-palette" }, slots.default?.());
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
/** Pass these as `components` to `@comark/vue`. */
|
|
44
|
+
const components = {
|
|
45
|
+
Color,
|
|
46
|
+
Palette
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
export { Color, Palette, components, src_default as default, isColor };
|
package/package.json
CHANGED
|
@@ -1,12 +1,90 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comark-colors",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.7.2",
|
|
4
|
+
"description": "Color swatches next to inline code that holds a color, like GitLab, and ::palette grids of named colors. A Comark plugin.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"color",
|
|
7
|
+
"comark",
|
|
8
|
+
"markdown",
|
|
9
|
+
"mdc",
|
|
10
|
+
"palette",
|
|
11
|
+
"plugin",
|
|
12
|
+
"swatch"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://comark-ui.onmax.me/colors",
|
|
15
|
+
"bugs": "https://github.com/onmax/comark-ui/issues",
|
|
5
16
|
"license": "MIT",
|
|
6
17
|
"author": "onmax",
|
|
7
18
|
"repository": {
|
|
8
19
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/onmax/comark-
|
|
20
|
+
"url": "git+https://github.com/onmax/comark-ui.git",
|
|
10
21
|
"directory": "packages/colors"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"sideEffects": [
|
|
28
|
+
"*.css"
|
|
29
|
+
],
|
|
30
|
+
"exports": {
|
|
31
|
+
".": "./dist/index.mjs",
|
|
32
|
+
"./client": "./dist/client.mjs",
|
|
33
|
+
"./html": "./dist/html.mjs",
|
|
34
|
+
"./react": "./dist/react.mjs",
|
|
35
|
+
"./style.css": "./dist/style.css",
|
|
36
|
+
"./svelte": {
|
|
37
|
+
"types": "./dist/svelte/index.d.ts",
|
|
38
|
+
"svelte": "./dist/svelte/index.js",
|
|
39
|
+
"default": "./dist/svelte/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./vue": "./dist/vue.mjs",
|
|
42
|
+
"./package.json": "./package.json"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public",
|
|
46
|
+
"provenance": true
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@comark/html": "^0.8.1",
|
|
50
|
+
"@comark/react": "^0.8.1",
|
|
51
|
+
"@comark/vue": "^0.8.1",
|
|
52
|
+
"@types/react": "^19.3.0",
|
|
53
|
+
"@types/react-dom": "^19.3.0",
|
|
54
|
+
"comark": "^0.8.1",
|
|
55
|
+
"react": "^19.3.1",
|
|
56
|
+
"react-dom": "^19.3.1",
|
|
57
|
+
"svelte": "^5.57.2",
|
|
58
|
+
"vue": "^3.5.44",
|
|
59
|
+
"comark-zoom": "0.7.2"
|
|
60
|
+
},
|
|
61
|
+
"peerDependencies": {
|
|
62
|
+
"@comark/html": "^0.8.0",
|
|
63
|
+
"comark": "^0.8.0",
|
|
64
|
+
"react": ">=18",
|
|
65
|
+
"svelte": ">=5",
|
|
66
|
+
"vue": ">=3.5"
|
|
67
|
+
},
|
|
68
|
+
"peerDependenciesMeta": {
|
|
69
|
+
"@comark/html": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"react": {
|
|
73
|
+
"optional": true
|
|
74
|
+
},
|
|
75
|
+
"svelte": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"vue": {
|
|
79
|
+
"optional": true
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"engines": {
|
|
83
|
+
"node": ">=22.12.0"
|
|
84
|
+
},
|
|
85
|
+
"scripts": {
|
|
86
|
+
"build": "tsdown",
|
|
87
|
+
"dev": "tsdown --watch",
|
|
88
|
+
"doctor": "vite-doctor . --no-cache --max-warnings 0 --format text"
|
|
11
89
|
}
|
|
12
|
-
}
|
|
90
|
+
}
|