# frozen_string_literal: true
require_relative 'test_helper'
context 'Links' do
test 'qualified url inline with text' do
assert_xpath "//a[@href='http://asciidoc.org'][@class='bare'][text() = 'http://asciidoc.org']", convert_string("The AsciiDoc project is located at http://asciidoc.org.")
end
test 'qualified url with role inline with text' do
assert_xpath "//a[@href='http://asciidoc.org'][@class='bare project'][text() = 'http://asciidoc.org']", convert_string("The AsciiDoc project is located at http://asciidoc.org[role=project].")
end
test 'qualified http url inline with hide-uri-scheme set' do
assert_xpath "//a[@href='http://asciidoc.org'][@class='bare'][text() = 'asciidoc.org']", convert_string("The AsciiDoc project is located at http://asciidoc.org.", attributes: { 'hide-uri-scheme' => '' })
end
test 'qualified file url inline with label' do
assert_xpath "//a[@href='file:///home/user/bookmarks.html'][text() = 'My Bookmarks']", convert_string_to_embedded('file:///home/user/bookmarks.html[My Bookmarks]')
end
test 'qualified file url inline with hide-uri-scheme set' do
assert_xpath "//a[@href='file:///etc/app.conf'][text() = '/etc/app.conf']", convert_string('Edit the configuration file link:file:///etc/app.conf[]', attributes: { 'hide-uri-scheme' => '' })
end
test 'should not hide bare URI scheme in implicit text of link macro when hide-uri-scheme is set' do
{
'link:https://[]' => 'https://',
'link:ssh://[]' => 'ssh://',
}.each do |input, expected|
assert_xpath %(/a[text() = "#{expected}"]), (convert_inline_string input, attributes: { 'hide-uri-scheme' => '' })
end
end
test 'qualified url with label' do
assert_xpath "//a[@href='http://asciidoc.org'][text() = 'AsciiDoc']", convert_string("We're parsing http://asciidoc.org[AsciiDoc] markup")
end
test 'qualified url with label containing escaped right square bracket' do
assert_xpath "//a[@href='http://asciidoc.org'][text() = '[Ascii]Doc']", convert_string("We're parsing http://asciidoc.org[[Ascii\\]Doc] markup")
end
test 'qualified url with backslash label' do
assert_xpath "//a[@href='https://google.com'][text() = 'Google for \\']", convert_string("I advise you to https://google.com[Google for +\\+]")
end
test 'qualified url with label using link macro' do
assert_xpath "//a[@href='http://asciidoc.org'][text() = 'AsciiDoc']", convert_string("We're parsing link:http://asciidoc.org[AsciiDoc] markup")
end
test 'qualified url with role using link macro' do
assert_xpath "//a[@href='http://asciidoc.org'][@class='bare project'][text() = 'http://asciidoc.org']", convert_string("We're parsing link:http://asciidoc.org[role=project] markup")
end
test 'qualified url using macro syntax with multi-line label inline with text' do
assert_xpath %{//a[@href='http://asciidoc.org'][text() = 'AsciiDoc\nmarkup']}, convert_string("We're parsing link:http://asciidoc.org[AsciiDoc\nmarkup]")
end
test 'qualified url with label containing square brackets using link macro' do
str = 'http://example.com[[bracket1\]]'
doc = document_from_string str, standalone: false, doctype: 'inline'
assert_match '[bracket1]', doc.convert, 1
doc = document_from_string str, standalone: false, backend: 'docbook', doctype: 'inline'
assert_match '[bracket1]', doc.convert, 1
end
test 'link macro with empty target' do
input = 'Link to link:[this page].'
output = convert_string_to_embedded input
assert_xpath '//a', output, 1
assert_xpath '//a[@href=""]', output, 1
end
test 'should not recognize link macro with double colons' do
input = 'The link::http://example.org[example domain] is reserved for tests and documentation.'
output = convert_string_to_embedded input
assert_includes output, 'link::http://example.org[example domain]'
end
test 'qualified url surrounded by angled brackets' do
assert_xpath '//a[@href="http://asciidoc.org"][text()="http://asciidoc.org"]', convert_string(' is the project page for AsciiDoc.'), 1
end
test 'qualified url surrounded by round brackets' do
assert_xpath '//a[@href="http://asciidoc.org"][text()="http://asciidoc.org"]', convert_string('(http://asciidoc.org) is the project page for AsciiDoc.'), 1
end
test 'qualified url with trailing round bracket' do
result = convert_string_to_embedded 'Asciidoctor is a Ruby-based AsciiDoc processor (see https://asciidoctor.org)'
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]', result, 1
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]/following-sibling::text()[starts-with(.,")")]', result, 1
end
test 'qualified url with trailing semi-colon' do
result = convert_string_to_embedded 'https://asciidoctor.org; where text gets parsed'
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]', result, 1
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]/following-sibling::text()[starts-with(.,";")]', result, 1
end
test 'qualified url with trailing colon' do
result = convert_string_to_embedded 'https://asciidoctor.org: where text gets parsed'
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]', result, 1
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]/following-sibling::text()[starts-with(.,":")]', result, 1
end
test 'qualified url in round brackets with trailing colon' do
result = convert_string_to_embedded '(https://asciidoctor.org): where text gets parsed'
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]', result, 1
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]/following-sibling::text()[starts-with(.,"):")]', result, 1
end
test 'qualified url with trailing round bracket followed by colon' do
result = convert_string_to_embedded '(from https://asciidoctor.org): where text gets parsed'
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]', result, 1
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]/following-sibling::text()[starts-with(., "):")]', result, 1
end
test 'qualified url in round brackets with trailing semi-colon' do
result = convert_string_to_embedded '(https://asciidoctor.org); where text gets parsed'
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]', result, 1
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]/following-sibling::text()[starts-with(., ");")]', result, 1
end
test 'qualified url with trailing round bracket followed by semi-colon' do
result = convert_string_to_embedded '(from https://asciidoctor.org); where text gets parsed'
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]', result, 1
assert_xpath '//a[@href="https://asciidoctor.org"][text()="https://asciidoctor.org"]/following-sibling::text()[starts-with(., ");")]', result, 1
end
test 'URI scheme with trailing characters should not be converted to a link' do
input_sources = %w(
(https://)
http://;
file://:
)
expected_outputs = %w(
(https://)
http://;
file://:
<ftp://>
)
input_sources.each_with_index do |input_source, i|
expected_output = expected_outputs[i]
actual = block_from_string input_source
assert_equal expected_output, actual.content
end
end
test 'qualified url containing round brackets' do
assert_xpath '//a[@href="http://jruby.org/apidocs/org/jruby/Ruby.html#addModule(org.jruby.RubyModule)"][text()="addModule() adds a Ruby module"]', convert_string('http://jruby.org/apidocs/org/jruby/Ruby.html#addModule(org.jruby.RubyModule)[addModule() adds a Ruby module]'), 1
end
test 'qualified url adjacent to text in square brackets' do
assert_xpath '//a[@href="http://asciidoc.org"][text()="AsciiDoc"]', convert_string(']http://asciidoc.org[AsciiDoc] project page.'), 1
end
test 'qualified url adjacent to text in round brackets' do
assert_xpath '//a[@href="http://asciidoc.org"][text()="AsciiDoc"]', convert_string(')http://asciidoc.org[AsciiDoc] project page.'), 1
end
test 'qualified url following no-break space' do
assert_xpath '//a[@href="http://asciidoc.org"][text()="AsciiDoc"]', convert_string(%(#{[0xa0].pack 'U1'}http://asciidoc.org[AsciiDoc] project page.)), 1
end
test 'qualified url following smart apostrophe' do
output = convert_string_to_embedded("l’http://www.irit.fr[IRIT]")
assert_match(/l’'), 1
end
test 'link with quoted text should not be separated into attributes when text contains an equal sign' do
assert_xpath '//a[@href="http://search.example.com"][text()="Google, Yahoo, Bing = Search Engines"]', convert_string_to_embedded('http://search.example.com["Google, Yahoo, Bing = Search Engines"]'), 1
end
test 'link with quoted text but no equal sign should carry quotes over to output' do
assert_xpath %(//a[@href="http://search.example.com"][text()='"Google, Yahoo, Bing"']), convert_string_to_embedded('http://search.example.com["Google, Yahoo, Bing"]'), 1
end
test 'link with comma in text but no equal sign should not be separated into attributes' do
assert_xpath '//a[@href="http://search.example.com"][text()="Google, Yahoo, Bing"]', convert_string_to_embedded('http://search.example.com[Google, Yahoo, Bing]'), 1
end
test 'role and window attributes on link are processed' do
assert_xpath '//a[@href="http://google.com"][@class="external"][@target="_blank"]', convert_string_to_embedded('http://google.com[Google, role=external, window="_blank"]'), 1
end
test 'link macro with attributes but no text should use URL as text' do
url = 'https://fonts.googleapis.com/css?family=Roboto:400,400italic,'
assert_xpath %(//a[@href="#{url}"][text()="#{url}"]), convert_string_to_embedded(%(link:#{url}[family=Roboto,weight=400])), 1
end
test 'link macro with attributes but blank text should use URL as text' do
url = 'https://fonts.googleapis.com/css?family=Roboto:400,400italic,'
assert_xpath %(//a[@href="#{url}"][text()="#{url}"]), convert_string_to_embedded(%(link:#{url}[,family=Roboto,weight=400])), 1
end
test 'link macro with comma but no explicit attributes in text should not parse text' do
url = 'https://fonts.googleapis.com/css?family=Roboto:400,400italic,'
assert_xpath %(//a[@href="#{url}"][text()="Roboto,400"]), convert_string_to_embedded(%(link:#{url}[Roboto,400])), 1
end
test 'link text that ends in ^ should set link window to _blank' do
assert_xpath '//a[@href="http://google.com"][@target="_blank"]', convert_string_to_embedded('http://google.com[Google^]'), 1
end
test 'rel=noopener should be added to a link that targets the _blank window' do
assert_xpath '//a[@href="http://google.com"][@target="_blank"][@rel="noopener"]', convert_string_to_embedded('http://google.com[Google^]'), 1
end
test 'rel=noopener should be added to a link that targets a named window when the noopener option is set' do
assert_xpath '//a[@href="http://google.com"][@target="name"][@rel="noopener"]', convert_string_to_embedded('http://google.com[Google,window=name,opts=noopener]'), 1
end
test 'rel=noopener should not be added to a link if it does not target a window' do
result = convert_string_to_embedded 'http://google.com[Google,opts=noopener]'
assert_xpath '//a[@href="http://google.com"]', result, 1
assert_xpath '//a[@href="http://google.com"][@rel="noopener"]', result, 0
end
test 'rel=nofollow should be added to a link when the nofollow option is set' do
assert_xpath '//a[@href="http://google.com"][@target="name"][@rel="nofollow noopener"]', convert_string_to_embedded('http://google.com[Google,window=name,opts="nofollow,noopener"]'), 1
end
test 'id attribute on link is processed' do
assert_xpath '//a[@href="http://google.com"][@id="link-1"]', convert_string_to_embedded('http://google.com[Google, id="link-1"]'), 1
end
test 'title attribute on link is processed' do
assert_xpath '//a[@href="http://google.com"][@title="title-1"]', convert_string_to_embedded('http://google.com[Google, title="title-1"]'), 1
end
test 'inline irc link' do
assert_xpath '//a[@href="irc://irc.freenode.net"][text()="irc://irc.freenode.net"]', convert_string_to_embedded('irc://irc.freenode.net'), 1
end
test 'inline irc link with text' do
assert_xpath '//a[@href="irc://irc.freenode.net"][text()="Freenode IRC"]', convert_string_to_embedded('irc://irc.freenode.net[Freenode IRC]'), 1
end
test 'inline ref' do
variations = %w([[tigers]] anchor:tigers[])
variations.each do |anchor|
doc = document_from_string %(Here you can read about tigers.#{anchor})
output = doc.convert
assert_kind_of Asciidoctor::Inline, doc.catalog[:refs]['tigers']
assert_nil doc.catalog[:refs]['tigers'].text
assert_xpath '//a[@id="tigers"]', output, 1
assert_xpath '//a[@id="tigers"]/child::text()', output, 0
end
end
test 'escaped inline ref' do
variations = %w([[tigers]] anchor:tigers[])
variations.each do |anchor|
doc = document_from_string %(Here you can read about tigers.\\#{anchor})
output = doc.convert
refute doc.catalog[:refs].key?('tigers')
assert_xpath '//a[@id="tigers"]', output, 0
end
end
test 'inline ref can start with colon' do
input = '[[:idname]] text'
output = convert_string_to_embedded input
assert_xpath '//a[@id=":idname"]', output, 1
end
test 'inline ref cannot start with digit' do
input = '[[1-install]] text'
output = convert_string_to_embedded input
assert_includes output, '[[1-install]]'
assert_xpath '//a[@id = "1-install"]', output, 0
end
test 'inline ref with reftext' do
%w([[tigers,Tigers]] anchor:tigers[Tigers]).each do |anchor|
doc = document_from_string %(Here you can read about tigers.#{anchor})
output = doc.convert
assert_kind_of Asciidoctor::Inline, doc.catalog[:refs]['tigers']
assert_equal 'Tigers', doc.catalog[:refs]['tigers'].text
assert_xpath '//a[@id="tigers"]', output, 1
assert_xpath '//a[@id="tigers"]/child::text()', output, 0
end
end
test 'should encode double quotes in reftext of anchor macro in DocBook output' do
input = 'anchor:uncola[the "un"-cola]'
result = convert_inline_string input, backend: :docbook
assert_equal '', result
end
test 'should substitute attribute references in reftext when registering inline ref' do
%w([[tigers,{label-tigers}]] anchor:tigers[{label-tigers}]).each do |anchor|
doc = document_from_string %(Here you can read about tigers.#{anchor}), attributes: { 'label-tigers' => 'Tigers' }
doc.convert
assert_kind_of Asciidoctor::Inline, doc.catalog[:refs]['tigers']
assert_equal 'Tigers', doc.catalog[:refs]['tigers'].text
end
end
test 'inline ref with reftext converted to DocBook' do
%w([[tigers,]] anchor:tigers[]).each do |anchor|
doc = document_from_string %(Here you can read about tigers.#{anchor}), backend: :docbook
output = doc.convert standalone: false
assert_kind_of Asciidoctor::Inline, doc.catalog[:refs]['tigers']
assert_equal '', doc.catalog[:refs]['tigers'].text
assert_includes output, ''
end
end
test 'does not match bibliography anchor in prose when scanning for inline anchor' do
doc = document_from_string 'Use [[[label]]] to assign a label to a bibliography entry.'
refute doc.catalog[:refs].key? 'label'
end
test 'repeating inline anchor macro with empty reftext' do
input = 'anchor:one[] anchor:two[] anchor:three[]'
result = convert_inline_string input
assert_equal '', result
end
test 'mixed inline anchor macro and anchor shorthand with empty reftext' do
input = 'anchor:one[][[two]]anchor:three[][[four]]anchor:five[]'
result = convert_inline_string input
assert_equal '', result
end
test 'assigns xreflabel value for anchor macro without reftext in DocBook output' do
input = 'anchor:foo[]'
result = convert_inline_string input, backend: :docbook
assert_equal '', result
end
test 'unescapes square bracket in reftext of anchor macro' do
input = <<~'EOS'
see <>
anchor:foo[b[a\]r]tex'
EOS
result = convert_string_to_embedded input
assert_includes result, 'see b[a]r'
end
test 'unescapes square bracket in reftext of anchor macro in DocBook output' do
input = 'anchor:foo[b[a\]r]'
result = convert_inline_string input, backend: :docbook
assert_equal '', result
end
test 'xref using angled bracket syntax' do
doc = document_from_string '<>'
doc.register :refs, ['tigers', (Asciidoctor::Inline.new doc, :anchor, '[tigers]', type: :ref, target: 'tigers'), '[tigers]']
assert_xpath '//a[@href="#tigers"][text() = "[tigers]"]', doc.convert, 1
end
test 'xref using angled bracket syntax with explicit hash' do
doc = document_from_string '<<#tigers>>'
doc.register :refs, ['tigers', (Asciidoctor::Inline.new doc, :anchor, 'Tigers', type: :ref, target: 'tigers'), 'Tigers']
assert_xpath '//a[@href="#tigers"][text() = "Tigers"]', doc.convert, 1
end
test 'xref using angled bracket syntax with label' do
input = <<~'EOS'
<>
[#tigers]
== Tigers
EOS
assert_xpath '//a[@href="#tigers"][text() = "About Tigers"]', convert_string(input), 1
end
test 'xref using angled bracket syntax with quoted label' do
input = <<~'EOS'
<>
[#tigers]
== Tigers
EOS
assert_xpath %q(//a[@href="#tigers"][text() = '"About Tigers"']), convert_string(input), 1
end
test 'should not interpret path sans extension in xref with angled bracket syntax in compat mode' do
using_memory_logger do |logger|
doc = document_from_string '<>', standalone: false, attributes: { 'compat-mode' => '' }
assert_xpath '//a[@href="#tigers#"][text() = "[tigers#]"]', doc.convert, 1
end
end
test 'xref using angled bracket syntax with path sans extension' do
doc = document_from_string '<>', standalone: false
assert_xpath '//a[@href="tigers.html"][text() = "tigers.html"]', doc.convert, 1
end
test 'inter-document xref shorthand syntax should assume AsciiDoc extension if AsciiDoc extension not present' do
{
'using-.net-web-services#' => 'Using .NET web services',
'asciidoctor.1#' => 'Asciidoctor Manual',
'path/to/document#' => 'Document Title',
}.each do |target, text|
result = convert_string_to_embedded %(<<#{target},#{text}>>)
assert_xpath %(//a[@href="#{target.chop}.html"][text()="#{text}"]), result, 1
end
end
test 'xref macro with explicit inter-document target should not assume AsciiDoc extension if AsciiDoc extension not present' do
{
'using-.net-web-services#' => 'Using .NET web services',
'asciidoctor.1#' => 'Asciidoctor Manual',
'path/to/document#' => 'Document Title',
}.each do |target, text|
result = convert_string_to_embedded %(xref:#{target}[#{text}])
assert_xpath %(//a[@href="#{target.chop}"][text()="#{text}"]), result, 1
end
end
test 'xref macro with implicit inter-document target should preserve path with file extension' do
{
'refcard.pdf' => 'Refcard',
'asciidoctor.1' => 'Asciidoctor Manual',
}.each do |path, text|
result = convert_string_to_embedded %(xref:#{path}[#{text}])
assert_xpath %(//a[@href="#{path}"][text()="#{text}"]), result, 1
end
end
test 'inter-document xref should only remove the file extension part if the path contains a period elsewhere' do
result = convert_string_to_embedded '<>'
assert_xpath '//a[@href="using-.net-web-services.html"][text() = "Using .NET web services"]', result, 1
end
test 'xref macro target containing dot should be interpreted as a path unless prefixed by #' do
result = convert_string_to_embedded 'xref:using-.net-web-services[Using .NET web services]'
assert_xpath '//a[@href="using-.net-web-services"][text() = "Using .NET web services"]', result, 1
result = convert_string_to_embedded 'xref:#using-.net-web-services[Using .NET web services]'
assert_xpath '//a[@href="#using-.net-web-services"][text() = "Using .NET web services"]', result, 1
end
test 'xref using angled bracket syntax with path sans extension using docbook backend' do
doc = document_from_string '<>', standalone: false, backend: 'docbook'
assert_match 'tigers.xml', doc.convert, 1
end
test 'xref using angled bracket syntax with ancestor path sans extension' do
doc = document_from_string '<<../tigers#,tigers>>', standalone: false
assert_xpath '//a[@href="../tigers.html"][text() = "tigers"]', doc.convert, 1
end
test 'xref using angled bracket syntax with absolute path sans extension' do
doc = document_from_string '<>', standalone: false
assert_xpath '//a[@href="/path/to/tigers.html"][text() = "tigers"]', doc.convert, 1
end
test 'xref using angled bracket syntax with path and extension' do
using_memory_logger do |logger|
doc = document_from_string '<>', standalone: false
assert_xpath '//a[@href="#tigers.adoc"][text() = "[tigers.adoc]"]', doc.convert, 1
end
end
test 'xref using angled bracket syntax with path and extension with hash' do
doc = document_from_string '<>', standalone: false
assert_xpath '//a[@href="tigers.html"][text() = "tigers.html"]', doc.convert, 1
end
test 'xref using angled bracket syntax with path and extension with fragment' do
doc = document_from_string '<>', standalone: false
assert_xpath '//a[@href="tigers.html#id"][text() = "tigers.html"]', doc.convert, 1
end
test 'xref using macro syntax with path and extension in compat mode' do
using_memory_logger do |logger|
doc = document_from_string 'xref:tigers.adoc[]', standalone: false, attributes: { 'compat-mode' => '' }
assert_xpath '//a[@href="#tigers.adoc"][text() = "[tigers.adoc]"]', doc.convert, 1
end
end
test 'xref using macro syntax with path and extension' do
doc = document_from_string 'xref:tigers.adoc[]', standalone: false
assert_xpath '//a[@href="tigers.html"][text() = "tigers.html"]', doc.convert, 1
end
test 'xref using angled bracket syntax with path and fragment' do
doc = document_from_string '<>', standalone: false
assert_xpath '//a[@href="tigers.html#about"][text() = "tigers.html"]', doc.convert, 1
end
test 'xref using angled bracket syntax with path, fragment and text' do
doc = document_from_string '<>', standalone: false
assert_xpath '//a[@href="tigers.html#about"][text() = "About Tigers"]', doc.convert, 1
end
test 'xref using angled bracket syntax with path and custom relfilesuffix and outfilesuffix' do
attributes = { 'relfileprefix' => '../', 'outfilesuffix' => '/' }
doc = document_from_string '<>', standalone: false, attributes: attributes
assert_xpath '//a[@href="../tigers/#about"][text() = "About Tigers"]', doc.convert, 1
end
test 'xref using angled bracket syntax with path and custom relfilesuffix' do
attributes = { 'relfilesuffix' => '/' }
doc = document_from_string '<>', standalone: false, attributes: attributes
assert_xpath '//a[@href="tigers/#about"][text() = "About Tigers"]', doc.convert, 1
end
test 'xref using angled bracket syntax with path which has been included in this document' do
using_memory_logger do |logger|
in_verbose_mode do
doc = document_from_string '<>', standalone: false
doc.catalog[:includes]['tigers'] = true
output = doc.convert
assert_xpath '//a[@href="#about"][text() = "About Tigers"]', output, 1
assert_message logger, :INFO, 'possible invalid reference: about'
end
end
end
test 'xref using angled bracket syntax with nested path which has been included in this document' do
using_memory_logger do |logger|
in_verbose_mode do
doc = document_from_string '<>', standalone: false
doc.catalog[:includes]['part1/tigers'] = true
output = doc.convert
assert_xpath '//a[@href="#about"][text() = "About Tigers"]', output, 1
assert_message logger, :INFO, 'possible invalid reference: about'
end
end
end
test 'xref using angled bracket syntax inline with text' do
input = <<~'EOS'
Want to learn <>?
[#tigers]
== Tigers
EOS
assert_xpath '//a[@href="#tigers"][text() = "about tigers"]', convert_string(input), 1
end
test 'xref using angled bracket syntax with multi-line label inline with text' do
input = <<~'EOS'
Want to learn <>?
[#tigers]
== Tigers
EOS
assert_xpath %{//a[@href="#tigers"][normalize-space(text()) = "about tigers"]}, convert_string(input), 1
end
test 'xref with escaped text' do
# when \x0 was used as boundary character for passthrough, it was getting stripped
# now using unicode marks as boundary characters, which resolves issue
input = <<~'EOS'
See the <> section for details about tigers.
[#tigers]
== Tigers
EOS
output = convert_string_to_embedded input
assert_xpath %(//a[@href="#tigers"]/code[text()="[tigers]"]), output, 1
end
test 'xref with target that begins with attribute reference in title' do
['<<{lessonsdir}/lesson-1#,Lesson 1>>', 'xref:{lessonsdir}/lesson-1.adoc[Lesson 1]'].each do |xref|
input = <<~EOS
:lessonsdir: lessons
[#lesson-1-listing]
== #{xref}
A summary of the first lesson.
EOS
output = convert_string_to_embedded input
assert_xpath '//h2/a[@href="lessons/lesson-1.html"]', output, 1
end
end
test 'xref using macro syntax' do
doc = document_from_string 'xref:tigers[]'
doc.register :refs, ['tigers', (Asciidoctor::Inline.new doc, :anchor, '[tigers]', type: :ref, target: 'tigers'), '[tigers]']
assert_xpath '//a[@href="#tigers"][text() = "[tigers]"]', doc.convert, 1
end
test 'multiple xref macros with implicit text in single line' do
input = <<~'EOS'
This document has two sections, xref:sect-a[] and xref:sect-b[].
[#sect-a]
== Section A
[#sect-b]
== Section B
EOS
result = convert_string_to_embedded input
assert_xpath '//a[@href="#sect-a"][text() = "Section A"]', result, 1
assert_xpath '//a[@href="#sect-b"][text() = "Section B"]', result, 1
end
test 'xref using macro syntax with explicit hash' do
doc = document_from_string 'xref:#tigers[]'
doc.register :refs, ['tigers', (Asciidoctor::Inline.new doc, :anchor, 'Tigers', type: :ref, target: 'tigers'), 'Tigers']
assert_xpath '//a[@href="#tigers"][text() = "Tigers"]', doc.convert, 1
end
test 'xref using macro syntax with label' do
input = <<~'EOS'
xref:tigers[About Tigers]
[#tigers]
== Tigers
EOS
assert_xpath '//a[@href="#tigers"][text() = "About Tigers"]', convert_string(input), 1
end
test 'xref using macro syntax inline with text' do
input = <<~'EOS'
Want to learn xref:tigers[about tigers]?
[#tigers]
== Tigers
EOS
assert_xpath '//a[@href="#tigers"][text() = "about tigers"]', convert_string(input), 1
end
test 'xref using macro syntax with multi-line label inline with text' do
input = <<~'EOS'
Want to learn xref:tigers[about
tigers]?
[#tigers]
== Tigers
EOS
assert_xpath %{//a[@href="#tigers"][normalize-space(text()) = "about tigers"]}, convert_string(input), 1
end
test 'xref using macro syntax with text that ends with an escaped closing bracket' do
input = <<~'EOS'
xref:tigers[[tigers\]]
[#tigers]
== Tigers
EOS
assert_xpath '//a[@href="#tigers"][text() = "[tigers]"]', convert_string_to_embedded(input), 1
end
test 'xref using macro syntax with text that contains an escaped closing bracket' do
input = <<~'EOS'
xref:tigers[[tigers\] are cats]
[#tigers]
== Tigers
EOS
assert_xpath '//a[@href="#tigers"][text() = "[tigers] are cats"]', convert_string_to_embedded(input), 1
end
test 'unescapes square bracket in reftext used by xref' do
input = <<~'EOS'
anchor:foo[b[a\]r]about
see <>
EOS
result = convert_string_to_embedded input
assert_xpath '//a[@href="#foo"]', result, 1
assert_xpath '//a[@href="#foo"][text()="b[a]r"]', result, 1
end
test 'xref using invalid macro syntax does not create link' do
doc = document_from_string 'xref:tigers'
doc.register :refs, ['tigers', (Asciidoctor::Inline.new doc, :anchor, 'Tigers', type: :ref, target: 'tigers'), 'Tigers']
assert_xpath '//a', doc.convert, 0
end
test 'should warn and create link if verbose flag is set and reference is not found' do
input = <<~'EOS'
[#foobar]
== Foobar
== Section B
See <>.
EOS
using_memory_logger do |logger|
in_verbose_mode do
output = convert_string_to_embedded input
assert_xpath '//a[@href="#foobaz"][text() = "[foobaz]"]', output, 1
assert_message logger, :INFO, 'possible invalid reference: foobaz'
end
end
end
test 'should warn and create link if verbose flag is set and reference using # notation is not found' do
input = <<~'EOS'
[#foobar]
== Foobar
== Section B
See <<#foobaz>>.
EOS
using_memory_logger do |logger|
in_verbose_mode do
output = convert_string_to_embedded input
assert_xpath '//a[@href="#foobaz"][text() = "[foobaz]"]', output, 1
assert_message logger, :INFO, 'possible invalid reference: foobaz'
end
end
end
test 'should produce an internal anchor from an inter-document xref to file included into current file' do
input = <<~'EOS'
= Book Title
:doctype: book
[#ch1]
== Chapter 1
So it begins.
Read <> to find out what happens next!
include::other-chapters.adoc[]
EOS
doc = document_from_string input, safe: :safe, base_dir: fixturedir
assert doc.catalog[:includes].key?('other-chapters')
assert doc.catalog[:includes]['other-chapters']
output = doc.convert
assert_xpath '//a[@href="#ch2"][text()="Chapter 2"]', output, 1
end
test 'should produce an internal anchor from an inter-document xref to file included entirely into current file using tags' do
input = <<~'EOS'
= Book Title
:doctype: book
[#ch1]
== Chapter 1
So it begins.
Read <> to find out what happens next!
include::other-chapters.adoc[tags=**]
EOS
output = convert_string_to_embedded input, safe: :safe, base_dir: fixturedir
assert_xpath '//a[@href="#ch2"][text()="Chapter 2"]', output, 1
end
test 'should not produce an internal anchor for inter-document xref to file partially included into current file' do
input = <<~'EOS'
= Book Title
:doctype: book
[#ch1]
== Chapter 1
So it begins.
Read <> to find out what happens next!
include::other-chapters.adoc[tags=ch2]
EOS
doc = document_from_string input, safe: :safe, base_dir: fixturedir
assert doc.catalog[:includes].key?('other-chapters')
refute doc.catalog[:includes]['other-chapters']
output = doc.convert
assert_xpath '//a[@href="other-chapters.html#ch2"][text()="the next chapter"]', output, 1
end
test 'should warn and create link if debug mode is enabled, inter-document xref points to current doc, and reference not found' do
input = <<~'EOS'
[#foobar]
== Foobar
== Section B
See <>.
EOS
using_memory_logger do |logger|
in_verbose_mode do
output = convert_string_to_embedded input, attributes: { 'docname' => 'test' }
assert_xpath '//a[@href="#foobaz"][text() = "[foobaz]"]', output, 1
assert_message logger, :INFO, 'possible invalid reference: foobaz'
end
end
end
test 'should produce an internal anchor for inter-document xref to file outside of base directory' do
input = <<~'EOS'
= Document Title
See <<../section-a.adoc#section-a>>.
include::../section-a.adoc[]
EOS
doc = document_from_string input, safe: :unsafe, base_dir: (File.join fixturedir, 'subdir')
assert_includes doc.catalog[:includes], '../section-a'
output = doc.convert standalone: false
assert_xpath '//a[@href="#section-a"][text()="Section A"]', output, 1
end
test 'xref uses title of target as label for forward and backward references in html output' do
input = <<~'EOS'
== Section A
<<_section_b>>
== Section B
<<_section_a>>
EOS
output = convert_string_to_embedded input
assert_xpath '//h2[@id="_section_a"][text()="Section A"]', output, 1
assert_xpath '//a[@href="#_section_a"][text()="Section A"]', output, 1
assert_xpath '//h2[@id="_section_b"][text()="Section B"]', output, 1
assert_xpath '//a[@href="#_section_b"][text()="Section B"]', output, 1
end
test 'anchor creates reference' do
doc = document_from_string '[[tigers]]Tigers roam here.'
ref = doc.catalog[:refs]['tigers']
refute_nil ref
assert_nil ref.reftext
end
test 'anchor with label creates reference' do
doc = document_from_string '[[tigers,Tigers]]Tigers roam here.'
ref = doc.catalog[:refs]['tigers']
refute_nil ref
assert_equal 'Tigers', ref.reftext
end
test 'anchor with quoted label creates reference with quoted label text' do
doc = document_from_string %([[tigers,"Tigers roam here"]]Tigers roam here.)
ref = doc.catalog[:refs]['tigers']
refute_nil ref
assert_equal '"Tigers roam here"', ref.reftext
end
test 'anchor with label containing a comma creates reference' do
doc = document_from_string %([[tigers,Tigers, scary tigers, roam here]]Tigers roam here.)
ref = doc.catalog[:refs]['tigers']
refute_nil ref
assert_equal 'Tigers, scary tigers, roam here', ref.reftext
end
end