# 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?('
GET /groups/{group-id}
') 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<±b24a2ca ) 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(/]*width="100px"[^>]*>/, output, 1) refute_match(/]*width="500px"[^>]*>/, output) refute_match(/]*height="500px"[^>]*>/, output) refute_match(/]*style="width:500px;height:500px"[^>]*>/, output) end test 'renders inline SVG image using svg element even when data-uri is set' do input = <<-EOS :imagesdir: fixtures :data-uri: [%inline] image::circle.svg[Tiger,100] EOS output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'docdir' => ::File.dirname(__FILE__) } assert_match(/]*width="100px">/, output, 1) end test 'renders alt text for inline svg element if svg cannot be read' do input = <<-EOS [%inline] image::no-such-image.svg[Alt Text] EOS output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SERVER assert_xpath '//span[@class="alt"][text()="Alt Text"]', output, 1 end test 'can render block image with alt text defined in macro containing escaped square bracket' do input = <<-EOS image::images/tiger.png[A [Bengal\\] Tiger] EOS output = render_string input img = xmlnodes_at_xpath '//img', output, 1 assert_equal 'A [Bengal] Tiger', img.attr('alt').value end test 'can render block image with alt text defined in block attribute above macro' do input = <<-EOS [Tiger] image::images/tiger.png[] EOS output = render_embedded_string input assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1 end test 'alt text in macro overrides alt text above macro' do input = <<-EOS [Alt Text] 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 'alt text is escaped in HTML backend' do input = <<-EOS image::images/open.png[File > Open] EOS output = render_embedded_string input assert_match(/File > Open/, output) end test 'alt text is escaped in DocBook backend' do input = <<-EOS image::images/open.png[File > Open] EOS output = render_embedded_string input, :backend => :docbook assert_match(/File > Open/, output) end test "can render block image with auto-generated alt text" do input = <<-EOS image::images/tiger.png[] EOS output = render_embedded_string input assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="tiger"]', output, 1 end test "can render block image with alt text and height and width" do input = <<-EOS image::images/tiger.png[Tiger, 200, 300] EOS output = render_embedded_string input assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"][@width="200"][@height="300"]', output, 1 end test "can render block image with link" do input = <<-EOS image::images/tiger.png[Tiger, link='http://en.wikipedia.org/wiki/Tiger'] EOS output = render_embedded_string input assert_xpath '/*[@class="imageblock"]//a[@class="image"][@href="http://en.wikipedia.org/wiki/Tiger"]/img[@src="images/tiger.png"][@alt="Tiger"]', output, 1 end test "can render block image with caption" do input = <<-EOS .The AsciiDoc Tiger image::images/tiger.png[Tiger] EOS doc = document_from_string input output = doc.render assert_xpath '//*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1 assert_xpath '//*[@class="imageblock"]/*[@class="title"][text() = "Figure 1. The AsciiDoc Tiger"]', output, 1 assert_equal 1, doc.attributes['figure-number'] end test 'can render block image with explicit caption' do input = <<-EOS [caption="Voila! "] .The AsciiDoc Tiger image::images/tiger.png[Tiger] EOS doc = document_from_string input output = doc.render assert_xpath '//*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1 assert_xpath '//*[@class="imageblock"]/*[@class="title"][text() = "Voila! The AsciiDoc Tiger"]', output, 1 assert !doc.attributes.has_key?('figure-number') end test 'can align image in DocBook backend' do input = <<-EOS image::images/sunset.jpg[Sunset, align="right"] EOS output = render_embedded_string input, :backend => :docbook assert_xpath '//imagedata', output, 1 assert_xpath '//imagedata[@align="right"]', output, 1 end test 'can scale image in DocBook backend' do input = <<-EOS image::images/sunset.jpg[Sunset, scale="200"] EOS output = render_embedded_string input, :backend => :docbook assert_xpath '//imagedata', output, 1 assert_xpath '//imagedata[@scale="200"]', output, 1 end test 'can scale image width in DocBook backend' do input = <<-EOS image::images/sunset.jpg[Sunset, scaledwidth="25%"] EOS output = render_embedded_string input, :backend => :docbook assert_xpath '//imagedata', output, 1 assert_xpath '//imagedata[@width="25%"]', output, 1 assert_xpath '//imagedata[@scalefit="1"]', output, 1 end test 'adds % to scaled width if no units given in DocBook backend ' do input = <<-EOS image::images/sunset.jpg[Sunset, scaledwidth="25"] EOS output = render_embedded_string input, :backend => :docbook assert_xpath '//imagedata', output, 1 assert_xpath '//imagedata[@width="25%"]', output, 1 assert_xpath '//imagedata[@scalefit="1"]', output, 1 end test 'keeps line unprocessed if image target is missing attribute reference and attribute-missing is skip' do input = <<-EOS :attribute-missing: skip image::{bogus}[] EOS output = render_embedded_string input assert output.include?('image::{bogus}[]') end test 'drops line if image target is missing attribute reference and attribute-missing is drop' do input = <<-EOS :attribute-missing: drop image::{bogus}[] EOS output = render_embedded_string input assert output.strip.empty? end test 'drops line if image target is missing attribute reference and attribute-missing is drop-line' do input = <<-EOS :attribute-missing: drop-line image::{bogus}[] EOS output = render_embedded_string input assert output.strip.empty? end test 'dropped image does not break processing of following section and attribute-missing is drop-line' do input = <<-EOS :attribute-missing: drop-line image::{bogus}[] == Section Title EOS output = render_embedded_string input assert_css 'img', output, 0 assert_css 'h2', output, 1 assert !output.include?('== Section Title') end test 'should pass through image that references uri' do input = <<-EOS :imagesdir: images image::http://asciidoc.org/images/tiger.png[Tiger] EOS output = render_embedded_string input assert_xpath '/*[@class="imageblock"]//img[@src="http://asciidoc.org/images/tiger.png"][@alt="Tiger"]', output, 1 end test 'can resolve image relative to imagesdir' do input = <<-EOS :imagesdir: images image::tiger.png[Tiger] EOS output = render_embedded_string input assert_xpath '/*[@class="imageblock"]//img[@src="images/tiger.png"][@alt="Tiger"]', output, 1 end test 'embeds base64-encoded data uri for image when data-uri attribute is set' do input = <<-EOS :data-uri: :imagesdir: fixtures image::dot.gif[Dot] EOS doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)} assert_equal 'fixtures', doc.attributes['imagesdir'] output = doc.render assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1 end test 'embeds base64-encoded data uri for remote image when data-uri attribute is set' do input = <<-EOS :data-uri: image::http://#{resolve_localhost}:9876/fixtures/dot.gif[Dot] EOS output = using_test_webserver do render_embedded_string input, :safe => :safe, :attributes => {'allow-uri-read' => ''} end assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1 end test 'embeds base64-encoded data uri for remote image when imagesdir is a URI and data-uri attribute is set' do input = <<-EOS :data-uri: :imagesdir: http://#{resolve_localhost}:9876/fixtures image::dot.gif[Dot] EOS output = using_test_webserver do render_embedded_string input, :safe => :safe, :attributes => {'allow-uri-read' => ''} end assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1 end test 'uses remote image uri when data-uri attribute is set and image cannot be retrieved' do image_uri = "http://#{resolve_localhost}:9876/fixtures/missing-image.gif" input = <<-EOS :data-uri: image::#{image_uri}[Missing image] EOS output = using_test_webserver do render_embedded_string input, :safe => :safe, :attributes => {'allow-uri-read' => ''} end assert_xpath %(/*[@class="imageblock"]//img[@src="#{image_uri}"][@alt="Missing image"]), output, 1 end test 'uses remote image uri when data-uri attribute is set and allow-uri-read is not set' do image_uri = "http://#{resolve_localhost}:9876/fixtures/dot.gif" input = <<-EOS :data-uri: image::#{image_uri}[Dot] EOS output = using_test_webserver do render_embedded_string input, :safe => :safe end assert_xpath %(/*[@class="imageblock"]//img[@src="#{image_uri}"][@alt="Dot"]), output, 1 end test 'can handle embedded data uri images' do input = <<-EOS image::data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=[Dot] EOS output = render_embedded_string input assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1 end test 'can handle embedded data uri images when data-uri attribute is set' do input = <<-EOS :data-uri: image::data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=[Dot] EOS output = render_embedded_string input assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1 end # this test will cause a warning to be printed to the console (until we have a message facility) test 'cleans reference to ancestor directories in imagesdir before reading image if safe mode level is at least SAFE' do input = <<-EOS :data-uri: :imagesdir: ../..//fixtures/./../../fixtures image::dot.gif[Dot] EOS doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)} assert_equal '../..//fixtures/./../../fixtures', doc.attributes['imagesdir'] output = doc.render # image target resolves to fixtures/dot.gif relative to docdir (which is explicitly set to the directory of this file) # the reference cannot fall outside of the document directory in safe mode assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1 end test 'cleans reference to ancestor directories in target before reading image if safe mode level is at least SAFE' do input = <<-EOS :data-uri: :imagesdir: ./ image::../..//fixtures/./../../fixtures/dot.gif[Dot] EOS doc = document_from_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)} assert_equal './', doc.attributes['imagesdir'] output = doc.render # image target resolves to fixtures/dot.gif relative to docdir (which is explicitly set to the directory of this file) # the reference cannot fall outside of the document directory in safe mode assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1 end end context 'Media' do test 'should detect and render video macro' do input = <<-EOS video::cats-vs-dogs.avi[] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_css 'video[src="cats-vs-dogs.avi"]', output, 1 end test 'should detect and render video macro with positional attributes for poster and dimensions' do input = <<-EOS video::cats-vs-dogs.avi[cats-and-dogs.png, 200, 300] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_css 'video[src="cats-vs-dogs.avi"]', output, 1 assert_css 'video[poster="cats-and-dogs.png"]', output, 1 assert_css 'video[width="200"]', output, 1 assert_css 'video[height="300"]', output, 1 end test 'video macro should honor all options' do input = <<-EOS video::cats-vs-dogs.avi[options="autoplay,nocontrols,loop"] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_css 'video[autoplay]', output, 1 assert_css 'video:not([controls])', output, 1 assert_css 'video[loop]', output, 1 end test 'video macro should add time range anchor with start time if start attribute is set' do input = <<-EOS video::cats-vs-dogs.avi[start="30"] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_xpath '//video[@src="cats-vs-dogs.avi#t=30"]', output, 1 end test 'video macro should add time range anchor with end time if end attribute is set' do input = <<-EOS video::cats-vs-dogs.avi[end="30"] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_xpath '//video[@src="cats-vs-dogs.avi#t=,30"]', output, 1 end test 'video macro should add time range anchor with start and end time if start and end attributes are set' do input = <<-EOS video::cats-vs-dogs.avi[start="30",end="60"] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_xpath '//video[@src="cats-vs-dogs.avi#t=30,60"]', output, 1 end test 'video macro should use imagesdir attribute to resolve target and poster' do input = <<-EOS :imagesdir: assets video::cats-vs-dogs.avi[cats-and-dogs.png, 200, 300] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_css 'video[src="assets/cats-vs-dogs.avi"]', output, 1 assert_css 'video[poster="assets/cats-and-dogs.png"]', output, 1 assert_css 'video[width="200"]', output, 1 assert_css 'video[height="300"]', output, 1 end test 'video macro should not use imagesdir attribute to resolve target if target is a URL' do input = <<-EOS :imagesdir: assets video::http://example.org/videos/cats-vs-dogs.avi[] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_css 'video[src="http://example.org/videos/cats-vs-dogs.avi"]', output, 1 end test 'video macro should output custom HTML with iframe for vimeo service' do input = <<-EOS video::67480300[vimeo, 400, 300, start=60, options=autoplay] EOS output = render_embedded_string input assert_css 'video', output, 0 assert_css 'iframe', output, 1 assert_css 'iframe[src="https://player.vimeo.com/video/67480300#at=60?autoplay=1"]', output, 1 assert_css 'iframe[width="400"]', output, 1 assert_css 'iframe[height="300"]', output, 1 end test 'video macro should output custom HTML with iframe for youtube service' do input = <<-EOS video::U8GBXvdmHT4/PLg7s6cbtAD15Das5LK9mXt_g59DLWxKUe[youtube, 640, 360, start=60, options="autoplay,modest", theme=light] EOS output = render_embedded_string input assert_css 'video', output, 0 assert_css 'iframe', output, 1 assert_css 'iframe[src="https://www.youtube.com/embed/U8GBXvdmHT4?rel=0&start=60&autoplay=1&list=PLg7s6cbtAD15Das5LK9mXt_g59DLWxKUe&modestbranding=1&theme=light"]', output, 1 assert_css 'iframe[width="640"]', output, 1 assert_css 'iframe[height="360"]', output, 1 end test 'video macro should output custom HTML with iframe for youtube service with dynamic playlist' do input = <<-EOS video::SCZF6I-Rc4I,AsKGOeonbIs,HwrPhOp6-aM[youtube, 640, 360, start=60, options=autoplay] EOS output = render_embedded_string input assert_css 'video', output, 0 assert_css 'iframe', output, 1 assert_css 'iframe[src="https://www.youtube.com/embed/SCZF6I-Rc4I?rel=0&start=60&autoplay=1&playlist=AsKGOeonbIs,HwrPhOp6-aM"]', output, 1 assert_css 'iframe[width="640"]', output, 1 assert_css 'iframe[height="360"]', output, 1 end test 'should detect and render audio macro' do input = <<-EOS audio::podcast.mp3[] EOS output = render_embedded_string input assert_css 'audio', output, 1 assert_css 'audio[src="podcast.mp3"]', output, 1 end test 'audio macro should use imagesdir attribute to resolve target' do input = <<-EOS :imagesdir: assets audio::podcast.mp3[] EOS output = render_embedded_string input assert_css 'audio', output, 1 assert_css 'audio[src="assets/podcast.mp3"]', output, 1 end test 'audio macro should not use imagesdir attribute to resolve target if target is a URL' do input = <<-EOS :imagesdir: assets video::http://example.org/podcast.mp3[] EOS output = render_embedded_string input assert_css 'video', output, 1 assert_css 'video[src="http://example.org/podcast.mp3"]', output, 1 end test 'audio macro should honor all options' do input = <<-EOS audio::podcast.mp3[options="autoplay,nocontrols,loop"] EOS output = render_embedded_string input assert_css 'audio', output, 1 assert_css 'audio[autoplay]', output, 1 assert_css 'audio:not([controls])', output, 1 assert_css 'audio[loop]', output, 1 end end context 'Admonition icons' do test 'can resolve icon relative to default iconsdir' do input = <<-EOS :icons: [TIP] You can use icons for admonitions by setting the 'icons' attribute. EOS output = render_string input, :safe => Asciidoctor::SafeMode::SERVER assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="./images/icons/tip.png"][@alt="Tip"]', output, 1 end test 'can resolve icon relative to custom iconsdir' do input = <<-EOS :icons: :iconsdir: icons [TIP] You can use icons for admonitions by setting the 'icons' attribute. EOS output = render_string input, :safe => Asciidoctor::SafeMode::SERVER assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="icons/tip.png"][@alt="Tip"]', output, 1 end test 'should add file extension to custom icon if not specified' do input = <<-EOS :icons: font :iconsdir: images/icons [TIP,icon=a] Override the icon of an admonition block using an attribute EOS output = render_string input, :safe => Asciidoctor::SafeMode::SERVER assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="images/icons/a.png"]', output, 1 end test 'embeds base64-encoded data uri of icon when data-uri attribute is set and safe mode level is less than SECURE' do input = <<-EOS :icons: :iconsdir: fixtures :icontype: gif :data-uri: [TIP] You can use icons for admonitions by setting the 'icons' attribute. EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)} assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1 end test 'does not embed base64-encoded data uri of icon when safe mode level is SECURE or greater' do input = <<-EOS :icons: :iconsdir: fixtures :icontype: gif :data-uri: [TIP] You can use icons for admonitions by setting the 'icons' attribute. EOS output = render_string input, :attributes => {'icons' => ''} assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="fixtures/tip.gif"][@alt="Tip"]', output, 1 end test 'cleans reference to ancestor directories before reading icon if safe mode level is at least SAFE' do input = <<-EOS :icons: :iconsdir: ../fixtures :icontype: gif :data-uri: [TIP] You can use icons for admonitions by setting the 'icons' attribute. EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'docdir' => File.dirname(__FILE__)} assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Tip"]', output, 1 end test 'should import Font Awesome and use font-based icons when value of icons attribute is font' do input = <<-EOS :icons: font [TIP] You can use icons for admonitions by setting the 'icons' attribute. EOS output = render_string input, :safe => Asciidoctor::SafeMode::SERVER assert_css 'html > head > link[rel="stylesheet"][href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"]', output, 1 assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/i[@class="fa icon-tip"]', output, 1 end test 'font-based icon should not override icon specified on admonition' do input = <<-EOS :icons: font :iconsdir: images/icons [TIP,icon=a.png] Override the icon of an admonition block using an attribute EOS output = render_string input, :safe => Asciidoctor::SafeMode::SERVER assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/i[@class="fa icon-tip"]', output, 0 assert_xpath '//*[@class="admonitionblock tip"]//*[@class="icon"]/img[@src="images/icons/a.png"]', output, 1 end test 'should use http uri scheme for assets when asset-uri-scheme is http' do input = <<-EOS :asset-uri-scheme: http :icons: font :source-highlighter: highlightjs TIP: You can control the URI scheme used for assets with the asset-uri-scheme attribute [source,ruby] puts "AsciiDoc, FTW!" EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE assert_css 'html > head > link[rel="stylesheet"][href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"]', output, 1 assert_css 'html > body > script[src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/highlight.min.js"]', output, 1 end test 'should use no uri scheme for assets when asset-uri-scheme is blank' do input = <<-EOS :asset-uri-scheme: :icons: font :source-highlighter: highlightjs TIP: You can control the URI scheme used for assets with the asset-uri-scheme attribute [source,ruby] puts "AsciiDoc, FTW!" EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE assert_css 'html > head > link[rel="stylesheet"][href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"]', output, 1 assert_css 'html > body > script[src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/highlight.min.js"]', output, 1 end end context 'Image paths' do test 'restricts access to ancestor directories when safe mode level is at least SAFE' do input = <<-EOS image::asciidoctor.png[Asciidoctor] EOS basedir = File.expand_path File.dirname(__FILE__) block = block_from_string input, :attributes => {'docdir' => basedir} doc = block.document assert doc.safe >= Asciidoctor::SafeMode::SAFE assert_equal File.join(basedir, 'images'), block.normalize_asset_path('images') assert_equal File.join(basedir, 'etc/images'), block.normalize_asset_path("#{disk_root}etc/images") assert_equal File.join(basedir, 'images'), block.normalize_asset_path('../../images') end test 'does not restrict access to ancestor directories when safe mode is disabled' do input = <<-EOS image::asciidoctor.png[Asciidoctor] EOS basedir = File.expand_path File.dirname(__FILE__) block = block_from_string input, :safe => Asciidoctor::SafeMode::UNSAFE, :attributes => {'docdir' => basedir} doc = block.document assert doc.safe == Asciidoctor::SafeMode::UNSAFE assert_equal File.join(basedir, 'images'), block.normalize_asset_path('images') absolute_path = "#{disk_root}etc/images" assert_equal absolute_path, block.normalize_asset_path(absolute_path) assert_equal File.expand_path(File.join(basedir, '../../images')), block.normalize_asset_path('../../images') end end context 'Source code' do test 'should support fenced code block using backticks' do input = <<-EOS ``` puts "Hello, World!" ``` EOS output = render_embedded_string input assert_css '.listingblock', output, 1 assert_css '.listingblock pre code', output, 1 assert_css '.listingblock pre code:not([class])', output, 1 end test 'should not recognize fenced code blocks with more than three delimiters' do input = <<-EOS ````ruby puts "Hello, World!" ```` ~~~~ javascript alert("Hello, World!") ~~~~ EOS output = render_embedded_string input assert_css '.listingblock', output, 0 end test 'should support fenced code blocks with languages' do input = <<-EOS ```ruby puts "Hello, World!" ``` ``` javascript alert("Hello, World!") ``` EOS output = render_embedded_string input assert_css '.listingblock', output, 2 assert_css '.listingblock pre code.language-ruby[data-lang=ruby]', output, 1 assert_css '.listingblock pre code.language-javascript[data-lang=javascript]', output, 1 end test 'should support fenced code blocks with languages and numbering' do input = <<-EOS ```ruby,numbered puts "Hello, World!" ``` ``` javascript, numbered alert("Hello, World!") ``` EOS output = render_embedded_string input assert_css '.listingblock', output, 2 assert_css '.listingblock pre code.language-ruby[data-lang=ruby]', output, 1 assert_css '.listingblock pre code.language-javascript[data-lang=javascript]', output, 1 end test 'should highlight source if source-highlighter attribute is coderay' do input = <<-EOS :source-highlighter: coderay [source, ruby] ---- require 'coderay' html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) ---- EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :linkcss_default => true assert_xpath '//pre[@class="CodeRay highlight"]/code[@data-lang="ruby"]//span[@class = "constant"][text() = "CodeRay"]', output, 1 assert_match(/\.CodeRay *\{/, output) end test 'should read source language from source-language document attribute if not specified on source block' do input = <<-EOS :source-highlighter: coderay :source-language: ruby [source] ---- require 'coderay' html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) ---- EOS output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SAFE, :linkcss_default => true assert_xpath '//pre[@class="CodeRay highlight"]/code[@data-lang="ruby"]//span[@class = "constant"][text() = "CodeRay"]', output, 1 end test 'should rename document attribute named language to source-language when compat-mode is enabled' do input = <<-EOS :language: ruby {source-language} EOS assert_equal 'ruby', render_string(input, :doctype => :inline, :attributes => {'compat-mode' => ''}) input = <<-EOS :language: ruby {source-language} EOS assert_equal '{source-language}', render_string(input, :doctype => :inline) end test 'should replace callout marks but not highlight them if source-highlighter attribute is coderay' do input = <<-EOS :source-highlighter: coderay [source, ruby] ---- require 'coderay' # <1> html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) # <2> puts html # <3> <4> exit 0 # <5><6> ---- <1> Load library <2> Highlight source <3> Print to stdout <4> Redirect to a file to capture output <5> Exit program <6> Reports success EOS output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SAFE assert_match(/coderay<\/span>.* \(1\)<\/b>$/, output) assert_match(/puts 'Hello, world!'<\/span>.* \(2\)<\/b>$/, output) assert_match(/puts html * \(3\)<\/b> \(4\)<\/b>$/, output) assert_match(/exit.* \(5\)<\/b> \(6\)<\/b><\/code>/, output) end test 'should restore callout marks to correct lines if source highlighter is coderay and table line numbering is enabled' do input = <<-EOS :source-highlighter: coderay :coderay-linenums-mode: table [source, ruby, numbered] ---- require 'coderay' # <1> html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) # <2> puts html # <3> <4> exit 0 # <5><6> ---- <1> Load library <2> Highlight source <3> Print to stdout <4> Redirect to a file to capture output <5> Exit program <6> Reports success EOS output = render_embedded_string input, :safe => Asciidoctor::SafeMode::SAFE assert_match(/coderay<\/span>.* \(1\)<\/b>$/, output) assert_match(/puts 'Hello, world!'<\/span>.* \(2\)<\/b>$/, output) assert_match(/puts html * \(3\)<\/b> \(4\)<\/b>$/, output) assert_match(/exit.* \(5\)<\/b> \(6\)<\/b><\/pre>/, output) end test 'should preserve passthrough placeholders when highlighting source using coderay' do input = <<-EOS :source-highlighter: coderay [source,java] [subs="specialcharacters,macros,callouts"] ---- public class Printer { public static void main(String[] args) { System.pass:quotes[_out_].println("*asterisks* make text pass:quotes[*bold*]"); } } ---- EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE assert_match(/\.out<\/em>\./, output, 1) assert_match(/\*asterisks\*/, output, 1) assert_match(/bold<\/strong>/, output, 1) assert !output.include?(Asciidoctor::Substitutors::PASS_START) end test 'should link to CodeRay stylesheet if source-highlighter is coderay and linkcss is set' do input = <<-EOS :source-highlighter: coderay [source, ruby] ---- require 'coderay' html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) ---- EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :attributes => {'linkcss' => ''} assert_xpath '//pre[@class="CodeRay highlight"]/code[@data-lang="ruby"]//span[@class = "constant"][text() = "CodeRay"]', output, 1 assert_css 'link[rel="stylesheet"][href="./coderay-asciidoctor.css"]', output, 1 end test 'should highlight source inline if source-highlighter attribute is coderay and coderay-css is style' do input = <<-EOS :source-highlighter: coderay :coderay-css: style [source, ruby] ---- require 'coderay' html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) ---- EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE, :linkcss_default => true assert_xpath '//pre[@class="CodeRay highlight"]/code[@data-lang="ruby"]//span[@style = "color:#036;font-weight:bold"][text() = "CodeRay"]', output, 1 refute_match(/\.CodeRay \{/, output) end test 'should include remote highlight.js assets if source-highlighter attribute is highlightjs' do input = <<-EOS :source-highlighter: highlightjs [source, javascript] ---- ---- EOS output = render_string input, :safe => Asciidoctor::SafeMode::SAFE assert_match(/ {'source-highlighter' => 'prettify'} assert_css 'pre[class="prettyprint highlight"]', output, 1 assert_css 'pre > code.language-ruby[data-lang="ruby"]', output, 1 end test 'should set lang attribute on pre when source-highlighter is html-pipeline' do input = <<-EOS [source,ruby] ---- filters = [ HTML::Pipeline::AsciiDocFilter, HTML::Pipeline::SanitizationFilter, HTML::Pipeline::SyntaxHighlightFilter ] puts HTML::Pipeline.new(filters, {}).call(input)[:output] ---- EOS output = render_string input, :attributes => {'source-highlighter' => 'html-pipeline'} assert_css 'pre[lang="ruby"]', output, 1 assert_css 'pre[lang="ruby"] > code', output, 1 assert_css 'pre[class]', output, 0 assert_css 'code[class]', output, 0 end test 'document cannot turn on source highlighting if safe mode is at least SERVER' do input = <<-EOS :source-highlighter: coderay EOS doc = document_from_string input, :safe => Asciidoctor::SafeMode::SERVER assert doc.attributes['source-highlighter'].nil? end end context 'Abstract and Part Intro' do test 'should make abstract on open block without title a quote block for article' do input = <<-EOS = Article [abstract] -- This article is about stuff. And other stuff. -- == Section One content EOS output = render_string input assert_css '.quoteblock', output, 1 assert_css '.quoteblock.abstract', output, 1 assert_css '#preamble .quoteblock', output, 1 assert_css '.quoteblock > blockquote', output, 1 assert_css '.quoteblock > blockquote > .paragraph', output, 2 end test 'should make abstract on open block with title a quote block with title for article' do input = <<-EOS = Article .My abstract [abstract] -- This article is about stuff. -- == Section One content EOS output = render_string input assert_css '.quoteblock', output, 1 assert_css '.quoteblock.abstract', output, 1 assert_css '#preamble .quoteblock', output, 1 assert_css '.quoteblock > .title', output, 1 assert_css '.quoteblock > .title + blockquote', output, 1 assert_css '.quoteblock > .title + blockquote > .paragraph', output, 1 end test 'should allow abstract in document with title if doctype is book' do input = <<-EOS = Book :doctype: book [abstract] Abstract for book with title is valid EOS output = render_string input assert_css '.abstract', output, 1 end test 'should not allow abstract as direct child of document if doctype is book' do input = <<-EOS :doctype: book [abstract] Abstract for book without title is invalid. EOS warnings = nil output = nil redirect_streams do |stdout, stderr| output = render_string input warnings = stderr.string end assert_css '.abstract', output, 0 refute_nil warnings assert_match(/WARNING:.*abstract block/, warnings) end test 'should make abstract on open block without title rendered to DocBook' do input = <<-EOS = Article [abstract] -- This article is about stuff. And other stuff. -- EOS output = render_string input, :backend => 'docbook' assert_css 'abstract', output, 1 assert_css 'abstract > simpara', output, 2 end test 'should make abstract on open block with title rendered to DocBook' do input = <<-EOS = Article .My abstract [abstract] -- This article is about stuff. -- EOS output = render_string input, :backend => 'docbook' assert_css 'abstract', output, 1 assert_css 'abstract > title', output, 1 assert_css 'abstract > title + simpara', output, 1 end test 'should allow abstract in document with title if doctype is book rendered to DocBook' do input = <<-EOS = Book :doctype: book [abstract] Abstract for book with title is valid EOS output = render_string input, :backend => 'docbook' assert_css 'abstract', output, 1 end test 'should not allow abstract as direct child of document if doctype is book rendered to DocBook' do input = <<-EOS :doctype: book [abstract] Abstract for book is invalid. EOS output = nil warnings = nil redirect_streams do |stdout, stderr| output = render_string input, :backend => 'docbook' warnings = stderr.string end assert_css 'abstract', output, 0 refute_nil warnings assert_match(/WARNING:.*abstract block/, warnings) end # TODO partintro shouldn't be recognized if doctype is not book, should be in proper place test 'should accept partintro on open block without title' do input = <<-EOS = Book :doctype: book = Part 1 [partintro] -- This is a part intro. It can have multiple paragraphs. -- == Chapter 1 content EOS output = render_string input assert_css '.openblock', output, 1 assert_css '.openblock.partintro', output, 1 assert_css '.openblock .title', output, 0 assert_css '.openblock .content', output, 1 assert_xpath %(//h1[@id="_part_1"]/following-sibling::*[#{contains_class(:openblock)}]), output, 1 assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="content"]/*[@class="paragraph"]), output, 2 end test 'should accept partintro on open block with title' do input = <<-EOS = Book :doctype: book = Part 1 .Intro title [partintro] -- This is a part intro with a title. -- == Chapter 1 content EOS output = render_string input assert_css '.openblock', output, 1 assert_css '.openblock.partintro', output, 1 assert_css '.openblock .title', output, 1 assert_css '.openblock .content', output, 1 assert_xpath %(//h1[@id="_part_1"]/following-sibling::*[#{contains_class(:openblock)}]), output, 1 assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="title"][text() = "Intro title"]), output, 1 assert_xpath %(//*[#{contains_class(:openblock)}]/*[@class="content"]/*[@class="paragraph"]), output, 1 end test 'should exclude partintro if not a child of part' do input = <<-EOS = Book :doctype: book [partintro] part intro paragraph EOS output = render_string input assert_css '.partintro', output, 0 end test 'should not allow partintro unless doctype is book' do input = <<-EOS [partintro] part intro paragraph EOS output = render_string input assert_css '.partintro', output, 0 end test 'should accept partintro on open block without title rendered to DocBook' do input = <<-EOS = Book :doctype: book = Part 1 [partintro] -- This is a part intro. It can have multiple paragraphs. -- == Chapter 1 content EOS output = render_string input, :backend => 'docbook45' assert_css 'partintro', output, 1 assert_css 'part#_part_1 > partintro', output, 1 assert_css 'partintro > simpara', output, 2 end test 'should accept partintro on open block with title rendered to DocBook' do input = <<-EOS = Book :doctype: book = Part 1 .Intro title [partintro] -- This is a part intro with a title. -- == Chapter 1 content EOS output = render_string input, :backend => 'docbook45' assert_css 'partintro', output, 1 assert_css 'part#_part_1 > partintro', output, 1 assert_css 'partintro > title', output, 1 assert_css 'partintro > title + simpara', output, 1 end test 'should exclude partintro if not a child of part rendered to DocBook' do input = <<-EOS = Book :doctype: book [partintro] part intro paragraph EOS output = render_string input, :backend => 'docbook' assert_css 'partintro', output, 0 end test 'should not allow partintro unless doctype is book rendered to DocBook' do input = <<-EOS [partintro] part intro paragraph EOS output = render_string input, :backend => 'docbook' assert_css 'partintro', output, 0 end end context 'Substitutions' do test 'should be able to append subs to default block substitution list' do input = <<-EOS :application: Asciidoctor [subs="+attributes,+macros"] .... {application} .... EOS doc = document_from_string input block = doc.blocks.first assert_equal [:specialcharacters, :attributes, :macros], block.subs end test 'should be able to prepend subs to default block substitution list' do input = <<-EOS :application: Asciidoctor [subs="attributes+"] .... {application} .... EOS doc = document_from_string input block = doc.blocks.first assert_equal [:attributes, :specialcharacters], block.subs end test 'should be able to remove subs to default block substitution list' do input = <<-EOS [subs="-quotes,-replacements"] content EOS doc = document_from_string input block = doc.blocks.first assert_equal [:specialcharacters, :attributes, :macros, :post_replacements], block.subs end test 'should be able to prepend, append and remove subs from default block substitution list' do input = <<-EOS :application: asciidoctor [subs="attributes+,-verbatim,+specialcharacters,+macros"] .... http://{application}.org[{gt}{gt}] <1> .... EOS doc = document_from_string input, :header_footer => false block = doc.blocks.first assert_equal [:attributes, :specialcharacters, :macros], block.subs result = doc.render assert result.include?('
>> <1>
') end test 'should be able to set subs then modify them' do input = <<-EOS [subs="verbatim,-callouts"] _hey now_ <1> EOS doc = document_from_string input, :header_footer => false block = doc.blocks.first assert_equal [:specialcharacters], block.subs result = doc.render assert result.include?('_hey now_ <1>') end end context 'References' do test 'should not recognize block anchor with illegal id characters' do input = <<-EOS [[illegal$id,Reference Text]] ---- content ---- EOS doc = document_from_string input block = doc.blocks.first assert_nil block.id assert_nil(block.attr 'reftext') assert !doc.references[:ids].has_key?('illegal$id') end test 'should use specified id and reftext when registering block reference' do input = <<-EOS [[debian,Debian Install]] .Installation on Debian ---- $ apt-get install asciidoctor ---- EOS doc = document_from_string input reftext = doc.references[:ids]['debian'] refute_nil reftext assert_equal 'Debian Install', reftext end test 'should allow square brackets in block reference text' do input = <<-EOS [[debian,[Debian] Install]] .Installation on Debian ---- $ apt-get install asciidoctor ---- EOS doc = document_from_string input reftext = doc.references[:ids]['debian'] refute_nil reftext assert_equal '[Debian] Install', reftext end test 'should allow comma in block reference text' do input = <<-EOS [[debian, Debian, Ubuntu]] .Installation on Debian ---- $ apt-get install asciidoctor ---- EOS doc = document_from_string input reftext = doc.references[:ids]['debian'] refute_nil reftext assert_equal 'Debian, Ubuntu', reftext end test 'should use specified reftext when registering block reference' do input = <<-EOS [[debian]] [reftext="Debian Install"] .Installation on Debian ---- $ apt-get install asciidoctor ---- EOS doc = document_from_string input reftext = doc.references[:ids]['debian'] refute_nil reftext assert_equal 'Debian Install', reftext end end end