# frozen_string_literal: true require_relative 'test_helper' BUILT_IN_ELEMENTS = %w(admonition audio colist dlist document embedded example floating_title image inline_anchor inline_break inline_button inline_callout inline_footnote inline_image inline_indexterm inline_kbd inline_menu inline_quoted listing literal stem olist open page_break paragraph pass preamble quote section sidebar table thematic_break toc ulist verse video) context 'Document' do context 'Example document' do test 'document title' do doc = example_document :asciidoc_index assert_equal 'AsciiDoc Home Page', doc.doctitle assert_equal 'AsciiDoc Home Page', doc.name refute_nil doc.header assert_equal :section, doc.header.context assert_equal 'header', doc.header.sectname assert_equal 14, doc.blocks.size assert_equal :preamble, doc.blocks[0].context assert_equal :section, doc.blocks[1].context # verify compat-mode is set when atx-style doctitle is used result = doc.blocks[0].convert assert_xpath '//em[text()="Stuart Rackham"]', result, 1 end end context 'Default settings' do test 'safe mode level set to SECURE by default' do doc = empty_document assert_equal Asciidoctor::SafeMode::SECURE, doc.safe end test 'safe mode level set using string' do doc = empty_document safe: 'server' assert_equal Asciidoctor::SafeMode::SERVER, doc.safe doc = empty_document safe: 'foo' assert_equal Asciidoctor::SafeMode::SECURE, doc.safe end test 'safe mode level set using symbol' do doc = empty_document safe: :server assert_equal Asciidoctor::SafeMode::SERVER, doc.safe doc = empty_document safe: :foo assert_equal Asciidoctor::SafeMode::SECURE, doc.safe end test 'safe mode level set using integer' do doc = empty_document safe: 10 assert_equal Asciidoctor::SafeMode::SERVER, doc.safe doc = empty_document safe: 100 assert_equal 100, doc.safe end test 'safe mode attributes are set on document' do doc = empty_document assert_equal Asciidoctor::SafeMode::SECURE, doc.attr('safe-mode-level') assert_equal 'secure', doc.attr('safe-mode-name') assert doc.attr?('safe-mode-secure') refute doc.attr?('safe-mode-unsafe') refute doc.attr?('safe-mode-safe') refute doc.attr?('safe-mode-server') end test 'safe mode level can be set in the constructor' do doc = Asciidoctor::Document.new [], safe: Asciidoctor::SafeMode::SAFE assert_equal Asciidoctor::SafeMode::SAFE, doc.safe end test 'safe model level cannot be modified' do assert_raises NoMethodError, 'safe mode property of Asciidoctor::Document should not be writable!' do empty_document.safe = Asciidoctor::SafeMode::UNSAFE end end test 'toc and sectnums should be enabled by default in DocBook backend' do doc = document_from_string 'content', backend: 'docbook', parse: true assert doc.attr?('toc') assert doc.attr?('sectnums') result = doc.convert assert_match '', result assert_match '', result end test 'maxdepth attribute should be set on asciidoc-toc and asciidoc-numbered processing instructions in DocBook backend' do doc = document_from_string 'content', backend: 'docbook', parse: true, attributes: { 'toclevels' => '1', 'sectnumlevels' => '1' } assert doc.attr?('toc') assert doc.attr?('sectnums') result = doc.convert assert_match '', result assert_match '', result end test 'should be able to disable toc and sectnums in document header in DocBook backend' do input = <<~'EOS' = Document Title :toc!: :sectnums!: EOS doc = document_from_string input, backend: 'docbook' refute doc.attr?('toc') refute doc.attr?('sectnums') end test 'noheader attribute should suppress info element when converting to DocBook' do input = <<~'EOS' = Document Title :noheader: content EOS result = convert_string input, backend: 'docbook' assert_xpath '/article', result, 1 assert_xpath '/article/info', result, 0 end test 'should be able to disable section numbering using numbered attribute in document header in DocBook backend' do input = <<~'EOS' = Document Title :numbered!: EOS doc = document_from_string input, backend: 'docbook' refute doc.attr?('sectnums') end end context 'Docinfo files' do test 'should include docinfo files for html backend' do sample_input_path = fixture_path 'basic.adoc' cases = { 'docinfo' => { head_script: 1, meta: 0, top_link: 0, footer_script: 1, navbar: 1 }, 'docinfo=private' => { head_script: 1, meta: 0, top_link: 0, footer_script: 1, navbar: 1 }, 'docinfo1' => { head_script: 0, meta: 1, top_link: 1, footer_script: 0, navbar: 0 }, 'docinfo=shared' => { head_script: 0, meta: 1, top_link: 1, footer_script: 0, navbar: 0 }, 'docinfo2' => { head_script: 1, meta: 1, top_link: 1, footer_script: 1, navbar: 1 }, 'docinfo docinfo2' => { head_script: 1, meta: 1, top_link: 1, footer_script: 1, navbar: 1 }, 'docinfo=private,shared' => { head_script: 1, meta: 1, top_link: 1, footer_script: 1, navbar: 1 }, 'docinfo=private-head' => { head_script: 1, meta: 0, top_link: 0, footer_script: 0, navbar: 0 }, 'docinfo=private-header' => { head_script: 0, meta: 0, top_link: 0, footer_script: 0, navbar: 1 }, 'docinfo=shared-head' => { head_script: 0, meta: 1, top_link: 0, footer_script: 0, navbar: 0 }, 'docinfo=private-footer' => { head_script: 0, meta: 0, top_link: 0, footer_script: 1, navbar: 0 }, 'docinfo=shared-footer' => { head_script: 0, meta: 0, top_link: 1, footer_script: 0, navbar: 0 }, 'docinfo=private-head\ ,\ shared-footer' => { head_script: 1, meta: 0, top_link: 1, footer_script: 0, navbar: 0 }, } cases.each do |attr_val, markup| output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: %(linkcss copycss! #{attr_val}) refute_empty output assert_css 'script[src="modernizr.js"]', output, markup[:head_script] assert_css 'meta[http-equiv="imagetoolbar"]', output, markup[:meta] assert_css 'body > a#top', output, markup[:top_link] assert_css 'body > script', output, markup[:footer_script] assert_css 'body > nav.navbar', output, markup[:navbar] assert_css 'body > nav.navbar + #header', output, markup[:navbar] end end test 'should include docinfo header even if noheader attribute is set' do sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo' => 'private-header', 'noheader' => '' } refute_empty output assert_css 'body > nav.navbar', output, 1 assert_css 'body > nav.navbar + #content', output, 1 end test 'should include docinfo footer even if nofooter attribute is set' do sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo1' => '', 'nofooter' => '' } refute_empty output assert_css 'body > a#top', output, 1 end test 'should include user docinfo after built-in docinfo' do sample_input_path = fixture_path 'basic.adoc' attrs = { 'docinfo' => 'shared', 'source-highlighter' => 'highlight.js', 'linkcss' => '', 'copycss' => nil } output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: :safe, attributes: attrs assert_css 'link[rel=stylesheet] + meta[http-equiv=imagetoolbar]', output, 1 assert_css 'meta[http-equiv=imagetoolbar] + *', output, 0 assert_css 'script + a#top', output, 1 assert_css 'a#top + *', output, 0 end test 'should include docinfo files for html backend with custom docinfodir' do sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo' => '', 'docinfodir' => 'custom-docinfodir' } refute_empty output assert_css 'script[src="bootstrap.js"]', output, 1 assert_css 'meta[name="robots"]', output, 0 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo1' => '', 'docinfodir' => 'custom-docinfodir' } refute_empty output assert_css 'script[src="bootstrap.js"]', output, 0 assert_css 'meta[name="robots"]', output, 1 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo2' => '', 'docinfodir' => './custom-docinfodir' } refute_empty output assert_css 'script[src="bootstrap.js"]', output, 1 assert_css 'meta[name="robots"]', output, 1 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo2' => '', 'docinfodir' => 'custom-docinfodir/subfolder' } refute_empty output assert_css 'script[src="bootstrap.js"]', output, 0 assert_css 'meta[name="robots"]', output, 0 end test 'should include docinfo files in docbook backend' do sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo' => '' } refute_empty output assert_css 'productname', output, 0 assert_css 'copyright', output, 1 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo1' => '' } refute_empty output assert_css 'productname', output, 1 assert_xpath '//xmlns:productname[text()="Asciidoctorâ„¢"]', output, 1 assert_css 'edition', output, 1 assert_xpath '//xmlns:edition[text()="1.0"]', output, 1 # verifies substitutions are performed assert_css 'copyright', output, 0 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo2' => '' } refute_empty output assert_css 'productname', output, 1 assert_xpath '//xmlns:productname[text()="Asciidoctorâ„¢"]', output, 1 assert_css 'edition', output, 1 assert_xpath '//xmlns:edition[text()="1.0"]', output, 1 # verifies substitutions are performed assert_css 'copyright', output, 1 end test 'should use header docinfo in place of default header' do output = Asciidoctor.convert_file fixture_path('sample.adoc'), to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo' => 'private-header', 'noheader' => '' } refute_empty output assert_css 'article > info', output, 1 assert_css 'article > info > title', output, 1 assert_css 'article > info > revhistory', output, 1 assert_css 'article > info > revhistory > revision', output, 2 end test 'should include docinfo footer files for html backend' do sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo' => '' } refute_empty output assert_css 'body script', output, 1 assert_css 'a#top', output, 0 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo1' => '' } refute_empty output assert_css 'body script', output, 0 assert_css 'a#top', output, 1 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo2' => '' } refute_empty output assert_css 'body script', output, 1 assert_css 'a#top', output, 1 end test 'should include docinfo footer files in DocBook backend' do sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo' => '' } refute_empty output assert_css 'article > revhistory', output, 1 assert_xpath '/xmlns:article/xmlns:revhistory/xmlns:revision/xmlns:revnumber[text()="1.0"]', output, 1 # verifies substitutions are performed assert_css 'glossary', output, 0 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo1' => '' } refute_empty output assert_css 'article > revhistory', output, 0 assert_css 'glossary[xml|id="_glossary"]', output, 1 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo2' => '' } refute_empty output assert_css 'article > revhistory', output, 1 assert_xpath '/xmlns:article/xmlns:revhistory/xmlns:revision/xmlns:revnumber[text()="1.0"]', output, 1 # verifies substitutions are performed assert_css 'glossary[xml|id="_glossary"]', output, 1 end # WARNING this test manipulates runtime settings; should probably be run in forked process test 'should force encoding of docinfo files to UTF-8' do old_external = Encoding.default_external old_internal = Encoding.default_internal old_verbose = $VERBOSE begin $VERBOSE = nil # disable warnings since we have to modify constants Encoding.default_external = Encoding.default_internal = Encoding::IBM437 sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER, attributes: { 'docinfo' => 'private,shared' } refute_empty output assert_css 'productname', output, 1 assert_includes output, 'Asciidoctorâ„¢' assert_css 'edition', output, 1 assert_xpath '//xmlns:edition[text()="1.0"]', output, 1 # verifies substitutions are performed assert_css 'copyright', output, 1 ensure Encoding.default_external = old_external Encoding.default_internal = old_internal $VERBOSE = old_verbose end end test 'should not include docinfo files by default' do sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: Asciidoctor::SafeMode::SERVER refute_empty output assert_css 'script[src="modernizr.js"]', output, 0 assert_css 'meta[http-equiv="imagetoolbar"]', output, 0 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', safe: Asciidoctor::SafeMode::SERVER refute_empty output assert_css 'productname', output, 0 assert_css 'copyright', output, 0 end test 'should not include docinfo files if safe mode is SECURE or greater' do sample_input_path = fixture_path 'basic.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, attributes: { 'docinfo2' => '' } refute_empty output assert_css 'script[src="modernizr.js"]', output, 0 assert_css 'meta[http-equiv="imagetoolbar"]', output, 0 output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, backend: 'docbook', attributes: { 'docinfo2' => '' } refute_empty output assert_css 'productname', output, 0 assert_css 'copyright', output, 0 end test 'should substitute attributes in docinfo files by default' do sample_input_path = fixture_path 'subs.adoc' using_memory_logger do |logger| output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: :server, attributes: { 'docinfo' => '', 'bootstrap-version' => nil, 'linkcss' => '', 'attribute-missing' => 'drop-line' } refute_empty output assert_css 'script', output, 0 assert_xpath %(//meta[@name="copyright"][@content="(C) OpenDevise"]), output, 1 assert_message logger, :INFO, 'dropping line containing reference to missing attribute: bootstrap-version' end end test 'should apply explicit substitutions to docinfo files' do sample_input_path = fixture_path 'subs.adoc' output = Asciidoctor.convert_file sample_input_path, to_file: false, standalone: true, safe: :server, attributes: { 'docinfo' => '', 'docinfosubs' => 'attributes,replacements', 'linkcss' => '' } refute_empty output assert_css 'script[src="bootstrap.3.2.0.min.js"]', output, 1 assert_xpath %(//meta[@name="copyright"][@content="#{decode_char 169} OpenDevise"]), output, 1 end end context 'MathJax' do test 'should add MathJax script to HTML head if stem attribute is set' do output = convert_string '', attributes: { 'stem' => '' } assert_match '