Skip to content

Commit b9136f5

Browse files
committed
Automatically disambiguate anchor names
1 parent bb4cfb2 commit b9136f5

3 files changed

Lines changed: 26 additions & 17 deletions

File tree

src/expand_bibliography.jl

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -362,13 +362,7 @@ function expand_bibliography(node::MarkdownAST.Node, meta, page, doc)
362362
end
363363
for (key, entry) in entries_to_show
364364
if fields[:Canonical]
365-
try
366-
anchor_key = get_anchor_key(key, bib.anchor_keys)
367-
catch exception
368-
@error "Cannot generate anchor for $(repr(key)) on page $(warn_loc)" exception
369-
push!(doc.internal.errors, :bibliography_block)
370-
continue # skip entry
371-
end
365+
anchor_key = get_anchor_key(key, bib.anchor_keys)
372366
# Add anchor that citations can link to from anywhere in the docs.
373367
if Documenter.anchor_exists(anchors, anchor_key)
374368
# Skip entries that already have a canonical bib entry
@@ -422,12 +416,20 @@ end
422416
# compatibility with CSS selectors, see https://stackoverflow.com/a/79022.
423417
# Even more importantly, these characters are not supported by the
424418
# `Documenter.DOM` framework that we use to generate HTML: it will silently
425-
# drop anything after a colon or period.
426-
function get_anchor_key(citation_key::String, cache::Bijections.Bijection{String,String})
419+
# drop anything after a colon or period. The numerical `suffix_index` gets
420+
# appended to the anchor name if > 0 and can be used to disambiguate labels.
421+
function get_anchor_key(
422+
citation_key::String,
423+
cache::Bijections.Bijection{String,String};
424+
suffix_index::Int64=1
425+
)
427426
if haskey(cache, citation_key)
428427
anchor_key = cache[citation_key]
429428
else
430429
anchor_key = normalize_anchor(citation_key) # => [A-Za-z0-0_-]
430+
if suffix_index > 1
431+
anchor_key *= "-$suffix_index"
432+
end
431433
if !startswith(anchor_key, r"[A-Za-z]")
432434
# Anchors must start with a letter. Instead of rejecting "invalid"
433435
# anchors, we just prepend something arbitrary.
@@ -438,8 +440,14 @@ function get_anchor_key(citation_key::String, cache::Bijections.Bijection{String
438440
# duplicates here.
439441
cache[citation_key] = anchor_key
440442
catch
441-
msg = "Cannot generate HTML anchor for citation key $(repr(citation_key)): normalizes to ambiguous $(repr(anchor_key)) conflicting with citation key $(repr(cache(anchor_key)))"
442-
error(msg)
443+
suffix_index += 1
444+
msg = "HTML anchor for citation key $(repr(citation_key)) normalizes to ambiguous $(repr(anchor_key)) conflicting with citation key $(repr(cache(anchor_key))). Disambiguating with suffix \"-$(suffix_index)\""
445+
@warn(msg)
446+
if suffix_index < 100
447+
return get_anchor_key(citation_key, cache; suffix_index)
448+
else
449+
error("Internal error: cannot find disambiguated anchor key")
450+
end
443451
end
444452
@debug "Generated anchor key $(repr(anchor_key)) for citation key $(repr(citation_key))"
445453
end

test/test_anchor_keys.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@ include("run_makedocs.jl")
2525
c = IOCapture.capture(rethrow=Union{}) do
2626
get_anchor_key("AbsilMahonySepulchre.2008", cache)
2727
end
28-
@test c.value isa ErrorException
29-
msg = "Cannot generate HTML anchor for citation key \"AbsilMahonySepulchre.2008\": normalizes to ambiguous \"AbsilMahonySepulchre2008\" conflicting with citation key \"AbsilMahonySepulchre:2008\""
30-
@Test c.value.msg == msg
31-
28+
@test c.value == "AbsilMahonySepulchre2008-2"
29+
msg = "Warning: HTML anchor for citation key \"AbsilMahonySepulchre.2008\" normalizes to ambiguous \"AbsilMahonySepulchre2008\" conflicting with citation key \"AbsilMahonySepulchre:2008\". Disambiguating with suffix \"-2\""
30+
@test contains(c.output, msg)
3231

3332
end
3433

@@ -54,16 +53,18 @@ end
5453
@test success
5554

5655
@test bib.anchor_keys["Chirikjian:2012"] == "Chirikjian2012"
56+
@test bib.anchor_keys["Chirikjian2012"] == "Chirikjian2012-2"
5757

58-
@test contains(output, "Error: Cannot generate anchor for \"Chirikjian2012\"")
5958
@test contains(output, "normalizes to ambiguous \"Chirikjian2012\"")
6059

6160
#! format: off
6261
index_html = read(joinpath(dir, "build", "index.html"), String)
6362
@Test contains(index_html, "<a href=\"references/#Chirikjian2012\">")
63+
@Test contains(index_html, "<a href=\"references/#Chirikjian2012-2\">")
6464

6565
references_html = read(joinpath(dir, "build", "references", "index.html"), String)
6666
@Test contains(references_html, "<div id=\"Chirikjian2012\">")
67+
@Test contains(references_html, "<div id=\"Chirikjian2012-2\">")
6768
#! format: on
6869

6970
end

test/test_anchor_keys/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
You can read more about the theory of Lie groups for example in [Chirikjian:2012](@cite).
44

5-
Note the ambiguous citations keys, as for Ref. [Chirikjian2012](@cite) leads to errors.
5+
Note the ambiguous citations keys, as for Ref. [Chirikjian2012](@cite) are automatically disambiguated.

0 commit comments

Comments
 (0)