@@ -12,7 +12,9 @@ function getSingleLocalNamesForComposes(root) {
1212 `composition is only allowed when selector is single :local class name not in "${ root } "`
1313 ) ;
1414 }
15+
1516 node = node . nodes [ 0 ] ;
17+
1618 if (
1719 node . type !== 'pseudo' ||
1820 node . value !== ':local' ||
@@ -26,7 +28,9 @@ function getSingleLocalNamesForComposes(root) {
2628 '" is weird'
2729 ) ;
2830 }
31+
2932 node = node . first ;
33+
3034 if ( node . type !== 'selector' || node . length !== 1 ) {
3135 throw new Error (
3236 'composition is only allowed when selector is single :local class name not in "' +
@@ -36,7 +40,9 @@ function getSingleLocalNamesForComposes(root) {
3640 '" is weird'
3741 ) ;
3842 }
43+
3944 node = node . first ;
45+
4046 if ( node . type !== 'class' ) {
4147 // 'id' is not possible, because you can't compose ids
4248 throw new Error (
@@ -47,6 +53,7 @@ function getSingleLocalNamesForComposes(root) {
4753 '" is weird'
4854 ) ;
4955 }
56+
5057 return node . value ;
5158 } ) ;
5259}
@@ -77,6 +84,8 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
7784 return css => {
7885 const generateScopedName =
7986 ( options && options . generateScopedName ) || processor . generateScopedName ;
87+ const generateExportEntry =
88+ ( options && options . generateExportEntry ) || processor . generateExportEntry ;
8089
8190 const exports = Object . create ( null ) ;
8291
@@ -86,13 +95,18 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
8695 css . source . input . from ,
8796 css . source . input . css
8897 ) ;
98+ const exportEntry = generateExportEntry (
99+ rawName ? rawName : name ,
100+ scopedName ,
101+ css . source . input . from ,
102+ css . source . input . css
103+ ) ;
104+ const { key, value } = exportEntry ;
89105
90- exports [ name ] = exports [ name ] || [ ] ;
91-
92- const unescapedScopedName = unescape ( scopedName ) ;
106+ exports [ key ] = exports [ key ] || [ ] ;
93107
94- if ( exports [ name ] . indexOf ( unescapedScopedName ) < 0 ) {
95- exports [ name ] . push ( unescapedScopedName ) ;
108+ if ( exports [ key ] . indexOf ( value ) < 0 ) {
109+ exports [ key ] . push ( value ) ;
96110 }
97111
98112 return scopedName ;
@@ -119,6 +133,7 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
119133 } ) ;
120134 }
121135 }
136+
122137 throw new Error (
123138 `${ node . type } ("${ node } ") is not allowed in a :local block`
124139 ) ;
@@ -131,12 +146,14 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
131146 if ( node . nodes . length !== 1 ) {
132147 throw new Error ( 'Unexpected comma (",") in :local block' ) ;
133148 }
149+
134150 const selector = localizeNode ( node . first , node . spaces ) ;
135151 // move the spaces that were around the psuedo selector to the first
136152 // non-container node
137153 selector . first . spaces = node . spaces ;
138154
139155 node . replaceWith ( selector ) ;
156+
140157 return ;
141158 }
142159 /* falls through */
@@ -151,6 +168,7 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
151168
152169 // Find any :import and remember imported names
153170 const importedNames = { } ;
171+
154172 css . walkRules ( rule => {
155173 if ( / ^ : i m p o r t \( .+ \) $ / . test ( rule . selector ) ) {
156174 rule . walkDecls ( decl => {
@@ -173,10 +191,11 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
173191 let parsedSelector = selectorParser ( ) . astSync ( rule ) ;
174192
175193 rule . selector = traverseNode ( parsedSelector . clone ( ) ) . toString ( ) ;
176- // console.log(rule.selector);
194+
177195 rule . walkDecls ( / c o m p o s e s | c o m p o s e - w i t h / , decl => {
178196 const localNames = getSingleLocalNamesForComposes ( parsedSelector ) ;
179197 const classes = decl . value . split ( / \s + / ) ;
198+
180199 classes . forEach ( className => {
181200 const global = / ^ g l o b a l \( ( [ ^ \) ] + ) \) $ / . exec ( className ) ;
182201
@@ -200,14 +219,17 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
200219 ) ;
201220 }
202221 } ) ;
222+
203223 decl . remove ( ) ;
204224 } ) ;
205225
206226 rule . walkDecls ( decl => {
207- var tokens = decl . value . split ( / ( , | ' [ ^ ' ] * ' | " [ ^ " ] * " ) / ) ;
227+ let tokens = decl . value . split ( / ( , | ' [ ^ ' ] * ' | " [ ^ " ] * " ) / ) ;
228+
208229 tokens = tokens . map ( ( token , idx ) => {
209230 if ( idx === 0 || tokens [ idx - 1 ] === ',' ) {
210231 const localMatch = / ^ ( \s * ) : l o c a l \s * \( ( .+ ?) \) / . exec ( token ) ;
232+
211233 if ( localMatch ) {
212234 return (
213235 localMatch [ 1 ] +
@@ -221,14 +243,16 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
221243 return token ;
222244 }
223245 } ) ;
246+
224247 decl . value = tokens . join ( '' ) ;
225248 } ) ;
226249 } ) ;
227250
228251 // Find any :local keyframes
229252 css . walkAtRules ( atrule => {
230253 if ( / k e y f r a m e s $ / i. test ( atrule . name ) ) {
231- var localMatch = / ^ \s * : l o c a l \s * \( ( .+ ?) \) \s * $ / . exec ( atrule . params ) ;
254+ const localMatch = / ^ \s * : l o c a l \s * \( ( .+ ?) \) \s * $ / . exec ( atrule . params ) ;
255+
232256 if ( localMatch ) {
233257 atrule . params = exportScopedName ( localMatch [ 1 ] ) ;
234258 }
@@ -237,26 +261,37 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
237261
238262 // If we found any :locals, insert an :export rule
239263 const exportedNames = Object . keys ( exports ) ;
264+
240265 if ( exportedNames . length > 0 ) {
241266 const exportRule = postcss . rule ( { selector : ':export' } ) ;
267+
242268 exportedNames . forEach ( exportedName =>
243269 exportRule . append ( {
244270 prop : exportedName ,
245271 value : exports [ exportedName ] . join ( ' ' ) ,
246272 raws : { before : '\n ' } ,
247273 } )
248274 ) ;
275+
249276 css . append ( exportRule ) ;
250277 }
251278 } ;
252279} ) ;
253280
254- processor . generateScopedName = function ( exportedName , path ) {
281+ processor . generateScopedName = function ( name , path ) {
255282 const sanitisedPath = path
256283 . replace ( / \. [ ^ \. \/ \\ ] + $ / , '' )
257284 . replace ( / [ \W _ ] + / g, '_' )
258285 . replace ( / ^ _ | _ $ / g, '' ) ;
259- return `_${ sanitisedPath } __${ exportedName } ` . trim ( ) ;
286+
287+ return `_${ sanitisedPath } __${ name } ` . trim ( ) ;
288+ } ;
289+
290+ processor . generateExportEntry = function ( name , scopedName ) {
291+ return {
292+ key : unescape ( name ) ,
293+ value : unescape ( scopedName ) ,
294+ } ;
260295} ;
261296
262297module . exports = processor ;
0 commit comments