@vmz/vmz 0.1.11 → 0.1.13

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.
Files changed (43) hide show
  1. package/dist/build-assemble.js +3 -4
  2. package/dist/cdn-policy.js +4 -5
  3. package/dist/cli.js +15 -50
  4. package/dist/content-addressed-assets.d.ts +2 -8
  5. package/dist/content-addressed-assets.js +34 -110
  6. package/dist/delivery-profile.d.ts +1 -11
  7. package/dist/delivery-profile.js +1 -70
  8. package/dist/dev-session.d.ts +0 -1
  9. package/dist/dev-session.js +64 -220
  10. package/dist/document-build.js +34 -61
  11. package/dist/document-cmd.js +9 -2
  12. package/dist/document-enrich.d.ts +1 -2
  13. package/dist/document-enrich.js +4 -15
  14. package/dist/document-integrate.js +21 -28
  15. package/dist/embedded-packaging.js +1 -2
  16. package/dist/index.d.ts +1 -15
  17. package/dist/index.js +3 -58
  18. package/dist/locale-check.js +61 -28
  19. package/dist/locale-cmd.js +42 -10
  20. package/dist/locale-route-emit.d.ts +1 -4
  21. package/dist/locale-route-emit.js +32 -7
  22. package/dist/locale-router.js +8 -26
  23. package/dist/pack.js +2 -3
  24. package/dist/production-observability.js +2 -3
  25. package/dist/production-test-pack.js +3 -4
  26. package/dist/release-pack.js +18 -5
  27. package/dist/server-artifact.js +3 -4
  28. package/dist/site-delivery.js +3 -4
  29. package/dist/static-emit.js +78 -116
  30. package/dist/test-cmd.js +1 -2
  31. package/package.json +12 -12
  32. package/dist/dev-watch-roots.d.ts +0 -67
  33. package/dist/dev-watch-roots.js +0 -220
  34. package/dist/document-host-chrome.d.ts +0 -28
  35. package/dist/document-host-chrome.js +0 -128
  36. package/dist/native-addon.d.ts +0 -9
  37. package/dist/native-addon.js +0 -84
  38. package/dist/pretty-json.d.ts +0 -19
  39. package/dist/pretty-json.js +0 -43
  40. package/dist/route-path.d.ts +0 -35
  41. package/dist/route-path.js +0 -77
  42. package/dist/wechat-packaging.d.ts +0 -22
  43. package/dist/wechat-packaging.js +0 -59
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/vmz",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "description": "VMZ Node toolchain — N-API workspace session + CLI (publish name @vmz/vmz)",
6
6
  "license": "MIT",
@@ -48,15 +48,15 @@
48
48
  }
49
49
  },
50
50
  "dependencies": {
51
- "@vmz/core": "0.1.11",
52
- "@vmz/plugin": "0.1.11",
53
- "@vmz/protocol": "0.1.11",
51
+ "@vmz/core": "0.1.13",
52
+ "@vmz/plugin": "0.1.13",
53
+ "@vmz/protocol": "0.1.13",
54
54
  "jiti": "^2.6.1",
55
55
  "json5": "^2.2.3"
56
56
  },
57
57
  "peerDependencies": {
58
- "@vmz/plugin-markdown-it": "0.1.11",
59
- "@vmz/test": "0.1.11",
58
+ "@vmz/plugin-markdown-it": "0.1.13",
59
+ "@vmz/test": "0.1.13",
60
60
  "typescript": "^5.8.3"
61
61
  },
62
62
  "peerDependenciesMeta": {
@@ -90,12 +90,12 @@
90
90
  "cli"
91
91
  ],
