"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-space-inside"; const messages = ruleMessages(ruleName, { expectedOpening: 'Expected single space after "("', rejectedOpening: 'Unexpected whitespace after "("', expectedClosing: 'Expected single space before ")"', rejectedClosing: 'Unexpected whitespace before ")"', expectedOpeningSingleLine: 'Expected single space after "(" in a single-line function', rejectedOpeningSingleLine: 'Unexpected whitespace after "(" in a single-line function', expectedClosingSingleLine: 'Expected single space before ")" in a single-line function', rejectedClosingSingleLine: 'Unexpected whitespace before ")" in a single-line function' }); const rule = function(expectation, options, context) { return (root, result) => { const validOptions = validateOptions(result, ruleName, { actual: expectation, possible: ["always", "never", "always-single-line", "never-single-line"] }); if (!validOptions) { return; } root.walkDecls(decl => { if (decl.value.indexOf("(") === -1) { 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; } // Ignore function without parameters if (!valueNode.nodes.length) { return; } const functionString = valueParser.stringify(valueNode); const isSingleLine = isSingleLineString(functionString); // Check opening ... const openingIndex = valueNode.sourceIndex + valueNode.value.length + 1; if (expectation === "always" && valueNode.before !== " ") { if (context.fix) { hasFixed = true; valueNode.before = " "; } else { complain(messages.expectedOpening, openingIndex); } } if (expectation === "never" && valueNode.before !== "") { if (context.fix) { hasFixed = true; valueNode.before = ""; } else { complain(messages.rejectedOpening, openingIndex); } } if ( isSingleLine && expectation === "always-single-line" && valueNode.before !== " " ) { if (context.fix) { hasFixed = true; valueNode.before = " "; } else { complain(messages.expectedOpeningSingleLine, openingIndex); } } if ( isSingleLine && expectation === "never-single-line" && valueNode.before !== "" ) { if (context.fix) { hasFixed = true; valueNode.before = ""; } else { complain(messages.rejectedOpeningSingleLine, openingIndex); } } // Check closing ... const closingIndex = valueNode.sourceIndex + functionString.length - 2; if (expectation === "always" && valueNode.after !== " ") { if (context.fix) { hasFixed = true; valueNode.after = " "; } else { complain(messages.expectedClosing, closingIndex); } } if (expectation === "never" && valueNode.after !== "") { if (context.fix) { hasFixed = true; valueNode.after = ""; } else { complain(messages.rejectedClosing, closingIndex); } } if ( isSingleLine && expectation === "always-single-line" && valueNode.after !== " " ) { if (context.fix) { hasFixed = true; valueNode.after = " "; } else { complain(messages.expectedClosingSingleLine, closingIndex); } } if ( isSingleLine && expectation === "never-single-line" && valueNode.after !== "" ) { if (context.fix) { hasFixed = true; valueNode.after = ""; } else { complain(messages.rejectedClosingSingleLine, 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 }); } }); }; }; rule.ruleName = ruleName; rule.messages = messages; module.exports = rule;