diff --git a/.yarnclean b/.yarnclean new file mode 100644 index 00000000000..25bdd148295 --- /dev/null +++ b/.yarnclean @@ -0,0 +1,42 @@ +# test directories +__tests__ +test +tests +powered-test + +# asset directories +docs +doc +website +images +assets + +# examples +example +examples + +# code coverage directories +coverage +.nyc_output + +# build scripts +Makefile +Gulpfile.js +Gruntfile.js + +# configs +.tern-project +.gitattributes +.editorconfig +.*ignore +.eslintrc +.jshintrc +.flowconfig +.documentup.json +.yarn-metadata.json +.*.yml +*.yml + +# misc +*.gz +*.md diff --git a/lib/stripped-build-plugins.js b/lib/stripped-build-plugins.js index af4310c6d25..f5011b4621d 100644 --- a/lib/stripped-build-plugins.js +++ b/lib/stripped-build-plugins.js @@ -55,12 +55,9 @@ module.exports = function(environment) { plugins.push( [FilterImports, filteredImports], + [StripFilteredImports, filteredImports], [TransformBlockScoping, { 'throwIfClosureRequired': true }] ); - if (environment === 'production') { - plugins.push([StripFilteredImports, 'ember-data/-debug']); - } - return { plugins, postTransformPlugins }; }; diff --git a/lib/transforms/babel-plugin-remove-imports.js b/lib/transforms/babel-plugin-remove-imports.js index aec7d8852d0..3e85e463d0f 100644 --- a/lib/transforms/babel-plugin-remove-imports.js +++ b/lib/transforms/babel-plugin-remove-imports.js @@ -1,15 +1,15 @@ -var path = require('path'); - -function removeImports() { +function PluginRemoveFilteredImports() { var importDeclarationsToRemove; var filteredImports; + var filteredImportNames; return { name: 'remove-filtered-imports', visitor: { Program: { enter: function(_, state) { - filteredImports = state.opts instanceof Array ? state.opts : (state.opts ? [state.opts] : []); + filteredImports = state.opts || {}; + filteredImportNames = Object.keys(filteredImports); importDeclarationsToRemove = []; }, exit: function() { @@ -24,8 +24,39 @@ function removeImports() { ImportDeclaration: function(path) { var name = path.node.source.value; - if (filteredImports.indexOf(name) !== -1) { - importDeclarationsToRemove.push(path); + if (filteredImportNames.indexOf(name) !== -1) { + if (filteredImports[name] === true || filteredImports[name] === '*') { + importDeclarationsToRemove.push(path); + } else { + let removables = []; + let imports = path.node.specifiers; + const hasSpecifiers = imports.length > 0; + + for (let i = 0; i < imports.length; i++) { + if (imports[i].type === 'ImportNamespaceSpecifier') { + continue; + } + + let specifier = imports[i].imported; + + if (!specifier) { + debugger; + } + + if (filteredImports[name].indexOf(specifier.name) !== -1) { + removables.push(imports[i]); + } + } + + if (hasSpecifiers && removables.length === imports.length) { + importDeclarationsToRemove.push(path); + } else { + for (let i = 0; i < removables.length; i++) { + let index = imports.indexOf(removables[i]); + imports.splice(index, 1); + } + } + } } } @@ -33,8 +64,8 @@ function removeImports() { }; } -removeImports.baseDir = function() { +PluginRemoveFilteredImports.baseDir = function() { return __dirname; }; -module.exports = removeImports; +module.exports = PluginRemoveFilteredImports; diff --git a/node-tests/unit/babel-plugin-remove-imports-test.js b/node-tests/unit/babel-plugin-remove-imports-test.js new file mode 100644 index 00000000000..22c36b69937 --- /dev/null +++ b/node-tests/unit/babel-plugin-remove-imports-test.js @@ -0,0 +1,110 @@ +const BroccoliTestHelper = require('broccoli-test-helper'); +const co = require('co'); +const Babel = require('broccoli-babel-transpiler'); +const chai = require('ember-cli-blueprint-test-helpers/chai'); +const stripIndent = require('common-tags').stripIndent; +const StripFilteredImports = require('../../lib/transforms/babel-plugin-remove-imports'); + +const { expect } = chai; +const createTempDir = BroccoliTestHelper.createTempDir; +const createBuilder = BroccoliTestHelper.createBuilder; + +function stripNewlines(str) { + return str.replace(/[\r\n]/g, ''); +} + +describe('Unit: babel-plugin-remove-filtered-imports', function() { + let plugins, pluginOptions; + let input, output; + + function transform(code) { + return co.wrap(function* () { + input.write({ 'test.js': code }); + let babel = new Babel(input.path(), { + plugins + }); + + output = createBuilder(babel); + + yield output.build(); + })(); + } + + function getOutput() { + const transpiled = output.read(); + + return stripNewlines(transpiled['test.js']); + } + + beforeEach(co.wrap(function* () { + pluginOptions = {}; + + plugins = [ + [StripFilteredImports, pluginOptions] + ]; + + input = yield createTempDir(); + })); + + afterEach(co.wrap(function* () { + if (input) { + yield input.dispose(); + } + if (output) { + yield output.dispose(); + } + + input = output = undefined; + })); + + it('Returns a plugin', function() { + let plugin = StripFilteredImports(); + expect(plugin).to.be.ok; + }); + + it('Does not alter a file if no imports are meant to be filtered', co.wrap(function*() { + let input = stripIndent` + import Foo from 'bar'; + import { baz } from 'none'; + import * as drinks from 'drinks'; + import 'bem'; + `; + + yield transform(input); + + expect(getOutput()).to.equal(stripNewlines(input)); + })); + + it('Properly strips desired imports and specifiers', co.wrap(function*() { + let input = stripIndent` + import Foo from 'bar'; + import { bit } from 'wow'; + import { baz, bell } from 'none'; + import { foo } from 'happy'; + import * as drinks from 'drinks'; + import * as dranks from 'dranks'; + import 'bem'; + import 'bosh'; + import 'bell'; + `; + + pluginOptions.none = ['baz']; + pluginOptions.bar = true; + pluginOptions.drinks = '*'; + pluginOptions.wow = ['bit']; + pluginOptions.bem = ['biz']; + pluginOptions.bosh = '*'; + pluginOptions.dranks = ['bex']; + pluginOptions.bell = true; + + yield transform(input); + let expectedOutput = stripNewlines(stripIndent` + import { bell } from 'none'; + import { foo } from 'happy'; + import * as dranks from 'dranks'; + import 'bem'; + `); + + expect(getOutput()).to.equal(expectedOutput); + })); +}); diff --git a/package.json b/package.json index e5ae5e843e0..c5dfb496c2f 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,11 @@ "broccoli-funnel": "^1.2.0", "broccoli-merge-trees": "^2.0.0", "broccoli-rollup": "^1.2.0", + "broccoli-test-helper": "^1.2.0", "calculate-cache-key-for-tree": "^1.1.0", "chalk": "^1.1.1", + "co": "^4.6.0", + "common-tags": "^1.4.0", "ember-cli-babel": "^6.4.1", "ember-cli-path-utils": "^1.0.0", "ember-cli-string-utils": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 9b557f2fb2b..784ac2b322e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1319,6 +1319,10 @@ broccoli-middleware@^1.0.0-beta.8: handlebars "^4.0.4" mime "^1.2.11" +broccoli-node-info@1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/broccoli-node-info/-/broccoli-node-info-1.1.0.tgz#3aa2e31e07e5bdb516dd25214f7c45ba1c459412" + broccoli-persistent-filter@^1.0.3, broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.2.0, broccoli-persistent-filter@^1.4.0, broccoli-persistent-filter@^1.4.2: version "1.4.2" resolved "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.2.tgz#17af1278a25ff2556f9d7d23e115accfad3a7ce7" @@ -1372,7 +1376,7 @@ broccoli-rollup@^1.2.0: symlink-or-copy "^1.1.8" walk-sync "^0.3.1" -broccoli-slow-trees@^3.0.1: +broccoli-slow-trees@3.0.1, broccoli-slow-trees@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/broccoli-slow-trees/-/broccoli-slow-trees-3.0.1.tgz#9bf2a9e2f8eb3ed3a3f2abdde988da437ccdc9b4" dependencies: @@ -1418,6 +1422,17 @@ broccoli-string-replace@^0.1.1: broccoli-persistent-filter "^1.1.5" minimatch "^3.0.3" +broccoli-test-helper@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/broccoli-test-helper/-/broccoli-test-helper-1.2.0.tgz#d01005d8611fd73ebe1b29552bf052ff59badfb4" + dependencies: + broccoli "^1.1.0" + fixturify "^0.3.2" + fs-tree-diff "^0.5.6" + mktemp "^0.4.0" + rimraf "^2.5.4" + walk-sync "^0.3.1" + broccoli-uglify-sourcemap@^1.0.0, broccoli-uglify-sourcemap@^1.0.1: version "1.5.2" resolved "https://registry.npmjs.org/broccoli-uglify-sourcemap/-/broccoli-uglify-sourcemap-1.5.2.tgz#04f84ab0db539031fa868ccfa563c9932d50cedb" @@ -1449,6 +1464,26 @@ broccoli-yuidoc@^2.1.0: rsvp "~3.1.0" yuidocjs "~0.9.0" +broccoli@^1.1.0: + version "1.1.3" + resolved "https://registry.npmjs.org/broccoli/-/broccoli-1.1.3.tgz#98405e86b7b0e6c268fb8302a006d834d17ed292" + dependencies: + broccoli-node-info "1.1.0" + broccoli-slow-trees "3.0.1" + broccoli-source "^1.1.0" + commander "^2.5.0" + connect "^3.3.3" + copy-dereference "^1.0.0" + findup-sync "^1.0.0" + handlebars "^4.0.4" + heimdalljs-logger "^0.1.7" + mime "^1.2.11" + rimraf "^2.4.3" + rsvp "^3.5.0" + sane "^1.4.1" + tmp "0.0.31" + underscore.string "^3.2.2" + browserslist@^2.1.2: version "2.1.5" resolved "https://registry.npmjs.org/browserslist/-/browserslist-2.1.5.tgz#e882550df3d1cd6d481c1a3e0038f2baf13a4711" @@ -1738,6 +1773,12 @@ commander@~2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" +common-tags@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0" + dependencies: + babel-runtime "^6.18.0" + commoner@~0.10.3: version "0.10.8" resolved "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5" @@ -1822,6 +1863,15 @@ configstore@^3.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" +connect@^3.3.3: + version "3.6.3" + resolved "https://registry.npmjs.org/connect/-/connect-3.6.3.tgz#f7320d46a25b4be7b483a2236517f24b1e27e301" + dependencies: + debug "2.6.8" + finalhandler "1.0.4" + parseurl "~1.3.1" + utils-merge "1.0.0" + console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -3018,6 +3068,18 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +finalhandler@1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7" + dependencies: + debug "2.6.8" + encodeurl "~1.0.1" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.1" + statuses "~1.3.1" + unpipe "~1.0.0" + finalhandler@~1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89" @@ -3056,6 +3118,15 @@ findup-sync@^0.4.2: micromatch "^2.3.7" resolve-dir "^0.1.0" +findup-sync@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/findup-sync/-/findup-sync-1.0.0.tgz#6f7e4b57b6ee3a4037b4414eaedea3f58f71e0ec" + dependencies: + detect-file "^0.1.0" + is-glob "^2.0.1" + micromatch "^2.3.7" + resolve-dir "^0.1.0" + findup@^0.1.5: version "0.1.5" resolved "https://registry.npmjs.org/findup/-/findup-0.1.5.tgz#8ad929a3393bac627957a7e5de4623b06b0e2ceb" @@ -3073,6 +3144,12 @@ fireworm@^0.7.0: lodash.flatten "^3.0.2" minimatch "^3.0.2" +fixturify@^0.3.2: + version "0.3.3" + resolved "https://registry.npmjs.org/fixturify/-/fixturify-0.3.3.tgz#842eaa120564c9881e099ed06dc082a81e97fa71" + dependencies: + fs-extra "^0.30.0" + flat-cache@^1.2.1: version "1.2.2" resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" @@ -5231,7 +5308,7 @@ safe-json-parse@~1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" -sane@^1.1.1, sane@^1.6.0: +sane@^1.1.1, sane@^1.4.1, sane@^1.6.0: version "1.7.0" resolved "https://registry.npmjs.org/sane/-/sane-1.7.0.tgz#b3579bccb45c94cf20355cc81124990dfd346e30" dependencies: @@ -5702,6 +5779,12 @@ tmp@0.0.30: dependencies: os-tmpdir "~1.0.1" +tmp@0.0.31: + version "0.0.31" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + tmp@^0.0.29: version "0.0.29" resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" @@ -5802,7 +5885,7 @@ ultron@1.0.x: version "1.0.2" resolved "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" -underscore.string@~3.3.4: +underscore.string@^3.2.2, underscore.string@~3.3.4: version "3.3.4" resolved "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db" dependencies: