@vmz/vmz 0.3.11 → 0.3.12
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/workspace/cdn-policy.js +12 -0
- package/dist/workspace/pack-client-packages.d.ts +4 -2
- package/dist/workspace/pack-client-packages.js +116 -3
- package/dist/workspace/pack.d.ts +7 -1
- package/dist/workspace/pack.js +14 -2
- package/dist/workspace/plugin-host.js +3 -6
- package/package.json +20 -20
|
@@ -396,6 +396,18 @@ function contentType(file) {
|
|
|
396
396
|
return 'text/javascript; charset=utf-8';
|
|
397
397
|
if (file.endsWith('.css'))
|
|
398
398
|
return 'text/css; charset=utf-8';
|
|
399
|
+
if (file.endsWith('.wasm'))
|
|
400
|
+
return 'application/wasm';
|
|
401
|
+
if (file.endsWith('.woff2'))
|
|
402
|
+
return 'font/woff2';
|
|
403
|
+
if (file.endsWith('.woff'))
|
|
404
|
+
return 'font/woff';
|
|
405
|
+
if (file.endsWith('.otf'))
|
|
406
|
+
return 'font/otf';
|
|
407
|
+
if (file.endsWith('.ttf'))
|
|
408
|
+
return 'font/ttf';
|
|
409
|
+
if (file.endsWith('.svg'))
|
|
410
|
+
return 'image/svg+xml';
|
|
399
411
|
if (file.endsWith('.xml'))
|
|
400
412
|
return 'application/xml';
|
|
401
413
|
if (file.endsWith('.txt'))
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* via a bounded rewrite of generated module syntax. Pack must not re-enter the
|
|
8
8
|
* parser pipeline for every emitted JavaScript file.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* This stage is only that thin slice. Linking, dead-code elimination, chunk
|
|
11
|
+
* splitting, and minification are NOT implemented here — the pack manifest
|
|
12
|
+
* reports their absence rather than a placeholder backend.
|
|
11
13
|
*/
|
|
12
14
|
/**
|
|
13
15
|
* @param {string} outDir
|
|
@@ -27,6 +29,6 @@ export declare function packClientBareImports(outDir: string, opts?: PackClientB
|
|
|
27
29
|
};
|
|
28
30
|
/** @param {string} js */
|
|
29
31
|
export declare function collectBareSpecs(js: any): unknown[];
|
|
30
|
-
/**
|
|
32
|
+
/** Native (N-API) module specifier rewrite (`.ts`→`.js` + optional exact map). */
|
|
31
33
|
export declare function rewriteRelativeTsSpecs(js: any, exactMap?: any): any;
|
|
32
34
|
export {};
|
|
@@ -7,15 +7,22 @@
|
|
|
7
7
|
* via a bounded rewrite of generated module syntax. Pack must not re-enter the
|
|
8
8
|
* parser pipeline for every emitted JavaScript file.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* This stage is only that thin slice. Linking, dead-code elimination, chunk
|
|
11
|
+
* splitting, and minification are NOT implemented here — the pack manifest
|
|
12
|
+
* reports their absence rather than a placeholder backend.
|
|
11
13
|
*/
|
|
12
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from 'node:fs';
|
|
14
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from 'node:fs';
|
|
13
15
|
import path from 'node:path';
|
|
14
16
|
import { createRequire } from 'node:module';
|
|
15
17
|
import { resolvePackageRoot } from './packages.js';
|
|
16
18
|
import { requireNativeAddon } from './native-addon.js';
|
|
17
19
|
const VENDOR_DIR = 'vendor';
|
|
18
20
|
const SKIP_PREFIXES = ['node:', 'nodejs:', 'cloudflare:', 'data:', 'http:', 'https:', 'vmz:', '#'];
|
|
21
|
+
const STYLE_EXT = /\.css$/i;
|
|
22
|
+
/** `new URL('<file>', import.meta.url)` — runtime assets a vendored module loads itself. */
|
|
23
|
+
const IMPORT_META_URL_RE = /\bnew\s+URL\s*\(\s*(['"])([^'"\n]+)\1\s*,\s*import\.meta\.url\s*\)/g;
|
|
24
|
+
/** `url(<file>)` inside a vendored stylesheet. */
|
|
25
|
+
const CSS_URL_RE = /\burl\s*\(\s*(['"]?)([^'")\n]+)\1\s*\)/g;
|
|
19
26
|
export function packClientBareImports(outDir, opts = {}) {
|
|
20
27
|
const projectRoot = opts.projectRoot ? path.resolve(opts.projectRoot) : path.dirname(path.resolve(outDir));
|
|
21
28
|
/** @type {Map<string, string>} bareSpec → absolute vendored .js path */
|
|
@@ -49,6 +56,16 @@ export function packClientBareImports(outDir, opts = {}) {
|
|
|
49
56
|
skippedVmz.push(spec);
|
|
50
57
|
continue;
|
|
51
58
|
}
|
|
59
|
+
// Stylesheets are not browser modules: materialize the CSS (plus its
|
|
60
|
+
// `url()` assets) and expose a loader module that links it once.
|
|
61
|
+
if (STYLE_EXT.test(resolved.sourceFile)) {
|
|
62
|
+
const styleDest = vendorPathForSource(outDir, resolved.pkgName, resolved.pkgRoot, resolved.sourceFile);
|
|
63
|
+
materializeStyleFile(resolved.sourceFile, styleDest);
|
|
64
|
+
const loaderDest = `${styleDest}.js`;
|
|
65
|
+
writeFileSync(loaderDest, styleLoaderSource(path.basename(styleDest)), 'utf8');
|
|
66
|
+
bareToVendor.set(spec, loaderDest);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
52
69
|
const destAbs = materializeSourceTree(outDir, resolved, materializedSources, bareQueue);
|
|
53
70
|
if (destAbs)
|
|
54
71
|
bareToVendor.set(spec, destAbs);
|
|
@@ -109,6 +126,7 @@ function materializeSourceTree(outDir, resolved, materializedSources, bareQueue)
|
|
|
109
126
|
mkdirSync(path.dirname(destAbs), { recursive: true });
|
|
110
127
|
const js = materializeModule(sourceFile);
|
|
111
128
|
writeFileSync(destAbs, js, 'utf8');
|
|
129
|
+
materializeRuntimeAssets(sourceFile, destAbs, js);
|
|
112
130
|
if (sourceFile === resolved.sourceFile)
|
|
113
131
|
entryDest = destAbs;
|
|
114
132
|
for (const bare of collectBareSpecs(js))
|
|
@@ -272,6 +290,8 @@ function resolveExportFile(pkgRoot, subpath) {
|
|
|
272
290
|
if (pkg.exports && typeof pkg.exports === 'object' && !Array.isArray(pkg.exports)) {
|
|
273
291
|
const entry = pkg.exports[key] ?? (!subpath ? pkg.exports['.'] : null);
|
|
274
292
|
target = flattenExportTarget(entry);
|
|
293
|
+
if (!target && subpath)
|
|
294
|
+
target = matchWildcardExport(pkg.exports, key);
|
|
275
295
|
}
|
|
276
296
|
if (!target && !subpath)
|
|
277
297
|
target = pkg.module || pkg.main || './index.js';
|
|
@@ -301,6 +321,29 @@ function resolveExportFile(pkgRoot, subpath) {
|
|
|
301
321
|
}
|
|
302
322
|
return null;
|
|
303
323
|
}
|
|
324
|
+
/** Longest-prefix `./*` / `./js/*` style export match for a subpath key. */
|
|
325
|
+
function matchWildcardExport(exportsMap, key) {
|
|
326
|
+
let best = null;
|
|
327
|
+
let bestPrefix = -1;
|
|
328
|
+
for (const [pattern, entry] of Object.entries(exportsMap)) {
|
|
329
|
+
const star = pattern.indexOf('*');
|
|
330
|
+
if (star < 0)
|
|
331
|
+
continue;
|
|
332
|
+
const prefix = pattern.slice(0, star);
|
|
333
|
+
const suffix = pattern.slice(star + 1);
|
|
334
|
+
if (!key.startsWith(prefix) || !key.endsWith(suffix))
|
|
335
|
+
continue;
|
|
336
|
+
const target = flattenExportTarget(entry);
|
|
337
|
+
if (typeof target !== 'string')
|
|
338
|
+
continue;
|
|
339
|
+
const middle = key.slice(prefix.length, key.length - suffix.length);
|
|
340
|
+
if (prefix.length > bestPrefix) {
|
|
341
|
+
best = target.replace('*', middle);
|
|
342
|
+
bestPrefix = prefix.length;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return best;
|
|
346
|
+
}
|
|
304
347
|
function flattenExportTarget(entry) {
|
|
305
348
|
if (typeof entry === 'string')
|
|
306
349
|
return entry;
|
|
@@ -338,6 +381,76 @@ function materializeModule(sourceFile) {
|
|
|
338
381
|
throw new Error(`pack source ${sourceFile}: ${error instanceof Error ? error.message : String(error)}`);
|
|
339
382
|
}
|
|
340
383
|
}
|
|
384
|
+
function isLocalAssetRef(ref) {
|
|
385
|
+
const value = ref.trim();
|
|
386
|
+
if (!value)
|
|
387
|
+
return false;
|
|
388
|
+
if (value.startsWith('/') || value.startsWith('\\') || value.startsWith('#'))
|
|
389
|
+
return false;
|
|
390
|
+
return !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(value);
|
|
391
|
+
}
|
|
392
|
+
function copyVendoredAsset(fromDir, destDir, ref) {
|
|
393
|
+
const cleaned = ref.replace(/[?#].*$/, '');
|
|
394
|
+
if (!isLocalAssetRef(cleaned))
|
|
395
|
+
return;
|
|
396
|
+
const source = path.resolve(fromDir, cleaned);
|
|
397
|
+
let stat;
|
|
398
|
+
try {
|
|
399
|
+
stat = statSync(source);
|
|
400
|
+
}
|
|
401
|
+
catch {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (!stat.isFile())
|
|
405
|
+
return;
|
|
406
|
+
const dest = path.resolve(destDir, cleaned);
|
|
407
|
+
mkdirSync(path.dirname(dest), { recursive: true });
|
|
408
|
+
copyFileSync(source, dest);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Copy files a vendored module loads by URL at runtime (`new URL(…, import.meta.url)`),
|
|
412
|
+
* so `.wasm`, `.json` payloads, … stay reachable next to their module.
|
|
413
|
+
*/
|
|
414
|
+
function materializeRuntimeAssets(sourceFile, destAbs, js) {
|
|
415
|
+
IMPORT_META_URL_RE.lastIndex = 0;
|
|
416
|
+
let match;
|
|
417
|
+
while ((match = IMPORT_META_URL_RE.exec(js))) {
|
|
418
|
+
copyVendoredAsset(path.dirname(sourceFile), path.dirname(destAbs), match[2]);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/** Copy a stylesheet and everything its `url()` references. */
|
|
422
|
+
function materializeStyleFile(sourceFile, destAbs) {
|
|
423
|
+
const css = readFileSync(sourceFile, 'utf8');
|
|
424
|
+
mkdirSync(path.dirname(destAbs), { recursive: true });
|
|
425
|
+
writeFileSync(destAbs, css, 'utf8');
|
|
426
|
+
CSS_URL_RE.lastIndex = 0;
|
|
427
|
+
let match;
|
|
428
|
+
while ((match = CSS_URL_RE.exec(css))) {
|
|
429
|
+
copyVendoredAsset(path.dirname(sourceFile), path.dirname(destAbs), match[2]);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Loader module for a vendored stylesheet: links it once and exposes the load
|
|
434
|
+
* promise as the default export.
|
|
435
|
+
*/
|
|
436
|
+
function styleLoaderSource(fileName) {
|
|
437
|
+
return `const href = new URL(${JSON.stringify(`./${fileName}`)}, import.meta.url).href;
|
|
438
|
+
const ready =
|
|
439
|
+
typeof document === 'undefined'
|
|
440
|
+
? Promise.resolve()
|
|
441
|
+
: Array.from(document.querySelectorAll('link[rel="stylesheet"]')).some((el) => el.href === href)
|
|
442
|
+
? Promise.resolve()
|
|
443
|
+
: new Promise((resolve, reject) => {
|
|
444
|
+
const link = document.createElement('link');
|
|
445
|
+
link.rel = 'stylesheet';
|
|
446
|
+
link.href = href;
|
|
447
|
+
link.onload = () => resolve();
|
|
448
|
+
link.onerror = () => reject(new Error('VMZ stylesheet failed to load: ' + href));
|
|
449
|
+
document.head.appendChild(link);
|
|
450
|
+
});
|
|
451
|
+
export default ready;
|
|
452
|
+
`;
|
|
453
|
+
}
|
|
341
454
|
function transpileTs(source, filename) {
|
|
342
455
|
try {
|
|
343
456
|
const require = createRequire(import.meta.url);
|
|
@@ -365,7 +478,7 @@ function rewriteTsExt(p) {
|
|
|
365
478
|
.replace(/\.tsx$/i, '.js')
|
|
366
479
|
.replace(/\.ts$/i, '.js');
|
|
367
480
|
}
|
|
368
|
-
/**
|
|
481
|
+
/** Native (N-API) module specifier rewrite (`.ts`→`.js` + optional exact map). */
|
|
369
482
|
export function rewriteRelativeTsSpecs(js, exactMap = null) {
|
|
370
483
|
const source = String(js ?? '');
|
|
371
484
|
const hasModuleTsSpecifier = /(?:import\s*(?:[^'"()]*?\s*from\s*)?|export\s+[^'"()]*?\s*from\s*|import\s*\()(['"])[^'"\r\n]+\.tsx?\1/i.test(source);
|
package/dist/workspace/pack.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pack stage: consume Deployment IR (VPG-owned units), emit pack manifest,
|
|
3
3
|
* and lower browser-unreachable bare package imports to `dist/vendor/**`.
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Current status: a thin module-moving slice — reachable module closure
|
|
6
|
+
* materialization, specifier rewriting, and TypeScript `transpileModule` type
|
|
7
|
+
* erasure. Linking, dead-code elimination, chunk splitting, and minification
|
|
8
|
+
* are NOT implemented in this stage; the manifest reports that honestly.
|
|
9
|
+
* (Any compaction of compile-emitted modules happens upstream in the compiler,
|
|
10
|
+
* not here — pack never rewrites bytes beyond specifier lowering.)
|
|
5
11
|
*/
|
|
6
12
|
export declare const PACK_MANIFEST_SCHEMA = "vmz.pack.manifest.v0";
|
|
7
13
|
/**
|
package/dist/workspace/pack.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pack stage: consume Deployment IR (VPG-owned units), emit pack manifest,
|
|
3
3
|
* and lower browser-unreachable bare package imports to `dist/vendor/**`.
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Current status: a thin module-moving slice — reachable module closure
|
|
6
|
+
* materialization, specifier rewriting, and TypeScript `transpileModule` type
|
|
7
|
+
* erasure. Linking, dead-code elimination, chunk splitting, and minification
|
|
8
|
+
* are NOT implemented in this stage; the manifest reports that honestly.
|
|
9
|
+
* (Any compaction of compile-emitted modules happens upstream in the compiler,
|
|
10
|
+
* not here — pack never rewrites bytes beyond specifier lowering.)
|
|
5
11
|
*/
|
|
6
12
|
import crypto from 'node:crypto';
|
|
7
13
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
@@ -75,7 +81,13 @@ export function packFromDeploymentIr(outDir, opts = {}) {
|
|
|
75
81
|
deploymentSchema: ir.schema,
|
|
76
82
|
unitCount: units.length,
|
|
77
83
|
units,
|
|
78
|
-
|
|
84
|
+
// Pack runs no compressor in either mode: it reports the bytes it was
|
|
85
|
+
// given (dev output written verbatim). Release artifacts may already be
|
|
86
|
+
// compacted by the compiler's release print path upstream — pack does not
|
|
87
|
+
// claim, add, or verify that compaction.
|
|
88
|
+
minify: opts.release ? 'none' : 'dev-identity',
|
|
89
|
+
// Names how VPG deployment units are selected for this manifest. It does
|
|
90
|
+
// NOT mean JavaScript dead-code elimination ran — that is not implemented.
|
|
79
91
|
treeShakeBasis: 'vpg-deployment-ir',
|
|
80
92
|
bundler: 'vmz-pack',
|
|
81
93
|
clientPackageLowering: {
|
|
@@ -322,13 +322,12 @@ function buildMathFacade(defaultEngine, engines) {
|
|
|
322
322
|
const tag = engineToTag(eng);
|
|
323
323
|
const kw = i === 0 ? 'v-if' : 'v-else-if';
|
|
324
324
|
const engLit = jsSingleQuoted(eng);
|
|
325
|
-
return `
|
|
325
|
+
return ` <${tag} ${kw}="(engine || ${defaultLit}) === ${engLit}" :tex="tex" :display="display" />`;
|
|
326
326
|
})
|
|
327
327
|
.join('\n');
|
|
328
328
|
return `<template>
|
|
329
329
|
${branches}
|
|
330
330
|
</template>
|
|
331
|
-
|
|
332
331
|
<script client>
|
|
333
332
|
export default class Math {
|
|
334
333
|
public tex: string = '';
|
|
@@ -349,13 +348,12 @@ function buildCodeFacade(defaultEngine, engines) {
|
|
|
349
348
|
const tag = engineToTag(eng);
|
|
350
349
|
const kw = i === 0 ? 'v-if' : 'v-else-if';
|
|
351
350
|
const engLit = jsSingleQuoted(eng);
|
|
352
|
-
return `
|
|
351
|
+
return ` <${tag} ${kw}="(engine || ${defaultLit}) === ${engLit}" :code="code" :lang="lang" :theme="theme" />`;
|
|
353
352
|
})
|
|
354
353
|
.join('\n');
|
|
355
354
|
return `<template>
|
|
356
355
|
${branches}
|
|
357
356
|
</template>
|
|
358
|
-
|
|
359
357
|
<script client>
|
|
360
358
|
export default class Code {
|
|
361
359
|
public code: string = '';
|
|
@@ -377,13 +375,12 @@ function buildMarkdownFacade(defaultEngine, engines) {
|
|
|
377
375
|
const tag = engineToTag(eng);
|
|
378
376
|
const kw = i === 0 ? 'v-if' : 'v-else-if';
|
|
379
377
|
const engLit = jsSingleQuoted(eng);
|
|
380
|
-
return `
|
|
378
|
+
return ` <${tag} ${kw}="(engine || ${defaultLit}) === ${engLit}" :source="source" />`;
|
|
381
379
|
})
|
|
382
380
|
.join('\n');
|
|
383
381
|
return `<template>
|
|
384
382
|
${branches}
|
|
385
383
|
</template>
|
|
386
|
-
|
|
387
384
|
<script client>
|
|
388
385
|
export default class Markdown {
|
|
389
386
|
public source: string = '';
|
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
|
-
"@vmz/core": "0.3.
|
|
8
|
-
"@vmz/diagnostic": "0.3.
|
|
9
|
-
"@vmz/plugin": "0.3.
|
|
10
|
-
"@vmz/protocol": "0.3.
|
|
6
|
+
"@vmz/commander": "0.3.12",
|
|
7
|
+
"@vmz/core": "0.3.12",
|
|
8
|
+
"@vmz/diagnostic": "0.3.12",
|
|
9
|
+
"@vmz/plugin": "0.3.12",
|
|
10
|
+
"@vmz/protocol": "0.3.12"
|
|
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.
|
|
16
|
-
"@vmz/plugin-katex": "0.3.
|
|
17
|
-
"@vmz/plugin-markdown-it": "0.3.
|
|
18
|
-
"@vmz/plugin-shiki": "0.3.
|
|
19
|
-
"@vmz/test": "0.3.
|
|
15
|
+
"@vmz/plugin": "0.3.12",
|
|
16
|
+
"@vmz/plugin-katex": "0.3.12",
|
|
17
|
+
"@vmz/plugin-markdown-it": "0.3.12",
|
|
18
|
+
"@vmz/plugin-shiki": "0.3.12",
|
|
19
|
+
"@vmz/test": "0.3.12",
|
|
20
20
|
"linkedom": "^0.18.13",
|
|
21
21
|
"typescript": "^5.8.3",
|
|
22
|
-
"vmz-plugin-conformance": "0.3.
|
|
22
|
+
"vmz-plugin-conformance": "0.3.12"
|
|
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.
|
|
84
|
-
"@vmz/vmz-darwin-x64": "0.3.
|
|
85
|
-
"@vmz/vmz-linux-arm64": "0.3.
|
|
86
|
-
"@vmz/vmz-linux-x64": "0.3.
|
|
87
|
-
"@vmz/vmz-win32-arm64": "0.3.
|
|
88
|
-
"@vmz/vmz-win32-x64": "0.3.
|
|
83
|
+
"@vmz/vmz-darwin-arm64": "0.3.12",
|
|
84
|
+
"@vmz/vmz-darwin-x64": "0.3.12",
|
|
85
|
+
"@vmz/vmz-linux-arm64": "0.3.12",
|
|
86
|
+
"@vmz/vmz-linux-x64": "0.3.12",
|
|
87
|
+
"@vmz/vmz-win32-arm64": "0.3.12",
|
|
88
|
+
"@vmz/vmz-win32-x64": "0.3.12"
|
|
89
89
|
},
|
|
90
90
|
"peerDependencies": {
|
|
91
|
-
"@vmz/plugin-markdown-it": "0.3.
|
|
92
|
-
"@vmz/test": "0.3.
|
|
91
|
+
"@vmz/plugin-markdown-it": "0.3.12",
|
|
92
|
+
"@vmz/test": "0.3.12",
|
|
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.
|
|
125
|
+
"version": "0.3.12"
|
|
126
126
|
}
|