From 857ce75f16a88f9cb3017ecb30f61e7bc4eaade4 Mon Sep 17 00:00:00 2001 From: rogenobl <153444176+rogenobl@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:05:38 +0900 Subject: [PATCH 1/3] Add support for encoding options of java18 or later --- lib/novelconverter.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/novelconverter.rb b/lib/novelconverter.rb index 446d6257..1a7437c0 100644 --- a/lib/novelconverter.rb +++ b/lib/novelconverter.rb @@ -165,7 +165,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) From 325a65de46a7b6292fd9ab148152de41460e15d5 Mon Sep 17 00:00:00 2001 From: happynow Date: Wed, 21 Feb 2024 00:07:04 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E9=9B=BB=E6=9B=B8=E5=8D=94=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=BC=E3=83=9E=E3=83=83=E3=83=88=E3=81=B8=E3=81=AE?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 電書協フォーマットの改造版(v1.1.1以降)に対応 --- lib/aozoraepub3.rb | 297 ++++++++++++++++++ lib/command/init.rb | 42 +-- lib/novelconverter.rb | 37 +-- ...al_font_with_dakuten.css => denshokyo.css} | 51 +-- preset/vertical_font.css | 10 + 5 files changed, 356 insertions(+), 81 deletions(-) create mode 100644 lib/aozoraepub3.rb rename preset/{vertical_font_with_dakuten.css => denshokyo.css} (65%) diff --git a/lib/aozoraepub3.rb b/lib/aozoraepub3.rb new file mode 100644 index 00000000..f2689aa8 --- /dev/null +++ b/lib/aozoraepub3.rb @@ -0,0 +1,297 @@ +# 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) + File.join(File.dirname(file_path) + "_custom", 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) + 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 1a7437c0..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) @@ -178,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 @@ -186,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; } From de425147a0b12dcbfac538ca5a2e37cb711fff8e Mon Sep 17 00:00:00 2001 From: happynow Date: Tue, 12 Mar 2024 20:54:44 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E9=9B=BB=E6=9B=B8=E5=8D=94=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=BC=E3=83=9E=E3=83=83=E3=83=88=E3=81=B8=E3=81=AE?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C(revison)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 電書協フォーマットの改造版(v1.1.1以降)に対応(revison) --- lib/aozoraepub3.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/aozoraepub3.rb b/lib/aozoraepub3.rb index f2689aa8..7da7faef 100644 --- a/lib/aozoraepub3.rb +++ b/lib/aozoraepub3.rb @@ -127,8 +127,12 @@ def clear_log end attr_reader :updated_file_paths, :copied_file_paths - def self.get_custom_file_path(file_path) - File.join(File.dirname(file_path) + "_custom", File.basename(file_path)) + 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ファイルのコピー @@ -197,7 +201,7 @@ def create_css_text2(original_css_path, css_template_path, yokogaki, use_dakuten # カスタムCSSファイルの配置 def create_custom_css_file(dst_css_file_path, css) - custom_css_file_path = AozoraResourceUpdater.get_custom_file_path(dst_css_file_path) + 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