Improve dom_id uniqueness in guides

All headers in a guide get a unique `dom_id` to make anchor links work.
If a header is already present we would prefix it with the `dom_id` of
the parent node. This would not work for headers without parent nodes.

This commit simplifies the `dom_id` uniqueness by only prepending the
parent node if it exists. This can still result in duplicates at the
same level, but for these we already show a warning:

    *** DUPLICATE ID: 'some_id', please make sure that there are no
    headings with the same name at the same level.

Co-authored-by: Carlos Antonio da Silva <carlosantoniodasilva@gmail.com>
This commit is contained in:
Petrik 2024-02-06 20:45:44 +01:00
parent bab4aa7cb2
commit a720480a0a
2 changed files with 12 additions and 5 deletions

@ -177,7 +177,7 @@ def extract_anchors(html)
anchors = Set.new
html.scan(/<h\d\s+id="([^"]+)/).flatten.each do |anchor|
if anchors.member?(anchor)
puts "*** DUPLICATE ID: #{anchor}, please make sure that there are no headings with the same name at the same level."
puts "*** DUPLICATE ID: '#{anchor}', please make sure that there are no headings with the same name at the same level."
else
anchors << anchor
end

@ -35,16 +35,15 @@ def render(body)
def dom_id(nodes)
dom_id = dom_id_text(nodes.last.text)
# Fix duplicate node by prefix with its parent node
# Fix duplicate dom_ids by prefixing the parent node dom_id
if @node_ids[dom_id]
if @node_ids[dom_id].size > 1
duplicate_nodes = @node_ids.delete(dom_id)
new_node_id = "#{duplicate_nodes[-2][:id]}-#{duplicate_nodes.last[:id]}"
new_node_id = dom_id_with_parent_node(dom_id, duplicate_nodes[-2])
duplicate_nodes.last[:id] = new_node_id
@node_ids[new_node_id] = duplicate_nodes
end
dom_id = "#{nodes[-2][:id]}-#{dom_id}"
dom_id = dom_id_with_parent_node(dom_id, nodes[-2])
end
@node_ids[dom_id] = nodes
@ -60,6 +59,14 @@ def dom_id_text(text)
.gsub(/\s+/, "-")
end
def dom_id_with_parent_node(dom_id, parent_node)
if parent_node
[parent_node[:id], dom_id].join("-")
else
dom_id
end
end
def engine
renderer = @epub ? EpubRenderer : Renderer
@engine ||= Redcarpet::Markdown.new(renderer,