Skip to content

Commit 9676337

Browse files
committed
strip universal selector when possible #43
1 parent 5da79d5 commit 9676337

File tree

14 files changed

+201
-119
lines changed

14 files changed

+201
-119
lines changed

CHANGELOG.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
- [x] declarations
88
- [ ] declaration values
99
- [ ] exclude -webkit-* gradients
10-
- [x] css selector validation
11-
- [x] pseudo element
12-
- [x] partial pseudo class validation. does not validate parameters
13-
- [x] attribute selector
14-
- [x] combinator
15-
- [x] simple selector
16-
- [x] nested selector
17-
- [ ] strict mode: allow unknown items such as pseudo classes
18-
- [x] allow unknown pseudo classes
19-
- [x] allow unknown attribute selectors
20-
- [ ] strip universal selector when possible
10+
- [x] css selector validation
11+
- [x] pseudo element
12+
- [x] partial pseudo class validation. does not validate parameters
13+
- [x] attribute selector
14+
- [x] combinator
15+
- [x] simple selector
16+
- [x] nested selector
17+
- [ ] strict mode: allow unknown items such as pseudo classes
18+
- [x] allow unknown pseudo classes
19+
- [x] allow unknown attribute selectors
20+
- [x] strip universal selector when possible
2121

2222
# v0.6.0
2323
- [x] light-dark() color

dist/index-umd-web.js

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66

77
var ValidationLevel;
88
(function (ValidationLevel) {
9-
ValidationLevel[ValidationLevel["None"] = 0] = "None";
10-
ValidationLevel[ValidationLevel["Valid"] = 1] = "Valid";
11-
ValidationLevel[ValidationLevel["Drop"] = 2] = "Drop";
9+
ValidationLevel[ValidationLevel["Valid"] = 0] = "Valid";
10+
ValidationLevel[ValidationLevel["Drop"] = 1] = "Drop";
1211
})(ValidationLevel || (ValidationLevel = {}));
1312
exports.EnumToken = void 0;
1413
(function (EnumToken) {
@@ -59920,6 +59919,7 @@
5992059919
if (delim.typ == exports.EnumToken.BlockStartTokenType) {
5992159920
const position = map.get(tokens[0]);
5992259921
const uniq = new Map;
59922+
// const uniqTokens: Token[][] = [[]];
5992359923
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
5992459924
if (curr.typ == exports.EnumToken.CommentTokenType) {
5992559925
return acc;
@@ -59935,27 +59935,31 @@
5993559935
let t = renderToken(curr, { minify: false });
5993659936
if (t == ',') {
5993759937
acc.push([]);
59938+
// uniqTokens.push([]);
5993859939
}
5993959940
else {
5994059941
acc[acc.length - 1].push(t);
59942+
// uniqTokens[uniqTokens.length - 1].push(curr);
5994159943
}
5994259944
return acc;
5994359945
}, [[]]).reduce((acc, curr) => {
59944-
// for (let i = 0; i < curr.length; i++) {
59945-
//
59946-
// if (curr[i] == '*' && i + 1 < curr.length) {
59947-
//
59948-
// curr.splice(i, curr[i + 1] == ' ' ? 2 : 1);
59949-
// i--;
59950-
// }
59951-
// }
59946+
let i = 0;
59947+
for (; i < curr.length; i++) {
59948+
if (i + 1 < curr.length && curr[i] == '*') {
59949+
if (curr[i] == '*') {
59950+
let index = curr[i + 1] == ' ' ? 2 : 1;
59951+
if (!['>', '~', '+'].includes(curr[index])) {
59952+
curr.splice(i, index);
59953+
}
59954+
}
59955+
}
59956+
}
5995259957
acc.set(curr.join(''), curr);
5995359958
return acc;
5995459959
}, uniq);
5995559960
const ruleType = context.typ == exports.EnumToken.AtRuleNodeType && context.nam == 'keyframes' ? exports.EnumToken.KeyFrameRuleNodeType : exports.EnumToken.RuleNodeType;
5995659961
if (ruleType == exports.EnumToken.RuleNodeType) {
59957-
parseSelector(tokens);
59958-
const valid = validateSelector(tokens, options, context);
59962+
const valid = validateSelector(parseSelector(tokens), options, context);
5995959963
if (valid.valid != ValidationLevel.Valid) {
5996059964
const node = {
5996159965
typ: exports.EnumToken.InvalidRuleTokenType,
@@ -59968,14 +59972,12 @@
5996859972
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
5996959973
location: { src, ...(map.get(valid.node) ?? position) }
5997059974
});
59971-
// @ts-ignore
5997259975
context.chi.push(node);
5997359976
return node;
5997459977
}
5997559978
}
5997659979
const node = {
5997759980
typ: ruleType,
59978-
// @ts-ignore
5997959981
sel: [...uniq.keys()].join(','),
5998059982
chi: []
5998159983
};
@@ -60175,12 +60177,13 @@
6017560177
}
6017660178
}
6017760179
let i = 0;
60180+
const combinators = [
60181+
exports.EnumToken.ChildCombinatorTokenType,
60182+
exports.EnumToken.NextSiblingCombinatorTokenType,
60183+
exports.EnumToken.SubsequentSiblingCombinatorTokenType
60184+
];
6017860185
for (; i < tokens.length; i++) {
60179-
if ([
60180-
exports.EnumToken.ChildCombinatorTokenType,
60181-
exports.EnumToken.NextSiblingCombinatorTokenType,
60182-
exports.EnumToken.SubsequentSiblingCombinatorTokenType
60183-
].includes(tokens[i].typ)) {
60186+
if (combinators.includes(tokens[i].typ)) {
6018460187
if (i + 1 < tokens.length && [exports.EnumToken.WhitespaceTokenType, exports.EnumToken.DescendantCombinatorTokenType].includes(tokens[i + 1].typ)) {
6018560188
tokens.splice(i + 1, 1);
6018660189
}
@@ -60952,7 +60955,12 @@
6095260955
return 1;
6095360956
}
6095460957
return b == '&' ? -1 : 0;
60955-
}).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
60958+
}).reduce((acc, curr) => {
60959+
if (acc.length > 0 && curr == '&' && (replace.charAt(0) != '.' || replace.includes(' '))) {
60960+
return acc + ':is(' + replace + ')';
60961+
}
60962+
return acc + (curr == '&' ? replace : curr);
60963+
}, '');
6095660964
}
6095760965

