summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/rules/template-curly-spacing.js
blob: 972e2daa28f0eceff5dec3e7272ba52860b0fa64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/**
 * @fileoverview Rule to enforce spacing around embedded expressions of template strings
 * @author Toru Nagashima
 * @copyright 2016 Toru Nagashima. All rights reserved.
 * See LICENSE file in root directory for full license.
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var astUtils = require("../ast-utils");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

var OPEN_PAREN = /\$\{$/;
var CLOSE_PAREN = /^\}/;

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function(context) {
    var sourceCode = context.getSourceCode();
    var always = context.options[0] === "always";
    var prefix = always ? "Expected" : "Unexpected";

    /**
     * Checks spacing before `}` of a given token.
     * @param {Token} token - A token to check. This is a Template token.
     * @returns {void}
     */
    function checkSpacingBefore(token) {
        var prevToken = sourceCode.getTokenBefore(token);
        if (prevToken &&
            CLOSE_PAREN.test(token.value) &&
            astUtils.isTokenOnSameLine(prevToken, token) &&
            sourceCode.isSpaceBetweenTokens(prevToken, token) !== always
        ) {
            context.report({
                loc: token.loc.start,
                message: prefix + " space(s) before '}'.",
                fix: function(fixer) {
                    if (always) {
                        return fixer.insertTextBefore(token, " ");
                    }
                    return fixer.removeRange([
                        prevToken.range[1],
                        token.range[0]
                    ]);
                }
            });
        }
    }

    /**
     * Checks spacing after `${` of a given token.
     * @param {Token} token - A token to check. This is a Template token.
     * @returns {void}
     */
    function checkSpacingAfter(token) {
        var nextToken = sourceCode.getTokenAfter(token);
        if (nextToken &&
            OPEN_PAREN.test(token.value) &&
            astUtils.isTokenOnSameLine(token, nextToken) &&
            sourceCode.isSpaceBetweenTokens(token, nextToken) !== always
        ) {
            context.report({
                loc: {
                    line: token.loc.end.line,
                    column: token.loc.end.column - 2
                },
                message: prefix + " space(s) after '${'.",
                fix: function(fixer) {
                    if (always) {
                        return fixer.insertTextAfter(token, " ");
                    }
                    return fixer.removeRange([
                        token.range[1],
                        nextToken.range[0]
                    ]);
                }
            });
        }
    }

    return {
        TemplateElement: function(node) {
            var token = sourceCode.getFirstToken(node);
            checkSpacingBefore(token);
            checkSpacingAfter(token);
        }
    };
};

module.exports.schema = [
    {enum: ["always", "never"]}
];