Skip to content

Commit a977487

Browse files
committed
new scoped css implementation
1 parent 5282f7e commit a977487

File tree

6 files changed

+46
-74
lines changed

6 files changed

+46
-74
lines changed

lib/id-generator.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// keep track of unique ids for component modules.
2+
3+
var ids = Object.create(null)
4+
var count = 0
5+
6+
exports.get = function (path) {
7+
var id = ids[path]
8+
if (!id) {
9+
id = ids[path] = ++count
10+
}
11+
return '_v-' + id
12+
}

lib/style-rewriter.js

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,27 @@
11
var postcss = require('postcss')
2-
var nested = require('postcss-nested')
32
var selectorParser = require('postcss-selector-parser')
4-
var hash = require('hash-sum')
3+
var idGen = require('./id-generator')
54

6-
var liftRE = /^(html|head|body)\b/
7-
var scopeRE = /:scope\b/
8-
var processRoot = postcss.plugin('process-root', function () {
5+
var currentId
6+
var addId = postcss.plugin('add-id', function () {
97
return function (root) {
10-
var lifted = 0
11-
function lift (node) {
12-
node.moveBefore(root.nodes[lifted++])
13-
}
148
root.each(function (node) {
15-
node.each(function (node) {
16-
var kept = []
17-
selectorParser(function (selectors) {
18-
selectors.each(function (selector) {
19-
var sel = selector.toString()
20-
if (liftRE.test(sel)) {
21-
lift(node.clone({
22-
selector: sel
23-
}))
24-
} else {
25-
kept.push(sel)
26-
}
27-
})
28-
}).process(node.selector)
29-
if (!kept.length) {
30-
node.removeSelf()
31-
} else {
32-
node.selector = kept.join(',').replace(scopeRE, '&')
33-
}
34-
})
9+
node.selector = selectorParser(function (selectors) {
10+
selectors.each(function (selector) {
11+
selector.append(selectorParser.attribute({
12+
attribute: currentId
13+
}))
14+
})
15+
}).process(node.selector).result
3516
})
3617
}
3718
})
3819

3920
module.exports = function (css) {
4021
this.cacheable()
4122
var cb = this.async()
42-
var cls = '.v-' + hash(this.resourcePath)
43-
css = cls + '{' + css + '}'
44-
postcss([processRoot, nested])
23+
currentId = idGen.get(this.resourcePath)
24+
postcss([addId])
4525
.process(css)
4626
.then(function (result) {
4727
cb(null, result)

lib/template-rewriter.js

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
11
var parse5 = require('parse5')
22
var parser = new parse5.Parser()
33
var serializer = new parse5.Serializer()
4-
var hash = require('hash-sum')
4+
var idGen = require('./id-generator')
55

66
module.exports = function (html) {
77
this.cacheable()
8-
var cls = 'v-' + hash(this.resourcePath)
8+
var id = idGen.get(this.resourcePath)
99
var tree = parser.parseFragment(html)
10-
tree.childNodes.forEach(function (node) {
10+
walk(tree, function (node) {
1111
if (node.attrs) {
12-
var hasClass = false
13-
for (var i = 0, l = node.attrs.length; i < l; i++) {
14-
var attr = node.attrs[i]
15-
if (attr.name === 'class') {
16-
attr.value += ' ' + cls
17-
hasClass = true
18-
break
19-
}
20-
}
21-
if (!hasClass) {
22-
node.attrs.push({
23-
name: 'class',
24-
value: cls
25-
})
26-
}
12+
node.attrs.push({
13+
name: id,
14+
value: ''
15+
})
2716
}
2817
})
2918
return serializer.serialize(tree)
3019
}
20+
21+
function walk (tree, fn) {
22+
if (tree.childNodes) {
23+
tree.childNodes.forEach(function (node) {
24+
fn(node)
25+
walk(node, fn)
26+
})
27+
}
28+
}

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@
2323
"test": "eslint lib && mocha test/test.js --slow 5000"
2424
},
2525
"dependencies": {
26-
"hash-sum": "^1.0.2",
2726
"loader-utils": "^0.2.10",
2827
"parse5": "^1.5.0",
2928
"postcss": "^4.1.16",
30-
"postcss-nested": "^0.3.2",
3129
"postcss-selector-parser": "^1.1.2"
3230
},
3331
"peerDependencies": {

test/fixtures/scoped-css.vue

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
<style scoped>
2-
body, h2 {
2+
.test {
33
color: yellow;
44
}
5-
:scope {
6-
color: red;
7-
}
8-
div:scope.test {
9-
color: blue;
10-
}
115
h1 {
126
color: green;
137
}

test/test.js

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,22 +94,13 @@ describe('vue-loader', function () {
9494
entry: './test/fixtures/scoped-css.js'
9595
}, function (window) {
9696
var module = window.testModule
97-
var cls = '.v-' + hash(require.resolve('./fixtures/scoped-css.vue'))
9897
expect(module.template).to.contain(
99-
'<div class="' + cls.slice(1) + '"><h1>hi</h1></div>\n' +
100-
'<p class="abc def ' + cls.slice(1) + '">hi</p>'
98+
'<div _v-1=""><h1 _v-1="">hi</h1></div>\n' +
99+
'<p class="abc def" _v-1="">hi</p>'
101100
)
102101
var style = window.document.querySelector('style').textContent
103-
// lift selectors that start with body
104-
expect(style).to.contain('body {\n color: yellow;\n}')
105-
expect(style).not.to.contain(cls + ' body')
106-
expect(style).to.contain(cls + ' h2 {\n color: yellow;\n}')
107-
// lift and replace :scope inside compound selectors
108-
expect(style).to.contain('\ndiv' + cls + '.test {\n color: blue;\n}')
109-
// lift :scope
110-
expect(style).to.contain('\n' + cls + ' {\n color: red;\n}')
111-
// nest normal selectors
112-
expect(style).to.contain('\n' + cls + ' h1 {\n color: green;\n}')
102+
expect(style).to.contain('.test[_v-1] {\n color: yellow;\n}')
103+
expect(style).to.contain('h1[_v-1] {\n color: green;\n}')
113104
done()
114105
})
115106
})
@@ -121,8 +112,7 @@ describe('vue-loader', function () {
121112
var styles = window.document.querySelectorAll('style')
122113
expect(styles[0].textContent).to.contain('h1 { color: red; }')
123114
// import with scoped
124-
var cls = '.v-' + hash(require.resolve('./fixtures/import-scoped.css'))
125-
expect(styles[1].textContent).to.contain(cls + ' h1 {\n color: green;\n}')
115+
expect(styles[1].textContent).to.contain('h1[_v-2] { color: green; }')
126116
done()
127117
})
128118
})

0 commit comments

Comments
 (0)