Skip to content

Commit

Permalink
::slotted() should only accept a <compound-selector>
Browse files Browse the repository at this point in the history
  • Loading branch information
bramus committed Dec 12, 2022
1 parent debb7c5 commit 3f9ebc0
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 3 deletions.
5 changes: 5 additions & 0 deletions fixtures/ast/selector/functional-pseudo/slotted.json
Expand Up @@ -59,6 +59,11 @@
}
},
"error": [
{
"source": "::slotted(.a .b)",
"offset": " ^",
"error": "CompoundSelector is expected"
},
{
"source": "::slotted(.a{)",
"offset": " ^",
Expand Down
2 changes: 1 addition & 1 deletion lib/__tests/common.js
Expand Up @@ -39,7 +39,7 @@ describe('Common', () => {

assert.deepStrictEqual(
[...foundTypes].sort(),
types.sort().filter(type => type !== 'WhiteSpace') // FIXME: temporary filter white space
types.sort().filter(type => !['WhiteSpace', 'CompoundSelector'].includes(type)) // FIXME: temporary filter white space
);
});

Expand Down
2 changes: 1 addition & 1 deletion lib/__tests/walk.js
Expand Up @@ -561,7 +561,7 @@ describe('AST traversal', () => {
it('should throws when visit has wrong value', () => {
assert.throws(
() => walk(ast, { visit: 'Foo' }),
/Bad value `Foo` for `visit` option \(should be: AnPlusB, Atrule, AtrulePrelude, AttributeSelector, Block, Brackets, CDC, CDO, ClassSelector, Combinator, Comment, Declaration, DeclarationList, Dimension, Function, Hash, IdSelector, Identifier, MediaFeature, MediaQuery, MediaQueryList, NestingSelector, Nth, Number, Operator, Parentheses, Percentage, PseudoClassSelector, PseudoElementSelector, Ratio, Raw, Rule, Selector, SelectorList, String, StyleSheet, TypeSelector, UnicodeRange, Url, Value, WhiteSpace\)/
/Bad value `Foo` for `visit` option \(should be: AnPlusB, Atrule, AtrulePrelude, AttributeSelector, Block, Brackets, CDC, CDO, ClassSelector, Combinator, Comment, CompoundSelector, Declaration, DeclarationList, Dimension, Function, Hash, IdSelector, Identifier, MediaFeature, MediaQuery, MediaQueryList, NestingSelector, Nth, Number, Operator, Parentheses, Percentage, PseudoClassSelector, PseudoElementSelector, Ratio, Raw, Rule, Selector, SelectorList, String, StyleSheet, TypeSelector, UnicodeRange, Url, Value, WhiteSpace\)/
);
});
});
Expand Down
1 change: 1 addition & 0 deletions lib/syntax/config/parser.js
Expand Up @@ -16,6 +16,7 @@ export default {
rule: 'Rule',
selectorList: 'SelectorList',
selector: 'Selector',
compoundSelector: 'CompoundSelector',
block() {
return this.Block(true);
},
Expand Down
39 changes: 39 additions & 0 deletions lib/syntax/node/CompoundSelector.js
@@ -0,0 +1,39 @@
export const name = 'CompoundSelector';
export const structure = {
children: [[
'TypeSelector',
'IdSelector',
'ClassSelector',
'AttributeSelector',
'PseudoClassSelector',
'PseudoElementSelector',
'Combinator',
'WhiteSpace'
]]
};

export function parse() {
const children = this.readSequence(this.scope.Selector);

// nothing were consumed
if (this.getFirstListNode(children) === null) {
this.error('Selector is expected');
}

// Selector Contains Combinator
children.forEach((entry) => {
if (entry.type === 'Combinator') {
this.error('CompoundSelector is expected');
}
});

return {
type: 'Selector', // Report as Selector
loc: this.getLocationFromList(children),
children
};
}

export function generate(node) {
this.children(node);
}
1 change: 1 addition & 0 deletions lib/syntax/node/index-generate.js
Expand Up @@ -29,6 +29,7 @@ export { generate as PseudoElementSelector } from './PseudoElementSelector.js';
export { generate as Ratio } from './Ratio.js';
export { generate as Raw } from './Raw.js';
export { generate as Rule } from './Rule.js';
export { generate as CompoundSelector } from './CompoundSelector.js';
export { generate as Selector } from './Selector.js';
export { generate as SelectorList } from './SelectorList.js';
export { generate as String } from './String.js';
Expand Down
1 change: 1 addition & 0 deletions lib/syntax/node/index-parse-selector.js
Expand Up @@ -9,6 +9,7 @@ export { parse as Percentage } from './Percentage.js';
export { parse as PseudoClassSelector } from './PseudoClassSelector.js';
export { parse as PseudoElementSelector } from './PseudoElementSelector.js';
export { parse as Raw } from './Raw.js';
export { parse as CompoundSelector } from './CompoundSelector.js';
export { parse as Selector } from './Selector.js';
export { parse as SelectorList } from './SelectorList.js';
export { parse as String } from './String.js';
Expand Down
1 change: 1 addition & 0 deletions lib/syntax/node/index-parse.js
Expand Up @@ -29,6 +29,7 @@ export { parse as PseudoElementSelector } from './PseudoElementSelector.js';
export { parse as Ratio } from './Ratio.js';
export { parse as Raw } from './Raw.js';
export { parse as Rule } from './Rule.js';
export { parse as CompoundSelector } from './CompoundSelector.js';
export { parse as Selector } from './Selector.js';
export { parse as SelectorList } from './SelectorList.js';
export { parse as String } from './String.js';
Expand Down
1 change: 1 addition & 0 deletions lib/syntax/node/index.js
Expand Up @@ -30,6 +30,7 @@ export * as PseudoElementSelector from './PseudoElementSelector.js';
export * as Ratio from './Ratio.js';
export * as Raw from './Raw.js';
export * as Rule from './Rule.js';
export * as CompoundSelector from './CompoundSelector.js';
export * as Selector from './Selector.js';
export * as SelectorList from './SelectorList.js';
export * as String from './String.js';
Expand Down
10 changes: 9 additions & 1 deletion lib/syntax/pseudo/index.js
Expand Up @@ -30,6 +30,14 @@ const nth = {
}
};

const compoundSelector = {
parse() {
return this.createSingleNodeList(
this.CompoundSelector()
);
}
};

export default {
'dir': identList,
'has': selectorList,
Expand All @@ -44,5 +52,5 @@ export default {
'nth-last-child': nth,
'nth-last-of-type': nth,
'nth-of-type': nth,
'slotted': selector
'slotted': compoundSelector
};

0 comments on commit 3f9ebc0

Please sign in to comment.