Class: VivlioStarter::CLI::IndexCommands::HeadingOutline
- Inherits:
-
Object
- Object
- VivlioStarter::CLI::IndexCommands::HeadingOutline
- Defined in:
- lib/vivlio_starter/cli/index/heading_outline.rb
Overview
章の見出し構造
Defined Under Namespace
Constant Summary collapse
- HEADING =
行末は
$(改行の手前)で止める。\zにすると each_prose_line が渡す 改行つきの行にマッチしない。 /\A(\#{1,6})[ \t]+(\S.*?)[ \t]*$/
Instance Attribute Summary collapse
-
#headings ⇒ Object
readonly
Returns the value of attribute headings.
Class Method Summary collapse
-
.normalize(text) ⇒ Object
見出しの文言を比較用に均す。 見出しには強調・インラインコード・ルビ・索引タグが混ざるうえ、 「CSS 組版」と「CSS組版」のような空白の揺れもある。.
- .parse(content) ⇒ Object
Instance Method Summary collapse
-
#initialize(headings, total_lines) ⇒ HeadingOutline
constructor
A new instance of HeadingOutline.
-
#locate(path) ⇒ Located?
節の指定を行範囲へ解決する。.
-
#nearest(path, limit: 2) ⇒ Object
「近いもの」を 1〜2 件だけ挙げる。候補を並べ立てない (著者が探しているのは正解であって、選択肢の山ではない)。.
-
#summary(limit: 6) ⇒ Object
警告に添える見出しの一覧(先頭から数件).
Constructor Details
#initialize(headings, total_lines) ⇒ HeadingOutline
Returns a new instance of HeadingOutline.
72 73 74 75 |
# File 'lib/vivlio_starter/cli/index/heading_outline.rb', line 72 def initialize(headings, total_lines) @headings = headings @total_lines = total_lines end |
Instance Attribute Details
#headings ⇒ Object (readonly)
Returns the value of attribute headings.
42 43 44 |
# File 'lib/vivlio_starter/cli/index/heading_outline.rb', line 42 def headings @headings end |
Class Method Details
.normalize(text) ⇒ Object
見出しの文言を比較用に均す。 見出しには強調・インラインコード・ルビ・索引タグが混ざるうえ、 「CSS 組版」と「CSS組版」のような空白の揺れもある。
64 65 66 67 68 69 70 |
# File 'lib/vivlio_starter/cli/index/heading_outline.rb', line 64 def self.normalize(text) text.gsub(/`([^`]*)`/, '\1') .gsub(/\*{1,3}([^*]*)\*{1,3}/, '\1') .gsub(/\{([^|}]*)\|[^}]*\}/, '\1') .gsub(/\[([^\]|]*)(?:\|[^\]]*)?\]/, '\1') .gsub(/[[:space:]]+/, '') end |
.parse(content) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/vivlio_starter/cli/index/heading_outline.rb', line 45 def self.parse(content) headings = [] stack = [] Masking.each_prose_line(content) do |line, lineno| m = HEADING.match(line) or next level = m[1].size stack.pop while stack.any? && stack.last.level >= level headings << Heading.new( lineno:, level:, text: m[2], normalized: normalize(m[2]), ancestors: stack.map(&:normalized) ) stack.push(headings.last) end new(headings, content.lines.size) end |
Instance Method Details
#locate(path) ⇒ Located?
節の指定を行範囲へ解決する。
80 81 82 83 84 85 86 87 |
# File 'lib/vivlio_starter/cli/index/heading_outline.rb', line 80 def locate(path) wanted = path.map { self.class.normalize(it) } hits = @headings.select { matches?(it, wanted) } return nil if hits.empty? Located.new(range: range_of(hits.first), ambiguous: hits.size > 1, candidates: hits.map { describe(it) }) end |
#nearest(path, limit: 2) ⇒ Object
「近いもの」を 1〜2 件だけ挙げる。候補を並べ立てない (著者が探しているのは正解であって、選択肢の山ではない)。
96 97 98 99 100 101 102 103 104 |
# File 'lib/vivlio_starter/cli/index/heading_outline.rb', line 96 def nearest(path, limit: 2) wanted = self.class.normalize(path.last.to_s) return [] if wanted.empty? @headings.map { [it, similarity(it.normalized, wanted)] } .select { |_, score| score >= 0.5 } .max_by(limit) { |_, score| score } .map { |h, _| h.text } end |
#summary(limit: 6) ⇒ Object
警告に添える見出しの一覧(先頭から数件)
90 91 92 |
# File 'lib/vivlio_starter/cli/index/heading_outline.rb', line 90 def summary(limit: 6) @headings.map(&:text).first(limit) end |