Skip to content

Commit e4a2b4a

Browse files
amiller-ghchriseppstein
authored andcommitted
feat: Flesh out broccoli-css-blocks plugin.
1 parent 6ba4a29 commit e4a2b4a

File tree

5 files changed

+105
-31
lines changed

5 files changed

+105
-31
lines changed

Diff for: package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@
3636
"remap-istanbul": "^0.9.5",
3737
"source-map-support": "^0.4.15",
3838
"test-console": "^1.1.0",
39-
"tslint": "^5.9.1",
4039
"ts-node": "^3.0.4",
40+
"tslint": "^5.9.1",
4141
"typedoc": "^0.7.1",
42-
"typescript": "^2.7.2",
42+
"typescript": "^2.8.1",
4343
"watch": "^1.0.2"
4444
},
4545
"workspaces": [

Diff for: packages/broccoli-css-blocks/package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,17 @@
3030
"dependencies": {
3131
"@glimmer/compiler": "^0.33.0",
3232
"@glimmer/syntax": "^0.33.0",
33+
"@types/recursive-readdir": "^2.2.0",
3334
"broccoli-funnel": "^2.0.1",
3435
"broccoli-merge-trees": "^3.0.0",
3536
"broccoli-plugin": "^1.3.0",
3637
"colors": "^1.2.1",
3738
"css-blocks": "^0.17.0",
3839
"debug": "^3.1.0",
40+
"fs-extra": "^5.0.0",
3941
"opticss": "file:../../../opticss/packages/opticss",
40-
"postcss": "^6.0.19",
42+
"postcss": "^6.0.14",
43+
"recursive-readdir": "^2.2.2",
4144
"walk-sync": "^0.3.2"
4245
}
4346
}

Diff for: packages/broccoli-css-blocks/src/index.ts

+71-19
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,56 @@
1-
import * as fs from "fs";
1+
import * as fs from "fs-extra";
22
import * as path from "path";
3-
import { promisify } from "util";
43

54
import { TemplateTypes } from "@opticss/template-api";
6-
import { Analyzer } from "css-blocks";
5+
import { Analyzer, BlockCompiler, StyleMapping } from "css-blocks";
6+
import { Optimizer } from "opticss";
7+
import * as postcss from "postcss";
8+
import * as readdir from "recursive-readdir";
79

810
import { BroccoliPlugin } from "./utils";
911

10-
const readdirAsync = promisify(fs.readdirSync) as (path: string) => Promise<string[]>;
11-
const symlinkAsync = promisify(fs.symlinkSync) as (from: string, to: string) => Promise<void>;
12-
1312
interface BroccoliOptions {
1413
entry: string[];
14+
output: string;
1515
analyzer: Analyzer<keyof TemplateTypes>;
16+
transport: {[key: string]: object};
1617
}
1718

