fuse-box
Version:
Fuse-Box a bundler that does it right
175 lines (173 loc) • 6.03 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const path = require("path");
let vueCompiler;
let vueTranspiler;
let typescriptTranspiler;
let babelCore;
let babelConfig;
class VuePluginClass {
constructor(options = {}) {
this.options = options;
this.test = /\.vue$/;
}
init(context) {
context.allowExtension(".vue");
}
transform(file) {
const context = file.context;
if (context.useCache) {
let cached = context.cache.getStaticCache(file);
if (cached) {
file.isLoaded = true;
if (cached.sourceMap) {
file.sourceMap = cached.sourceMap;
}
file.analysis.skip();
file.analysis.dependencies = cached.dependencies;
file.contents = cached.contents;
return;
}
}
file.loadContents();
if (!vueCompiler) {
vueCompiler = require("vue-template-compiler");
vueTranspiler = require("vue-template-es2015-compiler");
}
let result = vueCompiler.parseComponent(file.contents, this.options);
if (result.template && result.template.type === "template") {
let templateLang = (result.template.attrs) ? result.template.attrs.lang : null;
return compileTemplateContent(context, templateLang, result.template.content).then(html => {
var styles = extractStyle(result.styles);
if (styles.some)
file.addStringDependency("fuse-box-css");
file.contents = compileScript(file, this.options, context, html, result.script, styles);
file.analysis.parseUsingAcorn();
file.analysis.analyze();
if (context.useCache) {
context.emitJavascriptHotReload(file);
context.cache.writeStaticCache(file, file.sourceMap);
}
return true;
}).catch(err => {
console.error(err);
});
}
}
}
exports.VuePluginClass = VuePluginClass;
;
function extractStyle(styleList) {
var rv = { scoped: '', global: '', some: false };
if (styleList)
for (let s in styleList) {
let style = styleList[s], content = style.content;
if (style.lang)
console.error('Not supported yet: vue single-file-component style languages other than CSS');
if ('style' === style.type)
rv[style.scoped ? 'scoped' : 'global'] += content;
}
rv.some = !!(rv.global || rv.scoped);
return rv;
}
function toFunction(code) {
return vueTranspiler('function render () {' + code + '}');
}
function compileTemplateContent(context, engine, content) {
return new Promise((resolve, reject) => {
if (!engine) {
return resolve(content);
}
const cons = require('consolidate');
if (!cons[engine]) {
return content;
}
cons[engine].render(content, {
filename: 'base',
basedir: context.homeDir,
includeDir: context.homeDir
}, (err, html) => {
if (err) {
return reject(err);
}
resolve(html);
});
});
}
function compileScript(file, options, context, html, script, styles) {
let lang = script.attrs.lang;
if (lang === 'babel') {
return compileBabel(file, options, context, html, script, styles);
}
else {
return compileTypeScript(file, options, context, html, script, styles);
}
}
function compileTypeScript(file, options, context, html, script, styles) {
if (!typescriptTranspiler) {
typescriptTranspiler = require("typescript");
}
try {
const jsTranspiled = typescriptTranspiler.transpileModule(script.content, context.getTypeScriptConfig());
return reduceVueToScript(file, jsTranspiled.outputText, html, styles);
}
catch (err) {
console.log(err);
}
return '';
}
function compileBabel(file, options, context, html, script, styles) {
if (!babelCore) {
babelCore = require("babel-core");
if (options.babel !== undefined) {
babelConfig = options.babel.config;
}
else {
let babelRcPath = path.join(context.appRoot, `.babelrc`);
if (fs.existsSync(babelRcPath)) {
let babelRcConfig = fs.readFileSync(babelRcPath).toString();
if (babelRcConfig)
babelConfig = JSON.parse(babelRcConfig);
}
}
if (babelConfig === undefined) {
babelConfig = { plugins: ['transform-es2015-modules-commonjs'] };
}
}
try {
let jsTranspiled = babelCore.transform(script.content, babelConfig);
return reduceVueToScript(file, jsTranspiled.code, html, styles);
}
catch (err) {
console.log(err);
}
return '';
}
function reduceVueToScript(file, jsContent, html, styles) {
const compiled = vueCompiler.compile(html);
var cssInclude = '';
if (styles.global)
cssInclude += styles.global;
if (styles.scoped)
console.error('Functionality not yet supported: scoped style');
if (cssInclude)
cssInclude =
'require("fuse-box-css")(' +
JSON.stringify(file.info.fuseBoxPath) +
',' +
JSON.stringify(cssInclude) +
');';
return `var _p = {};
var _v = function(exports){${jsContent}
};${cssInclude}
_p.render = ` + toFunction(compiled.render) + `
_p.staticRenderFns = [ ` + compiled.staticRenderFns.map(toFunction).join(',') + ` ];
var _e = {}; _v(_e); Object.assign(_e.default.options||_e.default, _p)
module.exports = _e
`;
}
exports.VuePlugin = (options) => {
return new VuePluginClass(options);
};
//# sourceMappingURL=VuePlugin.js.map