Skip to content

Commit 213b1f8

Browse files
committed
invalid rules generated #14
1 parent 711a7ee commit 213b1f8

30 files changed

+145173
-470
lines changed

dist/index-umd-web.js

Lines changed: 230 additions & 189 deletions
Large diffs are not rendered by default.

dist/index.cjs

Lines changed: 230 additions & 189 deletions
Large diffs are not rendered by default.

dist/index.d.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ type AstNode =
633633
| AstDeclaration;
634634

635635
declare const combinators: string[];
636-
declare function minify(ast: AstNode, options?: ParserOptions, recursive?: boolean, errors?: ErrorDescription[]): AstNode;
636+
declare function minify(ast: AstNode, options?: ParserOptions, recursive?: boolean, errors?: ErrorDescription[], nestingContent?: boolean): AstNode;
637637
declare function reduceSelector(selector: string[][]): {
638638
match: boolean;
639639
optimized: string[];
@@ -644,7 +644,7 @@ declare function hasDeclaration(node: AstRule): boolean;
644644
declare function minifyRule(ast: AstRule | AstAtRule): AstRule | AstAtRule;
645645
declare function splitRule(buffer: string): string[][];
646646

647-
declare function walk(node: AstNode): Generator<{
647+
declare function walk(node: AstNode, parent?: AstRuleList, root?: AstRuleList): Generator<{
648648
node: AstNode;
649649
parent?: AstRuleList;
650650
root?: AstRuleList;
@@ -655,6 +655,7 @@ declare function walkValues(values: Token[], parent?: Token): Generator<{
655655
}>;
656656

657657
declare function expand(ast: AstNode): AstNode;
658+
declare function replaceCompound(input: string, replace: string): string;
658659

659660
declare const colorsFunc: string[];
660661
declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
@@ -707,4 +708,4 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
707708
declare function parse(iterator: string, opt?: ParserOptions): Promise<ParseResult>;
708709
declare function transform(css: string, options?: TransformOptions): Promise<TransformResult>;
709710

710-
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, resolve, splitRule, tokenize, transform, urlTokenMatcher, walk, walkValues };
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 };

dist/lib/ast/expand.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ function expandRule(node) {
6868
}, []).join(',');
6969
}
7070
else {
71-
rule.sel = replaceCompount(rule.sel, ast.sel);
71+
rule.sel = replaceCompound(rule.sel, ast.sel);
7272
}
7373
delete rule.raw;
7474
delete rule.optimized;
@@ -80,7 +80,7 @@ function expandRule(node) {
8080
const values = [];
8181
if (astAtRule.nam == 'scope') {
8282
if (astAtRule.val.includes('&')) {
83-
astAtRule.val = replaceCompount(astAtRule.val, ast.sel);
83+
astAtRule.val = replaceCompound(astAtRule.val, ast.sel);
8484
}
8585
// @ts-ignore
8686
astAtRule = expand(astAtRule);
@@ -122,7 +122,7 @@ function expandRule(node) {
122122
// @ts-ignore
123123
return ast.chi.length > 0 ? [ast].concat(result) : result;
124124
}
125-
function replaceCompount(input, replace) {
125+
function replaceCompound(input, replace) {
126126
const tokens = parseString(input);
127127
for (const t of walkValues(tokens)) {
128128
if (t.value.typ == 'Literal') {
@@ -156,4 +156,4 @@ function replaceCompoundLiteral(selector, replace) {
156156
}).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
157157
}
158158

159-
export { expand };
159+
export { expand, replaceCompound };

dist/lib/ast/minify.js

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { isIdentStart, isWhiteSpace, isIdent, isFunction } from '../parser/utils/syntax.js';
22
import { PropertyList } from '../parser/declaration/list.js';
33
import { eq } from '../parser/utils/eq.js';
4-
import { render } from '../renderer/render.js';
5-
import '../renderer/utils/color.js';
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';
68

79
const combinators = ['+', '>', '~'];
810
const notEndingWith = ['(', '['].concat(combinators);
911
const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
10-
function minify(ast, options = {}, recursive = false, errors) {
12+
function minify(ast, options = {}, recursive = false, errors, nestingContent) {
1113
function wrapNodes(previous, node, match, ast, i, nodeIndex) {
1214
// @ts-ignore
1315
let pSel = match.selector1.reduce(reducer, []).join(',');
@@ -296,8 +298,28 @@ function minify(ast, options = {}, recursive = false, errors) {
296298
selector2
297299
};
298300
}
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+
}
299318
// @ts-ignore
300319
if (('chi' in ast) && ast.chi?.length > 0) {
320+
if (!nestingContent) {
321+
nestingContent = options.nestingRules && ast.typ == 'Rule';
322+
}
301323
let i = 0;
302324
let previous;
303325
let node;
@@ -312,7 +334,6 @@ function minify(ast, options = {}, recursive = false, errors) {
312334
node = ast.chi[i];
313335
// @ts-ignore
314336
if (previous == node) {
315-
// console.error('idem!');
316337
// @ts-ignore
317338
ast.chi.splice(i, 1);
318339
i--;
@@ -328,7 +349,6 @@ function minify(ast, options = {}, recursive = false, errors) {
328349
i--;
329350
continue;
330351
}
331-
// console.debug({previous, node});
332352
// @ts-ignore
333353
if (previous?.typ == 'AtRule' &&
334354
previous.nam == node.nam &&
@@ -348,7 +368,7 @@ function minify(ast, options = {}, recursive = false, errors) {
348368
minifyRule(node);
349369
}
350370
else {
351-
minify(node, options, recursive, errors);
371+
minify(node, options, recursive, errors, nestingContent);
352372
}
353373
previous = node;
354374
nodeIndex = i;
@@ -402,7 +422,7 @@ function minify(ast, options = {}, recursive = false, errors) {
402422
nodeIndex = --i;
403423
// @ts-ignore
404424
previous = ast.chi[nodeIndex];
405-
minify(wrapper, options, recursive, errors);
425+
minify(wrapper, options, recursive, errors, nestingContent);
406426
continue;
407427
}
408428
// @ts-ignore
@@ -435,7 +455,7 @@ function minify(ast, options = {}, recursive = false, errors) {
435455
let wrap = true;
436456
// @ts-ignore
437457
const selector = node.optimized.selector.reduce((acc, curr) => {
438-
if (curr[0] == '&') {
458+
if (curr[0] == '&' && curr.length > 1) {
439459
if (curr[1] == ' ') {
440460
curr.splice(0, 2);
441461
}
@@ -459,15 +479,22 @@ function minify(ast, options = {}, recursive = false, errors) {
459479
if (!wrap) {
460480
wrap = selector.some(s => s[0] != '&');
461481
}
462-
const rule = selector.map(s => {
482+
let rule = selector.map(s => {
463483
if (s[0] == '&') {
464484
// @ts-ignore
465485
s[0] = node.optimized.optimized[0];
466486
}
467487
return s.join('');
468488
}).join(',');
469489
// @ts-ignore
470-
node.sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
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+
}
471498
}
472499
}
473500
// @ts-ignore
@@ -503,7 +530,7 @@ function minify(ast, options = {}, recursive = false, errors) {
503530
minifyRule(node);
504531
}
505532
else {
506-
minify(node, options, recursive, errors);
533+
minify(node, options, recursive, errors, nestingContent);
507534
}
508535
i--;
509536
previous = node;
@@ -548,7 +575,7 @@ function minify(ast, options = {}, recursive = false, errors) {
548575
minifyRule(previous);
549576
}
550577
else {
551-
minify(previous, options, recursive, errors);
578+
minify(previous, options, recursive, errors, nestingContent);
552579
}
553580
}
554581
}
@@ -560,11 +587,19 @@ function minify(ast, options = {}, recursive = false, errors) {
560587
minifyRule(previous);
561588
}
562589
else {
563-
minify(previous, options, recursive, errors);
590+
minify(previous, options, recursive, errors, nestingContent);
564591
}
565592
}
566593
}
567594
}
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+
}
568603
previous = node;
569604
nodeIndex = i;
570605
}
@@ -577,10 +612,18 @@ function minify(ast, options = {}, recursive = false, errors) {
577612
else {
578613
// @ts-ignore
579614
if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
580-
minify(node, options, recursive, errors);
615+
minify(node, options, recursive, errors, nestingContent);
581616
}
582617
}
583618
}
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+
}
584627
}
585628
return ast;
586629
}
@@ -819,7 +862,6 @@ function reduceRuleSelector(node) {
819862
Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: raw });
820863
}
821864
}
822-
// }
823865
}
824866

