Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Dec 28, 2021. It is now read-only.

Commit 2ee61c4

Browse files
authored
fix spec issues (#88)
* fix spec issues * also fix nesting rules * one more test * cleanup * more fixes : - fix #87 - add test to ensure that #85 was fixed * update CI
1 parent 7c5b8f7 commit 2ee61c4

21 files changed

+1038
-73
lines changed

.bin/test-tape.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default async function tape() {
1818
failures += await test('supports nested @media', { basename: 'media' })
1919
failures += await test('ignores invalid entries', { basename: 'ignore' })
2020
failures += await test('supports complex entries', { basename: 'complex' })
21+
failures += await test('supports all spec examples', { basename: 'spec-examples' })
2122

2223
let mixinPlugin = () => {
2324
return {

.github/workflows/test.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: test
2+
on:
3+
push:
4+
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
matrix:
10+
node: [12, 14, 16]
11+
steps:
12+
- uses: actions/checkout@v2
13+
- uses: actions/setup-node@v2
14+
with:
15+
node-version: 16
16+
17+
- run: npm install --ignore-scripts
18+
- run: npm run build
19+
20+
- uses: actions/setup-node@v2
21+
with:
22+
node-version: ${{ matrix.node }}
23+
- run: npm install --ignore-scripts
24+
- run: npm run test

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ yarn.lock
99
!.bin
1010
!.editorconfig
1111
!.gitignore
12+
!.github
1213
!.rollup.js
1314
!.tape.js
1415
!.travis.yml

.travis.yml

Lines changed: 0 additions & 7 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"node >= 12"
5656
],
5757
"engines": {
58-
"node": "12 - 16"
58+
"node": ">= 12"
5959
},
6060
"eslintConfig": {
6161
"extends": "eslint:recommended",

src/lib/merge-selectors.js

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
1-
import { complex, replaceable } from './valid-selector.js'
1+
import { replaceable } from './valid-selector.js'
22

33
export default function mergeSelectors(fromSelectors, toSelectors) {
4-
return fromSelectors.reduce(
5-
(selectors, fromSelector) => selectors.concat(
6-
toSelectors.map(
7-
(toSelector) => complex.test(toSelector)
8-
? toSelector.replace(replaceable, `:is(${fromSelector})`)
9-
: toSelector.replace(replaceable, fromSelector)
10-
)
11-
),
12-
[]
13-
)
4+
return toSelectors.map((toSelector) => {
5+
let needsIsOnFromSelector = false
6+
7+
if (fromSelectors.length > 1) {
8+
needsIsOnFromSelector = true
9+
}
10+
11+
// foo &foo foo & baz -> foo &:is(foo) foo & baz
12+
toSelector = toSelector.replace(/&((?:[\w-_|])(?:[^\s,{]*))/g, (match, p1) => {
13+
return `&:is(${p1})`
14+
})
15+
16+
// foo& -> foo:is(&)
17+
if (fromSelectors.length === 1 && /^(?:[\w-_|])/.test(fromSelectors[0])) {
18+
toSelector = toSelector.replace(/([\w-_|]+)(?:&)/g, (match, p1) => {
19+
return `${p1}:is(&)`
20+
})
21+
}
22+
23+
return needsIsOnFromSelector
24+
? toSelector.replace(replaceable, `:is(${fromSelectors.join(', ')})`)
25+
: toSelector.replace(replaceable, fromSelectors.join(', '))
26+
})
1427
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// see : https://www.w3.org/TR/css-nesting-1/#mixing
2+
export default function ensureCorrectMixingOfNestingRulesAndDeclarations(node) {
3+
const hasNestedChildren = node.some((child) => {
4+
return child.type === 'atrule' || child.type === 'rule'
5+
})
6+
7+
if (!hasNestedChildren) {
8+
return
9+
}
10+
11+
// Clone with only declarations
12+
const clone = node.cloneBefore()
13+
14+
let encounteredNestedRule = false
15+
clone.each((child) => {
16+
if (child.type === 'atrule' || child.type === 'rule') {
17+
encounteredNestedRule = true
18+
child.remove()
19+
return
20+
}
21+
22+
if (encounteredNestedRule) {
23+
// declarations after nesting rules are not allowed
24+
child.remove()
25+
return
26+
}
27+
})
28+
29+
if (clone.nodes.length === 0) {
30+
clone.remove()
31+
}
32+
33+
// Remove all declarations and preserve nesting rules
34+
encounteredNestedRule = false
35+
node.each((child) => {
36+
if (child.type === 'atrule' || child.type === 'rule') {
37+
return
38+
}
39+
40+
child.remove()
41+
})
42+
43+
if (node.nodes.length === 0) {
44+
node.remove()
45+
}
46+
}

src/lib/nest-rule-within-rule.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { comma } from './list.js'
22
import shiftNodesBeforeParent from './shift-nodes-before-parent.js'
33
import cleanupParent from './cleanup-parent.js'
44
import mergeSelectors from './merge-selectors.js'
5-
import validSelector from './valid-selector.js'
65
import walk from './walk.js'
76

87
export default function transformNestRuleWithinRule(node) {
@@ -25,4 +24,4 @@ export default function transformNestRuleWithinRule(node) {
2524
walk(rule)
2625
}
2726

28-
export const isNestRuleWithinRule = (node) => node.type === 'atrule' && node.name === 'nest' && Object(node.parent).type === 'rule' && comma(node.params).every((selector) => selector.split('&').length >= 2 && validSelector.test(selector))
27+
export const isNestRuleWithinRule = (node) => node.type === 'atrule' && node.name === 'nest' && Object(node.parent).type === 'rule' && comma(node.params).every((selector) => selector.split('&').length >= 2 && selector.indexOf('|') === -1)

src/lib/rule-within-rule.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import shiftNodesBeforeParent from './shift-nodes-before-parent.js'
22
import cleanupParent from './cleanup-parent.js'
33
import mergeSelectors from './merge-selectors.js'
4-
import validSelector from './valid-selector.js'
54

65
export default function transformRuleWithinRule(node) {
76
// move previous siblings and the node to before the parent
@@ -21,4 +20,4 @@ export default function transformRuleWithinRule(node) {
2120
cleanupParent(parent)
2221
}
2322

24-
export const isRuleWithinRule = (node) => node.type === 'rule' && Object(node.parent).type === 'rule' && node.selectors.every((selector) => selector.trim().lastIndexOf('&') === 0 && validSelector.test(selector))
23+
export const isRuleWithinRule = (node) => node.type === 'rule' && Object(node.parent).type === 'rule' && node.selectors.every((selector) => selector.trim().indexOf('&') === 0 && selector.indexOf('|') === -1)

src/lib/valid-selector.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,2 @@
1-
// a valid selector is an ampersand followed by a non-word character or nothing
2-
export default /&(?:[^\w-|]|$)/
3-
4-
export const complex = /&[^]*&/
5-
61
export const replaceable = /&/g
72

0 commit comments

Comments
 (0)