diff --git a/packages/@css-blocks/ember-cli/index.js b/packages/@css-blocks/ember-cli/index.js index 070b380b1..073bb87fa 100644 --- a/packages/@css-blocks/ember-cli/index.js +++ b/packages/@css-blocks/ember-cli/index.js @@ -1,9 +1,15 @@ 'use strict'; +const fs = require("fs"); +const path = require("path"); const { CSSBlocksAggregate, CSSBlocksAnalyze, Transport } = require("@css-blocks/broccoli"); const { GlimmerAnalyzer, GlimmerRewriter } = require("@css-blocks/glimmer"); + +const BroccoliStew = require("broccoli-stew"); +const BroccoliConcat = require("broccoli-concat"); +const BroccoliMerge = require("broccoli-merge-trees"); + const debugGenerator = require("debug"); -const path = require("path"); const DEBUG = debugGenerator("css-blocks:ember-cli"); @@ -21,6 +27,8 @@ const NOOP_PLUGIN = { name: 'css-blocks-noop', visitors: {}, visitor: {} }; module.exports = { name: '@css-blocks/ember-cli', + outputFile: 'app.css', + aggregateFile: 'css-blocks.css', isDevelopingAddon() { return true; }, transports: new Map(), _owners: new Set(), @@ -123,7 +131,7 @@ module.exports = { this._owners.add(parent); // Fetch information about the environment we're running in. - let env = this.getEnv(parent); + let env = this.env = this.getEnv(parent); // Fetch and validate user-provided options. let options = this._options = this.getOptions(env); @@ -131,11 +139,17 @@ module.exports = { // If the consuming app has explicitly disabled CSS Blocks, exit. if (options.disabled) { return; } + // Determine the aggregate file that we'll be storing Block styles in + // during the build. + this.aggregateFile = options.output || (env.isEmber ? `css-blocks.css` : "src/ui/styles/css-blocks.css"); + // In Ember, we need to inject the CSS Blocks runtime helpers. Only do this in // the top level addon. `app.import` is not a thing in Glimmer. // TODO: Pull in as CJS so we don't need to build @css-blocks/glimmer to CJS *and* AMD. // Blocked by: https://github.com/rwjblue/ember-cli-cjs-transform/issues/72 if (env.isEmber && env.app === parent) { + this.outputFile = env.app.options.outputPaths.app.css.app.slice(1); + env.app.import('node_modules/@css-blocks/glimmer/dist/amd/src/helpers/classnames.js', { using: [{ transformation: 'amd', as: '@css-blocks/helpers/classnames' }], resolveFrom: __dirname, @@ -172,6 +186,27 @@ module.exports = { }, + // At the very end of the build, append our CSS Blocks aggregate file to + // the main `app.css` file. Un-link the destination file first to make sure + // we don't modify the source file if broccoli sym-linked it all the way back. + postprocessTree(name, tree) { + + const aggregatorTree = this.env.app.trees.cssblocks; + + // If this is not the root app, or the css tree, no-op. + if (this.env.isAddon || name !== 'css' || !aggregatorTree) { return tree; } + + DEBUG(`Writing all CSS Blocks output to "${this.outputFile}".`); + let merged = new BroccoliMerge([tree, aggregatorTree], { overwrite: true }) + merged = new BroccoliConcat(merged, { + outputFile: this.outputFile, + inputFiles: [ this.outputFile, this.aggregateFile ], + allowNone: true, + }); + + return new BroccoliMerge([tree, merged], { overwrite: true }); + }, + getEnv(parent){ // Fetch a reference to the parent app @@ -251,8 +286,6 @@ module.exports = { genTreeWrapper(env, options, prev = NOOP) { const { isEmber, app, parent, rootDir, moduleConfig, modulePrefix } = env; - const outputPath = options.output || (isEmber ? `app.css` : "src/ui/styles/app.css"); - // In Ember, we treat every template as an entry point. `BroccoliCSSBlocks` will // automatically discover all template files if an empty entry array is passed. const entry = isEmber ? [] : (Array.isArray(options.entry) ? options.entry : [options.entry]); @@ -276,7 +309,7 @@ module.exports = { return (tree) => { if (!tree) { return prev.call(parent, tree); } tree = new CSSBlocksAnalyze(tree, transport, broccoliOptions); - app.trees.styles = new CSSBlocksAggregate([app.trees.styles, tree], transport, outputPath); + app.trees.cssblocks = new CSSBlocksAggregate([app.trees.cssblocks || app.trees.styles, tree], transport, this.aggregateFile); // Mad hax for Engines <=0.5.20 support 💩 Right now, engines will throw away the // tree passed to `treeForAddon` and re-generate it. In order for template rewriting diff --git a/packages/@css-blocks/ember-cli/package.json b/packages/@css-blocks/ember-cli/package.json index 686bc0699..683961763 100644 --- a/packages/@css-blocks/ember-cli/package.json +++ b/packages/@css-blocks/ember-cli/package.json @@ -24,8 +24,9 @@ "@css-blocks/broccoli": "^0.20.0-beta.7", "@css-blocks/glimmer": "^0.20.0-beta.7", "@glimmer/application-pipeline": "^0.11.1", + "broccoli-concat": "^3.7.3", "broccoli-funnel": "^2.0.1", - "broccoli-merge-trees": "^3.0.0", + "broccoli-merge-trees": "^3.0.2", "debug": "^3.1.0", "ember-cli-babel": "^6.16.0", "ember-cli-htmlbars": "^3.0.0", diff --git a/packages/@css-blocks/ember-cli/tests/dummy/app/styles/app.css b/packages/@css-blocks/ember-cli/tests/dummy/app/styles/app.css index 813782725..d85bd995b 100644 --- a/packages/@css-blocks/ember-cli/tests/dummy/app/styles/app.css +++ b/packages/@css-blocks/ember-cli/tests/dummy/app/styles/app.css @@ -6,4 +6,4 @@ body { #reset-stylesheet-selector { --reset-stylesheet-selector: applied; color: rgb(102, 51, 153); -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 95ad084ba..e9e199eba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2876,6 +2876,23 @@ broccoli-concat@^3.0.1, broccoli-concat@^3.2.2: lodash.uniq "^4.2.0" walk-sync "^0.3.2" +broccoli-concat@^3.7.3: + version "3.7.3" + resolved "https://registry.npmjs.org/broccoli-concat/-/broccoli-concat-3.7.3.tgz#0dca01311567ffb13180e6b4eb111824628e4885" + dependencies: + broccoli-debug "^0.6.5" + broccoli-kitchen-sink-helpers "^0.3.1" + broccoli-plugin "^1.3.0" + ensure-posix-path "^1.0.2" + fast-sourcemap-concat "^1.4.0" + find-index "^1.1.0" + fs-extra "^4.0.3" + fs-tree-diff "^0.5.7" + lodash.merge "^4.3.1" + lodash.omit "^4.1.0" + lodash.uniq "^4.2.0" + walk-sync "^0.3.2" + broccoli-config-loader@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/broccoli-config-loader/-/broccoli-config-loader-1.0.1.tgz#d10aaf8ebc0cb45c1da5baa82720e1d88d28c80a" @@ -2902,6 +2919,17 @@ broccoli-debug@^0.6.1, broccoli-debug@^0.6.2, broccoli-debug@^0.6.3, broccoli-de symlink-or-copy "^1.1.8" tree-sync "^1.2.2" +broccoli-debug@^0.6.5: + version "0.6.5" + resolved "https://registry.npmjs.org/broccoli-debug/-/broccoli-debug-0.6.5.tgz#164a5cdafd8936e525e702bf8f91f39d758e2e78" + dependencies: + broccoli-plugin "^1.2.1" + fs-tree-diff "^0.5.2" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + symlink-or-copy "^1.1.8" + tree-sync "^1.2.2" + broccoli-dependency-funnel@^2.0.1: version "2.1.0" resolved "https://registry.npmjs.org/broccoli-dependency-funnel/-/broccoli-dependency-funnel-2.1.0.tgz#c06c55549c5e92e0bfde4fc8eedc45a8112e5335" @@ -3031,6 +3059,13 @@ broccoli-merge-trees@^3.0.0: broccoli-plugin "^1.3.0" merge-trees "^2.0.0" +broccoli-merge-trees@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-3.0.2.tgz#f33b451994225522b5c9bcf27d59decfd8ba537d" + dependencies: + broccoli-plugin "^1.3.0" + merge-trees "^2.0.0" + broccoli-middleware@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/broccoli-middleware/-/broccoli-middleware-1.2.1.tgz#a21f255f8bfe5a21c2f0fbf2417addd9d24c9436" @@ -6130,6 +6165,19 @@ fast-sourcemap-concat@^1.3.1: source-map-url "^0.3.0" sourcemap-validator "^1.1.0" +fast-sourcemap-concat@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/fast-sourcemap-concat/-/fast-sourcemap-concat-1.4.0.tgz#122c330d4a2afaff16ad143bc9674b87cd76c8ad" + dependencies: + chalk "^2.0.0" + fs-extra "^5.0.0" + heimdalljs-logger "^0.1.9" + memory-streams "^0.1.3" + mkdirp "^0.5.0" + source-map "^0.4.2" + source-map-url "^0.3.0" + sourcemap-validator "^1.1.0" + fastparse@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"