]> git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/template-curly-spacing.js
5133a54539cb32e5dded906757d5c3565a328d99
[pve-eslint.git] / eslint / lib / rules / template-curly-spacing.js
1 /**
2 * @fileoverview Rule to enforce spacing around embedded expressions of template strings
3 * @author Toru Nagashima
4 */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Rule Definition
16 //------------------------------------------------------------------------------
17
18 module.exports = {
19 meta: {
20 type: "layout",
21
22 docs: {
23 description: "require or disallow spacing around embedded expressions of template strings",
24 recommended: false,
25 url: "https://eslint.org/docs/rules/template-curly-spacing"
26 },
27
28 fixable: "whitespace",
29
30 schema: [
31 { enum: ["always", "never"] }
32 ],
33 messages: {
34 expectedBefore: "Expected space(s) before '}'.",
35 expectedAfter: "Expected space(s) after '${'.",
36 unexpectedBefore: "Unexpected space(s) before '}'.",
37 unexpectedAfter: "Unexpected space(s) after '${'."
38 }
39 },
40
41 create(context) {
42 const sourceCode = context.getSourceCode();
43 const always = context.options[0] === "always";
44
45 /**
46 * Checks spacing before `}` of a given token.
47 * @param {Token} token A token to check. This is a Template token.
48 * @returns {void}
49 */
50 function checkSpacingBefore(token) {
51 if (!token.value.startsWith("}")) {
52 return; // starts with a backtick, this is the first template element in the template literal
53 }
54
55 const prevToken = sourceCode.getTokenBefore(token, { includeComments: true }),
56 hasSpace = sourceCode.isSpaceBetween(prevToken, token);
57
58 if (!astUtils.isTokenOnSameLine(prevToken, token)) {
59 return;
60 }
61
62 if (always && !hasSpace) {
63 context.report({
64 loc: {
65 start: token.loc.start,
66 end: {
67 line: token.loc.start.line,
68 column: token.loc.start.column + 1
69 }
70 },
71 messageId: "expectedBefore",
72 fix: fixer => fixer.insertTextBefore(token, " ")
73 });
74 }
75
76 if (!always && hasSpace) {
77 context.report({
78 loc: {
79 start: prevToken.loc.end,
80 end: token.loc.start
81 },
82 messageId: "unexpectedBefore",
83 fix: fixer => fixer.removeRange([prevToken.range[1], token.range[0]])
84 });
85 }
86 }
87
88 /**
89 * Checks spacing after `${` of a given token.
90 * @param {Token} token A token to check. This is a Template token.
91 * @returns {void}
92 */
93 function checkSpacingAfter(token) {
94 if (!token.value.endsWith("${")) {
95 return; // ends with a backtick, this is the last template element in the template literal
96 }
97
98 const nextToken = sourceCode.getTokenAfter(token, { includeComments: true }),
99 hasSpace = sourceCode.isSpaceBetween(token, nextToken);
100
101 if (!astUtils.isTokenOnSameLine(token, nextToken)) {
102 return;
103 }
104
105 if (always && !hasSpace) {
106 context.report({
107 loc: {
108 start: {
109 line: token.loc.end.line,
110 column: token.loc.end.column - 2
111 },
112 end: token.loc.end
113 },
114 messageId: "expectedAfter",
115 fix: fixer => fixer.insertTextAfter(token, " ")
116 });
117 }
118
119 if (!always && hasSpace) {
120 context.report({
121 loc: {
122 start: token.loc.end,
123 end: nextToken.loc.start
124 },
125 messageId: "unexpectedAfter",
126 fix: fixer => fixer.removeRange([token.range[1], nextToken.range[0]])
127 });
128 }
129 }
130
131 return {
132 TemplateElement(node) {
133 const token = sourceCode.getFirstToken(node);
134
135 checkSpacingBefore(token);
136 checkSpacingAfter(token);
137 }
138 };
139 }
140 };