11/* eslint-env node */
22import postcss from "postcss" ;
33import Tokenizer from "css-selector-tokenizer" ;
4+ import { extractICSS , createICSSRules } from "icss-utils" ;
5+ import genericNames from "generic-names" ;
46
57const plugin = "postcss-modules-local-by-default" ;
68
@@ -19,7 +21,7 @@ const isModifier = node =>
1921 node . type === "pseudo-class" &&
2022 ( node . name === "local" || node . name === "global" ) ;
2123
22- function localizeNode ( node , { mode, inside } ) {
24+ function localizeNode ( node , { mode, inside, getAlias } ) {
2325 const newNodes = node . nodes . reduce ( ( acc , n , index , nodes ) => {
2426 switch ( n . type ) {
2527 case "spacing" :
@@ -62,28 +64,25 @@ function localizeNode(node, { mode, inside }) {
6264 }
6365 return [
6466 ...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
6672 ] ;
6773 } else {
6874 return [
6975 ...acc ,
7076 Object . assign ( { } , n , {
71- nodes : localizeNode ( n . nodes [ 0 ] , { mode, inside } ) . nodes
77+ nodes : localizeNode ( n . nodes [ 0 ] , { mode, inside, getAlias } ) . nodes
7278 } )
7379 ] ;
7480 }
7581
7682 case "id" :
7783 case "class" :
7884 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 ) } ) ] ;
8786 }
8887 return [ ...acc , n ] ;
8988
@@ -95,11 +94,11 @@ function localizeNode(node, { mode, inside }) {
9594 return Object . assign ( { } , node , { nodes : trimNodes ( newNodes ) } ) ;
9695}
9796
98- const localizeSelectors = ( selectors , mode ) => {
97+ const localizeSelectors = ( selectors , mode , getAlias ) => {
9998 const node = Tokenizer . parse ( selectors ) ;
10099 return Tokenizer . stringify (
101100 Object . assign ( { } , node , {
102- nodes : node . nodes . map ( n => localizeNode ( n , { mode } ) )
101+ nodes : node . nodes . map ( n => localizeNode ( n , { mode, getAlias } ) )
103102 } )
104103 ) ;
105104} ;
@@ -113,14 +112,29 @@ const walkRules = (css, callback) => {
113112} ;
114113
115114module . 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+ } ;
116126 walkRules ( css , rule => {
117127 try {
118128 rule . selector = localizeSelectors (
119129 rule . selector ,
120- options . mode === "global" ? "global" : "local"
130+ options . mode === "global" ? "global" : "local" ,
131+ getAlias
121132 ) ;
122133 } catch ( e ) {
123134 throw rule . error ( e . message ) ;
124135 }
125136 } ) ;
137+ css . prepend (
138+ createICSSRules ( icssImports , Object . assign ( { } , icssExports , aliases ) )
139+ ) ;
126140} ) ;
0 commit comments