Skip to content

Commit

Permalink
Erb-scanner: Replaces better_html with regex
Browse files Browse the repository at this point in the history
- Simplify the ERB AST scanner by using the regex from erubi.
  • Loading branch information
davidwessman authored and glebm committed Jan 16, 2024
1 parent d2e38db commit d76961f
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 135 deletions.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Unreleased

* ErbAst-parser now only used for `*.html.erb`-files, not e.g. `*.js.erb`
* ERB AST-scanner now uses regex instead of better_html to allow
parsing files other than HTML.

## v1.0.13

Expand Down
1 change: 0 additions & 1 deletion i18n-tasks.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ Gem::Specification.new do |s|

s.add_dependency 'activesupport', '>= 4.0.2'
s.add_dependency 'ast', '>= 2.1.0'
s.add_dependency 'better_html', '>= 1.0', '< 3.0'
s.add_dependency 'erubi'
s.add_dependency 'highline', '>= 2.0.0'
s.add_dependency 'i18n'
Expand Down
74 changes: 0 additions & 74 deletions lib/i18n/tasks/scanners/erb_ast_processor.rb

This file was deleted.

80 changes: 55 additions & 25 deletions lib/i18n/tasks/scanners/erb_ast_scanner.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# frozen_string_literal: true

require 'i18n/tasks/scanners/ruby_ast_scanner'
require 'i18n/tasks/scanners/erb_ast_processor'
require 'better_html/errors'
require 'better_html/parser'
require 'i18n/tasks/scanners/local_ruby_parser'

