narou 2.6.1 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of narou might be problematic. Click here for more details.

Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +65 -0
  3. data/README.md +69 -22
  4. data/lib/command.rb +1 -0
  5. data/lib/command/alias.rb +2 -2
  6. data/lib/command/convert.rb +3 -3
  7. data/lib/command/csv.rb +108 -0
  8. data/lib/command/download.rb +13 -1
  9. data/lib/command/freeze.rb +1 -1
  10. data/lib/command/init.rb +5 -1
  11. data/lib/command/inspect.rb +1 -1
  12. data/lib/command/mail.rb +1 -1
  13. data/lib/command/send.rb +2 -2
  14. data/lib/command/setting.rb +17 -1
  15. data/lib/command/tag.rb +28 -9
  16. data/lib/command/update.rb +57 -30
  17. data/lib/commandbase.rb +3 -2
  18. data/lib/commandline.rb +2 -2
  19. data/lib/converterbase.rb +70 -7
  20. data/lib/database.rb +1 -1
  21. data/lib/device.rb +3 -0
  22. data/lib/device/ibooks.rb +2 -2
  23. data/lib/device/ibunko.rb +4 -0
  24. data/lib/diffviewer.rb +2 -2
  25. data/lib/downloader.rb +16 -9
  26. data/lib/helper.rb +53 -22
  27. data/lib/inventory.rb +6 -2
  28. data/lib/narou.rb +13 -6
  29. data/lib/novelconverter.rb +35 -13
  30. data/lib/novelsetting.rb +7 -1
  31. data/lib/version.rb +1 -1
  32. data/lib/web/appserver.rb +78 -8
  33. data/lib/web/public/resources/common.ui.js +0 -39
  34. data/lib/web/public/resources/dataTables.colVis.js +1 -1
  35. data/lib/web/public/resources/default-style.css +1 -1
  36. data/lib/web/public/resources/help/bookmarklet1.png +0 -0
  37. data/lib/web/public/resources/help/bookmarklet2.png +0 -0
  38. data/lib/web/public/resources/images/dl_button0.gif +0 -0
  39. data/lib/web/public/resources/images/dl_button1.gif +0 -0
  40. data/lib/web/public/resources/narou.library.js +268 -36
  41. data/lib/web/public/resources/narou.queue.js +51 -0
  42. data/lib/web/public/resources/narou.ui.js +156 -59
  43. data/lib/web/settingmessages.rb +2 -1
  44. data/lib/web/views/{js/widget.erb → bookmarklet/download.js.erb} +1 -1
  45. data/lib/web/views/bookmarklet/insert_button.js.erb +133 -0
  46. data/lib/web/views/help.haml +31 -14
  47. data/lib/web/views/index.haml +62 -0
  48. data/lib/web/views/layout.haml +8 -7
  49. data/lib/web/views/parts/csv_import.haml +68 -0
  50. data/lib/web/views/parts/download_form.haml +89 -0
  51. data/lib/web/views/settings.haml +8 -3
  52. data/lib/web/views/style.scss +200 -14
  53. data/lib/web/views/{widget.haml → widget/download.haml} +18 -4
  54. data/lib/web/views/widget/drag_and_drop.haml +97 -0
  55. data/lib/web/worker.rb +39 -1
  56. data/narou.gemspec +56 -56
  57. data/preset/custom_chuki_tag.txt +1 -1
  58. data/preset/doubledash.png +0 -0
  59. data/preset/singledash.png +0 -0
  60. data/preset/vertical_font.css +1 -1
  61. data/spec/convert_spec.rb +5 -1
  62. data/spec/data/convert_test/auto_join_line/correct_test_auto_join_line.txt +6 -0
  63. data/spec/data/convert_test/auto_join_line/test_auto_join_line.txt +8 -0
  64. data/spec/data/convert_test/double_dash_to_image/correct_test_double_dash_to_image.txt +14 -0
  65. data/spec/data/convert_test/double_dash_to_image/setting.ini +1 -0
  66. data/spec/data/convert_test/double_dash_to_image/test_double_dash_to_image.txt +12 -0
  67. data/spec/worker_spec.rb +21 -2
  68. metadata +97 -60
@@ -52,7 +52,7 @@ class Database
52
52
  end
53
53
 
54
54
  def refresh
55
- @database = Inventory.load(DATABASE_NAME, :local)
55
+ @database = Inventory.load(DATABASE_NAME)
56
56
  end
57
57
 
58
58
  #
@@ -138,6 +138,9 @@ class Device
138
138
  raise SendFailure, res[1].rstrip
