narou 3.5.0.1 → 3.7.2

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.

data/lib/downloader.rb CHANGED
@@ -89,7 +89,7 @@ class Downloader
89
89
  #
90
90
  def self.get_target_type(target)
91
91
  case target
92
- when URI.regexp
92
+ when URI::DEFAULT_PARSER.make_regexp
93
93
  :url
94
94
  when /^n\d+[a-z]+$/i
95
95
  target.downcase!
@@ -157,7 +157,7 @@ class Downloader
157
157
  # toc 読込
158
158
  #
159
159
  def self.get_toc_data(archive_path)
160
- YAML.load_file(File.join(archive_path, TOC_FILE_NAME))
160
+ YAML.unsafe_load_file(File.join(archive_path, TOC_FILE_NAME))
161
161
  end
162
162
 
163
163
  def self.get_toc_by_target(target)
@@ -801,6 +801,7 @@ class Downloader
801
801
  raise if through_error # エラー処理はしなくていいからそのまま例外を受け取りたい時用
802
802
  if e.message.include?("404")
803
803
  @stream.error "小説が削除されているか非公開な可能性があります"
804
+ sleep_for_download
804
805
  if database.novel_exists?(@id)
805
806
  Command::Tag.execute!(%W(#{@id} --add 404 --color white --no-overwrite-color), io: Narou::NullIO.new)
806
807
  Command::Freeze.execute!(@id, "--on")
@@ -1042,7 +1043,7 @@ class Downloader
1042
1043
  def different_section?(old_relative_path, new_subtitle_info)
1043
1044
  path = get_novel_data_dir.join(old_relative_path)
1044
1045
  return true unless path.exist?
1045
- YAML.load_file(path)["element"] != new_subtitle_info["element"]
1046
+ YAML.unsafe_load_file(path)["element"] != new_subtitle_info["element"]
1046
1047
  end
1047
1048
 
1048
1049
  #
@@ -1267,7 +1268,7 @@ class Downloader
1267
1268
  #
1268
1269
  # 小説データの格納ディレクトリから読み込む
1269
1270
  def load_novel_data(filename)
1270
- YAML.load_file(get_novel_data_dir.join(filename))
1271
+ YAML.unsafe_load_file(get_novel_data_dir.join(filename))
1271
1272
  rescue Errno::ENOENT
1272
1273
  nil
1273
1274
  end
data/lib/helper.rb CHANGED
@@ -350,10 +350,10 @@ module Helper
350
350
  # 長過ぎるファイルパスを詰める
351
351
  # ファイル名部分のみを詰める。拡張子は維持する
352
352
  #
353
- def truncate_path(path, limit = Inventory.load["filename-length-limit"])
353
+ def truncate_path(path, limit = Inventory.load["filename-length-limit"], extname: nil)
354
354
  limit ||= FILENAME_LENGTH_LIMIT
355
355
  dirname = File.dirname(path)
356
- extname = File.extname(path)
356
+ extname ||= File.extname(path)
357
357
  basename = File.basename(path, extname)
358
358
  if basename.length > limit
359
359
  basename = basename[0...limit]
@@ -375,7 +375,7 @@ module Helper
375
375
  #
376
376
  def erb_copy(src, dst, _binding)
377
377
  data = File.read(src, mode: "r:BOM|UTF-8")
378
- result = ERB.new(data, nil, "-").result(_binding)
378
+ result = ERB.new(data, trim_mode: "-").result(_binding)
379
379
  File.write(dst, result)
380
380
  end
381
381
 
data/lib/illustration.rb CHANGED
@@ -27,7 +27,7 @@ class Illustration
27
27
  source.gsub!(/[#挿絵((.+?))入る]/) do |match|
28
28
  url = $1
29
29
  url = "https:#{url}" if url.start_with?("//")
30
- if url =~ URI.regexp
30
+ if url =~ URI::DEFAULT_PARSER.make_regexp
31
31
  path = download_image(url)
32
32
  path ? block.call(make_illust_chuki(path)) : ""
33
33
  else
@@ -53,6 +53,8 @@ class Illustration
53
53
  if path = search_image(basename)
54
54
  return path
55
55
  end
56
+
57
+ url = transform_mitemin_url(url)
56
58
  URI.open(url, make_open_uri_options(allow_redirections: :safe)) do |fp|
57
59
  content_type = fp.meta["content-type"]
58
60
  ext = MIME[content_type] or raise UnknownMIMEType, content_type
@@ -77,6 +79,13 @@ class Illustration
77
79
  Dir.glob(path)[0]
78
80
  end
79
81
 
82
+ def transform_mitemin_url(url)
83
+ uri = URI.parse(url)
84
+ return url unless uri.host.end_with?(".mitemin.net")
85
+
86
+ url.sub("viewimagebig", "viewimage")
87
+ end
88
+
80
89
  def create_illust_path(basename)
81
90
  illust_abs_dir = File.join(@setting.archive_path, ILLUST_DIR)
82
91
  Dir.mkdir(illust_abs_dir) unless File.exist?(illust_abs_dir)
data/lib/inventory.rb CHANGED
@@ -44,13 +44,13 @@ module Inventory
44
44
  return unless File.exist?(@inventory_file_path)
45
45
  self.merge!(Helper::CacheLoader.memo(@inventory_file_path) { |yaml|
46
46
  begin
47
- YAML.load(yaml)
47
+ YAML.unsafe_load(yaml)
48
48
  rescue Psych::SyntaxError
49
49
  unless restore(@inventory_file_path)
50
50
  error "#{@inventory_file_path} が壊れてるっぽい"
51
51
  raise
52
52
  end
53
- YAML.load_file(@inventory_file_path)
53
+ YAML.unsafe_load_file(@inventory_file_path)
54
54
  end
55
55
  })
56
56
  end
data/lib/mailer.rb CHANGED
@@ -23,7 +23,7 @@ class Mailer
23
23
  this.clear
24
24
  setting_file_path = File.join(Narou.root_dir, SETTING_FILE)
25
25
  if File.exist?(setting_file_path)
26
- options = YAML.load_file(setting_file_path)
26
+ options = YAML.unsafe_load_file(setting_file_path)
27
27
  unless options.delete(:complete)
28
28
  raise SettingUncompleteError, "設定ファイルの書き換えが終了していないようです。\n" +
29
29
  "設定ファイルは #{setting_file_path} にあります"
data/lib/narou.rb CHANGED
@@ -38,330 +38,336 @@ module Narou
38
38
 
39
39
  extend Mixin::Locker
40
40
 
41
- class << self
42
- extend Memoist
41
+ class << self
42
+ extend Memoist
43
43
 
44
- @@is_web = false
44
+ @@is_web = false
45
45
 
46
- def last_commit_year
47
- 2020
48
- end
46
+ def last_commit_year
47
+ 2021
48
+ end
49
49
 
50
- def root_dir
51
- root = nil
52
- path = Dir.pwd
53
- drive_letter = ""
54
- if Helper.os_windows?
55
- path.encode!(Encoding::UTF_8)
56
- path.gsub!(/^[a-z]:/i, "")
57
- drive_letter = $&
58
- end
59
- while path != ""
60
- if File.directory?("#{drive_letter}#{path}/#{LOCAL_SETTING_DIR_NAME}")
61
- root = drive_letter + path
62
- break
50
+ def root_dir
51
+ root = nil
52
+ path = Dir.pwd
53
+ drive_letter = ""
54
+ if Helper.os_windows?
55
+ path.encode!(Encoding::UTF_8)
56
+ path.gsub!(/^[a-z]:/i, "")
57
+ drive_letter = $&
58
+ end
59
+ while path != ""
60
+ if File.directory?("#{drive_letter}#{path}/#{LOCAL_SETTING_DIR_NAME}")
61
+ root = drive_letter + path
62
+ break
63
+ end
64
+ path.gsub!(%r!/[^/]*$!, "")
63
65
  end
64
- path.gsub!(%r!/[^/]*$!, "")
66
+ Pathname(root) if root
65
67
  end
66
- Pathname(root) if root
67
- end
68
- memoize :root_dir
68
+ memoize :root_dir
69
69
 
70
- def local_setting_dir
71
- root_dir&.join(LOCAL_SETTING_DIR_NAME)
72
- end
73
- memoize :local_setting_dir
70
+ def local_setting_dir
71
+ root_dir&.join(LOCAL_SETTING_DIR_NAME)
72
+ end
73
+ memoize :local_setting_dir
74
74
 
75
- def global_setting_dir
76
- if root_dir
77
- dir = root_dir.join(GLOBAL_SETTING_DIR_NAME)
78
- return dir if dir.directory?
75
+ def global_setting_dir
76
+ if root_dir
77
+ dir = root_dir.join(GLOBAL_SETTING_DIR_NAME)
78
+ return dir if dir.directory?
79
+ end
80
+ dir = Pathname(GLOBAL_SETTING_DIR_NAME).expand_path("~")
81
+ dir.mkdir unless dir.exist?
82
+ dir
79
83
  end
80
- dir = Pathname(GLOBAL_SETTING_DIR_NAME).expand_path("~")
81
- dir.mkdir unless dir.exist?
82
- dir
83
- end
84
- memoize :global_setting_dir
84
+ memoize :global_setting_dir
85
85
 
86
- def script_dir
87
- Pathname(__dir__).join("..").expand_path
88
- end
89
- memoize :script_dir
86
+ def script_dir
87
+ Pathname(__dir__).join("..").expand_path
88
+ end
89
+ memoize :script_dir
90
90
 
91
- def log_dir
92
- root_dir&.join(LOG_DIR)
93
- end
91
+ def log_dir
92
+ root_dir&.join(LOG_DIR)
93
+ end
94
94
 
95
- def preset_dir
96
- script_dir&.join(PRESET_DIR)
97
- end
98
- memoize :preset_dir
95
+ def preset_dir
96
+ script_dir&.join(PRESET_DIR)
97
+ end
98
+ memoize :preset_dir
99
99
 
100
- def already_init?
101
- root_dir.present?
102
- end
100
+ def already_init?
101
+ root_dir.present?
102
+ end
103
103
 
104
- def init
105
- return nil if already_init?
106
- FileUtils.mkdir(LOCAL_SETTING_DIR_NAME)
107
- puts "#{LOCAL_SETTING_DIR_NAME}/ を作成しました"
108
- Database.init
109
- end
104
+ def init
105
+ return nil if already_init?
106
+ FileUtils.mkdir(LOCAL_SETTING_DIR_NAME)
107
+ puts "#{LOCAL_SETTING_DIR_NAME}/ を作成しました"
108
+ Database.init
109
+ end
110
110
 
111
- #
112
- # target が alias だった場合はIDに変換する
113
- #
114
- # 全てのtarget照合系はこのメソッドを通過するので、ここで小文字にしてしまう
115
- #
116
- def alias_to_id(target)
117
- aliases = Inventory.load("alias")
118
- if aliases[target]
119
- return aliases[target]
120
- end
121
- target.kind_of?(Numeric) ? target : target.downcase
122
- end
111
+ #
112
+ # target が alias だった場合はIDに変換する
113
+ #
114
+ # 全てのtarget照合系はこのメソッドを通過するので、ここで小文字にしてしまう
115
+ #
116
+ def alias_to_id(target)
117
+ aliases = Inventory.load("alias")
118
+ if aliases[target]
119
+ return aliases[target]
120
+ end
121
+ target.is_a?(Numeric) ? target : target.downcase
122
+ end
123
123
 
124
- def novel_frozen?(target)
125
- id = Downloader.get_id_by_target(target) or return false
126
- Inventory.load("freeze").include?(id)
127
- end
124
+ def novel_frozen?(target)
125
+ id = Downloader.get_id_by_target(target) or return false
126
+ Inventory.load("freeze").include?(id)
127
+ end
128
128
 
129
- def create_aozoraepub3_jar_path(*paths)
130
- Pathname(File.expand_path(File.join(*paths, AOZORAEPUB3_JAR_NAME)))
131
- end
129
+ def create_aozoraepub3_jar_path(*paths)
130
+ Pathname(File.expand_path(File.join(*paths, AOZORAEPUB3_JAR_NAME)))
131
+ end
132
132
 
133
- def aozoraepub3_directory?(path)
134
- create_aozoraepub3_jar_path(path).exist?
135
- end
133
+ def aozoraepub3_directory?(path)
134
+ create_aozoraepub3_jar_path(path).exist?
135
+ end
136
136
 
137
- def parse_replace_txt(text)
138
- pattern = []
139
- text.each_line do |line|
140
- line.sub!(/[\r\n]+\z/, "")
141
- next if line[0] == ";" # コメント記号
142
- pair = line.split("\t", 2)
143
- if pair.length == 2 && pair[0]
144
- pattern << pair
137
+ def parse_replace_txt(text)
138
+ pattern = []
139
+ text.each_line do |line|
140
+ line.sub!(/[\r\n]+\z/, "")
141
+ next if line[0] == ";" # コメント記号
142
+ pair = line.split("\t", 2)
143
+ if pair.length == 2 && pair[0]
144
+ pattern << pair
145
+ end
145
146
  end
147
+ pattern
146
148
  end
147
- pattern
148
- end
149
149
 
150
- def write_replace_txt(path, pairs)
151
- buffer = pairs.each_with_object("\t").map(&:join).join("\n")
152
- File.write(path, buffer)
153
- end
150
+ def write_replace_txt(path, pairs)
151
+ buffer = pairs.each_with_object("\t").map(&:join).join("\n")
152
+ File.write(path, buffer)
153
+ end
154
154
 
155
- def load_global_replace_pattern
156
- path = root_dir.join(GLOBAL_REPLACE_NAME)
157
- pairs =
158
- if path.exist?
159
- Helper::CacheLoader.memo(path) do |text|
160
- parse_replace_txt(text)
155
+ def load_global_replace_pattern
156
+ path = root_dir.join(GLOBAL_REPLACE_NAME)
157
+ pairs =
158
+ if path.exist?
159
+ Helper::CacheLoader.memo(path) do |text|
160
+ parse_replace_txt(text)
161
+ end
162
+ else
163
+ []
161
164
  end
162
- else
163
- []
164
- end
165
- @@global_replace_pattern_pairs = pairs
166
- pairs
167
- end
165
+ @@global_replace_pattern_pairs = pairs
166
+ pairs
167
+ end
168
168
 
169
- def global_replace_pattern
170
- @@global_replace_pattern_pairs ||= load_global_replace_pattern
171
- end
169
+ def global_replace_pattern
170
+ @@global_replace_pattern_pairs ||= load_global_replace_pattern
171
+ end
172
172
 
173
- def save_global_replace_pattern
174
- path = root_dir.join(GLOBAL_REPLACE_NAME)
175
- write_replace_txt(path, @@global_replace_pattern_pairs)
176
- end
173
+ def save_global_replace_pattern
174
+ path = root_dir.join(GLOBAL_REPLACE_NAME)
175
+ write_replace_txt(path, @@global_replace_pattern_pairs)
176
+ end
177
177
 
178
- #
179
- # AozoraEpub3 の実行ファイル(.jar)のフルパス取得
180
- # 検索順序
181
- # 1. グローバルセッティング (global_setting aozoraepub3dir)
182
- # 2. 小説保存ディレクトリ(Narou.root_dir) 直下の AozoraEpub3
183
- # 3. スクリプト保存ディレクトリ(Narou.script_dir) 直下の AozoraEpub3
184
- #
185
- def aozoraepub3_path
186
- global_setting_aozora_path = Inventory.load("global_setting", :global)["aozoraepub3dir"]
187
- if global_setting_aozora_path
188
- aozora_jar_path = create_aozoraepub3_jar_path(global_setting_aozora_path)
189
- if aozora_jar_path.exist?
190
- return aozora_jar_path
178
+ #
179
+ # AozoraEpub3 の実行ファイル(.jar)のフルパス取得
180
+ # 検索順序
181
+ # 1. グローバルセッティング (global_setting aozoraepub3dir)
182
+ # 2. 小説保存ディレクトリ(Narou.root_dir) 直下の AozoraEpub3
183
+ # 3. スクリプト保存ディレクトリ(Narou.script_dir) 直下の AozoraEpub3
184
+ #
185
+ def aozoraepub3_path
186
+ global_setting_aozora_path = Inventory.load("global_setting", :global)["aozoraepub3dir"]
187
+ if global_setting_aozora_path
188
+ aozora_jar_path = create_aozoraepub3_jar_path(global_setting_aozora_path)
189
+ if aozora_jar_path.exist?
190
+ return aozora_jar_path
191
+ end
191
192
  end
192
- end
193
- [Narou.root_dir, Narou.script_dir].each do |dir|
194
- aozora_jar_path = create_aozoraepub3_jar_path(dir, AOZORAEPUB3_DIR)
195
- return aozora_jar_path if aozora_jar_path.exist?
196
- end
197
- nil
198
- end
199
- memoize :aozoraepub3_path
200
-
201
- #
202
- # 書籍ファイル名を生成する
203
- # convert.filename-to-ncode を設定している場合に novel_data に ncode、domain を
204
- # 設定しない場合は id カラムが必須
205
- #
206
- def create_novel_filename(novel_data, ext = "")
207
- filename_to_ncode = Inventory.load("local_setting")["convert.filename-to-ncode"]
208
- novel_setting =
209
- if novel_data["id"]
210
- NovelSetting.load(novel_data["id"])
211
- else
212
- OpenStruct.new
193
+ [Narou.root_dir, Narou.script_dir].each do |dir|
194
+ aozora_jar_path = create_aozoraepub3_jar_path(dir, AOZORAEPUB3_DIR)
195
+ return aozora_jar_path if aozora_jar_path.exist?
213
196
  end
214
- if novel_setting.output_filename.present?
215
- %!#{novel_setting.output_filename}#{ext}!
216
- elsif filename_to_ncode
217
- ncode, domain = novel_data["ncode"], novel_data["domain"]
218
- if !ncode || !domain
219
- id = novel_data["id"]
220
- unless id
221
- raise ArgumentError, %!novel_data["id"] を設定して下さい!
197
+ nil
198
+ end
199
+ memoize :aozoraepub3_path
200
+
201
+ #
202
+ # 書籍ファイル名を生成する
203
+ # convert.filename-to-ncode を設定している場合に novel_data に ncode、domain を
204
+ # 設定しない場合は id カラムが必須
205
+ #
206
+ # rubocop:disable Metrics/CyclomaticComplexity
207
+ # rubocop:disable Metrics/PerceivedComplexity
208
+ def create_novel_filename(novel_data, ext = "")
209
+ filename_to_ncode = Inventory.load("local_setting")["convert.filename-to-ncode"]
210
+ novel_setting =
211
+ if novel_data["id"]
212
+ NovelSetting.load(novel_data["id"])
213
+ else
214
+ OpenStruct.new
215
+ end
216
+ if novel_setting.output_filename.present?
217
+ %!#{novel_setting.output_filename}#{ext}!
218
+ elsif filename_to_ncode
219
+ ncode = novel_data["ncode"]
220
+ domain = novel_data["domain"]
221
+ if !ncode || !domain
222
+ id = novel_data["id"]
223
+ unless id
224
+ raise ArgumentError, %!novel_data["id"] を設定して下さい!
225
+ end
226
+ site_setting = Downloader.get_sitesetting_by_target(id)
227
+ ncode = site_setting["ncode"]
228
+ domain = site_setting["domain"]
222
229
  end
223
- site_setting = Downloader.get_sitesetting_by_target(id)
224
- ncode = site_setting["ncode"]
225
- domain = site_setting["domain"]
230
+ serialized_domain = domain.to_s.gsub(".", "_")
231
+ %!#{serialized_domain}_#{ncode}#{ext}!
232
+ else
233
+ author = Helper.replace_filename_special_chars(
234
+ novel_setting.novel_author.presence || novel_data["author"],
235
+ true
236
+ )
237
+ title = Helper.replace_filename_special_chars(
238
+ novel_setting.novel_title.presence || novel_data["title"],
239
+ true
240
+ )
241
+ filename = "[#{author}] #{title}#{ext}"
242
+ length_limit = Inventory.load["ebook-filename-length-limit"]
243
+ length_limit ? Helper.truncate_path(filename, length_limit, extname: ext) : filename
226
244
  end
227
- serialized_domain = domain.to_s.gsub(".", "_")
228
- %!#{serialized_domain}_#{ncode}#{ext}!
229
- else
230
- author = Helper.replace_filename_special_chars(
231
- novel_setting.novel_author.presence || novel_data["author"],
232
- true
233
- )
234
- title = Helper.replace_filename_special_chars(
235
- novel_setting.novel_title.presence || novel_data["title"],
236
- true
237
- )
238
- filename = "[#{author}] #{title}#{ext}"
239
- length_limit = Inventory.load["ebook-filename-length-limit"]
240
- length_limit ? Helper.truncate_path(filename, length_limit) : filename
241
245
  end
242
- end
246
+ # rubocop:enable Metrics/CyclomaticComplexity
247
+ # rubocop:enable Metrics/PerceivedComplexity
243
248
 
244
- def get_mobi_paths(target)
245
- get_ebook_file_paths(target, ".mobi")
246
- end
249
+ def get_mobi_paths(target)
250
+ get_ebook_file_paths(target, ".mobi")
251
+ end
247
252
 
248
- def get_ebook_file_paths(target, ext)
249
- data = Downloader.get_data_by_target(target)
250
- return nil unless data
251
- dir = Downloader.get_novel_data_dir_by_target(target)
252
- fname = create_novel_filename(data, ext)
253
- base = File.basename(fname, ext)
254
- get_ebook_file_paths_from_components(dir, base, ext)
255
- end
253
+ def get_ebook_file_paths(target, ext)
254
+ data = Downloader.get_data_by_target(target)
255
+ return nil unless data
256
256
 
257
- def get_ebook_file_paths_from_components(dir, base, ext)
258
- paths = [File.join(dir, "#{base}#{ext}")]
259
- index = 2
260
- while File.exist?(path = File.join(dir, "#{base}_#{index}#{ext}"))
261
- paths.push(Pathname(path))
262
- index += 1
257
+ dir = Downloader.get_novel_data_dir_by_target(target)
258
+ fname = create_novel_filename(data, ext)
259
+ base = File.basename(fname, ext)
260
+ get_ebook_file_paths_from_components(dir, base, ext)
263
261
  end
264
- paths
265
- end
266
262
 
267
- def misc_dir
268
- root_dir.join(MISC_DIR)
269
- end
263
+ def get_ebook_file_paths_from_components(dir, base, ext)
264
+ paths = [File.join(dir, "#{base}#{ext}")]
265
+ index = 2
266
+ while File.exist?(path = File.join(dir, "#{base}_#{index}#{ext}"))
267
+ paths.push(Pathname(path))
268
+ index += 1
269
+ end
270
+ paths
271
+ end
272
+
273
+ def misc_dir
274
+ root_dir.join(MISC_DIR)
275
+ end
270
276
 
271
- require_relative "device"
277
+ require_relative "device"
272
278
 
273
- def get_device(device_name = nil)
274
- device_name = Inventory.load("local_setting")["device"] unless device_name
275
- if device_name && Device.exists?(device_name)
276
- return Device.create(device_name)
279
+ def get_device(device_name = nil)
280
+ device_name ||= Inventory.load("local_setting")["device"]
281
+ if device_name && Device.exists?(device_name)
282
+ return Device.create(device_name)
283
+ end
284
+ nil
277
285
  end
278
- nil
279
- end
280
286
 
281
- def web=(bool)
282
- @@is_web = bool
283
- end
287
+ def web=(bool)
288
+ @@is_web = bool
289
+ end
284
290
 
285
- def web?
286
- @@is_web
287
- end
291
+ def web?
292
+ @@is_web
293
+ end
288
294
 
289
- def update_sort_key_summaries(left_space = 28)
290
- summaries = { "KEY" => " 対象" }.merge(UPDATE_SORT_KEYS)
291
- key_max_width = summaries.keys.max_by(&:length).length
292
- summaries.map do |(key, summary)|
293
- "#{" " * left_space}| #{key.center(key_max_width)} | #{summary}"
294
- end.join("\n")
295
- end
295
+ def update_sort_key_summaries(left_space = 28)
296
+ summaries = { "KEY" => " 対象" }.merge(UPDATE_SORT_KEYS)
297
+ key_max_width = summaries.keys.max_by(&:length).length
298
+ summaries.map do |(key, summary)|
299
+ "#{" " * left_space}| #{key.center(key_max_width)} | #{summary}"
300
+ end.join("\n")
301
+ end
296
302
 
297
- def get_theme
298
- Inventory.load("local_setting")["webui.theme"]
299
- end
303
+ def theme
304
+ Inventory.load("local_setting")["webui.theme"]
305
+ end
300
306
 
301
- def get_theme_dir(name = nil)
302
- Pathname(File.join([script_dir, "lib/web/public/theme", name].compact))
303
- end
307
+ def get_theme_dir(name = nil)
308
+ Pathname(File.join([script_dir, "lib/web/public/theme", name].compact))
309
+ end
304
310
 
305
- def get_theme_names
306
- Dir.glob(get_theme_dir("*")).map do |path|
307
- name = File.basename(path)
308
- name == "fonts" ? nil : name
309
- end.compact
310
- end
311
- memoize :get_theme_names
311
+ def theme_names
312
+ Dir.glob(get_theme_dir("*")).map do |path|
313
+ name = File.basename(path)
314
+ name == "fonts" ? nil : name
315
+ end.compact
316
+ end
317
+ memoize :theme_names
312
318
 
313
- def economy?(mode)
314
- eco_modes = Inventory.load("local_setting")["economy"].to_s.split(",").map(&:strip)
315
- eco_modes.include?(mode)
316
- end
319
+ def economy?(mode)
320
+ eco_modes = Inventory.load("local_setting")["economy"].to_s.split(",").map(&:strip)
321
+ eco_modes.include?(mode)
322
+ end
317
323
 
318
- def novel_type_text(type)
319
- type == 2 ? "短編" : "連載"
320
- end
324
+ def novel_type_text(type)
325
+ type == 2 ? "短編" : "連載"
326
+ end
321
327
 
322
- #
323
- # Narou.rb gem の最新バージョン番号を取得する
324
- #
325
- # rubygems公式APIによる取得は、WindowsでのSSL証明書問題で取得出来ない
326
- # 環境があるため、gemコマンド経由で取得する
327
- #
328
- def latest_version
329
- response = `gem search ^narou$`.split("\n")
330
- if response.last =~ /\Anarou \(([0-9.]+).*?\)\z/
331
- $1
328
+ #
329
+ # Narou.rb gem の最新バージョン番号を取得する
330
+ #
331
+ # rubygems公式APIによる取得は、WindowsでのSSL証明書問題で取得出来ない
332
+ # 環境があるため、gemコマンド経由で取得する
333
+ #
334
+ def latest_version
335
+ response = `gem search ^narou$`.split("\n")
336
+ if response.last =~ /\Anarou \(([0-9.]+).*?\)\z/
337
+ $1
338
+ end
332
339
  end
333
- end
334
340
 
335
- def commit_version
336
- cv_path = File.expand_path("commitversion", script_dir)
337
- File.read(cv_path) if File.exist?(cv_path)
338
- end
339
- memoize :commit_version
341
+ def commit_version
342
+ cv_path = File.expand_path("commitversion", script_dir)
343
+ File.read(cv_path) if File.exist?(cv_path)
344
+ end
345
+ memoize :commit_version
340
346
 
341
- def kindlegen_path
342
- postfix = Helper.os_windows? ? ".exe" : ""
343
- aozoraepub3_path.dirname.join("kindlegen#{postfix}")
344
- end
345
- memoize :kindlegen_path
347
+ def kindlegen_path
348
+ postfix = Helper.os_windows? ? ".exe" : ""
349
+ aozoraepub3_path.dirname.join("kindlegen#{postfix}")
350
+ end
351
+ memoize :kindlegen_path
346
352
 
347
- def line_height(default: LINE_HEIGHT_DEFAULT)
348
- global_setting = Inventory.load("global_setting", :global)
349
- global_setting["line-height"] || default
350
- end
353
+ def line_height(default: LINE_HEIGHT_DEFAULT)
354
+ global_setting = Inventory.load("global_setting", :global)
355
+ global_setting["line-height"] || default
356
+ end
351
357
 
352
- def concurrency_enabled?
353
- $stdout != $stdout2
354
- end
355
- memoize :concurrency_enabled?
358
+ def concurrency_enabled?
359
+ $stdout != $stdout2
360
+ end
361
+ memoize :concurrency_enabled?
356
362
 
357
- # 同時実行が有効ならキューに積んで、無効なら普通に実行する
358
- def concurrency_call(&block)
359
- if concurrency_enabled?
360
- Worker.push(&block)
361
- EXIT_SUCCESS
362
- else
363
- block.call
363
+ # 同時実行が有効ならキューに積んで、無効なら普通に実行する
364
+ def concurrency_call(&block)
365
+ if concurrency_enabled?
366
+ Worker.push(&block)
367
+ EXIT_SUCCESS
368
+ else
369
+ block.call
370
+ end
364
371
  end
365
372
  end
366
- end
367
373
  end