1
1
import * as fs from "fs-extra" ;
2
2
import * as path from "path" ;
3
3
4
- import { Analyzer , Block , BlockCompiler , StyleMapping } from "@css-blocks/core" ;
4
+ import { Analyzer , BlockCompiler , StyleMapping } from "@css-blocks/core" ;
5
5
import { TemplateTypes } from "@opticss/template-api" ;
6
-
7
6
import * as debugGenerator from "debug" ;
8
- import { OptiCSSOptions , Optimizer , postcss } from "opticss" ;
7
+ import { OptiCSSOptions , Optimizer } from "opticss" ;
8
+ import * as postcss from "postcss" ;
9
9
import * as readdir from "recursive-readdir" ;
10
10
11
11
import { BroccoliPlugin } from "./utils" ;
12
12
13
13
const debug = debugGenerator ( "css-blocks:broccoli" ) ;
14
14
15
- export interface Transport {
16
- id : string ;
17
- mapping ?: StyleMapping < keyof TemplateTypes > ;
18
- blocks ?: Set < Block > ;
19
- analyzer ?: Analyzer < keyof TemplateTypes > ;
20
- css ?: string ;
21
- }
22
-
23
15
export interface BroccoliOptions {
24
16
entry : string [ ] ;
25
17
output : string ;
26
- root : string ;
27
18
analyzer : Analyzer < keyof TemplateTypes > ;
28
- transport : Transport ;
19
+ transport : { [ key : string ] : object } ;
29
20
optimization ?: Partial < OptiCSSOptions > ;
30
21
}
31
22
32
23
class BroccoliCSSBlocks extends BroccoliPlugin {
33
24
34
25
private analyzer : Analyzer < keyof TemplateTypes > ;
35
- private entries : string [ ] ;
26
+ private entry : string [ ] ;
36
27
private output : string ;
37
- private root : string ;
38
- private transport : Transport ;
28
+ private transport : { [ key : string ] : object } ;
39
29
private optimizationOptions : Partial < OptiCSSOptions > ;
30
+
40
31
// tslint:disable-next-line:prefer-whatever-to-any
41
32
constructor ( inputNode : any , options : BroccoliOptions ) {
42
33
super ( [ inputNode ] , { name : "broccoli-css-blocks" } ) ;
43
34
44
- this . entries = options . entry . slice ( 0 ) ;
45
- this . output = options . output || "css-blocks.css" ;
35
+ this . entry = options . entry ;
36
+ this . output = options . output ;
37
+ this . analyzer = options . analyzer ;
46
38
this . transport = options . transport ;
47
39
this . optimizationOptions = options . optimization || { } ;
48
- this . analyzer = options . analyzer ;
49
- this . root = options . root || process . cwd ( ) ;
50
- this . transport . css = this . transport . css ? this . transport . css : "" ;
40
+
41
+ if ( ! this . output ) {
42
+ throw new Error ( "CSS Blocks Broccoli Plugin requires an output file name." ) ;
43
+ }
51
44
}
52
45
53
46
async build ( ) {
54
47
let options = this . analyzer . cssBlocksOptions ;
55
48
let blockCompiler = new BlockCompiler ( postcss , options ) ;
56
49
let optimizer = new Optimizer ( this . optimizationOptions , this . analyzer . optimizationOptions ) ;
57
50
58
- // When no entry points are passed, we treat *every* template as an entry point.
59
- let discover = ! this . entries . length ;
60
-
61
51
// This build step is *mostly* just a pass-through of all files!
62
52
// QUESTION: Tom, is there a better way to do this in Broccoli?
63
53
let files = await readdir ( this . inputPaths [ 0 ] ) ;
64
54
for ( let file of files ) {
65
55
file = path . relative ( this . inputPaths [ 0 ] , file ) ;
66
-
67
- // If we're in Classic or Pods mode, every hbs file is an entry point.
68
- if ( discover && path . extname ( file ) === ".hbs" ) { this . entries . push ( file ) ; }
69
-
70
- fs . ensureDirSync ( path . join ( this . outputPath , path . dirname ( file ) ) ) ;
56
+ await fs . ensureDir ( path . join ( this . outputPath , path . dirname ( file ) ) ) ;
71
57
try {
72
- fs . symlinkSync (
58
+ await fs . symlink (
73
59
path . join ( this . inputPaths [ 0 ] , file ) ,
74
60
path . join ( this . outputPath , file ) ,
75
61
) ;
76
62
} catch ( e ) {
77
63
// tslint:disable-next-line:no-console
78
64
console . log ( "Error linking" , path . join ( this . inputPaths [ 0 ] , file ) , "to output directory." ) ;
79
65
}
80
-
81
66
}
82
67
83
- // The glimmer-analyzer package tries to require() package.json
84
- // in the root of the directory it is passed. We pass it our broccoli
85
- // tree, so it needs to contain package.json too.
86
- // TODO: Ideally this is configurable in glimmer-analyzer. We can
87
- // contribute that option back to the project. However,
88
- // other template integrations may want this available too...
89
- fs . writeFileSync (
90
- path . join ( this . outputPath , "package.json" ) ,
91
- fs . readFileSync ( path . join ( this . root , "package.json" ) ) ,
92
- ) ;
93
-
94
68
// Oh hey look, we're analyzing.
95
69
this . analyzer . reset ( ) ;
96
- await this . analyzer . analyze ( this . outputPath , this . entries ) ;
70
+ await this . analyzer . analyze ( ... this . entry ) ;
97
71
98
72
// Compile all Blocks and add them as sources to the Optimizer.
99
73
// TODO: handle a sourcemap from compiling the block file via a preprocessor.
@@ -106,9 +80,10 @@ class BroccoliCSSBlocks extends BroccoliPlugin {
106
80
let filename = filesystemPath || options . importer . debugIdentifier ( block . identifier , options ) ;
107
81
108
82
// If this Block has a representation on disk, remove it from our output tree.
83
+ // TODO: This isn't working right now because `importer.filesystemPath` doesn't return the expected path...
109
84
if ( filesystemPath ) {
110
- debug ( `Removing block file ${ filesystemPath } from output.` ) ;
111
- fs . unlinkSync ( filesystemPath ) ;
85
+ debug ( `Removing block file ${ path . relative ( options . rootDir , filesystemPath ) } from output.` ) ;
86
+ await fs . unlink ( path . join ( this . outputPath , path . relative ( options . rootDir , filesystemPath ) ) ) ;
112
87
}
113
88
114
89
// Add the compiled Block file to the optimizer.
@@ -131,9 +106,13 @@ class BroccoliCSSBlocks extends BroccoliPlugin {
131
106
this . transport . mapping = styleMapping ;
132
107
this . transport . blocks = blocks ;
133
108
this . transport . analyzer = this . analyzer ;
134
- this . transport . css + = optimized . output . content . toString ( ) ;
109
+ this . transport . css = optimized . output ;
135
110
136
- debug ( `Compilation Finished: ${ this . transport . id } ` ) ;
111
+ // Write our compiled CSS to the output tree.
112
+ await fs . writeFile (
113
+ path . join ( this . outputPath , this . output ) ,
114
+ optimized . output . content . toString ( ) ,
115
+ ) ;
137
116
138
117
}
139
118
0 commit comments