Skip to content

Commit f354290

Browse files
committed
refactor
1 parent 39f322d commit f354290

File tree

3 files changed

+78
-59
lines changed

3 files changed

+78
-59
lines changed

lib/loader.js

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
var loaderUtils = require('loader-utils')
2+
var selectorPath = require.resolve('./selector')
3+
var parserPath = require.resolve('./parser')
4+
var cssRewriterPath = require.resolve('./css-rewriter')
25

36
module.exports = function (content) {
47
var self = this
@@ -26,74 +29,76 @@ module.exports = function (content) {
2629
script: 'js'
2730
}
2831

29-
/**
30-
* Determine the loaders to use for an extracted part.
31-
*
32-
* @param {String} part - style|script|template
33-
* @param {String} lang
34-
* @return {String}
35-
*/
36-
function loader (part, lang) {
37-
lang = lang || defaultLang[part]
38-
var loader = loaders[lang] !== undefined
39-
? loaders[lang]
40-
: loaderPrefix[part] + lang
41-
return loader ? loader + '!' : ''
32+
function getRequire (type, part, index) {
33+
return 'require(' +
34+
loaderUtils.stringifyRequest(self,
35+
// disable system loaders (except post loaders)
36+
'-!' +
37+
// check for local CSS rewrite
38+
(part.local ? cssRewriterPath + '!' : '') +
39+
// get loader string for pre-processors
40+
getPreprocessorString(type, part.lang) +
41+
// select the corresponding part from the vue file
42+
getSelectorString(type, index || 0) +
43+
// the url to the actual vuefile
44+
vueUrl
45+
) +
46+
')\n'
4247
}
4348

44-
/**
45-
* Generate a require call for an extracted part.
46-
*
47-
* @param {String} part - style|script|template
48-
* @param {String} lang
49-
* @return {String}
50-
*/
51-
function getRequire (part, lang) {
49+
function getRequireForImport (include) {
5250
return 'require(' +
5351
loaderUtils.stringifyRequest(self,
54-
'-!' + loader(part, lang) +
55-
require.resolve('./selector.js') + '?' + part + '/' + lang + '!' +
56-
vueUrl
52+
'-!' +
53+
getPreprocessorString(include.type, include.lang) +
54+
include.src
5755
) +
58-
')'
56+
')\n'
57+
}
58+
59+
function getPreprocessorString (type, lang) {
60+
lang = lang || defaultLang[type]
61+
var loader = loaders[lang] !== undefined
62+
? loaders[lang]
63+
: loaderPrefix[type] + lang
64+
return loader ? loader + '!' : ''
5965
}
6066

61-
var url = '!!' + require.resolve('./parser.js') + '!' + vueUrl
67+
function getSelectorString (type, index) {
68+
return selectorPath +
69+
'?type=' + type +
70+
'&index=' + index + '!'
71+
}
72+
73+
var url = '!!' + parserPath + '!' + vueUrl
6274
this.loadModule(url, function (err, source) {
6375
if (err) return cb(err)
6476

6577
// up to this part, what we have done is basically executing
6678
// parser.js on the raw vue file and get the parsing result
6779
// which is an object that contains info about the vue file.
6880
var parts = self.exec(source, url)
69-
var lang
70-
71-
// add require for all the src imports
72-
for (var i = 0; i < parts.includes.length; i++) {
73-
var include = parts.includes[i]
74-
output += 'require(' + loaderUtils.stringifyRequest(this,
75-
'-!' + loader(include.type, include.lang) + include.src
76-
) + ')\n'
77-
}
7881

79-
// add require for styles
80-
for (lang in parts.style) {
81-
output += getRequire('style', lang) + '\n'
82-
}
82+
// add requires for src imports
83+
parts.includes.forEach(function (include) {
84+
output += getRequireForImport(include)
85+
})
86+
87+
// add requires for styles
88+
parts.style.forEach(function (style, i) {
89+
output += getRequire('style', style, i)
90+
})
8391

84-
// add require for script
85-
for (lang in parts.script) {
86-
output += 'module.exports = ' + getRequire('script', lang) + '\n'
92+
// only one script tag allowed
93+
if (parts.script.length) {
94+
output += 'module.exports = ' +
95+
getRequire('script', parts.script[0])
8796
}
8897

89-
// add require for template
90-
var hasTemplate = false
91-
for (lang in parts.template) {
92-
if (hasTemplate) {
93-
return cb(new Error('Only one template element allowed per vue component!'))
94-
}
95-
output += 'module.exports.template = ' + getRequire('template', lang)
96-
hasTemplate = true
98+
// only one template tag allowed
99+
if (parts.template.length) {
100+
output += 'module.exports.template = ' +
101+
getRequire('template', parts.template[0])
97102
}
98103

99104
// done

lib/parser.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@ module.exports = function (content) {
55
this.cacheable()
66
var cb = this.async()
77
var output = {
8-
template: {},
9-
style: {},
10-
script: {},
8+
template: [],
9+
style: [],
10+
script: [],
1111
includes: []
1212
}
1313

1414
var fragment = parser.parseFragment(content)
1515

1616
fragment.childNodes.forEach(function (node) {
1717
var type = node.tagName
18-
var lang = getAttribute(node, 'lang') || ''
18+
var lang = getAttribute(node, 'lang')
1919
var src = getAttribute(node, 'src')
20+
var local = getAttribute(node, 'local')
2021

2122
if (src) {
2223
output.includes.push({
@@ -35,6 +36,15 @@ module.exports = function (content) {
3536
return
3637
}
3738

39+
if (
40+
(type === 'script' || type === 'template') &&
41+
output[type].length > 0
42+
) {
43+
return cb(new Error(
44+
'Only one <script> or <template> tag is allowed inside a Vue component.'
45+
))
46+
}
47+
3848
// Work around changes in parse5 >= 1.2.0
3949
if (node.childNodes[0].nodeName === '#document-fragment') {
4050
node = node.childNodes[0]
@@ -45,7 +55,11 @@ module.exports = function (content) {
4555

4656
var start = node.childNodes[0].__location.start
4757
var end = node.childNodes[node.childNodes.length - 1].__location.end
48-
output[type][lang] = content.substring(start, end).trim()
58+
output[type].push({
59+
lang: lang,
60+
local: local,
61+
content: content.substring(start, end).trim()
62+
})
4963
})
5064

5165
cb(null, 'module.exports = ' + JSON.stringify(output))

lib/selector.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
var loaderUtils = require('loader-utils')
2+
13
module.exports = function () {
24
this.cacheable()
35
var cb = this.async()
4-
var path = this.query.substr(1).split('/')
6+
var query = loaderUtils.parseQuery(this.query)
57

68
var self = this
79
var url = '!!' + require.resolve('./parser.js') + '!' + this.resource
810
this.loadModule(url, function (err, source) {
911
if (err) return cb(err)
1012
var parts = self.exec(source, url)
11-
var type = path[0]
12-
var lang = path[1] || ''
13-
cb(null, parts[type][lang])
13+
cb(null, parts[query.type][query.index].content)
1414
})
1515
}

0 commit comments

Comments
 (0)