UNPKG

2.91 kBJavaScriptView Raw
1'use strict';
2
3const _ = require('lodash');
4const atRuleParamIndex = require('../../utils/atRuleParamIndex');
5const functionArgumentsSearch = require('../../utils/functionArgumentsSearch');
6const isStandardSyntaxUrl = require('../../utils/isStandardSyntaxUrl');
7const optionsMatches = require('../../utils/optionsMatches');
8const report = require('../../utils/report');
9const ruleMessages = require('../../utils/ruleMessages');
10const validateOptions = require('../../utils/validateOptions');
11
12const ruleName = 'function-url-quotes';
13
14const messages = ruleMessages(ruleName, {
15 expected: () => 'Expected quotes',
16 rejected: () => 'Unexpected quotes',
17});
18
19const rule = function(expectation, options) {
20 return (root, result) => {
21 const validOptions = validateOptions(
22 result,
23 ruleName,
24 {
25 actual: expectation,
26 possible: ['always', 'never'],
27 },
28 {
29 actual: options,
30 possible: {
31 except: ['empty'],
32 },
33 optional: true,
34 },
35 );
36
37 if (!validOptions) {
38 return;
39 }
40
41 root.walkAtRules(checkAtRuleParams);
42 root.walkDecls(checkDeclParams);
43
44 function checkDeclParams(decl) {
45 functionArgumentsSearch(decl.toString().toLowerCase(), 'url', (args, index) => {
46 checkArgs(args, decl, index, 'url');
47 });
48 }
49
50 function checkAtRuleParams(atRule) {
51 const atRuleParamsLowerCase = atRule.params.toLowerCase();
52
53 functionArgumentsSearch(atRuleParamsLowerCase, 'url', (args, index) => {
54 checkArgs(args, atRule, index + atRuleParamIndex(atRule), 'url');
55 });
56 functionArgumentsSearch(atRuleParamsLowerCase, 'url-prefix', (args, index) => {
57 checkArgs(args, atRule, index + atRuleParamIndex(atRule), 'url-prefix');
58 });
59 functionArgumentsSearch(atRuleParamsLowerCase, 'domain', (args, index) => {
60 checkArgs(args, atRule, index + atRuleParamIndex(atRule), 'domain');
61 });
62 }
63
64 function checkArgs(args, node, index, functionName) {
65 let shouldHasQuotes = expectation === 'always';
66
67 const leftTrimmedArgs = args.trimLeft();
68
69 if (!isStandardSyntaxUrl(leftTrimmedArgs)) {
70 return;
71 }
72
73 const complaintIndex = index + args.length - leftTrimmedArgs.length;
74 const hasQuotes = leftTrimmedArgs[0] === "'" || leftTrimmedArgs[0] === '"';
75
76 const trimmedArg = args.trim();
77 const isEmptyArgument = _.includes(['', "''", '""'], trimmedArg);
78
79 if (optionsMatches(options, 'except', 'empty') && isEmptyArgument) {
80 shouldHasQuotes = !shouldHasQuotes;
81 }
82
83 if (shouldHasQuotes) {
84 if (hasQuotes) {
85 return;
86 }
87
88 complain(messages.expected(functionName), node, complaintIndex);
89 } else {
90 if (!hasQuotes) {
91 return;
92 }
93
94 complain(messages.rejected(functionName), node, complaintIndex);
95 }
96 }
97
98 function complain(message, node, index) {
99 report({
100 message,
101 node,
102 index,
103 result,
104 ruleName,
105 });
106 }
107 };
108};
109
110rule.ruleName = ruleName;
111rule.messages = messages;
112module.exports = rule;