@refrakt-md/cli 0.21.0 → 0.22.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/dist/bin.js +61 -0
- package/dist/bin.js.map +1 -1
- package/dist/commands/gallery.d.ts +16 -0
- package/dist/commands/gallery.d.ts.map +1 -0
- package/dist/commands/gallery.js +323 -0
- package/dist/commands/gallery.js.map +1 -0
- package/dist/commands/inspect.js +5 -3
- package/dist/commands/inspect.js.map +1 -1
- package/dist/commands/plugin-validate.d.ts.map +1 -1
- package/dist/commands/plugin-validate.js +54 -6
- package/dist/commands/plugin-validate.js.map +1 -1
- package/dist/lib/fixtures.d.ts +9 -6
- package/dist/lib/fixtures.d.ts.map +1 -1
- package/dist/lib/fixtures.js +20 -119
- package/dist/lib/fixtures.js.map +1 -1
- package/dist/lib/gallery.d.ts +50 -0
- package/dist/lib/gallery.d.ts.map +1 -0
- package/dist/lib/gallery.js +169 -0
- package/dist/lib/gallery.js.map +1 -0
- package/package.json +7 -5
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Recursively inline `@import './x.css';` statements into a single CSS string so
|
|
5
|
+
* the gallery is self-contained (no path/serving concerns, deterministic for
|
|
6
|
+
* screenshots). Only *relative* imports are inlined; any `url(...)`/remote
|
|
7
|
+
* import is left untouched. A `seen` set guards against import cycles.
|
|
8
|
+
*/
|
|
9
|
+
export function flattenCssImports(entryPath, seen = new Set()) {
|
|
10
|
+
const abs = resolve(entryPath);
|
|
11
|
+
if (seen.has(abs))
|
|
12
|
+
return '';
|
|
13
|
+
seen.add(abs);
|
|
14
|
+
const dir = dirname(abs);
|
|
15
|
+
const css = readFileSync(abs, 'utf-8');
|
|
16
|
+
return css.replace(/@import\s+(?:url\()?['"]([^'"]+)['"]\)?\s*;/g, (match, importPath) => {
|
|
17
|
+
if (!importPath.startsWith('.'))
|
|
18
|
+
return match; // leave remote imports as-is
|
|
19
|
+
return flattenCssImports(resolve(dir, importPath), seen);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** Default web-font links — tactically Lumina's families (WORK-407 defers the
|
|
23
|
+
* theme-owned-font system). The harness needs fonts actually loaded for stable
|
|
24
|
+
* screenshots. */
|
|
25
|
+
const DEFAULT_FONT_LINKS = [
|
|
26
|
+
'<link rel="preconnect" href="https://fonts.googleapis.com">',
|
|
27
|
+
'<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>',
|
|
28
|
+
'<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300..700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">',
|
|
29
|
+
].join('\n');
|
|
30
|
+
/** Gallery chrome + determinism CSS. Kills animation/transition/caret so
|
|
31
|
+
* screenshots are stable; lays out runes in labelled cells. */
|
|
32
|
+
const GALLERY_CSS = `
|
|
33
|
+
*, *::before, *::after {
|
|
34
|
+
animation-duration: 0s !important;
|
|
35
|
+
animation-delay: 0s !important;
|
|
36
|
+
transition-duration: 0s !important;
|
|
37
|
+
transition-delay: 0s !important;
|
|
38
|
+
caret-color: transparent !important;
|
|
39
|
+
scroll-behavior: auto !important;
|
|
40
|
+
}
|
|
41
|
+
body.rf-gallery {
|
|
42
|
+
background: var(--rf-color-bg);
|
|
43
|
+
color: var(--rf-color-text);
|
|
44
|
+
font-family: var(--rf-font-sans, sans-serif);
|
|
45
|
+
margin: 0;
|
|
46
|
+
padding: 2.5rem 1.5rem;
|
|
47
|
+
}
|
|
48
|
+
.rf-gallery__inner { max-width: 72rem; margin: 0 auto; }
|
|
49
|
+
.rf-gallery__rune { margin: 0 0 3.5rem; }
|
|
50
|
+
.rf-gallery__rune-title {
|
|
51
|
+
font-family: var(--rf-font-mono, monospace);
|
|
52
|
+
font-size: 0.75rem;
|
|
53
|
+
text-transform: uppercase;
|
|
54
|
+
letter-spacing: 0.08em;
|
|
55
|
+
color: var(--rf-color-muted, #888);
|
|
56
|
+
border-bottom: 1px solid var(--rf-color-border, #ddd);
|
|
57
|
+
padding-bottom: 0.5rem;
|
|
58
|
+
margin: 0 0 1.5rem;
|
|
59
|
+
}
|
|
60
|
+
.rf-gallery__cell { margin: 0 0 2rem; }
|
|
61
|
+
.rf-gallery__gap {
|
|
62
|
+
font-family: var(--rf-font-mono, monospace);
|
|
63
|
+
font-size: 0.75rem;
|
|
64
|
+
color: var(--rf-color-muted, #999);
|
|
65
|
+
border: 1px dashed var(--rf-color-border, #ccc);
|
|
66
|
+
border-radius: var(--rf-radius-sm, 4px);
|
|
67
|
+
padding: 0.75rem 1rem;
|
|
68
|
+
}
|
|
69
|
+
.rf-gallery__cell-label {
|
|
70
|
+
display: block;
|
|
71
|
+
font-family: var(--rf-font-mono, monospace);
|
|
72
|
+
font-size: 0.6875rem;
|
|
73
|
+
color: var(--rf-color-muted, #999);
|
|
74
|
+
margin: 0 0 0.5rem;
|
|
75
|
+
}
|
|
76
|
+
`.trim();
|
|
77
|
+
/** Determinism reset for layout fixtures (no gallery chrome — the layout *is*
|
|
78
|
+
* the page). Kills animation/transition/caret so screenshots are stable. */
|
|
79
|
+
const LAYOUT_RESET_CSS = `
|
|
80
|
+
*, *::before, *::after {
|
|
81
|
+
animation-duration: 0s !important;
|
|
82
|
+
animation-delay: 0s !important;
|
|
83
|
+
transition-duration: 0s !important;
|
|
84
|
+
transition-delay: 0s !important;
|
|
85
|
+
caret-color: transparent !important;
|
|
86
|
+
scroll-behavior: auto !important;
|
|
87
|
+
}
|
|
88
|
+
body { margin: 0; background: var(--rf-color-bg); color: var(--rf-color-text); font-family: var(--rf-font-sans, sans-serif); }
|
|
89
|
+
`.trim();
|
|
90
|
+
/**
|
|
91
|
+
* Render a standalone full-page document for a layout fixture — the layout's
|
|
92
|
+
* own chrome *is* the page (no gallery cell grid), so the harness can shoot it
|
|
93
|
+
* whole-page at multiple viewports.
|
|
94
|
+
*/
|
|
95
|
+
export function renderLayoutDocument(opts) {
|
|
96
|
+
const { mode, themeCss, bodyHtml, name, fontLinks = DEFAULT_FONT_LINKS, behaviorScript } = opts;
|
|
97
|
+
const htmlAttr = mode === 'dark' ? ' data-theme="dark"' : '';
|
|
98
|
+
const tail = behaviorScript
|
|
99
|
+
? `<script type="application/json" id="rf-context">{"pages":[],"currentUrl":"/"}</script>\n<script>${behaviorScript}</script>\n`
|
|
100
|
+
: '';
|
|
101
|
+
return `<!DOCTYPE html>
|
|
102
|
+
<html lang="en"${htmlAttr}>
|
|
103
|
+
<head>
|
|
104
|
+
<meta charset="utf-8">
|
|
105
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
106
|
+
<meta name="color-scheme" content="light dark">
|
|
107
|
+
<title>refrakt layout — ${name} (${mode})</title>
|
|
108
|
+
${fontLinks}
|
|
109
|
+
<style>${themeCss}</style>
|
|
110
|
+
<style>${LAYOUT_RESET_CSS}</style>
|
|
111
|
+
</head>
|
|
112
|
+
<body>
|
|
113
|
+
${bodyHtml}
|
|
114
|
+
${tail}</body>
|
|
115
|
+
</html>
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
function escapeHtml(s) {
|
|
119
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Render the full self-contained gallery HTML document for one mode. Cells are
|
|
123
|
+
* grouped by rune; each carries a stable `data-gallery-cell="<rune>--<variant>"`
|
|
124
|
+
* anchor so the harness ({% WORK-409 %}) can clip per variant.
|
|
125
|
+
*/
|
|
126
|
+
export function renderGalleryDocument(opts) {
|
|
127
|
+
const { mode, themeCss, cells, fontLinks = DEFAULT_FONT_LINKS, behaviorScript } = opts;
|
|
128
|
+
// Group cells by rune, preserving insertion order.
|
|
129
|
+
const byRune = new Map();
|
|
130
|
+
for (const cell of cells) {
|
|
131
|
+
const list = byRune.get(cell.rune) ?? [];
|
|
132
|
+
list.push(cell);
|
|
133
|
+
byRune.set(cell.rune, list);
|
|
134
|
+
}
|
|
135
|
+
const sections = [];
|
|
136
|
+
for (const [rune, runeCells] of byRune) {
|
|
137
|
+
const cellHtml = runeCells.map(cell => {
|
|
138
|
+
const anchor = `${cell.rune}--${cell.variant}`;
|
|
139
|
+
return ` <div class="rf-gallery__cell" data-gallery-cell="${escapeHtml(anchor)}" data-rune="${escapeHtml(cell.rune)}" data-variant="${escapeHtml(cell.variant)}">
|
|
140
|
+
<span class="rf-gallery__cell-label">${escapeHtml(cell.variant)}</span>
|
|
141
|
+
${cell.html}
|
|
142
|
+
</div>`;
|
|
143
|
+
}).join('\n');
|
|
144
|
+
sections.push(` <section class="rf-gallery__rune" data-gallery-rune="${escapeHtml(rune)}">
|
|
145
|
+
<h2 class="rf-gallery__rune-title">${escapeHtml(rune)}</h2>
|
|
146
|
+
${cellHtml}
|
|
147
|
+
</section>`);
|
|
148
|
+
}
|
|
149
|
+
const htmlAttr = mode === 'dark' ? ' data-theme="dark"' : '';
|
|
150
|
+
return `<!DOCTYPE html>
|
|
151
|
+
<html lang="en"${htmlAttr}>
|
|
152
|
+
<head>
|
|
153
|
+
<meta charset="utf-8">
|
|
154
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
155
|
+
<meta name="color-scheme" content="light dark">
|
|
156
|
+
<title>refrakt gallery (${mode})</title>
|
|
157
|
+
${fontLinks}
|
|
158
|
+
<style>${themeCss}</style>
|
|
159
|
+
<style>${GALLERY_CSS}</style>
|
|
160
|
+
</head>
|
|
161
|
+
<body class="rf-gallery">
|
|
162
|
+
<div class="rf-gallery__inner">
|
|
163
|
+
${sections.join('\n')}
|
|
164
|
+
</div>
|
|
165
|
+
${behaviorScript ? `<script type="application/json" id="rf-context">{"pages":[],"currentUrl":"/"}</script>\n<script>${behaviorScript}</script>\n` : ''}</body>
|
|
166
|
+
</html>
|
|
167
|
+
`;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=gallery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gallery.js","sourceRoot":"","sources":["../../src/lib/gallery.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@refrakt-md/cli",
|
|
3
3
|
"description": "CLI tools for refrakt.md",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.22.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -36,10 +36,12 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@markdoc/markdoc": "0.4.0",
|
|
39
|
-
"@refrakt-md/ai": "0.
|
|
40
|
-
"@refrakt-md/editor": "0.
|
|
41
|
-
"@refrakt-md/
|
|
42
|
-
"@refrakt-md/
|
|
39
|
+
"@refrakt-md/ai": "0.22.0",
|
|
40
|
+
"@refrakt-md/editor": "0.22.0",
|
|
41
|
+
"@refrakt-md/html": "0.22.0",
|
|
42
|
+
"@refrakt-md/runes": "0.22.0",
|
|
43
|
+
"@refrakt-md/transform": "0.22.0",
|
|
44
|
+
"esbuild": "^0.27.5",
|
|
43
45
|
"postcss": "^8.4.0"
|
|
44
46
|
}
|
|
45
47
|
}
|