| "use strict"; |
| |
| const _ = require("lodash"); |
| const atRuleParamIndex = require("../../utils/atRuleParamIndex"); |
| const functionArgumentsSearch = require("../../utils/functionArgumentsSearch"); |
| const isStandardSyntaxUrl = require("../../utils/isStandardSyntaxUrl"); |
| const optionsMatches = require("../../utils/optionsMatches"); |
| const report = require("../../utils/report"); |
| const ruleMessages = require("../../utils/ruleMessages"); |
| const validateOptions = require("../../utils/validateOptions"); |
| |
| const ruleName = "function-url-quotes"; |
| |
| const messages = ruleMessages(ruleName, { |
| expected: () => "Expected quotes", |
| rejected: () => "Unexpected quotes" |
| }); |
| |
| const rule = function(expectation, options) { |
| return (root, result) => { |
| const validOptions = validateOptions( |
| result, |
| ruleName, |
| { |
| actual: expectation, |
| possible: ["always", "never"] |
| }, |
| { |
| actual: options, |
| possible: { |
| except: ["empty"] |
| }, |
| optional: true |
| } |
| ); |
| |
| if (!validOptions) { |
| return; |
| } |
| |
| root.walkAtRules(checkAtRuleParams); |
| root.walkDecls(checkDeclParams); |
| |
| function checkDeclParams(decl) { |
| functionArgumentsSearch( |
| decl.toString().toLowerCase(), |
| "url", |
| (args, index) => { |
| checkArgs(args, decl, index, "url"); |
| } |
| ); |
| } |
| |
| function checkAtRuleParams(atRule) { |
| const atRuleParamsLowerCase = atRule.params.toLowerCase(); |
| |
| functionArgumentsSearch(atRuleParamsLowerCase, "url", (args, index) => { |
| checkArgs(args, atRule, index + atRuleParamIndex(atRule), "url"); |
| }); |
| functionArgumentsSearch( |
| atRuleParamsLowerCase, |
| "url-prefix", |
| (args, index) => { |
| checkArgs( |
| args, |
| atRule, |
| index + atRuleParamIndex(atRule), |
| "url-prefix" |
| ); |
| } |
| ); |
| functionArgumentsSearch( |
| atRuleParamsLowerCase, |
| "domain", |
| (args, index) => { |
| checkArgs(args, atRule, index + atRuleParamIndex(atRule), "domain"); |
| } |
| ); |
| } |
| |
| function checkArgs(args, node, index, functionName) { |
| let shouldHasQuotes = expectation === "always"; |
| |
| const leftTrimmedArgs = args.trimLeft(); |
| |
| if (!isStandardSyntaxUrl(leftTrimmedArgs)) { |
| return; |
| } |
| |
| const complaintIndex = index + args.length - leftTrimmedArgs.length; |
| const hasQuotes = |
| leftTrimmedArgs[0] === "'" || leftTrimmedArgs[0] === '"'; |
| |
| const trimmedArg = args.trim(); |
| const isEmptyArgument = _.includes(["", "''", '""'], trimmedArg); |
| |
| if (optionsMatches(options, "except", "empty") && isEmptyArgument) { |
| shouldHasQuotes = !shouldHasQuotes; |
| } |
| |
| if (shouldHasQuotes) { |
| if (hasQuotes) { |
| return; |
| } |
| |
| complain(messages.expected(functionName), node, complaintIndex); |
| } else { |
| if (!hasQuotes) { |
| return; |
| } |
| |
| complain(messages.rejected(functionName), node, complaintIndex); |
| } |
| } |
| |
| function complain(message, node, index) { |
| report({ |
| message, |
| node, |
| index, |
| result, |
| ruleName |
| }); |
| } |
| }; |
| }; |
| |
| rule.ruleName = ruleName; |
| rule.messages = messages; |
| module.exports = rule; |