asciidoctor 1.5.6.2 → 1.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +330 -143
- data/README-fr.adoc +441 -0
- data/README-jp.adoc +418 -0
- data/README-zh_CN.adoc +430 -0
- data/README.adoc +454 -0
- data/Rakefile +57 -0
- data/asciidoctor.gemspec +7 -1
- data/data/locale/attributes-ar.adoc +22 -0
- data/data/locale/attributes-bg.adoc +22 -0
- data/data/locale/attributes-ca.adoc +22 -0
- data/data/locale/attributes-cs.adoc +22 -0
- data/data/locale/attributes-da.adoc +22 -0
- data/data/locale/attributes-de.adoc +22 -0
- data/data/locale/attributes-en.adoc +23 -0
- data/data/locale/attributes-es.adoc +22 -0
- data/data/locale/attributes-fa.adoc +22 -0
- data/data/locale/attributes-fi.adoc +22 -0
- data/data/locale/attributes-fr.adoc +22 -0
- data/data/locale/attributes-hu.adoc +22 -0
- data/data/locale/attributes-id.adoc +22 -0
- data/data/locale/attributes-it.adoc +22 -0
- data/data/locale/attributes-ja.adoc +22 -0
- data/data/locale/attributes-kr.adoc +22 -0
- data/data/locale/attributes-nb.adoc +22 -0
- data/data/locale/attributes-nl.adoc +22 -0
- data/data/locale/attributes-nn.adoc +22 -0
- data/data/locale/attributes-pl.adoc +22 -0
- data/data/locale/attributes-pt.adoc +22 -0
- data/data/locale/attributes-pt_BR.adoc +22 -0
- data/data/locale/attributes-ro.adoc +22 -0
- data/data/locale/attributes-ru.adoc +22 -0
- data/data/locale/attributes-sr.adoc +22 -0
- data/data/locale/attributes-sr_Latn.adoc +22 -0
- data/data/locale/attributes-tr.adoc +22 -0
- data/data/locale/attributes-uk.adoc +22 -0
- data/data/locale/attributes-zh_CN.adoc +22 -0
- data/data/locale/attributes-zh_TW.adoc +22 -0
- data/data/locale/attributes.adoc +8 -649
- data/data/stylesheets/asciidoctor-default.css +77 -72
- data/features/xref.feature +366 -7
- data/lib/asciidoctor.rb +107 -93
- data/lib/asciidoctor/abstract_block.rb +247 -239
- data/lib/asciidoctor/abstract_node.rb +56 -58
- data/lib/asciidoctor/block.rb +3 -3
- data/lib/asciidoctor/callouts.rb +1 -1
- data/lib/asciidoctor/cli/invoker.rb +36 -9
- data/lib/asciidoctor/cli/options.rb +63 -25
- data/lib/asciidoctor/converter.rb +23 -13
- data/lib/asciidoctor/converter/base.rb +4 -0
- data/lib/asciidoctor/converter/docbook45.rb +16 -9
- data/lib/asciidoctor/converter/docbook5.rb +115 -97
- data/lib/asciidoctor/converter/factory.rb +29 -31
- data/lib/asciidoctor/converter/html5.rb +229 -192
- data/lib/asciidoctor/converter/manpage.rb +72 -50
- data/lib/asciidoctor/converter/template.rb +12 -12
- data/lib/asciidoctor/core_ext.rb +5 -1
- data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +6 -0
- data/lib/asciidoctor/document.rb +168 -77
- data/lib/asciidoctor/extensions.rb +79 -47
- data/lib/asciidoctor/helpers.rb +33 -11
- data/lib/asciidoctor/inline.rb +3 -2
- data/lib/asciidoctor/list.rb +2 -1
- data/lib/asciidoctor/logging.rb +122 -0
- data/lib/asciidoctor/parser.rb +406 -382
- data/lib/asciidoctor/path_resolver.rb +169 -162
- data/lib/asciidoctor/reader.rb +166 -121
- data/lib/asciidoctor/section.rb +45 -28
- data/lib/asciidoctor/stylesheets.rb +13 -5
- data/lib/asciidoctor/substitutors.rb +328 -254
- data/lib/asciidoctor/table.rb +105 -48
- data/lib/asciidoctor/timings.rb +34 -6
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +41 -23
- data/man/asciidoctor.adoc +14 -8
- data/test/api_test.rb +1004 -0
- data/test/attributes_test.rb +241 -50
- data/test/blocks_test.rb +549 -124
- data/test/converter_test.rb +170 -78
- data/test/document_test.rb +208 -767
- data/test/extensions_test.rb +188 -53
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +1 -1
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +1 -1
- data/test/fixtures/file-with-missing-include.adoc +1 -0
- data/test/fixtures/include-file.jsx +8 -0
- data/test/fixtures/lists.adoc +96 -0
- data/test/fixtures/other-chapters.adoc +11 -0
- data/test/fixtures/outer-include.adoc +5 -0
- data/test/fixtures/sample.asciidoc +5 -1
- data/test/fixtures/subdir/index.adoc +3 -0
- data/test/fixtures/subdir/inner-include.adoc +3 -0
- data/test/fixtures/subdir/middle-include.adoc +5 -0
- data/test/fixtures/tagged-class-enclosed.rb +0 -1
- data/test/fixtures/unclosed-tag.adoc +3 -0
- data/test/fixtures/unexpected-end-tag.adoc +4 -0
- data/test/invoker_test.rb +101 -40
- data/test/links_test.rb +266 -72
- data/test/lists_test.rb +243 -45
- data/test/logger_test.rb +211 -0
- data/test/manpage_test.rb +124 -6
- data/test/options_test.rb +46 -1
- data/test/paragraphs_test.rb +23 -10
- data/test/parser_test.rb +30 -1
- data/test/paths_test.rb +115 -33
- data/test/preamble_test.rb +1 -1
- data/test/reader_test.rb +337 -81
- data/test/sections_test.rb +656 -72
- data/test/substitutions_test.rb +182 -57
- data/test/tables_test.rb +324 -57
- data/test/test_helper.rb +77 -32
- data/test/text_test.rb +7 -7
- metadata +67 -3
    
        data/test/sections_test.rb
    CHANGED
    
    | @@ -11,12 +11,12 @@ context 'Sections' do | |
| 11 11 | 
             
                  assert_equal '_section_one', sec.id
         | 
| 12 12 | 
             
                end
         | 
| 13 13 |  | 
| 14 | 
            -
                test 'synthetic id  | 
