9eb6d86077da36baa6bea5ac8369901021cda8b6
[dotfiles/.git] / template-tag-spacing.js
1 /**
2  * @fileoverview Rule to check spacing between template tags and their literals
3  * @author Jonathan Wilsson
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Rule Definition
10 //------------------------------------------------------------------------------
11
12 module.exports = {
13     meta: {
14         type: "layout",
15
16         docs: {
17             description: "require or disallow spacing between template tags and their literals",
18             category: "Stylistic Issues",
19             recommended: false,
20             url: "https://eslint.org/docs/rules/template-tag-spacing"
21         },
22
23         fixable: "whitespace",
24
25         schema: [
26             { enum: ["always", "never"] }
27         ],
28         messages: {
29             unexpected: "Unexpected space between template tag and template literal.",
30             missing: "Missing space between template tag and template literal."
31         }
32     },
33
34     create(context) {
35         const never = context.options[0] !== "always";
36         const sourceCode = context.getSourceCode();
37
38         /**
39          * Check if a space is present between a template tag and its literal
40          * @param {ASTNode} node node to evaluate
41          * @returns {void}
42          * @private
43          */
44         function checkSpacing(node) {
45             const tagToken = sourceCode.getTokenBefore(node.quasi);
46             const literalToken = sourceCode.getFirstToken(node.quasi);
47             const hasWhitespace = sourceCode.isSpaceBetweenTokens(tagToken, literalToken);
48
49             if (never && hasWhitespace) {
50                 context.report({
51                     node,
52                     loc: tagToken.loc.start,
53                     messageId: "unexpected",
54                     fix(fixer) {
55                         const comments = sourceCode.getCommentsBefore(node.quasi);
56
57                         // Don't fix anything if there's a single line comment after the template tag
58                         if (comments.some(comment => comment.type === "Line")) {
59                             return null;
60                         }
61
62                         return fixer.replaceTextRange(
63                             [tagToken.range[1], literalToken.range[0]],
64                             comments.reduce((text, comment) => text + sourceCode.getText(comment), "")
65                         );
66                     }
67                 });
68             } else if (!never && !hasWhitespace) {
69                 context.report({
70                     node,
71                     loc: tagToken.loc.start,
72                     messageId: "missing",
73                     fix(fixer) {
74                         return fixer.insertTextAfter(tagToken, " ");
75                     }
76                 });
77             }
78         }
79
80         return {
81             TaggedTemplateExpression: checkSpacing
82         };
83     }
84 };