@@ -4,7 +4,8 @@ import * as postcss from "postcss";
4
4
import * as parser from "postcss-selector-parser" ;
5
5
import * as vars from "postcss-simple-vars" ;
6
6
7
- import { BemSelector , BlockClassSelector } from "./interface" ;
7
+ import { BemSelector , BlockClassSelector , SelectorBemObject } from "./interface" ;
8
+ import { getBemNamesFromUser } from "./userInput" ;
8
9
import { findLcsMap } from "./utils" ;
9
10
export declare type PostcssAny = unknown ;
10
11
@@ -19,19 +20,22 @@ const COMMON_PREFIXES_FOR_MODIFIERS = ["is"];
19
20
export function convertBemToBlocks ( files : Array < string > ) : Promise < void > [ ] {
20
21
let promises : Promise < void > [ ] = [ ] ;
21
22
files . forEach ( file => {
22
- fs . readFile ( file , ( _err , css ) => {
23
- let output = postcss ( [
23
+ fs . readFile ( file , async ( _err , css ) => {
24
+ postcss ( [
24
25
// Using postcss-simple-vars to pass the fileName to the plugin
25
26
vars ( {
26
- variables : ( ) => { return { fileName : path . relative ( process . cwd ( ) , file ) } ;
27
+ variables : ( ) => { return { fileName : path . relative ( process . cwd ( ) , file ) } ; } ,
27
28
} ) ,
28
29
bemToBlocksPlugin ,
29
30
] )
30
- . process ( css , { from : file } ) ;
31
- // rewrite the file with the processed output
32
- const parsedFilePath = path . parse ( file ) ;
33
- const blockFilePath = Object . assign ( parsedFilePath , { ext : `.block${ parsedFilePath . ext } ` , base : undefined } ) ;
34
- promises . push ( fs . writeFile ( path . format ( blockFilePath ) , output . toString ( ) ) ) ;
31
+ . process ( css , { from : file } )
32
+ . then ( output => {
33
+ // rewrite the file with the processed output
34
+ const parsedFilePath = path . parse ( file ) ;
35
+ const blockFilePath = Object . assign ( parsedFilePath , { ext : `.block${ parsedFilePath . ext } ` , base : undefined } ) ;
36
+ promises . push ( fs . writeFile ( path . format ( blockFilePath ) , output . toString ( ) ) ) ;
37
+ } ) . catch ( e => { throw ( e ) ; } ) ;
38
+
35
39
} ) ;
36
40
} ) ;
37
41
return promises ;
@@ -141,32 +145,46 @@ export function constructBlocksMap(bemSelectorCache: BemSelectorMap): BemToBlock
141
145
export const bemToBlocksPlugin : postcss . Plugin < PostcssAny > = postcss . plugin ( "bem-to-blocks-plugin" , ( options ) => {
142
146
options = options || { } ;
143
147
144
- return ( root , result ) => {
145
- let fileName = result . messages . filter ( varObj => { return varObj . name === "fileName" ; } ) [ 0 ] . value ;
148
+ return async ( root , result ) => {
149
+ let fileNameObject = result . messages . find ( varObj => { return varObj . name === "fileName" ; } ) ;
150
+ let fileName = fileNameObject ? fileNameObject . value : undefined ;
146
151
147
152
const bemSelectorCache : BemSelectorMap = new Map ( ) ;
148
153
149
- const buildCache : parser . ProcessorFn = ( selectors ) => {
154
+ const buildCache : parser . ProcessorFn = async ( selectors ) => {
155
+ let promises : Promise < SelectorBemObject > [ ] = [ ] ;
156
+
150
157
selectors . walk ( ( selector ) => {
151
158
// only iterate through classes
152
159
if ( parser . isClassName ( selector ) ) {
153
160
try {
154
- let bemSelector = new BemSelector ( selector . value , fileName ) ;
161
+ let bemSelector = new BemSelector ( selector . value ) ;
155
162
if ( bemSelector . block ) {
156
163
// add it to the cache so it's available for the next pass
157
164
bemSelectorCache . set ( selector . value , bemSelector ) ;
158
165
}
159
166
} catch ( e ) {
160
- if ( selector . parent ) {
161
- selector . parent . insertBefore ( selector , parser . comment ( { value : `ERROR: ${ e . message } ` , spaces : { before : "/* " , after : " */\n" } } ) ) ;
162
- }
167
+ // if the selector does not have a block value, get it from the user
168
+ promises . push ( getBemNamesFromUser ( selector . value , fileName ) ) ;
169
+ // if (selector.parent) {
170
+ // selector.parent.insertBefore(selector, parser.comment({value: `ERROR: ${e.message}`, spaces: {before: "/* ", after: " */\n"}}));
171
+ // }
163
172
}
164
173
}
165
174
} ) ;
166
- return selectors . toString ( ) ;
175
+
176
+ // wait for all the user input
177
+ let answers = await Promise . all ( promises ) ;
178
+
179
+ // add all the user defined blocks to the cache
180
+ for ( let userBem of answers ) {
181
+ let selector = userBem . selector ;
182
+ bemSelectorCache . set ( selector , new BemSelector ( selector , userBem . bemObj ) ) ;
183
+ }
167
184
} ;
168
185
169
186
const rewriteSelectors : parser . ProcessorFn = ( selectors ) => {
187
+
170
188
selectors . walk ( ( selector ) => {
171
189
// we only need to modify class names. We can ignore everything else,
172
190
// like existing attributes, pseudo selectors, comments, imports,
@@ -224,12 +242,16 @@ export const bemToBlocksPlugin: postcss.Plugin<PostcssAny> = postcss.plugin("bem
224
242
} ;
225
243
226
244
// in this pass, we collect all the selectors
227
- root . walkRules ( rule => {
228
- rule . selector = parser ( buildCache ) . processSync ( rule ) ;
245
+ let bemToBlockClassMap : BemToBlockClassMap ;
246
+
247
+ let buildCachePromises : unknown [ ] = [ ] ;
248
+ root . walkRules ( async ( rule ) => {
249
+ buildCachePromises . push ( parser ( buildCache ) . process ( rule ) ) ;
229
250
} ) ;
251
+ await Promise . all ( buildCachePromises ) ;
230
252
231
253
// convert selectors to block selectors
232
- let bemToBlockClassMap : BemToBlockClassMap = constructBlocksMap ( bemSelectorCache ) ;
254
+ bemToBlockClassMap = constructBlocksMap ( bemSelectorCache ) ;
233
255
234
256
// rewrite into a CSS block
235
257
root . walkRules ( rule => {
0 commit comments