| 15 | 
            -
                  sec = block_from_string("== We | 
| 16 | 
            -
                  assert_equal ' | 
| 14 | 
            +
                test 'synthetic id removes non-word characters' do
         | 
| 15 | 
            +
                  sec = block_from_string("== We’re back!")
         | 
| 16 | 
            +
                  assert_equal '_were_back', sec.id
         | 
| 17 17 | 
             
                end
         | 
| 18 18 |  | 
| 19 | 
            -
                test 'synthetic id removes repeating  | 
| 19 | 
            +
                test 'synthetic id removes repeating separators' do
         | 
| 20 20 | 
             
                  sec = block_from_string('== Section $ One')
         | 
| 21 21 | 
             
                  assert_equal '_section_one', sec.id
         | 
| 22 22 | 
             
                end
         | 
| @@ -31,6 +31,26 @@ context 'Sections' do | |
| 31 31 | 
             
                  assert_equal '_a_b', sec.id
         | 
| 32 32 | 
             
                end
         | 
| 33 33 |  | 
| 34 | 
            +
                test 'synthetic id removes XML tags' do
         | 
| 35 | 
            +
                  sec = block_from_string('== Use the `run` command to make it icon:gear[]')
         | 
| 36 | 
            +
                  assert_equal '_use_the_run_command_to_make_it_gear', sec.id
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                test 'synthetic id collapses repeating spaces' do
         | 
| 40 | 
            +
                  sec = block_from_string('== Go    Far')
         | 
| 41 | 
            +
                  assert_equal '_go_far', sec.id
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                test 'synthetic id replaces hyphens with separator' do
         | 
| 45 | 
            +
                  sec = block_from_string('== State-of-the-art design')
         | 
| 46 | 
            +
                  assert_equal '_state_of_the_art_design', sec.id
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                test 'synthetic id replaces dots with separator' do
         | 
| 50 | 
            +
                  sec = block_from_string("== Section 1.1.1")
         | 
| 51 | 
            +
                  assert_equal '_section_1_1_1', sec.id
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 34 54 | 
             
                test 'synthetic id prefix can be customized' do
         | 
| 35 55 | 
             
                  sec = block_from_string(":idprefix: id_\n\n== Section One")
         | 
| 36 56 | 
             
                  assert_equal 'id_section_one', sec.id
         | 
| @@ -42,7 +62,7 @@ context 'Sections' do | |
| 42 62 | 
             
                end
         | 
| 43 63 |  | 
| 44 64 | 
             
                test 'synthetic id prefix is stripped from beginning of id if set to blank' do
         | 
| 45 | 
            -
                  sec = block_from_string(":idprefix:\n\n== & More")
         | 
| 65 | 
            +
                  sec = block_from_string(":idprefix:\n\n== & ! More")
         | 
| 46 66 | 
             
                  assert_equal 'more', sec.id
         | 
| 47 67 | 
             
                end
         | 
| 48 68 |  | 
| @@ -51,6 +71,26 @@ context 'Sections' do | |
| 51 71 | 
             
                  assert_equal '_section-one', sec.id
         | 
| 52 72 | 
             
                end
         | 
| 53 73 |  | 
| 74 | 
            +
                test 'synthetic id separator can be hyphen and hyphens are preserved' do
         | 
| 75 | 
            +
                  sec = block_from_string(":idseparator: -\n\n== State-of-the-art design")
         | 
| 76 | 
            +
                  assert_equal '_state-of-the-art-design', sec.id
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                test 'synthetic id separator can be dot and dots are preserved' do
         | 
| 80 | 
            +
                  sec = block_from_string(":idseparator: .\n\n== Version 5.0.1")
         | 
| 81 | 
            +
                  assert_equal '_version.5.0.1', sec.id
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                test 'synthetic id separator can only be one character' do
         | 
| 85 | 
            +
                  input = <<-EOS
         | 
| 86 | 
            +
            :idseparator: -=-
         | 
| 87 | 
            +
             | 
| 88 | 
            +
            == This Section Is All You Need
         | 
| 89 | 
            +
                  EOS
         | 
| 90 | 
            +
                  sec = block_from_string input
         | 
| 91 | 
            +
                  assert_equal '_this-section-is-all-you-need', sec.id
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 54 94 | 
             
                test 'synthetic id separator can be set to blank' do
         | 
| 55 95 | 
             
                  sec = block_from_string(":idseparator:\n\n== Section One")
         | 
| 56 96 | 
             
                  assert_equal '_sectionone', sec.id
         | 
| @@ -76,6 +116,26 @@ context 'Sections' do | |
| 76 116 | 
             
                  assert_equal 'one', sec.id
         | 
| 77 117 | 
             
                end
         | 
| 78 118 |  | 
| 119 | 
            +
                test 'explicit id in block attributes above section title overrides synthetic id' do
         | 
| 120 | 
            +
                  sec = block_from_string("[id=one]\n== Section One")
         | 
| 121 | 
            +
                  assert_equal 'one', sec.id
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                test 'explicit id set using shorthand in style above section title overrides synthetic id' do
         | 
| 125 | 
            +
                  sec = block_from_string("[#one]\n== Section One")
         | 
| 126 | 
            +
                  assert_equal 'one', sec.id
         | 
| 127 | 
            +
                end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                test 'should use explicit id from last block attribute line above section title that defines an explicit id' do
         | 
| 130 | 
            +
                  input = <<-EOS
         | 
| 131 | 
            +
            [#un]
         | 
| 132 | 
            +
            [#one]
         | 
| 133 | 
            +
            == Section One
         | 
| 134 | 
            +
                  EOS
         | 
| 135 | 
            +
                  sec = block_from_string input
         | 
| 136 | 
            +
                  assert_equal 'one', sec.id
         | 
| 137 | 
            +
                end
         | 
| 138 | 
            +
             | 
| 79 139 | 
             
                test 'explicit id can be defined using an embedded anchor' do
         | 
| 80 140 | 
             
                  sec = block_from_string("== Section One [[one]] ==")
         | 
| 81 141 | 
             
                  assert_equal 'one', sec.id
         | 
| @@ -120,6 +180,12 @@ Section Title [[refid,reftext]] | |
| 120 180 | 
             
                  assert_equal 'Section One [[one]]', sec.title
         | 
| 121 181 | 
             
                end
         | 
| 122 182 |  | 
| 183 | 
            +
                test 'should not process inline anchor in section title if section has explicit ID' do
         | 
| 184 | 
            +
                  sec = block_from_string(%([#sect-one]\n== Section One [[one]]))
         | 
| 185 | 
            +
                  assert_equal 'sect-one', sec.id
         | 
| 186 | 
            +
                  assert_equal 'Section One <a id="one"></a>', sec.title
         | 
| 187 | 
            +
                end
         | 
| 188 | 
            +
             | 
| 123 189 | 
             
                test 'title substitutions are applied before generating id' do
         | 
| 124 190 | 
             
                  sec = block_from_string("== Section{sp}One\n")
         | 
| 125 191 | 
             
                  assert_equal '_section_one', sec.id
         | 
| @@ -219,11 +285,13 @@ content | |
| 219 285 | 
             
            content
         | 
| 220 286 | 
             
                  EOS
         | 
| 221 287 |  | 
| 222 | 
            -
                   | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 288 | 
            +
                  using_memory_logger do |logger|
         | 
| 289 | 
            +
                    doc = document_from_string input
         | 
| 290 | 
            +
                    reftext = doc.catalog[:ids]['install']
         | 
| 291 | 
            +
                    refute_nil reftext
         | 
| 292 | 
            +
                    assert_equal 'First Install', reftext
         | 
| 293 | 
            +
                    assert_message logger, :WARN, '<stdin>: line 7: id assigned to section already in use: install', Hash
         | 
| 294 | 
            +
                  end
         | 
| 227 295 | 
             
                end
         | 
| 228 296 |  | 
| 229 297 | 
             
                test 'duplicate block id should not overwrite existing section id entry in references table' do
         | 
| @@ -237,11 +305,13 @@ content | |
| 237 305 | 
             
            content
         | 
| 238 306 | 
             
                  EOS
         | 
| 239 307 |  | 
| 240 | 
            -
                   | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 308 | 
            +
                  using_memory_logger do |logger|
         | 
| 309 | 
            +
                    doc = document_from_string input
         | 
| 310 | 
            +
                    reftext = doc.catalog[:ids]['install']
         | 
| 311 | 
            +
                    refute_nil reftext
         | 
| 312 | 
            +
                    assert_equal 'First Install', reftext
         | 
| 313 | 
            +
                    assert_message logger, :WARN, '<stdin>: line 7: id assigned to block already in use: install', Hash
         | 
| 314 | 
            +
                  end
         | 
| 245 315 | 
             
                end
         | 
| 246 316 | 
             
              end
         | 
| 247 317 |  | 
| @@ -284,21 +354,39 @@ preamble | |
| 284 354 | 
             
                test "not enough chars for a multiline document title" do
         | 
| 285 355 | 
             
                  title = "My Title"
         | 
| 286 356 | 
             
                  chars = "=" * (title.length - 2)
         | 
| 287 | 
            -
                   | 
| 288 | 
            -
             | 
| 357 | 
            +
                  using_memory_logger do |logger|
         | 
| 358 | 
            +
                    output = render_string(title + "\n" + chars)
         | 
| 359 | 
            +
                    assert_xpath '//h1', output, 0
         | 
| 360 | 
            +
                    refute logger.empty?
         | 
| 361 | 
            +
                    logger.clear
         | 
| 362 | 
            +
                    output = render_string(title + "\n" + chars + "\n")
         | 
| 363 | 
            +
                    assert_xpath '//h1', output, 0
         | 
| 364 | 
            +
                    refute logger.empty?
         | 
| 365 | 
            +
                  end
         | 
| 289 366 | 
             
                end
         | 
| 290 367 |  | 
| 291 368 | 
             
                test "too many chars for a multiline document title" do
         | 
| 292 369 | 
             
                  title = "My Title"
         | 
| 293 370 | 
             
                  chars = "=" * (title.length + 2)
         | 
| 294 | 
            -
                   | 
| 295 | 
            -
             | 
| 371 | 
            +
                  using_memory_logger do |logger|
         | 
| 372 | 
            +
                    output = render_string(title + "\n" + chars)
         | 
| 373 | 
            +
                    assert_xpath '//h1', output, 0
         | 
| 374 | 
            +
                    refute logger.empty?
         | 
| 375 | 
            +
                    logger.clear
         | 
| 376 | 
            +
                    output = render_string(title + "\n" + chars + "\n")
         | 
| 377 | 
            +
                    assert_xpath '//h1', output, 0
         | 
| 378 | 
            +
                    refute logger.empty?
         | 
| 379 | 
            +
                  end
         | 
| 296 380 | 
             
                end
         | 
| 297 381 |  | 
| 298 382 | 
             
                test "document title with multiline syntax cannot begin with a dot" do
         | 
| 299 383 | 
             
                  title = ".My Title"
         | 
| 300 384 | 
             
                  chars = "=" * title.length
         | 
| 301 | 
            -
                   | 
| 385 | 
            +
                  using_memory_logger do |logger|
         | 
| 386 | 
            +
                    output = render_string(title + "\n" + chars)
         | 
| 387 | 
            +
                    assert_xpath '//h1', output, 0
         | 
| 388 | 
            +
                    refute logger.empty?
         | 
| 389 | 
            +
                  end
         | 
| 302 390 | 
             
                end
         | 
| 303 391 |  | 
| 304 392 | 
             
                test "document title with atx syntax" do
         | 
| @@ -339,7 +427,7 @@ content | |
| 339 427 | 
             
                  assert_css 'body#idname', output, 1
         | 
| 340 428 | 
             
                end
         | 
| 341 429 |  | 
| 342 | 
            -
                test 'should use  | 
| 430 | 
            +
                test 'should use ID defined in block attributes instead of ID defined inline' do
         | 
| 343 431 | 
             
                  input = <<-EOS
         | 
| 344 432 | 
             
            [#idname-block]
         | 
| 345 433 | 
             
            = Document Title [[idname-inline]]
         | 
| @@ -347,7 +435,7 @@ content | |
| 347 435 | 
             
            content
         | 
| 348 436 | 
             
                  EOS
         | 
| 349 437 | 
             
                  output = render_string input
         | 
| 350 | 
            -
                  assert_css 'body#idname- | 
| 438 | 
            +
                  assert_css 'body#idname-block', output, 1
         | 
| 351 439 | 
             
                end
         | 
| 352 440 |  | 
| 353 441 | 
             
                test 'block id above document title sets id on document' do
         | 
| @@ -361,10 +449,23 @@ preamble | |
| 361 449 | 
             
                  doc = document_from_string input
         | 
| 362 450 | 
             
                  assert_equal 'reference', doc.id
         | 
| 363 451 | 
             
                  assert_equal 'refguide', doc.attr('css-signature')
         | 
| 364 | 
            -
                  output = doc. | 
| 452 | 
            +
                  output = doc.convert
         | 
| 365 453 | 
             
                  assert_css 'body#reference', output, 1
         | 
| 366 454 | 
             
                end
         | 
| 367 455 |  | 
| 456 | 
            +
                test 'should register document in catalog if id is set' do
         | 
| 457 | 
            +
                  input = <<-EOS
         | 
| 458 | 
            +
            [[manual,Manual]]
         | 
| 459 | 
            +
            = Reference Manual
         | 
| 460 | 
            +
             | 
| 461 | 
            +
            preamble
         | 
| 462 | 
            +
                  EOS
         | 
| 463 | 
            +
                  doc = document_from_string input
         | 
| 464 | 
            +
                  assert_equal 'manual', doc.id
         | 
| 465 | 
            +
                  assert_equal 'Manual', doc.attributes['reftext']
         | 
| 466 | 
            +
                  assert_equal doc, doc.catalog[:refs]['manual']
         | 
| 467 | 
            +
                end
         | 
| 468 | 
            +
             | 
| 368 469 | 
             
                test 'should discard style, role and options shorthand attributes defined on document title' do
         | 
| 369 470 | 
             
                  input = <<-EOS
         | 
| 370 471 | 
             
            [style#idname.rolename%optionname]
         | 
| @@ -375,8 +476,10 @@ content | |
| 375 476 | 
             
                  doc = document_from_string input
         | 
| 376 477 | 
             
                  assert_empty doc.blocks[0].attributes
         | 
| 377 478 | 
             
                  output = doc.convert
         | 
| 479 | 
            +
                  assert_css '#idname', output, 1
         | 
| 378 480 | 
             
                  assert_css 'body#idname', output, 1
         | 
| 379 | 
            -
                  assert_css '.rolename', output,  | 
| 481 | 
            +
                  assert_css '.rolename', output, 1
         | 
| 482 | 
            +
                  assert_css 'body.rolename', output, 1
         | 
| 380 483 | 
             
                end
         | 
| 381 484 | 
             
              end
         | 
| 382 485 |  | 
| @@ -410,7 +513,11 @@ endif::[] | |
| 410 513 | 
             
                test "heading title with multiline syntax cannot begin with a dot" do
         | 
| 411 514 | 
             
                  title = ".My Title"
         | 
| 412 515 | 
             
                  chars = "-" * title.length
         | 
| 413 | 
            -
                   | 
| 516 | 
            +
                  using_memory_logger do |logger|
         | 
| 517 | 
            +
                    output = render_string(title + "\n" + chars)
         | 
| 518 | 
            +
                    assert_xpath '//h2', output, 0
         | 
| 519 | 
            +
                    refute logger.empty?
         | 
| 520 | 
            +
                  end
         | 
| 414 521 | 
             
                end
         | 
| 415 522 |  | 
| 416 523 | 
             
                test "with atx syntax" do
         | 
| @@ -426,11 +533,11 @@ endif::[] | |
| 426 533 | 
             
                end
         | 
| 427 534 |  | 
| 428 535 | 
             
                test "with XML entity" do
         | 
| 429 | 
            -
                  assert_xpath "//h2[@id=' | 
| 536 | 
            +
                  assert_xpath "//h2[@id='_whats_new'][text() = \"What#{decode_char 8217}s new?\"]", render_string("== What's new?")
         | 
| 430 537 | 
             
                end
         | 
| 431 538 |  | 
| 432 539 | 
             
                test "with non-word character" do
         | 
| 433 | 
            -
                  assert_xpath "//h2[@id=' | 
| 540 | 
            +
                  assert_xpath "//h2[@id='_whats_new'][text() = \"What’s new?\"]", render_string("== What’s new?")
         | 
| 434 541 | 
             
                end
         | 
| 435 542 |  | 
| 436 543 | 
             
                test "with sequential non-word characters" do
         | 
| @@ -523,6 +630,191 @@ content | |
| 523 630 | 
             
                end
         | 
| 524 631 | 
             
              end
         | 
| 525 632 |  | 
| 633 | 
            +
              context 'Nesting' do
         | 
| 634 | 
            +
                test 'should warn if section title is out of sequence' do
         | 
| 635 | 
            +
                  input = <<-EOS
         | 
| 636 | 
            +
            = Document Title
         | 
| 637 | 
            +
             | 
| 638 | 
            +
            == Section A
         | 
| 639 | 
            +
             | 
| 640 | 
            +
            ==== Nested Section
         | 
| 641 | 
            +
             | 
| 642 | 
            +
            content
         | 
| 643 | 
            +
             | 
| 644 | 
            +
            == Section B
         | 
| 645 | 
            +
             | 
| 646 | 
            +
            content
         | 
| 647 | 
            +
                  EOS
         | 
| 648 | 
            +
             | 
| 649 | 
            +
                  using_memory_logger do |logger|
         | 
| 650 | 
            +
                    result = render_embedded_string input
         | 
| 651 | 
            +
                    assert_xpath '//h4[text()="Nested Section"]', result, 1
         | 
| 652 | 
            +
                    assert_message logger, :WARN, '<stdin>: line 5: section title out of sequence: expected level 2, got level 3', Hash
         | 
| 653 | 
            +
                  end
         | 
| 654 | 
            +
                end
         | 
| 655 | 
            +
             | 
| 656 | 
            +
                test 'should warn if chapter title is out of sequence' do
         | 
| 657 | 
            +
                  input = <<-EOS
         | 
| 658 | 
            +
            = Document Title
         | 
| 659 | 
            +
            :doctype: book
         | 
| 660 | 
            +
             | 
| 661 | 
            +
            === Not a Chapter
         | 
| 662 | 
            +
             | 
| 663 | 
            +
            content
         | 
| 664 | 
            +
                  EOS
         | 
| 665 | 
            +
             | 
| 666 | 
            +
                  using_memory_logger do |logger|
         | 
| 667 | 
            +
                    result = render_embedded_string input
         | 
| 668 | 
            +
                    assert_xpath '//h3[text()="Not a Chapter"]', result, 1
         | 
| 669 | 
            +
                    assert_message logger, :WARN, '<stdin>: line 4: section title out of sequence: expected levels 0 or 1, got level 2', Hash
         | 
| 670 | 
            +
                  end
         | 
| 671 | 
            +
                end
         | 
| 672 | 
            +
             | 
| 673 | 
            +
                test 'should not warn if top-level section title is out of sequence when fragment attribute is set on document' do
         | 
| 674 | 
            +
                  input = <<-EOS
         | 
| 675 | 
            +
            = Document Title
         | 
| 676 | 
            +
             | 
| 677 | 
            +
            === First Section
         | 
| 678 | 
            +
             | 
| 679 | 
            +
            content
         | 
| 680 | 
            +
                  EOS
         | 
| 681 | 
            +
             | 
| 682 | 
            +
                  using_memory_logger do |logger|
         | 
| 683 | 
            +
                    render_embedded_string input, :attributes => { 'fragment' => '' }
         | 
| 684 | 
            +
                    assert logger.empty?
         | 
| 685 | 
            +
                  end
         | 
| 686 | 
            +
                end
         | 
| 687 | 
            +
             | 
| 688 | 
            +
                test 'should warn if nested section title is out of sequence when fragment attribute is set on document' do
         | 
| 689 | 
            +
                  input = <<-EOS
         | 
| 690 | 
            +
            = Document Title
         | 
| 691 | 
            +
             | 
| 692 | 
            +
            === First Section
         | 
| 693 | 
            +
             | 
| 694 | 
            +
            ===== Nested Section
         | 
| 695 | 
            +
                  EOS
         | 
| 696 | 
            +
             | 
| 697 | 
            +
                  using_memory_logger do |logger|
         | 
| 698 | 
            +
                    render_embedded_string input, :attributes => { 'fragment' => '' }
         | 
| 699 | 
            +
                    assert_message logger, :WARN, '<stdin>: line 5: section title out of sequence: expected level 3, got level 4', Hash
         | 
| 700 | 
            +
                  end
         | 
| 701 | 
            +
                end
         | 
| 702 | 
            +
                test 'should log error if subsections are found in special sections in article that do not support subsections' do
         | 
| 703 | 
            +
                  input = <<-EOS
         | 
| 704 | 
            +
            = Document Title
         | 
| 705 | 
            +
             | 
| 706 | 
            +
            == Section
         | 
| 707 | 
            +
             | 
| 708 | 
            +
            === Subsection of Section
         | 
| 709 | 
            +
             | 
| 710 | 
            +
            allowed
         | 
| 711 | 
            +
             | 
| 712 | 
            +
            [appendix]
         | 
| 713 | 
            +
            == Appendix
         | 
| 714 | 
            +
             | 
| 715 | 
            +
            === Subsection of Appendix
         | 
| 716 | 
            +
             | 
| 717 | 
            +
            allowed
         | 
| 718 | 
            +
             | 
| 719 | 
            +
            [glossary]
         | 
| 720 | 
            +
            == Glossary
         | 
| 721 | 
            +
             | 
| 722 | 
            +
            === Subsection of Glossary
         | 
| 723 | 
            +
             | 
| 724 | 
            +
            not allowed
         | 
| 725 | 
            +
             | 
| 726 | 
            +
            [bibliography]
         | 
| 727 | 
            +
            == Bibliography
         | 
| 728 | 
            +
             | 
| 729 | 
            +
            === Subsection of Bibliography
         | 
| 730 | 
            +
             | 
| 731 | 
            +
            not allowed
         | 
| 732 | 
            +
                  EOS
         | 
| 733 | 
            +
             | 
| 734 | 
            +
                  using_memory_logger do |logger|
         | 
| 735 | 
            +
                    render_embedded_string input
         | 
| 736 | 
            +
                    assert_messages logger, [
         | 
| 737 | 
            +
                      [:ERROR, '<stdin>: line 19: glossary sections do not support nested sections', Hash],
         | 
| 738 | 
            +
                      [:ERROR, '<stdin>: line 26: bibliography sections do not support nested sections', Hash],
         | 
| 739 | 
            +
                    ]
         | 
| 740 | 
            +
                  end
         | 
| 741 | 
            +
                end
         | 
| 742 | 
            +
             | 
| 743 | 
            +
                test 'should log error if subsections are found in special sections in book that do not support subsections' do
         | 
| 744 | 
            +
                  input = <<-EOS
         | 
| 745 | 
            +
            = Document Title
         | 
| 746 | 
            +
            :doctype: book
         | 
| 747 | 
            +
             | 
| 748 | 
            +
            [preface]
         | 
| 749 | 
            +
            = Preface
         | 
| 750 | 
            +
             | 
| 751 | 
            +
            === Subsection of Preface
         | 
| 752 | 
            +
             | 
| 753 | 
            +
            allowed
         | 
| 754 | 
            +
             | 
| 755 | 
            +
            [colophon]
         | 
| 756 | 
            +
            = Colophon
         | 
| 757 | 
            +
             | 
| 758 | 
            +
            === Subsection of Colophon
         | 
| 759 | 
            +
             | 
| 760 | 
            +
            not allowed
         | 
| 761 | 
            +
             | 
| 762 | 
            +
            [dedication]
         | 
| 763 | 
            +
            = Dedication
         | 
| 764 | 
            +
             | 
| 765 | 
            +
            === Subsection of Dedication
         | 
| 766 | 
            +
             | 
| 767 | 
            +
            not allowed
         | 
| 768 | 
            +
             | 
| 769 | 
            +
            = Part 1
         | 
| 770 | 
            +
             | 
| 771 | 
            +
            [abstract]
         | 
| 772 | 
            +
            == Abstract
         | 
| 773 | 
            +
             | 
| 774 | 
            +
            === Subsection of Abstract
         | 
| 775 | 
            +
             | 
| 776 | 
            +
            allowed
         | 
| 777 | 
            +
             | 
| 778 | 
            +
            == Chapter 1
         | 
| 779 | 
            +
             | 
| 780 | 
            +
            === Subsection of Chapter
         | 
| 781 | 
            +
             | 
| 782 | 
            +
            allowed
         | 
| 783 | 
            +
             | 
| 784 | 
            +
            [appendix]
         | 
| 785 | 
            +
            = Appendix
         | 
| 786 | 
            +
             | 
| 787 | 
            +
            === Subsection of Appendix
         | 
| 788 | 
            +
             | 
| 789 | 
            +
            allowed
         | 
| 790 | 
            +
             | 
| 791 | 
            +
            [glossary]
         | 
| 792 | 
            +
            = Glossary
         | 
| 793 | 
            +
             | 
| 794 | 
            +
            === Subsection of Glossary
         | 
| 795 | 
            +
             | 
| 796 | 
            +
            not allowed
         | 
| 797 | 
            +
             | 
| 798 | 
            +
            [bibliography]
         | 
| 799 | 
            +
            = Bibliography
         | 
| 800 | 
            +
             | 
| 801 | 
            +
            === Subsection of Bibliography
         | 
| 802 | 
            +
             | 
| 803 | 
            +
            not allowed
         | 
| 804 | 
            +
                  EOS
         | 
| 805 | 
            +
             | 
| 806 | 
            +
                  using_memory_logger do |logger|
         | 
| 807 | 
            +
                    render_embedded_string input
         | 
| 808 | 
            +
                    assert_messages logger, [
         | 
| 809 | 
            +
                      [:ERROR, '<stdin>: line 14: colophon sections do not support nested sections', Hash],
         | 
| 810 | 
            +
                      [:ERROR, '<stdin>: line 21: dedication sections do not support nested sections', Hash],
         | 
| 811 | 
            +
                      [:ERROR, '<stdin>: line 50: glossary sections do not support nested sections', Hash],
         | 
| 812 | 
            +
                      [:ERROR, '<stdin>: line 57: bibliography sections do not support nested sections', Hash]
         | 
| 813 | 
            +
                    ]
         | 
| 814 | 
            +
                  end
         | 
| 815 | 
            +
                end
         | 
| 816 | 
            +
              end
         | 
| 817 | 
            +
             | 
| 526 818 | 
             
              context 'Markdown-style headings' do
         | 
| 527 819 | 
             
                test 'atx document title with leading marker' do
         | 
| 528 820 | 
             
                  input = <<-EOS
         | 
| @@ -664,7 +956,7 @@ not in section | |
| 664 956 |  | 
| 665 957 | 
             
                  doc = document_from_string input
         | 
| 666 958 | 
             
                  heading = doc.blocks.first
         | 
| 667 | 
            -
                   | 
| 959 | 
            +
                  assert_kind_of Asciidoctor::Block, heading
         | 
| 668 960 | 
             
                  assert_equal :floating_title, heading.context
         | 
| 669 961 | 
             
                  assert_equal '_independent_heading', heading.id
         | 
| 670 962 | 
             
                  assert doc.catalog[:ids].has_key?('_independent_heading')
         | 
| @@ -801,6 +1093,19 @@ content | |
| 801 1093 | 
             
                  refute_nil reftext
         | 
| 802 1094 | 
             
                  assert_equal 'Install Procedure', reftext
         | 
| 803 1095 | 
             
                end
         | 
| 1096 | 
            +
             | 
| 1097 | 
            +
                test 'should not process inline anchor in discrete heading if explicit ID is assigned' do
         | 
| 1098 | 
            +
                  input = <<-EOS
         | 
| 1099 | 
            +
            [discrete#install]
         | 
| 1100 | 
            +
            == Install [[installation]]
         | 
| 1101 | 
            +
             | 
| 1102 | 
            +
            content
         | 
| 1103 | 
            +
                  EOS
         | 
| 1104 | 
            +
             | 
| 1105 | 
            +
                  block = block_from_string input
         | 
| 1106 | 
            +
                  assert_equal block.id, 'install'
         | 
| 1107 | 
            +
                  assert_equal 'Install <a id="installation"></a>', block.title
         | 
| 1108 | 
            +
                end
         | 
| 804 1109 | 
             
              end
         | 
| 805 1110 |  | 
| 806 1111 | 
             
              context 'Level offset' do
         | 
| @@ -820,14 +1125,10 @@ text in standalone | |
| 820 1125 | 
             
            // end simulated include::[]
         | 
| 821 1126 | 
             
                  EOS
         | 
| 822 1127 |  | 
| 823 | 
            -
                   | 
| 824 | 
            -
                  redirect_streams do |out, err|
         | 
| 1128 | 
            +
                  using_memory_logger do |logger|
         | 
| 825 1129 | 
             
                    render_string input
         | 
| 826 | 
            -
                     | 
| 1130 | 
            +
                    assert_message logger, :ERROR, '<stdin>: line 7: level 0 sections can only be used when doctype is book', Hash
         | 
| 827 1131 | 
             
                  end
         | 
| 828 | 
            -
             | 
| 829 | 
            -
                  refute_empty warnings
         | 
| 830 | 
            -
                  assert_match(/only book doctypes can contain level 0 sections/, warnings)
         | 
| 831 1132 | 
             
                end
         | 
| 832 1133 |  | 
| 833 1134 | 
             
                test 'should add level offset to section level' do
         | 
| @@ -857,13 +1158,12 @@ Standalone section text. | |
| 857 1158 | 
             
            Master section text.
         | 
| 858 1159 | 
             
                  EOS
         | 
| 859 1160 |  | 
| 860 | 
            -
                  output =  | 
| 861 | 
            -
                   | 
| 1161 | 
            +
                  output = nil
         | 
| 1162 | 
            +
                  using_memory_logger do |logger|
         | 
| 862 1163 | 
             
                    output = render_string input
         | 
| 863 | 
            -
                     | 
| 1164 | 
            +
                    assert logger.empty?
         | 
| 864 1165 | 
             
                  end
         | 
| 865 1166 |  | 
| 866 | 
            -
                  assert_empty warnings
         | 
| 867 1167 | 
             
                  assert_match(/Master document written by Doc Writer/, output)
         | 
| 868 1168 | 
             
                  assert_match(/Standalone document written by Junior Writer/, output)
         | 
| 869 1169 | 
             
                  assert_xpath '//*[@class="sect1"]/h2[text() = "Standalone Document"]', output, 1
         | 
| @@ -937,40 +1237,50 @@ content | |
| 937 1237 |  | 
| 938 1238 | 
             
              context 'Section Numbering' do
         | 
| 939 1239 | 
             
                test 'should create section number with one entry for level 1' do
         | 
| 940 | 
            -
                   | 
| 1240 | 
            +
                  doc = empty_document
         | 
| 1241 | 
            +
                  sect1 = Asciidoctor::Section.new nil, nil, true
         | 
| 1242 | 
            +
                  doc << sect1
         | 
| 941 1243 | 
             
                  assert_equal '1.', sect1.sectnum
         | 
| 942 1244 | 
             
                end
         | 
| 943 1245 |  | 
| 944 1246 | 
             
                test 'should create section number with two entries for level 2' do
         | 
| 945 | 
            -
                   | 
| 946 | 
            -
                   | 
| 1247 | 
            +
                  doc = empty_document
         | 
| 1248 | 
            +
                  sect1 = Asciidoctor::Section.new nil, nil, true
         | 
| 1249 | 
            +
                  doc << sect1
         | 
| 1250 | 
            +
                  sect1_1 = Asciidoctor::Section.new sect1, nil, true
         | 
| 947 1251 | 
             
                  sect1 << sect1_1
         | 
| 948 1252 | 
             
                  assert_equal '1.1.', sect1_1.sectnum
         | 
| 949 1253 | 
             
                end
         | 
| 950 1254 |  | 
| 951 1255 | 
             
                test 'should create section number with three entries for level 3' do
         | 
| 952 | 
            -
                   | 
| 953 | 
            -
                   | 
| 1256 | 
            +
                  doc = empty_document
         | 
| 1257 | 
            +
                  sect1 = Asciidoctor::Section.new nil, nil, true
         | 
| 1258 | 
            +
                  doc << sect1
         | 
| 1259 | 
            +
                  sect1_1 = Asciidoctor::Section.new sect1, nil, true
         | 
| 954 1260 | 
             
                  sect1 << sect1_1
         | 
| 955 | 
            -
                  sect1_1_1 = Asciidoctor::Section.new | 
| 1261 | 
            +
                  sect1_1_1 = Asciidoctor::Section.new sect1_1, nil, true
         | 
| 956 1262 | 
             
                  sect1_1 << sect1_1_1
         | 
| 957 1263 | 
             
                  assert_equal '1.1.1.', sect1_1_1.sectnum
         | 
| 958 1264 | 
             
                end
         | 
| 959 1265 |  | 
| 960 1266 | 
             
                test 'should create section number for second section in level' do
         | 
| 961 | 
            -
                   | 
| 962 | 
            -
                   | 
| 1267 | 
            +
                  doc = empty_document
         | 
| 1268 | 
            +
                  sect1 = Asciidoctor::Section.new nil, nil, true
         | 
| 1269 | 
            +
                  doc << sect1
         | 
| 1270 | 
            +
                  sect1_1 = Asciidoctor::Section.new sect1, nil, true
         | 
| 963 1271 | 
             
                  sect1 << sect1_1
         | 
| 964 | 
            -
                  sect1_2 = Asciidoctor::Section.new | 
| 1272 | 
            +
                  sect1_2 = Asciidoctor::Section.new sect1, nil, true
         | 
| 965 1273 | 
             
                  sect1 << sect1_2
         | 
| 966 1274 | 
             
                  assert_equal '1.2.', sect1_2.sectnum
         | 
| 967 1275 | 
             
                end
         | 
| 968 1276 |  | 
| 969 1277 | 
             
                test 'sectnum should use specified delimiter and append string' do
         | 
| 970 | 
            -
                   | 
| 971 | 
            -
                   | 
| 1278 | 
            +
                  doc = empty_document
         | 
| 1279 | 
            +
                  sect1 = Asciidoctor::Section.new nil, nil, true
         | 
| 1280 | 
            +
                  doc << sect1
         | 
| 1281 | 
            +
                  sect1_1 = Asciidoctor::Section.new sect1, nil, true
         | 
| 972 1282 | 
             
                  sect1 << sect1_1
         | 
| 973 | 
            -
                  sect1_1_1 = Asciidoctor::Section.new | 
| 1283 | 
            +
                  sect1_1_1 = Asciidoctor::Section.new sect1_1, nil, true
         | 
| 974 1284 | 
             
                  sect1_1 << sect1_1_1
         | 
| 975 1285 | 
             
                  assert_equal '1,1,1,', sect1_1_1.sectnum(',')
         | 
| 976 1286 | 
             
                  assert_equal '1:1:1', sect1_1_1.sectnum(':', false)
         | 
| @@ -1054,6 +1364,31 @@ text | |
| 1054 1364 | 
             
                  assert_xpath '//h3[@id="_section_2_2"][starts-with(text(), "2.2. ")]', output, 1
         | 
| 1055 1365 | 
             
                end
         | 
| 1056 1366 |  | 
| 1367 | 
            +
                test 'should number parts when doctype is book and partnums attributes is set' do
         | 
| 1368 | 
            +
                  input = <<-EOS
         | 
| 1369 | 
            +
            = Book Title
         | 
| 1370 | 
            +
            :doctype: book
         | 
| 1371 | 
            +
            :sectnums:
         | 
| 1372 | 
            +
            :partnums:
         | 
| 1373 | 
            +
             | 
| 1374 | 
            +
            = Language
         | 
| 1375 | 
            +
             | 
| 1376 | 
            +
            == Syntax
         | 
| 1377 | 
            +
             | 
| 1378 | 
            +
            content
         | 
| 1379 | 
            +
             | 
| 1380 | 
            +
            = Processor
         | 
| 1381 | 
            +
             | 
| 1382 | 
            +
            == CLI
         | 
| 1383 | 
            +
             | 
| 1384 | 
            +
            content
         | 
| 1385 | 
            +
                  EOS
         | 
| 1386 | 
            +
             | 
| 1387 | 
            +
                  output = render_string input
         | 
| 1388 | 
            +
                  assert_xpath '//h1[@id="_language"][text() = "I. Language"]', output, 1
         | 
| 1389 | 
            +
                  assert_xpath '//h1[@id="_processor"][text() = "II. Processor"]', output, 1
         | 
| 1390 | 
            +
                end
         | 
| 1391 | 
            +
             | 
| 1057 1392 | 
             
                test 'blocks should have level' do
         | 
| 1058 1393 | 
             
                  input = <<-EOS
         | 
| 1059 1394 | 
             
            = Title
         | 
| @@ -1313,7 +1648,7 @@ content | |
| 1313 1648 | 
             
                  EOS
         | 
| 1314 1649 |  | 
| 1315 1650 | 
             
                  doc = document_from_string input
         | 
| 1316 | 
            -
                  second_section = Asciidoctor::Section.new doc
         | 
| 1651 | 
            +
                  second_section = Asciidoctor::Section.new doc, nil, true
         | 
| 1317 1652 | 
             
                  doc.blocks.insert 1, second_section
         | 
| 1318 1653 | 
             
                  doc.reindex_sections
         | 
| 1319 1654 | 
             
                  sections = doc.sections
         | 
| @@ -1345,6 +1680,26 @@ Linux installation instructions. | |
| 1345 1680 | 
             
                  assert_xpath '//*[@class="sect2"]/h3[@id="_linux"]/a/following-sibling::text()="Linux"', output, true
         | 
| 1346 1681 | 
             
                end
         | 
| 1347 1682 |  | 
| 1683 | 
            +
                test 'should position after title text if sectanchors is set to after' do
         | 
| 1684 | 
            +
                  input = <<-EOS
         | 
| 1685 | 
            +
            == Installation
         | 
| 1686 | 
            +
             | 
| 1687 | 
            +
            Installation section.
         | 
| 1688 | 
            +
             | 
| 1689 | 
            +
            === Linux
         | 
| 1690 | 
            +
             | 
| 1691 | 
            +
            Linux installation instructions.
         | 
| 1692 | 
            +
                  EOS
         | 
| 1693 | 
            +
             | 
| 1694 | 
            +
                  output = render_embedded_string input, :attributes => {'sectanchors' => 'after'}
         | 
| 1695 | 
            +
                  assert_xpath '/*[@class="sect1"]/h2[@id="_installation"]/a', output, 1
         | 
| 1696 | 
            +
                  assert_xpath '/*[@class="sect1"]/h2[@id="_installation"]/a[@class="anchor"][@href="#_installation"]', output, 1
         | 
| 1697 | 
            +
                  assert_xpath '/*[@class="sect1"]/h2[@id="_installation"]/a/preceding-sibling::text()="Installation"', output, true
         | 
| 1698 | 
            +
                  assert_xpath '//*[@class="sect2"]/h3[@id="_linux"]/a', output, 1
         | 
| 1699 | 
            +
                  assert_xpath '//*[@class="sect2"]/h3[@id="_linux"]/a[@class="anchor"][@href="#_linux"]', output, 1
         | 
| 1700 | 
            +
                  assert_xpath '//*[@class="sect2"]/h3[@id="_linux"]/a/preceding-sibling::text()="Linux"', output, true
         | 
| 1701 | 
            +
                end
         | 
| 1702 | 
            +
             | 
| 1348 1703 | 
             
                test 'should link section if sectlinks document attribute is set' do
         | 
| 1349 1704 | 
             
                  input = <<-EOS
         | 
| 1350 1705 | 
             
            == Installation
         | 
| @@ -1394,6 +1749,32 @@ Details | |
| 1394 1749 | 
             
                  assert_xpath '//h2[text()="Appendix A: Attribute Options"]', output, 1
         | 
| 1395 1750 | 
             
                end
         | 
| 1396 1751 |  | 
| 1752 | 
            +
                test 'should use style from last block attribute line above section that defines a style' do
         | 
| 1753 | 
            +
                  input = <<-EOS
         | 
| 1754 | 
            +
            [glossary]
         | 
| 1755 | 
            +
            [appendix]
         | 
| 1756 | 
            +
            == Attribute Options
         | 
| 1757 | 
            +
             | 
| 1758 | 
            +
            Details
         | 
| 1759 | 
            +
                  EOS
         | 
| 1760 | 
            +
             | 
| 1761 | 
            +
                  output = render_embedded_string input
         | 
| 1762 | 
            +
                  assert_xpath '//h2[text()="Appendix A: Attribute Options"]', output, 1
         | 
| 1763 | 
            +
                end
         | 
| 1764 | 
            +
             | 
| 1765 | 
            +
                test 'setting ID using style shorthand should not clear section style' do
         | 
| 1766 | 
            +
                  input = <<-EOS
         | 
| 1767 | 
            +
            [appendix]
         | 
| 1768 | 
            +
            [#attribute-options]
         | 
| 1769 | 
            +
            == Attribute Options
         | 
| 1770 | 
            +
             | 
| 1771 | 
            +
            Details
         | 
| 1772 | 
            +
                  EOS
         | 
| 1773 | 
            +
             | 
| 1774 | 
            +
                  output = render_embedded_string input
         | 
| 1775 | 
            +
                  assert_xpath '//h2[@id="attribute-options"][text()="Appendix A: Attribute Options"]', output, 1
         | 
| 1776 | 
            +
                end
         | 
| 1777 | 
            +
             | 
| 1397 1778 | 
             
                test 'should use custom appendix caption if specified' do
         | 
| 1398 1779 | 
             
                  input = <<-EOS
         | 
| 1399 1780 | 
             
            :appendix-caption: App
         | 
| @@ -1624,17 +2005,20 @@ Terms | |
| 1624 2005 |  | 
| 1625 2006 | 
             
                test 'should not number special sections or their subsections by default except for appendices' do
         | 
| 1626 2007 | 
             
                  input = <<-EOS
         | 
| 2008 | 
            +
            :doctype: book
         | 
| 1627 2009 | 
             
            :sectnums:
         | 
| 1628 2010 |  | 
| 1629 | 
            -
            [ | 
| 1630 | 
            -
            ==  | 
| 2011 | 
            +
            [preface]
         | 
| 2012 | 
            +
            == Preface
         | 
| 1631 2013 |  | 
| 1632 | 
            -
            ===  | 
| 2014 | 
            +
            === Preface Subsection
         | 
| 1633 2015 |  | 
| 1634 2016 | 
             
            content
         | 
| 1635 2017 |  | 
| 1636 2018 | 
             
            == Section One
         | 
| 1637 2019 |  | 
| 2020 | 
            +
            content
         | 
| 2021 | 
            +
             | 
| 1638 2022 | 
             
            [appendix]
         | 
| 1639 2023 | 
             
            == Attribute Options
         | 
| 1640 2024 |  | 
| @@ -1656,8 +2040,8 @@ Terms | |
| 1656 2040 | 
             
                  EOS
         | 
| 1657 2041 |  | 
| 1658 2042 | 
             
                  output = render_embedded_string input
         | 
| 1659 | 
            -
                  assert_xpath '(//h2)[1][text()=" | 
| 1660 | 
            -
                  assert_xpath '(//h3)[1][text()=" | 
| 2043 | 
            +
                  assert_xpath '(//h2)[1][text()="Preface"]', output, 1
         | 
| 2044 | 
            +
                  assert_xpath '(//h3)[1][text()="Preface Subsection"]', output, 1
         | 
| 1661 2045 | 
             
                  assert_xpath '(//h2)[2][text()="1. Section One"]', output, 1
         | 
| 1662 2046 | 
             
                  assert_xpath '(//h2)[3][text()="Appendix A: Attribute Options"]', output, 1
         | 
| 1663 2047 | 
             
                  assert_xpath '(//h2)[4][text()="Appendix B: Migration"]', output, 1
         | 
| @@ -1667,18 +2051,21 @@ Terms | |
| 1667 2051 |  | 
| 1668 2052 | 
             
                test 'should not number special sections or their subsections in toc by default except for appendices' do
         | 
| 1669 2053 | 
             
                  input = <<-EOS
         | 
| 2054 | 
            +
            :doctype: book
         | 
| 1670 2055 | 
             
            :sectnums:
         | 
| 1671 2056 | 
             
            :toc:
         | 
| 1672 2057 |  | 
| 1673 | 
            -
            [ | 
| 1674 | 
            -
            ==  | 
| 2058 | 
            +
            [preface]
         | 
| 2059 | 
            +
            == Preface
         | 
| 1675 2060 |  | 
| 1676 | 
            -
            ===  | 
| 2061 | 
            +
            === Preface Subsection
         | 
| 1677 2062 |  | 
| 1678 2063 | 
             
            content
         | 
| 1679 2064 |  | 
| 1680 2065 | 
             
            == Section One
         | 
| 1681 2066 |  | 
| 2067 | 
            +
            content
         | 
| 2068 | 
            +
             | 
| 1682 2069 | 
             
            [appendix]
         | 
| 1683 2070 | 
             
            == Attribute Options
         | 
| 1684 2071 |  | 
| @@ -1700,8 +2087,8 @@ Terms | |
| 1700 2087 | 
             
                  EOS
         | 
| 1701 2088 |  | 
| 1702 2089 | 
             
                  output = render_string input
         | 
| 1703 | 
            -
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()=" | 
| 1704 | 
            -
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()=" | 
| 2090 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="Preface"]', output, 1
         | 
| 2091 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="Preface Subsection"]', output, 1
         | 
| 1705 2092 | 
             
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="1. Section One"]', output, 1
         | 
| 1706 2093 | 
             
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="Appendix A: Attribute Options"]', output, 1
         | 
| 1707 2094 | 
             
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="Appendix B: Migration"]', output, 1
         | 
| @@ -1709,6 +2096,99 @@ Terms | |
| 1709 2096 | 
             
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="Glossary"]', output, 1
         | 
| 1710 2097 | 
             
                end
         | 
| 1711 2098 |  | 
| 2099 | 
            +
                test 'should number special sections and their subsections when sectnums is all' do
         | 
| 2100 | 
            +
                  input = <<-EOS
         | 
| 2101 | 
            +
            :doctype: book
         | 
| 2102 | 
            +
            :sectnums: all
         | 
| 2103 | 
            +
             | 
| 2104 | 
            +
            [preface]
         | 
| 2105 | 
            +
            == Preface
         | 
| 2106 | 
            +
             | 
| 2107 | 
            +
            === Preface Subsection
         | 
| 2108 | 
            +
             | 
| 2109 | 
            +
            content
         | 
| 2110 | 
            +
             | 
| 2111 | 
            +
            == Section One
         | 
| 2112 | 
            +
             | 
| 2113 | 
            +
            content
         | 
| 2114 | 
            +
             | 
| 2115 | 
            +
            [appendix]
         | 
| 2116 | 
            +
            == Attribute Options
         | 
| 2117 | 
            +
             | 
| 2118 | 
            +
            Details
         | 
| 2119 | 
            +
             | 
| 2120 | 
            +
            [appendix]
         | 
| 2121 | 
            +
            == Migration
         | 
| 2122 | 
            +
             | 
| 2123 | 
            +
            Details
         | 
| 2124 | 
            +
             | 
| 2125 | 
            +
            === Gotchas
         | 
| 2126 | 
            +
             | 
| 2127 | 
            +
            Details
         | 
| 2128 | 
            +
             | 
| 2129 | 
            +
            [glossary]
         | 
| 2130 | 
            +
            == Glossary
         | 
| 2131 | 
            +
             | 
| 2132 | 
            +
            Terms
         | 
| 2133 | 
            +
                  EOS
         | 
| 2134 | 
            +
             | 
| 2135 | 
            +
                  output = render_embedded_string input
         | 
| 2136 | 
            +
                  assert_xpath '(//h2)[1][text()="1. Preface"]', output, 1
         | 
| 2137 | 
            +
                  assert_xpath '(//h3)[1][text()="1.1. Preface Subsection"]', output, 1
         | 
| 2138 | 
            +
                  assert_xpath '(//h2)[2][text()="2. Section One"]', output, 1
         | 
| 2139 | 
            +
                  assert_xpath '(//h2)[3][text()="Appendix A: Attribute Options"]', output, 1
         | 
| 2140 | 
            +
                  assert_xpath '(//h2)[4][text()="Appendix B: Migration"]', output, 1
         | 
| 2141 | 
            +
                  assert_xpath '(//h3)[2][text()="B.1. Gotchas"]', output, 1
         | 
| 2142 | 
            +
                  assert_xpath '(//h2)[5][text()="3. Glossary"]', output, 1
         | 
| 2143 | 
            +
                end
         | 
| 2144 | 
            +
             | 
| 2145 | 
            +
                test 'should number special sections and their subsections in toc when sectnums is all' do
         | 
| 2146 | 
            +
                  input = <<-EOS
         | 
| 2147 | 
            +
            :doctype: book
         | 
| 2148 | 
            +
            :sectnums: all
         | 
| 2149 | 
            +
            :toc:
         | 
| 2150 | 
            +
             | 
| 2151 | 
            +
            [preface]
         | 
| 2152 | 
            +
            == Preface
         | 
| 2153 | 
            +
             | 
| 2154 | 
            +
            === Preface Subsection
         | 
| 2155 | 
            +
             | 
| 2156 | 
            +
            content
         | 
| 2157 | 
            +
             | 
| 2158 | 
            +
            == Section One
         | 
| 2159 | 
            +
             | 
| 2160 | 
            +
            content
         | 
| 2161 | 
            +
             | 
| 2162 | 
            +
            [appendix]
         | 
| 2163 | 
            +
            == Attribute Options
         | 
| 2164 | 
            +
             | 
| 2165 | 
            +
            Details
         | 
| 2166 | 
            +
             | 
| 2167 | 
            +
            [appendix]
         | 
| 2168 | 
            +
            == Migration
         | 
| 2169 | 
            +
             | 
| 2170 | 
            +
            Details
         | 
| 2171 | 
            +
             | 
| 2172 | 
            +
            === Gotchas
         | 
| 2173 | 
            +
             | 
| 2174 | 
            +
            Details
         | 
| 2175 | 
            +
             | 
| 2176 | 
            +
            [glossary]
         | 
| 2177 | 
            +
            == Glossary
         | 
| 2178 | 
            +
             | 
| 2179 | 
            +
            Terms
         | 
| 2180 | 
            +
                  EOS
         | 
| 2181 | 
            +
             | 
| 2182 | 
            +
                  output = render_string input
         | 
| 2183 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="1. Preface"]', output, 1
         | 
| 2184 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="1.1. Preface Subsection"]', output, 1
         | 
| 2185 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="2. Section One"]', output, 1
         | 
| 2186 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="Appendix A: Attribute Options"]', output, 1
         | 
| 2187 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="Appendix B: Migration"]', output, 1
         | 
| 2188 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="B.1. Gotchas"]', output, 1
         | 
