309 lines
No EOL
8.2 KiB
JavaScript
Executable file
309 lines
No EOL
8.2 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
|
|
|
const Asset = require('../Asset');
|
|
const localRequire = require('../utils/localRequire');
|
|
const md5 = require('../utils/md5');
|
|
|
|
var _require = require('uglify-es');
|
|
|
|
const minify = _require.minify;
|
|
|
|
|
|
class VueAsset extends Asset {
|
|
constructor(name, pkg, options) {
|
|
super(name, pkg, options);
|
|
this.type = 'js';
|
|
}
|
|
|
|
parse(code) {
|
|
var _this = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
// Is being used in component-compiler-utils, errors if not installed...
|
|
_this.vueTemplateCompiler = yield localRequire('vue-template-compiler', _this.name);
|
|
_this.vue = yield localRequire('@vue/component-compiler-utils', _this.name);
|
|
|
|
return _this.vue.parse({
|
|
source: code,
|
|
needMap: _this.options.sourceMaps,
|
|
filename: _this.relativeName, // Used for sourcemaps
|
|
sourceRoot: '' // Used for sourcemaps. Override so it doesn't use cwd
|
|
});
|
|
})();
|
|
}
|
|
|
|
generate() {
|
|
var _this2 = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
let descriptor = _this2.ast;
|
|
let parts = [];
|
|
|
|
if (descriptor.script) {
|
|
parts.push({
|
|
type: descriptor.script.lang || 'js',
|
|
value: descriptor.script.content,
|
|
sourceMap: descriptor.script.map
|
|
});
|
|
}
|
|
|
|
if (descriptor.template) {
|
|
parts.push({
|
|
type: descriptor.template.lang || 'html',
|
|
value: descriptor.template.content.trim()
|
|
});
|
|
}
|
|
|
|
if (descriptor.styles) {
|
|
var _iteratorNormalCompletion = true;
|
|
var _didIteratorError = false;
|
|
var _iteratorError = undefined;
|
|
|
|
try {
|
|
for (var _iterator = descriptor.styles[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
let style = _step.value;
|
|
|
|
parts.push({
|
|
type: style.lang || 'css',
|
|
value: style.content.trim(),
|
|
modules: !!style.module
|
|
});
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError = true;
|
|
_iteratorError = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
|
_iterator.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError) {
|
|
throw _iteratorError;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return parts;
|
|
})();
|
|
}
|
|
|
|
postProcess(generated) {
|
|
var _this3 = this;
|
|
|
|
return _asyncToGenerator(function* () {
|
|
let result = [];
|
|
|
|
let hasScoped = _this3.ast.styles.some(function (s) {
|
|
return s.scoped;
|
|
});
|
|
let id = md5(_this3.name).slice(-6);
|
|
let scopeId = hasScoped ? `data-v-${id}` : null;
|
|
let optsVar = '$' + id;
|
|
|
|
// Generate JS output.
|
|
let js = _this3.ast.script ? generated[0].value : '';
|
|
let supplemental = `
|
|
var ${optsVar} = exports.default || module.exports;
|
|
if (typeof ${optsVar} === 'function') {
|
|
${optsVar} = ${optsVar}.options;
|
|
}
|
|
`;
|
|
|
|
supplemental += _this3.compileTemplate(generated, scopeId, optsVar);
|
|
supplemental += _this3.compileCSSModules(generated, optsVar);
|
|
supplemental += _this3.compileHMR(generated, optsVar);
|
|
|
|
if (_this3.options.minify && supplemental) {
|
|
var _minify = minify(supplemental, { toplevel: true });
|
|
|
|
let code = _minify.code,
|
|
error = _minify.error;
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
supplemental = code;
|
|
}
|
|
|
|
js += supplemental;
|
|
|
|
if (js) {
|
|
result.push({
|
|
type: 'js',
|
|
value: js
|
|
});
|
|
}
|
|
|
|
let map = generated.find(function (r) {
|
|
return r.type === 'map';
|
|
});
|
|
if (map) {
|
|
result.push(map);
|
|
}
|
|
|
|
let css = _this3.compileStyle(generated, scopeId);
|
|
if (css) {
|
|
result.push({
|
|
type: 'css',
|
|
value: css
|
|
});
|
|
}
|
|
|
|
return result;
|
|
})();
|
|
}
|
|
|
|
compileTemplate(generated, scopeId, optsVar) {
|
|
let html = generated.find(r => r.type === 'html');
|
|
if (html) {
|
|
let isFunctional = this.ast.template.attrs.functional;
|
|
let template = this.vue.compileTemplate({
|
|
source: html.value,
|
|
filename: this.relativeName,
|
|
compiler: this.vueTemplateCompiler,
|
|
isProduction: this.options.production,
|
|
isFunctional,
|
|
compilerOptions: {
|
|
scopeId
|
|
}
|
|
});
|
|
|
|
if (Array.isArray(template.errors) && template.errors.length >= 1) {
|
|
throw new Error(template.errors[0]);
|
|
}
|
|
|
|
return `
|
|
/* template */
|
|
Object.assign(${optsVar}, (function () {
|
|
${template.code}
|
|
return {
|
|
render: render,
|
|
staticRenderFns: staticRenderFns,
|
|
_compiled: true,
|
|
_scopeId: ${JSON.stringify(scopeId)},
|
|
functional: ${JSON.stringify(isFunctional)}
|
|
};
|
|
})());
|
|
`;
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
compileCSSModules(generated, optsVar) {
|
|
let cssRenditions = generated.filter(r => r.type === 'css');
|
|
let cssModulesCode = '';
|
|
this.ast.styles.forEach((style, index) => {
|
|
if (style.module) {
|
|
let cssModules = JSON.stringify(cssRenditions[index].cssModules);
|
|
let name = style.module === true ? '$style' : style.module;
|
|
cssModulesCode += `\nthis[${JSON.stringify(name)}] = ${cssModules};`;
|
|
}
|
|
});
|
|
|
|
if (cssModulesCode) {
|
|
cssModulesCode = `function hook(){${cssModulesCode}\n}`;
|
|
|
|
let isFunctional = this.ast.template && this.ast.template.attrs.functional;
|
|
if (isFunctional) {
|
|
return `
|
|
/* css modules */
|
|
(function () {
|
|
${cssModulesCode}
|
|
${optsVar}._injectStyles = hook;
|
|
var originalRender = ${optsVar}.render;
|
|
${optsVar}.render = function (h, context) {
|
|
hook.call(context);
|
|
return originalRender(h, context);
|
|
};
|
|
})();
|
|
`;
|
|
} else {
|
|
return `
|
|
/* css modules */
|
|
(function () {
|
|
${cssModulesCode}
|
|
${optsVar}.beforeCreate = ${optsVar}.beforeCreate ? ${optsVar}.beforeCreate.concat(hook) : [hook];
|
|
})();
|
|
`;
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
compileStyle(generated, scopeId) {
|
|
return generated.filter(r => r.type === 'css').reduce((p, r, i) => {
|
|
let css = r.value;
|
|
let scoped = this.ast.styles[i].scoped;
|
|
|
|
// Process scoped styles if needed.
|
|
if (scoped) {
|
|
var _vue$compileStyle = this.vue.compileStyle({
|
|
source: css,
|
|
filename: this.relativeName,
|
|
id: scopeId,
|
|
scoped
|
|
});
|
|
|
|
let code = _vue$compileStyle.code,
|
|
errors = _vue$compileStyle.errors;
|
|
|
|
|
|
if (errors.length) {
|
|
throw errors[0];
|
|
}
|
|
|
|
css = code;
|
|
}
|
|
|
|
return p + css;
|
|
}, '');
|
|
}
|
|
|
|
compileHMR(generated, optsVar) {
|
|
if (!this.options.hmr) {
|
|
return '';
|
|
}
|
|
|
|
this.addDependency('vue-hot-reload-api');
|
|
this.addDependency('vue');
|
|
|
|
let cssHMR = '';
|
|
if (this.ast.styles.length) {
|
|
cssHMR = `
|
|
var reloadCSS = require('_css_loader');
|
|
module.hot.dispose(reloadCSS);
|
|
module.hot.accept(reloadCSS);
|
|
`;
|
|
}
|
|
|
|
let isFunctional = this.ast.template && this.ast.template.attrs.functional;
|
|
|
|
return `
|
|
/* hot reload */
|
|
(function () {
|
|
if (module.hot) {
|
|
var api = require('vue-hot-reload-api');
|
|
api.install(require('vue'));
|
|
if (api.compatible) {
|
|
module.hot.accept();
|
|
if (!module.hot.data) {
|
|
api.createRecord('${optsVar}', ${optsVar});
|
|
} else {
|
|
api.${isFunctional ? 'rerender' : 'reload'}('${optsVar}', ${optsVar});
|
|
}
|
|
}
|
|
|
|
${cssHMR}
|
|
}
|
|
})();`;
|
|
}
|
|
}
|
|
|
|
module.exports = VueAsset; |