139
139
  end
140
140
  end
141
+ if Narou.economy?("send_delete")
142
+ FileUtils.rm_f(src_file)
143
+ end
141
144
  dst_path
142
145
  else
143
146
  nil
@@ -60,7 +60,7 @@ module Device::Ibooks
60
60
  end
61
61
 
62
62
  def get_epubdir_path_in_ibooks_container
63
- list = Inventory.load("ibooks_epubdir_path_list", :local)
63
+ list = Inventory.load("ibooks_epubdir_path_list")
64
64
  if list[@toc_url]
65
65
  list[@toc_url]
66
66
  else
@@ -106,7 +106,7 @@ module Device::Ibooks
106
106
  end
107
107
 
108
108
  def regist_epubdir_path_to_setting(path)
109
- list = Inventory.load("ibooks_epubdir_path_list", :local)
109
+ list = Inventory.load("ibooks_epubdir_path_list")
110
110
  list[@toc_url] = path
111
111
  list.save
112
112
  end
@@ -51,6 +51,10 @@ module Device::Ibunko
51
51
  end
52
52
  puts File.basename(zipfile_path) + " を出力しました"
53
53
  puts "<bold><green>#{@device.display_name}用ファイルを出力しました</green></bold>".termcolor
54
+ if Narou.economy?("cleanup_temp") && @argument_target_type == :novel
55
+ # 作業用ファイルを削除
56
+ FileUtils.rm_f(@converted_txt_path)
57
+ end
54
58
  zipfile_path
55
59
  end
56
60
 
@@ -134,8 +134,8 @@ class DiffViewer
134
134
  end
135
135
  end
136
136
  end
137
- result = "<bold><red>-#{old_str}</red>\n" \
138
- "<green>+#{new_str}</green></bold>"
137
+ result = "<bold><red>-#{old_str}</red></bold>\n" \
138
+ "<bold><green>+#{new_str}</green></bold>"
139
139
  when "-"
140
140
  result = "<bold><red>-#{TermColorLight.escape(old_element)}</red></bold>"
141
141
  when "+"
@@ -289,11 +289,14 @@ class Downloader
289
289
  @id = id || @@database.create_new_id
290
290
  @new_novel = @@database[@id].!
291
291
  @section_download_cache = {}
292
- @download_wait_steps = Inventory.load("local_setting", :local)["download.wait-steps"] || 0
292
+ @download_wait_steps = Inventory.load("local_setting")["download.wait-steps"] || 0
293
293
  @download_use_subdirectory = use_subdirectory?
294
294
  if @setting["is_narou"] && (@download_wait_steps > 10 || @download_wait_steps == 0)
295
295
  @download_wait_steps = 10
296
296
  end
297
+ @nosave_diff = Narou.economy?("nosave_diff")
298
+ @nosave_raw = Narou.economy?("nosave_raw")
299
+ @gurad_spoiler = Inventory.load("local_setting")["guard-spoiler"]
297
300
  initialize_wait_counter
298
301
  end
299
302
 
@@ -307,7 +310,7 @@ class Downloader
307
310
  @@__wait_counter = 0
308
311
  @@__last_download_time = Time.now - 20
309
312
  end
310
- @@interval_sleep_time = Inventory.load("local_setting", :local)["download.interval"] || 0
313
+ @@interval_sleep_time = Inventory.load("local_setting")["download.interval"] || 0
311
314
  @@interval_sleep_time = 0 if @@interval_sleep_time < 0
312
315
  @@max_steps_wait_time = [STEPS_WAIT_TIME, @@interval_sleep_time].max
313
316
  end
@@ -318,7 +321,7 @@ class Downloader
318
321
  def use_subdirectory?
319
322
  if @new_novel
320
323
  # 新規DLする小説
321
- Inventory.load("local_setting", :local)["download.use-subdirectory"] || false
324
+ Inventory.load("local_setting")["download.use-subdirectory"] || false
322
325
  else
323
326
  # すでにDL済みの小説
324
327
  @@database[@id]["use_subdirectory"] || false
@@ -410,8 +413,7 @@ class Downloader
410
413
  end
411
414
  rescue Interrupt
412
415
  remove_cache_dir
413
- @stream.puts "ダウンロードを中断しました"
414
- exit Narou::EXIT_ERROR_CODE
416
+ raise
415
417
  end
416
418
  update_database
417
419
  :ok
@@ -437,7 +439,7 @@ class Downloader
437
439
  unless tags.include?("end")
