UNPKG

2.84 kBJavaScriptView Raw
1'use strict';
2
3const report = require('../../utils/report');
4const ruleMessages = require('../../utils/ruleMessages');
5const validateOptions = require('../../utils/validateOptions');
6
7const ruleName = 'no-irregular-whitespace';
8
9const messages = ruleMessages(ruleName, {
10 unexpected: 'Unexpected irregular whitespace',
11});
12
13const meta = {
14 url: 'https://stylelint.io/user-guide/rules/list/no-irregular-whitespace',
15};
16
17const IRREGULAR_WHITESPACES = [
18 '\u000B', // Line Tabulation (\v) - <VT>
19 '\u000C', // Form Feed (\f) - <FF>
20 '\u00A0', // No-Break Space - <NBSP>
21 '\u0085', // Next Line
22 '\u1680', // Ogham Space Mark
23 '\u180E', // Mongolian Vowel Separator - <MVS>
24 '\uFEFF', // Zero Width No-Break Space - <BOM>
25 '\u2000', // En Quad
26 '\u2001', // Em Quad
27 '\u2002', // En Space - <ENSP>
28 '\u2003', // Em Space - <EMSP>
29 '\u2004', // Tree-Per-Em
30 '\u2005', // Four-Per-Em
31 '\u2006', // Six-Per-Em
32 '\u2007', // Figure Space
33 '\u2008', // Punctuation Space - <PUNCSP>
34 '\u2009', // Thin Space
35 '\u200A', // Hair Space
36 '\u200B', // Zero Width Space - <ZWSP>
37 '\u2028', // Line Separator
38 '\u2029', // Paragraph Separator
39 '\u202F', // Narrow No-Break Space
40 '\u205F', // Medium Mathematical Space
41 '\u3000', // Ideographic Space
42];
43
44const IRREGULAR_WHITESPACES_PATTERN = new RegExp(`([${IRREGULAR_WHITESPACES.join('')}])`);
45
46/**
47 * @param {string} str
48 * @returns {string | null}
49 */
50const findIrregularWhitespace = (str) => {
51 const result = IRREGULAR_WHITESPACES_PATTERN.exec(str);
52
53 return result ? result[1] : null;
54};
55
56/** @type {import('stylelint').Rule} */
57const rule = (primary) => {
58 return (root, result) => {
59 const validOptions = validateOptions(result, ruleName, { actual: primary });
60
61 if (!validOptions) {
62 return;
63 }
64
65 /**
66 * @param {import('postcss').Node} node
67 * @param {string | undefined} value
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
108rule.ruleName = ruleName;
109rule.messages = messages;
110rule.meta = meta;
111module.exports = rule;