copy_tuner_incompatible_search 1.0.0 → 2.0.0

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: deec2ce275a80adfa8b8cc254f8c1c231b24f105f135c9562879bc3e97594f27
4
- data.tar.gz: 3be254a36173f790085c55b5c16faf630037772adb462ea235228b63c620c628
3
+ metadata.gz: bc4286519e2113ead29b31af8cf83dfd670a7c6f6f9c6bdc64a04521761449c8
4
+ data.tar.gz: b3d299b35e57cab0718788e1835b5d9c962af93bce74949fe178b235406472d1
5
5
  SHA512:
6
- metadata.gz: f25cdab6e4336dfd507b00091758c4bdde845db9f642ea1a2ebfd80d76a421a85a6d9e6a250bfd30b48ce77ed9f909d40be257701a1f5c86134b6695a6d0c6a9
7
- data.tar.gz: d8a375d7f39a73e526c352c94acafad366bed3e74eb811be7c9685189ecec68ca58bba5f8824a2a54390d8ee4ede049e1b3da61e288359f0db0fa7212613ee06
6
+ metadata.gz: d444bc38349d99fecda3dd7f5bf6380809291f8f33b086a258ce7a32b86e454606028743763ef1f28b02cb1f822a831820e304ea3e26b928ab7a5f87aa3c4362
7
+ data.tar.gz: e251abc409a2d201075202ded4a7f1659664aa9ed37b3b9557cc79c83c891f92a0c23b2f77bae137db3150fa65348963aafab9e0be4b2c86222ee7de1fe81da8
data/.rubocop.yml CHANGED
@@ -14,3 +14,11 @@ RSpec/ReceiveMessages:
14
14
  Enabled: false
15
15
  RSpec/NestedGroups:
16
16
  Enabled: false
17
+ RSpec/ContextWording:
18
+ Enabled: false
19
+ RSpec/ExampleLength:
20
+ Enabled: false
21
+ RSpec/VerifiedDoubles:
22
+ Enabled: false
23
+ RSpec/MessageSpies:
24
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
1
  ## [Unreleased]
2
+ ## [2.0.0] - 2024-05-03
3
+
4
+ - Add command copy_tuner_incompatible_replace
5
+
2
6
  ## [1.0.0] - 2024-04-28
3
7
 
4
8
  - Release the first version
data/README.md CHANGED
@@ -20,6 +20,8 @@ If bundler is not being used to manage dependencies, install the gem by executin
20
20
 
21
21
  copy_tuner_incompatible_search
22
22
 
23
+ copy_tuner_incompatible_replace <usage.xlsx> <blurbs.csv>
24
+
23
25
  ## Development
24
26
 
25
27
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/Steepfile CHANGED
@@ -29,5 +29,7 @@
29
29
  # end
30
30
  target :lib do
31
31
  check 'lib'
32
+ # すぐにrbsを導入するのは難しそうなのであとまわし
33
+ ignore 'lib/copy_tuner_incompatible_search/replace_command.rb'
32
34
  signature 'sig'
