narou 2.5.2 → 2.6.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/ChangeLog.md +54 -0
  4. data/LICENSE.txt +26 -0
  5. data/README.md +70 -84
  6. data/lib/command/alias.rb +7 -0
  7. data/lib/command/convert.rb +40 -61
  8. data/lib/command/download.rb +9 -1
  9. data/lib/command/mail.rb +24 -13
  10. data/lib/command/send.rb +18 -2
  11. data/lib/command/setting.rb +152 -34
  12. data/lib/command/tag.rb +5 -0
  13. data/lib/command/update.rb +137 -4
  14. data/lib/converterbase.rb +12 -6
  15. data/lib/database.rb +1 -1
  16. data/lib/device/ibooks.rb +6 -5
  17. data/lib/downloader.rb +85 -83
  18. data/lib/helper.rb +3 -2
  19. data/lib/html.rb +3 -0
  20. data/lib/logger.rb +20 -12
  21. data/lib/narou.rb +16 -0
  22. data/lib/novelconverter.rb +209 -75
  23. data/lib/novelinfo.rb +1 -1
  24. data/lib/novelsetting.rb +53 -29
  25. data/lib/template.rb +4 -3
  26. data/lib/version.rb +1 -1
  27. data/lib/web/appserver.rb +46 -32
  28. data/lib/web/public/resources/common.ui.js +2 -4
  29. data/lib/web/public/resources/default-style.css +37 -0
  30. data/lib/web/public/resources/narou.library.js +48 -57
  31. data/lib/web/public/resources/narou.ui.js +71 -39
  32. data/lib/web/public/theme/Cerulean/bootstrap.min.css +11 -0
  33. data/lib/web/public/theme/Cerulean/style.css +49 -0
  34. data/lib/web/public/theme/Darkly/bootstrap.min.css +11 -0
  35. data/lib/web/public/theme/Darkly/style.css +53 -0
  36. data/lib/web/public/theme/Readable/bootstrap.min.css +11 -0
  37. data/lib/web/public/theme/Readable/style.css +53 -0
  38. data/lib/web/public/theme/Slate/bootstrap.min.css +11 -0
  39. data/lib/web/public/theme/Slate/style.css +40 -0
  40. data/lib/web/public/theme/Superhero/bootstrap.min.css +11 -0
  41. data/lib/web/public/theme/Superhero/style.css +40 -0
  42. data/lib/web/public/theme/United/bootstrap.min.css +11 -0
  43. data/lib/web/public/theme/United/style.css +47 -0
  44. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.eot +0 -0
  45. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.svg +288 -0
  46. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.ttf +0 -0
  47. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.woff +0 -0
  48. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.woff2 +0 -0
  49. data/lib/web/settingmessages.rb +5 -0
  50. data/lib/web/views/index.haml +15 -19
  51. data/lib/web/views/layout.haml +6 -1
  52. data/lib/web/views/novels/setting.haml +76 -75
  53. data/lib/web/views/settings.haml +111 -107
  54. data/lib/web/views/style.scss +6 -21
  55. data/narou.gemspec +49 -6
  56. data/narou.rb +3 -1
  57. data/preset/ncode.syosetu.com/n7975cr/setting.ini +7 -0
  58. data/spec/README.txt +4 -0
  59. data/spec/data/convert_test/ruby/correct_test_ruby.txt +4 -4
  60. data/template/hotentry.txt.erb +28 -0
  61. data/template/ibunko_novel.txt.erb +4 -2
  62. data/template/novel.txt.erb +6 -3
  63. data/template/setting.ini.erb +18 -2
  64. metadata +73 -8
data/lib/novelinfo.rb CHANGED
@@ -37,7 +37,7 @@ class NovelInfo
37
37
  info_source = ""
38
38
  cookie = @setting["cookie"] || ""
39
39
  open(info_url, "Cookie" => cookie) do |fp|
40
- info_source = Helper.pretreatment_source(fp.read, @setting["encoding"])
40
+ info_source = Helper.restor_entity(Helper.pretreatment_source(fp.read, @setting["encoding"]))
41
41
  raise Downloader::DownloaderNotFoundError if Downloader.detect_error_message(@setting, info_source)
