UNPKG

1.82 kBJavaScriptView Raw
1'use strict';
2
3const hasBlock = require('../../utils/hasBlock');
4const report = require('../../utils/report');
5const ruleMessages = require('../../utils/ruleMessages');
6const validateOptions = require('../../utils/validateOptions');
7
8const ruleName = 'declaration-block-trailing-semicolon';
9
10const messages = ruleMessages(ruleName, {
11 expected: 'Expected a trailing semicolon',
12 rejected: 'Unexpected trailing semicolon',
13});
14
15function rule(expectation, _, context) {
16 return (root, result) => {
17 const validOptions = validateOptions(result, ruleName, {
18 actual: expectation,
19 possible: ['always', 'never'],
20 });
21
22 if (!validOptions) {
23 return;
24 }
25
26 root.walkAtRules((atRule) => {
27 if (atRule.parent === root) {
28 return;
29 }
30
31 if (atRule !== atRule.parent.last) {
32 return;
33 }
34
35 if (hasBlock(atRule)) {
36 return;
37 }
38
39 checkLastNode(atRule);
40 });
41
42 root.walkDecls((decl) => {
43 if (decl !== decl.parent.last) {
44 return;
45 }
46
47 checkLastNode(decl);
48 });
49
50 function checkLastNode(node) {
51 let message;
52
53 if (expectation === 'always') {
54 if (node.parent.raws.semicolon) {
55 return;
56 }
57
58 // auto-fix
59 if (context.fix) {
60 node.parent.raws.semicolon = true;
61
62 if (node.type === 'atrule') {
63 node.raws.between = '';
64 node.parent.raws.after = ' ';
65 }
66
67 return;
68 }
69
70 message = messages.expected;
71 } else if (expectation === 'never') {
72 if (!node.parent.raws.semicolon) {
73 return;
74 }
75
76 // auto-fix
77 if (context.fix) {
78 node.parent.raws.semicolon = false;
79
80 return;
81 }
82
83 message = messages.rejected;
84 }
85
86 report({
87 message,
88 node,
89 index: node.toString().trim().length - 1,
90 result,
91 ruleName,
92 });
93 }
94 };
95}
96
97rule.ruleName = ruleName;
98rule.messages = messages;
99module.exports = rule;