11const postcss = require ( 'postcss' ) ;
22const valueParser = require ( 'postcss-value-parser' ) ;
3- const loaderUtils = require ( 'loader-utils' ) ;
43
54const pluginName = 'postcss-import-parser' ;
65
@@ -19,7 +18,7 @@ function getUrl(node) {
1918 return node . value ;
2019 }
2120
22- return '' ;
21+ return null ;
2322}
2423
2524function parseImport ( params ) {
@@ -31,7 +30,7 @@ function parseImport(params) {
3130
3231 const url = getUrl ( nodes [ 0 ] ) ;
3332
34- if ( url . trim ( ) . length === 0 ) {
33+ if ( ! url || url . trim ( ) . length === 0 ) {
3534 return null ;
3635 }
3736
@@ -44,61 +43,66 @@ function parseImport(params) {
4443 } ;
4544}
4645
46+ function walkAtRules ( css , result , filter ) {
47+ const items = [ ] ;
48+
49+ css . walkAtRules ( / ^ i m p o r t $ / i, ( atRule ) => {
50+ // Convert only top-level @import
51+ if ( atRule . parent . type !== 'root' ) {
52+ return ;
53+ }
54+
55+ if ( atRule . nodes ) {
56+ result . warn (
57+ "It looks like you didn't end your @import statement correctly. " +
58+ 'Child nodes are attached to it.' ,
59+ { node : atRule }
60+ ) ;
61+ return ;
62+ }
63+
64+ const parsed = parseImport ( atRule . params ) ;
65+
66+ if ( ! parsed ) {
67+ // eslint-disable-next-line consistent-return
68+ return result . warn ( `Unable to find uri in '${ atRule . toString ( ) } '` , {
69+ node : atRule ,
70+ } ) ;
71+ }
72+
73+ if ( filter && ! filter ( parsed ) ) {
74+ return ;
75+ }
76+
77+ atRule . remove ( ) ;
78+
79+ const { url, media } = parsed ;
80+
81+ items . push ( { url, media } ) ;
82+ } ) ;
83+
84+ return items ;
85+ }
86+
87+ function uniq ( array ) {
88+ return array . reduce (
89+ ( acc , d ) =>
90+ ! acc . find ( ( el ) => el . url === d . url && el . media === d . media )
91+ ? [ ...acc , d ]
92+ : acc ,
93+ [ ]
94+ ) ;
95+ }
96+
4797module . exports = postcss . plugin (
4898 pluginName ,
49- ( ) =>
99+ ( options = { } ) =>
50100 function process ( css , result ) {
51- css . walkAtRules ( / ^ i m p o r t $ / i, ( atRule ) => {
52- // Convert only top-level @import
53- if ( atRule . parent . type !== 'root' ) {
54- return ;
55- }
56-
57- if ( atRule . nodes ) {
58- result . warn (
59- "It looks like you didn't end your @import statement correctly. " +
60- 'Child nodes are attached to it.' ,
61- { node : atRule }
62- ) ;
63- return ;
64- }
65-
66- const parsed = parseImport ( atRule . params ) ;
67-
68- if ( ! parsed ) {
69- // eslint-disable-next-line consistent-return
70- return result . warn ( `Unable to find uri in '${ atRule . toString ( ) } '` , {
71- node : atRule ,
72- } ) ;
73- }
74-
75- atRule . remove ( ) ;
76-
77- const { media } = parsed ;
78- let { url } = parsed ;
79- const isUrlRequest = loaderUtils . isUrlRequest ( url ) ;
80-
81- if ( isUrlRequest ) {
82- url = loaderUtils . urlToRequest ( url ) ;
83- }
84-
85- const alreadyIncluded = result . messages . find (
86- ( message ) =>
87- message . pluginName === pluginName &&
88- message . type === 'import' &&
89- message . item . url === url &&
90- message . item . media === media
91- ) ;
92-
93- if ( alreadyIncluded ) {
94- return ;
95- }
96-
97- result . messages . push ( {
98- pluginName,
99- type : 'import' ,
100- item : { url, media } ,
101- } ) ;
101+ const traversed = walkAtRules ( css , result , options . filter ) ;
102+ const paths = uniq ( traversed ) ;
103+
104+ paths . forEach ( ( item ) => {
105+ result . messages . push ( { pluginName, type : 'import' , item } ) ;
102106 } ) ;
103107 }
104108) ;
0 commit comments