Module: Mdlint::Toc
- Defined in:
- lib/mdlint/toc.rb,
sig/mdlint.rbs,
sig/internal.rbs
Constant Summary collapse
- START_MARKERS =
["<!-- toc -->", "<!-- toc:start -->"].freeze
- END_MARKERS =
["<!-- toc -->", "<!-- toc:end -->"].freeze
Class Method Summary collapse
- .marker_pairs(lines) ⇒ Array[Array[Integer]]
- .slugify(value, counts) ⇒ String
- .table_of_contents(tokens) ⇒ Array[String]
- .update(source, options = {}) ⇒ String
Instance Method Summary collapse
Class Method Details
.marker_pairs(lines) ⇒ Array[Array[Integer]]
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/mdlint/toc.rb', line 40 def marker_pairs(lines) pairs = [] index = 0 while index < lines.length marker = lines[index].strip.downcase if marker == "<!-- toc:start -->" ending = lines[(index + 1)..]&.index { |line| line.strip.downcase == "<!-- toc:end -->" } if ending pairs << [index, index + ending + 1] index += ending + 1 end elsif marker == "<!-- toc -->" ending = lines[(index + 1)..]&.index { |line| line.strip.downcase == "<!-- toc -->" } if ending pairs << [index, index + ending + 1] index += ending + 1 end end index += 1 end pairs end |
.slugify(value, counts) ⇒ String
63 64 65 66 67 68 69 70 71 72 |
# File 'lib/mdlint/toc.rb', line 63 def slugify(value, counts) base = value.gsub(/[`*_~\[\]()<>]/, "") .downcase .gsub(/[^\p{Alnum}\p{Han}\p{Hiragana}\p{Katakana}\p{Hangul}\s-]/, "") .strip .gsub(/\s+/, "-") suffix = counts[base] counts[base] += 1 suffix.zero? ? base : "#{base}-#{suffix}" end |
.table_of_contents(tokens) ⇒ Array[String]
25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/mdlint/toc.rb', line 25 def table_of_contents(tokens) counts = Hash.new(0) tokens.each_with_index.filter_map do |token, index| next unless token.type == :heading_open inline = tokens[(index + 1)..]&.find { |candidate| candidate.type == :inline } title = inline&.content.to_s.strip slug = slugify(title, counts) next if title.empty? || slug.empty? level = token.tag.to_s.delete_prefix("h").to_i "#{" " * [level - 1, 0].max}- [#{title}](##{slug})" end end |
.update(source, options = {}) ⇒ String
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/mdlint/toc.rb', line 10 def update(source, = {}) eol = source.include?("\r\n") ? "\r\n" : "\n" normalized_source = source.gsub("\r\n", "\n") lines = normalized_source.split("\n", -1) heading_tokens = Parser.parse(normalized_source, ) entries = table_of_contents(heading_tokens) replacement = entries.join("\n") marker_pairs(lines).reverse_each do |pair| start_index = pair.fetch(0) end_index = pair.fetch(1) lines[(start_index + 1)...end_index] = replacement.empty? ? [] : replacement.lines(chomp: true) end lines.join(eol) end |
Instance Method Details
#update(source, options = {}) ⇒ String
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/mdlint/toc.rb', line 10 def update(source, = {}) eol = source.include?("\r\n") ? "\r\n" : "\n" normalized_source = source.gsub("\r\n", "\n") lines = normalized_source.split("\n", -1) heading_tokens = Parser.parse(normalized_source, ) entries = table_of_contents(heading_tokens) replacement = entries.join("\n") marker_pairs(lines).reverse_each do |pair| start_index = pair.fetch(0) end_index = pair.fetch(1) lines[(start_index + 1)...end_index] = replacement.empty? ? [] : replacement.lines(chomp: true) end lines.join(eol) end |