UNPKG

3.05 kBJavaScriptView Raw
1// @ts-nocheck
2
3'use strict';
4
5const valueParser = require('postcss-value-parser');
6
7const declarationValueIndex = require('../../utils/declarationValueIndex');
8const isStandardSyntaxDeclaration = require('../../utils/isStandardSyntaxDeclaration');
9const isStandardSyntaxValue = require('../../utils/isStandardSyntaxValue');
10const report = require('../../utils/report');
11const ruleMessages = require('../../utils/ruleMessages');
12const validateOptions = require('../../utils/validateOptions');
13
14const ruleName = 'hue-degree-notation';
15
16const messages = ruleMessages(ruleName, {
17 expected: (unfixed, fixed) => `Expected "${unfixed}" to be "${fixed}"`,
18});
19
20const HUE_FIRST_ARG_FUNCS = ['hsl', 'hsla', 'hwb'];
21const HUE_THIRD_ARG_FUNCS = ['lch'];
22const HUE_FUNCS = [...HUE_FIRST_ARG_FUNCS, ...HUE_THIRD_ARG_FUNCS];
23
24function rule(primary, secondary, context) {
25 return (root, result) => {
26 const validOptions = validateOptions(result, ruleName, {
27 actual: primary,
28 possible: ['angle', 'number'],
29 });
30
31 if (!validOptions) return;
32
33 root.walkDecls((decl) => {
34 if (!isStandardSyntaxDeclaration(decl)) return;
35
36 let needsFix = false;
37 const parsedValue = valueParser(getValue(decl));
38
39 parsedValue.walk((node) => {
40 if (node.type !== 'function') return;
41
42 if (!HUE_FUNCS.includes(node.value.toLowerCase())) return;
43
44 const hue = findHue(node);
45
46 if (!hue) return;
47
48 const { value } = hue;
49
50 if (!isStandardSyntaxValue(value)) return;
51
52 if (!isDegree(value) && !isNumber(value)) return;
53
54 if (primary === 'angle' && isDegree(value)) return;
55
56 if (primary === 'number' && isNumber(value)) return;
57
58 const fixed = primary === 'angle' ? asDegree(value) : asNumber(value);
59 const unfixed = value;
60
61 if (context.fix) {
62 hue.value = fixed;
63 needsFix = true;
64
65 return;
66 }
67
68 report({
69 message: messages.expected(unfixed, fixed),
70 node: decl,
71 index: declarationValueIndex(decl) + hue.sourceIndex,
72 result,
73 ruleName,
74 });
75 });
76
77 if (needsFix) {
78 setValue(decl, parsedValue.toString());
79 }
80 });
81 };
82}
83
84function asDegree(value) {
85 return `${value}deg`;
86}
87
88function asNumber(value) {
89 const { number } = valueParser.unit(value);
90
91 return number;
92}
93
94function findHue(node) {
95 const args = node.nodes.filter(({ type }) => type === 'word' || type === 'function');
96 const value = node.value.toLowerCase();
97
98 if (HUE_FIRST_ARG_FUNCS.includes(value)) {
99 return args[0];
100 }
101
102 if (HUE_THIRD_ARG_FUNCS.includes(value)) {
103 return args[2];
104 }
105
106 return false;
107}
108
109function isDegree(value) {
110 const { unit } = valueParser.unit(value);
111
112 return unit && unit.toLowerCase() === 'deg';
113}
114
115function isNumber(value) {
116 const { unit } = valueParser.unit(value);
117
118 return unit === '';
119}
120
121function getValue(decl) {
122 return decl.raws.value ? decl.raws.value.raw : decl.value;
123}
124
125function setValue(decl, value) {
126 if (decl.raws.value) decl.raws.value.raw = value;
127 else decl.value = value;
128
129 return decl;
130}
131
132rule.ruleName = ruleName;
133rule.messages = messages;
134module.exports = rule;