diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 1690933c7..91b5c53a2 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -5,6 +5,12 @@
This document provides a high-level view of the changes to the {project-name} by release.
For a detailed view of what has changed, refer to the {url-repo}/commits/main[commit history] on GitHub.
+== Unreleased
+
+Enhancements::
+
+* add backlink from bibref to first reference to that entry in the document (#1737)
+
== 2.0.6 (2022-05-30) - @mojavelinux
Bug Fixes::
diff --git a/lib/asciidoctor/pdf/converter.rb b/lib/asciidoctor/pdf/converter.rb
index a5a33b798..72d29e7de 100644
--- a/lib/asciidoctor/pdf/converter.rb
+++ b/lib/asciidoctor/pdf/converter.rb
@@ -400,6 +400,7 @@ def init_pdf doc
@list_bullets = []
@bottom_gutters = [{}]
@rendered_footnotes = []
+ @bibref_refs = ::Set.new
@conum_glyphs = ConumSets[@theme.conum_glyphs || 'circled'] || (@theme.conum_glyphs.split ',').map do |r|
from, to = r.lstrip.split '-', 2
to ? ((get_char from)..(get_char to)).to_a : [(get_char from)]
@@ -2373,9 +2374,10 @@ def convert_inline_anchor node
if (text = ref.xreftext node.attr 'xrefstyle', nil, true)&.include? '#{DummyText}) if ref.inline? && ref.type == :bibref && (@bibref_refs.add? refid)
@resolving_xref = nil
end
- %(#{text || "[#{refid}]"}).gsub ']', ']'
+ %(#{backref || ''}#{text || "[#{refid}]"}).gsub ']', ']'
else
%(#{node.text || '[^top]'})
end
@@ -2383,10 +2385,12 @@ def convert_inline_anchor node
# NOTE: destination is created inside callback registered by FormattedTextTransform#build_fragment
%(#{DummyText})
when :bibref
- # NOTE: destination is created inside callback registered by FormattedTextTransform#build_fragment
+ id = node.id
# NOTE: technically node.text should be node.reftext, but subs have already been applied to text
- reftext = (reftext = node.reftext) ? %([#{reftext}]) : %([#{node.id}])
- %(#{DummyText}#{reftext})
+ reftext = (reftext = node.reftext) ? %([#{reftext}]) : %([#{id}])
+ reftext = %(#{reftext}) if @bibref_refs.include? id
+ # NOTE: destination is created inside callback registered by FormattedTextTransform#build_fragment
+ %(#{DummyText}#{reftext})
else
log :warn, %(unknown anchor type: #{node.type.inspect})
nil
diff --git a/spec/list_spec.rb b/spec/list_spec.rb
index 3b4b9882e..cfc19fbab 100644
--- a/spec/list_spec.rb
+++ b/spec/list_spec.rb
@@ -2112,5 +2112,32 @@
(expect lines).to include 'The recommended reading includes [1].'
(expect lines).to include '▪ [1] Bar, Foo. All The Things. 2010.'
end
+
+ it 'should create bidirectional links between bibref reference and entry' do
+ pdf = to_pdf <<~'EOS'
+ The recommended reading includes <>.
+
+ Did you read <>?
+
+ <<<
+
+ [bibliography]
+ == Bibliography
+
+ * [[[bar]]] Bar, Foo. All The Things. 2010.
+ * [[[baz]]] Baz. The Rest of the Story. 2020.
+ EOS
+
+ forward_refs = get_annotations pdf, 1
+ (expect forward_refs).to have_size 2
+ (expect forward_refs.map {|it| it[:Dest] }.uniq).to eql %w(bar)
+ ids = (get_names pdf).keys
+ (expect ids).to include '_bibref_ref_bar'
+ (expect ids).to include 'bar'
+ (expect ids).to include 'baz'
+ back_refs = get_annotations pdf, 2
+ (expect back_refs).to have_size 1
+ (expect back_refs[0][:Dest]).to eql '_bibref_ref_bar'
+ end
end
end