1
1
/* eslint-env node */
2
2
import postcss from "postcss" ;
3
3
import Tokenizer from "css-selector-tokenizer" ;
4
+ import { extractICSS , createICSSRules } from "icss-utils" ;
5
+ import genericNames from "generic-names" ;
4
6
5
7
const plugin = "postcss-modules-local-by-default" ;
6
8
@@ -19,7 +21,7 @@ const isModifier = node =>
19
21
node . type === "pseudo-class" &&
20
22
( node . name === "local" || node . name === "global" ) ;
21
23
22
- function localizeNode ( node , { mode, inside } ) {
24
+ function localizeNode ( node , { mode, inside, getAlias } ) {
23
25
const newNodes = node . nodes . reduce ( ( acc , n , index , nodes ) => {
24
26
switch ( n . type ) {
25
27
case "spacing" :
@@ -62,28 +64,25 @@ function localizeNode(node, { mode, inside }) {
62
64
}
63
65
return [
64
66
...acc ,
65
- ...localizeNode ( n . nodes [ 0 ] , { mode : n . name , inside : n . name } ) . nodes
67
+ ...localizeNode ( n . nodes [ 0 ] , {
68
+ mode : n . name ,
69
+ inside : n . name ,
70
+ getAlias
71
+ } ) . nodes
66
72
] ;
67
73
} else {
68
74
return [
69
75
...acc ,
70
76
Object . assign ( { } , n , {
71
- nodes : localizeNode ( n . nodes [ 0 ] , { mode, inside } ) . nodes
77
+ nodes : localizeNode ( n . nodes [ 0 ] , { mode, inside, getAlias } ) . nodes
72
78
} )
73
79
] ;
74
80
}
75
81
76
82
case "id" :
77
83
case "class" :
78
84
if ( mode === "local" ) {
79
- return [
80
- ...acc ,
81
- {
82
- type : "nested-pseudo-class" ,
83
- name : "local" ,
84
- nodes : [ n ]
85
- }
86
- ] ;
85
+ return [ ...acc , Object . assign ( { } , n , { name : getAlias ( n . name ) } ) ] ;
87
86
}
88
87
return [ ...acc , n ] ;
89
88
@@ -95,11 +94,11 @@ function localizeNode(node, { mode, inside }) {
95
94
return Object . assign ( { } , node , { nodes : trimNodes ( newNodes ) } ) ;
96
95
}
97
96
98
- const localizeSelectors = ( selectors , mode ) => {
97
+ const localizeSelectors = ( selectors , mode , getAlias ) => {
99
98
const node = Tokenizer . parse ( selectors ) ;
100
99
return Tokenizer . stringify (
101
100
Object . assign ( { } , node , {
102
- nodes : node . nodes . map ( n => localizeNode ( n , { mode } ) )
101
+ nodes : node . nodes . map ( n => localizeNode ( n , { mode, getAlias } ) )
103
102
} )
104
103
) ;
105
104
} ;
@@ -113,14 +112,29 @@ const walkRules = (css, callback) => {
113
112
} ;
114
113
115
114
module . exports = postcss . plugin ( plugin , ( options = { } ) => css => {
115
+ const generateScopedName =
116
+ options . generateScopedName ||
117
+ genericNames ( "[name]__[local]---[hash:base64:5]" ) ;
118
+ const input = ( css && css . source && css . source . input ) || { } ;
119
+ const { icssImports, icssExports } = extractICSS ( css ) ;
120
+ const aliases = { } ;
121
+ const getAlias = name => {
122
+ const alias = generateScopedName ( name , input . from , input . css ) ;
123
+ aliases [ name ] = alias ;
124
+ return alias ;
125
+ } ;
116
126
walkRules ( css , rule => {
117
127
try {
118
128
rule . selector = localizeSelectors (
119
129
rule . selector ,
120
- options . mode === "global" ? "global" : "local"
130
+ options . mode === "global" ? "global" : "local" ,
131
+ getAlias
121
132
) ;
122
133
} catch ( e ) {
123
134
throw rule . error ( e . message ) ;
124
135
}
125
136
} ) ;
137
+ css . prepend (
138
+ createICSSRules ( icssImports , Object . assign ( { } , icssExports , aliases ) )
139
+ ) ;
126
140
} ) ;
0 commit comments