|
1 | 1 | /* eslint-env node */ |
2 | | -import postcss from 'postcss' |
3 | | -import Tokenizer from 'css-selector-tokenizer' |
| 2 | +import postcss from "postcss"; |
| 3 | +import Tokenizer from "css-selector-tokenizer"; |
4 | 4 |
|
5 | 5 | function normalizeNodeArray(nodes) { |
6 | | - var array = [] |
| 6 | + var array = []; |
7 | 7 | nodes.forEach(function(x) { |
8 | 8 | if (Array.isArray(x)) { |
9 | 9 | normalizeNodeArray(x).forEach(function(item) { |
10 | | - array.push(item) |
11 | | - }) |
| 10 | + array.push(item); |
| 11 | + }); |
12 | 12 | } else if (x) { |
13 | | - array.push(x) |
| 13 | + array.push(x); |
14 | 14 | } |
15 | | - }) |
16 | | - if (array.length > 0 && array[array.length - 1].type === 'spacing') { |
17 | | - array.pop() |
| 15 | + }); |
| 16 | + if (array.length > 0 && array[array.length - 1].type === "spacing") { |
| 17 | + array.pop(); |
18 | 18 | } |
19 | | - return array |
| 19 | + return array; |
20 | 20 | } |
21 | 21 |
|
22 | 22 | function localizeNode(node, context) { |
23 | | - if (context.ignoreNextSpacing && node.type !== 'spacing') { |
24 | | - throw new Error('Missing whitespace after :' + context.ignoreNextSpacing) |
| 23 | + if (context.ignoreNextSpacing && node.type !== "spacing") { |
| 24 | + throw new Error("Missing whitespace after :" + context.ignoreNextSpacing); |
25 | 25 | } |
26 | | - if (context.enforceNoSpacing && node.type === 'spacing') { |
27 | | - throw new Error('Missing whitespace before :' + context.enforceNoSpacing) |
| 26 | + if (context.enforceNoSpacing && node.type === "spacing") { |
| 27 | + throw new Error("Missing whitespace before :" + context.enforceNoSpacing); |
28 | 28 | } |
29 | 29 |
|
30 | | - var newNodes |
| 30 | + var newNodes; |
31 | 31 | switch (node.type) { |
32 | | - case 'selectors': |
33 | | - var resultingGlobal |
34 | | - context.hasPureGlobals = false |
| 32 | + case "selectors": |
| 33 | + var resultingGlobal; |
| 34 | + context.hasPureGlobals = false; |
35 | 35 | newNodes = node.nodes.map(function(n) { |
36 | 36 | var nContext = { |
37 | 37 | global: context.global, |
38 | 38 | lastWasSpacing: true, |
39 | 39 | hasLocals: false, |
40 | 40 | explicit: false |
41 | | - } |
42 | | - n = localizeNode(n, nContext) |
43 | | - if (typeof resultingGlobal === 'undefined') { |
44 | | - resultingGlobal = nContext.global |
| 41 | + }; |
| 42 | + n = localizeNode(n, nContext); |
| 43 | + if (typeof resultingGlobal === "undefined") { |
| 44 | + resultingGlobal = nContext.global; |
45 | 45 | } else if (resultingGlobal !== nContext.global) { |
46 | 46 | throw new Error( |
47 | 47 | 'Inconsistent rule global/local result in rule "' + |
48 | 48 | Tokenizer.stringify(node) + |
49 | 49 | '" (multiple selectors must result in the same mode for the rule)' |
50 | | - ) |
| 50 | + ); |
51 | 51 | } |
52 | 52 | if (!nContext.hasLocals) { |
53 | | - context.hasPureGlobals = true |
| 53 | + context.hasPureGlobals = true; |
54 | 54 | } |
55 | | - return n |
56 | | - }) |
57 | | - context.global = resultingGlobal |
58 | | - node = Object.create(node) |
59 | | - node.nodes = normalizeNodeArray(newNodes) |
60 | | - break |
| 55 | + return n; |
| 56 | + }); |
| 57 | + context.global = resultingGlobal; |
| 58 | + node = Object.create(node); |
| 59 | + node.nodes = normalizeNodeArray(newNodes); |
| 60 | + break; |
61 | 61 |
|
62 | | - case 'selector': |
| 62 | + case "selector": |
63 | 63 | newNodes = node.nodes.map(function(n) { |
64 | | - return localizeNode(n, context) |
65 | | - }) |
66 | | - node = Object.create(node) |
67 | | - node.nodes = normalizeNodeArray(newNodes) |
68 | | - break |
| 64 | + return localizeNode(n, context); |
| 65 | + }); |
| 66 | + node = Object.create(node); |
| 67 | + node.nodes = normalizeNodeArray(newNodes); |
| 68 | + break; |
69 | 69 |
|
70 | | - case 'spacing': |
| 70 | + case "spacing": |
71 | 71 | if (context.ignoreNextSpacing) { |
72 | | - context.ignoreNextSpacing = false |
73 | | - context.lastWasSpacing = false |
74 | | - context.enforceNoSpacing = false |
75 | | - return null |
| 72 | + context.ignoreNextSpacing = false; |
| 73 | + context.lastWasSpacing = false; |
| 74 | + context.enforceNoSpacing = false; |
| 75 | + return null; |
76 | 76 | } |
77 | | - context.lastWasSpacing = true |
78 | | - return node |
| 77 | + context.lastWasSpacing = true; |
| 78 | + return node; |
79 | 79 |
|
80 | | - case 'pseudo-class': |
81 | | - if (node.name === 'local' || node.name === 'global') { |
| 80 | + case "pseudo-class": |
| 81 | + if (node.name === "local" || node.name === "global") { |
82 | 82 | if (context.inside) { |
83 | 83 | throw new Error( |
84 | | - 'A :' + |
| 84 | + "A :" + |
85 | 85 | node.name + |
86 | | - ' is not allowed inside of a :' + |
| 86 | + " is not allowed inside of a :" + |
87 | 87 | context.inside + |
88 | | - '(...)' |
89 | | - ) |
| 88 | + "(...)" |
| 89 | + ); |
90 | 90 | } |
91 | | - context.ignoreNextSpacing = context.lastWasSpacing ? node.name : false |
92 | | - context.enforceNoSpacing = context.lastWasSpacing ? false : node.name |
93 | | - context.global = node.name === 'global' |
94 | | - context.explicit = true |
95 | | - return null |
| 91 | + context.ignoreNextSpacing = context.lastWasSpacing ? node.name : false; |
| 92 | + context.enforceNoSpacing = context.lastWasSpacing ? false : node.name; |
| 93 | + context.global = node.name === "global"; |
| 94 | + context.explicit = true; |
| 95 | + return null; |
96 | 96 | } |
97 | | - break |
| 97 | + break; |
98 | 98 |
|
99 | | - case 'nested-pseudo-class': |
100 | | - var subContext |
101 | | - if (node.name === 'local' || node.name === 'global') { |
| 99 | + case "nested-pseudo-class": |
| 100 | + var subContext; |
| 101 | + if (node.name === "local" || node.name === "global") { |
102 | 102 | if (context.inside) { |
103 | 103 | throw new Error( |
104 | | - 'A :' + |
| 104 | + "A :" + |
105 | 105 | node.name + |
106 | | - '(...) is not allowed inside of a :' + |
| 106 | + "(...) is not allowed inside of a :" + |
107 | 107 | context.inside + |
108 | | - '(...)' |
109 | | - ) |
| 108 | + "(...)" |
| 109 | + ); |
110 | 110 | } |
111 | 111 | subContext = { |
112 | | - global: node.name === 'global', |
| 112 | + global: node.name === "global", |
113 | 113 | inside: node.name, |
114 | 114 | hasLocals: false, |
115 | 115 | explicit: true |
116 | | - } |
| 116 | + }; |
117 | 117 | node = node.nodes.map(function(n) { |
118 | | - return localizeNode(n, subContext) |
119 | | - }) |
| 118 | + return localizeNode(n, subContext); |
| 119 | + }); |
120 | 120 | // don't leak spacing |
121 | | - node[0].before = undefined |
122 | | - node[node.length - 1].after = undefined |
| 121 | + node[0].before = undefined; |
| 122 | + node[node.length - 1].after = undefined; |
123 | 123 | } else { |
124 | 124 | subContext = { |
125 | 125 | global: context.global, |
126 | 126 | inside: context.inside, |
127 | 127 | lastWasSpacing: true, |
128 | 128 | hasLocals: false, |
129 | 129 | explicit: context.explicit |
130 | | - } |
| 130 | + }; |
131 | 131 | newNodes = node.nodes.map(function(n) { |
132 | | - return localizeNode(n, subContext) |
133 | | - }) |
134 | | - node = Object.create(node) |
135 | | - node.nodes = normalizeNodeArray(newNodes) |
| 132 | + return localizeNode(n, subContext); |
| 133 | + }); |
| 134 | + node = Object.create(node); |
| 135 | + node.nodes = normalizeNodeArray(newNodes); |
136 | 136 | } |
137 | 137 | if (subContext.hasLocals) { |
138 | | - context.hasLocals = true |
| 138 | + context.hasLocals = true; |
139 | 139 | } |
140 | | - break |
| 140 | + break; |
141 | 141 |
|
142 | | - case 'id': |
143 | | - case 'class': |
| 142 | + case "id": |
| 143 | + case "class": |
144 | 144 | if (!context.global) { |
145 | 145 | node = { |
146 | | - type: 'nested-pseudo-class', |
147 | | - name: 'local', |
| 146 | + type: "nested-pseudo-class", |
| 147 | + name: "local", |
148 | 148 | nodes: [node] |
149 | | - } |
150 | | - context.hasLocals = true |
| 149 | + }; |
| 150 | + context.hasLocals = true; |
151 | 151 | } |
152 | | - break |
| 152 | + break; |
153 | 153 | } |
154 | 154 |
|
155 | 155 | // reset context |
156 | | - context.lastWasSpacing = false |
157 | | - context.ignoreNextSpacing = false |
158 | | - context.enforceNoSpacing = false |
159 | | - return node |
| 156 | + context.lastWasSpacing = false; |
| 157 | + context.ignoreNextSpacing = false; |
| 158 | + context.enforceNoSpacing = false; |
| 159 | + return node; |
160 | 160 | } |
161 | 161 |
|
162 | 162 | module.exports = postcss.plugin( |
163 | | - 'postcss-modules-local-by-default', |
| 163 | + "postcss-modules-local-by-default", |
164 | 164 | (options = {}) => css => { |
165 | 165 | if ( |
166 | 166 | options.mode && |
167 | | - options.mode !== 'global' && |
168 | | - options.mode !== 'local' && |
169 | | - options.mode !== 'pure' |
| 167 | + options.mode !== "global" && |
| 168 | + options.mode !== "local" && |
| 169 | + options.mode !== "pure" |
170 | 170 | ) { |
171 | 171 | throw Error( |
172 | 172 | 'options.mode must be either "global", "local" or "pure" (default "local")' |
173 | | - ) |
| 173 | + ); |
174 | 174 | } |
175 | | - var pureMode = options.mode === 'pure' |
176 | | - var globalMode = options.mode === 'global' |
| 175 | + var pureMode = options.mode === "pure"; |
| 176 | + var globalMode = options.mode === "global"; |
177 | 177 | css.walkRules(function(rule) { |
178 | 178 | if ( |
179 | | - rule.parent.type === 'atrule' && |
| 179 | + rule.parent.type === "atrule" && |
180 | 180 | /keyframes$/.test(rule.parent.name) |
181 | 181 | ) { |
182 | 182 | // ignore keyframe rules |
183 | | - return |
| 183 | + return; |
184 | 184 | } |
185 | | - var selector = Tokenizer.parse(rule.selector) |
| 185 | + var selector = Tokenizer.parse(rule.selector); |
186 | 186 | var context = { |
187 | 187 | options: options, |
188 | 188 | global: globalMode, |
189 | 189 | hasPureGlobals: false |
190 | | - } |
191 | | - var newSelector |
| 190 | + }; |
| 191 | + var newSelector; |
192 | 192 | try { |
193 | | - newSelector = localizeNode(selector, context) |
| 193 | + newSelector = localizeNode(selector, context); |
194 | 194 | } catch (e) { |
195 | | - throw rule.error(e.message) |
| 195 | + throw rule.error(e.message); |
196 | 196 | } |
197 | 197 | if (pureMode && context.hasPureGlobals) { |
198 | 198 | throw rule.error( |
199 | 199 | 'Selector "' + |
200 | 200 | Tokenizer.stringify(selector) + |
201 | 201 | '" is not pure ' + |
202 | | - '(pure selectors must contain at least one local class or id)' |
203 | | - ) |
| 202 | + "(pure selectors must contain at least one local class or id)" |
| 203 | + ); |
204 | 204 | } |
205 | | - rule.selector = Tokenizer.stringify(newSelector) |
206 | | - }) |
| 205 | + rule.selector = Tokenizer.stringify(newSelector); |
| 206 | + }); |
207 | 207 | } |
208 | | -) |
| 208 | +); |
0 commit comments