zyzz 0.0.28 → 0.0.29
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/binding/wasi/wasi-worker.mjs +186 -0
- package/binding/wasi/zyzz.wasi.cjs +2302 -0
- package/binding/wasi/zyzz.wasm32-wasi.wasm +0 -0
- package/binding/zyzz.linux-x64-gnu.node +0 -0
- package/dist/babel/index.d.ts.map +1 -1
- package/dist/babel/index.js +2 -4
- package/dist/babel/index.js.map +1 -1
- package/dist/babel/internal/Compilation.d.ts +0 -1
- package/dist/babel/internal/Compilation.d.ts.map +1 -1
- package/dist/compiler/Graph.d.ts +14 -11
- package/dist/compiler/Graph.d.ts.map +1 -1
- package/dist/compiler/Graph.js +57 -1442
- package/dist/compiler/Graph.js.map +1 -1
- package/dist/compiler/Native.d.ts +7 -9
- package/dist/compiler/Native.d.ts.map +1 -1
- package/dist/compiler/Native.js +12 -716
- package/dist/compiler/Native.js.map +1 -1
- package/dist/compiler/Source.d.ts +122 -24
- package/dist/compiler/Source.d.ts.map +1 -1
- package/dist/compiler/Source.js +10 -1267
- package/dist/compiler/Source.js.map +1 -1
- package/dist/compiler/Transform.d.ts +4 -3
- package/dist/compiler/Transform.d.ts.map +1 -1
- package/dist/compiler/Transform.js +13 -961
- package/dist/compiler/Transform.js.map +1 -1
- package/dist/compiler/internal/AtRules.d.ts +5 -1
- package/dist/compiler/internal/AtRules.d.ts.map +1 -1
- package/dist/compiler/internal/AtRules.js +12 -106
- package/dist/compiler/internal/AtRules.js.map +1 -1
- package/dist/compiler/internal/Context.d.ts +11 -0
- package/dist/compiler/internal/Context.d.ts.map +1 -0
- package/dist/compiler/internal/Context.js +11 -0
- package/dist/compiler/internal/Context.js.map +1 -0
- package/dist/compiler/internal/Results.d.ts +148 -0
- package/dist/compiler/internal/Results.d.ts.map +1 -0
- package/dist/compiler/internal/Results.js +259 -0
- package/dist/compiler/internal/Results.js.map +1 -0
- package/dist/compiler/internal/Syntax.d.ts +0 -2
- package/dist/compiler/internal/Syntax.d.ts.map +1 -1
- package/dist/compiler/internal/Syntax.js +0 -2
- package/dist/compiler/internal/Syntax.js.map +1 -1
- package/dist/compiler/internal/Wire.d.ts +17 -0
- package/dist/compiler/internal/Wire.d.ts.map +1 -0
- package/dist/compiler/internal/Wire.js +795 -0
- package/dist/compiler/internal/Wire.js.map +1 -0
- package/dist/internal/Addon.d.ts +28 -0
- package/dist/internal/Addon.d.ts.map +1 -0
- package/dist/internal/Addon.js +87 -0
- package/dist/internal/Addon.js.map +1 -0
- package/dist/internal/Literal.d.ts +4 -1
- package/dist/internal/Literal.d.ts.map +1 -1
- package/dist/internal/Literal.js +4 -2
- package/dist/internal/Literal.js.map +1 -1
- package/dist/internal/Token.d.ts +2 -1
- package/dist/internal/Token.d.ts.map +1 -1
- package/dist/internal/Token.js +2 -2
- package/dist/internal/Token.js.map +1 -1
- package/dist/internal/Vlq.d.ts +14 -0
- package/dist/internal/Vlq.d.ts.map +1 -0
- package/dist/internal/Vlq.js +47 -0
- package/dist/internal/Vlq.js.map +1 -0
- package/dist/internal/Wasm.d.ts +22 -0
- package/dist/internal/Wasm.d.ts.map +1 -0
- package/dist/internal/Wasm.js +83 -0
- package/dist/internal/Wasm.js.map +1 -0
- package/dist/metro/Graph.d.ts +0 -1
- package/dist/metro/Graph.d.ts.map +1 -1
- package/dist/metro/transformer.d.ts.map +1 -1
- package/dist/metro/transformer.js +0 -1
- package/dist/metro/transformer.js.map +1 -1
- package/dist/next/internal/Project.d.ts.map +1 -1
- package/dist/next/internal/Project.js +2 -5
- package/dist/next/internal/Project.js.map +1 -1
- package/dist/node/Host.d.ts.map +1 -1
- package/dist/node/Host.js +0 -2
- package/dist/node/Host.js.map +1 -1
- package/dist/node/internal/Contracts.d.ts.map +1 -1
- package/dist/node/internal/Contracts.js +3 -7
- package/dist/node/internal/Contracts.js.map +1 -1
- package/dist/node/internal/Snapshot.d.ts +0 -1
- package/dist/node/internal/Snapshot.d.ts.map +1 -1
- package/dist/node/internal/Snapshot.js +0 -6
- package/dist/node/internal/Snapshot.js.map +1 -1
- package/dist/runtime/Composition.d.ts +2 -3
- package/dist/runtime/Composition.d.ts.map +1 -1
- package/dist/runtime/Composition.js +51 -30
- package/dist/runtime/Composition.js.map +1 -1
- package/dist/runtime/Recipe.d.ts.map +1 -1
- package/dist/runtime/Recipe.js +16 -12
- package/dist/runtime/Recipe.js.map +1 -1
- package/dist/unplugin/index.d.ts.map +1 -1
- package/dist/unplugin/index.js +3 -6
- package/dist/unplugin/index.js.map +1 -1
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +696 -201
- package/dist/vite/index.js.map +1 -1
- package/dist/web/Css.d.ts +8 -3
- package/dist/web/Css.d.ts.map +1 -1
- package/dist/web/Css.js +5 -721
- package/dist/web/Css.js.map +1 -1
- package/dist/web/internal/Block.d.ts +0 -2
- package/dist/web/internal/Block.d.ts.map +1 -1
- package/dist/web/internal/Block.js +1 -12
- package/dist/web/internal/Block.js.map +1 -1
- package/dist/web/internal/ClassName.d.ts +23 -18
- package/dist/web/internal/ClassName.d.ts.map +1 -1
- package/dist/web/internal/ClassName.js +26 -55
- package/dist/web/internal/ClassName.js.map +1 -1
- package/dist/web/internal/Contributions.d.ts +3 -5
- package/dist/web/internal/Contributions.d.ts.map +1 -1
- package/dist/web/internal/Contributions.js +0 -45
- package/dist/web/internal/Contributions.js.map +1 -1
- package/dist/web/internal/Engine.browser.d.ts +8 -0
- package/dist/web/internal/Engine.browser.d.ts.map +1 -0
- package/dist/web/internal/Engine.browser.js +42 -0
- package/dist/web/internal/Engine.browser.js.map +1 -0
- package/dist/web/internal/Engine.d.ts +9 -0
- package/dist/web/internal/Engine.d.ts.map +1 -0
- package/dist/web/internal/Engine.js +14 -0
- package/dist/web/internal/Engine.js.map +1 -0
- package/dist/web/internal/Themes.d.ts +1 -9
- package/dist/web/internal/Themes.d.ts.map +1 -1
- package/dist/web/internal/Themes.js +3 -221
- package/dist/web/internal/Themes.js.map +1 -1
- package/dist/web/internal/Wasm.generated.d.ts +4 -0
- package/dist/web/internal/Wasm.generated.d.ts.map +1 -0
- package/dist/web/internal/Wasm.generated.js +4 -0
- package/dist/web/internal/Wasm.generated.js.map +1 -0
- package/dist/web/internal/Wire.d.ts +19 -0
- package/dist/web/internal/Wire.d.ts.map +1 -0
- package/dist/web/internal/Wire.js +387 -0
- package/dist/web/internal/Wire.js.map +1 -0
- package/package.json +20 -1
- package/src/babel/index.ts +2 -5
- package/src/babel/internal/Compilation.ts +0 -1
- package/src/compiler/Graph.ts +89 -1930
- package/src/compiler/Native.ts +18 -871
- package/src/compiler/Source.ts +144 -1803
- package/src/compiler/Transform.ts +16 -1315
- package/src/compiler/internal/AtRules.ts +27 -115
- package/src/compiler/internal/Context.ts +11 -0
- package/src/compiler/internal/Results.ts +406 -0
- package/src/compiler/internal/Syntax.ts +0 -3
- package/src/compiler/internal/Wire.ts +1045 -0
- package/src/internal/Addon.ts +118 -0
- package/src/internal/Literal.ts +4 -2
- package/src/internal/Token.ts +2 -2
- package/src/internal/Vlq.ts +59 -0
- package/src/internal/Wasm.ts +111 -0
- package/src/metro/transformer.ts +0 -1
- package/src/next/internal/Project.ts +2 -9
- package/src/node/Host.ts +0 -2
- package/src/node/internal/Contracts.ts +3 -7
- package/src/node/internal/Snapshot.ts +0 -8
- package/src/runtime/Composition.ts +48 -25
- package/src/runtime/Recipe.ts +21 -14
- package/src/unplugin/index.ts +6 -6
- package/src/vite/index.ts +922 -221
- package/src/web/Css.ts +12 -908
- package/src/web/internal/Block.ts +0 -14
- package/src/web/internal/ClassName.ts +52 -85
- package/src/web/internal/Contributions.ts +3 -59
- package/src/web/internal/Engine.browser.ts +51 -0
- package/src/web/internal/Engine.ts +17 -0
- package/src/web/internal/Themes.ts +3 -279
- package/src/web/internal/Wasm.generated.ts +3 -0
- package/src/web/internal/Wire.ts +466 -0
- package/src/web/internal/wasm.d.ts +9 -0
- package/dist/compiler/internal/Applications.d.ts +0 -55
- package/dist/compiler/internal/Applications.d.ts.map +0 -1
- package/dist/compiler/internal/Applications.js +0 -393
- package/dist/compiler/internal/Applications.js.map +0 -1
- package/dist/compiler/internal/ColorProfiles.d.ts +0 -3
- package/dist/compiler/internal/ColorProfiles.d.ts.map +0 -1
- package/dist/compiler/internal/ColorProfiles.js +0 -84
- package/dist/compiler/internal/ColorProfiles.js.map +0 -1
- package/dist/compiler/internal/CompositionBindings.d.ts +0 -16
- package/dist/compiler/internal/CompositionBindings.d.ts.map +0 -1
- package/dist/compiler/internal/CompositionBindings.js +0 -89
- package/dist/compiler/internal/CompositionBindings.js.map +0 -1
- package/dist/compiler/internal/Compositions.d.ts +0 -37
- package/dist/compiler/internal/Compositions.d.ts.map +0 -1
- package/dist/compiler/internal/Compositions.js +0 -494
- package/dist/compiler/internal/Compositions.js.map +0 -1
- package/dist/compiler/internal/Configurations.d.ts +0 -26
- package/dist/compiler/internal/Configurations.d.ts.map +0 -1
- package/dist/compiler/internal/Configurations.js +0 -259
- package/dist/compiler/internal/Configurations.js.map +0 -1
- package/dist/compiler/internal/Contract.d.ts +0 -30
- package/dist/compiler/internal/Contract.d.ts.map +0 -1
- package/dist/compiler/internal/Contract.js +0 -753
- package/dist/compiler/internal/Contract.js.map +0 -1
- package/dist/compiler/internal/Contributions.d.ts +0 -54
- package/dist/compiler/internal/Contributions.d.ts.map +0 -1
- package/dist/compiler/internal/Contributions.js +0 -1151
- package/dist/compiler/internal/Contributions.js.map +0 -1
- package/dist/compiler/internal/Descriptors.d.ts +0 -15
- package/dist/compiler/internal/Descriptors.d.ts.map +0 -1
- package/dist/compiler/internal/Descriptors.js +0 -192
- package/dist/compiler/internal/Descriptors.js.map +0 -1
- package/dist/compiler/internal/Dynamic.d.ts +0 -14
- package/dist/compiler/internal/Dynamic.d.ts.map +0 -1
- package/dist/compiler/internal/Dynamic.js +0 -175
- package/dist/compiler/internal/Dynamic.js.map +0 -1
- package/dist/compiler/internal/Expression.d.ts +0 -19
- package/dist/compiler/internal/Expression.d.ts.map +0 -1
- package/dist/compiler/internal/Expression.js +0 -164
- package/dist/compiler/internal/Expression.js.map +0 -1
- package/dist/compiler/internal/Functions.d.ts +0 -5
- package/dist/compiler/internal/Functions.d.ts.map +0 -1
- package/dist/compiler/internal/Functions.js +0 -191
- package/dist/compiler/internal/Functions.js.map +0 -1
- package/dist/compiler/internal/Keyframes.d.ts +0 -5
- package/dist/compiler/internal/Keyframes.d.ts.map +0 -1
- package/dist/compiler/internal/Keyframes.js +0 -51
- package/dist/compiler/internal/Keyframes.js.map +0 -1
- package/dist/compiler/internal/Names.d.ts +0 -5
- package/dist/compiler/internal/Names.d.ts.map +0 -1
- package/dist/compiler/internal/Names.js +0 -37
- package/dist/compiler/internal/Names.js.map +0 -1
- package/dist/compiler/internal/NativeBindings.d.ts +0 -72
- package/dist/compiler/internal/NativeBindings.d.ts.map +0 -1
- package/dist/compiler/internal/NativeBindings.js +0 -171
- package/dist/compiler/internal/NativeBindings.js.map +0 -1
- package/dist/compiler/internal/NativeMedia.d.ts +0 -14
- package/dist/compiler/internal/NativeMedia.d.ts.map +0 -1
- package/dist/compiler/internal/NativeMedia.js +0 -287
- package/dist/compiler/internal/NativeMedia.js.map +0 -1
- package/dist/compiler/internal/NativeVars.d.ts +0 -28
- package/dist/compiler/internal/NativeVars.d.ts.map +0 -1
- package/dist/compiler/internal/NativeVars.js +0 -160
- package/dist/compiler/internal/NativeVars.js.map +0 -1
- package/dist/compiler/internal/PackedStyles.d.ts +0 -37
- package/dist/compiler/internal/PackedStyles.d.ts.map +0 -1
- package/dist/compiler/internal/PackedStyles.js +0 -344
- package/dist/compiler/internal/PackedStyles.js.map +0 -1
- package/dist/compiler/internal/Properties.d.ts +0 -5
- package/dist/compiler/internal/Properties.d.ts.map +0 -1
- package/dist/compiler/internal/Properties.js +0 -82
- package/dist/compiler/internal/Properties.js.map +0 -1
- package/dist/compiler/internal/RecipeConditions.d.ts +0 -41
- package/dist/compiler/internal/RecipeConditions.d.ts.map +0 -1
- package/dist/compiler/internal/RecipeConditions.js +0 -82
- package/dist/compiler/internal/RecipeConditions.js.map +0 -1
- package/dist/compiler/internal/RecipePayloads.d.ts +0 -31
- package/dist/compiler/internal/RecipePayloads.d.ts.map +0 -1
- package/dist/compiler/internal/RecipePayloads.js +0 -99
- package/dist/compiler/internal/RecipePayloads.js.map +0 -1
- package/dist/compiler/internal/Recipes.d.ts +0 -32
- package/dist/compiler/internal/Recipes.d.ts.map +0 -1
- package/dist/compiler/internal/Recipes.js +0 -339
- package/dist/compiler/internal/Recipes.js.map +0 -1
- package/dist/compiler/internal/Selectors.d.ts +0 -13
- package/dist/compiler/internal/Selectors.d.ts.map +0 -1
- package/dist/compiler/internal/Selectors.js +0 -280
- package/dist/compiler/internal/Selectors.js.map +0 -1
- package/dist/compiler/internal/Static.d.ts +0 -39
- package/dist/compiler/internal/Static.d.ts.map +0 -1
- package/dist/compiler/internal/Static.js +0 -534
- package/dist/compiler/internal/Static.js.map +0 -1
- package/dist/compiler/internal/Themes.d.ts +0 -190
- package/dist/compiler/internal/Themes.d.ts.map +0 -1
- package/dist/compiler/internal/Themes.js +0 -1577
- package/dist/compiler/internal/Themes.js.map +0 -1
- package/dist/compiler/internal/Vars.d.ts +0 -33
- package/dist/compiler/internal/Vars.d.ts.map +0 -1
- package/dist/compiler/internal/Vars.js +0 -387
- package/dist/compiler/internal/Vars.js.map +0 -1
- package/dist/compiler/internal/ViewTransitions.d.ts +0 -3
- package/dist/compiler/internal/ViewTransitions.d.ts.map +0 -1
- package/dist/compiler/internal/ViewTransitions.js +0 -68
- package/dist/compiler/internal/ViewTransitions.js.map +0 -1
- package/dist/internal/Cascade.d.ts +0 -74
- package/dist/internal/Cascade.d.ts.map +0 -1
- package/dist/internal/Cascade.js +0 -210
- package/dist/internal/Cascade.js.map +0 -1
- package/src/compiler/internal/Applications.ts +0 -610
- package/src/compiler/internal/ColorProfiles.ts +0 -93
- package/src/compiler/internal/CompositionBindings.ts +0 -120
- package/src/compiler/internal/Compositions.ts +0 -678
- package/src/compiler/internal/Configurations.ts +0 -349
- package/src/compiler/internal/Contract.ts +0 -1028
- package/src/compiler/internal/Contributions.ts +0 -1561
- package/src/compiler/internal/Descriptors.ts +0 -242
- package/src/compiler/internal/Dynamic.ts +0 -275
- package/src/compiler/internal/Expression.ts +0 -218
- package/src/compiler/internal/Functions.ts +0 -206
- package/src/compiler/internal/Keyframes.ts +0 -62
- package/src/compiler/internal/Names.ts +0 -48
- package/src/compiler/internal/NativeBindings.ts +0 -235
- package/src/compiler/internal/NativeMedia.ts +0 -342
- package/src/compiler/internal/NativeVars.ts +0 -231
- package/src/compiler/internal/PackedStyles.ts +0 -473
- package/src/compiler/internal/Properties.ts +0 -121
- package/src/compiler/internal/RecipeConditions.ts +0 -139
- package/src/compiler/internal/RecipePayloads.ts +0 -132
- package/src/compiler/internal/Recipes.ts +0 -531
- package/src/compiler/internal/Selectors.ts +0 -353
- package/src/compiler/internal/Static.ts +0 -784
- package/src/compiler/internal/Themes.ts +0 -2398
- package/src/compiler/internal/Vars.ts +0 -516
- package/src/compiler/internal/ViewTransitions.ts +0 -82
|
@@ -0,0 +1,1045 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decodes Rust `source.extract` results into the frozen data `Source.extract` returns.
|
|
3
|
+
* The format is documented in `crates/compiler/src/compiler/internal/wire.rs`.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import * as Authoring from '../../internal/Authoring.js'
|
|
7
|
+
import * as Binding from '../../internal/Binding.js'
|
|
8
|
+
import type * as Block from '../../web/internal/Block.js'
|
|
9
|
+
import * as ClassName from '../../web/internal/ClassName.js'
|
|
10
|
+
import * as Configuration from '../../internal/Configuration.js'
|
|
11
|
+
import type * as Css from '../../web/Css.js'
|
|
12
|
+
import * as Identity from '../../internal/Identity.js'
|
|
13
|
+
import { MissingTransformError } from '../../styleFunction.js'
|
|
14
|
+
import type * as Query from '../../internal/Query.js'
|
|
15
|
+
import * as Source from '../Source.js'
|
|
16
|
+
import * as Style from '../../Style.js'
|
|
17
|
+
import * as Theme from '../../internal/Theme.js'
|
|
18
|
+
import * as Token from '../../internal/Token.js'
|
|
19
|
+
import * as Vars from '../../Vars.js'
|
|
20
|
+
|
|
21
|
+
type Json =
|
|
22
|
+
| null
|
|
23
|
+
| boolean
|
|
24
|
+
| number
|
|
25
|
+
| string
|
|
26
|
+
| readonly Json[]
|
|
27
|
+
| { readonly [key: string]: Json }
|
|
28
|
+
type Pairs = readonly (readonly [string, Json])[]
|
|
29
|
+
type Fields = { readonly [key: string]: Json }
|
|
30
|
+
|
|
31
|
+
/** A failure encoded by the Rust compiler. */
|
|
32
|
+
type Failure = {
|
|
33
|
+
readonly diagnostics?: readonly Fields[]
|
|
34
|
+
readonly message: string
|
|
35
|
+
readonly name: string
|
|
36
|
+
readonly path?: readonly string[]
|
|
37
|
+
readonly reason?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Decodes one extraction result, or throws the error the extraction failed with.
|
|
42
|
+
* @param text - JSON text returned by the `source.extract` operation.
|
|
43
|
+
* @returns Frozen calls, styles, theme data, and contributions.
|
|
44
|
+
* @throws {Source.ExtractError} With every source diagnostic of a failed extraction.
|
|
45
|
+
*/
|
|
46
|
+
export function decode(
|
|
47
|
+
text: string,
|
|
48
|
+
options: decode.Options = {},
|
|
49
|
+
): Source.extract.ReturnType {
|
|
50
|
+
const output = JSON.parse(text) as {
|
|
51
|
+
readonly contracts?: readonly Fields[]
|
|
52
|
+
readonly error?: Failure
|
|
53
|
+
readonly result?: Fields
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (output.error) throw failure(output.error)
|
|
57
|
+
|
|
58
|
+
const contracts = (output.contracts ?? []).map(contract)
|
|
59
|
+
const decoder = create(contracts, options)
|
|
60
|
+
|
|
61
|
+
return decoder.result(output.result ?? {})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Extraction options that shape the decoded result. */
|
|
65
|
+
export declare namespace decode {
|
|
66
|
+
/** The options passed to the extraction. */
|
|
67
|
+
type Options = {
|
|
68
|
+
/** `false` when the extraction collected portable identities without source rewriting. */
|
|
69
|
+
readonly compiler?: boolean | undefined
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Reconstructs the error class a TypeScript extraction throws. */
|
|
74
|
+
function failure(error: Failure): Error {
|
|
75
|
+
switch (error.name) {
|
|
76
|
+
case 'Source.ExtractError':
|
|
77
|
+
return new Source.ExtractError(
|
|
78
|
+
(error.diagnostics ?? []).map((diagnostic) =>
|
|
79
|
+
Object.freeze({
|
|
80
|
+
code: diagnostic.code as Source.Diagnostic['code'],
|
|
81
|
+
end: diagnostic.end as number,
|
|
82
|
+
message: diagnostic.message as string,
|
|
83
|
+
source: diagnostic.source as string,
|
|
84
|
+
start: diagnostic.start as number,
|
|
85
|
+
}),
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
case 'Config.InvalidError':
|
|
89
|
+
return new Configuration.InvalidError(error.message)
|
|
90
|
+
case 'Theme.InvalidError':
|
|
91
|
+
return new Theme.InvalidError(
|
|
92
|
+
error.path ?? [],
|
|
93
|
+
error.reason ?? error.message,
|
|
94
|
+
)
|
|
95
|
+
case 'Vars.InvalidError':
|
|
96
|
+
return new Vars.InvalidError(
|
|
97
|
+
error.path ?? [],
|
|
98
|
+
error.reason ?? error.message,
|
|
99
|
+
)
|
|
100
|
+
case 'Style.InvalidError':
|
|
101
|
+
return new Style.InvalidError(
|
|
102
|
+
(error.diagnostics ?? []).map((diagnostic) => {
|
|
103
|
+
const location = diagnostic.location as Fields | undefined
|
|
104
|
+
|
|
105
|
+
return Object.freeze({
|
|
106
|
+
code: diagnostic.code as 'invalid_structure' | 'invalid_value',
|
|
107
|
+
...(location
|
|
108
|
+
? {
|
|
109
|
+
location: Object.freeze({
|
|
110
|
+
end: location.end as number,
|
|
111
|
+
path: Object.freeze([...(location.path as string[])]),
|
|
112
|
+
source: location.source as string,
|
|
113
|
+
start: location.start as number,
|
|
114
|
+
}),
|
|
115
|
+
}
|
|
116
|
+
: {}),
|
|
117
|
+
message: diagnostic.message as string,
|
|
118
|
+
path: Object.freeze([...(diagnostic.path as string[])]),
|
|
119
|
+
}) as Style.Diagnostic
|
|
120
|
+
}),
|
|
121
|
+
)
|
|
122
|
+
case 'MissingTransformError':
|
|
123
|
+
return new MissingTransformError()
|
|
124
|
+
default:
|
|
125
|
+
return new Error(error.message)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Rebuilds a contract with its enumerable properties in creation order. */
|
|
130
|
+
function contract(input: Fields): Token.Contract {
|
|
131
|
+
const value: Record<string | symbol, unknown> = {}
|
|
132
|
+
|
|
133
|
+
for (const key of input.keys as string[]) {
|
|
134
|
+
if (key === 'variableSet') value.variableSet = true
|
|
135
|
+
else if (key === 'mappings')
|
|
136
|
+
value.mappings = (() => {
|
|
137
|
+
if (input.mappings === undefined) return undefined
|
|
138
|
+
if (input.mappings === false) return false
|
|
139
|
+
return properties(input.mappings as Pairs)
|
|
140
|
+
})()
|
|
141
|
+
else if (key === 'shorthands')
|
|
142
|
+
value.shorthands = shorthands(input.shorthands)
|
|
143
|
+
else value[key] = input[key]
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (input.identity !== null) value[Token.identity] = input.identity
|
|
147
|
+
if (input.complete) value[Token.complete] = true
|
|
148
|
+
|
|
149
|
+
return Object.freeze(value) as Token.Contract
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Shorthand mappings are frozen null-prototype records, as `Shorthands.read` returns them. */
|
|
153
|
+
function shorthands(
|
|
154
|
+
input: Json | undefined,
|
|
155
|
+
): Readonly<Record<string, readonly string[]>> {
|
|
156
|
+
return Object.freeze(lookup(input, strings))
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** A frozen record of frozen string lists. */
|
|
160
|
+
function properties(input: Pairs): Readonly<Record<string, readonly string[]>> {
|
|
161
|
+
return Object.freeze(
|
|
162
|
+
Object.fromEntries(
|
|
163
|
+
input.map(([key, value]) => [
|
|
164
|
+
key,
|
|
165
|
+
Object.freeze([...(value as string[])]),
|
|
166
|
+
]),
|
|
167
|
+
),
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function number(input: Json | undefined): number {
|
|
172
|
+
if (typeof input === 'number') return input
|
|
173
|
+
const tag = (input as Fields).n
|
|
174
|
+
if (tag === 'NaN') return Number.NaN
|
|
175
|
+
if (tag === 'Infinity') return Number.POSITIVE_INFINITY
|
|
176
|
+
if (tag === '-Infinity') return Number.NEGATIVE_INFINITY
|
|
177
|
+
return -0
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function isNumber(input: Json | undefined): boolean {
|
|
181
|
+
return (
|
|
182
|
+
typeof input === 'number' ||
|
|
183
|
+
(typeof input === 'object' &&
|
|
184
|
+
input !== null &&
|
|
185
|
+
!Array.isArray(input) &&
|
|
186
|
+
'n' in input)
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function strings(input: Json | undefined): readonly string[] {
|
|
191
|
+
return Object.freeze([...(input as string[])])
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function record<value>(
|
|
195
|
+
input: Json | undefined,
|
|
196
|
+
decode: (value: Json) => value,
|
|
197
|
+
): Readonly<Record<string, value>> {
|
|
198
|
+
return Object.freeze(
|
|
199
|
+
Object.fromEntries(
|
|
200
|
+
(input as Pairs).map(([key, value]) => [key, decode(value)]),
|
|
201
|
+
),
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Authored container names are frozen copies, and an omitted list is a fresh array. */
|
|
206
|
+
function containerNames(input: Json | undefined): readonly string[] {
|
|
207
|
+
const names = input as string[]
|
|
208
|
+
return names.length ? Object.freeze([...names]) : []
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** A mutable null-prototype record. */
|
|
212
|
+
function lookup<value>(
|
|
213
|
+
input: Json | undefined,
|
|
214
|
+
decode: (value: Json) => value,
|
|
215
|
+
): Record<string, value> {
|
|
216
|
+
return Object.assign(
|
|
217
|
+
Object.create(null) as Record<string, value>,
|
|
218
|
+
Object.fromEntries(
|
|
219
|
+
(input as Pairs).map(([key, value]) => [key, decode(value)]),
|
|
220
|
+
),
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Creates a decoder that shares one contract table. */
|
|
225
|
+
function create(contracts: readonly Token.Contract[], options: decode.Options) {
|
|
226
|
+
function binding(input: Fields): Binding.Reference {
|
|
227
|
+
const value = {
|
|
228
|
+
name: input.name as `--${string}`,
|
|
229
|
+
type: input.type as Binding.Domain,
|
|
230
|
+
...(input.zero ? { zero: true } : {}),
|
|
231
|
+
variable: true as const,
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return Object.freeze(
|
|
235
|
+
input.dynamic
|
|
236
|
+
? Object.defineProperty(value, Binding.dynamic, { value: true })
|
|
237
|
+
: value,
|
|
238
|
+
) as Binding.Reference
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function reference(input: Fields): Token.Reference {
|
|
242
|
+
const value = Token.create({
|
|
243
|
+
contract: contracts[input.c as number]!,
|
|
244
|
+
group: input.g as Token.Group,
|
|
245
|
+
path: input.p as string,
|
|
246
|
+
value: tokenValue(input.v) as Token.Value,
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
return input.w
|
|
250
|
+
? (Object.freeze({
|
|
251
|
+
...value,
|
|
252
|
+
[Token.web]: true as const,
|
|
253
|
+
}) as Token.Reference)
|
|
254
|
+
: value
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function expression(input: Fields): Token.Expression {
|
|
258
|
+
const parts = Object.freeze(
|
|
259
|
+
(input.parts as Json[]).map((part) => {
|
|
260
|
+
if (typeof part === 'string') return part
|
|
261
|
+
const fields = part as Fields
|
|
262
|
+
if ('binding' in fields) return binding(fields.binding as Fields)
|
|
263
|
+
return reference(fields.ref as Fields)
|
|
264
|
+
}),
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
return Object.freeze(
|
|
268
|
+
input.group === null
|
|
269
|
+
? { [Token.expression]: true as const, parts }
|
|
270
|
+
: { [Token.expression]: true as const, group: input.group, parts },
|
|
271
|
+
) as Token.Expression
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function tokenValue(input: Json | undefined): unknown {
|
|
275
|
+
if (typeof input === 'string') return input
|
|
276
|
+
if (isNumber(input)) return number(input)
|
|
277
|
+
const fields = input as Fields
|
|
278
|
+
if ('ref' in fields) return reference(fields.ref as Fields)
|
|
279
|
+
if ('expr' in fields) return expression(fields.expr as Fields)
|
|
280
|
+
return record(fields.obj!, tokenValue)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function data(input: Json | undefined): unknown {
|
|
284
|
+
if (input === undefined) return undefined
|
|
285
|
+
if (
|
|
286
|
+
input === null ||
|
|
287
|
+
typeof input === 'string' ||
|
|
288
|
+
typeof input === 'boolean'
|
|
289
|
+
)
|
|
290
|
+
return input
|
|
291
|
+
if (typeof input === 'number') return input
|
|
292
|
+
if (Array.isArray(input)) return Object.freeze(input.map(data))
|
|
293
|
+
const fields = input as Fields
|
|
294
|
+
if ('n' in fields) return number(fields)
|
|
295
|
+
if ('$' in fields) return undefined
|
|
296
|
+
if ('ref' in fields) return reference(fields.ref as Fields)
|
|
297
|
+
if ('expr' in fields) return expression(fields.expr as Fields)
|
|
298
|
+
if ('binding' in fields) return binding(fields.binding as Fields)
|
|
299
|
+
if ('theme' in fields) return definition(fields.theme as Fields)
|
|
300
|
+
return record(fields.obj!, data)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Authored configuration literals are mutable, and their objects have no prototype.
|
|
304
|
+
function authored(input: Json | undefined): unknown {
|
|
305
|
+
if (Array.isArray(input)) return input.map(authored)
|
|
306
|
+
if (input === null || typeof input !== 'object') return data(input)
|
|
307
|
+
const fields = input as Fields
|
|
308
|
+
if (!('obj' in fields)) return data(input)
|
|
309
|
+
return lookup(fields.obj, authored)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Theme values flatten token groups into mutable records around the frozen token values.
|
|
313
|
+
// A group is never a value, so an object with scheme or condition keys is one.
|
|
314
|
+
function tree(input: Json | undefined): unknown {
|
|
315
|
+
const fields = input as Fields | null
|
|
316
|
+
const entries =
|
|
317
|
+
fields !== null && typeof fields === 'object'
|
|
318
|
+
? (fields.obj as Pairs)
|
|
319
|
+
: undefined
|
|
320
|
+
if (
|
|
321
|
+
!entries ||
|
|
322
|
+
entries.some(
|
|
323
|
+
([key]) => key === 'default' || key === 'light' || key === 'dark',
|
|
324
|
+
)
|
|
325
|
+
)
|
|
326
|
+
return data(input)
|
|
327
|
+
return Object.fromEntries(entries.map(([key, value]) => [key, tree(value)]))
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Query metadata spreads over the token values of each configured theme.
|
|
331
|
+
function themeValues(input: Json | undefined) {
|
|
332
|
+
return Object.fromEntries(
|
|
333
|
+
((input as Fields).obj as Pairs).map(([key, value]) => {
|
|
334
|
+
if (key === 'breakpoint' || key === 'container')
|
|
335
|
+
return [key, Object.freeze(lookup((value as Fields).obj, String))]
|
|
336
|
+
if (key === 'containerNames') return [key, containerNames(value)]
|
|
337
|
+
return [key, tree(value)]
|
|
338
|
+
}),
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Normalized configuration options keep authored literals beside the flattened themes.
|
|
343
|
+
function configOptions(input: Json | undefined): Record<string, unknown> {
|
|
344
|
+
return Object.fromEntries(
|
|
345
|
+
((input as Fields).obj as Pairs).map(([key, value]) => {
|
|
346
|
+
if (key === 'theme') return [key, themeValues(value)]
|
|
347
|
+
if (key === 'themes')
|
|
348
|
+
return [
|
|
349
|
+
key,
|
|
350
|
+
Object.fromEntries(
|
|
351
|
+
((value as Fields).obj as Pairs).map(([name, theme]) => [
|
|
352
|
+
name,
|
|
353
|
+
themeValues(theme),
|
|
354
|
+
]),
|
|
355
|
+
),
|
|
356
|
+
]
|
|
357
|
+
return [key, authored(value)]
|
|
358
|
+
}),
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function definition(input: Fields): Theme.Definition {
|
|
363
|
+
const contract = contracts[input.contract as number]!
|
|
364
|
+
const queries = input.queries as Fields | null
|
|
365
|
+
const metadata = Object.freeze({
|
|
366
|
+
contract,
|
|
367
|
+
...(input.cssName !== null ? { cssName: input.cssName as string } : {}),
|
|
368
|
+
...(input.paths !== null
|
|
369
|
+
? { paths: properties(input.paths as Pairs) }
|
|
370
|
+
: {}),
|
|
371
|
+
values: record(input.values, tokenValue) as Token.Metadata['values'],
|
|
372
|
+
// Variable sets always record their query metadata, even when it is empty.
|
|
373
|
+
...(contract.variableSet && !queries ? { queries: undefined } : {}),
|
|
374
|
+
...(queries
|
|
375
|
+
? {
|
|
376
|
+
queries: Object.freeze({
|
|
377
|
+
breakpoint: Object.freeze(lookup(queries.breakpoint, String)),
|
|
378
|
+
containerNames: containerNames(queries.containerNames),
|
|
379
|
+
container: Object.freeze(lookup(queries.container, String)),
|
|
380
|
+
}) as Query.Metadata,
|
|
381
|
+
}
|
|
382
|
+
: {}),
|
|
383
|
+
})
|
|
384
|
+
const className = input.className as Fields
|
|
385
|
+
const value: Theme.Definition = Object.freeze(
|
|
386
|
+
Object.defineProperty(
|
|
387
|
+
{
|
|
388
|
+
get className(): string {
|
|
389
|
+
if ('ok' in className) return className.ok as string
|
|
390
|
+
if (className.error === new MissingTransformError().message)
|
|
391
|
+
throw new MissingTransformError()
|
|
392
|
+
throw new Error(className.error as string)
|
|
393
|
+
},
|
|
394
|
+
style: (styles?: unknown, options: Record<string, unknown> = {}) => {
|
|
395
|
+
if (!contract[Token.identity])
|
|
396
|
+
Identity.requireId(undefined, 'Theme.define')
|
|
397
|
+
return Authoring.create(styles, {
|
|
398
|
+
...options,
|
|
399
|
+
theme: value,
|
|
400
|
+
} as never)
|
|
401
|
+
},
|
|
402
|
+
tokens: data(input.tokens),
|
|
403
|
+
variants: (
|
|
404
|
+
styles: Record<string, unknown>,
|
|
405
|
+
options: Record<string, unknown> = {},
|
|
406
|
+
) => Authoring.variants(styles, options as never),
|
|
407
|
+
vars: data(input.vars),
|
|
408
|
+
},
|
|
409
|
+
Token.definition,
|
|
410
|
+
{ value: metadata },
|
|
411
|
+
),
|
|
412
|
+
) as unknown as Theme.Definition
|
|
413
|
+
|
|
414
|
+
return value
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function declarationValue(input: Json): Style.Declaration['value'] {
|
|
418
|
+
return data(input) as Style.Declaration['value']
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function style(input: Fields): Style.NamedStyle {
|
|
422
|
+
const declarations = Object.freeze(
|
|
423
|
+
(input.declarations as Json[][]).map(([property, value, important]) =>
|
|
424
|
+
Object.freeze({
|
|
425
|
+
...(important ? { important: true } : {}),
|
|
426
|
+
property: property as Style.Declaration['property'],
|
|
427
|
+
value: declarationValue(value!),
|
|
428
|
+
}),
|
|
429
|
+
),
|
|
430
|
+
)
|
|
431
|
+
const rules = input.rules as Json[][] | undefined
|
|
432
|
+
const targets = input.targets as Fields | undefined
|
|
433
|
+
const body = rules
|
|
434
|
+
? {
|
|
435
|
+
name: input.name as string,
|
|
436
|
+
declarations,
|
|
437
|
+
rules: Object.freeze(
|
|
438
|
+
rules.map(([condition, child]) =>
|
|
439
|
+
Object.freeze({
|
|
440
|
+
...(condition !== null
|
|
441
|
+
? { condition: condition as string }
|
|
442
|
+
: {}),
|
|
443
|
+
style: style(child as Fields),
|
|
444
|
+
}),
|
|
445
|
+
),
|
|
446
|
+
),
|
|
447
|
+
}
|
|
448
|
+
: { declarations, name: input.name as string }
|
|
449
|
+
|
|
450
|
+
return Object.freeze({
|
|
451
|
+
...body,
|
|
452
|
+
...(targets
|
|
453
|
+
? {
|
|
454
|
+
targets: Object.freeze({
|
|
455
|
+
...(targets.native !== undefined
|
|
456
|
+
? { native: target(targets.native) }
|
|
457
|
+
: {}),
|
|
458
|
+
...(targets.ios !== undefined
|
|
459
|
+
? { ios: target(targets.ios) }
|
|
460
|
+
: {}),
|
|
461
|
+
...(targets.android !== undefined
|
|
462
|
+
? { android: target(targets.android) }
|
|
463
|
+
: {}),
|
|
464
|
+
...(targets.web !== undefined
|
|
465
|
+
? { web: style(targets.web as Fields) }
|
|
466
|
+
: {}),
|
|
467
|
+
}),
|
|
468
|
+
}
|
|
469
|
+
: {}),
|
|
470
|
+
...(input.composition !== undefined
|
|
471
|
+
? { composition: input.composition }
|
|
472
|
+
: {}),
|
|
473
|
+
...(input.cssOutput !== undefined ? { cssOutput: input.cssOutput } : {}),
|
|
474
|
+
}) as Style.NamedStyle
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Native target data is copied into frozen null-prototype records, as `Targets.copy` does.
|
|
478
|
+
function target(input: Json | undefined): unknown {
|
|
479
|
+
if (Array.isArray(input)) return Object.freeze(input.map(target))
|
|
480
|
+
if (input === null || typeof input !== 'object' || !('obj' in input))
|
|
481
|
+
return data(input)
|
|
482
|
+
return Object.freeze(lookup((input as Fields).obj, target))
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function styles(input: Fields): Style.Definition {
|
|
486
|
+
return Object.freeze({
|
|
487
|
+
styles: Object.freeze((input.styles as Fields[]).map(style)),
|
|
488
|
+
})
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Compositions copy the styles they combine, and a copy differs from its source in content.
|
|
492
|
+
function composed(
|
|
493
|
+
input: Fields,
|
|
494
|
+
sources: ReadonlyMap<string, string>,
|
|
495
|
+
): Style.NamedStyle {
|
|
496
|
+
const decoded = style(input)
|
|
497
|
+
const rules = input.rules as Json[][] | undefined
|
|
498
|
+
const name = input.name as string
|
|
499
|
+
|
|
500
|
+
if (!rules || !decoded.rules) return decoded
|
|
501
|
+
|
|
502
|
+
const copied = (child: Fields) =>
|
|
503
|
+
sources.get(child.name as string) !== JSON.stringify(child)
|
|
504
|
+
|
|
505
|
+
// Runtime compositions copy each conditional rule with the output mode of its source.
|
|
506
|
+
if (name.startsWith('composition-'))
|
|
507
|
+
return Object.freeze({
|
|
508
|
+
...decoded,
|
|
509
|
+
rules: Object.freeze(
|
|
510
|
+
decoded.rules.map((rule, index) => {
|
|
511
|
+
const child = rules[index]![1] as Fields
|
|
512
|
+
return copied(child) && !('cssOutput' in rule.style)
|
|
513
|
+
? Object.freeze({
|
|
514
|
+
...rule,
|
|
515
|
+
style: Object.freeze({ ...rule.style, cssOutput: undefined }),
|
|
516
|
+
})
|
|
517
|
+
: rule
|
|
518
|
+
}),
|
|
519
|
+
),
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
// Static compositions copy referenced styles mutably beside their inline parts.
|
|
523
|
+
if (
|
|
524
|
+
decoded.declarations.length ||
|
|
525
|
+
rules.some(([condition]) => condition !== null)
|
|
526
|
+
)
|
|
527
|
+
return decoded
|
|
528
|
+
|
|
529
|
+
return Object.freeze({
|
|
530
|
+
...decoded,
|
|
531
|
+
rules: Object.freeze(
|
|
532
|
+
decoded.rules.map((rule) =>
|
|
533
|
+
rule.style.name === name
|
|
534
|
+
? rule
|
|
535
|
+
: Object.freeze({ ...rule, style: { ...rule.style } }),
|
|
536
|
+
),
|
|
537
|
+
),
|
|
538
|
+
})
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function labelled(input: Fields): Style.Definition {
|
|
542
|
+
const inputs = input.styles as Fields[]
|
|
543
|
+
const sources = new Map(
|
|
544
|
+
inputs.map((entry) => [entry.name as string, JSON.stringify(entry)]),
|
|
545
|
+
)
|
|
546
|
+
const definition: Record<string | symbol, unknown> = {
|
|
547
|
+
styles: Object.freeze(inputs.map((entry) => composed(entry, sources))),
|
|
548
|
+
}
|
|
549
|
+
const labels = input.labels as Json[][] | undefined
|
|
550
|
+
|
|
551
|
+
if (labels)
|
|
552
|
+
Object.defineProperty(definition, ClassName.labels, {
|
|
553
|
+
value: Object.freeze(
|
|
554
|
+
Object.fromEntries(
|
|
555
|
+
labels.map(([name, label, namespace]) => [
|
|
556
|
+
name,
|
|
557
|
+
{ name: label, namespace: namespace ?? undefined },
|
|
558
|
+
]),
|
|
559
|
+
),
|
|
560
|
+
),
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
return Object.freeze(definition) as Style.Definition
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// A call's lowered recipe shares the axes and defaults of its recipe metadata.
|
|
567
|
+
function staticRecipe(
|
|
568
|
+
input: Fields,
|
|
569
|
+
shared: ReturnType<typeof recipe> | undefined,
|
|
570
|
+
) {
|
|
571
|
+
return {
|
|
572
|
+
axes:
|
|
573
|
+
shared?.axes ??
|
|
574
|
+
lookup(input.axes, (choices) => [...(choices as string[])]),
|
|
575
|
+
defaults: shared?.defaults ?? lookup(input.defaults, (value) => value),
|
|
576
|
+
rules: (input.rules as Fields[]).map((rule) => ({
|
|
577
|
+
matches: (rule.matches as Pairs).map(([axis, choices]) => [
|
|
578
|
+
axis,
|
|
579
|
+
[...(choices as string[])],
|
|
580
|
+
]),
|
|
581
|
+
value: styles(rule.value as Fields),
|
|
582
|
+
})),
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Recipe metadata is mutable and keyed by null-prototype records, as `Recipes.expand` builds it.
|
|
587
|
+
function recipe(input: Fields) {
|
|
588
|
+
return {
|
|
589
|
+
axes: lookup(input.axes, (choices) => [...(choices as string[])]),
|
|
590
|
+
defaults: lookup(input.defaults, (value) => value),
|
|
591
|
+
...(input.payloads !== undefined
|
|
592
|
+
? {
|
|
593
|
+
payloads: (input.payloads as Fields[]).map((payload) => ({
|
|
594
|
+
axis: payload.axis as string,
|
|
595
|
+
choice: payload.choice as string,
|
|
596
|
+
slots: (payload.slots as Pairs[]).map((slots) =>
|
|
597
|
+
Object.fromEntries(slots),
|
|
598
|
+
),
|
|
599
|
+
})),
|
|
600
|
+
defaultPayloads: lookup(input.defaultPayloads, (fields) =>
|
|
601
|
+
lookup(fields, (value) =>
|
|
602
|
+
isNumber(value) ? number(value) : value,
|
|
603
|
+
),
|
|
604
|
+
),
|
|
605
|
+
}
|
|
606
|
+
: {}),
|
|
607
|
+
...(input.conditions !== undefined
|
|
608
|
+
? { conditions: [...(input.conditions as string[])] }
|
|
609
|
+
: {}),
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
function slots(input: Json | undefined) {
|
|
614
|
+
return record(input, (value) => binding(value as Fields))
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Callback slots are null-prototype records, so field names never meet inherited keys.
|
|
618
|
+
function fields(input: Json | undefined) {
|
|
619
|
+
return Object.freeze(
|
|
620
|
+
Object.assign(
|
|
621
|
+
Object.create(null) as Record<string, Binding.Reference>,
|
|
622
|
+
Object.fromEntries(
|
|
623
|
+
(input as Pairs).map(([key, value]) => [
|
|
624
|
+
key,
|
|
625
|
+
binding(value as Fields),
|
|
626
|
+
]),
|
|
627
|
+
),
|
|
628
|
+
),
|
|
629
|
+
)
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function nativeContext(input: Fields) {
|
|
633
|
+
return Object.freeze({
|
|
634
|
+
defaultVars: input.defaultVars as string,
|
|
635
|
+
vars: record(input.vars, (value) => definition(value as Fields)),
|
|
636
|
+
})
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function owner(input: Fields) {
|
|
640
|
+
return Object.freeze({
|
|
641
|
+
attributes: strings(input.attributes),
|
|
642
|
+
identity: input.identity as string,
|
|
643
|
+
slots: strings(input.slots),
|
|
644
|
+
})
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function counts(input: Json | undefined): ReadonlyMap<number, number> {
|
|
648
|
+
return new Map(
|
|
649
|
+
(input as [number, number][]).map(([start, count]) => [start, count]),
|
|
650
|
+
)
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
function call(input: Fields): Source.Call {
|
|
654
|
+
const value: Record<string, unknown> = {}
|
|
655
|
+
const shared =
|
|
656
|
+
input.recipe !== undefined ? recipe(input.recipe as Fields) : undefined
|
|
657
|
+
|
|
658
|
+
// Without source rewriting, every definition call records its portable identity, if any.
|
|
659
|
+
if (
|
|
660
|
+
options.compiler === false &&
|
|
661
|
+
input.composition === undefined &&
|
|
662
|
+
input.runtimeComposition === undefined &&
|
|
663
|
+
input.compositionCase === undefined
|
|
664
|
+
)
|
|
665
|
+
value.portable = undefined
|
|
666
|
+
|
|
667
|
+
for (const [key, entry] of Object.entries(input)) {
|
|
668
|
+
switch (key) {
|
|
669
|
+
case 'nativeContext':
|
|
670
|
+
value[key] = nativeContext(entry as Fields)
|
|
671
|
+
break
|
|
672
|
+
case 'cssNamespace':
|
|
673
|
+
value[key] = entry ?? undefined
|
|
674
|
+
break
|
|
675
|
+
case 'portable':
|
|
676
|
+
value[key] = entry ?? undefined
|
|
677
|
+
break
|
|
678
|
+
// Composition metadata is assembled as mutable lists.
|
|
679
|
+
case 'portableInputs':
|
|
680
|
+
case 'compositionCases':
|
|
681
|
+
case 'composition':
|
|
682
|
+
value[key] = [...(entry as string[])]
|
|
683
|
+
break
|
|
684
|
+
case 'ownership':
|
|
685
|
+
value[key] = owner(entry as Fields)
|
|
686
|
+
break
|
|
687
|
+
case 'runtimeComposition':
|
|
688
|
+
value[key] = (entry as Fields[]).map((input) => ({
|
|
689
|
+
...(input.applicationStart !== undefined
|
|
690
|
+
? { applicationStart: input.applicationStart as number }
|
|
691
|
+
: {}),
|
|
692
|
+
...(input.condition !== undefined
|
|
693
|
+
? { condition: input.condition as number }
|
|
694
|
+
: {}),
|
|
695
|
+
end: input.end as number,
|
|
696
|
+
name: input.name as string,
|
|
697
|
+
owners: (input.owners as Fields[]).map((owner) => ({
|
|
698
|
+
attributes: [...(owner.attributes as string[])],
|
|
699
|
+
identity: owner.identity as string,
|
|
700
|
+
slots: [...(owner.slots as string[])],
|
|
701
|
+
})),
|
|
702
|
+
start: input.start as number,
|
|
703
|
+
}))
|
|
704
|
+
break
|
|
705
|
+
case 'recipe':
|
|
706
|
+
value[key] = shared
|
|
707
|
+
break
|
|
708
|
+
case 'dynamicRecipe':
|
|
709
|
+
case 'staticRecipe':
|
|
710
|
+
value[key] = staticRecipe(entry as Fields, shared)
|
|
711
|
+
break
|
|
712
|
+
case 'recipeTypes':
|
|
713
|
+
value[key] = lookup(entry, (choices) => lookup(choices, String))
|
|
714
|
+
break
|
|
715
|
+
case 'shorthands':
|
|
716
|
+
value[key] = shorthands(entry)
|
|
717
|
+
break
|
|
718
|
+
case 'typography':
|
|
719
|
+
case 'typographyQueries':
|
|
720
|
+
value[key] = counts(entry)
|
|
721
|
+
break
|
|
722
|
+
case 'slots':
|
|
723
|
+
value[key] = fields(entry)
|
|
724
|
+
break
|
|
725
|
+
default:
|
|
726
|
+
value[key] = entry
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
return Object.freeze(value) as Source.Call
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
function signature(input: Fields) {
|
|
734
|
+
return {
|
|
735
|
+
// Parameters are the evaluated literal records, which have no prototype.
|
|
736
|
+
parameters: (input.parameters as Fields[]).map((parameter) =>
|
|
737
|
+
Object.assign(Object.create(null) as Record<string, unknown>, {
|
|
738
|
+
...(parameter.default !== undefined
|
|
739
|
+
? {
|
|
740
|
+
default: isNumber(parameter.default)
|
|
741
|
+
? number(parameter.default)
|
|
742
|
+
: parameter.default,
|
|
743
|
+
}
|
|
744
|
+
: {}),
|
|
745
|
+
name: parameter.name,
|
|
746
|
+
...(parameter.syntax !== undefined
|
|
747
|
+
? { syntax: parameter.syntax }
|
|
748
|
+
: {}),
|
|
749
|
+
}),
|
|
750
|
+
),
|
|
751
|
+
returns: input.returns,
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Authored variable mappings stay the mutable null-prototype literal the configuration read.
|
|
756
|
+
function mappings(
|
|
757
|
+
input: Json | undefined,
|
|
758
|
+
): Source.extract.ReturnType['themeCalls'][number]['variableMappings'] {
|
|
759
|
+
if (input === null || input === undefined) return undefined
|
|
760
|
+
if (input === false) return false
|
|
761
|
+
return lookup(input, (properties) => [
|
|
762
|
+
...(properties as string[]),
|
|
763
|
+
]) as NonNullable<
|
|
764
|
+
Source.extract.ReturnType['themeCalls'][number]['variableMappings']
|
|
765
|
+
>
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// Configuration calls carry `appearance` and stay mutable. Factory calls are frozen.
|
|
769
|
+
function themeCall(
|
|
770
|
+
input: Fields,
|
|
771
|
+
): Source.extract.ReturnType['themeCalls'][number] {
|
|
772
|
+
const value: Record<string, unknown> = {}
|
|
773
|
+
|
|
774
|
+
for (const [key, entry] of Object.entries(input)) {
|
|
775
|
+
// Variable configurations always record their mappings, even when none were authored.
|
|
776
|
+
if (
|
|
777
|
+
key === 'variableMappings' &&
|
|
778
|
+
(input.variableConfig || entry === false)
|
|
779
|
+
) {
|
|
780
|
+
value[key] = mappings(entry)
|
|
781
|
+
continue
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
if (entry === null || entry === false) continue
|
|
785
|
+
|
|
786
|
+
switch (key) {
|
|
787
|
+
case 'function':
|
|
788
|
+
value[key] = signature(entry as Fields)
|
|
789
|
+
break
|
|
790
|
+
case 'members':
|
|
791
|
+
value[key] = input.appearance
|
|
792
|
+
? Object.fromEntries(entry as Pairs)
|
|
793
|
+
: record(entry, String)
|
|
794
|
+
break
|
|
795
|
+
case 'options':
|
|
796
|
+
value[key] = configOptions(entry)
|
|
797
|
+
break
|
|
798
|
+
case 'variables':
|
|
799
|
+
value[key] = slots(entry)
|
|
800
|
+
break
|
|
801
|
+
default:
|
|
802
|
+
value[key] = entry
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
return (
|
|
807
|
+
input.appearance ? value : Object.freeze(value)
|
|
808
|
+
) as Source.extract.ReturnType['themeCalls'][number]
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
function alias(
|
|
812
|
+
input: Fields,
|
|
813
|
+
): Source.extract.ReturnType['themeAliases'][number] {
|
|
814
|
+
const call = input.call as Fields
|
|
815
|
+
|
|
816
|
+
// A style alias copies a fixed set of the theme call's fields, defined or not.
|
|
817
|
+
if (input.bindings !== null)
|
|
818
|
+
return {
|
|
819
|
+
recipe: call.recipe as boolean,
|
|
820
|
+
destructured: input.destructured as boolean,
|
|
821
|
+
end: call.end as number,
|
|
822
|
+
name: call.name as string,
|
|
823
|
+
start: call.start as number,
|
|
824
|
+
tokenType: call.tokenType as string,
|
|
825
|
+
type: (call.type ?? undefined) as string | undefined,
|
|
826
|
+
options:
|
|
827
|
+
call.options === null ? undefined : configOptions(call.options),
|
|
828
|
+
variableConfig: call.variableConfig ? true : undefined,
|
|
829
|
+
variableMappings: mappings(call.variableMappings),
|
|
830
|
+
output: (call.output ?? undefined) as 'html' | undefined,
|
|
831
|
+
bindings: [...(input.bindings as ('style' | 'variants')[])],
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
return {
|
|
835
|
+
...themeCall(call),
|
|
836
|
+
destructured: input.destructured as boolean,
|
|
837
|
+
...(input.retained ? { retained: true } : {}),
|
|
838
|
+
} as Source.extract.ReturnType['themeAliases'][number]
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
function varsRead(
|
|
842
|
+
input: Fields,
|
|
843
|
+
): NonNullable<Source.extract.ReturnType['nativeVars']>[number] {
|
|
844
|
+
return {
|
|
845
|
+
defaultVars: input.defaultVars as string,
|
|
846
|
+
end: input.end as number,
|
|
847
|
+
owner: input.owner as string,
|
|
848
|
+
start: input.start as number,
|
|
849
|
+
unnamed: input.unnamed as boolean,
|
|
850
|
+
vars: Object.fromEntries(
|
|
851
|
+
(input.vars as Pairs).map(([key, value]) => [
|
|
852
|
+
key,
|
|
853
|
+
definition(value as Fields),
|
|
854
|
+
]),
|
|
855
|
+
),
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// Contribution data is mutable. Only the styles `Style.define` produces inside it are frozen.
|
|
860
|
+
function entry(input: Fields): Block.Entry {
|
|
861
|
+
if (input.kind === 'block')
|
|
862
|
+
return {
|
|
863
|
+
kind: 'block',
|
|
864
|
+
header: input.header as string,
|
|
865
|
+
entries: (input.entries as Fields[]).map(entry),
|
|
866
|
+
}
|
|
867
|
+
if (input.kind === 'descriptor')
|
|
868
|
+
return {
|
|
869
|
+
kind: 'descriptor',
|
|
870
|
+
name: input.name as string,
|
|
871
|
+
value: (isNumber(input.value!) ? number(input.value!) : input.value) as
|
|
872
|
+
| string
|
|
873
|
+
| number,
|
|
874
|
+
}
|
|
875
|
+
return { kind: 'style', style: style(input.style as Fields) }
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
function scalarRecord(input: Json | undefined) {
|
|
879
|
+
return Object.fromEntries(
|
|
880
|
+
(input as Pairs).map(([key, value]) => [
|
|
881
|
+
key,
|
|
882
|
+
isNumber(value) ? number(value) : value,
|
|
883
|
+
]),
|
|
884
|
+
) as Record<string, string | number>
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// Grouping rules nest plain `global` styles around the defined styles of their selectors.
|
|
888
|
+
function ruleStyle(input: Fields): Style.NamedStyle {
|
|
889
|
+
if (input.name !== 'global') return style(input)
|
|
890
|
+
|
|
891
|
+
return {
|
|
892
|
+
name: 'global',
|
|
893
|
+
declarations: [],
|
|
894
|
+
rules: ((input.rules as Json[][] | undefined) ?? []).map(
|
|
895
|
+
([condition, child]) => ({
|
|
896
|
+
condition: condition as string,
|
|
897
|
+
style: ruleStyle(child as Fields),
|
|
898
|
+
}),
|
|
899
|
+
),
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
function contribution(input: Fields): Css.Contribution {
|
|
904
|
+
const value = ((): Record<string, unknown> => {
|
|
905
|
+
switch (input.kind) {
|
|
906
|
+
case 'block':
|
|
907
|
+
return {
|
|
908
|
+
kind: 'block',
|
|
909
|
+
header: input.header,
|
|
910
|
+
entries: (input.entries as Fields[]).map(entry),
|
|
911
|
+
}
|
|
912
|
+
case 'descriptor':
|
|
913
|
+
return {
|
|
914
|
+
kind: 'descriptor',
|
|
915
|
+
rule: input.rule,
|
|
916
|
+
name: input.name,
|
|
917
|
+
declarations: scalarRecord(input.declarations),
|
|
918
|
+
}
|
|
919
|
+
case 'font-face':
|
|
920
|
+
return {
|
|
921
|
+
kind: 'font-face',
|
|
922
|
+
declarations: scalarRecord(input.declarations),
|
|
923
|
+
}
|
|
924
|
+
case 'keyframes':
|
|
925
|
+
return {
|
|
926
|
+
kind: 'keyframes',
|
|
927
|
+
name: input.name,
|
|
928
|
+
frames: (input.frames as Fields[]).map((frame) => ({
|
|
929
|
+
stop: frame.stop as string,
|
|
930
|
+
style: style(frame.style as Fields),
|
|
931
|
+
})),
|
|
932
|
+
}
|
|
933
|
+
case 'layers':
|
|
934
|
+
return { kind: 'layers', names: [...(input.names as string[])] }
|
|
935
|
+
case 'rule':
|
|
936
|
+
return {
|
|
937
|
+
kind: 'rule',
|
|
938
|
+
selector: input.selector,
|
|
939
|
+
style: ruleStyle(input.style as Fields),
|
|
940
|
+
}
|
|
941
|
+
default:
|
|
942
|
+
return Object.fromEntries(
|
|
943
|
+
Object.entries(input).filter(([key]) => key !== 'within'),
|
|
944
|
+
)
|
|
945
|
+
}
|
|
946
|
+
})()
|
|
947
|
+
|
|
948
|
+
return (
|
|
949
|
+
input.within !== undefined
|
|
950
|
+
? { ...value, within: [...(input.within as string[])] }
|
|
951
|
+
: value
|
|
952
|
+
) as Css.Contribution
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
function contributionCall(
|
|
956
|
+
input: Fields,
|
|
957
|
+
): NonNullable<Source.extract.ReturnType['contributionCalls']>[number] {
|
|
958
|
+
return {
|
|
959
|
+
kind: input.kind,
|
|
960
|
+
start: input.start,
|
|
961
|
+
end: input.end,
|
|
962
|
+
...(input.function !== undefined
|
|
963
|
+
? { function: signature(input.function as Fields) }
|
|
964
|
+
: {}),
|
|
965
|
+
...(input.name !== undefined ? { name: input.name } : {}),
|
|
966
|
+
...(input.binding !== undefined ? { binding: input.binding } : {}),
|
|
967
|
+
...(input.exported !== undefined ? { exported: input.exported } : {}),
|
|
968
|
+
} as NonNullable<Source.extract.ReturnType['contributionCalls']>[number]
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
function result(input: Fields): Source.extract.ReturnType {
|
|
972
|
+
const contributions = (
|
|
973
|
+
(input.contributions as Fields[] | undefined) ?? []
|
|
974
|
+
).map(contribution)
|
|
975
|
+
// Namespaces are the namespace contributions themselves, as a filtered list.
|
|
976
|
+
const value: Record<string, unknown> = {
|
|
977
|
+
namespaces: contributions.filter((entry) => entry.kind === 'namespace'),
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
if (input.contributions !== undefined) {
|
|
981
|
+
value.contributions = contributions
|
|
982
|
+
value.contributionStarts = [...(input.contributionStarts as number[])]
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
if (input.contributionCalls !== undefined)
|
|
986
|
+
value.contributionCalls = (input.contributionCalls as Fields[]).map(
|
|
987
|
+
contributionCall,
|
|
988
|
+
)
|
|
989
|
+
|
|
990
|
+
value.calls = Object.freeze((input.calls as Fields[]).map(call))
|
|
991
|
+
value.styles = labelled(input.styles as Fields)
|
|
992
|
+
|
|
993
|
+
if (input.variableCalls !== undefined)
|
|
994
|
+
value.variableCalls = Object.freeze(
|
|
995
|
+
(input.variableCalls as Fields[]).map((entry) =>
|
|
996
|
+
Object.freeze({
|
|
997
|
+
explicit: entry.explicit as boolean,
|
|
998
|
+
start: entry.start as number,
|
|
999
|
+
end: entry.end as number,
|
|
1000
|
+
slots: slots(entry.slots),
|
|
1001
|
+
}),
|
|
1002
|
+
),
|
|
1003
|
+
)
|
|
1004
|
+
|
|
1005
|
+
value.themeAliases = Object.freeze(
|
|
1006
|
+
(input.themeAliases as Fields[]).map(alias),
|
|
1007
|
+
)
|
|
1008
|
+
|
|
1009
|
+
for (const key of ['themeAppearances', 'themeScripts', 'themeSelections'])
|
|
1010
|
+
if (input[key] !== undefined) value[key] = strings(input[key]!)
|
|
1011
|
+
|
|
1012
|
+
value.themeCalls = Object.freeze(
|
|
1013
|
+
(input.themeCalls as Fields[]).map(themeCall),
|
|
1014
|
+
)
|
|
1015
|
+
|
|
1016
|
+
if (input.staticThemeReferences !== undefined)
|
|
1017
|
+
value.staticThemeReferences = Object.freeze(
|
|
1018
|
+
(input.staticThemeReferences as Fields[]).map((entry) => ({
|
|
1019
|
+
...entry,
|
|
1020
|
+
})),
|
|
1021
|
+
)
|
|
1022
|
+
|
|
1023
|
+
value.themeReferences = Object.freeze(
|
|
1024
|
+
(input.themeReferences as Fields[]).map((entry) =>
|
|
1025
|
+
Object.freeze({ ...entry }),
|
|
1026
|
+
),
|
|
1027
|
+
)
|
|
1028
|
+
// Collected themes are keyed by a null-prototype record. A module without theme
|
|
1029
|
+
// imports collects none and returns an ordinary empty record.
|
|
1030
|
+
value.vars = Object.freeze(
|
|
1031
|
+
input.collectedThemes
|
|
1032
|
+
? lookup(input.vars, (entry) => definition(entry as Fields))
|
|
1033
|
+
: {},
|
|
1034
|
+
)
|
|
1035
|
+
|
|
1036
|
+
if (input.nativeVars !== undefined)
|
|
1037
|
+
value.nativeVars = Object.freeze(
|
|
1038
|
+
(input.nativeVars as Fields[]).map(varsRead),
|
|
1039
|
+
)
|
|
1040
|
+
|
|
1041
|
+
return Object.freeze(value) as unknown as Source.extract.ReturnType
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
return { result }
|
|
1045
|
+
}
|