Module: VivlioStarter::CLI::PreProcessCommands::CrossReferenceProcessor
- Defined in:
- lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb
Overview
クロスリファレンス処理モジュール rubocop:disable Metrics/ModuleLength
Defined Under Namespace
Classes: CaptionedBlockTransformer, Label, LabelCollectorContext, ReferenceReplacer
Constant Summary collapse
- LABEL_TYPE_NAMES =
ラベル種別の日本語名(sec は見出しラベル・at-directive-tier1-spec.md §2.4.1)
{ list: 'リスト', table: '表', fig: '図', sec: '節' }.freeze
- CAPTION_PATTERN =
/^\*\*\s*(.+?)\s+@([-\w]+)\s*\*\*\s*$/- HEADING_LABEL_PATTERN =
見出し行末の
@id(見出しラベル)。紙面には出さずアンカーだけを残す。 /^(\#{1,6})\s+(.+?)\s+@([-\w]+)\s*$/- RESERVED_IDS =
自動採番用の予約ID(キャプションで @auto / @omakase / @id と書くと type-chapter-N 形式に採番される)
%w[auto omakase id].freeze
- RESERVED_MACRO_IDS =
組み込み置換ルール(ReplacementRules)・ビルド生成物(QrTransformer)の マクロ名(完全一致で予約)。これは @ID 参照ではなくシステム予約のマクロなので、 未定義のラベルIDとして警告せず後段(post_process / pre_process)へ素通しする。 (@nega/@posi の後方互換別名・@comment/@commend の編集者コメントは廃止済み)
%w[vspace hspace pagebreak pageref version today title qr].freeze
- IMAGE_PATTERN =
/^!\[[^\]]*\]\([^)]+\)(?:\{[^}]+\})?$/- MAIN_CHAPTER_RANGE =
PostProcessCommands::HeadingProcessor::MAIN_CHAPTER_RANGE
Class Method Summary collapse
-
.appendix_letter_for(filename) ⇒ Object
付録ファイル(90〜98)の図表番号プレフィックスに使う付録レター("A".."I")を返す。 付録の見出し(付録 D)・節番号(D-1)と図表番号(表 D-1)を一致させるため、 付録では章番号ではなくレターを用いる。本文章・前後付では nil を返し、 各呼び出し元の既存挙動(章番号 / 表示番号)を維持する。.
-
.build_labels_map_with_duplicates_check(all_labels) ⇒ Hash
ラベルマップ構築(重複チェック付き).
-
.code_line_numbers(content) ⇒ Object
コード(フェンス区切り行・内容行)とみなす行番号(1 始まり)の集合を Masking で判定する。 各内部クラスのフェンス追跡(自前の状態機械)を Masking(唯一の実装)へ一元化するための述語。 可変長フェンス・入れ子・~~~・```include: 除外に一貫して追従する。.
-
.collect_labels(content, source_file, chapter_number) ⇒ Object
ラベル収集.
- .detect_block_type(lines, idx) ⇒ Object
- .display_chapter_number_for_filename(filename) ⇒ Object
- .extract_caption_label(line) ⇒ Object
-
.extract_chapter_number(filename) ⇒ Object
章番号関連.
-
.extract_heading_label(line) ⇒ Object
見出し行末の
@idを取り出す(## インストール @install)。 見出しラベルは @pageref / @id 参照の飛び先になる(at-directive-tier1-spec.md §1.1)。. -
.replace_references(content, labels_map, filename = nil) ⇒ Object
参照置換.
-
.reserved_id?(label_id) ⇒ Boolean
予約IDの判定を一元化する。 RESERVED_IDS: auto / omakase / id RESERVED_MACRO_IDS: vspace / hspace / pagebreak / …(完全一致).
-
.transform_captioned_blocks(content, filename, labels_map) ⇒ Object
キャプション付きブロック変換.
Class Method Details
.appendix_letter_for(filename) ⇒ Object
付録ファイル(90〜98)の図表番号プレフィックスに使う付録レター("A".."I")を返す。 付録の見出し(付録 D)・節番号(D-1)と図表番号(表 D-1)を一致させるため、 付録では章番号ではなくレターを用いる。本文章・前後付では nil を返し、 各呼び出し元の既存挙動(章番号 / 表示番号)を維持する。
138 139 140 141 142 143 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 138 def appendix_letter_for(filename) num = extract_chapter_number(filename).to_i return nil unless (90..98).cover?(num) Common.appendix_number_to_letter(num)&.upcase end |
.build_labels_map_with_duplicates_check(all_labels) ⇒ Hash
ラベルマップ構築(重複チェック付き)
251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 251 def build_labels_map_with_duplicates_check(all_labels) map = {} # IDごとに全ラベルを蓄積する(先勝ちで map に登録) all_occurrences = Hash.new { |h, k| h[k] = [] } all_labels.each do |label| all_occurrences[label.id] << label map[label.id] ||= label end duplicates_by_id = all_occurrences.select { |_, labels| labels.size > 1 } { labels_map: map, duplicates_by_id: } end |
.code_line_numbers(content) ⇒ Object
コード(フェンス区切り行・内容行)とみなす行番号(1 始まり)の集合を Masking で判定する。 各内部クラスのフェンス追跡(自前の状態機械)を Masking(唯一の実装)へ一元化するための述語。 可変長フェンス・入れ子・~~~・```include: 除外に一貫して追従する。
76 77 78 79 80 81 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 76 def code_line_numbers(content) prose = Set.new Masking.each_prose_line(content) { |_line, lineno| prose << lineno } total = content.each_line.count (1..total).reject { prose.include?(it) }.to_set end |
.collect_labels(content, source_file, chapter_number) ⇒ Object
ラベル収集
146 147 148 149 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 146 def collect_labels(content, source_file, chapter_number) collector = LabelCollectorContext.new(source_file, chapter_number) collector.collect(content) end |
.detect_block_type(lines, idx) ⇒ Object
100 101 102 103 104 105 106 107 108 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 100 def detect_block_type(lines, idx) ((idx + 1)...lines.size).each do |index| line = lines[index].strip next if line.empty? || line.start_with?(':::{') return detect_type_from_line(line) end nil end |
.display_chapter_number_for_filename(filename) ⇒ Object
125 126 127 128 129 130 131 132 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 125 def display_chapter_number_for_filename(filename) num = extract_chapter_number(filename).to_i return num.to_s unless MAIN_CHAPTER_RANGE.include?(num) token = File.basename(filename, File.extname(filename)) idx = main_chapter_order.index(token) idx ? (idx + 1).to_s : (num - 10).to_s end |
.extract_caption_label(line) ⇒ Object
83 84 85 86 87 88 89 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 83 def extract_caption_label(line) match = line.match(CAPTION_PATTERN) return nil unless match { title: match[1].strip, id: match[2].strip, auto: RESERVED_IDS.include?(match[2].strip) } end |
.extract_chapter_number(filename) ⇒ Object
章番号関連
120 121 122 123 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 120 def extract_chapter_number(filename) match = File.basename(filename, '.*').match(/^(\d+)/) match ? match[1] : '0' end |
.extract_heading_label(line) ⇒ Object
見出し行末の @id を取り出す(## インストール @install)。
見出しラベルは @pageref / @id 参照の飛び先になる(at-directive-tier1-spec.md §1.1)。
93 94 95 96 97 98 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 93 def extract_heading_label(line) match = line.match(HEADING_LABEL_PATTERN) return nil unless match { level: match[1].length, title: match[2].strip, id: match[3].strip } end |
.replace_references(content, labels_map, filename = nil) ⇒ Object
参照置換
244 245 246 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 244 def replace_references(content, labels_map, filename = nil) ReferenceReplacer.new(content, labels_map, filename).replace end |
.reserved_id?(label_id) ⇒ Boolean
予約IDの判定を一元化する。 RESERVED_IDS: auto / omakase / id RESERVED_MACRO_IDS: vspace / hspace / pagebreak / …(完全一致)
50 51 52 53 54 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 50 def self.reserved_id?(label_id) return true if RESERVED_IDS.include?(label_id) RESERVED_MACRO_IDS.include?(label_id) end |
.transform_captioned_blocks(content, filename, labels_map) ⇒ Object
キャプション付きブロック変換
239 240 241 |
# File 'lib/vivlio_starter/cli/pre_process/cross_reference_processor.rb', line 239 def transform_captioned_blocks(content, filename, labels_map) CaptionedBlockTransformer.new(content, filename, labels_map).transform end |