narou 3.2.5.1 → 3.3.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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -5
  3. data/.haml-lint.yml +7 -0
  4. data/.rubocop.yml +23 -5
  5. data/.scss-lint.yml +9 -0
  6. data/ChangeLog.md +86 -0
  7. data/Gemfile.lock +35 -35
  8. data/README.md +80 -64
  9. data/lib/backtracer.rb +2 -2
  10. data/lib/color.rb +5 -1
  11. data/lib/command.rb +7 -2
  12. data/lib/command/alias.rb +3 -5
  13. data/lib/command/backup.rb +3 -5
  14. data/lib/command/browser.rb +3 -5
  15. data/lib/command/clean.rb +5 -1
  16. data/lib/command/console.rb +33 -0
  17. data/lib/command/convert.rb +143 -117
  18. data/lib/command/csv.rb +2 -1
  19. data/lib/command/diff.rb +20 -18
  20. data/lib/command/download.rb +25 -14
  21. data/lib/command/folder.rb +3 -5
  22. data/lib/command/freeze.rb +3 -5
  23. data/lib/command/help.rb +20 -18
  24. data/lib/command/init.rb +4 -3
  25. data/lib/command/inspect.rb +2 -1
  26. data/lib/command/list.rb +10 -8
  27. data/lib/command/list/novel_decorator.rb +2 -1
  28. data/lib/command/log.rb +100 -0
  29. data/lib/command/log/tail.rb +76 -0
  30. data/lib/command/mail.rb +20 -17
  31. data/lib/command/remove.rb +7 -6
  32. data/lib/command/send.rb +23 -20
  33. data/lib/command/setting.rb +74 -40
  34. data/lib/command/tag.rb +16 -15
  35. data/lib/command/trace.rb +2 -2
  36. data/lib/command/update.rb +78 -128
  37. data/lib/command/update/general_lastup_updater.rb +3 -2
  38. data/lib/command/update/hotentry_manager.rb +2 -1
  39. data/lib/command/update/interval.rb +2 -1
  40. data/lib/command/version.rb +2 -1
  41. data/lib/command/web.rb +17 -3
  42. data/lib/commandbase.rb +34 -7
  43. data/lib/commandline.rb +54 -35
  44. data/lib/converterbase.rb +21 -15
  45. data/lib/database.rb +3 -2
  46. data/lib/device.rb +5 -4
  47. data/lib/device/epub.rb +2 -1
  48. data/lib/device/ibooks.rb +2 -1
  49. data/lib/device/ibunko.rb +2 -1
  50. data/lib/device/kindle.rb +2 -1
  51. data/lib/device/kobo.rb +2 -1
  52. data/lib/device/library/cygwin.rb +2 -1
  53. data/lib/device/library/linux.rb +2 -1
  54. data/lib/device/library/mac.rb +2 -1
  55. data/lib/device/library/windows.rb +2 -1
  56. data/lib/device/library/windows/eject.rb +2 -1
  57. data/lib/device/reader.rb +2 -1
  58. data/lib/diffviewer.rb +8 -11
  59. data/lib/downloader.rb +159 -151
  60. data/lib/eventable.rb +2 -1
  61. data/lib/extension.rb +16 -14
  62. data/lib/extensions/jruby.rb +2 -1
  63. data/lib/extensions/monkey_patches.rb +7 -0
  64. data/lib/extensions/monkey_patches/pathname.rb +22 -0
  65. data/lib/extensions/windows.rb +2 -1
  66. data/lib/extensions/windows_write_color.rb +2 -1
  67. data/lib/helper.rb +35 -20
  68. data/lib/html.rb +2 -1
  69. data/lib/illustration.rb +2 -1
  70. data/lib/ini.rb +2 -1
  71. data/lib/input.rb +2 -1
  72. data/lib/inspector.rb +3 -2
  73. data/lib/inventory.rb +3 -3
  74. data/lib/mailer.rb +3 -2
  75. data/lib/mixin/all.rb +8 -0
  76. data/lib/mixin/locker.rb +40 -0
  77. data/lib/mixin/output_error.rb +28 -0
  78. data/lib/narou.rb +69 -51
  79. data/lib/narou/api.rb +2 -4
  80. data/lib/narou_logger.rb +236 -108
  81. data/lib/novelconverter.rb +77 -69
  82. data/lib/novelinfo.rb +4 -2
  83. data/lib/novelsetting.rb +15 -12
  84. data/lib/progressbar.rb +13 -9
  85. data/lib/sitesetting.rb +39 -18
  86. data/lib/template.rb +5 -4
  87. data/lib/version.rb +3 -2
  88. data/lib/web/all.rb +2 -1
  89. data/lib/web/appserver.rb +83 -65
  90. data/lib/web/helper4web.rb +10 -5
  91. data/lib/web/progressbar4web.rb +8 -4
  92. data/lib/web/public/resources/default-style.css +2 -3
  93. data/lib/web/public/resources/narou.library.js +86 -60
  94. data/lib/web/public/resources/narou.queue.js +24 -30
  95. data/lib/web/public/resources/narou.ui.js +22 -3
  96. data/lib/web/public/theme/Cerulean/style.css +5 -5
  97. data/lib/web/public/theme/Darkly/style.css +5 -5
  98. data/lib/web/public/theme/Readable/style.css +5 -5
  99. data/lib/web/public/theme/Slate/style.css +2 -3
  100. data/lib/web/public/theme/Superhero/style.css +2 -3
  101. data/lib/web/public/theme/United/style.css +5 -5
  102. data/lib/web/pushserver.rb +10 -7
  103. data/lib/web/server_helpers.rb +16 -1
  104. data/lib/web/settingmessages.rb +10 -7
  105. data/lib/web/streaminginput.rb +2 -1
  106. data/lib/web/streaminglogger.rb +45 -32
  107. data/lib/web/views/_about.haml +6 -3
  108. data/lib/web/views/_header.haml +2 -3
  109. data/lib/web/views/_move_to_top.haml +2 -0
  110. data/lib/web/views/_queue.haml +7 -0
  111. data/lib/web/views/bookmarklet/insert_button.js.erb +1 -1
  112. data/lib/web/views/index.haml +30 -27
  113. data/lib/web/views/layout.haml +2 -0
  114. data/lib/web/views/novels/setting.haml +3 -4
  115. data/lib/web/views/settings.haml +22 -8
  116. data/lib/web/views/style.scss +54 -3
  117. data/lib/web/views/widget/download.haml +9 -3
  118. data/lib/web/views/widget/drag_and_drop.haml +10 -4
  119. data/lib/web/web_worker.rb +132 -0
  120. data/lib/worker.rb +142 -0
  121. data/narou.gemspec +80 -45
  122. data/narou.rb +6 -4
  123. data/template/novel.txt.erb +1 -0
  124. data/webnovel/kakuyomu.jp.yaml +9 -13
  125. data/webnovel/ncode.syosetu.com.yaml +3 -1
  126. data/webnovel/novel18.syosetu.com.yaml +8 -1
  127. data/webnovel/syosetu.org.yaml +3 -1
  128. data/webnovel/www.akatsuki-novels.com.yaml +4 -2
  129. data/webnovel/www.mai-net.net.yaml +3 -1
  130. metadata +109 -48
  131. data/lib/web/worker.rb +0 -126
