i18n-tasks 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 053f1f934ed84abbf4f86a11762c37c78cc286f8f809d3c8c5ca2918af57cb2a
4
- data.tar.gz: 0f70179fa394de1faafc750185774d9a47f359de6b41c8542e038e8189933186
3
+ metadata.gz: 5006a01bb4cc0233b564962b0260a626c0985b9e787e234d95a8176c93716d94
4
+ data.tar.gz: a996c445790d6f679e17d77b241769d62fb6ee334af7bfa65f622b0c4b6b4864
5
5
  SHA512:
6
- metadata.gz: 45934bf36576b5dfdf8e88f019779603ddcfe989c4d6ce5c3da75d07571b5097b1f06a7147663fadaef4995532d3d2661fc1733e2bf49396820202c14d33c005
7
- data.tar.gz: 4853657f6fb46102d63d4a6f44ca0b07e3915ab7029369c815ec7530654973af30aee1184d826cc2df1a4a8c393525a3afa05005ef30aaabcf14435a66f693e6
6
+ metadata.gz: 26c74331f3f32be4c8fbb49c16b308d6549f75eada577c2a589b0897591607d29a92d535a3a680d93957ada6a402ecafe87b923c54ef5563bdad7ec09f3949ac
7
+ data.tar.gz: 792b07d6e3e8b90d15a2582c509b817189051846f9a1c520b0fb78a44aaa5c166def08c7819f204b3685d6d86a27f858e6c4a8ae0516c6305177a7c53217490b
data/README.md CHANGED
@@ -24,7 +24,7 @@ i18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (def
24
24
  Add i18n-tasks to the Gemfile:
25
25
 
26
26
  ```ruby
27
- gem 'i18n-tasks', '~> 1.0.1'
27
+ gem 'i18n-tasks', '~> 1.0.4'
28
28
  ```
29
29
 
30
30
  Copy the default [configuration file](#configuration):
@@ -223,7 +223,7 @@ See the full list of tasks with `i18n-tasks --help`.
223
223
 
224
224
  ### Features and limitations
225
225
 
226
- `i18n-tasks` uses an AST scanner for `.rb` files, and a regexp-based scanner for other files, such as `.haml`.
226
+ `i18n-tasks` uses an AST scanner for `.rb` and `.html.erb` files, and a regexp-based scanner for other files, such as `.haml`.
227
227
 
228
228
  #### Relative keys
229
229
 
@@ -2,22 +2,26 @@
2
2
 
3
3
  module I18n::Tasks
4
4
  module Interpolations
5
- VARIABLE_REGEX = /%{[^}]+}/.freeze
5
+ class << self
6
+ attr_accessor :variable_regex
7
+ end
8
+ @variable_regex = /%{[^}]+}/.freeze
6
9
 
7
10
  def inconsistent_interpolations(locales: nil, base_locale: nil) # rubocop:disable Metrics/AbcSize
8
11
  locales ||= self.locales
9
12
  base_locale ||= self.base_locale
10
13
  result = empty_forest
14
+ variable_regex = I18n::Tasks::Interpolations.variable_regex
11
15
 
12
16
  data[base_locale].key_values.each do |key, value|
13
17
  next if !value.is_a?(String) || ignore_key?(key, :inconsistent_interpolations)
14
18
 
15
- base_vars = Set.new(value.scan(VARIABLE_REGEX))
19
+ base_vars = Set.new(value.scan(variable_regex))
16
20
  (locales - [base_locale]).each do |current_locale|
17
21
  node = data[current_locale].first.children[key]
18
22
  next unless node&.value.is_a?(String)
19
23
 
20
- if base_vars != Set.new(node.value.scan(VARIABLE_REGEX))
24
+ if base_vars != Set.new(node.value.scan(variable_regex))
21
25
  result.merge!(node.walk_to_root.reduce(nil) { |c, p| [p.derive(children: c)] })
22
26
  end
23
27
  end
@@ -9,7 +9,7 @@ module I18n::Tasks::Scanners
9
9
  include AST::Processor::Mixin
10
10
  def initialize
11
11
  super()
12
- @ruby_parser = LocalRubyParser.new
12
+ @ruby_parser = LocalRubyParser.new(ignore_blocks: true)
13
13
  @comments = []
14
14
  end
15
15
 
