@@ -82,13 +82,15 @@ export class CSSBlocksApplicationPlugin extends Filter {
82
82
debug ( `Loaded ${ blocksUsed . size } blocks.` ) ;
83
83
debug ( `Loaded ${ optimizer . analyses . length } analyses.` ) ;
84
84
let cssFileName = cssBlocksOutputFilename ( this . cssBlocksOptions ) ;
85
- let sourceMapFileName = `${ cssFileName } .map` ;
86
85
let optLogFileName = `${ cssFileName } .optimization.log` ;
87
86
let optimizationResult = await optimizer . optimize ( cssFileName ) ;
88
87
debug ( `Optimized CSS. There were ${ optimizationResult . actions . performed . length } optimizations performed.` ) ;
88
+
89
+ // Embed the sourcemap into the final css output
90
+ const finalizedCss = addSourcemapInfoToOptimizedCss ( optimizationResult . output . content . toString ( ) , optimizationResult . output . sourceMap ?. toString ( ) ) ;
91
+
89
92
this . output . mkdirSync ( path . dirname ( cssFileName ) , { recursive : true } ) ;
90
- this . output . writeFileSync ( cssFileName , optimizationResult . output . content . toString ( ) , "utf8" ) ;
91
- this . output . writeFileSync ( sourceMapFileName , optimizationResult . output . sourceMap ?. toString ( ) , "utf8" ) ;
93
+ this . output . writeFileSync ( cssFileName , finalizedCss , "utf8" ) ;
92
94
this . output . writeFileSync ( optLogFileName , optimizationResult . actions . logStrings ( ) . join ( "\n" ) , "utf8" ) ;
93
95
debug ( "Wrote css, sourcemap, and optimization log." ) ;
94
96
@@ -145,11 +147,10 @@ export class CSSBlocksApplicationPlugin extends Filter {
145
147
* 1) The result of the CSSBlocksApplicationPlugin.
146
148
* 2) The css tree, passed in to `preprocessTree()`.
147
149
*
148
- * The result of this plugin will be a file in app/styles/app.css that includes existing content appended
149
- * with the contents of css-blocks.css. This should be merged with the existing css tree to overwrite
150
- * the app.css file with this one.
150
+ * This plugin will add the compiled CSS content created by the CSSBlocksApplicationPlugin and place
151
+ * it into the CSS tree at the preferred location.
151
152
*/
152
- export class CSSBlocksStylesProcessorPlugin extends Plugin {
153
+ export class CSSBlocksStylesPreprocessorPlugin extends Plugin {
153
154
appName : string ;
154
155
previousSourceTree : FSTree ;
155
156
cssBlocksOptions : ResolvedCSSBlocksEmberOptions ;
@@ -160,63 +161,56 @@ export class CSSBlocksStylesProcessorPlugin extends Plugin {
160
161
this . cssBlocksOptions = cssBlocksOptions ;
161
162
}
162
163
async build ( ) {
163
- let mergeIntoAppStyles = true ;
164
- if ( this . cssBlocksOptions . output ) {
165
- // if the output filename is explicitly declared, we don't merge it with
166
- // the application styles.
167
- mergeIntoAppStyles = false ;
168
- }
169
- // Read the optimized CSS Blocks styles file, generated previously by the CSSBlocksApplicationPlugin.
164
+ // Are there any changes to make? If not, bail out early.
170
165
let stylesheetPath = cssBlocksOutputFilename ( this . cssBlocksOptions ) ;
171
- let applicationStylesheetPath = `app/styles/app.css` ;
172
- if ( ! this . input . existsSync ( applicationStylesheetPath ) ) {
173
- mergeIntoAppStyles = false ;
174
- debug ( `No app/styles/app.css file found. Blocks content is in ${ stylesheetPath } . The application should handle it.` ) ;
175
- }
176
- let globs : Array < string > ;
177
- if ( mergeIntoAppStyles ) {
178
- globs = [ stylesheetPath , applicationStylesheetPath ] ;
179
- } else {
180
- globs = [ stylesheetPath ] ;
181
- }
182
- let entries = this . input . entries ( "." , { globs} ) ;
166
+ let entries = this . input . entries ( "." , { globs : [ stylesheetPath ] } ) ;
183
167
let currentFSTree = FSTree . fromEntries ( entries ) ;
184
168
let patch = this . previousSourceTree . calculatePatch ( currentFSTree ) ;
185
169
if ( patch . length === 0 ) {
186
170
return ;
187
171
} else {
188
172
this . previousSourceTree = currentFSTree ;
189
173
}
174
+ // Read in the CSS Blocks compiled content that was created previously.
190
175
let blocksFileContents : string ;
191
- // And read the application CSS that was previously built by Ember and ignored by CSS Blocks.
192
176
if ( this . input . existsSync ( stylesheetPath ) ) {
193
177
blocksFileContents = this . input . readFileSync ( stylesheetPath , { encoding : "utf8" } ) ;
194
178
} else {
195
179
// We always write the output file if this addon is installed, even if
196
180
// there's no css-blocks files.
197
181
blocksFileContents = "" ;
198
182
}
199
- let outputContents : string ;
200
- let outputPath : string ;
201
- if ( mergeIntoAppStyles ) {
202
- const appCssFileContents = this . input . readFileSync ( applicationStylesheetPath , { encoding : "utf8" } ) ;
203
- if ( blocksFileContents ) {
204
- outputContents = `${ appCssFileContents } \n${ blocksFileContents } ` ;
205
- } else {
206
- outputContents = appCssFileContents ;
207
- }
208
- outputPath = applicationStylesheetPath ;
209
- } else {
210
- outputContents = blocksFileContents ;
211
- outputPath = stylesheetPath ;
212
- }
213
183
214
- // Now, write out the combined result of the application CSS and CSS Blocks contents.
215
- this . output . mkdirSync ( path . dirname ( outputPath ) , { recursive : true } ) ;
216
- this . output . writeFileSync ( outputPath , outputContents ) ;
184
+ // Now, write out compiled content to its expected location.
185
+ // By default, this is app/styles/css-blocks.css.
186
+ this . output . mkdirSync ( path . dirname ( stylesheetPath ) , { recursive : true } ) ;
187
+ this . output . writeFileSync ( stylesheetPath , blocksFileContents ) ;
217
188
}
218
189
}
219
190
191
+ /**
192
+ * Given CSS and a sourcemap, append an embedded sourcemap (base64 encoded)
193
+ * to the end of the css.
194
+ * @param css - The CSS content to be added to.
195
+ * @param sourcemap - The sourcemap data to add.
196
+ * @returns - The CSS with embedded sourcemap, or just the CSS if no sourcemap was given.
197
+ */
198
+ function addSourcemapInfoToOptimizedCss ( css : string , sourcemap ?: string ) {
199
+ if ( ! sourcemap ) {
200
+ return css ;
201
+ }
202
+
203
+ const encodedSourcemap = Buffer . from ( sourcemap ) . toString ( "base64" ) ;
204
+ return `${ css } \n/*# sourceMappingURL=data:application/json;base64,${ encodedSourcemap } */` ;
205
+ }
206
+
207
+ /**
208
+ * Generate the output path for the compiled CSS Blocks content, using the
209
+ * preferred filename given by the user. If none is given, the default
210
+ * path is "app/styles/css-blocks.css".
211
+ * @param options - The options passed to the Ember plugin.
212
+ * @returns - The path for the CSS Blocks compiled content.
213
+ */
220
214
function cssBlocksOutputFilename ( options : ResolvedCSSBlocksEmberOptions ) {
221
215
let outputName = options . output || "css-blocks.css" ;
222
216
return `app/styles/${ outputName } ` ;
0 commit comments