1 | let parser = require('postcss-value-parser')
|
2 |
|
3 | let Value = require('./value')
|
4 | let insertAreas = require('./hacks/grid-utils').insertAreas
|
5 |
|
6 | const OLD_LINEAR = /(^|[^-])linear-gradient\(\s*(top|left|right|bottom)/i
|
7 | const OLD_RADIAL = /(^|[^-])radial-gradient\(\s*\d+(\w*|%)\s+\d+(\w*|%)\s*,/i
|
8 | const IGNORE_NEXT = /(!\s*)?autoprefixer:\s*ignore\s+next/i
|
9 | const GRID_REGEX = /(!\s*)?autoprefixer\s*grid:\s*(on|off|(no-)?autoplace)/i
|
10 |
|
11 | const SIZES = [
|
12 | 'width',
|
13 | 'height',
|
14 | 'min-width',
|
15 | 'max-width',
|
16 | 'min-height',
|
17 | 'max-height',
|
18 | 'inline-size',
|
19 | 'min-inline-size',
|
20 | 'max-inline-size',
|
21 | 'block-size',
|
22 | 'min-block-size',
|
23 | 'max-block-size'
|
24 | ]
|
25 |
|
26 | function hasGridTemplate(decl) {
|
27 | return decl.parent.some(
|
28 | i => i.prop === 'grid-template' || i.prop === 'grid-template-areas'
|
29 | )
|
30 | }
|
31 |
|
32 | function hasRowsAndColumns(decl) {
|
33 | let hasRows = decl.parent.some(i => i.prop === 'grid-template-rows')
|
34 | let hasColumns = decl.parent.some(i => i.prop === 'grid-template-columns')
|
35 | return hasRows && hasColumns
|
36 | }
|
37 |
|
38 | class Processor {
|
39 | constructor(prefixes) {
|
40 | this.prefixes = prefixes
|
41 | }
|
42 |
|
43 | |
44 |
|
45 |
|
46 | add(css, result) {
|
47 |
|
48 | let resolution = this.prefixes.add['@resolution']
|
49 | let keyframes = this.prefixes.add['@keyframes']
|
50 | let viewport = this.prefixes.add['@viewport']
|
51 | let supports = this.prefixes.add['@supports']
|
52 |
|
53 | css.walkAtRules(rule => {
|
54 | if (rule.name === 'keyframes') {
|
55 | if (!this.disabled(rule, result)) {
|
56 | return keyframes && keyframes.process(rule)
|
57 | }
|
58 | } else if (rule.name === 'viewport') {
|
59 | if (!this.disabled(rule, result)) {
|
60 | return viewport && viewport.process(rule)
|
61 | }
|
62 | } else if (rule.name === 'supports') {
|
63 | if (
|
64 | this.prefixes.options.supports !== false &&
|
65 | !this.disabled(rule, result)
|
66 | ) {
|
67 | return supports.process(rule)
|
68 | }
|
69 | } else if (rule.name === 'media' && rule.params.includes('-resolution')) {
|
70 | if (!this.disabled(rule, result)) {
|
71 | return resolution && resolution.process(rule)
|
72 | }
|
73 | }
|
74 |
|
75 | return undefined
|
76 | })
|
77 |
|
78 |
|
79 | css.walkRules(rule => {
|
80 | if (this.disabled(rule, result)) return undefined
|
81 |
|
82 | return this.prefixes.add.selectors.map(selector => {
|
83 | return selector.process(rule, result)
|
84 | })
|
85 | })
|
86 |
|
87 | function insideGrid(decl) {
|
88 | return decl.parent.nodes.some(node => {
|
89 | if (node.type !== 'decl') return false
|
90 | let displayGrid =
|
91 | node.prop === 'display' && /(inline-)?grid/.test(node.value)
|
92 | let gridTemplate = node.prop.startsWith('grid-template')
|
93 | let gridGap = /^grid-([A-z]+-)?gap/.test(node.prop)
|
94 | return displayGrid || gridTemplate || gridGap
|
95 | })
|
96 | }
|
97 | function insideFlex(decl) {
|
98 | return decl.parent.some(node => {
|
99 | return node.prop === 'display' && /(inline-)?flex/.test(node.value)
|
100 | })
|
101 | }
|
102 |
|
103 | let gridPrefixes =
|
104 | this.gridStatus(css, result) &&
|
105 | this.prefixes.add['grid-area'] &&
|
106 | this.prefixes.add['grid-area'].prefixes
|
107 |
|
108 | css.walkDecls(decl => {
|
109 | if (this.disabledDecl(decl, result)) return undefined
|
110 |
|
111 | let parent = decl.parent
|
112 | let prop = decl.prop
|
113 | let value = decl.value
|
114 |
|
115 | if (prop === 'grid-row-span') {
|
116 | result.warn(
|
117 | 'grid-row-span is not part of final Grid Layout. Use grid-row.',
|
118 | { node: decl }
|
119 | )
|
120 | return undefined
|
121 | } else if (prop === 'grid-column-span') {
|
122 | result.warn(
|
123 | 'grid-column-span is not part of final Grid Layout. Use grid-column.',
|
124 | { node: decl }
|
125 | )
|
126 | return undefined
|
127 | } else if (prop === 'display' && value === 'box') {
|
128 | result.warn(
|
129 | 'You should write display: flex by final spec ' +
|
130 | 'instead of display: box',
|
131 | { node: decl }
|
132 | )
|
133 | return undefined
|
134 | } else if (prop === 'text-emphasis-position') {
|
135 | if (value === 'under' || value === 'over') {
|
136 | result.warn(
|
137 | 'You should use 2 values for text-emphasis-position ' +
|
138 | 'For example, `under left` instead of just `under`.',
|
139 | { node: decl }
|
140 | )
|
141 | }
|
142 | } else if (
|
143 | /^(align|justify|place)-(items|content)$/.test(prop) &&
|
144 | insideFlex(decl)
|
145 | ) {
|
146 | if (value === 'start' || value === 'end') {
|
147 | result.warn(
|
148 | `${value} value has mixed support, consider using ` +
|
149 | `flex-${value} instead`,
|
150 | { node: decl }
|
151 | )
|
152 | }
|
153 | } else if (prop === 'text-decoration-skip' && value === 'ink') {
|
154 | result.warn(
|
155 | 'Replace text-decoration-skip: ink to ' +
|
156 | 'text-decoration-skip-ink: auto, because spec had been changed',
|
157 | { node: decl }
|
158 | )
|
159 | } else {
|
160 | if (gridPrefixes && this.gridStatus(decl, result)) {
|
161 | if (decl.value === 'subgrid') {
|
162 | result.warn('IE does not support subgrid', { node: decl })
|
163 | }
|
164 | if (/^(align|justify|place)-items$/.test(prop) && insideGrid(decl)) {
|
165 | let fixed = prop.replace('-items', '-self')
|
166 | result.warn(
|
167 | `IE does not support ${prop} on grid containers. ` +
|
168 | `Try using ${fixed} on child elements instead: ` +
|
169 | `${decl.parent.selector} > * { ${fixed}: ${decl.value} }`,
|
170 | { node: decl }
|
171 | )
|
172 | } else if (
|
173 | /^(align|justify|place)-content$/.test(prop) &&
|
174 | insideGrid(decl)
|
175 | ) {
|
176 | result.warn(`IE does not support ${decl.prop} on grid containers`, {
|
177 | node: decl
|
178 | })
|
179 | } else if (prop === 'display' && decl.value === 'contents') {
|
180 | result.warn(
|
181 | 'Please do not use display: contents; ' +
|
182 | 'if you have grid setting enabled',
|
183 | { node: decl }
|
184 | )
|
185 | return undefined
|
186 | } else if (decl.prop === 'grid-gap') {
|
187 | let status = this.gridStatus(decl, result)
|
188 | if (
|
189 | status === 'autoplace' &&
|
190 | !hasRowsAndColumns(decl) &&
|
191 | !hasGridTemplate(decl)
|
192 | ) {
|
193 | result.warn(
|
194 | 'grid-gap only works if grid-template(-areas) is being ' +
|
195 | 'used or both rows and columns have been declared ' +
|
196 | 'and cells have not been manually ' +
|
197 | 'placed inside the explicit grid',
|
198 | { node: decl }
|
199 | )
|
200 | } else if (
|
201 | (status === true || status === 'no-autoplace') &&
|
202 | !hasGridTemplate(decl)
|
203 | ) {
|
204 | result.warn(
|
205 | 'grid-gap only works if grid-template(-areas) is being used',
|
206 | { node: decl }
|
207 | )
|
208 | }
|
209 | } else if (prop === 'grid-auto-columns') {
|
210 | result.warn('grid-auto-columns is not supported by IE', {
|
211 | node: decl
|
212 | })
|
213 | return undefined
|
214 | } else if (prop === 'grid-auto-rows') {
|
215 | result.warn('grid-auto-rows is not supported by IE', { node: decl })
|
216 | return undefined
|
217 | } else if (prop === 'grid-auto-flow') {
|
218 | let hasRows = parent.some(i => i.prop === 'grid-template-rows')
|
219 | let hasCols = parent.some(i => i.prop === 'grid-template-columns')
|
220 |
|
221 | if (hasGridTemplate(decl)) {
|
222 | result.warn('grid-auto-flow is not supported by IE', {
|
223 | node: decl
|
224 | })
|
225 | } else if (value.includes('dense')) {
|
226 | result.warn('grid-auto-flow: dense is not supported by IE', {
|
227 | node: decl
|
228 | })
|
229 | } else if (!hasRows && !hasCols) {
|
230 | result.warn(
|
231 | 'grid-auto-flow works only if grid-template-rows and ' +
|
232 | 'grid-template-columns are present in the same rule',
|
233 | { node: decl }
|
234 | )
|
235 | }
|
236 | return undefined
|
237 | } else if (value.includes('auto-fit')) {
|
238 | result.warn('auto-fit value is not supported by IE', {
|
239 | node: decl,
|
240 | word: 'auto-fit'
|
241 | })
|
242 | return undefined
|
243 | } else if (value.includes('auto-fill')) {
|
244 | result.warn('auto-fill value is not supported by IE', {
|
245 | node: decl,
|
246 | word: 'auto-fill'
|
247 | })
|
248 | return undefined
|
249 | } else if (prop.startsWith('grid-template') && value.includes('[')) {
|
250 | result.warn(
|
251 | 'Autoprefixer currently does not support line names. ' +
|
252 | 'Try using grid-template-areas instead.',
|
253 | { node: decl, word: '[' }
|
254 | )
|
255 | }
|
256 | }
|
257 | if (value.includes('radial-gradient')) {
|
258 | if (OLD_RADIAL.test(decl.value)) {
|
259 | result.warn(
|
260 | 'Gradient has outdated direction syntax. ' +
|
261 | 'New syntax is like `closest-side at 0 0` ' +
|
262 | 'instead of `0 0, closest-side`.',
|
263 | { node: decl }
|
264 | )
|
265 | } else {
|
266 | let ast = parser(value)
|
267 |
|
268 | for (let i of ast.nodes) {
|
269 | if (i.type === 'function' && i.value === 'radial-gradient') {
|
270 | for (let word of i.nodes) {
|
271 | if (word.type === 'word') {
|
272 | if (word.value === 'cover') {
|
273 | result.warn(
|
274 | 'Gradient has outdated direction syntax. ' +
|
275 | 'Replace `cover` to `farthest-corner`.',
|
276 | { node: decl }
|
277 | )
|
278 | } else if (word.value === 'contain') {
|
279 | result.warn(
|
280 | 'Gradient has outdated direction syntax. ' +
|
281 | 'Replace `contain` to `closest-side`.',
|
282 | { node: decl }
|
283 | )
|
284 | }
|
285 | }
|
286 | }
|
287 | }
|
288 | }
|
289 | }
|
290 | }
|
291 | if (value.includes('linear-gradient')) {
|
292 | if (OLD_LINEAR.test(value)) {
|
293 | result.warn(
|
294 | 'Gradient has outdated direction syntax. ' +
|
295 | 'New syntax is like `to left` instead of `right`.',
|
296 | { node: decl }
|
297 | )
|
298 | }
|
299 | }
|
300 | }
|
301 |
|
302 | if (SIZES.includes(decl.prop)) {
|
303 | if (!decl.value.includes('-fill-available')) {
|
304 | if (decl.value.includes('fill-available')) {
|
305 | result.warn(
|
306 | 'Replace fill-available to stretch, ' +
|
307 | 'because spec had been changed',
|
308 | { node: decl }
|
309 | )
|
310 | } else if (decl.value.includes('fill')) {
|
311 | let ast = parser(value)
|
312 | if (ast.nodes.some(i => i.type === 'word' && i.value === 'fill')) {
|
313 | result.warn(
|
314 | 'Replace fill to stretch, because spec had been changed',
|
315 | { node: decl }
|
316 | )
|
317 | }
|
318 | }
|
319 | }
|
320 | }
|
321 |
|
322 | let prefixer
|
323 |
|
324 | if (decl.prop === 'transition' || decl.prop === 'transition-property') {
|
325 |
|
326 | return this.prefixes.transition.add(decl, result)
|
327 | } else if (decl.prop === 'align-self') {
|
328 |
|
329 | let display = this.displayType(decl)
|
330 | if (display !== 'grid' && this.prefixes.options.flexbox !== false) {
|
331 | prefixer = this.prefixes.add['align-self']
|
332 | if (prefixer && prefixer.prefixes) {
|
333 | prefixer.process(decl)
|
334 | }
|
335 | }
|
336 | if (this.gridStatus(decl, result) !== false) {
|
337 | prefixer = this.prefixes.add['grid-row-align']
|
338 | if (prefixer && prefixer.prefixes) {
|
339 | return prefixer.process(decl, result)
|
340 | }
|
341 | }
|
342 | } else if (decl.prop === 'justify-self') {
|
343 |
|
344 | if (this.gridStatus(decl, result) !== false) {
|
345 | prefixer = this.prefixes.add['grid-column-align']
|
346 | if (prefixer && prefixer.prefixes) {
|
347 | return prefixer.process(decl, result)
|
348 | }
|
349 | }
|
350 | } else if (decl.prop === 'place-self') {
|
351 | prefixer = this.prefixes.add['place-self']
|
352 | if (
|
353 | prefixer &&
|
354 | prefixer.prefixes &&
|
355 | this.gridStatus(decl, result) !== false
|
356 | ) {
|
357 | return prefixer.process(decl, result)
|
358 | }
|
359 | } else {
|
360 |
|
361 | prefixer = this.prefixes.add[decl.prop]
|
362 | if (prefixer && prefixer.prefixes) {
|
363 | return prefixer.process(decl, result)
|
364 | }
|
365 | }
|
366 |
|
367 | return undefined
|
368 | })
|
369 |
|
370 |
|
371 |
|
372 | if (this.gridStatus(css, result)) {
|
373 | insertAreas(css, this.disabled)
|
374 | }
|
375 |
|
376 |
|
377 | return css.walkDecls(decl => {
|
378 | if (this.disabledValue(decl, result)) return
|
379 |
|
380 | let unprefixed = this.prefixes.unprefixed(decl.prop)
|
381 | let list = this.prefixes.values('add', unprefixed)
|
382 | if (Array.isArray(list)) {
|
383 | for (let value of list) {
|
384 | if (value.process) value.process(decl, result)
|
385 | }
|
386 | }
|
387 | Value.save(this.prefixes, decl)
|
388 | })
|
389 | }
|
390 |
|
391 | |
392 |
|
393 |
|
394 | remove(css, result) {
|
395 |
|
396 | let resolution = this.prefixes.remove['@resolution']
|
397 |
|
398 | css.walkAtRules((rule, i) => {
|
399 | if (this.prefixes.remove[`@${rule.name}`]) {
|
400 | if (!this.disabled(rule, result)) {
|
401 | rule.parent.removeChild(i)
|
402 | }
|
403 | } else if (
|
404 | rule.name === 'media' &&
|
405 | rule.params.includes('-resolution') &&
|
406 | resolution
|
407 | ) {
|
408 | resolution.clean(rule)
|
409 | }
|
410 | })
|
411 |
|
412 |
|
413 | for (let checker of this.prefixes.remove.selectors) {
|
414 | css.walkRules((rule, i) => {
|
415 | if (checker.check(rule)) {
|
416 | if (!this.disabled(rule, result)) {
|
417 | rule.parent.removeChild(i)
|
418 | }
|
419 | }
|
420 | })
|
421 | }
|
422 |
|
423 | return css.walkDecls((decl, i) => {
|
424 | if (this.disabled(decl, result)) return
|
425 |
|
426 | let rule = decl.parent
|
427 | let unprefixed = this.prefixes.unprefixed(decl.prop)
|
428 |
|
429 |
|
430 | if (decl.prop === 'transition' || decl.prop === 'transition-property') {
|
431 | this.prefixes.transition.remove(decl)
|
432 | }
|
433 |
|
434 |
|
435 | if (
|
436 | this.prefixes.remove[decl.prop] &&
|
437 | this.prefixes.remove[decl.prop].remove
|
438 | ) {
|
439 | let notHack = this.prefixes.group(decl).down(other => {
|
440 | return this.prefixes.normalize(other.prop) === unprefixed
|
441 | })
|
442 |
|
443 | if (unprefixed === 'flex-flow') {
|
444 | notHack = true
|
445 | }
|
446 |
|
447 | if (decl.prop === '-webkit-box-orient') {
|
448 | let hacks = { 'flex-direction': true, 'flex-flow': true }
|
449 | if (!decl.parent.some(j => hacks[j.prop])) return
|
450 | }
|
451 |
|
452 | if (notHack && !this.withHackValue(decl)) {
|
453 | if (decl.raw('before').includes('\n')) {
|
454 | this.reduceSpaces(decl)
|
455 | }
|
456 | rule.removeChild(i)
|
457 | return
|
458 | }
|
459 | }
|
460 |
|
461 |
|
462 | for (let checker of this.prefixes.values('remove', unprefixed)) {
|
463 | if (!checker.check) continue
|
464 | if (!checker.check(decl.value)) continue
|
465 |
|
466 | unprefixed = checker.unprefixed
|
467 | let notHack = this.prefixes.group(decl).down(other => {
|
468 | return other.value.includes(unprefixed)
|
469 | })
|
470 |
|
471 | if (notHack) {
|
472 | rule.removeChild(i)
|
473 | return
|
474 | }
|
475 | }
|
476 | })
|
477 | }
|
478 |
|
479 | |
480 |
|
481 |
|
482 | withHackValue(decl) {
|
483 | return decl.prop === '-webkit-background-clip' && decl.value === 'text'
|
484 | }
|
485 |
|
486 | |
487 |
|
488 |
|
489 | disabledValue(node, result) {
|
490 | if (this.gridStatus(node, result) === false && node.type === 'decl') {
|
491 | if (node.prop === 'display' && node.value.includes('grid')) {
|
492 | return true
|
493 | }
|
494 | }
|
495 | if (this.prefixes.options.flexbox === false && node.type === 'decl') {
|
496 | if (node.prop === 'display' && node.value.includes('flex')) {
|
497 | return true
|
498 | }
|
499 | }
|
500 | if (node.type === 'decl' && node.prop === 'content') {
|
501 | return true
|
502 | }
|
503 |
|
504 | return this.disabled(node, result)
|
505 | }
|
506 |
|
507 | |
508 |
|
509 |
|
510 | disabledDecl(node, result) {
|
511 | if (this.gridStatus(node, result) === false && node.type === 'decl') {
|
512 | if (node.prop.includes('grid') || node.prop === 'justify-items') {
|
513 | return true
|
514 | }
|
515 | }
|
516 | if (this.prefixes.options.flexbox === false && node.type === 'decl') {
|
517 | let other = ['order', 'justify-content', 'align-items', 'align-content']
|
518 | if (node.prop.includes('flex') || other.includes(node.prop)) {
|
519 | return true
|
520 | }
|
521 | }
|
522 |
|
523 | return this.disabled(node, result)
|
524 | }
|
525 |
|
526 | |
527 |
|
528 |
|
529 | disabled(node, result) {
|
530 | if (!node) return false
|
531 |
|
532 | if (node._autoprefixerDisabled !== undefined) {
|
533 | return node._autoprefixerDisabled
|
534 | }
|
535 |
|
536 | if (node.parent) {
|
537 | let p = node.prev()
|
538 | if (p && p.type === 'comment' && IGNORE_NEXT.test(p.text)) {
|
539 | node._autoprefixerDisabled = true
|
540 | node._autoprefixerSelfDisabled = true
|
541 | return true
|
542 | }
|
543 | }
|
544 |
|
545 | let value = null
|
546 | if (node.nodes) {
|
547 | let status
|
548 | node.each(i => {
|
549 | if (i.type !== 'comment') return
|
550 | if (/(!\s*)?autoprefixer:\s*(off|on)/i.test(i.text)) {
|
551 | if (typeof status !== 'undefined') {
|
552 | result.warn(
|
553 | 'Second Autoprefixer control comment ' +
|
554 | 'was ignored. Autoprefixer applies control ' +
|
555 | 'comment to whole block, not to next rules.',
|
556 | { node: i }
|
557 | )
|
558 | } else {
|
559 | status = /on/i.test(i.text)
|
560 | }
|
561 | }
|
562 | })
|
563 |
|
564 | if (status !== undefined) {
|
565 | value = !status
|
566 | }
|
567 | }
|
568 | if (!node.nodes || value === null) {
|
569 | if (node.parent) {
|
570 | let isParentDisabled = this.disabled(node.parent, result)
|
571 | if (node.parent._autoprefixerSelfDisabled === true) {
|
572 | value = false
|
573 | } else {
|
574 | value = isParentDisabled
|
575 | }
|
576 | } else {
|
577 | value = false
|
578 | }
|
579 | }
|
580 | node._autoprefixerDisabled = value
|
581 | return value
|
582 | }
|
583 |
|
584 | |
585 |
|
586 |
|
587 | reduceSpaces(decl) {
|
588 | let stop = false
|
589 | this.prefixes.group(decl).up(() => {
|
590 | stop = true
|
591 | return true
|
592 | })
|
593 | if (stop) {
|
594 | return
|
595 | }
|
596 |
|
597 | let parts = decl.raw('before').split('\n')
|
598 | let prevMin = parts[parts.length - 1].length
|
599 | let diff = false
|
600 |
|
601 | this.prefixes.group(decl).down(other => {
|
602 | parts = other.raw('before').split('\n')
|
603 | let last = parts.length - 1
|
604 |
|
605 | if (parts[last].length > prevMin) {
|
606 | if (diff === false) {
|
607 | diff = parts[last].length - prevMin
|
608 | }
|
609 |
|
610 | parts[last] = parts[last].slice(0, -diff)
|
611 | other.raws.before = parts.join('\n')
|
612 | }
|
613 | })
|
614 | }
|
615 |
|
616 | |
617 |
|
618 |
|
619 | displayType(decl) {
|
620 | for (let i of decl.parent.nodes) {
|
621 | if (i.prop !== 'display') {
|
622 | continue
|
623 | }
|
624 |
|
625 | if (i.value.includes('flex')) {
|
626 | return 'flex'
|
627 | }
|
628 |
|
629 | if (i.value.includes('grid')) {
|
630 | return 'grid'
|
631 | }
|
632 | }
|
633 |
|
634 | return false
|
635 | }
|
636 |
|
637 | |
638 |
|
639 |
|
640 | gridStatus(node, result) {
|
641 | if (!node) return false
|
642 |
|
643 | if (node._autoprefixerGridStatus !== undefined) {
|
644 | return node._autoprefixerGridStatus
|
645 | }
|
646 |
|
647 | let value = null
|
648 | if (node.nodes) {
|
649 | let status
|
650 | node.each(i => {
|
651 | if (i.type !== 'comment') return
|
652 | if (GRID_REGEX.test(i.text)) {
|
653 | let hasAutoplace = /:\s*autoplace/i.test(i.text)
|
654 | let noAutoplace = /no-autoplace/i.test(i.text)
|
655 | if (typeof status !== 'undefined') {
|
656 | result.warn(
|
657 | 'Second Autoprefixer grid control comment was ' +
|
658 | 'ignored. Autoprefixer applies control comments to the whole ' +
|
659 | 'block, not to the next rules.',
|
660 | { node: i }
|
661 | )
|
662 | } else if (hasAutoplace) {
|
663 | status = 'autoplace'
|
664 | } else if (noAutoplace) {
|
665 | status = true
|
666 | } else {
|
667 | status = /on/i.test(i.text)
|
668 | }
|
669 | }
|
670 | })
|
671 |
|
672 | if (status !== undefined) {
|
673 | value = status
|
674 | }
|
675 | }
|
676 |
|
677 | if (node.type === 'atrule' && node.name === 'supports') {
|
678 | let params = node.params
|
679 | if (params.includes('grid') && params.includes('auto')) {
|
680 | value = false
|
681 | }
|
682 | }
|
683 |
|
684 | if (!node.nodes || value === null) {
|
685 | if (node.parent) {
|
686 | let isParentGrid = this.gridStatus(node.parent, result)
|
687 | if (node.parent._autoprefixerSelfDisabled === true) {
|
688 | value = false
|
689 | } else {
|
690 | value = isParentGrid
|
691 | }
|
692 | } else if (typeof this.prefixes.options.grid !== 'undefined') {
|
693 | value = this.prefixes.options.grid
|
694 | } else if (typeof process.env.AUTOPREFIXER_GRID !== 'undefined') {
|
695 | if (process.env.AUTOPREFIXER_GRID === 'autoplace') {
|
696 | value = 'autoplace'
|
697 | } else {
|
698 | value = true
|
699 | }
|
700 | } else {
|
701 | value = false
|
702 | }
|
703 | }
|
704 |
|
705 | node._autoprefixerGridStatus = value
|
706 | return value
|
707 | }
|
708 | }
|
709 |
|
710 | module.exports = Processor
|