Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 1 | // @ts-nocheck |
| 2 | |
| 3 | 'use strict'; |
| 4 | |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 5 | const declarationValueIndex = require('../utils/declarationValueIndex'); |
Tim van der Lippe | 0a9b84d | 2021-03-24 11:53:15 +0000 | [diff] [blame^] | 6 | const getDeclarationValue = require('../utils/getDeclarationValue'); |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 7 | const isStandardSyntaxFunction = require('../utils/isStandardSyntaxFunction'); |
| 8 | const report = require('../utils/report'); |
Tim van der Lippe | 0a9b84d | 2021-03-24 11:53:15 +0000 | [diff] [blame^] | 9 | const setDeclarationValue = require('../utils/setDeclarationValue'); |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 10 | const valueParser = require('postcss-value-parser'); |
| 11 | |
| 12 | module.exports = function (opts) { |
| 13 | opts.root.walkDecls((decl) => { |
Tim van der Lippe | 0a9b84d | 2021-03-24 11:53:15 +0000 | [diff] [blame^] | 14 | const declValue = getDeclarationValue(decl); |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 15 | |
| 16 | let hasFixed; |
| 17 | const parsedValue = valueParser(declValue); |
| 18 | |
| 19 | parsedValue.walk((valueNode) => { |
| 20 | if (valueNode.type !== 'function') { |
| 21 | return; |
| 22 | } |
| 23 | |
| 24 | if (!isStandardSyntaxFunction(valueNode)) { |
| 25 | return; |
| 26 | } |
| 27 | |
| 28 | // Ignore `url()` arguments, which may contain data URIs or other funky stuff |
| 29 | if (valueNode.value.toLowerCase() === 'url') { |
| 30 | return; |
| 31 | } |
| 32 | |
| 33 | const argumentStrings = valueNode.nodes.map((node) => valueParser.stringify(node)); |
| 34 | |
| 35 | const functionArguments = (() => { |
| 36 | // Remove function name and parens |
| 37 | let result = valueNode.before + argumentStrings.join('') + valueNode.after; |
| 38 | |
| 39 | // 1. Remove comments including preceding whitespace (when only succeeded by whitespace) |
| 40 | // 2. Remove all other comments, but leave adjacent whitespace intact |
| 41 | result = result.replace(/( *\/(\*.*\*\/(?!\S)|\/.*)|(\/(\*.*\*\/|\/.*)))/, ''); |
| 42 | |
| 43 | return result; |
| 44 | })(); |
| 45 | |
| 46 | /** |
| 47 | * Gets the index of the comma for checking. |
| 48 | * @param {Node} commaNode The comma node |
| 49 | * @param {number} nodeIndex The index of the comma node |
| 50 | * @returns {number} The index of the comma for checking |
| 51 | */ |
| 52 | function getCommaCheckIndex(commaNode, nodeIndex) { |
| 53 | let commaBefore = |
| 54 | valueNode.before + argumentStrings.slice(0, nodeIndex).join('') + commaNode.before; |
| 55 | |
| 56 | // 1. Remove comments including preceding whitespace (when only succeeded by whitespace) |
| 57 | // 2. Remove all other comments, but leave adjacent whitespace intact |
| 58 | commaBefore = commaBefore.replace(/( *\/(\*.*\*\/(?!\S)|\/.*)|(\/(\*.*\*\/|\/.*)))/, ''); |
| 59 | |
| 60 | return commaBefore.length; |
| 61 | } |
| 62 | |
| 63 | const commaDataList = []; |
| 64 | |
| 65 | valueNode.nodes.forEach((node, nodeIndex) => { |
| 66 | if (node.type !== 'div' || node.value !== ',') { |
| 67 | return; |
| 68 | } |
| 69 | |
| 70 | const checkIndex = getCommaCheckIndex(node, nodeIndex); |
| 71 | |
| 72 | commaDataList.push({ |
| 73 | commaNode: node, |
| 74 | checkIndex, |
| 75 | nodeIndex, |
| 76 | }); |
| 77 | }); |
| 78 | |
| 79 | for (const { commaNode, checkIndex, nodeIndex } of commaDataList) { |
| 80 | opts.locationChecker({ |
| 81 | source: functionArguments, |
| 82 | index: checkIndex, |
| 83 | err: (message) => { |
| 84 | const index = |
| 85 | declarationValueIndex(decl) + commaNode.sourceIndex + commaNode.before.length; |
| 86 | |
| 87 | if (opts.fix && opts.fix(commaNode, nodeIndex, valueNode.nodes)) { |
| 88 | hasFixed = true; |
| 89 | |
| 90 | return; |
| 91 | } |
| 92 | |
| 93 | report({ |
| 94 | index, |
| 95 | message, |
| 96 | node: decl, |
| 97 | result: opts.result, |
| 98 | ruleName: opts.checkedRuleName, |
| 99 | }); |
| 100 | }, |
| 101 | }); |
| 102 | } |
| 103 | }); |
| 104 | |
| 105 | if (hasFixed) { |
Tim van der Lippe | 0a9b84d | 2021-03-24 11:53:15 +0000 | [diff] [blame^] | 106 | setDeclarationValue(decl, parsedValue.toString()); |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 107 | } |
| 108 | }); |
| 109 | }; |