1
1
const postcss = require ( 'postcss' ) ;
2
2
const valueParser = require ( 'postcss-value-parser' ) ;
3
- const loaderUtils = require ( 'loader-utils' ) ;
4
3
5
4
const pluginName = 'postcss-import-parser' ;
6
5
@@ -19,7 +18,7 @@ function getUrl(node) {
19
18
return node . value ;
20
19
}
21
20
22
- return '' ;
21
+ return null ;
23
22
}
24
23
25
24
function parseImport ( params ) {
@@ -31,7 +30,7 @@ function parseImport(params) {
31
30
32
31
const url = getUrl ( nodes [ 0 ] ) ;
33
32
34
- if ( url . trim ( ) . length === 0 ) {
33
+ if ( ! url || url . trim ( ) . length === 0 ) {
35
34
return null ;
36
35
}
37
36
@@ -44,61 +43,66 @@ function parseImport(params) {
44
43
} ;
45
44
}
46
45
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
+
47
97
module . exports = postcss . plugin (
48
98
pluginName ,
49
- ( ) =>
99
+ ( options = { } ) =>
50
100
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 } ) ;
102
106
} ) ;
103
107
}
104
108
) ;
0 commit comments