1
- import type { AddonImplementation } from "ember-cli/lib/models/addon" ;
1
+ import funnel = require( "broccoli-funnel" ) ;
2
+ import mergeTrees = require( "broccoli-merge-trees" ) ;
3
+ import type { InputNode } from "broccoli-node-api" ;
4
+ import Filter = require( "broccoli-persistent-filter" ) ;
5
+ import type { PluginOptions } from "broccoli-plugin/dist/interfaces" ;
6
+ import EmberApp from "ember-cli/lib/broccoli/ember-app" ;
7
+ import type Addon from "ember-cli/lib/models/addon" ;
8
+ import type { AddonImplementation , ThisAddon } from "ember-cli/lib/models/addon" ;
9
+ import Project from "ember-cli/lib/models/project" ;
10
+
11
+ class CSSBlocksApplicationPlugin extends Filter {
12
+ appName : string ;
13
+ constructor ( appName : string , inputNodes : InputNode [ ] , options ?: PluginOptions ) {
14
+ super ( mergeTrees ( inputNodes ) , options || { } ) ;
15
+ this . appName = appName ;
16
+ }
17
+ processString ( contents : string , _relativePath : string ) : string {
18
+ return contents ;
19
+ }
20
+ async build ( ) {
21
+ await super . build ( ) ;
22
+ // console.log(`XXX ${this.appName}`);
23
+ // let entries = this.input.entries(".", {globs: ["**/*"]});
24
+ // for (let entry of entries) {
25
+ // console.log(entry.relativePath);
26
+ // }
27
+ this . output . writeFileSync (
28
+ `${ this . appName } /services/-css-blocks-data.js` ,
29
+ `// CSS Blocks Generated Data. DO NOT EDIT.
30
+ export const data = {className: "it-worked"};
31
+ ` ) ;
32
+ }
33
+ }
34
+
35
+ interface AddonEnvironment {
36
+ parent : Addon | EmberApp ;
37
+ app : EmberApp ;
38
+ rootDir : string ;
39
+ isApp : boolean ;
40
+ modulePrefix : string ;
41
+ }
42
+
43
+ interface CSSBlocksApplicationAddon {
44
+ _modulePrefix ( ) : string ;
45
+ env : AddonEnvironment | undefined ;
46
+ getEnv ( parent ) : AddonEnvironment ;
47
+ }
2
48
3
49
/**
4
50
* An ember-cli addon for Ember applications using CSS Blocks in its
5
51
* application code. This addon should be a dependency in Ember applications.
6
52
*
7
53
* This addon is responsible for bundling together all CSS Blocks content
8
54
* from the application, concatenating it into a final artifact, and
9
- * optimizing its content using OptiCSS. Additionaly , this addon generates a
55
+ * optimizing its content using OptiCSS. Additionally , this addon generates a
10
56
* JSON bundle that contains runtime data that templates need to resolve
11
57
* what classes to add to each CSS Blocks-powered component. And, finally,
12
58
* this addon provides a runtime helper to actually write out those classes.
@@ -31,12 +77,14 @@ import type { AddonImplementation } from "ember-cli/lib/models/addon";
31
77
*
32
78
* @todo : Provide a link for Ember build pipeline readme.
33
79
*/
34
- const EMBER_ADDON : AddonImplementation = {
80
+ const EMBER_ADDON : AddonImplementation < CSSBlocksApplicationAddon > = {
35
81
/**
36
82
* The name of this addon. Generally matches the package name in package.json.
37
83
*/
38
84
name : "@css-blocks/ember-app" ,
39
85
86
+ env : undefined ,
87
+
40
88
/**
41
89
* Initalizes this addon instance for use.
42
90
* @param parent - The project or addon that directly depends on this addon.
@@ -47,6 +95,42 @@ const EMBER_ADDON: AddonImplementation = {
47
95
// recommend guarding this call, so we're gonna ask TSLint to chill.
48
96
// tslint:disable-next-line: no-unused-expression
49
97
this . _super . init && this . _super . init . call ( this , parent , project ) ;
98
+ this . treePaths . app = "../runtime/app" ;
99
+ this . treePaths . addon = "../runtime/addon" ;
100
+ } ,
101
+
102
+ _modulePrefix ( ) : string {
103
+ /// @ts -ignore
104
+ const parent = this . parent ;
105
+ const config = typeof parent . config === "function" ? parent . config ( ) || { } : { } ;
106
+ const name = typeof parent . name === "function" ? parent . name ( ) : parent . name ;
107
+ const moduleName = typeof parent . moduleName === "function" ? parent . moduleName ( ) : parent . moduleName ;
108
+ return moduleName || parent . modulePrefix || config . modulePrefix || name || "" ;
109
+ } ,
110
+
111
+ getEnv ( this : ThisAddon < CSSBlocksApplicationAddon > , parent : Addon | EmberApp ) : AddonEnvironment {
112
+ // Fetch a reference to the parent app
113
+ let current : Addon | Project = this ;
114
+ let app : EmberApp | undefined ;
115
+ do { app = ( < Addon > current ) . app || app ; }
116
+ while ( ( < Addon > ( < Addon > current ) . parent ) . parent && ( current = ( < Addon > current ) . parent ) ) ;
117
+
118
+ let isApp = parent === app ;
119
+
120
+ // The absolute path to the root of our app (aka: the directory that contains "src").
121
+ // Needed because app root !== project root in addons – its located at `tests/dummy`.
122
+ // TODO: Is there a better way to get this for Ember?
123
+ let rootDir = ( < Addon > parent ) . root || ( < EmberApp > parent ) . project . root ;
124
+
125
+ let modulePrefix = this . _modulePrefix ( ) ;
126
+
127
+ return {
128
+ parent,
129
+ app : app ! ,
130
+ rootDir,
131
+ isApp,
132
+ modulePrefix,
133
+ } ;
50
134
} ,
51
135
52
136
/**
@@ -57,6 +141,7 @@ const EMBER_ADDON: AddonImplementation = {
57
141
included ( parent ) {
58
142
// We must call this._super or weird stuff happens.
59
143
this . _super . included . apply ( this , [ parent ] ) ;
144
+ this . env = this . getEnv ( parent ) ;
60
145
} ,
61
146
62
147
/**
@@ -66,10 +151,17 @@ const EMBER_ADDON: AddonImplementation = {
66
151
* @returns - A tree that's ready to process.
67
152
*/
68
153
preprocessTree ( type , tree ) {
69
- if ( type !== "template" ) return tree ;
70
-
71
- // TODO: Do something in the template tree.
72
- return tree ;
154
+ let env = this . env ! ;
155
+ if ( type === "js" ) {
156
+ if ( env . isApp ) {
157
+ let appAndAddonTree = new CSSBlocksApplicationPlugin ( env . modulePrefix , [ env . app . addonTree ( ) , tree ] ) ;
158
+ return funnel ( appAndAddonTree , { srcDir : env . modulePrefix , destDir : env . modulePrefix } ) ;
159
+ } else {
160
+ return tree ;
161
+ }
162
+ } else {
163
+ return tree ;
164
+ }
73
165
} ,
74
166
75
167
/**
0 commit comments