Skip to content

Add UseRenderModeInsteadOfPrimitives cop - #5

Merged
akabiru merged 1 commit into
mainfrom
feature/use-render-mode-instead-of-primitives
Jun 25, 2026
Merged

Add UseRenderModeInsteadOfPrimitives cop#5
akabiru merged 1 commit into
mainfrom
feature/use-render-mode-instead-of-primitives

Conversation

@akabiru

@akabiru akabiru commented May 27, 2026

Copy link
Copy Markdown
Member

https://community.openproject.org/wp/75389

What this cop does

Flags format_text(...) calls that pass the external-rendering primitive flags — static_html: true, plain_text: true, or only_path: false — instead of the canonical render_mode: API. Suggested fix: render_mode: :external_html / render_mode: :external_text, or format_mail_html / format_mail_text inside mailer templates.

Why now

format_text renders trusted Markdown for two distinct audiences: in-app HTML and external surfaces (mailer bodies, feeds). External surfaces need absolute URLs and a subset of macros pre-resolved to static HTML / plain text, because the recipient has no JavaScript runtime to hydrate the rest. Expressing that requirement as three loosely coupled toggles makes call sites easy to get partially right and silently wrong.

openproject#23337 introduced the render_mode: API and the mailer view helpers as the structural fix; this cop prevents regression.

Scope and behaviour

  • Fires on both .rb and .erb sources — OpenProject's .erb_lint.yml inherits .rubocop.yml, so mailer templates are covered automatically.
  • Honors render_mode: as an explicit escape hatch: if the call already passes render_mode:, the primitive flags are treated as an intentional override and no offense is raised.
  • v1 is flag-only. Autocorrect is deferred — static_html: true, only_path: false collapses to a single kwarg whose source range may not be contiguous.

Preview of offenses on opf/openproject dev

Smoke-test against a dev:

app/views/common/feed.atom.builder:72            format_text(item_event, :event_description, only_path: false)
app/views/journals/index.atom.builder:65         format_text(change, :notes, only_path: false)
app/views/user_mailer/message_posted.html.erb:35 format_text @message.content, object: @message, only_path: false
app/views/user_mailer/news_added.html.erb:33     format_text @news.description, only_path: false
app/views/user_mailer/news_comment_added.html.erb:34 format_text @comment.text, only_path: false

Flags `format_text` calls that pass the external-rendering primitive
flags (`static_html: true`, `plain_text: true`, `only_path: false`)
instead of the canonical `render_mode:` API or the mailer view helpers
`format_mail_html` / `format_mail_text`.

The primitive flags are a coupled set whose partial application
silently produced numeric work package IDs in watcher notifications
(openproject#74762). `render_mode:` documents the intent and bundles
the toggles into one canonical surface.

The cop fires on both `.rb` and `.erb` sources via OpenProject's
erb_lint Rubocop bridge. v1 is flag-only; autocorrect is a follow-up.

@oliverguenther oliverguenther left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks @akabiru 👏

@akabiru
akabiru merged commit 909da25 into main Jun 25, 2026
4 checks passed
@akabiru
akabiru deleted the feature/use-render-mode-instead-of-primitives branch June 25, 2026 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants