Skip to content

Indent ERB views with htmlbeautifier when saving - #5

Merged
aesmail merged 1 commit into
masterfrom
erb-format-on-save
Sep 29, 2026
Merged

aesmail merged 1 commit into
masterfrom
erb-format-on-save

Conversation

@aesmail

@aesmail aesmail commented Sep 29, 2026

Copy link
Copy Markdown

Summary

  • Format ERB on Save (new, callback.document.will-save, scope text.html.erb) indents HTML views with htmlbeautifier.
    • It only runs on .html.erb files, including variants such as .html+phone.erb. Mailer text views and other ERB files are left alone.
    • It uses the document's tab settings (--tab-stops N or --tab) and passes --keep-blank-lines 1, because htmlbeautifier removes every blank line by default. It also passes --stop-on-errors: a view with a closing tag that has no opening tag is saved unchanged, with a tool tip saying where.
    • It runs htmlbeautifier with Bundler when the bundle has it, otherwise as installed for the project's Ruby, through mise. If it isn't installed for that Ruby (a mise shim for another Ruby doesn't count), the view is saved unchanged, without a message.
    • TM_ERB_FORMAT_ON_SAVE = false turns it off. TM_HTMLBEAUTIFIER and TM_HTMLBEAUTIFIER_OPTIONS set the command and add options.
  • Formatted text is applied in place. It goes through mate --lsp workspace/applyEdit (built with osascript), so TextMate replaces only the lines that change. With Pair lines that differ only in white space when applying edits textmate#13, the caret and bookmarks also stay on re-indented lines. Untitled documents, or a TextMate that can't apply the edit, get the whole document replaced as before (exit 202). Format Document's RuboCop CLI fallback now works the same way.
  • Refactor: Support/lib/rubocop.sh becomes format.sh. ruby_gem_executable GEM … runs RuboCop and htmlbeautifier the same way (TM_«GEM», Bundler, mise) and returns 127 when the tool isn't installed. The temporary folder is shared.
  • Tests:
    • They now run commands as script files, as TextMate does.
    • CI moves to macOS, for bash 3.2 and osascript.
    • The README has an ERB section.

Test plan

  • ruby Support/test/test_format.rb: 18 runs, 0 failures, 0 skips. New tests cover:
    • edits applied by TextMate, and replacing the whole document when it can't;
    • options and tab settings;
    • only HTML views being indented;
    • turned off, and no changes;
    • htmlbeautifier not installed, both without mise and with mise for a Ruby that lacks it;
    • the bundle's htmlbeautifier;
    • the invalid-nesting tool tip.
  • End to end, with my no-UI harness (real TextMate client, real htmlbeautifier 1.4.3 under Ruby 3.4.8): a view was indented on save, three blank lines were collapsed to one, and the file on disk was untouched until saving. With Added test methods of Ruby 1.9 (pass, flunk and skip). textmate/ruby.tmbundle#13, all four bookmarks stayed on their lines. No temporary files were left behind.
  • RuboCop through ruby-lsp still formats in place, with bookmarks kept.

🤖 Generated with Claude Code

Format ERB on Save indents HTML views (.html.erb) with htmlbeautifier, with
the document's tab settings, keeping one blank line between blocks, unless
TM_ERB_FORMAT_ON_SAVE is false. htmlbeautifier runs with Bundler when the
bundle has it, or as installed for the project's Ruby; without it, views
are saved as they are. Views with invalid nesting are left, with a tool tip.

Formatted text is applied through TextMate (mate --lsp workspace/applyEdit),
which replaces only the lines that change, so the caret and bookmarks stay;
Format Document's RuboCop fallback does the same now, rather than replacing
the document.

Support/lib/rubocop.sh is now format.sh, and runs gems with
ruby_gem_executable, which tells when one is not installed for the Ruby of
the project. The tests run the commands as script files, as TextMate does,
on macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aesmail
aesmail merged commit 4098773 into master Sep 29, 2026
1 check passed
@aesmail
aesmail deleted the erb-format-on-save branch September 29, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant