# encoding: UTF-8
unless defined? ASCIIDOCTOR_PROJECT_DIR
$: << File.dirname(__FILE__); $:.uniq!
require 'test_helper'
end
context "Blocks" do
context 'Line Breaks' do
test "ruler" do
output = render_string("'''")
assert_xpath '//*[@id="content"]/hr', output, 1
assert_xpath '//*[@id="content"]/*', output, 1
end
test "ruler between blocks" do
output = render_string("Block above\n\n'''\n\nBlock below")
assert_xpath '//*[@id="content"]/hr', output, 1
assert_xpath '//*[@id="content"]/hr/preceding-sibling::*', output, 1
assert_xpath '//*[@id="content"]/hr/following-sibling::*', output, 1
end
test "page break" do
output = render_embedded_string("page 1\n\n<<<\n\npage 2")
assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]', output, 1
assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]/preceding-sibling::div/p[text()="page 1"]', output, 1
assert_xpath '/*[translate(@style, ";", "")="page-break-after: always"]/following-sibling::div/p[text()="page 2"]', output, 1
end
end
context 'Comments' do
test 'line comment between paragraphs offset by blank lines' do
input = <<-EOS
first paragraph
// line comment
second paragraph
EOS
output = render_embedded_string input
refute_match(/line comment/, output)
assert_xpath '//p', output, 2
end
test 'adjacent line comment between paragraphs' do
input = <<-EOS
first line
// line comment
second line
EOS
output = render_embedded_string input
refute_match(/line comment/, output)
assert_xpath '//p', output, 1
assert_xpath "//p[1][text()='first line\nsecond line']", output, 1
end
test 'comment block between paragraphs offset by blank lines' do
input = <<-EOS
first paragraph
////
block comment
////
second paragraph
EOS
output = render_embedded_string input
refute_match(/block comment/, output)
assert_xpath '//p', output, 2
end
test 'adjacent comment block between paragraphs' do
input = <<-EOS
first paragraph
////
block comment
////
second paragraph
EOS
output = render_embedded_string input
refute_match(/block comment/, output)
assert_xpath '//p', output, 2
end
test "can render with block comment at end of document with trailing endlines" do
input = <<-EOS
paragraph
////
block comment
////
EOS
output = render_embedded_string input
refute_match(/block comment/, output)
end
test "trailing endlines after block comment at end of document does not create paragraph" do
input = <<-EOS
paragraph
////
block comment
////
EOS
d = document_from_string input
assert_equal 1, d.blocks.size
assert_xpath '//p', d.render, 1
end
test 'line starting with three slashes should not be line comment' do
input = <<-EOS
/// not a line comment
EOS
output = render_embedded_string input
assert !output.strip.empty?, "Line should be emitted => #{input.rstrip}"
end
test 'preprocessor directives should not be processed within comment block within block metadata' do
input = <<-EOS
.sample title
////
ifdef::asciidoctor[////]
////
line should be rendered
EOS
output = render_embedded_string input
assert_xpath '//p[text() = "line should be rendered"]', output, 1
end
test 'preprocessor directives should not be processed within comment block' do
input = <<-EOS
dummy line
////
ifdef::asciidoctor[////]
////
line should be rendered
EOS
output = render_embedded_string input
assert_xpath '//p[text() = "line should be rendered"]', output, 1
end
# WARNING if first line of content is a directive, it will get interpretted before we know it's a comment block
# it happens because we always look a line ahead...not sure what we can do about it
test 'preprocessor directives should not be processed within comment open block' do
input = <<-EOS
[comment]
--
first line of comment
ifdef::asciidoctor[--]
line should not be rendered
--
EOS
output = render_embedded_string input
assert_xpath '//p', output, 0
end
# WARNING if first line of content is a directive, it will get interpretted before we know it's a comment block
# it happens because we always look a line ahead...not sure what we can do about it
test 'preprocessor directives should not be processed within comment paragraph' do
input = <<-EOS
[comment]
first line of content
ifdef::asciidoctor[////]
this line should be rendered
EOS
output = render_embedded_string input
assert_xpath '//p[text() = "this line should be rendered"]', output, 1
end
test 'comment style on open block should only skip block' do
input = <<-EOS
[comment]
--
skip
this block
--
not this text
EOS
result = render_embedded_string input
assert_xpath '//p', result, 1
assert_xpath '//p[text()="not this text"]', result, 1
end
test 'comment style on paragraph should only skip paragraph' do
input = <<-EOS
[comment]
skip
this paragraph
not this text
EOS
result = render_embedded_string input
assert_xpath '//p', result, 1
assert_xpath '//p[text()="not this text"]', result, 1
end
test 'comment style on paragraph should not cause adjacent block to be skipped' do
input = <<-EOS
[comment]
skip
this paragraph
[example]
not this text
EOS
result = render_embedded_string input
assert_xpath '/*[@class="exampleblock"]', result, 1
assert_xpath '/*[@class="exampleblock"]//*[normalize-space(text())="not this text"]', result, 1
end
end
context 'Quote and Verse Blocks' do
test 'quote block with no attribution' do
input = <<-EOS
____
A famous quote.
____
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
assert_css '.quoteblock > .attribution', output, 0
assert_xpath '//*[@class = "quoteblock"]//p[text() = "A famous quote."]', output, 1
end
test 'quote block with attribution' do
input = <<-EOS
[quote, Famous Person, Famous Book (1999)]
____
A famous quote.
____
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
assert_css '.quoteblock > .attribution', output, 1
assert_css '.quoteblock > .attribution > cite', output, 1
assert_css '.quoteblock > .attribution > br + cite', output, 1
assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Book (1999)"]', output, 1
attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
author = attribution.children.first
assert_equal "#{expand_entity 8212} Famous Person", author.text.strip
end
test 'quote block with attribute and id and role shorthand' do
input = <<-EOS
[quote#think.big, Donald Trump]
____
As long as your going to be thinking anyway, think big.
____
EOS
output = render_embedded_string input
assert_css '.quoteblock', output, 1
assert_css '#think.quoteblock.big', output, 1
assert_css '.quoteblock > .attribution', output, 1
end
test 'quote block with complex content' do
input = <<-EOS
____
A famous quote.
NOTE: _That_ was inspiring.
____
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph', output, 1
assert_css '.quoteblock > blockquote > .paragraph + .admonitionblock', output, 1
end
test 'quote block using air quotes with no attribution' do
input = <<-EOS
""
A famous quote.
""
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
assert_css '.quoteblock > .attribution', output, 0
assert_xpath '//*[@class = "quoteblock"]//p[text() = "A famous quote."]', output, 1
end
test 'markdown-style quote block with single paragraph and no attribution' do
input = <<-EOS
> A famous quote.
> Some more inspiring words.
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
assert_css '.quoteblock > .attribution', output, 0
assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
end
test 'lazy markdown-style quote block with single paragraph and no attribution' do
input = <<-EOS
> A famous quote.
Some more inspiring words.
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
assert_css '.quoteblock > .attribution', output, 0
assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
end
test 'markdown-style quote block with multiple paragraphs and no attribution' do
input = <<-EOS
> A famous quote.
>
> Some more inspiring words.
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph > p', output, 2
assert_css '.quoteblock > .attribution', output, 0
assert_xpath %((//*[@class = "quoteblock"]//p)[1][text() = "A famous quote."]), output, 1
assert_xpath %((//*[@class = "quoteblock"]//p)[2][text() = "Some more inspiring words."]), output, 1
end
test 'markdown-style quote block with multiple blocks and no attribution' do
input = <<-EOS
> A famous quote.
>
> NOTE: Some more inspiring words.
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
assert_css '.quoteblock > blockquote > .admonitionblock', output, 1
assert_css '.quoteblock > .attribution', output, 0
assert_xpath %((//*[@class = "quoteblock"]//p)[1][text() = "A famous quote."]), output, 1
assert_xpath %((//*[@class = "quoteblock"]//*[@class = "admonitionblock note"]//*[@class="content"])[1][normalize-space(text()) = "Some more inspiring words."]), output, 1
end
test 'markdown-style quote block with single paragraph and attribution' do
input = <<-EOS
> A famous quote.
> Some more inspiring words.
> -- Famous Person, Famous Source, Volume 1 (1999)
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_css '.quoteblock > blockquote > .paragraph > p', output, 1
assert_xpath %(//*[@class = "quoteblock"]//p[text() = "A famous quote.\nSome more inspiring words."]), output, 1
assert_css '.quoteblock > .attribution', output, 1
assert_css '.quoteblock > .attribution > cite', output, 1
assert_css '.quoteblock > .attribution > br + cite', output, 1
assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Source, Volume 1 (1999)"]', output, 1
attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
author = attribution.children.first
assert_equal "#{expand_entity 8212} Famous Person", author.text.strip
end
test 'quoted paragraph-style quote block with attribution' do
input = <<-EOS
"A famous quote.
Some more inspiring words."
-- Famous Person, Famous Source, Volume 1 (1999)
EOS
output = render_string input
assert_css '.quoteblock', output, 1
assert_css '.quoteblock > blockquote', output, 1
assert_xpath %(//*[@class = "quoteblock"]/blockquote[normalize-space(text()) = "A famous quote. Some more inspiring words."]), output, 1
assert_css '.quoteblock > .attribution', output, 1
assert_css '.quoteblock > .attribution > cite', output, 1
assert_css '.quoteblock > .attribution > br + cite', output, 1
assert_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]/cite[text() = "Famous Source, Volume 1 (1999)"]', output, 1
attribution = xmlnodes_at_xpath '//*[@class = "quoteblock"]/*[@class = "attribution"]', output, 1
author = attribution.children.first
assert_equal "#{expand_entity 8212} Famous Person", author.text.strip
end
test 'single-line verse block without attribution' do
input = <<-EOS
[verse]
____
A famous verse.
____
EOS
output = render_string input
assert_css '.verseblock', output, 1
assert_css '.verseblock > pre', output, 1
assert_css '.verseblock > .attribution', output, 0
assert_css '.verseblock p', output, 0
assert_xpath '//*[@class = "verseblock"]/pre[normalize-space(text()) = "A famous verse."]', output, 1
end
test 'single-line verse block with attribution' do
input = <<-EOS
[verse, Famous Poet, Famous Poem]
____
A famous verse.
____
EOS
output = render_string input
assert_css '.verseblock', output, 1
assert_css '.verseblock p', output, 0
assert_css '.verseblock > pre', output, 1
assert_css '.verseblock > .attribution', output, 1
assert_css '.verseblock > .attribution > cite', output, 1
assert_css '.verseblock > .attribution > br + cite', output, 1
assert_xpath '//*[@class = "verseblock"]/*[@class = "attribution"]/cite[text() = "Famous Poem"]', output, 1
attribution = xmlnodes_at_xpath '//*[@class = "verseblock"]/*[@class = "attribution"]', output, 1
author = attribution.children.first
assert_equal "#{expand_entity 8212} Famous Poet", author.text.strip
end
test 'multi-stanza verse block' do
input = <<-EOS
[verse]
____
A famous verse.
Stanza two.
____
EOS
output = render_string input
assert_xpath '//*[@class = "verseblock"]', output, 1
assert_xpath '//*[@class = "verseblock"]/pre', output, 1
assert_xpath '//*[@class = "verseblock"]//p', output, 0
assert_xpath '//*[@class = "verseblock"]/pre[contains(text(), "A famous verse.")]', output, 1
assert_xpath '//*[@class = "verseblock"]/pre[contains(text(), "Stanza two.")]', output, 1
end
test 'verse block does not contain block elements' do
input = <<-EOS
[verse]
____
A famous verse.
....
not a literal
....
____
EOS
output = render_string input
assert_css '.verseblock', output, 1
assert_css '.verseblock > pre', output, 1
assert_css '.verseblock p', output, 0
assert_css '.verseblock .literalblock', output, 0
end
test 'verse should have normal subs' do
input = <<-EOS
[verse]
____
A famous verse
____
EOS
verse = block_from_string input
assert_equal Asciidoctor::Substitutors::SUBS[:normal], verse.subs
end
test 'should not recognize callouts in a verse' do
input = <<-EOS
[verse]
____
La la la <1>
____
<1> Not pointing to a callout
EOS
output = render_embedded_string input
assert_xpath '//pre[text()="La la la <1>"]', output, 1
end
test 'should perform normal subs on a verse block' do
input = <<-EOS
[verse]
____
_GET /groups/link:#group-id[\{group-id\}]_
____
EOS
output = render_embedded_string input
assert output.include?('
')
end
end
context "Example Blocks" do
test "can render example block" do
input = <<-EOS
====
This is an example of an example block.
How crazy is that?
====
EOS
output = render_string input
assert_xpath '//*[@class="exampleblock"]//p', output, 2
end
test "assigns sequential numbered caption to example block with title" do
input = <<-EOS
.Writing Docs with AsciiDoc
====
Here's how you write AsciiDoc.
You just write.
====
.Writing Docs with DocBook
====
Here's how you write DocBook.
You futz with XML.
====
EOS
doc = document_from_string input
output = doc.render
assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Example 1. Writing Docs with AsciiDoc"]', output, 1
assert_xpath '(//*[@class="exampleblock"])[2]/*[@class="title"][text()="Example 2. Writing Docs with DocBook"]', output, 1
assert_equal 2, doc.attributes['example-number']
end
test "assigns sequential character caption to example block with title" do
input = <<-EOS
:example-number: @
.Writing Docs with AsciiDoc
====
Here's how you write AsciiDoc.
You just write.
====
.Writing Docs with DocBook
====
Here's how you write DocBook.
You futz with XML.
====
EOS
doc = document_from_string input
output = doc.render
assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Example A. Writing Docs with AsciiDoc"]', output, 1
assert_xpath '(//*[@class="exampleblock"])[2]/*[@class="title"][text()="Example B. Writing Docs with DocBook"]', output, 1
assert_equal 'B', doc.attributes['example-number']
end
test "explicit caption is used if provided" do
input = <<-EOS
[caption="Look! "]
.Writing Docs with AsciiDoc
====
Here's how you write AsciiDoc.
You just write.
====
EOS
doc = document_from_string input
output = doc.render
assert_xpath '(//*[@class="exampleblock"])[1]/*[@class="title"][text()="Look! Writing Docs with AsciiDoc"]', output, 1
assert !doc.attributes.has_key?('example-number')
end
test 'explicit caption is set on block even if block has no title' do
input = <<-EOS
[caption="Look!"]
====
Just write.
====
EOS
doc = document_from_string input
assert_equal 'Look!', doc.blocks.first.caption
output = doc.render
refute_match(/Look/, output)
end
test 'automatic caption can be turned off and on and modified' do
input = <<-EOS
.first example
====
an example
====
:caption:
.second example
====
another example
====
:caption!:
:example-caption: Exhibit
.third example
====
yet another example
====
EOS
output = render_embedded_string input
assert_xpath '/*[@class="exampleblock"]', output, 3
assert_xpath '(/*[@class="exampleblock"])[1]/*[@class="title"][starts-with(text(), "Example ")]', output, 1
assert_xpath '(/*[@class="exampleblock"])[2]/*[@class="title"][text()="second example"]', output, 1
assert_xpath '(/*[@class="exampleblock"])[3]/*[@class="title"][starts-with(text(), "Exhibit ")]', output, 1
end
end
context 'Admonition Blocks' do
test 'caption block-level attribute should be used as caption' do
input = <<-EOS
:tip-caption: Pro Tip
[caption="Pro Tip"]
TIP: Override the caption of an admonition block using an attribute entry
EOS
output = render_embedded_string input
assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Pro Tip"]', output, 1
end
test 'can override caption of admonition block using document attribute' do
input = <<-EOS
:tip-caption: Pro Tip
TIP: Override the caption of an admonition block using an attribute entry
EOS
output = render_embedded_string input
assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Pro Tip"]', output, 1
end
test 'blank caption document attribute should not blank admonition block caption' do
input = <<-EOS
:caption:
TIP: Override the caption of an admonition block using an attribute entry
EOS
output = render_embedded_string input
assert_xpath '/*[@class="admonitionblock tip"]//*[@class="icon"]/*[@class="title"][text()="Tip"]', output, 1
end
end
context "Preformatted Blocks" do
test 'should separate adjacent paragraphs and listing into blocks' do
input = <<-EOS
paragraph 1
----
listing content
----
paragraph 2
EOS
output = render_embedded_string input
assert_xpath '/*[@class="paragraph"]/p', output, 2
assert_xpath '/*[@class="listingblock"]', output, 1
assert_xpath '(/*[@class="paragraph"]/following-sibling::*)[1][@class="listingblock"]', output, 1
end
test "should preserve endlines in literal block" do
input = <<-EOS
....
line one
line two
line three
....
EOS
[true, false].each {|header_footer|
output = render_string input, :header_footer => header_footer
assert_xpath '//pre', output, 1
assert_xpath '//pre/text()', output, 1
text = xmlnodes_at_xpath('//pre/text()', output, 1).text
lines = text.lines.entries
assert_equal 5, lines.size
expected = "line one\n\nline two\n\nline three".lines.entries
assert_equal expected, lines
blank_lines = output.scan(/\n[ \t]*\n/).size
assert blank_lines >= 2
}
end
test "should preserve endlines in listing block" do
input = <<-EOS
[source]
----
line one
line two
line three
----
EOS
[true, false].each {|header_footer|
output = render_string input, header_footer => header_footer
assert_xpath '//pre/code', output, 1
assert_xpath '//pre/code/text()', output, 1
text = xmlnodes_at_xpath('//pre/code/text()', output, 1).text
lines = text.lines.entries
assert_equal 5, lines.size
expected = "line one\n\nline two\n\nline three".lines.entries
assert_equal expected, lines
blank_lines = output.scan(/\n[ \t]*\n/).size
assert blank_lines >= 2
}
end
test "should preserve endlines in verse block" do
input = <<-EOS
--
[verse]
____
line one
line two
line three
____
--
EOS
[true, false].each {|header_footer|
output = render_string input, :header_footer => header_footer
assert_xpath '//*[@class="verseblock"]/pre', output, 1
assert_xpath '//*[@class="verseblock"]/pre/text()', output, 1
text = xmlnodes_at_xpath('//*[@class="verseblock"]/pre/text()', output, 1).text
lines = text.lines.entries
assert_equal 5, lines.size
expected = "line one\n\nline two\n\nline three".lines.entries
assert_equal expected, lines
blank_lines = output.scan(/\n[ \t]*\n/).size
assert blank_lines >= 2
}
end
test 'should strip leading and trailing blank lines when rendering verbatim block' do
input = <<-EOS
[subs="attributes"]
....
first line
last line
{empty}
....
EOS
doc = document_from_string input, :header_footer => false
block = doc.blocks.first
assert_equal ['', '', ' first line', '', 'last line', '', '{empty}', ''], block.lines
result = doc.render
assert_xpath %(//pre[text()=" first line\n\nlast line"]), result, 1
end
test 'should process block with CRLF endlines' do
input = <<-EOS
[source]\r
----\r
source line 1\r
source line 2\r
----\r
EOS
output = render_embedded_string input
refute_match(/\[source\]/, output)
assert_xpath '/*[@class="listingblock"]//pre', output, 1
assert_xpath '/*[@class="listingblock"]//pre/code', output, 1
assert_xpath %(/*[@class="listingblock"]//pre/code[text()="source line 1\nsource line 2"]), output, 1
end
test 'should remove block indent if indent attribute is 0' do
input = <<-EOS
[indent="0"]
----
def names
@names.split ' '
end
----
EOS
expected = <<-EOS
def names
@names.split ' '
end
EOS
output = render_embedded_string input
assert_css 'pre', output, 1
assert_css '.listingblock pre', output, 1
result = xmlnodes_at_xpath('//pre', output, 1).text
assert_equal expected.chomp, result
end
test 'should not remove block indent if indent attribute is -1' do
input = <<-EOS
[indent="-1"]
----
def names
@names.split ' '
end
----
EOS
expected = <<-EOS
def names
@names.split ' '
end
EOS
output = render_embedded_string input
assert_css 'pre', output, 1
assert_css '.listingblock pre', output, 1
result = xmlnodes_at_xpath('//pre', output, 1).text
assert_equal expected.chomp, result
end
test 'should set block indent to value specified by indent attribute' do
input = <<-EOS
[indent="1"]
----
def names
@names.split ' '
end
----
EOS
expected = <<-EOS
def names
@names.split ' '
end
EOS
output = render_embedded_string input
assert_css 'pre', output, 1
assert_css '.listingblock pre', output, 1
result = xmlnodes_at_xpath('//pre', output, 1).text
assert_equal expected.chomp, result
end
test 'should set block indent to value specified by indent document attribute' do
input = <<-EOS
:source-indent: 1
[source,ruby]
----
def names
@names.split ' '
end
----
EOS
expected = <<-EOS
def names
@names.split ' '
end
EOS
output = render_embedded_string input
assert_css 'pre', output, 1
assert_css '.listingblock pre', output, 1
result = xmlnodes_at_xpath('//pre', output, 1).text
assert_equal expected.chomp, result
end
test 'should expand tabs if tabsize attribute is positive' do
input = <<-EOS
:tabsize: 4
[indent=0]
----
def names
@names.split ' '
end
----
EOS
expected = <<-EOS
def names
@names.split ' '
end
EOS
output = render_embedded_string input
assert_css 'pre', output, 1
assert_css '.listingblock pre', output, 1
result = xmlnodes_at_xpath('//pre', output, 1).text
assert_equal expected.chomp, result
end
test 'literal block should honor nowrap option' do
input = <<-EOS
[options="nowrap"]
----
Do not wrap me if I get too long.
----
EOS
output = render_embedded_string input
assert_css 'pre.nowrap', output, 1
end
test 'literal block should set nowrap class if prewrap document attribute is disabled' do
input = <<-EOS
:prewrap!:
----
Do not wrap me if I get too long.
----
EOS
output = render_embedded_string input
assert_css 'pre.nowrap', output, 1
end
test 'literal block should honor explicit subs list' do
input = <<-EOS
[subs="verbatim,quotes"]
----
Map *attributes*; //<1>
----
EOS
block = block_from_string input
assert_equal [:specialcharacters,:callouts,:quotes], block.subs
output = block.render
assert output.include?('Map<String, String> attributes;')
assert_xpath '//pre/b[text()="(1)"]', output, 1
end
test 'should be able to disable callouts for literal block' do
input = <<-EOS
[subs="specialcharacters"]
----
No callout here <1>
----
EOS
block = block_from_string input
assert_equal [:specialcharacters], block.subs
output = block.render
assert_xpath '//pre/b[text()="(1)"]', output, 0
end
test 'listing block should honor explicit subs list' do
input = <<-EOS
[subs="specialcharacters,quotes"]
----
$ *python functional_tests.py*
Traceback (most recent call last):
File "functional_tests.py", line 4, in
assert 'Django' in browser.title
AssertionError
----
EOS
output = render_embedded_string input
assert_css '.listingblock pre', output, 1
assert_css '.listingblock pre strong', output, 1
assert_css '.listingblock pre em', output, 0
input2 = <<-EOS
[subs="specialcharacters,macros"]
----
$ pass:quotes[*python functional_tests.py*]
Traceback (most recent call last):
File "functional_tests.py", line 4, in
assert pass:quotes['Django'] in browser.title
AssertionError
----
EOS
output2 = render_embedded_string input2
# FIXME JRuby is adding extra trailing endlines in the second document,
# for now, rstrip is necessary
assert_equal output.rstrip, output2.rstrip
end
test 'listing block without title should generate screen element in docbook' do
input = <<-EOS
----
listing block
----
EOS
output = render_embedded_string input, :backend => 'docbook'
assert_xpath '/screen[text()="listing block"]', output, 1
end
test 'listing block with title should generate screen element inside formalpara element in docbook' do
input = <<-EOS
.title
----
listing block
----
EOS
output = render_embedded_string input, :backend => 'docbook'
assert_xpath '/formalpara', output, 1
assert_xpath '/formalpara/title[text()="title"]', output, 1
assert_xpath '/formalpara/para/screen[text()="listing block"]', output, 1
end
test 'source block with no title or language should generate screen element in docbook' do
input = <<-EOS
[source]
----
listing block
----
EOS
output = render_embedded_string input, :backend => 'docbook'
assert_xpath '/screen[text()="listing block"]', output, 1
end
test 'source block with title and no language should generate screen element inside formalpara element in docbook' do
input = <<-EOS
[source]
.title
----
listing block
----
EOS
output = render_embedded_string input, :backend => 'docbook'
assert_xpath '/formalpara', output, 1
assert_xpath '/formalpara/title[text()="title"]', output, 1
assert_xpath '/formalpara/para/screen[text()="listing block"]', output, 1
end
end
context "Open Blocks" do
test "can render open block" do
input = <<-EOS
--
This is an open block.
It can span multiple lines.
--
EOS
output = render_string input
assert_xpath '//*[@class="openblock"]//p', output, 2
end
test "open block can contain another block" do
input = <<-EOS
--
This is an open block.
It can span multiple lines.
____
It can hold great quotes like this one.
____
--
EOS
output = render_string input
assert_xpath '//*[@class="openblock"]//p', output, 3
assert_xpath '//*[@class="openblock"]//*[@class="quoteblock"]', output, 1
end
end
context 'Passthrough Blocks' do
test 'can parse a passthrough block' do
input = <<-EOS
++++
This is a passthrough block.
++++
EOS
block = block_from_string input
assert !block.nil?
assert_equal 1, block.lines.size
assert_equal 'This is a passthrough block.', block.source
end
test 'does not perform subs on a passthrough block by default' do
input = <<-EOS
:type: passthrough
++++
This is a '{type}' block.
http://asciidoc.org
image:tiger.png[]
++++
EOS
expected = %(This is a '{type}' block.\nhttp://asciidoc.org\nimage:tiger.png[])
output = render_embedded_string input
assert_equal expected, output.strip
end
test 'does not perform subs on a passthrough block with pass style by default' do
input = <<-EOS
:type: passthrough
[pass]
++++
This is a '{type}' block.
http://asciidoc.org
image:tiger.png[]
++++
EOS
expected = %(This is a '{type}' block.\nhttp://asciidoc.org\nimage:tiger.png[])
output = render_embedded_string input
assert_equal expected, output.strip
end
test 'passthrough block honors explicit subs list' do
input = <<-EOS
:type: passthrough
[subs="attributes,quotes,macros"]
++++
This is a _{type}_ block.
http://asciidoc.org
++++
EOS
expected = %(This is a passthrough block.\nhttp://asciidoc.org)
output = render_embedded_string input
assert_equal expected, output.strip
end
test 'should strip leading and trailing blank lines when rendering raw block' do
input = <<-EOS
++++
line above
++++
++++
first line
last line
++++
++++
line below
++++
EOS
doc = document_from_string input, :header_footer => false
block = doc.blocks[1]
assert_equal ['', '', ' first line', '', 'last line', '', ''], block.lines
result = doc.render
assert_equal "line above\n first line\n\nlast line\nline below", result, 1
end
end
context 'Math blocks' do
test 'should add LaTeX math delimiters around latexmath block content' do
input = <<-'EOS'
[latexmath]
++++
\sqrt{3x-1}+(1+x)^2 < y
++++
EOS
output = render_embedded_string input
assert_css '.stemblock', output, 1
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output, 1
assert_equal '\[\sqrt{3x-1}+(1+x)^2 < y\]', nodes.first.to_s.strip
end
test 'should not add LaTeX math delimiters around latexmath block content if already present' do
input = <<-'EOS'
[latexmath]
++++
\[\sqrt{3x-1}+(1+x)^2 < y\]
++++
EOS
output = render_embedded_string input
assert_css '.stemblock', output, 1
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output, 1
assert_equal '\[\sqrt{3x-1}+(1+x)^2 < y\]', nodes.first.to_s.strip
end
test 'should render latexmath block in alt of equation in DocBook backend' do
input = <<-'EOS'
[latexmath]
++++
\sqrt{3x-1}+(1+x)^2 < y
++++
EOS
expect = <<-'EOS'
EOS
output = render_embedded_string input, :backend => :docbook
assert_equal expect.strip, output.strip
end
test 'should add AsciiMath delimiters around asciimath block content' do
input = <<-'EOS'
[asciimath]
++++
sqrt(3x-1)+(1+x)^2 < y
++++
EOS
output = render_embedded_string input
assert_css '.stemblock', output, 1
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output, 1
assert_equal '\$sqrt(3x-1)+(1+x)^2 < y\$', nodes.first.to_s.strip
end
test 'should not add AsciiMath delimiters around asciimath block content if already present' do
input = <<-'EOS'
[asciimath]
++++
\$sqrt(3x-1)+(1+x)^2 < y\$
++++
EOS
output = render_embedded_string input
assert_css '.stemblock', output, 1
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output, 1
assert_equal '\$sqrt(3x-1)+(1+x)^2 < y\$', nodes.first.to_s.strip
end
test 'should render asciimath block in textobject of equation in DocBook backend' do
input = <<-'EOS'
[asciimath]
++++
x+b/(2a)<+-sqrt((b^2)/(4a^2)-c/a)
++++
EOS
expect = %(x+b2a<±b24a2−ca)
output = render_embedded_string input, :backend => :docbook
assert_equal expect.strip, output.strip
end
test 'should output title for latexmath block if defined' do
input = <<-'EOS'
.The Lorenz Equations
[latexmath]
++++
\begin{aligned}
\dot{x} & = \sigma(y-x) \\
\dot{y} & = \rho x - y - xz \\
\dot{z} & = -\beta z + xy
\end{aligned}
++++
EOS
output = render_embedded_string input
assert_css '.stemblock', output, 1
assert_css '.stemblock .title', output, 1
assert_xpath '//*[@class="title"][text()="The Lorenz Equations"]', output, 1
end
test 'should output title for asciimath block if defined' do
input = <<-'EOS'
.Simple fraction
[asciimath]
++++
a//b
++++
EOS
output = render_embedded_string input
assert_css '.stemblock', output, 1
assert_css '.stemblock .title', output, 1
assert_xpath '//*[@class="title"][text()="Simple fraction"]', output, 1
end
test 'should add AsciiMath delimiters around stem block content if stem attribute != latexmath' do
input = <<-'EOS'
[stem]
++++
sqrt(3x-1)+(1+x)^2 < y
++++
EOS
[
{},
{'stem' => ''},
{'stem' => 'asciimath'}
].each do |attributes|
output = render_embedded_string input, :attributes => attributes
assert_css '.stemblock', output, 1
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output, 1
assert_equal '\$sqrt(3x-1)+(1+x)^2 < y\$', nodes.first.to_s.strip
end
end
test 'should add LaTeX math delimiters around stem block content if stem attribute is latexmath' do
input = <<-'EOS'
[stem]
++++
\sqrt{3x-1}+(1+x)^2 < y
++++
EOS
output = render_embedded_string input, :attributes => {'stem' => 'latexmath'}
assert_css '.stemblock', output, 1
nodes = xmlnodes_at_xpath '//*[@class="content"]/child::text()', output, 1
assert_equal '\[\sqrt{3x-1}+(1+x)^2 < y\]', nodes.first.to_s.strip
end
end
context 'Metadata' do
test 'block title above section gets carried over to first block in section' do
input = <<-EOS
.Title
== Section
paragraph
EOS
output = render_string input
assert_xpath '//*[@class="paragraph"]', output, 1
assert_xpath '//*[@class="paragraph"]/*[@class="title"][text() = "Title"]', output, 1
assert_xpath '//*[@class="paragraph"]/p[text() = "paragraph"]', output, 1
end
test 'block title above document title demotes document title to a section title' do
input = <<-EOS
.Block title
= Section Title
section paragraph
EOS
output, errors = nil
redirect_streams do |stdout, stderr|
output = render_string input
errors = stderr.string
end
assert_xpath '//*[@id="header"]/*', output, 0
assert_xpath '//*[@id="preamble"]/*', output, 0
assert_xpath '//*[@id="content"]/h1[text()="Section Title"]', output, 1
assert_xpath '//*[@class="paragraph"]', output, 1
assert_xpath '//*[@class="paragraph"]/*[@class="title"][text()="Block title"]', output, 1
assert !errors.empty?
assert_match(/only book doctypes can contain level 0 sections/, errors)
end
test 'block title above document title gets carried over to first block in first section if no preamble' do
input = <<-EOS
.Block title
= Document Title
== First Section
paragraph
EOS
output = render_string input
assert_xpath '//*[@class="sect1"]//*[@class="paragraph"]/*[@class="title"][text() = "Block title"]', output, 1
end
test 'empty attribute list should not appear in output' do
input = <<-EOS
[]
--
Block content
--
EOS
output = render_embedded_string input
assert output.include?('Block content')
assert !output.include?('[]')
end
test 'empty block anchor should not appear in output' do
input = <<-EOS
[[]]
--
Block content
--
EOS
output = render_embedded_string input
assert output.include?('Block content')
assert !output.include?('[[]]')
end
end
context 'Images' do
test 'can render block image with alt text defined in macro' do
input = <<-EOS
image::images/tiger.png[Tiger]
EOS
output = render_embedded_string input
assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1
end
test 'renders SVG image using img element by default' do
input = <<-EOS
image::tiger.svg[Tiger]
EOS
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER
assert_xpath '/*[@class="imageblock"]//img[@src="tiger.svg"][@alt="Tiger"]', output, 1
end
test 'renders interactive SVG image with alt text using object element' do
input = <<-EOS
:imagesdir: images
[%interactive]
image::tiger.svg[Tiger,100]
EOS
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER
assert_xpath '/*[@class="imageblock"]//object[@type="image/svg+xml"][@data="images/tiger.svg"][@width="100"]/span[@class="alt"][text()="Tiger"]', output, 1
end
test 'renders SVG image with alt text using img element when safe mode is secure' do
input = <<-EOS
[%interactive]
image::images/tiger.svg[Tiger,100]
EOS
output = render_embedded_string input
assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.svg"][@alt="Tiger"]', output, 1
end
test 'inserts fallback image for SVG inside object element using same dimensions' do
input = <<-EOS
:imagesdir: images
[%interactive]
image::tiger.svg[Tiger,100,fallback=tiger.png]
EOS
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER
assert_xpath '/*[@class="imageblock"]//object[@type="image/svg+xml"][@data="images/tiger.svg"][@width="100"]/img[@src="images/tiger.png"][@width="100"]', output, 1
end
test 'detects SVG image URI that contains a query string' do
input = <<-EOS
:imagesdir: images
[%interactive]
image::http://example.org/tiger.svg?foo=bar[Tiger,100]
EOS
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER
assert_xpath '/*[@class="imageblock"]//object[@type="image/svg+xml"][@data="http://example.org/tiger.svg?foo=bar"][@width="100"]/span[@class="alt"][text()="Tiger"]', output, 1
end
test 'detects SVG image when format attribute is svg' do
input = <<-EOS
:imagesdir: images
[%interactive]
image::http://example.org/tiger-svg[Tiger,100,format=svg]
EOS
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER
assert_xpath '/*[@class="imageblock"]//object[@type="image/svg+xml"][@data="http://example.org/tiger-svg"][@width="100"]/span[@class="alt"][text()="Tiger"]', output, 1
end
test 'renders inline SVG image using svg element' do
input = <<-EOS
:imagesdir: fixtures
[%inline]
image::circle.svg[Tiger,100]
EOS
output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'docdir' => ::File.dirname(__FILE__) }
assert_match(/