diff --git a/lib/aozoraepub3.rb b/lib/aozoraepub3.rb
new file mode 100644
index 00000000..7da7faef
--- /dev/null
+++ b/lib/aozoraepub3.rb
@@ -0,0 +1,301 @@
+# frozen_string_literal: true
+
+#
+# Copyright 2013 whiteleaf. All rights reserved.
+#
+
+require "fileutils"
+require_relative "narou"
+
+#
+# AozoraEpub3 設定処理
+#
+module AozoraEpub3
+ @prev_use_dakuten_font = nil
+
+ def self.setup(global_setting)
+ aozora_dir_path = global_setting["aozoraepub3dir"]
+
+ # 資材アップデーターの取得
+ updater = get_resouce_updater(aozora_dir_path)
+
+ # 更新ファイル名のクリア
+ updater.clear_log
+
+ # iniファイルのコピー
+ updater.copy_ini_file
+
+ # chuki_tag.txt の書き換え
+ updater.replace_chuki_tag_file
+
+ yokogaki = false # dummy
+ use_dakuten_font = false # dummy
+ line_height = global_setting["line-height"]
+ # カスタムCSSファイルのコピー
+ # MEMO:
+ # 変換の時に毎回更新しているので本当はここでやる必要はない
+ # ただ、ここで行えば更新ファイル名をログに出せる
+ updater.copy_css_files(yokogaki, use_dakuten_font, line_height)
+
+ # 内容が同じだと書き換えを行わない場合もあるので、更新日時をアップデート
+ updater.updated_file_paths.each { |path| FileUtils.touch(path) }
+
+ yield(updater.copied_file_paths, updater.updated_file_paths) if block_given?
+ end
+ public_class_method :setup
+
+ #
+ # Aozoraの資材更新
+ #
+ # MEMO:
+ # 資材更新が必要かどうかは作品ごとに異なる。
+ # たとえば濁点フォント機能を有効にしている場合、濁点文字を使ってる作品なら、
+ # 濁点フォントやCSSをコピーする必要があるし、そうでなければ濁点の資材を取り除かなければならない
+ def self.update_resources(yokogaki, use_dakuten_font)
+ return if @prev_use_dakuten_font == use_dakuten_font
+
+ line_height = Narou.line_height
+
+ # 資材アップデーターの取得
+ updater = get_resouce_updater
+
+ # ファイル更新情報のクリア
+ updater.clear_log
+
+ # CSSファイルのコピー
+ updater.copy_css_files(yokogaki, use_dakuten_font, line_height)
+
+ if use_dakuten_font
+ # 濁点フォントファイルのコピー
+ updater.copy_dakuten_font
+ else
+ # 濁点フォントファイルの削除
+ updater.remove_dakuten_font
+ end
+
+ # 設定値の保存
+ @prev_use_dakuten_font = use_dakuten_font
+ end
+ public_class_method :update_resources
+
+ #
+ # Aozora資材アップデーターの取得
+ #
+ def self.get_resouce_updater(aozora_dir_path = nil)
+ aozora_dir_path ||= File.dirname(Narou.aozoraepub3_path)
+ if denshokyo_version?(aozora_dir_path)
+ AozoraResourceUpdaterDen.new(aozora_dir_path)
+ else
+ AozoraResourceUpdater.new(aozora_dir_path)
+ end
+ end
+ private_class_method :get_resouce_updater
+
+ #
+ # Aozora出力形式の判定
+ #
+ def self.denshokyo_version?(aozora_dir_path)
+ # template/item ディレクトリがあれば電書協対応版 (改造版v1.1.1以降) とみなす
+ Dir.exist?(File.join(aozora_dir_path, "template", "item"))
+ end
+ private_class_method :denshokyo_version?
+
+ #
+ # Aozora資材アップデーター
+ #
+ class AozoraResourceUpdater
+ VERTICAL_CSS = "vertical_font.css"
+ DAKUTEN_FONT = "DMincho.ttf"
+
+ def initialize(aozora_dir_path = nil)
+ @format_type = "honke"
+ @aozora_dir_path = aozora_dir_path || File.dirname(Narou.aozoraepub3_path)
+ aozora_ops_dir = File.join(@aozora_dir_path, "template", "OPS")
+ @aozora_naroubak_dir = File.join(@aozora_dir_path, "template", "narou_bak")
+ @aozora_css_dir = File.join(aozora_ops_dir, "css")
+ @aozora_font_dir = File.join(aozora_ops_dir, "fonts")
+
+ @aozora_chuki_path = File.join(@aozora_dir_path, "chuki_tag.txt")
+ @narou_rb_chuki_path = File.join(Narou.preset_dir, "custom_chuki_tag.txt")
+
+ clear_log
+ end
+
+ def clear_log
+ @updated_file_paths = []
+ @copied_file_paths = []
+ end
+ attr_reader :updated_file_paths, :copied_file_paths
+
+ def self.get_custom_file_path(file_path, should_create_directory)
+ dir_path = File.dirname(file_path) + "_custom"
+ if should_create_directory
+ FileUtils.mkdir_p(dir_path)
+ end
+ File.join(dir_path, File.basename(file_path))
+ end
+
+ # iniファイルのコピー
+ def copy_ini_file
+ src = File.join(Narou.preset_dir, "AozoraEpub3.ini")
+ dst = File.join(@aozora_dir_path, "AozoraEpub3.ini")
+ FileUtils.copy(src, dst)
+ @copied_file_paths << dst
+ end
+
+ # 注記ファイルのコピー
+ def replace_chuki_tag_file
+ narou_rb_chuki = File.read(@narou_rb_chuki_path, mode: "r:BOM|UTF-8")
+ aozora_chuki = File.read(@aozora_chuki_path, mode: "r:BOM|UTF-8")
+ embedded_mark = "### Narou.rb embedded custom chuki ###"
+ if aozora_chuki =~ /#{embedded_mark}/
+ # MEMO:
+ # 再実行時、ファイル末尾に余計な改行を増やさないよう置換文字列を strip する
+ aozora_chuki.gsub!(/#{embedded_mark}.+#{embedded_mark}/m, narou_rb_chuki.strip)
+ else
+ aozora_chuki << "\n" << narou_rb_chuki
+ end
+ File.write(@aozora_chuki_path, aozora_chuki)
+ @updated_file_paths << @aozora_chuki_path
+ end
+
+ # CSSファイルのコピー
+ def copy_css_files(yokogaki, use_dakuten_font, line_height)
+ css_template_path = File.join(Narou.preset_dir, VERTICAL_CSS)
+ aozora_vrtl_css_path = File.join(@aozora_css_dir, VERTICAL_CSS)
+ css = create_css_text(css_template_path, yokogaki, use_dakuten_font, line_height)
+ create_custom_css_file(aozora_vrtl_css_path, css)
+ end
+
+ # テンプレートファイルをもとにCSS(文字列)を作成
+ def create_css_text(template_file_path, yokogaki, use_dakuten_font, line_height)
+ tategaki = !yokogaki
+ format_type = @format_type
+ template = File.read(template_file_path, mode: "rb:BOM|UTF-8")
+ # yokogaki, tategaki, line_height, use_dakuten_font, format_type などの変数を binding でテンプレートに渡す
+ ERB.new(template, trim_mode: "-").result(binding)
+ end
+
+ # AozoraEpub3 と Narou.rb の CSS をもとに カスタムCSSを作成する
+ def create_css_text2(original_css_path, css_template_path, yokogaki, use_dakuten_font, line_height)
+ # オリジナルCSSファイルを読み込み、内容をバッファに追加
+ lines = File.read(original_css_path, mode: "rb:BOM|UTF-8")
+ # 改行コードを取得
+ eol = lines.include?("\r\n") ? "\r\n" : "\n"
+
+ lines << eol
+ lines << "/*** [START] Narou.rb embedded custom style ***/" << eol
+
+ css = create_css_text(css_template_path, yokogaki, use_dakuten_font, line_height)
+ css.each_line do |line|
+ unless line.match?(/^\s*@(?:charset|namespace)/)
+ # 内容をバッファに追加
+ lines << line.chomp! << eol
+ end
+ end
+
+ lines << eol
+ lines << "/*** [END] Narou.rb embedded custom style ***/" << eol
+ lines
+ end
+
+ # カスタムCSSファイルの配置
+ def create_custom_css_file(dst_css_file_path, css)
+ custom_css_file_path = AozoraResourceUpdater.get_custom_file_path(dst_css_file_path, true)
+ file_write(custom_css_file_path, css)
+ @copied_file_paths << custom_css_file_path
+ end
+
+ # 濁点フォントパス
+ def dst_dakuten_font_path
+ File.join(@aozora_font_dir, DAKUTEN_FONT)
+ end
+
+ # 濁点フォントファイルのコピー
+ def copy_dakuten_font
+ unless File.exist?(dst_dakuten_font_path)
+ # フォントファイルがない場合、控えのフォントファイルをコピー先に移動する
+ move_file_from_backup(DAKUTEN_FONT, dst_dakuten_font_path)
+ end
+ @copied_file_paths << dst_dakuten_font_path
+ end
+
+ # 濁点フォントファイルの削除
+ def remove_dakuten_font
+ # ファイルをバックアップフォルダに移動する
+ move_file_to_backup(dst_dakuten_font_path)
+ end
+
+ # バックアップファイルをコピー先に移動する
+ # バックアップファイルがない場合、プリセットのファイルをコピー先にコピーする
+ def move_file_from_backup(filename, dst_file_path)
+ FileUtils.mkdir_p(File.dirname(dst_file_path))
+ bak_file_path = File.join(@aozora_naroubak_dir, filename)
+ if File.exist?(bak_file_path)
+ FileUtils.move(bak_file_path, dst_file_path)
+ else
+ src_file_path = File.join(Narou.preset_dir, filename)
+ FileUtils.copy(src_file_path, dst_file_path)
+ end
+ end
+
+ # ファイルをバックアップフォルダに移動する
+ def move_file_to_backup(dst_file_path)
+ return unless File.exist?(dst_file_path)
+
+ FileUtils.mkdir_p(@aozora_naroubak_dir)
+ bak_file_path = File.join(@aozora_naroubak_dir, File.basename(dst_file_path))
+ FileUtils.move(dst_file_path, bak_file_path)
+ end
+ end
+ private_constant :AozoraResourceUpdater
+
+ #
+ # Aozora電書協 資材アップデーター
+ #
+ class AozoraResourceUpdaterDen < AozoraResourceUpdater
+ BOOK_STYLE_CSS = "book-style.css"
+ DENSHOKYO_CSS = "denshokyo.css"
+
+ def initialize(aozora_dir_path = nil)
+ super(aozora_dir_path)
+ @format_type = "denshokyo"
+ aozora_item_dir = File.join(@aozora_dir_path, "template", "item")
+ @aozora_css_dir = File.join(aozora_item_dir, "style")
+ @aozora_font_dir = File.join(aozora_item_dir, "fonts")
+ end
+
+ #
+ # カスタムCSSファイルの配置
+ #
+ def copy_css_files(yokogaki, use_dakuten_font, line_height)
+ aozora_css_path = File.join(@aozora_css_dir, BOOK_STYLE_CSS)
+ # オリジナルのCSSがなければエラー
+ unless File.exist?(aozora_css_path)
+ raise Errno::ENOENT, "'#{aozora_css_path}' not found."
+ end
+
+ css_template_path = File.join(Narou.preset_dir, DENSHOKYO_CSS)
+ css = create_css_text2(aozora_css_path, css_template_path, yokogaki, use_dakuten_font, line_height)
+ # CSSカスタムファイルの作成
+ create_custom_css_file(aozora_css_path, css)
+ end
+ end
+ private_constant :AozoraResourceUpdaterDen
+end
+
+# ファイルの読込み
+def try_reading_file(filepath)
+ File.exist?(filepath) ? File.read(filepath, mode: "rb:BOM|UTF-8") : nil
+end
+
+# ファイルの書込み
+# 内容が同じなら書き込まない
+def file_write(filepath, content)
+ should_write = !File.exist?(filepath) || try_reading_file(filepath) != content
+ return unless should_write
+
+ File.open(filepath, mode: "wb:UTF-8") do |f|
+ f.write(content)
+ end
+end
diff --git a/lib/command/init.rb b/lib/command/init.rb
index f2555588..6ca6d31b 100644
--- a/lib/command/init.rb
+++ b/lib/command/init.rb
@@ -4,6 +4,7 @@
# Copyright 2013 whiteleaf. All rights reserved.
#
+require_relative "../aozoraepub3"
require_relative "../inventory"
require_relative "../commandbase"
@@ -103,41 +104,24 @@ def init_aozoraepub3(force = false)
end
line_height = @options["line_height"] || ask_line_height
puts
- rewrite_aozoraepub3_files(aozora_path, line_height)
@global_setting["aozoraepub3dir"] = aozora_path
@global_setting["line-height"] = line_height
+ AozoraEpub3.setup(@global_setting) { |copied_file_paths, updated_file_paths|
+ puts "(次のファイルを書き換えました)"
+ updated_file_paths.each do |path|
+ puts path
+ end
+ puts
+
+ puts "(次のファイルをコピーor上書きしました)"
+ copied_file_paths.each do |path|
+ puts path
+ end
+ }
@global_setting.save
puts "AozoraEpub3の設定を終了しました".termcolor
end
- def rewrite_aozoraepub3_files(aozora_path, line_height)
- # chuki_tag.txt の書き換え
- custom_chuki_tag_path = File.join(Narou.preset_dir, "custom_chuki_tag.txt")
- chuki_tag_path = File.join(aozora_path, "chuki_tag.txt")
- custom_chuki_tag = File.read(custom_chuki_tag_path, mode: "r:BOM|UTF-8")
- chuki_tag = File.read(chuki_tag_path, mode: "r:BOM|UTF-8")
- embedded_mark = "### Narou.rb embedded custom chuki ###"
- if chuki_tag =~ /#{embedded_mark}/
- chuki_tag.gsub!(/#{embedded_mark}.+#{embedded_mark}/m, custom_chuki_tag)
- else
- chuki_tag << "\n" + custom_chuki_tag
- end
- File.write(chuki_tag_path, chuki_tag)
- puts "(次のファイルを書き換えました)"
- puts chuki_tag_path
- puts
- # ファイルコピー
- src = ["AozoraEpub3.ini", "vertical_font.css"]
- dst = ["AozoraEpub3.ini", "template/OPS/css_custom/vertical_font.css"]
- puts "(次のファイルをコピーor上書きしました)"
- src.size.times do |i|
- src_full_path = File.join(Narou.preset_dir, src[i])
- dst_full_path = File.join(aozora_path, dst[i])
- Helper.erb_copy(src_full_path, dst_full_path, binding)
- puts dst_full_path
- end
- end
-
def ask_aozoraepub3_path
puts
print "AozoraEpub3のあるフォルダを入力して下さい:\n(未入力でスキップ".termcolor
diff --git a/lib/novelconverter.rb b/lib/novelconverter.rb
index 446d6257..9d522b3b 100644
--- a/lib/novelconverter.rb
+++ b/lib/novelconverter.rb
@@ -6,6 +6,7 @@
require "fileutils"
require "stringio"
+require_relative "aozoraepub3"
require_relative "novelsetting"
require_relative "inspector"
require_relative "illustration"
@@ -85,36 +86,6 @@ def self.convert_file(filename, options = {})
}
end
- DAKUTEN_FROM = ["vertical_font_with_dakuten.css", "DMincho.ttf"]
- DAKUTEN_TO = ["template/OPS/css_custom/vertical_font.css", "template/OPS/fonts/DMincho.ttf"]
- DAKUTEN_ERB = [true, false]
-
- def self.activate_dakuten_font_files
- preset_dir = Narou.preset_dir
- aozora_dir = File.dirname(Narou.aozoraepub3_path)
- line_height = Narou.line_height
-
- DAKUTEN_FROM.each_with_index do |name, i|
- src = File.join(preset_dir, name)
- dst = File.join(aozora_dir, DAKUTEN_TO[i])
- if DAKUTEN_ERB[i]
- Helper.erb_copy(src, dst, binding)
- else
- FileUtils.copy(src, dst)
- end
- end
- end
-
- def self.inactivate_dakuten_font_files
- preset_dir = Narou.preset_dir
- aozora_dir = File.dirname(Narou.aozoraepub3_path)
- path_normal_vertical_css = File.join(preset_dir, "vertical_font.css")
- line_height = Narou.line_height
-
- Helper.erb_copy(path_normal_vertical_css, File.join(aozora_dir, DAKUTEN_TO[0]), binding)
- FileUtils.remove(File.join(aozora_dir, DAKUTEN_TO[1]))
- end
-
#
# AozoraEpub3でEPUBファイル作成
#
@@ -126,6 +97,9 @@ def self.inactivate_dakuten_font_files
# 返り値:正常終了 :success、エラー終了 :error、AozoraEpub3が見つからなかった nil
#
def self.txt_to_epub(filename, dst_dir: nil, device: nil, verbose: false, yokogaki: false, use_dakuten_font: false, stream_io: $stdout2)
+ # AozoraEpub3のリソース更新
+ AozoraEpub3.update_resources(yokogaki, use_dakuten_font)
+
abs_srcpath = File.expand_path(filename)
src_dir = File.dirname(abs_srcpath)
@@ -165,7 +139,9 @@ def self.txt_to_epub(filename, dst_dir: nil, device: nil, verbose: false, yokoga
aozoraepub3_basename = File.basename(aozoraepub3_path)
aozoraepub3_dir = File.dirname(aozoraepub3_path)
- java_encoding = "-Dfile.encoding=UTF-8"
+ java_encoding = "-Dfile.encoding=UTF-8" +
+ " -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8" +
+ " -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8"
if Helper.os_cygwin?
abs_srcpath = Helper.convert_to_windows_path(abs_srcpath)
@@ -176,7 +152,7 @@ def self.txt_to_epub(filename, dst_dir: nil, device: nil, verbose: false, yokoga
if Helper.os_windows?
command = "cmd /c #{command}".encode(Encoding::Windows_31J)
end
- activate_dakuten_font_files if use_dakuten_font
+
stream_io.print "AozoraEpub3でEPUBに変換しています"
begin
res = Helper::AsyncCommand.exec(command) do
@@ -184,7 +160,6 @@ def self.txt_to_epub(filename, dst_dir: nil, device: nil, verbose: false, yokoga
end
ensure
Dir.chdir(pwd)
- inactivate_dakuten_font_files if use_dakuten_font
end
# AozoraEpub3はエラーだとしてもexitコードは0なので、
diff --git a/preset/vertical_font_with_dakuten.css b/preset/denshokyo.css
similarity index 65%
rename from preset/vertical_font_with_dakuten.css
rename to preset/denshokyo.css
index c611a738..a3e1e8ee 100644
--- a/preset/vertical_font_with_dakuten.css
+++ b/preset/denshokyo.css
@@ -1,22 +1,18 @@
@charset "utf-8";
@namespace "http://www.w3.org/1999/xhtml";
-body {
+.vrtl body, .hltr body {
font-family: "@MS 明朝", "@MS Mincho", "ヒラギノ明朝 ProN W3", "HiraMinProN-W3", serif, sans-serif;
line-height: <%= line_height %>em !important;
}
-.gtc, .b {
+.vrtl .gtc, .hltr .gtc, .b {
font-family: '@MS ゴシック','@MS Gothic',sans-serif !important;
}
-.b { font-weight: bold; }
-.i { font-style: italic; }
-
-rt { font-size: 0.6em; }
+.vrtl rt, .hltr rt { font-size: 0.6em; }
/* カスタム注記用 */
-
/* 柱(もどき) */
.running_head {
position: absolute !important;
@@ -24,17 +20,32 @@ rt { font-size: 0.6em; }
left: 10px;
font-size: 0.8em;
}
-
+<% if tategaki %>
+/* ページ左右中央 調整 */
+.main.block-align-center div.mt3 {
+ margin-left: 0 !important;
+ margin-right: 0 !important;
+}
+.main.block-align-center > div {
+ margin-top: 4em !important;
+}
+div.main.block-align-center div.running_head {
+ position: absolute !important;
+ top: 2em;
+ left: 10px;
+ font-size: 0.8em;
+}
+<% end %>
+<% if use_dakuten_font %>
/* 濁点フォント */
@font-face {
font-family: "DakutenAokinMincho";
src: url(../fonts/DMincho.ttf) format("truetype");
}
-
-.dakuten {
+.vrtl .dakuten, .hltr .dakuten {
font-family: "DakutenAokinMincho" !important;
}
-
+<% end %>
/* 二分アキ */
.half_em_space { padding-top: 0.5em; }
@@ -52,15 +63,15 @@ rt { font-size: 0.6em; }
box-shadow: 3px 3px 3px #bbb;
-webkit-box-shadow: 3px 3px 3px #bbb;
}
-.jzm .custom_parameter_block {
+.vrtl .jzm .custom_parameter_block, .hltr .jzm .custom_parameter_block {
display: block;
}
-.jzm .p .custom_parameter_block {
+.vrtl .jzm .p .custom_parameter_block, .hltr .jzm .p .custom_parameter_block {
display: inline-block;
}
/* 前書き */
-.introduction {
+.vrtl .introduction {
float: right;
font-size: 83%;
line-height: 1.5em !important;
@@ -74,15 +85,15 @@ rt { font-size: 0.6em; }
text-align: left !important;
height: 70%;
}
-.jzm .introduction {
+.vrtl .jzm .introduction, .hltr .jzm .introduction {
display: block;
}
-.jzm .p .introduction {
+.vrtl .jzm .p .introduction, .hltr .jzm .p .introduction {
display: inline-block;
}
/* 後書き */
-.postscript {
+.vrtl .postscript {
float: right;
font-size: 83%;
line-height: 1.5em !important;
@@ -96,13 +107,13 @@ rt { font-size: 0.6em; }
text-align: left !important;
height: 70%;
}
-.jzm .postscript {
+.vrtl .jzm .postscript, .hltr .jzm .postscript {
display: block;
}
-.jzm .p .postscript {
+.vrtl .jzm .p .postscript, .hltr .jzm .p .postscript {
display: inline-block;
}
-div.clear {
+.vrtl div.clear, .hltr div.clear {
clear: both;
}
diff --git a/preset/vertical_font.css b/preset/vertical_font.css
index c77f0307..e8bebe67 100644
--- a/preset/vertical_font.css
+++ b/preset/vertical_font.css
@@ -24,7 +24,17 @@ rt { font-size: 0.6em; }
left: 10px;
font-size: 0.8em;
}
+<% if use_dakuten_font %>
+/* 濁点フォント */
+@font-face {
+ font-family: "DakutenAokinMincho";
+ src: url(../fonts/DMincho.ttf) format("truetype");
+}
+.dakuten {
+ font-family: "DakutenAokinMincho" !important;
+}
+<% end %>
/* 二分アキ */
.half_em_space { padding-top: 0.5em; }