UNPKG

@berun/fuse-box-plugin-babel

Version:

Fuse Box Babel Plugin

181 lines (180 loc) 6.45 kB
// Forked from fuse-box/fuse-box with only change being to allow // use of context at file level for each transform, not class level // this allows use of this plugin in a Fuse-Box plugin chain // Copyright (c) 2016 fuse-box var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs")); const path = __importStar(require("path")); let babelCore; /** * @export * @class FuseBoxBabelPlugin * @implements {Plugin} */ class BabelPluginClass { constructor(opts = {}) { /** * We can add tsx and ts here as well * Because Babel won't capture it just being a Plugin * Typescript files are handled before any external plugin is executed */ this.extensions = ['.jsx']; this.test = /\.(j|t)s(x)?$/; this.limit2project = true; this.config = {}; this.configPrinted = false; this.configLoaded = false; // if it is an object containing only a babel config if (opts.config === undefined && opts.test === undefined && opts.limit2project === undefined && opts.extensions === undefined && Object.keys(opts).length) { this.config = opts; return; } if (opts.config) { this.config = opts.config; } if (opts.extensions !== undefined) { this.extensions = opts.extensions; if (opts.test === undefined) { this.test = string2RegExp(opts.extensions.join('|')); } } if (opts.test !== undefined) { this.test = opts.test; } if (opts.limit2project !== undefined) { this.limit2project = opts.limit2project; } } /** * @see this.init */ handleBabelRc(context) { if (this.configLoaded) { return; } let babelRcConfig; const babelRcPath = path.join(context.appRoot, `.babelrc`); if (fs.existsSync(babelRcPath)) { babelRcConfig = fs.readFileSync(babelRcPath).toString(); if (babelRcConfig) { try { babelRcConfig = { ...JSON.parse(babelRcConfig), ...this.config }; } catch (ex) { console.error(`Error parsing .babelrc ${ex.message}`); process.exit(1); } } } if (babelRcConfig) { this.config = babelRcConfig; } this.configLoaded = true; } /** * @param {WorkFlowContext} context */ init(context) { if (Array.isArray(this.extensions)) { this.extensions.forEach(ext => context.allowExtension(ext)); } this.handleBabelRc(context); } /** * @param {File} file */ transform(file, ast) { file.wasTranspiled = true; if (!babelCore) { // eslint-disable-next-line global-require babelCore = require('@babel/core'); } if (this.configPrinted === false && file.context.doLog === true) { file.context.debug('BabelPlugin', `\n\tConfiguration: ${JSON.stringify(this.config)}`); this.configPrinted = true; } if (file.context.useCache) { if (file.loadFromCache()) { return; } } // contents might not be loaded if using a custom file extension file.loadContents(); // whether we should transform the contents // @TODO needs improvement for the regex matching of what to include // with globs & regex if (this.limit2project === false || file.collection.name === file.context.defaultPackageName) { let result; try { this.config.filename = file.absPath; result = babelCore.transform(file.contents, this.config); } catch (e) { file.analysis.skip(); console.error(e); return; } // By default we would want to limit the babel // And use acorn instead (it's faster) if (result.ast) { file.analysis.loadAst(result.ast); let sourceMaps = result.map; // escodegen does not realy like babel // so a custom function handles tranformation here if needed // This happens only when the code is required regeneration // for example with alises -> in any cases this will stay untouched file.context.setCodeGenerator(ast2 => { const result2 = babelCore.transformFromAst(ast2); sourceMaps = result2.map; return result2.code; }); file.contents = result.code; file.analysis.analyze(); if (sourceMaps) { sourceMaps.file = file.info.fuseBoxPath; sourceMaps.sources = [ `${file.context.sourceMapsRoot}/${file.info.fuseBoxPath}` ]; if (!file.context.inlineSourceMaps) { delete sourceMaps.sourcesContent; } file.sourceMap = JSON.stringify(sourceMaps); } if (file.context.useCache) { file.context.emitJavascriptHotReload(file); file.context.cache.writeStaticCache(file, file.sourceMap); } } } } } exports.BabelPluginClass = BabelPluginClass; exports.BabelPlugin = (opts = {}) => { return new BabelPluginClass(opts); }; function string2RegExp(obj) { let escapedRegEx = obj .replace(/\*/g, '@') .replace(/[.?*+[\]-]/g, '\\$&') .replace(/@@/g, '.*', 'i') .replace(/@/g, '\\w{1,}', 'i'); if (escapedRegEx.indexOf('$') === -1) { escapedRegEx += '$'; } return new RegExp(escapedRegEx); }