42
42
  end
43
43
  @setting.multi_match(info_source, *request_output_parameters)
data/lib/novelsetting.rb CHANGED
@@ -5,9 +5,11 @@
5
5
 
6
6
  require "fileutils"
7
7
  require_relative "ini"
8
+ require_relative "downloader"
8
9
 
9
10
  class NovelSetting
10
11
  INI_NAME = "setting.ini"
12
+ INI_ERB_BINARY_VERSION = 1.2
11
13
  REPLACE_NAME = "replace.txt"
12
14
 
13
15
  attr_accessor :id, :author, :title, :archive_path, :replace_pattern, :settings
@@ -123,14 +125,19 @@ class NovelSetting
123
125
  load_settings_by_pattern("default")
124
126
  end
125
127
 
128
+ def get_value_by_original(name)
129
+ index = ORIGINAL_SETTINGS_KEY_INDEXES[name]
130
+ index ? ORIGINAL_SETTINGS[index] : nil
131
+ end
132
+
126
133
  #
127
134
  # 設定を保存
128
135
  #
129
136
  def save_settings
130
- ini = Ini.new
131
- ini.filename = File.join(@archive_path, INI_NAME)
132
- ini.object["global"].merge!(@settings)
133
- ini.save
137
+ original_settings = NovelSetting.get_original_settings
138
+ default_settings = NovelSetting.load_default_settings
139
+ novel_setting = self
140
+ Template.write(INI_NAME, @archive_path, binding, INI_ERB_BINARY_VERSION, Template::OVERWRITE)
134
141
  end
135
142
 
136
143
  def type_eq_value(type, value)
@@ -147,10 +154,9 @@ class NovelSetting
147
154
  # 指定された設定の型チェック
148
155
  #
149
156
  def check_value_of_type(name, value)
150
- index = ORIGINAL_SETTINGS.index { |v| v[:name] == name }
151
- return unless index
152
- original = ORIGINAL_SETTINGS[index]
153
- if original && !type_eq_value(original[:type], value)
157
+ original = get_value_by_original(name)
158
+ return unless original
159
+ unless type_eq_value(original[:type], value)
154
160
  raise Helper::InvalidVariableType, original[:type]
155
161
  end
156
162
  end
@@ -207,22 +213,32 @@ class NovelSetting
207
213
  Narou.write_replace_txt(replace_txt_path, @replace_pattern)
208
214
  end
209
215
 