@@ -30,6 +30,7 @@
30
30
  var local_initialize_functions = [];
31
31
  var slideNavbar;
32
32
  %body
33
+ = embed_concurrency_enabled
33
34
  - if session[:alert]
34
35
  - message, type = session[:alert]
35
36
  - session[:alert] = nil
@@ -37,6 +38,7 @@
37
38
  .fadeout-alert.alert(class="alert-#{type}")
38
39
  &= message
39
40
  != yield
41
+ = partial :move_to_top
40
42
  %script{:src => "//code.jquery.com/jquery-1.11.1.min.js"}
41
43
  %script{:src => "//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"}
42
44
  %script{:src => "//cdn.datatables.net/1.10.10/js/jquery.dataTables.min.js"}
@@ -2,7 +2,8 @@
2
2
  :javascript
3
3
  local_initialize_functions.push(function($) {
4
4
  var stream_console = new Narou.Console({
5
- restore: false, buttons: false
5
+ restore: false, buttons: false,
6
+ stream_id: Narou.concurrencyIsEnabled() ? "stdout2" : "stdout"
6
7
  });
7
8
  var action = new Narou.Action(null);
8
9
  var storage = new Narou.Storage;
@@ -66,9 +67,7 @@
66
67
  %input.btn.btn-info(type="submit" value="設定を保存" style="margin-left: 50px")
67
68
  %button#btn-convert.btn.btn-default この小説を変換
68
69
  %button#btn-folder.btn.btn-default フォルダを開く
69
- %p#queue-text.navbar-text.navbar-right(data-toggle="tooltip" title="キューに積まれた処理の数" data-placement="bottom")
70
- %span.glyphicon.glyphicon-inbox
71
- %span#queue 0
70
+ = partial :queue
72
71
 
73
72
  .container.container-main.theme-showcase(role="main")
74
73
  %p.visible-xs-inline
@@ -1,6 +1,10 @@
1
1
  -# このページ内専用のjavascriptでjQueryオブジェクトを参照したい場合この関数に記述
2
2
  :javascript
3
3
  local_initialize_functions.push(function($) {
4
+ var storage = new Narou.Storage;
5
+ var action = new Narou.Action(null);
6
+ var notification = Narou.Notification.instance();
7
+
4
8
  $("[data-toggle=tooltip]").tooltip({
5
9
  animation: false,
6
10
  container: "body",
@@ -11,7 +15,6 @@
11
15
  width: "100%"
12
16
  });
13
17
 
14
- var storage = new Narou.Storage;
15
18
  // 直前に開いていたタブを復元
16
19
  var related_active_tab = storage.get("related_active_tab");
17
20
  if (related_active_tab) {
@@ -23,10 +26,18 @@
23
26
  storage.set("related_active_tab", active_tab);
24
27
  storage.save();
25
28
  })
29
+
30
+ notification.on("server.rebooted", function() {
31
+ location.href = "/";
32
+ });
33
+
34
+ $("#btn-reboot").on("click", function(e) {
35
+ e.preventDefault();
36
+ action.rebootDialog();
37
+ });
26
38
  });
27
39
 
28
40
  :ruby
29
- Inventory.clear
30
41
  inventory = Inventory.load("local_setting").merge(Inventory.load("global_setting", :global))
31
42
  local_and_global_variables = @setting_variables[:local].merge(@setting_variables[:global])
32
43
  tab_info = Command::Setting.get_setting_tab_info
@@ -68,12 +79,15 @@
68
79
  = tab_info[key]
69
80
  .list-group
70
81
  - local_and_global_variables.each do |name, value|
71
- - next if value[:tab] != key
72
- - item = inventory[name]
73
- - need_clear = false
74
- - message = Narou::SETTING_VARIABLES_WEBUI_MESSAGES[name] || value[:help]
75
- - message = message.strip.gsub("\n", "<br>")
76
- - error_style = {class: "has-error", style: "background-color:#f2dede"}
82
+ :ruby
83
+ next if value[:tab] != key
84
+ item = inventory[name]
85
+ need_clear = false
86
+ msg_for_web = Narou::SETTING_VARIABLES_WEBUI_MESSAGES[name]
87
+ message = msg_for_web || value[:help]
88
+ message = message.gsub("%%ORIG%%", value[:help]) if msg_for_web
89
+ message = message.strip.gsub("\n", "<br>")
90
+ error_style = { class: "has-error", style: "background-color: #f2dede" }
77
91
  .list-group-item.form-group{@error_list[name] ? error_style : {}}
78
92
  %h4.list-group-item-heading #{name}
79
93
  .list-group-item-text
@@ -691,6 +691,11 @@ $console-color: white;
691
691
  margin-bottom: 7px;
692
692
  }
