Skip to content

Commit

Permalink
Add Strict locals missing linter (#175)
Browse files Browse the repository at this point in the history
And here I propose another linter that we would love to use in our
project. It checks for [Strict
locals](https://guides.rubyonrails.org/action_view_overview.html#strict-locals)
magic line and reports when the magic line is missing from the template.
Strict locals are encouraged by some in Rails partials as they allow to
define an explicit "API" for the templates showing clearly which
variables should be passed into the template when rendering it vs. which
ones are purely local for the template. They also allow to define
default values. I wrote a little
[post](https://dev.to/nejremeslnici/strict-locals-in-slim-haml-partials-in-rails-2f73)
about them recently. Thanks for your considering this!


![image](https://github.com/sds/slim-lint/assets/462701/c34333ec-4dbe-42f4-8e34-fabf879ecc69)


![image](https://github.com/sds/slim-lint/assets/462701/96c491ee-4ccd-44fe-8bcb-4227770af5c5)
  • Loading branch information
borama committed Apr 1, 2024
1 parent 77affdc commit d165c9b
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 0 deletions.
6 changes: 6 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ linters:
- Style/WhileUntilDo
- Style/WhileUntilModifier

StrictLocalsMissing:
enabled: false
include:
# Include only Rails partial templates by default
- app/views/**/_*.html.slim

Tab:
enabled: true

Expand Down
35 changes: 35 additions & 0 deletions lib/slim_lint/linter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Below is a list of linters supported by `slim-lint`, ordered alphabetically.
* [LineLength](#linelength)
* [RedundantDiv](#redundantdiv)
* [RuboCop](#rubocop)
* [StrictLocalsMissing](#strictlocalsmissing)
* [Tab](#tab)
* [TagCase](#tagcase)
* [TrailingBlankLines](#trailingblanklines)
Expand Down Expand Up @@ -281,6 +282,40 @@ AllCops:
DisplayCopNames: true
```

## StrictLocalsMissing

Reports on missing [strict locals magic comment](https://guides.rubyonrails.org/action_view_overview.html#strict-locals)
in Slim templates. Use the `include` configuration option to narrow down
the files to e.g. only partial view templates in Rails:

```yaml
linters:
StrictLocalsMissing:
enabled: true
include:
- app/views/**/_*.html.slim
```

**Bad for the above configuration**

In `app/views/somewhere/_partial.html.slim`:

```slim
= some_helper(foo, bar)
```
**Good for the above configuration**

In `app/views/somewhere/_partial.html.slim`:

```slim
/# locals: (foo:, bar: 'default')
= some_helper(foo, bar)
```

By default, Rails partial templates accept any local variables.
Strict locals, on the other hand, help define an explicit interface
for the template that shows which local variables it accepts.

## Tab

Reports detection of tabs used for indentation.
Expand Down
15 changes: 15 additions & 0 deletions lib/slim_lint/linter/strict_locals_missing.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module SlimLint
# Reports on missing strict locals magic line in Slim templates.
class Linter::StrictLocalsMissing < Linter
include LinterRegistry

on_start do |_sexp|
unless document.source =~ %r{/#\s+locals:\s+\(.*\)}
dummy_node = Struct.new(:line)
report_lint(dummy_node.new(1), 'Strict locals magic line is missing')
end
end
end
end
35 changes: 35 additions & 0 deletions spec/slim_lint/linter/strict_locals_missing_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

require 'spec_helper'

describe SlimLint::Linter::StrictLocalsMissing do
include_context 'linter'

context 'when magic line defines strict locals' do
let(:slim) { '/# locals: (foo:, bar:)' }

it { should_not report_lint }
end

context 'when magic line defines empty strict locals' do
let(:slim) { '/# locals: ()' }

it { should_not report_lint }
end

context 'when magic line is not at the top of the file' do
let(:slim) { <<-SLIM }
h1 Hello
= call(foo, bar)
/# locals: (foo:, bar:)
SLIM

it { should_not report_lint }
end

context 'when template has no strict locals definition' do
let(:slim) { 'h1 hello' }

it { should report_lint }
end
end

0 comments on commit d165c9b

Please sign in to comment.