216
+ def self.get_original_settings
217
+ ORIGINAL_SETTINGS
218
+ end
219
+
210
220
  ORIGINAL_SETTINGS = [
211
221
  # name: 変数名
212
222
  # type: 変数の型
213
223
  # value: 初期値
214
224
  # help: 説明(setting.ini に書き出される)
225
+ {
226
+ name: "enable_inspect",
227
+ type: :boolean,
228
+ value: false,
229
+ help: "小説に対する各種調査を実行する。結果を表示するには narou inspect コマンドを使用"
230
+ },
215
231
  {
216
232
  name: "enable_convert_num_to_kanji",
217
233
  type: :boolean,
218
234
  value: true,
219
- help: "数字の漢数字変換を有効に"
235
+ help: "数字の漢数字変換を有効にする"
220
236
  },
221
237
  {
222
238
  name: "enable_kanji_num_with_units",
223
239
  type: :boolean,
224
240
  value: true,
225
- help: "漢数字変換した場合、千・万などに変換するか"
241
+ help: "漢数字変換した場合、千・万などに変換する"
226
242
  },
227
243
  {
228
244
  name: "kanji_num_with_units_lower_digit_zero",
@@ -246,25 +262,19 @@ class NovelSetting
246
262
  name: "enable_auto_indent",
247
263
  type: :boolean,
248
264
  value: true,
249
- help: "自動行頭字下げ機能。行頭字下げが行われているかを判断し、適切に行頭字下げをする"
265
+ help: "自動行頭字下げ機能。行頭字下げが行われているかを判断し、適切に行頭字下げをするか"
250
266
  },
251
267
  {
252
268
  name: "enable_force_indent",
253
269
  type: :boolean,
254
270
  value: false,
255
- help: "行頭字下げを必ず行う。enable_auto_indent の設定は無視される"
271
+ help: "行頭字下げを必ず行うか。enable_auto_indent の設定は無視される"
256
272
  },
257
273
  {
258
274
  name: "enable_auto_join_in_brackets",
259
275
  type: :boolean,
260
276
  value: true,
261
- help: "かぎ括弧内自動連結を有効に\n例)\n「~~~!\n ***?」 → 「~~~! ***?」"
262
- },
263
- {
264
- name: "enable_inspect_invalid_openclose_brackets",
265
- type: :boolean,
266
- value: false,
267
- help: "かぎ括弧内のとじ開きが正しくされているかどうか調査する"
277
+ help: "かぎ括弧内自動連結を有効にする\n例)\n「~~~!\n ***?」 → 「~~~! ***?」"
268
278
  },
269
279
  {
270
280
  name: "enable_auto_join_line",
@@ -282,25 +292,25 @@ class NovelSetting
282
292
  name: "enable_author_comments",
283
293
  type: :boolean,
284
294
  value: true,
285
- help: "作者コメントを検出するか(テキストファイルを直接変換する場合のみの設定)"
295
+ help: "作者コメントを検出する(テキストファイルを直接変換する場合のみの設定)"
286
296
  },
287
297
  {
288
298
  name: "enable_erase_introduction",
289
299
  type: :boolean,
290
300
  value: false,
291
- help: "前書きを削除するか"
301
+ help: "前書きを削除する"
292
302
  },
293
303
  {
294
304
  name: "enable_erase_postscript",
295
305
  type: :boolean,
296
306
  value: false,
297
- help: "後書きを削除するか"
307
+ help: "後書きを削除する"
298
308
  },
299
309
  {
300
310
  name: "enable_ruby",
301
311
  type: :boolean,
302
312
  value: true,
303
- help: "ルビ処理を有効に"
313
+ help: "ルビ処理を有効にする"
304
314
  },
305
315
  {
306
316
  name: "enable_illust",
@@ -348,19 +358,19 @@ class NovelSetting
348
358
  name: "enable_dakuten_font",
349
359
  type: :boolean,
350
360
  value: true,
351
- help: "濁点フォントを使用するか。false の場合は縦中横による擬似表現を使用する"
361
+ help: "濁点フォントを使用する。false の場合は縦中横による擬似表現を使用する"
352
362
  },
353
363
  {
354
364
  name: "enable_display_end_of_book",
355
365
  type: :boolean,
356
366
  value: true,
357
- help: "小説の最後に本を読み終わった表示をするかどうか"
367
+ help: "小説の最後に本を読み終わった表示をする"
358
368
  },
359
369
  {
360
370
  name: "enable_add_date_to_title",
361
371
  type: :boolean,
362
372
  value: false,
363
- help: "変換後の小説のタイトルに更新日の日付を付加するかどうか"
373
+ help: "変換後の小説のタイトルに最新話掲載日や更新日等の日付を付加する"
364
374
  },
365
375
  {
366
376
  name: "title_date_format",
@@ -376,23 +386,31 @@ class NovelSetting
376
386
  select_keys: %w(left right),
377
387
  select_summaries: %w(タイトルの前 タイトルの後)
378
388
  },
389
+ {
390
+ name: "title_date_target",
391
+ type: :select,
392
+ value: "general_lastup",
393
+ help: "enable_add_date_to_title で付与する日付の種類。\ngeneral_lastup(最新話掲載日),last_update(更新日),new_arrivals_date(新着を確認した日),convert(変換した日)",
394
+ select_keys: %w(general_lastup last_update new_arrivals_date convert),
395
+ select_summaries: %w(最新話掲載日 更新日 新着を確認した日 変換した日)
396
+ },
379
397
  {
380
398
  name: "enable_ruby_youon_to_big",
381
399
  type: :boolean,
382
400
  value: false,
383
- help: "ルビの拗音(ぁ、ぃ等)を商業書籍のように大きくするかどうか"
401
+ help: "ルビの拗音(ぁ、ぃ等)を商業書籍のように大きくする"
384
402
  },
385
403
  {
386
404
  name: "enable_pack_blank_line",
387
405
  type: :boolean,
388
406
  value: true,
389
- help: "縦書きで読みやすいように空行を減らすかどうか"
407
+ help: "縦書きで読みやすいように空行を減らす"
390
408
  },
391
409
  {
392
410
  name: "enable_kana_ni_to_kanji_ni",
393
411
  type: :boolean,
394
412
  value: true,
395
- help: "漢字の二と間違えてカタカナのニを使っていそうなのを、漢字に直すかどうか"
413
+ help: "漢字の二と間違えてカタカナのニを使っていそうなのを、漢字に直す"
396
414
  },
397
415
  {
398
416
  name: "enable_insert_word_separator",
@@ -407,4 +425,10 @@ class NovelSetting
407
425
  help: "文字選択がしやすいように1文字ずつ区切りデータを挿入する(Kindle専用。enable_insert_word_separator が有効な場合無この設定は無視される)"
408
426
  },
409
427
  ]
