erb_lint Documentation

repository·main·Indexed 20 days ago

https://github.com/shopify/erb_lint

A linting tool for ERB and HTML files that ensures code quality through built-in linters—such as Rubocop and ErbSafety—and support for custom linter definitions. It features a configurable system via .erb_lint.yml, CLI execution, and capabilities for autocorrection and file globbing/exclusion patterns.

Tokens
8.1K
Snippets
31
Records
42
Agent score
73%

What's inside erb_lint

  1. Use the CommentSyntax linter

    main

    The CommentSyntax linter enforces correct ERB comment syntax. It flags Ruby-style comments (<% # comment %>) which are technically invalid in ERB and can cause parsing failures, recommending the ERB-specific syntax (<%# comment %>) instead. Multi-line comments using standard Ruby syntax inside ERB tags are acceptable.

    Bad ❌
    <% # This is a Ruby comment %>
    Good ✅
    <%# This is an ERB comment %>
    
    Good ✅
    <%
      # This is a multi-line ERB comment.
    %>
  2. Create custom linters

    main

    You can extend erb_lint by creating custom linters. These must be placed in the .erb_linters directory at the root of your repository.

    To implement a linter:

    1. Define a class inheriting from Linter within the ERBLint::Linters module.
    2. Include LinterRegistry.
    3. Define a ConfigSchema using LinterConfig to handle custom configuration.
    4. Implement the run(processed_source) method to detect offenses using add_offense.

    By default, custom linters are disabled. Enable them in .erb_lint.yml under the linters key.

    # .erb_linters/custom_linter.rb
    
    module ERBLint
      module Linters
        class CustomLinter < Linter
          include LinterRegistry
    
          class ConfigSchema < LinterConfig
            property :custom_message, accepts: String
          end
          self.config_schema = ConfigSchema
    
          def run(processed_source)
            unless processed_source.file_content.include?('this file is fine')
              add_offense(
                processed_source.to_source_range(0 ... processed_source.file_content.size),
                "This file isn't fine. #{@config.custom_message}"
              )
            end
          end
        end
      end
    end
  3. Use caching to speed up linting

    main

    Caching is opt-in. To enable it, use the --cache option followed by the directory to cache.

    • Enable cache: erb_lint --cache ./path/to/dir
    • Custom cache directory: Use the --cache-dir option to specify a location other than the default .erb_lint_cache.
    • Clear cache: Use the --clear-cache option to delete the existing cache directory.

    Cached results store CachedOffense attributes necessary to restore results without re-running the full linting process. The cache automatically prunes outdated files during execution.

    # Enable caching for the app directory
    erb_lint --cache ./app
    
    # Clear the cache
    erb_lint --clear-cache
  4. Enable and test custom linters

    main

    After creating a custom linter, enable it in your .erb_lint.yml file. You can then test it using the CLI with the --enable-linters flag and --lint-all to ensure it is running correctly.

    # .erb_lint.yml
    ---
    linters:
      CustomLinter:
        enabled: true
        custom_message: We suggest you change this file.
    bundle exec erb_lint --enable-linters custom_linter --lint-all
  5. Disable a rule at the offense level

    main

    You can suppress specific linting errors on a per-line basis by adding a disable comment to the offending line in your .erb file.

    Format: <%# erb_lint:disable RuleName %>

    Options:

    • To report errors when a disable comment is present but does nothing, enable the NoUnusedDisable rule.
    • To ignore all inline disable comments and report all offenses regardless, use the --disable-inline-configs CLI option.
    <hr /> <%# erb_lint:disable SelfClosingTag %>
  6. Install ERB Lint

    main

    You can install erb_lint as a standalone gem or as a dependency in your application's Gemfile.

    Requirements:

    • Ruby 2.3.0 or higher (required for safe navigation operator &. and tilde-heredoc <<~ syntax).
    gem install erb_lint

    Or in your Gemfile

    gem 'erb_lint', require: false
  7. Manage global exclusions in ERB Lint

    main

    You can define a global list of files or patterns to exclude from linting by using the exclude key in your configuration. This list is automatically merged into the configuration of every individual linter, ensuring that excluded files are ignored across the entire suite.

    Example configuration structure:

    exclude:
      - "spec/**/*"
      - "vendor/**/*"
  8. Configure global and linter-local exclusions

    main

    You can define exclusion patterns at two levels:

    1. Global: Applies to all linters.
    2. Linter-local: Applies only to a specific linter defined under the linters key.
    ---
    exclude:
      - '**/global-lib/**/*'
    linters:
      ErbSafety:
        exclude:
          - '**/local-lib/**/*'
  9. Configure ERB Lint with .erb_lint.yml

    main

    Create a .erb_lint.yml file in your project root to customize linter behavior. While not mandatory (the tool works with defaults), a configuration file allows you to enable/disable linters and pass specific configurations to them.

    Note: If you reference external configuration files (like .better-html.yml or .rubocop.yml), those files must exist, otherwise the tool will error.

    ---
    EnableDefaultLinters: true
    linters:
      ErbSafety:
        enabled: true
        better_html_config: .better-html.yml
      Rubocop:
        enabled: true
        rubocop_config:
          inherit_from:
            - .rubocop.yml
  10. Configure the SelfClosingTag linter

    main

    Enforces self-closing tag styles for void elements (e.g., area, br, img, input, link, etc.).

    Options:

    • enforced_style:
      • always (XHTML style): Requires <img />.
      • never (HTML5 style): Requires <img>.
      • Defaults to never.
    ---
    linters:
      SelfClosingTag:
        enabled: true
        enforced_style: 'always'
  11. Configure the SpaceAroundErbTag linter

    main

    Enforces a single space after <% and before %>. It ignores tags where the <% is followed by a newline or the %> is preceded by a newline.

    ---
    linters:
      SpaceAroundErbTag:
        enabled: true
  12. Configure the AllowedScriptType linter

    main

    Prevents <script> tags from using type attributes that are not in an allowed whitelist. This helps prevent XSS vulnerabilities and typos.

    Options:

    • allowed_types: An array of allowed types. Defaults to ["text/javascript"].
    • allow_blank: If false, <script> tags without a type attribute will be auto-corrected to <script type="text/javascript">. Defaults to true.
    • disallow_inline_scripts: If true, prevents inline <script> tags anywhere in ERB templates. Defaults to false.
    ---
    linters:
      AllowedScriptType:
        enabled: true
        allowed_types:
          - 'application/json'
          - 'text/javascript'
          - 'text/html'
        allow_blank: false
        disallow_inline_scripts: false