1 | 'use strict';
|
2 |
|
3 | const report = require('../../utils/report');
|
4 | const ruleMessages = require('../../utils/ruleMessages');
|
5 | const validateOptions = require('../../utils/validateOptions');
|
6 |
|
7 | const ruleName = 'no-irregular-whitespace';
|
8 |
|
9 | const messages = ruleMessages(ruleName, {
|
10 | unexpected: 'Unexpected irregular whitespace',
|
11 | });
|
12 |
|
13 | const meta = {
|
14 | url: 'https://stylelint.io/user-guide/rules/list/no-irregular-whitespace',
|
15 | };
|
16 |
|
17 | const IRREGULAR_WHITESPACES = [
|
18 | '\u000B',
|
19 | '\u000C',
|
20 | '\u00A0',
|
21 | '\u0085',
|
22 | '\u1680',
|
23 | '\u180E',
|
24 | '\uFEFF',
|
25 | '\u2000',
|
26 | '\u2001',
|
27 | '\u2002',
|
28 | '\u2003',
|
29 | '\u2004',
|
30 | '\u2005',
|
31 | '\u2006',
|
32 | '\u2007',
|
33 | '\u2008',
|
34 | '\u2009',
|
35 | '\u200A',
|
36 | '\u200B',
|
37 | '\u2028',
|
38 | '\u2029',
|
39 | '\u202F',
|
40 | '\u205F',
|
41 | '\u3000',
|
42 | ];
|
43 |
|
44 | const IRREGULAR_WHITESPACES_PATTERN = new RegExp(`([${IRREGULAR_WHITESPACES.join('')}])`);
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 | const findIrregularWhitespace = (str) => {
|
51 | const result = IRREGULAR_WHITESPACES_PATTERN.exec(str);
|
52 |
|
53 | return result ? result[1] : null;
|
54 | };
|
55 |
|
56 |
|
57 | const rule = (primary) => {
|
58 | return (root, result) => {
|
59 | const validOptions = validateOptions(result, ruleName, { actual: primary });
|
60 |
|
61 | if (!validOptions) {
|
62 | return;
|
63 | }
|
64 |
|
65 | |
66 |
|
67 |
|
68 |
|
69 | const validate = (node, value) => {
|
70 | const issue = value && findIrregularWhitespace(value);
|
71 |
|
72 | if (issue) {
|
73 | report({
|
74 | ruleName,
|
75 | result,
|
76 | message: messages.unexpected,
|
77 | node,
|
78 | word: issue,
|
79 | });
|
80 | }
|
81 | };
|
82 |
|
83 | root.walkAtRules((atRule) => {
|
84 | validate(atRule, atRule.name);
|
85 | validate(atRule, atRule.params);
|
86 | validate(atRule, atRule.raws.before);
|
87 | validate(atRule, atRule.raws.after);
|
88 | validate(atRule, atRule.raws.afterName);
|
89 | validate(atRule, atRule.raws.between);
|
90 | });
|
91 |
|
92 | root.walkRules((ruleNode) => {
|
93 | validate(ruleNode, ruleNode.selector);
|
94 | validate(ruleNode, ruleNode.raws.before);
|
95 | validate(ruleNode, ruleNode.raws.after);
|
96 | validate(ruleNode, ruleNode.raws.between);
|
97 | });
|
98 |
|
99 | root.walkDecls((decl) => {
|
100 | validate(decl, decl.prop);
|
101 | validate(decl, decl.value);
|
102 | validate(decl, decl.raws.before);
|
103 | validate(decl, decl.raws.between);
|
104 | });
|
105 | };
|
106 | };
|
107 |
|
108 | rule.ruleName = ruleName;
|
109 | rule.messages = messages;
|
110 | rule.meta = meta;
|
111 | module.exports = rule;
|