| 2189 | 
            +
                  assert_xpath '//*[@id="toc"]/ul//li/a[text()="3. Glossary"]', output, 1
         | 
| 2190 | 
            +
                end
         | 
| 2191 | 
            +
             | 
| 1712 2192 | 
             
                test 'level 0 special sections in multipart book should be rendered as level 1' do
         | 
| 1713 2193 | 
             
                  input = <<-EOS
         | 
| 1714 2194 | 
             
            = Multipart Book
         | 
| @@ -1883,6 +2363,19 @@ The corresponding definition. | |
| 1883 2363 | 
             
                  assert_xpath '//glossary/title[text()="Glossary A"]', output, 1
         | 
| 1884 2364 | 
             
                  assert_xpath '//glossary/glossentry', output, 2
         | 
| 1885 2365 | 
             
                end
         | 
| 2366 | 
            +
             | 
| 2367 | 
            +
                test 'should drop title on special section in DocBook output if untitled option is set' do
         | 
| 2368 | 
            +
                  input = <<-EOS
         | 
| 2369 | 
            +
            [dedication%untitled]
         | 
| 2370 | 
            +
            == Dedication
         | 
| 2371 | 
            +
             | 
| 2372 | 
            +
            content
         | 
| 2373 | 
            +
                  EOS
         | 