428
+
429
+ ORIGINAL_SETTINGS_KEY_INDEXES = {}.tap { |hash|
430
+ ORIGINAL_SETTINGS.each_with_index do |s, i|
431
+ hash[s[:name]] = i
432
+ end
433
+ }
410
434
  end
data/lib/template.rb CHANGED
@@ -8,6 +8,7 @@ require_relative "narou"
8
8
 
9
9
  class Template
10
10
  TEMPLATE_DIR = "template/"
11
+ OVERWRITE = true
11
12
 
12
13
  class LoadError < StandardError; end
13
14
 
@@ -55,7 +56,7 @@ class Template
55
56
  end
56
57
 
57
58
  def self.invalid_templace_version?
58
- @@src_version < @@binary_version
59
+ @@src_version != @@binary_version
59
60
  end
60
61
 
61
62
  #
@@ -67,8 +68,8 @@ class Template
67
68
  def self.target_binary_version(version)
68
69
  @@src_version = version
69
70
  if invalid_templace_version?
70
- error "テンプレートのバージョンが古いので意図しない動作をする可能性があります\n" +
71
- "(#{@@src_filename}.erb ver #{version.to_f} < #{@@binary_version.to_f})"
71
+ error "テンプレートのバージョンが異なるので意図しない動作をする可能性があります\n" +
72
+ "(#{@@src_filename}.erb ver #{version.to_f} != #{@@binary_version.to_f})"
72
73
  end
73
74
  end
74
75
  end
data/lib/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  # Copyright 2013 whiteleaf. All rights reserved.
4
4
  #
5
5
 
6
- Version = "2.5.2"
6
+ Version = "2.6.0"
7
7
 
data/lib/web/appserver.rb CHANGED
@@ -89,15 +89,15 @@ module Narou::ServerHelpers
89
89
  end
90
90
 
91
91
  #
92
- # 与えられたデータが真偽値だった場合、設定画面用に「する」「しない」に変換する
92
+ # 与えられたデータが真偽値だった場合、設定画面用に「はい」「いいえ」に変換する
93
93
  # 真偽値ではなかった場合、そのまま返す
94
94
  #
95
95
  def value_to_msg(value)
96
96
  case value
97
97
  when TrueClass
98
- "する"
98
+ "はい"
99
99
  when FalseClass
100
- "しない"
100
+ "いいえ"
101
101
  else
102
102
  value
103
103
  end
@@ -177,6 +177,14 @@ class Narou::AppServer < Sinatra::Base
177
177
  # ===================================================================
178
178
 
179
179
  before do
