Skip to content

Conversation

@cb341
Copy link

@cb341 cb341 commented Oct 18, 2025

Summary

Add a new linter rule html-turbo-permanent to validate correct usage of the data-turbo-permanent boolean attribute in HTML files.

Context

In HTML, boolean attributes are considered true when present, regardless of their assigned value.
The following examples are functionally identical:

<a data-turbo-permanent />
<a data-turbo-permanent="" />
<a data-turbo-permanent="true" />
<a data-turbo-permanent="false" />

This makes data-turbo-permanent="false" misleading since it behaves as if the attribute were true.
The new rule prevents such confusion by flagging data-turbo-permanent="false" as an error.

Rule Behavior

Allowed

<div data-turbo-permanent></div>
<div data-turbo-permanent=""></div>
<div data-turbo-permanent="true"></div>
<div data-turbo-permanent="foo"></div>

Disallowed

<div data-turbo-permanent="false"></div>

Rationale

data-turbo-permanent marks elements that persist across Turbo Drive navigations.
Explicitly setting the value to "false" does not disable this behavior and introduces ambiguity.
This rule enforces clear, unambiguous use of the attribute.

References

@cb341 cb341 changed the title Linter rule: html-turbo-permanent Linter: html-turbo-permanent Oct 18, 2025
@marcoroth
Copy link
Owner

marcoroth commented Oct 20, 2025

Hey @CuddlyBunion341, thanks for working this pull request!

While this is a great rule, I wonder if this should be reserved for a potential turbo-lint package, similar to how we put the Stimulus related rules in its own stimulus-lint package.

That said, we also have to think about how we deal with Rails and ActionView-specific rules, like #480.

So I wonder if it would make more sense if we have some kind of "built-in plugins" or "set of plugins", like stimulus/*, turbo/*, rails/*, actionview/* etc. which are disabled by default and that you can manually enable in the upcoming config file. Or that they get enabled when the Linter sees the presence of a dependency in the Gemfile or package.json.

@marcoroth marcoroth changed the title Linter: html-turbo-permanent Linter: Implement html-turbo-permanent linter rule Oct 20, 2025
@cb341
Copy link
Author

cb341 commented Oct 20, 2025

Hey @CuddlyBunion341, thanks for working this pull request!

While this is a great rule, I wonder if this should be reserved for a potential turbo-lint package, similar to how we put the Stimulus related rules in its own stimulus-lint package.

That said, we also have to think about how we deal with Rails and ActionView-specific rules, like #480.

So I wonder if it would make more sense if we have some kind of "built-in plugins" or "set of plugins", like stimulus/*, turbo/*, rails/*, actionview/* etc. which are disabled by default and that you can enable manually in the upcoming config file. Or that thy get enabled when the Linter sees the presence of a dependency in the Gemfile or package.json.

Thanks for the suggestion regarding the turbo-lint package.
I see how it can be valuable to group related packages. And allow herb to be used on non-rails projects.
Sounds like quite the task introducing a new package and rules for enabling rules. I very much support this idea.

I'd expect a PR that implements just the boilerplate of the turbo package, which I could merge my rules into.
The custom stimulus lint logo is awesome by the way.

@cb341
Copy link
Author

cb341 commented Oct 20, 2025

With the project specific rule activation I can see some problems.
Like for example determining project root or what Gemfile to use in case of nested ruby projects.

We would need to cover Gemfiles, Plugingemfiles, environments..
Also there could be multiple package.jsons.

I think for now the easiest approach would be to enable all plugins by default (providing the best experience for RoR) and enable users to deactivate certain plugins.

@github-actions github-actions bot added documentation Improvements or additions to documentation javascript vscode typescript labels Nov 5, 2025
@cb341 cb341 changed the title Linter: Implement html-turbo-permanent linter rule Linter: Implement html-turbo-permanent linter rule alongside turbo-lint package Nov 5, 2025
@cb341
Copy link
Author

cb341 commented Nov 5, 2025

@marcoroth

I have created a new package turbo-lint, inspired by the already existing stimulus-lint package.
Alongside a simple cli which allows you to process a singular file at the moment.

I'd love to hear your thoughts regarding the namespacing and the boilerplate.
I also took the liberty of restricting the rule to only allow data-turbo-permanent without a value.

@marcoroth
Copy link
Owner

Thanks for exploring this, @CuddlyBunion341. I checked, and sadly we cannot have the turbo-lint package name on NPM, as it's too close to turbolint.

But then I was wondering if we should even have its own package/linter CLI. I'm more and more leaning towards migrating stimulus-lint to a herb-linter-stimulus, herb-plugin-stimulus, @herb-tools/stimulus or @herb-tools/stimulus-plugin package, so that you can configure in the .herb.yml like:

linter:
  plugins:
    - herb-plugin-stimulus

And then just let it run as part of the regular herb-lint command. Similar to the rewriters config for the formatter (#759).

As there are quite a lot of moving pieces right now, I'd like to push this back a bit after Herb v0.8.0, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants