@cassida/compiler 0.1.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/LICENSE +21 -0
- package/config.schema.json +88 -0
- package/dist/canonicalizer.d.ts +42 -0
- package/dist/canonicalizer.d.ts.map +1 -0
- package/dist/canonicalizer.js +185 -0
- package/dist/canonicalizer.js.map +1 -0
- package/dist/compile.d.ts +46 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +84 -0
- package/dist/compile.js.map +1 -0
- package/dist/config.d.ts +182 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +150 -0
- package/dist/config.js.map +1 -0
- package/dist/emitter.d.ts +44 -0
- package/dist/emitter.d.ts.map +1 -0
- package/dist/emitter.js +189 -0
- package/dist/emitter.js.map +1 -0
- package/dist/generated-property-specs.d.ts +3193 -0
- package/dist/generated-property-specs.d.ts.map +1 -0
- package/dist/generated-property-specs.js +472 -0
- package/dist/generated-property-specs.js.map +1 -0
- package/dist/hasher.d.ts +8 -0
- package/dist/hasher.d.ts.map +1 -0
- package/dist/hasher.js +10 -0
- package/dist/hasher.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/modifier-spec.d.ts +104 -0
- package/dist/modifier-spec.d.ts.map +1 -0
- package/dist/modifier-spec.js +52 -0
- package/dist/modifier-spec.js.map +1 -0
- package/dist/plugin.d.ts +66 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +65 -0
- package/dist/plugin.js.map +1 -0
- package/dist/property-spec.d.ts +321 -0
- package/dist/property-spec.d.ts.map +1 -0
- package/dist/property-spec.js +382 -0
- package/dist/property-spec.js.map +1 -0
- package/dist/registry.d.ts +71 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +123 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +135 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +6 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +6 -0
- package/dist/util.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FSS contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "CassConfig",
|
|
4
|
+
"description": "FSS (Functional Style Sheet) configuration. Place this at the project root as cassida.config.json. Every field is optional; missing fields fall back to FSS defaults.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"properties": {
|
|
8
|
+
"$schema": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "JSON Schema URL for editor autocomplete."
|
|
11
|
+
},
|
|
12
|
+
"layer": {
|
|
13
|
+
"type": ["string", "null"],
|
|
14
|
+
"description": "@layer name for the cascade-isolation wrapper. Use null to disable the @layer wrap entirely.",
|
|
15
|
+
"default": "fss"
|
|
16
|
+
},
|
|
17
|
+
"importSource": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "Module specifier the parser recognizes as the source of `fss`. Renamed imports (`{ fss as ff }`) are honored automatically.",
|
|
20
|
+
"default": "@cassida/core"
|
|
21
|
+
},
|
|
22
|
+
"hash": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"description": "Class-name hashing parameters.",
|
|
26
|
+
"properties": {
|
|
27
|
+
"prefix": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Prefix prepended to every generated class name.",
|
|
30
|
+
"default": "cas-"
|
|
31
|
+
},
|
|
32
|
+
"length": {
|
|
33
|
+
"type": "integer",
|
|
34
|
+
"description": "Hex characters of SHA-1 digest used as the hash. 8 is enough for ~tens of thousands of unique rules; bump to 10–12 for very large apps.",
|
|
35
|
+
"minimum": 4,
|
|
36
|
+
"maximum": 40,
|
|
37
|
+
"default": 8
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"media": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"additionalProperties": false,
|
|
44
|
+
"description": "Media-query handling.",
|
|
45
|
+
"properties": {
|
|
46
|
+
"sort": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"enum": ["mobile-first", "desktop-first"],
|
|
49
|
+
"description": "Cascade direction for width-based @media queries. Mobile-first sorts min-width ascending and max-width descending; desktop-first reverses both.",
|
|
50
|
+
"default": "mobile-first"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"css": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"additionalProperties": false,
|
|
57
|
+
"description": "CSS-emission strategy and post-processing.",
|
|
58
|
+
"properties": {
|
|
59
|
+
"mode": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"enum": ["rule-per-class", "shared-by-declaration"],
|
|
62
|
+
"description": "rule-per-class: one rule per className with declarations baked in. shared-by-declaration: one rule per (property, value) with grouped selectors. Phase 4+ feature; recognized but not yet implemented.",
|
|
63
|
+
"default": "rule-per-class"
|
|
64
|
+
},
|
|
65
|
+
"lightningcss": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"description": "Optional lightningcss post-processing of the emitted CSS. Phase 5+ feature; recognized but not yet implemented.",
|
|
69
|
+
"properties": {
|
|
70
|
+
"enabled": {
|
|
71
|
+
"type": "boolean",
|
|
72
|
+
"default": false
|
|
73
|
+
},
|
|
74
|
+
"minify": {
|
|
75
|
+
"type": "boolean",
|
|
76
|
+
"default": true
|
|
77
|
+
},
|
|
78
|
+
"targets": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"description": "Browserslist string passed to lightningcss.",
|
|
81
|
+
"default": "defaults"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Op, type Scope, type ScopeBag } from './types.js';
|
|
2
|
+
import type { Registry } from './registry.js';
|
|
3
|
+
import type { ShorthandPolicy } from './config.js';
|
|
4
|
+
/**
|
|
5
|
+
* Walks an `Op[]` chain, LIFO-collapsing each scope's declarations and
|
|
6
|
+
* recursing into nested scoped sub-chains. The output is a deterministic
|
|
7
|
+
* `ScopeBag` tree: the root has `scope: null` and owns "base"
|
|
8
|
+
* declarations; each child carries its modifier (`:hover`, `@media (...)`,
|
|
9
|
+
* raw selector) plus its own bag and further children.
|
|
10
|
+
*
|
|
11
|
+
* Multiple scoped ops at the same scope key (e.g. two `.hover(...)`
|
|
12
|
+
* calls in the same chain) are merged: their inner ops are concatenated,
|
|
13
|
+
* then re-collapsed inside the merged scope. This matches the user's
|
|
14
|
+
* intuition that "`.hover()` adds, doesn't replace" while still
|
|
15
|
+
* applying property-level LIFO inside the merged scope.
|
|
16
|
+
*/
|
|
17
|
+
export declare class Canonicalizer {
|
|
18
|
+
private readonly registry;
|
|
19
|
+
private readonly policy;
|
|
20
|
+
constructor(registry: Registry, policy?: ShorthandPolicy);
|
|
21
|
+
collapse(ops: readonly Op[], scope?: Scope | null): ScopeBag;
|
|
22
|
+
/**
|
|
23
|
+
* Apply the configured shorthand-policy check. Throws when the user
|
|
24
|
+
* mixes shorthand and longhand of the same family within a single
|
|
25
|
+
* scope in a way the policy forbids. The error message names both
|
|
26
|
+
* methods and points at the three escape hatches: modifier callback,
|
|
27
|
+
* looser `policy` config, or sticking to one form.
|
|
28
|
+
*/
|
|
29
|
+
private checkShorthandPolicy;
|
|
30
|
+
private policyError;
|
|
31
|
+
/**
|
|
32
|
+
* Deterministic key derived from a scope tree.
|
|
33
|
+
*
|
|
34
|
+
* For static-only chains (no modifiers, no nested scopes) the format
|
|
35
|
+
* matches Phase 1 exactly — sorted entry pairs — so existing class
|
|
36
|
+
* hashes are preserved across the Phase 2 upgrade. Trees with any
|
|
37
|
+
* nested scope use the structured form, which encodes the full
|
|
38
|
+
* sorted scope-tree shape.
|
|
39
|
+
*/
|
|
40
|
+
canonicalKey(tree: ScopeBag): string;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=canonicalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonicalizer.d.ts","sourceRoot":"","sources":["../src/canonicalizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,EAAE,EACP,KAAK,KAAK,EACV,KAAK,QAAQ,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,eAAe,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,QAAQ,EAAE,QAAQ,EAClB,MAAM,GAAE,eAA0B;IAGrD,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,GAAE,KAAK,GAAG,IAAW,GAAG,QAAQ;IA4ElE;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IAkC5B,OAAO,CAAC,WAAW;IAiBnB;;;;;;;;OAQG;IACH,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM;CAOrC"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { DYNAMIC_PLACEHOLDER, isDynamic, isMethodOp, isRawOp, isScopedOp, } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Walks an `Op[]` chain, LIFO-collapsing each scope's declarations and
|
|
4
|
+
* recursing into nested scoped sub-chains. The output is a deterministic
|
|
5
|
+
* `ScopeBag` tree: the root has `scope: null` and owns "base"
|
|
6
|
+
* declarations; each child carries its modifier (`:hover`, `@media (...)`,
|
|
7
|
+
* raw selector) plus its own bag and further children.
|
|
8
|
+
*
|
|
9
|
+
* Multiple scoped ops at the same scope key (e.g. two `.hover(...)`
|
|
10
|
+
* calls in the same chain) are merged: their inner ops are concatenated,
|
|
11
|
+
* then re-collapsed inside the merged scope. This matches the user's
|
|
12
|
+
* intuition that "`.hover()` adds, doesn't replace" while still
|
|
13
|
+
* applying property-level LIFO inside the merged scope.
|
|
14
|
+
*/
|
|
15
|
+
export class Canonicalizer {
|
|
16
|
+
registry;
|
|
17
|
+
policy;
|
|
18
|
+
constructor(registry, policy = 'strict') {
|
|
19
|
+
this.registry = registry;
|
|
20
|
+
this.policy = policy;
|
|
21
|
+
}
|
|
22
|
+
collapse(ops, scope = null) {
|
|
23
|
+
const bag = {};
|
|
24
|
+
const slots = {};
|
|
25
|
+
const childOpsByKey = new Map();
|
|
26
|
+
// Per-scope tracking for shorthand ↔ longhand co-occurrence.
|
|
27
|
+
// Recursion into ScopedOps creates a fresh `collapse` invocation
|
|
28
|
+
// with its own local `seenShorthand` / `seenLonghand`, so the
|
|
29
|
+
// `media`/`hover`/`on` scope automatically reset the constraint.
|
|
30
|
+
const seenShorthand = new Map();
|
|
31
|
+
const seenLonghand = new Map();
|
|
32
|
+
for (const op of ops) {
|
|
33
|
+
if (isMethodOp(op)) {
|
|
34
|
+
const entry = this.registry[op.method];
|
|
35
|
+
if (!entry) {
|
|
36
|
+
throw new Error(`[cassida] unknown method "${op.method}". Add it to the registry or check for typos.`);
|
|
37
|
+
}
|
|
38
|
+
this.checkShorthandPolicy(op.method, entry, seenShorthand, seenLonghand);
|
|
39
|
+
const dynamics = op.args.filter(isDynamic);
|
|
40
|
+
if (dynamics.length === 0) {
|
|
41
|
+
bag[entry.property] = entry.format(...op.args);
|
|
42
|
+
delete slots[entry.property];
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (op.args.length !== 1 || dynamics.length !== 1) {
|
|
46
|
+
throw new Error(`[cassida] mixed/multi-dynamic args are not supported in this phase; method "${op.method}"`);
|
|
47
|
+
}
|
|
48
|
+
bag[entry.property] = DYNAMIC_PLACEHOLDER;
|
|
49
|
+
slots[entry.property] = dynamics[0].id;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (isScopedOp(op)) {
|
|
53
|
+
const key = scopeKey(op.scope);
|
|
54
|
+
const existing = childOpsByKey.get(key);
|
|
55
|
+
if (existing) {
|
|
56
|
+
existing.ops.push(...op.ops);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
childOpsByKey.set(key, { scope: op.scope, ops: [...op.ops] });
|
|
60
|
+
}
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (isRawOp(op)) {
|
|
64
|
+
// RawOps bypass the registry entirely. They sit in the bag as
|
|
65
|
+
// pre-formatted CSS declarations. Shorthand-policy and family
|
|
66
|
+
// tracking deliberately do NOT apply — the user already opted
|
|
67
|
+
// out of the safety net by routing through `cas.unsafe`.
|
|
68
|
+
bag[op.property] = op.value;
|
|
69
|
+
delete slots[op.property];
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const children = [];
|
|
74
|
+
for (const { scope: childScope, ops: childOps } of childOpsByKey.values()) {
|
|
75
|
+
children.push(this.collapse(childOps, childScope));
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
scope,
|
|
79
|
+
bag,
|
|
80
|
+
slots,
|
|
81
|
+
children,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Apply the configured shorthand-policy check. Throws when the user
|
|
86
|
+
* mixes shorthand and longhand of the same family within a single
|
|
87
|
+
* scope in a way the policy forbids. The error message names both
|
|
88
|
+
* methods and points at the three escape hatches: modifier callback,
|
|
89
|
+
* looser `policy` config, or sticking to one form.
|
|
90
|
+
*/
|
|
91
|
+
checkShorthandPolicy(methodName, entry, seenShorthand, seenLonghand) {
|
|
92
|
+
if (this.policy === 'lenient') {
|
|
93
|
+
// No-op, but still record so downstream code can introspect if needed.
|
|
94
|
+
if (entry.shorthandFamily)
|
|
95
|
+
seenShorthand.set(entry.shorthandFamily, methodName);
|
|
96
|
+
if (entry.longhandFamily)
|
|
97
|
+
seenLonghand.set(entry.longhandFamily, methodName);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// longhand → shorthand check (strict only — the bug-prone direction).
|
|
101
|
+
if (entry.shorthandFamily) {
|
|
102
|
+
const family = entry.shorthandFamily;
|
|
103
|
+
const conflicting = seenLonghand.get(family);
|
|
104
|
+
if (this.policy === 'strict' && conflicting !== undefined) {
|
|
105
|
+
throw new Error(this.policyError('shorthand', methodName, conflicting, family));
|
|
106
|
+
}
|
|
107
|
+
seenShorthand.set(family, methodName);
|
|
108
|
+
}
|
|
109
|
+
// shorthand → longhand check (always — both 'strict' and 'shorthand-first').
|
|
110
|
+
if (entry.longhandFamily) {
|
|
111
|
+
const family = entry.longhandFamily;
|
|
112
|
+
const conflicting = seenShorthand.get(family);
|
|
113
|
+
if (conflicting !== undefined) {
|
|
114
|
+
throw new Error(this.policyError('longhand', methodName, conflicting, family));
|
|
115
|
+
}
|
|
116
|
+
seenLonghand.set(family, methodName);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
policyError(incomingKind, incomingMethod, earlierMethod, family) {
|
|
120
|
+
const prior = incomingKind === 'shorthand' ? 'longhand' : 'shorthand';
|
|
121
|
+
return (`[cassida] ${incomingKind} "${incomingMethod}" cannot follow ${prior} "${earlierMethod}" ` +
|
|
122
|
+
`in the same scope (family: "${family}", policy: "${this.policy}"). ` +
|
|
123
|
+
`Resolve via one of:\n` +
|
|
124
|
+
` • Use a modifier callback (.media(...), .hover(...), .on(...)) to scope them separately.\n` +
|
|
125
|
+
` • Set "shorthand.policy" to "shorthand-first" or "lenient" in cassida.config.json.\n` +
|
|
126
|
+
` • Stick to a single form (only shorthand, or only longhands) in this scope.`);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Deterministic key derived from a scope tree.
|
|
130
|
+
*
|
|
131
|
+
* For static-only chains (no modifiers, no nested scopes) the format
|
|
132
|
+
* matches Phase 1 exactly — sorted entry pairs — so existing class
|
|
133
|
+
* hashes are preserved across the Phase 2 upgrade. Trees with any
|
|
134
|
+
* nested scope use the structured form, which encodes the full
|
|
135
|
+
* sorted scope-tree shape.
|
|
136
|
+
*/
|
|
137
|
+
canonicalKey(tree) {
|
|
138
|
+
if (tree.scope === null && tree.children.length === 0) {
|
|
139
|
+
const keys = Object.keys(tree.bag).sort();
|
|
140
|
+
return JSON.stringify(keys.map((k) => [k, tree.bag[k]]));
|
|
141
|
+
}
|
|
142
|
+
return JSON.stringify(serialize(tree));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function serialize(node) {
|
|
146
|
+
const bag = Object.keys(node.bag)
|
|
147
|
+
.sort()
|
|
148
|
+
.map((k) => [k, node.bag[k]]);
|
|
149
|
+
const sortedChildren = [...node.children].sort((a, b) => scopeOrderKey(a.scope).localeCompare(scopeOrderKey(b.scope)));
|
|
150
|
+
return {
|
|
151
|
+
s: serializeScope(node.scope),
|
|
152
|
+
b: bag,
|
|
153
|
+
c: sortedChildren.map(serialize),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function serializeScope(scope) {
|
|
157
|
+
if (scope === null)
|
|
158
|
+
return null;
|
|
159
|
+
if (scope.kind === 'pseudo')
|
|
160
|
+
return { k: 'pseudo', v: scope.selector };
|
|
161
|
+
if (scope.kind === 'media')
|
|
162
|
+
return { k: 'media', v: scope.query };
|
|
163
|
+
return { k: 'raw', v: scope.selector };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Stable string used to (a) identify same-scope ops in `collapse`, and
|
|
167
|
+
* (b) sort sibling children deterministically in `canonicalKey`.
|
|
168
|
+
*
|
|
169
|
+
* Pseudo scopes sort before media scopes before raw scopes, with
|
|
170
|
+
* lexicographic order within each group. This is purely a
|
|
171
|
+
* canonicalization device — emission ordering for output CSS is
|
|
172
|
+
* decided by the emitter (which uses the same prefix to keep `:hover`
|
|
173
|
+
* rules before `@media` rules in the output).
|
|
174
|
+
*/
|
|
175
|
+
function scopeKey(scope) {
|
|
176
|
+
return scopeOrderKey(scope);
|
|
177
|
+
}
|
|
178
|
+
function scopeOrderKey(scope) {
|
|
179
|
+
if (scope.kind === 'pseudo')
|
|
180
|
+
return `0${scope.selector}`;
|
|
181
|
+
if (scope.kind === 'media')
|
|
182
|
+
return `1${scope.query}`;
|
|
183
|
+
return `2${scope.selector}`;
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=canonicalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonicalizer.js","sourceRoot":"","sources":["../src/canonicalizer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,UAAU,EACV,OAAO,EACP,UAAU,GAKX,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,aAAa;IAEL;IACA;IAFnB,YACmB,QAAkB,EAClB,SAA0B,QAAQ;QADlC,aAAQ,GAAR,QAAQ,CAAU;QAClB,WAAM,GAAN,MAAM,CAA4B;IAClD,CAAC;IAEJ,QAAQ,CAAC,GAAkB,EAAE,QAAsB,IAAI;QACrD,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,MAAM,KAAK,GAA2B,EAAE,CAAC;QACzC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAuC,CAAC;QACrE,6DAA6D;QAC7D,iEAAiE;QACjE,8DAA8D;QAC9D,iEAAiE;QACjE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;QAChD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE/C,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;gBACvC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,MAAM,IAAI,KAAK,CACb,6BAA6B,EAAE,CAAC,MAAM,+CAA+C,CACtF,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;gBAEzE,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAA0B,CAAC;gBAEpE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC1B,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;oBAC/C,OAAO,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;oBAC7B,SAAS;gBACX,CAAC;gBAED,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAClD,MAAM,IAAI,KAAK,CACb,+EAA+E,EAAE,CAAC,MAAM,GAAG,CAC5F,CAAC;gBACJ,CAAC;gBAED,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,mBAAmB,CAAC;gBAC1C,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;gBACxC,SAAS;YACX,CAAC;YAED,IAAI,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnB,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;gBAC/B,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACxC,IAAI,QAAQ,EAAE,CAAC;oBACb,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACN,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAChE,CAAC;gBACD,SAAS;YACX,CAAC;YAED,IAAI,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChB,8DAA8D;gBAC9D,8DAA8D;gBAC9D,8DAA8D;gBAC9D,yDAAyD;gBACzD,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;gBAC5B,OAAO,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;gBAC1B,SAAS;YACX,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAe,EAAE,CAAC;QAChC,KAAK,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1E,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;QACrD,CAAC;QAED,OAAO;YACL,KAAK;YACL,GAAG;YACH,KAAK;YACL,QAAQ;SACT,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACK,oBAAoB,CAC1B,UAAkB,EAClB,KAAoB,EACpB,aAAkC,EAClC,YAAiC;QAEjC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,uEAAuE;YACvE,IAAI,KAAK,CAAC,eAAe;gBAAE,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAChF,IAAI,KAAK,CAAC,cAAc;gBAAE,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QAED,sEAAsE;QACtE,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,eAAe,CAAC;YACrC,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC1D,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;YAClF,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACxC,CAAC;QAED,6EAA6E;QAC7E,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;YACpC,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC9C,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;YACjF,CAAC;YACD,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAEO,WAAW,CACjB,YAAsC,EACtC,cAAsB,EACtB,aAAqB,EACrB,MAAc;QAEd,MAAM,KAAK,GAAG,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;QACtE,OAAO,CACL,aAAa,YAAY,KAAK,cAAc,mBAAmB,KAAK,KAAK,aAAa,IAAI;YAC1F,+BAA+B,MAAM,eAAe,IAAI,CAAC,MAAM,MAAM;YACrE,uBAAuB;YACvB,8FAA8F;YAC9F,wFAAwF;YACxF,+EAA+E,CAChF,CAAC;IACJ,CAAC;IAED;;;;;;;;OAQG;IACH,YAAY,CAAC,IAAc;QACzB,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,CAAC;CACF;AAaD,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,GAAG,GAAqC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;SAChE,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,CAAU,CAAC,CAAC;IAC1C,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACtD,aAAa,CAAC,CAAC,CAAC,KAAM,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,KAAM,CAAC,CAAC,CAC/D,CAAC;IACF,OAAO;QACL,CAAC,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;QAC7B,CAAC,EAAE,GAAG;QACN,CAAC,EAAE,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAmB;IACzC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IACvE,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAClE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;AACzC,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,QAAQ,CAAC,KAAY;IAC5B,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,aAAa,CAAC,KAAY;IACjC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1D,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;IACtD,OAAO,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type CompiledRule, type Op } from './types.js';
|
|
2
|
+
import type { Registry } from './registry.js';
|
|
3
|
+
import { type HashOptions } from './hasher.js';
|
|
4
|
+
import { type PropertyMeta } from './property-spec.js';
|
|
5
|
+
import type { ShorthandPolicy } from './config.js';
|
|
6
|
+
import { type CassPlugin, type PluginContext } from './plugin.js';
|
|
7
|
+
export interface CompileOptions extends HashOptions {
|
|
8
|
+
readonly registry: Registry;
|
|
9
|
+
/**
|
|
10
|
+
* Override the property → metadata table used to enrich dynamic slots
|
|
11
|
+
* with `animatable` / `syntax` / `initialValue`. Defaults to the
|
|
12
|
+
* canonical spec's own metadata; only override when extending the
|
|
13
|
+
* registry with custom properties that need their own `@property`
|
|
14
|
+
* descriptors.
|
|
15
|
+
*/
|
|
16
|
+
readonly propertyMeta?: Readonly<Record<string, PropertyMeta>>;
|
|
17
|
+
/**
|
|
18
|
+
* Policy for shorthand ↔ longhand co-occurrence within a single
|
|
19
|
+
* scope. Defaults to `'strict'`. See `ShorthandPolicy` in `config.ts`.
|
|
20
|
+
*/
|
|
21
|
+
readonly shorthandPolicy?: ShorthandPolicy;
|
|
22
|
+
/**
|
|
23
|
+
* Build-time plugins. Each plugin receives the post-collapse
|
|
24
|
+
* `ScopeBag` tree and returns a new tree; the className is derived
|
|
25
|
+
* from the post-plugin form. Plugins run in array order.
|
|
26
|
+
*/
|
|
27
|
+
readonly plugins?: readonly CassPlugin[];
|
|
28
|
+
/**
|
|
29
|
+
* Subset of resolved config exposed to plugins through their
|
|
30
|
+
* `PluginContext`. Optional — if omitted, plugins receive a minimal
|
|
31
|
+
* default context.
|
|
32
|
+
*/
|
|
33
|
+
readonly pluginContext?: PluginContext;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Pure: an `Op[]` chain in, a deterministic `CompiledRule` out.
|
|
37
|
+
*
|
|
38
|
+
* The canonical key is computed from the *shape* of the scope tree (not
|
|
39
|
+
* concrete dynamic values), so chains with the same set of properties
|
|
40
|
+
* and modifiers collapse to the same className regardless of the
|
|
41
|
+
* dynamic source values. Each dynamic slot ends up in `dynamics` with a
|
|
42
|
+
* fresh `--<className>-<scope-segments>-<prop>` variable name; the
|
|
43
|
+
* parser uses these to populate the element's inline style.
|
|
44
|
+
*/
|
|
45
|
+
export declare function compileOps(ops: readonly Op[], options: CompileOptions): CompiledRule;
|
|
46
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,EAAE,EAIR,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAQ,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAgB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhF,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC/D;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,YAAY,CA0BpF"}
|
package/dist/compile.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { DYNAMIC_PLACEHOLDER, } from './types.js';
|
|
2
|
+
import { Canonicalizer } from './canonicalizer.js';
|
|
3
|
+
import { hash } from './hasher.js';
|
|
4
|
+
import { defaultPropertyMeta } from './property-spec.js';
|
|
5
|
+
import { applyPlugins } from './plugin.js';
|
|
6
|
+
/**
|
|
7
|
+
* Pure: an `Op[]` chain in, a deterministic `CompiledRule` out.
|
|
8
|
+
*
|
|
9
|
+
* The canonical key is computed from the *shape* of the scope tree (not
|
|
10
|
+
* concrete dynamic values), so chains with the same set of properties
|
|
11
|
+
* and modifiers collapse to the same className regardless of the
|
|
12
|
+
* dynamic source values. Each dynamic slot ends up in `dynamics` with a
|
|
13
|
+
* fresh `--<className>-<scope-segments>-<prop>` variable name; the
|
|
14
|
+
* parser uses these to populate the element's inline style.
|
|
15
|
+
*/
|
|
16
|
+
export function compileOps(ops, options) {
|
|
17
|
+
const canon = new Canonicalizer(options.registry, options.shorthandPolicy ?? 'strict');
|
|
18
|
+
const rawTree = canon.collapse(ops);
|
|
19
|
+
// Plugin pipeline: between collapse and canonicalKey so that any
|
|
20
|
+
// tree shape change (e.g. wrapping :hover in @media (hover: hover))
|
|
21
|
+
// propagates into the className. This is the FSS bijection
|
|
22
|
+
// contract: same hash ⇔ same final-state CSS.
|
|
23
|
+
const ctx = options.pluginContext ?? {
|
|
24
|
+
config: { layer: 'fss', importSource: '@cassida/core' },
|
|
25
|
+
};
|
|
26
|
+
const transformedTree = applyPlugins(rawTree, options.plugins, ctx);
|
|
27
|
+
const canonical = canon.canonicalKey(transformedTree);
|
|
28
|
+
const className = hash(canonical, options);
|
|
29
|
+
const meta = options.propertyMeta ?? defaultPropertyMeta;
|
|
30
|
+
const dynamics = [];
|
|
31
|
+
const tree = substituteVars(transformedTree, className, meta, dynamics, []);
|
|
32
|
+
return {
|
|
33
|
+
className,
|
|
34
|
+
tree,
|
|
35
|
+
canonical,
|
|
36
|
+
dynamics: Object.freeze(dynamics),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function substituteVars(node, className, meta, dynamics, scopePath) {
|
|
40
|
+
const newBag = {};
|
|
41
|
+
for (const prop of Object.keys(node.bag).sort()) {
|
|
42
|
+
const val = node.bag[prop];
|
|
43
|
+
if (val === DYNAMIC_PLACEHOLDER) {
|
|
44
|
+
const varName = makeVarName(className, scopePath, prop);
|
|
45
|
+
newBag[prop] = `var(${varName})`;
|
|
46
|
+
const m = meta[prop];
|
|
47
|
+
dynamics.push({
|
|
48
|
+
property: prop,
|
|
49
|
+
varName,
|
|
50
|
+
sourceId: node.slots[prop],
|
|
51
|
+
animatable: m?.animatable ?? false,
|
|
52
|
+
syntax: m?.syntax,
|
|
53
|
+
initialValue: m?.initialValue,
|
|
54
|
+
scopePath: [...scopePath],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
newBag[prop] = val;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const newChildren = node.children.map((c) => substituteVars(c, className, meta, dynamics, [...scopePath, c.scope]));
|
|
62
|
+
return {
|
|
63
|
+
scope: node.scope,
|
|
64
|
+
bag: Object.freeze(newBag),
|
|
65
|
+
slots: node.slots,
|
|
66
|
+
children: Object.freeze(newChildren),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function makeVarName(className, scopePath, prop) {
|
|
70
|
+
const parts = [className];
|
|
71
|
+
for (const s of scopePath) {
|
|
72
|
+
parts.push(scopeToVarSegment(s));
|
|
73
|
+
}
|
|
74
|
+
parts.push(prop);
|
|
75
|
+
return '--' + parts.join('-');
|
|
76
|
+
}
|
|
77
|
+
function scopeToVarSegment(s) {
|
|
78
|
+
if (s.kind === 'pseudo')
|
|
79
|
+
return s.selector.replace(/:/g, '_');
|
|
80
|
+
if (s.kind === 'media')
|
|
81
|
+
return 'm-' + s.query.replace(/[^a-zA-Z0-9]/g, '_');
|
|
82
|
+
return 'r-' + s.selector.replace(/[^a-zA-Z0-9]/g, '_');
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAOpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAoB,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAqB,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAAE,YAAY,EAAuC,MAAM,aAAa,CAAC;AA+BhF;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,GAAkB,EAAE,OAAuB;IACpE,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,eAAe,IAAI,QAAQ,CAAC,CAAC;IACvF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAEpC,iEAAiE;IACjE,oEAAoE;IACpE,2DAA2D;IAC3D,8CAA8C;IAC9C,MAAM,GAAG,GAAkB,OAAO,CAAC,aAAa,IAAI;QAClD,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE;KACxD,CAAC;IACF,MAAM,eAAe,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAEpE,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAE3C,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,IAAI,mBAAmB,CAAC;IACzD,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,cAAc,CAAC,eAAe,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IAE5E,OAAO;QACL,SAAS;QACT,IAAI;QACJ,SAAS;QACT,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;KAClC,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CACrB,IAAc,EACd,SAAiB,EACjB,IAA4C,EAC5C,QAAuB,EACvB,SAA2B;IAE3B,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAC5B,IAAI,GAAG,KAAK,mBAAmB,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;YACxD,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,OAAO,GAAG,CAAC;YACjC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,IAAI;gBACd,OAAO;gBACP,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAE;gBAC3B,UAAU,EAAE,CAAC,EAAE,UAAU,IAAI,KAAK;gBAClC,MAAM,EAAE,CAAC,EAAE,MAAM;gBACjB,YAAY,EAAE,CAAC,EAAE,YAAY;gBAC7B,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC;aAC1B,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QACrB,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAe,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACtD,cAAc,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC,KAAM,CAAC,CAAC,CACvE,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAgB;QACzC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,SAAiB,EACjB,SAA2B,EAC3B,IAAY;IAEZ,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,OAAO,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAQ;IACjC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC9D,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;IAC5E,OAAO,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;AACzD,CAAC"}
|