Skip to content

Commit d84c2b6

Browse files
ahdinosauryoshuawuyts
authored andcommitted
implement #2
re-write using postcss-selector-parser breaking change to API: prefix *must* be a single node, at the moment either an #id or a .className Signed-off-by: Yoshua Wuyts <[email protected]> Closes #3
1 parent 5249203 commit d84c2b6

File tree

3 files changed

+56
-7
lines changed

3 files changed

+56
-7
lines changed

index.js

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const postcss = require('postcss')
2+
const Selector = require('postcss-selector-parser')
23

34
module.exports = postcss.plugin('postcss-prefix', postcssPrefix)
45

@@ -7,11 +8,58 @@ function postcssPrefix (prefix, options) {
78

89
return function (root) {
910
root.walkRules(function (rule) {
10-
rule.selectors = rule.selectors.map(function (selector) {
11-
if (rule.selector.indexOf(':root') === 0) return selector
12-
return prefix + selector
13-
})
14-
rule.selector = rule.selectors.join(', ')
11+
const selector = Selector(
12+
transformSelectors
13+
).process(rule.selector).result
14+
15+
rule.selector = selector
16+
})
17+
}
18+
19+
function transformSelectors (selectors) {
20+
selectors.eachInside(function (selector) {
21+
if (
22+
// if parent is not selector and
23+
selector.parent.type !== 'selector' ||
24+
// if not first node in container
25+
selector.parent.nodes[0] !== selector
26+
) return
27+
28+
const prefixNode = getPrefixNode(prefix)
29+
30+
if (selector.type === 'pseudo') {
31+
switch (selector.value) {
32+
case ':root':
33+
return
34+
case ':host':
35+
const replacement = Selector.selector()
36+
replacement.nodes = [prefixNode].concat(selector.clone().nodes)
37+
selector.replaceWith(replacement)
38+
return
39+
}
40+
}
41+
42+
// prefix
43+
//
44+
// start by prepending a space combinator
45+
selector.parent.prepend(Selector.combinator({ value: ' ' }))
46+
// then prepend the prefix node, preserving spacing
47+
prefixNode.spaces.before = selector.spaces.before
48+
selector.spaces.before = ''
49+
selector.parent.prepend(prefixNode)
1550
})
1651
}
52+
53+
}
54+
55+
function getPrefixNode (prefix) {
56+
const sigil = prefix[0]
57+
const value = prefix.slice(1)
58+
59+
switch (sigil) {
60+
case '#':
61+
return Selector.id({ value })
62+
case '.':
63+
return Selector.className({ value })
64+
}
1765
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"name": "postcss-prefix",
33
"version": "1.0.1",
44
"dependencies": {
5-
"postcss": "^5.0.8"
5+
"postcss": "^5.0.8",
6+
"postcss-selector-parser": "^1.3.0"
67
},
78
"devDependencies": {
89
"tape": "^4.2.1"

test/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ test('postcss-prefix', function (t) {
88
const expected = fs.readFileSync(path.join(__dirname, 'fixture-out.css'), 'utf8')
99
const css = fs.readFileSync(path.join(__dirname, 'fixture.css'), 'utf8')
1010
const out = postcss()
11-
.use(prefix('#hello-world '))
11+
.use(prefix('#hello-world'))
1212
.process(css)
1313
.toString()
1414

0 commit comments

Comments
 (0)