@master/css-engine 2.0.0-rc.70

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.
Files changed (68) hide show
  1. package/README.md +57 -0
  2. package/dist/animation-rule.d.ts +12 -0
  3. package/dist/animation-rule.mjs +38 -0
  4. package/dist/common.d.ts +40 -0
  5. package/dist/common.mjs +114 -0
  6. package/dist/compile-manifest.d.ts +54 -0
  7. package/dist/compile-manifest.mjs +451 -0
  8. package/dist/compiler.d.ts +32 -0
  9. package/dist/compiler.mjs +38 -0
  10. package/dist/core.d.ts +141 -0
  11. package/dist/core.mjs +848 -0
  12. package/dist/emitted-globals.d.ts +4 -0
  13. package/dist/emitted-globals.mjs +1 -0
  14. package/dist/hydration-manifest.d.ts +4 -0
  15. package/dist/hydration-manifest.mjs +61 -0
  16. package/dist/index.d.ts +22 -0
  17. package/dist/index.mjs +15 -0
  18. package/dist/key-aliases.d.ts +4 -0
  19. package/dist/key-aliases.mjs +95 -0
  20. package/dist/layer.d.ts +17 -0
  21. package/dist/layer.mjs +78 -0
  22. package/dist/namespaces.d.ts +5 -0
  23. package/dist/namespaces.mjs +28 -0
  24. package/dist/native-value-namespaces.d.ts +9 -0
  25. package/dist/native-value-namespaces.mjs +346 -0
  26. package/dist/non-layer.d.ts +12 -0
  27. package/dist/non-layer.mjs +53 -0
  28. package/dist/rule.d.ts +7 -0
  29. package/dist/rule.mjs +14 -0
  30. package/dist/theme-layer.d.ts +21 -0
  31. package/dist/theme-layer.mjs +52 -0
  32. package/dist/utility-layer.d.ts +10 -0
  33. package/dist/utility-layer.mjs +118 -0
  34. package/dist/utility.d.ts +102 -0
  35. package/dist/utility.mjs +1263 -0
  36. package/dist/utils/collect-animation-names.d.ts +10 -0
  37. package/dist/utils/collect-animation-names.mjs +61 -0
  38. package/dist/utils/collect-variable-names.d.ts +3 -0
  39. package/dist/utils/collect-variable-names.mjs +18 -0
  40. package/dist/utils/compare-rule-priority.d.ts +14 -0
  41. package/dist/utils/compare-rule-priority.mjs +136 -0
  42. package/dist/utils/css-variables.d.ts +12 -0
  43. package/dist/utils/css-variables.mjs +197 -0
  44. package/dist/utils/find-native-css-rule-index.d.ts +1 -0
  45. package/dist/utils/find-native-css-rule-index.mjs +10 -0
  46. package/dist/utils/generate-at.d.ts +2 -0
  47. package/dist/utils/generate-at.mjs +32 -0
  48. package/dist/utils/generate-selector.d.ts +2 -0
  49. package/dist/utils/generate-selector.mjs +48 -0
  50. package/dist/utils/natural-compare.d.ts +2 -0
  51. package/dist/utils/natural-compare.mjs +6 -0
  52. package/dist/utils/parse-at.d.ts +44 -0
  53. package/dist/utils/parse-at.mjs +179 -0
  54. package/dist/utils/parse-pair.d.ts +8 -0
  55. package/dist/utils/parse-pair.mjs +46 -0
  56. package/dist/utils/parse-selector.d.ts +19 -0
  57. package/dist/utils/parse-selector.mjs +124 -0
  58. package/dist/utils/parse-value.d.ts +2 -0
  59. package/dist/utils/parse-value.mjs +37 -0
  60. package/dist/utils/replace-char-outside-quotes.d.ts +1 -0
  61. package/dist/utils/replace-char-outside-quotes.mjs +19 -0
  62. package/dist/utils/split-char-outside-quotes.d.ts +1 -0
  63. package/dist/utils/split-char-outside-quotes.mjs +27 -0
  64. package/dist/utils/wrap-at-rules.d.ts +1 -0
  65. package/dist/utils/wrap-at-rules.mjs +10 -0
  66. package/dist/variable-rule.d.ts +26 -0
  67. package/dist/variable-rule.mjs +105 -0
  68. package/package.json +1 -0