693
693
  }
694
+
695
+ #console-stdout2 .progress {
696
+ width: 100%;
697
+ }
698
+
694
699
  .console-buttons {
695
700
  position: absolute;
696
701
  top: 3px;
@@ -698,11 +703,19 @@ $console-color: white;
698
703
  color: $console-color;
699
704
  cursor: pointer;
700
705
 
706
+ text-shadow: 1px 1px 2px #000, -1px 1px 2px #000, 1px -1px 2px #000, -1px -1px 2px #000;
707
+
701
708
  span:hover {
702
709
  color: mix($console-color, red, 80%);
703
710
  }
704
711
  }
705
712
 
713
+ .console-col-left,
714
+ .console-col-right {
715
+ padding-left: 1px;
716
+ padding-right: 1px;
717
+ }
718
+
706
719
  /*
707
720
  * ツールチップ
708
721
  */
@@ -723,7 +736,7 @@ $console-color: white;
723
736
  left: auto;
724
737
  }
725
738
  /* Freifox で表示が崩れる対策 */
726
- ul.dropdown-menu {
739
+ .navbar-nav ul.dropdown-menu {
727
740
  min-width: 260px;
728
741
 
729
742
  & > li {
@@ -836,12 +849,13 @@ $console-color: white;
836
849
  /*
837
850
  * キュー
838
851
  */
839
- #queue-text {
852
+ .queue {
840
853
  position: relative;
841
854
  margin-right: 0;
842
855
  cursor: default;
843
856
  }
844
- #queue {
857
+
858
+ .queue__sizes {
845
859
  position: relative;
846
860
  font-size: 0.8em;
847
861
  vertical-align: top;
@@ -858,6 +872,26 @@ $console-color: white;
858
872
  top: -3px;
859
873
  }
860
874
 
875
+ .queue__size {
876
+ }
877
+
878
+ .queue__size--default {
879
+ }
880
+
881
+ .queue__size--divider {
882
+ padding-right: 1px;
883
+ padding-left: 1px;
884
+ position: relative;
885
+ top: -1px;
886
+
887
+ &::before {
888
+ content: ':';
889
+ }
890
+ }
891
+
892
+ .queue__size--convert {
893
+ }
894
+
861
895
  /*
862
896
  * ヘルプ画面
863
897
  */
@@ -1157,3 +1191,20 @@ $console-color: white;
1157
1191
  .popover {
1158
1192
  max-width: 50%;
1159
1193
  }
1194
+
1195
+ .move-to-top {
1196
+ position: fixed;
1197
+ right: 6px;
1198
+ bottom: 6px;
1199
+ width: 40px;
1200
+ height: 40px;
1201
+ background-color: black;
1202
+ border-radius: 5px;
1203
+ font-size: 26px;
1204
+ color: white;
1205
+ padding-top: 4px;
1206
+ padding-left: 6px;
1207
+ cursor: pointer;
1208
+ @include opacity(0.3);
1209
+ z-index: 1040;
1210
+ }
@@ -22,7 +22,7 @@
22
22
  margin: 0;
23
23
  padding: 0;
24
24
  }
25
- #queue-text {
25
+ .queue {
26
26
  position: absolute;
27
27
  top: 3px;
28
28
  right: 3px;
@@ -31,10 +31,16 @@
31
31
  padding: 0;
32
32
  }
33
33
 
34
+ = embed_concurrency_enabled
35
+
34
36
  #console.console.fullscreen
35
- #queue-text.navbar-text.navbar-right
37
+ .queue.navbar-text.navbar-right
36
38
  %span.glyphicon.glyphicon-inbox
37
- %span#queue 0
39
+ %span.queue__sizes
40
+ %span.queue__size.queue__size--default> 0
41
+ - if Narou.concurrency_enabled?
42
+ %span.queue__size.queue__size--divider
43
+ %span.queue__size.queue__size--convert> 0
38
44
 
39
45
  %script{:src => "//code.jquery.com/jquery-1.11.1.min.js"}
40
46
  %script{:src => "//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"}
@@ -36,7 +36,7 @@
36
36
  opacity: 0.17;
37
37
  filter: alpha(opacity=17);
38
38
  }
39
- #queue-text {
39
+ .queue {
40
40
  position: absolute;
41
41
  top: 3px;
42
42
  right: 3px;
@@ -45,13 +45,20 @@
45
45
  padding: 0;
46
46
  }
47
47
 
48
+ = embed_concurrency_enabled
49
+
48
50
  #console.console.fullscreen
49
51
  #information
50
52
  このウィンドウ内にダウンロードしたい<br>
51
53
  小説のリンクをドラッグ&ドロップ
52
- #queue-text.navbar-text.navbar-right
54
+ .queue.navbar-text.navbar-right
53
55
  %span.glyphicon.glyphicon-inbox
54
- %span#queue 0
56
+ %span.queue__sizes
57
+ %span.queue__size.queue__size--default> 0
58
+ - if Narou.concurrency_enabled?
59
+ %span.queue__size.queue__size--divider
60
+ %span.queue__size.queue__size--convert> 0
61
+
55
62
  #link-drop-here
56
63
  .inner
57
64
  .glyphicon.glyphicon-download-alt
@@ -95,4 +102,3 @@
95
102
  $("#link-drop-here").hide();
96
103
  });
