Module: VivlioStarter::CLI::PreProcessCommands::TableConverter
- Defined in:
- lib/vivlio_starter/cli/pre_process/table_converter.rb
Overview
拡張パイプテーブル変換(統合テーブル変換)
Defined Under Namespace
Constant Summary collapse
- PIPE_PLACEHOLDER =
セル内エスケープ
\|を退避する一時マーカー(分割規則から除外するため)。 "\u{E000}"- CELL_PAD_MM =
--- 版面自動フィット(§6.2)の凍結定数 --- セル左右パディングの中庸値(mm)。table.css の padding clamp(0.6〜1.4mm)+罫線幅の中間。
1.2- SAFETY =
文字幅推定(プロポーショナル欧文等)の誤差を吸収する安全率。
0.95- SCALE_MIN =
縮小率の下限。これ未満は可読性が失われるため止め、著者に縮小限界の判断を委ねる。
0.30- SCALE_MAX =
拡大率の上限。回転テーブルは専用ページを与えられるので版面いっぱいまで拡大してよいが、 行数・列数の少ない表は「版面に収める」だけだと何倍にでも伸びてしまう (実測: 4 列 2 行の表で 555%)。本文の 2 倍を超える文字で組まれた表は、 表というよりポスターに見えるのでここで止める。
2.0- ROTATE_ID_PREFIX =
回転テーブルのラッパへ振る内部 ID の接頭辞。Kindle では KFX が transform を 解さないため PDF の該当ページを画像へ焼いて差し替えるが、その「該当ページ」を 引く目印がこの ID になる(kindle-rotate-table-image-spec.md §4)。 本文からは参照しないので、著者に見える記法は増やさない。
'rot-'
Class Method Summary collapse
-
.assign_rotate_id(attrs, source_basename, index) ⇒ Object
回転テーブルのラッパに内部 ID を振る(Kindle 画像化の目印・§4)。 章 basename と章内の出現順で決まるので、原稿が動かなければ ID も動かない。 著者が既に id を書いていればそちらを尊重する。.
-
.convert_container_inner(content, class_name, page_cfg: nil, source_basename: nil) ⇒ Object
…の内側テーブルを拡張変換する。 テーブルブロックは常に自前パーサ(不成立ブロックのみ Kramdown へフォールバック)、 非テーブル区間(キャプション段落等)は Kramdown で描画し、出現順に結合する。 class_name が 'rotate-table' かつ page_cfg があれば版面自動フィットを style へマージし、 source_basename があれば Kindle 画像化用の内部 ID を振る。.
-
.estimate_rotate_style(table_model, page_cfg) ⇒ Hash
rotate-table の版面自動フィット(§6.2)。純粋関数(CONFIG を直接参照しない)。.
-
.intercept_extended_tables(content) ⇒ Array(String, Integer)
コンテナ外の素パイプテーブルのうち、拡張記法(colspan / 複数行ヘッダー)を 含むものだけを横取りして生
HTML へ変換する(§4)。 コードフェンス・インラインコード内は Masking で退避して誤検出を防ぐ。.
- .pipe_table_to_html(md_text) ⇒ String?
拡張パイプテーブル 1 個を HTML 化する。不成立(テーブルでない)なら nil。.
- .rotate_anchor_id(source_basename, index) ⇒ Object
Class Method Details
.assign_rotate_id(attrs, source_basename, index) ⇒ Object
回転テーブルのラッパに内部 ID を振る(Kindle 画像化の目印・§4)。 章 basename と章内の出現順で決まるので、原稿が動かなければ ID も動かない。 著者が既に id を書いていればそちらを尊重する。
99 100 101 102 103
# File 'lib/vivlio_starter/cli/pre_process/table_converter.rb', line 99 def assign_rotate_id(attrs, source_basename, index) return attrs if attrs.match?(/\bid\s*=/) %(id="#{rotate_anchor_id(source_basename, index)}" #{attrs}) end
.convert_container_inner(content, class_name, page_cfg: nil, source_basename: nil) ⇒ Object
…の内側テーブルを拡張変換する。 テーブルブロックは常に自前パーサ(不成立ブロックのみ Kramdown へフォールバック)、 非テーブル区間(キャプション段落等)は Kramdown で描画し、出現順に結合する。 class_name が 'rotate-table' かつ page_cfg があれば版面自動フィットを style へマージし、 source_basename があれば Kindle 画像化用の内部 ID を振る。78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
# File 'lib/vivlio_starter/cli/pre_process/table_converter.rb', line 78 def convert_container_inner(content, class_name, page_cfg: nil, source_basename: nil) rotate = class_name == 'rotate-table' index = 0 pattern = %r{<div\s+([^>]*\bclass="[^"]*\b#{Regexp.escape(class_name)}\b[^"]*"[^>]*)>\s*(.*?)\s*</div>}m content.gsub(pattern) do attrs = ::Regexp.last_match(1) inner = ::Regexp.last_match(2) html = render_container_inner(inner) if rotate attrs = merge_rotate_style(attrs, inner, page_cfg) if page_cfg attrs = assign_rotate_id(attrs, source_basename, index += 1) if source_basename end "<div #{attrs}>\n#{html}\n</div>" end end
.estimate_rotate_style(table_model, page_cfg) ⇒ Hash
rotate-table の版面自動フィット(§6.2)。純粋関数(CONFIG を直接参照しない)。
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
# File 'lib/vivlio_starter/cli/pre_process/table_converter.rb', line 151 def estimate_rotate_style(table_model, page_cfg) page_w, page_h = Common.resolve_page_size(page_cfg).map { Units.length_to_mm(it) } content_w = page_w - mm(page_cfg[:margin_inner]) - mm(page_cfg[:margin_outer]) content_h = page_h - mm(page_cfg[:margin_top]) - mm(page_cfg[:margin_bottom]) height = { 'rotate-table-height' => "#{content_h.round(1)}mm" } font_mm = Units.length_to_mm(page_cfg[:base_font_size]) line_height_mm = Units.length_to_mm(page_cfg[:base_line_height]) return height unless font_mm && line_height_mm table_w, table_h = table_dimensions_mm(table_model, font_mm, line_height_mm) return height if table_w.zero? || table_h.zero? # -90°回転で幅↔高さが入れ替わる。回転後にページ版面へ収める縮尺。 # # **等倍で頭打ちにしない。** 回転テーブルは `break-before/after: page` で専用ページを # 与えられているので、そこに余白を残す理由がない。かつては上限 1.0 を掛けており、 # 実測で版面高さの 68% しか使えていなかった(7 列 4 行の表で scale 90%・ # kindle-rotate-table-image-spec.md §8 の画像で判明)。 scale = [content_h / table_w, content_w / table_h].min * SAFETY scale = scale.clamp(SCALE_MIN, SCALE_MAX) scale = (scale / 0.05).floor * 0.05 # 5% 刻みへ切り捨て height.merge('rotate-table-scale' => "#{(scale * 100).round}%") end
.intercept_extended_tables(content) ⇒ Array(String, Integer)
コンテナ外の素パイプテーブルのうち、拡張記法(colspan / 複数行ヘッダー)を 含むものだけを横取りして生
HTML へ変換する(§4)。 コードフェンス・インラインコード内は Masking で退避して誤検出を防ぐ。
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
# File 'lib/vivlio_starter/cli/pre_process/table_converter.rb', line 113 def intercept_extended_tables(content) protected_text, spans = Masking.protect_code(content) out = +'' count = 0 lines = protected_text.lines i = 0 while i < lines.size unless table_block_line?(lines[i]) out << lines[i] i += 1 next end # --- テーブルブロックを収集 --- j = i j += 1 while j < lines.size && table_block_line?(lines[j]) block = lines[i...j].join html = intercept_candidate?(block) ? pipe_table_to_html(block) : nil if html count += 1 out << "\n" unless out.empty? || out.end_with?("\n\n") out << html << "\n\n" else out << block end i = j end [Masking.restore_code(out, spans), count] end
.pipe_table_to_html(md_text) ⇒ String?
拡張パイプテーブル 1 個を HTML 化する。不成立(テーブルでない)なら nil。
65 66 67 68 69 70
# File 'lib/vivlio_starter/cli/pre_process/table_converter.rb', line 65 def pipe_table_to_html(md_text) table = parse(md_text) return nil unless table render_table(table) end
.rotate_anchor_id(source_basename, index) ⇒ Object
107
# File 'lib/vivlio_starter/cli/pre_process/table_converter.rb', line 107 def rotate_anchor_id(source_basename, index) = "#{ROTATE_ID_PREFIX}#{source_basename}-#{index}"
- .pipe_table_to_html(md_text) ⇒ String?