| 2374 | 
            +
             | 
| 2375 | 
            +
                  output = render_embedded_string input, :backend => :docbook
         | 
| 2376 | 
            +
                  assert_xpath '/dedication', output, 1
         | 
| 2377 | 
            +
                  assert_xpath '/dedication/title', output, 0
         | 
| 2378 | 
            +
                end
         | 
| 1886 2379 | 
             
              end
         | 
| 1887 2380 |  | 
| 1888 2381 | 
             
              context "heading patterns in blocks" do
         | 
| @@ -2567,6 +3060,61 @@ It only has content. | |
| 2567 3060 | 
             
                    assert_css '#toctitle', output, 0
         | 
| 2568 3061 | 
             
                  end
         | 
| 2569 3062 | 
             
                end
         | 
| 3063 | 
            +
             | 
| 3064 | 
            +
                test 'should drop anchors from contents of entries in table of contents' do
         | 
| 3065 | 
            +
                  input = <<-EOS
         | 
| 3066 | 
            +
            = Document Title
         | 
| 3067 | 
            +
            :toc:
         | 
| 3068 | 
            +
             | 
| 3069 | 
            +
            == [[un]]Section One
         | 
| 3070 | 
            +
             | 
| 3071 | 
            +
            content
         | 
| 3072 | 
            +
             | 