180
+ @bootstrap_theme = case params["theme"]
181
+ when nil
182
+ Narou.get_theme
183
+ when "" # 環境設定画面で未設定が選択された時
184
+ nil
185
+ else
186
+ params["theme"]
187
+ end
180
188
  Narou::Worker.push_as_system_worker do
181
189
  Inventory.clear
182
190
  Database.instance.refresh
@@ -200,7 +208,6 @@ class Narou::AppServer < Sinatra::Base
200
208
 
201
209
  before "/settings" do
202
210
  @title = "環境設定"
203
- @view_invisible = params["view_invisible"] == "1"
204
211
  @setting_variables = Command::Setting.get_setting_variables
205
212
  @error_list = {}
206
213
  @global_replace_pattern = @replace_pattern = Narou.global_replace_pattern
@@ -299,13 +306,13 @@ class Narou::AppServer < Sinatra::Base
299
306
  end
300
307
 
301
308
  before "/novels/:id/setting" do
302
- @title = "小説の変換設定"
303
309
  @novel_title = @data["title"]
310
+ @title = "小説の変換設定 - #{h @novel_title}"
304
311
  @setting_variables = []
305
312
  @error_list = {}
306
313
  @novel_setting = NovelSetting.new(@id, true, true) # 空っぽの設定を作成
307
314
  @novel_setting.settings = @novel_setting.load_setting_ini["global"]
308
- @original_settings = NovelSetting::ORIGINAL_SETTINGS
315
+ @original_settings = NovelSetting.get_original_settings
309
316
  @force_settings = NovelSetting.load_force_settings
310
317
  @default_settings = NovelSetting.load_default_settings
311
318
  @replace_pattern = @novel_setting.load_replace_pattern
@@ -420,10 +427,12 @@ class Narou::AppServer < Sinatra::Base
420
427
  end
421
428
 
422
429
  post "/api/download" do
423
- target = params["target"] or pass
430
+ targets = params["targets"] or pass
431
+ targets = targets.split
432
+ pass if targets.size == 0
424
433
  Narou::Worker.push do
425
- CommandLine.run!(["download", target])
426
- @@push_server.send_all("table.reload" => true)
434
+ CommandLine.run!(["download"] + targets)
435
+ @@push_server.send_all(:"table.reload")
427
436
  end
428
437
  end
429
438
 
@@ -431,33 +440,24 @@ class Narou::AppServer < Sinatra::Base
431
440
  ids = select_valid_novel_ids(params["ids"]) or pass
432
441
  Narou::Worker.push do
433
442
  CommandLine.run!(["download", "--force", ids])
434
- @@push_server.send_all("table.reload" => true)
443
+ @@push_server.send_all(:"table.reload")
435
444
  end
436
445
  end
437
446
 
438
447
  post "/api/update" do
439
- Narou::Worker.push do
440
- CommandLine.run!(["update"])
441
- @@push_server.send_all("table.reload" => true)
448
+ ids = select_valid_novel_ids(params["ids"]) || []
449
+ opt_arguments = []
450
+ if params["force"] == "true"
451
+ opt_arguments << "--force"
442
452
  end
443
- end
444
-
445
- post "/api/update_select" do
446
- ids = select_valid_novel_ids(params["ids"]) or pass
447
453
  Narou::Worker.push do
448
- CommandLine.run!(["update", ids])
449
- @@push_server.send_all("table.reload" => true)
454
+ CommandLine.run!(["update", ids, opt_arguments])
455
+ @@push_server.send_all(:"table.reload")
450
456
  end
451
457
  end
452
458
 
453
459
  post "/api/send" do
454
- Narou::Worker.push do
455
- CommandLine.run!(["send"])
456
- end
457
- end
458
-
459
- post "/api/send_select" do
460
- ids = select_valid_novel_ids(params["ids"]) or pass
460
+ ids = select_valid_novel_ids(params["ids"]) || []
461
461
  Narou::Worker.push do
462
462
  CommandLine.run!(["send", ids])
463
463
  end
@@ -467,7 +467,7 @@ class Narou::AppServer < Sinatra::Base
467
467
  ids = select_valid_novel_ids(params["ids"]) or pass