@@ -0,0 +1,179 @@
1
+ import { AT_COMPARISON_OPERATORS, AT_LOGICAL_OPERATORS, AT_IDENTIFIERS, AT_COMPARABLE_FEATURES, AT_FEATURE_ALIASES } from '../common.mjs';
2
+ import parsePair from './parse-pair.mjs';
3
+ import parseValue from './parse-value.mjs';
4
+ import replaceCharOutsideQuotes from './replace-char-outside-quotes.mjs';
5
+ import splitCharOutsideQuotes from './split-char-outside-quotes.mjs';
6
+
7
+ function resolveAtFeatureName(value) {
8
+ return AT_FEATURE_ALIASES[value] || value;
9
+ }
10
+ function isAtFeatureName(value) {
11
+ return AT_COMPARABLE_FEATURES.includes(resolveAtFeatureName(value));
12
+ }
13
+ function isAtIdentifier(value) {
14
+ return AT_IDENTIFIERS.includes(value);
15
+ }
16
+ function parseAt(token, css, isRaw = true) {
17
+ let id;
18
+ let firstToken;
19
+ const resolve = (token)=>{
20
+ const regex = /([a-zA-Z0-9-:%|]+|[&|!|,|>|<|=][=]?)/g;
21
+ const raws = [
22
+ ...token.matchAll(regex)
23
+ ].map((match)=>match[0]);
24
+ let nodes = [];
25
+ const addNode = (node)=>{
26
+ let prev = nodes[nodes.length - 1];
27
+ if (node.type === 'number' && !node.name) {
28
+ if (prev?.type === 'comparison') {
29
+ node.operator = prev.value;
30
+ if (node.raw && prev.raw) {
31
+ node.raw = prev.raw + node.raw;
32
+ }
33
+ nodes.pop();
34
+ prev = nodes[nodes.length - 1];
35
+ if (prev?.type === 'string') {
36
+ node.name = resolveAtFeatureName(prev.value);
37
+ if (node.raw && prev.raw) {
38
+ node.raw = prev.raw + node.raw;
39
+ }
40
+ nodes.pop();
41
+ } else {
42
+ node.name = 'width';
43
+ }
44
+ } else {
45
+ node.name = 'width';
46
+ node.operator = '>=';
47
+ }
48
+ }
49
+ nodes.push(node);
50
+ };
51
+ raws.forEach((raw, rawIndex)=>{
52
+ if (AT_COMPARISON_OPERATORS.includes(raw)) {
53
+ const newNode = {
54
+ type: 'comparison',
55
+ value: raw
56
+ };
57
+ if (isRaw) newNode.raw = raw;
58
+ nodes.push(newNode);
59
+ return;
60
+ } else if (raw in AT_LOGICAL_OPERATORS) {
61
+ const newNode = {
62
+ type: 'logical',
63
+ value: AT_LOGICAL_OPERATORS[raw]
64
+ };
65
+ if (isRaw) newNode.raw = raw;
66
+ nodes.push(newNode);
67
+ return;
68
+ }
69
+ const definedAtRule = id === 'container' ? css.containerAtRules.get(raw) || (css.breakpointAtRules.has(raw) ? undefined : css.atRules.get(raw)) : css.atRules.get(raw);
70
+ if (!id && !firstToken) {
71
+ firstToken = raw;
72
+ if (isAtIdentifier(firstToken)) {
73
+ id = firstToken;
74
+ return;
75
+ } else if (definedAtRule) {
76
+ id = definedAtRule.id;
77
+ } else if (isAtFeatureName(firstToken)) {
78
+ id = 'media';
79
+ } else if (firstToken.charAt(0).match(/[a-zA-Z-]/)) {
80
+ id = 'container';
81
+ } else {
82
+ id = 'media';
83
+ }
84
+ }
85
+ let node = {
86
+ type: 'string'
87
+ };
88
+ if (isRaw) node.raw = raw;
89
+ if (definedAtRule) {
90
+ if (definedAtRule.nodes.length === 1) {
91
+ addNode({
92
+ ...definedAtRule.nodes[0],
93
+ raw
94
+ });
95
+ } else if (definedAtRule.nodes.length) {
96
+ addNode({
97
+ raw,
98
+ children: definedAtRule.nodes
99
+ });
100
+ }
101
+ return;
102
+ } else {
103
+ const [splitedNameOrValue, splitedValue] = splitCharOutsideQuotes(raw, ':');
104
+ if (splitedValue) {
105
+ node.name = resolveAtFeatureName(splitedNameOrValue);
106
+ node.value = splitedValue;
107
+ } else {
108
+ node.value = resolveAtFeatureName(splitedNameOrValue);
109
+ }
110
+ if (id === 'container' || id === 'media') {
111
+ const featureValue = String(node.value);
112
+ if (!splitedValue && isAtFeatureName(featureValue)) {
113
+ if (AT_COMPARISON_OPERATORS.includes(raws[rawIndex + 1])) {
114
+ addNode(node);
115
+ } else {
116
+ addNode({
117
+ type: 'boolean',
118
+ name: featureValue,
119
+ ...isRaw && {
120
+ raw
121
+ }
122
+ });
123
+ }
124
+ return;
125
+ } else {
126
+ const { token, ...newNode } = parseValue(node.value, 'rem', css.settings.rootSize);
127
+ Object.assign(node, newNode);
128
+ }
129
+ }
130
+ addNode(node);
131
+ }
132
+ });
133
+ return nodes;
134
+ };
135
+ const pair = (token)=>{
136
+ const pairedAtNodes = [];
137
+ const paired = parsePair(token);
138
+ if (paired) {
139
+ if (paired.pre) {
140
+ pairedAtNodes.push(...pair(paired.pre));
141
+ }
142
+ if (paired.body) {
143
+ if (id === 'supports') {
144
+ pairedAtNodes.push({
145
+ type: 'group',
146
+ children: [
147
+ {
148
+ type: 'string',
149
+ value: replaceCharOutsideQuotes(paired.body, '|', ' ')
150
+ }
151
+ ]
152
+ });
153
+ } else {
154
+ const children = pair(paired.body);
155
+ if (children.length > 1) {
156
+ pairedAtNodes.push({
157
+ type: 'group',
158
+ children: pair(paired.body)
159
+ });
160
+ } else {
161
+ pairedAtNodes.push(...children);
162
+ }
163
+ }
164
+ }
165
+ if (paired.post) {
166
+ pairedAtNodes.push(...pair(paired.post));
167
+ }
168
+ } else {
169
+ pairedAtNodes.push(...resolve(token));
170
+ }
171
+ return pairedAtNodes;
172
+ };
173
+ return {
174
+ nodes: pair(token),
175
+ id: id || 'media' // should be assigned to here
176
+ };
177
+ }
178
+
179
+ export { parseAt as default };
@@ -0,0 +1,8 @@
1
+ export interface ParsedPair {
2
+ start: number;
3
+ end: number;
4
+ pre: string;
5
+ body: string;
6
+ post: string;
7
+ }
8
+ export default function parsePair(str: string, a?: string, b?: string): ParsedPair | null;
@@ -0,0 +1,46 @@
1
+ function parsePair(str, a = '(', b = ')') {
2
+ const stack = [];
3
+ let result = null;
4
+ let inString = null;
5
+ for(let i = 0; i < str.length; i++){
6
+ const char = str[i];
7
+ const prevChar = str[i - 1];
8
+ // 處理 escape 字元,例如 \"
9
+ if (char === '\\') {
10
+ i++; // skip next character
11
+ continue;
12
+ }
13
+ // 處理字串區段進入與離開
14
+ if ((char === '"' || char === '\'') && prevChar !== '\\') {
15
+ if (inString === char) {
16
+ inString = null; // 離開字串
17
+ } else if (!inString) {
18
+ inString = char; // 進入字串
19
+ }
20
+ continue;
21
+ }
22
+ if (inString) continue; // 若在字串中就忽略括號處理
23
+ // 開始符號
24
+ if (str.startsWith(a, i)) {
25
+ stack.push({
26
+ start: i
27
+ });
28
+ i += a.length - 1;
29
+ } else if (str.startsWith(b, i)) {
30
+ const last = stack.pop();
31
+ if (last) {
32
+ result = {
33
+ start: last.start,
34
+ end: i,
35
+ pre: str.slice(stack.length > 0 ? stack[stack.length - 1].start + a.length : 0, last.start),
36
+ body: str.slice(last.start + a.length, i),
37
+ post: str.slice(i + b.length)
38
+ };
39
+ }
40
+ i += b.length - 1;
41
+ }
42
+ }
43
+ return result;
44
+ }
45
+
46
+ export { parsePair as default };
@@ -0,0 +1,19 @@
1
+ import type MasterCSS from '../core';
2
+ export declare type SelectorLiteralNode = {
3
+ type?: 'attribute' | 'pseudo-class' | 'pseudo-element' | 'class' | 'universal' | 'id';
4
+ raw?: string;
5
+ value?: string;
6
+ children?: SelectorNode[];
7
+ };
8
+ export declare type SelectorSeparatorNode = {
9
+ type: 'separator';
10
+ raw?: string;
11
+ value: string;
12
+ };
13
+ export declare type SelectorCombinatorNode = {
14
+ type: 'combinator';
15
+ raw?: string;
16
+ value: string;
17
+ };
18
+ export declare type SelectorNode = SelectorLiteralNode | SelectorCombinatorNode | SelectorSeparatorNode;
19
+ export default function parseSelector(token: string, css: MasterCSS, isRaw?: boolean): SelectorNode[];
@@ -0,0 +1,124 @@
1
+ import { SELECTOR_COMBINATORS } from '../common.mjs';
2
+ import parsePair from './parse-pair.mjs';
3
+
4
+ const SELECTOR_REGEX = new RegExp(`(?:[a-zA-Z0-9-]+)|([${SELECTOR_COMBINATORS.join('')}#.:,*])|(a-zA-Z0-9-)`, 'g');
5
+ const LEGACY_PSEUDO_ELEMENTS = new Set([
6
+ 'before',
7
+ 'after',
8
+ 'first-letter',
9
+ 'first-line'
10
+ ]);
11
+ function parseSelector(token, css, isRaw = true) {
12
+ const resolve = (eachToken)=>{
13
+ const nodes = [];
14
+ let currentPrefix = '';
15
+ let tokenIndex = 0;
16
+ for (const match of eachToken.matchAll(SELECTOR_REGEX)){
17
+ const raw = match[0];
18
+ tokenIndex += raw.length;
19
+ if (raw === ':' || raw === '.' || raw === '#') {
20
+ currentPrefix += raw;
21
+ continue;
22
+ }
23
+ let type;
24
+ let value = raw;
25
+ const definedNodes = css.selectors.get(currentPrefix + raw);
26
+ if (definedNodes) {
27
+ const firstNode = definedNodes[definedNodes.length - 1];
28
+ nodes.push(definedNodes.length === 1 && firstNode.type ? {
29
+ ...firstNode,
30
+ raw: currentPrefix + raw
31
+ } : {
32
+ children: definedNodes,
33
+ raw: currentPrefix + raw
34
+ });
35
+ currentPrefix = '';
36
+ continue;
37
+ }
38
+ if (SELECTOR_COMBINATORS.includes(raw)) {
39
+ type = 'combinator';
40
+ if (raw === '_') {
41
+ const nextRawValue = eachToken[tokenIndex];
42
+ const prevRawValue = eachToken[tokenIndex - raw.length - 1];
43
+ if (prevRawValue !== '_' && nextRawValue !== '_') {
44
+ value = ' '; // support BEM __
45
+ }
46
+ }
47
+ } else if (raw === ',') {
48
+ type = 'separator';
49
+ } else if (raw === '*') {
50
+ type = 'universal';
51
+ } else if (currentPrefix === ':') {
52
+ type = LEGACY_PSEUDO_ELEMENTS.has(raw) ? 'pseudo-element' : 'pseudo-class';
53
+ } else if (currentPrefix === '::') {
54
+ type = 'pseudo-element';
55
+ } else if (currentPrefix === '.') {
56
+ type = 'class';
57
+ } else if (currentPrefix === '#') {
58
+ type = 'id';
59
+ }
60
+ nodes.push({
61
+ value,
62
+ ...isRaw && {
63
+ raw: currentPrefix + raw
64
+ },
65
+ ...type && {
66
+ type
67
+ }
68
+ });
69
+ currentPrefix = '';
70
+ }
71
+ return nodes;
72
+ };
73
+ const pair = (eachToken, nodes = [])=>{
74
+ const paired = parsePair(eachToken);
75
+ if (paired) {
76
+ let { pre, body, post } = paired;
77
+ let name;
78
+ if (body) {
79
+ const lastColonIndex = pre.lastIndexOf(':');
80
+ if (lastColonIndex !== -1) {
81
+ // Walk back through any leading `:` (so `::foo(args)` keeps
82
+ // both colons in `name`, not just the last one).
83
+ let nameStart = lastColonIndex;
84
+ while(nameStart > 0 && pre[nameStart - 1] === ':'){
85
+ nameStart--;
86
+ }
87
+ name = pre.slice(nameStart);
88
+ pre = pre.slice(0, nameStart);
89
+ }
90
+ }
91
+ if (pre) nodes.push(...pair(pre));
92
+ if (body) {
93
+ const children = pair(body);
94
+ if (name) {
95
+ const node = resolve(name)[0];
96
+ if (children.length) node.children = children;
97
+ nodes.push(node);
98
+ } else {
99
+ nodes.push(...children);
100
+ }
101
+ }
102
+ if (post) nodes.push(...pair(post));
103
+ return nodes;
104
+ }
105
+ const attrPaired = parsePair(eachToken, '[', ']');
106
+ if (attrPaired) {
107
+ const { pre, body, post } = attrPaired;
108
+ if (pre) nodes.push(...pair(pre));
109
+ nodes.push({
110
+ value: body,
111
+ type: 'attribute',
112
+ ...isRaw && {
113
+ raw: `[${body}]`
114
+ }
115
+ });
116
+ if (post) nodes.push(...pair(post));
117
+ return nodes;
118
+ }
119
+ return resolve(eachToken);
120
+ };
121
+ return pair(token);
122
+ }
123
+
124
+ export { parseSelector as default };
@@ -0,0 +1,2 @@
1
+ import type { NumberValueComponent, StringValueComponent } from '@master/css-schema/css-syntax';
2
+ export default function parseValue(token: string | number, unit?: string, rootSize?: number): StringValueComponent | NumberValueComponent;
@@ -0,0 +1,37 @@
1
+ import { UNIT_REGEX } from '../common.mjs';
2
+
3
+ function parseValue(token, unit = '', rootSize = 1) {
4
+ const isNumber = typeof token === 'number';
5
+ const defaultUnit = unit;
6
+ // 如果是純數字
7
+ if (isNumber) {
8
+ return {
9
+ unit: defaultUnit,
10
+ type: 'number',
11
+ value: defaultUnit === 'rem' || defaultUnit === 'em' ? token / rootSize : token
12
+ };
13
+ }
14
+ const matches = token.match(UNIT_REGEX);
15
+ if (matches) {
16
+ let value = parseFloat(matches[1]);
17
+ let parsedUnit = matches[2] || '';
18
+ if (!parsedUnit && (defaultUnit === 'rem' || defaultUnit === 'em')) {
19
+ value = value / rootSize;
20
+ parsedUnit = defaultUnit;
21
+ }
22
+ return {
23
+ token,
24
+ value,
25
+ unit: parsedUnit || defaultUnit,
26
+ type: 'number'
27
+ };
28
+ }
29
+ // 無法解析則當作純字串
30
+ return {
31
+ token,
32
+ value: token,
33
+ type: 'string'
34
+ };
35
+ }
36
+
37
+ export { parseValue as default };
@@ -0,0 +1 @@
1
+ export default function replaceCharOutsideQuotes(str: string, target: string, replace: string): string;
@@ -0,0 +1,19 @@
1
+ function replaceCharOutsideQuotes(str, target, replace) {
2
+ let result = '';
3
+ let inSingle = false;
4
+ let inDouble = false;
5
+ for(let i = 0; i < str.length; i++){
6
+ const char = str[i];
7
+ const prev = str[i - 1];
8
+ if (char === '\'' && prev !== '\\' && !inDouble) inSingle = !inSingle;
9
+ else if (char === '"' && prev !== '\\' && !inSingle) inDouble = !inDouble;
10
+ if (char === target && !inSingle && !inDouble) {
11
+ result += replace;
12
+ } else {
13
+ result += char;
14
+ }
15
+ }
16
+ return result;
17
+ }
18
+
19
+ export { replaceCharOutsideQuotes as default };
@@ -0,0 +1 @@
1
+ export default function splitCharOutsideQuotes(str: string, char: string): string[];
@@ -0,0 +1,27 @@
1
+ function splitCharOutsideQuotes(str, char) {
2
+ const result = [];
3
+ let current = '';
4
+ let inSingle = false;
5
+ let inDouble = false;
6
+ for(let i = 0; i < str.length; i++){
7
+ const c = str[i];
8
+ const prev = str[i - 1];
9
+ // 處理 quote 開關
10
+ if (c === '\'' && !inDouble && prev !== '\\') {
11
+ inSingle = !inSingle;
12
+ } else if (c === '"' && !inSingle && prev !== '\\') {
13
+ inDouble = !inDouble;
14
+ }
15
+ // 在引號之外遇到目標字元就切分
16
+ if (c === char && !inSingle && !inDouble) {
17
+ result.push(current.trim());
18
+ current = '';
19
+ } else {
20
+ current += c;
21
+ }
22
+ }
23
+ if (current) result.push(current.trim());
24
+ return result;
25
+ }
26
+
27
+ export { splitCharOutsideQuotes as default };
@@ -0,0 +1 @@
1
+ export default function wrapAtRules(text: string, atRules?: string[]): string;
@@ -0,0 +1,10 @@
1
+ function wrapAtRules(text, atRules) {
2
+ if (!atRules?.length) return text;
3
+ for(let index = atRules.length - 1; index >= 0; index--){
4
+ const atRule = atRules[index]?.trim();
5
+ if (atRule) text = `${atRule}{${text}}`;
6
+ }
7
+ return text;
8
+ }
9
+
10
+ export { wrapAtRules as default };
@@ -0,0 +1,26 @@
1
+ import MasterCSS from './core';
2
+ import type { ResolvedVariableValue, Variable } from '@master/css-schema/css-syntax';
3
+ export default class VariableRule {
4
+ readonly name: string;
5
+ readonly variable: Variable;
6
+ readonly css: MasterCSS;
7
+ nodes: VariableRuleNode[];
8
+ constructor(name: string, variable: Variable, css: MasterCSS);
9
+ get key(): string;
10
+ get text(): string;
11
+ }
12
+ export declare class VariableRuleNode {
13
+ readonly rule: VariableRule;
14
+ readonly variable: ResolvedVariableValue;
15
+ readonly css: MasterCSS;
16
+ readonly mode?: string | undefined;
17
+ native?: CSSRule;
18
+ isDefaultMode: boolean;
19
+ constructor(rule: VariableRule, variable: ResolvedVariableValue, css: MasterCSS, mode?: string | undefined);
20
+ get selectorText(): string;
21
+ get declarationName(): string;
22
+ get declarationValue(): string;
23
+ get declarationText(): string;
24
+ get mediaText(): string;
25
+ get text(): string;
26
+ }
@@ -0,0 +1,105 @@
1
+ import { replaceCSSVariableReferences, normalizeVariableValue } from './utils/css-variables.mjs';
2
+
3
+ class VariableRule {
4
+ name;
5
+ variable;
6
+ css;
7
+ nodes = [];
8
+ constructor(name, variable, css){
9
+ this.name = name;
10
+ this.variable = variable;
11
+ this.css = css;
12
+ const hasDefaultValue = variable.value !== undefined;
13
+ if (hasDefaultValue) {
14
+ this.nodes.push(new VariableRuleNode(this, variable, css));
15
+ }
16
+ if (variable.modes && this.css.settings.modeTrigger) {
17
+ for(const mode in variable.modes){
18
+ const modeVariable = variable.modes[mode];
19
+ const variableRule = new VariableRuleNode(this, modeVariable, css, mode);
20
+ const isDefaultMode = hasDefaultValue ? false : this.css.settings.defaultMode !== 'none' && this.css.settings.defaultMode === mode;
21
+ variableRule.isDefaultMode = isDefaultMode;
22
+ if (isDefaultMode) {
23
+ this.nodes.unshift(variableRule);
24
+ } else {
25
+ this.nodes.push(variableRule);
26
+ }
27
+ }
28
+ }
29
+ }
30
+ get key() {
31
+ return this.name;
32
+ }
33
+ get text() {
34
+ return this.nodes.map(({ text })=>text).join('');
35
+ }
36
+ }
37
+ class VariableRuleNode {
38
+ rule;
39
+ variable;
40
+ css;
41
+ mode;
42
+ native;
43
+ isDefaultMode = false;
44
+ constructor(rule, variable, css, mode){
45
+ this.rule = rule;
46
+ this.variable = variable;
47
+ this.css = css;
48
+ this.mode = mode;
49
+ }
50
+ get selectorText() {
51
+ const isDefaultMode = this.isDefaultMode;
52
+ if (this.mode) {
53
+ switch(this.css.settings.modeTrigger){
54
+ case 'host':
55
+ return `:host(.${this.mode})${isDefaultMode ? ',:host' : ''}`;
56
+ case 'class':
57
+ return `.${this.mode}${isDefaultMode ? ',:root' : ''}`;
58
+ default:
59
+ return ':root';
60
+ }
61
+ } else {
62
+ return ':root';
63
+ }
64
+ }
65
+ get declarationName() {
66
+ return `--${this.rule.name}`;
67
+ }
68
+ get declarationValue() {
69
+ const resolveInlineReferences = (value, stack)=>{
70
+ return replaceCSSVariableReferences(normalizeVariableValue(value).value, (name)=>{
71
+ const variable = this.css.variables.get(name);
72
+ if (!variable?.inline || variable.value === undefined) return;
73
+ const stackIndex = stack.indexOf(name);
74
+ if (stackIndex !== -1) {
75
+ throw new Error(`Circular inline variable reference: ${[
76
+ ...stack.slice(stackIndex),
77
+ name
78
+ ].join(' -> ')}`);
79
+ }
80
+ return resolveInlineReferences(variable.value, [
81
+ ...stack,
82
+ name
83
+ ]);
84
+ });
85
+ };
86
+ return resolveInlineReferences(this.variable.value, [
87
+ this.rule.name
88
+ ]);
89
+ }
90
+ get declarationText() {
91
+ return `${this.declarationName}:${this.declarationValue}`;
92
+ }
93
+ get mediaText() {
94
+ return this.css.settings.modeTrigger === 'media' && this.mode ? `@media (prefers-color-scheme:${this.mode})` : '';
95
+ }
96
+ get text() {
97
+ let text = `${this.selectorText}{${this.declarationText}}`;
98
+ if (this.css.settings.modeTrigger === 'media' && this.mode) {
99
+ text = `@media (prefers-color-scheme:${this.mode}){${text}}`;
100
+ }
101
+ return text;
102
+ }
103
+ }
104
+
105
+ export { VariableRuleNode, VariableRule as default };
package/package.json ADDED
@@ -0,0 +1 @@
1
+ {"name":"@master/css-engine","type":"module","scripts":{"build":"techor build \"src/**/*.ts\" --formats esm","dev":"pnpm build --watch","test":"vitest","bench":"vitest bench","type-check":"tsc --noEmit","lint":"eslint"},"license":"MIT","description":"The manifest-driven Master CSS engine","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/engine"},"keywords":["style","styles","html","variants","virtual","virtual-css","utility","css","ui","lightweight","class","webpack","plugin","integration","vite","parcel","build-tools","mastercss"],"sideEffects":false,"main":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","default":"./dist/index.mjs"},"./compiler":{"types":"./dist/compiler.d.ts","import":"./dist/compiler.mjs","default":"./dist/compiler.mjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css-lexer":"^2.0.0-rc.70","csstype":"^3.2.3","@master/css-schema":"^2.0.0-rc.70"},"devDependencies":{"@master/css-preset":"^2.0.0-rc.70"},"version":"2.0.0-rc.70"}