# eslint-plugin-lodash-template

ESLint plugin for John Resig-style micro templating.

NPM license (opens new window) NPM version (opens new window) NPM downloads (opens new window)

It can be used in projects using Underscore.js (opens new window) and Lodash (opens new window)'s template.

This plugin supports code checking for templates like the examples below.

<div id="<%= id %>" class="<%= (i % 2 == 1 ? ' even': '') %>">
  <div class="grid_1 alpha right">
    <img class="righted" src="<%= profile_image_url %>"/>
  </div>
  <div class="grid_6 omega contents">
    <p><b><a href="/<%= from_user %>"><%= from_user %></a>:</b> <%= text %></p>
  </div>
</div>
<% for ( var i = 0; i < users.length; i++ ) { %>
  <li><a href="<%= users[i].url %>"><%= users[i].name %></a></li>
<% } %>

Playground on the Web

# Features

# Installation

npm install --save-dev eslint eslint-plugin-lodash-template

# Usage

Create .eslintrc.* file to configure rules. See also: http://eslint.org/docs/user-guide/configuring (opens new window).

Example .eslintrc.js:

module.exports = {
  extends: [
    // add more generic rulesets here, such as:
    // 'eslint:recommended',
    'plugin:lodash-template/recommended-with-html'
  ],
  rules: {
    // override/add rules settings here, such as:
    // 'lodash-template/no-warning-html-comments': 'error'
  }
}

# Attention

This plugin does special handling for the following rule warnings in the template.

Rule ID Process Description Another way this plugin supports
indent (opens new window) Disable warnings lodash-template/scriptlet-indent rule,
lodash-template/html-indent rule
strict (opens new window) Disable warnings --
no-empty (opens new window) Disable warnings --
max-statements-per-line (opens new window) Disable warnings --
padded-blocks (opens new window) Disable warnings --
no-implicit-globals (opens new window) Disable warnings --
no-multi-spaces (opens new window) Disable warnings lodash-template/no-multi-spaces-in-scriptlet rule,
lodash-template/no-multi-spaces-in-html-tag rule
no-unused-expressions (opens new window) Disable warnings within interpolate(<%=...%>) --
quotes (opens new window) Disable warnings if doublequote is set --
no-irregular-whitespace (opens new window) Disable warnings outside template tags lodash-template/no-irregular-whitespace rule

# Configs

This plugin provides 6 predefined configs:

  • plugin:lodash-template/base - Settings and rules to enable correct ESLint parsing
  • plugin:lodash-template/best-practices - Above, plus rules to improve dev experience
  • plugin:lodash-template/recommended - Above, plus rules to improve code readability
  • plugin:lodash-template/recommended-with-html - Above, plus rules to improve code readability with HTML template
  • plugin:lodash-template/recommended-with-script - plugin:lodash-template/recommended config, plus to enable ESLint parsing of JavaScript templates (This is an experimental feature)
  • plugin:lodash-template/all - All rules of this plugin are included

# All Rules

Please see All Rules

# Plugin Option

# Suppress no-undef warnings in the template tag

Please set the global variable used in all templates as follows.

.eslintrc.*:

  {
      "settings": {
+         "lodash-template/globals": ["variableName"]
      }
  }

Please write the global comment in the file as follows for the variable to be used with a specific template.

+ <% /* global users */ %>
  <% for ( var i = 0; i < users.length; i++ ) { %>
    <li><a href="<%= users[i].url %>"><%= users[i].name %></a></li>
  <% } %>

# Suppress reports for specific rules in template files

Please set as follows.

.eslintrc.*:

  {
      "settings": {
+         "lodash-template/ignoreRules": ["no-undef", "no-tabs"]
      }
  }

The ESLint standard suppression method can also be used by using template tag, as follows.

+ <% /* eslint no-ternary: 0 */ %>

# Customize parser

For example, if you set Lodash templateSettings (opens new window) as follows,

_.templateSettings = {
    evaluate:    /{{([\s\S]+?)}}/g,
    interpolate: /{{=([\s\S]+?)}}/g,
    escape:      /{{-([\s\S]+?)}}/g
};

please set parserOptions(ex. .eslintrc.*) as follows.

      parserOptions: {
+         templateSettings: {
+             evaluate:    ["{{", "}}"],
+             interpolate: ["{{=", "}}"],
+             escape:      ["{{-", "}}"],
+         },
      },

For example, to parse like EJS (opens new window), set as follows,

