zyzz 0.0.6 → 0.0.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/README.md +26 -1
- package/dist/Style.d.ts +3 -3
- package/dist/Style.d.ts.map +1 -1
- package/dist/Style.js +12 -1
- package/dist/Style.js.map +1 -1
- package/dist/babel/index.d.ts +4 -1
- package/dist/babel/index.d.ts.map +1 -1
- package/dist/babel/index.js +6 -3
- package/dist/babel/index.js.map +1 -1
- package/dist/babel/internal/Compilation.d.ts +12 -0
- package/dist/babel/internal/Compilation.d.ts.map +1 -0
- package/dist/babel/internal/Compilation.js +3 -0
- package/dist/babel/internal/Compilation.js.map +1 -0
- package/dist/compiler/Graph.d.ts +6 -1
- package/dist/compiler/Graph.d.ts.map +1 -1
- package/dist/compiler/Graph.js +160 -36
- package/dist/compiler/Graph.js.map +1 -1
- package/dist/compiler/Transform.d.ts.map +1 -1
- package/dist/compiler/Transform.js +2 -1
- package/dist/compiler/Transform.js.map +1 -1
- package/dist/compiler/internal/Stylesheets.d.ts +8 -0
- package/dist/compiler/internal/Stylesheets.d.ts.map +1 -1
- package/dist/compiler/internal/Stylesheets.js +4 -0
- package/dist/compiler/internal/Stylesheets.js.map +1 -1
- package/dist/internal/Authoring.d.ts.map +1 -1
- package/dist/internal/Authoring.js +14 -0
- package/dist/internal/Authoring.js.map +1 -1
- package/dist/internal/Binding.d.ts +7 -0
- package/dist/internal/Binding.d.ts.map +1 -1
- package/dist/internal/Binding.js.map +1 -1
- package/dist/internal/Configuration.d.ts +1 -1
- package/dist/internal/Configuration.d.ts.map +1 -1
- package/dist/internal/Configuration.js +7 -6
- package/dist/internal/Configuration.js.map +1 -1
- package/dist/internal/Theme.d.ts +1 -1
- package/dist/internal/Theme.d.ts.map +1 -1
- package/dist/internal/Theme.js.map +1 -1
- package/dist/internal/Token.d.ts +3 -1
- package/dist/internal/Token.d.ts.map +1 -1
- package/dist/internal/Token.js +28 -3
- package/dist/internal/Token.js.map +1 -1
- package/dist/internal/Value.d.ts +22 -0
- package/dist/internal/Value.d.ts.map +1 -1
- package/dist/internal/Value.js +76 -9
- package/dist/internal/Value.js.map +1 -1
- package/dist/metro/Graph.d.ts +9 -1
- package/dist/metro/Graph.d.ts.map +1 -1
- package/dist/metro/Graph.js +5 -4
- package/dist/metro/Graph.js.map +1 -1
- package/dist/metro/transformer.d.ts +0 -1
- package/dist/metro/transformer.d.ts.map +1 -1
- package/dist/metro/transformer.js +19 -1
- package/dist/metro/transformer.js.map +1 -1
- package/dist/next/index.d.ts +3 -3
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +25 -30
- package/dist/next/index.js.map +1 -1
- package/dist/next/internal/Project.d.ts +28 -0
- package/dist/next/internal/Project.d.ts.map +1 -0
- package/dist/next/internal/Project.js +295 -0
- package/dist/next/internal/Project.js.map +1 -0
- package/dist/next/loader.d.ts +5 -6
- package/dist/next/loader.d.ts.map +1 -1
- package/dist/next/loader.js +161 -247
- package/dist/next/loader.js.map +1 -1
- package/dist/node/Host.d.ts.map +1 -1
- package/dist/node/Host.js +11 -3
- package/dist/node/Host.js.map +1 -1
- package/dist/node/internal/Snapshot.d.ts +12 -0
- package/dist/node/internal/Snapshot.d.ts.map +1 -0
- package/dist/node/internal/Snapshot.js +74 -0
- package/dist/node/internal/Snapshot.js.map +1 -0
- package/dist/unplugin/index.d.ts.map +1 -1
- package/dist/unplugin/index.js +10 -5
- package/dist/unplugin/index.js.map +1 -1
- package/dist/variants.d.ts +1 -1
- package/dist/variants.d.ts.map +1 -1
- package/dist/variants.js.map +1 -1
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +19 -4
- package/dist/vite/index.js.map +1 -1
- package/package.json +1 -1
- package/src/Style.ts +42 -8
- package/src/babel/index.ts +10 -4
- package/src/babel/internal/Compilation.ts +13 -0
- package/src/compiler/Graph.ts +213 -47
- package/src/compiler/Transform.ts +2 -1
- package/src/compiler/internal/Stylesheets.ts +9 -0
- package/src/internal/Authoring.ts +21 -0
- package/src/internal/Binding.ts +30 -0
- package/src/internal/Configuration.ts +19 -13
- package/src/internal/Theme.ts +5 -1
- package/src/internal/Token.ts +34 -3
- package/src/internal/Value.ts +180 -10
- package/src/metro/Graph.ts +5 -3
- package/src/metro/transformer.ts +26 -1
- package/src/next/index.ts +26 -31
- package/src/next/internal/Project.ts +378 -0
- package/src/next/loader.ts +195 -315
- package/src/node/Host.ts +15 -3
- package/src/node/internal/Snapshot.ts +79 -0
- package/src/unplugin/index.ts +10 -5
- package/src/variants.ts +1 -0
- package/src/vite/index.ts +24 -4
package/src/compiler/Graph.ts
CHANGED
|
@@ -38,6 +38,8 @@ export declare namespace compile {
|
|
|
38
38
|
|
|
39
39
|
/** Source modules available for relative import resolution. */
|
|
40
40
|
type Options = {
|
|
41
|
+
/** Host entrypoints emit owned stylesheet effects without packed contracts. */
|
|
42
|
+
readonly [Stylesheets.entry]?: string | undefined
|
|
41
43
|
/** Host syntax from the same immutable source snapshot. */
|
|
42
44
|
readonly [Syntax.cache]?:
|
|
43
45
|
| ReadonlyMap<string, Parser.ParseResult>
|
|
@@ -71,6 +73,8 @@ export declare namespace compile {
|
|
|
71
73
|
|
|
72
74
|
/** Compiled modules and their direct source dependencies. */
|
|
73
75
|
type ReturnType = {
|
|
76
|
+
/** Packed resources deduplicated by the host across scoped source outputs. */
|
|
77
|
+
readonly [Stylesheets.packed]?: readonly Stylesheets.Resource[]
|
|
74
78
|
/** Versioned compiler-only JSON per module; publish beside the compiled entrypoint as <entry>.zyzz.json. */
|
|
75
79
|
readonly contracts: Readonly<Record<string, string>>
|
|
76
80
|
/** Direct static runtime source and library-contract dependencies, keyed by module identity. */
|
|
@@ -88,7 +92,7 @@ export declare namespace compile {
|
|
|
88
92
|
}
|
|
89
93
|
}
|
|
90
94
|
|
|
91
|
-
/** Creates an isolated compiler
|
|
95
|
+
/** Creates an isolated compiler with bounded extraction reuse across source graphs. */
|
|
92
96
|
export function create(): create.ReturnType {
|
|
93
97
|
let previous: Cache | undefined
|
|
94
98
|
|
|
@@ -112,6 +116,26 @@ export declare namespace create {
|
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
118
|
|
|
119
|
+
type Extraction = {
|
|
120
|
+
dependencies: readonly string[]
|
|
121
|
+
extracted: Source.extract.ReturnType
|
|
122
|
+
inputs: ReadonlyMap<
|
|
123
|
+
string,
|
|
124
|
+
Source.extract.ReturnType | ReturnType<typeof Contract.read>
|
|
125
|
+
>
|
|
126
|
+
resolution: string
|
|
127
|
+
source: string
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
type Transformed = {
|
|
131
|
+
classes: Readonly<Record<string, string | undefined>>
|
|
132
|
+
extracted: Source.extract.ReturnType
|
|
133
|
+
owners: string
|
|
134
|
+
output: Transform.compile.ReturnType
|
|
135
|
+
schemes: boolean
|
|
136
|
+
themes: Readonly<Record<string, Theme.Definition>>
|
|
137
|
+
}
|
|
138
|
+
|
|
115
139
|
type Cache = {
|
|
116
140
|
compiler: boolean
|
|
117
141
|
composition: Css.compile.Options['composition']
|
|
@@ -119,9 +143,12 @@ type Cache = {
|
|
|
119
143
|
|
|
120
144
|
contracts: string
|
|
121
145
|
development: boolean
|
|
146
|
+
entry: string | undefined
|
|
122
147
|
extracted: ReadonlyMap<string, Source.extract.ReturnType>
|
|
123
148
|
libraries: Readonly<Record<string, ReturnType<typeof Contract.read>>>
|
|
124
149
|
reset: string | undefined
|
|
150
|
+
retained: ReadonlyMap<string, Extraction>
|
|
151
|
+
transformed: ReadonlyMap<string, Transformed>
|
|
125
152
|
resolutions: Readonly<Record<string, string>>
|
|
126
153
|
native: compile.Options['native']
|
|
127
154
|
result: compile.ReturnType
|
|
@@ -195,14 +222,15 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
195
222
|
]),
|
|
196
223
|
)
|
|
197
224
|
|
|
198
|
-
//
|
|
225
|
+
// Host resolutions remain explicit when generated modules enter or leave the graph.
|
|
199
226
|
const previous = (() => {
|
|
200
227
|
if (
|
|
201
228
|
cache &&
|
|
202
229
|
cache.contracts === contracts &&
|
|
203
230
|
cache.development === !!options.development &&
|
|
204
|
-
|
|
205
|
-
|
|
231
|
+
(options.imports !== undefined ||
|
|
232
|
+
(ids.length === Object.keys(cache.sources).length &&
|
|
233
|
+
ids.every((id) => Object.hasOwn(cache.sources, id))))
|
|
206
234
|
) {
|
|
207
235
|
return cache
|
|
208
236
|
}
|
|
@@ -211,6 +239,8 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
211
239
|
})()
|
|
212
240
|
if (
|
|
213
241
|
previous &&
|
|
242
|
+
previous.entry === options[Stylesheets.entry] &&
|
|
243
|
+
ids.length === Object.keys(previous.sources).length &&
|
|
214
244
|
Object.keys(resolutions).length ===
|
|
215
245
|
Object.keys(previous.resolutions).length &&
|
|
216
246
|
Object.entries(resolutions).every(
|
|
@@ -224,6 +254,8 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
224
254
|
)
|
|
225
255
|
return previous
|
|
226
256
|
|
|
257
|
+
const retained = new Map(previous?.retained)
|
|
258
|
+
const transformed = new Map(previous?.transformed)
|
|
227
259
|
const dependencies: Record<string, readonly string[]> = Object.create(null)
|
|
228
260
|
const extracted = new Map<string, Source.extract.ReturnType>()
|
|
229
261
|
const identifiers = new Map<string, Set<string>>()
|
|
@@ -365,29 +397,6 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
365
397
|
let direct: Ast.Node | undefined
|
|
366
398
|
const stars: string[] = []
|
|
367
399
|
for (const statement of program.body) {
|
|
368
|
-
if (
|
|
369
|
-
statement.type === 'ImportDeclaration' &&
|
|
370
|
-
statement.importKind !== 'type'
|
|
371
|
-
) {
|
|
372
|
-
const target = resolve(moduleId, statement.source.value, statement)
|
|
373
|
-
if (!target) continue
|
|
374
|
-
for (const specifier of statement.specifiers) {
|
|
375
|
-
if (
|
|
376
|
-
specifier.type === 'ImportNamespaceSpecifier' ||
|
|
377
|
-
(specifier.type === 'ImportSpecifier' &&
|
|
378
|
-
specifier.importKind === 'type')
|
|
379
|
-
)
|
|
380
|
-
continue
|
|
381
|
-
const imported =
|
|
382
|
-
specifier.type === 'ImportDefaultSpecifier'
|
|
383
|
-
? 'default'
|
|
384
|
-
: specifier.imported.type === 'Identifier'
|
|
385
|
-
? specifier.imported.name
|
|
386
|
-
: specifier.imported.value
|
|
387
|
-
const value = constant(target, imported, next)
|
|
388
|
-
if (value) imports[specifier.local.name] = relocate(value, specifier)
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
400
|
if (statement.type === 'ExportDefaultDeclaration' && name === 'default') {
|
|
392
401
|
direct = statement.declaration
|
|
393
402
|
exported = true
|
|
@@ -436,7 +445,47 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
436
445
|
.filter((value) => value !== undefined),
|
|
437
446
|
),
|
|
438
447
|
]
|
|
439
|
-
|
|
448
|
+
const value = candidates.length === 1 ? candidates[0] : undefined
|
|
449
|
+
if (value || !stars.length) constants.set(key, value)
|
|
450
|
+
return value
|
|
451
|
+
}
|
|
452
|
+
if (
|
|
453
|
+
direct &&
|
|
454
|
+
[
|
|
455
|
+
'FunctionDeclaration',
|
|
456
|
+
'FunctionExpression',
|
|
457
|
+
'ArrowFunctionExpression',
|
|
458
|
+
'ClassDeclaration',
|
|
459
|
+
'ClassExpression',
|
|
460
|
+
].includes(direct.type)
|
|
461
|
+
) {
|
|
462
|
+
constants.set(key, undefined)
|
|
463
|
+
return undefined
|
|
464
|
+
}
|
|
465
|
+
for (const statement of program.body) {
|
|
466
|
+
if (
|
|
467
|
+
statement.type === 'ImportDeclaration' &&
|
|
468
|
+
statement.importKind !== 'type'
|
|
469
|
+
) {
|
|
470
|
+
const target = resolve(moduleId, statement.source.value, statement)
|
|
471
|
+
if (!target) continue
|
|
472
|
+
for (const specifier of statement.specifiers) {
|
|
473
|
+
if (
|
|
474
|
+
specifier.type === 'ImportNamespaceSpecifier' ||
|
|
475
|
+
(specifier.type === 'ImportSpecifier' &&
|
|
476
|
+
specifier.importKind === 'type')
|
|
477
|
+
)
|
|
478
|
+
continue
|
|
479
|
+
const imported =
|
|
480
|
+
specifier.type === 'ImportDefaultSpecifier'
|
|
481
|
+
? 'default'
|
|
482
|
+
: specifier.imported.type === 'Identifier'
|
|
483
|
+
? specifier.imported.name
|
|
484
|
+
: specifier.imported.value
|
|
485
|
+
const value = constant(target, imported, next)
|
|
486
|
+
if (value) imports[specifier.local.name] = relocate(value, specifier)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
440
489
|
}
|
|
441
490
|
const scope = new Scope.Tracker({ preserveExitedScopes: true })
|
|
442
491
|
Walker.walk(program, { scopeTracker: scope })
|
|
@@ -602,21 +651,34 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
602
651
|
|
|
603
652
|
const source = options.modules[moduleId]!
|
|
604
653
|
|
|
654
|
+
const snapshot =
|
|
655
|
+
previous?.retained.get(moduleId) ??
|
|
656
|
+
(previous && Object.hasOwn(previous.sources, moduleId)
|
|
657
|
+
? {
|
|
658
|
+
dependencies: previous.result.dependencies[moduleId]!,
|
|
659
|
+
extracted: previous.extracted.get(moduleId)!,
|
|
660
|
+
inputs: new Map(
|
|
661
|
+
previous.result.dependencies[moduleId]!.map((target) => [
|
|
662
|
+
target,
|
|
663
|
+
previous.libraries[target] ?? previous.extracted.get(target)!,
|
|
664
|
+
]),
|
|
665
|
+
),
|
|
666
|
+
resolution: previous.resolutions[moduleId]!,
|
|
667
|
+
source: previous.sources[moduleId]!,
|
|
668
|
+
}
|
|
669
|
+
: undefined)
|
|
605
670
|
if (
|
|
606
|
-
|
|
607
|
-
source ===
|
|
608
|
-
resolutions[moduleId] ===
|
|
609
|
-
|
|
610
|
-
(target)
|
|
611
|
-
|
|
612
|
-
|
|
671
|
+
snapshot &&
|
|
672
|
+
source === snapshot.source &&
|
|
673
|
+
resolutions[moduleId] === snapshot.resolution &&
|
|
674
|
+
snapshot.dependencies.every((target) =>
|
|
675
|
+
Object.hasOwn(libraries, target)
|
|
676
|
+
? libraries[target] === snapshot.inputs.get(target)
|
|
677
|
+
: Object.hasOwn(options.modules, target) &&
|
|
678
|
+
visit(target) === snapshot.inputs.get(target),
|
|
613
679
|
)
|
|
614
680
|
) {
|
|
615
|
-
return retain(
|
|
616
|
-
moduleId,
|
|
617
|
-
previous.extracted.get(moduleId)!,
|
|
618
|
-
previous.result.dependencies[moduleId]!,
|
|
619
|
-
)
|
|
681
|
+
return retain(moduleId, snapshot.extracted, snapshot.dependencies)
|
|
620
682
|
}
|
|
621
683
|
|
|
622
684
|
// Validate identity and syntax through the public source boundary before linking.
|
|
@@ -957,6 +1019,20 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
957
1019
|
|
|
958
1020
|
extracted.set(moduleId, result)
|
|
959
1021
|
dependencies[moduleId] = imports
|
|
1022
|
+
retained.delete(moduleId)
|
|
1023
|
+
retained.set(moduleId, {
|
|
1024
|
+
dependencies: imports,
|
|
1025
|
+
extracted: result,
|
|
1026
|
+
inputs: new Map(
|
|
1027
|
+
imports.map((target) => [
|
|
1028
|
+
target,
|
|
1029
|
+
libraries[target] ?? extracted.get(target)!,
|
|
1030
|
+
]),
|
|
1031
|
+
),
|
|
1032
|
+
resolution: resolutions[moduleId]!,
|
|
1033
|
+
source: options.modules[moduleId]!,
|
|
1034
|
+
})
|
|
1035
|
+
if (retained.size > 256) retained.delete(retained.keys().next().value!)
|
|
960
1036
|
|
|
961
1037
|
for (const call of result.themeCalls)
|
|
962
1038
|
for (const name of new Set([
|
|
@@ -1072,6 +1148,9 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
1072
1148
|
...(options.native.units && { units: { ...options.native.units } }),
|
|
1073
1149
|
},
|
|
1074
1150
|
reset: options.reset,
|
|
1151
|
+
entry: options[Stylesheets.entry],
|
|
1152
|
+
retained,
|
|
1153
|
+
transformed,
|
|
1075
1154
|
resolutions: Object.freeze(resolutions),
|
|
1076
1155
|
result: Object.freeze({
|
|
1077
1156
|
contracts: Object.freeze(
|
|
@@ -1248,16 +1327,58 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
1248
1327
|
}
|
|
1249
1328
|
|
|
1250
1329
|
const sharedVisited = new Set<string>()
|
|
1330
|
+
const packed: Stylesheets.Resource[] = []
|
|
1251
1331
|
|
|
1252
1332
|
const shared = (() => {
|
|
1253
1333
|
try {
|
|
1254
|
-
const
|
|
1334
|
+
const entry = options[Stylesheets.entry]
|
|
1335
|
+
const packedSections =
|
|
1336
|
+
entry === undefined
|
|
1337
|
+
? []
|
|
1338
|
+
: (dependencies[entry] ?? [])
|
|
1339
|
+
.filter((id) => Object.hasOwn(libraries, id))
|
|
1340
|
+
.flatMap((id) => reachable(id, sharedVisited))
|
|
1341
|
+
const sharedSections =
|
|
1342
|
+
entry === undefined
|
|
1343
|
+
? ids.flatMap((id) => reachable(id, sharedVisited))
|
|
1344
|
+
: (sections.get(entry) ?? [])
|
|
1345
|
+
if (packedSections.length) {
|
|
1346
|
+
// Validate combined ownership and ordering before splitting independently loaded resources.
|
|
1347
|
+
Stylesheets.render([...packedSections, ...sharedSections])
|
|
1348
|
+
for (const section of packedSections) {
|
|
1349
|
+
packed.push({
|
|
1350
|
+
id: JSON.stringify([section.owner, section.source, section.key]),
|
|
1351
|
+
...Stylesheets.render([section]),
|
|
1352
|
+
})
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1255
1355
|
const resetSource =
|
|
1256
1356
|
(options.reset === undefined ? undefined : 'zyzz/reset.css') ??
|
|
1257
1357
|
resetOwners[0] ??
|
|
1258
1358
|
sharedSections.find((section) => section.key === 'optional-reset-order')
|
|
1259
1359
|
?.source
|
|
1260
1360
|
|
|
1361
|
+
if (packed.length) {
|
|
1362
|
+
const order = Stylesheets.render([
|
|
1363
|
+
...(resetSource === undefined
|
|
1364
|
+
? []
|
|
1365
|
+
: [
|
|
1366
|
+
{
|
|
1367
|
+
source: resetSource,
|
|
1368
|
+
css: '',
|
|
1369
|
+
layers: layerNames.length
|
|
1370
|
+
? layerNames.map((name) => ['reset', name])
|
|
1371
|
+
: [['reset']],
|
|
1372
|
+
},
|
|
1373
|
+
]),
|
|
1374
|
+
...[...packedSections, ...sharedSections].map((section) => ({
|
|
1375
|
+
...section,
|
|
1376
|
+
css: '',
|
|
1377
|
+
})),
|
|
1378
|
+
])
|
|
1379
|
+
if (order.css) packed.unshift({ ...order, id: order.css })
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1261
1382
|
return Stylesheets.render([
|
|
1262
1383
|
...(resetSource === undefined
|
|
1263
1384
|
? []
|
|
@@ -1406,12 +1527,26 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
1406
1527
|
),
|
|
1407
1528
|
)
|
|
1408
1529
|
|
|
1530
|
+
const ownerSignature = JSON.stringify(owners)
|
|
1531
|
+
|
|
1409
1532
|
// Extraction visits dependencies first; their emitted classes must precede consumers.
|
|
1410
1533
|
for (const moduleId of extracted.keys()) {
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
extracted
|
|
1534
|
+
const cached = transformed.get(moduleId)
|
|
1535
|
+
const reusable =
|
|
1536
|
+
cached &&
|
|
1537
|
+
cached.extracted === extracted.get(moduleId) &&
|
|
1538
|
+
cached.schemes === schemes &&
|
|
1539
|
+
Object.keys(cached.themes).length === names.length &&
|
|
1540
|
+
names.every((name) => cached.themes[name] === themes[name]) &&
|
|
1541
|
+
Object.entries(cached.classes).every(
|
|
1542
|
+
([name, value]) => styleClasses[name] === value,
|
|
1543
|
+
) &&
|
|
1544
|
+
cached.owners === ownerSignature
|
|
1545
|
+
modules[moduleId] = reusable
|
|
1546
|
+
? cached.output
|
|
1547
|
+
: sameThemes &&
|
|
1548
|
+
previous!.schemes === schemes &&
|
|
1549
|
+
extracted.get(moduleId) === previous!.extracted.get(moduleId)
|
|
1415
1550
|
? previous!.result.modules[moduleId]!
|
|
1416
1551
|
: Transform.compile({
|
|
1417
1552
|
compiler: options.compiler,
|
|
@@ -1422,6 +1557,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
1422
1557
|
schemes,
|
|
1423
1558
|
source: options.modules[moduleId]!,
|
|
1424
1559
|
[Themes.context]: {
|
|
1560
|
+
parsed: parse({ moduleId, source: options.modules[moduleId]! }),
|
|
1425
1561
|
extracted: Object.freeze({
|
|
1426
1562
|
...extracted.get(moduleId)!,
|
|
1427
1563
|
vars: sharedThemes,
|
|
@@ -1432,13 +1568,39 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
1432
1568
|
styleClasses,
|
|
1433
1569
|
},
|
|
1434
1570
|
})
|
|
1571
|
+
transformed.delete(moduleId)
|
|
1572
|
+
transformed.set(moduleId, {
|
|
1573
|
+
classes: Object.fromEntries(
|
|
1574
|
+
extracted
|
|
1575
|
+
.get(moduleId)!
|
|
1576
|
+
.calls.flatMap((call) =>
|
|
1577
|
+
(call.runtimeComposition ?? []).map((input) => [
|
|
1578
|
+
input.name,
|
|
1579
|
+
styleClasses[input.name],
|
|
1580
|
+
]),
|
|
1581
|
+
),
|
|
1582
|
+
),
|
|
1583
|
+
extracted: extracted.get(moduleId)!,
|
|
1584
|
+
owners: ownerSignature,
|
|
1585
|
+
output: modules[moduleId]!,
|
|
1586
|
+
schemes,
|
|
1587
|
+
themes: sharedThemes,
|
|
1588
|
+
})
|
|
1589
|
+
if (transformed.size > 256)
|
|
1590
|
+
transformed.delete(transformed.keys().next().value!)
|
|
1435
1591
|
// Module-local checks cannot detect truncated ownership hashes colliding across files.
|
|
1592
|
+
const emitted = new Set(
|
|
1593
|
+
Array.from(
|
|
1594
|
+
modules[moduleId]!.css.matchAll(/\.(z-[\w-]+)\{/g),
|
|
1595
|
+
(match) => match[1],
|
|
1596
|
+
),
|
|
1597
|
+
)
|
|
1436
1598
|
for (const value of Object.values(modules[moduleId]!.classes))
|
|
1437
1599
|
for (const name of value.split(' ')) {
|
|
1438
1600
|
if (
|
|
1439
1601
|
options.compiler === false ||
|
|
1440
1602
|
!name.startsWith('z-') ||
|
|
1441
|
-
!
|
|
1603
|
+
!emitted.has(name)
|
|
1442
1604
|
)
|
|
1443
1605
|
continue
|
|
1444
1606
|
|
|
@@ -1531,8 +1693,12 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
1531
1693
|
libraries: Object.freeze(libraries),
|
|
1532
1694
|
native: undefined,
|
|
1533
1695
|
reset: options.reset,
|
|
1696
|
+
entry: options[Stylesheets.entry],
|
|
1697
|
+
retained,
|
|
1698
|
+
transformed,
|
|
1534
1699
|
resolutions: Object.freeze(resolutions),
|
|
1535
1700
|
result: Object.freeze({
|
|
1701
|
+
...(packed.length ? { [Stylesheets.packed]: packed } : {}),
|
|
1536
1702
|
...(sharedCss
|
|
1537
1703
|
? {
|
|
1538
1704
|
sharedCss,
|
|
@@ -1543,7 +1709,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
|
|
|
1543
1709
|
: {}),
|
|
1544
1710
|
contracts: Object.freeze(
|
|
1545
1711
|
Object.fromEntries(
|
|
1546
|
-
ids
|
|
1712
|
+
(options[Stylesheets.entry] === undefined ? ids : [])
|
|
1547
1713
|
.filter(
|
|
1548
1714
|
(id) =>
|
|
1549
1715
|
Object.keys(extracted.get(id)!.themeExports ?? {}).length ||
|
|
@@ -96,7 +96,8 @@ export function compile(options: compile.Options): compile.ReturnType {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
const module = new MagicString(options.source)
|
|
99
|
-
const program = Syntax.parse(options)
|
|
99
|
+
const program = (options[Themes.context]?.parsed ?? Syntax.parse(options))
|
|
100
|
+
.program
|
|
100
101
|
|
|
101
102
|
for (const call of extracted.contributionCalls ?? [])
|
|
102
103
|
module.overwrite(
|
|
@@ -17,6 +17,15 @@ export class ConflictError extends Error {
|
|
|
17
17
|
override name = 'Stylesheets.ConflictError'
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/** Selects module-owned effects when the host loads source dependencies separately. */
|
|
21
|
+
export const entry = Symbol('stylesheet entry')
|
|
22
|
+
|
|
23
|
+
/** Independently shared packed sections for hosts that load source modules separately. */
|
|
24
|
+
export const packed = Symbol('packed stylesheets')
|
|
25
|
+
|
|
26
|
+
/** One packed resource with stable source ownership for development updates. */
|
|
27
|
+
export type Resource = ReturnType<typeof render> & { readonly id: string }
|
|
28
|
+
|
|
20
29
|
/** Ordered CSS owned by one portable source module. */
|
|
21
30
|
export type Section = {
|
|
22
31
|
/** Isolated selector namespaces belonging to the source owner. */
|
|
@@ -74,6 +74,10 @@ export function create(
|
|
|
74
74
|
if (!dynamic && !id && Object.keys(input as object).length === 0)
|
|
75
75
|
Identity.requireId(undefined, 'Empty style')
|
|
76
76
|
|
|
77
|
+
if (id && !dynamic && options.theme)
|
|
78
|
+
Style.define({ style: body(input as Record<string, unknown>) } as never, {
|
|
79
|
+
vars: options.theme,
|
|
80
|
+
})
|
|
77
81
|
const className = id
|
|
78
82
|
? `z-style-${id}`
|
|
79
83
|
: Identity.style(
|
|
@@ -125,6 +129,23 @@ export function variants(
|
|
|
125
129
|
options: Options = {},
|
|
126
130
|
): unknown {
|
|
127
131
|
const id = Identity.requireId(options.id, 'variants')
|
|
132
|
+
if (options.theme) {
|
|
133
|
+
const styles = [
|
|
134
|
+
input.base,
|
|
135
|
+
...Object.values(
|
|
136
|
+
(input.variants ?? {}) as Record<string, Record<string, unknown>>,
|
|
137
|
+
).flatMap(Object.values),
|
|
138
|
+
...((input.compoundVariants ?? []) as readonly { style: unknown }[]).map(
|
|
139
|
+
(entry) => entry.style,
|
|
140
|
+
),
|
|
141
|
+
]
|
|
142
|
+
for (const input of styles)
|
|
143
|
+
if (input && typeof input === 'object')
|
|
144
|
+
Style.define(
|
|
145
|
+
{ style: body(input as Record<string, unknown>) } as never,
|
|
146
|
+
{ vars: options.theme },
|
|
147
|
+
)
|
|
148
|
+
}
|
|
128
149
|
const className = `z-style-${id}`
|
|
129
150
|
const axes = Object.entries(
|
|
130
151
|
(input.variants ?? {}) as Record<string, Record<string, unknown>>,
|
package/src/internal/Binding.ts
CHANGED
|
@@ -127,6 +127,36 @@ export type Checked<style> = {
|
|
|
127
127
|
: unknown
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
/** Excludes token-name slots, which cannot resolve token names during application. */
|
|
131
|
+
export type TokenSlots<style, values, tokens, mappings = {}> = {
|
|
132
|
+
[property in keyof style]: property extends keyof Literal.Properties
|
|
133
|
+
? SlotValue<
|
|
134
|
+
style[property],
|
|
135
|
+
values[keyof values],
|
|
136
|
+
Token.Names<tokens, property>
|
|
137
|
+
>
|
|
138
|
+
: property extends keyof mappings
|
|
139
|
+
? mappings[property] extends readonly (infer target extends
|
|
140
|
+
keyof Literal.Properties)[]
|
|
141
|
+
? SlotValue<
|
|
142
|
+
style[property],
|
|
143
|
+
values[keyof values],
|
|
144
|
+
Token.Names<tokens, target>
|
|
145
|
+
>
|
|
146
|
+
: unknown
|
|
147
|
+
: property extends 'vars'
|
|
148
|
+
? unknown
|
|
149
|
+
: style[property] extends Record<string, unknown>
|
|
150
|
+
? TokenSlots<style[property], values, tokens, mappings>
|
|
151
|
+
: unknown
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
type SlotValue<value, inputs, names> = value extends readonly unknown[]
|
|
155
|
+
? { [key in keyof value]: SlotValue<value[key], inputs, names> }
|
|
156
|
+
: Extract<Extract<value, inputs>, names> extends never
|
|
157
|
+
? unknown
|
|
158
|
+
: never
|
|
159
|
+
|
|
130
160
|
/** Rejects reserved callback field names and importance-bearing value domains. */
|
|
131
161
|
export type Inputs<values> = {
|
|
132
162
|
[key in keyof values]: key extends
|
|
@@ -277,14 +277,16 @@ export function create(
|
|
|
277
277
|
})
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
|
-
function boundVariants(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
280
|
+
function boundVariants(theme?: Theme.Definition) {
|
|
281
|
+
return (
|
|
282
|
+
definition: Record<string, unknown>,
|
|
283
|
+
options: style.DefinitionOptions = {},
|
|
284
|
+
) =>
|
|
285
|
+
Authoring.variants(definition, {
|
|
286
|
+
...options,
|
|
287
|
+
output: input.output as style.Output | undefined,
|
|
288
|
+
theme,
|
|
289
|
+
})
|
|
288
290
|
}
|
|
289
291
|
function handle(theme: Theme.Definition, name: string) {
|
|
290
292
|
const original = Token.bind(theme, contract)
|
|
@@ -313,7 +315,7 @@ export function create(
|
|
|
313
315
|
})
|
|
314
316
|
Object.assign(select, {
|
|
315
317
|
style: boundStyle(original),
|
|
316
|
-
variants: boundVariants,
|
|
318
|
+
variants: boundVariants(original),
|
|
317
319
|
})
|
|
318
320
|
return select
|
|
319
321
|
}
|
|
@@ -410,7 +412,9 @@ export function create(
|
|
|
410
412
|
),
|
|
411
413
|
theme: bound[input.defaultTheme],
|
|
412
414
|
themes: Object.freeze(select),
|
|
413
|
-
variants: boundVariants
|
|
415
|
+
variants: boundVariants(
|
|
416
|
+
bound[input.defaultTheme] as unknown as Theme.Definition,
|
|
417
|
+
),
|
|
414
418
|
})
|
|
415
419
|
}
|
|
416
420
|
|
|
@@ -424,7 +428,7 @@ export function create(
|
|
|
424
428
|
script: Appearance.create([], { storageKey }),
|
|
425
429
|
style: boundStyle(theme as unknown as Theme.Definition),
|
|
426
430
|
theme,
|
|
427
|
-
variants: boundVariants,
|
|
431
|
+
variants: boundVariants(theme as unknown as Theme.Definition),
|
|
428
432
|
})
|
|
429
433
|
}
|
|
430
434
|
|
|
@@ -436,7 +440,7 @@ export function create(
|
|
|
436
440
|
appearance: Appearance.root([], { storageKey }),
|
|
437
441
|
script: Appearance.create([], { storageKey }),
|
|
438
442
|
style: boundStyle(theme),
|
|
439
|
-
variants: boundVariants,
|
|
443
|
+
variants: boundVariants(theme),
|
|
440
444
|
})
|
|
441
445
|
}
|
|
442
446
|
|
|
@@ -590,7 +594,9 @@ export type StyleFactory<
|
|
|
590
594
|
values: values,
|
|
591
595
|
) => styles &
|
|
592
596
|
NoInfer<
|
|
593
|
-
Body<styles, tokens, layers, mappings> &
|
|
597
|
+
Body<styles, tokens, layers, mappings> &
|
|
598
|
+
Binding.Checked<styles> &
|
|
599
|
+
Binding.TokenSlots<styles, values, tokens, mappings>
|
|
594
600
|
>) &
|
|
595
601
|
Completion.Properties<tokens, NoInfer<styles>>,
|
|
596
602
|
...options: Parameters<callback> extends [Record<string, string | number>]
|
package/src/internal/Theme.ts
CHANGED
|
@@ -30,7 +30,11 @@ export type StyleFactory<tokens extends Tokens> = {
|
|
|
30
30
|
styles: ((
|
|
31
31
|
values: values,
|
|
32
32
|
) => styles &
|
|
33
|
-
NoInfer<
|
|
33
|
+
NoInfer<
|
|
34
|
+
Style.Accepted<styles, tokens> &
|
|
35
|
+
Binding.Checked<styles> &
|
|
36
|
+
Binding.TokenSlots<styles, values, tokens>
|
|
37
|
+
>) &
|
|
34
38
|
(values extends Binding.Inputs<values> ? unknown : never),
|
|
35
39
|
options?: style.DefinitionOptions,
|
|
36
40
|
): style.Dynamic<values>
|
package/src/internal/Token.ts
CHANGED
|
@@ -444,11 +444,11 @@ export type Reference<group extends Group = Group> = {
|
|
|
444
444
|
|
|
445
445
|
const reference = Symbol('zyzz.token')
|
|
446
446
|
|
|
447
|
-
/** Resolves
|
|
447
|
+
/** Resolves configured token names, with specific color groups first. */
|
|
448
448
|
export function resolve(value: unknown, options: resolve.Options): unknown {
|
|
449
449
|
if (
|
|
450
|
-
(
|
|
451
|
-
|
|
450
|
+
options.property.startsWith('--') ||
|
|
451
|
+
(typeof value !== 'string' && typeof value !== 'number')
|
|
452
452
|
)
|
|
453
453
|
return value
|
|
454
454
|
|
|
@@ -529,6 +529,37 @@ export function resolve(value: unknown, options: resolve.Options): unknown {
|
|
|
529
529
|
return value
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
+
/** Whether the configured catalog supplies tokens for a property. */
|
|
533
|
+
export function mapped(
|
|
534
|
+
theme: object,
|
|
535
|
+
property: keyof Literal.Properties,
|
|
536
|
+
): boolean {
|
|
537
|
+
if (property.startsWith('--')) return false
|
|
538
|
+
const data = Object.getOwnPropertyDescriptor(theme, definition)
|
|
539
|
+
?.value as Metadata
|
|
540
|
+
return Object.keys(data.values).some((path) => {
|
|
541
|
+
const category = path.split('.')[0]!
|
|
542
|
+
const targets =
|
|
543
|
+
data.contract.mappings === false
|
|
544
|
+
? undefined
|
|
545
|
+
: data.contract.mappings?.[category]
|
|
546
|
+
if (
|
|
547
|
+
data.contract.mappings !== false &&
|
|
548
|
+
!(targets
|
|
549
|
+
? targets.includes(property)
|
|
550
|
+
: accepts(category as Group, property))
|
|
551
|
+
)
|
|
552
|
+
return false
|
|
553
|
+
let leaf: unknown = Object.getOwnPropertyDescriptor(theme, 'tokens')?.value
|
|
554
|
+
for (const key of path.split('.'))
|
|
555
|
+
leaf =
|
|
556
|
+
leaf && typeof leaf === 'object'
|
|
557
|
+
? Object.getOwnPropertyDescriptor(leaf, key)?.value
|
|
558
|
+
: undefined
|
|
559
|
+
return is(leaf) && acceptsReference(leaf, property)
|
|
560
|
+
})
|
|
561
|
+
}
|
|
562
|
+
|
|
532
563
|
/** Input contract for theme token resolution. */
|
|
533
564
|
export declare namespace resolve {
|
|
534
565
|
/** Property domain and immutable theme metadata supplied by style validation. */
|