438
440
  update_database if update_subtitles.count == 0
439
441
  $stdout.silence do
440
- Command::Tag.execute!([@id, "--add", "end", "--color", "white"])
442
+ Command::Tag.execute!(%W(#{id} --add end --color white --no-overwrite-color))
441
443
  end
442
444
  msg = old_toc.empty? ? "完結しているようです" : "完結したようです"
443
445
  @stream.puts "<cyan>#{id_and_title.escape} は#{msg}</cyan>".termcolor
@@ -524,6 +526,7 @@ class Downloader
524
526
  # 差分用キャッシュ保存ディレクトリ作成
525
527
  #
526
528
  def create_cache_dir
529
+ return nil if @nosave_diff
527
530
  now = Time.now
528
531
  name = now.strftime("%Y.%m.%d@%H.%M.%S")
529
532
  cache_dir = File.join(get_novel_data_dir, SECTION_SAVE_DIR_NAME, CACHE_SAVE_DIR_NAME, name)
@@ -760,7 +763,7 @@ class Downloader
760
763
  @stream.error "小説が削除されているか非公開な可能性があります"
761
764
  if @@database.novel_exists?(@id)
762
765
  $stdout.silence do
763
- Command::Tag.execute!(%W(#{@id} --add 404 --color white))
766
+ Command::Tag.execute!(%W(#{@id} --add 404 --color white --no-overwrite-color))
764
767
  end
765
768
  Command::Freeze.execute!([@id])
766
769
  end
@@ -786,7 +789,7 @@ class Downloader
786
789
  # 更新された subtitle だけまとまった配列を返す
787
790
  #
788
791
  def update_body_check(old_subtitles, latest_subtitles)
789
- strong_update = Inventory.load("local_setting", :local)["update.strong"]
792
+ strong_update = Inventory.load("local_setting")["update.strong"]
790
793
  latest_subtitles.select do |latest|
791
794
  index = latest["index"]
792
795
  index_in_old_toc = __search_index_in_subtitles(old_subtitles, index)
@@ -945,7 +948,8 @@ class Downloader
945
948
  else
946
949
  @stream.print "短編 "
947
950
  end
948
- @stream.print "#{subtitle} (#{i+1}/#{max})"
951
+ printable_subtitle = @gurad_spoiler ? Helper.to_unprintable_words(subtitle) : subtitle
952
+ @stream.print "#{printable_subtitle} (#{i+1}/#{max})"
949
953
 
950
954
  section_file_name = "#{index} #{file_subtitle}.yaml"
951
955
  section_file_relative_path = File.join(SECTION_SAVE_DIR_NAME, section_file_name)
@@ -992,6 +996,7 @@ class Downloader
992
996
  # 差分用のキャッシュとして保存
993
997
  #
994
998
  def move_to_cache_dir(relative_path)
999
+ return if @nosave_diff
995
1000
  path = File.join(get_novel_data_dir, relative_path)
996
1001
  if File.exist?(path) && @cache_dir
997
1002
  FileUtils.mv(path, @cache_dir)
@@ -1091,6 +1096,7 @@ class Downloader
1091
1096
  end
1092
1097
 
1093
1098
  def init_raw_dir
1099
+ return if @nosave_raw
1094
1100
  path = get_raw_dir
1095
1101
  FileUtils.mkdir_p(path) unless File.exist?(path)
1096
1102
  end
@@ -1099,6 +1105,7 @@ class Downloader
1099
1105
  # テキストデータの生データを保存
1100
1106
  #
1101
1107
  def save_raw_data(raw_data, subtitle_info, ext = ".txt")
1108
+ return if @nosave_raw
1102
1109
  index = subtitle_info["index"]
1103
1110
  file_subtitle = subtitle_info["file_subtitle"]
1104
1111
  path = File.join(get_raw_dir, "#{index} #{file_subtitle}#{ext}")
@@ -5,6 +5,7 @@
5
5
 
6
6
  require "open3"
7
7
  require "time"
8
+ require "systemu"
8
9
 
9
10
  #
10
11
  # 雑多なお助けメソッド群
@@ -176,8 +177,10 @@ module Helper
176
177
  "整数 "
177
178
  when :float
178
179
  "小数点数 "
179
- when :string, :select, :multiple
180
+ when :string, :select
180
181
  "文字列 "
182
+ when :multiple
183
+ "文字列(複数)"
181
184
  when :directory
182
185
  "フォルダパス"
183
186
  when :file
@@ -285,9 +288,29 @@ module Helper
285
288
  result
286
289
  end
287
290
 
291
+ #
292
+ # 伏せ字にする
293
+ #
294
+ # 数字やスペース、句読点、感嘆符はそのままにする
295
+ #
296
+ def to_unprintable_words(string, mask = "●")
297
+ result = ""
298
+ string.each_char do |char|
299
+ result += case char
300
+ when /[0-90-9  、。!?!?]/
301
+ char
302
+ else
303
+ mask
304
+ end
305
+ end
306
+ result
307
+ end
308
+
288
309
  #
289
310
  # 外部コマンド実行中の待機ループの処理を書けるクラス
290
311
  #
312
+ # 返り値:[標準出力のキャプチャ, 標準エラーのキャプチャ, Process::Status]
313
+ #
291
314
  # response = Helper::AsyncCommand.exec("処理に時間がかかる外部コマンド") do
292
315
  # print "*"
293
316
  # end
@@ -297,30 +320,38 @@ module Helper
297
320
  #
298
321
  class AsyncCommand
299
322
  def self.exec(command, sleep_time = 0.5, &block)
300
- Thread.new {
301
- loop do
302
- block.call if block
303
- sleep(sleep_time)
323
+ looper = nil
324
+ _pid = nil
325
+ status, stdout, stderr = systemu(command) do |pid|
326
+ _pid = pid
327
+ looper = Thread.new(pid) do |pid|
328
+ loop do
329
+ block.call if block
330
+ sleep(sleep_time)
331
+ if Narou::Worker.canceled?
332
+ Process.kill("KILL", pid)
333
+ Process.detach(pid)
334
+ break
335
+ end
336
+ end
304
337
  end
305
- }.tap { |th|
338
+ looper.join
339
+ looper = nil
340
+ end
341
+ stdout.force_encoding(Encoding::UTF_8)
342
+ stderr.force_encoding(Encoding::UTF_8)
343
+ return [stdout, stderr, status]
344
+ rescue Interrupt
345
+ if _pid
306
346
  begin
307
- if Helper.engine_jruby?
308
- # MEMO:
309
- # Open3.capture3 - 全く動かない
310
- # `` バッククウォート - 出力が文字化けする
311
- res = Open3.popen3(command) { |i, o, e|
312
- i.close
313
- `cd` # create dummy Process::Status object to $?
314
- [o.read, e.read, $?]
315
- }
316
- else
317
- res = Open3.capture3(command)
318
- end
319
- ensure
320
- th.kill
347
+ Process.kill("KILL", _pid)
348
+ Process.detach(_pid) # 死亡確認しないとゾンビ化する
349
+ rescue
321
350
  end
322
- return res
323
- }
351
+ end
352
+ raise
353
+ ensure
354
+ looper.kill if looper
324
355
  end
325
356
  end
326
357
 
@@ -10,9 +10,10 @@ require_relative "narou"
10
10
  # Narou.rbのシステムが記録するデータ単位
11
11
  #
12
12
  # .narou ディレクトリにYAMLファイルとして保存される
13
+ # scope に :global を指定するとユーザーディレクトリ/.narousetting に保存される
13
14
  #
14
15
  module Inventory
15
- def self.load(name, scope)
16
+ def self.load(name, scope = :local)
16
17
  @@cache ||= {}
17
18
  return @@cache[name] if @@cache[name]
18
19
  {}.tap { |h|
@@ -36,6 +37,7 @@ module Inventory
36
37
  raise "Unknown scope"
37
38
  end
38
39
  return nil unless dir
40
+ @mutex = Mutex.new
39
41
  @inventory_file_path = File.join(dir, name + ".yaml")
40
42
  if File.exist?(@inventory_file_path)
41
43
  self.merge!(Helper::CacheLoader.memo(@inventory_file_path) { |yaml|
@@ -48,7 +50,9 @@ module Inventory
48
50
  unless @inventory_file_path
49
51
  raise "not initialized setting dir yet"
50
52
  end
51
- File.write(@inventory_file_path, YAML.dump(self))
53
+ @mutex.synchronize do
54
+ File.write(@inventory_file_path, YAML.dump(self))
55
+ end
52
56
  end
53
57
  end
54
58
 
@@ -18,8 +18,9 @@ module Narou
18
18
  AOZORAEPUB3_DIR = "AozoraEpub3"
19
19
  PRESET_DIR = "preset"
20
20
  MISC_DIR = "misc"
21
- EXIT_ERROR_CODE = 127
22
21
  GLOBAL_REPLACE_NAME = "replace.txt"
22
+ EXIT_ERROR_CODE = 127
23
+ EXIT_INTERRUPT = 126
23
24
 
24
25
  UPDATE_SORT_KEYS = {
25
26
  "id" => "ID", "last_update" => "更新日", "title" => "タイトル", "author" => "作者名",
@@ -33,9 +34,10 @@ module Narou
33
34
 
34
35
  def get_root_dir
35
36
  root_dir = nil
36
- path = File.expand_path(File.dirname("."))
37
+ path = Dir.pwd
37
38
  drive_letter = ""
38
39
  if Helper.os_windows?
40
+ path.encode!(Encoding::UTF_8)
39
41
  path.gsub!(/^[a-z]:/i, "")
40
42
  drive_letter = $&
41
43
  end
@@ -86,7 +88,7 @@ module Narou
86
88
  end
87
89
 
88
90
  def alias_to_id(target)
89
- aliases = Inventory.load("alias", :local)
91
+ aliases = Inventory.load("alias")
90
92
  if aliases[target]
91
93
  return aliases[target]
92
94
  end
@@ -95,7 +97,7 @@ module Narou
95
97
 
96
98
  def novel_frozen?(target)
97
99
  id = Downloader.get_id_by_target(target) or return false
98
- Inventory.load("freeze", :local).include?(id)
100
+ Inventory.load("freeze").include?(id)
99
101
  end
100
102
 
101
103
  def get_preset_dir
@@ -201,7 +203,7 @@ module Narou
201
203
  require_relative "device"
202
204
 
203
205
  def get_device(device_name = nil)
204
- device_name = Inventory.load("local_setting", :local)["device"] unless device_name
206
+ device_name = Inventory.load("local_setting")["device"] unless device_name
205
207
  if device_name && Device.exists?(device_name)
206
208
  return Device.create(device_name)
207
209
  end
@@ -223,7 +225,7 @@ module Narou
223
225
  end
224
226
 
225
227
  def get_theme
226
- Inventory.load("local_setting", :local)["theme"]
228
+ Inventory.load("local_setting")["theme"]
227
229
  end
228
230
 
229
231
  def get_theme_dir(name = nil)
@@ -237,5 +239,10 @@ module Narou
237
239
  end.compact
238
240
  end
239
241
  memoize :get_theme_names
242
+
243
+ def economy?(mode)
244
+ eco_modes = Inventory.load("local_setting")["economy"].to_s.split(",").map(&:strip)
245
+ eco_modes.include?(mode)
246
+ end
240
247
  end
241
248
  end
@@ -181,6 +181,10 @@ class NovelConverter
181
181
  return :error
182
182
  end
183
183
 
184
+ error_list = stdout_capture.scan(/^(?:\[ERROR\]|エラーが発生しました :).+$/)
185
+ warn_list = stdout_capture.scan(/^\[WARN\].+$/)
186
+ info_list = stdout_capture.scan(/^\[INFO\].+$/)
187
+
184
188
  if verbose
185
189
  puts
186
190
  puts "==== AozoraEpub3 stdout capture " + "=" * 47
@@ -188,12 +192,11 @@ class NovelConverter
188
192
  puts "=" * 79
189
193
  end
190
194
 
191
- error_list = stdout_capture.scan(/^(?:\[ERROR\]|エラーが発生しました :).+$/)
192
- warn_list = stdout_capture.scan(/^\[WARN\].+$/)
193
- info_list = stdout_capture.scan(/^\[INFO\].+$/)
194
- if !error_list.empty? || !warn_list.empty? || !info_list.empty?
195
- puts
196
- puts error_list, warn_list, info_list
195
+ if !error_list.empty? || !warn_list.empty?
196
+ unless verbose
197
+ puts
198
+ puts error_list, warn_list
199
+ end
197
200
  unless error_list.empty?
198
201
  # AozoraEpub3 のエラーにはEPUBが出力されないエラーとEPUBが出力されるエラーの2種類ある。
199
202
  # EPUBが出力される場合は「変換完了」という文字があるのでそれを検出する
@@ -270,12 +273,15 @@ class NovelConverter
270
273
  verbose: false,
271
274
  no_epub: false,
272
275
  no_mobi: false,
273
- no_strip: false
276
+ no_strip: false,
277
+ no_cleanup_txt: false,
274
278
  }.merge(options)
275
279
 
276
280
  device = options[:device]
281
+ clean_up_file_list = []
277
282
 
278
283
  return false if options[:no_epub]
284
+ clean_up_file_list << txt_path unless options[:no_cleanup_txt]
279
285
  # epub
280
286
  status = NovelConverter.txt_to_epub(txt_path, options[:use_dakuten_font],
281
287
  options[:dst_dir], device, options[:verbose])
@@ -293,6 +299,7 @@ class NovelConverter
293
299
  return epub_path
294
300
  end
295
301
 
302
+ clean_up_file_list << epub_path
296
303
  # mobi
297
304
  status = NovelConverter.epub_to_mobi(epub_path, options[:verbose])
298
305
  return nil if status != :success
@@ -311,9 +318,20 @@ class NovelConverter
311
318
  puts "<bold><green>MOBIファイルを出力しました</green></bold>".termcolor
312
319
 
313
320
  return mobi_path
321
+ ensure
322
+ if Narou.economy?("cleanup_temp")
323
+ # 作業用ファイルを削除
324
+ clean_up_temp_files(clean_up_file_list)
325
+ end
326
+ end
327
+
328
+ def self.clean_up_temp_files(path_list)
329
+ path_list.each do |path|
330
+ FileUtils.rm_f(path)
331
+ end
314
332
  end
315
333
 
316
- def initialize(setting, output_filename = nil, display_inspector = false)
334
+ def initialize(setting, output_filename = nil, display_inspector = false, output_text_dir = nil)
317
335
  @setting = setting
318
336
  @novel_id = setting.id
319
337
  @novel_author = setting.author
@@ -324,6 +342,7 @@ class NovelConverter
324
342
  @display_inspector = display_inspector
325
343
  @use_dakuten_font = false
326
344
  @converter = create_converter
345
+ @converter.output_text_dir = output_text_dir
327
346
  end
328
347
 
329
348
  #
@@ -357,10 +376,10 @@ class NovelConverter
357
376
  progressbar = ProgressBar.new(subtitles.size)
358
377
  end
359
378
  on(:"convert_main.loop") do |i|
360
- progressbar.output(i)
379
+ progressbar.output(i) if progressbar
361
380
  end
362
381
  one(:"convert_main.finish") do
363
- progressbar.clear
382
+ progressbar.clear if progressbar
364
383
  end
365
384
  end
366
385
 
@@ -497,6 +516,8 @@ class NovelConverter
497
516
  #
498
517
  def convert_main_for_novel(subtitles = nil, is_hotentry = false)
499
518
  toc = Downloader.get_toc_data(@setting.archive_path)
519
+ subtitles ||= toc["subtitles"]
520
+ @converter.subtitles = subtitles
500
521
  toc["story"] = @converter.convert(toc["story"], "story")
501
522
  html = HTML.new
502
523
  html.strip_decoration_tag = @setting.enable_strip_decoration_tag
@@ -504,7 +525,6 @@ class NovelConverter
504
525
  html.set_illust_setting({current_url: site_setting["illust_current_url"],
505
526
  grep_pattern: site_setting["illust_grep_pattern"]})
506
527
 
507
- subtitles ||= toc["subtitles"]
508
528
  sections = subtitles_to_sections(subtitles, html)
509
529
  converted_text = create_novel_text_by_template(sections, toc, is_hotentry)
510
530
 
@@ -521,6 +541,7 @@ class NovelConverter
521
541
  trigger(:"convert_main.init", subtitles)
522
542
  subtitles.each_with_index do |subinfo, i|
523
543
  trigger(:"convert_main.loop", i)
544
+ @converter.current_index = i
524
545
  section = load_novel_section(subinfo, section_save_dir)
525
546
  if section["chapter"].length > 0
526
547
  section["chapter"] = @converter.convert(section["chapter"], "chapter")
@@ -538,9 +559,10 @@ class NovelConverter
538
559
  section["subtitle"] = @converter.convert(section["subtitle"], "subtitle")
539
560
  sections << section
540
561
  end
541
- trigger(:"convert_main.finish")
542
562
  @use_dakuten_font = @converter.use_dakuten_font
543
563
  sections
564
+ ensure
565
+ trigger(:"convert_main.finish")
544
566
  end
545
567
 
546
568
  #
@@ -585,7 +607,7 @@ class NovelConverter
585
607
  #
586
608
  def update_latest_convert_novel
587
609
  id = Downloader.get_id_by_target(@novel_title)
588
- Inventory.load("latest_convert", :local).tap { |inv|
610
+ Inventory.load("latest_convert").tap { |inv|
589
611
  inv["id"] = id
590
612
  inv.save
591
613
  }