Module: VivlioStarter::CLI::Build::Utilities
- Defined in:
- lib/vivlio_starter/cli/build/utilities.rb
Overview
ビルド共通ユーティリティモジュール
Class Method Summary collapse
-
.build_pdf_with_body_guard!(output_path, min_pages:, attempts: 3) { ... } ⇒ true
本文 PDF(閲覧用 _sections.pdf / 入稿用 _sections_print.pdf)の生成を、 本文欠落に備えてリトライ付きで実行する。.
-
.chapter_numbers_for_book(entries_or_keep = nil) ⇒ Array<Integer>
1..89 範囲の章番号(整数)の配列を返す(新仕様).
-
.chapter_numbers_for_outline(entries_or_keep = nil) ⇒ Array<Integer>
PDF アウトライン生成対象の章番号リストを取得(新仕様).
-
.ensure_blank_page_pdf(path = 'blank_page.pdf') ⇒ Object
空白1ページPDFを生成.
-
.page_count(file) ⇒ Object
PDF のページ数を取得(pdfinfo → HexaPDF フォールバック → MIT版へ変更).
-
.page_size_points_from_config ⇒ Object
現在の設定からページサイズ(pt)を取得.
-
.page_size_strings_from_config ⇒ Object
現在の設定からページサイズ(文字列: mm/pt)を取得.
-
.resolve_entries(entries_or_keep) ⇒ Array<TokenResolver::Entry>
Entry 配列または basename 配列を Entry 配列に解決.
Class Method Details
.build_pdf_with_body_guard!(output_path, min_pages:, attempts: 3) { ... } ⇒ true
本文 PDF(閲覧用 _sections.pdf / 入稿用 _sections_print.pdf)の生成を、 本文欠落に備えてリトライ付きで実行する。
背景: 入稿用本文はトンボ・塗り足し付きの最重量レンダリングで、Chrome の 一過性失敗により本文欠落(数ページの degenerate)になる flaky があった。 従来は失敗が握り潰され、merge が front+colophon だけで「成功」してしまい、 約4ページの不正な PDF が出荷されていた。ここで本文相応のページ数を検証し、 失敗・degenerate ならリトライ、回復不能ならビルドを明示的に中断する (黙って本文欠落 PDF を残さない)。
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/vivlio_starter/cli/build/utilities.rb', line 63 def build_pdf_with_body_guard!(output_path, min_pages:, attempts: 3) attempts.times do |i| success = yield pages = page_count(output_path).to_i return true if success && File.exist?(output_path) && pages >= min_pages Common.log_warn( "[本文ガード] #{output_path} が生成失敗/本文欠落の疑い" \ "(success=#{success}, #{pages}p < 想定 #{min_pages}p)。再ビルドします(#{i + 1}/#{attempts})" ) end Common.log_error("[本文ガード] #{output_path} の本文生成に繰り返し失敗しました。ビルドを中止します。") exit 1 end |
.chapter_numbers_for_book(entries_or_keep = nil) ⇒ Array<Integer>
1..89 範囲の章番号(整数)の配列を返す(新仕様)
82 83 84 85 86 87 88 89 |
# File 'lib/vivlio_starter/cli/build/utilities.rb', line 82 def chapter_numbers_for_book(entries_or_keep = nil) entries = resolve_entries(entries_or_keep) entries .filter_map { it.number&.to_i } .grep(1..89) .uniq .sort end |
.chapter_numbers_for_outline(entries_or_keep = nil) ⇒ Array<Integer>
PDF アウトライン生成対象の章番号リストを取得(新仕様)
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/vivlio_starter/cli/build/utilities.rb', line 94 def chapter_numbers_for_outline(entries_or_keep = nil) # 新仕様: 0=PREFACE, 1-89=CHAPTERS, 90-98=APPENDICES, 99=POSTFACE allowed_numbers = [0, 99] + (1..89).to_a + (90..98).to_a entries = resolve_entries(entries_or_keep) numbers = entries .filter_map { it.number&.to_i } .select { allowed_numbers.include?(it) } # TOC (_toc.html) はアウトライン生成時に別途処理されるため、ここでは追加不要 numbers.uniq! numbers.sort! numbers end |
.ensure_blank_page_pdf(path = 'blank_page.pdf') ⇒ Object
空白1ページPDFを生成
128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/vivlio_starter/cli/build/utilities.rb', line 128 def ensure_blank_page_pdf(path = 'blank_page.pdf') return path if File.exist?(path) w_pt, h_pt = Build::Utilities.page_size_points_from_config require 'vivlio_starter/cli/pdf/provider' VivlioStarter::Pdf.provider.ensure_blank_page_pdf(path, w_pt, h_pt) # --- 旧実装(MIT化動作確認後に削除予定) --- # doc = HexaPDF::Document.new # w_pt, h_pt = Build::Utilities.page_size_points_from_config # doc.pages.add([0, 0, w_pt, h_pt]) # doc.write(path, optimize: true) # path end |
.page_count(file) ⇒ Object
PDF のページ数を取得(pdfinfo → HexaPDF フォールバック → MIT版へ変更)
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/vivlio_starter/cli/build/utilities.rb', line 27 def page_count(file) return nil unless File.exist?(file) # pdfinfo を優先 if system('which pdfinfo >/dev/null 2>&1') info = `pdfinfo "#{file}" 2>/dev/null` pages = info[/^Pages:\s+(\d+)/i, 1] return pages.to_i if pages end # 新実装 (MIT版 Provider への委譲) require 'vivlio_starter/cli/pdf/provider' VivlioStarter::Pdf.provider.page_count(file) # --- 旧実装(MIT化動作確認後に削除予定) --- # doc = HexaPDF::Document.open(file) # doc.pages.count rescue StandardError nil end |
.page_size_points_from_config ⇒ Object
現在の設定からページサイズ(pt)を取得
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/vivlio_starter/cli/build/utilities.rb', line 156 def page_size_points_from_config width_s, height_s = page_size_strings_from_config mm_to_pt = Units::PT_PER_MM parse_len = lambda { |s| str = s.to_s.strip.downcase if str.end_with?('mm') str.sub(/mm\z/, '').to_f * mm_to_pt elsif str.end_with?('pt') str.sub(/pt\z/, '').to_f else str.to_f end } w_pt = parse_len.call(width_s) h_pt = parse_len.call(height_s) if w_pt <= 0 || h_pt <= 0 || w_pt.nan? || h_pt.nan? w_pt = 182.0 * mm_to_pt h_pt = 257.0 * mm_to_pt end [w_pt, h_pt] end |
.page_size_strings_from_config ⇒ Object
現在の設定からページサイズ(文字列: mm/pt)を取得
144 145 146 147 148 149 150 151 152 153 |
# File 'lib/vivlio_starter/cli/build/utilities.rb', line 144 def page_size_strings_from_config result = Common.resolve_page_size(Common::CONFIG.page.to_h) if result.is_a?(Array) && result.size == 2 && result.all? do |dim| dim.to_s.strip.match?(/\A[0-9.]+(mm|pt)?\z/) end result else %w[182mm 257mm] end end |
.resolve_entries(entries_or_keep) ⇒ Array<TokenResolver::Entry>
Entry 配列または basename 配列を Entry 配列に解決
113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/vivlio_starter/cli/build/utilities.rb', line 113 def resolve_entries(entries_or_keep) raw = Array(entries_or_keep).compact if raw.empty? # 全ファイルを解決 resolver = TokenResolver::Resolver.new Dir[File.join(Common::CONTENTS_DIR, '*.md')].map { resolver.resolve_file(it) } elsif raw.first.respond_to?(:kind) raw else resolver = TokenResolver::Resolver.new raw.map { resolver.resolve_file(it) } end end |