Skip to content

Fixed wrong nesting selector parse. #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 32 additions & 25 deletions lib/styles/selectors/resolver/css-selector-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
isTypeSelector,
findNestingSelectors,
hasNodesSelector,
isSelectorCombinator,
} from "../../utils/selectors"
import {
VCSSStyleSheet,
Expand Down Expand Up @@ -202,44 +203,50 @@ export class CSSSelectorResolver {
parentSelectors: ResolvedSelector[],
container: VCSSNode,
) {
const nesting = findNestingSelectors(selectorNodes).next().value
if (!nesting) {
const nestingNext = findNestingSelectors(selectorNodes).next()
if (nestingNext.done) {
// Must be nest-containing, which means it contains a nesting selector in it somewhere.
return [new ResolvedSelector(selectorNodes, container)]
}
const {
nestingIndex,
nodes: hasNestingNodes,
node: nestingNode,
} = nesting
} = nestingNext.value

const nestingLeftNode = hasNestingNodes[nestingIndex - 1]
const nestingRightNode = hasNestingNodes[(nestingIndex as number) + 1]
const beforeSelector = hasNestingNodes.slice(0, nestingIndex)
const afterSelector = hasNestingNodes.slice(nestingIndex + 1)
const nestingLeftNode =
beforeSelector.length > 0
? beforeSelector[beforeSelector.length - 1]
: null
const nestingRightNode =
afterSelector.length > 0 ? afterSelector[0] : null
const maybeJoinLeft =
nestingLeftNode && nestingLeftNode.range[1] === nestingNode.range[0]
const needJoinRight =
nestingLeftNode &&
nestingLeftNode.range[1] === nestingNode.range[0] &&
!isSelectorCombinator(nestingLeftNode)
const maybeJoinRight =
nestingRightNode &&
nestingNode.range[1] === nestingRightNode.range[0] &&
isTypeSelector(nestingRightNode)

const beforeSelector = hasNestingNodes.slice(0, nestingIndex)
const afterSelector = hasNestingNodes.slice(
(nestingIndex as number) + 1,
)

let resolved = parentSelectors.map(p => {
const before = [...beforeSelector]
const after = [...afterSelector]
const parentSelector = [...p.selector]
const needJoinLeft =
maybeJoinLeft && isTypeSelector(parentSelector[0])
const needJoinRight =
maybeJoinRight &&
!isSelectorCombinator(parentSelector[parentSelector.length - 1])
if (needJoinLeft && needJoinRight && parentSelector.length === 1) {
// concat both (e.g. `bar { @nest foo-&-baz {} }` -> .foo-bar-baz)
// concat both (e.g. `bar { @nest .foo-&-baz {} }` -> .foo-bar-baz)
before.push(
newNestingConcatBothSelectorNodes(
before.pop() as VCSSTypeSelector,
parentSelector.shift() as VCSSSelectorNode,
after.shift() as VCSSSelectorNode,
before.pop() as VCSSSelectorValueNode,
parentSelector.shift() as VCSSTypeSelector,
after.shift() as VCSSTypeSelector,
nestingNode,
),
)
Expand All @@ -248,8 +255,8 @@ export class CSSSelectorResolver {
// concat left (e.g. `bar { @nest .foo-& {} }` -> .foo-bar)
before.push(
newNestingConcatLeftSelectorNodes(
before.pop() as VCSSTypeSelector,
parentSelector.shift() as VCSSSelectorNode,
before.pop() as VCSSSelectorValueNode,
parentSelector.shift() as VCSSTypeSelector,
nestingNode,
),
)
Expand All @@ -259,7 +266,7 @@ export class CSSSelectorResolver {
after.unshift(
newNestingConcatRightSelectorNodes(
parentSelector.pop() as VCSSSelectorValueNode,
after.shift() as VCSSSelectorValueNode,
after.shift() as VCSSTypeSelector,
nestingNode,
),
)
Expand Down Expand Up @@ -302,9 +309,9 @@ export class CSSSelectorResolver {
* Creates a selector node that concats the left and right selectors of the parent selector and the nested selector.
*/
function newNestingConcatBothSelectorNodes(
left: VCSSTypeSelector,
parent: VCSSSelectorNode,
right: VCSSSelectorNode,
left: VCSSSelectorValueNode,
parent: VCSSTypeSelector,
right: VCSSTypeSelector,
_nesting: any,
) {
const loc = {
Expand All @@ -326,8 +333,8 @@ function newNestingConcatBothSelectorNodes(
* Creates a selector node that concats the left selectors of the parent selector and the nested selector.
*/
function newNestingConcatLeftSelectorNodes(
left: VCSSTypeSelector,
parent: VCSSSelectorNode,
left: VCSSSelectorValueNode,
parent: VCSSTypeSelector,
nesting: VCSSNestingSelector,
) {
const loc = {
Expand All @@ -349,7 +356,7 @@ function newNestingConcatLeftSelectorNodes(
*/
function newNestingConcatRightSelectorNodes(
parent: VCSSSelectorValueNode,
right: VCSSSelectorValueNode,
right: VCSSTypeSelector,
nesting: VCSSNestingSelector,
) {
const loc = {
Expand Down
2 changes: 1 addition & 1 deletion lib/styles/utils/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export function isNestingAtRule(
return isVCSSAtRule(node) && node.name === "nest"
}

type NestingInfo = {
export type NestingInfo = {
node: VCSSNestingSelector
nodes: VCSSSelectorNode[]
nestingIndex: number
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-vue-scoped-css",
"version": "0.2.0",
"version": "0.2.1",
"description": "ESLint plugin for Scoped CSS in Vue.js",
"main": "dist/index.js",
"scripts": {
Expand Down
Loading