| 3073 | 
            +
            == [[two]][[deux]]Section Two
         | 
| 3074 | 
            +
             | 
| 3075 | 
            +
            content
         | 
| 3076 | 
            +
             | 
| 3077 | 
            +
            == Plant Trees by https://ecosia.org[Searching]
         | 
| 3078 | 
            +
             | 
| 3079 | 
            +
            content
         | 
| 3080 | 
            +
                  EOS
         | 
| 3081 | 
            +
             | 
| 3082 | 
            +
                  output = render_embedded_string input
         | 
| 3083 | 
            +
                  assert_xpath '/*[@id="toc"]', output, 1
         | 
| 3084 | 
            +
                  toc_links = xmlnodes_at_xpath '/*[@id="toc"]//li', output
         | 
| 3085 | 
            +
                  assert_equal 3, toc_links.size
         | 
| 3086 | 
            +
                  assert_equal '<a href="#_section_one">Section One</a>', toc_links[0].inner_html
         | 
| 3087 | 
            +
                  assert_equal '<a href="#_section_two">Section Two</a>', toc_links[1].inner_html
         | 
| 3088 | 
            +
                  assert_equal '<a href="#_plant_trees_by_searching">Plant Trees by Searching</a>', toc_links[2].inner_html
         | 
| 3089 | 
            +
                end
         | 
