ember-cli 4.0.0 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/.github/workflows/ci.yml +4 -4
  2. package/CHANGELOG.md +42 -2
  3. package/blueprints/addon/additional-dev-dependencies.json +1 -1
  4. package/blueprints/addon/files/.github/workflows/ci.yml +0 -1
  5. package/blueprints/addon/files/.travis.yml +0 -1
  6. package/blueprints/addon/files/addon-config/ember-try.js +0 -13
  7. package/blueprints/app/files/config/environment.js +1 -1
  8. package/blueprints/app/files/package.json +6 -6
  9. package/docs/build/data.json +3 -3
  10. package/lib/models/host-info-cache.js +3 -5
  11. package/lib/models/per-bundle-addon-cache/index.js +2 -3
  12. package/lib/tasks/npm-task.js +1 -1
  13. package/lib/utilities/get-lang-arg.js +45 -45
  14. package/package.json +25 -25
  15. package/tests/helpers/mock-project.js +1 -1
  16. package/.github/ISSUE_TEMPLATE.md +0 -12
  17. package/.github/dependabot.yml +0 -15
  18. package/.github/workflows/coverage.yml +0 -31
  19. package/docs/analytics.md +0 -44
  20. package/docs/architecture.md +0 -316
  21. package/docs/assets/architecture/Ember-CLI architecture.png +0 -0
  22. package/docs/assets/architecture/Ember-CLI architecture.xml +0 -1
  23. package/docs/assets/architecture/README.md +0 -5
  24. package/docs/brocfile-transition.md +0 -46
  25. package/docs/build/api.js +0 -44
  26. package/docs/build/assets/css/external-small.png +0 -0
  27. package/docs/build/assets/css/logo.png +0 -0
  28. package/docs/build/assets/css/main.css +0 -555
  29. package/docs/build/assets/favicon.ico +0 -0
  30. package/docs/build/assets/img/spinner.gif +0 -0
  31. package/docs/build/assets/index.html +0 -10
  32. package/docs/build/assets/js/api-filter.js +0 -56
  33. package/docs/build/assets/js/api-list.js +0 -255
  34. package/docs/build/assets/js/api-search.js +0 -98
  35. package/docs/build/assets/js/apidocs.js +0 -376
  36. package/docs/build/assets/js/yui-prettify.js +0 -17
  37. package/docs/build/assets/vendor/prettify/CHANGES.html +0 -130
  38. package/docs/build/assets/vendor/prettify/COPYING +0 -202
  39. package/docs/build/assets/vendor/prettify/README.html +0 -203
  40. package/docs/build/assets/vendor/prettify/prettify-min.css +0 -1
  41. package/docs/build/assets/vendor/prettify/prettify-min.js +0 -1
  42. package/docs/build/classes/Addon.html +0 -4318
  43. package/docs/build/classes/AmdTransformAddon.html +0 -202
  44. package/docs/build/classes/Blueprint.html +0 -4796
  45. package/docs/build/classes/Builder.html +0 -611
  46. package/docs/build/classes/CLI.html +0 -810
  47. package/docs/build/classes/Command.html +0 -1655
  48. package/docs/build/classes/DefaultPackager.html +0 -202
  49. package/docs/build/classes/EmberAddon.html +0 -2207
  50. package/docs/build/classes/EmberApp.html +0 -2225
  51. package/docs/build/classes/HardwareInfo.html +0 -620
  52. package/docs/build/classes/HistorySupportAddon.html +0 -203
  53. package/docs/build/classes/Instrumentation.html +0 -695
  54. package/docs/build/classes/NodeModulesList.html +0 -460
  55. package/docs/build/classes/NpmTask.html +0 -333
  56. package/docs/build/classes/PackageInfo.html +0 -1390
  57. package/docs/build/classes/PackageInfoCache.html +0 -963
  58. package/docs/build/classes/PerBundleAddonCache {.html +0 -1010
  59. package/docs/build/classes/Project.html +0 -2083
  60. package/docs/build/classes/ServeFilesAddon.html +0 -260
  61. package/docs/build/classes/TestsServerAddon.html +0 -203
  62. package/docs/build/classes/WatcherAddon.html +0 -204
  63. package/docs/build/classes/WindowsSymlinkChecker.html +0 -1505
  64. package/docs/build/files/lib_broccoli_default-packager.js.html +0 -1426
  65. package/docs/build/files/lib_broccoli_ember-addon.js.html +0 -159
  66. package/docs/build/files/lib_broccoli_ember-app.js.html +0 -1913
  67. package/docs/build/files/lib_cli_cli.js.html +0 -417
  68. package/docs/build/files/lib_models_addon-info.js.html +0 -112
  69. package/docs/build/files/lib_models_addon.js.html +0 -1866
  70. package/docs/build/files/lib_models_blueprint.js.html +0 -1678
  71. package/docs/build/files/lib_models_builder.js.html +0 -417
  72. package/docs/build/files/lib_models_command.js.html +0 -804
  73. package/docs/build/files/lib_models_hardware-info.js.html +0 -479
  74. package/docs/build/files/lib_models_host-info-cache.js.html +0 -428
  75. package/docs/build/files/lib_models_installation-checker.js.html +0 -181
  76. package/docs/build/files/lib_models_instantiate-addons.js.html +0 -191
  77. package/docs/build/files/lib_models_instrumentation.js.html +0 -433
  78. package/docs/build/files/lib_models_package-info-cache_index.js.html +0 -793
  79. package/docs/build/files/lib_models_package-info-cache_node-modules-list.js.html +0 -208
  80. package/docs/build/files/lib_models_package-info-cache_package-info.js.html +0 -661
  81. package/docs/build/files/lib_models_per-bundle-addon-cache_addon-proxy.js.html +0 -252
  82. package/docs/build/files/lib_models_per-bundle-addon-cache_index.js.html +0 -485
  83. package/docs/build/files/lib_models_per-bundle-addon-cache_target-instance.js.html +0 -108
  84. package/docs/build/files/lib_models_project.js.html +0 -913
  85. package/docs/build/files/lib_models_task.js.html +0 -117
  86. package/docs/build/files/lib_tasks_build-watch.js.html +0 -157
  87. package/docs/build/files/lib_tasks_npm-task.js.html +0 -463
  88. package/docs/build/files/lib_tasks_serve.js.html +0 -207
  89. package/docs/build/files/lib_tasks_server_middleware_broccoli-serve-files_index.js.html +0 -127
  90. package/docs/build/files/lib_tasks_server_middleware_broccoli-watcher_index.js.html +0 -158
  91. package/docs/build/files/lib_tasks_server_middleware_history-support_index.js.html +0 -181
  92. package/docs/build/files/lib_tasks_server_middleware_tests-server_index.js.html +0 -171
  93. package/docs/build/files/lib_tasks_test-server.js.html +0 -167
  94. package/docs/build/files/lib_tasks_transforms_amd_index.js.html +0 -143
  95. package/docs/build/files/lib_utilities_ember-app-utils.js.html +0 -292
  96. package/docs/build/files/lib_utilities_insert-into-file.js.html +0 -219
  97. package/docs/build/files/lib_utilities_is-lazy-engine.js.html +0 -125
  98. package/docs/build/files/lib_utilities_is-yarn-project.js.html +0 -120
  99. package/docs/build/files/lib_utilities_valid-project-name.js.html +0 -142
  100. package/docs/build/files/lib_utilities_will-interrupt-process.js.html +0 -290
  101. package/docs/build/files/lib_utilities_windows-admin.js.html +0 -230
  102. package/docs/build/index.html +0 -125
  103. package/docs/build/modules/ember-cli.html +0 -152
  104. package/docs/build/modules/is-lazy-engine.html +0 -106
  105. package/docs/build-concurrency.md +0 -15
  106. package/docs/build-pipeline-debugging.md +0 -33
  107. package/docs/code-coverage.md +0 -14
  108. package/docs/error-propagation.md +0 -136
  109. package/docs/experiments.md +0 -53
  110. package/docs/node-support.md +0 -43
  111. package/docs/perf-guide.md +0 -250
  112. package/docs/project_version_preprocessor.js +0 -8
  113. package/docs/sourcemaps.md +0 -60
  114. package/docs/yuidoc.json +0 -13
@@ -1,1913 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <title>lib/broccoli/ember-app.js - ember-cli</title>
6
- <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
7
- <link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
8
- <script src="https://cdnjs.cloudflare.com/ajax/libs/yui/3.18.0/yui/yui-min.js"></script>
9
- </head>
10
- <body class="yui3-skin-sam">
11
-
12
- <div id="doc">
13
- <div class="yui3-g">
14
- <div id="sidebar" class="yui3-u">
15
- <div class="logo">
16
- <a href="../index.html">
17
- <img src="https://ember-cli.com/assets/images/ember-cli-logo-small-dark.png">
18
- </a>
19
- </div>
20
-
21
- <div id="modules" class="sidebox">
22
- <div class="hd">
23
- <h2 class="no-toc">Modules</h2>
24
- </div>
25
- <div class="bd">
26
- <ul>
27
- <li><a href="../modules/ember-cli.html">ember-cli</a>
28
- </li>
29
- <li><a href="../modules/is-lazy-engine.html">is-lazy-engine</a>
30
- </li>
31
- </ul>
32
- </div>
33
- </div>
34
-
35
- <div id="classes" class="sidebox">
36
- <div class="hd">
37
- <h2 class="no-toc">Classes</h2>
38
- </div>
39
- <div class="bd">
40
- <ul>
41
- <li><a href="../classes/Addon.html">Addon</a></li>
42
- <li><a href="../classes/AmdTransformAddon.html">AmdTransformAddon</a></li>
43
- <li><a href="../classes/Blueprint.html">Blueprint</a></li>
44
- <li><a href="../classes/Builder.html">Builder</a></li>
45
- <li><a href="../classes/CLI.html">CLI</a></li>
46
- <li><a href="../classes/Command.html">Command</a></li>
47
- <li><a href="../classes/DefaultPackager.html">DefaultPackager</a></li>
48
- <li><a href="../classes/EmberAddon.html">EmberAddon</a></li>
49
- <li><a href="../classes/EmberApp.html">EmberApp</a></li>
50
- <li><a href="../classes/HardwareInfo.html">HardwareInfo</a></li>
51
- <li><a href="../classes/HistorySupportAddon.html">HistorySupportAddon</a></li>
52
- <li><a href="../classes/Instrumentation.html">Instrumentation</a></li>
53
- <li><a href="../classes/NodeModulesList.html">NodeModulesList</a></li>
54
- <li><a href="../classes/NpmTask.html">NpmTask</a></li>
55
- <li><a href="../classes/PackageInfo.html">PackageInfo</a></li>
56
- <li><a href="../classes/PackageInfoCache.html">PackageInfoCache</a></li>
57
- <li><a href="../classes/PerBundleAddonCache {.html">PerBundleAddonCache {</a></li>
58
- <li><a href="../classes/Project.html">Project</a></li>
59
- <li><a href="../classes/ServeFilesAddon.html">ServeFilesAddon</a></li>
60
- <li><a href="../classes/TestsServerAddon.html">TestsServerAddon</a></li>
61
- <li><a href="../classes/WatcherAddon.html">WatcherAddon</a></li>
62
- <li><a href="../classes/WindowsSymlinkChecker.html">WindowsSymlinkChecker</a></li>
63
- </ul>
64
- </div>
65
- </div>
66
-
67
-
68
-
69
-
70
-
71
- <div class="version-info">
72
- Version: 4.0.0-release-b4cbb1029f
73
- </div>
74
-
75
- </div>
76
-
77
- <div id="main" class="yui3-u">
78
- <div class="content"><div class="title">
79
- <h1 class="file-name">lib/broccoli/ember-app.js</h1>
80
- </div>
81
-
82
- <pre class="code prettyprint linenums">
83
- &#x27;use strict&#x27;;
84
-
85
- /**
86
- @module ember-cli
87
- */
88
- const fs = require(&#x27;fs&#x27;);
89
- const path = require(&#x27;path&#x27;);
90
- const p = require(&#x27;ember-cli-preprocess-registry/preprocessors&#x27;);
91
- const chalk = require(&#x27;chalk&#x27;);
92
- const resolve = require(&#x27;resolve&#x27;);
93
-
94
- const Project = require(&#x27;../models/project&#x27;);
95
-
96
- let preprocessJs = p.preprocessJs;
97
- let isType = p.isType;
98
-
99
- let preprocessTemplates = p.preprocessTemplates;
100
-
101
- const concat = require(&#x27;broccoli-concat&#x27;);
102
- const BroccoliDebug = require(&#x27;broccoli-debug&#x27;);
103
- const AmdFunnel = require(&#x27;broccoli-amd-funnel&#x27;);
104
- const mergeTrees = require(&#x27;./merge-trees&#x27;);
105
- const WatchedDir = require(&#x27;broccoli-source&#x27;).WatchedDir;
106
- const UnwatchedDir = require(&#x27;broccoli-source&#x27;).UnwatchedDir;
107
- const BroccoliMergeTrees = require(&#x27;broccoli-merge-trees&#x27;);
108
-
109
- const merge = require(&#x27;ember-cli-lodash-subset&#x27;).merge;
110
- const defaultsDeep = require(&#x27;ember-cli-lodash-subset&#x27;).defaultsDeep;
111
- const omitBy = require(&#x27;ember-cli-lodash-subset&#x27;).omitBy;
112
- const isNull = require(&#x27;ember-cli-lodash-subset&#x27;).isNull;
113
- const Funnel = require(&#x27;broccoli-funnel&#x27;);
114
- const logger = require(&#x27;heimdalljs-logger&#x27;)(&#x27;ember-cli:ember-app&#x27;);
115
- const addonProcessTree = require(&#x27;../utilities/addon-process-tree&#x27;);
116
- const lintAddonsByType = require(&#x27;../utilities/lint-addons-by-type&#x27;);
117
- const emberCLIBabelConfigKey = require(&#x27;../utilities/ember-cli-babel-config-key&#x27;);
118
- const { isExperimentEnabled } = require(&#x27;../experiments&#x27;);
119
- const semver = require(&#x27;semver&#x27;);
120
- const DefaultPackager = require(&#x27;./default-packager&#x27;);
121
-
122
- let DEFAULT_CONFIG = {
123
- storeConfigInMeta: true,
124
- autoRun: true,
125
- outputPaths: {
126
- app: {
127
- html: &#x27;index.html&#x27;,
128
- },
129
- tests: {
130
- js: &#x27;/assets/tests.js&#x27;,
131
- },
132
- vendor: {
133
- css: &#x27;/assets/vendor.css&#x27;,
134
- js: &#x27;/assets/vendor.js&#x27;,
135
- },
136
- testSupport: {
137
- css: &#x27;/assets/test-support.css&#x27;,
138
- js: {
139
- testSupport: &#x27;/assets/test-support.js&#x27;,
140
- testLoader: &#x27;/assets/test-loader.js&#x27;,
141
- },
142
- },
143
- },
144
- minifyCSS: {
145
- options: { relativeTo: &#x27;assets&#x27; },
146
- },
147
- sourcemaps: {},
148
- trees: {},
149
- jshintrc: {},
150
- addons: {},
151
- };
152
-
153
- class EmberApp {
154
- /**
155
- EmberApp is the main class Ember CLI uses to manage the Broccoli trees
156
- for your application. It is very tightly integrated with Broccoli and has
157
- a &#x60;toTree()&#x60; method you can use to get the entire tree for your application.
158
-
159
- Available init options:
160
- - storeConfigInMeta, defaults to &#x60;true&#x60;
161
- - autoRun, defaults to &#x60;true&#x60;
162
- - outputPaths, defaults to &#x60;{}&#x60;
163
- - minifyCSS, defaults to &#x60;{enabled: !!isProduction,options: { relativeTo: &#x27;assets&#x27; }}
164
- - minifyJS, defaults to &#x60;{enabled: !!isProduction}
165
- - sourcemaps, defaults to &#x60;{}&#x60;
166
- - trees, defaults to &#x60;{}&#x60;
167
- - jshintrc, defaults to &#x60;{}&#x60;
168
- - vendorFiles, defaults to &#x60;{}&#x60;
169
- - addons, defaults to &#x60;{ exclude: [], include: [] }&#x60;
170
-
171
- @class EmberApp
172
- @constructor
173
- @param {Object} [defaults]
174
- @param {Object} [options={}] Configuration options
175
- */
176
- constructor(defaults, options) {
177
- if (arguments.length === 0) {
178
- options = {};
179
- } else if (arguments.length === 1) {
180
- options = defaults;
181
- } else {
182
- defaultsDeep(options, defaults);
183
- }
184
-
185
- this._initProject(options);
186
- this.name = options.name || this.project.name();
187
-
188
- this.env = EmberApp.env();
189
- this.isProduction = this.env === &#x27;production&#x27;;
190
-
191
- this.registry = options.registry || p.defaultRegistry(this);
192
-
193
- this.bowerDirectory = this.project.bowerDirectory;
194
-
195
- this._initTestsAndHinting(options);
196
- this._initOptions(options);
197
- this._initVendorFiles();
198
-
199
- this._styleOutputFiles = {};
200
-
201
- // ensure addon.css always gets concated
202
- this._styleOutputFiles[this.options.outputPaths.vendor.css] = [];
203
-
204
- this._scriptOutputFiles = {};
205
- this._customTransformsMap = new Map();
206
-
207
- this.otherAssetPaths = [];
208
- this.legacyTestFilesToAppend = [];
209
- this.vendorTestStaticStyles = [];
210
- this._nodeModules = new Map();
211
-
212
- this.trees = this.options.trees;
213
-
214
- this.populateLegacyFiles();
215
- this.initializeAddons();
216
- this.project.addons.forEach((addon) =&gt; (addon.app = this));
217
- p.setupRegistry(this);
218
- this._importAddonTransforms();
219
- this._notifyAddonIncluded();
220
-
221
- this._debugTree = BroccoliDebug.buildDebugCallback(&#x27;ember-app&#x27;);
222
-
223
- this._defaultPackager = new DefaultPackager({
224
- env: this.env,
225
- name: this.name,
226
- autoRun: this.options.autoRun,
227
- project: this.project,
228
- registry: this.registry,
229
- sourcemaps: this.options.sourcemaps,
230
- minifyCSS: this.options.minifyCSS,
231
- areTestsEnabled: this.tests,
232
- styleOutputFiles: this._styleOutputFiles,
233
- scriptOutputFiles: this._scriptOutputFiles,
234
- storeConfigInMeta: this.options.storeConfigInMeta,
235
- customTransformsMap: this._customTransformsMap,
236
- additionalAssetPaths: this.otherAssetPaths,
237
- vendorTestStaticStyles: this.vendorTestStaticStyles,
238
- legacyTestFilesToAppend: this.legacyTestFilesToAppend,
239
- distPaths: {
240
- appJsFile: this.options.outputPaths.app.js,
241
- appCssFile: this.options.outputPaths.app.css,
242
- testJsFile: this.options.outputPaths.tests.js,
243
- appHtmlFile: this.options.outputPaths.app.html,
244
- vendorJsFile: this.options.outputPaths.vendor.js,
245
- vendorCssFile: this.options.outputPaths.vendor.css,
246
- testSupportJsFile: this.options.outputPaths.testSupport.js,
247
- testSupportCssFile: this.options.outputPaths.testSupport.css,
248
- },
249
- });
250
-
251
- this._isPackageHookSupplied = typeof this.options.package === &#x27;function&#x27;;
252
- this._cachedAddonBundles = {};
253
-
254
- if (this.project.perBundleAddonCache &amp;&amp; this.project.perBundleAddonCache.numProxies &gt; 0) {
255
- if (this.options.addons.include &amp;&amp; this.options.addons.include.length) {
256
- let optionKey = this.options.addons.hasWhitelist ? &#x27;whitelist&#x27; : &#x27;include&#x27;;
257
-
258
- throw new Error(
259
- [
260
- &#x60;[ember-cli] addon bundle caching is disabled for apps that specify an addon &quot;${optionKey}&quot;&#x60;,
261
- &#x27;&#x27;,
262
- &#x27;All addons using bundle caching:&#x27;,
263
- ...this.project.perBundleAddonCache.getPathsToAddonsOptedIn(),
264
- ].join(&#x27;\n&#x27;)
265
- );
266
- }
267
-
268
- if (this.options.addons.exclude &amp;&amp; this.options.addons.exclude.length) {
269
- let optionKey = this.options.addons.hasBlacklist ? &#x27;blacklist&#x27; : &#x27;exclude&#x27;;
270
-
271
- throw new Error(
272
- [
273
- &#x60;[ember-cli] addon bundle caching is disabled for apps that specify an addon &quot;${optionKey}&quot;&#x60;,
274
- &#x27;&#x27;,
275
- &#x27;All addons using bundle caching:&#x27;,
276
- ...this.project.perBundleAddonCache.getPathsToAddonsOptedIn(),
277
- ].join(&#x27;\n&#x27;)
278
- );
279
- }
280
- }
281
- }
282
-
283
- /**
284
- Initializes the &#x60;tests&#x60; and &#x60;hinting&#x60; properties.
285
-
286
- Defaults to &#x60;false&#x60; unless &#x60;ember test&#x60; was used or this is *not* a production build.
287
-
288
- @private
289
- @method _initTestsAndHinting
290
- @param {Object} options
291
- */
292
- _initTestsAndHinting(options) {
293
- let testsEnabledDefault = process.env.EMBER_CLI_TEST_COMMAND === &#x27;true&#x27; || !this.isProduction;
294
-
295
- this.tests = &#x27;tests&#x27; in options ? options.tests : testsEnabledDefault;
296
- this.hinting = &#x27;hinting&#x27; in options ? options.hinting : testsEnabledDefault;
297
- }
298
-
299
- /**
300
- Initializes the &#x60;project&#x60; property from &#x60;options.project&#x60; or the
301
- closest Ember CLI project from the current working directory.
302
-
303
- @private
304
- @method _initProject
305
- @param {Object} options
306
- */
307
- _initProject(options) {
308
- let app = this;
309
-
310
- this.project = options.project || Project.closestSync(process.cwd());
311
-
312
- if (options.configPath) {
313
- this.project.configPath = function () {
314
- return app._resolveLocal(options.configPath);
315
- };
316
- this.project.configCache.clear();
317
- }
318
- }
319
-
320
- /**
321
- Initializes the &#x60;options&#x60; property from the &#x60;options&#x60; parameter and
322
- a set of default values from Ember CLI.
323
-
324
- @private
325
- @method _initOptions
326
- @param {Object} options
327
- */
328
- _initOptions(options) {
329
- let resolvePathFor = (defaultPath, specified) =&gt; {
330
- let path = defaultPath;
331
- if (specified &amp;&amp; typeof specified === &#x27;string&#x27;) {
332
- path = specified;
333
- }
334
- let resolvedPath = this._resolveLocal(path);
335
-
336
- return resolvedPath;
337
- };
338
-
339
- let buildTreeFor = (defaultPath, specified, shouldWatch) =&gt; {
340
- if (specified !== null &amp;&amp; specified !== undefined &amp;&amp; typeof specified !== &#x27;string&#x27;) {
341
- return specified;
342
- }
343
-
344
- let tree = null;
345
- let resolvedPath = resolvePathFor(defaultPath, specified);
346
- if (fs.existsSync(resolvedPath)) {
347
- if (shouldWatch !== false) {
348
- tree = new WatchedDir(resolvedPath);
349
- } else {
350
- tree = new UnwatchedDir(resolvedPath);
351
- }
352
- }
353
-
354
- return tree;
355
- };
356
- let trees = (options &amp;&amp; options.trees) || {};
357
-
358
- let appTree = buildTreeFor(&#x27;app&#x27;, trees.app);
359
-
360
- let testsPath = typeof trees.tests === &#x27;string&#x27; ? resolvePathFor(&#x27;tests&#x27;, trees.tests) : null;
361
- let testsTree = buildTreeFor(&#x27;tests&#x27;, trees.tests, options.tests);
362
-
363
- // these are contained within app/ no need to watch again
364
- // (we should probably have the builder or the watcher dedup though)
365
- this._stylesPath = resolvePathFor(&#x27;app/styles&#x27;, trees.styles);
366
-
367
- let stylesTree = null;
368
- if (fs.existsSync(this._stylesPath)) {
369
- stylesTree = new UnwatchedDir(this._stylesPath);
370
- }
371
-
372
- let templatesTree = buildTreeFor(&#x27;app/templates&#x27;, trees.templates, false);
373
-
374
- // do not watch bower&#x27;s default directory by default
375
- let bowerTree = buildTreeFor(this.bowerDirectory, null, !!this.project._watchmanInfo.enabled);
376
-
377
- // Set the flag to make sure:
378
- //
379
- // - we do not blow up if there is no bower_components folder
380
- // - we do not attempt to merge bower and vendor together if they are the
381
- // same tree
382
- this._bowerEnabled = this.bowerDirectory !== &#x27;vendor&#x27; &amp;&amp; fs.existsSync(this.bowerDirectory);
383
-
384
- let vendorTree = buildTreeFor(&#x27;vendor&#x27;, trees.vendor);
385
- let publicTree = buildTreeFor(&#x27;public&#x27;, trees.public);
386
-
387
- let detectedDefaultOptions = {
388
- babel: {},
389
- jshintrc: {
390
- app: this.project.root,
391
- tests: testsPath,
392
- },
393
- minifyCSS: {
394
- enabled: this.isProduction,
395
- options: { processImport: false },
396
- },
397
- // TODO: remove this with a deprecation (nothing in the default app/addon setup consumes it)
398
- minifyJS: {
399
- enabled: this.isProduction,
400
- options: {
401
- compress: {
402
- // this is adversely affects heuristics for IIFE eval
403
- // eslint-disable-next-line camelcase
404
- negate_iife: false,
405
- // limit sequences because of memory issues during parsing
406
- sequences: 30,
407
- },
408
- output: {
409
- // no difference in size and much easier to debug
410
- semicolons: false,
411
- },
412
- },
413
- },
414
- outputPaths: {
415
- app: {
416
- css: {
417
- app: &#x60;/assets/${this.name}.css&#x60;,
418
- },
419
- js: &#x60;/assets/${this.name}.js&#x60;,
420
- },
421
- },
422
- sourcemaps: {
423
- enabled: !this.isProduction,
424
- extensions: [&#x27;js&#x27;],
425
- },
426
- trees: {
427
- app: appTree,
428
- tests: testsTree,
429
- styles: stylesTree,
430
- templates: templatesTree,
431
- bower: bowerTree,
432
- vendor: vendorTree,
433
- public: publicTree,
434
- },
435
- };
436
-
437
- let emberCLIBabelInstance = this.project.findAddonByName(&#x27;ember-cli-babel&#x27;);
438
- if (emberCLIBabelInstance) {
439
- let version = this.project.require(&#x27;ember-cli-babel/package.json&#x27;).version;
440
- if (semver.lt(version, &#x27;6.0.0-alpha.1&#x27;)) {
441
- detectedDefaultOptions.babel = {
442
- modules: &#x27;amdStrict&#x27;,
443
- moduleIds: true,
444
- resolveModuleSource: require(&#x27;amd-name-resolver&#x27;).moduleResolve,
445
- };
446
- }
447
-
448
- let emberCLIBabelConfigKey = this._emberCLIBabelConfigKey();
449
- detectedDefaultOptions[emberCLIBabelConfigKey] = detectedDefaultOptions[emberCLIBabelConfigKey] || {};
450
- detectedDefaultOptions[emberCLIBabelConfigKey].compileModules = true;
451
- }
452
-
453
- this.options = defaultsDeep(options, detectedDefaultOptions, DEFAULT_CONFIG);
454
-
455
- if (this.options.addons.blacklist) {
456
- if (this.options.addons.exclude) {
457
- throw new Error(&#x27;Specifying both &quot;blacklist&quot; and &quot;exclude&quot; is not supported. Please use only one.&#x27;);
458
- }
459
-
460
- this.options.addons.hasBlacklist = true;
461
- this.options.addons.exclude = this.options.addons.blacklist;
462
- }
463
-
464
- Object.defineProperty(this.options.addons, &#x27;blacklist&#x27;, {
465
- get() {
466
- console.log(chalk.yellow(&#x27;Please use &quot;exclude&quot; instead of &quot;blacklist&quot;.&#x27;));
467
-
468
- return this.exclude;
469
- },
470
- });
471
-
472
- if (this.options.addons.whitelist) {
473
- if (this.options.addons.include) {
474
- throw new Error(&#x27;Specifying both &quot;whitelist&quot; and &quot;include&quot; is not supported. Please use only one.&#x27;);
475
- }
476
-
477
- this.options.addons.hasWhitelist = true;
478
- this.options.addons.include = this.options.addons.whitelist;
479
- }
480
-
481
- Object.defineProperty(this.options.addons, &#x27;whitelist&#x27;, {
482
- get() {
483
- console.log(chalk.yellow(&#x27;Please use &quot;include&quot; instead of &quot;whitelist&quot;.&#x27;));
484
-
485
- return this.include;
486
- },
487
- });
488
-
489
- // For now we must disable Babel sourcemaps due to unforeseen
490
- // performance regressions.
491
- if (!(&#x27;sourceMaps&#x27; in this.options.babel)) {
492
- this.options.babel.sourceMaps = false;
493
- }
494
-
495
- // Add testem.js to excludes for broccoli-asset-rev.
496
- // This will allow tests to run against the production builds.
497
- this.options.fingerprint = this.options.fingerprint || {};
498
- this.options.fingerprint.exclude = this.options.fingerprint.exclude || [];
499
- this.options.fingerprint.exclude.push(&#x27;testem&#x27;);
500
- }
501
-
502
- _emberCLIBabelConfigKey() {
503
- let emberCLIBabelInstance = this.project.findAddonByName(&#x27;ember-cli-babel&#x27;);
504
-
505
- return emberCLIBabelConfigKey(emberCLIBabelInstance);
506
- }
507
-
508
- /**
509
- Resolves a path relative to the project&#x27;s root
510
-
511
- @private
512
- @method _resolveLocal
513
- */
514
- _resolveLocal(to) {
515
- return path.join(this.project.root, to);
516
- }
517
-
518
- /**
519
- @private
520
- @method _initVendorFiles
521
- */
522
- _initVendorFiles() {
523
- let bowerDeps = this.project.bowerDependencies();
524
- let ember = this.project.findAddonByName(&#x27;ember-source&#x27;);
525
- let addonEmberCliShims = this.project.findAddonByName(&#x27;ember-cli-shims&#x27;);
526
- let bowerEmberCliShims = bowerDeps[&#x27;ember-cli-shims&#x27;];
527
- let developmentEmber;
528
- let productionEmber;
529
- let emberTesting;
530
- let emberShims = null;
531
-
532
- if (ember) {
533
- developmentEmber = ember.paths.debug;
534
- productionEmber = ember.paths.prod;
535
- emberTesting = ember.paths.testing;
536
- emberShims = ember.paths.shims;
537
- } else {
538
- if (bowerEmberCliShims) {
539
- emberShims = &#x60;${this.bowerDirectory}/ember-cli-shims/app-shims.js&#x60;;
540
- }
541
-
542
- // in Ember 1.10 and higher &#x60;ember.js&#x60; is deprecated in favor of
543
- // the more aptly named &#x60;ember.debug.js&#x60;.
544
- productionEmber = &#x60;${this.bowerDirectory}/ember/ember.prod.js&#x60;;
545
- developmentEmber = &#x60;${this.bowerDirectory}/ember/ember.debug.js&#x60;;
546
- if (!fs.existsSync(this._resolveLocal(developmentEmber))) {
547
- developmentEmber = &#x60;${this.bowerDirectory}/ember/ember.js&#x60;;
548
- }
549
- emberTesting = &#x60;${this.bowerDirectory}/ember/ember-testing.js&#x60;;
550
- }
551
-
552
- let handlebarsVendorFiles;
553
- if (&#x27;handlebars&#x27; in bowerDeps) {
554
- handlebarsVendorFiles = {
555
- development: &#x60;${this.bowerDirectory}/handlebars/handlebars.js&#x60;,
556
- production: &#x60;${this.bowerDirectory}/handlebars/handlebars.runtime.js&#x60;,
557
- };
558
- } else {
559
- handlebarsVendorFiles = null;
560
- }
561
-
562
- this.vendorFiles = omitBy(
563
- merge(
564
- {
565
- &#x27;handlebars.js&#x27;: handlebarsVendorFiles,
566
- &#x27;ember.js&#x27;: {
567
- development: developmentEmber,
568
- production: productionEmber,
569
- },
570
- &#x27;ember-testing.js&#x27;: [emberTesting, { type: &#x27;test&#x27; }],
571
- &#x27;app-shims.js&#x27;: emberShims,
572
- &#x27;ember-resolver.js&#x27;: [
573
- &#x60;${this.bowerDirectory}/ember-resolver/dist/modules/ember-resolver.js&#x60;,
574
- {
575
- exports: {
576
- &#x27;ember/resolver&#x27;: [&#x27;default&#x27;],
577
- },
578
- },
579
- ],
580
- },
581
- this.options.vendorFiles
582
- ),
583
- isNull
584
- );
585
-
586
- this._addJqueryInLegacyEmber();
587
-
588
- if (this._addonInstalled(&#x27;ember-resolver&#x27;) || !bowerDeps[&#x27;ember-resolver&#x27;]) {
589
- // if the project is using &#x60;ember-resolver&#x60; as an addon
590
- // remove it from &#x60;vendorFiles&#x60; (the npm version properly works
591
- // without &#x60;app.import&#x60;s)
592
- delete this.vendorFiles[&#x27;ember-resolver.js&#x27;];
593
- }
594
-
595
- // Warn if ember-cli-shims is not included.
596
- // certain versions of &#x60;ember-source&#x60; bundle them by default,
597
- // so we must check if that is the load mechanism of ember
598
- // before checking &#x60;bower&#x60;.
599
- let emberCliShimsRequired = this._checkEmberCliBabel(this.project.addons);
600
- if (!emberShims &amp;&amp; !addonEmberCliShims &amp;&amp; !bowerEmberCliShims &amp;&amp; emberCliShimsRequired) {
601
- this.project.ui.writeWarnLine(
602
- &quot;You have not included &#x60;ember-cli-shims&#x60; in your project&#x27;s &#x60;bower.json&#x60; or &#x60;package.json&#x60;. This only works if you provide an alternative yourself and unset &#x60;app.vendorFiles[&#x27;app-shims.js&#x27;]&#x60;.&quot;
603
- );
604
- }
605
-
606
- // If ember-testing.js is coming from Bower (not ember-source) and it does not
607
- // exist, then we remove it from vendor files. This is needed to support versions
608
- // of Ember older than 1.8.0 (when ember-testing.js was incldued in ember.js itself)
609
- if (!ember &amp;&amp; this.vendorFiles[&#x27;ember-testing.js&#x27;] &amp;&amp; !fs.existsSync(this.vendorFiles[&#x27;ember-testing.js&#x27;][0])) {
610
- delete this.vendorFiles[&#x27;ember-testing.js&#x27;];
611
- }
612
- }
613
-
614
- _addJqueryInLegacyEmber() {
615
- if (this.project.findAddonByName(&#x27;@ember/jquery&#x27;)) {
616
- return;
617
- }
618
- let ember = this.project.findAddonByName(&#x27;ember-source&#x27;);
619
- let jqueryPath;
620
- if (ember) {
621
- let optionFeatures = this.project.findAddonByName(&#x27;@ember/optional-features&#x27;);
622
- if (optionFeatures &amp;&amp; !optionFeatures.isFeatureEnabled(&#x27;jquery-integration&#x27;)) {
623
- return;
624
- }
625
- this.project.ui.writeDeprecateLine(
626
- &#x27;The integration of jQuery into Ember has been deprecated and will be removed with Ember 4.0. You can either&#x27; +
627
- &#x27; opt-out of using jQuery, or install the &#x60;@ember/jquery&#x60; addon to provide the jQuery integration. Please&#x27; +
628
- &#x27; consult the deprecation guide for further details: https://emberjs.com/deprecations/v3.x#toc_jquery-apis&#x27;
629
- );
630
- jqueryPath = ember.paths.jquery;
631
- } else {
632
- jqueryPath = &#x60;${this.bowerDirectory}/jquery/dist/jquery.js&#x60;;
633
- }
634
- this.vendorFiles = merge({ &#x27;jquery.js&#x27;: jqueryPath }, this.vendorFiles);
635
- }
636
-
637
- /**
638
- Returns the environment name
639
-
640
- @public
641
- @static
642
- @method env
643
- @return {String} Environment name
644
- */
645
- static env() {
646
- return process.env.EMBER_ENV || &#x27;development&#x27;;
647
- }
648
-
649
- /**
650
- Delegates to &#x60;broccoli-concat&#x60; with the &#x60;sourceMapConfig&#x60; option set to &#x60;options.sourcemaps&#x60;.
651
-
652
- @private
653
- @method _concatFiles
654
- @param tree
655
- @param options
656
- @return
657
- */
658
- _concatFiles(tree, options) {
659
- options.sourceMapConfig = this.options.sourcemaps;
660
-
661
- return concat(tree, options);
662
- }
663
-
664
- /**
665
- Checks the result of &#x60;addon.isEnabled()&#x60; if it exists, defaults to &#x60;true&#x60; otherwise.
666
-
667
- @private
668
- @method _addonEnabled
669
- @param {Addon} addon
670
- @return {Boolean}
671
- */
672
- _addonEnabled(addon) {
673
- return !addon.isEnabled || addon.isEnabled();
674
- }
675
-
676
- /**
677
- @private
678
- @method _addonDisabledByExclude
679
- @param {Addon} addon
680
- @return {Boolean}
681
- */
682
- _addonDisabledByExclude(addon) {
683
- let exclude = this.options.addons.exclude;
684
- return !!exclude &amp;&amp; exclude.indexOf(addon.name) !== -1;
685
- }
686
-
687
- /**
688
- @private
689
- @method _addonDisabledByInclude
690
- @param {Addon} addon
691
- @return {Boolean}
692
- */
693
- _addonDisabledByInclude(addon) {
694
- let include = this.options.addons.include;
695
- return !!include &amp;&amp; include.indexOf(addon.name) === -1;
696
- }
697
-
698
- /**
699
- @private
700
- @method _checkEmberCliBabel
701
- @param {Addons} addons
702
- @return {Boolean}
703
- */
704
- _checkEmberCliBabel(addons, result, roots) {
705
- addons = addons || [];
706
- result = result || false;
707
- roots = roots || {};
708
-
709
- let babelInstance = addons.find((addon) =&gt; addon.name === &#x27;ember-cli-babel&#x27;);
710
- if (babelInstance) {
711
- let version = babelInstance.pkg.version;
712
- if (semver.lt(version, &#x27;6.6.0&#x27;)) {
713
- result = true;
714
- }
715
- if (semver.lt(version, &#x27;6.0.0&#x27;) &amp;&amp; !roots[babelInstance.root]) {
716
- roots[babelInstance.root] = true;
717
- this.project.ui.writeDeprecateLine(
718
- &#x60;ember-cli-babel 5.x has been deprecated. Please upgrade to at least ember-cli-babel 6.6. Version ${version} located: ${babelInstance.root}&#x60;
719
- );
720
- }
721
- }
722
-
723
- return addons.some((addon) =&gt; this._checkEmberCliBabel(addon.addons, result, roots)) || result;
724
- }
725
-
726
- /**
727
- Returns whether an addon should be added to the project
728
-
729
- @private
730
- @method shouldIncludeAddon
731
- @param {Addon} addon
732
- @return {Boolean}
733
- */
734
- shouldIncludeAddon(addon) {
735
- if (!this._addonEnabled(addon)) {
736
- return false;
737
- }
738
-
739
- return !this._addonDisabledByExclude(addon) &amp;&amp; !this._addonDisabledByInclude(addon);
740
- }
741
-
742
- /**
743
- Calls the included hook on addons.
744
-
745
- @private
746
- @method _notifyAddonIncluded
747
- */
748
- _notifyAddonIncluded() {
749
- let addonNames = this.project.addons.map((addon) =&gt; addon.name);
750
-
751
- if (this.options.addons.exclude) {
752
- let optionKey = this.options.addons.hasBlacklist ? &#x27;blacklist&#x27; : &#x27;exclude&#x27;;
753
-
754
- this.options.addons.exclude.forEach((addonName) =&gt; {
755
- if (addonNames.indexOf(addonName) === -1) {
756
- throw new Error(&#x60;Addon &quot;${addonName}&quot; defined in &quot;${optionKey}&quot; is not found&#x60;);
757
- }
758
- });
759
- }
760
-
761
- if (this.options.addons.include) {
762
- let optionKey = this.options.addons.hasWhitelist ? &#x27;whitelist&#x27; : &#x27;include&#x27;;
763
-
764
- this.options.addons.include.forEach((addonName) =&gt; {
765
- if (addonNames.indexOf(addonName) === -1) {
766
- throw new Error(&#x60;Addon &quot;${addonName}&quot; defined in &quot;${optionKey}&quot; is not found&#x60;);
767
- }
768
- });
769
- }
770
-
771
- // the addons must be filtered before the &#x60;included&#x60; hook is called
772
- // in case an addon caches the project.addons list
773
- this.project.addons = this.project.addons.filter((addon) =&gt; this.shouldIncludeAddon(addon));
774
-
775
- this.project.addons.forEach((addon) =&gt; {
776
- if (addon.included) {
777
- addon.included(this);
778
- }
779
- });
780
- }
781
-
782
- /**
783
- Calls the importTransforms hook on addons.
784
-
785
- @private
786
- @method _importAddonTransforms
787
- */
788
- _importAddonTransforms() {
789
- this.project.addons.forEach((addon) =&gt; {
790
- if (this.shouldIncludeAddon(addon)) {
791
- if (addon.importTransforms) {
792
- let transforms = addon.importTransforms();
793
-
794
- if (!transforms) {
795
- throw new Error(&#x60;Addon &quot;${addon.name}&quot; did not return a transform map from importTransforms function&#x60;);
796
- }
797
-
798
- Object.keys(transforms).forEach((transformName) =&gt; {
799
- let transformConfig = {
800
- files: [],
801
- options: {},
802
- };
803
-
804
- // store the transform info
805
- if (typeof transforms[transformName] === &#x27;object&#x27;) {
806
- transformConfig[&#x27;callback&#x27;] = transforms[transformName].transform;
807
- transformConfig[&#x27;processOptions&#x27;] = transforms[transformName].processOptions;
808
- } else if (typeof transforms[transformName] === &#x27;function&#x27;) {
809
- transformConfig[&#x27;callback&#x27;] = transforms[transformName];
810
- transformConfig[&#x27;processOptions&#x27;] = (assetPath, entry, options) =&gt; options;
811
- } else {
812
- throw new Error(
813
- &#x60;Addon &quot;${addon.name}&quot; did not return a callback function correctly for transform &quot;${transformName}&quot;.&#x60;
814
- );
815
- }
816
-
817
- if (this._customTransformsMap.has(transformName)) {
818
- // there is already a transform with a same name, therefore we warn the user
819
- this.project.ui.writeWarnLine(
820
- &#x60;Addon &quot;${addon.name}&quot; is defining a transform name: ${transformName} that is already being defined. Using transform from addon: &quot;${addon.name}&quot;.&#x60;
821
- );
822
- }
823
-
824
- this._customTransformsMap.set(transformName, transformConfig);
825
- });
826
- }
827
- }
828
- });
829
- }
830
-
831
- /**
832
- Loads and initializes addons for this project.
833
- Calls initializeAddons on the Project.
834
-
835
- @private
836
- @method initializeAddons
837
- */
838
- initializeAddons() {
839
- this.project.initializeAddons();
840
- }
841
-
842
- _addonTreesFor(type) {
843
- return this.project.addons.reduce((sum, addon) =&gt; {
844
- if (addon.treeFor) {
845
- let tree = addon.treeFor(type);
846
- if (tree &amp;&amp; !mergeTrees.isEmptyTree(tree)) {
847
- sum.push({
848
- name: addon.name,
849
- tree,
850
- root: addon.root,
851
- });
852
- }
853
- }
854
- return sum;
855
- }, []);
856
- }
857
-
858
- /**
859
- Returns a list of trees for a given type, returned by all addons.
860
-
861
- @private
862
- @method addonTreesFor
863
- @param {String} type Type of tree
864
- @return {Array} List of trees
865
- */
866
- addonTreesFor(type) {
867
- return this._addonTreesFor(type).map((addonBundle) =&gt; addonBundle.tree);
868
- }
869
-
870
- _getDefaultPluginForType(type) {
871
- let plugins = this.registry.load(type);
872
- let defaultsForType = plugins.filter((plugin) =&gt; plugin.isDefaultForType);
873
-
874
- if (defaultsForType.length &gt; 1) {
875
- throw new Error(
876
- &#x60;There are multiple preprocessor plugins marked as default for &#x27;${type}&#x27;: ${defaultsForType
877
- .map((p) =&gt; p.name)
878
- .join(&#x27;, &#x27;)}&#x60;
879
- );
880
- }
881
-
882
- return defaultsForType[0];
883
- }
884
-
885
- _compileAddonTemplates(tree) {
886
- let defaultPluginForType = this._getDefaultPluginForType(&#x27;template&#x27;);
887
- let options = {
888
- annotation: &#x60;_compileAddonTemplates&#x60;,
889
- registry: this.registry,
890
- };
891
-
892
- if (defaultPluginForType) {
893
- tree = defaultPluginForType.toTree(tree, options);
894
- } else {
895
- tree = preprocessTemplates(tree, options);
896
- }
897
-
898
- return tree;
899
- }
900
-
901
- _compileAddonJs(tree) {
902
- let defaultPluginForType = this._getDefaultPluginForType(&#x27;js&#x27;);
903
- let options = {
904
- annotation: &#x27;_compileAddonJs&#x27;,
905
- registry: this.registry,
906
- };
907
-
908
- if (defaultPluginForType) {
909
- tree = defaultPluginForType.toTree(tree, options);
910
- } else {
911
- tree = preprocessJs(tree, &#x27;/&#x27;, &#x27;/&#x27;, options);
912
- }
913
-
914
- return tree;
915
- }
916
-
917
- _compileAddonTree(tree, skipTemplates) {
918
- if (!skipTemplates) {
919
- tree = this._compileAddonTemplates(tree);
920
- }
921
- tree = this._compileAddonJs(tree);
922
-
923
- return tree;
924
- }
925
-
926
- _precompileAppJsTree(tree) {
927
- let emberCLIBabelConfigKey = this._emberCLIBabelConfigKey();
928
-
929
- let original = this.options[emberCLIBabelConfigKey];
930
-
931
- // the app will handle transpilation after it tree-shakes
932
- // do it here instead of the constructor because
933
- // ember-data and others do their own compilation in their
934
- // treeForAddon without calling super
935
- // they need the original params preserved because they call
936
- // babel themselves and expect compilation the old way
937
- this.options[emberCLIBabelConfigKey] = Object.assign({}, original, {
938
- compileModules: false,
939
- disablePresetEnv: true,
940
- disableDebugTooling: true,
941
- disableEmberModulesAPIPolyfill: true,
942
- });
943
-
944
- tree = preprocessJs(tree, &#x27;/&#x27;, &#x27;/&#x27;, {
945
- annotation: &#x60;_precompileAppJsTree&#x60;,
946
- registry: this.registry,
947
- treeType: &#x27;app&#x27;,
948
- });
949
-
950
- // return the original params because there are multiple
951
- // entrances to preprocessJs
952
- this.options[emberCLIBabelConfigKey] = original;
953
-
954
- return tree;
955
- }
956
-
957
- /**
958
- Runs addon post-processing on a given tree and returns the processed tree.
959
-
960
- This enables addons to do process immediately **after** the preprocessor for a
961
- given type is run, but before concatenation occurs. If an addon wishes to
962
- apply a transform before the preprocessors run, they can instead implement the
963
- preprocessTree hook.
964
-
965
- To utilize this addons implement &#x60;postprocessTree&#x60; hook.
966
-
967
- An example, would be to apply some broccoli transform on all JS files, but
968
- only after the existing pre-processors have run.
969
-
970
- &#x60;&#x60;&#x60;js
971
- module.exports = {
972
- name: &#x27;my-cool-addon&#x27;,
973
- postprocessTree(type, tree) {
974
- if (type === &#x27;js&#x27;) {
975
- return someBroccoliTransform(tree);
976
- }
977
-
978
- return tree;
979
- }
980
- }
981
-
982
- &#x60;&#x60;&#x60;
983
-
984
- @private
985
- @method addonPostprocessTree
986
- @param {String} type Type of tree
987
- @param {Tree} tree Tree to process
988
- @return {Tree} Processed tree
989
- */
990
- addonPostprocessTree(type, tree) {
991
- return addonProcessTree(this.project, &#x27;postprocessTree&#x27;, type, tree);
992
- }
993
-
994
- /**
995
- Runs addon pre-processing on a given tree and returns the processed tree.
996
-
997
- This enables addons to do process immediately **before** the preprocessor for a
998
- given type is run. If an addon wishes to apply a transform after the
999
- preprocessors run, they can instead implement the postprocessTree hook.
1000
-
1001
- To utilize this addons implement &#x60;preprocessTree&#x60; hook.
1002
-
1003
- An example, would be to remove some set of files before the preprocessors run.
1004
-
1005
- &#x60;&#x60;&#x60;js
1006
- var stew = require(&#x27;broccoli-stew&#x27;);
1007
-
1008
- module.exports = {
1009
- name: &#x27;my-cool-addon&#x27;,
1010
- preprocessTree(type, tree) {
1011
- if (type === &#x27;js&#x27; &amp;&amp; type === &#x27;template&#x27;) {
1012
- return stew.rm(tree, someGlobPattern);
1013
- }
1014
-
1015
- return tree;
1016
- }
1017
- }
1018
- &#x60;&#x60;&#x60;
1019
-
1020
- @private
1021
- @method addonPreprocessTree
1022
- @param {String} type Type of tree
1023
- @param {Tree} tree Tree to process
1024
- @return {Tree} Processed tree
1025
- */
1026
- addonPreprocessTree(type, tree) {
1027
- return addonProcessTree(this.project, &#x27;preprocessTree&#x27;, type, tree);
1028
- }
1029
-
1030
- /**
1031
- Runs addon lintTree hooks and returns a single tree containing all
1032
- their output.
1033
-
1034
- @private
1035
- @method addonLintTree
1036
- @param {String} type Type of tree
1037
- @param {Tree} tree Tree to process
1038
- @return {Tree} Processed tree
1039
- */
1040
- addonLintTree(type, tree) {
1041
- let output = lintAddonsByType(this.project.addons, type, tree);
1042
-
1043
- return mergeTrees(output, {
1044
- overwrite: true,
1045
- annotation: &#x60;TreeMerger (lint ${type})&#x60;,
1046
- });
1047
- }
1048
-
1049
- /**
1050
- Imports legacy imports in this.vendorFiles
1051
-
1052
- @private
1053
- @method populateLegacyFiles
1054
- */
1055
- populateLegacyFiles() {
1056
- let name;
1057
- for (name in this.vendorFiles) {
1058
- let args = this.vendorFiles[name];
1059
-
1060
- if (args === null) {
1061
- continue;
1062
- }
1063
-
1064
- this.import.apply(this, [].concat(args));
1065
- }
1066
- }
1067
-
1068
- podTemplates() {
1069
- return new Funnel(this.trees.app, {
1070
- include: this._podTemplatePatterns(),
1071
- exclude: [&#x27;templates/**/*&#x27;],
1072
- destDir: this.name,
1073
- annotation: &#x27;Funnel: Pod Templates&#x27;,
1074
- });
1075
- }
1076
-
1077
- _templatesTree() {
1078
- if (!this._cachedTemplateTree) {
1079
- let trees = [];
1080
- if (this.trees.templates) {
1081
- let standardTemplates = new Funnel(this.trees.templates, {
1082
- srcDir: &#x27;/&#x27;,
1083
- destDir: &#x60;${this.name}/templates&#x60;,
1084
- annotation: &#x27;Funnel: Templates&#x27;,
1085
- });
1086
-
1087
- trees.push(standardTemplates);
1088
- }
1089
-
1090
- if (this.trees.app) {
1091
- trees.push(this.podTemplates());
1092
- }
1093
-
1094
- this._cachedTemplateTree = mergeTrees(trees, {
1095
- annotation: &#x27;TreeMerge (templates)&#x27;,
1096
- });
1097
- }
1098
-
1099
- return this._cachedTemplateTree;
1100
- }
1101
-
1102
- /*
1103
- * Gather application and add-ons javascript files and return them in a single
1104
- * tree.
1105
- *
1106
- * Resulting tree:
1107
- *
1108
- * &#x60;&#x60;&#x60;
1109
- * the-best-app-ever/
1110
- * ├── adapters
1111
- * │ └── application.js
1112
- * ├── app.js
1113
- * ├── components
1114
- * ├── controllers
1115
- * ├── helpers
1116
- * │ ├── and.js
1117
- * │ ├── app-version.js
1118
- * │ ├── await.js
1119
- * │ ├── camelize.js
1120
- * │ ├── cancel-all.js
1121
- * │ ├── dasherize.js
1122
- * │ ├── dec.js
1123
- * │ ├── drop.js
1124
- * │ └── eq.js
1125
- * ...
1126
- * &#x60;&#x60;&#x60;
1127
- *
1128
- * Note, files in the example are &quot;made up&quot; and will differ from the real
1129
- * application.
1130
- *
1131
- * @private
1132
- * @method getAppJavascript
1133
- * @return {BroccoliTree}
1134
- */
1135
- getAppJavascript(isPackageHookSupplied) {
1136
- let appTrees = [].concat(this.addonTreesFor(&#x27;app&#x27;), this.trees.app).filter(Boolean);
1137
-
1138
- let mergedApp = mergeTrees(appTrees, {
1139
- overwrite: true,
1140
- annotation: &#x27;TreeMerger (app)&#x27;,
1141
- });
1142
-
1143
- let appTree = new Funnel(mergedApp, {
1144
- srcDir: &#x27;/&#x27;,
1145
- destDir: this.name,
1146
- annotation: &#x27;ProcessedAppTree&#x27;,
1147
- });
1148
-
1149
- if (isExperimentEnabled(&#x27;PACKAGER&#x27;) &amp;&amp; isPackageHookSupplied) {
1150
- appTree = this._precompileAppJsTree(appTree);
1151
- }
1152
-
1153
- return appTree;
1154
- }
1155
-
1156
- /*
1157
- * Gather add-ons style (css/sass/less) files and return them in a single
1158
- * tree.
1159
- *
1160
- * Resulting tree:
1161
- *
1162
- * &#x60;&#x60;&#x60;
1163
- * the-best-app-ever/
1164
- * └── app
1165
- * └── styles
1166
- * ├── ember-basic-dropdown.scss
1167
- * └── ember-power-select.scss
1168
- * &#x60;&#x60;&#x60;
1169
- *
1170
- * @private
1171
- * @method getStyles
1172
- * @return {BroccoliTree}
1173
- */
1174
- getStyles() {
1175
- let styles;
1176
- if (this.trees.styles) {
1177
- styles = new Funnel(this.trees.styles, {
1178
- srcDir: &#x27;/&#x27;,
1179
- destDir: &#x27;/app/styles&#x27;,
1180
- annotation: &#x27;Funnel (styles)&#x27;,
1181
- });
1182
- }
1183
- let addons = this.addonTreesFor(&#x27;styles&#x27;);
1184
-
1185
- styles = mergeTrees(addons.concat(styles), {
1186
- overwrite: true,
1187
- annotation: &#x27;Styles&#x27;,
1188
- });
1189
-
1190
- return styles;
1191
- }
1192
-
1193
- /*
1194
- * Gather add-ons template files and return them in a single tree.
1195
- *
1196
- * Resulting tree:
1197
- *
1198
- * &#x60;&#x60;&#x60;
1199
- * the-best-app-ever/
1200
- * └── templates
1201
- * ├── application.hbs
1202
- * ├── error.hbs
1203
- * ├── index.hbs
1204
- * └── loading.hbs
1205
- * &#x60;&#x60;&#x60;
1206
- *
1207
- * Note, files in the example are &quot;made up&quot; and will differ from the real
1208
- * application.
1209
- *
1210
- * @private
1211
- * @method getAddonTemplates
1212
- * @return {BroccoliTree}
1213
- */
1214
- getAddonTemplates() {
1215
- let addonTrees = this.addonTreesFor(&#x27;templates&#x27;);
1216
- let mergedTemplates = mergeTrees(addonTrees, {
1217
- overwrite: true,
1218
- annotation: &#x27;TreeMerger (templates)&#x27;,
1219
- });
1220
-
1221
- let addonTemplates = new Funnel(mergedTemplates, {
1222
- srcDir: &#x27;/&#x27;,
1223
- destDir: &#x60;${this.name}/templates&#x60;,
1224
- annotation: &#x27;ProcessedTemplateTree&#x27;,
1225
- });
1226
-
1227
- return addonTemplates;
1228
- }
1229
-
1230
- /**
1231
- @private
1232
- @method _podTemplatePatterns
1233
- @return {Array} An array of regular expressions.
1234
- */
1235
- _podTemplatePatterns() {
1236
- return this.registry.extensionsForType(&#x27;template&#x27;).map((extension) =&gt; &#x60;**/*/template.${extension}&#x60;);
1237
- }
1238
-
1239
- _nodeModuleTrees() {
1240
- if (!this._cachedNodeModuleTrees) {
1241
- this._cachedNodeModuleTrees = Array.from(
1242
- this._nodeModules.values(),
1243
- (module) =&gt;
1244
- new Funnel(module.path, {
1245
- srcDir: &#x27;/&#x27;,
1246
- destDir: &#x60;node_modules/${module.name}/&#x60;,
1247
- annotation: &#x60;Funnel (node_modules/${module.name})&#x60;,
1248
- })
1249
- );
1250
- }
1251
-
1252
- return this._cachedNodeModuleTrees;
1253
- }
1254
-
1255
- _addonBundles(type) {
1256
- if (!this._cachedAddonBundles[type]) {
1257
- let addonBundles = this._addonTreesFor(type);
1258
-
1259
- this._cachedAddonBundles[type] = addonBundles;
1260
- }
1261
-
1262
- return this._cachedAddonBundles[type];
1263
- }
1264
-
1265
- /*
1266
- * @private
1267
- * @method @createAddonTree
1268
- */
1269
- createAddonTree(type, outputDir, options) {
1270
- let addonBundles = this._addonBundles(type, options);
1271
-
1272
- let tree = mergeTrees(
1273
- addonBundles.map(({ tree }) =&gt; tree),
1274
- {
1275
- overwrite: true,
1276
- annotation: &#x60;TreeMerger (${type})&#x60;,
1277
- }
1278
- );
1279
-
1280
- return new Funnel(tree, {
1281
- destDir: outputDir,
1282
- annotation: &#x60;Funnel: ${outputDir} ${type}&#x60;,
1283
- });
1284
- }
1285
-
1286
- addonTree() {
1287
- if (!this._cachedAddonTree) {
1288
- this._cachedAddonTree = this.createAddonTree(&#x27;addon&#x27;, &#x27;addon-tree-output&#x27;);
1289
- }
1290
-
1291
- return this._cachedAddonTree;
1292
- }
1293
-
1294
- addonTestSupportTree() {
1295
- if (!this._cachedAddonTestSupportTree) {
1296
- this._cachedAddonTestSupportTree = this.createAddonTree(&#x27;addon-test-support&#x27;, &#x27;addon-test-support&#x27;);
1297
- }
1298
-
1299
- return this._cachedAddonTestSupportTree;
1300
- }
1301
-
1302
- /*
1303
- * Gather all dependencies external to &#x60;ember-cli&#x60;, namely:
1304
- *
1305
- * + app &#x60;vendor&#x60; files
1306
- * + add-ons&#x27; &#x60;vendor&#x60; files
1307
- * + bower packages
1308
- * + node modules
1309
- *
1310
- * Resulting tree:
1311
- *
1312
- * &#x60;&#x60;&#x60;
1313
- * /
1314
- * ├── addon-tree-output/
1315
- * ├── bower_components/
1316
- * └── vendor/
1317
- * &#x60;&#x60;&#x60;
1318
- *
1319
- * @private
1320
- * @method getExternalTree
1321
- * @return {BroccoliTree}
1322
- */
1323
- getExternalTree() {
1324
- if (!this._cachedExternalTree) {
1325
- let vendorTrees = this.addonTreesFor(&#x27;vendor&#x27;);
1326
-
1327
- vendorTrees.push(this.trees.vendor);
1328
-
1329
- let vendor = this._defaultPackager.packageVendor(
1330
- mergeTrees(vendorTrees, {
1331
- overwrite: true,
1332
- annotation: &#x27;TreeMerger (vendor)&#x27;,
1333
- })
1334
- );
1335
-
1336
- let addons = this.addonTree();
1337
-
1338
- let trees = [vendor].concat(addons);
1339
- if (this._bowerEnabled) {
1340
- let bower = this._defaultPackager.packageBower(this.trees.bower, this.bowerDirectory);
1341
-
1342
- trees.push(bower);
1343
- }
1344
-
1345
- trees = this._nodeModuleTrees().concat(trees);
1346
-
1347
- this._cachedExternalTree = mergeTrees(trees, {
1348
- annotation: &#x27;TreeMerger (ExternalTree)&#x27;,
1349
- overwrite: true,
1350
- });
1351
- }
1352
-
1353
- return this._cachedExternalTree;
1354
- }
1355
-
1356
- /*
1357
- * Gather all tests under &#x60;tests&#x60; folder.
1358
- *
1359
- * Resulting tree:
1360
- *
1361
- * &#x60;&#x60;&#x60;
1362
- * /
1363
- * └── tests/
1364
- * ├── acceptance/
1365
- * ├── addon-test-support/
1366
- * ├── helpers/
1367
- * ├── integration/
1368
- * ├── lint/
1369
- * ├── unit/
1370
- * ├── index.html
1371
- * └── test-helper.js
1372
- * &#x60;&#x60;&#x60;
1373
- *
1374
- * @private
1375
- * @method getTests
1376
- * @return {BroccoliTree}
1377
- */
1378
- getTests() {
1379
- let addonTrees = this.addonTreesFor(&#x27;test-support&#x27;);
1380
-
1381
- if (this.hinting) {
1382
- addonTrees.push(this.getLintTests());
1383
- }
1384
-
1385
- let addonTestSupportFiles = this.addonTestSupportTree();
1386
- let allTests = mergeTrees(addonTrees.concat(this.trees.tests, addonTestSupportFiles), {
1387
- overwrite: true,
1388
- annotation: &#x27;TreeMerger (tests)&#x27;,
1389
- });
1390
-
1391
- return new Funnel(allTests, {
1392
- destDir: &#x27;tests&#x27;,
1393
- });
1394
- }
1395
-
1396
- /*
1397
- * Merges both application and add-ons public files and returns them in a
1398
- * single tree.
1399
- *
1400
- * Given a tree:
1401
- *
1402
- * &#x60;&#x60;&#x60;
1403
- * ├── 500.html
1404
- * ├── images
1405
- * ├── maintenance.html
1406
- * └── robots.txt
1407
- * &#x60;&#x60;&#x60;
1408
- *
1409
- * And add-on tree:
1410
- *
1411
- * &#x60;&#x60;&#x60;
1412
- * ember-fetch/
1413
- * └── fastboot-fetch.js
1414
- * &#x60;&#x60;&#x60;
1415
- *
1416
- * Returns:
1417
- *
1418
- * &#x60;&#x60;&#x60;
1419
- * ├── 500.html
1420
- * ├── ember-fetch
1421
- * │ └── fastboot-fetch.js
1422
- * ├── images
1423
- * ├── maintenance.html
1424
- * └── robots.txt
1425
- * &#x60;&#x60;&#x60;
1426
- *
1427
- * @private
1428
- * @method getPublic
1429
- * @return {BroccoliTree}
1430
- */
1431
- getPublic() {
1432
- let addonPublicTrees = this.addonTreesFor(&#x27;public&#x27;);
1433
- addonPublicTrees = addonPublicTrees.concat(this.trees.public);
1434
-
1435
- let mergedPublicTrees = mergeTrees(addonPublicTrees, {
1436
- annotation: &#x27;Public&#x27;,
1437
- overwrite: true,
1438
- });
1439
-
1440
- return new Funnel(mergedPublicTrees, {
1441
- destDir: &#x27;public&#x27;,
1442
- });
1443
- }
1444
-
1445
- /**
1446
- Runs the &#x60;app&#x60;, &#x60;tests&#x60; and &#x60;templates&#x60; trees through the chain of addons that produces lint trees.
1447
-
1448
- Those lint trees are afterwards funneled into the &#x60;tests&#x60; folder, babel-ified and returned as an array.
1449
-
1450
- @private
1451
- @method getLintTests
1452
- @return {Array}
1453
- */
1454
- getLintTests() {
1455
- let lintTrees = [];
1456
-
1457
- if (this.trees.app) {
1458
- let lintedApp = this.addonLintTree(&#x27;app&#x27;, this.trees.app);
1459
- lintedApp = new Funnel(lintedApp, {
1460
- destDir: &#x27;lint&#x27;,
1461
- annotation: &#x27;Funnel (lint app)&#x27;,
1462
- });
1463
-
1464
- lintTrees.push(lintedApp);
1465
- }
1466
-
1467
- let lintedTests = this.addonLintTree(&#x27;tests&#x27;, this.trees.tests);
1468
- let lintedTemplates = this.addonLintTree(&#x27;templates&#x27;, this._templatesTree());
1469
-
1470
- lintedTests = new Funnel(lintedTests, {
1471
- destDir: &#x27;lint&#x27;,
1472
- annotation: &#x27;Funnel (lint tests)&#x27;,
1473
- });
1474
-
1475
- lintedTemplates = new Funnel(lintedTemplates, {
1476
- destDir: &#x27;lint&#x27;,
1477
- annotation: &#x27;Funnel (lint templates)&#x27;,
1478
- });
1479
-
1480
- return mergeTrees([lintedTests, lintedTemplates].concat(lintTrees), {
1481
- overwrite: true,
1482
- });
1483
- }
1484
-
1485
- /**
1486
- * @private
1487
- * @method _addonInstalled
1488
- * @param {String} addonName The name of the addon we are checking to see if it&#x27;s installed
1489
- * @return {Boolean}
1490
- */
1491
- _addonInstalled(addonName) {
1492
- return !!this.registry.availablePlugins[addonName];
1493
- }
1494
-
1495
- /**
1496
- @public
1497
- @method dependencies
1498
- @return {Object} Alias to the project&#x27;s dependencies function
1499
- */
1500
- dependencies(pkg) {
1501
- return this.project.dependencies(pkg);
1502
- }
1503
-
1504
- /**
1505
- Imports an asset into the application.
1506
-
1507
- @public
1508
- @method import
1509
- @param {Object|String} asset Either a path to the asset or an object with environment names and paths as key-value pairs.
1510
- @param {Object} [options] Options object
1511
- @param {String} [options.type=&#x27;vendor&#x27;] Either &#x27;vendor&#x27; or &#x27;test&#x27;
1512
- @param {Boolean} [options.prepend=false] Whether or not this asset should be prepended
1513
- @param {String} [options.destDir] Destination directory, defaults to the name of the directory the asset is in
1514
- @param {String} [options.outputFile] Specifies the output file for given import. Defaults to assets/vendor.{js,css}
1515
- @param {Array} [options.using] Specifies the array of transformations to be done on the asset. Can do an amd shim and/or custom transformation
1516
- */
1517
- import(asset, options) {
1518
- let assetPath = this._getAssetPath(asset);
1519
-
1520
- if (!assetPath) {
1521
- return;
1522
- }
1523
-
1524
- options = defaultsDeep(options || {}, {
1525
- type: &#x27;vendor&#x27;,
1526
- prepend: false,
1527
- });
1528
-
1529
- let match = assetPath.match(/^node_modules\/((@[^/]+\/)?[^/]+)\//);
1530
- if (match !== null) {
1531
- let basedir = options.resolveFrom || this.project.root;
1532
- let name = match[1];
1533
- let _path = path.dirname(resolve.sync(&#x60;${name}/package.json&#x60;, { basedir }));
1534
- this._nodeModules.set(_path, { name, path: _path });
1535
- }
1536
-
1537
- let directory = path.dirname(assetPath);
1538
- let subdirectory = directory.replace(new RegExp(&#x60;^vendor/|${this.bowerDirectory}|node_modules/&#x60;), &#x27;&#x27;);
1539
- let extension = path.extname(assetPath);
1540
-
1541
- if (!extension) {
1542
- throw new Error(
1543
- &#x27;You must pass a file to &#x60;app.import&#x60;. For directories specify them to the constructor under the &#x60;trees&#x60; option.&#x27;
1544
- );
1545
- }
1546
-
1547
- this._import(assetPath, options, directory, subdirectory, extension);
1548
- }
1549
-
1550
- /**
1551
- @private
1552
- @method _import
1553
- @param {String} assetPath
1554
- @param {Object} options
1555
- @param {String} directory
1556
- @param {String} subdirectory
1557
- @param {String} extension
1558
- */
1559
- _import(assetPath, options, directory, subdirectory, extension) {
1560
- // TODO: refactor, this has gotten very messy. Relevant tests: tests/unit/broccoli/ember-app-test.js
1561
- let basename = path.basename(assetPath);
1562
-
1563
- if (isType(assetPath, &#x27;js&#x27;, { registry: this.registry })) {
1564
- if (options.using) {
1565
- if (!Array.isArray(options.using)) {
1566
- throw new Error(&#x27;You must pass an array of transformations for &#x60;using&#x60; option&#x27;);
1567
- }
1568
- options.using.forEach((entry) =&gt; {
1569
- if (!entry.transformation) {
1570
- throw new Error(
1571
- &#x60;while importing ${assetPath}: each entry in the \&#x60;using\&#x60; list must have a \&#x60;transformation\&#x60; name&#x60;
1572
- );
1573
- }
1574
-
1575
- let transformName = entry.transformation;
1576
-
1577
- if (!this._customTransformsMap.has(transformName)) {
1578
- let availableTransformNames = Array.from(this._customTransformsMap.keys()).join(&#x27;,&#x27;);
1579
- throw new Error(
1580
- &#x60;while import ${assetPath}: found an unknown transformation name ${transformName}. Available transformNames are: ${availableTransformNames}&#x60;
1581
- );
1582
- }
1583
-
1584
- // process options for the transform and update the options
1585
- let customTransforms = this._customTransformsMap.get(transformName);
1586
- customTransforms.options = customTransforms.processOptions(assetPath, entry, customTransforms.options);
1587
- customTransforms.files.push(assetPath);
1588
- });
1589
- }
1590
-
1591
- if (options.type === &#x27;vendor&#x27;) {
1592
- options.outputFile = options.outputFile || this.options.outputPaths.vendor.js;
1593
- addOutputFile(&#x27;firstOneWins&#x27;, this._scriptOutputFiles, assetPath, options);
1594
- } else if (options.type === &#x27;test&#x27;) {
1595
- if (!allowImport(&#x27;firstOneWins&#x27;, this.legacyTestFilesToAppend, assetPath, options)) {
1596
- return;
1597
- }
1598
- if (options.prepend) {
1599
- this.legacyTestFilesToAppend.unshift(assetPath);
1600
- } else {
1601
- this.legacyTestFilesToAppend.push(assetPath);
1602
- }
1603
- } else {
1604
- throw new Error(
1605
- &#x60;You must pass either \&#x60;vendor\&#x60; or \&#x60;test\&#x60; for options.type in your call to \&#x60;app.import\&#x60; for file: ${basename}&#x60;
1606
- );
1607
- }
1608
- } else if (extension === &#x27;.css&#x27;) {
1609
- if (options.type === &#x27;vendor&#x27;) {
1610
- options.outputFile = options.outputFile || this.options.outputPaths.vendor.css;
1611
- addOutputFile(&#x27;lastOneWins&#x27;, this._styleOutputFiles, assetPath, options);
1612
- } else {
1613
- if (!allowImport(&#x27;lastOneWins&#x27;, this.vendorTestStaticStyles, assetPath, options)) {
1614
- return;
1615
- }
1616
- if (options.prepend) {
1617
- this.vendorTestStaticStyles.unshift(assetPath);
1618
- } else {
1619
- this.vendorTestStaticStyles.push(assetPath);
1620
- }
1621
- }
1622
- } else {
1623
- let destDir = options.destDir;
1624
- if (destDir === &#x27;&#x27;) {
1625
- destDir = &#x27;/&#x27;;
1626
- }
1627
- this.otherAssetPaths.push({
1628
- src: directory,
1629
- file: basename,
1630
- dest: destDir || subdirectory,
1631
- });
1632
- }
1633
- }
1634
-
1635
- /**
1636
- @private
1637
- @method _getAssetPath
1638
- @param {(Object|String)} asset
1639
- @return {(String|undefined)} assetPath
1640
- */
1641
- _getAssetPath(asset) {
1642
- /* @type {String} */
1643
- let assetPath;
1644
-
1645
- if (typeof asset !== &#x27;object&#x27;) {
1646
- assetPath = asset;
1647
- } else if (this.env in asset) {
1648
- assetPath = asset[this.env];
1649
- } else {
1650
- assetPath = asset.development;
1651
- }
1652
-
1653
- if (!assetPath) {
1654
- return;
1655
- }
1656
-
1657
- assetPath = assetPath.split(&#x27;\\&#x27;).join(&#x27;/&#x27;);
1658
-
1659
- if (assetPath.split(&#x27;/&#x27;).length &lt; 2) {
1660
- console.log(
1661
- chalk.red(
1662
- &#x60;Using \&#x60;app.import\&#x60; with a file in the root of \&#x60;vendor/\&#x60; causes a significant performance penalty. Please move \&#x60;${assetPath}\&#x60; into a subdirectory.&#x60;
1663
- )
1664
- );
1665
- }
1666
-
1667
- if (/[*,]/.test(assetPath)) {
1668
- throw new Error(
1669
- &#x60;You must pass a file path (without glob pattern) to \&#x60;app.import\&#x60;. path was: \&#x60;${assetPath}\&#x60;&#x60;
1670
- );
1671
- }
1672
-
1673
- return assetPath;
1674
- }
1675
-
1676
- /**
1677
- Returns an array of trees for this application
1678
-
1679
- @private
1680
- @method toArray
1681
- @return {Array} An array of trees
1682
- */
1683
- toArray() {
1684
- return [
1685
- this.getAddonTemplates(),
1686
- this.getStyles(),
1687
- this.getTests(),
1688
- this.getExternalTree(),
1689
- this.getPublic(),
1690
- this.getAppJavascript(this._isPackageHookSupplied),
1691
- ].filter(Boolean);
1692
- }
1693
-
1694
- _legacyAddonCompile(type, outputDir, _options) {
1695
- let options = Object.assign(
1696
- {
1697
- // moduleNormalizerDisabled: this.options.moduleNormalizerDisabled,
1698
- amdFunnelDisabled: this.options.amdFunnelDisabled,
1699
- skipTemplates: false,
1700
- },
1701
- _options
1702
- );
1703
-
1704
- let addonBundles = this._cachedAddonBundles[type];
1705
-
1706
- let addonTrees = addonBundles.map((addonBundle) =&gt; {
1707
- let { name, tree, root } = addonBundle;
1708
-
1709
- let precompiledSource = tree;
1710
-
1711
- if (!options.amdFunnelDisabled) {
1712
- // don&#x27;t want to double compile the AMD modules
1713
- let hasAlreadyPrintedAmdDeprecation;
1714
- precompiledSource = new AmdFunnel(precompiledSource, {
1715
- callback: () =&gt; {
1716
- if (!hasAlreadyPrintedAmdDeprecation) {
1717
- this.project.ui.writeDeprecateLine(
1718
- &#x60;Addon &quot;${name}&quot; (found at &quot;${root}&quot;) is manually generating AMD modules. Code should be ES6 modules only. Support for this will be removed in a future version.&#x60;
1719
- );
1720
- hasAlreadyPrintedAmdDeprecation = true;
1721
- }
1722
- },
1723
- annotation: &#x60;AmdFunnel (${type} ${name})&#x60;,
1724
- });
1725
- }
1726
-
1727
- return [tree, precompiledSource];
1728
- });
1729
-
1730
- let precompiledSource = addonTrees.map((pair) =&gt; pair[1]);
1731
- addonTrees = addonTrees.map((pair) =&gt; pair[0]);
1732
-
1733
- precompiledSource = mergeTrees(precompiledSource, {
1734
- overwrite: true,
1735
- annotation: &#x60;TreeMerger (${type})&#x60;,
1736
- });
1737
-
1738
- precompiledSource = this._debugTree(precompiledSource, &#x60;precompiledAddonTree:${type}&#x60;);
1739
-
1740
- let compiledSource = this._compileAddonTree(precompiledSource, options.skipTemplates);
1741
-
1742
- compiledSource = this._debugTree(compiledSource, &#x60;postcompiledAddonTree:${type}&#x60;);
1743
-
1744
- let combinedAddonTree;
1745
-
1746
- if (options.amdFunnelDisabled) {
1747
- combinedAddonTree = compiledSource;
1748
- } else {
1749
- combinedAddonTree = mergeTrees(addonTrees.concat(compiledSource), {
1750
- overwrite: true,
1751
- annotation: &#x60;AmdFunnel TreeMerger (${type})&#x60;,
1752
- });
1753
- }
1754
-
1755
- return new Funnel(combinedAddonTree, {
1756
- destDir: outputDir,
1757
- annotation: &#x60;Funnel: ${outputDir} ${type}&#x60;,
1758
- });
1759
- }
1760
-
1761
- _legacyPackage(fullTree) {
1762
- let javascriptTree = this._defaultPackager.packageJavascript(fullTree);
1763
- let stylesTree = this._defaultPackager.packageStyles(fullTree);
1764
- let appIndex = this._defaultPackager.processIndex(fullTree);
1765
- let additionalAssets = this._defaultPackager.importAdditionalAssets(fullTree);
1766
- let publicTree = this._defaultPackager.packagePublic(fullTree);
1767
-
1768
- let sourceTrees = [appIndex, javascriptTree, stylesTree, additionalAssets, publicTree].filter(Boolean);
1769
-
1770
- if (this.tests &amp;&amp; this.trees.tests) {
1771
- sourceTrees.push(this._defaultPackager.packageTests(fullTree));
1772
- }
1773
-
1774
- return mergeTrees(sourceTrees, {
1775
- overwrite: true,
1776
- annotation: &#x27;Application Dist&#x27;,
1777
- });
1778
- }
1779
-
1780
- /**
1781
- Returns the merged tree for this application
1782
-
1783
- @public
1784
- @method toTree
1785
- @param {Array} [additionalTrees] Array of additional trees to merge
1786
- @return {Tree} Merged tree for this application
1787
- */
1788
- toTree(additionalTrees) {
1789
- let packagedTree;
1790
- let packageFn = this.options.package;
1791
-
1792
- let fullTree = mergeTrees(this.toArray(), {
1793
- overwrite: true,
1794
- annotation: &#x27;Full Application&#x27;,
1795
- });
1796
-
1797
- fullTree = this._debugTree(fullTree, &#x27;prepackage&#x27;);
1798
-
1799
- if (isExperimentEnabled(&#x27;PACKAGER&#x27;)) {
1800
- if (this._isPackageHookSupplied) {
1801
- packagedTree = packageFn.call(this, fullTree);
1802
- } else {
1803
- this.project.ui.writeWarnLine(&#x27;&#x60;package&#x60; hook must be a function, falling back to default packaging.&#x27;);
1804
- }
1805
- }
1806
-
1807
- if (!packagedTree) {
1808
- packagedTree = this._legacyPackage(fullTree);
1809
- }
1810
-
1811
- let trees = [].concat(packagedTree, additionalTrees).filter(Boolean);
1812
- let combinedPackageTree = new BroccoliMergeTrees(trees);
1813
-
1814
- return this.addonPostprocessTree(&#x27;all&#x27;, combinedPackageTree);
1815
- }
1816
- }
1817
-
1818
- module.exports = EmberApp;
1819
-
1820
- function addOutputFile(strategy, container, assetPath, options) {
1821
- let outputFile = options.outputFile;
1822
-
1823
- if (!outputFile) {
1824
- throw new Error(&#x27;outputFile is not specified&#x27;);
1825
- }
1826
-
1827
- if (!container[outputFile]) {
1828
- container[outputFile] = [];
1829
- }
1830
- if (!allowImport(strategy, container[outputFile], assetPath, options)) {
1831
- return;
1832
- }
1833
-
1834
- if (options.prepend) {
1835
- container[outputFile].unshift(assetPath);
1836
- } else {
1837
- container[outputFile].push(assetPath);
1838
- }
1839
- }
1840
-
1841
- // In this strategy the last instance of the asset in the array is the one which will be used.
1842
- // This applies to CSS where the last asset always &quot;wins&quot; no matter what.
1843
- function _lastOneWins(fileList, assetPath, options) {
1844
- let assetIndex = fileList.indexOf(assetPath);
1845
-
1846
- // Doesn&#x27;t exist in the current fileList. Safe to remove.
1847
- if (assetIndex === -1) {
1848
- return true;
1849
- }
1850
-
1851
- logger.info(&#x60;Highlander Rule: duplicate \&#x60;app.import(${assetPath})\&#x60;. Only including the last by order.&#x60;);
1852
-
1853
- if (options.prepend) {
1854
- // The existing asset is _already after_ this inclusion and would win.
1855
- // Therefore this branch is a no-op.
1856
- return false;
1857
- } else {
1858
- // The existing asset is _before_ this inclusion and needs to be removed.
1859
- fileList.splice(fileList.indexOf(assetPath), 1);
1860
- return true;
1861
- }
1862
- }
1863
-
1864
- // In JS the asset which would be first will win.
1865
- // If it is something which includes globals we want those defined as early as
1866
- // possible. Any initialization would likely be repeated. Any mutation of global
1867
- // state that occurs on initialization is likely _fixed_.
1868
- // Any module definitions will be identical except in the scenario where they&#x27;red
1869
- // reified to reassignment. This is likely fine.
1870
- function _firstOneWins(fileList, assetPath, options) {
1871
- let assetIndex = fileList.indexOf(assetPath);
1872
-
1873
- // Doesn&#x27;t exist in the current fileList. Safe to remove.
1874
- if (assetIndex === -1) {
1875
- return true;
1876
- }
1877
-
1878
- logger.info(&#x60;Highlander Rule: duplicate \&#x60;app.import(${assetPath})\&#x60;. Only including the first by order.&#x60;);
1879
-
1880
- if (options.prepend) {
1881
- // The existing asset is _after_ this inclusion and needs to be removed.
1882
- fileList.splice(fileList.indexOf(assetPath), 1);
1883
- return true;
1884
- } else {
1885
- // The existing asset is _already before_ this inclusion and would win.
1886
- // Therefore this branch is a no-op.
1887
- return false;
1888
- }
1889
- }
1890
-
1891
- function allowImport(strategy, fileList, assetPath, options) {
1892
- if (strategy === &#x27;firstOneWins&#x27;) {
1893
- // We must find all occurrences and decide what to do with each.
1894
- return _firstOneWins.call(undefined, fileList, assetPath, options);
1895
- } else if (strategy === &#x27;lastOneWins&#x27;) {
1896
- // We can simply use the &quot;last one wins&quot; strategy.
1897
- return _lastOneWins.call(undefined, fileList, assetPath, options);
1898
- } else {
1899
- return true;
1900
- }
1901
- }
1902
-
1903
- </pre>
1904
-
1905
- </div>
1906
- </div>
1907
- </div>
1908
- </div>
1909
- <script src="../assets/vendor/prettify/prettify-min.js"></script>
1910
- <script>prettyPrint();</script>
1911
- <script src="../assets/js/yui-prettify.js"></script>
1912
- </body>
1913
- </html>