@tbela99/css-parser 0.0.1-rc5 → 0.0.1-rc7
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 +59 -1
- package/dist/config.json.js +49 -0
- package/dist/index-umd-web.js +2527 -2199
- package/dist/index.cjs +2527 -2199
- package/dist/index.d.ts +36 -26
- package/dist/lib/ast/expand.js +159 -0
- package/dist/lib/ast/minify.js +139 -95
- package/dist/lib/ast/walk.js +12 -7
- package/dist/lib/parser/declaration/list.js +1 -1
- package/dist/lib/parser/declaration/map.js +8 -0
- package/dist/lib/parser/parse.js +38 -24
- package/dist/lib/parser/tokenize.js +142 -76
- package/dist/lib/parser/utils/syntax.js +10 -17
- package/dist/lib/renderer/render.js +18 -25
- package/dist/lib/transform.js +4 -1
- package/dist/node/index.js +5 -4
- package/dist/web/index.js +5 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -477,9 +477,9 @@ interface BorderRadius {
|
|
|
477
477
|
interface ErrorDescription {
|
|
478
478
|
|
|
479
479
|
// drop rule or declaration | fix rule or declaration
|
|
480
|
-
action: 'drop';
|
|
480
|
+
action: 'drop' | 'ignore';
|
|
481
481
|
message: string;
|
|
482
|
-
location
|
|
482
|
+
location?: {
|
|
483
483
|
src: string,
|
|
484
484
|
lin: number,
|
|
485
485
|
col: number;
|
|
@@ -505,6 +505,7 @@ interface ParserOptions {
|
|
|
505
505
|
interface RenderOptions {
|
|
506
506
|
|
|
507
507
|
minify?: boolean;
|
|
508
|
+
expandNestingRules?: boolean;
|
|
508
509
|
preserveLicense?: boolean;
|
|
509
510
|
indent?: string;
|
|
510
511
|
newLine?: string;
|
|
@@ -529,6 +530,7 @@ interface ParseResult {
|
|
|
529
530
|
|
|
530
531
|
interface RenderResult {
|
|
531
532
|
code: string ;
|
|
533
|
+
errors: ErrorDescription[];
|
|
532
534
|
stats: {
|
|
533
535
|
total: string;
|
|
534
536
|
}
|
|
@@ -577,7 +579,7 @@ interface Node {
|
|
|
577
579
|
|
|
578
580
|
interface AstComment extends Node {
|
|
579
581
|
|
|
580
|
-
typ: 'Comment',
|
|
582
|
+
typ: 'Comment' | 'CDOCOMM',
|
|
581
583
|
val: string;
|
|
582
584
|
}
|
|
583
585
|
interface AstDeclaration extends Node {
|
|
@@ -630,6 +632,35 @@ type AstNode =
|
|
|
630
632
|
| AstRule
|
|
631
633
|
| AstDeclaration;
|
|
632
634
|
|
|
635
|
+
declare const combinators: string[];
|
|
636
|
+
declare function minify(ast: AstNode, options?: ParserOptions, recursive?: boolean, errors?: ErrorDescription[], nestingContent?: boolean): AstNode;
|
|
637
|
+
declare function reduceSelector(selector: string[][]): {
|
|
638
|
+
match: boolean;
|
|
639
|
+
optimized: string[];
|
|
640
|
+
selector: string[][];
|
|
641
|
+
reducible: boolean;
|
|
642
|
+
} | null;
|
|
643
|
+
declare function hasDeclaration(node: AstRule): boolean;
|
|
644
|
+
declare function minifyRule(ast: AstRule | AstAtRule): AstRule | AstAtRule;
|
|
645
|
+
declare function splitRule(buffer: string): string[][];
|
|
646
|
+
|
|
647
|
+
declare function walk(node: AstNode, parent?: AstRuleList, root?: AstRuleList): Generator<{
|
|
648
|
+
node: AstNode;
|
|
649
|
+
parent?: AstRuleList;
|
|
650
|
+
root?: AstRuleList;
|
|
651
|
+
}>;
|
|
652
|
+
declare function walkValues(values: Token[], parent?: Token): Generator<{
|
|
653
|
+
value: Token;
|
|
654
|
+
parent: Token | null;
|
|
655
|
+
}>;
|
|
656
|
+
|
|
657
|
+
declare function expand(ast: AstNode): AstNode;
|
|
658
|
+
declare function replaceCompound(input: string, replace: string): string;
|
|
659
|
+
|
|
660
|
+
declare const colorsFunc: string[];
|
|
661
|
+
declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
|
|
662
|
+
declare function renderToken(token: Token, options?: RenderOptions, reducer?: (acc: string, curr: Token) => string, errors?: ErrorDescription[]): string;
|
|
663
|
+
|
|
633
664
|
declare const urlTokenMatcher: RegExp;
|
|
634
665
|
declare function parseString(src: string, options?: {
|
|
635
666
|
location: boolean;
|
|
@@ -647,6 +678,7 @@ declare function isIdentStart(codepoint: number): boolean;
|
|
|
647
678
|
declare function isDigit(codepoint: number): boolean;
|
|
648
679
|
declare function isIdentCodepoint(codepoint: number): boolean;
|
|
649
680
|
declare function isIdent(name: string): boolean;
|
|
681
|
+
declare function isNonPrintable(codepoint: number): boolean;
|
|
650
682
|
declare function isPseudo(name: string): boolean;
|
|
651
683
|
declare function isHash(name: string): boolean;
|
|
652
684
|
declare function isNumber(name: string): boolean;
|
|
@@ -654,7 +686,6 @@ declare function isDimension(name: string): boolean;
|
|
|
654
686
|
declare function isPercentage(name: string): boolean;
|
|
655
687
|
declare function parseDimension(name: string): DimensionToken | LengthToken | AngleToken;
|
|
656
688
|
declare function isHexColor(name: string): boolean;
|
|
657
|
-
declare function isHexDigit(name: string): boolean;
|
|
658
689
|
declare function isFunction(name: string): boolean;
|
|
659
690
|
declare function isAtKeyword(name: string): boolean;
|
|
660
691
|
declare function isNewLine(codepoint: number): boolean;
|
|
@@ -665,27 +696,6 @@ declare const getConfig: () => PropertiesConfig;
|
|
|
665
696
|
declare const funcList: string[];
|
|
666
697
|
declare function matchType(val: Token, properties: PropertyMapType): boolean;
|
|
667
698
|
|
|
668
|
-
declare const colorsFunc: string[];
|
|
669
|
-
declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
|
|
670
|
-
declare function renderToken(token: Token, options?: RenderOptions, reducer?: (acc: string, curr: Token) => string): string;
|
|
671
|
-
|
|
672
|
-
declare const combinators: string[];
|
|
673
|
-
declare function minify(ast: AstNode, options?: ParserOptions, recursive?: boolean): AstNode;
|
|
674
|
-
declare function reduceSelector(selector: string[][]): {
|
|
675
|
-
match: boolean;
|
|
676
|
-
optimized: string[];
|
|
677
|
-
selector: string[][];
|
|
678
|
-
reducible: boolean;
|
|
679
|
-
} | null;
|
|
680
|
-
declare function hasDeclaration(node: AstRule): boolean;
|
|
681
|
-
declare function minifyRule(ast: AstRule | AstAtRule): AstRule | AstAtRule;
|
|
682
|
-
|
|
683
|
-
declare function walk(node: AstNode): Generator<{
|
|
684
|
-
node: AstNode;
|
|
685
|
-
parent?: AstRuleList;
|
|
686
|
-
root?: AstRuleList;
|
|
687
|
-
}>;
|
|
688
|
-
|
|
689
699
|
declare function load(url: string, currentFile: string): Promise<string>;
|
|
690
700
|
|
|
691
701
|
declare const matchUrl: RegExp;
|
|
@@ -698,4 +708,4 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
|
|
|
698
708
|
declare function parse(iterator: string, opt?: ParserOptions): Promise<ParseResult>;
|
|
699
709
|
declare function transform(css: string, options?: TransformOptions): Promise<TransformResult>;
|
|
700
710
|
|
|
701
|
-
export { colorsFunc, combinators, dirname, funcList, getConfig, hasDeclaration, isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor,
|
|
711
|
+
export { colorsFunc, combinators, dirname, expand, funcList, getConfig, hasDeclaration, isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, load, matchType, matchUrl, minify, minifyRule, parse, parseDimension, parseString, reduceSelector, render, renderToken, replaceCompound, resolve, splitRule, tokenize, transform, urlTokenMatcher, walk, walkValues };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { splitRule, combinators } from './minify.js';
|
|
2
|
+
import { parseString } from '../parser/parse.js';
|
|
3
|
+
import { renderToken } from '../renderer/render.js';
|
|
4
|
+
import '../renderer/utils/color.js';
|
|
5
|
+
import { walkValues } from './walk.js';
|
|
6
|
+
|
|
7
|
+
function expand(ast) {
|
|
8
|
+
//
|
|
9
|
+
if (!['Rule', 'StyleSheet', 'AtRule'].includes(ast.typ)) {
|
|
10
|
+
return ast;
|
|
11
|
+
}
|
|
12
|
+
if ('Rule' == ast.typ) {
|
|
13
|
+
return {
|
|
14
|
+
typ: 'StyleSheet',
|
|
15
|
+
chi: expandRule(ast)
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (!('chi' in ast)) {
|
|
19
|
+
return { ...ast };
|
|
20
|
+
}
|
|
21
|
+
const result = { ...ast, chi: [] };
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
for (let i = 0; i < ast.chi.length; i++) {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
const node = ast.chi[i];
|
|
26
|
+
if (node.typ == 'Rule') {
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
result.chi.push(...expandRule(node));
|
|
29
|
+
// i += expanded.length - 1;
|
|
30
|
+
}
|
|
31
|
+
else if (node.typ == 'AtRule' && 'chi' in node) {
|
|
32
|
+
let hasRule = false;
|
|
33
|
+
let j = node.chi.length;
|
|
34
|
+
while (j--) {
|
|
35
|
+
if (node.chi[j].typ == 'Rule' || node.chi[j].typ == 'AtRule') {
|
|
36
|
+
hasRule = true;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
result.chi.push({ ...(hasRule ? expand(node) : node) });
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
result.chi.push(node);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
function expandRule(node) {
|
|
51
|
+
const ast = { ...node, chi: node.chi.slice() };
|
|
52
|
+
const result = [];
|
|
53
|
+
if (ast.typ == 'Rule') {
|
|
54
|
+
let i = 0;
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
delete ast.raw;
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
delete ast.optimized;
|
|
59
|
+
for (; i < ast.chi.length; i++) {
|
|
60
|
+
if (ast.chi[i].typ == 'Rule') {
|
|
61
|
+
const rule = ast.chi[i];
|
|
62
|
+
if (!rule.sel.includes('&')) {
|
|
63
|
+
const selRule = splitRule(rule.sel);
|
|
64
|
+
selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(ast.sel) : arr.unshift(ast.sel, ' '));
|
|
65
|
+
rule.sel = selRule.reduce((acc, curr) => {
|
|
66
|
+
acc.push(curr.join(''));
|
|
67
|
+
return acc;
|
|
68
|
+
}, []).join(',');
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
rule.sel = replaceCompound(rule.sel, ast.sel);
|
|
72
|
+
}
|
|
73
|
+
delete rule.raw;
|
|
74
|
+
delete rule.optimized;
|
|
75
|
+
ast.chi.splice(i--, 1);
|
|
76
|
+
result.push(...expandRule(rule));
|
|
77
|
+
}
|
|
78
|
+
else if (ast.chi[i].typ == 'AtRule') {
|
|
79
|
+
let astAtRule = ast.chi[i];
|
|
80
|
+
const values = [];
|
|
81
|
+
if (astAtRule.nam == 'scope') {
|
|
82
|
+
if (astAtRule.val.includes('&')) {
|
|
83
|
+
astAtRule.val = replaceCompound(astAtRule.val, ast.sel);
|
|
84
|
+
}
|
|
85
|
+
// @ts-ignore
|
|
86
|
+
astAtRule = expand(astAtRule);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
const clone = { ...ast, chi: astAtRule.chi.slice() };
|
|
91
|
+
// @ts-ignore
|
|
92
|
+
astAtRule.chi.length = 0;
|
|
93
|
+
for (const r of expandRule(clone)) {
|
|
94
|
+
if (r.typ == 'AtRule' && 'chi' in r) {
|
|
95
|
+
if (astAtRule.val !== '' && r.val !== '') {
|
|
96
|
+
if (astAtRule.nam == 'media' && r.nam == 'media') {
|
|
97
|
+
r.val = astAtRule.val + ' and ' + r.val;
|
|
98
|
+
}
|
|
99
|
+
else if (astAtRule.nam == 'layer' && r.nam == 'layer') {
|
|
100
|
+
r.val = astAtRule.val + '.' + r.val;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// @ts-ignore
|
|
104
|
+
values.push(r);
|
|
105
|
+
}
|
|
106
|
+
else if (r.typ == 'Rule') {
|
|
107
|
+
// @ts-ignore
|
|
108
|
+
astAtRule.chi.push(...expandRule(r));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
astAtRule.chi.push(r);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// @ts-ignore
|
|
117
|
+
result.push(...(astAtRule.chi.length > 0 ? [astAtRule].concat(values) : values));
|
|
118
|
+
ast.chi.splice(i--, 1);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// @ts-ignore
|
|
123
|
+
return ast.chi.length > 0 ? [ast].concat(result) : result;
|
|
124
|
+
}
|
|
125
|
+
function replaceCompound(input, replace) {
|
|
126
|
+
const tokens = parseString(input);
|
|
127
|
+
for (const t of walkValues(tokens)) {
|
|
128
|
+
if (t.value.typ == 'Literal') {
|
|
129
|
+
if (t.value.val == '&') {
|
|
130
|
+
t.value.val = replace;
|
|
131
|
+
}
|
|
132
|
+
else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
|
|
133
|
+
t.value.val = replaceCompoundLiteral(t.value.val, replace);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return tokens.reduce((acc, curr) => acc + renderToken(curr), '');
|
|
138
|
+
}
|
|
139
|
+
function replaceCompoundLiteral(selector, replace) {
|
|
140
|
+
const tokens = [''];
|
|
141
|
+
let i = 0;
|
|
142
|
+
for (; i < selector.length; i++) {
|
|
143
|
+
if (selector.charAt(i) == '&') {
|
|
144
|
+
tokens.push('&');
|
|
145
|
+
tokens.push('');
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
tokens[tokens.length - 1] += selector.charAt(i);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return tokens.sort((a, b) => {
|
|
152
|
+
if (a == '&') {
|
|
153
|
+
return 1;
|
|
154
|
+
}
|
|
155
|
+
return b == '&' ? -1 : 0;
|
|
156
|
+
}).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export { expand, replaceCompound };
|
package/dist/lib/ast/minify.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { isIdentStart, isIdent, isFunction
|
|
1
|
+
import { isIdentStart, isWhiteSpace, isIdent, isFunction } from '../parser/utils/syntax.js';
|
|
2
2
|
import { PropertyList } from '../parser/declaration/list.js';
|
|
3
3
|
import { eq } from '../parser/utils/eq.js';
|
|
4
|
-
import { render } from '../renderer/render.js';
|
|
5
|
-
import '../
|
|
4
|
+
import { render, renderToken } from '../renderer/render.js';
|
|
5
|
+
import { parseString } from '../parser/parse.js';
|
|
6
|
+
import { replaceCompound } from './expand.js';
|
|
7
|
+
import { walkValues } from './walk.js';
|
|
6
8
|
|
|
7
9
|
const combinators = ['+', '>', '~'];
|
|
8
10
|
const notEndingWith = ['(', '['].concat(combinators);
|
|
9
|
-
|
|
11
|
+
const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
|
|
12
|
+
function minify(ast, options = {}, recursive = false, errors, nestingContent) {
|
|
10
13
|
function wrapNodes(previous, node, match, ast, i, nodeIndex) {
|
|
11
14
|
// @ts-ignore
|
|
12
15
|
let pSel = match.selector1.reduce(reducer, []).join(',');
|
|
@@ -15,9 +18,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
15
18
|
// @ts-ignore
|
|
16
19
|
const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
|
|
17
20
|
// @ts-ignore
|
|
18
|
-
Object.defineProperty(wrapper, 'raw', {
|
|
19
|
-
enumerable: false,
|
|
20
|
-
writable: true,
|
|
21
|
+
Object.defineProperty(wrapper, 'raw', { ...definedPropertySettings,
|
|
21
22
|
// @ts-ignore
|
|
22
23
|
value: match.match.map(t => t.slice())
|
|
23
24
|
});
|
|
@@ -25,7 +26,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
25
26
|
// @ts-ignore
|
|
26
27
|
wrapper.chi.push(...previous.chi);
|
|
27
28
|
// @ts-ignore
|
|
28
|
-
if ((nSel == '&' || nSel === '')
|
|
29
|
+
if ((nSel == '&' || nSel === '')) {
|
|
29
30
|
// @ts-ignore
|
|
30
31
|
wrapper.chi.push(...node.chi);
|
|
31
32
|
}
|
|
@@ -96,10 +97,10 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
96
97
|
node1 = { ...node1, chi: node1.chi.slice() };
|
|
97
98
|
node2 = { ...node2, chi: node2.chi.slice() };
|
|
98
99
|
if (raw1 != null) {
|
|
99
|
-
Object.defineProperty(node1, 'raw', {
|
|
100
|
+
Object.defineProperty(node1, 'raw', { ...definedPropertySettings, value: raw1 });
|
|
100
101
|
}
|
|
101
102
|
if (raw2 != null) {
|
|
102
|
-
Object.defineProperty(node2, 'raw', {
|
|
103
|
+
Object.defineProperty(node2, 'raw', { ...definedPropertySettings, value: raw2 });
|
|
103
104
|
}
|
|
104
105
|
const intersect = [];
|
|
105
106
|
while (i--) {
|
|
@@ -199,8 +200,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
199
200
|
}
|
|
200
201
|
}
|
|
201
202
|
if (match.length > 1) {
|
|
202
|
-
|
|
203
|
-
console.error({ match, selector1, selector2 });
|
|
203
|
+
errors?.push({ action: 'ignore', message: `minify: unsupported multilevel matching\n${JSON.stringify({ match, selector1, selector2 }, null, 1)}` });
|
|
204
204
|
return null;
|
|
205
205
|
}
|
|
206
206
|
for (const part of match) {
|
|
@@ -298,8 +298,28 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
298
298
|
selector2
|
|
299
299
|
};
|
|
300
300
|
}
|
|
301
|
+
function fixSelector(node) {
|
|
302
|
+
// @ts-ignore
|
|
303
|
+
if (node.sel.includes('&')) {
|
|
304
|
+
const attributes = parseString(node.sel);
|
|
305
|
+
for (const attr of walkValues(attributes)) {
|
|
306
|
+
if (attr.value.typ == 'Pseudo-class-func' && attr.value.val == ':is') {
|
|
307
|
+
let i = attr.value.chi.length;
|
|
308
|
+
while (i--) {
|
|
309
|
+
if (attr.value.chi[i].typ == 'Literal' && attr.value.chi[i].val == '&') {
|
|
310
|
+
attr.value.chi.splice(i, 1);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
301
318
|
// @ts-ignore
|
|
302
319
|
if (('chi' in ast) && ast.chi?.length > 0) {
|
|
320
|
+
if (!nestingContent) {
|
|
321
|
+
nestingContent = options.nestingRules && ast.typ == 'Rule';
|
|
322
|
+
}
|
|
303
323
|
let i = 0;
|
|
304
324
|
let previous;
|
|
305
325
|
let node;
|
|
@@ -314,7 +334,6 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
314
334
|
node = ast.chi[i];
|
|
315
335
|
// @ts-ignore
|
|
316
336
|
if (previous == node) {
|
|
317
|
-
// console.error('idem!');
|
|
318
337
|
// @ts-ignore
|
|
319
338
|
ast.chi.splice(i, 1);
|
|
320
339
|
i--;
|
|
@@ -330,7 +349,6 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
330
349
|
i--;
|
|
331
350
|
continue;
|
|
332
351
|
}
|
|
333
|
-
// console.debug({previous, node});
|
|
334
352
|
// @ts-ignore
|
|
335
353
|
if (previous?.typ == 'AtRule' &&
|
|
336
354
|
previous.nam == node.nam &&
|
|
@@ -350,7 +368,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
350
368
|
minifyRule(node);
|
|
351
369
|
}
|
|
352
370
|
else {
|
|
353
|
-
minify(node, options, recursive);
|
|
371
|
+
minify(node, options, recursive, errors, nestingContent);
|
|
354
372
|
}
|
|
355
373
|
previous = node;
|
|
356
374
|
nodeIndex = i;
|
|
@@ -404,7 +422,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
404
422
|
nodeIndex = --i;
|
|
405
423
|
// @ts-ignore
|
|
406
424
|
previous = ast.chi[nodeIndex];
|
|
407
|
-
minify(wrapper, options, recursive);
|
|
425
|
+
minify(wrapper, options, recursive, errors, nestingContent);
|
|
408
426
|
continue;
|
|
409
427
|
}
|
|
410
428
|
// @ts-ignore
|
|
@@ -417,8 +435,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
417
435
|
wrapper = { ...node, chi: [], sel: node.optimized.optimized[0] };
|
|
418
436
|
// @ts-ignore
|
|
419
437
|
Object.defineProperty(wrapper, 'raw', {
|
|
420
|
-
|
|
421
|
-
writable: true,
|
|
438
|
+
...definedPropertySettings,
|
|
422
439
|
// @ts-ignore
|
|
423
440
|
value: [[node.optimized.optimized[0]]]
|
|
424
441
|
});
|
|
@@ -438,7 +455,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
438
455
|
let wrap = true;
|
|
439
456
|
// @ts-ignore
|
|
440
457
|
const selector = node.optimized.selector.reduce((acc, curr) => {
|
|
441
|
-
if (curr[0] == '&') {
|
|
458
|
+
if (curr[0] == '&' && curr.length > 1) {
|
|
442
459
|
if (curr[1] == ' ') {
|
|
443
460
|
curr.splice(0, 2);
|
|
444
461
|
}
|
|
@@ -462,7 +479,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
462
479
|
if (!wrap) {
|
|
463
480
|
wrap = selector.some(s => s[0] != '&');
|
|
464
481
|
}
|
|
465
|
-
|
|
482
|
+
let rule = selector.map(s => {
|
|
466
483
|
if (s[0] == '&') {
|
|
467
484
|
// @ts-ignore
|
|
468
485
|
s[0] = node.optimized.optimized[0];
|
|
@@ -470,89 +487,119 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
470
487
|
return s.join('');
|
|
471
488
|
}).join(',');
|
|
472
489
|
// @ts-ignore
|
|
473
|
-
|
|
490
|
+
let sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
|
|
491
|
+
if (rule.includes('&')) {
|
|
492
|
+
// @ts-ignore
|
|
493
|
+
rule = replaceCompound(rule, node.optimized.optimized[0]);
|
|
494
|
+
}
|
|
495
|
+
if (sel.length < node.sel.length) {
|
|
496
|
+
node.sel = sel;
|
|
497
|
+
}
|
|
474
498
|
}
|
|
475
499
|
}
|
|
476
500
|
// @ts-ignore
|
|
477
|
-
if (previous != null
|
|
501
|
+
if (previous != null) {
|
|
478
502
|
// @ts-ignore
|
|
479
|
-
if (previous
|
|
480
|
-
let shouldMerge = true;
|
|
503
|
+
if ('chi' in previous && ('chi' in node)) {
|
|
481
504
|
// @ts-ignore
|
|
482
|
-
|
|
483
|
-
|
|
505
|
+
if (previous.typ == node.typ) {
|
|
506
|
+
let shouldMerge = true;
|
|
484
507
|
// @ts-ignore
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
// @ts-ignore
|
|
489
|
-
shouldMerge = previous.chi[k].typ == 'Declaration';
|
|
490
|
-
break;
|
|
491
|
-
}
|
|
492
|
-
if (shouldMerge) {
|
|
493
|
-
// @ts-ignore
|
|
494
|
-
if ((node.typ == 'Rule' && node.sel == previous.sel) ||
|
|
508
|
+
let k = previous.chi.length;
|
|
509
|
+
while (k-- > 0) {
|
|
495
510
|
// @ts-ignore
|
|
496
|
-
(
|
|
497
|
-
|
|
498
|
-
|
|
511
|
+
if (previous.chi[k].typ == 'Comment') {
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
499
514
|
// @ts-ignore
|
|
500
|
-
|
|
515
|
+
shouldMerge = previous.chi[k].typ == 'Declaration';
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
if (shouldMerge) {
|
|
501
519
|
// @ts-ignore
|
|
502
|
-
if (
|
|
520
|
+
if ((node.typ == 'Rule' && node.sel == previous.sel) ||
|
|
503
521
|
// @ts-ignore
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
nodeIndex = i;
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
else if (node.typ == 'Rule' && previous?.typ == 'Rule') {
|
|
515
|
-
const intersect = diff(previous, node, options);
|
|
516
|
-
if (intersect != null) {
|
|
517
|
-
if (intersect.node1.chi.length == 0) {
|
|
518
|
-
// @ts-ignore
|
|
519
|
-
ast.chi.splice(i--, 1);
|
|
522
|
+
(node.typ == 'AtRule') && node.val != 'font-face' && node.val == previous.val) {
|
|
523
|
+
// @ts-ignore
|
|
524
|
+
node.chi.unshift(...previous.chi);
|
|
525
|
+
// @ts-ignore
|
|
526
|
+
ast.chi.splice(nodeIndex, 1);
|
|
527
|
+
// @ts-ignore
|
|
528
|
+
if (hasDeclaration(node)) {
|
|
520
529
|
// @ts-ignore
|
|
521
|
-
node
|
|
530
|
+
minifyRule(node);
|
|
522
531
|
}
|
|
523
532
|
else {
|
|
524
|
-
|
|
525
|
-
ast.chi.splice(i, 1, intersect.node1);
|
|
526
|
-
node = intersect.node1;
|
|
527
|
-
}
|
|
528
|
-
if (intersect.node2.chi.length == 0) {
|
|
529
|
-
// @ts-ignore
|
|
530
|
-
ast.chi.splice(nodeIndex, 1, intersect.result);
|
|
531
|
-
previous = intersect.result;
|
|
533
|
+
minify(node, options, recursive, errors, nestingContent);
|
|
532
534
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
535
|
+
i--;
|
|
536
|
+
previous = node;
|
|
537
|
+
nodeIndex = i;
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
else if (node.typ == 'Rule' && previous?.typ == 'Rule') {
|
|
541
|
+
const intersect = diff(previous, node, options);
|
|
542
|
+
if (intersect != null) {
|
|
543
|
+
if (intersect.node1.chi.length == 0) {
|
|
544
|
+
// @ts-ignore
|
|
545
|
+
ast.chi.splice(i--, 1);
|
|
546
|
+
// @ts-ignore
|
|
547
|
+
node = ast.chi[i];
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
// @ts-ignore
|
|
551
|
+
ast.chi.splice(i, 1, intersect.node1);
|
|
552
|
+
node = intersect.node1;
|
|
553
|
+
}
|
|
554
|
+
if (intersect.node2.chi.length == 0) {
|
|
555
|
+
// @ts-ignore
|
|
556
|
+
ast.chi.splice(nodeIndex, 1, intersect.result);
|
|
557
|
+
previous = intersect.result;
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
// @ts-ignore
|
|
561
|
+
ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
|
|
562
|
+
previous = intersect.result;
|
|
563
|
+
// @ts-ignore
|
|
564
|
+
i = nodeIndex;
|
|
565
|
+
}
|
|
539
566
|
}
|
|
540
567
|
}
|
|
541
568
|
}
|
|
542
569
|
}
|
|
543
|
-
}
|
|
544
|
-
// @ts-ignore
|
|
545
|
-
if (recursive && previous != node) {
|
|
546
570
|
// @ts-ignore
|
|
547
|
-
if (
|
|
571
|
+
if (recursive && previous != node) {
|
|
548
572
|
// @ts-ignore
|
|
549
|
-
|
|
573
|
+
if (hasDeclaration(previous)) {
|
|
574
|
+
// @ts-ignore
|
|
575
|
+
minifyRule(previous);
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
minify(previous, options, recursive, errors, nestingContent);
|
|
579
|
+
}
|
|
550
580
|
}
|
|
551
|
-
|
|
552
|
-
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
if ('chi' in previous) {
|
|
584
|
+
// @ts-ignore
|
|
585
|
+
if (hasDeclaration(previous)) {
|
|
586
|
+
// @ts-ignore
|
|
587
|
+
minifyRule(previous);
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
minify(previous, options, recursive, errors, nestingContent);
|
|
591
|
+
}
|
|
553
592
|
}
|
|
554
593
|
}
|
|
555
594
|
}
|
|
595
|
+
if (!nestingContent &&
|
|
596
|
+
// @ts-ignore
|
|
597
|
+
previous != null &&
|
|
598
|
+
// previous.optimized != null &&
|
|
599
|
+
previous.typ == 'Rule' &&
|
|
600
|
+
previous.sel.includes('&')) {
|
|
601
|
+
fixSelector(previous);
|
|
602
|
+
}
|
|
556
603
|
previous = node;
|
|
557
604
|
nodeIndex = i;
|
|
558
605
|
}
|
|
@@ -565,10 +612,18 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
565
612
|
else {
|
|
566
613
|
// @ts-ignore
|
|
567
614
|
if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
|
|
568
|
-
minify(node, options, recursive);
|
|
615
|
+
minify(node, options, recursive, errors, nestingContent);
|
|
569
616
|
}
|
|
570
617
|
}
|
|
571
618
|
}
|
|
619
|
+
if (!nestingContent &&
|
|
620
|
+
// @ts-ignore
|
|
621
|
+
node != null &&
|
|
622
|
+
// previous.optimized != null &&
|
|
623
|
+
node.typ == 'Rule' &&
|
|
624
|
+
node.sel.includes('&')) {
|
|
625
|
+
fixSelector(node);
|
|
626
|
+
}
|
|
572
627
|
}
|
|
573
628
|
return ast;
|
|
574
629
|
}
|
|
@@ -651,16 +706,6 @@ function reduceSelector(selector) {
|
|
|
651
706
|
reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
|
|
652
707
|
};
|
|
653
708
|
}
|
|
654
|
-
function hasOnlyDeclarations(node) {
|
|
655
|
-
let k = node.chi.length;
|
|
656
|
-
while (k--) {
|
|
657
|
-
if (node.chi[k].typ == 'Comment') {
|
|
658
|
-
continue;
|
|
659
|
-
}
|
|
660
|
-
return node.chi[k].typ == 'Declaration';
|
|
661
|
-
}
|
|
662
|
-
return true;
|
|
663
|
-
}
|
|
664
709
|
function hasDeclaration(node) {
|
|
665
710
|
// @ts-ignore
|
|
666
711
|
for (let i = 0; i < node.chi?.length; i++) {
|
|
@@ -786,7 +831,7 @@ function splitRule(buffer) {
|
|
|
786
831
|
}
|
|
787
832
|
function reduceRuleSelector(node) {
|
|
788
833
|
if (node.raw == null) {
|
|
789
|
-
Object.defineProperty(node, 'raw', {
|
|
834
|
+
Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: splitRule(node.sel) });
|
|
790
835
|
}
|
|
791
836
|
// @ts-ignore
|
|
792
837
|
// if (node.raw != null) {
|
|
@@ -796,7 +841,7 @@ function reduceRuleSelector(node) {
|
|
|
796
841
|
return acc;
|
|
797
842
|
}, []));
|
|
798
843
|
if (optimized != null) {
|
|
799
|
-
Object.defineProperty(node, 'optimized', {
|
|
844
|
+
Object.defineProperty(node, 'optimized', { ...definedPropertySettings, value: optimized });
|
|
800
845
|
}
|
|
801
846
|
if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
|
|
802
847
|
const raw = [
|
|
@@ -814,10 +859,9 @@ function reduceRuleSelector(node) {
|
|
|
814
859
|
if (sel.length < node.sel.length) {
|
|
815
860
|
node.sel = sel;
|
|
816
861
|
// node.raw = raw;
|
|
817
|
-
Object.defineProperty(node, 'raw', {
|
|
862
|
+
Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: raw });
|
|
818
863
|
}
|
|
819
864
|
}
|
|
820
|
-
// }
|
|
821
865
|
}
|
|
822
866
|
|
|
823
|
-
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector };
|
|
867
|
+
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector, splitRule };
|