module I18n::Tasks::Scanners
# Scan for I18n.translate calls in ERB-file better-html and ASTs
class ErbAstScanner < RubyAstScanner
DEFAULT_REGEXP = /<%(={1,2}|-|\#|%)?(.*?)([-=])?%>/m.freeze

def initialize(**args)
super(**args)
@erb_ast_processor = ErbAstProcessor.new
@ruby_parser = LocalRubyParser.new(ignore_blocks: true)
end

private
Expand All @@ -20,29 +20,59 @@ def initialize(**args)
# @param path Path to file to parse
# @return [{Parser::AST::Node}, [Parser::Source::Comment]]
def path_to_ast_and_comments(path)
parser = BetterHtml::Parser.new(make_buffer(path))
ast = convert_better_html(parser.ast)
@erb_ast_processor.process_and_extract_comments(ast)
comments = []
buffer = make_buffer(path)

children = []
buffer
.source
.scan(DEFAULT_REGEXP) do |indicator, code, tailch, _rspace|
match = Regexp.last_match
character = indicator ? indicator[0] : nil

start = match.begin(0) + 2 + (character&.size || 0)
stop = match.end(0) - 2 - (tailch&.size || 0)

case character
when '=', nil, '-'
parsed, parsed_comments = handle_code(buffer, code, start, stop)
comments.concat(parsed_comments)
children << parsed unless parsed.nil?
when '#', '#-'
comments << handle_comment(buffer, start, stop)
end
end

[root_node(children, buffer), comments]
end

# Convert BetterHtml nodes to Parser::AST::Node
#
# @param node BetterHtml::Parser::AST::Node
# @return Parser::AST::Node
def convert_better_html(node)
definition = Parser::Source::Map::Definition.new(
node.location.begin,
node.location.begin,
node.location.begin,
node.location.end
)
Parser::AST::Node.new(
node.type,
node.children.map { |child| child.is_a?(BetterHtml::AST::Node) ? convert_better_html(child) : child },
{
location: definition
}
)
def handle_code(buffer, code, start, stop)
range = ::Parser::Source::Range.new(buffer, start, stop)
location =
Parser::Source::Map::Definition.new(
range.begin,
range.begin,
range.begin,
range.end
)
@ruby_parser.parse(code, location: location)
end

def handle_comment(buffer, start, stop)
range = ::Parser::Source::Range.new(buffer, start, stop)
::Parser::Source::Comment.new(range)
end

def root_node(children, buffer)
range = ::Parser::Source::Range.new(buffer, 0, buffer.source.size)
location =
Parser::Source::Map::Definition.new(
range.begin,
range.begin,
range.begin,
range.end
)
::Parser::AST::Node.new(:erb, children, location: location)
end
end
end
68 changes: 34 additions & 34 deletions spec/used_keys_erb_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
[
{
path: 'app/views/application/show.html.erb',
pos: 17,
line_num: 1, line_pos: 17,
pos: 18,
line_num: 1, line_pos: 18,
line: "<div id=first><%= t('a') %></div>",
raw_key: 'a'
},
Expand All @@ -56,8 +56,8 @@
[
{
path: 'app/views/application/show.html.erb',
pos: 184,
line_num: 7, line_pos: 5,
pos: 185,
line_num: 7, line_pos: 6,
line: ' <%= MeetingNote.model_name.human(count: 1) %>',
raw_key: 'activerecord.models.meeting_note'
}
Expand All @@ -72,8 +72,8 @@
[
{
path: 'app/views/application/show.html.erb',
pos: 232,
line_num: 8, line_pos: 5,
pos: 233,
line_num: 8, line_pos: 6,
line: ' <%= AgendaItem.human_attribute_name(:title) %>',
raw_key: 'activerecord.attributes.agenda_item.title'
}
Expand All @@ -88,8 +88,8 @@
[
{
path: 'app/views/application/show.html.erb',
pos: 292,
line_num: 11, line_pos: 5,
pos: 293,
line_num: 11, line_pos: 6,
line: " <%= t('with_parameter', parameter: \"erb is the best\") %>",
raw_key: 'with_parameter'
}
Expand All @@ -104,8 +104,8 @@
[
{
path: 'app/views/application/show.html.erb',
pos: 351,
line_num: 12, line_pos: 5,
pos: 352,
line_num: 12, line_pos: 6,
line: " <%= t 'with_scope', scope: \"scope_a.scope_b\", default: t(\".nested_call\") %>",
raw_key: 'scope_a.scope_b.with_scope'
}
Expand Down Expand Up @@ -168,9 +168,9 @@
[
{
path: 'app/views/application/show.html.erb',
pos: 88,
line_num: 5, line_pos: 4,
line: " <% # i18n-tasks-use t('comment.absolute.attribute') %>",
pos: 147,
line_num: 6, line_pos: 6,
line: ' <%= Translate.absolute.attribute %>',
raw_key: 'comment.absolute.attribute'
}
]
Expand All @@ -196,9 +196,9 @@
[
{
path: 'app/views/application/comments.html.erb',
pos: 90,
line_num: 4, line_pos: 2,
line: "<% # i18n-tasks-use t('ruby.comment.works') %>",
pos: 139,
line_num: 5, line_pos: 4,
line: '<%= Translate.ruby_comment_works %>',
raw_key: 'ruby.comment.works'
}
]
Expand All @@ -212,9 +212,9 @@
[
{
path: 'app/views/application/comments.html.erb',
pos: 174,
line_num: 7, line_pos: 4,
line: "<%# i18n-tasks-use t('erb.comment.works') %>",
pos: 221,
line_num: 8, line_pos: 4,
line: '<%= Translate.erb_comment_works %>',
raw_key: 'erb.comment.works'
}
]
Expand All @@ -228,9 +228,9 @@
[
{
path: 'app/views/application/comments.html.erb',
pos: 255,
line_num: 10, line_pos: 2,
line: "<%# i18n-tasks-use t('erb_multi.comment.line1')",
pos: 352,
line_num: 12, line_pos: 4,
line: '<%= t("erb_multi.comment.#{type}") %>', # rubocop:disable Lint/InterpolationCheck
raw_key: 'erb_multi.comment.line1'
}
]
Expand All @@ -245,9 +245,9 @@
[
{
path: 'app/views/application/comments.html.erb',
pos: 255,
line_num: 10, line_pos: 2,
line: "<%# i18n-tasks-use t('erb_multi.comment.line1')",
pos: 352,
line_num: 12, line_pos: 4,
line: '<%= t("erb_multi.comment.#{type}") %>', # rubocop:disable Lint/InterpolationCheck
raw_key: 'erb_multi.comment.line2'
}
]
Expand All @@ -261,9 +261,9 @@
[
{
path: 'app/views/application/comments.html.erb',
pos: 389,
line_num: 14, line_pos: 2,
line: '<%#-',
pos: 498,
line_num: 17, line_pos: 4,
line: '<%= t("erb_multi_dash.comment.#{type}") %>', # rubocop:disable Lint/InterpolationCheck
raw_key: 'erb_multi_dash.comment.line1'
}
]
Expand All @@ -277,9 +277,9 @@
[
{
path: 'app/views/application/comments.html.erb',
pos: 389,
line_num: 14, line_pos: 2,
line: '<%#-',
pos: 498,
line_num: 17, line_pos: 4,
line: '<%= t("erb_multi_dash.comment.#{type}") %>', # rubocop:disable Lint/InterpolationCheck
raw_key: 'erb_multi_dash.comment.line2'
}
]
Expand All @@ -293,9 +293,9 @@
[
{
path: 'app/views/application/comments.html.erb',
pos: 540,
line_num: 19, line_pos: 2,
line: '<%',
pos: 642,
line_num: 22, line_pos: 4,
line: '<%= t("ruby_multi.comment.#{type}") %>', # rubocop:disable Lint/InterpolationCheck
raw_key: 'ruby_multi.comment.line1'
}
]
Expand Down

0 comments on commit d76961f

Please sign in to comment.