| 3090 | 
            +
             | 
| 3091 | 
            +
                test 'should not remove non-anchor tags from contents of entries in table of contents' do
         | 
| 3092 | 
            +
                  input = <<-EOS
         | 
| 3093 | 
            +
            = Document Title
         | 
| 3094 | 
            +
            :toc:
         | 
| 3095 | 
            +
            :icons: font
         | 
| 3096 | 
            +
             | 
| 3097 | 
            +
            == `run` command
         | 
| 3098 | 
            +
             | 
| 3099 | 
            +
            content
         | 
| 3100 | 
            +
             | 
| 3101 | 
            +
            == icon:bug[] Issues
         | 
| 3102 | 
            +
             | 
| 3103 | 
            +
            content
         | 
| 3104 | 
            +
             | 
| 3105 | 
            +
            == https://ecosia.org[_Sustainable_ Searches]
         | 
| 3106 | 
            +
             | 
| 3107 | 
            +
            content
         | 
| 3108 | 
            +
                  EOS
         | 
| 3109 | 
            +
             | 
| 3110 | 
            +
                  output = render_embedded_string input, :safe => :safe
         | 
| 3111 | 
            +
                  assert_xpath '/*[@id="toc"]', output, 1
         | 
| 3112 | 
            +
                  toc_links = xmlnodes_at_xpath '/*[@id="toc"]//li', output
         | 
