@vmz/vmz 0.3.7 → 0.3.8

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.
@@ -66,7 +66,7 @@ export async function buildDocuments(opts) {
66
66
  assertIntegratedDistReady(appDistDir);
67
67
  }
68
68
  fs.mkdirSync(outDir, { recursive: true });
69
- const designs = resolveDocumentDesignsCss(projectRoot);
69
+ const designs = resolveDocumentDesignsCss(projectRoot, appDistDir);
70
70
  let designsHref = null;
71
71
  if (designs.css && designs.href) {
72
72
  const cssPath = path.join(outDir, designs.href);
@@ -3,4 +3,4 @@ export interface DocumentDesignsCssResult {
3
3
  source: string | null;
4
4
  href: string | null;
5
5
  }
6
- export declare function resolveDocumentDesignsCss(projectRoot: string): DocumentDesignsCssResult;
6
+ export declare function resolveDocumentDesignsCss(projectRoot: string, appDistDir?: string | null): DocumentDesignsCssResult;
@@ -1,18 +1,25 @@
1
1
  /**
2
- * Document — wire project `/designs` into static document assets.
3
- * Prefer compiled `vmz-designs.css` / `vmz.css`; else emit a minimal token CSS.
2
+ * Document — wire project `/designs` and the compiled app stylesheet into
3
+ * static document assets.
4
+ *
5
+ * Layout chrome comes from `designs/document/chrome.css`. Theme tokens are not
6
+ * re-derived here: they come from the app build output (`vmz-designs.css` /
7
+ * `vmz.css` under `appDistDir`), which is the single compiled artifact.
4
8
  */
5
9
  import fs from 'node:fs';
6
10
  import path from 'node:path';
7
- export function resolveDocumentDesignsCss(projectRoot) {
11
+ export function resolveDocumentDesignsCss(projectRoot, appDistDir) {
8
12
  const designsDir = path.join(projectRoot, 'designs');
9
13
  if (!fs.existsSync(designsDir) || !fs.statSync(designsDir).isDirectory()) {
10
14
  return { css: '', source: null, href: null };
11
15
  }
12
16
  const parts = [];
13
17
  const sources = [];
14
- // Layout first so @import (fonts) stays at stylesheet top; theme tokens follow.
15
- const layoutCandidates = [path.join(designsDir, 'document', 'chrome.css'), path.join(designsDir, 'styles', 'document.css')];
18
+ // Layout first so @import stays at stylesheet top; compiled tokens follow.
19
+ const layoutCandidates = [
20
+ path.join(designsDir, 'document', 'chrome.css'),
21
+ path.join(designsDir, 'styles', 'document.css'),
22
+ ];
16
23
  for (const p of layoutCandidates) {
17
24
  if (!fs.existsSync(p))
18
25
  continue;
@@ -20,122 +27,27 @@ export function resolveDocumentDesignsCss(projectRoot) {
20
27
  sources.push(path.relative(projectRoot, p).replace(/\\/g, '/'));
21
28
  break;
22
29
  }
23
- const distCandidates = [path.join(projectRoot, 'dist', 'vmz-designs.css'), path.join(projectRoot, 'dist', 'vmz.css')];
24
- for (const p of distCandidates) {
25
- if (fs.existsSync(p)) {
26
- parts.push(fs.readFileSync(p, 'utf8'));
27
- sources.push(path.relative(projectRoot, p).replace(/\\/g, '/'));
28
- break;
30
+ if (appDistDir) {
31
+ const compiled = [path.join(appDistDir, 'vmz-designs.css'), path.join(appDistDir, 'vmz.css')].find((p) => fs.existsSync(p));
32
+ if (!compiled) {
33
+ throw new Error(`vmz.document: app dist ${appDistDir} is missing vmz-designs.css / vmz.css; build the app before the documents`);
29
34
  }
30
- }
31
- if (parts.length) {
32
- return {
33
- css: parts.join('\n\n'),
34
- source: sources.join('+'),
35
- href: 'assets/vmz-designs.css',
36
- };
37
- }
38
- const styleCandidates = [path.join(designsDir, 'styles', 'index.css')];
39
- for (const p of styleCandidates) {
40
- if (fs.existsSync(p)) {
41
- return {
42
- css: fs.readFileSync(p, 'utf8'),
43
- source: path.relative(projectRoot, p).replace(/\\/g, '/'),
44
- href: 'assets/vmz-designs.css',
45
- };
35
+ parts.push(fs.readFileSync(compiled, 'utf8'));
36
+ sources.push(path.relative(projectRoot, compiled).replace(/\\/g, '/'));
37
+ }
38
+ else {
39
+ const entry = path.join(designsDir, 'styles', 'index.css');
40
+ if (fs.existsSync(entry)) {
41
+ parts.push(fs.readFileSync(entry, 'utf8'));
42
+ sources.push(path.relative(projectRoot, entry).replace(/\\/g, '/'));
46
43
  }
47
44
  }
48
- const emitted = emitMinimalDesignsCss(designsDir);
49
- if (emitted) {
50
- return { css: emitted, source: 'designs/', href: 'assets/vmz-designs.css' };
51
- }
52
- return { css: '', source: 'designs/', href: null };
53
- }
54
- function emitMinimalDesignsCss(designsDir) {
55
- const vars = {};
56
- const tokenDir = path.join(designsDir, 'tokens');
57
- if (fs.existsSync(tokenDir)) {
58
- walkJson(tokenDir, (obj, prefix) => {
59
- collectStyleThemeEntries(obj, vars);
60
- flattenTokens(obj, prefix, vars);
61
- });
62
- }
63
- const themeJson = path.join(designsDir, 'theme.json');
64
- if (fs.existsSync(themeJson)) {
65
- try {
66
- const theme = JSON.parse(fs.readFileSync(themeJson, 'utf8'));
67
- collectStyleThemeEntries(theme, vars);
68
- flattenTokens(theme, '', vars);
69
- }
70
- catch {
71
- /* ignore */
72
- }
73
- }
74
- const keys = Object.keys(vars).sort();
75
- if (!keys.length) {
76
- // Presence of /designs still warrants a readable baseline sheet.
77
- return `/* vmz.document designs baseline */\n:root { color-scheme: light; }\nbody { font-family: system-ui, sans-serif; line-height: 1.5; margin: 0; }\nmain { max-width: 48rem; margin: 0 auto; padding: 1.5rem; }\nnav { padding: 1rem 1.5rem; border-bottom: 1px solid #ddd; }\n`;
78
- }
79
- const lines = keys.map((k) => ` ${cssVar(k)}: ${vars[k]};`);
80
- return `/* vmz.document designs from /designs */\n:root {\n${lines.join('\n')}\n}\nbody { font-family: var(--font-sans, system-ui, sans-serif); line-height: 1.5; margin: 0; color: var(--color-fg, #111); background: var(--color-bg, #fff); }\nmain { max-width: 48rem; margin: 0 auto; padding: 1.5rem; }\nnav { padding: 1rem 1.5rem; border-bottom: 1px solid var(--color-border, #ddd); }\n`;
81
- }
82
- function cssVar(key) {
83
- const name = String(key)
84
- .replace(/[^a-zA-Z0-9_-]+/g, '-')
85
- .replace(/^-|-$/g, '');
86
- return `--${name}`;
87
- }
88
- /** Style Theme entries (`key.path` + `value`) → `vmz-*` CSS vars (same naming as application compile). */
89
- function collectStyleThemeEntries(obj, out) {
90
- if (obj == null || typeof obj !== 'object' || Array.isArray(obj))
91
- return;
92
- const entries = obj.entries;
93
- if (!Array.isArray(entries))
94
- return;
95
- for (const e of entries) {
96
- const pathParts = e?.key?.path;
97
- if (!Array.isArray(pathParts) || pathParts.length === 0)
98
- continue;
99
- if (typeof e.value !== 'string' && typeof e.value !== 'number')
100
- continue;
101
- const dotted = pathParts.map(String).join('-');
102
- out[`vmz-${dotted}`] = String(e.value);
103
- }
104
- }
105
- function flattenTokens(obj, prefix, out) {
106
- if (obj == null || typeof obj !== 'object' || Array.isArray(obj))
107
- return;
108
- for (const [k, v] of Object.entries(obj)) {
109
- if (k === 'entries')
110
- continue;
111
- const key = prefix ? `${prefix}-${k}` : k;
112
- if (v != null && typeof v === 'object' && !Array.isArray(v)) {
113
- if ('value' in v && (typeof v.value === 'string' || typeof v.value === 'number')) {
114
- out[key] = String(v.value);
115
- }
116
- else {
117
- flattenTokens(v, key, out);
118
- }
119
- }
120
- else if (typeof v === 'string' || typeof v === 'number') {
121
- out[key] = String(v);
122
- }
123
- }
124
- }
125
- function walkJson(dir, fn) {
126
- if (!fs.existsSync(dir))
127
- return;
128
- for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
129
- const full = path.join(dir, ent.name);
130
- if (ent.isDirectory())
131
- walkJson(full, fn);
132
- else if (ent.isFile() && ent.name.endsWith('.json')) {
133
- try {
134
- fn(JSON.parse(fs.readFileSync(full, 'utf8')), '');
135
- }
136
- catch {
137
- /* ignore */
138
- }
139
- }
45
+ if (!parts.length) {
46
+ return { css: '', source: 'designs/', href: null };
140
47
  }
48
+ return {
49
+ css: parts.join('\n\n'),
50
+ source: sources.join('+'),
51
+ href: 'assets/vmz-designs.css',
52
+ };
141
53
  }
package/package.json CHANGED
@@ -3,23 +3,23 @@
3
3
  "vmz": "./bin/vmz.js"
4
4
  },
5
5
  "dependencies": {
6
- "@vmz/commander": "0.3.7",
7
- "@vmz/core": "0.3.7",
8
- "@vmz/diagnostic": "0.3.7",
9
- "@vmz/plugin": "0.3.7",
10
- "@vmz/protocol": "0.3.7"
6
+ "@vmz/commander": "0.3.8",
7
+ "@vmz/core": "0.3.8",
8
+ "@vmz/diagnostic": "0.3.8",
9
+ "@vmz/plugin": "0.3.8",
10
+ "@vmz/protocol": "0.3.8"
11
11
  },
12
12
  "description": "VMZ Node toolchain — N-API workspace session + CLI (publish name @vmz/vmz)",
13
13
  "devDependencies": {
14
14
  "@types/node": "^22.15.0",
15
- "@vmz/plugin": "0.3.7",
16
- "@vmz/plugin-katex": "0.3.7",
17
- "@vmz/plugin-markdown-it": "0.3.7",
18
- "@vmz/plugin-shiki": "0.3.7",
19
- "@vmz/test": "0.3.7",
15
+ "@vmz/plugin": "0.3.8",
16
+ "@vmz/plugin-katex": "0.3.8",
17
+ "@vmz/plugin-markdown-it": "0.3.8",
18
+ "@vmz/plugin-shiki": "0.3.8",
19
+ "@vmz/test": "0.3.8",
20
20
  "linkedom": "^0.18.13",
21
21
  "typescript": "^5.8.3",
22
- "vmz-plugin-conformance": "0.3.7"
22
+ "vmz-plugin-conformance": "0.3.8"
23
23
  },
24
24
  "engines": {
25
25
  "node": ">=24.12.0"
@@ -80,16 +80,16 @@
80
80
  "main": "./dist/index.js",
81
81
  "name": "@vmz/vmz",
82
82
  "optionalDependencies": {
83
- "@vmz/vmz-darwin-arm64": "0.3.7",
84
- "@vmz/vmz-darwin-x64": "0.3.7",
85
- "@vmz/vmz-linux-arm64": "0.3.7",
86
- "@vmz/vmz-linux-x64": "0.3.7",
87
- "@vmz/vmz-win32-arm64": "0.3.7",
88
- "@vmz/vmz-win32-x64": "0.3.7"
83
+ "@vmz/vmz-darwin-arm64": "0.3.8",
84
+ "@vmz/vmz-darwin-x64": "0.3.8",
85
+ "@vmz/vmz-linux-arm64": "0.3.8",
86
+ "@vmz/vmz-linux-x64": "0.3.8",
87
+ "@vmz/vmz-win32-arm64": "0.3.8",
88
+ "@vmz/vmz-win32-x64": "0.3.8"
89
89
  },
90
90
  "peerDependencies": {
91
- "@vmz/plugin-markdown-it": "0.3.7",
92
- "@vmz/test": "0.3.7",
91
+ "@vmz/plugin-markdown-it": "0.3.8",
92
+ "@vmz/test": "0.3.8",
93
93
  "typescript": "^5.8.3"
94
94
  },
95
95
  "peerDependenciesMeta": {
@@ -122,5 +122,5 @@
122
122
  },
123
123
  "type": "module",
124
124
  "types": "./dist/index.d.ts",
125
- "version": "0.3.7"
125
+ "version": "0.3.8"
126
126
  }