(If plugin:lodash-template/*** is set in extends, it is automatically applied to the extension .ejs.)

      parserOptions: {
+         templateSettings: {
+             evaluate:    [ ["<%", "<%_"], ["%>", "-%>", "_%>"] ],
+             interpolate: [  "<%-",        ["%>", "-%>", "_%>"] ],
+             escape:      [  "<%=",        ["%>", "-%>", "_%>"] ],
+             comment:     [  "<%#",        ["%>", "-%>", "_%>"] ],
+             literal:     [  "<%%" ],
+         },
      },

(This plugin do not provide complete support for EJS (opens new window). e.g. the include directive.)

# Customize target extensions

Please set .eslintrc.* as follows.

(For example, for EJS (opens new window).)

+    "overrides": [
+        {
+            "files": ["*.ejs"],
+            "processor": "lodash-template/html"
+        }
+    ]

# For JavaScript (TypeScript) Templates

(This is an experimental feature. Also check for known limitations.)

For example if you have a file like below.

/* eslint no-multi-spaces: error */
<% /* eslint lodash-template/no-multi-spaces-in-scriptlet: error */ %>

// if this plugin is not used, a parsing error will occur.
const obj    = <%= JSON.stringify(options     ) %>
//       ^^^^                            ^^^^^ 
//         |                              |
//         |          If you don't use `"plugin:lodash-template/recommended-with-script"`,
//         |          only the space after `options` is reported.
//         |
//         + When using `"plugin:lodash-template/recommended-with-script"`, the space after `obj` is also reported.

Playground on the Web (opens new window)

# Configuring

Please set .eslintrc.* as follows.

+    "overrides": [
+        {
+            "files": ["**/your/templates/*.js"],
+            "extends": ["plugin:lodash-template/recommended-with-script"]
+        }
+    ]

If you do not want to use the included rules, set the details as follows.

    "overrides": [
        {
            "files": ["**/your/templates/*.js"],
-            "extends": ["plugin:lodash-template/recommended-with-script"],
+            "extends": ["plugin:lodash-template/base"],
+            "processor": "lodash-template/script"
        }
    ]

If you want to use it with TypeScript, you need to configure parserOptions.

    "overrides": [
        {
-            "files": ["**/your/templates/*.js"],
+            "files": ["**/your/templates/*.ts"],
+            "parserOptions": {
+                 "parser": "@typescript-eslint/parser",
+                 "sourceType": "module"
+            },
            "extends": ["plugin:lodash-template/recommended-with-script"]
        }
    ]

# FAQ

# Known Limitations in Script Templates

Due to known limitations in script templates, you may need to rewrite some templates. Otherwise, you may not be able to use this plugin or some rules.

# Parsing Error

Interpolation in the script template will try to replace it with an identifier and parse it. If you generate a complex script in interpolation, you may get a parsing error.

👍 The following script can be parsed well.

let <%= idName %> = 42;
export { <%= idName %> };

👎 The following script cannot be parsed well.

<%= 'let ' + idName %> = 42;
export { <%= idName %> };

# False Positives in Some Rules

If you use branching in your template, the plugin will generate multiple script ASTs needed to cover all branches. (Then merge the results of validating these ASTs.)
This can confuse some rules and cause false positives.

However, this is necessary to avoid script parsing errors.

e.g.

Template:

const a = 'foo'
<% if (x) { %>
  const b = 1;
<% } else { %>
  const b = 2;
<% } %>

Generated Script 1:


const a = 'foo'

  const b = 1;



Generated Script 2:


const a = 'foo'



  const b = 2;

If we use the following script, it is a parsing error.


const a = 'foo'

  const b = 1;

  const b = 2; // <- Identifier 'b' has already been declared

The plugin also tries to generate scripts using branches that are as consistent as possible.

e.g.

Template:

<% if (x.foo) { %>
  const a = 'x.foo is true'
<% } %>
// ...
<% if (x.foo) { %>
  console.log(a)
<% } else { %>
  // process for x.foo is false
<% } %>

Generated Script 1:


  const a = 'x.foo is true'

// ...

  console.log(a)



Generated Script 2:




// ...



  // process for x.foo is false

However, branching conditions are compared using text, so even logically the same can be confusing.

e.g.

Template:

<% if (x['foo']) { %>
  const a = 'x.foo is true'
<% } %>
// ...
<% if (x.foo) { %>
  console.log(a)
<% } else { %>
  // process for x.foo is false
<% } %>

Generated Script 1:


  const a = 'x.foo is true'

// ...

  console.log(a)



Generated Script 2:


  const a = 'x.foo is true'

// ...



  // process for x.foo is false

This template gets an error 'a' is assigned a value but never used. from the no-unused-vars rule.

# Editor Settings

About how to mark warnings on editor.

  • VSCode (VS Code ESLint extension (opens new window))

    settings.json:

    {
        "eslint.validate": [ "javascript", "javascriptreact", { "language": "html", "autoFix": true } ]
    }
    
  • Sublime Text3 (SublimeLinter-eslint (opens new window))

    [Preference] > [Package Settings] > [SublimeLinter] > [Settings]

    // SublimeLinter Settings - User
    {
        "linters": {
            "eslint": {
                "selector": "text.html, source.js - meta.attribute-with-value"
            }
        }
    }
    

# Migrations

# Contributing

Welcome contributing!

Please use GitHub's Issues/PRs.

# parserServices

Information provided by parserServices on this plugin

# Development Tools

  • npm test runs tests and measures coverage.
  • npm run update runs in order to update readme and recommended configuration.

# License

See the LICENSE (opens new window) file for license rights and limitations (MIT).