postcss-minify-params 9.0.3 → 9.0.5
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/package.json +3 -4
- package/src/index.js +4 -136
- package/src/lib/media.js +86 -0
- package/src/lib/tokenUtils.js +180 -0
- package/src/lib/transform.js +102 -0
- package/src/lib/whitespace.js +229 -0
- package/types/index.d.ts +1 -3
- package/types/index.d.ts.map +1 -1
- package/types/lib/media.d.ts +9 -0
- package/types/lib/media.d.ts.map +1 -0
- package/types/lib/token-utils.d.ts +44 -0
- package/types/lib/token-utils.d.ts.map +1 -0
- package/types/lib/tokenUtils.d.ts +44 -0
- package/types/lib/tokenUtils.d.ts.map +1 -0
- package/types/lib/transform.d.ts +7 -0
- package/types/lib/transform.d.ts.map +1 -0
- package/types/lib/whitespace.d.ts +18 -0
- package/types/lib/whitespace.d.ts.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postcss-minify-params",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.5",
|
|
4
4
|
"description": "Minify at-rule params with PostCSS",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -41,9 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"homepage": "https://github.com/cssnano/cssnano",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"browserslist": "^4.29.
|
|
45
|
-
"cssnano-utils": "^
|
|
46
|
-
"postcss-value-parser": "^4.2.0"
|
|
44
|
+
"browserslist": "^4.29.2",
|
|
45
|
+
"cssnano-utils": "^8.0.1"
|
|
47
46
|
},
|
|
48
47
|
"engines": {
|
|
49
48
|
"node": "^22.22.3 || ^24.15.0 || >=26.0"
|
package/src/index.js
CHANGED
|
@@ -1,138 +1,9 @@
|
|
|
1
1
|
import getBrowsersList from '#getBrowsersList';
|
|
2
|
-
import
|
|
3
|
-
import cssnanoUtils from 'cssnano-utils';
|
|
2
|
+
import transform from './lib/transform.js';
|
|
4
3
|
|
|
5
|
-
const { getArguments } = cssnanoUtils;
|
|
6
4
|
/** @import browserslist from 'browserslist' */
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
* Return the greatest common divisor
|
|
10
|
-
* of two numbers.
|
|
11
|
-
*
|
|
12
|
-
* @param {number} a
|
|
13
|
-
* @param {number} b
|
|
14
|
-
* @return {number}
|
|
15
|
-
*/
|
|
16
|
-
function gcd(a, b) {
|
|
17
|
-
return b ? gcd(b, a % b) : a;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @param {number} a
|
|
22
|
-
* @param {number} b
|
|
23
|
-
* @return {[number, number]}
|
|
24
|
-
*/
|
|
25
|
-
function aspectRatio(a, b) {
|
|
26
|
-
const divisor = gcd(a, b);
|
|
27
|
-
|
|
28
|
-
return [a / divisor, b / divisor];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param {valueParser.Node[]} args
|
|
33
|
-
* @return {string}
|
|
34
|
-
*/
|
|
35
|
-
function split(args) {
|
|
36
|
-
return args.map((arg) => valueParser.stringify(arg)).join('');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @param {valueParser.Node} node
|
|
41
|
-
* @return {void}
|
|
42
|
-
*/
|
|
43
|
-
function removeNode(node) {
|
|
44
|
-
node.value = '';
|
|
45
|
-
node.type = 'word';
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @param {unknown[]} items
|
|
50
|
-
* @return {string}
|
|
51
|
-
*/
|
|
52
|
-
function sortAndDedupe(items) {
|
|
53
|
-
const a = [...new Set(items)];
|
|
54
|
-
a.sort();
|
|
55
|
-
return a.join();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @param {boolean} legacy
|
|
60
|
-
* @param {import('postcss').AtRule} rule
|
|
61
|
-
* @return {void}
|
|
62
|
-
*/
|
|
63
|
-
function transform(legacy, rule) {
|
|
64
|
-
const ruleName = rule.name.toLowerCase();
|
|
65
|
-
|
|
66
|
-
// We should re-arrange parameters only for `@media` and `@supports` at-rules
|
|
67
|
-
if (!rule.params || !['media', 'supports'].includes(ruleName)) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const params = valueParser(rule.params);
|
|
72
|
-
|
|
73
|
-
params.walk((node, index) => {
|
|
74
|
-
if (node.type === 'div') {
|
|
75
|
-
node.before = node.after = '';
|
|
76
|
-
} else if (node.type === 'function') {
|
|
77
|
-
node.before = '';
|
|
78
|
-
if (
|
|
79
|
-
node.nodes[0] &&
|
|
80
|
-
node.nodes[0].type === 'word' &&
|
|
81
|
-
node.nodes[0].value.startsWith('--') &&
|
|
82
|
-
node.nodes[2] === undefined
|
|
83
|
-
) {
|
|
84
|
-
node.after = ' ';
|
|
85
|
-
} else {
|
|
86
|
-
node.after = '';
|
|
87
|
-
}
|
|
88
|
-
if (
|
|
89
|
-
node.nodes[4] &&
|
|
90
|
-
node.nodes[0].value.toLowerCase().indexOf('-aspect-ratio') === 3
|
|
91
|
-
) {
|
|
92
|
-
const [a, b] = aspectRatio(
|
|
93
|
-
Number(node.nodes[2].value),
|
|
94
|
-
Number(node.nodes[4].value)
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
node.nodes[2].value = a.toString();
|
|
98
|
-
node.nodes[4].value = b.toString();
|
|
99
|
-
}
|
|
100
|
-
} else if (node.type === 'space') {
|
|
101
|
-
node.value = ' ';
|
|
102
|
-
} else {
|
|
103
|
-
const prevWord = params.nodes[index - 2];
|
|
104
|
-
|
|
105
|
-
if (
|
|
106
|
-
node.value.toLowerCase() === 'all' &&
|
|
107
|
-
rule.name.toLowerCase() === 'media' &&
|
|
108
|
-
!prevWord
|
|
109
|
-
) {
|
|
110
|
-
const nextWord = params.nodes[index + 2];
|
|
111
|
-
|
|
112
|
-
if (!legacy || nextWord) {
|
|
113
|
-
removeNode(node);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (nextWord && nextWord.value.toLowerCase() === 'and') {
|
|
117
|
-
const nextSpace = params.nodes[index + 1];
|
|
118
|
-
const secondSpace = params.nodes[index + 3];
|
|
119
|
-
|
|
120
|
-
removeNode(nextWord);
|
|
121
|
-
removeNode(nextSpace);
|
|
122
|
-
removeNode(secondSpace);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}, true);
|
|
127
|
-
|
|
128
|
-
rule.params = sortAndDedupe(getArguments(params).map(split));
|
|
129
|
-
|
|
130
|
-
if (!rule.params.length) {
|
|
131
|
-
rule.raws.afterName = '';
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const allBugBrowers = new Set(['ie 10', 'ie 11']);
|
|
6
|
+
const allBugBrowsers = new Set(['ie 10', 'ie 11']);
|
|
136
7
|
|
|
137
8
|
/**
|
|
138
9
|
* @typedef {{ overrideBrowserslist?: string | string[] }} AutoprefixerOptions
|
|
@@ -155,13 +26,10 @@ function pluginCreator(options = {}) {
|
|
|
155
26
|
prepare(result) {
|
|
156
27
|
const { stats, env, from, file } = result.opts || {};
|
|
157
28
|
const browsers = getBrowsersList(options, stats, from, file, env);
|
|
158
|
-
|
|
159
|
-
const hasAllBug = !new Set(browsers).isDisjointFrom(allBugBrowers);
|
|
29
|
+
const hasAllBug = !new Set(browsers).isDisjointFrom(allBugBrowsers);
|
|
160
30
|
|
|
161
31
|
return {
|
|
162
|
-
/**
|
|
163
|
-
* @param {import('postcss').Root} css
|
|
164
|
-
*/
|
|
32
|
+
/** @param {import('postcss').Root} css */
|
|
165
33
|
OnceExit(css) {
|
|
166
34
|
css.walkAtRules((rule) => transform(hasAllBug, rule));
|
|
167
35
|
},
|
package/src/lib/media.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
decoded,
|
|
3
|
+
significantIndex,
|
|
4
|
+
TokenType,
|
|
5
|
+
tokenEnd,
|
|
6
|
+
} from './tokenUtils.js';
|
|
7
|
+
|
|
8
|
+
/** @import cssnanoUtils from 'cssnano-utils' */
|
|
9
|
+
/** @typedef {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens']} Tokens */
|
|
10
|
+
|
|
11
|
+
/** @param {Tokens} input @param {{startIndex:number,endIndex:number}} segment @return {{endIndex:number,first:number,last:number}} */
|
|
12
|
+
function mediaSegmentInfo(input, { startIndex, endIndex }) {
|
|
13
|
+
const first = significantIndex(input, startIndex, 1);
|
|
14
|
+
let last = endIndex - 1;
|
|
15
|
+
while (
|
|
16
|
+
last >= first &&
|
|
17
|
+
(input[last][0] === TokenType.Whitespace ||
|
|
18
|
+
input[last][0] === TokenType.Comment)
|
|
19
|
+
) {
|
|
20
|
+
last--;
|
|
21
|
+
}
|
|
22
|
+
return { endIndex, first, last };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** @param {Tokens} input @param {{first:number,last:number}} segment @return {boolean} */
|
|
26
|
+
function isStandaloneAll(input, { first, last }) {
|
|
27
|
+
return (
|
|
28
|
+
first === last &&
|
|
29
|
+
input[first]?.[0] === TokenType.Ident &&
|
|
30
|
+
decoded(input[first]).toLowerCase() === 'all'
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @param {boolean} legacy @param {Tokens} input @param {{endIndex:number,first:number}} segment @param {{start:number,end:number,text:string}[]} changes @return {void} */
|
|
35
|
+
function minifyMediaAllSegment(legacy, input, { endIndex, first }, changes) {
|
|
36
|
+
if (
|
|
37
|
+
input[first]?.[0] !== TokenType.Ident ||
|
|
38
|
+
decoded(input[first]).toLowerCase() !== 'all'
|
|
39
|
+
)
|
|
40
|
+
return;
|
|
41
|
+
const second = significantIndex(input, first + 1, 1);
|
|
42
|
+
const and =
|
|
43
|
+
second < endIndex &&
|
|
44
|
+
input[second]?.[0] === TokenType.Ident &&
|
|
45
|
+
decoded(input[second]).toLowerCase() === 'and';
|
|
46
|
+
if (legacy && !and) return;
|
|
47
|
+
const end = and ? second : first;
|
|
48
|
+
for (let i = first; i <= end; i++) {
|
|
49
|
+
if (
|
|
50
|
+
input[i][0] === TokenType.Ident ||
|
|
51
|
+
input[i][0] === TokenType.Whitespace
|
|
52
|
+
) {
|
|
53
|
+
changes.push({
|
|
54
|
+
start: input[i][2],
|
|
55
|
+
end: tokenEnd(input[i]),
|
|
56
|
+
text: '',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const trailing = end + 1;
|
|
61
|
+
if (trailing < endIndex && input[trailing]?.[0] === TokenType.Whitespace) {
|
|
62
|
+
changes.push({
|
|
63
|
+
start: input[trailing][2],
|
|
64
|
+
end: tokenEnd(input[trailing]),
|
|
65
|
+
text: '',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** @param {boolean} legacy @param {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>} structure @param {{start:number,end:number,text:string}[]} changes @return {boolean} */
|
|
71
|
+
export default function minifyMediaAll(legacy, structure, changes) {
|
|
72
|
+
const { tokens: input } = structure;
|
|
73
|
+
const ranges = structure
|
|
74
|
+
.topLevelSegments()
|
|
75
|
+
.map((segment) => mediaSegmentInfo(input, segment));
|
|
76
|
+
|
|
77
|
+
if (!legacy && ranges.some((segment) => isStandaloneAll(input, segment))) {
|
|
78
|
+
const last = input.at(-1);
|
|
79
|
+
if (last) changes.push({ start: 0, end: tokenEnd(last), text: '' });
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (const segment of ranges)
|
|
84
|
+
minifyMediaAllSegment(legacy, input, segment, changes);
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import cssnanoUtils from 'cssnano-utils';
|
|
2
|
+
|
|
3
|
+
const { TokenType } = cssnanoUtils;
|
|
4
|
+
const decoded = /** @type {typeof cssnanoUtils.decoded} */ (
|
|
5
|
+
cssnanoUtils.decoded
|
|
6
|
+
);
|
|
7
|
+
const tokenEnd = /** @type {typeof cssnanoUtils.tokenEnd} */ (
|
|
8
|
+
cssnanoUtils.tokenEnd
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
/** @typedef {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens']} Tokens */
|
|
12
|
+
|
|
13
|
+
export { TokenType, decoded, tokenEnd };
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Reports whether a value ends in a backslash that begins an escape
|
|
17
|
+
* sequence, as opposed to a backslash that is itself escaped.
|
|
18
|
+
* @param {string} value
|
|
19
|
+
* @return {boolean}
|
|
20
|
+
*/
|
|
21
|
+
export function endsWithEscapingBackslash(value) {
|
|
22
|
+
if (!value.endsWith('\\')) return false;
|
|
23
|
+
|
|
24
|
+
let backslashes = 0;
|
|
25
|
+
for (let i = value.length - 1; i >= 0 && value[i] === '\\'; i--) {
|
|
26
|
+
backslashes++;
|
|
27
|
+
}
|
|
28
|
+
return backslashes % 2 === 1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const openingTypes = new Set([
|
|
32
|
+
TokenType.Function,
|
|
33
|
+
TokenType.OpenParen,
|
|
34
|
+
TokenType.OpenSquare,
|
|
35
|
+
TokenType.OpenCurly,
|
|
36
|
+
]);
|
|
37
|
+
export const closingTypes = new Set([
|
|
38
|
+
TokenType.CloseParen,
|
|
39
|
+
TokenType.CloseSquare,
|
|
40
|
+
TokenType.CloseCurly,
|
|
41
|
+
]);
|
|
42
|
+
export const calcProductEndTypes = new Set([
|
|
43
|
+
TokenType.Number,
|
|
44
|
+
TokenType.Percentage,
|
|
45
|
+
TokenType.Dimension,
|
|
46
|
+
TokenType.Ident,
|
|
47
|
+
TokenType.CloseParen,
|
|
48
|
+
]);
|
|
49
|
+
export const calcProductStartTypes = new Set([
|
|
50
|
+
TokenType.Number,
|
|
51
|
+
TokenType.Percentage,
|
|
52
|
+
TokenType.Dimension,
|
|
53
|
+
TokenType.Ident,
|
|
54
|
+
TokenType.Function,
|
|
55
|
+
TokenType.OpenParen,
|
|
56
|
+
]);
|
|
57
|
+
export const mathFunctions = cssnanoUtils.mathFunctions;
|
|
58
|
+
export const whitespaceInsensitiveFunctions = new Set(['selector']);
|
|
59
|
+
export const aspectRatioFeatures = new Set([
|
|
60
|
+
'aspect-ratio',
|
|
61
|
+
'min-aspect-ratio',
|
|
62
|
+
'max-aspect-ratio',
|
|
63
|
+
'device-aspect-ratio',
|
|
64
|
+
'min-device-aspect-ratio',
|
|
65
|
+
'max-device-aspect-ratio',
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Convert a CSS number spelling to an exact rational number.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} source
|
|
72
|
+
* @return {[bigint, bigint] | undefined}
|
|
73
|
+
*/
|
|
74
|
+
function rational(source) {
|
|
75
|
+
const match = source.match(
|
|
76
|
+
/^[+]?((?:\d+(?:\.\d*)?)|(?:\.\d+))(?:[eE]([+\-]?\d+))?$/v
|
|
77
|
+
);
|
|
78
|
+
if (!match) return undefined;
|
|
79
|
+
const [, coefficient, exponent = '0'] = match;
|
|
80
|
+
const [whole, fraction = ''] = coefficient.split('.');
|
|
81
|
+
const digits = `${whole}${fraction}`;
|
|
82
|
+
let numerator = BigInt(digits);
|
|
83
|
+
let denominator = 10n ** BigInt(fraction.length);
|
|
84
|
+
if (numerator === 0n) return [0n, 1n];
|
|
85
|
+
const power = BigInt(exponent);
|
|
86
|
+
if (power > 10000n || power < -10000n) return undefined;
|
|
87
|
+
if (power >= 0n) numerator *= 10n ** power;
|
|
88
|
+
else denominator *= 10n ** -power;
|
|
89
|
+
return [numerator, denominator];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** @param {bigint} a @param {bigint} b @return {bigint} */
|
|
93
|
+
function gcd(a, b) {
|
|
94
|
+
return b ? gcd(b, a % b) : a;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} left
|
|
99
|
+
* @param {string} right
|
|
100
|
+
* @return {[string, string] | undefined}
|
|
101
|
+
*/
|
|
102
|
+
export function aspectRatio(left, right) {
|
|
103
|
+
const a = rational(left);
|
|
104
|
+
const b = rational(right);
|
|
105
|
+
if (!a || !b) return undefined;
|
|
106
|
+
const numerator = a[0] * b[1];
|
|
107
|
+
const denominator = b[0] * a[1];
|
|
108
|
+
if (numerator === 0n && denominator === 0n) return undefined;
|
|
109
|
+
const divisor = gcd(numerator, denominator);
|
|
110
|
+
const result = [String(numerator / divisor), String(denominator / divisor)];
|
|
111
|
+
return result.join('/').length < left.length + right.length + 1
|
|
112
|
+
? /** @type {[string, string]} */ (result)
|
|
113
|
+
: undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** @param {Tokens} input @param {number} index @param {number} step @return {number} */
|
|
117
|
+
export function significantIndex(input, index, step) {
|
|
118
|
+
let cursor = index;
|
|
119
|
+
while (
|
|
120
|
+
input[cursor] &&
|
|
121
|
+
(input[cursor][0] === TokenType.Whitespace ||
|
|
122
|
+
input[cursor][0] === TokenType.Comment)
|
|
123
|
+
) {
|
|
124
|
+
cursor += step;
|
|
125
|
+
}
|
|
126
|
+
return cursor;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {string} source
|
|
131
|
+
* @param {{start:number,end:number}[]} segments
|
|
132
|
+
* @param {{start:number,end:number,text:string}[]} edits
|
|
133
|
+
* @return {string[]}
|
|
134
|
+
*/
|
|
135
|
+
export function serializeSegments(source, segments, edits) {
|
|
136
|
+
let segmentIndex = 0;
|
|
137
|
+
let previousEnd = -1;
|
|
138
|
+
let previousEdit;
|
|
139
|
+
for (const edit of edits) {
|
|
140
|
+
if (
|
|
141
|
+
previousEdit &&
|
|
142
|
+
edit.start === previousEdit.start &&
|
|
143
|
+
edit.end === previousEdit.end &&
|
|
144
|
+
edit.text === previousEdit.text
|
|
145
|
+
) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
while (
|
|
149
|
+
segmentIndex < segments.length &&
|
|
150
|
+
edit.start >= segments[segmentIndex].end
|
|
151
|
+
) {
|
|
152
|
+
segmentIndex++;
|
|
153
|
+
}
|
|
154
|
+
const segment = segments[segmentIndex];
|
|
155
|
+
if (
|
|
156
|
+
!segment ||
|
|
157
|
+
edit.start < segment.start ||
|
|
158
|
+
edit.start < previousEnd ||
|
|
159
|
+
edit.end < edit.start ||
|
|
160
|
+
edit.end > segment.end
|
|
161
|
+
) {
|
|
162
|
+
return segments.map(({ start, end }) => source.slice(start, end));
|
|
163
|
+
}
|
|
164
|
+
previousEnd = edit.end;
|
|
165
|
+
previousEdit = edit;
|
|
166
|
+
}
|
|
167
|
+
let editIndex = 0;
|
|
168
|
+
return segments.map(({ start, end }) => {
|
|
169
|
+
let cursor = start;
|
|
170
|
+
let result = '';
|
|
171
|
+
while (editIndex < edits.length && edits[editIndex].start < end) {
|
|
172
|
+
const edit = edits[editIndex++];
|
|
173
|
+
if (edit.start < start || edit.start < cursor) continue;
|
|
174
|
+
result += source.slice(cursor, edit.start) + edit.text;
|
|
175
|
+
cursor = edit.end;
|
|
176
|
+
}
|
|
177
|
+
result += source.slice(cursor, end);
|
|
178
|
+
return result;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import cssnanoUtils from 'cssnano-utils';
|
|
2
|
+
import minifyMediaAll from './media.js';
|
|
3
|
+
import {
|
|
4
|
+
minifyAspectRatios,
|
|
5
|
+
minifyWhitespace,
|
|
6
|
+
parentIndexes,
|
|
7
|
+
} from './whitespace.js';
|
|
8
|
+
import {
|
|
9
|
+
endsWithEscapingBackslash,
|
|
10
|
+
serializeSegments,
|
|
11
|
+
tokenEnd,
|
|
12
|
+
TokenType,
|
|
13
|
+
} from './tokenUtils.js';
|
|
14
|
+
|
|
15
|
+
const { balancedTokens, tokens: tokenizeValue } = cssnanoUtils;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {boolean} legacy
|
|
19
|
+
* @param {import('postcss').AtRule} rule
|
|
20
|
+
* @return {void}
|
|
21
|
+
*/
|
|
22
|
+
export default function transform(legacy, rule) {
|
|
23
|
+
const ruleName = rule.name.toLowerCase();
|
|
24
|
+
|
|
25
|
+
// We should re-arrange parameters only for `@media` and `@supports` at-rules
|
|
26
|
+
if (!rule.params || !['media', 'supports'].includes(ruleName)) return;
|
|
27
|
+
|
|
28
|
+
const source =
|
|
29
|
+
rule.raws.params?.value === rule.params
|
|
30
|
+
? (rule.raws.params.raw ?? rule.params)
|
|
31
|
+
: rule.params;
|
|
32
|
+
const structure = balancedTokens(source);
|
|
33
|
+
if (!structure) {
|
|
34
|
+
if (rule.raws.params?.raw) {
|
|
35
|
+
rule.raws.params = { raw: rule.params, value: rule.params };
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
/** @type {{start:number,end:number,text:string}[]} */
|
|
40
|
+
const changes = [];
|
|
41
|
+
const parents = parentIndexes(structure);
|
|
42
|
+
const mediaIsUnconditional =
|
|
43
|
+
ruleName === 'media' && minifyMediaAll(legacy, structure, changes);
|
|
44
|
+
if (mediaIsUnconditional) {
|
|
45
|
+
rule.params = '';
|
|
46
|
+
if (rule.raws.params?.raw) rule.raws.params = { raw: '', value: '' };
|
|
47
|
+
updateAfterName(rule);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
minifyWhitespace(structure, parents, changes);
|
|
51
|
+
minifyAspectRatios(ruleName === 'supports', structure, parents, changes);
|
|
52
|
+
const { tokens: input } = structure;
|
|
53
|
+
const segmentRanges = structure
|
|
54
|
+
.topLevelSegments()
|
|
55
|
+
.map(({ startIndex, endIndex }) => {
|
|
56
|
+
const start = input[startIndex]?.[2] ?? source.length;
|
|
57
|
+
const end = endIndex > startIndex ? tokenEnd(input[endIndex - 1]) : start;
|
|
58
|
+
return { start, end };
|
|
59
|
+
});
|
|
60
|
+
changes.sort((a, b) => a.start - b.start);
|
|
61
|
+
const segments = serializeSegments(source, segmentRanges, changes);
|
|
62
|
+
rule.params = [...new Set(segments)].toSorted().join();
|
|
63
|
+
if (rule.raws.params?.raw) {
|
|
64
|
+
rule.raws.params = { raw: rule.params, value: rule.params };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
updateAfterName(rule);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Strip whitespace after @media or @supports when parameters begin with (.
|
|
72
|
+
*
|
|
73
|
+
* @param {import('postcss').AtRule} rule
|
|
74
|
+
* @return {void}
|
|
75
|
+
*/
|
|
76
|
+
function updateAfterName(rule) {
|
|
77
|
+
if (!rule.params.length) {
|
|
78
|
+
rule.raws.afterName = '';
|
|
79
|
+
} else if (
|
|
80
|
+
rule.params.startsWith('(') &&
|
|
81
|
+
!endsWithEscapingBackslash(rule.name)
|
|
82
|
+
) {
|
|
83
|
+
rule.raws.afterName = stripWhitespacePreservingComments(
|
|
84
|
+
rule.raws.afterName
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {string | undefined} raw
|
|
91
|
+
* @return {string}
|
|
92
|
+
*/
|
|
93
|
+
function stripWhitespacePreservingComments(raw) {
|
|
94
|
+
if (!raw?.includes('/*')) return '';
|
|
95
|
+
let result = '';
|
|
96
|
+
for (const [type, tokenRaw] of tokenizeValue(raw)) {
|
|
97
|
+
if (type !== TokenType.Whitespace) {
|
|
98
|
+
result += tokenRaw;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import cssnanoUtils from 'cssnano-utils';
|
|
2
|
+
import {
|
|
3
|
+
aspectRatio,
|
|
4
|
+
aspectRatioFeatures,
|
|
5
|
+
calcProductEndTypes,
|
|
6
|
+
calcProductStartTypes,
|
|
7
|
+
closingTypes,
|
|
8
|
+
decoded,
|
|
9
|
+
mathFunctions,
|
|
10
|
+
openingTypes,
|
|
11
|
+
significantIndex,
|
|
12
|
+
TokenType,
|
|
13
|
+
tokenEnd,
|
|
14
|
+
whitespaceInsensitiveFunctions,
|
|
15
|
+
} from './tokenUtils.js';
|
|
16
|
+
|
|
17
|
+
const { numeric } = cssnanoUtils;
|
|
18
|
+
/** @typedef {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens']} Tokens */
|
|
19
|
+
|
|
20
|
+
/** @param {ReturnType<typeof cssnanoUtils.balancedTokens>} structure @return {(number|undefined)[]} */
|
|
21
|
+
export function parentIndexes(structure) {
|
|
22
|
+
if (!structure) return [];
|
|
23
|
+
const parents = [];
|
|
24
|
+
const stack = [];
|
|
25
|
+
for (let i = 0; i < structure.tokens.length; i++) {
|
|
26
|
+
const type = structure.tokens[i][0];
|
|
27
|
+
parents[i] = stack.at(-1);
|
|
28
|
+
if (openingTypes.has(type)) stack.push(i);
|
|
29
|
+
else if (closingTypes.has(type)) stack.pop();
|
|
30
|
+
}
|
|
31
|
+
return parents;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @param {Tokens} input @param {number} index @return {boolean} */
|
|
35
|
+
function isTightWhitespace(input, index) {
|
|
36
|
+
const previous = input[index - 1];
|
|
37
|
+
const next = input[index + 1];
|
|
38
|
+
return [
|
|
39
|
+
previous?.[0] === TokenType.Function,
|
|
40
|
+
previous?.[0] === TokenType.OpenParen,
|
|
41
|
+
next?.[0] === TokenType.CloseParen,
|
|
42
|
+
previous?.[0] === TokenType.Comma,
|
|
43
|
+
next?.[0] === TokenType.Comma,
|
|
44
|
+
previous?.[0] === TokenType.Colon,
|
|
45
|
+
next?.[0] === TokenType.Colon,
|
|
46
|
+
previous?.[0] === TokenType.Delim,
|
|
47
|
+
next?.[0] === TokenType.Delim,
|
|
48
|
+
].some(Boolean);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** @param {unknown} token @return {boolean} */
|
|
52
|
+
function isAdditiveOperator(token) {
|
|
53
|
+
return (
|
|
54
|
+
Array.isArray(token) &&
|
|
55
|
+
token[0] === TokenType.Delim &&
|
|
56
|
+
(token[1] === '+' || token[1] === '-')
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** @param {Tokens} input @param {number} index @param {(number|undefined)[]} parents @return {boolean} */
|
|
61
|
+
function isRequiredMathOperatorWhitespace(input, index, parents) {
|
|
62
|
+
const previous = significantIndex(input, index - 1, -1);
|
|
63
|
+
const next = significantIndex(input, index + 1, 1);
|
|
64
|
+
const before = input[previous];
|
|
65
|
+
const after = input[next];
|
|
66
|
+
let operator;
|
|
67
|
+
if (isAdditiveOperator(before)) operator = previous;
|
|
68
|
+
else if (isAdditiveOperator(after)) operator = next;
|
|
69
|
+
if (operator === undefined) return false;
|
|
70
|
+
|
|
71
|
+
let parent = parents[index];
|
|
72
|
+
while (parent !== undefined) {
|
|
73
|
+
const token = input[parent];
|
|
74
|
+
if (token?.[0] === TokenType.Function) {
|
|
75
|
+
const name = String(decoded(token)).toLowerCase();
|
|
76
|
+
if (whitespaceInsensitiveFunctions.has(name)) return false;
|
|
77
|
+
if (!mathFunctions.has(name)) return true;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
parent = parents[parent];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const left = input[significantIndex(input, operator - 1, -1)];
|
|
84
|
+
const right = input[significantIndex(input, operator + 1, 1)];
|
|
85
|
+
return (
|
|
86
|
+
calcProductEndTypes.has(left?.[0]) && calcProductStartTypes.has(right?.[0])
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** @param {Tokens} input @param {number} name @param {number} colon @param {number} left @param {number} slash @param {number} right @param {number} after @param {number} close @return {boolean} */
|
|
91
|
+
function isAspectRatioFeature(
|
|
92
|
+
input,
|
|
93
|
+
name,
|
|
94
|
+
colon,
|
|
95
|
+
left,
|
|
96
|
+
slash,
|
|
97
|
+
right,
|
|
98
|
+
after,
|
|
99
|
+
close
|
|
100
|
+
) {
|
|
101
|
+
if (name >= close || input[name]?.[0] !== TokenType.Ident) return false;
|
|
102
|
+
const a = input[left] ? numeric(input[left]) : false;
|
|
103
|
+
const b = input[right] ? numeric(input[right]) : false;
|
|
104
|
+
const lowerName = String(decoded(input[name])).toLowerCase();
|
|
105
|
+
return (
|
|
106
|
+
aspectRatioFeatures.has(lowerName) &&
|
|
107
|
+
input[colon]?.[0] === TokenType.Colon &&
|
|
108
|
+
input[slash]?.[0] === TokenType.Delim &&
|
|
109
|
+
input[slash][1] === '/' &&
|
|
110
|
+
input[left]?.[0] === TokenType.Number &&
|
|
111
|
+
input[right]?.[0] === TokenType.Number &&
|
|
112
|
+
a &&
|
|
113
|
+
b &&
|
|
114
|
+
!a.unit &&
|
|
115
|
+
!b.unit &&
|
|
116
|
+
after === close
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** @param {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>} structure @param {number} index @param {(number|undefined)[]} parents @return {{start:number,end:number,text:string}} */
|
|
121
|
+
function whitespaceEdit(structure, index, parents) {
|
|
122
|
+
const input = structure.tokens;
|
|
123
|
+
const token = input[index];
|
|
124
|
+
const next = input[index + 1];
|
|
125
|
+
const tight = isTightWhitespace(input, index);
|
|
126
|
+
const open = parents[index];
|
|
127
|
+
const first = open === undefined ? -1 : significantIndex(input, open + 1, 1);
|
|
128
|
+
const colon = significantIndex(input, first + 1, 1);
|
|
129
|
+
const close = open === undefined ? -1 : (structure.endForOpening(open) ?? -1);
|
|
130
|
+
const emptyCustomProperty =
|
|
131
|
+
next?.[0] === TokenType.CloseParen &&
|
|
132
|
+
first >= 0 &&
|
|
133
|
+
input[first][0] === TokenType.Ident &&
|
|
134
|
+
decoded(input[first]).startsWith('--') &&
|
|
135
|
+
input[colon]?.[0] === TokenType.Colon &&
|
|
136
|
+
significantIndex(input, colon + 1, 1) === close;
|
|
137
|
+
return {
|
|
138
|
+
start: token[2],
|
|
139
|
+
end: tokenEnd(token),
|
|
140
|
+
text:
|
|
141
|
+
tight &&
|
|
142
|
+
!emptyCustomProperty &&
|
|
143
|
+
!isRequiredMathOperatorWhitespace(input, index, parents)
|
|
144
|
+
? ''
|
|
145
|
+
: ' ',
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** @param {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>} structure @param {(number|undefined)[]} parents @param {{start:number,end:number,text:string}[]} changes @return {void} */
|
|
150
|
+
export function minifyWhitespace(structure, parents, changes) {
|
|
151
|
+
const { tokens: input } = structure;
|
|
152
|
+
const existingRanges = new Set(
|
|
153
|
+
changes.map((change) => `${change.start}:${change.end}`)
|
|
154
|
+
);
|
|
155
|
+
for (let i = 0; i < input.length; i++) {
|
|
156
|
+
if (input[i][0] === TokenType.Whitespace) {
|
|
157
|
+
const edit = whitespaceEdit(structure, i, parents);
|
|
158
|
+
const range = `${edit.start}:${edit.end}`;
|
|
159
|
+
if (!existingRanges.has(range)) {
|
|
160
|
+
changes.push(edit);
|
|
161
|
+
existingRanges.add(range);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** @param {Tokens} input @param {(number|undefined)[]} parents @param {number} index @return {boolean} */
|
|
168
|
+
function isGroupingParent(input, parents, index) {
|
|
169
|
+
let parent = parents[index];
|
|
170
|
+
while (parent !== undefined) {
|
|
171
|
+
if (input[parent][0] !== TokenType.OpenParen) return false;
|
|
172
|
+
parent = parents[parent];
|
|
173
|
+
}
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** @param {boolean} supports @param {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>} structure @param {(number|undefined)[]} parents @param {{start:number,end:number,text:string}[]} changes @return {void} */
|
|
178
|
+
export function minifyAspectRatios(supports, structure, parents, changes) {
|
|
179
|
+
const { tokens: input } = structure;
|
|
180
|
+
for (let open = 0; open < input.length; open++) {
|
|
181
|
+
if (
|
|
182
|
+
input[open][0] !== TokenType.OpenParen ||
|
|
183
|
+
(supports
|
|
184
|
+
? !isGroupingParent(input, parents, open)
|
|
185
|
+
: parents[open] !== undefined)
|
|
186
|
+
)
|
|
187
|
+
continue;
|
|
188
|
+
const close = structure.endForOpening(open);
|
|
189
|
+
if (close === undefined) continue;
|
|
190
|
+
const name = significantIndex(input, open + 1, 1);
|
|
191
|
+
const colon = significantIndex(input, name + 1, 1);
|
|
192
|
+
const left = significantIndex(input, colon + 1, 1);
|
|
193
|
+
const slash = significantIndex(input, left + 1, 1);
|
|
194
|
+
const right = significantIndex(input, slash + 1, 1);
|
|
195
|
+
const after = significantIndex(input, right + 1, 1);
|
|
196
|
+
if (
|
|
197
|
+
!isAspectRatioFeature(
|
|
198
|
+
input,
|
|
199
|
+
name,
|
|
200
|
+
colon,
|
|
201
|
+
left,
|
|
202
|
+
slash,
|
|
203
|
+
right,
|
|
204
|
+
after,
|
|
205
|
+
close
|
|
206
|
+
)
|
|
207
|
+
)
|
|
208
|
+
continue;
|
|
209
|
+
const a = numeric(input[left]);
|
|
210
|
+
const b = numeric(input[right]);
|
|
211
|
+
if (
|
|
212
|
+
!a ||
|
|
213
|
+
!b ||
|
|
214
|
+
!Number.isFinite(a.number) ||
|
|
215
|
+
a.number < 0 ||
|
|
216
|
+
!Number.isFinite(b.number) ||
|
|
217
|
+
b.number < 0 ||
|
|
218
|
+
(a.number === 0 && b.number === 0)
|
|
219
|
+
)
|
|
220
|
+
continue;
|
|
221
|
+
const ratio = aspectRatio(input[left][1], input[right][1]);
|
|
222
|
+
if (!ratio) continue;
|
|
223
|
+
const [x, y] = ratio;
|
|
224
|
+
changes.push(
|
|
225
|
+
{ start: input[left][2], end: tokenEnd(input[left]), text: String(x) },
|
|
226
|
+
{ start: input[right][2], end: tokenEnd(input[right]), text: String(y) }
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
package/types/index.d.ts
CHANGED
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAGI,OAAQ,KAAA,YAAY,MAAM,cAAc,CAAA;AAKzC,YAAwD,mBAAmB,GAAjE;IAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,CAAqB;AAC3E,YAAgE,mBAAmB,GAAzE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC,CAAqB;AACnF,YAAqD,OAAO,GAAlD,mBAAmB,GAAG,mBAAmB,CAAS;AAH/D;;;;GAIG;AAEH;;;;GAIG;AACH,iBAAS,aAAa,CAAC,OAAO,KAAK;IAE/B,aAAa;IAEb;;OAEG;IACH,OAAO,SAFI,OAAO,SAAS,EAAE,MAAM,GAAG;QAAC,IAAI,EAAE,mBAAmB,GAAG;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAC,CAAA;KAAC;QAQ/E,0CAA0C;QAC1C,QAAQ,MADI,OAAO,SAAS,EAAE,IAAI;;EAOzC;AAGD,QAAA,MAAM,aAAa,sBAAgB,CAAC;AAEpC,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type cssnanoUtils from 'cssnano-utils';
|
|
2
|
+
export type Tokens = Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens'];
|
|
3
|
+
/** @param {boolean} legacy @param {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>} structure @param {{start:number,end:number,text:string}[]} changes @return {boolean} */
|
|
4
|
+
export default function minifyMediaAll(legacy: boolean, structure: Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>, changes: {
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
text: string;
|
|
8
|
+
}[]): boolean;
|
|
9
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/lib/media.js"],"names":[],"mappings":"AAOI,OAAQ,KAAA,YAAY,MAAM,eAAe,CAAA;AACzC,YAAwF,MAAM,GAApF,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAQ;AA6DlG,+LAA+L;AAC/L,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,MAAM,EADjC,OACiC,EAAE,SAAS,EADpB,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,cAAc,CAAC,EAAE,SAAS,CAC7C,EAAE,OAAO,EADyD;IAAC,KAAK,EAAC,MAAM,CAAC;IAAA,GAAG,EAAC,MAAM,CAAC;IAAA,IAAI,EAAC,MAAM,CAAA;CAAC,EAC9F,GADmH,OAAO,CAgB1L"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import cssnanoUtils from 'cssnano-utils';
|
|
2
|
+
declare const TokenType: typeof import("@csstools/css-tokenizer").TokenType;
|
|
3
|
+
declare const decoded: typeof cssnanoUtils.decoded;
|
|
4
|
+
declare const tokenEnd: typeof cssnanoUtils.tokenEnd;
|
|
5
|
+
export type Tokens = Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens'];
|
|
6
|
+
/** @typedef {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens']} Tokens */
|
|
7
|
+
export { TokenType, decoded, tokenEnd };
|
|
8
|
+
/**
|
|
9
|
+
* Reports whether a value ends in a backslash that begins an escape
|
|
10
|
+
* sequence, as opposed to a backslash that is itself escaped.
|
|
11
|
+
* @param {string} value
|
|
12
|
+
* @return {boolean}
|
|
13
|
+
*/
|
|
14
|
+
export declare function endsWithEscapingBackslash(value: string): boolean;
|
|
15
|
+
export declare const openingTypes: Set<import("@csstools/css-tokenizer").TokenType>;
|
|
16
|
+
export declare const closingTypes: Set<import("@csstools/css-tokenizer").TokenType>;
|
|
17
|
+
export declare const calcProductEndTypes: Set<import("@csstools/css-tokenizer").TokenType>;
|
|
18
|
+
export declare const calcProductStartTypes: Set<import("@csstools/css-tokenizer").TokenType>;
|
|
19
|
+
export declare const mathFunctions: Set<string>;
|
|
20
|
+
export declare const whitespaceInsensitiveFunctions: Set<string>;
|
|
21
|
+
export declare const aspectRatioFeatures: Set<string>;
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} left
|
|
24
|
+
* @param {string} right
|
|
25
|
+
* @return {[string, string] | undefined}
|
|
26
|
+
*/
|
|
27
|
+
export declare function aspectRatio(left: string, right: string): [string, string] | undefined;
|
|
28
|
+
/** @param {Tokens} input @param {number} index @param {number} step @return {number} */
|
|
29
|
+
export declare function significantIndex(input: Tokens, index: number, step: number): number;
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} source
|
|
32
|
+
* @param {{start:number,end:number}[]} segments
|
|
33
|
+
* @param {{start:number,end:number,text:string}[]} edits
|
|
34
|
+
* @return {string[]}
|
|
35
|
+
*/
|
|
36
|
+
export declare function serializeSegments(source: string, segments: {
|
|
37
|
+
start: number;
|
|
38
|
+
end: number;
|
|
39
|
+
}[], edits: {
|
|
40
|
+
start: number;
|
|
41
|
+
end: number;
|
|
42
|
+
text: string;
|
|
43
|
+
}[]): string[];
|
|
44
|
+
//# sourceMappingURL=token-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-utils.d.ts","sourceRoot":"","sources":["../../src/lib/token-utils.js"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,QAAA,MAAQ,SAAS,oDAAiB,CAAC;AACnC,QAAA,MAAM,OAAO,EAAc,OAAO,YAAY,CAAC,OAE9C,CAAC;AACF,QAAA,MAAM,QAAQ,EAAc,OAAO,YAAY,CAAC,QAE/C,CAAC;AAEE,YAAwF,MAAM,GAApF,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAQ;AAAlG,qGAAqG;AAErG,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAExC;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAHpC,MAGoC,GAFnC,OAAO,CAUlB;AAED,eAAO,MAAM,YAAY,kDAKvB,CAAC;AACH,eAAO,MAAM,YAAY,kDAIvB,CAAC;AACH,eAAO,MAAM,mBAAmB,kDAM9B,CAAC;AACH,eAAO,MAAM,qBAAqB,kDAOhC,CAAC;AACH,eAAO,MAAM,aAAa,aAA6B,CAAC;AACxD,eAAO,MAAM,8BAA8B,aAAwB,CAAC;AACpE,eAAO,MAAM,mBAAmB,aAO9B,CAAC;AA+BH;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAJrB,MAIqB,EAAE,KAAK,EAH5B,MAG4B,GAF3B,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAcvC;AAED,wFAAwF;AACxF,wBAAgB,gBAAgB,CAAC,KAAK,EAD1B,MAC0B,EAAE,KAAK,EADX,MACW,EAAE,IAAI,EADK,MACL,GAD2B,MAAM,CAWnF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAL7B,MAK6B,EAAE,QAAQ,EAJvC;IAAC,KAAK,EAAC,MAAM,CAAC;IAAA,GAAG,EAAC,MAAM,CAAA;CAAC,EAIc,EAAE,KAAK,EAH9C;IAAC,KAAK,EAAC,MAAM,CAAC;IAAA,GAAG,EAAC,MAAM,CAAC;IAAA,IAAI,EAAC,MAAM,CAAA;CAAC,EAGS,GAF7C,MAAM,EAAE,CA+CnB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import cssnanoUtils from 'cssnano-utils';
|
|
2
|
+
declare const TokenType: typeof import("@csstools/css-tokenizer").TokenType;
|
|
3
|
+
declare const decoded: typeof cssnanoUtils.decoded;
|
|
4
|
+
declare const tokenEnd: typeof cssnanoUtils.tokenEnd;
|
|
5
|
+
export type Tokens = Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens'];
|
|
6
|
+
/** @typedef {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens']} Tokens */
|
|
7
|
+
export { TokenType, decoded, tokenEnd };
|
|
8
|
+
/**
|
|
9
|
+
* Reports whether a value ends in a backslash that begins an escape
|
|
10
|
+
* sequence, as opposed to a backslash that is itself escaped.
|
|
11
|
+
* @param {string} value
|
|
12
|
+
* @return {boolean}
|
|
13
|
+
*/
|
|
14
|
+
export declare function endsWithEscapingBackslash(value: string): boolean;
|
|
15
|
+
export declare const openingTypes: Set<import("@csstools/css-tokenizer").TokenType>;
|
|
16
|
+
export declare const closingTypes: Set<import("@csstools/css-tokenizer").TokenType>;
|
|
17
|
+
export declare const calcProductEndTypes: Set<import("@csstools/css-tokenizer").TokenType>;
|
|
18
|
+
export declare const calcProductStartTypes: Set<import("@csstools/css-tokenizer").TokenType>;
|
|
19
|
+
export declare const mathFunctions: Set<string>;
|
|
20
|
+
export declare const whitespaceInsensitiveFunctions: Set<string>;
|
|
21
|
+
export declare const aspectRatioFeatures: Set<string>;
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} left
|
|
24
|
+
* @param {string} right
|
|
25
|
+
* @return {[string, string] | undefined}
|
|
26
|
+
*/
|
|
27
|
+
export declare function aspectRatio(left: string, right: string): [string, string] | undefined;
|
|
28
|
+
/** @param {Tokens} input @param {number} index @param {number} step @return {number} */
|
|
29
|
+
export declare function significantIndex(input: Tokens, index: number, step: number): number;
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} source
|
|
32
|
+
* @param {{start:number,end:number}[]} segments
|
|
33
|
+
* @param {{start:number,end:number,text:string}[]} edits
|
|
34
|
+
* @return {string[]}
|
|
35
|
+
*/
|
|
36
|
+
export declare function serializeSegments(source: string, segments: {
|
|
37
|
+
start: number;
|
|
38
|
+
end: number;
|
|
39
|
+
}[], edits: {
|
|
40
|
+
start: number;
|
|
41
|
+
end: number;
|
|
42
|
+
text: string;
|
|
43
|
+
}[]): string[];
|
|
44
|
+
//# sourceMappingURL=tokenUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenUtils.d.ts","sourceRoot":"","sources":["../../src/lib/tokenUtils.js"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,QAAA,MAAQ,SAAS,oDAAiB,CAAC;AACnC,QAAA,MAAM,OAAO,EAAc,OAAO,YAAY,CAAC,OAE9C,CAAC;AACF,QAAA,MAAM,QAAQ,EAAc,OAAO,YAAY,CAAC,QAE/C,CAAC;AAEE,YAAwF,MAAM,GAApF,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAQ;AAAlG,qGAAqG;AAErG,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAExC;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAHpC,MAGoC,GAFnC,OAAO,CAUlB;AAED,eAAO,MAAM,YAAY,kDAKvB,CAAC;AACH,eAAO,MAAM,YAAY,kDAIvB,CAAC;AACH,eAAO,MAAM,mBAAmB,kDAM9B,CAAC;AACH,eAAO,MAAM,qBAAqB,kDAOhC,CAAC;AACH,eAAO,MAAM,aAAa,aAA6B,CAAC;AACxD,eAAO,MAAM,8BAA8B,aAAwB,CAAC;AACpE,eAAO,MAAM,mBAAmB,aAO9B,CAAC;AA+BH;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAJrB,MAIqB,EAAE,KAAK,EAH5B,MAG4B,GAF3B,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAcvC;AAED,wFAAwF;AACxF,wBAAgB,gBAAgB,CAAC,KAAK,EAD1B,MAC0B,EAAE,KAAK,EADX,MACW,EAAE,IAAI,EADK,MACL,GAD2B,MAAM,CAWnF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAL7B,MAK6B,EAAE,QAAQ,EAJvC;IAAC,KAAK,EAAC,MAAM,CAAC;IAAA,GAAG,EAAC,MAAM,CAAA;CAAC,EAIc,EAAE,KAAK,EAH9C;IAAC,KAAK,EAAC,MAAM,CAAC;IAAA,GAAG,EAAC,MAAM,CAAC;IAAA,IAAI,EAAC,MAAM,CAAA;CAAC,EAGS,GAF7C,MAAM,EAAE,CA+CnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/lib/transform.js"],"names":[],"mappings":"AAgBA;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,MAAM,EAJ7B,OAI6B,EAAE,IAAI,EAHnC,OAAO,SAAS,EAAE,MAGiB,GAFlC,IAAI,CAgDf"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import cssnanoUtils from 'cssnano-utils';
|
|
2
|
+
export type Tokens = Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens'];
|
|
3
|
+
/** @typedef {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>['tokens']} Tokens */
|
|
4
|
+
/** @param {ReturnType<typeof cssnanoUtils.balancedTokens>} structure @return {(number|undefined)[]} */
|
|
5
|
+
export declare function parentIndexes(structure: ReturnType<typeof cssnanoUtils.balancedTokens>): (number | undefined)[];
|
|
6
|
+
/** @param {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>} structure @param {(number|undefined)[]} parents @param {{start:number,end:number,text:string}[]} changes @return {void} */
|
|
7
|
+
export declare function minifyWhitespace(structure: Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>, parents: (number | undefined)[], changes: {
|
|
8
|
+
start: number;
|
|
9
|
+
end: number;
|
|
10
|
+
text: string;
|
|
11
|
+
}[]): void;
|
|
12
|
+
/** @param {boolean} supports @param {Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>} structure @param {(number|undefined)[]} parents @param {{start:number,end:number,text:string}[]} changes @return {void} */
|
|
13
|
+
export declare function minifyAspectRatios(supports: boolean, structure: Exclude<ReturnType<typeof cssnanoUtils.balancedTokens>, undefined>, parents: (number | undefined)[], changes: {
|
|
14
|
+
start: number;
|
|
15
|
+
end: number;
|
|
16
|
+
text: string;
|
|
17
|
+
}[]): void;
|
|
18
|
+
//# sourceMappingURL=whitespace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whitespace.d.ts","sourceRoot":"","sources":["../../src/lib/whitespace.js"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAiBrC,YAAwF,MAAM,GAApF,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAQ;AAAlG,qGAAqG;AAErG,uGAAuG;AACvG,wBAAgB,aAAa,CAAC,SAAS,EAD3B,UAAU,CAAC,OAAO,YAAY,CAAC,cAAc,CAClB,GADwC,CAAC,MAAM,GAAC,SAAS,CAAC,EAAE,CAYlG;AAqHD,0MAA0M;AAC1M,wBAAgB,gBAAgB,CAAC,SAAS,EAD9B,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,cAAc,CAAC,EAAE,SAAS,CACnC,EAAE,OAAO,EAD+C,CAAC,MAAM,GAAC,SAAS,CAAC,EACjE,EAAE,OAAO,EAD4E;IAAC,KAAK,EAAC,MAAM,CAAC;IAAA,GAAG,EAAC,MAAM,CAAC;IAAA,IAAI,EAAC,MAAM,CAAA;CAAC,EACjH,GADsI,IAAI,CAgBrM;AAYD,oOAAoO;AACpO,wBAAgB,kBAAkB,CAAC,QAAQ,EAD/B,OAC+B,EAAE,SAAS,EADhB,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,cAAc,CAAC,EAAE,SAAS,CACjD,EAAE,OAAO,EAD6D,CAAC,MAAM,GAAC,SAAS,CAAC,EAC/E,EAAE,OAAO,EAD0F;IAAC,KAAK,EAAC,MAAM,CAAC;IAAA,GAAG,EAAC,MAAM,CAAC;IAAA,IAAI,EAAC,MAAM,CAAA;CAAC,EAC/H,GADoJ,IAAI,CAoD/N"}
|