@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.
- package/dist/build-assemble.js +3 -4
- package/dist/cdn-policy.js +4 -5
- package/dist/cli.js +15 -50
- package/dist/content-addressed-assets.d.ts +2 -8
- package/dist/content-addressed-assets.js +34 -110
- package/dist/delivery-profile.d.ts +1 -11
- package/dist/delivery-profile.js +1 -70
- package/dist/dev-session.d.ts +0 -1
- package/dist/dev-session.js +64 -220
- package/dist/document-build.js +34 -61
- package/dist/document-cmd.js +9 -2
- package/dist/document-enrich.d.ts +1 -2
- package/dist/document-enrich.js +4 -15
- package/dist/document-integrate.js +21 -28
- package/dist/embedded-packaging.js +1 -2
- package/dist/index.d.ts +1 -15
- package/dist/index.js +3 -58
- package/dist/locale-check.js +61 -28
- package/dist/locale-cmd.js +42 -10
- package/dist/locale-route-emit.d.ts +1 -4
- package/dist/locale-route-emit.js +32 -7
- package/dist/locale-router.js +8 -26
- package/dist/pack.js +2 -3
- package/dist/production-observability.js +2 -3
- package/dist/production-test-pack.js +3 -4
- package/dist/release-pack.js +18 -5
- package/dist/server-artifact.js +3 -4
- package/dist/site-delivery.js +3 -4
- package/dist/static-emit.js +78 -116
- package/dist/test-cmd.js +1 -2
- package/package.json +12 -12
- package/dist/dev-watch-roots.d.ts +0 -67
- package/dist/dev-watch-roots.js +0 -220
- package/dist/document-host-chrome.d.ts +0 -28
- package/dist/document-host-chrome.js +0 -128
- package/dist/native-addon.d.ts +0 -9
- package/dist/native-addon.js +0 -84
- package/dist/pretty-json.d.ts +0 -19
- package/dist/pretty-json.js +0 -43
- package/dist/route-path.d.ts +0 -35
- package/dist/route-path.js +0 -77
- package/dist/wechat-packaging.d.ts +0 -22
- 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.
|
|
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.
|
|
52
|
-
"@vmz/plugin": "0.1.
|
|
53
|
-
"@vmz/protocol": "0.1.
|
|
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.
|
|
59
|
-
"@vmz/test": "0.1.
|
|
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.
|
|
94
|
-
"@vmz/vmz-win32-arm64": "0.1.
|
|
95
|
-
"@vmz/vmz-darwin-x64": "0.1.
|
|
96
|
-
"@vmz/vmz-darwin-arm64": "0.1.
|
|
97
|
-
"@vmz/vmz-linux-x64": "0.1.
|
|
98
|
-
"@vmz/vmz-linux-arm64": "0.1.
|
|
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;
|
package/dist/dev-watch-roots.js
DELETED
|
@@ -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, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
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
|
-
}
|
package/dist/native-addon.d.ts
DELETED
package/dist/native-addon.js
DELETED
|
@@ -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
|
-
}
|
package/dist/pretty-json.d.ts
DELETED
|
@@ -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;
|
package/dist/pretty-json.js
DELETED
|
@@ -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
|
-
}
|