# frozen_string_literal: true
require_relative 'test_helper'
# TODO
# - test negatives
# - test role on every quote type
context 'Substitutions' do
BACKSLASH = ?\\
context 'Dispatcher' do
test 'apply normal substitutions' do
para = block_from_string "[blue]_http://asciidoc.org[AsciiDoc]_ & [red]*Ruby*\n§ Making +++documentation+++ together +\nsince (C) {inception_year}."
para.document.attributes['inception_year'] = '2012'
result = para.apply_subs para.source
assert_equal %(AsciiDoc & Ruby\n§ Making documentation together
\nsince © 2012.), result
end
test 'apply_subs should not modify string directly' do
input = ' -- the root of all web'
para = block_from_string input
para_source = para.source
result = para.apply_subs para_source
assert_equal '<html> — the root of all web', result
assert_equal input, para_source
end
test 'should not drop trailing blank lines when performing substitutions' do
para = block_from_string %([%hardbreaks]\nthis\nis\n-> {program})
para.lines << ''
para.lines << ''
para.document.attributes['program'] = 'Asciidoctor'
result = para.apply_subs para.lines
assert_equal ['this
', 'is
', '→ Asciidoctor
', '
', ''], result
result = para.apply_subs para.lines * "\n"
assert_equal %(this
\nis
\n→ Asciidoctor
\n
\n), result
end
test 'should expand subs passed to expand_subs' do
para = block_from_string %({program}\n*bold*\n2 > 1)
para.document.attributes['program'] = 'Asciidoctor'
assert_equal [:specialcharacters], (para.expand_subs [:specialchars])
refute para.expand_subs([:none])
assert_equal [:specialcharacters, :quotes, :attributes, :replacements, :macros, :post_replacements], (para.expand_subs [:normal])
end
test 'apply_subs should allow the subs argument to be nil' do
block = block_from_string %([pass]\n*raw*)
result = block.apply_subs block.source, nil
assert_equal '*raw*', result
end
end
context 'Quotes' do
test 'single-line double-quoted string' do
para = block_from_string %q(``a few quoted words''), attributes: { 'compat-mode' => '' }
assert_equal '“a few quoted words”', para.sub_quotes(para.source)
para = block_from_string '"`a few quoted words`"'
assert_equal '“a few quoted words”', para.sub_quotes(para.source)
para = block_from_string '"`a few quoted words`"', backend: 'docbook'
assert_equal 'a few quoted words
', para.sub_quotes(para.source)
end
test 'escaped single-line double-quoted string' do
para = block_from_string %(#{BACKSLASH}``a few quoted words''), attributes: { 'compat-mode' => '' }
assert_equal %q(‘`a few quoted words’'), para.sub_quotes(para.source)
para = block_from_string %(#{BACKSLASH * 2}``a few quoted words''), attributes: { 'compat-mode' => '' }
assert_equal %q(``a few quoted words''), para.sub_quotes(para.source)
para = block_from_string %(#{BACKSLASH}"`a few quoted words`")
assert_equal '"`a few quoted words`"', para.sub_quotes(para.source)
para = block_from_string %(#{BACKSLASH * 2}"`a few quoted words`")
assert_equal %(#{BACKSLASH}"`a few quoted words`"), para.sub_quotes(para.source)
end
test 'multi-line double-quoted string' do
para = block_from_string %(``a few\nquoted words''), attributes: { 'compat-mode' => '' }
assert_equal %(“a few\nquoted words”), para.sub_quotes(para.source)
para = block_from_string %("`a few\nquoted words`")
assert_equal %(“a few\nquoted words”), para.sub_quotes(para.source)
end
test 'double-quoted string with inline single quote' do
para = block_from_string %q(``Here's Johnny!''), attributes: { 'compat-mode' => '' }
assert_equal %q(“Here's Johnny!”), para.sub_quotes(para.source)
para = block_from_string %q("`Here's Johnny!`")
assert_equal %q(“Here's Johnny!”), para.sub_quotes(para.source)
end
test 'double-quoted string with inline backquote' do
para = block_from_string %q(``Here`s Johnny!''), attributes: { 'compat-mode' => '' }
assert_equal '“Here`s Johnny!”', para.sub_quotes(para.source)
para = block_from_string '"`Here`s Johnny!`"'
assert_equal '“Here`s Johnny!”', para.sub_quotes(para.source)
end
test 'double-quoted string around monospaced text' do
para = block_from_string '"``E=mc^2^` is the solution!`"'
assert_equal '“`E=mc2` is the solution!”', para.apply_subs(para.source)
para = block_from_string '"```E=mc^2^`` is the solution!`"'
assert_equal '“E=mc2 is the solution!”', para.apply_subs(para.source)
end
test 'single-line single-quoted string' do
para = block_from_string %q(`a few quoted words'), attributes: { 'compat-mode' => '' }
assert_equal '‘a few quoted words’', para.sub_quotes(para.source)
para = block_from_string %q('`a few quoted words`')
assert_equal '‘a few quoted words’', para.sub_quotes(para.source)
para = block_from_string %q('`a few quoted words`'), backend: 'docbook'
assert_equal 'a few quoted words
', para.sub_quotes(para.source)
end
test 'escaped single-line single-quoted string' do
para = block_from_string %(#{BACKSLASH}`a few quoted words'), attributes: { 'compat-mode' => '' }
assert_equal %(`a few quoted words'), para.sub_quotes(para.source)
para = block_from_string %(#{BACKSLASH}'`a few quoted words`')
assert_equal %('`a few quoted words`'), para.sub_quotes(para.source)
end
test 'multi-line single-quoted string' do
para = block_from_string %(`a few\nquoted words'), attributes: { 'compat-mode' => '' }
assert_equal %(‘a few\nquoted words’), para.sub_quotes(para.source)
para = block_from_string %('`a few\nquoted words`')
assert_equal %(‘a few\nquoted words’), para.sub_quotes(para.source)
end
test 'single-quoted string with inline single quote' do
para = block_from_string %q(`That isn't what I did.'), attributes: { 'compat-mode' => '' }
assert_equal %q(‘That isn't what I did.’), para.sub_quotes(para.source)
para = block_from_string %q('`That isn't what I did.`')
assert_equal %q(‘That isn't what I did.’), para.sub_quotes(para.source)
end
test 'single-quoted string with inline backquote' do
para = block_from_string %q(`Here`s Johnny!'), attributes: { 'compat-mode' => '' }
assert_equal '‘Here`s Johnny!’', para.sub_quotes(para.source)
para = block_from_string %q('`Here`s Johnny!`')
assert_equal '‘Here`s Johnny!’', para.sub_quotes(para.source)
end
test 'single-line constrained marked string' do
#para = block_from_string('#a few words#', attributes: { 'compat-mode' => '' })
#assert_equal 'a few words', para.sub_quotes(para.source)
para = block_from_string '#a few words#'
assert_equal 'a few words', para.sub_quotes(para.source)
end
test 'escaped single-line constrained marked string' do
para = block_from_string %(#{BACKSLASH}#a few words#)
assert_equal '#a few words#', para.sub_quotes(para.source)
end
test 'multi-line constrained marked string' do
#para = block_from_string %(#a few\nwords#), attributes: { 'compat-mode' => '' }
#assert_equal %(a few\nwords), para.sub_quotes(para.source)
para = block_from_string %(#a few\nwords#)
assert_equal %(a few\nwords), para.sub_quotes(para.source)
end
test 'constrained marked string should not match entity references' do
para = block_from_string '111 #mark a# 222 "`quote a`" 333 #mark b# 444'
assert_equal %(111 mark a 222 “quote a” 333 mark b 444), para.sub_quotes(para.source)
end
test 'single-line unconstrained marked string' do
#para = block_from_string('##--anything goes ##', attributes: { 'compat-mode' => '' })
#assert_equal '--anything goes ', para.sub_quotes(para.source)
para = block_from_string '##--anything goes ##'
assert_equal '--anything goes ', para.sub_quotes(para.source)
end
test 'escaped single-line unconstrained marked string' do
para = block_from_string %(#{BACKSLASH}#{BACKSLASH}##--anything goes ##)
assert_equal '##--anything goes ##', para.sub_quotes(para.source)
end
test 'multi-line unconstrained marked string' do
#para = block_from_string %(##--anything\ngoes ##), attributes: { 'compat-mode' => '' }
#assert_equal %(--anything\ngoes ), para.sub_quotes(para.source)
para = block_from_string %(##--anything\ngoes ##)
assert_equal %(--anything\ngoes ), para.sub_quotes(para.source)
end
test 'single-line constrained marked string with role' do
para = block_from_string '[statement]#a few words#'
assert_equal 'a few words', para.sub_quotes(para.source)
end
test 'does not recognize attribute list with left square bracket on formatted text' do
para = block_from_string 'key: [ *before [.redacted]#redacted# after* ]'
assert_equal 'key: [ before redacted after ]', para.sub_quotes(para.source)
end
test 'should ignore enclosing square brackets when processing formatted text with attribute list' do
doc = document_from_string 'nums = [1, 2, 3, [.blue]#4#]', doctype: :inline
assert_equal 'nums = [1, 2, 3, 4]', doc.convert
end
test 'single-line constrained strong string' do
para = block_from_string '*a few strong words*'
assert_equal 'a few strong words', para.sub_quotes(para.source)
end
test 'escaped single-line constrained strong string' do
para = block_from_string %(#{BACKSLASH}*a few strong words*)
assert_equal '*a few strong words*', para.sub_quotes(para.source)
end
test 'multi-line constrained strong string' do
para = block_from_string %(*a few\nstrong words*)
assert_equal %(a few\nstrong words), para.sub_quotes(para.source)
end
test 'constrained strong string containing an asterisk' do
para = block_from_string '*bl*ck*-eye'
assert_equal 'bl*ck-eye', para.sub_quotes(para.source)
end
test 'constrained strong string containing an asterisk and multibyte word chars' do
para = block_from_string '*黑*眼圈*'
assert_equal '黑*眼圈', para.sub_quotes(para.source)
end
test 'single-line constrained quote variation emphasized string' do
para = block_from_string '_a few emphasized words_'
assert_equal 'a few emphasized words', para.sub_quotes(para.source)
end
test 'escaped single-line constrained quote variation emphasized string' do
para = block_from_string %(#{BACKSLASH}_a few emphasized words_)
assert_equal '_a few emphasized words_', para.sub_quotes(para.source)
end
test 'escaped single quoted string' do
para = block_from_string %(#{BACKSLASH}'a few emphasized words')
# NOTE the \' is replaced with ' by the :replacements substitution, later in the substitution pipeline
assert_equal %(#{BACKSLASH}'a few emphasized words'), para.sub_quotes(para.source)
end
test 'multi-line constrained emphasized quote variation string' do
para = block_from_string %(_a few\nemphasized words_)
assert_equal %(a few\nemphasized words), para.sub_quotes(para.source)
end
test 'single-quoted string containing an emphasized phrase' do
para = block_from_string %q(`I told him, 'Just go for it!''), attributes: { 'compat-mode' => '' }
assert_equal '‘I told him, Just go for it!’', para.sub_quotes(para.source)
para = block_from_string %q('`I told him, 'Just go for it!'`')
assert_equal %q(‘I told him, 'Just go for it!'’), para.sub_quotes(para.source)
end
test 'escaped single-quotes inside emphasized words are restored' do
para = block_from_string %('Here#{BACKSLASH}'s Johnny!'), attributes: { 'compat-mode' => '' }
assert_equal %q(Here's Johnny!), para.apply_subs(para.source)
para = block_from_string %('Here#{BACKSLASH}'s Johnny!')
assert_equal %q('Here's Johnny!'), para.apply_subs(para.source)
end
test 'single-line constrained emphasized underline variation string' do
para = block_from_string '_a few emphasized words_'
assert_equal 'a few emphasized words', para.sub_quotes(para.source)
end
test 'escaped single-line constrained emphasized underline variation string' do
para = block_from_string %(#{BACKSLASH}_a few emphasized words_)
assert_equal '_a few emphasized words_', para.sub_quotes(para.source)
end
test 'multi-line constrained emphasized underline variation string' do
para = block_from_string %(_a few\nemphasized words_)
assert_equal %(a few\nemphasized words), para.sub_quotes(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'single-line constrained monospaced string' do
para = block_from_string %(`a few <{monospaced}> words`), attributes: { 'monospaced' => 'monospaced', 'compat-mode' => '' }
assert_equal 'a few <{monospaced}> words', para.apply_subs(para.source)
para = block_from_string %(`a few <{monospaced}> words`), attributes: { 'monospaced' => 'monospaced' }
assert_equal 'a few <monospaced> words', para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'single-line constrained monospaced string with role' do
para = block_from_string %([input]`a few <{monospaced}> words`), attributes: { 'monospaced' => 'monospaced', 'compat-mode' => '' }
assert_equal 'a few <{monospaced}> words', para.apply_subs(para.source)
para = block_from_string %([input]`a few <{monospaced}> words`), attributes: { 'monospaced' => 'monospaced' }
assert_equal 'a few <monospaced> words', para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'escaped single-line constrained monospaced string' do
para = block_from_string %(#{BACKSLASH}`a few words`), attributes: { 'compat-mode' => '' }
assert_equal '`a few <monospaced> words`', para.apply_subs(para.source)
para = block_from_string %(#{BACKSLASH}`a few words`)
assert_equal '`a few <monospaced> words`', para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'escaped single-line constrained monospaced string with role' do
para = block_from_string %([input]#{BACKSLASH}`a few words`), attributes: { 'compat-mode' => '' }
assert_equal '[input]`a few <monospaced> words`', para.apply_subs(para.source)
para = block_from_string %([input]#{BACKSLASH}`a few words`)
assert_equal '[input]`a few <monospaced> words`', para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'escaped role on single-line constrained monospaced string' do
para = block_from_string %(#{BACKSLASH}[input]`a few words`), attributes: { 'compat-mode' => '' }
assert_equal '[input]a few <monospaced> words', para.apply_subs(para.source)
para = block_from_string %(#{BACKSLASH}[input]`a few words`)
assert_equal '[input]a few <monospaced> words', para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'escaped role on escaped single-line constrained monospaced string' do
para = block_from_string %(#{BACKSLASH}[input]#{BACKSLASH}`a few words`), attributes: { 'compat-mode' => '' }
assert_equal %(#{BACKSLASH}[input]`a few <monospaced> words`), para.apply_subs(para.source)
para = block_from_string %(#{BACKSLASH}[input]#{BACKSLASH}`a few words`)
assert_equal %(#{BACKSLASH}[input]`a few <monospaced> words`), para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'should ignore role that ends with transitional role on constrained monospace span' do
para = block_from_string %([foox-]`leave it alone`)
assert_equal 'leave it alone', para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'escaped single-line constrained monospace string with forced compat role' do
para = block_from_string %([x-]#{BACKSLASH}`leave it alone`)
assert_equal '[x-]`leave it alone`', para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'escaped forced compat role on single-line constrained monospace string' do
para = block_from_string %(#{BACKSLASH}[x-]`just *mono*`)
assert_equal '[x-]just mono', para.apply_subs(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'multi-line constrained monospaced string' do
para = block_from_string %(`a few\n<{monospaced}> words`), attributes: { 'monospaced' => 'monospaced', 'compat-mode' => '' }
assert_equal "a few\n<{monospaced}> words", para.apply_subs(para.source)
para = block_from_string %(`a few\n<{monospaced}> words`), attributes: { 'monospaced' => 'monospaced' }
assert_equal "a few\n<monospaced> words", para.apply_subs(para.source)
end
test 'single-line unconstrained strong chars' do
para = block_from_string '**Git**Hub'
assert_equal 'GitHub', para.sub_quotes(para.source)
end
test 'escaped single-line unconstrained strong chars' do
para = block_from_string %(#{BACKSLASH}**Git**Hub)
assert_equal '*Git*Hub', para.sub_quotes(para.source)
end
test 'multi-line unconstrained strong chars' do
para = block_from_string %(**G\ni\nt\n**Hub)
assert_equal %(G\ni\nt\nHub), para.sub_quotes(para.source)
end
test 'unconstrained strong chars with inline asterisk' do
para = block_from_string '**bl*ck**-eye'
assert_equal 'bl*ck-eye', para.sub_quotes(para.source)
end
test 'unconstrained strong chars with role' do
para = block_from_string 'Git[blue]**Hub**'
assert_equal 'GitHub', para.sub_quotes(para.source)
end
# TODO this is not the same result as AsciiDoc, though I don't understand why AsciiDoc gets what it gets
test 'escaped unconstrained strong chars with role' do
para = block_from_string %(Git#{BACKSLASH}[blue]**Hub**)
assert_equal 'Git[blue]*Hub*', para.sub_quotes(para.source)
end
test 'single-line unconstrained emphasized chars' do
para = block_from_string '__Git__Hub'
assert_equal 'GitHub', para.sub_quotes(para.source)
end
test 'escaped single-line unconstrained emphasized chars' do
para = block_from_string %(#{BACKSLASH}__Git__Hub)
assert_equal '__Git__Hub', para.sub_quotes(para.source)
end
test 'escaped single-line unconstrained emphasized chars around word' do
para = block_from_string %(#{BACKSLASH}#{BACKSLASH}__GitHub__)
assert_equal '__GitHub__', para.sub_quotes(para.source)
end
test 'multi-line unconstrained emphasized chars' do
para = block_from_string %(__G\ni\nt\n__Hub)
assert_equal %(G\ni\nt\nHub), para.sub_quotes(para.source)
end
test 'unconstrained emphasis chars with role' do
para = block_from_string '[gray]__Git__Hub'
assert_equal 'GitHub', para.sub_quotes(para.source)
end
test 'escaped unconstrained emphasis chars with role' do
para = block_from_string %(#{BACKSLASH}[gray]__Git__Hub)
assert_equal '[gray]__Git__Hub', para.sub_quotes(para.source)
end
test 'single-line constrained monospaced chars' do
para = block_from_string 'call +save()+ to persist the changes', attributes: { 'compat-mode' => '' }
assert_equal 'call save() to persist the changes', para.sub_quotes(para.source)
para = block_from_string 'call [x-]+save()+ to persist the changes'
assert_equal 'call save() to persist the changes', para.apply_subs(para.source)
para = block_from_string 'call `save()` to persist the changes'
assert_equal 'call save() to persist the changes', para.sub_quotes(para.source)
end
test 'single-line constrained monospaced chars with role' do
para = block_from_string 'call [method]+save()+ to persist the changes', attributes: { 'compat-mode' => '' }
assert_equal 'call save() to persist the changes', para.sub_quotes(para.source)
para = block_from_string 'call [method x-]+save()+ to persist the changes'
assert_equal 'call save() to persist the changes', para.apply_subs(para.source)
para = block_from_string 'call [method]`save()` to persist the changes'
assert_equal 'call save() to persist the changes', para.sub_quotes(para.source)
end
test 'escaped single-line constrained monospaced chars' do
para = block_from_string %(call #{BACKSLASH}+save()+ to persist the changes), attributes: { 'compat-mode' => '' }
assert_equal 'call +save()+ to persist the changes', para.sub_quotes(para.source)
para = block_from_string %(call #{BACKSLASH}`save()` to persist the changes)
assert_equal 'call `save()` to persist the changes', para.sub_quotes(para.source)
end
test 'escaped single-line constrained monospaced chars with role' do
para = block_from_string %(call [method]#{BACKSLASH}+save()+ to persist the changes), attributes: { 'compat-mode' => '' }
assert_equal 'call [method]+save()+ to persist the changes', para.sub_quotes(para.source)
para = block_from_string %(call [method]#{BACKSLASH}`save()` to persist the changes)
assert_equal 'call [method]`save()` to persist the changes', para.sub_quotes(para.source)
end
test 'escaped role on single-line constrained monospaced chars' do
para = block_from_string %(call #{BACKSLASH}[method]+save()+ to persist the changes), attributes: { 'compat-mode' => '' }
assert_equal 'call [method]save() to persist the changes', para.sub_quotes(para.source)
para = block_from_string %(call #{BACKSLASH}[method]`save()` to persist the changes)
assert_equal 'call [method]save() to persist the changes', para.sub_quotes(para.source)
end
test 'escaped role on escaped single-line constrained monospaced chars' do
para = block_from_string %(call #{BACKSLASH}[method]#{BACKSLASH}+save()+ to persist the changes), attributes: { 'compat-mode' => '' }
assert_equal %(call #{BACKSLASH}[method]+save()+ to persist the changes), para.sub_quotes(para.source)
para = block_from_string %(call #{BACKSLASH}[method]#{BACKSLASH}`save()` to persist the changes)
assert_equal %(call #{BACKSLASH}[method]`save()` to persist the changes), para.sub_quotes(para.source)
end
# NOTE must use apply_subs because constrained monospaced is handled as a passthrough
test 'escaped single-line constrained passthrough string with forced compat role' do
para = block_from_string %([x-]#{BACKSLASH}+leave it alone+)
assert_equal '[x-]+leave it alone+', para.apply_subs(para.source)
end
test 'single-line unconstrained monospaced chars' do
para = block_from_string 'Git++Hub++', attributes: { 'compat-mode' => '' }
assert_equal 'GitHub', para.sub_quotes(para.source)
para = block_from_string 'Git[x-]++Hub++'
assert_equal 'GitHub', para.apply_subs(para.source)
para = block_from_string 'Git``Hub``'
assert_equal 'GitHub', para.sub_quotes(para.source)
end
test 'escaped single-line unconstrained monospaced chars' do
para = block_from_string %(Git#{BACKSLASH}++Hub++), attributes: { 'compat-mode' => '' }
assert_equal 'Git+Hub+', para.sub_quotes(para.source)
para = block_from_string %(Git#{BACKSLASH * 2}++Hub++), attributes: { 'compat-mode' => '' }
assert_equal 'Git++Hub++', para.sub_quotes(para.source)
para = block_from_string %(Git#{BACKSLASH}``Hub``)
assert_equal 'Git``Hub``', para.sub_quotes(para.source)
end
test 'multi-line unconstrained monospaced chars' do
para = block_from_string %(Git++\nH\nu\nb++), attributes: { 'compat-mode' => '' }
assert_equal %(Git\nH\nu\nb), para.sub_quotes(para.source)
para = block_from_string %(Git[x-]++\nH\nu\nb++)
assert_equal %(Git\nH\nu\nb), para.apply_subs(para.source)
para = block_from_string %(Git``\nH\nu\nb``)
assert_equal %(Git\nH\nu\nb), para.sub_quotes(para.source)
end
test 'single-line superscript chars' do
para = block_from_string %(x^2^ = x * x, e = mc^2^, there's a 1^st^ time for everything)
assert_equal %(x2 = x * x, e = mc2, there\'s a 1st time for everything), para.sub_quotes(para.source)
end
test 'escaped single-line superscript chars' do
para = block_from_string %(x#{BACKSLASH}^2^ = x * x)
assert_equal 'x^2^ = x * x', para.sub_quotes(para.source)
end
test 'does not match superscript across whitespace' do
para = block_from_string %(x^(n\n-\n1)^)
assert_equal para.source, para.sub_quotes(para.source)
end
test 'allow spaces in superscript if spaces are inserted using an attribute reference' do
para = block_from_string 'Night ^A{sp}poem{sp}by{sp}Jane{sp}Kondo^.'
assert_equal 'Night A poem by Jane Kondo.', para.apply_subs(para.source)
end
test 'allow spaces in superscript if text is wrapped in a passthrough' do
para = block_from_string 'Night ^+A poem by Jane Kondo+^.'
assert_equal 'Night A poem by Jane Kondo.', para.apply_subs(para.source)
end
test 'does not match adjacent superscript chars' do
para = block_from_string 'a ^^ b'
assert_equal 'a ^^ b', para.sub_quotes(para.source)
end
test 'does not confuse superscript and links with blank window shorthand' do
para = block_from_string 'http://localhost[Text^] on the 21^st^ and 22^nd^'
assert_equal 'Text on the 21st and 22nd', para.content
end
test 'single-line subscript chars' do
para = block_from_string 'H~2~O'
assert_equal 'H2O', para.sub_quotes(para.source)
end
test 'escaped single-line subscript chars' do
para = block_from_string %(H#{BACKSLASH}~2~O)
assert_equal 'H~2~O', para.sub_quotes(para.source)
end
test 'does not match subscript across whitespace' do
para = block_from_string %(project~ view\non\nGitHub~)
assert_equal para.source, para.sub_quotes(para.source)
end
test 'does not match adjacent subscript chars' do
para = block_from_string 'a ~~ b'
assert_equal 'a ~~ b', para.sub_quotes(para.source)
end
test 'does not match subscript across distinct URLs' do
para = block_from_string 'http://www.abc.com/~def[DEF] and http://www.abc.com/~ghi[GHI]'
assert_equal para.source, para.sub_quotes(para.source)
end
test 'quoted text with role shorthand' do
para = block_from_string '[.white.red-background]#alert#'
assert_equal 'alert', para.sub_quotes(para.source)
end
test 'quoted text with id shorthand' do
para = block_from_string '[#bond]#007#'
assert_equal '007', para.sub_quotes(para.source)
end
test 'quoted text with id and role shorthand' do
para = block_from_string '[#bond.white.red-background]#007#'
assert_equal '007', para.sub_quotes(para.source)
end
test 'quoted text with id and role shorthand with roles before id' do
para = block_from_string '[.white.red-background#bond]#007#'
assert_equal '007', para.sub_quotes(para.source)
end
test 'quoted text with id and role shorthand with roles around id' do
para = block_from_string '[.white#bond.red-background]#007#'
assert_equal '007', para.sub_quotes(para.source)
end
test 'quoted text with id and role shorthand using docbook backend' do
para = block_from_string '[#bond.white.red-background]#007#', backend: 'docbook'
assert_equal '007', para.sub_quotes(para.source)
end
test 'should not assign role attribute if shorthand style has no roles' do
para = block_from_string '[#idname]*blah*'
assert_equal 'blah', para.content
end
test 'should remove trailing spaces from role defined using shorthand' do
para = block_from_string '[.rolename ]*blah*'
assert_equal 'blah', para.content
end
test 'should allow role to be defined using attribute reference' do
input = '[{rolename}]#phrase#'
result = convert_string_to_embedded input, doctype: 'inline', attributes: { 'rolename' => 'red' }
assert_equal 'phrase', result
end
test 'should ignore attributes after comma' do
para = block_from_string '[red, foobar]#alert#'
assert_equal 'alert', para.sub_quotes(para.source)
end
test 'should remove leading and trailing spaces around role after ignoring attributes after comma' do
para = block_from_string '[ red , foobar]#alert#'
assert_equal 'alert', para.sub_quotes(para.source)
end
test 'should not assign role if value before comma is empty' do
para = block_from_string '[,]#anonymous#'
assert_equal 'anonymous', para.sub_quotes(para.source)
end
test 'inline passthrough with id and role set using shorthand' do
%w(#idname.rolename .rolename#idname).each do |attrlist|
para = block_from_string %([#{attrlist}]+pass+)
assert_equal 'pass', para.content
end
end
end
context 'Macros' do
test 'a single-line link macro should be interpreted as a link' do
para = block_from_string 'link:/home.html[]'
assert_equal '/home.html', para.sub_macros(para.source)
end
test 'a single-line link macro with text should be interpreted as a link' do
para = block_from_string 'link:/home.html[Home]'
assert_equal 'Home', para.sub_macros(para.source)
end
test 'a mailto macro should be interpreted as a mailto link' do
para = block_from_string 'mailto:doc.writer@asciidoc.org[]'
assert_equal 'doc.writer@asciidoc.org', para.sub_macros(para.source)
end
test 'a mailto macro with text should be interpreted as a mailto link' do
para = block_from_string 'mailto:doc.writer@asciidoc.org[Doc Writer]'
assert_equal 'Doc Writer', para.sub_macros(para.source)
end
test 'a mailto macro with text and subject should be interpreted as a mailto link' do
para = block_from_string 'mailto:doc.writer@asciidoc.org[Doc Writer, Pull request]'
assert_equal 'Doc Writer', para.sub_macros(para.source)
end
test 'a mailto macro with text, subject and body should be interpreted as a mailto link' do
para = block_from_string 'mailto:doc.writer@asciidoc.org[Doc Writer, Pull request, Please accept my pull request]'
assert_equal 'Doc Writer', para.sub_macros(para.source)
end
test 'a mailto macro with subject and body only should use e-mail as text' do
para = block_from_string 'mailto:doc.writer@asciidoc.org[,Pull request,Please accept my pull request]'
assert_equal 'doc.writer@asciidoc.org', para.sub_macros(para.source)
end
test 'a mailto macro supports id and role attributes' do
para = block_from_string 'mailto:doc.writer@asciidoc.org[,id=contact,role=icon]'
assert_equal 'doc.writer@asciidoc.org', para.sub_macros(para.source)
end
test 'should recognize inline email addresses' do
%w(
doc.writer@asciidoc.org
author+website@4fs.no
john@domain.uk.co
name@somewhere.else.com
joe_bloggs@mail_server.com
joe-bloggs@mail-server.com
joe.bloggs@mail.server.com
FOO@BAR.COM
docs@writing.ninja
).each do |input|
para = block_from_string input
assert_equal %(#{input}), (para.sub_macros para.source)
end
end
test 'should recognize inline email address containing an ampersand' do
para = block_from_string 'bert&ernie@sesamestreet.com'
assert_equal 'bert&ernie@sesamestreet.com', para.apply_subs(para.source)
end
test 'should recognize inline email address surrounded by angle brackets' do
para = block_from_string ''
assert_equal '<doc.writer@asciidoc.org>', para.apply_subs(para.source)
end
test 'should ignore escaped inline email address' do
para = block_from_string %(#{BACKSLASH}doc.writer@asciidoc.org)
assert_equal 'doc.writer@asciidoc.org', para.sub_macros(para.source)
end
test 'a single-line raw url should be interpreted as a link' do
para = block_from_string 'http://google.com'
assert_equal 'http://google.com', para.sub_macros(para.source)
end
test 'a single-line raw url with text should be interpreted as a link' do
para = block_from_string 'http://google.com[Google]'
assert_equal 'Google', para.sub_macros(para.source)
end
test 'a multi-line raw url with text should be interpreted as a link' do
para = block_from_string %(http://google.com[Google\nHomepage])
assert_equal %(Google\nHomepage), para.sub_macros(para.source)
end
test 'a single-line raw url with attribute as text should be interpreted as a link with resolved attribute' do
para = block_from_string 'http://google.com[{google_homepage}]'
para.document.attributes['google_homepage'] = 'Google Homepage'
assert_equal 'Google Homepage', para.sub_macros(para.sub_attributes(para.source))
end
test 'should not resolve an escaped attribute in link text' do
{
'http://google.com' => "http://google.com[#{BACKSLASH}{google_homepage}]",
'http://google.com?q=,' => "link:http://google.com?q=,[#{BACKSLASH}{google_homepage}]",
}.each do |uri, macro|
para = block_from_string macro
para.document.attributes['google_homepage'] = 'Google Homepage'
assert_equal %({google_homepage}), para.sub_macros(para.sub_attributes(para.source))
end
end
test 'a single-line escaped raw url should not be interpreted as a link' do
para = block_from_string %(#{BACKSLASH}http://google.com)
assert_equal 'http://google.com', para.sub_macros(para.source)
end
test 'a comma separated list of links should not include commas in links' do
para = block_from_string 'http://foo.com, http://bar.com, http://example.org'
assert_equal 'http://foo.com, http://bar.com, http://example.org', para.sub_macros(para.source)
end
test 'a single-line image macro should be interpreted as an image' do
para = block_from_string 'image:tiger.png[]'
assert_equal '
', para.sub_macros(para.source).gsub(/>\s+, '><')
end
test 'should replace underscore and hyphen with space in generated alt text for an inline image' do
para = block_from_string 'image:tiger-with-family_1.png[]'
assert_equal '
', para.sub_macros(para.source).gsub(/>\s+, '><')
end
test 'a single-line image macro with text should be interpreted as an image with alt text' do
para = block_from_string 'image:tiger.png[Tiger]'
assert_equal '
', para.sub_macros(para.source).gsub(/>\s+, '><')
end
test 'should encode special characters in alt text of inline image' do
input = 'A tiger\'s "roar" is < a bear\'s "growl"'
expected = 'A tiger’s "roar" is < a bear’s "growl"'
output = (convert_inline_string %(image:tiger-roar.png[#{input}])).gsub(/>\s+, '><')
assert_equal %(
), output
end
test 'an image macro with SVG image and text should be interpreted as an image with alt text' do
para = block_from_string 'image:tiger.svg[Tiger]'
assert_equal '
', para.sub_macros(para.source).gsub(/>\s+, '><')
end
test 'an image macro with an interactive SVG image and alt text should be converted to an object element' do
para = block_from_string 'image:tiger.svg[Tiger,opts=interactive]', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'imagesdir' => 'images' }
assert_equal '', para.sub_macros(para.source).gsub(/>\s+, '><')
end
test 'an image macro with an interactive SVG image, fallback and alt text should be converted to an object element' do
para = block_from_string 'image:tiger.svg[Tiger,fallback=tiger.png,opts=interactive]', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'imagesdir' => 'images' }
assert_equal '', para.sub_macros(para.source).gsub(/>\s+, '><')
end
test 'an image macro with an inline SVG image should be converted to an svg element' do
para = block_from_string 'image:circle.svg[Tiger,100,opts=inline]', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'imagesdir' => 'fixtures', 'docdir' => testdir }
result = para.sub_macros(para.source).gsub(/>\s+, '><')
assert_match(/