@animus-ui/extract 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/dist/correlate-external-tokens.d.ts.map +1 -1
- package/dist/discover-packages.d.ts +50 -2
- package/dist/discover-packages.d.ts.map +1 -1
- package/dist/external-keyframes.d.ts.map +1 -1
- package/dist/index.cjs +336 -24
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +319 -21
- package/dist/manifest-diagnostics.d.ts +10 -0
- package/dist/manifest-diagnostics.d.ts.map +1 -1
- package/dist/replacement-plans.d.ts +46 -0
- package/dist/replacement-plans.d.ts.map +1 -0
- package/dist/source-identity.d.ts +93 -0
- package/dist/source-identity.d.ts.map +1 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,9 @@ export { KEYFRAMES_EXPORT_COLLISION, KEYFRAMES_EXTERNAL_ENTRY_FAILED, mergeExter
|
|
|
10
10
|
export type { ExternalKeyframesMerge } from './external-keyframes';
|
|
11
11
|
export { discoverFiles } from './discover-files';
|
|
12
12
|
export type { CollectedExternalPackages, ExternalPackageOutcome, } from './discover-packages';
|
|
13
|
-
export { collectExternalPackageSources, extractSystemFilePackages, findPackageRoot, staleDistIncludesMessage, unresolvableIncludesMessage, } from './discover-packages';
|
|
13
|
+
export { collectExternalPackageSources, excludeCollectedPackages, extractSystemFilePackages, findPackageRoot, firstOwners, isExcludedPackageRelativePath, resolveAbsolutePathSpecifier, staleDistIncludesMessage, unresolvableIncludesMessage, walkPackageSources, } from './discover-packages';
|
|
14
|
+
export type { ResolvedSourceId, SourceIdentity } from './source-identity';
|
|
15
|
+
export { createSourceIdentity, isPathWithinRoot, sharesVolumeRoot, } from './source-identity';
|
|
14
16
|
export { findAssetSpecifiers, substituteAssetPlaceholders, } from './asset-placeholders';
|
|
15
17
|
export { resolveAssetFile, resolveThroughPathAliases } from './resolve-asset';
|
|
16
18
|
export { enforceExternalTokenContracts } from './correlate-external-tokens';
|
|
@@ -29,10 +31,12 @@ export { readTsconfigAliasPairs } from './tsconfig-paths';
|
|
|
29
31
|
export type { DynamicPropConfigEntry, DynamicPropMeta, } from './dynamic-prop-config';
|
|
30
32
|
export { buildDynamicPropConfig } from './dynamic-prop-config';
|
|
31
33
|
export type { ManifestDiagnostic } from './manifest-diagnostics';
|
|
32
|
-
export { surfaceManifestDiagnostics } from './manifest-diagnostics';
|
|
34
|
+
export { isUnresolvedParentDrop, surfaceManifestDiagnostics, unresolvedParentName, } from './manifest-diagnostics';
|
|
33
35
|
export type { DefaultExtension, PreprocessMdxResult } from './mdx-preprocessor';
|
|
34
36
|
export { DEFAULT_EXTENSIONS, preprocessMdx } from './mdx-preprocessor';
|
|
35
37
|
export { applyPrefix } from './prefix';
|
|
38
|
+
export type { FilePlanSnapshot } from './replacement-plans';
|
|
39
|
+
export { diffFilePlans, hashReplacementPlans, snapshotFilePlans, } from './replacement-plans';
|
|
36
40
|
export { applyUnitFallback } from './unit-fallback';
|
|
37
41
|
export { camelToKebab } from './utils';
|
|
38
42
|
export { toWatchKeys } from './watch-keys';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../pipeline/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EACL,8BAA8B,EAC9B,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,EAC/B,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EACV,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,EACzB,eAAe,EACf,wBAAwB,EACxB,2BAA2B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../pipeline/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { createHash } from "crypto";
|
|
3
3
|
import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "fs";
|
|
4
|
-
import { dirname, extname, isAbsolute, join, relative, resolve
|
|
4
|
+
import { dirname, extname, isAbsolute, join, relative, resolve } from "path";
|
|
5
|
+
import { realpathSync as realpathSync$1 } from "node:fs";
|
|
6
|
+
import path, { basename, dirname as dirname$1, join as join$1, normalize } from "node:path";
|
|
5
7
|
import { createRequire as createRequire$1 } from "module";
|
|
6
8
|
import browserslist from "browserslist";
|
|
7
9
|
import { browserslistToTargets, transform } from "lightningcss";
|
|
8
10
|
import { isUnitlessProperty } from "@animus-ui/properties";
|
|
9
|
-
import { realpathSync as realpathSync$1 } from "node:fs";
|
|
10
|
-
import { basename, dirname as dirname$1, join as join$1, normalize } from "node:path";
|
|
11
11
|
//#region \0rolldown/runtime.js
|
|
12
12
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
13
13
|
//#endregion
|
|
@@ -249,7 +249,7 @@ function mergeExternalKeyframes(scan, consumerKeyframesJson, externalEntries, ro
|
|
|
249
249
|
file: entryPath,
|
|
250
250
|
component: "keyframes",
|
|
251
251
|
kind: "warn",
|
|
252
|
-
message: `external package entry failed the keyframes scan — its collections are invisible to extraction: ${String(error)} (${KEYFRAMES_EXTERNAL_ENTRY_FAILED})`,
|
|
252
|
+
message: `external package entry failed the keyframes scan — its collections are invisible to extraction: ${String(error)}. Keyframe collections must be reachable from the package's definition entry without evaluating framework re-exports: export them (directly or as a named re-export) from the definition entry, and avoid \`export *\` of framework packages there (${KEYFRAMES_EXTERNAL_ENTRY_FAILED})`,
|
|
253
253
|
code: KEYFRAMES_EXTERNAL_ENTRY_FAILED,
|
|
254
254
|
severity: "warn"
|
|
255
255
|
});
|
|
@@ -317,6 +317,126 @@ function discoverFiles(dir, rootDir, excludePatterns, extensionsSet) {
|
|
|
317
317
|
return results;
|
|
318
318
|
}
|
|
319
319
|
//#endregion
|
|
320
|
+
//#region pipeline/source-identity.ts
|
|
321
|
+
/**
|
|
322
|
+
* SourceId derivation authority + allowlist membership (openspec:
|
|
323
|
+
* external-source-watch-ingestion, design D1/D2/D5).
|
|
324
|
+
*
|
|
325
|
+
* One shared derivation produces the canonical source identity consumed by
|
|
326
|
+
* discovery, watch ingestion, ownership, deletion pruning, and diagnostics
|
|
327
|
+
* — raw event paths are lookup INPUTS only, so event spelling (symlink
|
|
328
|
+
* alias vs canonical, lexical vs realpath) can never fork identity.
|
|
329
|
+
*
|
|
330
|
+
* The containment and volume helpers are pure and path-API-injectable so
|
|
331
|
+
* Windows semantics are unit-testable via `path.win32` on any host; runtime
|
|
332
|
+
* callers use the ambient platform implementation.
|
|
333
|
+
*/
|
|
334
|
+
/**
|
|
335
|
+
* Structural containment: `target` is the root itself or a descendant of it,
|
|
336
|
+
* decided by `relative()` shape — never by string prefixing, so `/ui` can
|
|
337
|
+
* never claim `/ui-old`, and a cross-drive win32 target (whose relative()
|
|
338
|
+
* result is absolute) is never contained.
|
|
339
|
+
*/
|
|
340
|
+
function isPathWithinRoot(root, target, pathApi = path) {
|
|
341
|
+
const rel = pathApi.relative(root, target);
|
|
342
|
+
return rel === "" || !pathApi.isAbsolute(rel) && rel !== ".." && !rel.startsWith(".." + pathApi.sep);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Cross-volume gate (design D5): two paths share a platform path root
|
|
346
|
+
* (win32 drive letter or UNC share; always true on posix). Compared
|
|
347
|
+
* case-insensitively — win32 drive letters are case-insensitive.
|
|
348
|
+
*/
|
|
349
|
+
function sharesVolumeRoot(a, b, pathApi = path) {
|
|
350
|
+
const volumeOf = (p) => pathApi.parse(pathApi.resolve(p)).root.toLowerCase();
|
|
351
|
+
return volumeOf(a) === volumeOf(b);
|
|
352
|
+
}
|
|
353
|
+
function canonicalize(p) {
|
|
354
|
+
try {
|
|
355
|
+
return realpathSync$1(p);
|
|
356
|
+
} catch {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function createSourceIdentity(rootDir) {
|
|
361
|
+
const normalizedRootDir = path.normalize(rootDir);
|
|
362
|
+
const canonicalRootDir = canonicalize(normalizedRootDir) ?? normalizedRootDir;
|
|
363
|
+
const roots = [];
|
|
364
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
365
|
+
const owningRecord = (canonicalPath) => {
|
|
366
|
+
let owner = null;
|
|
367
|
+
for (const record of roots) {
|
|
368
|
+
if (!isPathWithinRoot(record.canonical, canonicalPath)) continue;
|
|
369
|
+
if (!owner || record.canonical.length > owner.canonical.length) owner = record;
|
|
370
|
+
}
|
|
371
|
+
return owner;
|
|
372
|
+
};
|
|
373
|
+
return {
|
|
374
|
+
rootDir: normalizedRootDir,
|
|
375
|
+
canonicalRootDir,
|
|
376
|
+
registerExternalRoot(root) {
|
|
377
|
+
const asRegistered = path.normalize(root);
|
|
378
|
+
const canonical = canonicalize(asRegistered) ?? asRegistered;
|
|
379
|
+
const existing = roots.find((record) => record.canonical === canonical);
|
|
380
|
+
if (existing) return existing.canonical;
|
|
381
|
+
roots.push({
|
|
382
|
+
asRegistered,
|
|
383
|
+
canonical
|
|
384
|
+
});
|
|
385
|
+
return canonical;
|
|
386
|
+
},
|
|
387
|
+
externalRoots() {
|
|
388
|
+
return roots.map((record) => record.canonical);
|
|
389
|
+
},
|
|
390
|
+
resolveSourceId(inputPath) {
|
|
391
|
+
const lexical = path.normalize(inputPath);
|
|
392
|
+
const canonical = canonicalize(lexical);
|
|
393
|
+
if (canonical === null) return null;
|
|
394
|
+
const owner = owningRecord(canonical);
|
|
395
|
+
const ownedBy = (record) => {
|
|
396
|
+
const pathInRoot = path.relative(record.canonical, canonical);
|
|
397
|
+
return {
|
|
398
|
+
sourceKey: path.relative(normalizedRootDir, path.join(record.asRegistered, pathInRoot)),
|
|
399
|
+
owningRoot: record.canonical,
|
|
400
|
+
pathInRoot
|
|
401
|
+
};
|
|
402
|
+
};
|
|
403
|
+
const ownerIsMoreSpecific = owner !== null && owner.canonical.length > canonicalRootDir.length;
|
|
404
|
+
let resolved;
|
|
405
|
+
if (!ownerIsMoreSpecific && isPathWithinRoot(canonicalRootDir, canonical)) {
|
|
406
|
+
const key = path.relative(canonicalRootDir, canonical);
|
|
407
|
+
resolved = {
|
|
408
|
+
sourceKey: key,
|
|
409
|
+
owningRoot: null,
|
|
410
|
+
pathInRoot: key
|
|
411
|
+
};
|
|
412
|
+
} else if (owner) resolved = ownedBy(owner);
|
|
413
|
+
else return null;
|
|
414
|
+
aliases.set(lexical, resolved);
|
|
415
|
+
aliases.set(canonical, resolved);
|
|
416
|
+
return resolved;
|
|
417
|
+
},
|
|
418
|
+
resolveDeletedSourceId(inputPath) {
|
|
419
|
+
return aliases.get(path.normalize(inputPath)) ?? null;
|
|
420
|
+
},
|
|
421
|
+
containingExternalRoot(inputPath) {
|
|
422
|
+
const lexical = path.normalize(inputPath);
|
|
423
|
+
let owner = null;
|
|
424
|
+
for (const record of roots) {
|
|
425
|
+
if (!(isPathWithinRoot(record.canonical, lexical) || isPathWithinRoot(record.asRegistered, lexical))) continue;
|
|
426
|
+
if (!owner || record.canonical.length > owner.canonical.length) owner = record;
|
|
427
|
+
}
|
|
428
|
+
if (owner) return owner.canonical;
|
|
429
|
+
const canonical = canonicalize(lexical);
|
|
430
|
+
if (canonical === null) return null;
|
|
431
|
+
for (const record of roots) {
|
|
432
|
+
if (!isPathWithinRoot(record.canonical, canonical)) continue;
|
|
433
|
+
if (!owner || record.canonical.length > owner.canonical.length) owner = record;
|
|
434
|
+
}
|
|
435
|
+
return owner?.canonical ?? null;
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
//#endregion
|
|
320
440
|
//#region pipeline/discover-packages.ts
|
|
321
441
|
/**
|
|
322
442
|
* Walk up from a resolved package entry file to the nearest directory
|
|
@@ -341,6 +461,20 @@ const PACKAGE_SRC_EXCLUDES = [
|
|
|
341
461
|
".test.",
|
|
342
462
|
".spec."
|
|
343
463
|
];
|
|
464
|
+
/** True when a PACKAGE-RELATIVE path matches a package-source exclusion
|
|
465
|
+
* fragment (the "within the package" filter — see PACKAGE_SRC_EXCLUDES). */
|
|
466
|
+
function isExcludedPackageRelativePath(rel) {
|
|
467
|
+
return PACKAGE_SRC_EXCLUDES.some((pattern) => rel.includes(pattern));
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* THE package-source walk (guardrail G1 — one policy): shared discovery with
|
|
471
|
+
* no consumer patterns, then exclusion by package-relative path so fragments
|
|
472
|
+
* in the package's own location can't blank out its sources. Used by the
|
|
473
|
+
* collector, hosts' dirty-root rewalks, and watch-path classification alike.
|
|
474
|
+
*/
|
|
475
|
+
function walkPackageSources(packageDir, extensionsSet) {
|
|
476
|
+
return discoverFiles(packageDir, packageDir, [], extensionsSet).filter((absPath) => !isExcludedPackageRelativePath(relative(packageDir, absPath)));
|
|
477
|
+
}
|
|
344
478
|
/** Exclusions for the compiled-output fallback when a package does not ship src/. */
|
|
345
479
|
const PACKAGE_OUTPUT_EXCLUDES = [
|
|
346
480
|
"node_modules",
|
|
@@ -379,7 +513,7 @@ function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
|
|
|
379
513
|
if (isAbsolute(specifier)) {
|
|
380
514
|
const resolved = resolveAbsolutePathSpecifier(specifier, extensionsSet);
|
|
381
515
|
if (!resolved) return null;
|
|
382
|
-
return
|
|
516
|
+
return isPathWithinRoot(srcDir, resolved) ? resolved : null;
|
|
383
517
|
}
|
|
384
518
|
const packageName = bareSpecifierPackageName(specifier);
|
|
385
519
|
return resolveAbsolutePathSpecifier(join(srcDir, specifier.slice(packageName.length + 1) || "index"), extensionsSet);
|
|
@@ -393,7 +527,7 @@ function sourceEntryForSpecifier(specifier, srcDir, extensionsSet) {
|
|
|
393
527
|
* file's mtime is readable. Detection only — reporting is the caller's policy.
|
|
394
528
|
*/
|
|
395
529
|
function distEntryIsStale(absEntry, srcDir, srcFiles) {
|
|
396
|
-
if (
|
|
530
|
+
if (isPathWithinRoot(srcDir, absEntry)) return false;
|
|
397
531
|
let distMtime;
|
|
398
532
|
try {
|
|
399
533
|
distMtime = statSync(absEntry).mtimeMs;
|
|
@@ -425,15 +559,19 @@ function distEntryIsStale(absEntry, srcDir, srcFiles) {
|
|
|
425
559
|
* them — any warning or gate is the caller's policy.
|
|
426
560
|
*/
|
|
427
561
|
async function collectExternalPackageSources(opts) {
|
|
428
|
-
const { specifiers, resolveSpecifier, rootDir, extensionsSet, hasEntry, preprocessFile, onUnreadable } = opts;
|
|
562
|
+
const { specifiers, resolveSpecifier, rootDir, extensionsSet, hasEntry, preprocessFile, onUnreadable, onPackageResolved } = opts;
|
|
429
563
|
const entries = [];
|
|
430
564
|
const pushed = /* @__PURE__ */ new Set();
|
|
431
565
|
const packageMap = {};
|
|
432
566
|
const sourceEntries = /* @__PURE__ */ new Map();
|
|
567
|
+
const keyframesScanEntries = /* @__PURE__ */ new Map();
|
|
433
568
|
const packageDirs = [];
|
|
434
|
-
const
|
|
569
|
+
const dirOwnerSets = {};
|
|
435
570
|
const fileOwners = {};
|
|
436
571
|
const outcomes = [];
|
|
572
|
+
const claimDir = (dir, specifier) => {
|
|
573
|
+
(dirOwnerSets[dir] ??= []).push(specifier);
|
|
574
|
+
};
|
|
437
575
|
const alreadyIngested = (relPath) => hasEntry(relPath) || pushed.has(relPath);
|
|
438
576
|
for (const specifier of specifiers) {
|
|
439
577
|
let absEntry;
|
|
@@ -456,12 +594,14 @@ async function collectExternalPackageSources(opts) {
|
|
|
456
594
|
let staleDist = false;
|
|
457
595
|
if (existsSync(srcDir)) {
|
|
458
596
|
packageDirs.push(srcDir);
|
|
459
|
-
|
|
597
|
+
claimDir(srcDir, specifier);
|
|
598
|
+
onPackageResolved?.(specifier, srcDir);
|
|
460
599
|
const srcEntry = sourceEntryForSpecifier(specifier, srcDir, extensionsSet);
|
|
461
600
|
if (srcEntry) {
|
|
462
601
|
packageMap[specifier] = relative(rootDir, srcEntry);
|
|
463
602
|
sourceEntries.set(specifier, srcEntry);
|
|
464
603
|
} else packageMap[specifier] = relative(rootDir, absEntry);
|
|
604
|
+
keyframesScanEntries.set(specifier, srcEntry ?? absEntry);
|
|
465
605
|
if (!isAbsolute(specifier)) {
|
|
466
606
|
const packageName = bareSpecifierPackageName(specifier);
|
|
467
607
|
if (packageName !== specifier && !(packageName in packageMap)) {
|
|
@@ -469,13 +609,11 @@ async function collectExternalPackageSources(opts) {
|
|
|
469
609
|
if (rootEntry) {
|
|
470
610
|
packageMap[packageName] = relative(rootDir, rootEntry);
|
|
471
611
|
sourceEntries.set(packageName, rootEntry);
|
|
612
|
+
keyframesScanEntries.set(packageName, rootEntry);
|
|
472
613
|
}
|
|
473
614
|
}
|
|
474
615
|
}
|
|
475
|
-
const pkgFiles =
|
|
476
|
-
const inPkg = relative(srcDir, absPath);
|
|
477
|
-
return !PACKAGE_SRC_EXCLUDES.some((pattern) => inPkg.includes(pattern));
|
|
478
|
-
});
|
|
616
|
+
const pkgFiles = walkPackageSources(srcDir, extensionsSet);
|
|
479
617
|
staleDist = distEntryIsStale(absEntry, srcDir, pkgFiles);
|
|
480
618
|
for (const pkgFile of pkgFiles) {
|
|
481
619
|
const relPath = relative(rootDir, pkgFile);
|
|
@@ -503,8 +641,10 @@ async function collectExternalPackageSources(opts) {
|
|
|
503
641
|
} else {
|
|
504
642
|
const outputDir = dirname(absEntry);
|
|
505
643
|
packageDirs.push(outputDir);
|
|
506
|
-
|
|
644
|
+
claimDir(outputDir, specifier);
|
|
645
|
+
onPackageResolved?.(specifier, outputDir);
|
|
507
646
|
packageMap[specifier] = relative(rootDir, absEntry);
|
|
647
|
+
keyframesScanEntries.set(specifier, absEntry);
|
|
508
648
|
const outputExtensions = new Set(extensionsSet);
|
|
509
649
|
outputExtensions.add(extname(absEntry));
|
|
510
650
|
const outputFiles = discoverFiles(outputDir, outputDir, [], outputExtensions).filter((file) => {
|
|
@@ -546,12 +686,71 @@ async function collectExternalPackageSources(opts) {
|
|
|
546
686
|
entries,
|
|
547
687
|
packageMap,
|
|
548
688
|
sourceEntries,
|
|
689
|
+
keyframesScanEntries,
|
|
549
690
|
packageDirs,
|
|
550
|
-
|
|
691
|
+
dirOwnerSets,
|
|
551
692
|
fileOwners,
|
|
552
693
|
outcomes
|
|
553
694
|
};
|
|
554
695
|
}
|
|
696
|
+
/** First-declared specifier per package dir — the single-value ownership
|
|
697
|
+
* view correlation consumers key on, derived from `dirOwnerSets`. */
|
|
698
|
+
function firstOwners(dirOwnerSets) {
|
|
699
|
+
const owners = {};
|
|
700
|
+
for (const [dir, specifiers] of Object.entries(dirOwnerSets)) if (specifiers.length > 0) owners[dir] = specifiers[0];
|
|
701
|
+
return owners;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Excise a set of rejected specifiers from a collection result ATOMICALLY
|
|
705
|
+
* (openspec: external-source-watch-ingestion, design D5): the returned copy
|
|
706
|
+
* carries no entries, package-map targets, source entries, package dirs, or
|
|
707
|
+
* ownership for the rejected packages — a package dir is removed only when
|
|
708
|
+
* EVERY specifier that claimed it is rejected (a dir-level rejection, such
|
|
709
|
+
* as the cross-volume gate, always rejects them together). Outcome records
|
|
710
|
+
* are reporting inputs, not membership, and pass through untouched.
|
|
711
|
+
*/
|
|
712
|
+
function excludeCollectedPackages(collected, rejectedSpecifiers, rootDir) {
|
|
713
|
+
if (rejectedSpecifiers.size === 0) return collected;
|
|
714
|
+
const rejectedDirs = Object.entries(collected.dirOwnerSets).filter(([, specs]) => specs.every((s) => rejectedSpecifiers.has(s))).map(([dir]) => dir);
|
|
715
|
+
const underRejectedDir = (absPath) => rejectedDirs.some((dir) => isPathWithinRoot(dir, absPath));
|
|
716
|
+
const targetRejected = (specifier, absTarget) => rejectedSpecifiers.has(specifier) || underRejectedDir(absTarget);
|
|
717
|
+
const packageMap = {};
|
|
718
|
+
for (const [specifier, relTarget] of Object.entries(collected.packageMap)) {
|
|
719
|
+
if (targetRejected(specifier, resolve(rootDir, relTarget))) continue;
|
|
720
|
+
packageMap[specifier] = relTarget;
|
|
721
|
+
}
|
|
722
|
+
const sourceEntries = /* @__PURE__ */ new Map();
|
|
723
|
+
for (const [specifier, absEntry] of collected.sourceEntries) {
|
|
724
|
+
if (targetRejected(specifier, absEntry)) continue;
|
|
725
|
+
sourceEntries.set(specifier, absEntry);
|
|
726
|
+
}
|
|
727
|
+
const keyframesScanEntries = /* @__PURE__ */ new Map();
|
|
728
|
+
for (const [specifier, absEntry] of collected.keyframesScanEntries) {
|
|
729
|
+
if (targetRejected(specifier, absEntry)) continue;
|
|
730
|
+
keyframesScanEntries.set(specifier, absEntry);
|
|
731
|
+
}
|
|
732
|
+
const dirOwnerSets = {};
|
|
733
|
+
for (const [dir, specs] of Object.entries(collected.dirOwnerSets)) {
|
|
734
|
+
const kept = specs.filter((s) => !rejectedSpecifiers.has(s));
|
|
735
|
+
if (kept.length === 0) continue;
|
|
736
|
+
dirOwnerSets[dir] = kept;
|
|
737
|
+
}
|
|
738
|
+
const fileOwners = {};
|
|
739
|
+
for (const [relPath, owner] of Object.entries(collected.fileOwners)) {
|
|
740
|
+
if (rejectedSpecifiers.has(owner)) continue;
|
|
741
|
+
fileOwners[relPath] = owner;
|
|
742
|
+
}
|
|
743
|
+
return {
|
|
744
|
+
entries: collected.entries.filter((entry) => !rejectedSpecifiers.has(collected.fileOwners[entry.path])),
|
|
745
|
+
packageMap,
|
|
746
|
+
sourceEntries,
|
|
747
|
+
keyframesScanEntries,
|
|
748
|
+
packageDirs: collected.packageDirs.filter((dir) => !rejectedDirs.includes(dir)),
|
|
749
|
+
dirOwnerSets,
|
|
750
|
+
fileOwners,
|
|
751
|
+
outcomes: collected.outcomes
|
|
752
|
+
};
|
|
753
|
+
}
|
|
555
754
|
/**
|
|
556
755
|
* Extract external DS package names from inheritance declarations in the
|
|
557
756
|
* system file.
|
|
@@ -921,7 +1120,7 @@ function buildSourceTokenIndex(opts) {
|
|
|
921
1120
|
if (existsSync(join(packageRoot, "package.json"))) addOwnerDir(packageRoot, specifier);
|
|
922
1121
|
}
|
|
923
1122
|
for (const [modulePath, exports] of Object.entries(manifests)) {
|
|
924
|
-
const owner = realDirOwners.find(({ dir }) =>
|
|
1123
|
+
const owner = realDirOwners.find(({ dir }) => isPathWithinRoot(dir, modulePath));
|
|
925
1124
|
if (!owner) continue;
|
|
926
1125
|
let tokens = index.get(owner.specifier);
|
|
927
1126
|
if (!tokens) {
|
|
@@ -1062,16 +1261,42 @@ function postProcessCss(css, opts) {
|
|
|
1062
1261
|
/** Stable code for selector forms with no substitutable subject.
|
|
1063
1262
|
* Mirrors the Rust constant in `extract-v2/src/eval.rs`. */
|
|
1064
1263
|
const SELECTOR_UNSUPPORTED_SUBJECT = "animus.selector.unsupported-subject";
|
|
1264
|
+
/** Unresolved-parent chain-drop message (mirrors the Rust diagnostic in
|
|
1265
|
+
* `extract-v2` — the ONE encoding of this message shape; consumers match
|
|
1266
|
+
* through the helpers below, never their own regex copies). */
|
|
1267
|
+
const UNRESOLVED_PARENT_RE = /chain dropped: could not resolve parent component '([^']+)'/;
|
|
1268
|
+
/** True when the diagnostic reports a chain dropped for an unresolved
|
|
1269
|
+
* parent component. */
|
|
1270
|
+
function isUnresolvedParentDrop(diagnostic) {
|
|
1271
|
+
return typeof diagnostic?.message === "string" && UNRESOLVED_PARENT_RE.test(diagnostic.message);
|
|
1272
|
+
}
|
|
1273
|
+
/** The parent binding named by an unresolved-parent drop, or null when the
|
|
1274
|
+
* diagnostic is not one. */
|
|
1275
|
+
function unresolvedParentName(diagnostic) {
|
|
1276
|
+
if (typeof diagnostic?.message !== "string") return null;
|
|
1277
|
+
return UNRESOLVED_PARENT_RE.exec(diagnostic.message)?.[1] ?? null;
|
|
1278
|
+
}
|
|
1065
1279
|
/** True when the selector string carries at least one substitutable `&`
|
|
1066
1280
|
* subject outside quoted text (mirrors the Rust `selector_subject` walk —
|
|
1067
1281
|
* ancestor, leading, and repeated subjects all count; a `&` inside a
|
|
1068
1282
|
* quoted attribute value does not). */
|
|
1069
1283
|
function hasSelectorSubject(value) {
|
|
1070
1284
|
let quote = null;
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1285
|
+
let escaped = false;
|
|
1286
|
+
for (const c of value) {
|
|
1287
|
+
if (escaped) {
|
|
1288
|
+
escaped = false;
|
|
1289
|
+
continue;
|
|
1290
|
+
}
|
|
1291
|
+
if (c === "\\") {
|
|
1292
|
+
escaped = true;
|
|
1293
|
+
continue;
|
|
1294
|
+
}
|
|
1295
|
+
if (quote !== null) {
|
|
1296
|
+
if (c === quote) quote = null;
|
|
1297
|
+
} else if (c === "\"" || c === "'") quote = c;
|
|
1298
|
+
else if (c === "&") return true;
|
|
1299
|
+
}
|
|
1075
1300
|
return false;
|
|
1076
1301
|
}
|
|
1077
1302
|
/**
|
|
@@ -1644,6 +1869,79 @@ async function preprocessMdx(source, filename) {
|
|
|
1644
1869
|
}
|
|
1645
1870
|
}
|
|
1646
1871
|
//#endregion
|
|
1872
|
+
//#region pipeline/replacement-plans.ts
|
|
1873
|
+
const snapshotByManifest = /* @__PURE__ */ new WeakMap();
|
|
1874
|
+
function snapshotFilePlans(manifest) {
|
|
1875
|
+
const memoKey = manifest !== null && typeof manifest === "object" ? manifest : null;
|
|
1876
|
+
if (memoKey) {
|
|
1877
|
+
const cached = snapshotByManifest.get(memoKey);
|
|
1878
|
+
if (cached) return cached;
|
|
1879
|
+
}
|
|
1880
|
+
const entriesByFile = /* @__PURE__ */ new Map();
|
|
1881
|
+
for (const [id, desc] of Object.entries(manifest?.components ?? {})) {
|
|
1882
|
+
const file = desc.file;
|
|
1883
|
+
if (!file) continue;
|
|
1884
|
+
const list = entriesByFile.get(file) ?? [];
|
|
1885
|
+
list.push([id, desc.replacement ?? ""]);
|
|
1886
|
+
entriesByFile.set(file, list);
|
|
1887
|
+
}
|
|
1888
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
1889
|
+
for (const [file, entries] of entriesByFile) {
|
|
1890
|
+
entries.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
1891
|
+
snapshot.set(file, JSON.stringify(entries));
|
|
1892
|
+
}
|
|
1893
|
+
if (memoKey) snapshotByManifest.set(memoKey, snapshot);
|
|
1894
|
+
return snapshot;
|
|
1895
|
+
}
|
|
1896
|
+
/**
|
|
1897
|
+
* Rel paths whose plan changed between two snapshots: absent→present,
|
|
1898
|
+
* present→absent, and any change to membership or replacement content.
|
|
1899
|
+
* `exclude` drops one path (the changed file itself on the edit path — its
|
|
1900
|
+
* own modules are already in the update set).
|
|
1901
|
+
*/
|
|
1902
|
+
function diffFilePlans(prev, next, opts) {
|
|
1903
|
+
const changed = /* @__PURE__ */ new Set();
|
|
1904
|
+
for (const [file, plan] of next) if (prev.get(file) !== plan) changed.add(file);
|
|
1905
|
+
for (const file of prev.keys()) if (!next.has(file)) changed.add(file);
|
|
1906
|
+
if (opts?.exclude) changed.delete(opts.exclude);
|
|
1907
|
+
return [...changed].sort();
|
|
1908
|
+
}
|
|
1909
|
+
/** Domain prefix keeping the epoch hash disjoint from every other
|
|
1910
|
+
* contentHash use in the pipeline (design D5). */
|
|
1911
|
+
const REPLACEMENT_PLANS_DOMAIN = "animus-replacement-plans-v1\0";
|
|
1912
|
+
/** Section marker for the served-dependency witness. Leads with NUL: every
|
|
1913
|
+
* plan entry ends `…\0` and neither file paths nor plan JSON contain NUL,
|
|
1914
|
+
* so `\0\0` is unreachable from entry serialization alone — a snapshot can
|
|
1915
|
+
* never forge the witness section. */
|
|
1916
|
+
const SERVED_DEPENDENCY_DOMAIN = "\0animus-served-dependency-v1\0";
|
|
1917
|
+
/**
|
|
1918
|
+
* Canonical replacement epoch: contentHash over the domain-prefixed, sorted
|
|
1919
|
+
* canonical serialization of a file-plan snapshot — each entry contributes
|
|
1920
|
+
* `file + '\0' + plan + '\0'` (unambiguous: neither file paths nor the
|
|
1921
|
+
* JSON plan strings contain NUL). Byte-identical plans → identical epoch;
|
|
1922
|
+
* any membership/replacement/absent↔present change moves it.
|
|
1923
|
+
*
|
|
1924
|
+
* `servedDependencyWitness` extends the epoch to content the plans cannot
|
|
1925
|
+
* see but restored modules depend on: transformed modules import the
|
|
1926
|
+
* session's served system-props artifact, so a consumer passes that
|
|
1927
|
+
* artifact's content here and an offline change to it moves the epoch —
|
|
1928
|
+
* invalidating persistent-cache snapshots that reference the old epoch
|
|
1929
|
+
* artifact. Absence and empty-string are distinct values.
|
|
1930
|
+
*
|
|
1931
|
+
* This is THE epoch definition — integrations consume this hash (or the
|
|
1932
|
+
* snapshot diff) and never define their own. Epoch values compare only for
|
|
1933
|
+
* equality (a moved value invalidates), so the serialization is free to
|
|
1934
|
+
* evolve with a domain bump: sessions running different serializations
|
|
1935
|
+
* simply disagree once and rebuild.
|
|
1936
|
+
*/
|
|
1937
|
+
function hashReplacementPlans(snapshot, servedDependencyWitness) {
|
|
1938
|
+
const entries = [...snapshot.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
1939
|
+
let serialized = REPLACEMENT_PLANS_DOMAIN;
|
|
1940
|
+
for (const [file, plan] of entries) serialized += file + "\0" + plan + "\0";
|
|
1941
|
+
if (servedDependencyWitness !== void 0) serialized += SERVED_DEPENDENCY_DOMAIN + servedDependencyWitness;
|
|
1942
|
+
return contentHash(serialized);
|
|
1943
|
+
}
|
|
1944
|
+
//#endregion
|
|
1647
1945
|
//#region pipeline/utils.ts
|
|
1648
1946
|
/** Convert camelCase CSS property names to kebab-case. */
|
|
1649
1947
|
function camelToKebab(str) {
|
|
@@ -1695,4 +1993,4 @@ function realpathThroughNearestExistingAncestor(path) {
|
|
|
1695
1993
|
}
|
|
1696
1994
|
}
|
|
1697
1995
|
//#endregion
|
|
1698
|
-
export { ANIMUS_LAYERS, DEFAULT_EXTENSIONS, KEYFRAMES_EXPORT_COLLISION, KEYFRAMES_EXTERNAL_ENTRY_FAILED, RETIRED_ENGINE_MESSAGE, applyPrefix, applyUnitFallback, assembleStylesheet, assertNoRetiredEngineSelection, buildAnalysisInputs, buildAnalyzeProjectArgs, buildDynamicPropConfig, buildPathAliasesJson, buildSystemPropsModule, camelToKebab, clearEngineCache, collectExternalPackageSources, contentHash, createV2EngineApi, discoverFiles, enforceExternalTokenContracts, extractSystemFilePackages, findAssetSpecifiers, findPackageRoot, formatRustTimingWaterfall, loadSystemConfig, mergeExternalKeyframes, postProcessCss, preprocessMdx, readTsconfigAliasPairs, resolveAssetFile, resolveLightningTargets, resolveThroughPathAliases, runProjectAnalysis, serializeStaticCss, staleDistIncludesMessage, stripLeadingLayerDeclaration, substituteAssetPlaceholders, surfaceManifestDiagnostics, toWatchKeys, unresolvableIncludesMessage, validateLayerOrder };
|
|
1996
|
+
export { ANIMUS_LAYERS, DEFAULT_EXTENSIONS, KEYFRAMES_EXPORT_COLLISION, KEYFRAMES_EXTERNAL_ENTRY_FAILED, RETIRED_ENGINE_MESSAGE, applyPrefix, applyUnitFallback, assembleStylesheet, assertNoRetiredEngineSelection, buildAnalysisInputs, buildAnalyzeProjectArgs, buildDynamicPropConfig, buildPathAliasesJson, buildSystemPropsModule, camelToKebab, clearEngineCache, collectExternalPackageSources, contentHash, createSourceIdentity, createV2EngineApi, diffFilePlans, discoverFiles, enforceExternalTokenContracts, excludeCollectedPackages, extractSystemFilePackages, findAssetSpecifiers, findPackageRoot, firstOwners, formatRustTimingWaterfall, hashReplacementPlans, isExcludedPackageRelativePath, isPathWithinRoot, isUnresolvedParentDrop, loadSystemConfig, mergeExternalKeyframes, postProcessCss, preprocessMdx, readTsconfigAliasPairs, resolveAbsolutePathSpecifier, resolveAssetFile, resolveLightningTargets, resolveThroughPathAliases, runProjectAnalysis, serializeStaticCss, sharesVolumeRoot, snapshotFilePlans, staleDistIncludesMessage, stripLeadingLayerDeclaration, substituteAssetPlaceholders, surfaceManifestDiagnostics, toWatchKeys, unresolvableIncludesMessage, unresolvedParentName, validateLayerOrder, walkPackageSources };
|
|
@@ -15,6 +15,16 @@ export type ManifestDiagnostic = {
|
|
|
15
15
|
/** Stable code for selector forms with no substitutable subject.
|
|
16
16
|
* Mirrors the Rust constant in `extract-v2/src/eval.rs`. */
|
|
17
17
|
export declare const SELECTOR_UNSUPPORTED_SUBJECT = "animus.selector.unsupported-subject";
|
|
18
|
+
/** True when the diagnostic reports a chain dropped for an unresolved
|
|
19
|
+
* parent component. */
|
|
20
|
+
export declare function isUnresolvedParentDrop(diagnostic: {
|
|
21
|
+
message?: unknown;
|
|
22
|
+
}): boolean;
|
|
23
|
+
/** The parent binding named by an unresolved-parent drop, or null when the
|
|
24
|
+
* diagnostic is not one. */
|
|
25
|
+
export declare function unresolvedParentName(diagnostic: {
|
|
26
|
+
message?: unknown;
|
|
27
|
+
}): string | null;
|
|
18
28
|
export interface DiagnosticPolicy {
|
|
19
29
|
/** When true, error-severity diagnostics throw instead of warning. */
|
|
20
30
|
strict?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-diagnostics.d.ts","sourceRoot":"","sources":["../pipeline/manifest-diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB;6EACyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;sBACkB;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;6DAC6D;AAC7D,eAAO,MAAM,4BAA4B,wCACF,CAAC;
|
|
1
|
+
{"version":3,"file":"manifest-diagnostics.d.ts","sourceRoot":"","sources":["../pipeline/manifest-diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB;6EACyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;sBACkB;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;6DAC6D;AAC7D,eAAO,MAAM,4BAA4B,wCACF,CAAC;AAQxC;wBACwB;AACxB,wBAAgB,sBAAsB,CAAC,UAAU,EAAE;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAKV;AAED;6BAC6B;AAC7B,wBAAgB,oBAAoB,CAAC,UAAU,EAAE;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,GAAG,IAAI,CAGhB;AAED,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;gEAC4D;IAC5D,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAChC;AAED;;;wCAGwC;AACxC,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAqBzD;AAED;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAC7C,mBAAmB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC7C,kBAAkB,EAAE,CAuBtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE;IAAE,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAAE,EAChD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAC/B,MAAM,GAAE,gBAAqB,GAC5B,IAAI,CA+BN"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-plan snapshot/diff — the invalidation candidate source shared by
|
|
3
|
+
* every analysis path (openspec: dev-transform-coherence,
|
|
4
|
+
* dev-served-transform-coherence). A file's plan is the keyed, ordered set
|
|
5
|
+
* of (component id, replacement) pairs the manifest holds for it. A file
|
|
6
|
+
* with NO entries is ABSENT from the snapshot — a distinct state from a
|
|
7
|
+
* present entry whose replacement is empty, so raw↔extracted transitions
|
|
8
|
+
* are plan changes like any other.
|
|
9
|
+
*
|
|
10
|
+
* Lives in the shared pipeline package so the Vite diff consumer and the
|
|
11
|
+
* Next (webpack/Turbopack) epoch consumers share ONE semantic definition
|
|
12
|
+
* (design D5, next-webpack-served-transform-coherence).
|
|
13
|
+
*/
|
|
14
|
+
export type FilePlanSnapshot = Map<string, string>;
|
|
15
|
+
export declare function snapshotFilePlans(manifest: any): FilePlanSnapshot;
|
|
16
|
+
/**
|
|
17
|
+
* Rel paths whose plan changed between two snapshots: absent→present,
|
|
18
|
+
* present→absent, and any change to membership or replacement content.
|
|
19
|
+
* `exclude` drops one path (the changed file itself on the edit path — its
|
|
20
|
+
* own modules are already in the update set).
|
|
21
|
+
*/
|
|
22
|
+
export declare function diffFilePlans(prev: FilePlanSnapshot, next: FilePlanSnapshot, opts?: {
|
|
23
|
+
exclude?: string;
|
|
24
|
+
}): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Canonical replacement epoch: contentHash over the domain-prefixed, sorted
|
|
27
|
+
* canonical serialization of a file-plan snapshot — each entry contributes
|
|
28
|
+
* `file + '\0' + plan + '\0'` (unambiguous: neither file paths nor the
|
|
29
|
+
* JSON plan strings contain NUL). Byte-identical plans → identical epoch;
|
|
30
|
+
* any membership/replacement/absent↔present change moves it.
|
|
31
|
+
*
|
|
32
|
+
* `servedDependencyWitness` extends the epoch to content the plans cannot
|
|
33
|
+
* see but restored modules depend on: transformed modules import the
|
|
34
|
+
* session's served system-props artifact, so a consumer passes that
|
|
35
|
+
* artifact's content here and an offline change to it moves the epoch —
|
|
36
|
+
* invalidating persistent-cache snapshots that reference the old epoch
|
|
37
|
+
* artifact. Absence and empty-string are distinct values.
|
|
38
|
+
*
|
|
39
|
+
* This is THE epoch definition — integrations consume this hash (or the
|
|
40
|
+
* snapshot diff) and never define their own. Epoch values compare only for
|
|
41
|
+
* equality (a moved value invalidates), so the serialization is free to
|
|
42
|
+
* evolve with a domain bump: sessions running different serializations
|
|
43
|
+
* simply disagree once and rebuild.
|
|
44
|
+
*/
|
|
45
|
+
export declare function hashReplacementPlans(snapshot: FilePlanSnapshot, servedDependencyWitness?: string): string;
|
|
46
|
+
//# sourceMappingURL=replacement-plans.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replacement-plans.d.ts","sourceRoot":"","sources":["../pipeline/replacement-plans.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAQnD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,GAAG,GAAG,gBAAgB,CA4BjE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,gBAAgB,EACtB,IAAI,EAAE,gBAAgB,EACtB,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,MAAM,EAAE,CAUV;AAYD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,EAC1B,uBAAuB,CAAC,EAAE,MAAM,GAC/B,MAAM,CAYR"}
|