@yahoo/uds-create-config 4.54.0 → 4.55.0
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/capture/class-grammar.js +2 -3
- package/dist/configs/platform.d.ts +8 -1
- package/dist/configs/react-native-system.d.ts +21 -9
- package/dist/configs/react-native-system.js +1 -1
- package/dist/configs/system.js +3 -1
- package/dist/css/value-type.js +24 -0
- package/dist/entities/documentation/Documentation.d.ts +1 -1
- package/dist/entities/native/NativeStyleProperty.d.ts +14 -9
- package/dist/entities/native/NativeStyleProperty.js +23 -2
- package/dist/entities/native/NativeToken.d.ts +10 -3
- package/dist/entities/native/NativeToken.js +39 -4
- package/dist/entities/system/Component.js +2 -1
- package/dist/entities/system/GlobalStyle.d.ts +2 -2
- package/dist/entities/system/GlobalStyle.js +2 -1
- package/dist/entities/system/Modifier.d.ts +3 -1
- package/dist/entities/system/Modifier.js +3 -1
- package/dist/entities/system/Settings.d.ts +9 -1
- package/dist/entities/system/Settings.js +6 -2
- package/dist/entities/system/StyleProperty.d.ts +39 -3
- package/dist/entities/system/StyleProperty.js +141 -18
- package/dist/entities/system/Token.d.ts +14 -1
- package/dist/entities/system/Token.js +21 -3
- package/dist/entities/system/calc.d.ts +28 -0
- package/dist/entities/system/calc.js +121 -0
- package/dist/entities/system/color.d.ts +29 -4
- package/dist/entities/system/color.js +61 -8
- package/dist/entities/system/component-module.js +15 -4
- package/dist/entities/system/composed-values.d.ts +3 -2
- package/dist/entities/system/composed-values.js +20 -1
- package/dist/entities/system/defineComponent.d.ts +3 -3
- package/dist/entities/system/link-plan.js +10 -1
- package/dist/entities/system/linked-token-values.d.ts +34 -0
- package/dist/entities/system/linked-token-values.js +135 -0
- package/dist/entities/system/shadow.d.ts +9 -7
- package/dist/entities/system/shadow.js +8 -7
- package/dist/entities/system/style-bag.d.ts +1 -1
- package/dist/entities/system/token-index.js +45 -2
- package/dist/entities/system/token-values.d.ts +3 -2
- package/dist/entities/system/token-values.js +9 -9
- package/dist/framework/Config.d.ts +14 -18
- package/dist/framework/Config.js +105 -55
- package/dist/framework/class-names.d.ts +47 -7
- package/dist/framework/class-names.js +115 -14
- package/dist/framework/defineEntity.d.ts +3 -1
- package/dist/framework/defineEntity.js +3 -1
- package/dist/framework/inline-sources.d.ts +3 -3
- package/dist/framework/inline-sources.js +1 -1
- package/dist/framework/projections.d.ts +84 -3
- package/dist/framework/projections.js +315 -20
- package/dist/framework/ref-graph.js +1 -1
- package/dist/framework/registry.d.ts +7 -0
- package/dist/framework/registry.js +2 -1
- package/dist/framework/schema-version.d.ts +1 -1
- package/dist/framework/schema-version.js +5 -5
- package/dist/framework/utils/group.d.ts +2 -1
- package/dist/framework/utils/refs.d.ts +19 -2
- package/dist/framework/utils/refs.js +100 -12
- package/dist/index.d.ts +12 -10
- package/dist/index.js +10 -8
- package/dist/migrations/20261001162046_oklch_and_emit_fields.d.ts +25 -0
- package/dist/migrations/20261001162046_oklch_and_emit_fields.js +10 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -72,7 +72,7 @@ interface RecordedSource {
|
|
|
72
72
|
* The dense-counter `2` a short-lived scheme stamped before the chain existed reads as the mint
|
|
73
73
|
* that replaced it (see `detectedWireVersion`).
|
|
74
74
|
*/
|
|
75
|
-
declare const SERIALIZED_CONFIG_VERSION =
|
|
75
|
+
declare const SERIALIZED_CONFIG_VERSION = 20261001162046;
|
|
76
76
|
interface SerializedConfig {
|
|
77
77
|
/** See {@link SERIALIZED_CONFIG_VERSION}. Always written; a stored artifact may lack it. */
|
|
78
78
|
readonly version: number;
|
|
@@ -1470,19 +1470,15 @@ declare class Config {
|
|
|
1470
1470
|
/**
|
|
1471
1471
|
* A slug this config doesn't declare, answered by a source that does.
|
|
1472
1472
|
*
|
|
1473
|
-
* It
|
|
1474
|
-
*
|
|
1475
|
-
*
|
|
1476
|
-
* `top` has no way to name it, because the slug belongs to the system that wrote the ref. Answering
|
|
1477
|
-
* `undefined` makes the ref unresolvable, which surfaces as `Cannot inline "style-property:bg@base"`
|
|
1478
|
-
* and takes the whole publish down. Depth one works only because there the slug is the consumer's own.
|
|
1473
|
+
* It supports refs in older published chains that still spell a transitive slug directly. New
|
|
1474
|
+
* borrowed bodies scope that name through their owner (`@mid~base`) so a consumer's own `base`
|
|
1475
|
+
* cannot shadow it, but an artifact written before that scoping may still carry `@base`.
|
|
1479
1476
|
*
|
|
1480
1477
|
* Read the way {@link configFor} already describes resolution: it hops configs, each answering for
|
|
1481
1478
|
* the links it declares. This is the same hop for the source address rather than the entity.
|
|
1482
1479
|
*
|
|
1483
|
-
* Local first
|
|
1484
|
-
* that declares `base` itself keeps meaning its own
|
|
1485
|
-
* wrote.
|
|
1480
|
+
* Local first for an ordinary slug. {@link sourceFor} tries {@link ownSourceFor} before reaching
|
|
1481
|
+
* here, so a config that declares `base` itself keeps meaning its own.
|
|
1486
1482
|
*
|
|
1487
1483
|
* Memoized per instance including the misses: a dangling sourced ref is read repeatedly, since
|
|
1488
1484
|
* `list`, `sourceClosure` and `toJSON` all pass over it, and each miss would otherwise re-walk every
|
|
@@ -2422,19 +2418,19 @@ declare class Config {
|
|
|
2422
2418
|
*/
|
|
2423
2419
|
recordedSources(): Record<string, RecordedSource>;
|
|
2424
2420
|
private recordSources;
|
|
2421
|
+
/** Record one source without walking every other link this config declares. */
|
|
2422
|
+
private recordSource;
|
|
2425
2423
|
/**
|
|
2426
2424
|
* Every slug this config's refs name, declared here or not — what {@link recordSources} owes a
|
|
2427
2425
|
* closure for.
|
|
2428
2426
|
*
|
|
2429
|
-
* Declared slugs are only half of it. Materializing a published chain keeps a ref whose target has
|
|
2430
|
-
* value to collapse into, so a component borrowed from `mid`
|
|
2431
|
-
*
|
|
2432
|
-
*
|
|
2433
|
-
* resolves to nothing.
|
|
2427
|
+
* Declared slugs are only half of it. Materializing a published chain keeps a ref whose target has
|
|
2428
|
+
* no value to collapse into, so a component borrowed from `mid` can arrive holding
|
|
2429
|
+
* `style-property:bg@mid~base`. Recording only the pins this config declares would leave that
|
|
2430
|
+
* routed ref with nothing behind it.
|
|
2434
2431
|
*
|
|
2435
|
-
* Reachability is already what a closure means; this applies the same rule to the source address
|
|
2436
|
-
*
|
|
2437
|
-
* the recorded artifact is self-contained.
|
|
2432
|
+
* Reachability is already what a closure means; this applies the same rule to the source address.
|
|
2433
|
+
* {@link sourceFor} follows the route, and the recorded artifact remains self-contained.
|
|
2438
2434
|
*
|
|
2439
2435
|
* Skipped entirely for a config that borrows nothing, so the common serialize walks nothing extra.
|
|
2440
2436
|
*/
|
package/dist/framework/Config.js
CHANGED
|
@@ -5,6 +5,7 @@ import { describePatch } from "./plan.js";
|
|
|
5
5
|
import { applyPathDelta, isPlainObject, namedFields, pathSegments, sectionDelta, touchedFields } from "./utils/field-path.js";
|
|
6
6
|
import { METADATA_KEYS, declaredField } from "./utils/field-schema.js";
|
|
7
7
|
import { dataSchema, resolveInputSchema } from "./schemas.js";
|
|
8
|
+
import { isComposedValue } from "../entities/system/composed-values.js";
|
|
8
9
|
import { borrowedSlug, classifyOverlay } from "./source-integrity.js";
|
|
9
10
|
import { kindBorrowable, titleCase } from "./registry.js";
|
|
10
11
|
import { isGroupBody } from "./utils/group.js";
|
|
@@ -145,11 +146,13 @@ function movesSource(patch, sourceIdentity) {
|
|
|
145
146
|
* nothing here.
|
|
146
147
|
*/
|
|
147
148
|
function reslug(entries, { from, to }) {
|
|
148
|
-
|
|
149
|
-
|
|
149
|
+
const moved = [...entries].filter(([slug]) => slug === from || slug.startsWith(`${from}~`));
|
|
150
|
+
if (moved.length === 0) return entries;
|
|
150
151
|
const next = new Map(entries);
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
for (const [slug, held] of moved) {
|
|
153
|
+
next.delete(slug);
|
|
154
|
+
if (to !== void 0) next.set(`${to}${slug.slice(from.length)}`, held);
|
|
155
|
+
}
|
|
153
156
|
return next;
|
|
154
157
|
}
|
|
155
158
|
/** A source as given — live, wrapped, or serialized — as the `LiveConfig` the state holds. */
|
|
@@ -2495,16 +2498,23 @@ var Config = class Config {
|
|
|
2495
2498
|
*/
|
|
2496
2499
|
extensionBody(kind, extension) {
|
|
2497
2500
|
const source = this.configFor(extension);
|
|
2501
|
+
if (!source) return void 0;
|
|
2498
2502
|
const base = source?.resolve(kind, pathOf(extension));
|
|
2499
2503
|
if (!base) return void 0;
|
|
2500
2504
|
const slug = sourceOf(extension);
|
|
2501
2505
|
const owns = (kindName) => source?.ownedKinds().includes(kindName) ?? false;
|
|
2502
|
-
|
|
2506
|
+
const merged = extendBody(slug ? qualifyRefs({
|
|
2503
2507
|
value: base.toJSON(),
|
|
2504
2508
|
source: slug,
|
|
2505
2509
|
owns,
|
|
2506
2510
|
namesItAlready: (target) => this.borrowsExactly(target, slug)
|
|
2507
2511
|
}) : base.toJSON(), extension.extend ?? {});
|
|
2512
|
+
return this.entityOf(kind)?.prepareLinkedBody?.({
|
|
2513
|
+
path: pathOf(extension),
|
|
2514
|
+
body: merged,
|
|
2515
|
+
source,
|
|
2516
|
+
config: this
|
|
2517
|
+
}) ?? merged;
|
|
2508
2518
|
}
|
|
2509
2519
|
/**
|
|
2510
2520
|
* Resolve one locally extended linked item: the pinned source body, shallowly overlaid by the fields
|
|
@@ -2531,7 +2541,16 @@ var Config = class Config {
|
|
|
2531
2541
|
if (cached === null && !strict) return void 0;
|
|
2532
2542
|
const entry = this.entityOf(kind);
|
|
2533
2543
|
if (!entry) return void 0;
|
|
2534
|
-
|
|
2544
|
+
let merged;
|
|
2545
|
+
try {
|
|
2546
|
+
merged = this.extensionBody(kind, extension);
|
|
2547
|
+
} catch (error) {
|
|
2548
|
+
if (!strict) {
|
|
2549
|
+
cache.set(cacheKey, null);
|
|
2550
|
+
return;
|
|
2551
|
+
}
|
|
2552
|
+
throw error;
|
|
2553
|
+
}
|
|
2535
2554
|
if (!merged) return void 0;
|
|
2536
2555
|
const parsed = dataSchema(entry.schemas, "create", {
|
|
2537
2556
|
config: this,
|
|
@@ -2573,10 +2592,18 @@ var Config = class Config {
|
|
|
2573
2592
|
ok: false,
|
|
2574
2593
|
error: `This system has no "${kind}", so nothing of that kind can be borrowed from "${slug}".`
|
|
2575
2594
|
};
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2595
|
+
let merged;
|
|
2596
|
+
try {
|
|
2597
|
+
merged = this.extensionBody(kind, {
|
|
2598
|
+
__ref: ref(kind, path, slug).__ref,
|
|
2599
|
+
extend: extend ?? {}
|
|
2600
|
+
});
|
|
2601
|
+
} catch (error) {
|
|
2602
|
+
return {
|
|
2603
|
+
ok: false,
|
|
2604
|
+
error: String(error)
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2580
2607
|
if (!merged) return { ok: true };
|
|
2581
2608
|
const parsed = dataSchema(entry.schemas, "create", {
|
|
2582
2609
|
config: this,
|
|
@@ -2834,6 +2861,14 @@ var Config = class Config {
|
|
|
2834
2861
|
* where the other side can change without us), and the Create badges.
|
|
2835
2862
|
*/
|
|
2836
2863
|
sourceFor(slug) {
|
|
2864
|
+
const hop = slug.indexOf("~");
|
|
2865
|
+
if (hop > 0 && hop < slug.length - 1) {
|
|
2866
|
+
const head = slug.slice(0, hop);
|
|
2867
|
+
const tail = slug.slice(hop + 1);
|
|
2868
|
+
const live = this.liveSourceFor(head);
|
|
2869
|
+
if (live) return live.sourceFor(tail) ?? this.ownSourceFor(slug);
|
|
2870
|
+
return this.ownSourceFor(slug) ?? this.sourceFor(head)?.sourceFor(tail) ?? this.sourceThrough(slug);
|
|
2871
|
+
}
|
|
2837
2872
|
return this.ownSourceFor(slug) ?? this.sourceThrough(slug);
|
|
2838
2873
|
}
|
|
2839
2874
|
/** This config's own answer for a slug — attached, else the closure it recorded. No hop, which is
|
|
@@ -2857,19 +2892,15 @@ var Config = class Config {
|
|
|
2857
2892
|
/**
|
|
2858
2893
|
* A slug this config doesn't declare, answered by a source that does.
|
|
2859
2894
|
*
|
|
2860
|
-
* It
|
|
2861
|
-
*
|
|
2862
|
-
*
|
|
2863
|
-
* `top` has no way to name it, because the slug belongs to the system that wrote the ref. Answering
|
|
2864
|
-
* `undefined` makes the ref unresolvable, which surfaces as `Cannot inline "style-property:bg@base"`
|
|
2865
|
-
* and takes the whole publish down. Depth one works only because there the slug is the consumer's own.
|
|
2895
|
+
* It supports refs in older published chains that still spell a transitive slug directly. New
|
|
2896
|
+
* borrowed bodies scope that name through their owner (`@mid~base`) so a consumer's own `base`
|
|
2897
|
+
* cannot shadow it, but an artifact written before that scoping may still carry `@base`.
|
|
2866
2898
|
*
|
|
2867
2899
|
* Read the way {@link configFor} already describes resolution: it hops configs, each answering for
|
|
2868
2900
|
* the links it declares. This is the same hop for the source address rather than the entity.
|
|
2869
2901
|
*
|
|
2870
|
-
* Local first
|
|
2871
|
-
* that declares `base` itself keeps meaning its own
|
|
2872
|
-
* wrote.
|
|
2902
|
+
* Local first for an ordinary slug. {@link sourceFor} tries {@link ownSourceFor} before reaching
|
|
2903
|
+
* here, so a config that declares `base` itself keeps meaning its own.
|
|
2873
2904
|
*
|
|
2874
2905
|
* Memoized per instance including the misses: a dangling sourced ref is read repeatedly, since
|
|
2875
2906
|
* `list`, `sourceClosure` and `toJSON` all pass over it, and each miss would otherwise re-walk every
|
|
@@ -4823,47 +4854,66 @@ var Config = class Config {
|
|
|
4823
4854
|
recordSources() {
|
|
4824
4855
|
const recorded = new Map(this.state.recorded);
|
|
4825
4856
|
for (const slug of this.reachedSlugs()) {
|
|
4826
|
-
const
|
|
4827
|
-
if (
|
|
4828
|
-
const items = {};
|
|
4829
|
-
const kinds = /* @__PURE__ */ new Set();
|
|
4830
|
-
for (const target of this.sourceClosure(slug)) {
|
|
4831
|
-
const kind = kindOf(target);
|
|
4832
|
-
const path = pathOf(target);
|
|
4833
|
-
const entity = source.resolve(kind, path);
|
|
4834
|
-
if (!entity) continue;
|
|
4835
|
-
kinds.add(kind);
|
|
4836
|
-
items[kind] ??= {};
|
|
4837
|
-
items[kind][path] = entity.toJSON();
|
|
4838
|
-
}
|
|
4839
|
-
if (kinds.size === 0) continue;
|
|
4840
|
-
const state = this.state.sourceStates.get(slug);
|
|
4841
|
-
recorded.set(slug, {
|
|
4842
|
-
...state?.status === "attached" ? { resolved: state.resolved } : {},
|
|
4843
|
-
config: {
|
|
4844
|
-
version: SERIALIZED_CONFIG_VERSION,
|
|
4845
|
-
name: source.name,
|
|
4846
|
-
ownedKinds: [...kinds],
|
|
4847
|
-
items,
|
|
4848
|
-
groups: groupsAbove(source, items)
|
|
4849
|
-
}
|
|
4850
|
-
});
|
|
4857
|
+
const closure = this.recordSource(slug);
|
|
4858
|
+
if (closure) recorded.set(slug, closure);
|
|
4851
4859
|
}
|
|
4852
4860
|
return recorded;
|
|
4853
4861
|
}
|
|
4862
|
+
/** Record one source without walking every other link this config declares. */
|
|
4863
|
+
recordSource(slug) {
|
|
4864
|
+
const source = this.sourceFor(slug);
|
|
4865
|
+
if (!source) return void 0;
|
|
4866
|
+
if (this.state.recorded.has(slug) && !this.liveSourceFor(slug) && source === this.ownSourceFor(slug)) return;
|
|
4867
|
+
const items = {};
|
|
4868
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
4869
|
+
for (const target of this.sourceClosure(slug)) {
|
|
4870
|
+
const kind = kindOf(target);
|
|
4871
|
+
const path = pathOf(target);
|
|
4872
|
+
const entity = source.resolve(kind, path);
|
|
4873
|
+
if (!entity) continue;
|
|
4874
|
+
kinds.add(kind);
|
|
4875
|
+
items[kind] ??= {};
|
|
4876
|
+
items[kind][path] = entity.toJSON();
|
|
4877
|
+
}
|
|
4878
|
+
const settings = source.resolve("settings", "settings");
|
|
4879
|
+
if (settings && source.ownedKinds().includes("settings")) {
|
|
4880
|
+
kinds.add("settings");
|
|
4881
|
+
items.settings = { settings: settings.toJSON() };
|
|
4882
|
+
}
|
|
4883
|
+
if (kinds.size === 0) return void 0;
|
|
4884
|
+
const nestedSlugs = /* @__PURE__ */ new Set();
|
|
4885
|
+
for (const entries of Object.values(items)) for (const body of Object.values(entries)) for (const target of collectRefs(body)) {
|
|
4886
|
+
const nested = sourceOf(target);
|
|
4887
|
+
if (nested !== void 0) nestedSlugs.add(nested);
|
|
4888
|
+
}
|
|
4889
|
+
const nestedSources = Object.fromEntries([...nestedSlugs].flatMap((nested) => {
|
|
4890
|
+
const closure = source.liveSourceFor(nested) ? source.recordSource(nested) : source.state.recorded.get(nested) ?? source.recordSource(nested);
|
|
4891
|
+
return closure ? [[nested, closure]] : [];
|
|
4892
|
+
}));
|
|
4893
|
+
const state = this.state.sourceStates.get(slug);
|
|
4894
|
+
return {
|
|
4895
|
+
...state?.status === "attached" ? { resolved: state.resolved } : {},
|
|
4896
|
+
config: {
|
|
4897
|
+
version: SERIALIZED_CONFIG_VERSION,
|
|
4898
|
+
name: source.name,
|
|
4899
|
+
ownedKinds: [...kinds],
|
|
4900
|
+
items,
|
|
4901
|
+
...Object.keys(nestedSources).length > 0 ? { sources: nestedSources } : {},
|
|
4902
|
+
groups: groupsAbove(source, items)
|
|
4903
|
+
}
|
|
4904
|
+
};
|
|
4905
|
+
}
|
|
4854
4906
|
/**
|
|
4855
4907
|
* Every slug this config's refs name, declared here or not — what {@link recordSources} owes a
|
|
4856
4908
|
* closure for.
|
|
4857
4909
|
*
|
|
4858
|
-
* Declared slugs are only half of it. Materializing a published chain keeps a ref whose target has
|
|
4859
|
-
* value to collapse into, so a component borrowed from `mid`
|
|
4860
|
-
*
|
|
4861
|
-
*
|
|
4862
|
-
* resolves to nothing.
|
|
4910
|
+
* Declared slugs are only half of it. Materializing a published chain keeps a ref whose target has
|
|
4911
|
+
* no value to collapse into, so a component borrowed from `mid` can arrive holding
|
|
4912
|
+
* `style-property:bg@mid~base`. Recording only the pins this config declares would leave that
|
|
4913
|
+
* routed ref with nothing behind it.
|
|
4863
4914
|
*
|
|
4864
|
-
* Reachability is already what a closure means; this applies the same rule to the source address
|
|
4865
|
-
*
|
|
4866
|
-
* the recorded artifact is self-contained.
|
|
4915
|
+
* Reachability is already what a closure means; this applies the same rule to the source address.
|
|
4916
|
+
* {@link sourceFor} follows the route, and the recorded artifact remains self-contained.
|
|
4867
4917
|
*
|
|
4868
4918
|
* Skipped entirely for a config that borrows nothing, so the common serialize walks nothing extra.
|
|
4869
4919
|
*/
|
|
@@ -5264,7 +5314,7 @@ var Config = class Config {
|
|
|
5264
5314
|
* links from the provided sources. A declared `linkedKind` with no provided source throws. */
|
|
5265
5315
|
hydrateFrom(stored, options) {
|
|
5266
5316
|
const claimed = schemaVersionOf(stored);
|
|
5267
|
-
if (claimed >
|
|
5317
|
+
if (claimed > 20261001162046) throw new SchemaVersionTooNew(claimed);
|
|
5268
5318
|
const wire = upgradeSerializedConfig(stored);
|
|
5269
5319
|
if (!Array.isArray(wire.ownedKinds) || typeof wire.items !== "object" || wire.items === null) throw new ConfigFormatError(`Config "${stored.name ?? "system-config"}" cannot be hydrated: this is not a serialized config-v2 config (no "ownedKinds"/"items"). A pre-cutover build artifact converts through the registered cutover migration — import the config type's module (e.g. \`configs/system\`) before hydrating, or port the repo once with \`uds migrate\`.`);
|
|
5270
5320
|
const leftover = wire.options;
|
|
@@ -5369,7 +5419,7 @@ function refusePhantomsIn({ kind, path, body }) {
|
|
|
5369
5419
|
for (const phantom of phantomsIn(body)) rejectData(`${kind}:${path} ${phantom.at.join(".")} holds ${phantom.spelled}${PHANTOM_IN_DATA}`, phantom.at);
|
|
5370
5420
|
}
|
|
5371
5421
|
function isPathSegment(meta, kind, raw) {
|
|
5372
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw) || isRef(raw)) return false;
|
|
5422
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw) || isRef(raw) || isComposedValue(raw)) return false;
|
|
5373
5423
|
const entry = meta.entities.get(kind);
|
|
5374
5424
|
if (!entry) return false;
|
|
5375
5425
|
const create = dataSchema(entry.schemas, "create");
|
|
@@ -5586,7 +5636,7 @@ function extensionChange(entry, kind, path, raw, validate = false) {
|
|
|
5586
5636
|
* every load.
|
|
5587
5637
|
*/
|
|
5588
5638
|
function itemChange(entry, kind, path, raw, validate = false) {
|
|
5589
|
-
const def = isRef(raw) || typeof raw !== "object" || raw === null ? { [entry.primaryField]: raw } : raw;
|
|
5639
|
+
const def = isRef(raw) || isComposedValue(raw) || typeof raw !== "object" || raw === null ? { [entry.primaryField]: raw } : raw;
|
|
5590
5640
|
if (validate) {
|
|
5591
5641
|
const parsed = wholeBodySchema(entry)?.safeParse(def);
|
|
5592
5642
|
if (parsed && !parsed.success) {
|
|
@@ -232,12 +232,45 @@ declare function stylePropClassBase(config: Config, path: string): string;
|
|
|
232
232
|
* The value is a LEAF, which is what a call site writes; an empty leaf is a boolean prop's `true`
|
|
233
233
|
* arm, whose class is the bare stem (`uds-border`) because a flag names no value.
|
|
234
234
|
*
|
|
235
|
-
* A slash
|
|
236
|
-
* is
|
|
237
|
-
*
|
|
238
|
-
* surfaced.
|
|
235
|
+
* A slash in a leaf is a group separator and becomes a dash (`red/500` → `bg-red-500`), except in a
|
|
236
|
+
* leaf that is a fraction, which keeps it (`w-1/2`). A dot is kept (`p-0.5`); the stylesheet writes
|
|
237
|
+
* the class through {@link classSelector}, which escapes both.
|
|
239
238
|
*/
|
|
240
239
|
declare function stylePropClassName(config: Config, path: string, leaf: string): string;
|
|
240
|
+
/** Each value of a prop that names its own class, as the class it is written as. Shared with the
|
|
241
|
+
* emitted runtime, which writes the same class for the same value. */
|
|
242
|
+
declare function stylePropOwnClasses(config: Config, path: string): Map<string, string>;
|
|
243
|
+
/**
|
|
244
|
+
* A leaf as a class spells it. Whitespace becomes a hyphen: a class list splits on it, so
|
|
245
|
+
* `my custom background` would put three classes on the element and match none of the one rule.
|
|
246
|
+
* The emitted `_style-props` runtime applies the same transform to the values a call site passes.
|
|
247
|
+
*/
|
|
248
|
+
declare function classLeaf(leaf: string): string;
|
|
249
|
+
/**
|
|
250
|
+
* A class as a selector: `.p-0\.5`, `.w-1\/2`, `.md\:flex`, `.\32xl\:p-4`. Every character outside
|
|
251
|
+
* an identifier's own is escaped, and a leading digit, which an identifier cannot start with, is
|
|
252
|
+
* written as its code point.
|
|
253
|
+
*/
|
|
254
|
+
declare function classSelector(name: string): string;
|
|
255
|
+
/**
|
|
256
|
+
* Whether a prop's bracketed value has to be written as its arbitrary class rather than inline.
|
|
257
|
+
* An inline style sets each of the prop's `properties` on the element and nothing else, so a prop
|
|
258
|
+
* with a `selector`, its own `declarations`, or a property keyed by a token ref would paint wrong.
|
|
259
|
+
*/
|
|
260
|
+
declare function arbitraryNeedsClass(config: Config, path: string): boolean;
|
|
261
|
+
/**
|
|
262
|
+
* The class a bracketed value is written as — `blur` and `[3px]` → `uds-blur-[3px]`. A space inside
|
|
263
|
+
* the brackets is spelled `_`, which the stylesheet reads back as one.
|
|
264
|
+
*/
|
|
265
|
+
declare function arbitraryClassName({
|
|
266
|
+
config,
|
|
267
|
+
path,
|
|
268
|
+
value
|
|
269
|
+
}: {
|
|
270
|
+
readonly config: Config;
|
|
271
|
+
readonly path: string; /** The authored value, brackets included. */
|
|
272
|
+
readonly value: string;
|
|
273
|
+
}): string;
|
|
241
274
|
/** What a prop bag amounts to once styling is taken out of it. */
|
|
242
275
|
interface SplitStyleProps {
|
|
243
276
|
/** The classes the bag's style props produce, space-joined. */
|
|
@@ -254,8 +287,9 @@ interface SplitStyleProps {
|
|
|
254
287
|
* but the CLASS NAMES both produce come from {@link stylePropClassName}, so the two can't disagree
|
|
255
288
|
* about what a value is called.
|
|
256
289
|
*
|
|
257
|
-
* An off-scale value
|
|
258
|
-
* `style` the caller passed still wins, since that's the
|
|
290
|
+
* An off-scale value lands in `style` on the returned rest, unless the prop needs its arbitrary class
|
|
291
|
+
* ({@link arbitraryNeedsClass}); an explicit `style` the caller passed still wins, since that's the
|
|
292
|
+
* escape hatch of last resort.
|
|
259
293
|
*/
|
|
260
294
|
declare function splitStyleProps({
|
|
261
295
|
config,
|
|
@@ -296,5 +330,11 @@ declare function stylePropClasses(config: Config, path: string): Map<string, str
|
|
|
296
330
|
* the system can predict it. Covering those needs the document as a second source of use.
|
|
297
331
|
*/
|
|
298
332
|
declare function modifierUtilitiesUsed(config: Config): Set<string>;
|
|
333
|
+
/**
|
|
334
|
+
* A class split at the colons that separate its modifiers, as `md:hover:[&_a]:bg-[url(a:b)]` is
|
|
335
|
+
* `md`, `hover`, `[&_a]` and `bg-[url(a:b)]`. A colon inside brackets or parentheses belongs to the
|
|
336
|
+
* value. The last segment is the utility.
|
|
337
|
+
*/
|
|
338
|
+
declare function splitVariants(cls: string): string[];
|
|
299
339
|
//#endregion
|
|
300
|
-
export { ComponentRuleClass, PickedComposite, SplitStyleProps, componentClassBase, componentCompositeClasses, componentLayerClass, componentMotionClasses, componentPropClasses, componentPropComposites, componentRuleClasses, forceModeAttribute, forceModeAttributeOf, forceModeProp, forceModePropGroup, forceModePropValue, forceModeProps, forceStateAttribute, inlineRuleComposites, isForceModeProp, kebabComponent, layerRoutedProps, modifierUtilitiesUsed, motionClassName, ruleCondition, splitStyleProps, stylePropClassBase, stylePropClassName, stylePropClasses, styleRuleMotionClasses };
|
|
340
|
+
export { ComponentRuleClass, PickedComposite, SplitStyleProps, arbitraryClassName, arbitraryNeedsClass, classLeaf, classSelector, componentClassBase, componentCompositeClasses, componentLayerClass, componentMotionClasses, componentPropClasses, componentPropComposites, componentRuleClasses, forceModeAttribute, forceModeAttributeOf, forceModeProp, forceModePropGroup, forceModePropValue, forceModeProps, forceStateAttribute, inlineRuleComposites, isForceModeProp, kebabComponent, layerRoutedProps, modifierUtilitiesUsed, motionClassName, ruleCondition, splitStyleProps, splitVariants, stylePropClassBase, stylePropClassName, stylePropClasses, stylePropOwnClasses, styleRuleMotionClasses };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { isRef, kindOf, memberOf, pathOf, refLeaf } from "./utils/refs.js";
|
|
1
|
+
import { isRef, kindOf, memberOf, pathOf, refLeaf, refOfKey } from "./utils/refs.js";
|
|
2
2
|
import { forwardsOf, rootLayerOf } from "../entities/system/element.js";
|
|
3
3
|
import { createSliceMemo } from "./memo.js";
|
|
4
|
-
import { classPrefixOf, varPrefixOf } from "../entities/system/Settings.js";
|
|
4
|
+
import { classPrefixOf, prefixed, varPrefixOf } from "../entities/system/Settings.js";
|
|
5
5
|
import { storedPreview } from "./preview-store.js";
|
|
6
|
-
import { authoredValue, className, negatedCssValue, renderStyleValue, resolveComponentProps, stylePropLeafForToken, stylePropValueLeaves, stylePropertyPathFor } from "./projections.js";
|
|
6
|
+
import { authoredValue, className, negatedCssValue, renderStyleValue, resolveComponentProps, stylePropEntries, stylePropLeafForToken, stylePropValueLeaves, stylePropertyPathFor } from "./projections.js";
|
|
7
7
|
import { ruleApplies } from "./layer-styles.js";
|
|
8
8
|
//#region src/framework/class-names.ts
|
|
9
9
|
/**
|
|
@@ -279,7 +279,10 @@ function componentCompositeClasses(config, path) {
|
|
|
279
279
|
/** The class a CSS motion preset is applied by. Namespaced, so it doesn't share a space with the
|
|
280
280
|
* style-prop utilities; the `@keyframes` it runs keep their own name. */
|
|
281
281
|
function motionClassName(config, path) {
|
|
282
|
-
return
|
|
282
|
+
return prefixed({
|
|
283
|
+
prefix: classPrefixOf(config),
|
|
284
|
+
name: `motion-${path.replaceAll("/", "-")}`
|
|
285
|
+
});
|
|
283
286
|
}
|
|
284
287
|
/**
|
|
285
288
|
* Every MOTION class a component's style rules apply — a layer bag naming a preset (`motion: 'spin'`).
|
|
@@ -472,7 +475,10 @@ function inlineRuleComposites(config, element, bag) {
|
|
|
472
475
|
const at = member.indexOf("/");
|
|
473
476
|
inlined = mergeStyleBags(inlined ?? {}, {
|
|
474
477
|
...styles,
|
|
475
|
-
[`--${
|
|
478
|
+
[`--${prefixed({
|
|
479
|
+
prefix: varPrefixOf(config),
|
|
480
|
+
name: `composite-${member.slice(0, at)}`
|
|
481
|
+
})}`]: member.slice(at + 1)
|
|
476
482
|
});
|
|
477
483
|
}
|
|
478
484
|
return inlined ? mergeStyleBags(inlined, rest) : bag;
|
|
@@ -587,15 +593,63 @@ function stylePropClassBase(config, path) {
|
|
|
587
593
|
* The value is a LEAF, which is what a call site writes; an empty leaf is a boolean prop's `true`
|
|
588
594
|
* arm, whose class is the bare stem (`uds-border`) because a flag names no value.
|
|
589
595
|
*
|
|
590
|
-
* A slash
|
|
591
|
-
* is
|
|
592
|
-
*
|
|
593
|
-
* surfaced.
|
|
596
|
+
* A slash in a leaf is a group separator and becomes a dash (`red/500` → `bg-red-500`), except in a
|
|
597
|
+
* leaf that is a fraction, which keeps it (`w-1/2`). A dot is kept (`p-0.5`); the stylesheet writes
|
|
598
|
+
* the class through {@link classSelector}, which escapes both.
|
|
594
599
|
*/
|
|
595
600
|
function stylePropClassName(config, path, leaf) {
|
|
601
|
+
const own = ownClassNames(config, path).get(leaf);
|
|
602
|
+
if (own !== void 0) return prefixed({
|
|
603
|
+
prefix: classPrefixOf(config),
|
|
604
|
+
name: own
|
|
605
|
+
});
|
|
596
606
|
const base = stylePropClassBase(config, path);
|
|
597
|
-
const suffix = leaf
|
|
598
|
-
|
|
607
|
+
const suffix = classLeaf(leaf);
|
|
608
|
+
if (!suffix) return base;
|
|
609
|
+
return base ? `${base}-${suffix}` : suffix;
|
|
610
|
+
}
|
|
611
|
+
/** Leaf → the class it names, per prop's entries, for the values that name their own. */
|
|
612
|
+
const ownClassNameCache = /* @__PURE__ */ new WeakMap();
|
|
613
|
+
/** The values of a prop that name their own class, by leaf. */
|
|
614
|
+
function ownClassNames(config, path) {
|
|
615
|
+
const entries = stylePropEntries(config, path);
|
|
616
|
+
let own = ownClassNameCache.get(entries);
|
|
617
|
+
if (!own) {
|
|
618
|
+
const built = /* @__PURE__ */ new Map();
|
|
619
|
+
for (const entry of entries) if (entry.className !== void 0 && !built.has(entry.leaf)) built.set(entry.leaf, entry.className);
|
|
620
|
+
own = built;
|
|
621
|
+
ownClassNameCache.set(entries, own);
|
|
622
|
+
}
|
|
623
|
+
return own;
|
|
624
|
+
}
|
|
625
|
+
/** Each value of a prop that names its own class, as the class it is written as. Shared with the
|
|
626
|
+
* emitted runtime, which writes the same class for the same value. */
|
|
627
|
+
function stylePropOwnClasses(config, path) {
|
|
628
|
+
const out = /* @__PURE__ */ new Map();
|
|
629
|
+
for (const leaf of ownClassNames(config, path).keys()) out.set(leaf, stylePropClassName(config, path, leaf));
|
|
630
|
+
return out;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* A leaf as a class spells it. Whitespace becomes a hyphen: a class list splits on it, so
|
|
634
|
+
* `my custom background` would put three classes on the element and match none of the one rule.
|
|
635
|
+
* The emitted `_style-props` runtime applies the same transform to the values a call site passes.
|
|
636
|
+
*/
|
|
637
|
+
function classLeaf(leaf) {
|
|
638
|
+
const spaced = leaf.replace(/\s+/g, "-");
|
|
639
|
+
return /^\d+\/\d+$/.test(spaced) ? spaced : spaced.replaceAll("/", "-");
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* A class as a selector: `.p-0\.5`, `.w-1\/2`, `.md\:flex`, `.\32xl\:p-4`. Every character outside
|
|
643
|
+
* an identifier's own is escaped, and a leading digit, which an identifier cannot start with, is
|
|
644
|
+
* written as its code point.
|
|
645
|
+
*/
|
|
646
|
+
function classSelector(name) {
|
|
647
|
+
const escaped = name.replace(/[^A-Za-z0-9_\-\u00a0-\uffff]/g, (char) => `\\${char}`);
|
|
648
|
+
const leading = /^-?\d/.exec(escaped);
|
|
649
|
+
if (!leading) return `.${escaped}`;
|
|
650
|
+
const at = leading[0].length - 1;
|
|
651
|
+
const digit = escaped.charCodeAt(at).toString(16);
|
|
652
|
+
return `.${escaped.slice(0, at)}\\${digit} ${escaped.slice(at + 1)}`;
|
|
599
653
|
}
|
|
600
654
|
/** An off-scale value and what it really is — `[13px]` → `13px`, else `undefined`. The brackets mark
|
|
601
655
|
* a value the system doesn't tokenize; they aren't part of it. No class can exist for one, because a
|
|
@@ -613,6 +667,23 @@ function unescapeArbitrary(value) {
|
|
|
613
667
|
return value.replace(/url\([^)]*\)|_/g, (span) => span === "_" ? " " : span);
|
|
614
668
|
}
|
|
615
669
|
/**
|
|
670
|
+
* Whether a prop's bracketed value has to be written as its arbitrary class rather than inline.
|
|
671
|
+
* An inline style sets each of the prop's `properties` on the element and nothing else, so a prop
|
|
672
|
+
* with a `selector`, its own `declarations`, or a property keyed by a token ref would paint wrong.
|
|
673
|
+
*/
|
|
674
|
+
function arbitraryNeedsClass(config, path) {
|
|
675
|
+
const { properties = [], declarations, selector } = config.resolve("style-property", path)?.toJSON() ?? {};
|
|
676
|
+
return Boolean(selector) || Object.keys(declarations ?? {}).length > 0 || properties.some((property) => refOfKey(property) !== void 0);
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* The class a bracketed value is written as — `blur` and `[3px]` → `uds-blur-[3px]`. A space inside
|
|
680
|
+
* the brackets is spelled `_`, which the stylesheet reads back as one.
|
|
681
|
+
*/
|
|
682
|
+
function arbitraryClassName({ config, path, value }) {
|
|
683
|
+
const inner = value.slice(1, -1).replace(/\s+/g, "_");
|
|
684
|
+
return `${stylePropClassBase(config, path)}-[${inner}]`;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
616
687
|
* Split a prop bag into a class string and the props that aren't styling.
|
|
617
688
|
*
|
|
618
689
|
* This is the same dispatch the emitted `_style-props` runtime performs, over a live config instead
|
|
@@ -621,8 +692,9 @@ function unescapeArbitrary(value) {
|
|
|
621
692
|
* but the CLASS NAMES both produce come from {@link stylePropClassName}, so the two can't disagree
|
|
622
693
|
* about what a value is called.
|
|
623
694
|
*
|
|
624
|
-
* An off-scale value
|
|
625
|
-
* `style` the caller passed still wins, since that's the
|
|
695
|
+
* An off-scale value lands in `style` on the returned rest, unless the prop needs its arbitrary class
|
|
696
|
+
* ({@link arbitraryNeedsClass}); an explicit `style` the caller passed still wins, since that's the
|
|
697
|
+
* escape hatch of last resort.
|
|
626
698
|
*/
|
|
627
699
|
function splitStyleProps({ config, bag, through }) {
|
|
628
700
|
const classes = [];
|
|
@@ -656,6 +728,14 @@ function splitStyleProps({ config, bag, through }) {
|
|
|
656
728
|
if (value === void 0 || value === null) continue;
|
|
657
729
|
const { arbitrary, properties = [], negates } = prop.toJSON();
|
|
658
730
|
const off = arbitrary ? offScale(value) : void 0;
|
|
731
|
+
if (off !== void 0 && arbitraryNeedsClass(config, name)) {
|
|
732
|
+
classes.push(arbitraryClassName({
|
|
733
|
+
config,
|
|
734
|
+
path: name,
|
|
735
|
+
value: String(value)
|
|
736
|
+
}));
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
659
739
|
if (off !== void 0) {
|
|
660
740
|
const declared = negates ? negatedCssValue(off) : off;
|
|
661
741
|
for (const property of properties) style[reactStyleKey(property)] = declared;
|
|
@@ -827,5 +907,26 @@ function classesUsedBy(config, stored, token, bagsOf) {
|
|
|
827
907
|
byVocabulary.set(token, found);
|
|
828
908
|
return found;
|
|
829
909
|
}
|
|
910
|
+
/**
|
|
911
|
+
* A class split at the colons that separate its modifiers, as `md:hover:[&_a]:bg-[url(a:b)]` is
|
|
912
|
+
* `md`, `hover`, `[&_a]` and `bg-[url(a:b)]`. A colon inside brackets or parentheses belongs to the
|
|
913
|
+
* value. The last segment is the utility.
|
|
914
|
+
*/
|
|
915
|
+
function splitVariants(cls) {
|
|
916
|
+
const segments = [];
|
|
917
|
+
let depth = 0;
|
|
918
|
+
let start = 0;
|
|
919
|
+
for (let at = 0; at < cls.length; at++) {
|
|
920
|
+
const char = cls[at];
|
|
921
|
+
if (char === "[" || char === "(") depth++;
|
|
922
|
+
else if ((char === "]" || char === ")") && depth > 0) depth--;
|
|
923
|
+
else if (char === ":" && depth === 0) {
|
|
924
|
+
segments.push(cls.slice(start, at));
|
|
925
|
+
start = at + 1;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
segments.push(cls.slice(start));
|
|
929
|
+
return segments;
|
|
930
|
+
}
|
|
830
931
|
//#endregion
|
|
831
|
-
export { componentClassBase, componentCompositeClasses, componentLayerClass, componentMotionClasses, componentPropClasses, componentPropComposites, componentRuleClasses, forceModeAttribute, forceModeAttributeOf, forceModeProp, forceModePropGroup, forceModePropValue, forceModeProps, forceStateAttribute, inlineRuleComposites, isForceModeProp, kebabComponent, layerRoutedProps, modifierUtilitiesUsed, motionClassName, ruleCondition, splitStyleProps, stylePropClassBase, stylePropClassName, stylePropClasses, styleRuleMotionClasses };
|
|
932
|
+
export { arbitraryClassName, arbitraryNeedsClass, classLeaf, classSelector, componentClassBase, componentCompositeClasses, componentLayerClass, componentMotionClasses, componentPropClasses, componentPropComposites, componentRuleClasses, forceModeAttribute, forceModeAttributeOf, forceModeProp, forceModePropGroup, forceModePropValue, forceModeProps, forceStateAttribute, inlineRuleComposites, isForceModeProp, kebabComponent, layerRoutedProps, modifierUtilitiesUsed, motionClassName, ruleCondition, splitStyleProps, splitVariants, stylePropClassBase, stylePropClassName, stylePropClasses, stylePropOwnClasses, styleRuleMotionClasses };
|
|
@@ -192,6 +192,7 @@ GI extends GroupInputs = Record<never, never>> = Omit<RefSchema, 'extend'> & {
|
|
|
192
192
|
* does call zod's `extend` on it.
|
|
193
193
|
*/
|
|
194
194
|
extend<F2 extends ShapeOverride = Record<never, never>, G2 extends ShapeOverride = Record<never, never>, S2 extends UserSchemas = never>(overrides: {
|
|
195
|
+
prepareLinkedBody?: EntityKind['prepareLinkedBody'];
|
|
195
196
|
fields?: F2;
|
|
196
197
|
groupFields?: G2;
|
|
197
198
|
subEntities?: Partial<Record<string, SubEntityClass | null>>;
|
|
@@ -353,7 +354,8 @@ declare function defineEntity<F extends FieldsSchema, G extends FieldsSchema = z
|
|
|
353
354
|
* Declare it alongside `bulkOverlay` for a kind whose minted rows should stay editable; without it,
|
|
354
355
|
* an edit to one has nowhere to land.
|
|
355
356
|
*/
|
|
356
|
-
bulkOverlayWrite?: (args: BulkOverlayWrite) => Record<string, unknown>;
|
|
357
|
+
bulkOverlayWrite?: (args: BulkOverlayWrite) => Record<string, unknown>; /** Adapt a pinned source body before linked validation. */
|
|
358
|
+
prepareLinkedBody?: EntityKind['prepareLinkedBody'];
|
|
357
359
|
/**
|
|
358
360
|
* Edges this kind's data implies by name rather than by ref, and how to rewrite one — the pair that
|
|
359
361
|
* makes a record keyed by another kind's item names behave like a reference: reported by
|
|
@@ -27,7 +27,8 @@ const EXTENDABLE_KEYS = new Set([
|
|
|
27
27
|
"schemas",
|
|
28
28
|
"label",
|
|
29
29
|
"labelPlural",
|
|
30
|
-
"entityName"
|
|
30
|
+
"entityName",
|
|
31
|
+
"prepareLinkedBody"
|
|
31
32
|
]);
|
|
32
33
|
/** Merge an override into the base's shape, key by key — using zod's real `extend`/`omit` on the
|
|
33
34
|
* plain object, where they are the right tools. A named key replaces or adds a field; `null`
|
|
@@ -122,6 +123,7 @@ function defineEntity(spec) {
|
|
|
122
123
|
bulkOverlay: spec.bulkOverlay,
|
|
123
124
|
bulkDirectives: spec.bulkDirectives,
|
|
124
125
|
bulkOverlayWrite: spec.bulkOverlayWrite,
|
|
126
|
+
prepareLinkedBody: spec.prepareLinkedBody,
|
|
125
127
|
nameEdges: spec.nameEdges,
|
|
126
128
|
styleBags: spec.styleBags,
|
|
127
129
|
rewriteName: spec.rewriteName,
|
|
@@ -13,9 +13,9 @@ import { Ref } from "./utils/refs.js";
|
|
|
13
13
|
* to become ours must not keep pointing anywhere.
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
|
-
* What to do with a sourced ref
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* What to do with a sourced identity ref — a modifier, component, `file`, or style property. There is
|
|
17
|
+
* no token value to substitute for one, so it needs its own answer, and which answer depends on
|
|
18
|
+
* whether the pin survives the edit.
|
|
19
19
|
*
|
|
20
20
|
* **It survives** for publishing and for reading a repo-local chain. The seam stays, so the ref stays:
|
|
21
21
|
* `keepIdentityRefs`. A borrowed component's `file` has to keep naming the system that owns the
|
|
@@ -40,7 +40,7 @@ function inlineSourcedRefs(value, config, slug, options) {
|
|
|
40
40
|
const target = config.resolveRef(value);
|
|
41
41
|
const body = target?.toJSON();
|
|
42
42
|
if (!target && !declaresGroup(owner, value)) rejectData(`Cannot inline "${value.__ref}": "${source}" has no ${kindOf(value)} at "${pathOf(value)}". A pin is exact, so this is a ref into a version that does not declare it.`);
|
|
43
|
-
if (body?.value === void 0) {
|
|
43
|
+
if (kindOf(value) !== "token" || body?.value === void 0) {
|
|
44
44
|
if (options?.keepIdentityRefs) return value;
|
|
45
45
|
const adopted = options?.adopted?.get(entityRefOf(value.__ref));
|
|
46
46
|
if (adopted !== void 0) return rewriteRefs(value, entityRefOf(value.__ref), adopted);
|