1819
class BroccoliCSSBlocks extends BroccoliPlugin {
1920

2021
private analyzer: Analyzer<keyof TemplateTypes>;
2122
private entry: string[];
23+
private output: string;
24+
private transport: { [key: string]: object };
25+
private optimizationOptions: object = {};
2226

2327
// tslint:disable-next-line:prefer-whatever-to-any
2428
constructor(inputNode: any, options: BroccoliOptions) {
25-
super([inputNode], {
26-
name: "broccoli-css-blocks",
27-
});
28-
this.analyzer = options.analyzer;
29+
super([inputNode], { name: "broccoli-css-blocks" });
30+
2931
this.entry = options.entry;
32+
this.output = options.output;
33+
this.analyzer = options.analyzer;
34+
this.transport = options.transport;
35+
36+
if (!this.output) {
37+
throw new Error("CSS Blocks Broccoli Plugin requires an output file name.");
38+
}
3039
}
3140

3241
async build() {
42+
let options = this.analyzer.cssBlocksOptions;
43+
let blockCompiler = new BlockCompiler(postcss, options);
44+
let optimizer = new Optimizer(this.optimizationOptions, this.analyzer.optimizationOptions);
3345

34-
// This build step is just a pass-through of all files!
35-
// We're just analyzing right now.
36-
let files = await readdirAsync(this.inputPaths[0]);
46+
// This build step is *mostly* just a pass-through of all files!
47+
// QUESTION: Tom, is there a better way to do this in Broccoli?
48+
let files = await readdir(this.inputPaths[0]);
3749
for (let file of files) {
50+
file = path.relative(this.inputPaths[0], file);
51+
await fs.ensureDir(path.join(this.outputPath, path.dirname(file)));
3852
try {
39-
await symlinkAsync(
53+
await fs.symlink(
4054
path.join(this.inputPaths[0], file),
4155
path.join(this.outputPath, file),
4256
);
@@ -48,12 +62,50 @@ class BroccoliCSSBlocks extends BroccoliPlugin {
4862
// Oh hey look, we're analyzing.
4963
await this.analyzer.analyze(...this.entry);
5064

51-
// Here we'd compile the blocks, optionally optimize our output,
52-
// and inject the final CSS file into the tree. Then, attach our
53-
// StyleMapping data to whatever shared memory data transport we
54-
// have to pass to funnel rewrite data to our Rewriter.
65+
// Compile all Blocks and add them as sources to the Optimizer.
66+
// TODO: handle a sourcemap from compiling the block file via a preprocessor.
67+
let blocks = this.analyzer.transitiveBlockDependencies();
68+
for (let block of blocks) {
69+
if (block.stylesheet) {
70+
let root = blockCompiler.compile(block, block.stylesheet, this.analyzer);
71+
let result = root.toResult({ to: this.output, map: { inline: false, annotation: false } });
72+
let filesystemPath = options.importer.filesystemPath(block.identifier, options);
73+
let filename = filesystemPath || options.importer.debugIdentifier(block.identifier, options);
74+
75+
// If this Block has a representation on disk, remove it from our output tree.
76+
// TODO: This isn't working right now because `importer.filesystemPath` doesn't return the expected path...
77+
if (filesystemPath) {
78+
await fs.remove(path.join(this.outputPath, path.relative(options.rootDir, filesystemPath)));
79+
}
80+
81+
// Add the compiled Block file to the optimizer.
82+
optimizer.addSource({
83+
content: result.css,
84+
filename,
85+
sourceMap: result.map.toJSON(),
86+
});
87+
}
88+
}
89+
90+
// Add each Analysis to the Optimizer.
91+
this.analyzer.eachAnalysis((a) => optimizer.addAnalysis(a.forOptimizer(options)));
92+
93+
// Run optimization and compute StyleMapping.
94+
let optimized = await optimizer.optimize(this.output);
95+
let styleMapping = new StyleMapping<"Opticss.Template">(optimized.styleMapping, blocks, options, this.analyzer.analyses());
96+
97+
// Attach all computed data to our magic shared memory transport object...
98+
this.transport.mapping = styleMapping;
99+
this.transport.blocks = blocks;
100+
this.transport.analyzer = this.analyzer;
101+
this.transport.css = optimized.output;
55102

56-
return this.analyzer;
103+
// Write our compiled CSS to the output tree.
104+
// QUESTION: GUH! TOM! THIS DOESN'T APPEAR IN THE OUTPUT TREE!
105+
await fs.outputFile(
106+
path.join(this.outputPath, this.output),
107+
optimized.output.content.toString(),
108+
);
57109

58110
}
59111

Diff for: packages/glimmer-templates/package.json

+3-4
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,12 @@
5151
"devDependencies": {
5252
"@css-blocks/code-style": "^0.17.0"
5353
},
54-
5554
"dependencies": {
5655
"@glimmer/compiler": "^0.33.0",
5756
"@glimmer/resolution-map-builder": "0.5.1",
5857
"@glimmer/resolver": "^0.4.3",
5958
"@glimmer/syntax": "^0.33.0",
6059
"@opticss/element-analysis": "file:../../../opticss/packages/element-analysis",
61-
"opticss": "file:../../../opticss/packages/opticss",
6260
"@opticss/template-api": "file:../../../opticss/packages/template-api",
6361
"@opticss/util": "file:../../../opticss/packages/util",
6462
"@types/glob": "^5.0.30",
@@ -67,6 +65,7 @@
6765
"glimmer-analyzer": "^0.2.0",
6866
"glob": "^7.1.2",
6967
"object.values": "^1.0.4",
70-
"postcss": "^6.0.1"
68+
"opticss": "file:../../../opticss/packages/opticss",
69+
"postcss": "^6.0.14"
7170
}
72-
}
71+
}

Diff for: yarn.lock

+25-5
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@
364364
version "1.10.0"
365365
resolved "https://registry.npmjs.org/@types/prettier/-/prettier-1.10.0.tgz#5abf1ec0a6e904fe2490cc2068f36a38e4a63c42"
366366

367+
"@types/recursive-readdir@^2.2.0":
368+
version "2.2.0"
369+
resolved "https://registry.npmjs.org/@types/recursive-readdir/-/recursive-readdir-2.2.0.tgz#b39cd5474fd58ea727fe434d5c68b7a20ba9121c"
370+
dependencies:
371+
"@types/node" "*"
372+
367373
"@types/shelljs@^0.7.0":
368374
version "0.7.8"
369375
resolved "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.8.tgz#4b4d6ee7926e58d7bca448a50ba442fd9f6715bd"
@@ -2284,6 +2290,14 @@ fs-extra@^4.0.1:
22842290
jsonfile "^4.0.0"
22852291
universalify "^0.1.0"
22862292

2293+
fs-extra@^5.0.0:
2294+
version "5.0.0"
2295+
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd"
2296+
dependencies:
2297+
graceful-fs "^4.1.2"
2298+
jsonfile "^4.0.0"
2299+
universalify "^0.1.0"
2300+
22872301
fs-tree-diff@^0.5.3:
22882302
version "0.5.7"
22892303
resolved "https://registry.npmjs.org/fs-tree-diff/-/fs-tree-diff-0.5.7.tgz#315e2b098d5fe7f622880ac965b1b051868ac871"
@@ -3676,7 +3690,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
36763690
version "1.0.1"
36773691
resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
36783692

3679-
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
3693+
"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
36803694
version "3.0.4"
36813695
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
36823696
dependencies:
@@ -4495,7 +4509,7 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0
44954509
source-map "^0.5.6"
44964510
supports-color "^3.2.3"
44974511

4498-
postcss@^6.0.1, postcss@^6.0.12, postcss@^6.0.14, postcss@^6.0.19:
4512+
postcss@^6.0.1, postcss@^6.0.12, postcss@^6.0.14:
44994513
version "6.0.19"
45004514
resolved "https://registry.npmjs.org/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555"
45014515
dependencies:
@@ -4747,6 +4761,12 @@ rechoir@^0.6.2:
47474761
dependencies:
47484762
resolve "^1.1.6"
47494763

4764+
recursive-readdir@^2.2.2:
4765+
version "2.2.2"
4766+
resolved "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f"
4767+
dependencies:
4768+
minimatch "3.0.4"
4769+
47504770
redent@^1.0.0:
47514771
version "1.0.0"
47524772
resolved "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
@@ -5725,9 +5745,9 @@ [email protected]:
57255745
version "2.3.4"
57265746
resolved "https://registry.npmjs.org/typescript/-/typescript-2.3.4.tgz#3d38321828231e434f287514959c37a82b629f42"
57275747

5728-
typescript@^2.7.2:
5729-
version "2.7.2"
5730-
resolved "https://registry.npmjs.org/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836"
5748+
typescript@^2.8.1:
5749+
version "2.8.1"
5750+
resolved "https://registry.npmjs.org/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624"
57315751

57325752
uglify-js@^2.6, uglify-js@^2.8.29:
57335753
version "2.8.29"

0 commit comments

Comments
 (0)