@thejaredwilcurt/csslop 0.0.49 → 0.0.50
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/README.md +0 -1
- package/package.json +1 -1
- package/src/declarations/border.js +1 -1
- package/src/index.js +7 -7
- package/src/rules/optimize/at-rules.js +113 -0
- package/src/rules/optimize/declaration-writes.js +70 -0
- package/src/rules/optimize/empty-rules.js +51 -0
- package/src/rules/optimize/expand-nesting.js +236 -0
- package/src/rules/optimize/factor-parents.js +343 -0
- package/src/rules/optimize/index.js +71 -0
- package/src/rules/optimize/merge-declarations.js +199 -0
- package/src/rules/optimize/merge-nested-rules.js +117 -0
- package/src/rules/optimize/merge-selectors.js +252 -0
- package/src/rules/optimize/nest-rules.js +202 -0
- package/src/rules/optimize/override-index.js +264 -0
- package/src/rules/optimize/prune-overridden.js +267 -0
- package/src/rules/optimize/selector-normalization.js +60 -0
- package/src/rules/optimize/specificity.js +280 -0
- package/src/{position-try.js → rules/position-try.js} +1 -1
- package/src/utilities.js +14 -0
- package/src/value/border.js +85 -0
- package/src/value/{colors.js → color/conversion.js} +3 -2
- package/src/value/color/functions.js +463 -0
- package/src/value/{light-dark.js → color/light-dark.js} +1 -1
- package/src/value/{color-mix.js → color/mix.js} +3 -3
- package/src/value/{relative-colors.js → color/relative.js} +3 -3
- package/src/value/color/shorten.js +93 -0
- package/src/value/gradients.js +1 -1
- package/src/value/hyphenate-limit-chars.js +72 -0
- package/src/value/initial-keywords.js +128 -0
- package/src/value/lengths.js +55 -0
- package/src/value/math/evaluate.js +36 -0
- package/src/value/math/fold.js +315 -0
- package/src/value/math/format.js +230 -0
- package/src/value/math/functions.js +302 -0
- package/src/value/math/index.js +219 -0
- package/src/value/math/parser.js +301 -0
- package/src/value/math/property-ranges.js +174 -0
- package/src/value/math/rewrite.js +222 -0
- package/src/value/math/tokenizer.js +160 -0
- package/src/value/math/unit-totals.js +194 -0
- package/src/value/minify.js +127 -1669
- package/src/value/numbers.js +28 -0
- package/src/value/positions.js +152 -0
- package/src/value/property-optimizations.js +485 -0
- package/src/value/segments.js +74 -0
- package/src/value/{svg-data-uri.js → svg/data-uri.js} +1 -1
- package/src/value/{svg-markup.js → svg/markup.js} +1 -1
- package/src/value/time.js +75 -0
- package/src/value/urls.js +242 -0
- package/src/value/whitespace.js +88 -0
- package/src/rules/optimize.js +0 -2314
- package/src/value/math-expression.js +0 -1156
- package/src/value/math.js +0 -886
- /package/src/value/{named-colors.js → color/named.js} +0 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Measures the specificity of selectors and selector lists, so rules can be regrouped and reordered without changing which declaration wins the cascade.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
findMatchingBracket,
|
|
7
|
+
findMatchingParenthesis,
|
|
8
|
+
splitTopLevelCommaList
|
|
9
|
+
} from '../../parser/source-search.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Advances past a CSS identifier (name) starting at the given index.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} text The selector text.
|
|
15
|
+
* @param {number} start The index to start scanning from.
|
|
16
|
+
* @return {number} The index just after the identifier.
|
|
17
|
+
*/
|
|
18
|
+
function skipSelectorName (text, start) {
|
|
19
|
+
let index = start;
|
|
20
|
+
// Advance over identifier characters (letters, digits, hyphen, underscore)
|
|
21
|
+
while (index < text.length && isSelectorNameCharacter(text.charCodeAt(index))) {
|
|
22
|
+
index++;
|
|
23
|
+
}
|
|
24
|
+
return index;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Reports whether a character code is an ASCII letter.
|
|
29
|
+
*
|
|
30
|
+
* @param {number} characterCode The UTF-16 code unit of the character.
|
|
31
|
+
* @return {boolean} True for `a`-`z` and `A`-`Z`.
|
|
32
|
+
*/
|
|
33
|
+
function isAsciiLetter (characterCode) {
|
|
34
|
+
return (
|
|
35
|
+
(characterCode >= 97 && characterCode <= 122) ||
|
|
36
|
+
(characterCode >= 65 && characterCode <= 90)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Reports whether a character code can appear in a selector name, which here
|
|
42
|
+
* means an ASCII letter, digit, hyphen, or underscore. Comparing character
|
|
43
|
+
* codes avoids running a regular expression once per character.
|
|
44
|
+
*
|
|
45
|
+
* @param {number} characterCode The UTF-16 code unit of the character.
|
|
46
|
+
* @return {boolean} True when the character continues a name.
|
|
47
|
+
*/
|
|
48
|
+
function isSelectorNameCharacter (characterCode) {
|
|
49
|
+
const isDigit = characterCode >= 48 && characterCode <= 57;
|
|
50
|
+
const isHyphen = characterCode === 45;
|
|
51
|
+
const isUnderscore = characterCode === 95;
|
|
52
|
+
return isAsciiLetter(characterCode) || isDigit || isHyphen || isUnderscore;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Compares two specificity tuples [ids, classes, types] lexicographically.
|
|
57
|
+
*
|
|
58
|
+
* @param {Array} first The first specificity tuple.
|
|
59
|
+
* @param {Array} second The second specificity tuple.
|
|
60
|
+
* @return {number} Negative, zero, or positive per standard comparison.
|
|
61
|
+
*/
|
|
62
|
+
function compareSpecificity (first, second) {
|
|
63
|
+
for (let index = 0; index < 3; index++) {
|
|
64
|
+
if (first[index] !== second[index]) {
|
|
65
|
+
return first[index] - second[index];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Computes the CSS specificity of a single complex selector as an
|
|
73
|
+
* [ids, classes, types] tuple. The nesting selector `&` is ignored because its
|
|
74
|
+
* contribution comes from the shared parent when comparing sibling selectors.
|
|
75
|
+
* Functional pseudo-classes `:is()`, `:not()`, `:has()`, and `:matches()` add
|
|
76
|
+
* the maximum specificity of their arguments; `:where()` adds nothing.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} selector A single complex selector string.
|
|
79
|
+
* @return {Array} The [ids, classes, types] specificity tuple.
|
|
80
|
+
*/
|
|
81
|
+
function computeSpecificity (selector) {
|
|
82
|
+
const specificity = [0, 0, 0];
|
|
83
|
+
const text = selector.trim();
|
|
84
|
+
let index = 0;
|
|
85
|
+
while (index < text.length) {
|
|
86
|
+
const character = text[index];
|
|
87
|
+
if (character === '#') {
|
|
88
|
+
specificity[0]++;
|
|
89
|
+
index = skipSelectorName(text, index + 1);
|
|
90
|
+
} else if (character === '.') {
|
|
91
|
+
specificity[1]++;
|
|
92
|
+
index = skipSelectorName(text, index + 1);
|
|
93
|
+
} else if (character === '[') {
|
|
94
|
+
specificity[1]++;
|
|
95
|
+
// An attribute selector that never closes runs to the end of the selector
|
|
96
|
+
const closeBracketIndex = findMatchingBracket(text, index);
|
|
97
|
+
index = closeBracketIndex === -1 ? text.length : closeBracketIndex + 1;
|
|
98
|
+
} else if (character === ':') {
|
|
99
|
+
if (text[index + 1] === ':') {
|
|
100
|
+
specificity[2]++;
|
|
101
|
+
index = skipSelectorName(text, index + 2);
|
|
102
|
+
} else {
|
|
103
|
+
const nameStart = index + 1;
|
|
104
|
+
const nameEnd = skipSelectorName(text, nameStart);
|
|
105
|
+
const name = text.slice(nameStart, nameEnd).toLowerCase();
|
|
106
|
+
if (text[nameEnd] === '(') {
|
|
107
|
+
// An argument list that never closes runs to the end of the selector
|
|
108
|
+
const closeIndex = findMatchingParenthesis(text, nameEnd);
|
|
109
|
+
const argumentsEnd = closeIndex === -1 ? text.length : closeIndex;
|
|
110
|
+
const inner = text.slice(nameEnd + 1, argumentsEnd);
|
|
111
|
+
if (name === 'where') {
|
|
112
|
+
// :where() contributes zero specificity
|
|
113
|
+
} else if (name === 'is' || name === 'not' || name === 'has' || name === 'matches') {
|
|
114
|
+
const innerMax = maxSelectorSpecificity(inner);
|
|
115
|
+
specificity[0] += innerMax[0];
|
|
116
|
+
specificity[1] += innerMax[1];
|
|
117
|
+
specificity[2] += innerMax[2];
|
|
118
|
+
} else {
|
|
119
|
+
specificity[1]++;
|
|
120
|
+
}
|
|
121
|
+
index = argumentsEnd + 1;
|
|
122
|
+
} else {
|
|
123
|
+
// Legacy single-colon pseudo-elements count as pseudo-elements
|
|
124
|
+
if (name === 'before' || name === 'after' || name === 'first-line' || name === 'first-letter') {
|
|
125
|
+
specificity[2]++;
|
|
126
|
+
} else {
|
|
127
|
+
specificity[1]++;
|
|
128
|
+
}
|
|
129
|
+
index = nameEnd;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} else if (character === '*' || character === '&') {
|
|
133
|
+
// Universal selector and nesting selector add no counted specificity here
|
|
134
|
+
index++;
|
|
135
|
+
} else if (isAsciiLetter(text.charCodeAt(index))) {
|
|
136
|
+
specificity[2]++;
|
|
137
|
+
index = skipSelectorName(text, index);
|
|
138
|
+
} else {
|
|
139
|
+
// Combinators and whitespace do not affect specificity
|
|
140
|
+
index++;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return specificity;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Memoizes the strongest and weakest specificity of each selector list seen
|
|
148
|
+
* during the current stylesheet. The same rules are measured again on every
|
|
149
|
+
* merge pass, and a selector list always has the same specificity, so each
|
|
150
|
+
* distinct list is only split and scanned once per stylesheet.
|
|
151
|
+
*
|
|
152
|
+
* @type {Map<string, {strongest: Array, weakest: Array}>}
|
|
153
|
+
*/
|
|
154
|
+
const specificityRangeCache = new Map();
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Discards every memoized specificity range. The minifier calls this around
|
|
158
|
+
* each stylesheet, so the cache does not outlive the pass that filled it.
|
|
159
|
+
*/
|
|
160
|
+
function clearSpecificityCache () {
|
|
161
|
+
specificityRangeCache.clear();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Scans every selector of a comma-separated list for the strongest and the
|
|
166
|
+
* weakest specificity among them. The returned tuples are frozen because they
|
|
167
|
+
* are shared by everything that asks about the same list.
|
|
168
|
+
*
|
|
169
|
+
* @param {string} selectorList The selector list string.
|
|
170
|
+
* @return {object} The `strongest` and `weakest` [ids, classes, types] tuples.
|
|
171
|
+
*/
|
|
172
|
+
function computeSpecificityRange (selectorList) {
|
|
173
|
+
let strongest = [0, 0, 0];
|
|
174
|
+
let weakest = null;
|
|
175
|
+
for (const selector of splitTopLevelCommaList(selectorList)) {
|
|
176
|
+
const specificity = computeSpecificity(selector);
|
|
177
|
+
if (compareSpecificity(specificity, strongest) > 0) {
|
|
178
|
+
strongest = specificity;
|
|
179
|
+
}
|
|
180
|
+
if (!weakest || compareSpecificity(specificity, weakest) < 0) {
|
|
181
|
+
weakest = specificity;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
strongest: Object.freeze(strongest),
|
|
186
|
+
weakest: Object.freeze(weakest || [0, 0, 0])
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Returns the strongest and weakest specificity of a selector list, measuring
|
|
192
|
+
* it the first time it is asked about.
|
|
193
|
+
*
|
|
194
|
+
* @param {string} selectorList The selector list string.
|
|
195
|
+
* @return {object} The `strongest` and `weakest` [ids, classes, types] tuples.
|
|
196
|
+
*/
|
|
197
|
+
function getSpecificityRange (selectorList) {
|
|
198
|
+
let range = specificityRangeCache.get(selectorList);
|
|
199
|
+
if (!range) {
|
|
200
|
+
range = computeSpecificityRange(selectorList);
|
|
201
|
+
specificityRangeCache.set(selectorList, range);
|
|
202
|
+
}
|
|
203
|
+
return range;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Returns the maximum specificity tuple across a comma-separated selector list,
|
|
208
|
+
* matching how a comma-separated group behaves as `:is()`.
|
|
209
|
+
*
|
|
210
|
+
* @param {string} selectorList The selector list string.
|
|
211
|
+
* @return {Array} The maximum [ids, classes, types] tuple.
|
|
212
|
+
*/
|
|
213
|
+
function maxSelectorSpecificity (selectorList) {
|
|
214
|
+
return getSpecificityRange(selectorList).strongest;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Returns the strongest specificity a rule can match with, which is the highest
|
|
219
|
+
* of its individual selectors.
|
|
220
|
+
*
|
|
221
|
+
* @param {Array} selectors The rule's selector strings.
|
|
222
|
+
* @return {Array} The [ids, classes, types] specificity tuple.
|
|
223
|
+
*/
|
|
224
|
+
function maximumRuleSpecificity (selectors) {
|
|
225
|
+
return maxSelectorSpecificity((selectors || []).join(','));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Returns the weakest specificity a rule's declarations are applied with. Every
|
|
230
|
+
* selector of a top-level rule applies the same declarations under its own
|
|
231
|
+
* specificity, so the weakest selector decides whether another rule is able to
|
|
232
|
+
* override the rule as a whole.
|
|
233
|
+
*
|
|
234
|
+
* @param {Array} selectors The rule's selector strings.
|
|
235
|
+
* @return {Array} The [ids, classes, types] specificity tuple.
|
|
236
|
+
*/
|
|
237
|
+
function minimumRuleSpecificity (selectors) {
|
|
238
|
+
return getSpecificityRange((selectors || []).join(',')).weakest;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Adds two specificity tuples together, which is how a nested selector combines
|
|
243
|
+
* with the parent selector it only ever matches through.
|
|
244
|
+
*
|
|
245
|
+
* @param {Array} first The first [ids, classes, types] tuple.
|
|
246
|
+
* @param {Array} second The second [ids, classes, types] tuple.
|
|
247
|
+
* @return {Array} The summed specificity tuple.
|
|
248
|
+
*/
|
|
249
|
+
function addSpecificity (first, second) {
|
|
250
|
+
return [
|
|
251
|
+
first[0] + second[0],
|
|
252
|
+
first[1] + second[1],
|
|
253
|
+
first[2] + second[2]
|
|
254
|
+
];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Reports whether a rule that nests blocks may take on further selectors. A
|
|
259
|
+
* nested selector resolves against its parent's whole selector list as `:is()`,
|
|
260
|
+
* which matches with the specificity of the strongest selector in that list, so
|
|
261
|
+
* the list may only grow while every selector in it weighs the same.
|
|
262
|
+
*
|
|
263
|
+
* @param {Array} selectors The selector list the merged rule would carry.
|
|
264
|
+
* @return {boolean} Whether the nested blocks keep their current weight.
|
|
265
|
+
*/
|
|
266
|
+
function selectorsShareSpecificity (selectors) {
|
|
267
|
+
const strongest = maximumRuleSpecificity(selectors);
|
|
268
|
+
const weakest = minimumRuleSpecificity(selectors);
|
|
269
|
+
return compareSpecificity(strongest, weakest) === 0;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export {
|
|
273
|
+
addSpecificity,
|
|
274
|
+
clearSpecificityCache,
|
|
275
|
+
compareSpecificity,
|
|
276
|
+
maximumRuleSpecificity,
|
|
277
|
+
maxSelectorSpecificity,
|
|
278
|
+
minimumRuleSpecificity,
|
|
279
|
+
selectorsShareSpecificity
|
|
280
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @file Handles `@position-try` rule analysis, usage tracking, and dead-rule elimination during CSS minification.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { registersCustomProperty } from './
|
|
5
|
+
import { registersCustomProperty } from './property.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Scans top-level rules to register `@property` custom properties in the context and collect `@position-try` rule declarations and initial usage counts.
|
package/src/utilities.js
CHANGED
|
@@ -19,6 +19,20 @@ function resolveUnicodeEscape (hex) {
|
|
|
19
19
|
return String.fromCodePoint(codePoint);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Reports whether a property is a custom property. A custom property holds an
|
|
24
|
+
* arbitrary token stream rather than a typed value, so every one of its tokens,
|
|
25
|
+
* whitespace included, is part of what it stores, and neither shorthands nor
|
|
26
|
+
* `all` ever reset it.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} property The CSS property name.
|
|
29
|
+
* @return {boolean} Whether the property is a custom property.
|
|
30
|
+
*/
|
|
31
|
+
function isCustomProperty (property) {
|
|
32
|
+
return Boolean(property) && property.startsWith('--');
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
export {
|
|
36
|
+
isCustomProperty,
|
|
23
37
|
resolveUnicodeEscape
|
|
24
38
|
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Rewrites `border` and `outline` values into their shortest canonical form, stating the width before the style and dropping the default width.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Matches the keywords that state a border line style.
|
|
7
|
+
*
|
|
8
|
+
* @type {string}
|
|
9
|
+
*/
|
|
10
|
+
const BORDER_STYLE_KEYWORD_SOURCE = 'solid|dashed|dotted|double|groove|ridge|inset|outset|hidden|none';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Matches the ways a border line width is stated: one of its three keywords, a
|
|
14
|
+
* length, or a math function that resolves to one.
|
|
15
|
+
*
|
|
16
|
+
* @type {string}
|
|
17
|
+
*/
|
|
18
|
+
const BORDER_WIDTH_SOURCE = 'thin|medium|thick|[+-]?(?:\\d+|\\d*\\.\\d+)(?:e[+-]?\\d+)?[a-z]*|(?:calc|min|max|clamp)\\([^()]*\\)';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Matches a `border` value that states its line style in front of its line
|
|
22
|
+
* width, with the two captured so they can be swapped.
|
|
23
|
+
*
|
|
24
|
+
* @type {RegExp}
|
|
25
|
+
*/
|
|
26
|
+
const BORDER_STYLE_BEFORE_WIDTH_PATTERN = new RegExp(
|
|
27
|
+
'^(' + BORDER_STYLE_KEYWORD_SOURCE + ')\\s+(' + BORDER_WIDTH_SOURCE + ')(?=\\s|$)',
|
|
28
|
+
'i'
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Rewrites a `border` value that leads with its line style into the canonical
|
|
33
|
+
* width-style-color order. The width has to be recognized before the two are
|
|
34
|
+
* swapped: `border` states its components in any order, so the component behind
|
|
35
|
+
* the style may be a color instead, as in `solid #8aadf4 1px`, and that one
|
|
36
|
+
* belongs behind the width rather than in front of it.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} value The `border` value.
|
|
39
|
+
* @return {string} The value with its width stated before its style.
|
|
40
|
+
*/
|
|
41
|
+
function reorderBorderWidthBeforeStyle (value) {
|
|
42
|
+
return value.replace(BORDER_STYLE_BEFORE_WIDTH_PATTERN, '$2 $1');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Removes the default `medium` line width from a `border` value, since the
|
|
47
|
+
* shorthand resets an unstated width to it anyway.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} value The `border` value.
|
|
50
|
+
* @return {string} The value without its default line width.
|
|
51
|
+
*/
|
|
52
|
+
function removeDefaultBorderWidth (value) {
|
|
53
|
+
// Match the medium keyword and the whitespace that separates it from the next component
|
|
54
|
+
return value.replace(/\bmedium\s+/g, '');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Matches a line style keyword written directly against one of the color
|
|
59
|
+
* keywords that can follow it, capturing both so a space can be put back
|
|
60
|
+
* between them.
|
|
61
|
+
*
|
|
62
|
+
* @type {RegExp}
|
|
63
|
+
*/
|
|
64
|
+
const STYLE_TOUCHING_COLOR_PATTERN = new RegExp(
|
|
65
|
+
'\\b(' + BORDER_STYLE_KEYWORD_SOURCE + ')(red|green|olive|tan|transparent)\\b',
|
|
66
|
+
'g'
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Restores the space between an `outline` value's line style and a color
|
|
71
|
+
* keyword when the two have been written against each other, since together
|
|
72
|
+
* they would read as one unknown keyword.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} value The `outline` value.
|
|
75
|
+
* @return {string} The value with its style and color keywords separated.
|
|
76
|
+
*/
|
|
77
|
+
function separateOutlineStyleFromColor (value) {
|
|
78
|
+
return value.replace(STYLE_TOUCHING_COLOR_PATTERN, '$1 $2');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export {
|
|
82
|
+
removeDefaultBorderWidth,
|
|
83
|
+
reorderBorderWidthBeforeStyle,
|
|
84
|
+
separateOutlineStyleFromColor
|
|
85
|
+
};
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* @file Provides color parsing, color space conversion (sRGB, OKLab, OKLCH, HSL, HWB), and hex formatting for CSS value minification.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { parseAlphaString } from '../shared.js';
|
|
6
|
+
|
|
7
|
+
import { namedColors } from './named.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Reverse lookup from "r,g,b" to the shortest CSS named color keyword.
|