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
| @@ -18,7 +18,7 @@ module Asciidoctor | |
| 18 18 | 
             
                LeadingPeriodRx = /^\./
         | 
| 19 19 | 
             
                EscapedMacroRx = /^(?:#{ESC}\\c\n)?#{ESC}\.((?:URL|MTO) ".*?" ".*?" )( |[^\s]*)(.*?)(?: *#{ESC}\\c)?$/
         | 
| 20 20 | 
             
                MockBoundaryRx = /<\/?BOUNDARY>/
         | 
| 21 | 
            -
                EmDashCharRefRx = /—( | 
| 21 | 
            +
                EmDashCharRefRx = /—(?:​)?/
         | 
| 22 22 | 
             
                EllipsisCharRefRx = /…(?:​)?/
         | 
| 23 23 |  | 
| 24 24 | 
             
                # Converts HTML entity references back to their original form, escapes
         | 
| @@ -57,6 +57,7 @@ module Asciidoctor | |
| 57 57 | 
             
                    gsub('⇐', '\(lA').  # leftwards double arrow
         | 
| 58 58 | 
             
                    gsub('⇒', '\(rA').  # rightwards double arrow
         | 
| 59 59 | 
             
                    gsub('​', '\:').    # zero width space
         | 
| 60 | 
            +
                    gsub('&','&').        # literal ampersand (NOTE must take place after any other replacement that includes &)
         | 
| 60 61 | 
             
                    gsub('\'', '\(aq').       # apostrophe-quote
         | 
| 61 62 | 
             
                    gsub(MockBoundaryRx, ''). # mock boundary
         | 
| 62 63 | 
             
                    gsub(ESC_BS, '\\').       # unescape troff backslash (NOTE update if more escapes are added)
         | 
| @@ -66,7 +67,7 @@ module Asciidoctor | |
| 66 67 | 
             
                end
         | 
| 67 68 |  | 
| 68 69 | 
             
                def skip_with_warning node, name = nil
         | 
| 69 | 
            -
                  warn %( | 
| 70 | 
            +
                  logger.warn %(converter missing for #{name || node.node_name} node in manpage backend)
         | 
| 70 71 | 
             
                  nil
         | 
| 71 72 | 
             
                end
         | 
| 72 73 |  | 
| @@ -81,7 +82,7 @@ module Asciidoctor | |
| 81 82 | 
             
                  # NOTE the first line enables the table (tbl) preprocessor, necessary for non-Linux systems
         | 
| 82 83 | 
             
                  result = [%('\\" t
         | 
| 83 84 | 
             
            .\\"     Title: #{mantitle}
         | 
| 84 | 
            -
            .\\"    Author: #{(node.attr? 'authors') ? (node.attr 'authors') : '[see the " | 
| 85 | 
            +
            .\\"    Author: #{(node.attr? 'authors') ? (node.attr 'authors') : '[see the "AUTHOR(S)" section]'}
         | 
| 85 86 | 
             
            .\\" Generator: Asciidoctor #{node.attr 'asciidoctor-version'})]
         | 
| 86 87 | 
             
                  result << %(.\\"      Date: #{docdate}) if docdate
         | 
| 87 88 | 
             
                  result << %(.\\"    Manual: #{(manual = node.attr 'manmanual') || '\ \&'}
         | 
| @@ -105,22 +106,33 @@ module Asciidoctor | |
| 105 106 | 
             
                  # define URL macro for portability
         | 
| 106 107 | 
             
                  # see http://web.archive.org/web/20060102165607/http://people.debian.org/~branden/talks/wtfm/wtfm.pdf
         | 
| 107 108 | 
             
                  #
         | 
| 108 | 
            -
                  #  | 
| 109 | 
            +
                  # Usage
         | 
| 110 | 
            +
                  #
         | 
| 111 | 
            +
                  # .URL "http://www.debian.org" "Debian" "."
         | 
| 109 112 | 
             
                  #
         | 
| 110 113 | 
             
                  # * First argument: the URL
         | 
| 111 114 | 
             
                  # * Second argument: text to be hyperlinked
         | 
| 112 | 
            -
                  # * Third (optional) argument: text that needs to immediately trail
         | 
| 113 | 
            -
                  #   the hyperlink without intervening whitespace
         | 
| 115 | 
            +
                  # * Third (optional) argument: text that needs to immediately trail the hyperlink without intervening whitespace
         | 
| 114 116 | 
             
                  result << '.de URL
         | 
| 115 | 
            -
            \\\\$2  | 
| 117 | 
            +
            \\fI\\\\$2\\fP <\\\\$1>\\\\$3
         | 
| 116 118 | 
             
            ..
         | 
| 117 | 
            -
            . | 
| 118 | 
            -
             | 
| 119 | 
            +
            .als MTO URL
         | 
| 120 | 
            +
            .if \n[.g] \{\
         | 
| 121 | 
            +
            .  mso www.tmac
         | 
| 122 | 
            +
            .  am URL
         | 
| 123 | 
            +
            .    ad l
         | 
| 124 | 
            +
            .  .
         | 
| 125 | 
            +
            .  am MTO
         | 
| 126 | 
            +
            .    ad l
         | 
| 127 | 
            +
            .  .'
         | 
| 128 | 
            +
                  result << %(.  LINKSTYLE #{node.attr 'man-linkstyle', 'blue R < >'})
         | 
| 129 | 
            +
                  result << '.\}'
         | 
| 119 130 |  | 
| 120 131 | 
             
                  unless node.noheader
         | 
| 121 132 | 
             
                    if node.attr? 'manpurpose'
         | 
| 122 | 
            -
                       | 
| 123 | 
            -
             | 
| 133 | 
            +
                      mannames = node.attr 'mannames', [manname]
         | 
| 134 | 
            +
                      result << %(.SH "#{(node.attr 'manname-title').upcase}"
         | 
| 135 | 
            +
            #{mannames.map {|n| manify n } * ', '} \\- #{manify node.attr 'manpurpose'})
         | 
| 124 136 | 
             
                    end
         | 
| 125 137 | 
             
                  end
         | 
| 126 138 |  | 
| @@ -132,14 +144,19 @@ module Asciidoctor | |
| 132 144 | 
             
                    result.concat(node.footnotes.map {|fn| %(#{fn.index}. #{fn.text}) })
         | 
| 133 145 | 
             
                  end
         | 
| 134 146 |  | 
| 135 | 
            -
                  # FIXME  | 
| 136 | 
            -
                  if node.attr | 
| 137 | 
            -
                     | 
| 147 | 
            +
                  # FIXME we really need an API that returns the authors as an array
         | 
| 148 | 
            +
                  if (num_authors = (node.attr 'authorcount') || 0) > 0
         | 
| 149 | 
            +
                    if num_authors == 1
         | 
| 150 | 
            +
                      result << %(.SH "AUTHOR"
         | 
| 138 151 | 
             
            .sp
         | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
            . | 
| 152 | 
            +
            #{node.attr 'author'})
         | 
| 153 | 
            +
                    else
         | 
| 154 | 
            +
                      result << '.SH "AUTHORS"'
         | 
| 155 | 
            +
                      (1.upto num_authors).each do |i|
         | 
| 156 | 
            +
                        result << %(.sp
         | 
| 157 | 
            +
            #{node.attr "author_#{i}"})
         | 
| 158 | 
            +
                      end
         | 
| 159 | 
            +
                    end
         | 
| 143 160 | 
             
                  end
         | 
| 144 161 |  | 
| 145 162 | 
             
                  result * LF
         | 
| @@ -176,16 +193,14 @@ Author(s). | |
| 176 193 |  | 
| 177 194 | 
             
                def admonition node
         | 
| 178 195 | 
             
                  result = []
         | 
| 179 | 
            -
                  result << %(.if n  | 
| 180 | 
            -
            .sp
         | 
| 181 | 
            -
            .\\}
         | 
| 196 | 
            +
                  result << %(.if n .sp
         | 
| 182 197 | 
             
            .RS 4
         | 
| 183 198 | 
             
            .it 1 an-trap
         | 
| 184 199 | 
             
            .nr an-no-space-flag 1
         | 
| 185 200 | 
             
            .nr an-break-flag 1
         | 
| 186 201 | 
             
            .br
         | 
| 187 202 | 
             
            .ps +1
         | 
| 188 | 
            -
            .B #{node.attr 'textlabel'}#{node.title? ? "\\fP: #{manify node.title}" :  | 
| 203 | 
            +
            .B #{node.attr 'textlabel'}#{node.title? ? "\\fP: #{manify node.title}" : ''}
         | 
| 189 204 | 
             
            .ps -1
         | 
| 190 205 | 
             
            .br
         | 
| 191 206 | 
             
            #{resolve_content node}
         | 
| @@ -216,10 +231,12 @@ r lw(\n(.lu*75u/100u).' | |
| 216 231 | 
             
                  result * LF
         | 
| 217 232 | 
             
                end
         | 
| 218 233 |  | 
| 219 | 
            -
                # TODO implement title for dlist
         | 
| 220 234 | 
             
                # TODO implement horizontal (if it makes sense)
         | 
| 221 235 | 
             
                def dlist node
         | 
| 222 236 | 
             
                  result = []
         | 
| 237 | 
            +
                  result << %(.sp
         | 
| 238 | 
            +
            .B #{manify node.title}
         | 
| 239 | 
            +
            .br) if node.title?
         | 
| 223 240 | 
             
                  counter = 0
         | 
| 224 241 | 
             
                  node.items.each do |terms, dd|
         | 
| 225 242 | 
             
                    counter += 1
         | 
| @@ -265,15 +282,11 @@ r lw(\n(.lu*75u/100u).' | |
| 265 282 | 
             
            .B #{manify node.captioned_title}
         | 
| 266 283 | 
             
            .br) if node.title?
         | 
| 267 284 | 
             
                  result << %(.sp
         | 
| 268 | 
            -
            .if n  | 
| 269 | 
            -
            .RS 4
         | 
| 270 | 
            -
            .\\}
         | 
| 285 | 
            +
            .if n .RS 4
         | 
| 271 286 | 
             
            .nf
         | 
| 272 287 | 
             
            #{manify node.content}
         | 
| 273 288 | 
             
            .fi
         | 
| 274 | 
            -
            .if n  | 
| 275 | 
            -
            .RE
         | 
| 276 | 
            -
            .\\})
         | 
| 289 | 
            +
            .if n .RE)
         | 
| 277 290 | 
             
                  result * LF
         | 
| 278 291 | 
             
                end
         | 
| 279 292 |  | 
| @@ -283,15 +296,11 @@ r lw(\n(.lu*75u/100u).' | |
| 283 296 | 
             
            .B #{manify node.title}
         | 
| 284 297 | 
             
            .br) if node.title?
         | 
| 285 298 | 
             
                  result << %(.sp
         | 
| 286 | 
            -
            .if n  | 
| 287 | 
            -
            .RS 4
         | 
| 288 | 
            -
            .\\}
         | 
| 299 | 
            +
            .if n .RS 4
         | 
| 289 300 | 
             
            .nf
         | 
| 290 301 | 
             
            #{manify node.content}
         | 
| 291 302 | 
             
            .fi
         | 
| 292 | 
            -
            .if n  | 
| 293 | 
            -
            .RE
         | 
| 294 | 
            -
            .\\})
         | 
| 303 | 
            +
            .if n .RE)
         | 
| 295 304 | 
             
                  result * LF
         | 
| 296 305 | 
             
                end
         | 
| 297 306 |  | 
| @@ -308,8 +317,8 @@ r lw(\n(.lu*75u/100u).' | |
| 308 317 | 
             
            \\h'-04' #{idx + 1}.\\h'+01'\\c
         | 
| 309 318 | 
             
            .\\}
         | 
| 310 319 | 
             
            .el \\{\\
         | 
| 311 | 
            -
            .sp -1
         | 
| 312 | 
            -
            .IP " #{idx + 1}." 4.2
         | 
| 320 | 
            +
            .  sp -1
         | 
| 321 | 
            +
            .  IP " #{idx + 1}." 4.2
         | 
| 313 322 | 
             
            .\\}
         | 
| 314 323 | 
             
            #{manify item.text})
         | 
| 315 324 | 
             
                    result << item.content if item.blocks?
         | 
| @@ -378,7 +387,7 @@ r lw(\n(.lu*75u/100u).' | |
| 378 387 | 
             
                def stem node
         | 
| 379 388 | 
             
                  title_element = node.title? ? %(.sp
         | 
| 380 389 | 
             
            .B #{manify node.title}
         | 
| 381 | 
            -
            .br) :  | 
| 390 | 
            +
            .br) : ''
         | 
| 382 391 | 
             
                  open, close = BLOCK_MATH_DELIMITERS[node.style.to_sym]
         | 
| 383 392 |  | 
| 384 393 | 
             
                  unless ((equation = node.content).start_with? open) && (equation.end_with? close)
         | 
| @@ -538,8 +547,8 @@ allbox tab(:);' | |
| 538 547 | 
             
            \\h'-04'\\(bu\\h'+03'\\c
         | 
| 539 548 | 
             
            .\\}
         | 
| 540 549 | 
             
            .el \\{\\
         | 
| 541 | 
            -
            .sp -1
         | 
| 542 | 
            -
            .IP \\(bu 2.3
         | 
| 550 | 
            +
            .  sp -1
         | 
| 551 | 
            +
            .  IP \\(bu 2.3
         | 
| 543 552 | 
             
            .\\}
         | 
| 544 553 | 
             
            #{manify item.text}]
         | 
| 545 554 | 
             
                    result << item.content if item.blocks?
         | 
| @@ -574,8 +583,8 @@ allbox tab(:);' | |
| 574 583 | 
             
                end
         | 
| 575 584 |  | 
| 576 585 | 
             
                def video node
         | 
| 577 | 
            -
                  start_param = (node.attr? 'start', nil, false) ? %(&start=#{node.attr 'start'}) :  | 
| 578 | 
            -
                  end_param = (node.attr? 'end', nil, false) ? %(&end=#{node.attr 'end'}) :  | 
| 586 | 
            +
                  start_param = (node.attr? 'start', nil, false) ? %(&start=#{node.attr 'start'}) : ''
         | 
| 587 | 
            +
                  end_param = (node.attr? 'end', nil, false) ? %(&end=#{node.attr 'end'}) : ''
         | 
| 579 588 | 
             
                  result = []
         | 
| 580 589 | 
             
                  result << %(.sp
         | 
| 581 590 | 
             
            .B #{manify node.title}
         | 
| @@ -588,17 +597,18 @@ allbox tab(:);' | |
| 588 597 | 
             
                  target = node.target
         | 
| 589 598 | 
             
                  case node.type
         | 
| 590 599 | 
             
                  when :link
         | 
| 591 | 
            -
                    if (text = node.text) == target
         | 
| 592 | 
            -
                      text = nil
         | 
| 593 | 
            -
                    else
         | 
| 594 | 
            -
                      text = text.gsub '"', %[#{ESC_BS}(dq]
         | 
| 595 | 
            -
                    end
         | 
| 596 600 | 
             
                    if target.start_with? 'mailto:'
         | 
| 597 601 | 
             
                      macro = 'MTO'
         | 
| 598 | 
            -
                      target = target | 
| 602 | 
            +
                      target = target.slice 7, target.length
         | 
| 599 603 | 
             
                    else
         | 
| 600 604 | 
             
                      macro = 'URL'
         | 
| 601 605 | 
             
                    end
         | 
| 606 | 
            +
                    if (text = node.text) == target
         | 
| 607 | 
            +
                      text = ''
         | 
| 608 | 
            +
                    else
         | 
| 609 | 
            +
                      text = text.gsub '"', %[#{ESC_BS}(dq]
         | 
| 610 | 
            +
                    end
         | 
| 611 | 
            +
                    target = target.sub '@', %[#{ESC_BS}(at] if macro == 'MTO'
         | 
| 602 612 | 
             
                    %(#{ESC_BS}c#{LF}#{ESC_FS}#{macro} "#{target}" "#{text}" )
         | 
| 603 613 | 
             
                  when :xref
         | 
| 604 614 | 
             
                    refid = (node.attr 'refid') || target
         | 
| @@ -607,7 +617,8 @@ allbox tab(:);' | |
| 607 617 | 
             
                    # These are anchor points, which shouldn't be visible
         | 
| 608 618 | 
             
                    ''
         | 
| 609 619 | 
             
                  else
         | 
| 610 | 
            -
                    warn %( | 
| 620 | 
            +
                    logger.warn %(unknown anchor type: #{node.type.inspect})
         | 
| 621 | 
            +
                    nil
         | 
| 611 622 | 
             
                  end
         | 
| 612 623 | 
             
                end
         | 
| 613 624 |  | 
| @@ -669,7 +680,7 @@ allbox tab(:);' | |
| 669 680 | 
             
                  when :strong
         | 
| 670 681 | 
             
                    %(#{ESC_BS}fB<BOUNDARY>#{node.text}</BOUNDARY>#{ESC_BS}fP)
         | 
| 671 682 | 
             
                  when :monospaced
         | 
| 672 | 
            -
                    % | 
| 683 | 
            +
                    %[#{ESC_BS}f(CR<BOUNDARY>#{node.text}</BOUNDARY>#{ESC_BS}fP]
         | 
| 673 684 | 
             
                  when :single
         | 
| 674 685 | 
             
                    %[#{ESC_BS}(oq<BOUNDARY>#{node.text}</BOUNDARY>#{ESC_BS}(cq]
         | 
| 675 686 | 
             
                  when :double
         | 
| @@ -682,5 +693,16 @@ allbox tab(:);' | |
| 682 693 | 
             
                def resolve_content node
         | 
| 683 694 | 
             
                  node.content_model == :compound ? node.content : %(.sp#{LF}#{manify node.content})
         | 
| 684 695 | 
             
                end
         | 
| 696 | 
            +
             | 
| 697 | 
            +
                def write_alternate_pages mannames, manvolnum, target
         | 
| 698 | 
            +
                  if mannames && mannames.size > 1
         | 
| 699 | 
            +
                    mannames.shift
         | 
| 700 | 
            +
                    manvolext = %(.#{manvolnum})
         | 
| 701 | 
            +
                    dir, basename = ::File.split target
         | 
| 702 | 
            +
                    mannames.each do |manname|
         | 
| 703 | 
            +
                      ::IO.write ::File.join(dir, %(#{manname}#{manvolext})), %(.so #{basename})
         | 
| 704 | 
            +
                    end
         | 
| 705 | 
            +
                  end
         | 
| 706 | 
            +
                end
         | 
| 685 707 | 
             
              end
         | 
| 686 708 | 
             
            end
         | 
| @@ -39,8 +39,6 @@ module Asciidoctor | |
| 39 39 | 
             
                  @caches = { :scans => ::ThreadSafe::Cache.new, :templates => ::ThreadSafe::Cache.new }
         | 
| 40 40 | 
             
                rescue ::LoadError
         | 
| 41 41 | 
             
                  @caches = { :scans => {}, :templates => {} }
         | 
| 42 | 
            -
                  # FIXME perhaps only warn if the cache option is enabled (meaning not disabled)?
         | 
| 43 | 
            -
                  warn 'asciidoctor: WARNING: gem \'thread_safe\' is not installed. This gem is recommended when using custom backend templates.'
         | 
| 44 42 | 
             
                end
         | 
| 45 43 |  | 
| 46 44 | 
             
                def self.caches
         | 
| @@ -77,6 +75,7 @@ module Asciidoctor | |
| 77 75 | 
             
                  end
         | 
| 78 76 | 
             
                  case opts[:template_cache]
         | 
| 79 77 | 
             
                  when true
         | 
| 78 | 
            +
                    logger.warn 'gem \'thread_safe\' is not installed. This gem is recommended when using the built-in template cache.' unless defined? ::ThreadSafe
         | 
| 80 79 | 
             
                    @caches = self.class.caches
         | 
| 81 80 | 
             
                  when ::Hash
         | 
| 82 81 | 
             
                    @caches = opts[:template_cache]
         | 
| @@ -105,24 +104,25 @@ module Asciidoctor | |
| 105 104 | 
             
                  engine = @engine
         | 
| 106 105 | 
             
                  @template_dirs.each do |template_dir|
         | 
| 107 106 | 
             
                    # FIXME need to think about safe mode restrictions here
         | 
| 108 | 
            -
                    next unless ::File.directory?(template_dir = (path_resolver.system_path template_dir | 
| 107 | 
            +
                    next unless ::File.directory?(template_dir = (path_resolver.system_path template_dir))
         | 
| 109 108 |  | 
| 110 | 
            -
                    # NOTE last matching template wins for template name if no engine is given
         | 
| 111 | 
            -
                    file_pattern = '*'
         | 
| 112 109 | 
             
                    if engine
         | 
| 113 110 | 
             
                      file_pattern = %(*.#{engine})
         | 
| 114 111 | 
             
                      # example: templates/haml
         | 
| 115 | 
            -
                      if ::File.directory?(engine_dir = ( | 
| 112 | 
            +
                      if ::File.directory?(engine_dir = %(#{template_dir}/#{engine}))
         | 
| 116 113 | 
             
                        template_dir = engine_dir
         | 
| 117 114 | 
             
                      end
         | 
| 115 | 
            +
                    else
         | 
| 116 | 
            +
                      # NOTE last matching template wins for template name if no engine is given
         | 
| 117 | 
            +
                      file_pattern = '*'
         | 
| 118 118 | 
             
                    end
         | 
| 119 119 |  | 
| 120 | 
            -
                    # example: templates/html5 or templates/haml/html5
         | 
| 121 | 
            -
                    if ::File.directory?(backend_dir = ( | 
| 120 | 
            +
                    # example: templates/html5 (engine not set) or templates/haml/html5 (engine set)
         | 
| 121 | 
            +
                    if ::File.directory?(backend_dir = %(#{template_dir}/#{backend}))
         | 
| 122 122 | 
             
                      template_dir = backend_dir
         | 
| 123 123 | 
             
                    end
         | 
| 124 124 |  | 
| 125 | 
            -
                    pattern =  | 
| 125 | 
            +
                    pattern = %(#{template_dir}/#{file_pattern})
         | 
| 126 126 |  | 
| 127 127 | 
             
                    if (scan_cache = @caches[:scans])
         | 
| 128 128 | 
             
                      template_cache = @caches[:templates]
         | 
| @@ -161,7 +161,7 @@ module Asciidoctor | |
| 161 161 | 
             
                    end
         | 
| 162 162 | 
             
                  else
         | 
| 163 163 | 
             
                    metaclass.send :define_method, name do |node|
         | 
| 164 | 
            -
                      (template.render node). | 
| 164 | 
            +
                      (template.render node).rstrip
         | 
| 165 165 | 
             
                    end
         | 
| 166 166 | 
             
                  end
         | 
| 167 167 | 
             
                end
         | 
| @@ -193,7 +193,7 @@ module Asciidoctor | |
| 193 193 | 
             
                  if template_name == 'document'
         | 
| 194 194 | 
             
                    (template.render node, opts).strip
         | 
| 195 195 | 
             
                  else
         | 
| 196 | 
            -
                    (template.render node, opts). | 
| 196 | 
            +
                    (template.render node, opts).rstrip
         | 
| 197 197 | 
             
                  end
         | 
| 198 198 | 
             
                end
         | 
| 199 199 |  | 
| @@ -280,7 +280,7 @@ module Asciidoctor | |
| 280 280 | 
             
                    end
         | 
| 281 281 | 
             
                    result[name] = template
         | 
| 282 282 | 
             
                  end
         | 
| 283 | 
            -
                  if helpers || ::File.file?(helpers = ( | 
| 283 | 
            +
                  if helpers || ::File.file?(helpers = %(#{template_dir}/helpers.rb))
         | 
| 284 284 | 
             
                    require helpers
         | 
| 285 285 | 
             
                  end
         | 
| 286 286 | 
             
                  result
         | 
    
        data/lib/asciidoctor/core_ext.rb
    CHANGED
    
    | @@ -2,8 +2,12 @@ require 'asciidoctor/core_ext/nil_or_empty' | |
| 2 2 | 
             
            require 'asciidoctor/core_ext/regexp/is_match'
         | 
| 3 3 | 
             
            if RUBY_MIN_VERSION_1_9
         | 
| 4 4 | 
             
              require 'asciidoctor/core_ext/string/limit_bytesize'
         | 
| 5 | 
            -
               | 
| 5 | 
            +
              if RUBY_ENGINE == 'opal'
         | 
| 6 | 
            +
                require 'asciidoctor/core_ext/1.8.7/io/binread'
         | 
| 7 | 
            +
                require 'asciidoctor/core_ext/1.8.7/io/write'
         | 
| 8 | 
            +
              end
         | 
| 6 9 | 
             
            elsif RUBY_ENGINE != 'opal'
         | 
| 10 | 
            +
              require 'asciidoctor/core_ext/1.8.7/base64/strict_encode64'
         | 
| 7 11 | 
             
              require 'asciidoctor/core_ext/1.8.7/hash/key'
         | 
| 8 12 | 
             
              require 'asciidoctor/core_ext/1.8.7/io/binread'
         | 
| 9 13 | 
             
              require 'asciidoctor/core_ext/1.8.7/io/write'
         | 
    
        data/lib/asciidoctor/document.rb
    CHANGED
    
    | @@ -1,22 +1,85 @@ | |
| 1 1 | 
             
            # encoding: UTF-8
         | 
| 2 2 | 
             
            module Asciidoctor
         | 
| 3 | 
            -
            # Public:  | 
| 3 | 
            +
            # Public: The Document class represents a parsed AsciiDoc document.
         | 
| 4 4 | 
             
            #
         | 
| 5 | 
            -
            #  | 
| 5 | 
            +
            # Document is the root node of a parsed AsciiDoc document. It provides an
         | 
| 6 | 
            +
            # abstract syntax tree (AST) that represents the structure of the AsciiDoc
         | 
| 7 | 
            +
            # document from which the Document object was parsed.
         | 
| 6 8 | 
             
            #
         | 
| 7 | 
            -
            #  | 
| 8 | 
            -
            # | 
| 9 | 
            -
            # | 
| 10 | 
            -
            #  | 
| 11 | 
            -
            #  | 
| 12 | 
            -
            # first_section.title - title of first section in document, if present
         | 
| 13 | 
            -
            # header.title - title of section level 0
         | 
| 9 | 
            +
            # Although the constructor can be used to create an empty document object, more
         | 
| 10 | 
            +
            # commonly, you'll load the document object from AsciiDoc source using the
         | 
| 11 | 
            +
            # primary API methods, {Asciidoctor.load} or {Asciidoctor.load_file}. When
         | 
| 12 | 
            +
            # using one of these APIs, you almost always want to set the safe mode to
         | 
| 13 | 
            +
            # :safe (or :unsafe) to enable all of Asciidoctor's features.
         | 
| 14 14 | 
             
            #
         | 
| 15 | 
            -
            #  | 
| 15 | 
            +
            #   Asciidoctor.load '= Hello, AsciiDoc!', safe: :safe
         | 
| 16 | 
            +
            #   # => Asciidoctor::Document { doctype: "article", doctitle: "Hello, Asciidoc!", blocks: 0 }
         | 
| 16 17 | 
             
            #
         | 
| 17 | 
            -
            #  | 
| 18 | 
            -
            #  | 
| 19 | 
            -
            #  | 
| 18 | 
            +
            # Instances of this class can be used to extract information from the document
         | 
| 19 | 
            +
            # or alter its structure. As such, the Document object is most often used in
         | 
| 20 | 
            +
            # extensions and by integrations.
         | 
| 21 | 
            +
            #
         | 
| 22 | 
            +
            # The most basic usage of the Document object is to retrieve the document's
         | 
| 23 | 
            +
            # title.
         | 
| 24 | 
            +
            #
         | 
| 25 | 
            +
            #   source = '= Document Title'
         | 
| 26 | 
            +
            #   document = Asciidoctor.load source, safe: :safe
         | 
| 27 | 
            +
            #   document.doctitle
         | 
| 28 | 
            +
            #   # => 'Document Title'
         | 
| 29 | 
            +
            #
         | 
| 30 | 
            +
            # If the document has no title, the {Document#doctitle} method returns the
         | 
| 31 | 
            +
            # title of the first section. If that check falls through, you can have the
         | 
| 32 | 
            +
            # method return a fallback value (the value of the untitled-label attribute).
         | 
| 33 | 
            +
            #
         | 
| 34 | 
            +
            #   Asciidoctor.load('no doctitle', safe: :safe).doctitle use_fallback: true
         | 
| 35 | 
            +
            #   # => "Untitled"
         | 
| 36 | 
            +
            #
         | 
| 37 | 
            +
            # You can also use the Document object to access document attributes defined in
         | 
| 38 | 
            +
            # the header, such as the author and doctype.
         | 
| 39 | 
            +
            #
         | 
| 40 | 
            +
            #   source = '= Document Title
         | 
| 41 | 
            +
            #   Author Name
         | 
| 42 | 
            +
            #   :doctype: book'
         | 
| 43 | 
            +
            #   document = Asciidoctor.load source, safe: :safe
         | 
| 44 | 
            +
            #   document.author
         | 
| 45 | 
            +
            #   # => 'Author Name'
         | 
| 46 | 
            +
            #   document.doctype
         | 
| 47 | 
            +
            #   # => 'book'
         | 
| 48 | 
            +
            #
         | 
| 49 | 
            +
            # You can retrieve arbitrary document attributes defined in the header using
         | 
| 50 | 
            +
            # {Document#attr} or check for the existence of one using {Document#attr?}:
         | 
| 51 | 
            +
            #
         | 
| 52 | 
            +
            #   source = '= Asciidoctor
         | 
| 53 | 
            +
            #   :uri-project: https://asciidoctor.org'
         | 
| 54 | 
            +
            #   document = Asciidoctor.load source, safe: :safe
         | 
| 55 | 
            +
            #   document.attr 'uri-project'
         | 
| 56 | 
            +
            #   # => 'https://asciidoctor.org'
         | 
| 57 | 
            +
            #   document.attr? 'icons'
         | 
| 58 | 
            +
            #   # => false
         | 
| 59 | 
            +
            #
         | 
| 60 | 
            +
            # Starting at the Document object, you can begin walking the document tree using
         | 
| 61 | 
            +
            # the {Document#blocks} method:
         | 
| 62 | 
            +
            #
         | 
| 63 | 
            +
            #   source = 'paragraph contents
         | 
| 64 | 
            +
            #
         | 
| 65 | 
            +
            #   [sidebar]
         | 
| 66 | 
            +
            #   sidebar contents'
         | 
| 67 | 
            +
            #   doc = Asciidoctor.load source, safe: :safe
         | 
| 68 | 
            +
            #   doc.blocks.map {|block| block.context }
         | 
| 69 | 
            +
            #   # => [:paragraph, :sidebar]
         | 
| 70 | 
            +
            #
         | 
| 71 | 
            +
            # You can discover block nodes at any depth in the tree using the
         | 
| 72 | 
            +
            # {AbstractBlock#find_by} method.
         | 
| 73 | 
            +
            #
         | 
| 74 | 
            +
            #   source = '****
         | 
| 75 | 
            +
            #   paragraph in sidebar
         | 
| 76 | 
            +
            #   ****'
         | 
| 77 | 
            +
            #   doc = Asciidoctor.load source, safe: :safe
         | 
| 78 | 
            +
            #   doc.find_by(context: :paragraph).map {|block| block.context }
         | 
| 79 | 
            +
            #   # => [:paragraph]
         | 
| 80 | 
            +
            #
         | 
| 81 | 
            +
            # Loading a document object is the first step in the conversion process. You
         | 
| 82 | 
            +
            # can take the process to completion by calling the {Document#convert} method.
         | 
| 20 83 | 
             
            class Document < AbstractBlock
         | 
| 21 84 |  | 
| 22 85 | 
             
              Footnote = ::Struct.new :index, :id, :text
         | 
| @@ -134,9 +197,6 @@ class Document < AbstractBlock | |
| 134 197 | 
             
              # Public: Get the Hash of document counters
         | 
| 135 198 | 
             
              attr_reader :counters
         | 
| 136 199 |  | 
| 137 | 
            -
              # Public: Get the Hash of callouts
         | 
| 138 | 
            -
              attr_reader :callouts
         | 
| 139 | 
            -
             | 
| 140 200 | 
             
              # Public: Get the level-0 Section
         | 
| 141 201 | 
             
              attr_reader :header
         | 
| 142 202 |  | 
| @@ -158,6 +218,9 @@ class Document < AbstractBlock | |
| 158 218 | 
             
              # Public: Get the Reader associated with this document
         | 
| 159 219 | 
             
              attr_reader :reader
         | 
| 160 220 |  | 
| 221 | 
            +
              # Public: Get/Set the PathResolver instance used to resolve paths in this Document.
         | 
| 222 | 
            +
              attr_reader :path_resolver
         | 
| 223 | 
            +
             | 
| 161 224 | 
             
              # Public: Get the Converter associated with this document
         | 
| 162 225 | 
             
              attr_reader :converter
         | 
| 163 226 |  | 
| @@ -183,11 +246,11 @@ class Document < AbstractBlock | |
| 183 246 | 
             
                if (parent_doc = options.delete :parent)
         | 
| 184 247 | 
             
                  @parent_document = parent_doc
         | 
| 185 248 | 
             
                  options[:base_dir] ||= parent_doc.base_dir
         | 
| 249 | 
            +
                  options[:catalog_assets] = true if parent_doc.options[:catalog_assets]
         | 
| 186 250 | 
             
                  @catalog = parent_doc.catalog.inject({}) do |accum, (key, table)|
         | 
| 187 251 | 
             
                    accum[key] = (key == :footnotes ? [] : table)
         | 
| 188 252 | 
             
                    accum
         | 
| 189 253 | 
             
                  end
         | 
| 190 | 
            -
                  @callouts = parent_doc.callouts
         | 
| 191 254 | 
             
                  # QUESTION should we support setting attribute in parent document from nested document?
         | 
| 192 255 | 
             
                  # NOTE we must dup or else all the assignments to the overrides clobbers the real attributes
         | 
| 193 256 | 
             
                  @attribute_overrides = attr_overrides = parent_doc.attributes.dup
         | 
| @@ -199,6 +262,8 @@ class Document < AbstractBlock | |
| 199 262 | 
             
                  @safe = parent_doc.safe
         | 
| 200 263 | 
             
                  @attributes['compat-mode'] = '' if (@compat_mode = parent_doc.compat_mode)
         | 
| 201 264 | 
             
                  @sourcemap = parent_doc.sourcemap
         | 
| 265 | 
            +
                  @timings = nil
         | 
| 266 | 
            +
                  @path_resolver = parent_doc.path_resolver
         | 
| 202 267 | 
             
                  @converter = parent_doc.converter
         | 
| 203 268 | 
             
                  initialize_extensions = false
         | 
| 204 269 | 
             
                  @extensions = parent_doc.extensions
         | 
| @@ -211,25 +276,33 @@ class Document < AbstractBlock | |
| 211 276 | 
             
                    :links => [],
         | 
| 212 277 | 
             
                    :images => [],
         | 
| 213 278 | 
             
                    :indexterms => [],
         | 
| 214 | 
            -
                    : | 
| 279 | 
            +
                    :callouts => Callouts.new,
         | 
| 280 | 
            +
                    :includes => {},
         | 
| 215 281 | 
             
                  }
         | 
| 216 | 
            -
                  @callouts = Callouts.new
         | 
| 217 282 | 
             
                  # copy attributes map and normalize keys
         | 
| 218 283 | 
             
                  # attribute overrides are attributes that can only be set from the commandline
         | 
| 219 284 | 
             
                  # a direct assignment effectively makes the attribute a constant
         | 
| 220 285 | 
             
                  # a nil value or name with leading or trailing ! will result in the attribute being unassigned
         | 
| 221 | 
            -
                  attr_overrides = {}
         | 
| 222 | 
            -
                  (options[:attributes] || {}).each do |key,  | 
| 223 | 
            -
                    if key. | 
| 224 | 
            -
                      key  | 
| 225 | 
            -
             | 
| 286 | 
            +
                  @attribute_overrides = attr_overrides = {}
         | 
| 287 | 
            +
                  (options[:attributes] || {}).each do |key, val|
         | 
| 288 | 
            +
                    if key.end_with? '@'
         | 
| 289 | 
            +
                      if key.start_with? '!'
         | 
| 290 | 
            +
                        key, val = (key.slice 1, key.length), false
         | 
| 291 | 
            +
                      elsif key.end_with? '!@'
         | 
| 292 | 
            +
                        key, val = (key.slice 0, key.length - 2), false
         | 
| 293 | 
            +
                      else
         | 
| 294 | 
            +
                        key, val = key.chop, %(#{val}@)
         | 
| 295 | 
            +
                      end
         | 
| 296 | 
            +
                    elsif key.start_with? '!'
         | 
| 297 | 
            +
                      key, val = (key.slice 1, key.length), val == '@' ? false : nil
         | 
| 226 298 | 
             
                    elsif key.end_with? '!'
         | 
| 227 | 
            -
                      key = key.chop
         | 
| 228 | 
            -
                      value = nil
         | 
| 299 | 
            +
                      key, val = key.chop, val == '@' ? false : nil
         | 
| 229 300 | 
             
                    end
         | 
| 230 | 
            -
                    attr_overrides[key.downcase] =  | 
| 301 | 
            +
                    attr_overrides[key.downcase] = val
         | 
| 302 | 
            +
                  end
         | 
| 303 | 
            +
                  if (to_file = options[:to_file])
         | 
| 304 | 
            +
                    attr_overrides['outfilesuffix'] = ::File.extname to_file
         | 
| 231 305 | 
             
                  end
         | 
| 232 | 
            -
                  @attribute_overrides = attr_overrides
         | 
| 233 306 | 
             
                  # safely resolve the safe mode from const, int or string
         | 
| 234 307 | 
             
                  if !(safe_mode = options[:safe])
         | 
| 235 308 | 
             
                    @safe = SafeMode::SECURE
         | 
| @@ -246,6 +319,8 @@ class Document < AbstractBlock | |
| 246 319 | 
             
                  end
         | 
| 247 320 | 
             
                  @compat_mode = attr_overrides.key? 'compat-mode'
         | 
| 248 321 | 
             
                  @sourcemap = options[:sourcemap]
         | 
| 322 | 
            +
                  @timings = options.delete :timings
         | 
| 323 | 
            +
                  @path_resolver = PathResolver.new
         | 
| 249 324 | 
             
                  @converter = nil
         | 
| 250 325 | 
             
                  initialize_extensions = defined? ::Asciidoctor::Extensions
         | 
| 251 326 | 
             
                  @extensions = nil # initialize furthur down
         | 
| @@ -292,9 +367,8 @@ class Document < AbstractBlock | |
| 292 367 | 
             
                attrs['table-caption'] = 'Table'
         | 
| 293 368 | 
             
                attrs['toc-title'] = 'Table of Contents'
         | 
| 294 369 | 
             
                #attrs['preface-title'] = 'Preface'
         | 
| 295 | 
            -
                attrs['manname-title'] = 'NAME'
         | 
| 296 370 | 
             
                attrs['section-refsig'] = 'Section'
         | 
| 297 | 
            -
                 | 
| 371 | 
            +
                attrs['part-refsig'] = 'Part'
         | 
| 298 372 | 
             
                attrs['chapter-refsig'] = 'Chapter'
         | 
| 299 373 | 
             
                attrs['appendix-caption'] = attrs['appendix-refsig'] = 'Appendix'
         | 
| 300 374 | 
             
                attrs['untitled-label'] = 'Untitled'
         | 
| @@ -327,7 +401,7 @@ class Document < AbstractBlock | |
| 327 401 | 
             
                elsif attr_overrides['docdir']
         | 
| 328 402 | 
             
                  @base_dir = attr_overrides['docdir']
         | 
| 329 403 | 
             
                else
         | 
| 330 | 
            -
                  #warn ' | 
| 404 | 
            +
                  #logger.warn 'setting base_dir is recommended when working with string documents' unless nested?
         | 
| 331 405 | 
             
                  @base_dir = attr_overrides['docdir'] = ::Dir.pwd
         | 
| 332 406 | 
             
                end
         | 
| 333 407 |  | 
| @@ -354,10 +428,8 @@ class Document < AbstractBlock | |
| 354 428 | 
             
                  if @safe >= SafeMode::SECURE
         | 
| 355 429 | 
             
                    attr_overrides['max-attribute-value-size'] = 4096 unless attr_overrides.key? 'max-attribute-value-size'
         | 
| 356 430 | 
             
                    # assign linkcss (preventing css embedding) unless explicitly disabled from the commandline or API
         | 
| 357 | 
            -
                    #  | 
| 358 | 
            -
                     | 
| 359 | 
            -
                      attr_overrides['linkcss'] = ''
         | 
| 360 | 
            -
                    end
         | 
| 431 | 
            +
                    #attr_overrides['linkcss'] = (attr_overrides.fetch 'linkcss', '') || nil
         | 
| 432 | 
            +
                    attr_overrides['linkcss'] = '' unless attr_overrides.key? 'linkcss'
         | 
| 361 433 | 
             
                    # restrict document from enabling icons
         | 
| 362 434 | 
             
                    attr_overrides['icons'] ||= nil
         | 
| 363 435 | 
             
                  end
         | 
| @@ -367,18 +439,16 @@ class Document < AbstractBlock | |
| 367 439 | 
             
                @max_attribute_value_size = (size = (attr_overrides['max-attribute-value-size'] ||= nil)) ? size.to_i.abs : nil
         | 
| 368 440 |  | 
| 369 441 | 
             
                attr_overrides.delete_if do |key, val|
         | 
| 370 | 
            -
                   | 
| 371 | 
            -
             | 
| 372 | 
            -
                  if val.nil?
         | 
| 373 | 
            -
                    attrs.delete(key)
         | 
| 374 | 
            -
                  else
         | 
| 375 | 
            -
                    # a value ending in @ indicates this attribute does not override
         | 
| 376 | 
            -
                    # an attribute with the same key in the document souce
         | 
| 442 | 
            +
                  if val
         | 
| 443 | 
            +
                    # a value ending in @ allows document to override value
         | 
| 377 444 | 
             
                    if ::String === val && (val.end_with? '@')
         | 
| 378 | 
            -
                      val = val.chop
         | 
| 379 | 
            -
                      verdict = true
         | 
| 445 | 
            +
                      val, verdict = val.chop, true
         | 
| 380 446 | 
             
                    end
         | 
| 381 447 | 
             
                    attrs[key] = val
         | 
| 448 | 
            +
                  else
         | 
| 449 | 
            +
                    # a nil or false value both unset the attribute; only a nil value locks it
         | 
| 450 | 
            +
                    attrs.delete key
         | 
| 451 | 
            +
                    verdict = val == false
         | 
| 382 452 | 
             
                  end
         | 
| 383 453 | 
             
                  verdict
         | 
| 384 454 | 
             
                end
         | 
| @@ -393,6 +463,7 @@ class Document < AbstractBlock | |
| 393 463 | 
             
                  # don't need to do the extra processing within our own document
         | 
| 394 464 | 
             
                  # FIXME line info isn't reported correctly within include files in nested document
         | 
| 395 465 | 
             
                  @reader = Reader.new data, options[:cursor]
         | 
| 466 | 
            +
                  @source_location = @reader.cursor if @sourcemap
         | 
| 396 467 |  | 
| 397 468 | 
             
                  # Now parse the lines in the reader into blocks
         | 
| 398 469 | 
             
                  # Eagerly parse (for now) since a subdocument is not a publicly accessible object
         | 
| @@ -441,24 +512,24 @@ class Document < AbstractBlock | |
| 441 512 |  | 
| 442 513 | 
             
                  # fallback directories
         | 
| 443 514 | 
             
                  attrs['stylesdir'] ||= '.'
         | 
| 444 | 
            -
                  attrs['iconsdir'] ||=  | 
| 515 | 
            +
                  attrs['iconsdir'] ||= %(#{attrs.fetch 'imagesdir', './images'}/icons)
         | 
| 445 516 |  | 
| 446 517 | 
             
                  if initialize_extensions
         | 
| 447 518 | 
             
                    if (ext_registry = options[:extension_registry])
         | 
| 448 | 
            -
                      # QUESTION should we warn the value type of  | 
| 449 | 
            -
                       | 
| 519 | 
            +
                      # QUESTION should we warn if the value type of this option is not a registry
         | 
| 520 | 
            +
                      if Extensions::Registry === ext_registry || (::RUBY_ENGINE_JRUBY &&
         | 
| 450 521 | 
             
                          ::AsciidoctorJ::Extensions::ExtensionRegistry === ext_registry)
         | 
| 451 | 
            -
                         | 
| 522 | 
            +
                        @extensions = ext_registry.activate self
         | 
| 452 523 | 
             
                      end
         | 
| 453 524 | 
             
                    elsif ::Proc === (ext_block = options[:extensions])
         | 
| 454 | 
            -
                       | 
| 455 | 
            -
                     | 
| 456 | 
            -
                       | 
| 525 | 
            +
                      @extensions = Extensions.create(&ext_block).activate self
         | 
| 526 | 
            +
                    elsif !Extensions.groups.empty?
         | 
| 527 | 
            +
                      @extensions = Extensions::Registry.new.activate self
         | 
| 457 528 | 
             
                    end
         | 
| 458 | 
            -
                    @extensions = ext_registry.activate self
         | 
| 459 529 | 
             
                  end
         | 
| 460 530 |  | 
| 461 531 | 
             
                  @reader = PreprocessorReader.new self, data, (Reader::Cursor.new attrs['docfile'], @base_dir), :normalize => true
         | 
| 532 | 
            +
                  @source_location = @reader.cursor if @sourcemap
         | 
| 462 533 | 
             
                end
         | 
| 463 534 | 
             
              end
         | 
| 464 535 |  | 
| @@ -481,6 +552,7 @@ class Document < AbstractBlock | |
| 481 552 | 
             
                  # create reader if data is provided (used when data is not known at the time the Document object is created)
         | 
| 482 553 | 
             
                  if data
         | 
| 483 554 | 
             
                    @reader = PreprocessorReader.new doc, data, (Reader::Cursor.new @attributes['docfile'], @base_dir), :normalize => true
         | 
| 555 | 
            +
                    @source_location = @reader.cursor if @sourcemap
         | 
| 484 556 | 
             
                  end
         | 
| 485 557 |  | 
| 486 558 | 
             
                  if (exts = @parent_document ? nil : @extensions) && exts.preprocessors?
         | 
| @@ -583,6 +655,10 @@ class Document < AbstractBlock | |
| 583 655 | 
             
                @catalog[:footnotes]
         | 
| 584 656 | 
             
              end
         | 
| 585 657 |  | 
| 658 | 
            +
              def callouts
         | 
| 659 | 
            +
                @catalog[:callouts]
         | 
| 660 | 
            +
              end
         | 
| 661 | 
            +
             | 
| 586 662 | 
             
              def nested?
         | 
| 587 663 | 
             
                @parent_document ? true : false
         | 
| 588 664 | 
             
              end
         | 
| @@ -609,14 +685,24 @@ class Document < AbstractBlock | |
| 609 685 | 
             
                @attributes['basebackend'] == base
         | 
| 610 686 | 
             
              end
         | 
| 611 687 |  | 
| 612 | 
            -
              #  | 
| 688 | 
            +
              # Public: Return the doctitle as a String
         | 
| 689 | 
            +
              #
         | 
| 690 | 
            +
              # Returns the resolved doctitle as a [String] or nil if a doctitle cannot be resolved
         | 
| 613 691 | 
             
              def title
         | 
| 614 | 
            -
                 | 
| 692 | 
            +
                doctitle
         | 
| 615 693 | 
             
              end
         | 
| 616 694 |  | 
| 695 | 
            +
              # Public: Set the title on the document header
         | 
| 696 | 
            +
              #
         | 
| 697 | 
            +
              # Set the title of the document header to the specified value. If the header
         | 
| 698 | 
            +
              # does not exist, it is first created.
         | 
| 699 | 
            +
              #
         | 
| 700 | 
            +
              # title - the String title to assign as the title of the document header
         | 
| 701 | 
            +
              #
         | 
| 702 | 
            +
              # Returns the new [String] title assigned to the document header
         | 
| 617 703 | 
             
              def title= title
         | 
| 618 704 | 
             
                unless (sect = @header)
         | 
| 619 | 
            -
                  (sect = (@header = Section.new self, 0 | 
| 705 | 
            +
                  (sect = (@header = Section.new self, 0)).sectname = 'header'
         | 
| 620 706 | 
             
                end
         | 
| 621 707 | 
             
                sect.title = title
         | 
| 622 708 | 
             
              end
         | 
| @@ -641,14 +727,12 @@ class Document < AbstractBlock | |
| 641 727 | 
             
              # Returns the resolved title as a [Title] if the :partition option is passed or a [String] if not
         | 
| 642 728 | 
             
              # or nil if no value can be resolved.
         | 
| 643 729 | 
             
              def doctitle opts = {}
         | 
| 644 | 
            -
                 | 
| 645 | 
            -
                   | 
| 646 | 
            -
             | 
| 647 | 
            -
                  val =  | 
| 648 | 
            -
             | 
| 649 | 
            -
                   | 
| 650 | 
            -
                else
         | 
| 651 | 
            -
                  return
         | 
| 730 | 
            +
                unless (val = @attributes['title'])
         | 
| 731 | 
            +
                  if (sect = first_section)
         | 
| 732 | 
            +
                    val = sect.title
         | 
| 733 | 
            +
                  elsif !(opts[:use_fallback] && (val = @attributes['untitled-label']))
         | 
| 734 | 
            +
                    return
         | 
| 735 | 
            +
                  end
         | 
| 652 736 | 
             
                end
         | 
| 653 737 |  | 
| 654 738 | 
             
                if (separator = opts[:partition])
         | 
| @@ -704,7 +788,7 @@ class Document < AbstractBlock | |
| 704 788 | 
             
              #
         | 
| 705 789 | 
             
              # Returns The parent Block
         | 
| 706 790 | 
             
              def << block
         | 
| 707 | 
            -
                 | 
| 791 | 
            +
                assign_numeral block if block.context == :section
         | 
| 708 792 | 
             
                super
         | 
| 709 793 | 
             
              end
         | 
| 710 794 |  | 
| @@ -800,9 +884,8 @@ class Document < AbstractBlock | |
| 800 884 |  | 
| 801 885 | 
             
              # Internal: Restore the attributes to the previously saved state (attributes in header)
         | 
| 802 886 | 
             
              def restore_attributes
         | 
| 803 | 
            -
                @callouts.rewind unless @parent_document
         | 
| 804 | 
            -
                 | 
| 805 | 
            -
                @attributes = @header_attributes
         | 
| 887 | 
            +
                @catalog[:callouts].rewind unless @parent_document
         | 
| 888 | 
            +
                @attributes.replace @header_attributes
         | 
| 806 889 | 
             
              end
         | 
| 807 890 |  | 
| 808 891 | 
             
              # Internal: Delete any attributes stored for playback
         | 
| @@ -914,7 +997,7 @@ class Document < AbstractBlock | |
| 914 997 | 
             
                  current_backend, current_basebackend, current_doctype = @backend, (attrs = @attributes)['basebackend'], @doctype
         | 
| 915 998 | 
             
                  if new_backend.start_with? 'xhtml'
         | 
| 916 999 | 
             
                    attrs['htmlsyntax'] = 'xml'
         | 
| 917 | 
            -
                    new_backend = new_backend | 
| 1000 | 
            +
                    new_backend = new_backend.slice 1, new_backend.length
         | 
| 918 1001 | 
             
                  elsif new_backend.start_with? 'html'
         | 
| 919 1002 | 
             
                    attrs['htmlsyntax'] = 'html' unless attrs['htmlsyntax'] == 'xml'
         | 
| 920 1003 | 
             
                  end
         | 
| @@ -941,7 +1024,7 @@ class Document < AbstractBlock | |
| 941 1024 | 
             
                  elsif @converter
         | 
| 942 1025 | 
             
                    new_basebackend = new_backend.sub TrailingDigitsRx, ''
         | 
| 943 1026 | 
             
                    if (new_outfilesuffix = DEFAULT_EXTENSIONS[new_basebackend])
         | 
| 944 | 
            -
                      new_filetype = new_outfilesuffix | 
| 1027 | 
            +
                      new_filetype = new_outfilesuffix.slice 1, new_outfilesuffix.length
         | 
| 945 1028 | 
             
                    else
         | 
| 946 1029 | 
             
                      new_outfilesuffix, new_basebackend, new_filetype = '.html', 'html', 'html'
         | 
| 947 1030 | 
             
                    end
         | 
| @@ -1006,12 +1089,13 @@ class Document < AbstractBlock | |
| 1006 1089 | 
             
              def create_converter
         | 
| 1007 1090 | 
             
                converter_opts = {}
         | 
| 1008 1091 | 
             
                converter_opts[:htmlsyntax] = @attributes['htmlsyntax']
         | 
| 1009 | 
            -
                 | 
| 1010 | 
            -
                   | 
| 1092 | 
            +
                if (template_dir = @options[:template_dir])
         | 
| 1093 | 
            +
                  template_dirs = [template_dir]
         | 
| 1011 1094 | 
             
                elsif (template_dirs = @options[:template_dirs])
         | 
| 1012 | 
            -
                   | 
| 1095 | 
            +
                  template_dirs = Array template_dirs
         | 
| 1013 1096 | 
             
                end
         | 
| 1014 1097 | 
             
                if template_dirs
         | 
| 1098 | 
            +
                  converter_opts[:template_dirs] = template_dirs
         | 
| 1015 1099 | 
             
                  converter_opts[:template_cache] = @options.fetch :template_cache, true
         | 
| 1016 1100 | 
             
                  converter_opts[:template_engine] = @options[:template_engine]
         | 
| 1017 1101 | 
             
                  converter_opts[:template_engine_options] = @options[:template_engine_options]
         | 
| @@ -1033,9 +1117,8 @@ class Document < AbstractBlock | |
| 1033 1117 | 
             
              # loaded by the Converter. If a :template_dir is not specified,
         | 
| 1034 1118 | 
             
              # or a template is missing, the converter will fall back to
         | 
| 1035 1119 | 
             
              # using the appropriate built-in template.
         | 
| 1036 | 
            -
              #--
         | 
| 1037 | 
            -
              # QUESTION should we dup @header_attributes before converting?
         | 
| 1038 1120 | 
             
              def convert opts = {}
         | 
| 1121 | 
            +
                @timings.start :convert if @timings
         | 
| 1039 1122 | 
             
                parse unless @parsed
         | 
| 1040 1123 | 
             
                unless @safe >= SafeMode::SERVER || opts.empty?
         | 
| 1041 1124 | 
             
                  # QUESTION should we store these on the Document object?
         | 
| @@ -1046,9 +1129,9 @@ class Document < AbstractBlock | |
| 1046 1129 | 
             
                # QUESTION should we add extensions that execute before conversion begins?
         | 
| 1047 1130 |  | 
| 1048 1131 | 
             
                if doctype == 'inline'
         | 
| 1049 | 
            -
                  if (block = @blocks[0])
         | 
| 1132 | 
            +
                  if (block = @blocks[0] || @header)
         | 
| 1050 1133 | 
             
                    if block.content_model == :compound || block.content_model == :empty
         | 
| 1051 | 
            -
                      warn  | 
| 1134 | 
            +
                      logger.warn 'no inline candidate; use the inline doctype to convert a single paragragh, verbatim, or raw block'
         | 
| 1052 1135 | 
             
                    else
         | 
| 1053 1136 | 
             
                      output = block.content
         | 
| 1054 1137 | 
             
                    end
         | 
| @@ -1066,6 +1149,7 @@ class Document < AbstractBlock | |
| 1066 1149 | 
             
                  end
         | 
| 1067 1150 | 
             
                end
         | 
| 1068 1151 |  | 
| 1152 | 
            +
                @timings.record :convert if @timings
         | 
| 1069 1153 | 
             
                output
         | 
| 1070 1154 | 
             
              end
         | 
| 1071 1155 |  | 
| @@ -1076,7 +1160,10 @@ class Document < AbstractBlock | |
| 1076 1160 | 
             
              #
         | 
| 1077 1161 | 
             
              # If the converter responds to :write, delegate the work of writing the file
         | 
| 1078 1162 | 
             
              # to that method. Otherwise, write the output the specified file.
         | 
| 1163 | 
            +
              #
         | 
| 1164 | 
            +
              # Returns nothing
         | 
| 1079 1165 | 
             
              def write output, target
         | 
| 1166 | 
            +
                @timings.start :write if @timings
         | 
| 1080 1167 | 
             
                if Writer === @converter
         | 
| 1081 1168 | 
             
                  @converter.write output, target
         | 
| 1082 1169 | 
             
                else
         | 
| @@ -1089,8 +1176,12 @@ class Document < AbstractBlock | |
| 1089 1176 | 
             
                  else
         | 
| 1090 1177 | 
             
                    ::IO.write target, output
         | 
| 1091 1178 | 
             
                  end
         | 
| 1092 | 
            -
                   | 
| 1179 | 
            +
                  if @backend == 'manpage' && ::String === target && (@converter.respond_to? :write_alternate_pages)
         | 
| 1180 | 
            +
                    @converter.write_alternate_pages @attributes['mannames'], @attributes['manvolnum'], target
         | 
| 1181 | 
            +
                  end
         | 
| 1093 1182 | 
             
                end
         | 
| 1183 | 
            +
                @timings.record :write if @timings
         | 
| 1184 | 
            +
                nil
         | 
| 1094 1185 | 
             
              end
         | 
| 1095 1186 |  | 
| 1096 1187 | 
             
            =begin
         |