825867
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector, splitRule };

dist/lib/ast/walk.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
function* walk(node) {
2-
// @ts-ignore
3-
yield* doWalk(node, null, null);
4-
}
5-
function* doWalk(node, parent, root) {
1+
function* walk(node, parent, root) {
62
yield { node, parent, root };
73
if ('chi' in node) {
84
for (const child of node.chi) {
9-
yield* doWalk(child, node, (root ?? node));
5+
yield* walk(child, node, (root ?? node));
106
}
117
}
128
}

dist/lib/parser/tokenize.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,16 @@ function* tokenize(iterator) {
121121
}
122122
function next(count = 1) {
123123
let char = '';
124-
while (count-- > 0 && ind < iterator.length) {
124+
let chr = '';
125+
if (count < 0) {
126+
return '';
127+
}
128+
while (count-- && (chr = iterator.charAt(ind + 1))) {
129+
char += chr;
125130
const codepoint = iterator.charCodeAt(++ind);
126131
if (isNaN(codepoint)) {
127132
return char;
128133
}
129-
char += iterator.charAt(ind);
130134
if (isNewLine(codepoint)) {
131135
lin++;
132136
col = 0;

dist/node/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector, splitRule } from '../lib/ast/minify.js';
22
export { walk, walkValues } from '../lib/ast/walk.js';
3-
export { expand } from '../lib/ast/expand.js';
3+
export { expand, replaceCompound } from '../lib/ast/expand.js';
44
export { colorsFunc, render, renderToken } from '../lib/renderer/render.js';
55
import { parse as parse$1 } from '../lib/parser/parse.js';
66
export { parseString, urlTokenMatcher } from '../lib/parser/parse.js';

dist/web/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector, splitRule } from '../lib/ast/minify.js';
22
export { walk, walkValues } from '../lib/ast/walk.js';
3-
export { expand } from '../lib/ast/expand.js';
3+
export { expand, replaceCompound } from '../lib/ast/expand.js';
44
export { colorsFunc, render, renderToken } from '../lib/renderer/render.js';
55
import { parse as parse$1 } from '../lib/parser/parse.js';
66
export { parseString, urlTokenMatcher } from '../lib/parser/parse.js';

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@tbela99/css-parser",
33
"description": "CSS parser for node and the browser",
4-
"version": "0.0.1-rc6",
4+
"version": "0.0.1-rc7",
55
"exports": {
66
".": "./dist/node/index.js",
77
"./umd": "./dist/index-umd-web.js",

0 commit comments

Comments
 (0)