468
468
  Narou::Worker.push do
469
469
  CommandLine.run!(["freeze", ids])
470
- @@push_server.send_all("table.reload" => true)
470
+ @@push_server.send_all(:"table.reload")
471
471
  end
472
472
  end
473
473
 
@@ -475,7 +475,7 @@ class Narou::AppServer < Sinatra::Base
475
475
  ids = select_valid_novel_ids(params["ids"]) or pass
476
476
  Narou::Worker.push do
477
477
  CommandLine.run!(["freeze", "--on", ids])
478
- @@push_server.send_all("table.reload" => true)
478
+ @@push_server.send_all(:"table.reload")
479
479
  end
480
480
  end
481
481
 
@@ -483,15 +483,19 @@ class Narou::AppServer < Sinatra::Base
483
483
  ids = select_valid_novel_ids(params["ids"]) or pass
484
484
  Narou::Worker.push do
485
485
  CommandLine.run!(["freeze", "--off", ids])
486
- @@push_server.send_all("table.reload" => true)
486
+ @@push_server.send_all(:"table.reload")
487
487
  end
488
488
  end
489
489
 
490
490
  post "/api/remove" do
491
491
  ids = select_valid_novel_ids(params["ids"]) or pass
492
+ opt_arguments = []
493
+ if params["with_file"] == "true"
494
+ opt_arguments << "--with-file"
495
+ end
492
496
  Narou::Worker.push do
493
- CommandLine.run!(["remove", "--yes", ids])
494
- @@push_server.send_all("table.reload" => true)
497
+ CommandLine.run!(["remove", "--yes", ids, opt_arguments])
498
+ @@push_server.send_all(:"table.reload")
495
499
  end
496
500
  end
497
501
 
@@ -499,7 +503,7 @@ class Narou::AppServer < Sinatra::Base
499
503
  ids = select_valid_novel_ids(params["ids"]) or pass
500
504
  Narou::Worker.push do
501
505
  CommandLine.run!(["remove", "--yes", "--with-file", ids])
502
- @@push_server.send_all("table.reload" => true)
506
+ @@push_server.send_all(:"table.reload")
503
507
  end
504
508
  end
505
509
 
@@ -611,6 +615,16 @@ class Narou::AppServer < Sinatra::Base
611
615
  end
612
616
  end
613
617
 
618
+ post "/api/setting_burn" do
619
+ ids = select_valid_novel_ids(params["ids"]) or pass
620
+ Narou::Worker.push do
621
+ CommandLine.run!(["setting", "--burn", ids])
622
+ end
623
+ end
624
+
625
+ # -------------------------------------------------------------------------------
626
+ # ウィジット関係
627
+ # -------------------------------------------------------------------------------
614
628
 
615
629
  get "/js/widget.js" do
616
630
  if %w(download).include?(params["mode"])
@@ -49,12 +49,10 @@ $(document).ready(function() {
49
49
  var diff = data - before_size;
50
50
  if (diff <= 0) return;
51
51
  var $plus = $("<span>+" + diff + "</span>");
52
- $plus.css({
52
+ $plus.addClass("queue-plus").css({
53
53
  position: "absolute",
54
54
  left: $queue.offset().left + $queue.outerWidth() + 1 - $(document).scrollLeft(),
55
55
  top: $queue.offset().top - 3 - $(document).scrollTop(),
56
- color: "#5cb85c",
57
- "font-weight": "bold",
58
56
  });
59
57
  $(".navbar").append($plus);
60
58
  $plus.delay(100).animate({
@@ -97,7 +95,7 @@ $(document).ready(function() {
97
95
  // キャンセル、OK を確認する confirm モーダル表示
98
96
  notification.on("modal.confirm", function(json) {
99
97
  var id = json.id;
100
- boxes[id] = bootbox.confirm(json.message, function(result) {
98
+ boxes[id] = bootbox.confirm(json.message.replace(/\n/g, "<br>"), function(result) {
101
99
  answer(id, result);
102
100
  });
103
101
  });