@@ -59,128 +59,80 @@ function walkUrls(parsed, callback) {
59
59
} ) ;
60
60
}
61
61
62
- function getUrlsFromValue ( value , result , filter , decl ) {
63
- if ( ! needParseDecl . test ( value ) ) {
64
- return ;
65
- }
66
-
67
- const parsed = valueParser ( value ) ;
68
- const urls = [ ] ;
69
-
70
- walkUrls ( parsed , ( node , url , needQuotes , isStringValue ) => {
71
- if ( url . trim ( ) . replace ( / \\ [ \r \n ] / g, '' ) . length === 0 ) {
72
- result . warn ( `Unable to find uri in '${ decl ? decl . toString ( ) : value } '` , {
73
- node : decl ,
74
- } ) ;
75
-
76
- return ;
77
- }
62
+ export default postcss . plugin ( pluginName , ( options ) => ( css , result ) => {
63
+ const importsMap = new Map ( ) ;
64
+ const replacersMap = new Map ( ) ;
78
65
79
- if ( filter && ! filter ( url ) ) {
66
+ css . walkDecls ( ( decl ) => {
67
+ if ( ! needParseDecl . test ( decl . value ) ) {
80
68
return ;
81
69
}
82
70
83
- const splittedUrl = url . split ( / ( \? ) ? # / ) ;
84
- const [ urlWithoutHash , singleQuery , hashValue ] = splittedUrl ;
85
- const hash =
86
- singleQuery || hashValue
87
- ? `${ singleQuery ? '?' : '' } ${ hashValue ? `#${ hashValue } ` : '' } `
88
- : '' ;
89
-
90
- const normalizedUrl = normalizeUrl ( urlWithoutHash , isStringValue ) ;
91
-
92
- urls . push ( { node, url : normalizedUrl , hash, needQuotes } ) ;
93
- } ) ;
94
-
95
- // eslint-disable-next-line consistent-return
96
- return { parsed, urls } ;
97
- }
98
-
99
- function walkDecls ( css , result , filter ) {
100
- const items = [ ] ;
71
+ const parsed = valueParser ( decl . value ) ;
101
72
102
- css . walkDecls ( ( decl ) => {
103
- const item = getUrlsFromValue ( decl . value , result , filter , decl ) ;
73
+ walkUrls ( parsed , ( node , url , needQuotes , isStringValue ) => {
74
+ if ( url . trim ( ) . replace ( / \\ [ \r \n ] / g, '' ) . length === 0 ) {
75
+ result . warn (
76
+ `Unable to find uri in '${ decl ? decl . toString ( ) : decl . value } '` ,
77
+ { node : decl }
78
+ ) ;
104
79
105
- if ( ! item || item . urls . length === 0 ) {
106
- return ;
107
- }
80
+ return ;
81
+ }
108
82
109
- items . push ( { decl, parsed : item . parsed , urls : item . urls } ) ;
110
- } ) ;
83
+ if ( options . filter && ! options . filter ( url ) ) {
84
+ return ;
85
+ }
111
86
112
- return items ;
113
- }
87
+ const splittedUrl = url . split ( / ( \? ) ? # / ) ;
88
+ const [ urlWithoutHash , singleQuery , hashValue ] = splittedUrl ;
89
+ const hash =
90
+ singleQuery || hashValue
91
+ ? `${ singleQuery ? '?' : '' } ${ hashValue ? `#${ hashValue } ` : '' } `
92
+ : '' ;
114
93
115
- function flatten ( array ) {
116
- return array . reduce ( ( a , b ) => a . concat ( b ) , [ ] ) ;
117
- }
94
+ const normalizedUrl = normalizeUrl ( urlWithoutHash , isStringValue ) ;
118
95
119
- function collectUniqueUrlsWithNodes ( array ) {
120
- return array . reduce ( ( accumulator , currentValue ) => {
121
- const { url, needQuotes, hash, node } = currentValue ;
122
- const found = accumulator . find (
123
- ( item ) =>
124
- url === item . url && needQuotes === item . needQuotes && hash === item . hash
125
- ) ;
126
-
127
- if ( ! found ) {
128
- accumulator . push ( { url, hash, needQuotes, nodes : [ node ] } ) ;
129
- } else {
130
- found . nodes . push ( node ) ;
131
- }
96
+ const importKey = normalizedUrl ;
97
+ let importName = importsMap . get ( importKey ) ;
132
98
133
- return accumulator ;
134
- } , [ ] ) ;
135
- }
99
+ if ( ! importName ) {
100
+ importName = `___CSS_LOADER_URL_IMPORT_ ${ importsMap . size } ___` ;
101
+ importsMap . set ( importKey , importName ) ;
136
102
137
- export default postcss . plugin (
138
- pluginName ,
139
- ( options ) =>
140
- function process ( css , result ) {
141
- const traversed = walkDecls ( css , result , options . filter ) ;
142
- const flattenTraversed = flatten ( traversed . map ( ( item ) => item . urls ) ) ;
143
- const urlsWithNodes = collectUniqueUrlsWithNodes ( flattenTraversed ) ;
144
- const replacers = new Map ( ) ;
145
-
146
- urlsWithNodes . forEach ( ( urlWithNodes , index ) => {
147
- const { url, hash, needQuotes, nodes } = urlWithNodes ;
148
- const replacementName = `___CSS_LOADER_URL_REPLACEMENT_${ index } ___` ;
149
-
150
- result . messages . push (
151
- {
152
- pluginName,
153
- type : 'import' ,
154
- value : { type : 'url' , replacementName, url, needQuotes, hash } ,
103
+ result . messages . push ( {
104
+ pluginName,
105
+ type : 'import' ,
106
+ value : {
107
+ type : 'url' ,
108
+ importName,
109
+ url : normalizedUrl ,
155
110
} ,
156
- {
157
- pluginName,
158
- type : 'replacer' ,
159
- value : { type : 'url' , replacementName } ,
160
- }
161
- ) ;
162
-
163
- nodes . forEach ( ( node ) => {
164
- replacers . set ( node , replacementName ) ;
165
111
} ) ;
166
- } ) ;
112
+ }
167
113
168
- traversed . forEach ( ( item ) => {
169
- walkUrls ( item . parsed , ( node ) => {
170
- const replacementName = replacers . get ( node ) ;
114
+ const replacerKey = JSON . stringify ( { importKey, hash, needQuotes } ) ;
171
115
172
- if ( ! replacementName ) {
173
- return ;
174
- }
116
+ let replacerName = replacersMap . get ( replacerKey ) ;
175
117
176
- // eslint-disable-next-line no-param-reassign
177
- node . type = 'word' ;
178
- // eslint-disable-next-line no-param-reassign
179
- node . value = replacementName ;
118
+ if ( ! replacerName ) {
119
+ replacerName = `___CSS_LOADER_URL_REPLACEMENT_${ replacersMap . size } ___` ;
120
+ replacersMap . set ( replacerKey , replacerName ) ;
121
+
122
+ result . messages . push ( {
123
+ pluginName,
124
+ type : 'replacer' ,
125
+ value : { type : 'url' , replacerName, importName, hash, needQuotes } ,
180
126
} ) ;
127
+ }
181
128
182
- // eslint-disable-next-line no-param-reassign
183
- item . decl . value = item . parsed . toString ( ) ;
184
- } ) ;
185
- }
186
- ) ;
129
+ // eslint-disable-next-line no-param-reassign
130
+ node . type = 'word' ;
131
+ // eslint-disable-next-line no-param-reassign
132
+ node . value = replacerName ;
133
+ } ) ;
134
+
135
+ // eslint-disable-next-line no-param-reassign
136
+ decl . value = parsed . toString ( ) ;
137
+ } ) ;
138
+ } ) ;
0 commit comments