class Headings
Extracts headings from a markdown document with unique anchor IDs. Handles duplicate heading text by appending counters (e.g., "deployment", "deployment-2", "deployment-3").
Definitions
def initialize
Initializes an empty heading-anchor registry.
Implementation
def initialize
@ids = {}
end
def anchor_for(node)
Generate a unique anchor for a node.
Signature
-
parameter
nodeMarkly::Node The heading node.
-
returns
String A unique anchor ID.
Implementation
def anchor_for(node)
base = base_anchor_for(node)
if @ids.key?(base)
@ids[base] += 1
"#{base}-#{@ids[base]}"
else
@ids[base] = 1
base
end
end
def extract(root, min_level: 1, max_level: 6)
Extract all headings from a document root with unique anchors.
Signature
-
parameter
rootMarkly::Node The document root node.
-
parameter
min_levelInteger The minimum heading level to extract.
-
parameter
max_levelInteger The maximum heading level to extract.
-
returns
Array(Heading) The extracted headings with unique anchors.
Implementation
def extract(root, min_level: 1, max_level: 6)
headings = []
root.walk do |node|
if node.type == :header
level = node.header_level
next if level < min_level || level > max_level
headings << Heading.new(
node: node,
level: level,
text: node.to_plaintext.chomp,
anchor: anchor_for(node)
)
end
end
headings
end
def self.extract(root, min_level: 1, max_level: 6)
Extract all headings using a new heading-anchor registry.
Signature
-
parameter
rootMarkly::Node The document root node.
-
parameter
min_levelInteger The minimum heading level to extract.
-
parameter
max_levelInteger The maximum heading level to extract.
-
returns
Array(Heading) The extracted headings with unique anchors.
Implementation
def self.extract(root, min_level: 1, max_level: 6)
new.extract(root, min_level: min_level, max_level: max_level)
end
def base_anchor_for(node)
Generate a base anchor from a node's text content.
Signature
-
parameter
nodeMarkly::Node The heading node.
-
returns
String The lowercase, hyphenated base anchor.
Implementation
def base_anchor_for(node)
text = node.to_plaintext.chomp.downcase
text.gsub(/\s+/, "-")
end