Class: VivlioStarter::CLI::Build::PdfPageMapExtractor
- Inherits:
-
Object
- Object
- VivlioStarter::CLI::Build::PdfPageMapExtractor
- Defined in:
- lib/vivlio_starter/cli/build/pdf_page_map_extractor.rb
Overview
生成済み PDF の named destinations からページマッピングを抽出する
Defined Under Namespace
Classes: IndexMappingEntry, MappingEntry, PageMapping
Constant Summary collapse
- GLOSSARY_PREFIX =
vivliostyle が付ける named destination の接頭辞(アンカー ID は最初の
#以降) 'gls-src-'- INDEX_PREFIX =
'idx-'
Class Method Summary collapse
-
.decode_destination_name(name) ⇒ String
vivliostyle の
:XXXX(UTF-16 コードユニットの 4 桁 hex)エスケープを復号する。 元名前中の:や#はすべてエスケープされるため、区切りの取り違えは起きない。 想定外の入力では復号せず元文字列を返し、呼び出し側の#判定で自然に捨てられる。.
Instance Method Summary collapse
-
#document_first_pages ⇒ Hash{String => Integer}
スパイン文書(HTML ベース名)→ その文書が始まる通しページ番号。.
- #extract! ⇒ PageMapping
-
#initialize(pdf_path) ⇒ PdfPageMapExtractor
constructor
A new instance of PdfPageMapExtractor.
-
#pages_for(ids) ⇒ Hash{String => Integer}
指定したアンカー ID の通しページ番号を引く。.
Constructor Details
#initialize(pdf_path) ⇒ PdfPageMapExtractor
Returns a new instance of PdfPageMapExtractor.
50 51 52 |
# File 'lib/vivlio_starter/cli/build/pdf_page_map_extractor.rb', line 50 def initialize(pdf_path) @pdf_path = pdf_path end |
Class Method Details
.decode_destination_name(name) ⇒ String
vivliostyle の :XXXX(UTF-16 コードユニットの 4 桁 hex)エスケープを復号する。
元名前中の : や # はすべてエスケープされるため、区切りの取り違えは起きない。
想定外の入力では復号せず元文字列を返し、呼び出し側の # 判定で自然に捨てられる。
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/vivlio_starter/cli/build/pdf_page_map_extractor.rb', line 118 def self.decode_destination_name(name) source = name.to_s units = [] i = 0 while i < source.length if source[i] == ':' && source[i + 1, 4]&.match?(/\A\h{4}\z/) units << source[i + 1, 4].hex i += 5 else units << source[i].ord i += 1 end end units.pack('U*') rescue StandardError name.to_s end |
Instance Method Details
#document_first_pages ⇒ Hash{String => Integer}
スパイン文書(HTML ベース名)→ その文書が始まる通しページ番号。
/Dests の名前には元 URL が丸ごと入っているため、# の手前を見れば
その destination がどの文書由来かが分かる。vivliostyle はスパイン文書ごとに
必ず改ページするので、1 文書内の最小ページ=その文書の開始ページになる。
id を 1 つも持たない文書は結果に現れない。呼び出し側は「欲しい文書の鍵が 取れたか」で判定すること——件数では判定できない。
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/vivlio_starter/cli/build/pdf_page_map_extractor.rb', line 81 def document_first_pages return {} unless File.exist?(pdf_path) each_destination(::PDF::Reader.new(pdf_path)).each_with_object({}) do |(document, _anchor, page), first| key = File.basename(document.to_s, '.html') next if key.empty? first[key] = page if first[key].nil? || page < first[key] end end |
#extract! ⇒ PageMapping
56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/vivlio_starter/cli/build/pdf_page_map_extractor.rb', line 56 def extract! raise "本文 PDF が見つかりません: #{pdf_path}" unless File.exist?(pdf_path) reader = ::PDF::Reader.new(pdf_path) anchor_to_page = build_anchor_page_map(reader) if anchor_to_page.empty? raise '本文 PDF に named destinations(/Dests)が見つかりません。' \ 'vivliostyle の出力仕様が変わった可能性があります' end Common.log_success("[backlink-dedup] ページマッピングを取得しました(#{anchor_to_page.size} 件)") build_page_mapping(anchor_to_page, reader.page_count) end |
#pages_for(ids) ⇒ Hash{String => Integer}
指定したアンカー ID の通しページ番号を引く。
document_first_pages が「文書 → 開始ページ」を返すのに対し、こちらは
「任意の id → その id が組まれたページ」を返す。回転テーブルの画像化が
使う(kindle-rotate-table-image-spec.md §4)。
引けなかった ID は戻り値に現れない。 /Dests に出るのはリンクの飛び先に
なっている id だけなので、呼び出し側は「欲しい ID の鍵が取れたか」で判定すること。
103 104 105 106 107 108 109 110 |
# File 'lib/vivlio_starter/cli/build/pdf_page_map_extractor.rb', line 103 def pages_for(ids) wanted = Array(ids).uniq return {} if wanted.empty? || !File.exist?(pdf_path) each_destination(::PDF::Reader.new(pdf_path)).each_with_object({}) do |(_document, anchor, page), found| found[anchor] = page if wanted.include?(anchor) end end |