diff options
Diffstat (limited to 'assets/node_modules/stylelint/lib/rules/function-parentheses-newline-inside/index.js')
-rw-r--r-- | assets/node_modules/stylelint/lib/rules/function-parentheses-newline-inside/index.js | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/assets/node_modules/stylelint/lib/rules/function-parentheses-newline-inside/index.js b/assets/node_modules/stylelint/lib/rules/function-parentheses-newline-inside/index.js new file mode 100644 index 0000000..1619e3d --- /dev/null +++ b/assets/node_modules/stylelint/lib/rules/function-parentheses-newline-inside/index.js @@ -0,0 +1,248 @@ +'use strict'; + +const _ = require('lodash'); +const declarationValueIndex = require('../../utils/declarationValueIndex'); +const isSingleLineString = require('../../utils/isSingleLineString'); +const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); +const valueParser = require('postcss-value-parser'); + +const ruleName = 'function-parentheses-newline-inside'; + +const messages = ruleMessages(ruleName, { + expectedOpening: 'Expected newline after "("', + expectedClosing: 'Expected newline before ")"', + expectedOpeningMultiLine: 'Expected newline after "(" in a multi-line function', + rejectedOpeningMultiLine: 'Unexpected whitespace after "(" in a multi-line function', + expectedClosingMultiLine: 'Expected newline before ")" in a multi-line function', + rejectedClosingMultiLine: 'Unexpected whitespace before ")" in a multi-line function', +}); + +function rule(expectation, options, context) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: expectation, + possible: ['always', 'always-multi-line', 'never-multi-line'], + }); + + if (!validOptions) { + return; + } + + root.walkDecls((decl) => { + if (!decl.value.includes('(')) { + return; + } + + let hasFixed = false; + const declValue = _.get(decl, 'raws.value.raw', decl.value); + const parsedValue = valueParser(declValue); + + parsedValue.walk((valueNode) => { + if (valueNode.type !== 'function') { + return; + } + + if (!isStandardSyntaxFunction(valueNode)) { + return; + } + + const functionString = valueParser.stringify(valueNode); + const isMultiLine = !isSingleLineString(functionString); + + function containsNewline(str) { + return str.includes('\n'); + } + + // Check opening ... + + const openingIndex = valueNode.sourceIndex + valueNode.value.length + 1; + const checkBefore = getCheckBefore(valueNode); + + if (expectation === 'always' && !containsNewline(checkBefore)) { + if (context.fix) { + hasFixed = true; + fixBeforeForAlways(valueNode, context.newline); + } else { + complain(messages.expectedOpening, openingIndex); + } + } + + if (isMultiLine && expectation === 'always-multi-line' && !containsNewline(checkBefore)) { + if (context.fix) { + hasFixed = true; + fixBeforeForAlways(valueNode, context.newline); + } else { + complain(messages.expectedOpeningMultiLine, openingIndex); + } + } + + if (isMultiLine && expectation === 'never-multi-line' && checkBefore !== '') { + if (context.fix) { + hasFixed = true; + fixBeforeForNever(valueNode); + } else { + complain(messages.rejectedOpeningMultiLine, openingIndex); + } + } + + // Check closing ... + + const closingIndex = valueNode.sourceIndex + functionString.length - 2; + const checkAfter = getCheckAfter(valueNode); + + if (expectation === 'always' && !containsNewline(checkAfter)) { + if (context.fix) { + hasFixed = true; + fixAfterForAlways(valueNode, context.newline); + } else { + complain(messages.expectedClosing, closingIndex); + } + } + + if (isMultiLine && expectation === 'always-multi-line' && !containsNewline(checkAfter)) { + if (context.fix) { + hasFixed = true; + fixAfterForAlways(valueNode, context.newline); + } else { + complain(messages.expectedClosingMultiLine, closingIndex); + } + } + + if (isMultiLine && expectation === 'never-multi-line' && checkAfter !== '') { + if (context.fix) { + hasFixed = true; + fixAfterForNever(valueNode); + } else { + complain(messages.rejectedClosingMultiLine, closingIndex); + } + } + }); + + if (hasFixed) { + if (!decl.raws.value) { + decl.value = parsedValue.toString(); + } else { + decl.raws.value.raw = parsedValue.toString(); + } + } + + function complain(message, offset) { + report({ + ruleName, + result, + message, + node: decl, + index: declarationValueIndex(decl) + offset, + }); + } + }); + }; +} + +function getCheckBefore(valueNode) { + let before = valueNode.before; + + for (const node of valueNode.nodes) { + if (node.type === 'comment') { + continue; + } + + if (node.type === 'space') { + before += node.value; + continue; + } + + break; + } + + return before; +} + +function getCheckAfter(valueNode) { + let after = ''; + + for (const node of valueNode.nodes.slice().reverse()) { + if (node.type === 'comment') { + continue; + } + + if (node.type === 'space') { + after = node.value + after; + continue; + } + + break; + } + + after += valueNode.after; + + return after; +} + +function fixBeforeForAlways(valueNode, newline) { + let target; + + for (const node of valueNode.nodes) { + if (node.type === 'comment') { + continue; + } + + if (node.type === 'space') { + target = node; + continue; + } + + break; + } + + if (target) { + target.value = newline + target.value; + } else { + valueNode.before = newline + valueNode.before; + } +} + +function fixBeforeForNever(valueNode) { + valueNode.before = ''; + + for (const node of valueNode.nodes) { + if (node.type === 'comment') { + continue; + } + + if (node.type === 'space') { + node.value = ''; + continue; + } + + break; + } +} + +function fixAfterForAlways(valueNode, newline) { + valueNode.after = newline + valueNode.after; +} + +function fixAfterForNever(valueNode) { + valueNode.after = ''; + + for (const node of valueNode.nodes.slice().reverse()) { + if (node.type === 'comment') { + continue; + } + + if (node.type === 'space') { + node.value = ''; + continue; + } + + break; + } +} + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; |