| 3113 | 
            +
                  assert_equal 3, toc_links.size
         | 
| 3114 | 
            +
                  assert_equal '<a href="#_run_command"><code>run</code> command</a>', toc_links[0].inner_html
         | 
| 3115 | 
            +
                  assert_equal '<a href="#_issues"><span class="icon"><i class="fa fa-bug"></i></span> Issues</a>', toc_links[1].inner_html
         | 
| 3116 | 
            +
                  assert_equal '<a href="#_sustainable_searches"><em>Sustainable</em> Searches</a>', toc_links[2].inner_html
         | 
| 3117 | 
            +
                end
         | 
| 2570 3118 | 
             
              end
         | 
| 2571 3119 |  | 
| 2572 3120 | 
             
              context 'article doctype' do
         | 
| @@ -2657,6 +3205,48 @@ That's all she wrote! | |
| 2657 3205 | 
             
                  assert_xpath '//h1[@id="_chapter_three"][text() = "Chapter Three"]', output, 1
         | 
| 2658 3206 | 
             
                end
         | 
| 2659 3207 |  | 
| 3208 | 
            +
                test 'should print error if level 0 section comes after nested section and doctype is not book' do
         | 
| 3209 | 
            +
                  input = <<-EOS
         | 
| 3210 | 
            +
            = Document Title
         | 