6095860966
var ValidationTokenEnum;
@@ -62632,7 +62640,6 @@
6263262640
return null;
6263362641
}
6263462642
selector = selector.reduce((acc, curr) => {
62635-
// trim :is()
6263662643
// @ts-ignore
6263762644
if (curr.length > 0 && curr.at(-1).startsWith(':is(')) {
6263862645
// @ts-ignore
@@ -62689,9 +62696,6 @@
6268962696
if (optimized[1] == ' ') {
6269062697
optimized.splice(0, 2);
6269162698
}
62692-
// else if (combinators.includes(optimized[1])) {
62693-
//
62694-
// }
6269562699
}
6269662700
if (optimized.length == 0 ||
6269762701
(optimized[0].charAt(0) == '&' ||

dist/index.cjs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ var promises = require('node:fs/promises');
55

66
var ValidationLevel;
77
(function (ValidationLevel) {
8-
ValidationLevel[ValidationLevel["None"] = 0] = "None";
9-
ValidationLevel[ValidationLevel["Valid"] = 1] = "Valid";
10-
ValidationLevel[ValidationLevel["Drop"] = 2] = "Drop";
8+
ValidationLevel[ValidationLevel["Valid"] = 0] = "Valid";
9+
ValidationLevel[ValidationLevel["Drop"] = 1] = "Drop";
1110
})(ValidationLevel || (ValidationLevel = {}));
1211
exports.EnumToken = void 0;
1312
(function (EnumToken) {
@@ -59919,6 +59918,7 @@ async function parseNode(results, context, stats, options, errors, src, map) {
5991959918
if (delim.typ == exports.EnumToken.BlockStartTokenType) {
5992059919
const position = map.get(tokens[0]);
5992159920
const uniq = new Map;
59921+
// const uniqTokens: Token[][] = [[]];
5992259922
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
5992359923
if (curr.typ == exports.EnumToken.CommentTokenType) {
5992459924
return acc;
@@ -59934,27 +59934,31 @@ async function parseNode(results, context, stats, options, errors, src, map) {
5993459934
let t = renderToken(curr, { minify: false });
5993559935
if (t == ',') {
5993659936
acc.push([]);
59937+
// uniqTokens.push([]);
5993759938
}
5993859939
else {
5993959940
acc[acc.length - 1].push(t);
59941+
// uniqTokens[uniqTokens.length - 1].push(curr);
5994059942
}
5994159943
return acc;
5994259944
}, [[]]).reduce((acc, curr) => {
59943-
// for (let i = 0; i < curr.length; i++) {
59944-
//
59945-
// if (curr[i] == '*' && i + 1 < curr.length) {
59946-
//
59947-
// curr.splice(i, curr[i + 1] == ' ' ? 2 : 1);
59948-
// i--;
59949-
// }
59950-
// }
59945+
let i = 0;
59946+
for (; i < curr.length; i++) {
59947+
if (i + 1 < curr.length && curr[i] == '*') {
59948+
if (curr[i] == '*') {
59949+
let index = curr[i + 1] == ' ' ? 2 : 1;
59950+
if (!['>', '~', '+'].includes(curr[index])) {
59951+
curr.splice(i, index);
59952+
}
59953+
}
59954+
}
59955+
}
5995159956
acc.set(curr.join(''), curr);
5995259957
return acc;
5995359958
}, uniq);
5995459959
const ruleType = context.typ == exports.EnumToken.AtRuleNodeType && context.nam == 'keyframes' ? exports.EnumToken.KeyFrameRuleNodeType : exports.EnumToken.RuleNodeType;
5995559960
if (ruleType == exports.EnumToken.RuleNodeType) {
59956-
parseSelector(tokens);
59957-
const valid = validateSelector(tokens, options, context);
59961+
const valid = validateSelector(parseSelector(tokens), options, context);
5995859962
if (valid.valid != ValidationLevel.Valid) {
5995959963
const node = {
5996059964
typ: exports.EnumToken.InvalidRuleTokenType,
@@ -59967,14 +59971,12 @@ async function parseNode(results, context, stats, options, errors, src, map) {
5996759971
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
5996859972
location: { src, ...(map.get(valid.node) ?? position) }
5996959973
});
59970-
// @ts-ignore
5997159974
context.chi.push(node);
5997259975
return node;
5997359976
}
5997459977
}
5997559978
const node = {
5997659979
typ: ruleType,
59977-
// @ts-ignore
5997859980
sel: [...uniq.keys()].join(','),
5997959981
chi: []
5998059982
};
@@ -60174,12 +60176,13 @@ function parseSelector(tokens) {
6017460176
}
6017560177
}
6017660178
let i = 0;
60179+
const combinators = [
60180+
exports.EnumToken.ChildCombinatorTokenType,
60181+
exports.EnumToken.NextSiblingCombinatorTokenType,
60182+
exports.EnumToken.SubsequentSiblingCombinatorTokenType
60183+
];
6017760184
for (; i < tokens.length; i++) {
60178-
if ([
60179-
exports.EnumToken.ChildCombinatorTokenType,
60180-
exports.EnumToken.NextSiblingCombinatorTokenType,
60181-
exports.EnumToken.SubsequentSiblingCombinatorTokenType
60182-
].includes(tokens[i].typ)) {
60185+
if (combinators.includes(tokens[i].typ)) {
6018360186
if (i + 1 < tokens.length && [exports.EnumToken.WhitespaceTokenType, exports.EnumToken.DescendantCombinatorTokenType].includes(tokens[i + 1].typ)) {
6018460187
tokens.splice(i + 1, 1);
6018560188
}
@@ -60951,7 +60954,12 @@ function replaceCompoundLiteral(selector, replace) {
6095160954
return 1;
6095260955
}
6095360956
return b == '&' ? -1 : 0;
60954-
}).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
60957+
}).reduce((acc, curr) => {
60958+
if (acc.length > 0 && curr == '&' && (replace.charAt(0) != '.' || replace.includes(' '))) {
60959+
return acc + ':is(' + replace + ')';
60960+
}
60961+
return acc + (curr == '&' ? replace : curr);
60962+
}, '');
6095560963
}
6095660964

6095760965
var ValidationTokenEnum;
@@ -62631,7 +62639,6 @@ function reduceSelector(selector) {
6263162639
return null;
6263262640
}
6263362641
selector = selector.reduce((acc, curr) => {
62634-
// trim :is()
6263562642
// @ts-ignore
6263662643
if (curr.length > 0 && curr.at(-1).startsWith(':is(')) {
6263762644
// @ts-ignore
@@ -62688,9 +62695,6 @@ function reduceSelector(selector) {
6268862695
if (optimized[1] == ' ') {
6268962696
optimized.splice(0, 2);
6269062697
}
62691-
// else if (combinators.includes(optimized[1])) {
62692-
//
62693-
// }
6269462698
}
6269562699
if (optimized.length == 0 ||
6269662700
(optimized[0].charAt(0) == '&' ||

dist/lib/ast/expand.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,12 @@ function replaceCompoundLiteral(selector, replace) {
155155
return 1;
156156
}
157157
return b == '&' ? -1 : 0;
158-
}).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
158+
}).reduce((acc, curr) => {
159+
if (acc.length > 0 && curr == '&' && (replace.charAt(0) != '.' || replace.includes(' '))) {
160+
return acc + ':is(' + replace + ')';
161+
}
162+
return acc + (curr == '&' ? replace : curr);
163+
}, '');
159164
}
160165

161166
export { expand, replaceCompound };

dist/lib/ast/minify.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,6 @@ function reduceSelector(selector) {
402402
return null;
403403
}
404404
selector = selector.reduce((acc, curr) => {
405-
// trim :is()
406405
// @ts-ignore
407406
if (curr.length > 0 && curr.at(-1).startsWith(':is(')) {
408407
// @ts-ignore
@@ -459,9 +458,6 @@ function reduceSelector(selector) {
459458
if (optimized[1] == ' ') {
460459
optimized.splice(0, 2);
461460
}
462-
// else if (combinators.includes(optimized[1])) {
463-
//
464-
// }
465461
}
466462
if (optimized.length == 0 ||
467463
(optimized[0].charAt(0) == '&' ||

dist/lib/ast/types.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
var ValidationLevel;
22
(function (ValidationLevel) {
3-
ValidationLevel[ValidationLevel["None"] = 0] = "None";
4-
ValidationLevel[ValidationLevel["Valid"] = 1] = "Valid";
5-
ValidationLevel[ValidationLevel["Drop"] = 2] = "Drop";
3+
ValidationLevel[ValidationLevel["Valid"] = 0] = "Valid";
4+
ValidationLevel[ValidationLevel["Drop"] = 1] = "Drop";
65
})(ValidationLevel || (ValidationLevel = {}));
76
var EnumToken;
87
(function (EnumToken) {

0 commit comments

Comments
 (0)