1
+ /* eslint-env node */
2
+ "use strict" ;
3
+
4
+ const { BroccoliCSSBlocks } = require ( "@css-blocks/broccoli" ) ;
5
+ const { Project, GlimmerAnalyzer, GlimmerRewriter } = require ( "@css-blocks/glimmer" ) ;
6
+ const path = require ( "path" ) ;
7
+ const Funnel = require ( "broccoli-funnel" ) ;
8
+
9
+ // QUESTION: Tom, how to we get the app's module config!?
10
+ // Is it possible for addons to augment it?
11
+ // If no, how to apps augment it?
12
+ const MODULE_CONFIG = require ( "@glimmer/application-pipeline/dist/lib/broccoli/default-module-configuration.js" ) . default ;
13
+ MODULE_CONFIG . types . stylesheet = { definitiveCollection : "components" } ;
14
+ MODULE_CONFIG . collections . components . types . push ( "stylesheet" ) ;
15
+
16
+ module . exports = {
17
+ name : "css-blocks" ,
18
+
19
+ isDevelopingAddon ( ) { return true ; } ,
20
+
21
+ setupPreprocessorRegistry ( type , registry ) {
22
+ if ( type !== 'parent' ) { return ; }
23
+ let self = this ;
24
+ registry . add ( "glimmer-ast-plugin" , function ( env ) {
25
+ // Woo, shared memory wormhole!...
26
+ let { analyzer, mapping } = self . transport ;
27
+
28
+ // TODO: Write a better `getAnalysis` method on `Analyzer`
29
+ let analysis = analyzer . analyses ( ) . find ( a => a . template . identifier === env . meta . specifier ) ;
30
+
31
+ // If there is no analysis for this template, don't do anything.
32
+ // Otherwise, run the rewriter!
33
+ if ( ! analysis ) { return { name : 'css-blocks-noop' , visitors : { } } ; }
34
+ return new GlimmerRewriter ( env . syntax , mapping , analysis ) ;
35
+ } ) ;
36
+ } ,
37
+
38
+ included ( app ) {
39
+
40
+ this . _super . included . apply ( this , arguments ) ;
41
+ let options = app . options [ "css-blocks" ] || { } ;
42
+
43
+ // Ember-cli is *mostly* used with Glimmer. However, it can technically be
44
+ // configured to use other template types. Here we default to the Glimmer
45
+ // analyzer, but if a `getAnalyzer` function is provided we defer to the
46
+ // user-supplied analyzer.
47
+ let analyzer = options . getAnalyzer ?
48
+ options . getAnalyzer ( app ) :
49
+ new GlimmerAnalyzer ( new Project ( app . project . root , MODULE_CONFIG ) ) ;
50
+
51
+ // TODO: Better options validation.
52
+ if ( typeof options . entry !== "string" ) {
53
+ throw new Error ( "Invalid css-block options in `ember-cli-build.js`: Entry option must be a string." ) ;
54
+ }
55
+ if ( typeof options . output !== "string" ) {
56
+ throw new Error ( "Invalid css-block options in `ember-cli-build.js`: Output option must be a string." ) ;
57
+ }
58
+
59
+ // TODO: This transport object need to be defined by CSS Blocks Core.
60
+ // We use the same construct in both Broccoli and Webpack and
61
+ // the data model for each should be standardized to Analyzers
62
+ // and Rewriters consistently know how to communicate.
63
+ this . transport = { } ;
64
+
65
+ app . trees . src = new BroccoliCSSBlocks ( app . trees . src , {
66
+ entry : [ options . entry ] ,
67
+ output : options . output ,
68
+ analyzer,
69
+ transport : this . transport // I hate shared memory...
70
+ } ) ;
71
+
72
+ // Remove all source css-blocks stylesheets
73
+ // TODO: This should remove all resolved Block object identifiers on the Analyzer.
74
+ // This should be handled by @css -blocks/broccoli, but we have a bug.
75
+ app . trees . src = new Funnel ( app . trees . src , {
76
+ exclude : [ "**/stylesheet.css" ]
77
+ } ) ;
78
+
79
+ // Place our generated CSS files into Glimmer's styles tree.
80
+ // Glimmer splits out its `styles` tree before we get our hands
81
+ // on the project, we need to re-insert all the project-wide
82
+ // work we did in the `src` tree here once we're done for it
83
+ // to be reflected in the final output.
84
+ // TODO: We will be working with Tom to improve how Glimmer
85
+ // exposes its app trees.
86
+ app . trees . styles = new Funnel ( app . trees . src , {
87
+ include : [ "src/ui/styles/**/*" ]
88
+ } ) ;
89
+
90
+ }
91
+ } ;
0 commit comments