| 3211 | 
            +
             | 
| 3212 | 
            +
            == Level 1 Section
         | 
| 3213 | 
            +
             | 
| 3214 | 
            +
            === Level 2 Section
         | 
| 3215 | 
            +
             | 
| 3216 | 
            +
            = Level 0 Section
         | 
| 3217 | 
            +
                  EOS
         | 
| 3218 | 
            +
             | 
| 3219 | 
            +
                  using_memory_logger do |logger|
         | 
| 3220 | 
            +
                    render_string input
         | 
| 3221 | 
            +
                    assert_message logger, :ERROR, '<stdin>: line 7: level 0 sections can only be used when doctype is book', Hash
         | 
| 3222 | 
            +
                  end
         | 
| 3223 | 
            +
                end
         | 
| 3224 | 
            +
             | 
| 3225 | 
            +
                test 'should add class matching role to part' do
         | 
| 3226 | 
            +
                  input = <<-EOS
         | 
| 3227 | 
            +
            = Book Title
         | 
| 3228 | 
            +
            :doctype: book
         | 
| 3229 | 
            +
             | 
| 3230 | 
            +
            [.newbie]
         | 
| 3231 | 
            +
            = Part 1
         | 
| 3232 | 
            +
             | 
| 3233 | 
            +
            == Chapter A
         | 
| 3234 | 
            +
             | 
| 3235 | 
            +
            content
         | 
| 3236 | 
            +
             | 
| 3237 | 
            +
            = Part 2
         | 
| 3238 | 
            +
             | 
| 3239 | 
            +
            == Chapter B
         | 
| 3240 | 
            +
             | 
| 3241 | 
            +
            content
         | 
| 3242 | 
            +
                  EOS
         | 
| 3243 | 
            +
             | 
| 3244 | 
            +
                  result = render_embedded_string input
         | 
| 3245 | 
            +
                  assert_css 'h1.sect0', result, 2
         | 
| 3246 | 
            +
                  assert_css 'h1.sect0.newbie', result, 1
         | 
| 3247 | 
            +
                  assert_css 'h1.sect0.newbie#_part_1', result, 1
         | 
| 3248 | 
            +
                end
         | 
| 3249 | 
            +
             | 
| 2660 3250 | 
             
                test 'should assign appropriate sectname for section type' do
         | 
| 2661 3251 | 
             
                  input = <<-EOS
         | 
| 2662 3252 | 
             
            = Book Title
         | 
| @@ -2761,15 +3351,10 @@ more part intro | |
| 2761 3351 | 
             
            intro
         | 
| 2762 3352 | 
             
                  EOS
         | 
| 2763 3353 |  | 
| 2764 | 
            -
                   | 
| 2765 | 
            -
                  redirect_streams do |out, err|
         | 
| 3354 | 
            +
                  using_memory_logger do |logger|
         | 
| 2766 3355 | 
             
                    document_from_string input
         | 
| 2767 | 
            -
                     | 
| 3356 | 
            +
                    assert_message logger, :ERROR, '<stdin>: line 8: invalid part, must have at least one section (e.g., chapter, appendix, etc.)', Hash
         | 
| 2768 3357 | 
             
                  end
         | 
| 2769 | 
            -
             | 
| 2770 | 
            -
                  refute_nil warnings
         | 
| 2771 | 
            -
                  refute_empty warnings
         | 
| 2772 | 
            -
                  assert_match(/ERROR:.*section/, warnings)
         | 
| 2773 3358 | 
             
                end
         | 
| 2774 3359 |  | 
| 2775 3360 | 
             
                test 'should create parts and chapters in docbook backend' do
         | 
| @@ -2850,12 +3435,11 @@ Appendix content | |
| 2850 3435 | 
             
            Appendix subsection content
         | 
| 2851 3436 | 
             
                  EOS
         | 
| 2852 3437 |  | 
| 2853 | 
            -
                  output =  | 
| 2854 | 
            -
                   | 
| 3438 | 
            +
                  output = nil
         | 
| 3439 | 
            +
                  using_memory_logger do |logger|
         | 
| 2855 3440 | 
             
                    output = render_string input, :backend => 'docbook'
         | 
| 2856 | 
            -
                     | 
| 3441 | 
            +
                    assert logger.empty?
         | 
| 2857 3442 | 
             
                  end
         | 
| 2858 | 
            -
                  assert_empty warnings
         | 
| 2859 3443 | 
             
                  assert_xpath '/book/preface', output, 1
         | 
| 2860 3444 | 
             
                  assert_xpath '/book/preface/section', output, 1
         | 
| 2861 3445 | 
             
                  assert_xpath '/book/part', output, 1
         |