-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
135 lines (113 loc) · 3.71 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
const path = require('path')
const loaderUtils = require('loader-utils')
const compiler = require('vue-template-compiler')
const transpile = require('vue-template-es2015-compiler')
const hash = require('hash-sum')
const cache = Object.create(null)
const genId = file => cache[file] || (cache[file] = hash(file))
// vue compiler module for using transforming `<tag>:<attribute>` to `require`
const defaultTransformToRequire = {
img: 'src'
}
let transformToRequire = defaultTransformToRequire
const defaultCompileOptions = {
modules: [{
postTransformNode(el) {
for (const tag in transformToRequire) {
if (el.tag === tag && el.attrs) {
const attributes = transformToRequire[tag]
if (typeof attributes === 'string') {
el.attrs.some(attr => rewrite(attr, attributes))
} else if (Array.isArray(attributes)) {
attributes.forEach(item => el.attrs.some(attr => rewrite(attr, item)))
}
}
}
}
}]
}
function rewrite(attr, name) {
if (attr.name === name) {
let value = attr.value
const isStatic = value.charAt(0) === '"' && value.charAt(value.length - 1) === '"'
if (!isStatic) {
return
}
const firstChar = value.charAt(1)
if (firstChar === '.' || firstChar === '~') {
if (firstChar === '~') {
value = '"' + value.slice(2)
}
attr.value = `require(${value})`
}
return true
}
}
module.exports = function (content) {
this.cacheable()
const isProduction = this.minimize || process.env.NODE_ENV === 'production'
const isServer = this.options.target === 'node'
const query = loaderUtils.getOptions(this)
const vueOptions = this.options.__vueOptions__ = this.options.__vueOptions__ ||
Object.assign({}, this.options.vue, this.vue, query)
if (vueOptions.transformToRequire) {
transformToRequire = Object.assign(
{},
defaultTransformToRequire,
vueOptions.transformToRequire
)
}
const compiled = compiler.compile(content, Object.assign({
preserveWhitespace: vueOptions.preserveWhitespace
}, defaultCompileOptions))
const id = genId(path.relative(this.options.context, this.resourcePath))
compiled.errors.forEach(error => {
this.emitError('template syntax error ' + error)
})
const bubleOptions = vueOptions.buble
let output = transpile(writeRenderCode(compiled, id), bubleOptions)
// mark with stripped (this enables Vue to use correct runtime proxy detection)
if (!isProduction && (
!bubleOptions || !bubleOptions.transforms ||
bubleOptions.transforms.stripWith !== false
)) {
output += `\nrender._withStripped = true`
}
if (!isServer && !this.minimize &&
process.env.NODE_ENV !== 'production') {
output += writeHotReloadCode(id)
}
return output
}
function writeRenderCode(compiled, id) {
return [
`var render = ${toFunction(compiled.render)}`,
`var staticRenderFns = [${compiled.staticRenderFns.map(toFunction).join(',')}]`,
'module.exports = function (options) {',
' options = options || {}',
' options.render = render',
' options.staticRenderFns = staticRenderFns',
' if (module.hot) {',
` api && api.createRecord("${id}", options)`,
' }',
' return options',
'}\n'
].join('\n')
}
function writeHotReloadCode(id) {
return [
'\nvar api = null',
'if (module.hot) {(function () {',
' api = require("vue-hot-reload-api")',
' api.install(require("vue"))',
' if (!api.compatible) return',
' module.hot.accept()',
' if (module.hot.data) {',
` api.rerender("${id}", { render: render, staticRenderFns: staticRenderFns })`,
' }',
'})()}\n'
].join('\n')
}
function toFunction(code) {
return `function(){${code}}`
}