.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / color-hex-length / index.js
1 "use strict";
2
3 const blurFunctionArguments = require("../../utils/blurFunctionArguments");
4 const report = require("../../utils/report");
5 const ruleMessages = require("../../utils/ruleMessages");
6 const styleSearch = require("style-search");
7 const validateOptions = require("../../utils/validateOptions");
8
9 const ruleName = "color-hex-length";
10
11 const messages = ruleMessages(ruleName, {
12   expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`
13 });
14
15 const rule = function(expectation, _, context) {
16   return (root, result) => {
17     const validOptions = validateOptions(result, ruleName, {
18       actual: expectation,
19       possible: ["short", "long"]
20     });
21     if (!validOptions) {
22       return;
23     }
24
25     root.walkDecls(decl => {
26       const declString = blurFunctionArguments(decl.toString(), "url");
27       const fixPositions = [];
28
29       styleSearch({ source: declString, target: "#" }, match => {
30         const hexMatch = /^#[0-9A-Za-z]+/.exec(
31           declString.substr(match.startIndex)
32         );
33         if (!hexMatch) {
34           return;
35         }
36
37         const hexValue = hexMatch[0];
38
39         if (
40           expectation === "long" &&
41           hexValue.length !== 4 &&
42           hexValue.length !== 5
43         ) {
44           return;
45         }
46
47         if (
48           expectation === "short" &&
49           (hexValue.length < 6 || !canShrink(hexValue))
50         ) {
51           return;
52         }
53
54         const variant = expectation === "long" ? longer : shorter;
55         const expectedHex = variant(hexValue);
56
57         if (context.fix) {
58           fixPositions.unshift({
59             expectedHex,
60             currentHex: hexValue,
61             startIndex: match.startIndex
62           });
63
64           return;
65         }
66
67         report({
68           message: messages.expected(hexValue, expectedHex),
69           node: decl,
70           index: match.startIndex,
71           result,
72           ruleName
73         });
74       });
75
76       if (fixPositions.length) {
77         const declProp = decl.prop;
78         const declBetween = decl.raws.between;
79
80         fixPositions.forEach(function(fixPosition) {
81           // 1 — it's a # length
82           decl.value = replaceHex(
83             decl.value,
84             fixPosition.currentHex,
85             fixPosition.expectedHex,
86             fixPosition.startIndex - declProp.length - declBetween.length - 1
87           );
88         });
89       }
90     });
91   };
92 };
93
94 function canShrink(hex) {
95   hex = hex.toLowerCase();
96
97   return (
98     hex[1] === hex[2] &&
99     hex[3] === hex[4] &&
100     hex[5] === hex[6] &&
101     (hex.length === 7 || (hex.length === 9 && hex[7] === hex[8]))
102   );
103 }
104
105 function shorter(hex) {
106   let hexVariant = "#";
107   for (let i = 1; i < hex.length; i = i + 2) {
108     hexVariant += hex[i];
109   }
110   return hexVariant;
111 }
112
113 function longer(hex) {
114   let hexVariant = "#";
115   for (let i = 1; i < hex.length; i++) {
116     hexVariant += hex[i] + hex[i];
117   }
118   return hexVariant;
119 }
120
121 function replaceHex(input, searchString, replaceString, startIndex) {
122   const offset = startIndex + 1;
123   const stringStart = input.slice(0, offset);
124   const stringEnd = input.slice(offset + searchString.length);
125
126   return stringStart + replaceString + stringEnd;
127 }
128
129 rule.ruleName = ruleName;
130 rule.messages = messages;
131 module.exports = rule;