@master/css 2.0.0-rc.14 → 2.0.0-rc.16
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/dist/_virtual/_commonjsHelpers.cjs +5 -0
- package/dist/_virtual/_commonjsHelpers.mjs +3 -0
- package/dist/_virtual/css-escape.cjs +5 -0
- package/dist/_virtual/css-escape.mjs +3 -0
- package/dist/bin/index.cjs +11 -0
- package/dist/bin/index.d.ts +1 -11
- package/dist/bin/index.mjs +9 -0
- package/dist/config/animations.cjs +113 -0
- package/dist/config/animations.mjs +111 -0
- package/dist/config/functions.cjs +352 -0
- package/dist/config/functions.mjs +350 -0
- package/dist/config/index.cjs +34 -0
- package/dist/config/index.mjs +25 -0
- package/dist/config/media-queries.cjs +7 -0
- package/dist/config/media-queries.mjs +1 -0
- package/dist/config/rules.cjs +2190 -0
- package/dist/config/rules.mjs +2184 -0
- package/dist/config/selectors.cjs +29 -0
- package/dist/config/selectors.mjs +27 -0
- package/dist/config/semantics.cjs +194 -0
- package/dist/config/semantics.mjs +192 -0
- package/dist/config/styles.cjs +2 -0
- package/dist/config/styles.mjs +1 -0
- package/dist/config/variables.cjs +583 -0
- package/dist/config/variables.mjs +581 -0
- package/dist/constants/base-unit-regex.cjs +5 -0
- package/dist/constants/base-unit-regex.mjs +3 -0
- package/dist/constants/start-symbol.cjs +10 -0
- package/dist/constants/start-symbol.mjs +8 -0
- package/dist/core.cjs +979 -0
- package/dist/core.d.ts +2 -3
- package/dist/core.mjs +974 -0
- package/dist/functions/reorder-for-readable-classes.cjs +68 -0
- package/dist/functions/reorder-for-readable-classes.d.ts +1 -1
- package/dist/functions/reorder-for-readable-classes.mjs +66 -0
- package/dist/functions/transform-color-with-opacity.cjs +9 -0
- package/dist/functions/transform-color-with-opacity.mjs +7 -0
- package/dist/index.cjs +37 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +13 -0
- package/dist/layer.cjs +23 -0
- package/dist/layer.mjs +23 -0
- package/dist/polyfills/css-escape.cjs +8 -0
- package/dist/polyfills/css-escape.mjs +2 -0
- package/dist/polyfills/css-escape2.cjs +68 -0
- package/dist/polyfills/css-escape2.mjs +64 -0
- package/dist/rule.cjs +702 -0
- package/dist/rule.d.ts +1 -1
- package/dist/rule.mjs +700 -0
- package/dist/shared/utils/css-escape.cjs +56 -0
- package/dist/shared/utils/css-escape.mjs +54 -0
- package/dist/tokens/screen-sizes.cjs +17 -0
- package/dist/tokens/screen-sizes.mjs +15 -0
- package/dist/utils/concat-arrays.cjs +12 -0
- package/dist/utils/concat-arrays.mjs +10 -0
- package/dist/utils/extend-config.cjs +59 -0
- package/dist/utils/extend-config.mjs +57 -0
- package/dist/utils/flatten-object.cjs +15 -0
- package/dist/utils/flatten-object.mjs +13 -0
- package/dist/utils/get-type.cjs +12 -0
- package/dist/utils/get-type.mjs +10 -0
- package/dist/utils/hex-to-rgb.cjs +30 -0
- package/dist/utils/hex-to-rgb.mjs +28 -0
- package/dist/utils/is-plain-object.cjs +15 -0
- package/dist/utils/is-plain-object.mjs +13 -0
- package/dist/utils/is-symbol.cjs +14 -0
- package/dist/utils/is-symbol.mjs +12 -0
- package/dist/utils/rgb-to-hex.cjs +7 -0
- package/dist/utils/rgb-to-hex.mjs +5 -0
- package/package.json +1 -1
- package/dist/bin/index.bundle.js +0 -33
- package/dist/index.bundle.js +0 -1
- package/dist/index.bundle.mjs +0 -1
- package/dist/types/global.d.ts +0 -5
package/dist/core.cjs
ADDED
|
@@ -0,0 +1,979 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var rule = require('./rule.cjs');
|
|
6
|
+
var index = require('./config/index.cjs');
|
|
7
|
+
var layer = require('./layer.cjs');
|
|
8
|
+
var hexToRgb = require('./utils/hex-to-rgb.cjs');
|
|
9
|
+
var flattenObject = require('./utils/flatten-object.cjs');
|
|
10
|
+
var extendConfig = require('./utils/extend-config.cjs');
|
|
11
|
+
|
|
12
|
+
class MasterCSS {
|
|
13
|
+
customConfig;
|
|
14
|
+
static config = index.config;
|
|
15
|
+
rules;
|
|
16
|
+
ruleBy;
|
|
17
|
+
classesUsage;
|
|
18
|
+
config;
|
|
19
|
+
RegisteredSemanticRules;
|
|
20
|
+
RegisteredRules;
|
|
21
|
+
constructor(customConfig = index.config){
|
|
22
|
+
this.customConfig = customConfig;
|
|
23
|
+
this.rules = [];
|
|
24
|
+
this.ruleBy = {};
|
|
25
|
+
this.classesUsage = {};
|
|
26
|
+
this.RegisteredSemanticRules = [];
|
|
27
|
+
this.RegisteredRules = [];
|
|
28
|
+
if (!customConfig?.override) {
|
|
29
|
+
this.config = extendConfig.extendConfig(index.config, customConfig);
|
|
30
|
+
} else {
|
|
31
|
+
this.config = extendConfig.extendConfig(customConfig);
|
|
32
|
+
}
|
|
33
|
+
this.resolve();
|
|
34
|
+
if (this.constructor === MasterCSS) {
|
|
35
|
+
masterCSSs.push(this);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
resolve() {
|
|
39
|
+
this.styles = {};
|
|
40
|
+
this.stylesBy = {};
|
|
41
|
+
this.selectors = {};
|
|
42
|
+
this.variables = {};
|
|
43
|
+
this.mediaQueries = {};
|
|
44
|
+
this.animations = {};
|
|
45
|
+
this.RegisteredRules.length = 0;
|
|
46
|
+
this.RegisteredSemanticRules.length = 0;
|
|
47
|
+
this.variablesNativeRules = {};
|
|
48
|
+
this.hasKeyframesRule = false;
|
|
49
|
+
const colorVariableNames = {
|
|
50
|
+
current: undefined,
|
|
51
|
+
currentColor: undefined,
|
|
52
|
+
transparent: undefined
|
|
53
|
+
};
|
|
54
|
+
const { styles, selectors, variables, semantics, mediaQueries, rules, animations } = this.config;
|
|
55
|
+
function escapeString(str) {
|
|
56
|
+
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
57
|
+
}
|
|
58
|
+
if (selectors) {
|
|
59
|
+
const resolvedSelectors = flattenObject.flattenObject(selectors);
|
|
60
|
+
for(const eachSelectorName in resolvedSelectors){
|
|
61
|
+
const eachResolvedSelectorText = resolvedSelectors[eachSelectorName];
|
|
62
|
+
const regexp = new RegExp(escapeString(eachSelectorName) + '(?![a-z-])');
|
|
63
|
+
for (const eachNewSelectorText of Array.isArray(eachResolvedSelectorText) ? eachResolvedSelectorText : [
|
|
64
|
+
eachResolvedSelectorText
|
|
65
|
+
]){
|
|
66
|
+
const vendor = eachNewSelectorText.match(/^::-[a-z]+-/m)?.[0] ?? '';
|
|
67
|
+
let selectorValues = this.selectors[vendor];
|
|
68
|
+
if (!selectorValues) {
|
|
69
|
+
selectorValues = this.selectors[vendor] = [];
|
|
70
|
+
}
|
|
71
|
+
let currentSelectValue = selectorValues.find(([_valueRegexp])=>_valueRegexp === regexp);
|
|
72
|
+
if (!currentSelectValue) {
|
|
73
|
+
currentSelectValue = [
|
|
74
|
+
regexp,
|
|
75
|
+
[]
|
|
76
|
+
];
|
|
77
|
+
selectorValues.push(currentSelectValue);
|
|
78
|
+
}
|
|
79
|
+
currentSelectValue[1].push(eachNewSelectorText);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (variables) {
|
|
84
|
+
const unexecutedAliasVariable = {};
|
|
85
|
+
const parseVariable = (variable, name, theme)=>{
|
|
86
|
+
if (!variable) return;
|
|
87
|
+
const addVariable = (name, variableValue, replacedTheme, alpha)=>{
|
|
88
|
+
if (variableValue === undefined) return;
|
|
89
|
+
if (variableValue.type === 'color') {
|
|
90
|
+
if (alpha) {
|
|
91
|
+
const slashIndex = variableValue.value.indexOf('/');
|
|
92
|
+
variableValue = {
|
|
93
|
+
...variableValue,
|
|
94
|
+
value: slashIndex === -1 ? variableValue.value + ' / ' + (alpha.startsWith('0.') ? alpha.slice(1) : alpha) : variableValue.value.slice(0, slashIndex + 2) + String(+variableValue.value.slice(slashIndex + 2) * +alpha).slice(1)
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
colorVariableNames[name] = undefined;
|
|
98
|
+
}
|
|
99
|
+
const currentTheme = replacedTheme ?? theme;
|
|
100
|
+
if (currentTheme !== undefined) {
|
|
101
|
+
if (Object.prototype.hasOwnProperty.call(this.variables, name)) {
|
|
102
|
+
const variable = this.variables[name];
|
|
103
|
+
if (currentTheme) {
|
|
104
|
+
if (!variable.themes) {
|
|
105
|
+
variable.themes = {};
|
|
106
|
+
}
|
|
107
|
+
variable.themes[currentTheme] = variableValue;
|
|
108
|
+
} else {
|
|
109
|
+
variable.value = variableValue.value;
|
|
110
|
+
if (variableValue.type === 'color') {
|
|
111
|
+
variable.space = variableValue.space;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
if (currentTheme) {
|
|
116
|
+
const newVariable = {
|
|
117
|
+
type: variableValue.type,
|
|
118
|
+
themes: {
|
|
119
|
+
[currentTheme]: variableValue
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
if (variableValue.type === 'color') {
|
|
123
|
+
newVariable.space = variableValue.space;
|
|
124
|
+
}
|
|
125
|
+
this.variables[name] = newVariable;
|
|
126
|
+
} else {
|
|
127
|
+
this.variables[name] = variableValue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
this.variables[name] = variableValue;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const type = typeof variable;
|
|
135
|
+
if (type === 'object') {
|
|
136
|
+
if (Array.isArray(variable)) {
|
|
137
|
+
addVariable(name, {
|
|
138
|
+
type: 'string',
|
|
139
|
+
value: variable.join(',')
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
const keys = Object.keys(variable);
|
|
143
|
+
for (const eachKey of keys){
|
|
144
|
+
if (eachKey === '' || eachKey.startsWith('@')) {
|
|
145
|
+
parseVariable(variable[eachKey], name, eachKey || keys.some((eachKey)=>eachKey.startsWith('@')) ? eachKey.slice(1) : undefined);
|
|
146
|
+
} else {
|
|
147
|
+
parseVariable(variable[eachKey], name + '-' + eachKey, undefined);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} else if (type === 'number') {
|
|
152
|
+
addVariable(name, {
|
|
153
|
+
type: 'number',
|
|
154
|
+
value: variable
|
|
155
|
+
});
|
|
156
|
+
addVariable('-' + name, {
|
|
157
|
+
type: 'number',
|
|
158
|
+
value: variable * -1
|
|
159
|
+
});
|
|
160
|
+
} else if (type === 'string') {
|
|
161
|
+
const aliasResult = /^\$\((.*?)\)(?: ?\/ ?(.+?))?$/.exec(variable);
|
|
162
|
+
if (aliasResult) {
|
|
163
|
+
if (!Object.prototype.hasOwnProperty.call(unexecutedAliasVariable, name)) {
|
|
164
|
+
unexecutedAliasVariable[name] = {};
|
|
165
|
+
}
|
|
166
|
+
unexecutedAliasVariable[name][theme] = ()=>{
|
|
167
|
+
delete unexecutedAliasVariable[name][theme];
|
|
168
|
+
const [alias, aliasTheme] = aliasResult[1].split('@');
|
|
169
|
+
if (alias) {
|
|
170
|
+
if (Object.prototype.hasOwnProperty.call(unexecutedAliasVariable, alias)) {
|
|
171
|
+
for (const theme of Object.keys(unexecutedAliasVariable[alias])){
|
|
172
|
+
unexecutedAliasVariable[alias][theme]?.();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const aliasVariable = this.variables[alias];
|
|
176
|
+
if (aliasVariable) {
|
|
177
|
+
if (aliasTheme === undefined && aliasVariable.themes) {
|
|
178
|
+
addVariable(name, {
|
|
179
|
+
type: aliasVariable.type,
|
|
180
|
+
value: aliasVariable.value,
|
|
181
|
+
space: aliasVariable.space
|
|
182
|
+
}, '', aliasResult[2]);
|
|
183
|
+
for(const theme in aliasVariable.themes){
|
|
184
|
+
addVariable(name, aliasVariable.themes[theme], theme, aliasResult[2]);
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
const variable = aliasTheme !== undefined ? aliasVariable.themes?.[aliasTheme] : aliasVariable;
|
|
188
|
+
if (variable) {
|
|
189
|
+
const newVariable = {
|
|
190
|
+
type: variable.type,
|
|
191
|
+
value: variable.value
|
|
192
|
+
};
|
|
193
|
+
if (variable.type === 'color') {
|
|
194
|
+
newVariable.space = variable.space;
|
|
195
|
+
}
|
|
196
|
+
addVariable(name, newVariable, undefined, aliasResult[2]);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
} else {
|
|
203
|
+
const hexColorResult = /^#([A-Fa-f0-9]{3,4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/.exec(variable);
|
|
204
|
+
if (hexColorResult) {
|
|
205
|
+
const [r, g, b, a] = hexToRgb.hexToRgb(hexColorResult[1]);
|
|
206
|
+
addVariable(name, {
|
|
207
|
+
type: 'color',
|
|
208
|
+
value: `${r} ${g} ${b}${a === 1 ? '' : ' / ' + a}`,
|
|
209
|
+
space: 'rgb'
|
|
210
|
+
});
|
|
211
|
+
} else {
|
|
212
|
+
const rgbFunctionResult = /^rgb\( *([0-9]{1,3})(?: *, *| +)([0-9]{1,3})(?: *, *| +)([0-9]{1,3}) *(?:(?:,|\/) *(.*?) *)?\)$/.exec(variable);
|
|
213
|
+
if (rgbFunctionResult) {
|
|
214
|
+
addVariable(name, {
|
|
215
|
+
type: 'color',
|
|
216
|
+
value: rgbFunctionResult[1] + ' ' + rgbFunctionResult[2] + ' ' + rgbFunctionResult[3] + (rgbFunctionResult[4] ? ' / ' + (rgbFunctionResult[4].startsWith('0.') ? rgbFunctionResult[4].slice(1) : rgbFunctionResult[4]) : ''),
|
|
217
|
+
space: 'rgb'
|
|
218
|
+
});
|
|
219
|
+
} else {
|
|
220
|
+
const hslFunctionResult = /^hsl\((.*?)\)$/.exec(variable);
|
|
221
|
+
if (hslFunctionResult) {
|
|
222
|
+
addVariable(name, {
|
|
223
|
+
type: 'color',
|
|
224
|
+
value: hslFunctionResult[1],
|
|
225
|
+
space: 'hsl'
|
|
226
|
+
});
|
|
227
|
+
} else {
|
|
228
|
+
addVariable(name, {
|
|
229
|
+
type: 'string',
|
|
230
|
+
value: variable
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
for(const parnetKey in variables){
|
|
239
|
+
parseVariable(variables[parnetKey], parnetKey);
|
|
240
|
+
}
|
|
241
|
+
for (const name of Object.keys(unexecutedAliasVariable)){
|
|
242
|
+
for (const theme of Object.keys(unexecutedAliasVariable[name])){
|
|
243
|
+
unexecutedAliasVariable[name][theme]?.();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (mediaQueries) {
|
|
248
|
+
this.mediaQueries = flattenObject.flattenObject(mediaQueries);
|
|
249
|
+
}
|
|
250
|
+
if (animations) {
|
|
251
|
+
for(const animationName in animations){
|
|
252
|
+
const eachAnimation = this.animations[animationName] = {};
|
|
253
|
+
const eachKeyframes = animations[animationName];
|
|
254
|
+
for(const eachKeyframeValue in eachKeyframes){
|
|
255
|
+
const newValueByPropertyName = eachAnimation[eachKeyframeValue] = {};
|
|
256
|
+
const eachKeyframeDeclarations = eachKeyframes[eachKeyframeValue];
|
|
257
|
+
for(const propertyName in eachKeyframeDeclarations){
|
|
258
|
+
newValueByPropertyName[propertyName] = eachKeyframeDeclarations[propertyName];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const flattedStyles = styles ? flattenObject.flattenObject(styles) : {};
|
|
264
|
+
const semanticNames = Object.keys(flattedStyles);
|
|
265
|
+
const handleSemanticName = (semanticName)=>{
|
|
266
|
+
if (Object.prototype.hasOwnProperty.call(this.styles, semanticName)) return;
|
|
267
|
+
const currentClass = this.styles[semanticName] = [];
|
|
268
|
+
const className = flattedStyles[semanticName];
|
|
269
|
+
if (!className) return;
|
|
270
|
+
const classNames = className.replace(/(?:\n(?:\s*))+/g, ' ').trim().split(' ');
|
|
271
|
+
for (const eachClassName of classNames){
|
|
272
|
+
const handle = (className)=>{
|
|
273
|
+
if (Object.prototype.hasOwnProperty.call(this.stylesBy, className)) {
|
|
274
|
+
const currentRelation = this.stylesBy[className];
|
|
275
|
+
if (!currentRelation.includes(semanticName)) {
|
|
276
|
+
currentRelation.push(semanticName);
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
this.stylesBy[className] = [
|
|
280
|
+
semanticName
|
|
281
|
+
];
|
|
282
|
+
}
|
|
283
|
+
if (!currentClass.includes(className)) {
|
|
284
|
+
currentClass.push(className);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
if (semanticNames.includes(eachClassName)) {
|
|
288
|
+
handleSemanticName(eachClassName);
|
|
289
|
+
for (const parentClassName of this.styles[eachClassName]){
|
|
290
|
+
handle(parentClassName);
|
|
291
|
+
}
|
|
292
|
+
} else {
|
|
293
|
+
handle(eachClassName);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
for (const eachSemanticName of semanticNames){
|
|
298
|
+
handleSemanticName(eachSemanticName);
|
|
299
|
+
}
|
|
300
|
+
if (semantics) {
|
|
301
|
+
Object.entries(semantics).sort((a, b)=>a[0].localeCompare(b[0])).forEach(([id, declarations], index)=>{
|
|
302
|
+
this.RegisteredSemanticRules.push({
|
|
303
|
+
id: '.' + id,
|
|
304
|
+
match: new RegExp('^' + escapeString(id) + '(?=!|\\*|>|\\+|~|:|\\[|@|_|\\.|$)', 'm'),
|
|
305
|
+
order: index,
|
|
306
|
+
definition: {
|
|
307
|
+
declarations,
|
|
308
|
+
layer: layer.Layer.Semantic
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
if (rules) {
|
|
314
|
+
const rulesEntries = Object.entries(rules).sort((a, b)=>{
|
|
315
|
+
if (a[1].layer !== b[1].layer) {
|
|
316
|
+
return (b[1].layer || 0) - (a[1].layer || 0);
|
|
317
|
+
}
|
|
318
|
+
return b[0].localeCompare(a[0]);
|
|
319
|
+
});
|
|
320
|
+
const rulesEntriesLength = rulesEntries.length;
|
|
321
|
+
const colorNames = Object.keys(colorVariableNames);
|
|
322
|
+
rulesEntries.forEach(([id, eachRuleDefinition], index)=>{
|
|
323
|
+
const eachRegisteredRule = {
|
|
324
|
+
id,
|
|
325
|
+
variables: {},
|
|
326
|
+
order: this.RegisteredSemanticRules.length + rulesEntriesLength - 1 - index,
|
|
327
|
+
definition: eachRuleDefinition
|
|
328
|
+
};
|
|
329
|
+
this.RegisteredRules.push(eachRegisteredRule);
|
|
330
|
+
const match = eachRuleDefinition.match;
|
|
331
|
+
// todo: 不可使用 startsWith 判斷,應改為更精準的從 config.variables 取得目標變數群組,但 config.variables 中的值還沒被 resolve 像是 Array
|
|
332
|
+
const addResolvedVariables = (prefix)=>{
|
|
333
|
+
for(const eachVariableName in this.variables){
|
|
334
|
+
if (eachVariableName.startsWith(prefix + '-') || eachVariableName.startsWith('-' + prefix + '-')) {
|
|
335
|
+
const simplifiedName = eachVariableName.slice(prefix.length + (prefix.startsWith('-') ? 0 : 1));
|
|
336
|
+
eachRegisteredRule.variables[simplifiedName] = {
|
|
337
|
+
...this.variables[eachVariableName],
|
|
338
|
+
name: eachVariableName
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
// 1. custom `config.rules[id].variables`
|
|
344
|
+
if (eachRuleDefinition.variables) {
|
|
345
|
+
for (const eachVariableGroup of eachRuleDefinition.variables){
|
|
346
|
+
addResolvedVariables(eachVariableGroup);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// 2. custom `config.variables`
|
|
350
|
+
addResolvedVariables(id);
|
|
351
|
+
if (match) {
|
|
352
|
+
if (Array.isArray(match)) {
|
|
353
|
+
const [key, values = []] = match;
|
|
354
|
+
const valueMatches = [];
|
|
355
|
+
if (values.length) {
|
|
356
|
+
valueMatches.push(`(?:${values.join('|')})(?![a-zA-Z0-9-])`);
|
|
357
|
+
}
|
|
358
|
+
if (Object.keys(eachRegisteredRule.variables).length) {
|
|
359
|
+
valueMatches.push(`(?:${Object.keys(eachRegisteredRule.variables).join('|')})(?![a-zA-Z0-9-])`);
|
|
360
|
+
}
|
|
361
|
+
if (eachRuleDefinition.colored) {
|
|
362
|
+
valueMatches.push('#', '(?:color|color-contrast|color-mix|hwb|lab|lch|oklab|oklch|rgb|rgba|hsl|hsla)\\(.*\\)', `(?:${colorNames.join('|')})(?![a-zA-Z0-9-])`);
|
|
363
|
+
}
|
|
364
|
+
if (eachRuleDefinition.numeric) {
|
|
365
|
+
valueMatches.push('[\\d\\.]', '(?:max|min|calc|clamp)\\(.*\\)');
|
|
366
|
+
}
|
|
367
|
+
if (valueMatches.length) eachRegisteredRule.match = new RegExp(`^${key}:(?:${valueMatches.join('|')})[^|]*?(?:@|$)`);
|
|
368
|
+
} else {
|
|
369
|
+
eachRegisteredRule.match = match;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Match check if Master CSS syntax
|
|
377
|
+
* @param className
|
|
378
|
+
* @returns css text
|
|
379
|
+
*/ match(className) {
|
|
380
|
+
// 1. rules
|
|
381
|
+
for (const eachRegisteredRule of this.RegisteredRules){
|
|
382
|
+
if (eachRegisteredRule.match?.test(className) || (eachRegisteredRule.definition.layer === layer.Layer.Native || eachRegisteredRule.definition.layer === layer.Layer.NativeShorthand || eachRegisteredRule.definition.layer === layer.Layer.CoreNative || eachRegisteredRule.definition.layer === layer.Layer.CoreNativeShorthand) && className.startsWith(eachRegisteredRule.id + ':')) {
|
|
383
|
+
return eachRegisteredRule;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
// 2. semantic rules
|
|
387
|
+
for (const EachRegisteredSemanticRule of this.RegisteredSemanticRules){
|
|
388
|
+
if (EachRegisteredSemanticRule.match?.test(className)) {
|
|
389
|
+
return EachRegisteredSemanticRule;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Generate rules from class name
|
|
395
|
+
* @param className
|
|
396
|
+
* @returns Rule[]
|
|
397
|
+
*/ generate(className) {
|
|
398
|
+
return (Object.prototype.hasOwnProperty.call(this.styles, className) ? this.styles[className].map((eachSyntax)=>this.create(eachSyntax)) : [
|
|
399
|
+
this.create(className)
|
|
400
|
+
]).filter((eachRule)=>eachRule && eachRule.text);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Create rule from given syntax
|
|
404
|
+
* @param syntax
|
|
405
|
+
* @returns Rule
|
|
406
|
+
*/ create(syntax) {
|
|
407
|
+
if (Object.prototype.hasOwnProperty.call(this.ruleBy, syntax)) return this.ruleBy[syntax];
|
|
408
|
+
const RegistedRule = this.match(syntax);
|
|
409
|
+
if (RegistedRule) {
|
|
410
|
+
return new rule.Rule(syntax, RegistedRule, this);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* 根據蒐集到的所有 DOM class 重新 create
|
|
415
|
+
*/ refresh(customConfig = this.customConfig) {
|
|
416
|
+
if (!customConfig?.override) {
|
|
417
|
+
// @ts-ignore
|
|
418
|
+
this.config = extendConfig.extendConfig(index.config, customConfig);
|
|
419
|
+
} else {
|
|
420
|
+
// @ts-ignore
|
|
421
|
+
this.config = extendConfig.extendConfig(customConfig);
|
|
422
|
+
}
|
|
423
|
+
this.resolve();
|
|
424
|
+
this.rules.length = 0;
|
|
425
|
+
// @ts-ignore
|
|
426
|
+
this.ruleBy = {};
|
|
427
|
+
/**
|
|
428
|
+
* 拿當前所有的 classNames 按照最新的 colors, config.rules 匹配並生成新的 style
|
|
429
|
+
* 所以 refresh 過後 rules 可能會變多也可能會變少
|
|
430
|
+
*/ for(const name in this.classesUsage){
|
|
431
|
+
this.add(name);
|
|
432
|
+
}
|
|
433
|
+
return this;
|
|
434
|
+
}
|
|
435
|
+
reset() {
|
|
436
|
+
// @ts-ignore
|
|
437
|
+
this.ruleBy = {};
|
|
438
|
+
// @ts-ignore
|
|
439
|
+
this.classesUsage = {};
|
|
440
|
+
this.rules.length = 0;
|
|
441
|
+
this.hasKeyframesRule = false;
|
|
442
|
+
this.variablesNativeRules = {};
|
|
443
|
+
for(const keyframeName in this.animations){
|
|
444
|
+
const animation = this.animations[keyframeName];
|
|
445
|
+
animation.usage = 0;
|
|
446
|
+
animation.native = undefined;
|
|
447
|
+
}
|
|
448
|
+
for(const variableName in this.variables){
|
|
449
|
+
const variable = this.variables[variableName];
|
|
450
|
+
variable.usage = 0;
|
|
451
|
+
}
|
|
452
|
+
return this;
|
|
453
|
+
}
|
|
454
|
+
destroy() {
|
|
455
|
+
this.reset();
|
|
456
|
+
masterCSSs.splice(masterCSSs.indexOf(this), 1);
|
|
457
|
+
return this;
|
|
458
|
+
}
|
|
459
|
+
add(...classNames) {
|
|
460
|
+
for (const className of classNames){
|
|
461
|
+
const rules = this.generate(className);
|
|
462
|
+
if (rules.length) {
|
|
463
|
+
for (const rule of rules){
|
|
464
|
+
this.insert(rule);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return this;
|
|
469
|
+
}
|
|
470
|
+
delete(...classNames) {
|
|
471
|
+
/**
|
|
472
|
+
* class name 從 DOM tree 中被移除,
|
|
473
|
+
* 匹配並刪除對應的 rule
|
|
474
|
+
*/ const sheet = this.style?.sheet;
|
|
475
|
+
const deleteRule = (name)=>{
|
|
476
|
+
const rule = this.ruleBy[name];
|
|
477
|
+
if (!rule || Object.prototype.hasOwnProperty.call(this.stylesBy, name) && this.stylesBy[name].some((eachClassName)=>Object.prototype.hasOwnProperty.call(this.classesUsage, eachClassName))) return;
|
|
478
|
+
if (sheet && rule.natives.length) {
|
|
479
|
+
const firstNative = rule.natives[0];
|
|
480
|
+
for(let index = 0; index < sheet.cssRules.length; index++){
|
|
481
|
+
const eachCSSRule = sheet.cssRules[index];
|
|
482
|
+
if (eachCSSRule === firstNative.cssRule) {
|
|
483
|
+
for(let i = 0; i < rule.natives.length; i++){
|
|
484
|
+
sheet.deleteRule(index);
|
|
485
|
+
}
|
|
486
|
+
break;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
this.rules.splice(this.rules.indexOf(rule), 1);
|
|
491
|
+
delete this.ruleBy[name];
|
|
492
|
+
// variables
|
|
493
|
+
if (rule.variableNames) {
|
|
494
|
+
for (const eachVariableName of rule.variableNames){
|
|
495
|
+
const variable = this.variables[eachVariableName];
|
|
496
|
+
if (!variable.usage) variable.usage = 0;
|
|
497
|
+
if (!--variable.usage) {
|
|
498
|
+
const removeProperty = (theme)=>{
|
|
499
|
+
const nativeRule = this.variablesNativeRules[theme];
|
|
500
|
+
nativeRule.cssRule.style.removeProperty('--' + eachVariableName);
|
|
501
|
+
if (!nativeRule.cssRule.style.length) {
|
|
502
|
+
const variablesRule = this.rules[0];
|
|
503
|
+
const index = variablesRule.natives.indexOf(nativeRule);
|
|
504
|
+
sheet?.deleteRule(index);
|
|
505
|
+
variablesRule.natives.splice(index, 1);
|
|
506
|
+
delete this.variablesNativeRules[theme];
|
|
507
|
+
if (!variablesRule.natives.length) {
|
|
508
|
+
this.rules.splice(0, 1);
|
|
509
|
+
this.variablesNativeRules = {};
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
if (variable.value) {
|
|
514
|
+
removeProperty('');
|
|
515
|
+
}
|
|
516
|
+
if (variable.themes) {
|
|
517
|
+
for(const theme in variable.themes){
|
|
518
|
+
removeProperty(theme);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
// animations
|
|
525
|
+
if (rule.animationNames) {
|
|
526
|
+
const keyframeRulesIndex = Object.keys(this.variablesNativeRules).length ? 1 : 0;
|
|
527
|
+
const keyframeRule = this.rules[keyframeRulesIndex];
|
|
528
|
+
for (const eachKeyframeName of rule.animationNames){
|
|
529
|
+
const keyframe = this.animations[eachKeyframeName];
|
|
530
|
+
if (!keyframe.usage) keyframe.usage = 0;
|
|
531
|
+
if (!--keyframe.usage && keyframe.native) {
|
|
532
|
+
const nativeIndex = keyframeRule.natives.indexOf(keyframe.native);
|
|
533
|
+
this.style.sheet?.deleteRule(Object.keys(this.variablesNativeRules).length + nativeIndex);
|
|
534
|
+
keyframeRule.natives.splice(nativeIndex, 1);
|
|
535
|
+
keyframe.native = undefined;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (!keyframeRule.natives.length) {
|
|
539
|
+
this.rules.splice(keyframeRulesIndex, 1);
|
|
540
|
+
this.hasKeyframesRule = false;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
rule.definition.delete?.call(rule, name);
|
|
544
|
+
};
|
|
545
|
+
for (const className of classNames){
|
|
546
|
+
if (Object.prototype.hasOwnProperty.call(this.styles, className)) {
|
|
547
|
+
for (const eachClassName of this.styles[className]){
|
|
548
|
+
if (!Object.prototype.hasOwnProperty.call(this.classesUsage, eachClassName)) {
|
|
549
|
+
deleteRule(eachClassName);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
delete this.ruleBy[className];
|
|
553
|
+
} else {
|
|
554
|
+
deleteRule(className);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* 加工插入規則
|
|
560
|
+
* 1. where
|
|
561
|
+
* 2. normal
|
|
562
|
+
* 3. where selectors
|
|
563
|
+
* 4. normal selectors
|
|
564
|
+
* 5. media where
|
|
565
|
+
* 6. media normal
|
|
566
|
+
* 7. media where selectors
|
|
567
|
+
* 8. media selectors
|
|
568
|
+
* 9. media width where
|
|
569
|
+
* 10. media width
|
|
570
|
+
* 11. media width where selectors
|
|
571
|
+
* 12. media width selectors
|
|
572
|
+
*/ insert(rule) {
|
|
573
|
+
if (this.ruleBy[rule.className]) return;
|
|
574
|
+
let index;
|
|
575
|
+
/**
|
|
576
|
+
* 必須按斷點值遞增,並透過索引插入,
|
|
577
|
+
* 以實現響應式先後套用的規則
|
|
578
|
+
* @example <1 <2 <3 ALL >=1 >=2 >=3
|
|
579
|
+
* @description
|
|
580
|
+
*/ const endIndex = this.rules.length - 1;
|
|
581
|
+
const { media, order, priority, hasWhere, className } = rule;
|
|
582
|
+
const findIndex = (startIndex, stopCheck, matchCheck)=>{
|
|
583
|
+
let i = startIndex;
|
|
584
|
+
for(; i <= endIndex; i++){
|
|
585
|
+
const eachRule = this.rules[i];
|
|
586
|
+
if (stopCheck?.(eachRule)) return matchCheck ? -1 : i - 1;
|
|
587
|
+
if (matchCheck?.(eachRule)) return i;
|
|
588
|
+
}
|
|
589
|
+
return matchCheck ? -1 : i - 1;
|
|
590
|
+
};
|
|
591
|
+
let matchStartIndex;
|
|
592
|
+
let matchEndIndex;
|
|
593
|
+
if (media) {
|
|
594
|
+
const mediaStartIndex = this.rules.findIndex((eachRule)=>eachRule.media);
|
|
595
|
+
if (mediaStartIndex === -1) {
|
|
596
|
+
index = endIndex + 1;
|
|
597
|
+
} else {
|
|
598
|
+
const { 'max-width': maxWidthFeature, 'min-width': minWidthFeature } = media.features;
|
|
599
|
+
if (maxWidthFeature || minWidthFeature) {
|
|
600
|
+
const mediaWidthStartIndex = this.rules.findIndex((eachRule)=>eachRule.media?.features['max-width'] || eachRule.media?.features['min-width']);
|
|
601
|
+
if (mediaWidthStartIndex === -1) {
|
|
602
|
+
index = endIndex + 1;
|
|
603
|
+
} else {
|
|
604
|
+
if (maxWidthFeature && minWidthFeature) {
|
|
605
|
+
/**
|
|
606
|
+
* 範圍越小 ( 越限定 越侷限 ) 越優先,
|
|
607
|
+
* 按照範圍 max-width - min-width 遞減排序
|
|
608
|
+
* find 第一個所遇到同樣 feature 且範圍值比自己大的 rule,
|
|
609
|
+
* 並插入在該 rule 之後,讓自己優先被套用
|
|
610
|
+
*/ if (priority === -1) {
|
|
611
|
+
matchStartIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.priority !== -1, (eachRule)=>eachRule.media.features['max-width'] && eachRule.media.features['min-width']);
|
|
612
|
+
matchEndIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.priority !== -1);
|
|
613
|
+
} else {
|
|
614
|
+
matchStartIndex = findIndex(mediaWidthStartIndex, undefined, (eachRule)=>eachRule.media.features['max-width'] && eachRule.media.features['min-width'] && eachRule.priority !== -1);
|
|
615
|
+
matchEndIndex = endIndex;
|
|
616
|
+
}
|
|
617
|
+
if (matchStartIndex !== -1) {
|
|
618
|
+
const range = maxWidthFeature.value - minWidthFeature.value;
|
|
619
|
+
let i = matchEndIndex;
|
|
620
|
+
const endI = matchStartIndex;
|
|
621
|
+
matchStartIndex = undefined;
|
|
622
|
+
for(; i >= endI; i--){
|
|
623
|
+
const { 'max-width': eachMaxWidthFeature, 'min-width': eachMinWidthFeature } = this.rules[i].media.features;
|
|
624
|
+
const eachRange = eachMaxWidthFeature.value - eachMinWidthFeature.value;
|
|
625
|
+
if (eachRange < range) {
|
|
626
|
+
matchEndIndex = i - 1;
|
|
627
|
+
} else if (eachRange === range) {
|
|
628
|
+
matchStartIndex = i;
|
|
629
|
+
} else {
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (matchStartIndex !== -1 && matchStartIndex !== undefined) {
|
|
635
|
+
const range = maxWidthFeature.value - minWidthFeature.value;
|
|
636
|
+
for(let i = matchEndIndex; i >= matchStartIndex; i--){
|
|
637
|
+
const { 'max-width': eachMaxWidthFeature, 'min-width': eachMinWidthFeature } = this.rules[i].media.features;
|
|
638
|
+
const eachRange = eachMaxWidthFeature.value - eachMinWidthFeature.value;
|
|
639
|
+
if (eachRange < range) {
|
|
640
|
+
matchEndIndex = i - 1;
|
|
641
|
+
} else if (eachRange > range) {
|
|
642
|
+
matchStartIndex = i + 1;
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
} else if (minWidthFeature) {
|
|
648
|
+
/**
|
|
649
|
+
* find 第一個所遇到同樣 feature 且值比自己大的 rule,
|
|
650
|
+
* 並插入在該 rule 之後,讓自己優先被套用
|
|
651
|
+
*/ if (priority === -1) {
|
|
652
|
+
matchStartIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.media.features['max-width'] && eachRule.media.features['min-width'] || eachRule.priority !== -1, (eachRule)=>!eachRule.media.features['max-width'] && eachRule.media.features['min-width']);
|
|
653
|
+
matchEndIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.media.features['max-width'] && eachRule.media.features['min-width'] || eachRule.priority !== -1);
|
|
654
|
+
} else {
|
|
655
|
+
matchStartIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.media.features['max-width'] && eachRule.media.features['min-width'] && eachRule.priority !== -1, (eachRule)=>!eachRule.media.features['max-width'] && eachRule.media.features['min-width'] && eachRule.priority !== -1);
|
|
656
|
+
matchEndIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.media.features['max-width'] && eachRule.media.features['min-width'] && eachRule.priority !== -1);
|
|
657
|
+
}
|
|
658
|
+
if (matchStartIndex !== -1) {
|
|
659
|
+
for(let i = matchEndIndex; i >= matchStartIndex; i--){
|
|
660
|
+
const value = this.rules[i].media.features['min-width'].value;
|
|
661
|
+
if (value > minWidthFeature.value) {
|
|
662
|
+
matchEndIndex = i - 1;
|
|
663
|
+
} else if (value < minWidthFeature.value) {
|
|
664
|
+
matchStartIndex = i + 1;
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
} else {
|
|
670
|
+
/**
|
|
671
|
+
* find 第一個所遇到同樣 feature 且值比自己大的 rule,
|
|
672
|
+
* 並插入在該 rule 之後,讓自己優先被套用
|
|
673
|
+
*/ if (priority === -1) {
|
|
674
|
+
matchStartIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.media.features['min-width'] || eachRule.priority !== -1, (eachRule)=>eachRule.media.features['max-width']);
|
|
675
|
+
matchEndIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.media.features['min-width'] || eachRule.priority !== -1);
|
|
676
|
+
} else {
|
|
677
|
+
matchStartIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.media.features['min-width'] && eachRule.priority !== -1, (eachRule)=>eachRule.media.features['max-width'] && eachRule.priority !== -1);
|
|
678
|
+
matchEndIndex = findIndex(mediaWidthStartIndex, (eachRule)=>eachRule.media.features['min-width'] && eachRule.priority !== -1);
|
|
679
|
+
}
|
|
680
|
+
if (matchStartIndex !== -1) {
|
|
681
|
+
for(let i = matchEndIndex; i >= matchStartIndex; i--){
|
|
682
|
+
const value = this.rules[i].media.features['max-width'].value;
|
|
683
|
+
if (value < maxWidthFeature.value) {
|
|
684
|
+
matchEndIndex = i - 1;
|
|
685
|
+
} else if (value > maxWidthFeature.value) {
|
|
686
|
+
matchStartIndex = i + 1;
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
} else {
|
|
694
|
+
if (priority === -1) {
|
|
695
|
+
matchStartIndex = mediaStartIndex;
|
|
696
|
+
matchEndIndex = findIndex(mediaStartIndex, (eachRule)=>eachRule.media?.features['max-width'] || eachRule.media?.features['min-width'] || eachRule.priority !== -1);
|
|
697
|
+
} else {
|
|
698
|
+
matchStartIndex = findIndex(mediaStartIndex, (eachRule)=>eachRule.media?.features['max-width'] || eachRule.media?.features['min-width'], (eachRule)=>eachRule.priority !== -1);
|
|
699
|
+
matchEndIndex = findIndex(mediaStartIndex, (eachRule)=>eachRule.media?.features['max-width'] || eachRule.media?.features['min-width']);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
} else {
|
|
704
|
+
const findStartIndex = Object.keys(this.variablesNativeRules).length ? this.hasKeyframesRule ? 2 : 1 : this.hasKeyframesRule ? 1 : 0;
|
|
705
|
+
if (priority === -1) {
|
|
706
|
+
matchStartIndex = findStartIndex;
|
|
707
|
+
matchEndIndex = findIndex(findStartIndex, (eachRule)=>eachRule.media || eachRule.priority !== -1);
|
|
708
|
+
} else {
|
|
709
|
+
matchStartIndex = findIndex(findStartIndex, (eachRule)=>eachRule.media, (eachRule)=>eachRule.priority !== -1);
|
|
710
|
+
matchEndIndex = findIndex(findStartIndex, (eachRule)=>eachRule.media);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
if (index === undefined && matchEndIndex !== undefined && matchStartIndex !== undefined) {
|
|
714
|
+
if (matchStartIndex === -1) {
|
|
715
|
+
index = matchEndIndex + 1;
|
|
716
|
+
} else {
|
|
717
|
+
if (priority === -1) {
|
|
718
|
+
for(let i = matchStartIndex; i <= matchEndIndex; i++){
|
|
719
|
+
const currentRule = this.rules[i];
|
|
720
|
+
if (!hasWhere && currentRule.hasWhere) continue;
|
|
721
|
+
if (hasWhere && !currentRule.hasWhere || currentRule.order >= order) {
|
|
722
|
+
index = i;
|
|
723
|
+
break;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
} else {
|
|
727
|
+
for(let i = matchStartIndex; i <= matchEndIndex; i++){
|
|
728
|
+
const currentRule = this.rules[i];
|
|
729
|
+
if (!hasWhere && currentRule.hasWhere) continue;
|
|
730
|
+
if (hasWhere && !currentRule.hasWhere) {
|
|
731
|
+
index = i;
|
|
732
|
+
break;
|
|
733
|
+
}
|
|
734
|
+
if (currentRule.priority < priority) {
|
|
735
|
+
index = i;
|
|
736
|
+
break;
|
|
737
|
+
} else if (currentRule.priority === priority) {
|
|
738
|
+
if (currentRule.order >= order) {
|
|
739
|
+
index = i;
|
|
740
|
+
break;
|
|
741
|
+
}
|
|
742
|
+
} else {
|
|
743
|
+
index = i + 1;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
if (index === undefined) {
|
|
748
|
+
index = matchEndIndex + 1;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
this.rules.splice(index, 0, rule);
|
|
753
|
+
this.ruleBy[className] = rule;
|
|
754
|
+
// 只在瀏覽器端運行
|
|
755
|
+
if (this.style) {
|
|
756
|
+
const sheet = this.style.sheet;
|
|
757
|
+
let cssRuleIndex = 0;
|
|
758
|
+
const getCssRuleIndex = (index)=>{
|
|
759
|
+
const previousRule = this.rules[index];
|
|
760
|
+
if (previousRule) {
|
|
761
|
+
if (!previousRule.natives.length) return getCssRuleIndex(index - 1);
|
|
762
|
+
const lastNative = previousRule.natives[previousRule.natives.length - 1];
|
|
763
|
+
const lastNativeCssRule = lastNative.cssRule?.parentRule ?? lastNative.cssRule;
|
|
764
|
+
if (sheet) for(let i = 0; i < sheet.cssRules.length; i++){
|
|
765
|
+
if (sheet.cssRules[i] === lastNativeCssRule) {
|
|
766
|
+
cssRuleIndex = i + 1;
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
getCssRuleIndex(index - 1);
|
|
773
|
+
for(let i = 0; i < rule.natives.length;){
|
|
774
|
+
try {
|
|
775
|
+
const native = rule.natives[i];
|
|
776
|
+
sheet?.insertRule(native.text, cssRuleIndex);
|
|
777
|
+
native.cssRule = sheet?.cssRules[cssRuleIndex++];
|
|
778
|
+
i++;
|
|
779
|
+
} catch (error) {
|
|
780
|
+
console.error(error);
|
|
781
|
+
rule.natives.splice(i, 1);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
// variables
|
|
786
|
+
this.handleRuleWithVariableNames(rule);
|
|
787
|
+
// animations
|
|
788
|
+
this.handleRuleWithAnimationNames(rule);
|
|
789
|
+
rule.definition.insert?.call(rule);
|
|
790
|
+
}
|
|
791
|
+
get text() {
|
|
792
|
+
return this.rules.map((eachRule)=>eachRule.text).join('');
|
|
793
|
+
}
|
|
794
|
+
handleRuleWithAnimationNames(rule, initializing = false) {
|
|
795
|
+
if (rule.animationNames) {
|
|
796
|
+
const sheet = this.style?.sheet;
|
|
797
|
+
for (const eachKeyframeName of rule.animationNames){
|
|
798
|
+
const animation = this.animations[eachKeyframeName];
|
|
799
|
+
if (animation.usage) {
|
|
800
|
+
animation.usage++;
|
|
801
|
+
} else {
|
|
802
|
+
const nativeRule = {
|
|
803
|
+
text: `@keyframes ${eachKeyframeName}{` + Object.entries(animation).filter(([key])=>key !== 'usage' && key !== 'native').map(([key, variables])=>`${key}{${Object.entries(variables).map(([name, value])=>name + ':' + value).join(';')}}`).join('') + '}'
|
|
804
|
+
};
|
|
805
|
+
const keyframeRulesIndex = Object.keys(this.variablesNativeRules).length ? 1 : 0;
|
|
806
|
+
let keyframeRule;
|
|
807
|
+
if (this.hasKeyframesRule) {
|
|
808
|
+
(keyframeRule = this.rules[keyframeRulesIndex]).natives.push(nativeRule);
|
|
809
|
+
} else {
|
|
810
|
+
this.rules.splice(keyframeRulesIndex, 0, keyframeRule = {
|
|
811
|
+
natives: [
|
|
812
|
+
nativeRule
|
|
813
|
+
],
|
|
814
|
+
get text () {
|
|
815
|
+
return this.natives.map((eachNative)=>eachNative.text).join('');
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
this.hasKeyframesRule = true;
|
|
819
|
+
}
|
|
820
|
+
if (sheet) {
|
|
821
|
+
let cssRule;
|
|
822
|
+
if (initializing) {
|
|
823
|
+
for(let i = 0; i < sheet.cssRules.length; i++){
|
|
824
|
+
const eachCSSRule = sheet.cssRules[i];
|
|
825
|
+
if (eachCSSRule.constructor.name === 'CSSKeyframesRule' && eachCSSRule.name === eachKeyframeName) {
|
|
826
|
+
cssRule = eachCSSRule;
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
if (cssRule) {
|
|
832
|
+
nativeRule.cssRule = cssRule;
|
|
833
|
+
} else {
|
|
834
|
+
const cssRuleIndex = Object.keys(this.variablesNativeRules).length + keyframeRule.natives.length - 1;
|
|
835
|
+
sheet.insertRule(nativeRule.text, cssRuleIndex);
|
|
836
|
+
nativeRule.cssRule = sheet.cssRules[cssRuleIndex];
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
animation.usage = 1;
|
|
840
|
+
animation.native = nativeRule;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
handleRuleWithVariableNames(rule, initializing = false) {
|
|
846
|
+
if (rule.variableNames) {
|
|
847
|
+
const sheet = this.style?.sheet;
|
|
848
|
+
for (const eachVariableName of rule.variableNames){
|
|
849
|
+
const variable = this.variables[eachVariableName];
|
|
850
|
+
if (variable.usage) {
|
|
851
|
+
variable.usage++;
|
|
852
|
+
} else {
|
|
853
|
+
const addProperty = (theme, variableValue)=>{
|
|
854
|
+
let nativeRule = this.variablesNativeRules[theme];
|
|
855
|
+
if (!nativeRule) {
|
|
856
|
+
let cssRule;
|
|
857
|
+
let mediaConditionText;
|
|
858
|
+
let selectorText;
|
|
859
|
+
if (theme) {
|
|
860
|
+
switch(this.config.themeDriver){
|
|
861
|
+
case 'media':
|
|
862
|
+
mediaConditionText = `@media(prefers-color-scheme:${theme})`;
|
|
863
|
+
selectorText = ':root';
|
|
864
|
+
break;
|
|
865
|
+
case 'host':
|
|
866
|
+
selectorText = `:host(.${theme})`;
|
|
867
|
+
break;
|
|
868
|
+
default:
|
|
869
|
+
selectorText = `.${theme}`;
|
|
870
|
+
break;
|
|
871
|
+
}
|
|
872
|
+
} else {
|
|
873
|
+
selectorText = ':root';
|
|
874
|
+
}
|
|
875
|
+
if (sheet) {
|
|
876
|
+
const newCSSRuleIndex = Object.keys(this.variablesNativeRules).length ? this.rules[0].natives.length : 0;
|
|
877
|
+
sheet.insertRule((mediaConditionText ? mediaConditionText + '{' : '') + selectorText + '{}' + (mediaConditionText ? mediaConditionText + '}' : ''), newCSSRuleIndex);
|
|
878
|
+
cssRule = mediaConditionText ? sheet.cssRules[newCSSRuleIndex].cssRules[0] : sheet.cssRules[newCSSRuleIndex];
|
|
879
|
+
} else {
|
|
880
|
+
const styleMap = new Map();
|
|
881
|
+
const style = Object.defineProperties({}, {
|
|
882
|
+
getPropertyValue: {
|
|
883
|
+
value: (property)=>styleMap.get(property)
|
|
884
|
+
},
|
|
885
|
+
removeProperty: {
|
|
886
|
+
value: (property)=>{
|
|
887
|
+
styleMap.delete(property);
|
|
888
|
+
for(let i = 0; i < style.length; i++){
|
|
889
|
+
if (style[i] === property) {
|
|
890
|
+
delete style[i];
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
},
|
|
895
|
+
setProperty: {
|
|
896
|
+
value: (property, value)=>{
|
|
897
|
+
style[style.length] = property;
|
|
898
|
+
styleMap.set(property, value);
|
|
899
|
+
}
|
|
900
|
+
},
|
|
901
|
+
length: {
|
|
902
|
+
get () {
|
|
903
|
+
return Object.keys(style).length;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
cssRule = {
|
|
908
|
+
selectorText,
|
|
909
|
+
style,
|
|
910
|
+
styleMap
|
|
911
|
+
};
|
|
912
|
+
if (mediaConditionText) {
|
|
913
|
+
// @ts-ignore
|
|
914
|
+
cssRule.parentRule = {
|
|
915
|
+
conditionText: mediaConditionText
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
nativeRule = this.pushVariableNativeRule(theme, cssRule);
|
|
920
|
+
}
|
|
921
|
+
const propertyName = '--' + eachVariableName;
|
|
922
|
+
if (!initializing || !nativeRule.cssRule.style.getPropertyValue(propertyName)) {
|
|
923
|
+
nativeRule.cssRule.style.setProperty(propertyName, String(variableValue.value));
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
if (variable.value) {
|
|
927
|
+
addProperty('', variable);
|
|
928
|
+
}
|
|
929
|
+
if (variable.themes) {
|
|
930
|
+
for(const theme in variable.themes){
|
|
931
|
+
addProperty(theme, variable.themes[theme]);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
variable.usage = 1;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
pushVariableNativeRule(theme, variableCSSRule) {
|
|
940
|
+
if (!Object.keys(this.variablesNativeRules).length) {
|
|
941
|
+
this.variablesNativeRules = {};
|
|
942
|
+
const newRule = {
|
|
943
|
+
natives: [],
|
|
944
|
+
get text () {
|
|
945
|
+
return this.natives.map((eachNative)=>eachNative.text).join('');
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
this.rules.splice(0, 0, newRule);
|
|
949
|
+
}
|
|
950
|
+
let prefix = '';
|
|
951
|
+
let suffix = '}';
|
|
952
|
+
if (variableCSSRule.parentRule) {
|
|
953
|
+
prefix += variableCSSRule.parentRule.conditionText.replace(/ /g, '') + '{';
|
|
954
|
+
suffix += '}';
|
|
955
|
+
}
|
|
956
|
+
prefix += variableCSSRule.selectorText + '{';
|
|
957
|
+
const nativeRule = {
|
|
958
|
+
cssRule: variableCSSRule,
|
|
959
|
+
get text () {
|
|
960
|
+
const properties = [];
|
|
961
|
+
for(let i = 0; i < variableCSSRule.style.length; i++){
|
|
962
|
+
const property = variableCSSRule.style[i];
|
|
963
|
+
properties.push(property + ':' + variableCSSRule.style.getPropertyValue(property));
|
|
964
|
+
}
|
|
965
|
+
return prefix + properties.join(';') + suffix;
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
this.rules[0].natives.push(this.variablesNativeRules[theme] = nativeRule);
|
|
969
|
+
return nativeRule;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
const masterCSSs = [];
|
|
973
|
+
(()=>{
|
|
974
|
+
globalThis.MasterCSS = MasterCSS;
|
|
975
|
+
globalThis.masterCSSs = masterCSSs;
|
|
976
|
+
})();
|
|
977
|
+
|
|
978
|
+
exports.default = MasterCSS;
|
|
979
|
+
exports.masterCSSs = masterCSSs;
|