@elastic/distillate 0.0.0 → 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.txt +93 -0
- package/NOTICE.txt +30 -0
- package/README.md +142 -0
- package/THIRD_PARTY_LICENSES.md +768 -0
- package/dist/cjs/collector.js +420 -0
- package/dist/cjs/collector.js.map +1 -0
- package/dist/cjs/css_scan.js +186 -0
- package/dist/cjs/css_scan.js.map +1 -0
- package/dist/cjs/dom_sink.js +40 -0
- package/dist/cjs/dom_sink.js.map +1 -0
- package/dist/cjs/emotion.js +189 -0
- package/dist/cjs/emotion.js.map +1 -0
- package/dist/cjs/engine.js +79 -0
- package/dist/cjs/engine.js.map +1 -0
- package/dist/cjs/environment.js +9 -0
- package/dist/cjs/environment.js.map +1 -0
- package/dist/cjs/hash.js +86 -0
- package/dist/cjs/hash.js.map +1 -0
- package/dist/cjs/idents.js +23 -0
- package/dist/cjs/idents.js.map +1 -0
- package/dist/cjs/index.js +42 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/instance.js +34 -0
- package/dist/cjs/instance.js.map +1 -0
- package/dist/cjs/local_vars.js +100 -0
- package/dist/cjs/local_vars.js.map +1 -0
- package/dist/cjs/minify.js +77 -0
- package/dist/cjs/minify.js.map +1 -0
- package/dist/cjs/names.js +77 -0
- package/dist/cjs/names.js.map +1 -0
- package/dist/cjs/nesting.js +406 -0
- package/dist/cjs/nesting.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/runtime.js +257 -0
- package/dist/cjs/runtime.js.map +1 -0
- package/dist/cjs/styles/authoring.js +169 -0
- package/dist/cjs/styles/authoring.js.map +1 -0
- package/dist/cjs/styles/declarations.js +139 -0
- package/dist/cjs/styles/declarations.js.map +1 -0
- package/dist/cjs/styles/index.js +32 -0
- package/dist/cjs/styles/index.js.map +1 -0
- package/dist/cjs/styles/module.js +233 -0
- package/dist/cjs/styles/module.js.map +1 -0
- package/dist/cjs/styles/registry.js +187 -0
- package/dist/cjs/styles/registry.js.map +1 -0
- package/dist/cjs/styles/types.js +9 -0
- package/dist/cjs/styles/types.js.map +1 -0
- package/dist/cjs/testing.js +37 -0
- package/dist/cjs/testing.js.map +1 -0
- package/dist/cjs/theme.js +249 -0
- package/dist/cjs/theme.js.map +1 -0
- package/dist/cjs/tokens/contextual_var.js +39 -0
- package/dist/cjs/tokens/contextual_var.js.map +1 -0
- package/dist/cjs/tokens/index.js +24 -0
- package/dist/cjs/tokens/index.js.map +1 -0
- package/dist/cjs/tokens/kind.js +14 -0
- package/dist/cjs/tokens/kind.js.map +1 -0
- package/dist/cjs/tokens/light_dark.js +42 -0
- package/dist/cjs/tokens/light_dark.js.map +1 -0
- package/dist/cjs/tokens/scale_token.js +28 -0
- package/dist/cjs/tokens/scale_token.js.map +1 -0
- package/dist/cjs/tokens/theme_token.js +28 -0
- package/dist/cjs/tokens/theme_token.js.map +1 -0
- package/dist/cjs/var_invariant.js +115 -0
- package/dist/cjs/var_invariant.js.map +1 -0
- package/dist/collector.d.ts +84 -0
- package/dist/collector.d.ts.map +1 -0
- package/dist/collector.js +416 -0
- package/dist/collector.js.map +1 -0
- package/dist/css_scan.d.ts +57 -0
- package/dist/css_scan.d.ts.map +1 -0
- package/dist/css_scan.js +180 -0
- package/dist/css_scan.js.map +1 -0
- package/dist/dom_sink.d.ts +27 -0
- package/dist/dom_sink.d.ts.map +1 -0
- package/dist/dom_sink.js +36 -0
- package/dist/dom_sink.js.map +1 -0
- package/dist/emotion.d.ts +47 -0
- package/dist/emotion.d.ts.map +1 -0
- package/dist/emotion.js +184 -0
- package/dist/emotion.js.map +1 -0
- package/dist/engine.d.ts +41 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +75 -0
- package/dist/engine.js.map +1 -0
- package/dist/environment.d.ts +43 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +8 -0
- package/dist/environment.js.map +1 -0
- package/dist/hash.d.ts +2 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +82 -0
- package/dist/hash.js.map +1 -0
- package/dist/idents.d.ts +9 -0
- package/dist/idents.d.ts.map +1 -0
- package/dist/idents.js +19 -0
- package/dist/idents.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/instance.d.ts +16 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/instance.js +30 -0
- package/dist/instance.js.map +1 -0
- package/dist/local_vars.d.ts +75 -0
- package/dist/local_vars.d.ts.map +1 -0
- package/dist/local_vars.js +92 -0
- package/dist/local_vars.js.map +1 -0
- package/dist/minify.d.ts +11 -0
- package/dist/minify.d.ts.map +1 -0
- package/dist/minify.js +73 -0
- package/dist/minify.js.map +1 -0
- package/dist/names.d.ts +39 -0
- package/dist/names.d.ts.map +1 -0
- package/dist/names.js +70 -0
- package/dist/names.js.map +1 -0
- package/dist/nesting.d.ts +59 -0
- package/dist/nesting.d.ts.map +1 -0
- package/dist/nesting.js +400 -0
- package/dist/nesting.js.map +1 -0
- package/dist/runtime.d.ts +36 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +252 -0
- package/dist/runtime.js.map +1 -0
- package/dist/styles/authoring.d.ts +59 -0
- package/dist/styles/authoring.d.ts.map +1 -0
- package/dist/styles/authoring.js +155 -0
- package/dist/styles/authoring.js.map +1 -0
- package/dist/styles/declarations.d.ts +10 -0
- package/dist/styles/declarations.d.ts.map +1 -0
- package/dist/styles/declarations.js +132 -0
- package/dist/styles/declarations.js.map +1 -0
- package/dist/styles/index.d.ts +7 -0
- package/dist/styles/index.d.ts.map +1 -0
- package/dist/styles/index.js +12 -0
- package/dist/styles/index.js.map +1 -0
- package/dist/styles/module.d.ts +5 -0
- package/dist/styles/module.d.ts.map +1 -0
- package/dist/styles/module.js +229 -0
- package/dist/styles/module.js.map +1 -0
- package/dist/styles/registry.d.ts +48 -0
- package/dist/styles/registry.d.ts.map +1 -0
- package/dist/styles/registry.js +182 -0
- package/dist/styles/registry.js.map +1 -0
- package/dist/styles/types.d.ts +211 -0
- package/dist/styles/types.d.ts.map +1 -0
- package/dist/styles/types.js +8 -0
- package/dist/styles/types.js.map +1 -0
- package/dist/testing.d.ts +10 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +31 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme.d.ts +85 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +240 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens/contextual_var.d.ts +35 -0
- package/dist/tokens/contextual_var.d.ts.map +1 -0
- package/dist/tokens/contextual_var.js +33 -0
- package/dist/tokens/contextual_var.js.map +1 -0
- package/dist/tokens/index.d.ts +5 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +11 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/tokens/kind.d.ts +2 -0
- package/dist/tokens/kind.d.ts.map +1 -0
- package/dist/tokens/kind.js +10 -0
- package/dist/tokens/kind.js.map +1 -0
- package/dist/tokens/light_dark.d.ts +20 -0
- package/dist/tokens/light_dark.d.ts.map +1 -0
- package/dist/tokens/light_dark.js +37 -0
- package/dist/tokens/light_dark.js.map +1 -0
- package/dist/tokens/scale_token.d.ts +20 -0
- package/dist/tokens/scale_token.d.ts.map +1 -0
- package/dist/tokens/scale_token.js +23 -0
- package/dist/tokens/scale_token.js.map +1 -0
- package/dist/tokens/theme_token.d.ts +20 -0
- package/dist/tokens/theme_token.d.ts.map +1 -0
- package/dist/tokens/theme_token.js +23 -0
- package/dist/tokens/theme_token.js.map +1 -0
- package/dist/var_invariant.d.ts +25 -0
- package/dist/var_invariant.d.ts.map +1 -0
- package/dist/var_invariant.js +108 -0
- package/dist/var_invariant.js.map +1 -0
- package/docs/concepts/authoring.md +115 -0
- package/docs/concepts/collection.md +66 -0
- package/docs/concepts/distillery.md +47 -0
- package/docs/concepts/index.md +18 -0
- package/docs/concepts/naming-and-output.md +123 -0
- package/docs/concepts/ordering.md +61 -0
- package/docs/concepts/single-copy.md +103 -0
- package/docs/concepts/tokens.md +99 -0
- package/docs/docset.yml +53 -0
- package/docs/examples/01-stylesheet.ts +20 -0
- package/docs/examples/02-artifact.ts +26 -0
- package/docs/examples/03-variants.ts +40 -0
- package/docs/examples/04-emotion.ts +33 -0
- package/docs/examples/05-var-invariant.ts +31 -0
- package/docs/examples/06-payload.ts +85 -0
- package/docs/examples/fixture.ts +22 -0
- package/docs/getting-started/index.md +14 -0
- package/docs/getting-started/installation.md +30 -0
- package/docs/getting-started/quick-start.md +61 -0
- package/docs/getting-started/your-first-stylesheet.md +57 -0
- package/docs/guides/compact-artifacts.md +87 -0
- package/docs/guides/emotion-migration.md +60 -0
- package/docs/guides/index.md +17 -0
- package/docs/guides/name-collisions.md +37 -0
- package/docs/guides/non-css-surfaces.md +73 -0
- package/docs/guides/react-renderer.md +158 -0
- package/docs/guides/theming.md +107 -0
- package/docs/guides/var-invariant.md +24 -0
- package/docs/guides/vs-emotion.md +61 -0
- package/docs/index.md +73 -0
- package/docs/logo.svg +7 -0
- package/docs/playground/index.html +12 -0
- package/docs/playground/package.json +23 -0
- package/docs/playground/src/app/app.tsx +109 -0
- package/docs/playground/src/app/css_panel.tsx +119 -0
- package/docs/playground/src/app/editor_panel.tsx +87 -0
- package/docs/playground/src/app/index.ts +8 -0
- package/docs/playground/src/app/monaco_css_editor.tsx +84 -0
- package/docs/playground/src/app/monaco_source_editor.tsx +132 -0
- package/docs/playground/src/app/preview_panel.tsx +99 -0
- package/docs/playground/src/app/tokens_panel.tsx +117 -0
- package/docs/playground/src/app/types.ts +10 -0
- package/docs/playground/src/examples/snippets.test.ts +28 -0
- package/docs/playground/src/examples/snippets.ts +418 -0
- package/docs/playground/src/lib/compile.test.ts +157 -0
- package/docs/playground/src/lib/compile.ts +242 -0
- package/docs/playground/src/lib/demo_environment.test.ts +123 -0
- package/docs/playground/src/lib/demo_environment.ts +140 -0
- package/docs/playground/src/lib/editor_lib.test.ts +39 -0
- package/docs/playground/src/lib/editor_lib.ts +142 -0
- package/docs/playground/src/lib/format_css.test.ts +41 -0
- package/docs/playground/src/lib/format_css.ts +71 -0
- package/docs/playground/src/main.tsx +25 -0
- package/docs/playground/src/setup/chrome.test.ts +47 -0
- package/docs/playground/src/setup/chrome.ts +365 -0
- package/docs/playground/src/setup/monaco_env.ts +64 -0
- package/docs/playground/tsconfig.json +22 -0
- package/docs/playground/vite.config.ts +37 -0
- package/docs/playground/vitest.config.ts +35 -0
- package/docs/playground.md +28 -0
- package/docs/reference/api/emotion.md +372 -0
- package/docs/reference/api/index-1.md +2180 -0
- package/docs/reference/api/index.md +9 -0
- package/docs/reference/api/testing.md +92 -0
- package/docs/reference/api.md +12 -0
- package/docs/reference/entry-points.md +125 -0
- package/docs/reference/environment.md +60 -0
- package/docs/reference/index.md +11 -0
- package/docs/reference/okf-map.md +92 -0
- package/package.json +127 -4
- package/src/collector.ts +526 -0
- package/src/css_scan.ts +263 -0
- package/src/dom_sink.ts +65 -0
- package/src/emotion.ts +311 -0
- package/src/engine.ts +191 -0
- package/src/environment.ts +56 -0
- package/src/hash.ts +111 -0
- package/src/idents.ts +21 -0
- package/src/index.ts +93 -0
- package/src/instance.ts +49 -0
- package/src/local_vars.ts +220 -0
- package/src/minify.ts +87 -0
- package/src/names.ts +129 -0
- package/src/nesting.ts +596 -0
- package/src/runtime.ts +428 -0
- package/src/styles/authoring.ts +244 -0
- package/src/styles/declarations.ts +172 -0
- package/src/styles/index.ts +58 -0
- package/src/styles/module.ts +396 -0
- package/src/styles/registry.ts +261 -0
- package/src/styles/types.ts +283 -0
- package/src/testing.ts +48 -0
- package/src/theme.ts +454 -0
- package/src/tokens/contextual_var.ts +72 -0
- package/src/tokens/index.ts +17 -0
- package/src/tokens/kind.ts +13 -0
- package/src/tokens/light_dark.ts +58 -0
- package/src/tokens/scale_token.ts +41 -0
- package/src/tokens/theme_token.ts +42 -0
- package/src/var_invariant.ts +147 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
4
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
5
|
+
* 2.0; you may not use this file except in compliance with the Elastic License
|
|
6
|
+
* 2.0.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.isHandleLike = exports.flattenTemplate = exports.hasNestedSyntax = void 0;
|
|
10
|
+
// Stylis-based flattener for Emotion-style nested `css` templates.
|
|
11
|
+
//
|
|
12
|
+
// Nesting semantics (`&` substitution, comma cross-products, descendant
|
|
13
|
+
// defaulting, `@media` hoisting) are owned entirely by stylis. We serialize
|
|
14
|
+
// the authored `(strings, values)` into a sentinel-carrying CSS string, hand
|
|
15
|
+
// it to `compile()`, then walk the element tree and re-attach the live
|
|
16
|
+
// interpolated values by matching sentinels.
|
|
17
|
+
//
|
|
18
|
+
// The walk is pinned to stylis 4.4.0; `nesting_contract.test.ts` asserts the
|
|
19
|
+
// `compile()` tree shape (`props` vs `value`, `@media` children, DECL text).
|
|
20
|
+
const stylis_1 = require("stylis");
|
|
21
|
+
const css_scan_1 = require("./css_scan");
|
|
22
|
+
const local_vars_1 = require("./local_vars");
|
|
23
|
+
const local_vars_2 = require("./local_vars");
|
|
24
|
+
const tokens_1 = require("./tokens");
|
|
25
|
+
const SELF_SENTINEL = '.__dstl_self__';
|
|
26
|
+
// Brace presence is the trigger for the nesting path. Brace-free templates
|
|
27
|
+
// keep the byte-identical fast path in `styles/authoring.ts`. Quoted braces (`content:
|
|
28
|
+
// "{"`) intentionally route here too — they used to throw.
|
|
29
|
+
const hasNestedSyntax = (strings) => strings.some((part) => part.includes('{') || part.includes('}'));
|
|
30
|
+
exports.hasNestedSyntax = hasNestedSyntax;
|
|
31
|
+
const flattenTemplate = (strings, values, options) => {
|
|
32
|
+
assertNoReservedPatterns(strings);
|
|
33
|
+
const inlined = options.inlineValue
|
|
34
|
+
? inlineTemplate(strings, values, options.inlineValue)
|
|
35
|
+
: { strings, values };
|
|
36
|
+
const { mode } = options;
|
|
37
|
+
const { text, sentinelValues } = serialize(inlined.strings, inlined.values, mode);
|
|
38
|
+
scanStructure(text, mode);
|
|
39
|
+
const tree = (0, stylis_1.compile)(canonicalizeAtMedia(text));
|
|
40
|
+
return walk(tree, mode, sentinelValues);
|
|
41
|
+
};
|
|
42
|
+
exports.flattenTemplate = flattenTemplate;
|
|
43
|
+
const serialize = (strings, values, mode) => {
|
|
44
|
+
let text = mode === 'self' ? `${SELF_SENTINEL}{` : '';
|
|
45
|
+
strings.forEach((part, index) => {
|
|
46
|
+
text += part;
|
|
47
|
+
if (index >= values.length) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const value = values[index];
|
|
51
|
+
if ((0, local_vars_1.isLocalVarMarker)(value)) {
|
|
52
|
+
// Property-name sentinel; stylis DECL `.props` is the ident (`--dstl-N`).
|
|
53
|
+
text += `--dstl-${index}:0;`;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (isSerializableScalar(value) || (0, exports.isHandleLike)(value)) {
|
|
57
|
+
// Identifier sentinel in selectors and values (`__dstlN__`).
|
|
58
|
+
text += `__dstl${index}__`;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`Unsupported interpolation in css template: ${describe(value)}. Interpolate a theme token, scale token, contextual var, local var (ref/marker), string, number, or a style handle in selector position.`);
|
|
62
|
+
});
|
|
63
|
+
if (mode === 'self') {
|
|
64
|
+
text += '}';
|
|
65
|
+
}
|
|
66
|
+
return { text, sentinelValues: values };
|
|
67
|
+
};
|
|
68
|
+
// --- Pre-compile validation ---------------------------------------------
|
|
69
|
+
const RESERVED_PATTERNS = [
|
|
70
|
+
/__dstl_self__/,
|
|
71
|
+
/__dstl\d+__/,
|
|
72
|
+
/--dstl-\d+/,
|
|
73
|
+
];
|
|
74
|
+
const assertNoReservedPatterns = (strings) => {
|
|
75
|
+
for (const part of strings) {
|
|
76
|
+
for (const pattern of RESERVED_PATTERNS) {
|
|
77
|
+
if (pattern.test(part)) {
|
|
78
|
+
throw new Error(`css template contains reserved flattener syntax (${pattern.source}); rename the offending identifier.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
// Scan-only structural validator over the serialized text. Classifies, never
|
|
84
|
+
// restructures — stylis owns all flattening. Enforces v1 scope before stylis
|
|
85
|
+
// can normalize, hoist, or silently drop malformed constructs.
|
|
86
|
+
const scanStructure = (text, mode) => {
|
|
87
|
+
let depth = 0;
|
|
88
|
+
let parenDepth = 0;
|
|
89
|
+
let mediaDepth = 0;
|
|
90
|
+
const mediaBraceStack = [];
|
|
91
|
+
let quote = null;
|
|
92
|
+
let inComment = false;
|
|
93
|
+
for (let i = 0; i < text.length; i += 1) {
|
|
94
|
+
const ch = text[i];
|
|
95
|
+
if (inComment) {
|
|
96
|
+
if (ch === '*' && text[i + 1] === '/') {
|
|
97
|
+
inComment = false;
|
|
98
|
+
i += 1;
|
|
99
|
+
}
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (quote) {
|
|
103
|
+
if (ch === '\\') {
|
|
104
|
+
i += 1;
|
|
105
|
+
}
|
|
106
|
+
else if (ch === quote) {
|
|
107
|
+
quote = null;
|
|
108
|
+
}
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (ch === '/' && text[i + 1] === '*') {
|
|
112
|
+
inComment = true;
|
|
113
|
+
i += 1;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (ch === '"' || ch === "'") {
|
|
117
|
+
quote = ch;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (ch === '(') {
|
|
121
|
+
parenDepth += 1;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (ch === ')') {
|
|
125
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (parenDepth > 0) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (ch === '@') {
|
|
132
|
+
const rest = text.slice(i + 1);
|
|
133
|
+
const name = /^[a-zA-Z-]+/.exec(rest)?.[0] ?? '';
|
|
134
|
+
if (name.toLowerCase() !== 'media') {
|
|
135
|
+
throw new Error(`Only @media is supported in css templates; found @${name || '(unknown)'}. (@supports, @container, @keyframes, @font-face, and others are follow-ups.)`);
|
|
136
|
+
}
|
|
137
|
+
if (mediaDepth > 0) {
|
|
138
|
+
throw new Error('Nested @media inside @media is not supported.');
|
|
139
|
+
}
|
|
140
|
+
mediaDepth += 1;
|
|
141
|
+
mediaBraceStack.push(depth);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (ch === '{') {
|
|
145
|
+
depth += 1;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (ch === '}') {
|
|
149
|
+
depth = Math.max(0, depth - 1);
|
|
150
|
+
if (mediaDepth > 0 &&
|
|
151
|
+
mediaBraceStack.length > 0 &&
|
|
152
|
+
depth === mediaBraceStack[mediaBraceStack.length - 1]) {
|
|
153
|
+
mediaBraceStack.pop();
|
|
154
|
+
mediaDepth -= 1;
|
|
155
|
+
}
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (mode === 'global' && depth === 0) {
|
|
159
|
+
if (ch === ';') {
|
|
160
|
+
throw new Error('injectGlobal templates cannot have top-level declarations; wrap them in a selector.');
|
|
161
|
+
}
|
|
162
|
+
if (ch === '&') {
|
|
163
|
+
throw new Error('injectGlobal templates cannot use `&` at the top level; global styles have no self handle.');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (depth !== 0 || quote || inComment) {
|
|
168
|
+
throw new Error('css template has unbalanced braces, quotes, or comments.');
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
/** stylis only wraps bare in-media declarations for lowercase `@media`. */
|
|
172
|
+
// stylis matches at-rules case-sensitively, so `@MEDIA` has to be normalized
|
|
173
|
+
// before it parses. Only `text` spans are eligible: an `@media` inside a
|
|
174
|
+
// string, a comment, or an unquoted `url(...)` is data, and rewriting the last
|
|
175
|
+
// of those silently changes a case-sensitive path.
|
|
176
|
+
const canonicalizeAtMedia = (text) => (0, css_scan_1.scanCss)(text)
|
|
177
|
+
.map((span) => span.kind === 'text'
|
|
178
|
+
? // A `\\b` here would also match `@media-foo`, rewriting an unknown
|
|
179
|
+
// at-rule whose name merely starts with `media`.
|
|
180
|
+
span.text.replace(/@media(?![\w-])/gi, '@media')
|
|
181
|
+
: span.text)
|
|
182
|
+
.join('');
|
|
183
|
+
// --- Walk + re-attach ----------------------------------------------------
|
|
184
|
+
const walk = (tree, mode, values) => {
|
|
185
|
+
const selfBuilder = new SliceBuilder(values);
|
|
186
|
+
let selfSeen = false;
|
|
187
|
+
const nested = [];
|
|
188
|
+
for (const element of tree) {
|
|
189
|
+
if (element.type === 'rule') {
|
|
190
|
+
const decls = declChildren(element);
|
|
191
|
+
if (decls.length === 0) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (mode === 'self' && isSelfSelector(element)) {
|
|
195
|
+
selfSeen = true;
|
|
196
|
+
selfBuilder.appendDecls(decls);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
nested.push(buildRule(element, values));
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (element.type.toLowerCase() === '@media') {
|
|
203
|
+
nested.push(buildMedia(element, mode, values));
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
// decl/comm at top level: only reachable in global mode (self mode wraps
|
|
207
|
+
// everything). Top-level decls are already rejected by the scan.
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
self: mode === 'self' ? (selfSeen ? selfBuilder.build() : emptySlice()) : null,
|
|
211
|
+
nested,
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
const buildRule = (element, values) => {
|
|
215
|
+
const builder = new SliceBuilder(values);
|
|
216
|
+
builder.appendDecls(declChildren(element));
|
|
217
|
+
return {
|
|
218
|
+
kind: 'rule',
|
|
219
|
+
alternatives: selectorsOf(element).map((selector) => reconstructSelector(selector, values)),
|
|
220
|
+
slice: builder.build(),
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
const buildMedia = (element, mode, values) => {
|
|
224
|
+
const query = reconstructMediaQuery(selectorsOf(element).join(','), values);
|
|
225
|
+
const children = Array.isArray(element.children) ? element.children : [];
|
|
226
|
+
const selfBuilder = new SliceBuilder(values);
|
|
227
|
+
let selfSeen = false;
|
|
228
|
+
const rules = [];
|
|
229
|
+
for (const child of children) {
|
|
230
|
+
if (child.type !== 'rule') {
|
|
231
|
+
if (child.type === 'decl') {
|
|
232
|
+
throw new Error('Declarations directly inside @media must be within a selector.');
|
|
233
|
+
}
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const decls = declChildren(child);
|
|
237
|
+
if (decls.length === 0) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (mode === 'self' && isSelfSelector(child)) {
|
|
241
|
+
selfSeen = true;
|
|
242
|
+
selfBuilder.appendDecls(decls);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
rules.push(buildRule(child, values));
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
kind: 'media',
|
|
249
|
+
query,
|
|
250
|
+
...(selfSeen ? { self: selfBuilder.build() } : {}),
|
|
251
|
+
rules,
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
// Rebuilds a `TemplateSlice` from a block's DECL elements in source order,
|
|
255
|
+
// swapping declaration sentinels back to marker objects and identifier
|
|
256
|
+
// sentinels back to their original values.
|
|
257
|
+
class SliceBuilder {
|
|
258
|
+
source;
|
|
259
|
+
strings = [''];
|
|
260
|
+
values = [];
|
|
261
|
+
constructor(source) {
|
|
262
|
+
this.source = source;
|
|
263
|
+
}
|
|
264
|
+
appendDecls(decls) {
|
|
265
|
+
for (const decl of decls) {
|
|
266
|
+
const markerMatch = /^--dstl-(\d+)$/.exec(propName(decl));
|
|
267
|
+
if (markerMatch) {
|
|
268
|
+
this.pushValue(this.source[Number(markerMatch[1])]);
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
this.appendText(typeof decl.value === 'string' ? decl.value : '');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
appendText(text) {
|
|
275
|
+
const pattern = /__dstl(\d+)__/g;
|
|
276
|
+
let lastIndex = 0;
|
|
277
|
+
let match;
|
|
278
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
279
|
+
this.strings[this.strings.length - 1] += text.slice(lastIndex, match.index);
|
|
280
|
+
const value = this.source[Number(match[1])];
|
|
281
|
+
if ((0, exports.isHandleLike)(value)) {
|
|
282
|
+
throw new Error('A style handle cannot be interpolated into a declaration value; compose with the emotion compat css instead.');
|
|
283
|
+
}
|
|
284
|
+
this.pushValue(value);
|
|
285
|
+
lastIndex = pattern.lastIndex;
|
|
286
|
+
}
|
|
287
|
+
this.strings[this.strings.length - 1] += text.slice(lastIndex);
|
|
288
|
+
}
|
|
289
|
+
pushValue(value) {
|
|
290
|
+
this.values.push(value);
|
|
291
|
+
this.strings.push('');
|
|
292
|
+
}
|
|
293
|
+
build() {
|
|
294
|
+
return { strings: this.strings, values: this.values };
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const reconstructSelector = (selector, values) => {
|
|
298
|
+
const withSelf = selector.split(SELF_SENTINEL).join('&');
|
|
299
|
+
const parts = [];
|
|
300
|
+
const pattern = /\.?__dstl(\d+)__/g;
|
|
301
|
+
let lastIndex = 0;
|
|
302
|
+
let buffer = '';
|
|
303
|
+
let match;
|
|
304
|
+
while ((match = pattern.exec(withSelf)) !== null) {
|
|
305
|
+
buffer += withSelf.slice(lastIndex, match.index);
|
|
306
|
+
if (buffer.length > 0) {
|
|
307
|
+
parts.push(buffer);
|
|
308
|
+
buffer = '';
|
|
309
|
+
}
|
|
310
|
+
const value = values[Number(match[1])];
|
|
311
|
+
if (!(0, exports.isHandleLike)(value)) {
|
|
312
|
+
throw new Error(`Only style handles may be interpolated into selector position; received ${describe(value)}.`);
|
|
313
|
+
}
|
|
314
|
+
parts.push(value);
|
|
315
|
+
lastIndex = pattern.lastIndex;
|
|
316
|
+
}
|
|
317
|
+
buffer += withSelf.slice(lastIndex);
|
|
318
|
+
if (buffer.length > 0 || parts.length === 0) {
|
|
319
|
+
parts.push(buffer);
|
|
320
|
+
}
|
|
321
|
+
return parts;
|
|
322
|
+
};
|
|
323
|
+
const reconstructMediaQuery = (query, values) => query.replace(/__dstl(\d+)__/g, (_match, index) => {
|
|
324
|
+
const value = values[Number(index)];
|
|
325
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
326
|
+
return String(value);
|
|
327
|
+
}
|
|
328
|
+
throw new Error(`Media queries may interpolate strings or numbers only; received ${describe(value)}.`);
|
|
329
|
+
});
|
|
330
|
+
// --- Composition inlining ------------------------------------------------
|
|
331
|
+
const inlineTemplate = (strings, values, inlineValue) => {
|
|
332
|
+
const outStrings = [strings[0] ?? ''];
|
|
333
|
+
const outValues = [];
|
|
334
|
+
const mergeSlice = (slice) => {
|
|
335
|
+
outStrings[outStrings.length - 1] += slice.strings[0] ?? '';
|
|
336
|
+
for (let i = 0; i < slice.values.length; i += 1) {
|
|
337
|
+
outValues.push(slice.values[i]);
|
|
338
|
+
outStrings.push(slice.strings[i + 1] ?? '');
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
values.forEach((value, index) => {
|
|
342
|
+
const position = detectPosition(strings, index);
|
|
343
|
+
const spliced = inlineValue(value, position);
|
|
344
|
+
if (spliced) {
|
|
345
|
+
mergeSlice(inlineTemplate(spliced.strings, spliced.values, inlineValue));
|
|
346
|
+
outStrings[outStrings.length - 1] += strings[index + 1] ?? '';
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
outValues.push(value);
|
|
350
|
+
outStrings.push(strings[index + 1] ?? '');
|
|
351
|
+
});
|
|
352
|
+
return { strings: outStrings, values: outValues };
|
|
353
|
+
};
|
|
354
|
+
// Cheap position heuristic: the first structural char in the following string
|
|
355
|
+
// decides. A `{` before any `;`/`}` means the interpolation is building a
|
|
356
|
+
// selector; anything else is a statement/value position.
|
|
357
|
+
const detectPosition = (strings, index) => {
|
|
358
|
+
const next = strings[index + 1] ?? '';
|
|
359
|
+
for (const ch of next) {
|
|
360
|
+
if (ch === '{') {
|
|
361
|
+
return 'selector';
|
|
362
|
+
}
|
|
363
|
+
if (ch === ';' || ch === '}') {
|
|
364
|
+
return 'statement';
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return 'statement';
|
|
368
|
+
};
|
|
369
|
+
// --- Element helpers -----------------------------------------------------
|
|
370
|
+
const selectorsOf = (element) => Array.isArray(element.props) ? element.props : [element.props];
|
|
371
|
+
const isSelfSelector = (element) => {
|
|
372
|
+
const selectors = selectorsOf(element);
|
|
373
|
+
return selectors.length === 1 && selectors[0] === SELF_SENTINEL;
|
|
374
|
+
};
|
|
375
|
+
const declChildren = (element) => Array.isArray(element.children)
|
|
376
|
+
? element.children.filter((child) => child.type === 'decl')
|
|
377
|
+
: [];
|
|
378
|
+
const propName = (element) => typeof element.props === 'string' ? element.props : (element.props[0] ?? '');
|
|
379
|
+
// --- Value guards --------------------------------------------------------
|
|
380
|
+
const isSerializableScalar = (value) => typeof value === 'string' ||
|
|
381
|
+
typeof value === 'number' ||
|
|
382
|
+
(0, tokens_1.isCssToken)(value) ||
|
|
383
|
+
(0, tokens_1.isContextualCssVar)(value) ||
|
|
384
|
+
(0, tokens_1.isContextualCssVarName)(value) ||
|
|
385
|
+
(0, tokens_1.isScaleToken)(value) ||
|
|
386
|
+
(0, local_vars_2.isLocalVarRef)(value);
|
|
387
|
+
const isHandleLike = (value) => Boolean(value &&
|
|
388
|
+
typeof value === 'object' &&
|
|
389
|
+
value.kind === 'handle');
|
|
390
|
+
exports.isHandleLike = isHandleLike;
|
|
391
|
+
const emptySlice = () => ({ strings: [''], values: [] });
|
|
392
|
+
const describe = (value) => {
|
|
393
|
+
if (value === null) {
|
|
394
|
+
return 'null';
|
|
395
|
+
}
|
|
396
|
+
if (value === undefined) {
|
|
397
|
+
return 'undefined';
|
|
398
|
+
}
|
|
399
|
+
if (typeof value === 'object') {
|
|
400
|
+
const kind = value.kind;
|
|
401
|
+
const brand = value.__kind;
|
|
402
|
+
return `object${kind ? ` (kind: ${kind})` : brand ? ` (${brand})` : ''}`;
|
|
403
|
+
}
|
|
404
|
+
return typeof value;
|
|
405
|
+
};
|
|
406
|
+
//# sourceMappingURL=nesting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nesting.js","sourceRoot":"","sources":["../../src/nesting.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\n// Stylis-based flattener for Emotion-style nested `css` templates.\n//\n// Nesting semantics (`&` substitution, comma cross-products, descendant\n// defaulting, `@media` hoisting) are owned entirely by stylis. We serialize\n// the authored `(strings, values)` into a sentinel-carrying CSS string, hand\n// it to `compile()`, then walk the element tree and re-attach the live\n// interpolated values by matching sentinels.\n//\n// The walk is pinned to stylis 4.4.0; `nesting_contract.test.ts` asserts the\n// `compile()` tree shape (`props` vs `value`, `@media` children, DECL text).\n\nimport { compile, type Element } from 'stylis';\n\nimport { scanCss } from './css_scan';\nimport { isLocalVarMarker } from './local_vars';\nimport { isLocalVarRef } from './local_vars';\nimport type { StyleHandle } from './styles/types';\nimport {\n isContextualCssVar,\n isContextualCssVarName,\n isCssToken,\n isScaleToken,\n} from './tokens';\n\n/** Rebuilt template fragment in tagged-template shape (`strings.length === values.length + 1`). */\nexport interface TemplateSlice {\n /** Literal pieces between interpolations. */\n readonly strings: readonly string[];\n /** Interpolated values, one per hole. */\n readonly values: readonly unknown[];\n}\n\n/** `&`-relative selector fragment: literal text or a cross-class {@link StyleHandle}. */\nexport type SelectorPart = string | StyleHandle;\n/** One comma alternative; parts concatenate into a selector. */\nexport type SelectorAlternative = readonly SelectorPart[];\n\n/** Flattened nested rule: selector alternatives plus declaration slice. */\nexport interface FlattenedRule {\n /** Discriminant for {@link FlattenedEntry}. */\n readonly kind: 'rule';\n /** Comma alternatives relative to the parent handle. */\n readonly alternatives: readonly SelectorAlternative[];\n /** Declaration template for this rule. */\n readonly slice: TemplateSlice;\n}\n\n/** Flattened `@media` block: query, optional self declarations, nested rules. */\nexport interface FlattenedMedia {\n /** Discriminant for {@link FlattenedEntry}. */\n readonly kind: 'media';\n /** Media query text. */\n readonly query: string;\n /** Bare declarations inside the block, applied to the self handle. */\n readonly self?: TemplateSlice;\n /** Nested `&` rules inside this media block. */\n readonly rules: readonly FlattenedRule[];\n}\n\n/** Nested rule or `@media` produced by flattening. */\nexport type FlattenedEntry = FlattenedRule | FlattenedMedia;\n\n/** Flattened `css` template: self declarations plus nested entries. */\nexport interface FlattenedTemplate {\n /** Self-handle declarations. `null` in global mode. */\n readonly self: TemplateSlice | null;\n /** Sibling nested rules and media blocks. */\n readonly nested: readonly FlattenedEntry[];\n}\n\n/** `self` keeps a host handle; `global` does not. */\nexport type FlattenMode = 'self' | 'global';\n\n/** Mode and optional inlining hook for {@link flattenTemplate}. */\nexport interface FlattenOptions {\n /** Whether the template authors a host handle or global rules. */\n readonly mode: FlattenMode;\n /**\n * Optional splice of a value's source slice before compilation.\n * Return `null`/`undefined` to serialize the value as a sentinel.\n */\n readonly inlineValue?: (\n value: unknown,\n position: InterpolationPosition\n ) => TemplateSlice | null | undefined;\n}\n\n/** Where an interpolation sits in the serialized template. */\nexport type InterpolationPosition = 'selector' | 'statement';\n\nconst SELF_SENTINEL = '.__dstl_self__';\n\n// Brace presence is the trigger for the nesting path. Brace-free templates\n// keep the byte-identical fast path in `styles/authoring.ts`. Quoted braces (`content:\n// \"{\"`) intentionally route here too — they used to throw.\nexport const hasNestedSyntax = (strings: readonly string[]): boolean =>\n strings.some((part) => part.includes('{') || part.includes('}'));\n\nexport const flattenTemplate = (\n strings: readonly string[],\n values: readonly unknown[],\n options: FlattenOptions\n): FlattenedTemplate => {\n assertNoReservedPatterns(strings);\n const inlined = options.inlineValue\n ? inlineTemplate(strings, values, options.inlineValue)\n : { strings, values };\n const { mode } = options;\n const { text, sentinelValues } = serialize(\n inlined.strings,\n inlined.values,\n mode\n );\n scanStructure(text, mode);\n const tree = compile(canonicalizeAtMedia(text));\n return walk(tree, mode, sentinelValues);\n};\n\n// --- Serialization -------------------------------------------------------\n\ninterface Serialized {\n /** Sentinel-carrying CSS string handed to stylis. */\n readonly text: string;\n /** Sentinel index → the live interpolated value. */\n readonly sentinelValues: readonly unknown[];\n}\n\nconst serialize = (\n strings: readonly string[],\n values: readonly unknown[],\n mode: FlattenMode\n): Serialized => {\n let text = mode === 'self' ? `${SELF_SENTINEL}{` : '';\n strings.forEach((part, index) => {\n text += part;\n if (index >= values.length) {\n return;\n }\n const value = values[index];\n if (isLocalVarMarker(value)) {\n // Property-name sentinel; stylis DECL `.props` is the ident (`--dstl-N`).\n text += `--dstl-${index}:0;`;\n return;\n }\n if (isSerializableScalar(value) || isHandleLike(value)) {\n // Identifier sentinel in selectors and values (`__dstlN__`).\n text += `__dstl${index}__`;\n return;\n }\n throw new Error(\n `Unsupported interpolation in css template: ${describe(value)}. Interpolate a theme token, scale token, contextual var, local var (ref/marker), string, number, or a style handle in selector position.`\n );\n });\n if (mode === 'self') {\n text += '}';\n }\n return { text, sentinelValues: values };\n};\n\n// --- Pre-compile validation ---------------------------------------------\n\nconst RESERVED_PATTERNS: readonly RegExp[] = [\n /__dstl_self__/,\n /__dstl\\d+__/,\n /--dstl-\\d+/,\n];\n\nconst assertNoReservedPatterns = (strings: readonly string[]): void => {\n for (const part of strings) {\n for (const pattern of RESERVED_PATTERNS) {\n if (pattern.test(part)) {\n throw new Error(\n `css template contains reserved flattener syntax (${pattern.source}); rename the offending identifier.`\n );\n }\n }\n }\n};\n\n// Scan-only structural validator over the serialized text. Classifies, never\n// restructures — stylis owns all flattening. Enforces v1 scope before stylis\n// can normalize, hoist, or silently drop malformed constructs.\nconst scanStructure = (text: string, mode: FlattenMode): void => {\n let depth = 0;\n let parenDepth = 0;\n let mediaDepth = 0;\n const mediaBraceStack: number[] = [];\n let quote: string | null = null;\n let inComment = false;\n\n for (let i = 0; i < text.length; i += 1) {\n const ch = text[i];\n if (inComment) {\n if (ch === '*' && text[i + 1] === '/') {\n inComment = false;\n i += 1;\n }\n continue;\n }\n if (quote) {\n if (ch === '\\\\') {\n i += 1;\n } else if (ch === quote) {\n quote = null;\n }\n continue;\n }\n if (ch === '/' && text[i + 1] === '*') {\n inComment = true;\n i += 1;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch;\n continue;\n }\n if (ch === '(') {\n parenDepth += 1;\n continue;\n }\n if (ch === ')') {\n parenDepth = Math.max(0, parenDepth - 1);\n continue;\n }\n if (parenDepth > 0) {\n continue;\n }\n if (ch === '@') {\n const rest = text.slice(i + 1);\n const name = /^[a-zA-Z-]+/.exec(rest)?.[0] ?? '';\n if (name.toLowerCase() !== 'media') {\n throw new Error(\n `Only @media is supported in css templates; found @${name || '(unknown)'}. (@supports, @container, @keyframes, @font-face, and others are follow-ups.)`\n );\n }\n if (mediaDepth > 0) {\n throw new Error('Nested @media inside @media is not supported.');\n }\n mediaDepth += 1;\n mediaBraceStack.push(depth);\n continue;\n }\n if (ch === '{') {\n depth += 1;\n continue;\n }\n if (ch === '}') {\n depth = Math.max(0, depth - 1);\n if (\n mediaDepth > 0 &&\n mediaBraceStack.length > 0 &&\n depth === mediaBraceStack[mediaBraceStack.length - 1]\n ) {\n mediaBraceStack.pop();\n mediaDepth -= 1;\n }\n continue;\n }\n if (mode === 'global' && depth === 0) {\n if (ch === ';') {\n throw new Error(\n 'injectGlobal templates cannot have top-level declarations; wrap them in a selector.'\n );\n }\n if (ch === '&') {\n throw new Error(\n 'injectGlobal templates cannot use `&` at the top level; global styles have no self handle.'\n );\n }\n }\n }\n\n if (depth !== 0 || quote || inComment) {\n throw new Error('css template has unbalanced braces, quotes, or comments.');\n }\n};\n\n/** stylis only wraps bare in-media declarations for lowercase `@media`. */\n// stylis matches at-rules case-sensitively, so `@MEDIA` has to be normalized\n// before it parses. Only `text` spans are eligible: an `@media` inside a\n// string, a comment, or an unquoted `url(...)` is data, and rewriting the last\n// of those silently changes a case-sensitive path.\nconst canonicalizeAtMedia = (text: string): string =>\n scanCss(text)\n .map((span) =>\n span.kind === 'text'\n ? // A `\\\\b` here would also match `@media-foo`, rewriting an unknown\n // at-rule whose name merely starts with `media`.\n span.text.replace(/@media(?![\\w-])/gi, '@media')\n : span.text\n )\n .join('');\n\n// --- Walk + re-attach ----------------------------------------------------\n\nconst walk = (\n tree: readonly Element[],\n mode: FlattenMode,\n values: readonly unknown[]\n): FlattenedTemplate => {\n const selfBuilder = new SliceBuilder(values);\n let selfSeen = false;\n const nested: FlattenedEntry[] = [];\n\n for (const element of tree) {\n if (element.type === 'rule') {\n const decls = declChildren(element);\n if (decls.length === 0) {\n continue;\n }\n if (mode === 'self' && isSelfSelector(element)) {\n selfSeen = true;\n selfBuilder.appendDecls(decls);\n continue;\n }\n nested.push(buildRule(element, values));\n continue;\n }\n if (element.type.toLowerCase() === '@media') {\n nested.push(buildMedia(element, mode, values));\n continue;\n }\n // decl/comm at top level: only reachable in global mode (self mode wraps\n // everything). Top-level decls are already rejected by the scan.\n }\n\n return {\n self:\n mode === 'self' ? (selfSeen ? selfBuilder.build() : emptySlice()) : null,\n nested,\n };\n};\n\nconst buildRule = (\n element: Element,\n values: readonly unknown[]\n): FlattenedRule => {\n const builder = new SliceBuilder(values);\n builder.appendDecls(declChildren(element));\n return {\n kind: 'rule',\n alternatives: selectorsOf(element).map((selector) =>\n reconstructSelector(selector, values)\n ),\n slice: builder.build(),\n };\n};\n\nconst buildMedia = (\n element: Element,\n mode: FlattenMode,\n values: readonly unknown[]\n): FlattenedMedia => {\n const query = reconstructMediaQuery(selectorsOf(element).join(','), values);\n const children = Array.isArray(element.children) ? element.children : [];\n const selfBuilder = new SliceBuilder(values);\n let selfSeen = false;\n const rules: FlattenedRule[] = [];\n\n for (const child of children) {\n if (child.type !== 'rule') {\n if (child.type === 'decl') {\n throw new Error(\n 'Declarations directly inside @media must be within a selector.'\n );\n }\n continue;\n }\n const decls = declChildren(child);\n if (decls.length === 0) {\n continue;\n }\n if (mode === 'self' && isSelfSelector(child)) {\n selfSeen = true;\n selfBuilder.appendDecls(decls);\n continue;\n }\n rules.push(buildRule(child, values));\n }\n\n return {\n kind: 'media',\n query,\n ...(selfSeen ? { self: selfBuilder.build() } : {}),\n rules,\n };\n};\n\n// Rebuilds a `TemplateSlice` from a block's DECL elements in source order,\n// swapping declaration sentinels back to marker objects and identifier\n// sentinels back to their original values.\nclass SliceBuilder {\n private readonly strings: string[] = [''];\n private readonly values: unknown[] = [];\n\n constructor(private readonly source: readonly unknown[]) {}\n\n appendDecls(decls: readonly Element[]): void {\n for (const decl of decls) {\n const markerMatch = /^--dstl-(\\d+)$/.exec(propName(decl));\n if (markerMatch) {\n this.pushValue(this.source[Number(markerMatch[1])]);\n continue;\n }\n this.appendText(typeof decl.value === 'string' ? decl.value : '');\n }\n }\n\n private appendText(text: string): void {\n const pattern = /__dstl(\\d+)__/g;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(text)) !== null) {\n this.strings[this.strings.length - 1] += text.slice(\n lastIndex,\n match.index\n );\n const value = this.source[Number(match[1])];\n if (isHandleLike(value)) {\n throw new Error(\n 'A style handle cannot be interpolated into a declaration value; compose with the emotion compat css instead.'\n );\n }\n this.pushValue(value);\n lastIndex = pattern.lastIndex;\n }\n this.strings[this.strings.length - 1] += text.slice(lastIndex);\n }\n\n private pushValue(value: unknown): void {\n this.values.push(value);\n this.strings.push('');\n }\n\n build(): TemplateSlice {\n return { strings: this.strings, values: this.values };\n }\n}\n\nconst reconstructSelector = (\n selector: string,\n values: readonly unknown[]\n): SelectorAlternative => {\n const withSelf = selector.split(SELF_SENTINEL).join('&');\n const parts: SelectorPart[] = [];\n const pattern = /\\.?__dstl(\\d+)__/g;\n let lastIndex = 0;\n let buffer = '';\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(withSelf)) !== null) {\n buffer += withSelf.slice(lastIndex, match.index);\n if (buffer.length > 0) {\n parts.push(buffer);\n buffer = '';\n }\n const value = values[Number(match[1])];\n if (!isHandleLike(value)) {\n throw new Error(\n `Only style handles may be interpolated into selector position; received ${describe(value)}.`\n );\n }\n parts.push(value);\n lastIndex = pattern.lastIndex;\n }\n buffer += withSelf.slice(lastIndex);\n if (buffer.length > 0 || parts.length === 0) {\n parts.push(buffer);\n }\n return parts;\n};\n\nconst reconstructMediaQuery = (\n query: string,\n values: readonly unknown[]\n): string =>\n query.replace(/__dstl(\\d+)__/g, (_match, index: string) => {\n const value = values[Number(index)];\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value);\n }\n throw new Error(\n `Media queries may interpolate strings or numbers only; received ${describe(value)}.`\n );\n });\n\n// --- Composition inlining ------------------------------------------------\n\nconst inlineTemplate = (\n strings: readonly string[],\n values: readonly unknown[],\n inlineValue: NonNullable<FlattenOptions['inlineValue']>\n): TemplateSlice => {\n const outStrings: string[] = [strings[0] ?? ''];\n const outValues: unknown[] = [];\n\n const mergeSlice = (slice: TemplateSlice): void => {\n outStrings[outStrings.length - 1] += slice.strings[0] ?? '';\n for (let i = 0; i < slice.values.length; i += 1) {\n outValues.push(slice.values[i]);\n outStrings.push(slice.strings[i + 1] ?? '');\n }\n };\n\n values.forEach((value, index) => {\n const position = detectPosition(strings, index);\n const spliced = inlineValue(value, position);\n if (spliced) {\n mergeSlice(inlineTemplate(spliced.strings, spliced.values, inlineValue));\n outStrings[outStrings.length - 1] += strings[index + 1] ?? '';\n return;\n }\n outValues.push(value);\n outStrings.push(strings[index + 1] ?? '');\n });\n\n return { strings: outStrings, values: outValues };\n};\n\n// Cheap position heuristic: the first structural char in the following string\n// decides. A `{` before any `;`/`}` means the interpolation is building a\n// selector; anything else is a statement/value position.\nconst detectPosition = (\n strings: readonly string[],\n index: number\n): InterpolationPosition => {\n const next = strings[index + 1] ?? '';\n for (const ch of next) {\n if (ch === '{') {\n return 'selector';\n }\n if (ch === ';' || ch === '}') {\n return 'statement';\n }\n }\n return 'statement';\n};\n\n// --- Element helpers -----------------------------------------------------\n\nconst selectorsOf = (element: Element): readonly string[] =>\n Array.isArray(element.props) ? element.props : [element.props];\n\nconst isSelfSelector = (element: Element): boolean => {\n const selectors = selectorsOf(element);\n return selectors.length === 1 && selectors[0] === SELF_SENTINEL;\n};\n\nconst declChildren = (element: Element): readonly Element[] =>\n Array.isArray(element.children)\n ? element.children.filter((child) => child.type === 'decl')\n : [];\n\nconst propName = (element: Element): string =>\n typeof element.props === 'string' ? element.props : (element.props[0] ?? '');\n\n// --- Value guards --------------------------------------------------------\n\nconst isSerializableScalar = (value: unknown): boolean =>\n typeof value === 'string' ||\n typeof value === 'number' ||\n isCssToken(value) ||\n isContextualCssVar(value) ||\n isContextualCssVarName(value) ||\n isScaleToken(value) ||\n isLocalVarRef(value);\n\nexport const isHandleLike = (value: unknown): value is StyleHandle =>\n Boolean(\n value &&\n typeof value === 'object' &&\n (value as { kind?: string }).kind === 'handle'\n );\n\nconst emptySlice = (): TemplateSlice => ({ strings: [''], values: [] });\n\nconst describe = (value: unknown): string => {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return 'undefined';\n }\n if (typeof value === 'object') {\n const kind = (value as { kind?: string; __kind?: string }).kind;\n const brand = (value as { __kind?: string }).__kind;\n return `object${kind ? ` (kind: ${kind})` : brand ? ` (${brand})` : ''}`;\n }\n return typeof value;\n};\n"]}
|