UNPKG

2.9 kBJavaScriptView Raw
1'use strict';
2
3const _ = require('lodash');
4const declarationValueIndex = require('../../utils/declarationValueIndex');
5const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction');
6const keywordSets = require('../../reference/keywordSets');
7const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp');
8const report = require('../../utils/report');
9const ruleMessages = require('../../utils/ruleMessages');
10const validateOptions = require('../../utils/validateOptions');
11const valueParser = require('postcss-value-parser');
12
13const ruleName = 'function-name-case';
14
15const messages = ruleMessages(ruleName, {
16 expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`,
17});
18
19const mapLowercaseFunctionNamesToCamelCase = new Map();
20
21keywordSets.camelCaseFunctionNames.forEach((func) => {
22 mapLowercaseFunctionNamesToCamelCase.set(func.toLowerCase(), func);
23});
24
25function rule(expectation, options, context) {
26 return (root, result) => {
27 const validOptions = validateOptions(
28 result,
29 ruleName,
30 {
31 actual: expectation,
32 possible: ['lower', 'upper'],
33 },
34 {
35 actual: options,
36 possible: {
37 ignoreFunctions: [_.isString, _.isRegExp],
38 },
39 optional: true,
40 },
41 );
42
43 if (!validOptions) {
44 return;
45 }
46
47 root.walkDecls((decl) => {
48 let needFix = false;
49 const parsed = valueParser(decl.raws.value ? decl.raws.value.raw : decl.value);
50
51 parsed.walk((node) => {
52 if (node.type !== 'function' || !isStandardSyntaxFunction(node)) {
53 return;
54 }
55
56 const functionName = node.value;
57 const functionNameLowerCase = functionName.toLowerCase();
58
59 const ignoreFunctions = (options && options.ignoreFunctions) || [];
60
61 if (ignoreFunctions.length > 0 && matchesStringOrRegExp(functionName, ignoreFunctions)) {
62 return;
63 }
64
65 let expectedFunctionName = null;
66
67 if (
68 expectation === 'lower' &&
69 mapLowercaseFunctionNamesToCamelCase.has(functionNameLowerCase)
70 ) {
71 expectedFunctionName = mapLowercaseFunctionNamesToCamelCase.get(functionNameLowerCase);
72 } else if (expectation === 'lower') {
73 expectedFunctionName = functionNameLowerCase;
74 } else {
75 expectedFunctionName = functionName.toUpperCase();
76 }
77
78 if (functionName === expectedFunctionName) {
79 return;
80 }
81
82 if (context.fix) {
83 needFix = true;
84 node.value = expectedFunctionName;
85
86 return;
87 }
88
89 report({
90 message: messages.expected(functionName, expectedFunctionName),
91 node: decl,
92 index: declarationValueIndex(decl) + node.sourceIndex,
93 result,
94 ruleName,
95 });
96 });
97
98 if (context.fix && needFix) {
99 const statement = parsed.toString();
100
101 if (decl.raws.value) {
102 decl.raws.value.raw = statement;
103 } else {
104 decl.value = statement;
105 }
106 }
107 });
108 };
109}
110
111rule.ruleName = ruleName;
112rule.messages = messages;
113module.exports = rule;