UNPKG

ember-introjs

Version:
232 lines (184 loc) 7.28 kB
'use strict'; var Filter = require('broccoli-persistent-filter'); var clone = require('clone'); var fs = require('fs'); var stringify = require('json-stable-stringify'); var mergeTrees = require('broccoli-merge-trees'); var funnel = require('broccoli-funnel'); var crypto = require('crypto'); var hashForDep = require('hash-for-dep'); var ParallelApi = require('./lib/parallel-api'); function getExtensionsRegex(extensions) { return extensions.map(function(extension) { return new RegExp('\.' + extension + '$'); }); } function replaceExtensions(extensionsRegex, name) { for (var i = 0, l = extensionsRegex.length; i < l; i++) { name = name.replace(extensionsRegex[i], ''); } return name; } function Babel(inputTree, _options) { if (!(this instanceof Babel)) { return new Babel(inputTree, _options); } var options = _options || {}; options.persist = 'persist' in options ? options.persist : true; options.async = true; Filter.call(this, inputTree, options); delete options.persist; delete options.async; delete options.annotation; delete options.description; this.console = options.console || console; delete options.console; this.options = options; this.extensions = this.options.filterExtensions || ['js']; this.extensionsRegex = getExtensionsRegex(this.extensions); this.name = 'broccoli-babel-transpiler'; if (this.options.helperWhiteList) { this.helperWhiteList = this.options.helperWhiteList; } // Note, Babel does not support this option so we must save it then // delete it from the options hash delete this.options.helperWhiteList; if (this.options.browserPolyfill) { var babelCorePath = require.resolve('babel-core'); babelCorePath = babelCorePath.replace(/\/babel-core\/.*$/, '/babel-core'); var polyfill = funnel(babelCorePath, { files: ['browser-polyfill.js'] }); this.inputTree = mergeTrees([polyfill, inputTree]); } else { this.inputTree = inputTree; } delete this.options.browserPolyfill; } Babel.prototype = Object.create(Filter.prototype); Babel.prototype.constructor = Babel; Babel.prototype.targetExtension = ['js']; Babel.prototype.baseDir = function() { return __dirname; }; Babel.prototype.transform = function(string, options) { return ParallelApi.transformString(string, options); }; /* * @private * * @method optionsString * @returns a stringified version of the input options */ Babel.prototype.optionsHash = function() { var options = this.options; var hash = {}; var key, value; if (!this._optionsHash) { for (key in options) { value = options[key]; hash[key] = (typeof value === 'function') ? (value + '') : value; } if (options.plugins) { hash.plugins = []; var cacheableItems = options.plugins.slice(); for (var i = 0; i < cacheableItems.length; i++) { var item = cacheableItems[i]; var type = typeof item; var augmentsCacheKey = false; var providesBaseDir = false; var requiresBaseDir = true; if (type === 'function') { augmentsCacheKey = typeof item.cacheKey === 'function'; providesBaseDir = typeof item.baseDir === 'function'; if (augmentsCacheKey) { hash.plugins.push(item.cacheKey()); } if (providesBaseDir) { var depHash = hashForDep(item.baseDir()); hash.plugins.push(depHash); } if (!providesBaseDir && requiresBaseDir){ // prevent caching completely if the plugin doesn't provide baseDir // we cannot ensure that we aren't causing invalid caching pain... this.console.warn('broccoli-babel-transpiler is opting out of caching due to a plugin that does not provide a caching strategy: `' + item + '`.'); hash.plugins.push((new Date).getTime() + '|' + Math.random()); break; } } else if (Array.isArray(item)) { item.forEach(function(part) { cacheableItems.push(part); }); continue; } else if (type !== 'object' || item === null) { // handle native strings, numbers, or null (which can JSON.stringify properly) hash.plugins.push(item); continue; } else if (type === 'object' && (typeof item.baseDir === 'function')) { hash.plugins.push(hashForDep(item.baseDir())); if (typeof item.cacheKey === 'function') { hash.plugins.push(item.cacheKey()); } } else if (type === 'object') { // iterate all keys in the item and push them into the cache var keys = Object.keys(item); keys.forEach(function(key) { cacheableItems.push(key); cacheableItems.push(item[key]); }); continue; } else { this.console.warn('broccoli-babel-transpiler is opting out of caching due to an non-cacheable item: `' + item + '` (' + type + ').'); hash.plugins.push((new Date).getTime() + '|' + Math.random()); break; } } } this._optionsHash = crypto.createHash('md5').update(stringify(hash), 'utf8').digest('hex'); } return this._optionsHash; }; Babel.prototype.cacheKeyProcessString = function(string, relativePath) { return this.optionsHash() + Filter.prototype.cacheKeyProcessString.call(this, string, relativePath); }; Babel.prototype.processString = function(string, relativePath) { var options = this.copyOptions(); options.filename = options.sourceMapTarget = options.sourceFileName = relativePath; if (options.moduleId === true) { options.moduleId = replaceExtensions(this.extensionsRegex, options.filename); } var plugin = this; return this.transform(string, options) .then(function (transpiled) { if (plugin.helperWhiteList) { var invalidHelpers = transpiled.metadata.usedHelpers.filter(function(helper) { return plugin.helperWhiteList.indexOf(helper) === -1; }, plugin); validateHelpers(invalidHelpers, relativePath); } return transpiled.code; }); }; Babel.prototype.copyOptions = function() { var cloned = clone(this.options); if (cloned.filterExtensions) { delete cloned.filterExtensions; } return cloned; }; function validateHelpers(invalidHelpers, relativePath) { if (invalidHelpers.length > 0) { var message = relativePath + ' was transformed and relies on `' + invalidHelpers[0] + '`, which was not included in the helper whitelist. Either add this helper to the whitelist or refactor to not be dependent on this runtime helper.'; if (invalidHelpers.length > 1) { var helpers = invalidHelpers.map(function(item, i) { if (i === invalidHelpers.length - 1) { return '& `' + item; } else if (i === invalidHelpers.length - 2) { return item + '`, '; } return item + '`, `'; }).join(''); message = relativePath + ' was transformed and relies on `' + helpers + '`, which were not included in the helper whitelist. Either add these helpers to the whitelist or refactor to not be dependent on these runtime helpers.'; } throw new Error(message); } } module.exports = Babel;