97
104
  });
98
-
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2013 whiteleaf. All rights reserved.
5
+ #
6
+
7
+ require "singleton"
8
+ require_relative "pushserver"
9
+ require_relative "../mixin/all"
10
+
11
+ module Narou
12
+ class WebWorker
13
+ include Singleton
14
+ include Mixin::OutputError
15
+
16
+ attr_reader :size
17
+
18
+ def self.run
19
+ instance.start
20
+ end
21
+
22
+ def initialize
23
+ @queue = Queue.new
24
+ @size = 0
25
+ @mutex = Mutex.new
26
+ @worker_thread = nil
27
+ @push_server = Narou::PushServer.instance
28
+ @cancel_signal = false
29
+ @thread_of_block_executing = nil
30
+ end
31
+
32
+ def running?
33
+ !@worker_thread.!
34
+ end
35
+
36
+ def start
37
+ return if running?
38
+ @worker_thread = Thread.new do
39
+ loop do
40
+ begin
41
+ q = @queue.pop
42
+ if canceled?
43
+ @queue.clear
44
+ @cancel_signal = false
45
+ else
46
+ @thread_of_block_executing = Thread.new do
47
+ q[:block].call
48
+ end
49
+ @thread_of_block_executing.join
50
+ @thread_of_block_executing = nil
51
+ end
52
+ rescue SystemExit
53
+ rescue Exception => e
54
+ # WebWorkerスレッド内での例外は表示するだけしてスレッドは生かしたままにする
55
+ output_error($stdout, e)
56
+ ensure
57
+ if q && q[:counting]
58
+ countdown
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def self.cancel
66
+ instance.cancel
67
+ end
68
+
69
+ def cancel
70
+ @mutex.synchronize do
71
+ if @size > 0
72
+ @cancel_signal = true
73
+ @size = 0
74
+ @thread_of_block_executing&.raise(Interrupt)
75
+ end
76
+ end
77
+ Thread.pass
78
+ end
79
+
80
+ def self.canceled?
81
+ instance.canceled?
82
+ end
83
+
84
+ def canceled?
85
+ @cancel_signal
86
+ end
87
+
88
+ def self.stop
89
+ instance.stop
90
+ end
91
+
92
+ def stop
93
+ @worker_thread&.kill
94
+ @worker_thread = nil
95
+ end
96
+
97
+ #
98
+ # システム用のワーカー追加。内部カウントは増やさない
99
+ #
100
+ def self.push_as_system_worker(&block)
101
+ instance.push(false, &block)
102
+ end
103
+
104
+ def self.push(&block)
105
+ instance.push(&block)
106
+ end
107
+
108
+ def push(counting = true, &block)
109
+ countup if counting
110
+ @queue.push(block: block, counting: counting)
111
+ end
112
+
113
+ def notification_queue
114
+ @push_server.send_all("notification.queue" => [@size, Narou::Worker.size])
115
+ end
116
+
117
+ def countup
118
+ @mutex.synchronize do
119
+ @size += 1
120
+ notification_queue
121
+ end
122
+ end
123
+
124
+ def countdown
125
+ @mutex.synchronize do
126
+ @size -= 1
127
+ @size = 0 if @size < 0
128
+ notification_queue
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2013 whiteleaf. All rights reserved.
5
+ #
6
+
7
+ require "singleton"
8
+ require_relative "mixin/all"
9
+
10
+ module Narou
11
+ class Worker
12
+ include Singleton
13
+ include Mixin::OutputError
14
+
15
+ attr_accessor :queue, :mutex, :size, :worker_thread, :cancel_signal, :thread_of_block_executing,
16
+ :push_server
17
+
18
+ class << self
19
+ extend Forwardable
20
+
21
+ def_delegators :instance, :push_server=, :join, :cancel, :canceled?, :stop, :push, :size
22
+
23
+ def run
24
+ instance.start
25
+ end
26
+ end
27
+
28
+ def initialize
29
+ self.queue = Queue.new
30
+ self.mutex = Mutex.new
31
+ self.size = 0
32
+ self.worker_thread = nil
33
+ self.cancel_signal = false
34
+ self.thread_of_block_executing = nil
35
+ end
36
+
37
+ def running?
38
+ worker_thread.present?
39
+ end
40
+
41
+ def start
42
+ return if running?
43
+ self.worker_thread = Thread.new do
44
+ loop do
45
+ begin
46
+ q = queue.pop
47
+ self.cancel_signal = false
48
+ self.thread_of_block_executing = Thread.new do
49
+ q[:block].call
50
+ end
51
+ thread_of_block_executing.join
52
+ self.thread_of_block_executing = nil
53
+ rescue SystemExit
54
+ rescue Interrupt
55
+ thread_of_block_executing&.raise(Interrupt)
56
+ self.thread_of_block_executing = nil
57
+ sleep 0.1
58
+ rescue Exception => e
59
+ output_error($stdout2, e)
60
+ ensure
61
+ countdown
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def join
68
+ until size.zero?
69
+ unless thread_of_block_executing
70
+ Thread.pass
71
+ next
72
+ end
73
+ thread_of_block_executing&.join
74
+ end
75
+ rescue Interrupt
76
+ thread_of_block_executing&.raise(Interrupt)
77
+ self.thread_of_block_executing = nil
78
+ sleep 0.1
79
+ end
80
+
81
+ def cancel
82
+ mutex.synchronize do
83
+ if size > 0
84
+ self.cancel_signal = true
85
+ self.size = 0
86
+ thread_of_block_executing&.raise(Interrupt)
87
+ self.thread_of_block_executing = nil
88
+ queue.clear
89
+ end
90
+ end
91
+ Thread.pass
92
+ end
93
+
94
+ def canceled?
95
+ cancel_signal
96
+ end
97
+
98
+ def stop
99
+ cancel
100
+ worker_thread&.kill
101
+ self.worker_thread = nil
102
+ end
103
+
104
+ def push(&block)
105
+ countup
106
+ queue.push(block: block)
107
+ end
108
+
109
+ def notification_queue
110
+ push_server&.send_all("notification.queue" => [Narou::WebWorker.instance.size, size])
111
+ end
112
+
113
+ def countup
114
+ mutex.synchronize do
115
+ self.size += 1
116
+ notification_queue
117
+ end
118
+ end
119
+
120
+ def countdown
121
+ mutex.synchronize do
122
+ self.size -= 1
123
+ self.size = 0 if size < 0
124
+ notification_queue
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ if Narou.concurrency_enabled?
131
+ Thread.abort_on_exception = true
132
+ Narou::Worker.run
133
+
134
+ at_exit do
135
+ next if Narou.web?
136
+ # ここまでたどり着いた時点でダウンロードとかは終わってるので変換ログを普通に表示する
137
+ $stdout2.silent = false
138
+ Narou::Worker.join
139
+ Narou::Worker.stop
140
+ Command::Convert.display_sending_error_list
141
+ end
142
+ end