92
92
  "optionalDependencies": {
93
- "@vmz/vmz-win32-x64": "0.1.11",
94
- "@vmz/vmz-win32-arm64": "0.1.11",
95
- "@vmz/vmz-darwin-x64": "0.1.11",
96
- "@vmz/vmz-darwin-arm64": "0.1.11",
97
- "@vmz/vmz-linux-x64": "0.1.11",
98
- "@vmz/vmz-linux-arm64": "0.1.11"
93
+ "@vmz/vmz-win32-x64": "0.1.13",
94
+ "@vmz/vmz-win32-arm64": "0.1.13",
95
+ "@vmz/vmz-darwin-x64": "0.1.13",
96
+ "@vmz/vmz-darwin-arm64": "0.1.13",
97
+ "@vmz/vmz-linux-x64": "0.1.13",
98
+ "@vmz/vmz-linux-arm64": "0.1.13"
99
99
  },
100
100
  "publishConfig": {
101
101
  "access": "public"
@@ -1,67 +0,0 @@
1
- /**
2
- * Dev watch helpers: coalesce multi-file bursts without dropping dirty set,
3
- * and derive extra watch roots from the compile graph (deployment unit sources).
4
- */
5
- /**
6
- * @typedef {{ changed: string[], deleted: string[] }} DirtySet
7
- */
8
- /**
9
- * Merge dirty sets: later change cancels delete and vice versa.
10
- * @param {DirtySet} a
11
- * @param {DirtySet} b
12
- * @returns {DirtySet}
13
- */
14
- export declare function mergeDirtySets(a: any, b: any): {
15
- changed: unknown[];
16
- deleted: unknown[];
17
- };
18
- /**
19
- * Wait until `root` stops changing; return the **accumulated** dirty set since `initial`.
20
- * Updates `fingerprints` for `root` as it polls. Does **not** discard `initial`.
21
- *
22
- * @param {string} root
23
- * @param {Map<string, Map<string, string>>} fingerprints
24
- * @param {DirtySet} initial
25
- * @param {{ sleep?: (ms: number) => Promise<void>, maxRounds?: number, settleMs?: number }} [opts]
26
- * @returns {Promise<DirtySet>}
27
- */
28
- export declare function coalesceRootBurst(root: any, fingerprints: any, initial: any, opts?: {}): Promise<{
29
- changed: any[];
30
- deleted: any[];
31
- }>;
32
- /**
33
- * Walk up from a file to find a package.json directory.
34
- * @param {string} file
35
- * @returns {string | null}
36
- */
37
- export declare function findPackageRoot(file: any): string;
38
- /**
39
- * Prefer package/src when present; otherwise the directory containing the source file.
40
- * @param {string} sourceFile
41
- * @returns {string | null}
42
- */
43
- export declare function watchRootForSourceFile(sourceFile: any): string;
44
- /**
45
- * Absolute roots for workspace / file / link deps that have a src tree.
46
- * @param {string} project
47
- * @returns {string[]}
48
- */
49
- export declare function localLinkDependencyRoots(project: any): any[];
50
- /**
51
- * Collect watch roots: project src/locales/documents + compile-graph external sources
52
- * + local link/workspace package roots. Never adds a bare registry node_modules tree.
53
- *
54
- * @param {{ project: string, outDir: string }} opts
55
- * @returns {{ roots: string[], dependencyRoots: string[], applicationRoots: string[] }}
56
- */
57
- export declare function collectDevWatchRoots(opts: any): {
58
- roots: any[];
59
- dependencyRoots: unknown[];
60
- applicationRoots: any[];
61
- };
62
- /**
63
- * Classify whether a changed file lives under a dependency watch root (not app src).
64
- * @param {string} file
65
- * @param {string[]} dependencyRoots
66
- */
67
- export declare function isDependencyPath(file: any, dependencyRoots: any): any;
@@ -1,220 +0,0 @@
1
- // @ts-nocheck
2
- /**
3
- * Dev watch helpers: coalesce multi-file bursts without dropping dirty set,
4
- * and derive extra watch roots from the compile graph (deployment unit sources).
5
- */
6
- import { existsSync, readFileSync, realpathSync } from 'node:fs';
7
- import path from 'node:path';
8
- import { diffFingerprints, fileFingerprintMap } from './watch-diff.js';
9
- /**
10
- * @typedef {{ changed: string[], deleted: string[] }} DirtySet
11
- */
12
- /**
13
- * Merge dirty sets: later change cancels delete and vice versa.
14
- * @param {DirtySet} a
15
- * @param {DirtySet} b
16
- * @returns {DirtySet}
17
- */
18
- export function mergeDirtySets(a, b) {
19
- const changed = new Set(a?.changed || []);
20
- const deleted = new Set(a?.deleted || []);
21
- for (const f of b?.changed || []) {
22
- changed.add(f);
23
- deleted.delete(f);
24
- }
25
- for (const f of b?.deleted || []) {
26
- deleted.add(f);
27
- changed.delete(f);
28
- }
29
- return { changed: [...changed], deleted: [...deleted] };
30
- }
31
- /**
32
- * Wait until `root` stops changing; return the **accumulated** dirty set since `initial`.
33
- * Updates `fingerprints` for `root` as it polls. Does **not** discard `initial`.
34
- *
35
- * @param {string} root
36
- * @param {Map<string, Map<string, string>>} fingerprints
37
- * @param {DirtySet} initial
38
- * @param {{ sleep?: (ms: number) => Promise<void>, maxRounds?: number, settleMs?: number }} [opts]
39
- * @returns {Promise<DirtySet>}
40
- */
41
- export async function coalesceRootBurst(root, fingerprints, initial, opts = {}) {
42
- const sleepFn = opts.sleep || ((ms) => new Promise((r) => setTimeout(r, ms)));
43
- const maxRounds = opts.maxRounds ?? 20;
44
- const settleMs = opts.settleMs ?? 220;
45
- let accumulated = {
46
- changed: [...(initial?.changed || [])],
47
- deleted: [...(initial?.deleted || [])],
48
- };
49
- let guard = 0;
50
- while (guard++ < maxRounds) {
51
- await sleepFn(settleMs);
52
- const prev = fingerprints.get(root) || new Map();
53
- const next = fileFingerprintMap(root);
54
- const diff = diffFingerprints(prev, next);
55
- fingerprints.set(root, next);
56
- if (!diff.changed.length && !diff.deleted.length)
57
- break;
58
- accumulated = mergeDirtySets(accumulated, diff);
59
- }
60
- return accumulated;
61
- }
62
- /**
63
- * Walk up from a file to find a package.json directory.
64
- * @param {string} file
65
- * @returns {string | null}
66
- */
67
- export function findPackageRoot(file) {
68
- let dir = path.dirname(path.resolve(file));
69
- for (let i = 0; i < 24; i++) {
70
- if (existsSync(path.join(dir, 'package.json')))
71
- return dir;
72
- const parent = path.dirname(dir);
73
- if (parent === dir)
74
- break;
75
- dir = parent;
76
- }
77
- return null;
78
- }
79
- /**
80
- * Prefer package/src when present; otherwise the directory containing the source file.
81
- * @param {string} sourceFile
82
- * @returns {string | null}
83
- */
84
- export function watchRootForSourceFile(sourceFile) {
85
- const abs = path.resolve(sourceFile);
86
- if (!existsSync(abs))
87
- return null;
88
- const pkg = findPackageRoot(abs);
89
- if (pkg) {
90
- const src = path.join(pkg, 'src');
91
- if (existsSync(src))
92
- return src;
93
- return pkg;
94
- }
95
- return path.dirname(abs);
96
- }
97
- /**
98
- * Absolute roots for workspace / file / link deps that have a src tree.
99
- * @param {string} project
100
- * @returns {string[]}
101
- */
102
- export function localLinkDependencyRoots(project) {
103
- const pkgPath = path.join(path.resolve(project), 'package.json');
104
- if (!existsSync(pkgPath))
105
- return [];
106
- /** @type {string[]} */
107
- const roots = [];
108
- try {
109
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
110
- const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
111
- for (const [name, spec] of Object.entries(deps)) {
112
- if (typeof spec !== 'string')
113
- continue;
114
- let target = null;
115
- if (spec.startsWith('workspace:')) {
116
- // Resolve via node_modules (pnpm links workspace packages there).
117
- const nm = path.join(path.resolve(project), 'node_modules', ...name.split('/'));
118
- if (existsSync(path.join(nm, 'package.json')))
119
- target = nm;
120
- }
121
- else if (spec.startsWith('file:') || spec.startsWith('link:')) {
122
- const rel = spec.replace(/^(file|link):/, '');
123
- target = path.resolve(project, rel);
124
- }
125
- if (!target)
126
- continue;
127
- try {
128
- target = realpathSync(target);
129
- }
130
- catch {
131
- /* keep as-is */
132
- }
133
- const src = path.join(target, 'src');
134
- if (existsSync(src))
135
- roots.push(src);
136
- else if (existsSync(target))
137
- roots.push(target);
138
- }
139
- }
140
- catch {
141
- /* ignore */
142
- }
143
- return roots;
144
- }
145
- /**
146
- * Collect watch roots: project src/locales/documents + compile-graph external sources
147
- * + local link/workspace package roots. Never adds a bare registry node_modules tree.
148
- *
149
- * @param {{ project: string, outDir: string }} opts
150
- * @returns {{ roots: string[], dependencyRoots: string[], applicationRoots: string[] }}
151
- */
152
- export function collectDevWatchRoots(opts) {
153
- const project = path.resolve(opts.project);
154
- const outDir = path.resolve(opts.outDir);
155
- const src = path.join(project, 'src');
156
- const docsRoot = path.join(project, 'documents');
157
- const localesRoot = path.join(project, 'locales');
158
- const designsRoot = path.join(project, 'designs');
159
- /** @type {string[]} */
160
- const applicationRoots = [];
161
- if (existsSync(src))
162
- applicationRoots.push(src);
163
- if (existsSync(docsRoot))
164
- applicationRoots.push(docsRoot);
165
- if (existsSync(localesRoot))
166
- applicationRoots.push(localesRoot);
167
- if (existsSync(designsRoot))
168
- applicationRoots.push(designsRoot);
169
- /** @type {Set<string>} */
170
- const depSet = new Set();
171
- const depJson = path.join(outDir, 'vmz-deployment.json');
172
- if (existsSync(depJson)) {
173
- try {
174
- const dep = JSON.parse(readFileSync(depJson, 'utf8'));
175
- for (const unit of dep.units || []) {
176
- const source = unit?.source;
177
- if (typeof source !== 'string' || !source)
178
- continue;
179
- let abs = path.resolve(source);
180
- try {
181
- abs = realpathSync(abs);
182
- }
183
- catch {
184
- /* keep */
185
- }
186
- const underProject = abs === project || abs.startsWith(project + path.sep) || abs.startsWith(project + '/');
187
- if (underProject)
188
- continue;
189
- const root = watchRootForSourceFile(abs);
190
- if (root)
191
- depSet.add(path.resolve(root));
192
- }
193
- }
194
- catch {
195
- /* ignore corrupt deployment */
196
- }
197
- }
198
- for (const r of localLinkDependencyRoots(project)) {
199
- depSet.add(path.resolve(r));
200
- }
201
- // Drop dependency roots that are already under an application root.
202
- const dependencyRoots = [...depSet].filter((r) => {
203
- return !applicationRoots.some((app) => r === app || r.startsWith(app + path.sep) || r.startsWith(app + '/'));
204
- });
205
- const roots = [...applicationRoots];
206
- for (const r of dependencyRoots) {
207
- if (!roots.includes(r))
208
- roots.push(r);
209
- }
210
- return { roots, dependencyRoots, applicationRoots };
211
- }
212
- /**
213
- * Classify whether a changed file lives under a dependency watch root (not app src).
214
- * @param {string} file
215
- * @param {string[]} dependencyRoots
216
- */
217
- export function isDependencyPath(file, dependencyRoots) {
218
- const abs = path.resolve(file);
219
- return (dependencyRoots || []).some((r) => abs === r || abs.startsWith(r + path.sep) || abs.startsWith(r + '/'));
220
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * @param {string} projectRoot
3
- * @returns {{ strategy?: string, defaultLocale?: string } | null}
4
- */
5
- export declare function loadLocalesRouting(projectRoot: any): any;
6
- /**
7
- * @param {string} projectRoot
8
- * @param {string} localeId
9
- */
10
- export declare function loadLocaleCommonMessages(projectRoot: any, localeId: any): any;
11
- /**
12
- * @param {string} projectRoot
13
- */
14
- export declare function readSiteGithubUrl(projectRoot: any): string;
15
- /**
16
- * @param {string} template
17
- * @param {string} localeId
18
- * @param {Record<string, string>} messages
19
- * @param {{ docsRootHref: string, guideHref: string, githubUrl: string, routing?: { strategy?: string } }} opts
20
- */
21
- export declare function renderHostChromeTemplate(template: any, localeId: any, messages: any, opts: any): any;
22
- /** Inline locale preference picker for strategy `none` (Host state, not URL). */
23
- export declare function localeNonePickerScript(): string;
24
- /**
25
- * @param {string} routeBase
26
- * @param {string} pageKey
27
- */
28
- export declare function docsRouteNone(routeBase: any, pageKey: any): string;
@@ -1,128 +0,0 @@
1
- // @ts-nocheck
2
- /**
3
- * Integrated DocumentMount — lower host SiteHeader/SiteFooter .vmz templates to
4
- * static HTML with locale-resolved copy (LocaleId is Host preference, not URL).
5
- */
6
- import fs from 'node:fs';
7
- import path from 'node:path';
8
- /**
9
- * @param {string} projectRoot
10
- * @returns {{ strategy?: string, defaultLocale?: string } | null}
11
- */
12
- export function loadLocalesRouting(projectRoot) {
13
- const p = path.join(projectRoot, 'locales', 'locales.json5');
14
- if (!fs.existsSync(p))
15
- return null;
16
- try {
17
- const raw = fs.readFileSync(p, 'utf8');
18
- let s = raw.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
19
- const m = s.match(/routing\s*:\s*\{([\s\S]*?)\}/);
20
- if (!m)
21
- return null;
22
- let block = `{${m[1]}}`;
23
- block = block.replace(/([,{]\s*)([A-Za-z_][A-Za-z0-9_]*)\s*:/g, '$1"$2":');
24
- block = block.replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, (_, inner) => JSON.stringify(inner));
25
- block = block.replace(/,\s*([}\]])/g, '$1');
26
- return JSON.parse(block);
27
- }
28
- catch {
29
- return null;
30
- }
31
- }
32
- /**
33
- * @param {string} projectRoot
34
- * @param {string} localeId
35
- */
36
- export function loadLocaleCommonMessages(projectRoot, localeId) {
37
- const p = path.join(projectRoot, 'locales', localeId, 'common.json5');
38
- if (!fs.existsSync(p))
39
- return {};
40
- try {
41
- let s = fs.readFileSync(p, 'utf8');
42
- s = s.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
43
- s = s.replace(/([,{]\s*)([A-Za-z_][A-Za-z0-9_]*)\s*:/g, '$1"$2":');
44
- s = s.replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, (_, inner) => JSON.stringify(inner));
45
- s = s.replace(/,\s*([}\]])/g, '$1');
46
- return JSON.parse(s);
47
- }
48
- catch {
49
- return {};
50
- }
51
- }
52
- /**
53
- * @param {string} projectRoot
54
- */
55
- export function readSiteGithubUrl(projectRoot) {
56
- const p = path.join(projectRoot, 'src', 'lib', 'site.ts');
57
- if (!fs.existsSync(p))
58
- return 'https://github.com/voml/iris-orm';
59
- const m = fs.readFileSync(p, 'utf8').match(/githubUrl\s*=\s*["']([^"']+)["']/);
60
- return m?.[1] || 'https://github.com/voml/iris-orm';
61
- }
62
- /**
63
- * @param {string} template
64
- * @param {string} localeId
65
- * @param {Record<string, string>} messages
66
- * @param {{ docsRootHref: string, guideHref: string, githubUrl: string, routing?: { strategy?: string } }} opts
67
- */
68
- export function renderHostChromeTemplate(template, localeId, messages, opts) {
69
- const esc = (s) => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
70
- const bindings = {
71
- brandLabel: messages.brand || 'Iris',
72
- brandFullLabel: `${messages.brand || 'Iris'} ORM`,
73
- navHomeLabel: messages.navHome || 'Home',
74
- navDocsLabel: messages.navDocs || 'Docs',
75
- navPlaygroundLabel: messages.navPlayground || 'Playground',
76
- navGithubLabel: messages.navGithub || 'GitHub',
77
- selectLanguageLabel: messages.selectLanguage || 'Language',
78
- langZhLabel: messages.langZh || '中文',
79
- langEnLabel: messages.langEn || 'English',
80
- footerTagLabel: messages.footerTag || messages.brand || 'Iris',
81
- footerScopeLabel: messages.footerScopeNote || '',
82
- footerCopyrightLabel: messages.footerCopyright || '',
83
- footerGuideLabel: messages.footerGuide || messages.ctaInstall || 'Getting started',
84
- footerColProductLabel: messages.footerColProduct || 'Product',
85
- footerColProjectLabel: messages.footerColProject || 'Project',
86
- ctaInstallLabel: messages.ctaInstall || messages.ctaDocs || 'Docs',
87
- docsRootHref: opts.docsRootHref,
88
- guideHref: opts.guideHref,
89
- githubUrl: opts.githubUrl,
90
- };
91
- let html = template;
92
- html = html.replace(/data-home=\{home \? 'true' : 'false'\}/g, 'data-home="false"');
93
- html = html.replace(/href=\{docsRootHref\}/g, `href="${esc(bindings.docsRootHref)}"`);
94
- html = html.replace(/href=\{guideHref\}/g, `href="${esc(bindings.guideHref)}"`);
95
- html = html.replace(/href=\{githubUrl\}/g, `href="${esc(bindings.githubUrl)}"`);
96
- for (const [key, val] of Object.entries(bindings)) {
97
- html = html.replace(new RegExp(`\\{${key}\\}`, 'g'), esc(String(val)));
98
- }
99
- html = html.replace(/<Link(\s)/g, '<a class="vmz-ui-link"$1');
100
- html = html.replace(/<\/Link>/g, '</a>');
101
- html = html.replace(/<Icon[^>]*\/>/g, '');
102
- html = html.replace(/<div class="locale-switch"[\s\S]*?<\/div>/g, () => {
103
- const zh = `<button type="button" class="locale-switch__btn${localeId === 'zh-hans' ? ' is-active' : ''}" data-vmz-locale-pick="zh-hans"${localeId === 'zh-hans' ? ' aria-current="true"' : ''}>${esc(bindings.langZhLabel)}</button>`;
104
- const en = `<button type="button" class="locale-switch__btn${localeId === 'en-us' ? ' is-active' : ''}" data-vmz-locale-pick="en-us"${localeId === 'en-us' ? ' aria-current="true"' : ''}>${esc(bindings.langEnLabel)}</button>`;
105
- return `<div class="locale-switch" role="group" aria-label="${esc(bindings.selectLanguageLabel)}">${zh}${en}</div>`;
106
- });
107
- html = html.replace(/<Button[\s\S]*?onClick=\{\(\) => this\.switchLocale\('zh-hans'\)\}[\s\S]*?>\s*[\s\S]*?<\/Button>/g, `<button type="button" class="locale-switch__btn${localeId === 'zh-hans' ? ' is-active' : ''}" data-vmz-locale-pick="zh-hans"${localeId === 'zh-hans' ? ' aria-current="true"' : ''}>${esc(bindings.langZhLabel)}</button>`);
108
- html = html.replace(/<Button[\s\S]*?onClick=\{\(\) => this\.switchLocale\('en-us'\)\}[\s\S]*?>\s*[\s\S]*?<\/Button>/g, `<button type="button" class="locale-switch__btn${localeId === 'en-us' ? ' is-active' : ''}" data-vmz-locale-pick="en-us"${localeId === 'en-us' ? ' aria-current="true"' : ''}>${esc(bindings.langEnLabel)}</button>`);
109
- html = html.replace(/<Button[\s\S]*?<\/Button>/g, '');
110
- html = html.replace(/aria-current=\{localeId === '[^']+' \? 'true' : null\}/g, '');
111
- html = html.replace(/aria-label=\{selectLanguageLabel\}/g, `aria-label="${esc(bindings.selectLanguageLabel)}"`);
112
- html = html.replace(/label=\{[^}]+\}/g, '');
113
- return html;
114
- }
115
- /** Inline locale preference picker for strategy `none` (Host state, not URL). */
116
- export function localeNonePickerScript() {
117
- return `<script>(function(){try{document.querySelectorAll("[data-vmz-locale-pick]").forEach(function(btn){btn.addEventListener("click",function(){var id=btn.getAttribute("data-vmz-locale-pick");if(!id)return;try{localStorage.setItem("vmz.locale",id);}catch(e){}try{document.cookie="vmz.locale="+encodeURIComponent(id)+"; path=/; max-age=31536000; SameSite=Lax";}catch(e){}location.reload();});});}catch(e){}})();</script>`;
118
- }
119
- /**
120
- * @param {string} routeBase
121
- * @param {string} pageKey
122
- */
123
- export function docsRouteNone(routeBase, pageKey) {
124
- const base = String(routeBase || '/').replace(/\/$/, '') || '';
125
- const key = pageKey === 'index' ? '' : pageKey.replace(/\\/g, '/');
126
- const parts = [base.replace(/^\//, ''), key].filter((p) => p !== '');
127
- return '/' + (parts.length ? parts.join('/') : '');
128
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * Load the N-API addon or throw (production printers must not fall back to TS).
3
- * @returns {any}
4
- */
5
- export declare function requireNativeAddon(): any;
6
- /**
7
- * @returns {any | null}
8
- */
9
- export declare function tryLoadNativeAddon(): any;
@@ -1,84 +0,0 @@
1
- // @ts-nocheck
2
- /**
3
- * Load the N-API `.node` addon without importing `index.js`
4
- * (avoids cycles with modules re-exported from the package entry).
5
- */
6
- import fs from 'node:fs';
7
- import { createRequire } from 'node:module';
8
- import path from 'node:path';
9
- import { fileURLToPath } from 'node:url';
10
- const require = createRequire(import.meta.url);
11
- /** @type {any} */
12
- let cached;
13
- /**
14
- * Load the N-API addon or throw (production printers must not fall back to TS).
15
- * @returns {any}
16
- */
17
- export function requireNativeAddon() {
18
- const native = tryLoadNativeAddon();
19
- if (!native) {
20
- throw new Error('vmz native addon missing — run `pnpm napi:build` (CodeGenerators live in vmz-generator via N-API)');
21
- }
22
- return native;
23
- }
24
- /**
25
- * @returns {any | null}
26
- */
27
- export function tryLoadNativeAddon() {
28
- if (cached !== undefined)
29
- return cached;
30
- try {
31
- const envPath = (typeof process.env.VMZ_NATIVE_NODE === 'string' && process.env.VMZ_NATIVE_NODE.trim()) || '';
32
- if (envPath) {
33
- cached = require(path.resolve(envPath));
34
- return cached;
35
- }
36
- const { platform, arch } = process;
37
- let triple = `${platform}-${arch}`;
38
- if (platform === 'win32' && arch === 'x64')
39
- triple = 'win32-x64-msvc';
40
- else if (platform === 'win32' && arch === 'arm64')
41
- triple = 'win32-arm64-msvc';
42
- else if (platform === 'darwin' && arch === 'arm64')
43
- triple = 'darwin-arm64';
44
- else if (platform === 'darwin' && arch === 'x64')
45
- triple = 'darwin-x64';
46
- else if (platform === 'linux' && arch === 'x64')
47
- triple = 'linux-x64-gnu';
48
- else if (platform === 'linux' && arch === 'arm64')
49
- triple = 'linux-arm64-gnu';
50
- const short = triple === 'win32-x64-msvc'
51
- ? 'win32-x64'
52
- : triple === 'win32-arm64-msvc'
53
- ? 'win32-arm64'
54
- : triple === 'linux-x64-gnu'
55
- ? 'linux-x64'
56
- : triple === 'linux-arm64-gnu'
57
- ? 'linux-arm64'
58
- : triple;
59
- const pkgRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
60
- const name = `@vmz/vmz-${short}`;
61
- /** @type {string[]} */
62
- const candidates = [];
63
- try {
64
- const resolved = require.resolve(`${name}/package.json`);
65
- const dir = path.dirname(resolved);
66
- candidates.push(path.join(dir, `vmz.${triple}.node`), path.join(dir, 'vmz.node'));
67
- }
68
- catch {
69
- /* optional */
70
- }
71
- candidates.push(path.join(pkgRoot, 'node_modules', name, `vmz.${triple}.node`), path.join(pkgRoot, 'node_modules', name, 'vmz.node'));
72
- for (const p of candidates) {
73
- if (fs.existsSync(p)) {
74
- cached = require(p);
75
- return cached;
76
- }
77
- }
78
- cached = null;
79
- }
80
- catch {
81
- cached = null;
82
- }
83
- return cached;
84
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * Pretty-print a value through `vmz-generator` (N-API).
3
- * @param {unknown} value
4
- * @returns {string} Pretty JSON without trailing newline.
5
- */
6
- export declare function generatePrettyJson(value: any): any;
7
- /**
8
- * Write a pretty JSON artifact with a trailing newline.
9
- * @param {string} filePath
10
- * @param {unknown} value
11
- */
12
- export declare function writePrettyJsonFile(filePath: any, value: any): void;
13
- /**
14
- * CLI `--json` helper: write to a path when `target` is a string, else stdout.
15
- * @param {string | boolean | undefined} target
16
- * @param {unknown} value
17
- * @param {{ logWrote?: (path: string) => void }} [opts]
18
- */
19
- export declare function emitPrettyJson(target: any, value: any, opts?: {}): void;
@@ -1,43 +0,0 @@
1
- // @ts-nocheck
2
- /**
3
- * Production JSON artifact printer — always via N-API JsonCodeGenerator.
4
- * Do not use `JSON.stringify(x, null, 2)` for on-disk artifacts.
5
- */
6
- import fs from 'node:fs';
7
- import { requireNativeAddon } from './native-addon.js';
8
- /**
9
- * Pretty-print a value through `vmz-generator` (N-API).
10
- * @param {unknown} value
11
- * @returns {string} Pretty JSON without trailing newline.
12
- */
13
- export function generatePrettyJson(value) {
14
- const native = requireNativeAddon();
15
- if (typeof native.generatePrettyJson !== 'function') {
16
- throw new Error('vmz native addon missing generatePrettyJson — rebuild with `pnpm napi:build`');
17
- }
18
- return native.generatePrettyJson(JSON.stringify(value));
19
- }
20
- /**
21
- * Write a pretty JSON artifact with a trailing newline.
22
- * @param {string} filePath
23
- * @param {unknown} value
24
- */
25
- export function writePrettyJsonFile(filePath, value) {
26
- fs.writeFileSync(filePath, `${generatePrettyJson(value)}\n`, 'utf8');
27
- }
28
- /**
29
- * CLI `--json` helper: write to a path when `target` is a string, else stdout.
30
- * @param {string | boolean | undefined} target
31
- * @param {unknown} value
32
- * @param {{ logWrote?: (path: string) => void }} [opts]
33
- */
34
- export function emitPrettyJson(target, value, opts = {}) {
35
- const text = generatePrettyJson(value);
36
- if (typeof target === 'string') {
37
- fs.writeFileSync(target, `${text}\n`, 'utf8');
38
- if (typeof opts.logWrote === 'function')
39
- opts.logWrote(target);
40
- return;
41
- }
42
- console.log(text);
43
- }