Lint your JavaScript code inside ERB files (.js.erb).
A zero-dependency plugin for ESLint.
Also lints your HTML code in .html.erb if you want to.
Install the plugin alongside ESLint:
npm install --save-dev eslint eslint-plugin-erb
Starting of v9 ESLint provides a new flat config format (eslint.config.js). Also see the configuration migration guide. Use it as follows and it will automatically lint all your JavaScript code in .js.erb files:
// eslint.config.js import erb from "eslint-plugin-erb"; export default [ erb.configs.recommended, { linterOptions: { // The "unused disable directive" is set to "warn" by default. // For the ERB plugin to work correctly, you must disable // this directive to avoid issues described here // https://github.com/eslint/eslint/discussions/18114 // If you're using the CLI, you might also use the following flag: // --report-unused-disable-directives-severity=off reportUnusedDisableDirectives: "off", }, // your other configuration options } ];
See more complete example
// eslint.config.js import js from "@eslint/js"; import stylistic from "@stylistic/eslint-plugin"; import globals from "globals"; import erb from "eslint-plugin-erb"; const customizedStylistic = stylistic.configs.customize({ "indent": 2, "jsx": false, "quote-props": "always", "semi": "always", "brace-style": "1tbs", }); const customGlobals = { MyGlobalVariableOrFunctionOrClassOrWhatever: "readable", }; // [1] https://eslint.org/docs/latest/use/configure/configuration-files-new#globally-ignoring-files-with-ignores export default [ js.configs.recommended, erb.configs.recommended, // Globally ignoring the following files // "Note that only global ignores patterns can match directories. // 'ignores' patterns that are specific to a configuration will // only match file names." ~ see [1] { ignores: [ "node_modules/", "tests/fixtures/", "tmp/", ], }, { plugins: { "@stylistic": stylistic, }, rules: { ...customizedStylistic.rules, "no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], "@stylistic/quotes": ["error", "double", { avoidEscape: true }], }, languageOptions: { ecmaVersion: 2022, sourceType: "module", globals: { ...customGlobals, ...globals.browser, ...globals.node, }, }, linterOptions: { // The "unused disable directive" is set to "warn" by default. // For the ERB plugin to work correctly, you must disable // this directive to avoid issues described here // https://github.com/eslint/eslint/discussions/18114 // If you're using the CLI, you might also use the following flag: // --report-unused-disable-directives-severity=off reportUnusedDisableDirectives: "off", }, }, ];
Alternative way to configure the processor
With this variant you have a bit more control over what is going on, e.g. you could name your files .js.special-erb and still lint them (if they contain JS and ERB syntax).
// eslint.config.js import erb from "eslint-plugin-erb"; export default [ { files: ["**/*.js.erb"], processor: erb.processors.processorJs, }, { linterOptions: { // The "unused disable directive" is set to "warn" by default. // For the ERB plugin to work correctly, you must disable // this directive to avoid issues described here // https://github.com/eslint/eslint/discussions/18114 // If you're using the CLI, you might also use the following flag: // --report-unused-disable-directives-severity=off reportUnusedDisableDirectives: "off", }, // your other configuration options } ];
Legacy: you can still use the old `.eslintrc.js` format
You can extend the plugin:erb/recommended-legacy config that will enable the ERB processor on all .js.erb files.
// .eslintrc.js module.exports = { extends: "plugin:erb/recommended-legacy" };
Or you can configure the processor manually:
// .eslintrc.js module.exports = { plugins: ["erb"], overrides: [ { files: ["**/*.js.erb"], processor: "erb/processorJs" } ] };
If you also want to lint HTML code in .html.erb files, you can use our preprocessor in conjunction with the amazing html-eslint plugin. Install html-eslint, then add the following to your ESLint config file (flat config format):
// eslint.config.js import erb from "eslint-plugin-erb"; export default [ // your other configurations... { processor: erb.processors["processorHtml"], ...html.configs["flat/recommended"], files: ["**/*.html", "**/*.html.erb"], rules: { ...html.configs["flat/recommended"].rules, "@html-eslint/indent": ["error", 2], // other rules... }, } ];
Additionally, you might want to add the following option to the other objects ({}) in export default [] (at the same level like the files key above), since other rules might be incompatible with HTML files:
ignores: ["**/*.html**"],
The ESLint extension for VSCode has built-in support for the ERB processor once you've configured it in your .eslintrc.js file as shown above.
If you're using VSCode, you may find this settings.json options useful:
{
"editor.formatOnSave": false, // it still autosaves with the options below
//////////////////////////////////////
// JS (ESLint)
//////////////////////////////////////
// https://eslint.style/guide/faq#how-to-auto-format-on-save
// https://github.com/microsoft/vscode-eslint#settings-options
"eslint.format.enable": true,
"[javascript]": {
"editor.formatOnSave": false, // to avoid formatting twice (ESLint + VSCode)
"editor.defaultFormatter": "dbaeumer.vscode-eslint" // use ESLint plugin
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit" // Auto-fix ESLint errors on save
},
// this disables VSCode built-int formatter (instead we want to use ESLint)
"javascript.validate.enable": false,
//////////////////////////////////////
// Files
//////////////////////////////////////
"files.associations": {
"*.js.erb": "javascript"
},
}- Does not account for code indentation inside
if/elseERB statements, e.g. this snippet
<% if you_feel_lucky %> console.log("You are lucky π"); <% end %>
will be autofixed to
<% if you_feel_lucky %> console.log("You are lucky π"); <% end %>
- No support for ESLint suggestions (but full support for autofixes as shown in the GIF above)