Class: VivlioStarter::CLI::PdfCommands::PdfCompressor

Inherits:
Object
  • Object
show all
Defined in:
lib/vivlio_starter/cli/pdf.rb

Overview

Ghostscript を利用して PDF を圧縮する

動作モード(options):

- false(既定): vs pdf:compress の単体実行。利用者の明示要求のため、
gs 不在・圧縮失敗は 🔴 エラー + exit 1 で報告する
- true: vs build の Step 12 から呼ばれる。PDF は生成済みのため、
gs 不在・圧縮失敗でもビルドを止めず 🟡 でスキップを案内して続行する

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options, cli_input = nil, cli_output = nil) ⇒ PdfCompressor

Returns a new instance of PdfCompressor.



223
224
225
226
227
228
229
230
231
# File 'lib/vivlio_starter/cli/pdf.rb', line 223

def initialize(options, cli_input = nil, cli_output = nil)
  @options = options || {}
  @cli_input = cli_input
  @cli_output = cli_output
  @input_pdf = nil
  @output_pdf = nil
  @compression_success = false
  @skipped = false
end

Class Method Details

.bleed_box?(path) ⇒ Boolean

ボックスで見る。入稿用は塗り足しぶん MediaBox が広く、TrimBox が仕上がり線を指す。

Pdf.provider を経由せず pdfinfo -box で足りる——入稿用かどうかを知るだけなら、 プロバイダの重い依存を持ち込む必要がない(§5)。

Returns:

  • (Boolean)


210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/vivlio_starter/cli/pdf.rb', line 210

def self.bleed_box?(path)
  out, status = Open3.capture2('pdfinfo', '-box', path, err: File::NULL)
  return false unless status.success?

  media = out[/^MediaBox:\s*(.+)$/, 1]
  trim  = out[/^TrimBox:\s*(.+)$/, 1]
  return false unless media && trim

  media.split != trim.split
rescue StandardError
  false
end

.configured_project_nameObject

設定からプロジェクト名を引く(設定が無い直接ビルド等では nil)。



200
201
202
203
204
# File 'lib/vivlio_starter/cli/pdf.rb', line 200

def self.configured_project_name
  return nil unless Common.configured?

  Common::CONFIG.project&.name
end

名前で見る。

generate_print_pdf_filename の戻り値と厳密一致させてはならない。 include_version: false なら _v1.0.0 が付かず、手元には過去のバージョンで ビルドしたものも残っている。バージョンは付いたり付かなかったりするが _print は必ず付くので、前方一致で 3 つの場面すべてを拾う(§3.1)。

Returns:

  • (Boolean)


193
194
195
196
197
# File 'lib/vivlio_starter/cli/pdf.rb', line 193

def self.print_pdf_filename?(path, project_name)
  return false if project_name.to_s.empty?

  File.basename(path).start_with?("#{project_name}_print")
end

入稿用 PDF かどうかを判定する(print-pdf-compress-guard-spec.md §3)。

2 つの手掛かりを OR で見る。 どちらか一方では取りこぼす——ファイル名は著者が リネームすると外れ、ページボックスは crop_marks: false の本では効かない (塗り足しが無く MediaBox = TrimBox のままになる)。両方が外れる「crop_marks なし + リネーム済み」は検出できないが、それは仕様上の限界として受け入れる—— 判定を緩めると閲覧用 PDF にまで警告が出て狼少年になる(§3.3)。

純粋関数なのでクラスメソッドに置く(インスタンス状態にも設定にも依らずテストできる)。

Returns:

  • (Boolean)


183
184
185
# File 'lib/vivlio_starter/cli/pdf.rb', line 183

def self.print_pdf_input?(path, project_name = configured_project_name)
  print_pdf_filename?(path, project_name) || bleed_box?(path)
end

Instance Method Details

#callObject



233
234
235
236
237
238
239
240
241
242
# File 'lib/vivlio_starter/cli/pdf.rb', line 233

def call
  apply_verbose
  determine_paths
  ensure_input_exists
  return unless confirm_print_pdf_compression

  Common.log_action("PDFを圧縮しています…(入力: #{input_pdf} → 出力: #{output_pdf}")
  compress_pdf
  report_result
end