1
1
const topologicalSort = require ( "./topologicalSort" ) ;
2
2
3
- const declWhitelist = [ "composes" ] ;
4
- const declFilter = new RegExp ( `^(${ declWhitelist . join ( "|" ) } )$` ) ;
5
3
const matchImports = / ^ ( .+ ?) \s + f r o m \s + (?: " ( [ ^ " ] + ) " | ' ( [ ^ ' ] + ) ' | ( g l o b a l ) ) $ / ;
6
4
const icssImport = / ^ : i m p o r t \( (?: " ( [ ^ " ] + ) " | ' ( [ ^ ' ] + ) ' ) \) / ;
7
5
8
6
const VISITED_MARKER = 1 ;
9
7
10
- function createParentName ( rule , root ) {
11
- return `__${ root . index ( rule . parent ) } _${ rule . selector } ` ;
12
- }
13
-
14
- function serializeImports ( imports ) {
15
- return imports . map ( ( importPath ) => "`" + importPath + "`" ) . join ( ", " ) ;
16
- }
17
-
18
8
/**
19
9
* :import('G') {}
20
10
*
@@ -54,53 +44,53 @@ function addImportToGraph(importId, parentId, graph, visited) {
54
44
}
55
45
56
46
visited [ visitedId ] = VISITED_MARKER ;
47
+
57
48
siblings . push ( importId ) ;
58
49
}
59
50
}
60
51
61
52
module . exports = ( options = { } ) => {
53
+ let importIndex = 0 ;
54
+ const createImportedName =
55
+ typeof options . createImportedName !== "function"
56
+ ? ( importName /*, path*/ ) =>
57
+ `i__imported_${ importName . replace ( / \W / g, "_" ) } _${ importIndex ++ } `
58
+ : options . createImportedName ;
62
59
const failOnWrongOrder = options . failOnWrongOrder ;
63
60
64
61
return {
65
62
postcssPlugin : "postcss-modules-extract-imports" ,
66
- prepare ( result ) {
63
+ prepare ( ) {
67
64
const graph = { } ;
68
65
const visited = { } ;
69
66
const existingImports = { } ;
70
67
const importDecls = { } ;
71
68
const imports = { } ;
72
69
73
- let importIndex = 0 ;
74
-
75
- const createImportedName =
76
- typeof options . createImportedName !== "function"
77
- ? ( importName /*, path*/ ) =>
78
- `i__imported_${ importName . replace ( / \W / g, "_" ) } _${ importIndex ++ } `
79
- : options . createImportedName ;
80
-
81
70
return {
82
- // Check the existing imports order and save refs
83
- Rule ( rule ) {
84
- const matches = icssImport . exec ( rule . selector ) ;
71
+ OnceExit ( root , postcss ) {
72
+ // Check the existing imports order and save refs
73
+ root . walkRules ( ( rule ) => {
74
+ const matches = icssImport . exec ( rule . selector ) ;
85
75
86
- if ( matches ) {
87
- const [ , /*match*/ doubleQuotePath , singleQuotePath ] = matches ;
88
- const importPath = doubleQuotePath || singleQuotePath ;
76
+ if ( matches ) {
77
+ const [ , /*match*/ doubleQuotePath , singleQuotePath ] = matches ;
78
+ const importPath = doubleQuotePath || singleQuotePath ;
89
79
90
- addImportToGraph ( importPath , "root" , graph , visited ) ;
80
+ addImportToGraph ( importPath , "root" , graph , visited ) ;
91
81
92
- existingImports [ importPath ] = rule ;
93
- }
94
- } ,
95
- Declaration ( decl ) {
96
- if ( ! declFilter . test ( decl . prop ) ) {
97
- return ;
98
- }
82
+ existingImports [ importPath ] = rule ;
83
+ }
84
+ } ) ;
85
+
86
+ root . walkDecls ( / ^ c o m p o s e s $ / , ( declaration ) => {
87
+ const matches = declaration . value . match ( matchImports ) ;
99
88
100
- let matches = decl . value . match ( matchImports ) ;
101
- let tmpSymbols ;
89
+ if ( ! matches ) {
90
+ return ;
91
+ }
102
92
103
- if ( matches ) {
93
+ let tmpSymbols ;
104
94
let [
105
95
,
106
96
/*match*/ symbols ,
@@ -114,11 +104,22 @@ module.exports = (options = {}) => {
114
104
tmpSymbols = symbols . split ( / \s + / ) . map ( ( s ) => `global(${ s } )` ) ;
115
105
} else {
116
106
const importPath = doubleQuotePath || singleQuotePath ;
117
- const parentRule = createParentName ( decl . parent , result . root ) ;
107
+
108
+ let parent = declaration . parent ;
109
+ let parentIndexes = "" ;
110
+
111
+ while ( parent . type !== "root" ) {
112
+ parentIndexes =
113
+ parent . parent . index ( parent ) + "_" + parentIndexes ;
114
+ parent = parent . parent ;
115
+ }
116
+
117
+ const { selector } = declaration . parent ;
118
+ const parentRule = `_${ parentIndexes } ${ selector } ` ;
118
119
119
120
addImportToGraph ( importPath , parentRule , graph , visited ) ;
120
121
121
- importDecls [ importPath ] = decl ;
122
+ importDecls [ importPath ] = declaration ;
122
123
imports [ importPath ] = imports [ importPath ] || { } ;
123
124
124
125
tmpSymbols = symbols . split ( / \s + / ) . map ( ( s ) => {
@@ -130,10 +131,9 @@ module.exports = (options = {}) => {
130
131
} ) ;
131
132
}
132
133
133
- decl . value = tmpSymbols . join ( " " ) ;
134
- }
135
- } ,
136
- OnceExit ( root , postcss ) {
134
+ declaration . value = tmpSymbols . join ( " " ) ;
135
+ } ) ;
136
+
137
137
const importsOrder = topologicalSort ( graph , failOnWrongOrder ) ;
138
138
139
139
if ( importsOrder instanceof Error ) {
@@ -143,15 +143,17 @@ module.exports = (options = {}) => {
143
143
) ;
144
144
const decl = importDecls [ importPath ] ;
145
145
146
- const errMsg =
146
+ throw decl . error (
147
147
"Failed to resolve order of composed modules " +
148
- serializeImports ( importsOrder . nodes ) +
149
- "." ;
150
-
151
- throw decl . error ( errMsg , {
152
- plugin : "postcss-modules-extract-imports" ,
153
- word : "composes" ,
154
- } ) ;
148
+ importsOrder . nodes
149
+ . map ( ( importPath ) => "`" + importPath + "`" )
150
+ . join ( ", " ) +
151
+ "." ,
152
+ {
153
+ plugin : "postcss-modules-extract-imports" ,
154
+ word : "composes" ,
155
+ }
156
+ ) ;
155
157
}
156
158
157
159
let lastImportRule ;
0 commit comments