Module: VivlioStarter::CLI::Import::PagebreakRestorer
- Defined in:
- lib/vivlio_starter/cli/import/pagebreak_restorer.rb
Overview
//clearpage の復元
Constant Summary collapse
- CLEARPAGE =
%r{\A//clearpage\s*\z}- REVIEW_COMMENT =
/\A\#@\#/- INLINE_MARKUP =
@<href>{url, テキスト}のような Re:VIEW のインライン記法 /@<[a-z]+>\{(.*?)\}/m- HEADING_MARK =
行頭の見出し記号・カラム記号(
=======[column]) /\A=+(?:\[[^\]]*\])?\s*/- DECORATION =
照合のときに両側から落とす飾り
/[*_`#>\s]|\A-\s/- FENCE_OPEN =
囲みの開き(
:::{.column}など) /\A:::\{/
Class Method Summary collapse
-
.clearpage_anchors(re_lines) ⇒ Object
//clearpageの直後にくる「素のテキスト」を出現順に返す. -
.comparable(text) ⇒ Object
飾りを落として突き合わせる(
**題名**と題名を同じものと見る). -
.hoist_above_container(lines, index) ⇒ Object
囲みの中に落ちたときは、いちばん外側の囲みの開きまで持ち上げる。 空行は消費しない——消費すると、入れ直した空行と重なって余分な空きになる.
-
.insertion_points(lines, anchors, md_path) ⇒ Object
Markdown 側の挿入位置を求める.
-
.plain_text(line) ⇒ Object
Re:VIEW の 1 行から素のテキストを取り出す。命令・コメントは対象外.
-
.previous_content_index(lines, from) ⇒ Object
直前の「空行でない行」の位置。無ければ nil.
- .restore!(temp_dir, starter_dir) ⇒ Object
-
.restore_chapter!(md_path, re_path) ⇒ Object
1 章ぶんを復元し、入れられた件数を返す.
- .warn_unplaced(md_path, anchor) ⇒ Object
Class Method Details
.clearpage_anchors(re_lines) ⇒ Object
//clearpage の直後にくる「素のテキスト」を出現順に返す
79 80 81 82 83 84 85 86 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 79 def clearpage_anchors(re_lines) re_lines.each_index.filter_map do |i| next unless CLEARPAGE.match?(re_lines[i].to_s.chomp) ((i + 1)...re_lines.size).filter_map { plain_text(re_lines[it]) } .find { !it.empty? } end.compact end |
.comparable(text) ⇒ Object
飾りを落として突き合わせる(**題名** と 題名 を同じものと見る)
135 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 135 def comparable(text) = text.to_s.gsub(DECORATION, '') |
.hoist_above_container(lines, index) ⇒ Object
囲みの中に落ちたときは、いちばん外側の囲みの開きまで持ち上げる。 空行は消費しない——消費すると、入れ直した空行と重なって余分な空きになる
104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 104 def hoist_above_container(lines, index) point = index loop do previous = previous_content_index(lines, point) break unless previous && FENCE_OPEN.match?(lines[previous]) point = previous end point end |
.insertion_points(lines, anchors, md_path) ⇒ Object
Markdown 側の挿入位置を求める
89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 89 def insertion_points(lines, anchors, md_path) cursor = 0 anchors.filter_map do |anchor| index = (cursor...lines.size).find { comparable(lines[it]).include?(comparable(anchor)) } next warn_unplaced(md_path, anchor) unless index point = hoist_above_container(lines, index) cursor = index + 1 point end end |
.plain_text(line) ⇒ Object
Re:VIEW の 1 行から素のテキストを取り出す。命令・コメントは対象外
125 126 127 128 129 130 131 132 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 125 def plain_text(line) text = line.to_s.strip return '' if text.empty? || text.start_with?('//') || REVIEW_COMMENT.match?(text) text.sub(HEADING_MARK, '') .gsub(INLINE_MARKUP) { Regexp.last_match(1).to_s.split(',').last.to_s.strip } .strip end |
.previous_content_index(lines, from) ⇒ Object
直前の「空行でない行」の位置。無ければ nil
118 119 120 121 122 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 118 def previous_content_index(lines, from) index = from - 1 index -= 1 while index >= 0 && lines[index].strip.empty? index.negative? ? nil : index end |
.restore!(temp_dir, starter_dir) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 46 def restore!(temp_dir, starter_dir) re_dir = SideimageRestorer.review_contents_dir(starter_dir) return unless Dir.exist?(re_dir) restored = Dir.glob(File.join(temp_dir, '*.md')).sum do |md_path| re_path = File.join(re_dir, "#{File.basename(md_path, '.md')}.re") File.exist?(re_path) ? restore_chapter!(md_path, re_path) : 0 end Common.log_info(" 改ページ(@pagebreak)を #{restored} 件復元しました") if restored.positive? end |
.restore_chapter!(md_path, re_path) ⇒ Object
1 章ぶんを復元し、入れられた件数を返す
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 59 def restore_chapter!(md_path, re_path) anchors = clearpage_anchors(File.readlines(re_path, encoding: 'utf-8')) return 0 if anchors.empty? lines = File.readlines(md_path, encoding: 'utf-8') points = insertion_points(lines, anchors, md_path) return 0 if points.empty? # 行番号がずれないよう後ろから入れる。直前が囲みの閉じなどで詰まっている # ときは空行を足す——@pagebreak は独立した 1 段落として置く記法のため points.sort.reverse_each do |point| lead = point.positive? && !lines[point - 1].strip.empty? ? "\n" : '' lines.insert(point, "#{lead}@pagebreak\n\n") end File.write(md_path, lines.join, encoding: 'utf-8') points.size end |
.warn_unplaced(md_path, anchor) ⇒ Object
137 138 139 140 141 142 143 |
# File 'lib/vivlio_starter/cli/import/pagebreak_restorer.rb', line 137 def warn_unplaced(md_path, anchor) Common.log_warn( " #{File.basename(md_path)}: //clearpage の位置を決められませんでした(目印: #{anchor[0, 20]})。", detail: '対処: 改ページしたい位置に @pagebreak と 1 行書いてください(22 章「改ページ」)。' ) nil end |