@animus-ui/extract 0.1.3 → 0.1.5
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/crates/extract-v2/animus-extract-v2.darwin-arm64.node +0 -0
- package/crates/extract-v2/animus-extract-v2.linux-arm64-gnu.node +0 -0
- package/crates/extract-v2/animus-extract-v2.linux-x64-gnu.node +0 -0
- package/crates/extract-v2/index.d.ts +14 -0
- package/dist/analyze-project-args.d.ts +6 -2
- package/dist/analyze-project-args.d.ts.map +1 -1
- package/dist/asset-placeholders.d.ts +29 -0
- package/dist/asset-placeholders.d.ts.map +1 -0
- package/dist/content-hash.d.ts +5 -3
- package/dist/content-hash.d.ts.map +1 -1
- package/dist/correlate-external-tokens.d.ts +46 -0
- package/dist/correlate-external-tokens.d.ts.map +1 -0
- package/dist/discover-packages.d.ts +32 -8
- package/dist/discover-packages.d.ts.map +1 -1
- package/dist/dynamic-prop-config.d.ts +21 -7
- package/dist/dynamic-prop-config.d.ts.map +1 -1
- package/dist/engine-adapter.d.ts +1 -1
- package/dist/engine-adapter.d.ts.map +1 -1
- package/dist/index.cjs +505 -38
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +506 -45
- package/dist/manifest-diagnostics.d.ts +3 -0
- package/dist/manifest-diagnostics.d.ts.map +1 -1
- package/dist/resolve-asset.d.ts +14 -0
- package/dist/resolve-asset.d.ts.map +1 -0
- package/dist/run-analysis.d.ts +2 -0
- package/dist/run-analysis.d.ts.map +1 -1
- package/dist/system-config.d.ts +5 -0
- package/dist/system-config.d.ts.map +1 -1
- package/dist/system-props-module.d.ts +4 -0
- package/dist/system-props-module.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
let crypto = require("crypto");
|
|
25
25
|
let fs = require("fs");
|
|
26
26
|
let path = require("path");
|
|
27
|
+
let module$1 = require("module");
|
|
27
28
|
let browserslist = require("browserslist");
|
|
28
29
|
browserslist = __toESM(browserslist);
|
|
29
30
|
let lightningcss = require("lightningcss");
|
|
@@ -121,7 +122,8 @@ function buildAnalyzeProjectArgs(inputs) {
|
|
|
121
122
|
inputs.pathAliasesJson,
|
|
122
123
|
inputs.keyframesJson,
|
|
123
124
|
inputs.staticCssJson,
|
|
124
|
-
inputs.conditionAliasesJson
|
|
125
|
+
inputs.conditionAliasesJson,
|
|
126
|
+
inputs.externalDirsJson
|
|
125
127
|
];
|
|
126
128
|
}
|
|
127
129
|
//#endregion
|
|
@@ -139,7 +141,7 @@ function createV2EngineApi(deps) {
|
|
|
139
141
|
const native = loadNativeEngine();
|
|
140
142
|
return {
|
|
141
143
|
loadSystemModule: (...args) => native.loadSystemModule(...args),
|
|
142
|
-
analyzeProject: (filesJsonRaw, scalesJson, variableMapJson, contextualVarsJson, propConfigJson, groupRegistryJson, packageResolutionJson, devMode, emitterConfigJson, selectorAliasesJson, _selectorOrderJson, globalStyleBlocksJson, pathAliasesJson, keyframesJson, staticCssJson, conditionAliasesJson) => {
|
|
144
|
+
analyzeProject: (filesJsonRaw, scalesJson, variableMapJson, contextualVarsJson, propConfigJson, groupRegistryJson, packageResolutionJson, devMode, emitterConfigJson, selectorAliasesJson, _selectorOrderJson, globalStyleBlocksJson, pathAliasesJson, keyframesJson, staticCssJson, conditionAliasesJson, externalDirsJson) => {
|
|
143
145
|
const filesJson = deps.rehydrateFilesJson ? deps.rehydrateFilesJson(filesJsonRaw) : filesJsonRaw;
|
|
144
146
|
const sent = /* @__PURE__ */ new Map();
|
|
145
147
|
for (const entry of JSON.parse(filesJson)) sent.set(entry.path, entry.source);
|
|
@@ -162,6 +164,7 @@ function createV2EngineApi(deps) {
|
|
|
162
164
|
packageResolutionJson: packageResolutionJson ?? void 0,
|
|
163
165
|
pathAliasesJson: pathAliasesJson ?? void 0,
|
|
164
166
|
staticCssJson: staticCssJson ?? void 0,
|
|
167
|
+
externalDirsJson: externalDirsJson ?? void 0,
|
|
165
168
|
devMode
|
|
166
169
|
};
|
|
167
170
|
const engine = new native.ExtractEngine(config);
|
|
@@ -220,8 +223,10 @@ function assertNoRetiredEngineSelection(engineOption) {
|
|
|
220
223
|
//#region pipeline/content-hash.ts
|
|
221
224
|
/**
|
|
222
225
|
* MD5 content hash used for file-change detection (HMR diffing) by both
|
|
223
|
-
* extraction plugins
|
|
224
|
-
* cache keys written by one
|
|
226
|
+
* extraction plugins, and for content-addressing copied asset bytes. The
|
|
227
|
+
* algorithm/encoding is a cross-plugin contract: cache keys written by one
|
|
228
|
+
* build path must compare equal in the next. Accepts a Buffer directly so
|
|
229
|
+
* binary sources hash without an intermediate string copy.
|
|
225
230
|
*/
|
|
226
231
|
function contentHash(source) {
|
|
227
232
|
return (0, crypto.createHash)("md5").update(source).digest("hex");
|
|
@@ -284,6 +289,14 @@ const PACKAGE_SRC_EXCLUDES = [
|
|
|
284
289
|
".test.",
|
|
285
290
|
".spec."
|
|
286
291
|
];
|
|
292
|
+
/** Exclusions for the compiled-output fallback when a package does not ship src/. */
|
|
293
|
+
const PACKAGE_OUTPUT_EXCLUDES = [
|
|
294
|
+
"node_modules",
|
|
295
|
+
".test.",
|
|
296
|
+
".spec.",
|
|
297
|
+
".d.ts",
|
|
298
|
+
".map"
|
|
299
|
+
];
|
|
287
300
|
const isFile = (path$2) => {
|
|
288
301
|
try {
|
|
289
302
|
return (0, fs.statSync)(path$2).isFile();
|
|
@@ -305,6 +318,42 @@ function resolveAbsolutePathSpecifier(absSpecifier, extensionsSet) {
|
|
|
305
318
|
...Array.from(extensionsSet, (ext) => (0, path.join)(absSpecifier, `index${ext}`))
|
|
306
319
|
].find(isFile) ?? null;
|
|
307
320
|
}
|
|
321
|
+
/** The package-name half of a bare specifier (`@scope/name/sub` → `@scope/name`). */
|
|
322
|
+
function bareSpecifierPackageName(specifier) {
|
|
323
|
+
const segments = specifier.split("/");
|
|
324
|
+
return specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
|
|
325
|
+
}
|
|
326
|
+
function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
|
|
327
|
+
if ((0, path.isAbsolute)(specifier)) {
|
|
328
|
+
const resolved = resolveAbsolutePathSpecifier(specifier, extensionsSet);
|
|
329
|
+
if (!resolved) return null;
|
|
330
|
+
return !(0, path.relative)(srcDir, resolved).startsWith("..") ? resolved : null;
|
|
331
|
+
}
|
|
332
|
+
const packageName = bareSpecifierPackageName(specifier);
|
|
333
|
+
return resolveAbsolutePathSpecifier((0, path.join)(srcDir, specifier.slice(packageName.length + 1) || "index"), extensionsSet);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* The D13 dist-freshness check: applicable only when a specifier has BOTH a
|
|
337
|
+
* walked src/ tree and a resolved dist entry that exists on disk outside that
|
|
338
|
+
* tree; stale when the dist entry's mtime is older than the newest walked
|
|
339
|
+
* source file's. Not applicable (never stale) when the entry resolves inside
|
|
340
|
+
* src/ (no dist to skew), when the entry file is missing, or when no source
|
|
341
|
+
* file's mtime is readable. Detection only — reporting is the caller's policy.
|
|
342
|
+
*/
|
|
343
|
+
function distEntryIsStale(absEntry, srcDir, srcFiles) {
|
|
344
|
+
if (!(0, path.relative)(srcDir, absEntry).startsWith("..")) return false;
|
|
345
|
+
let distMtime;
|
|
346
|
+
try {
|
|
347
|
+
distMtime = (0, fs.statSync)(absEntry).mtimeMs;
|
|
348
|
+
} catch {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
let newestSrcMtime = -Infinity;
|
|
352
|
+
for (const srcFile of srcFiles) try {
|
|
353
|
+
newestSrcMtime = Math.max(newestSrcMtime, (0, fs.statSync)(srcFile).mtimeMs);
|
|
354
|
+
} catch {}
|
|
355
|
+
return distMtime < newestSrcMtime;
|
|
356
|
+
}
|
|
308
357
|
/**
|
|
309
358
|
* Shared external-package source collection (spec:
|
|
310
359
|
* external-package-file-discovery), consumed by both extraction plugins.
|
|
@@ -330,6 +379,8 @@ async function collectExternalPackageSources(opts) {
|
|
|
330
379
|
const packageMap = {};
|
|
331
380
|
const sourceEntries = /* @__PURE__ */ new Map();
|
|
332
381
|
const packageDirs = [];
|
|
382
|
+
const dirOwners = {};
|
|
383
|
+
const fileOwners = {};
|
|
333
384
|
const outcomes = [];
|
|
334
385
|
const alreadyIngested = (relPath) => hasEntry(relPath) || pushed.has(relPath);
|
|
335
386
|
for (const specifier of specifiers) {
|
|
@@ -350,17 +401,30 @@ async function collectExternalPackageSources(opts) {
|
|
|
350
401
|
}
|
|
351
402
|
const srcDir = (0, path.join)(findPackageRoot(absEntry), "src");
|
|
352
403
|
let fileCount = 0;
|
|
404
|
+
let staleDist = false;
|
|
353
405
|
if ((0, fs.existsSync)(srcDir)) {
|
|
354
406
|
packageDirs.push(srcDir);
|
|
355
|
-
|
|
356
|
-
|
|
407
|
+
dirOwners[srcDir] ??= specifier;
|
|
408
|
+
const srcEntry = sourceEntryForSpecifier(specifier, srcDir, extensionsSet);
|
|
409
|
+
if (srcEntry) {
|
|
357
410
|
packageMap[specifier] = (0, path.relative)(rootDir, srcEntry);
|
|
358
411
|
sourceEntries.set(specifier, srcEntry);
|
|
359
412
|
} else packageMap[specifier] = (0, path.relative)(rootDir, absEntry);
|
|
413
|
+
if (!(0, path.isAbsolute)(specifier)) {
|
|
414
|
+
const packageName = bareSpecifierPackageName(specifier);
|
|
415
|
+
if (packageName !== specifier && !(packageName in packageMap)) {
|
|
416
|
+
const rootEntry = sourceEntryForSpecifier(packageName, srcDir, extensionsSet);
|
|
417
|
+
if (rootEntry) {
|
|
418
|
+
packageMap[packageName] = (0, path.relative)(rootDir, rootEntry);
|
|
419
|
+
sourceEntries.set(packageName, rootEntry);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
360
423
|
const pkgFiles = discoverFiles(srcDir, srcDir, [], extensionsSet).filter((absPath) => {
|
|
361
424
|
const inPkg = (0, path.relative)(srcDir, absPath);
|
|
362
425
|
return !PACKAGE_SRC_EXCLUDES.some((pattern) => inPkg.includes(pattern));
|
|
363
426
|
});
|
|
427
|
+
staleDist = distEntryIsStale(absEntry, srcDir, pkgFiles);
|
|
364
428
|
for (const pkgFile of pkgFiles) {
|
|
365
429
|
const relPath = (0, path.relative)(rootDir, pkgFile);
|
|
366
430
|
if (alreadyIngested(relPath)) {
|
|
@@ -381,28 +445,48 @@ async function collectExternalPackageSources(opts) {
|
|
|
381
445
|
source: processed.source
|
|
382
446
|
});
|
|
383
447
|
pushed.add(processed.relPath);
|
|
448
|
+
fileOwners[processed.relPath] ??= specifier;
|
|
384
449
|
fileCount++;
|
|
385
450
|
}
|
|
386
451
|
} else {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
452
|
+
const outputDir = (0, path.dirname)(absEntry);
|
|
453
|
+
packageDirs.push(outputDir);
|
|
454
|
+
dirOwners[outputDir] ??= specifier;
|
|
455
|
+
packageMap[specifier] = (0, path.relative)(rootDir, absEntry);
|
|
456
|
+
const outputExtensions = new Set(extensionsSet);
|
|
457
|
+
outputExtensions.add((0, path.extname)(absEntry));
|
|
458
|
+
const outputFiles = discoverFiles(outputDir, outputDir, [], outputExtensions).filter((file) => {
|
|
459
|
+
const relToOutput = (0, path.relative)(outputDir, file);
|
|
460
|
+
return !PACKAGE_OUTPUT_EXCLUDES.some((pattern) => relToOutput.includes(pattern));
|
|
461
|
+
});
|
|
462
|
+
if (!outputFiles.includes(absEntry)) outputFiles.unshift(absEntry);
|
|
463
|
+
for (const outputFile of outputFiles) {
|
|
464
|
+
const outputRelPath = (0, path.relative)(rootDir, outputFile);
|
|
465
|
+
if (alreadyIngested(outputRelPath)) {
|
|
466
|
+
fileCount++;
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
let source;
|
|
470
|
+
try {
|
|
471
|
+
source = (0, fs.readFileSync)(outputFile, "utf-8");
|
|
472
|
+
} catch (err) {
|
|
473
|
+
onUnreadable(outputRelPath, err);
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
const processed = await preprocessFile(source, outputRelPath, outputFile);
|
|
477
|
+
if (!processed) continue;
|
|
393
478
|
entries.push({
|
|
394
|
-
path: relPath,
|
|
395
|
-
source
|
|
479
|
+
path: processed.relPath,
|
|
480
|
+
source: processed.source
|
|
396
481
|
});
|
|
397
|
-
pushed.add(relPath);
|
|
482
|
+
pushed.add(processed.relPath);
|
|
483
|
+
fileOwners[processed.relPath] ??= specifier;
|
|
398
484
|
fileCount++;
|
|
399
|
-
} catch (err) {
|
|
400
|
-
onUnreadable(relPath, err);
|
|
401
485
|
}
|
|
402
486
|
}
|
|
403
487
|
outcomes.push({
|
|
404
488
|
specifier,
|
|
405
|
-
outcome: fileCount > 0 ? "resolved" : "empty",
|
|
489
|
+
outcome: staleDist ? "stale-dist" : fileCount > 0 ? "resolved" : "empty",
|
|
406
490
|
fileCount
|
|
407
491
|
});
|
|
408
492
|
}
|
|
@@ -411,24 +495,33 @@ async function collectExternalPackageSources(opts) {
|
|
|
411
495
|
packageMap,
|
|
412
496
|
sourceEntries,
|
|
413
497
|
packageDirs,
|
|
498
|
+
dirOwners,
|
|
499
|
+
fileOwners,
|
|
414
500
|
outcomes
|
|
415
501
|
};
|
|
416
502
|
}
|
|
417
503
|
/**
|
|
418
|
-
* Extract external DS package names from
|
|
504
|
+
* Extract external DS package names from inheritance declarations in the
|
|
505
|
+
* system file.
|
|
419
506
|
*
|
|
420
|
-
* Supports
|
|
421
|
-
* - Primary
|
|
422
|
-
*
|
|
507
|
+
* Supports four forms:
|
|
508
|
+
* - Primary: `createSystem(...).extend(identifier)` chain calls
|
|
509
|
+
* (repeatable, mixable with `.from()` links; each call
|
|
510
|
+
* contributes one source; a library-bundle identifier
|
|
511
|
+
* traces its base import)
|
|
512
|
+
* - Deprecated chain: `createSystem(...).from(identifier)` chain calls
|
|
513
|
+
* - Deprecated alias: `createSystem({ includes: [identifier, ...] })`
|
|
514
|
+
* - Legacy: `.includes([identifier, ...])` chain method (RC
|
|
515
|
+
* migration fallback)
|
|
423
516
|
*
|
|
424
517
|
* For each identifier found, traces back to its import declaration and returns
|
|
425
518
|
* the import specifier: a bare specifier normalized to its package name, a
|
|
426
519
|
* relative specifier resolved against the system file's directory into an
|
|
427
520
|
* absolute path (so a sibling package referenced by path contributes discovery
|
|
428
|
-
* too). Only packages explicitly declared
|
|
429
|
-
* external DS dependencies.
|
|
521
|
+
* too). Only packages explicitly declared through one of these forms are
|
|
522
|
+
* treated as external DS dependencies.
|
|
430
523
|
*
|
|
431
|
-
* Falls back to empty array if no
|
|
524
|
+
* Falls back to empty array if no declaration is found.
|
|
432
525
|
*/
|
|
433
526
|
/**
|
|
434
527
|
* The message for the strict/warn gate over unresolvable includes, or null
|
|
@@ -441,6 +534,18 @@ function unresolvableIncludesMessage(outcomes) {
|
|
|
441
534
|
if (unresolvable.length === 0) return null;
|
|
442
535
|
return `[animus-extract] unresolvable include specifier(s): ${unresolvable.join(", ")}`;
|
|
443
536
|
}
|
|
537
|
+
/**
|
|
538
|
+
* The message for the strict/warn gate over stale dist entries
|
|
539
|
+
* (first-class-extension D13), or null when no declared specifier is stale.
|
|
540
|
+
* A stale dist silently skews merged registry content while discovery
|
|
541
|
+
* compiles the fresh sources, so it surfaces like an unresolvable specifier:
|
|
542
|
+
* non-strict consumers warn with this line, strict consumers throw it.
|
|
543
|
+
*/
|
|
544
|
+
function staleDistIncludesMessage(outcomes) {
|
|
545
|
+
const stale = outcomes.filter((record) => record.outcome === "stale-dist").map((record) => record.specifier);
|
|
546
|
+
if (stale.length === 0) return null;
|
|
547
|
+
return `[animus-extract] stale dist for include specifier(s): ${stale.join(", ")} — dist entry is older than the newest src/ file; rebuild the package(s) before extracting`;
|
|
548
|
+
}
|
|
444
549
|
function extractSystemFilePackages(systemFilePath) {
|
|
445
550
|
let source;
|
|
446
551
|
try {
|
|
@@ -463,6 +568,94 @@ function extractSystemFilePackages(systemFilePath) {
|
|
|
463
568
|
};
|
|
464
569
|
collectIdentifiers(constructorRegex);
|
|
465
570
|
collectIdentifiers(chainRegex);
|
|
571
|
+
const IDENT_START_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*/;
|
|
572
|
+
/** Position after any run of whitespace, line comments, block comments. */
|
|
573
|
+
const skipTrivia = (from) => {
|
|
574
|
+
let pos = from;
|
|
575
|
+
for (;;) {
|
|
576
|
+
while (pos < source.length && /\s/.test(source[pos])) pos++;
|
|
577
|
+
if (source.startsWith("//", pos)) {
|
|
578
|
+
const newline = source.indexOf("\n", pos);
|
|
579
|
+
pos = newline === -1 ? source.length : newline + 1;
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
if (source.startsWith("/*", pos)) {
|
|
583
|
+
const close = source.indexOf("*/", pos + 2);
|
|
584
|
+
pos = close === -1 ? source.length : close + 2;
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
return pos;
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
/**
|
|
591
|
+
* Consume consecutive extend/from links starting at `from`, collecting
|
|
592
|
+
* each link's base identifier; tolerates trivia between tokens and a
|
|
593
|
+
* trailing comma in the argument list. Returns the position after the
|
|
594
|
+
* last consumed link (`from` itself when none matched).
|
|
595
|
+
*/
|
|
596
|
+
const consumeChainLinks = (from) => {
|
|
597
|
+
let pos = from;
|
|
598
|
+
for (;;) {
|
|
599
|
+
let cursor = skipTrivia(pos);
|
|
600
|
+
if (source[cursor] !== ".") return pos;
|
|
601
|
+
cursor = skipTrivia(cursor + 1);
|
|
602
|
+
const method = IDENT_START_RE.exec(source.slice(cursor))?.[0];
|
|
603
|
+
if (method !== "extend" && method !== "from") return pos;
|
|
604
|
+
cursor = skipTrivia(cursor + method.length);
|
|
605
|
+
if (source[cursor] !== "(") return pos;
|
|
606
|
+
cursor = skipTrivia(cursor + 1);
|
|
607
|
+
const base = IDENT_START_RE.exec(source.slice(cursor))?.[0];
|
|
608
|
+
if (!base) return pos;
|
|
609
|
+
cursor = skipTrivia(cursor + base.length);
|
|
610
|
+
while (source[cursor] === ".") {
|
|
611
|
+
const afterDot = skipTrivia(cursor + 1);
|
|
612
|
+
const segment = IDENT_START_RE.exec(source.slice(afterDot))?.[0];
|
|
613
|
+
if (!segment) break;
|
|
614
|
+
cursor = skipTrivia(afterDot + segment.length);
|
|
615
|
+
}
|
|
616
|
+
if (source[cursor] === ",") cursor = skipTrivia(cursor + 1);
|
|
617
|
+
if (source[cursor] !== ")") return pos;
|
|
618
|
+
identifiers.add(base);
|
|
619
|
+
pos = cursor + 1;
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
/** Identifier assigned directly before `index` (`const x = <here>`), if any. */
|
|
623
|
+
const boundIdentifierBefore = (index) => {
|
|
624
|
+
const match = /([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*$/.exec(source.slice(0, index));
|
|
625
|
+
return match ? match[1] : null;
|
|
626
|
+
};
|
|
627
|
+
const chainRootIdentifiers = /* @__PURE__ */ new Set();
|
|
628
|
+
const createSystemAnchor = /createSystem\s*\(/g;
|
|
629
|
+
let anchorMatch;
|
|
630
|
+
while ((anchorMatch = createSystemAnchor.exec(source)) !== null) {
|
|
631
|
+
let pos = anchorMatch.index + anchorMatch[0].length;
|
|
632
|
+
let depth = 1;
|
|
633
|
+
while (pos < source.length && depth > 0) {
|
|
634
|
+
const ch = source[pos];
|
|
635
|
+
if (ch === "(") depth++;
|
|
636
|
+
else if (ch === ")") depth--;
|
|
637
|
+
pos++;
|
|
638
|
+
}
|
|
639
|
+
consumeChainLinks(pos);
|
|
640
|
+
const bound = boundIdentifierBefore(anchorMatch.index);
|
|
641
|
+
if (bound) chainRootIdentifiers.add(bound);
|
|
642
|
+
}
|
|
643
|
+
const scannedRoots = /* @__PURE__ */ new Set();
|
|
644
|
+
for (;;) {
|
|
645
|
+
const pendingRoots = [...chainRootIdentifiers].filter((root) => !scannedRoots.has(root));
|
|
646
|
+
if (pendingRoots.length === 0) break;
|
|
647
|
+
for (const root of pendingRoots) {
|
|
648
|
+
scannedRoots.add(root);
|
|
649
|
+
const rootUse = new RegExp(`(?<![a-zA-Z0-9_$])${root.replace(/\$/g, "\\$")}(?![a-zA-Z0-9_$])`, "g");
|
|
650
|
+
let useMatch;
|
|
651
|
+
while ((useMatch = rootUse.exec(source)) !== null) {
|
|
652
|
+
const afterIdentifier = useMatch.index + useMatch[0].length;
|
|
653
|
+
if (consumeChainLinks(afterIdentifier) === afterIdentifier) continue;
|
|
654
|
+
const bound = boundIdentifierBefore(useMatch.index);
|
|
655
|
+
if (bound) chainRootIdentifiers.add(bound);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
466
659
|
if (identifiers.size === 0) return [];
|
|
467
660
|
const importMap = /* @__PURE__ */ new Map();
|
|
468
661
|
const importRegex = /^\s*import\s+(?:([a-zA-Z_$][a-zA-Z0-9_$]*)\s*,\s*)?(?:\{([^}]*)\}|([a-zA-Z_$][a-zA-Z0-9_$]*))\s+from\s+['"]([^'"]+)['"]/gm;
|
|
@@ -483,14 +676,265 @@ function extractSystemFilePackages(systemFilePath) {
|
|
|
483
676
|
const specifier = importMap.get(id);
|
|
484
677
|
if (!specifier) continue;
|
|
485
678
|
if (specifier.startsWith(".")) packages.add((0, path.resolve)(systemFileDir, specifier));
|
|
486
|
-
else
|
|
487
|
-
const pkgName = specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0];
|
|
488
|
-
packages.add(pkgName);
|
|
489
|
-
}
|
|
679
|
+
else packages.add(specifier);
|
|
490
680
|
}
|
|
491
681
|
return Array.from(packages);
|
|
492
682
|
}
|
|
493
683
|
//#endregion
|
|
684
|
+
//#region pipeline/asset-placeholders.ts
|
|
685
|
+
/**
|
|
686
|
+
* Host-side handling of `asset()` placeholders (global-styles-system):
|
|
687
|
+
* `animus-asset:<specifier>` markers ride through the sandbox and the
|
|
688
|
+
* emitter byte-exact; each HOST plugin substitutes them with its bundler's
|
|
689
|
+
* resolved asset URL after extraction. This module owns the shared scanning
|
|
690
|
+
* and replacement mechanics — resolution and strict gating stay at the
|
|
691
|
+
* plugin call sites.
|
|
692
|
+
*/
|
|
693
|
+
/** Mirrors the producer-side constant in `@animus-ui/system`'s `asset.ts`
|
|
694
|
+
* (extract must not take a runtime dependency on system); the pairing is
|
|
695
|
+
* pinned by a contract test in `tests/asset-placeholders.test.ts`. */
|
|
696
|
+
const ASSET_PLACEHOLDER_PREFIX = "animus-asset:";
|
|
697
|
+
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
698
|
+
const PREFIX_RE = escapeRegExp(ASSET_PLACEHOLDER_PREFIX);
|
|
699
|
+
/**
|
|
700
|
+
* Quoted `url('animus-asset:<specifier>')` form — the emitter always quotes
|
|
701
|
+
* `url()` values, so a quoted match carries the FULL specifier, including
|
|
702
|
+
* whitespace and parentheses (D5 pins the placeholder as specifier-verbatim,
|
|
703
|
+
* so scanning fidelity is the only place such characters can be honored).
|
|
704
|
+
*/
|
|
705
|
+
const QUOTED_PLACEHOLDER_RE = new RegExp(`(['"])${PREFIX_RE}([^'"]*?)\\1`, "g");
|
|
706
|
+
/** Bare-form fallback: a placeholder up to CSS url()/quote/whitespace. */
|
|
707
|
+
const BARE_PLACEHOLDER_RE = new RegExp(`${PREFIX_RE}([^'")\\s]+)`, "g");
|
|
708
|
+
/** Unique asset specifiers referenced by placeholders, in appearance order. */
|
|
709
|
+
function findAssetSpecifiers(css) {
|
|
710
|
+
if (!css.includes("animus-asset:")) return [];
|
|
711
|
+
const seen = /* @__PURE__ */ new Set();
|
|
712
|
+
const remainder = css.replace(QUOTED_PLACEHOLDER_RE, (_match, _quote, specifier) => {
|
|
713
|
+
seen.add(specifier);
|
|
714
|
+
return "";
|
|
715
|
+
});
|
|
716
|
+
for (const match of remainder.matchAll(BARE_PLACEHOLDER_RE)) seen.add(match[1]);
|
|
717
|
+
return [...seen];
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Replace each specifier's placeholder with its substitution. Specifiers
|
|
721
|
+
* absent from the map keep their placeholder — the caller decides whether
|
|
722
|
+
* that is a strict failure or a warn-and-emit-literally. A substitution may
|
|
723
|
+
* itself be a bundler marker (e.g. Vite's `__VITE_ASSET__<ref>__`) that the
|
|
724
|
+
* host's own asset pipeline resolves to a hashed file name later.
|
|
725
|
+
*
|
|
726
|
+
* Each replacement is anchored to a following delimiter (quote, `)`,
|
|
727
|
+
* whitespace, or end of input) so a specifier that textually prefixes a
|
|
728
|
+
* longer one can never clobber the longer placeholder; longest-first
|
|
729
|
+
* ordering additionally lets the longer of two mapped specifiers claim its
|
|
730
|
+
* occurrences before the shorter runs.
|
|
731
|
+
*/
|
|
732
|
+
function substituteAssetPlaceholders(css, urlBySpecifier) {
|
|
733
|
+
if (urlBySpecifier.size === 0) return css;
|
|
734
|
+
if (!css.includes("animus-asset:")) return css;
|
|
735
|
+
const specifiers = [...urlBySpecifier.keys()].sort((a, b) => b.length - a.length);
|
|
736
|
+
let out = css;
|
|
737
|
+
for (const specifier of specifiers) {
|
|
738
|
+
const placeholder = new RegExp(escapeRegExp(ASSET_PLACEHOLDER_PREFIX + specifier) + String.raw`(?=['")\s]|$)`, "g");
|
|
739
|
+
out = out.replace(placeholder, () => urlBySpecifier.get(specifier));
|
|
740
|
+
}
|
|
741
|
+
return out;
|
|
742
|
+
}
|
|
743
|
+
//#endregion
|
|
744
|
+
//#region pipeline/resolve-asset.ts
|
|
745
|
+
/**
|
|
746
|
+
* Node-side asset specifier resolution shared by the host plugins (the
|
|
747
|
+
* asset() contract, global-styles-system): host path aliases apply FIRST —
|
|
748
|
+
* an alias such as `@fonts` works in application modules, so
|
|
749
|
+
* `asset('@fonts/inter.woff2')` must resolve identically — then direct Node
|
|
750
|
+
* resolution, then the package-root fallback (exports maps rarely list
|
|
751
|
+
* asset subpaths). Bundler-native resolution (Vite's `this.resolve`) is
|
|
752
|
+
* still preferred where available; this resolver covers the paths that have
|
|
753
|
+
* no bundler hook (Next's session, Vite's dev re-analysis).
|
|
754
|
+
*/
|
|
755
|
+
const requireByRoot = /* @__PURE__ */ new Map();
|
|
756
|
+
function requireAnchoredAt(rootDir) {
|
|
757
|
+
let req = requireByRoot.get(rootDir);
|
|
758
|
+
if (!req) {
|
|
759
|
+
req = (0, module$1.createRequire)((0, path.join)(rootDir, "package.json"));
|
|
760
|
+
requireByRoot.set(rootDir, req);
|
|
761
|
+
}
|
|
762
|
+
return req;
|
|
763
|
+
}
|
|
764
|
+
function packageRootFromEntry(entry) {
|
|
765
|
+
let current = (0, path.dirname)(entry);
|
|
766
|
+
while (true) {
|
|
767
|
+
if ((0, fs.existsSync)((0, path.join)(current, "package.json"))) return current;
|
|
768
|
+
const parent = (0, path.dirname)(current);
|
|
769
|
+
if (parent === current) return null;
|
|
770
|
+
current = parent;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
const aliasTableCache = /* @__PURE__ */ new Map();
|
|
774
|
+
function parseAliasTable(pathAliasesJson) {
|
|
775
|
+
const cached = aliasTableCache.get(pathAliasesJson);
|
|
776
|
+
if (cached) return cached;
|
|
777
|
+
let aliases;
|
|
778
|
+
try {
|
|
779
|
+
aliases = JSON.parse(pathAliasesJson).aliases ?? [];
|
|
780
|
+
} catch {
|
|
781
|
+
aliases = [];
|
|
782
|
+
}
|
|
783
|
+
aliasTableCache.set(pathAliasesJson, aliases);
|
|
784
|
+
return aliases;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Map a specifier through the harvested host alias table (the same
|
|
788
|
+
* `pathAliasesJson` wire the engine consumes — entries pre-sorted longest
|
|
789
|
+
* pattern first by `buildPathAliasesJson`). Returns an absolute path to an
|
|
790
|
+
* EXISTING file, or null when no alias claims the specifier.
|
|
791
|
+
*/
|
|
792
|
+
function resolveThroughPathAliases(specifier, rootDir, pathAliasesJson) {
|
|
793
|
+
if (!pathAliasesJson) return null;
|
|
794
|
+
const aliases = parseAliasTable(pathAliasesJson);
|
|
795
|
+
for (const alias of aliases) {
|
|
796
|
+
let mapped = null;
|
|
797
|
+
if (alias.type === "exact") {
|
|
798
|
+
if (alias.pattern === specifier) mapped = alias.replacement;
|
|
799
|
+
} else if (specifier.startsWith(alias.pattern)) mapped = alias.replacement + specifier.slice(alias.pattern.length);
|
|
800
|
+
if (mapped === null) continue;
|
|
801
|
+
const absolute = (0, path.isAbsolute)(mapped) ? mapped : (0, path.join)(rootDir, mapped);
|
|
802
|
+
if ((0, fs.existsSync)(absolute)) return absolute;
|
|
803
|
+
}
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Resolve an asset specifier to an absolute file: host aliases, then direct
|
|
808
|
+
* Node resolution anchored at `rootDir`, then the package-root fallback.
|
|
809
|
+
* Returns null when nothing matches — strict gating stays at the caller.
|
|
810
|
+
*/
|
|
811
|
+
function resolveAssetFile(specifier, rootDir, pathAliasesJson) {
|
|
812
|
+
const aliased = resolveThroughPathAliases(specifier, rootDir, pathAliasesJson);
|
|
813
|
+
if (aliased) return aliased;
|
|
814
|
+
const requireFromRoot = requireAnchoredAt(rootDir);
|
|
815
|
+
try {
|
|
816
|
+
return requireFromRoot.resolve(specifier);
|
|
817
|
+
} catch {}
|
|
818
|
+
const segments = specifier.split("/");
|
|
819
|
+
const packageName = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
|
|
820
|
+
const subpath = specifier.slice(packageName.length + 1);
|
|
821
|
+
if (!subpath) return null;
|
|
822
|
+
for (const modulesDir of requireFromRoot.resolve.paths(packageName) ?? []) {
|
|
823
|
+
const packageRoot = (0, path.join)(modulesDir, packageName);
|
|
824
|
+
if (!(0, fs.existsSync)((0, path.join)(packageRoot, "package.json"))) continue;
|
|
825
|
+
const candidate = (0, path.join)(packageRoot, subpath);
|
|
826
|
+
if ((0, fs.existsSync)(candidate)) return candidate;
|
|
827
|
+
}
|
|
828
|
+
try {
|
|
829
|
+
const packageRoot = packageRootFromEntry(requireFromRoot.resolve(packageName));
|
|
830
|
+
if (!packageRoot) return null;
|
|
831
|
+
const candidate = (0, path.join)(packageRoot, subpath);
|
|
832
|
+
return (0, fs.existsSync)(candidate) ? candidate : null;
|
|
833
|
+
} catch {
|
|
834
|
+
return null;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
//#endregion
|
|
838
|
+
//#region pipeline/correlate-external-tokens.ts
|
|
839
|
+
/**
|
|
840
|
+
* Index the loader-captured theme manifests by owning specifier. Module paths
|
|
841
|
+
* are canonical absolute paths (symlinks resolved), so each package dir is
|
|
842
|
+
* realpath'd before prefix-matching; a module outside every known package dir
|
|
843
|
+
* (typically the consumer's own theme) contributes nothing.
|
|
844
|
+
*/
|
|
845
|
+
function buildSourceTokenIndex(opts) {
|
|
846
|
+
const index = /* @__PURE__ */ new Map();
|
|
847
|
+
if (!opts.sourceThemeManifestsJson) return index;
|
|
848
|
+
let manifests;
|
|
849
|
+
try {
|
|
850
|
+
manifests = JSON.parse(opts.sourceThemeManifestsJson);
|
|
851
|
+
} catch {
|
|
852
|
+
return index;
|
|
853
|
+
}
|
|
854
|
+
const realDirOwners = [];
|
|
855
|
+
const addOwnerDir = (dir, specifier) => {
|
|
856
|
+
if (!realDirOwners.some((entry) => entry.dir === dir)) realDirOwners.push({
|
|
857
|
+
dir,
|
|
858
|
+
specifier
|
|
859
|
+
});
|
|
860
|
+
};
|
|
861
|
+
for (const [dir, specifier] of Object.entries(opts.dirOwners)) {
|
|
862
|
+
let real = dir;
|
|
863
|
+
try {
|
|
864
|
+
real = (0, fs.realpathSync)(dir);
|
|
865
|
+
} catch {}
|
|
866
|
+
addOwnerDir(real, specifier);
|
|
867
|
+
let packageRoot = real;
|
|
868
|
+
while (packageRoot !== (0, path.dirname)(packageRoot) && !(0, fs.existsSync)((0, path.join)(packageRoot, "package.json"))) packageRoot = (0, path.dirname)(packageRoot);
|
|
869
|
+
if ((0, fs.existsSync)((0, path.join)(packageRoot, "package.json"))) addOwnerDir(packageRoot, specifier);
|
|
870
|
+
}
|
|
871
|
+
for (const [modulePath, exports] of Object.entries(manifests)) {
|
|
872
|
+
const owner = realDirOwners.find(({ dir }) => modulePath === dir || modulePath.startsWith(dir + path.sep));
|
|
873
|
+
if (!owner) continue;
|
|
874
|
+
let tokens = index.get(owner.specifier);
|
|
875
|
+
if (!tokens) {
|
|
876
|
+
tokens = /* @__PURE__ */ new Set();
|
|
877
|
+
index.set(owner.specifier, tokens);
|
|
878
|
+
}
|
|
879
|
+
for (const paths of Object.values(exports)) for (const token of paths) tokens.add(token);
|
|
880
|
+
}
|
|
881
|
+
return index;
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* The correlation join. Returns one teaching-error message per distinct
|
|
885
|
+
* (component, token, specifier) whose file belongs to a discovered source AND
|
|
886
|
+
* whose token that source's manifest defines. The messages follow the
|
|
887
|
+
* standard severity routing at the CALLER (throw under `strict`, warn
|
|
888
|
+
* otherwise) — this join never reports on its own.
|
|
889
|
+
*/
|
|
890
|
+
function correlateExternalTokenDiagnostics(opts) {
|
|
891
|
+
const messages = [];
|
|
892
|
+
const seen = /* @__PURE__ */ new Set();
|
|
893
|
+
for (const diagnostic of opts.diagnostics ?? []) {
|
|
894
|
+
if (diagnostic.kind !== "external-token-candidate" || !diagnostic.token) continue;
|
|
895
|
+
const specifier = opts.fileOwners[diagnostic.file];
|
|
896
|
+
if (!specifier) continue;
|
|
897
|
+
if (!opts.sourceTokens.get(specifier)?.has(diagnostic.token)) continue;
|
|
898
|
+
const key = `${diagnostic.component}\u0000${diagnostic.token}\u0000${specifier}`;
|
|
899
|
+
if (seen.has(key)) continue;
|
|
900
|
+
seen.add(key);
|
|
901
|
+
messages.push(`${diagnostic.component} (from '${specifier}') references token '${diagnostic.token}', which the consumer theme does not define — inherit the source's tokens with createTheme().extend(...) using the tokens (or bundle) export of '${specifier}'`);
|
|
902
|
+
}
|
|
903
|
+
return messages;
|
|
904
|
+
}
|
|
905
|
+
const indexCache = /* @__PURE__ */ new WeakMap();
|
|
906
|
+
/**
|
|
907
|
+
* The complete cross-source token-contract gate both plugins share
|
|
908
|
+
* (extraction-diagnostics): index the loader-captured source manifests,
|
|
909
|
+
* join them against the engine's candidates, and route the resulting
|
|
910
|
+
* teaching errors — throw under `strict`, warn otherwise. One entry point
|
|
911
|
+
* so the two hosts cannot drift on wiring or severity semantics.
|
|
912
|
+
*/
|
|
913
|
+
function enforceExternalTokenContracts(opts) {
|
|
914
|
+
const manifestsJson = opts.sourceThemeManifestsJson ?? "";
|
|
915
|
+
const cached = indexCache.get(opts.dirOwners);
|
|
916
|
+
let sourceTokens;
|
|
917
|
+
if (cached && cached.manifestsJson === manifestsJson) sourceTokens = cached.index;
|
|
918
|
+
else {
|
|
919
|
+
sourceTokens = buildSourceTokenIndex({
|
|
920
|
+
sourceThemeManifestsJson: opts.sourceThemeManifestsJson,
|
|
921
|
+
dirOwners: opts.dirOwners
|
|
922
|
+
});
|
|
923
|
+
indexCache.set(opts.dirOwners, {
|
|
924
|
+
manifestsJson,
|
|
925
|
+
index: sourceTokens
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
const messages = correlateExternalTokenDiagnostics({
|
|
929
|
+
diagnostics: opts.diagnostics,
|
|
930
|
+
fileOwners: opts.fileOwners,
|
|
931
|
+
sourceTokens
|
|
932
|
+
});
|
|
933
|
+
if (messages.length === 0) return;
|
|
934
|
+
if (opts.strict) throw new Error(`${opts.prefix} ${messages.join("\n")}`);
|
|
935
|
+
for (const message of messages) opts.warn(message);
|
|
936
|
+
}
|
|
937
|
+
//#endregion
|
|
494
938
|
//#region pipeline/path-aliases.ts
|
|
495
939
|
/**
|
|
496
940
|
* Normalize alias pairs: strip a `rootDir` prefix from targets, classify
|
|
@@ -584,7 +1028,7 @@ function surfaceManifestDiagnostics(manifest, warn) {
|
|
|
584
1028
|
*/
|
|
585
1029
|
function applyUnitFallback(css) {
|
|
586
1030
|
return css.replace(/([a-z-]+)\s*:\s*([^;{}]+);/g, (match, prop, value) => {
|
|
587
|
-
if (_animus_ui_properties.
|
|
1031
|
+
if ((0, _animus_ui_properties.isUnitlessProperty)(prop)) return match;
|
|
588
1032
|
let depth = 0;
|
|
589
1033
|
let fixed = "";
|
|
590
1034
|
let i = 0;
|
|
@@ -643,9 +1087,15 @@ function buildAnalysisInputs(opts) {
|
|
|
643
1087
|
pathAliasesJson: opts.pathAliasesJson,
|
|
644
1088
|
keyframesJson: opts.system.keyframesJson,
|
|
645
1089
|
staticCssJson: opts.staticCssJson ?? null,
|
|
646
|
-
conditionAliasesJson: opts.system.conditionAliasesJson ?? null
|
|
1090
|
+
conditionAliasesJson: opts.system.conditionAliasesJson ?? null,
|
|
1091
|
+
externalDirsJson: opts.externalDirs?.length && hasSourceThemeManifests(opts.system) ? JSON.stringify(opts.externalDirs) : null
|
|
647
1092
|
};
|
|
648
1093
|
}
|
|
1094
|
+
/** Whether the loader captured at least one source built-theme manifest. */
|
|
1095
|
+
function hasSourceThemeManifests(system) {
|
|
1096
|
+
const json = system.sourceThemeManifestsJson;
|
|
1097
|
+
return typeof json === "string" && json.length > 0 && json !== "{}";
|
|
1098
|
+
}
|
|
649
1099
|
/**
|
|
650
1100
|
* The one analysis invocation both plugins share: build the emitter
|
|
651
1101
|
* config, serialize inputs, call the NAPI `analyzeProject`, parse the
|
|
@@ -778,19 +1228,26 @@ function loadSystemConfig(engineApi, opts) {
|
|
|
778
1228
|
conditionAliasesJson: config.conditionAliases || null,
|
|
779
1229
|
globalStyleBlocksJson: config.globalStyleBlocks || null,
|
|
780
1230
|
keyframesJson: config.keyframesBlocks || null,
|
|
781
|
-
dependencies: config.dependencies ?? []
|
|
1231
|
+
dependencies: config.dependencies ?? [],
|
|
1232
|
+
sourceThemeManifestsJson: config.sourceThemeManifests || null
|
|
782
1233
|
};
|
|
783
1234
|
}
|
|
784
1235
|
//#endregion
|
|
785
1236
|
//#region pipeline/dynamic-prop-config.ts
|
|
786
1237
|
function buildDynamicPropConfig(dynamicProps) {
|
|
787
1238
|
const configEntries = {};
|
|
788
|
-
for (const [propName, meta] of Object.entries(dynamicProps))
|
|
789
|
-
varName: meta.
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1239
|
+
for (const [propName, meta] of Object.entries(dynamicProps)) {
|
|
1240
|
+
if (!meta.varName || !meta.slotClass) throw new Error(`buildDynamicPropConfig: dynamic prop '${propName}' carries no slot metadata — expected varName and slotClass, got keys [${Object.keys(meta).join(", ")}].`);
|
|
1241
|
+
const entry = {
|
|
1242
|
+
varName: meta.varName,
|
|
1243
|
+
slotClass: meta.slotClass
|
|
1244
|
+
};
|
|
1245
|
+
if (meta.property) entry.property = meta.property;
|
|
1246
|
+
if (meta.properties && meta.properties.length > 0) entry.properties = meta.properties;
|
|
1247
|
+
if (meta.transformName) entry.transformName = meta.transformName;
|
|
1248
|
+
if (meta.scaleValues && Object.keys(meta.scaleValues).length > 0) entry.scaleValues = meta.scaleValues;
|
|
1249
|
+
configEntries[propName] = entry;
|
|
1250
|
+
}
|
|
794
1251
|
return configEntries;
|
|
795
1252
|
}
|
|
796
1253
|
//#endregion
|
|
@@ -804,6 +1261,10 @@ function buildDynamicPropConfig(dynamicProps) {
|
|
|
804
1261
|
* Runtime transform functions for dynamic props are not yet supported
|
|
805
1262
|
* (transforms are resolved at extraction time via boa_engine in Rust), so
|
|
806
1263
|
* `transforms` defaults to an empty object literal.
|
|
1264
|
+
*
|
|
1265
|
+
* `dynamicPropConfig` entries carry the CSS property the slot class declares
|
|
1266
|
+
* — the runtime's unit-fallback decision. Their field order and omission
|
|
1267
|
+
* rules belong to buildDynamicPropConfig.
|
|
807
1268
|
*/
|
|
808
1269
|
function buildSystemPropsModule(opts) {
|
|
809
1270
|
const dynamicPropConfig = buildDynamicPropConfig(opts.dynamicProps);
|
|
@@ -1136,17 +1597,23 @@ exports.collectExternalPackageSources = collectExternalPackageSources;
|
|
|
1136
1597
|
exports.contentHash = contentHash;
|
|
1137
1598
|
exports.createV2EngineApi = createV2EngineApi;
|
|
1138
1599
|
exports.discoverFiles = discoverFiles;
|
|
1600
|
+
exports.enforceExternalTokenContracts = enforceExternalTokenContracts;
|
|
1139
1601
|
exports.extractSystemFilePackages = extractSystemFilePackages;
|
|
1602
|
+
exports.findAssetSpecifiers = findAssetSpecifiers;
|
|
1140
1603
|
exports.findPackageRoot = findPackageRoot;
|
|
1141
1604
|
exports.formatRustTimingWaterfall = formatRustTimingWaterfall;
|
|
1142
1605
|
exports.loadSystemConfig = loadSystemConfig;
|
|
1143
1606
|
exports.postProcessCss = postProcessCss;
|
|
1144
1607
|
exports.preprocessMdx = preprocessMdx;
|
|
1145
1608
|
exports.readTsconfigAliasPairs = readTsconfigAliasPairs;
|
|
1609
|
+
exports.resolveAssetFile = resolveAssetFile;
|
|
1146
1610
|
exports.resolveLightningTargets = resolveLightningTargets;
|
|
1611
|
+
exports.resolveThroughPathAliases = resolveThroughPathAliases;
|
|
1147
1612
|
exports.runProjectAnalysis = runProjectAnalysis;
|
|
1148
1613
|
exports.serializeStaticCss = serializeStaticCss;
|
|
1614
|
+
exports.staleDistIncludesMessage = staleDistIncludesMessage;
|
|
1149
1615
|
exports.stripLeadingLayerDeclaration = stripLeadingLayerDeclaration;
|
|
1616
|
+
exports.substituteAssetPlaceholders = substituteAssetPlaceholders;
|
|
1150
1617
|
exports.surfaceManifestDiagnostics = surfaceManifestDiagnostics;
|
|
1151
1618
|
exports.toWatchKeys = toWatchKeys;
|
|
1152
1619
|
exports.unresolvableIncludesMessage = unresolvableIncludesMessage;
|