@@ -35,7 +35,10 @@ module I18n::Tasks::Scanners
35
35
  node
36
36
  end
37
37
 
38
+ # @param node [::Parser::AST::Node]
39
+ # @return [::Parser::AST::Node]
38
40
  def handler_missing(node)
41
+ node = transform_misparsed_comment(node)
39
42
  node.updated(
40
43
  nil,
41
44
  node.children.map { |child| node?(child) ? process(child) : child }
@@ -44,6 +47,35 @@ module I18n::Tasks::Scanners
44
47
 
45
48
  private
46
49
 
50
+ # Works around incorrect handling of comments of the form:
51
+ # <%# ... #>
52
+ # (no space between % and #)
53
+ #
54
+ # With a space the AST is:
55
+ #
56
+ # s(:erb, nil, nil,
57
+ # s(:code, " # this should not fail: ' "), nil)
58
+ #
59
+ # Without a space the AST is:
60
+ #
61
+ # s(:erb,
62
+ # s(:indicator, "#"), nil,
63
+ # s(:code, " this should not fail: ' "), nil)
64
+ # @param node [::Parser::AST::Node]
65
+ # @return [::Parser::AST::Node]
66
+ def transform_misparsed_comment(node)
67
+ return node unless node.type == :erb && node.children.size == 4 &&
68
+ node.children[0]&.type == :indicator && node.children[0].children[0] == "#" &&
69
+ node.children[1].nil? &&
70
+ node.children[2]&.type == :code &&
71
+ node.children[3].nil?
72
+ code_node = node.children[2]
73
+ node.updated(
74
+ nil,
75
+ [nil, nil, code_node.updated(nil, ["##{code_node.children[0]}"]), nil]
76
+ )
77
+ end
78
+
47
79
  def node?(node)
48
80
  node.is_a?(::Parser::AST::Node)
49
81
  end
@@ -4,14 +4,23 @@ require 'parser/current'
4
4
 
5
5
  module I18n::Tasks::Scanners
6
6
  class LocalRubyParser
7
- def initialize
7
+ # ignore_blocks feature inspired by shopify/better-html
8
+ # https://github.com/Shopify/better-html/blob/087943ffd2a5877fa977d71532010b0c91239519/lib/better_html/test_helper/ruby_node.rb#L24
9
+ BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/.freeze
10
+
11
+ def initialize(ignore_blocks: false)
8
12
  @parser = ::Parser::CurrentRuby.new
13
+ @ignore_blocks = ignore_blocks
9
14
  end
10
15
 
11
16
  # Parse string and normalize location
12
17
  def parse(source, location: nil)
13
18
  buffer = ::Parser::Source::Buffer.new('(string)')
14
- buffer.source = source
19
+ buffer.source = if @ignore_blocks
20
+ source.sub(BLOCK_EXPR, '')
21
+ else
22
+ source
23
+ end
15
24
 
16
25
  @parser.reset
17
26
  ast, comments = @parser.parse_with_comments(buffer)
@@ -43,6 +52,8 @@ module I18n::Tasks::Scanners
43
52
  # @param local_location {Parser::Source::Map} Local location in the parsed string
44
53
  # @return {Parser::Source::Map}
45
54
  def updated_location(global_location, local_location)
55
+ return global_location if local_location.expression.nil?
56
+
46
57
  range = ::Parser::Source::Range.new(
47
58
  global_location.expression.source_buffer,
48
59
  global_location.expression.to_range.begin + local_location.expression.to_range.begin,
@@ -48,7 +48,7 @@ module I18n::Tasks
48
48
  # rubocop:enable Metrics/ParameterLists
49
49
 
50
50
  def inspect
51
- "Occurrence(#{@path}:#{@line_num}:#{@line_pos}:#{@pos}:#{@raw_key}:#{@default_arg}:#{@line})"
51
+ "Occurrence(#{@path}:#{@line_num}, line_pos: #{@line_pos}, pos: #{@pos}, raw_key: #{@raw_key}, default_arg: #{@default_arg}, line: #{@line})"
52
52
  end
53
53
 
54
54
  def ==(other)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module I18n
4
4
  module Tasks
5
- VERSION = '1.0.1'
5
+ VERSION = '1.0.4'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-24 00:00:00.000000000 Z
11
+ date: 2022-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport