narou 2.0.2 → 2.1.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/ChangeLog.md +45 -1
- data/README.md +45 -7
- data/lib/command.rb +0 -1
- data/lib/command/convert.rb +49 -7
- data/lib/command/list.rb +2 -5
- data/lib/command/send.rb +49 -6
- data/lib/command/setting.rb +9 -4
- data/lib/command/update.rb +89 -32
- data/lib/converterbase.rb +2 -1
- data/lib/device.rb +16 -2
- data/lib/device/epub.rb +20 -0
- data/lib/device/ibooks.rb +0 -4
- data/lib/device/kindle.rb +20 -0
- data/lib/device/reader.rb +3 -8
- data/lib/helper.rb +19 -0
- data/lib/logger.rb +21 -4
- data/lib/narou.rb +29 -25
- data/lib/novelconverter.rb +1 -3
- data/lib/novelsetting.rb +6 -0
- data/lib/version.rb +1 -1
- data/lib/web/appserver.rb +1 -1
- data/lib/web/helper4web.rb +11 -1
- data/lib/web/public/resources/narou.library.js +15 -8
- data/lib/web/settingmessages.rb +1 -0
- data/lib/web/streaminglogger.rb +16 -0
- data/lib/web/views/help.haml +18 -3
- data/lib/web/views/js/widget.erb +5 -1
- data/narou.gemspec +46 -0
- data/narou.rb +10 -1
- data/spec/logger_spec.rb +35 -1
- metadata +62 -3
- data/lib/command/flag.rb +0 -109
data/lib/converterbase.rb
CHANGED
@@ -575,10 +575,11 @@ class ConverterBase
|
|
575
575
|
#
|
576
576
|
# 必ず下げなければいけないところは強制的に字下げ
|
577
577
|
# 他の部分は全体的に判断して字下げ
|
578
|
+
# enable_force_indent が有効なら強制字下げ
|
578
579
|
#
|
579
580
|
def auto_indent(data)
|
580
581
|
data.gsub!(FULL_INDENT_TARGET, " \\1")
|
581
|
-
if @setting.enable_auto_indent && @inspector.inspect_indent(data)
|
582
|
+
if @setting.enable_force_indent || (@setting.enable_auto_indent && @inspector.inspect_indent(data))
|
582
583
|
data.gsub!(/^([^#{AUTO_INDENT_IGNORE_INDENT_CHAR}])/) do
|
583
584
|
# 行頭に三点リーダーの代わりに連続中黒(・・・)が来た場合の対策
|
584
585
|
# https://github.com/whiteleaf7/narou/issues/35
|
data/lib/device.rb
CHANGED
@@ -4,10 +4,24 @@
|
|
4
4
|
#
|
5
5
|
|
6
6
|
require "fileutils"
|
7
|
+
require "memoist"
|
7
8
|
require_relative "narou"
|
8
9
|
require_relative "helper"
|
9
10
|
|
10
11
|
class Device
|
12
|
+
#
|
13
|
+
# デバイスの栞をバックアップするときに使う時に include する
|
14
|
+
#
|
15
|
+
module BackupBookmarkUtility
|
16
|
+
extend Memoist
|
17
|
+
|
18
|
+
# 栞データを管理するディレクトリのパスを取得
|
19
|
+
def get_storage_path
|
20
|
+
File.join(Narou.get_misc_dir, "bookmark", @name)
|
21
|
+
end
|
22
|
+
memoize :get_storage_path
|
23
|
+
end
|
24
|
+
|
11
25
|
case Helper.determine_os
|
12
26
|
when :windows
|
13
27
|
require_relative "device/library/windows"
|
@@ -45,6 +59,7 @@ class Device
|
|
45
59
|
|
46
60
|
class UnknownDevice < StandardError; end
|
47
61
|
class SendFailure < StandardError; end
|
62
|
+
class DontConneting < StandardError; end
|
48
63
|
|
49
64
|
def self.exists?(device)
|
50
65
|
DEVICES.include?(device.downcase)
|
@@ -149,8 +164,6 @@ class Device
|
|
149
164
|
end
|
150
165
|
end
|
151
166
|
|
152
|
-
private
|
153
|
-
|
154
167
|
def create_device_check_methods
|
155
168
|
DEVICES.keys.each do |name|
|
156
169
|
instance_eval <<-EOS
|
@@ -160,4 +173,5 @@ class Device
|
|
160
173
|
EOS
|
161
174
|
end
|
162
175
|
end
|
176
|
+
private :create_device_check_methods
|
163
177
|
end
|
data/lib/device/epub.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright 2013 whiteleaf. All rights reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
#
|
7
|
+
# multi-device で単純なEPUB変換をしたい場合用
|
8
|
+
#
|
9
|
+
module Device::Epub
|
10
|
+
PHYSICAL_SUPPORT = false
|
11
|
+
VOLUME_NAME = nil
|
12
|
+
DOCUMENTS_PATH_LIST = nil
|
13
|
+
EBOOK_FILE_EXT = ".epub"
|
14
|
+
NAME = "EPUB"
|
15
|
+
DISPLAY_NAME = "EPUB"
|
16
|
+
|
17
|
+
RELATED_VARIABLES = {
|
18
|
+
"force.enable_half_indent_bracket" => false,
|
19
|
+
}
|
20
|
+
end
|
data/lib/device/ibooks.rb
CHANGED
@@ -15,15 +15,11 @@ module Device::Ibooks
|
|
15
15
|
|
16
16
|
RELATED_VARIABLES = {
|
17
17
|
"force.enable_half_indent_bracket" => false,
|
18
|
-
"force.enable_add_date_to_title" => false, # タイトルを変えてもiBooksに反映されないため
|
19
18
|
}
|
20
19
|
|
21
20
|
def hook_change_settings(&original_func)
|
22
21
|
@@__already_exec_change_settings ||= false
|
23
22
|
return if @@__already_exec_change_settings
|
24
|
-
force_change_settings_function({
|
25
|
-
"force.enable_half_indent_bracket" => false,
|
26
|
-
})
|
27
23
|
@@__ibooks_container_dir = File.expand_path(IBOOKS_CONTAINER_DIR)
|
28
24
|
unless File.exist?(@@__ibooks_container_dir)
|
29
25
|
error "iBooksの管理フォルダが見つかりませんでした。" \
|
data/lib/device/kindle.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
# Copyright 2013 whiteleaf. All rights reserved.
|
4
4
|
#
|
5
5
|
|
6
|
+
require "fileutils"
|
7
|
+
|
6
8
|
module Device::Kindle
|
7
9
|
PHYSICAL_SUPPORT = true
|
8
10
|
VOLUME_NAME = "Kindle"
|
@@ -14,4 +16,22 @@ module Device::Kindle
|
|
14
16
|
RELATED_VARIABLES = {
|
15
17
|
"force.enable_half_indent_bracket" => true,
|
16
18
|
}
|
19
|
+
|
20
|
+
include Device::BackupBookmarkUtility
|
21
|
+
|
22
|
+
def backup_bookmark
|
23
|
+
documents_path = get_documents_path
|
24
|
+
raise Device::DontConneting unless documents_path
|
25
|
+
paths = Dir.glob(File.join(documents_path, "*.sdr/*.azw3{f,r}"))
|
26
|
+
Helper.copy_files(paths, get_storage_path)
|
27
|
+
paths.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def restore_bookmark
|
31
|
+
documents_path = get_documents_path
|
32
|
+
raise Device::DontConneting unless documents_path
|
33
|
+
paths = Dir.glob(File.join(get_storage_path, "*.sdr/*"))
|
34
|
+
Helper.copy_files(paths, documents_path)
|
35
|
+
paths.size
|
36
|
+
end
|
17
37
|
end
|
data/lib/device/reader.rb
CHANGED
@@ -11,12 +11,7 @@ module Device::Reader
|
|
11
11
|
NAME = "Reader"
|
12
12
|
DISPLAY_NAME = "SonyReader"
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
force_change_settings_function({
|
18
|
-
"force.enable_half_indent_bracket" => false,
|
19
|
-
})
|
20
|
-
@@__already_exec_change_settings = true
|
21
|
-
end
|
14
|
+
RELATED_VARIABLES = {
|
15
|
+
"force.enable_half_indent_bracket" => false,
|
16
|
+
}
|
22
17
|
end
|
data/lib/helper.rb
CHANGED
@@ -238,6 +238,25 @@ module Helper
|
|
238
238
|
TYPE_OF_VALUE[value.class]
|
239
239
|
end
|
240
240
|
|
241
|
+
#
|
242
|
+
# ファイルを指定したディレクトリにまとめてコピーする
|
243
|
+
# 指定したディレクトリが存在しなければ作成する
|
244
|
+
#
|
245
|
+
# from: ファイルパスをまとめた Array
|
246
|
+
# dest_dir: コピー先のディレクトリ
|
247
|
+
#
|
248
|
+
def copy_files(from, dest_dir)
|
249
|
+
from.each do |path|
|
250
|
+
basename = File.basename(path)
|
251
|
+
dirname = File.basename(File.dirname(path))
|
252
|
+
save_dir = File.join(dest_dir, dirname)
|
253
|
+
unless File.directory?(save_dir)
|
254
|
+
FileUtils.mkdir_p(save_dir)
|
255
|
+
end
|
256
|
+
FileUtils.copy(path, File.join(save_dir, basename))
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
241
260
|
#
|
242
261
|
# 外部コマンド実行中の待機ループの処理を書けるクラス
|
243
262
|
#
|
data/lib/logger.rb
CHANGED
@@ -18,9 +18,18 @@ end
|
|
18
18
|
module Narou end unless defined?(Narou)
|
19
19
|
|
20
20
|
module Narou::LoggerModule
|
21
|
+
attr_accessor :capturing
|
22
|
+
|
21
23
|
def initialize
|
22
24
|
super
|
23
25
|
@is_silent = false
|
26
|
+
@capturing = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def copy_instance
|
30
|
+
self.class.new.tap { |obj|
|
31
|
+
obj.silent = silent
|
32
|
+
}
|
24
33
|
end
|
25
34
|
|
26
35
|
def silent=(enable)
|
@@ -55,18 +64,26 @@ module Narou::LoggerModule
|
|
55
64
|
# 標準出力($stdout)のバッファリング+取得
|
56
65
|
#
|
57
66
|
# キャプチャー用途なので標準エラーはキャプチャーしない
|
67
|
+
# quiet :: 標準出力に出力をしないかどうか
|
58
68
|
# ansicolor_strip :: エスケープシーケンスを除去するか
|
59
69
|
#
|
60
|
-
def capture(
|
70
|
+
def capture(options = {}, &block)
|
71
|
+
options = {
|
72
|
+
quiet: true, ansicolor_strip: true
|
73
|
+
}.merge(options)
|
61
74
|
raise "#capture block given" unless block
|
62
75
|
temp_stream = $stdout
|
63
|
-
$stdout = self
|
64
|
-
$stdout.
|
76
|
+
$stdout = (self == $stdout ? copy_instance : self)
|
77
|
+
$stdout.capturing = true
|
78
|
+
if options[:quiet]
|
79
|
+
$stdout.silence { block.call }
|
80
|
+
else
|
65
81
|
block.call
|
66
82
|
end
|
83
|
+
$stdout.capturing = false
|
67
84
|
buffer = $stdout.string
|
68
85
|
$stdout = temp_stream
|
69
|
-
ansicolor_strip ? strip_color(buffer) : buffer
|
86
|
+
options[:ansicolor_strip] ? strip_color(buffer) : buffer
|
70
87
|
end
|
71
88
|
|
72
89
|
def strip_color(str)
|
data/lib/narou.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
#
|
5
5
|
|
6
6
|
require "fileutils"
|
7
|
+
require "memoist"
|
7
8
|
require_relative "helper"
|
8
9
|
require_relative "inventory"
|
9
10
|
if Helper.engine_jruby?
|
@@ -11,24 +12,22 @@ if Helper.engine_jruby?
|
|
11
12
|
end
|
12
13
|
|
13
14
|
module Narou
|
15
|
+
extend Memoist
|
16
|
+
|
14
17
|
module_function
|
15
18
|
|
16
19
|
LOCAL_SETTING_DIR = ".narou"
|
17
20
|
GLOBAL_SETTING_DIR = ".narousetting"
|
18
21
|
AOZORAEPUB3_JAR_NAME = "AozoraEpub3.jar"
|
19
|
-
AOZORAEPUB3_DIR = "
|
20
|
-
PRESET_DIR = "
|
22
|
+
AOZORAEPUB3_DIR = "AozoraEpub3"
|
23
|
+
PRESET_DIR = "preset"
|
24
|
+
MISC_DIR = "misc"
|
21
25
|
EXIT_ERROR_CODE = 127
|
22
26
|
|
23
|
-
@@root_dir = nil
|
24
|
-
@@local_setting_dir = nil
|
25
|
-
@@global_setting_dir = nil
|
26
|
-
@@aozora_jar_path = nil
|
27
|
-
@@preset_dir = nil
|
28
27
|
@@is_web = false
|
29
28
|
|
30
29
|
def get_root_dir
|
31
|
-
|
30
|
+
root_dir = nil
|
32
31
|
path = File.expand_path(File.dirname("."))
|
33
32
|
drive_letter = ""
|
34
33
|
if Helper.os_windows?
|
@@ -37,35 +36,38 @@ module Narou
|
|
37
36
|
end
|
38
37
|
while path != ""
|
39
38
|
if File.directory?("#{drive_letter}#{path}/#{LOCAL_SETTING_DIR}")
|
40
|
-
|
39
|
+
root_dir = drive_letter + path
|
41
40
|
break
|
42
41
|
end
|
43
42
|
path.gsub!(%r!/[^/]*$!, "")
|
44
43
|
end
|
45
|
-
|
44
|
+
root_dir
|
46
45
|
end
|
46
|
+
memoize :get_root_dir
|
47
47
|
|
48
48
|
def get_local_setting_dir
|
49
|
-
|
49
|
+
local_setting_dir = nil
|
50
50
|
root_dir = get_root_dir
|
51
51
|
if root_dir
|
52
|
-
|
52
|
+
local_setting_dir = File.join(root_dir, LOCAL_SETTING_DIR)
|
53
53
|
end
|
54
|
-
|
54
|
+
local_setting_dir
|
55
55
|
end
|
56
|
+
memoize :get_local_setting_dir
|
56
57
|
|
57
58
|
def get_global_setting_dir
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
FileUtils.mkdir(@@global_setting_dir)
|
59
|
+
global_setting_dir = File.expand_path(File.join("~", GLOBAL_SETTING_DIR))
|
60
|
+
unless File.exist?(global_setting_dir)
|
61
|
+
FileUtils.mkdir(global_setting_dir)
|
62
62
|
end
|
63
|
-
|
63
|
+
global_setting_dir
|
64
64
|
end
|
65
|
+
memoize :get_global_setting_dir
|
65
66
|
|
66
67
|
def get_script_dir
|
67
|
-
|
68
|
+
File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
68
69
|
end
|
70
|
+
memoize :get_script_dir
|
69
71
|
|
70
72
|
def already_init?
|
71
73
|
!!get_root_dir
|
@@ -92,10 +94,9 @@ module Narou
|
|
92
94
|
end
|
93
95
|
|
94
96
|
def get_preset_dir
|
95
|
-
|
96
|
-
@@preset_dir = File.expand_path(File.join(get_script_dir, PRESET_DIR))
|
97
|
-
@@preset_dir
|
97
|
+
File.expand_path(File.join(get_script_dir, PRESET_DIR))
|
98
98
|
end
|
99
|
+
memoize :get_preset_dir
|
99
100
|
|
100
101
|
def create_aozoraepub3_jar_path(*paths)
|
101
102
|
File.expand_path(File.join(*paths, AOZORAEPUB3_JAR_NAME))
|
@@ -113,24 +114,22 @@ module Narou
|
|
113
114
|
# 3. スクリプト保存ディレクトリ(Narou.get_script_dir) 直下の AozoraEpub3
|
114
115
|
#
|
115
116
|
def get_aozoraepub3_path
|
116
|
-
return @@aozora_jar_path if @@aozora_jar_path
|
117
117
|
global_setting_aozora_path = Inventory.load("global_setting", :global)["aozoraepub3dir"]
|
118
118
|
if global_setting_aozora_path
|
119
119
|
aozora_jar_path = create_aozoraepub3_jar_path(global_setting_aozora_path)
|
120
120
|
if File.exist?(aozora_jar_path)
|
121
|
-
@@aozora_jar_path = aozora_jar_path
|
122
121
|
return aozora_jar_path
|
123
122
|
end
|
124
123
|
end
|
125
124
|
[Narou.get_root_dir, Narou.get_script_dir].each do |dir|
|
126
125
|
aozora_jar_path = create_aozoraepub3_jar_path(dir, AOZORAEPUB3_DIR)
|
127
126
|
if File.exist?(aozora_jar_path)
|
128
|
-
@@aozora_jar_path = aozora_jar_path
|
129
127
|
return aozora_jar_path
|
130
128
|
end
|
131
129
|
end
|
132
130
|
nil
|
133
131
|
end
|
132
|
+
memoize :get_aozoraepub3_path
|
134
133
|
|
135
134
|
def create_novel_filename(novel_data, ext = "")
|
136
135
|
author, title = %w(author title).map { |k|
|
@@ -150,6 +149,11 @@ module Narou
|
|
150
149
|
File.join(dir, create_novel_filename(data, ext))
|
151
150
|
end
|
152
151
|
|
152
|
+
def get_misc_dir
|
153
|
+
File.join(get_root_dir, MISC_DIR)
|
154
|
+
end
|
155
|
+
memoize :get_misc_dir
|
156
|
+
|
153
157
|
require_relative "device"
|
154
158
|
|
155
159
|
def get_device(device_name = nil)
|
data/lib/novelconverter.rb
CHANGED
@@ -289,10 +289,8 @@ class NovelConverter
|
|
289
289
|
end
|
290
290
|
end
|
291
291
|
# タイトルに完結したかどうかを付加する
|
292
|
-
flags = data["flags"] || {}
|
293
292
|
tags = data["tags"] || []
|
294
|
-
|
295
|
-
if flags["end"]
|
293
|
+
if tags.include?("end")
|
296
294
|
processed_title += " (完結)"
|
297
295
|
end
|
298
296
|
# タイトルがルビ化されてしまうのを抑制
|
data/lib/novelsetting.rb
CHANGED
@@ -197,6 +197,12 @@ class NovelSetting
|
|
197
197
|
value: true,
|
198
198
|
help: "自動行頭字下げ機能。行頭字下げが行われているかを判断し、適切に行頭字下げをする"
|
199
199
|
},
|
200
|
+
{
|
201
|
+
name: "enable_force_indent",
|
202
|
+
type: :boolean,
|
203
|
+
value: false,
|
204
|
+
help: "行頭字下げを必ず行う。enable_auto_indent の設定は無視される"
|
205
|
+
},
|
200
206
|
{
|
201
207
|
name: "enable_auto_join_in_brackets",
|
202
208
|
type: :boolean,
|
data/lib/version.rb
CHANGED
data/lib/web/appserver.rb
CHANGED
data/lib/web/helper4web.rb
CHANGED
@@ -8,8 +8,18 @@ require_relative "../helper"
|
|
8
8
|
module Helper
|
9
9
|
module_function
|
10
10
|
|
11
|
+
class << self
|
12
|
+
alias :original_print_horizontal_rule :print_horizontal_rule
|
13
|
+
end
|
14
|
+
|
11
15
|
def print_horizontal_rule
|
12
|
-
|
16
|
+
# タグがキャプチャーされると困るので、キャプチャ専用の出力とWEBへの出力は分ける
|
17
|
+
if $stdout.capturing
|
18
|
+
$stdout.silence do
|
19
|
+
original_print_horizontal_rule
|
20
|
+
end
|
21
|
+
end
|
22
|
+
$stdout.push_server.send_all(echo: "<hr>")
|
13
23
|
end
|
14
24
|
end
|
15
25
|
|
@@ -536,25 +536,32 @@ var Narou = (function() {
|
|
536
536
|
|
537
537
|
init_events_progressbar: function() {
|
538
538
|
var self = this;
|
539
|
-
var create_progress_html = function() {
|
540
|
-
return '<div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%"></div></div>';
|
541
|
-
};
|
542
539
|
var $progress = null;
|
540
|
+
var createProgressHtml = function(percent) {
|
541
|
+
return '<div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="' + percent + '" aria-valuemin="0" aria-valuemax="100" style="width:' + percent + '%"></div></div>';
|
542
|
+
};
|
543
|
+
var initializeProgressbar = function(percent) {
|
544
|
+
self.puts(createProgressHtml(percent));
|
545
|
+
$progress = self.console.find(".progress > div");
|
546
|
+
};
|
543
547
|
var setProgressValue = function(step) {
|
544
548
|
$progress.attr("aria-valuenow", step)
|
545
549
|
.width(step + "%");
|
546
550
|
};
|
547
551
|
this.notification.on("progressbar.init", function() {
|
548
|
-
|
549
|
-
$progress = self.console.find(".progress > div");
|
552
|
+
initializeProgressbar(0);
|
550
553
|
});
|
551
554
|
this.notification.on("progressbar.step", function(value) {
|
552
|
-
if (
|
553
|
-
|
555
|
+
if ($progress) {
|
556
|
+
setProgressValue(value);
|
557
|
+
}
|
558
|
+
else {
|
559
|
+
initializeProgressbar(value);
|
560
|
+
}
|
554
561
|
});
|
555
562
|
this.notification.on("progressbar.clear", function() {
|
556
563
|
if (!$progress) return;
|
557
|
-
//
|
564
|
+
// 表示と通信のタイムラグで100%付近のが表示されないまま消えてしまうので、
|
558
565
|
// 演出的にプログレスバーの消去を遅らせて、100%付近まで表示する
|
559
566
|
setProgressValue(100);
|
560
567
|
$progress = null;
|