diff --git a/lib/utopia/project/document.rb b/lib/utopia/project/document.rb
index 3283cda..1ee494e 100644
--- a/lib/utopia/project/document.rb
+++ b/lib/utopia/project/document.rb
@@ -174,30 +174,53 @@ def code_node(content, language = nil)
private
- # Replace source code references in the given text with HTML anchors.
+ # Resolve a source code reference to HTML.
# @parameter content [String] The source code reference.
# @parameter language [String | Nil] The explicit source language.
- # @returns [Markly::Node] The resolved link or code node.
+ # @returns [Markly::Node] The inline HTML node.
def reference_node(content, language: nil)
+ reference, definition = resolve_reference(content, language: language)
+
+ if definition
+ content = definition.qualified_form
+ language = reference.language.name
+ elsif reference
+ content = reference.identifier
+ language = reference.language.name
+ end
+
+ attributes = {}
+ attributes[:class] = "language-#{language}" if language
+
+ markup = XRB::Builder.fragment do |builder|
+ builder.inline("code", attributes) do
+ if definition
+ builder.inline("a", href: @base.link_for(definition), title: reference.identifier) do
+ builder.text(content)
+ end
+ else
+ builder.text(content)
+ end
+ end
+ end
+
+ return inline_html_node(markup.to_s)
+ end
+
+ # Resolve source code reference metadata and its indexed definition.
+ # @parameter content [String] The source code reference.
+ # @parameter language [String | Nil] The explicit source language.
+ # @returns [Array] The parsed reference and resolved definition.
+ def resolve_reference(content, language: nil)
reference = if language
@index.languages.reference_for(language, content)
else
@index.languages.parse_reference(content, default_language: @default_language)
end
- if reference
- definition = @index.lookup(reference, relative_to: @definition)
- end
+ definition = @index.lookup(reference, relative_to: @definition) if reference
- if definition
- link_node(reference.identifier, @base.link_for(definition),
- code_node(definition.qualified_form, reference.language.name)
- )
- elsif reference
- code_node(reference.identifier, reference.language.name)
- else
- code_node(content, language)
- end
+ return reference, definition
end
def resolve(root)
diff --git a/lib/utopia/project/renderer.rb b/lib/utopia/project/renderer.rb
index b82fc9c..1b652fe 100644
--- a/lib/utopia/project/renderer.rb
+++ b/lib/utopia/project/renderer.rb
@@ -11,10 +11,9 @@ module Project
# Renders project Markdown with support for Mermaid code blocks.
class Renderer < Markly::Renderer::HTML
# Initialize the project renderer.
- # @parameter inline_code_resolver [Proc | Nil] Resolves language-prefixed inline code into a replacement node.
+ # @parameter inline_code_resolver [Proc | Nil] Resolves language-prefixed inline code into an inline HTML node.
def initialize(inline_code_resolver: nil, **options)
@inline_code_resolver = inline_code_resolver
- @resolving_inline_code = false
super(**options)
end
@@ -58,13 +57,8 @@ def code_block(node)
# Render inline code, resolving language-prefixed references when possible.
# @parameter node [Markly::Node] The inline code node.
def code(node)
- if @inline_code_resolver && !@resolving_inline_code && (language = node.code_language)
- begin
- @resolving_inline_code = true
- out(@inline_code_resolver.call(node.string_content, language: language))
- ensure
- @resolving_inline_code = false
- end
+ if @inline_code_resolver && (language = node.code_language)
+ out(@inline_code_resolver.call(node.string_content, language: language))
else
super
end
diff --git a/releases.md b/releases.md
index e2b76f0..6f62ad6 100644
--- a/releases.md
+++ b/releases.md
@@ -1,5 +1,9 @@
# Changes
+## Unreleased
+
+ - Render resolved inline code references with links inside their code elements so hover and keyboard focus affect the complete reference.
+
## v0.44.0
- Add support for language-prefixed inline code references such as ruby:`Object.new`.
diff --git a/test/utopia/project/document.rb b/test/utopia/project/document.rb
index b527bf9..45d702d 100644
--- a/test/utopia/project/document.rb
+++ b/test/utopia/project/document.rb
@@ -33,6 +33,15 @@
expect(document.to_markdown).to be == "Use ruby:`Object.new` to create an object.\n"
end
+ it "escapes language-prefixed inline code" do
+ root = File.expand_path("../../..", __dir__)
+ base = Utopia::Project::Base.new(root)
+ document = subject.new("Compare ruby:`foo < bar`.", base)
+ html = document.to_html.to_s
+
+ expect(html).to be(:include?, 'foo < bar')
+ end
+
it "resolves language-prefixed inline code references" do
root = File.expand_path("../../..", __dir__)
base = Utopia::Project::Base.new(root)
@@ -41,8 +50,8 @@
document = subject.new("See ruby:`Utopia::Project::Document#root`.", base)
html = document.to_html.to_s
- expect(html).to be(:include?, 'Utopia::Project::Document#root')
+ expect(html).to be(:include?, 'Utopia::Project::Document#root")
end
it "continues to resolve legacy brace references" do
@@ -53,7 +62,8 @@
document = subject.new("See {ruby Utopia::Project::Document#root}.", base)
html = document.to_html.to_s
- expect(html).to be(:include?, '