ruby-lsp icon indicating copy to clipboard operation
ruby-lsp copied to clipboard

Add support for providing features on ERB files

Open vinistock opened this issue 2 years ago • 7 comments

I think there's a path to add support for ERB without a ton of effort. We can try to require erb from the main bundle and provide features only if it is a dependency.

Basically, we can use the ERB gem to parse the .erb file and extract the Ruby code. Then we parse the Ruby code with Prism and provide features for it.

require "erb"
erb = "<% x = 32 %><p><%= x %></p>"
ruby_code = ERB.new(erb).src # => "#coding:UTF-8\n_erbout = +'';  x = 32 ; _erbout.<< \"<p>\".freeze; _erbout.<<(( x ).to_s); _erbout.<< \"</p>\".freeze; _erbout"

Prism.parse(ruby_code) # => AST

In terms of the codebase, I think the best way forward would be turning creating an abstract parent class Document and turning our existing document class into RubyDocument. Then we can create an ErbDocument class to handle the specific details of ERB.

Notes

Diagnostics, formatting and on type formatting need to happen differently on ERB files. For example, if some is using [].each do %> and breaks the line, we need to insert <% end %> and not just end. Similarly, we can see if erb lint is available to provide diagnostics and potentially format the code too.

It might be worth separating these requests into RubyFormatting and ErbFormatting.

vinistock avatar Oct 02 '23 17:10 vinistock

You may need a custom Engine to parse the ERB supported by Rails properly: https://github.com/Shopify/spoom/blob/at-deadcode/lib/spoom/deadcode/erb.rb#L8.

The complexity is correctly mapping lines and columns to the original ERB source.

Morriar avatar Oct 03 '23 13:10 Morriar

Thanks for pointing that out. I suppose if Rails is available in the Gemfile, we'll probably be able to require their own custom engine and use it.

vinistock avatar Oct 03 '23 13:10 vinistock

Attempt at erasing the HTML

# typed: strict
# frozen_string_literal: true

require "prism"
require "strscan"

original = File.read("index.html.erb")
scanner = StringScanner.new(original)
output = +""

until scanner.eos?
  non_ruby_code = scanner.scan_until(/<%(-|=)?/)
  break unless non_ruby_code

  output << non_ruby_code.gsub(/[^\n]/, " ")

  ruby_code = scanner.scan_until(/(-)?%>/)
  break unless ruby_code

  output << ruby_code[...-2]
  output << "  "
end

puts output

p Prism.parse(output)

vinistock avatar Nov 13 '23 22:11 vinistock

+1 for ERB support

ERB support is really important for Rails projects

collimarco avatar Nov 19 '23 20:11 collimarco

We can use VS Code's embedded language features to forward HTML operations to the built-in language server and get features: https://code.visualstudio.com/api/language-extensions/embedded-languages.

vinistock avatar Jan 16 '24 13:01 vinistock

This issue is being marked as stale because there was no activity in the last 2 months

github-actions[bot] avatar Apr 29 '24 12:04 github-actions[bot]

:up: anti-stale bump

We can use VS Code's embedded language features to forward HTML operations […]

Remember that ERB isn’t only about Rails and HTML. ERB can generate CSS, JS, RBS, C, Ruby, even Python, you name it.

ParadoxV5 avatar May 19 '24 22:05 ParadoxV5

Initial support for ERB has been shipped in #2235, so I'm closing this issue in favour of more specific ones if we need them.

vinistock avatar Jul 12 '24 21:07 vinistock