Repository: ember-cli/ember-cli
Pull request #8033 (2018-09-10 18:46:07)

Restore `styles` behaviour

rwjblue: Confirmed this fixes the issue in an internal reproduction...

Patch:
diff --git a/blueprints/addon/files/.travis.yml b/blueprints/addon/files/.travis.yml
index 2f4f94a44..7732e8a6a 100644
--- a/blueprints/addon/files/.travis.yml
+++ b/blueprints/addon/files/.travis.yml
@@ -47,7 +47,8 @@ jobs:
     # we recommend new addons test the current and previous LTS
     # as well as latest stable release (bonus points to beta/canary)
     - stage: "Additional Tests"
-      env: EMBER_TRY_SCENARIO=ember-lts-2.16
+      env: EMBER_TRY_SCENARIO=ember-lts-2.12
+    - env: EMBER_TRY_SCENARIO=ember-lts-2.16
     - env: EMBER_TRY_SCENARIO=ember-lts-2.18
     - env: EMBER_TRY_SCENARIO=ember-release
     - env: EMBER_TRY_SCENARIO=ember-beta
diff --git a/lib/broccoli/default-packager.js b/lib/broccoli/default-packager.js
index 57753ac7e..3a8f36935 100644
--- a/lib/broccoli/default-packager.js
+++ b/lib/broccoli/default-packager.js
@@ -592,7 +592,7 @@ module.exports = class DefaultPackager {
 
         preprocessedStyles = preprocessCss(
           stylesAndVendor,
-          `/${this.name}/styles`,
+          '/app/styles',
           '/assets',
           options
         );
diff --git a/lib/broccoli/ember-app.js b/lib/broccoli/ember-app.js
index 382c4a8a6..e8d427110 100644
--- a/lib/broccoli/ember-app.js
+++ b/lib/broccoli/ember-app.js
@@ -1068,59 +1068,23 @@ class EmberApp {
    * ```
    *
    * @private
-   * @method getAddonStyles
+   * @method getStyles
    * @return {BroccoliTree}
   */
-  getAddonStyles() {
+  getStyles() {
+    let styles;
+    if (this.trees.styles) {
+      styles = new Funnel(this.trees.styles, {
+        srcDir: '/',
+        destDir: '/app/styles',
+        annotation: 'Funnel (styles)',
+      });
+    }
     let addons = this.addonTreesFor('styles');
 
-    /*
-     * There are several ways add-on can add a style to the application:
-
-     * + create `app/styles` folder
-     * + create `addon/styles` folder
-     * + return a tree from `treeForStyles` hook
-
-     * Previously, some add-ons (when using `treeForStyles` hook) would return
-     * content under `app/styles`. That used to work before packager changes.
-
-     * Because there's no contract (interface) that Ember CLI provides when you return
-     * a tree from `treeForStyles` hook, packager treats it as an opaque tree
-     * and moves its contents later on the "right" place. It unfortunately
-     * creates scenarios as such:
-
-     * ```
-     * the-best-app-ever/
-     *   styles/
-     *     app/
-     *       styles/
-     * ```
-
-     * where nested `app/styles` is a tree from an add-on.
-
-     * While I believe add-ons should return content under the "root" of the
-     * tree, we do need to support current behaviour w/o breaking anything.
-     */
-    let flatten = addons.map(tree =>
-      new Funnel(tree, {
-        getDestinationPath(relativePath) {
-          let stylesDirExists = relativePath.startsWith('app/styles');
-
-          if (stylesDirExists) {
-            return relativePath.replace('app/styles/', '');
-          }
-
-          return relativePath;
-        },
-      })
-    );
-    let merged = mergeTrees(flatten, {
+    return mergeTrees(addons.concat(styles), {
       overwrite: true,
-      annotation: 'Addon Styles',
-    });
-    return new Funnel(merged, {
-      allowEmpty: true,
-      destDir: `${this.name}/styles`,
+      annotation: 'Styles',
     });
   }
 
@@ -1653,7 +1617,7 @@ class EmberApp {
     let trees = [
       this.getAppJavascript(isPackageHookSupplied),
       this.getAddonTemplates(),
-      this.getAddonStyles(),
+      this.getStyles(),
       this.getTests(),
       this.getExternalTree(),
       this.getSrc(),


Test patch:
diff --git a/tests/fixtures/addon/npm/.travis.yml b/tests/fixtures/addon/npm/.travis.yml
index f904298f5..d1b971ca6 100644
--- a/tests/fixtures/addon/npm/.travis.yml
+++ b/tests/fixtures/addon/npm/.travis.yml
@@ -38,7 +38,8 @@ jobs:
     # we recommend new addons test the current and previous LTS
     # as well as latest stable release (bonus points to beta/canary)
     - stage: "Additional Tests"
-      env: EMBER_TRY_SCENARIO=ember-lts-2.16
+      env: EMBER_TRY_SCENARIO=ember-lts-2.12
+    - env: EMBER_TRY_SCENARIO=ember-lts-2.16
     - env: EMBER_TRY_SCENARIO=ember-lts-2.18
     - env: EMBER_TRY_SCENARIO=ember-release
     - env: EMBER_TRY_SCENARIO=ember-beta
diff --git a/tests/fixtures/addon/yarn/.travis.yml b/tests/fixtures/addon/yarn/.travis.yml
index 00af6f0e1..593c1743f 100644
--- a/tests/fixtures/addon/yarn/.travis.yml
+++ b/tests/fixtures/addon/yarn/.travis.yml
@@ -43,7 +43,8 @@ jobs:
     # we recommend new addons test the current and previous LTS
     # as well as latest stable release (bonus points to beta/canary)
     - stage: "Additional Tests"
-      env: EMBER_TRY_SCENARIO=ember-lts-2.16
+      env: EMBER_TRY_SCENARIO=ember-lts-2.12
+    - env: EMBER_TRY_SCENARIO=ember-lts-2.16
     - env: EMBER_TRY_SCENARIO=ember-lts-2.18
     - env: EMBER_TRY_SCENARIO=ember-release
     - env: EMBER_TRY_SCENARIO=ember-beta
diff --git a/tests/unit/broccoli/default-packager/styles-test.js b/tests/unit/broccoli/default-packager/styles-test.js
index b7a773e7a..69d86f49e 100644
--- a/tests/unit/broccoli/default-packager/styles-test.js
+++ b/tests/unit/broccoli/default-packager/styles-test.js
@@ -26,6 +26,12 @@ describe('Default Packager: Styles', function() {
   };
   let MODULES = {
     'addon-tree-output': { },
+    app: {
+      styles: {
+        'app.css': '@import "extra.css";\nhtml { height: 100%; }',
+        'extra.css': 'body{ position: relative; }',
+      },
+    },
     'the-best-app-ever': {
       'router.js': 'router.js',
       'app.js': 'app.js',
@@ -38,10 +44,6 @@ describe('Default Packager: Styles', function() {
       'config': {
         'environment.js': 'environment.js',
       },
-      styles: {
-        'app.css': '@import "extra.css";\nhtml { height: 100%; }',
-        'extra.css': 'body{ position: relative; }',
-      },
       'templates': {},
     },
     'bower_components': {
diff --git a/tests/unit/broccoli/ember-app-test.js b/tests/unit/broccoli/ember-app-test.js
index a42e5249f..80dd829b9 100644
--- a/tests/unit/broccoli/ember-app-test.js
+++ b/tests/unit/broccoli/ember-app-test.js
@@ -112,6 +112,10 @@ describe('EmberApp', function() {
       }));
 
       it('receives a full tree as an argument', co.wrap(function *() {
+        let appStyles = yield createTempDir();
+        appStyles.write({
+          'app.css': '// css styles',
+        });
         input.write({
           fake: {
             dist: {
@@ -122,6 +126,9 @@ describe('EmberApp', function() {
 
         let app = new EmberApp({
           project,
+          trees: {
+            styles: appStyles.path(),
+          },
         });
         mockTemplateRegistry(app);
 
@@ -145,8 +152,12 @@ describe('EmberApp', function() {
             },
             javascript: '// javascript.js',
           },
+          app: {
+            styles: {
+              'app.css': '// css styles',
+            },
+          },
           'test-project': {
-            styles: {},
             templates: {},
           },
           tests: {
@@ -172,7 +183,7 @@ describe('EmberApp', function() {
 
         app.getAppJavascript = td.function();
         app.getAddonTemplates = td.function();
-        app.getAddonStyles = td.function();
+        app.getStyles = td.function();
         app.getTests = td.function();
         app.getExternalTree = td.function();
         app.getSrc = td.function();
@@ -189,7 +200,7 @@ describe('EmberApp', function() {
         output = yield buildOutput(app.toTree());
 
         td.verify(app.getAppJavascript(false));
-        td.verify(app.getAddonStyles());
+        td.verify(app.getStyles());
         td.verify(app.getTests());
         td.verify(app.getExternalTree());
         td.verify(app.getSrc());
@@ -231,55 +242,33 @@ describe('EmberApp', function() {
     });
   }
 
-  describe('getAddonStyles()', function() {
+  describe('getStyles()', function() {
     it('can handle empty styles folders', co.wrap(function *() {
+      let appStyles = yield createTempDir();
+      appStyles.write({
+        'app.css': '// css styles',
+      });
+
       let app = new EmberApp({
         project,
+        trees: {
+          styles: appStyles.path(),
+        },
       });
 
       app.addonTreesFor = () => [];
 
-      let output = yield buildOutput(app.getAddonStyles());
+      let output = yield buildOutput(app.getStyles());
       let outputFiles = output.read();
 
-      expect(outputFiles['test-project']).to.deep.equal({
-        styles: { },
-      });
-
-      yield output.dispose();
-    }));
-
-    it('flattens `app/styles` folder from add-ons', co.wrap(function *() {
-      let addonFooStyles = yield createTempDir();
-
-      // `ember-cli-tailwind`
-      addonFooStyles.write({
+      expect(outputFiles).to.deep.equal({
         app: {
           styles: {
-            'foo.css': 'foo',
+            'app.css': '// css styles',
           },
         },
       });
 
-      let app = new EmberApp({
-        project,
-      });
-      app.addonTreesFor = function() {
-        return [
-          addonFooStyles.path(),
-        ];
-      };
-
-      let output = yield buildOutput(app.getAddonStyles());
-      let outputFiles = output.read();
-
-      expect(outputFiles['test-project']).to.deep.equal({
-        styles: {
-          'foo.css': 'foo',
-        },
-      });
-
-      yield addonFooStyles.dispose();
       yield output.dispose();
     }));
 
@@ -312,16 +301,18 @@ describe('EmberApp', function() {
         ];
       };
 
-      let output = yield buildOutput(app.getAddonStyles());
+      let output = yield buildOutput(app.getStyles());
       let outputFiles = output.read();
 
-      expect(outputFiles['test-project']).to.deep.equal({
-        styles: {
-          'foo.css': 'foo',
-          baztrap: {
-            'baztrap.css': '// baztrap.css',
+      expect(outputFiles).to.deep.equal({
+        app: {
+          styles: {
+            'foo.css': 'foo',
           },
         },
+        baztrap: {
+          'baztrap.css': '// baztrap.css',
+        },
       });
 
       yield addonFooStyles.dispose();