33
35
  end
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/copy_tuner_incompatible_search'
4
+
5
+ def show_keys(keys)
6
+ if keys.empty?
7
+ puts 'なし'
8
+ else
9
+ puts keys.uniq.sort
10
+ end
11
+ puts
12
+ end
13
+
14
+ project_name = File.basename(Dir.pwd)
15
+ timestamp = Time.now.strftime('%Y%m%d%H%M%S')
16
+ output_path = "tmp/with-html-suffix-#{project_name}-#{timestamp}.csv"
17
+ usage_path = ARGV[0]
18
+ blurbs_path = ARGV[1]
19
+ if usage_path.nil? || blurbs_path.nil?
20
+ puts 'Please specify file paths: copy_tuner_incompatible_replace <usage_xlsx> <blurbs_csv>'
21
+ puts 'usage_xlsx can be created by copy_tuner_incompatible_search'
22
+ puts 'blurbs_csv can be downloaded from CopyTuner server'
23
+ exit 1
24
+ end
25
+ result = CopyTunerIncompatibleSearch::ReplaceCommand.run(usage_path, blurbs_path, output_path)
26
+
27
+ puts "非互換のキーを_html付きのキーに変換したので、#{output_path}をCopyTunerにアップロードする。コードも置換済み"
28
+ show_keys result.newly_replaced_keys
29
+
30
+ puts '非互換だが、すでに_htmlまたは.htmlつきのキーが存在していたので、コードの置換のみ実行'
31
+ show_keys result.existing_keys
32
+
33
+ puts '使用箇所を見つけられなかったキー。手動で使用箇所を特定し、手動で_html付きのキーを作成する'
34
+ show_keys result.not_used_incompatible_keys
35
+
36
+ puts '非互換のキーはconfig.ignored_keysに追加する'
37
+ show_keys result.keys_to_ignore
38
+
39
+ puts '以下のキーはすでにconfig.ignored_keysに追加済み'
40
+ show_keys result.already_ignored_keys
41
+
42
+ puts '特殊文字を含むキー。手動で使用箇所を特定し、手動で_html付きのキーを作成する。config.ignored_keys にも追加する'
43
+ show_keys result.keys_with_special_chars
44
+
45
+ puts '動的なキーが使われている箇所の数。手動で使用箇所を特定し、手動で_html付きのキーを作成する'
46
+ puts result.dynamic_count
@@ -0,0 +1,217 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+ require 'set'
5
+
6
+ require 'roo'
7
+
8
+ module CopyTunerIncompatibleSearch
9
+ class ReplaceCommand # rubocop:disable Metrics/ClassLength
10
+ def self.run(usage_path, blurbs_path, output_path)
11
+ self.new(usage_path, blurbs_path).run(output_path)
12
+ end
13
+
14
+ def initialize(usage_path, blurbs_path)
15
+ @usage_path = usage_path
16
+ @blurbs_path = blurbs_path
17
+ end
18
+
19
+ def run(output_path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
20
+ # usages.xlsxから生成したUsageオブジェクトの配列
21
+ usages = usage_sheet.each(type: 'Type', key: 'Key', ignored: 'Ignored', file: 'File', line: 'Line').filter_map.with_index do |hash, i|
22
+ next if i.zero? # skip header
23
+
24
+ Usage.new(**hash)
25
+ end
26
+ # プロジェクト内で後方互換性のないキーの集合
27
+ incompatible_keys = Set[*usages.select(&:static?).map(&:key)]
28
+ # 使用箇所が判明しているUsageオブジェクトの配列(ただし、dynamicなキーを除く)
29
+ used_usages = usages.select(&:used?)
30
+ # _html付きのキーに変換する必要があるキーの集合
31
+ keys_to_convert = Set[*used_usages.map(&:key)]
32
+ # staticかつ使用箇所が判明しているUsageオブジェクトの配列を翻訳キーでグループ化
33
+ static_usages_by_key = used_usages.select(&:static?).group_by(&:key)
34
+ # lazyかつ使用箇所が判明しているUsageオブジェクトの配列を翻訳キーでグループ化
35
+ lazy_usages_by_key = used_usages.select(&:lazy?).group_by(&:key)
36
+
37
+ # blurbs.csvの全キーの集合と、特殊文字を含むキーの配列
38
+ all_blurb_keys, keys_with_special_chars = parse_blurbs_csv
39
+ # すでに_htmlで終わるキーが存在する後方互換性のないキーの集合
40
+ underscore_converted_keys = Set[*incompatible_keys.select { |k| all_blurb_keys.include?("#{k}_html") }]
41
+ # すでに.htmlで終わるキーが存在する後方互換性のないキーの集合
42
+ dot_converted_keys = Set[*incompatible_keys.select { |k| all_blurb_keys.include?("#{k}.html") }]
43
+
44
+ # コード上のキーを置換する必要があるキーの配列
45
+ keys_for_code_replace = []
46
+ # _html付きのキーを新たに登録しなければならないキーの配列
47
+ newly_replaced_keys = []
48
+ # 使用箇所が見つからなかった後方互換性のないキーの配列
49
+ not_used_incompatible_keys = []
50
+ # _html付きのキーを定義したCSVを保存する。このファイルはCopyTunerにアップロードするために使う
51
+ CSV.open(output_path, 'wb') do |csv_out|
52
+ CSV.parse(blurbs_csv_text, headers: true, quote_char: '"').each_with_index do |row, i|
53
+ if i.zero?
54
+ csv_out << row.headers
55
+ end
56
+ key = row[0]
57
+ converted_key = "#{key}_html"
58
+ if keys_to_convert.include?(key) && !dot_converted_keys.include?(key) && !underscore_converted_keys.include?(key)
59
+ csv_out << [converted_key, *row[1..]]
60
+ newly_replaced_keys << key
61
+ end
62
+ if keys_to_convert.include?(key)
63
+ keys_for_code_replace << key
64
+ elsif incompatible_keys.include?(key)
65
+ not_used_incompatible_keys << key
66
+ end
67
+ end
68
+ end
69
+
70
+ replace_code_for_static_usages(static_usages_by_key, keys_for_code_replace, underscore_converted_keys, dot_converted_keys)
71
+ replace_code_for_lazy_usages(lazy_usages_by_key, keys_for_code_replace, underscore_converted_keys, dot_converted_keys)
72
+
73
+ existing_keys = keys_for_code_replace - newly_replaced_keys
74
+ already_ignored_keys = search_ignored_keys.uniq
75
+ keys_to_ignore = usages.reject(&:dynamic?).map(&:key).uniq - already_ignored_keys
76
+ dynamic_count = usages.count(&:dynamic?)
77
+ Result.new(newly_replaced_keys, existing_keys, not_used_incompatible_keys, keys_to_ignore, already_ignored_keys, keys_with_special_chars, dynamic_count)
78
+ end
79
+
80
+ private
81
+
82
+ attr_reader :usage_path, :blurbs_path
83
+
84
+ class Usage
85
+ attr_reader :type, :key, :file, :line
86
+
87
+ def initialize(type:, key:, ignored:, file:, line:)
88
+ @type = type
89
+ @key = key
90
+ @ignored = ignored
91
+ @file = file
92
+ @line = line.to_s.empty? ? nil : line.to_i
93
+ end
94
+
95
+ def static?
96
+ @type == 'static'
97
+ end
98
+
99
+ def lazy?
100
+ @type == 'lazy'
101
+ end
102
+
103
+ def dynamic?
104
+ @type == 'dynamic'
105
+ end
106
+
107
+ def used?
108
+ !dynamic? && !@file.to_s.strip.empty?
109
+ end
110
+
111
+ def lazy_key
112
+ return unless lazy?
113
+
114
+ last_key = key.split('.').last
115
+ ".#{last_key}"
116
+ end
117
+ end
118
+
119
+ class Result
120
+ attr_reader :newly_replaced_keys, :existing_keys, :not_used_incompatible_keys, :keys_to_ignore, :already_ignored_keys, :keys_with_special_chars,
121
+ :dynamic_count
122
+
123
+ def initialize(newly_replaced_keys, existing_keys, not_used_incompatible_keys, keys_to_ignore, already_ignored_keys, keys_with_special_chars, dynamic_count) # rubocop:disable Metrics/ParameterLists, Layout/LineLength
124
+ @newly_replaced_keys = newly_replaced_keys
125
+ @existing_keys = existing_keys
126
+ @not_used_incompatible_keys = not_used_incompatible_keys
127
+ @keys_to_ignore = keys_to_ignore
128
+ @already_ignored_keys = already_ignored_keys
129
+ @keys_with_special_chars = keys_with_special_chars
130
+ @dynamic_count = dynamic_count
131
+ end
132
+ end
133
+
134
+ def usage_sheet
135
+ actual_xlsx = Roo::Spreadsheet.open(usage_path)
136
+ actual_xlsx.sheet(0)
137
+ end
138
+
139
+ def blurbs_csv_text
140
+ File.read(blurbs_path)
141
+ end
142
+
143
+ def search_ignored_keys
144
+ eval(ignored_keys_text) # rubocop:disable Security/Eval
145
+ end
146
+
147
+ def ignored_keys_text
148
+ `rails r "p CopyTunerClient::configuration.ignored_keys"`
149
+ end
150
+
151
+ def parse_blurbs_csv
152
+ keys_with_special_chars = []
153
+ all_blurb_keys = []
154
+ CSV.parse(blurbs_csv_text, headers: true, quote_char: '"').each do |row|
155
+ # FIXME: なぜか文字列で指定すると取得できない
156
+ # row['key']
157
+ key = row[0]
158
+ all_blurb_keys << key
159
+ translation = row[1]
160
+ if translation.match?(/&#\d+;|&\w+;/) && !key.match?(/[_.]html$/)
161
+ keys_with_special_chars << key
162
+ end
163
+ end
164
+ [Set[*all_blurb_keys], keys_with_special_chars]
165
+ end
166
+
167
+ def replace_code_for_lazy_usages(lazy_usages_by_key, keys_for_code_replace, underscore_converted_keys, dot_converted_keys)
168
+ lazy_usages_by_key.each do |key, usages|
169
+ next unless keys_for_code_replace.include?(key)
170
+
171
+ usages.each do |usage|
172
+ replace_code(usage, underscore_converted_keys, dot_converted_keys)
173
+ end
174
+ end
175
+ end
176
+
177
+ def replace_code_for_static_usages(static_usages_by_key, keys_for_code_replace, underscore_converted_keys, dot_converted_keys)
178
+ static_usages_by_key.each do |key, usages|
179
+ next unless keys_for_code_replace.include?(key)
180
+
181
+ usages.each do |usage|
182
+ replace_code(usage, underscore_converted_keys, dot_converted_keys)
183
+ end
184
+ end
185
+ end
186
+
187
+ def replace_code(usage, underscore_converted_keys, dot_converted_keys)
188
+ lines = file_readlines(usage.file)
189
+ if usage.lazy?
190
+ lazy_key = usage.lazy_key
191
+ regex = /(?<=['"])#{Regexp.escape(lazy_key)}(?=['"])/
192
+ else
193
+ regex = /(?<=['"])#{Regexp.escape(usage.key)}(?=['"])/
194
+ end
195
+ new_key = generate_html_key(usage, underscore_converted_keys, dot_converted_keys)
196
+ lines[usage.line - 1].gsub!(regex, new_key)
197
+ file_write(usage.file, lines.join)
198
+ end
199
+
200
+ def file_readlines(path)
201
+ File.readlines(path)
202
+ end
203
+
204
+ def file_write(path, text)
205
+ File.write(path, text)
206
+ end
207
+
208
+ # すでに_htmlまたは.htmlのキーが存在していればそのキーを、そうでなければ_html付きのキーを返す
209
+ def generate_html_key(usage, underscore_converted_keys, dot_converted_keys)
210
+ has_underscore = underscore_converted_keys.include?(usage.key)
211
+ has_dot = dot_converted_keys.include?(usage.key)
212
+ none = !has_underscore && !has_dot
213
+ key = usage.lazy? ? usage.lazy_key : usage.key
214
+ has_underscore || none ? "#{key}_html" : "#{key}.html"
215
+ end
216
+ end
217
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CopyTunerIncompatibleSearch
4
- VERSION = '1.0.0'
4
+ VERSION = '2.0.0'
5
5
  end
@@ -9,8 +9,8 @@ module CopyTunerIncompatibleSearch
9
9
  end
10
10
 
11
11
  def save_to(output_path)
12
- Axlsx::Package.new do |p|
13
- p.workbook.add_worksheet(name: 'Data') do |sheet|
12
+ Axlsx::Package.new do |pkg|
13
+ pkg.workbook.add_worksheet(name: 'Data') do |sheet|
14
14
  style = sheet.styles.add_style(font_name: 'Courier New', sz: 14)
15
15
  sheet.add_row %w[Type Key Ignored File Line Code], style: style
16
16
  sheet.auto_filter = 'A1:F1'
@@ -20,7 +20,7 @@ module CopyTunerIncompatibleSearch
20
20
  add_result_rows(sheet, result, style)
21
21
  end
22
22
  end
23
- p.serialize(output_path)
23
+ pkg.serialize(output_path)
24
24
  end
25
25
  end
26
26
 
@@ -3,6 +3,7 @@
3
3
  require_relative 'copy_tuner_incompatible_search/version'
4
4
  require_relative 'copy_tuner_incompatible_search/command'
5
5
  require_relative 'copy_tuner_incompatible_search/xlsx_writer'
6
+ require_relative 'copy_tuner_incompatible_search/replace_command'
6
7
 
7
8
  module CopyTunerIncompatibleSearch
8
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: copy_tuner_incompatible_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Junichi Ito
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-28 00:00:00.000000000 Z
11
+ date: 2024-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: caxlsx
@@ -28,6 +28,7 @@ description:
28
28
  email:
29
29
  - jit@sonicgarden.jp
30
30
  executables:
31
+ - copy_tuner_incompatible_replace
31
32
  - copy_tuner_incompatible_search
32
33
  extensions: []
33
34
  extra_rdoc_files: []
@@ -40,9 +41,11 @@ files:
40
41
  - README.md
41
42
  - Rakefile
42
43
  - Steepfile
44
+ - exe/copy_tuner_incompatible_replace
43
45
  - exe/copy_tuner_incompatible_search
44
46
  - lib/copy_tuner_incompatible_search.rb
45
47
  - lib/copy_tuner_incompatible_search/command.rb
48
+ - lib/copy_tuner_incompatible_search/replace_command.rb
46
49
  - lib/copy_tuner_incompatible_search/version.rb
47
50
  - lib/copy_tuner_incompatible_search/xlsx_writer.rb
48
51
  - sig/copy_tuner_incompatible_search.rbs