asciidoctor 1.5.4 → 1.5.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of asciidoctor might be problematic. Click here for more details.

Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +72 -5
  3. data/CONTRIBUTING.adoc +3 -3
  4. data/Gemfile +23 -0
  5. data/README-fr.adoc +416 -0
  6. data/README-jp.adoc +395 -0
  7. data/README-zh_CN.adoc +414 -0
  8. data/README.adoc +134 -72
  9. data/asciidoctor.gemspec +49 -0
  10. data/data/locale/attributes.adoc +470 -0
  11. data/data/stylesheets/asciidoctor-default.css +6 -5
  12. data/lib/asciidoctor.rb +22 -19
  13. data/lib/asciidoctor/abstract_block.rb +20 -10
  14. data/lib/asciidoctor/abstract_node.rb +3 -14
  15. data/lib/asciidoctor/cli/invoker.rb +5 -4
  16. data/lib/asciidoctor/cli/options.rb +1 -1
  17. data/lib/asciidoctor/converter/docbook5.rb +1 -1
  18. data/lib/asciidoctor/converter/factory.rb +1 -5
  19. data/lib/asciidoctor/converter/html5.rb +36 -31
  20. data/lib/asciidoctor/converter/manpage.rb +14 -9
  21. data/lib/asciidoctor/converter/template.rb +8 -4
  22. data/lib/asciidoctor/core_ext.rb +7 -6
  23. data/lib/asciidoctor/core_ext/{string → 1.8.7/string}/chr.rb +1 -1
  24. data/lib/asciidoctor/core_ext/1.8.7/string/limit.rb +28 -0
  25. data/lib/asciidoctor/core_ext/{symbol → 1.8.7/symbol}/length.rb +1 -1
  26. data/lib/asciidoctor/core_ext/nil_or_empty.rb +23 -0
  27. data/lib/asciidoctor/core_ext/string/limit.rb +10 -0
  28. data/lib/asciidoctor/document.rb +33 -26
  29. data/lib/asciidoctor/extensions.rb +16 -16
  30. data/lib/asciidoctor/helpers.rb +1 -1
  31. data/lib/asciidoctor/list.rb +3 -0
  32. data/lib/asciidoctor/parser.rb +47 -43
  33. data/lib/asciidoctor/path_resolver.rb +3 -1
  34. data/lib/asciidoctor/reader.rb +15 -14
  35. data/lib/asciidoctor/section.rb +2 -2
  36. data/lib/asciidoctor/stylesheets.rb +2 -1
  37. data/lib/asciidoctor/substitutors.rb +44 -46
  38. data/lib/asciidoctor/table.rb +41 -38
  39. data/lib/asciidoctor/version.rb +1 -1
  40. data/man/asciidoctor.1 +11 -4
  41. data/man/asciidoctor.adoc +7 -1
  42. data/test/attributes_test.rb +52 -0
  43. data/test/blocks_test.rb +8 -8
  44. data/test/document_test.rb +13 -1
  45. data/test/extensions_test.rb +38 -0
  46. data/test/invoker_test.rb +15 -0
  47. data/test/lists_test.rb +78 -53
  48. data/test/manpage_test.rb +15 -0
  49. data/test/paths_test.rb +3 -0
  50. data/test/reader_test.rb +2 -2
  51. data/test/sections_test.rb +10 -0
  52. data/test/substitutions_test.rb +12 -6
  53. data/test/tables_test.rb +76 -2
  54. metadata +16 -45
  55. data/lib/asciidoctor/core_ext/object/nil_or_empty.rb +0 -23
  56. data/test/fixtures/asciidoc_index.txt +0 -521
  57. data/test/fixtures/basic-docinfo-footer.html +0 -6
  58. data/test/fixtures/basic-docinfo-footer.xml +0 -8
  59. data/test/fixtures/basic-docinfo.html +0 -1
  60. data/test/fixtures/basic-docinfo.xml +0 -4
  61. data/test/fixtures/basic.asciidoc +0 -5
  62. data/test/fixtures/chapter-a.adoc +0 -3
  63. data/test/fixtures/child-include.adoc +0 -5
  64. data/test/fixtures/circle.svg +0 -8
  65. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
  66. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
  67. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
  68. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
  69. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
  70. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
  71. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
  72. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
  73. data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
  74. data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
  75. data/test/fixtures/docinfo-footer.html +0 -1
  76. data/test/fixtures/docinfo-footer.xml +0 -9
  77. data/test/fixtures/docinfo.html +0 -1
  78. data/test/fixtures/docinfo.xml +0 -3
  79. data/test/fixtures/dot.gif +0 -0
  80. data/test/fixtures/encoding.asciidoc +0 -13
  81. data/test/fixtures/grandchild-include.adoc +0 -3
  82. data/test/fixtures/hello-asciidoctor.pdf +0 -0
  83. data/test/fixtures/include-file.asciidoc +0 -24
  84. data/test/fixtures/include-file.xml +0 -5
  85. data/test/fixtures/master.adoc +0 -5
  86. data/test/fixtures/parent-include-restricted.adoc +0 -5
  87. data/test/fixtures/parent-include.adoc +0 -5
  88. data/test/fixtures/sample.asciidoc +0 -26
  89. data/test/fixtures/stylesheets/custom.css +0 -3
  90. data/test/fixtures/subs-docinfo.html +0 -2
  91. data/test/fixtures/subs.adoc +0 -7
  92. data/test/fixtures/tip.gif +0 -0
  93. data/test/test_helper.rb +0 -399
@@ -7,7 +7,6 @@ audio:not([controls]){display:none;height:0}
7
7
  [hidden],template{display:none}
8
8
  script{display:none!important}
9
9
  html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
10
- body{margin:0}
11
10
  a{background:transparent}
12
11
  a:focus{outline:thin dotted}
13
12
  a:active,a:hover{outline:0}
@@ -42,7 +41,7 @@ textarea{overflow:auto;vertical-align:top}
42
41
  table{border-collapse:collapse;border-spacing:0}
43
42
  *,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
44
43
  html,body{font-size:100%}
45
- body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
44
+ body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
46
45
  a:hover{cursor:pointer}
47
46
  img,object,embed{max-width:100%;height:auto}
48
47
  object,embed{height:100%}
@@ -54,7 +53,6 @@ img{-ms-interpolation-mode:bicubic}
54
53
  .text-center{text-align:center!important}
55
54
  .text-justify{text-align:justify!important}
56
55
  .hide{display:none}
57
- body{-webkit-font-smoothing:antialiased}
58
56
  img,object,svg{display:inline-block;vertical-align:middle}
59
57
  textarea{height:auto;min-height:50px}
60
58
  select{width:100%}
@@ -109,13 +107,16 @@ table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:
109
107
  table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
110
108
  table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
111
109
  table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
112
- body{tab-size:4}
113
110
  h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
114
111
  h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
115
112
  .clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
116
113
  .clearfix:after,.float-group:after{clear:both}
117
- *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
114
+ *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
115
+ *:not(pre)>code.nobreak{word-wrap:normal}
116
+ *:not(pre)>code.nowrap{white-space:nowrap}
118
117
  pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
118
+ em em{font-style:normal}
119
+ strong strong{font-weight:400}
119
120
  .keyseq{color:rgba(51,51,51,.8)}
120
121
  kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
121
122
  .keyseq kbd:first-child{margin-left:0}
@@ -13,7 +13,6 @@ if RUBY_ENGINE == 'opal'
13
13
  require 'asciidoctor/opal_ext'
14
14
  else
15
15
  autoload :Base64, 'base64'
16
- autoload :FileUtils, 'fileutils'
17
16
  autoload :OpenURI, 'open-uri'
18
17
  autoload :StringScanner, 'strscan'
19
18
  end
@@ -632,7 +631,7 @@ module Asciidoctor
632
631
  InlineSectionAnchorRx = /^(.*?)#{CG_BLANK}+(\\)?\[\[([#{CC_ALPHA}:_][#{CC_WORD}:.-]*)(?:,#{CG_BLANK}*(\S.*?))?\]\]$/
633
632
 
634
633
  # Matches invalid characters in a section id.
635
- InvalidSectionIdCharsRx = /&(?:[a-zA-Z]{2,}|#\d{2,5}|#x[a-fA-F0-9]{2,4});|[^#{CC_WORD}]+?/
634
+ InvalidSectionIdCharsRx = /&(?:[a-zA-Z]{2,}|#\d{2,6}|#x[a-fA-F0-9]{2,5});|[^#{CC_WORD}]+?/
636
635
 
637
636
  # Matches the block style used to designate a section title as a floating title.
638
637
  #
@@ -646,7 +645,9 @@ module Asciidoctor
646
645
  ## Lists
647
646
 
648
647
  # Detects the start of any list item.
649
- AnyListRx = /^(?:<?\d+>#{CG_BLANK}+#{CG_GRAPH}|#{CG_BLANK}*(?:-|(?:\*|\.|\u2022){1,5}|\d+\.|[a-zA-Z]\.|[IVXivx]+\))#{CG_BLANK}+#{CG_GRAPH}|#{CG_BLANK}*.*?(?::{2,4}|;;)(?:#{CG_BLANK}+#{CG_GRAPH}|$))/
648
+ #
649
+ # NOTE we only have to check as far as the blank character because we know it means non-whitespace follows.
650
+ AnyListRx = /^(?:#{CG_BLANK}*(?:-|([*.\u2022])\1{0,4}|\d+\.|[a-zA-Z]\.|[IVXivx]+\))#{CG_BLANK}|#{CG_BLANK}*.*?(?::{2,4}|;;)(?:$|#{CG_BLANK})|<?\d+>#{CG_BLANK})/
650
651
 
651
652
  # Matches an unordered list item (one level for hyphens, up to 5 levels for asterisks).
652
653
  #
@@ -656,6 +657,7 @@ module Asciidoctor
656
657
  # - Foo
657
658
  #
658
659
  # NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
660
+ # NOTE I want to use (-|([*\u2022])\2{0,4}) but breaks the parser since it relies on fixed match positions
659
661
  UnorderedListRx = /^#{CG_BLANK}*(-|\*{1,5}|\u2022{1,5})#{CG_BLANK}+(.*)$/
660
662
 
661
663
  # Matches an ordered list item (explicit numbering or up to 5 consecutive dots).
@@ -684,7 +686,7 @@ module Asciidoctor
684
686
  #:lowergreek => /[a-z]\]/
685
687
  }
686
688
 
687
- # Matches a definition list item.
689
+ # Matches a description list entry.
688
690
  #
689
691
  # Examples
690
692
  #
@@ -693,26 +695,26 @@ module Asciidoctor
693
695
  # foo::::
694
696
  # foo;;
695
697
  #
696
- # # should be followed by a definition, on the same line...
698
+ # # the term can be followed by a description on the same line...
697
699
  #
698
700
  # foo:: That which precedes 'bar' (see also, <<bar>>)
699
701
  #
700
- # # ...or on a separate line
702
+ # # ...or on a separate line (optionally indented)
701
703
  #
702
704
  # foo::
703
705
  # That which precedes 'bar' (see also, <<bar>>)
704
706
  #
705
- # # the term may be an attribute reference
707
+ # # the term or description may be an attribute reference
706
708
  #
707
709
  # {foo_term}:: {foo_def}
708
710
  #
709
711
  # NOTE negative match for comment line is intentional since that isn't handled when looking for next list item
710
- # QUESTION should we check for line comment in regex or when scanning the lines?
712
+ # TODO check for line comment when scanning lines instead of in regex
711
713
  #
712
- DefinitionListRx = /^(?!\/\/)#{CG_BLANK}*(.*?)(:{2,4}|;;)(?:#{CG_BLANK}+(.*))?$/
714
+ DescriptionListRx = /^(?!\/\/)#{CG_BLANK}*(.*?)(:{2,4}|;;)(?:#{CG_BLANK}+(.*))?$/
713
715
 
714
- # Matches a sibling definition list item (which does not include the keyed type).
715
- DefinitionListSiblingRx = {
716
+ # Matches a sibling description list item (which does not include the type in the key).
717
+ DescriptionListSiblingRx = {
716
718
  # (?:.*?[^:])? - a non-capturing group which grabs longest sequence of characters that doesn't end w/ colon
717
719
  '::' => /^(?!\/\/)#{CG_BLANK}*((?:.*[^:])?)(::)(?:#{CG_BLANK}+(.*))?$/,
718
720
  ':::' => /^(?!\/\/)#{CG_BLANK}*((?:.*[^:])?)(:::)(?:#{CG_BLANK}+(.*))?$/,
@@ -727,7 +729,7 @@ module Asciidoctor
727
729
  # <1> Foo
728
730
  #
729
731
  # NOTE we know trailing (.*) will match at least one character because we strip trailing spaces
730
- CalloutListRx = /^<?(\d+)>#{CG_BLANK}+(.*)/
732
+ CalloutListRx = /^<?(\d+)>#{CG_BLANK}+(.*)$/
731
733
 
732
734
  # Matches a callout reference inside literal text.
733
735
  #
@@ -749,7 +751,7 @@ module Asciidoctor
749
751
  ListRxMap = {
750
752
  :ulist => UnorderedListRx,
751
753
  :olist => OrderedListRx,
752
- :dlist => DefinitionListRx,
754
+ :dlist => DescriptionListRx,
753
755
  :colist => CalloutListRx
754
756
  }
755
757
 
@@ -965,12 +967,12 @@ module Asciidoctor
965
967
  ## Layout
966
968
 
967
969
  # Matches a trailing + preceded by at least one space character,
968
- # which forces a hard line break (<br> tag in HTML outputs).
970
+ # which forces a hard line break (<br> tag in HTML output).
969
971
  #
970
972
  # Examples
971
973
  #
972
- # +
973
- # Foo +
974
+ # Humpty Dumpty sat on a wall, +
975
+ # Humpty Dumpty had a great fall.
974
976
  #
975
977
  if RUBY_ENGINE == 'opal'
976
978
  # NOTE JavaScript only treats ^ and $ as line boundaries in multiline regexp; . won't match newlines
@@ -1249,7 +1251,7 @@ module Asciidoctor
1249
1251
  # left double arrow <=
1250
1252
  [/\\?&lt;=/, '&#8656;', :none],
1251
1253
  # restore entities
1252
- [/\\?(&)amp;((?:[a-zA-Z]+|#\d{2,5}|#x[a-fA-F0-9]{2,4});)/, '', :bounding]
1254
+ [/\\?(&)amp;((?:[a-zA-Z]{2,}|#\d{2,6}|#x[a-fA-F0-9]{2,5});)/, '', :bounding]
1253
1255
  ]
1254
1256
 
1255
1257
  class << self
@@ -1308,7 +1310,8 @@ module Asciidoctor
1308
1310
  if ::File === input
1309
1311
  # TODO cli checks if input path can be read and is file, but might want to add check to API
1310
1312
  input_path = ::File.expand_path input.path
1311
- input_mtime = input.mtime
1313
+ # See https://reproducible-builds.org/specs/source-date-epoch/
1314
+ input_mtime = ::ENV['SOURCE_DATE_EPOCH'] ? (::Time.at ::ENV['SOURCE_DATE_EPOCH'].to_i).utc : input.mtime
1312
1315
  lines = input.readlines
1313
1316
  # hold off on setting infile and indir until we get a better sense of their purpose
1314
1317
  attributes['docfile'] = input_path
@@ -1487,7 +1490,7 @@ module Asciidoctor
1487
1490
 
1488
1491
  unless ::File.directory? outdir
1489
1492
  if mkdirs
1490
- ::FileUtils.mkdir_p outdir
1493
+ Helpers.mkdir_p outdir
1491
1494
  else
1492
1495
  # NOTE we intentionally refer to the directory as it was passed to the API
1493
1496
  raise ::IOError, %(target directory does not exist: #{to_dir})
@@ -244,11 +244,10 @@ class AbstractBlock < AbstractNode
244
244
  end
245
245
  =end
246
246
 
247
- # Public: Query for all descendant block nodes in the document tree that
248
- # match the specified Symbol filter_context and, optionally, the style and/or
249
- # role specified in the options Hash. If a block is provided, it's used as an
250
- # additional filter. If no filters are specified, all block nodes in the tree
251
- # are returned.
247
+ # Public: Query for all descendant block-level nodes in the document tree
248
+ # that match the specified selector (context, style, id, and/or role). If a
249
+ # Ruby block is given, it's used as an additional filter. If no selector or
250
+ # Ruby block is supplied, all block-level nodes in the tree are returned.
252
251
  #
253
252
  # Examples
254
253
  #
@@ -262,7 +261,7 @@ class AbstractBlock < AbstractNode
262
261
  # doc.find_by context: :listing, style: 'source'
263
262
  # #=> Asciidoctor::Block@13136720 { context: :listing, content_model: :verbatim, style: "source", lines: 1 }
264
263
  #
265
- # Returns An Array of block nodes that match the given selector or an empty Array if no matches are found
264
+ # Returns An Array of block-level nodes that match the filter or an empty Array if no matches are found
266
265
  #--
267
266
  # TODO support jQuery-style selector (e.g., image.thumb)
268
267
  def find_by selector = {}, &block
@@ -290,8 +289,8 @@ class AbstractBlock < AbstractNode
290
289
  result.concat(@header.find_by selector, &block)
291
290
  end
292
291
 
293
- # yuck, dlist is a special case
294
292
  unless context_selector == :document # optimization
293
+ # yuck, dlist is a special case
295
294
  if @context == :dlist
296
295
  if any_context || context_selector != :section # optimization
297
296
  @blocks.flatten.each do |li|
@@ -356,6 +355,17 @@ class AbstractBlock < AbstractNode
356
355
  nil
357
356
  end
358
357
 
358
+ # Public: Retrieve the list marker keyword for the specified list type.
359
+ #
360
+ # For use in the HTML type attribute.
361
+ #
362
+ # list_type - the type of list; default to the @style if not specified
363
+ #
364
+ # Returns the single-character [String] keyword that represents the marker for the specified list type
365
+ def list_marker_keyword list_type = nil
366
+ ORDERED_LIST_KEYWORDS[list_type || @style]
367
+ end
368
+
359
369
  # Internal: Assign the next index (0-based) to this section
360
370
  #
361
371
  # Assign the next index of this section within the parent
@@ -369,10 +379,10 @@ class AbstractBlock < AbstractNode
369
379
  if section.sectname == 'appendix'
370
380
  appendix_number = @document.counter 'appendix-number', 'A'
371
381
  section.number = appendix_number if section.numbered
372
- if (caption = @document.attr 'appendix-caption', '') != ''
373
- section.caption = %(#{caption} #{appendix_number}: )
374
- else
382
+ if (caption = @document.attr 'appendix-caption', '').empty?
375
383
  section.caption = %(#{appendix_number}. )
384
+ else
385
+ section.caption = %(#{caption} #{appendix_number}: )
376
386
  end
377
387
  elsif section.numbered
378
388
  # chapters in a book doctype should be sequential even when divided into parts
@@ -548,9 +548,9 @@ class AbstractNode
548
548
  end
549
549
 
550
550
  # Public: Calculate the relative path to this absolute filename from the Document#base_dir
551
- def relative_path(filename)
552
- (@path_resolver ||= PathResolver.new).relative_path filename, @document.base_dir
553
- end
551
+ #def relative_path(filename)
552
+ # (@path_resolver ||= PathResolver.new).relative_path filename, @document.base_dir
553
+ #end
554
554
 
555
555
  # Public: Check whether the specified String is a URI by
556
556
  # matching it against the Asciidoctor::UriSniffRx regex.
@@ -559,16 +559,5 @@ class AbstractNode
559
559
  def is_uri? str
560
560
  Helpers.uriish? str
561
561
  end
562
-
563
- # Public: Retrieve the list marker keyword for the specified list type.
564
- #
565
- # For use in the HTML type attribute.
566
- #
567
- # list_type - the type of list; default to the @style if not specified
568
- #
569
- # Returns the single-character [String] keyword that represents the marker for the specified list type
570
- def list_marker_keyword(list_type = nil)
571
- ORDERED_LIST_KEYWORDS[list_type || @style]
572
- end
573
562
  end
574
563
  end
@@ -13,12 +13,13 @@ module Asciidoctor
13
13
  @err = nil
14
14
  @code = 0
15
15
  options = options.flatten
16
- if (first_option = options[0]).is_a?(Cli::Options)
16
+ case (first_option = options[0])
17
+ when Options
17
18
  @options = first_option
18
- elsif first_option.is_a?(::Hash)
19
- @options = Cli::Options.new(options)
19
+ when ::Hash
20
+ @options = Options.new options
20
21
  else
21
- if (result = Cli::Options.parse! options).is_a? ::Integer
22
+ if ::Integer === (result = Options.parse! options)
22
23
  @code = result
23
24
  @options = nil
24
25
  else
@@ -243,7 +243,7 @@ Example: asciidoctor -b html5 source.asciidoc
243
243
  os.puts %(Asciidoctor #{::Asciidoctor::VERSION} [http://asciidoctor.org])
244
244
  if RUBY_VERSION >= '1.9.3'
245
245
  encoding_info = {'lc' => 'locale', 'fs' => 'filesystem', 'in' => 'internal', 'ex' => 'external'}.map do |k,v|
246
- %(#{k}:#{Encoding.find(v) || '-'})
246
+ %(#{k}:#{::Encoding.find(v) || '-'})
247
247
  end
248
248
  os.puts %(Runtime Environment (#{RUBY_DESCRIPTION}) (#{encoding_info * ' '}))
249
249
  else
@@ -388,7 +388,7 @@ module Asciidoctor
388
388
  has_body = false
389
389
  result = []
390
390
  pgwide_attribute = (node.option? 'pgwide') ? ' pgwide="1"' : nil
391
- result << %(<#{tag_name = node.title? ? 'table' : 'informaltable'}#{common_attributes node.id, node.role, node.reftext}#{pgwide_attribute} frame="#{node.attr 'frame', 'all'}" rowsep="#{['none', 'cols'].include?(node.attr 'grid') ? 0 : 1}" colsep="#{['none', 'rows'].include?(node.attr 'grid') ? 0 : 1}">)
391
+ result << %(<#{tag_name = node.title? ? 'table' : 'informaltable'}#{common_attributes node.id, node.role, node.reftext}#{pgwide_attribute} frame="#{node.attr 'frame', 'all'}" rowsep="#{['none', 'cols'].include?(node.attr 'grid') ? 0 : 1}" colsep="#{['none', 'rows'].include?(node.attr 'grid') ? 0 : 1}"#{(node.attr? 'orientation', 'landscape', nil) ? ' orient="land"' : nil}>)
392
392
  if (node.option? 'unbreakable')
393
393
  result << '<?dbfo keep-together="always"?>'
394
394
  elsif (node.option? 'breakable')
@@ -184,11 +184,7 @@ module Asciidoctor
184
184
  # Returns the [Converter] object
185
185
  def create backend, opts = {}
186
186
  if (converter = resolve backend)
187
- if converter.is_a? ::Class
188
- return converter.new backend, opts
189
- else
190
- return converter
191
- end
187
+ return ::Class === converter ? (converter.new backend, opts) : converter
192
188
  end
193
189
 
194
190
  base_converter = case backend
@@ -19,7 +19,7 @@ module Asciidoctor
19
19
  #:latexmath => INLINE_MATH_DELIMITERS[:latexmath] + [false]
20
20
  }).default = [nil, nil, nil]
21
21
 
22
- SvgPreambleRx = /\A.*?(?=<svg[ >])/m
22
+ SvgPreambleRx = /\A.*?(?=<svg\b)/m
23
23
  SvgStartTagRx = /\A<svg[^>]*>/
24
24
  DimensionAttributeRx = /\s(?:width|height|style)=(["']).*?\1/
25
25
 
@@ -74,7 +74,7 @@ module Asciidoctor
74
74
 
75
75
  if node.attr? 'icons', 'font'
76
76
  if node.attr? 'iconfont-remote'
77
- result << %(<link rel="stylesheet" href="#{node.attr 'iconfont-cdn', %[#{cdn_base}/font-awesome/4.5.0/css/font-awesome.min.css]}"#{slash}>)
77
+ result << %(<link rel="stylesheet" href="#{node.attr 'iconfont-cdn', %[#{cdn_base}/font-awesome/4.6.3/css/font-awesome.min.css]}"#{slash}>)
78
78
  else
79
79
  iconfont_stylesheet = %(#{node.attr 'iconfont-name', 'font-awesome'}.css)
80
80
  result << %(<link rel="stylesheet" href="#{node.normalize_web_path iconfont_stylesheet, (node.attr 'stylesdir', ''), false}"#{slash}>)
@@ -220,7 +220,7 @@ module Asciidoctor
220
220
 
221
221
  if node.attr? 'stem'
222
222
  eqnums_val = node.attr 'eqnums', 'none'
223
- eqnums_val = 'AMS' if eqnums_val == ''
223
+ eqnums_val = 'AMS' if eqnums_val.empty?
224
224
  eqnums_opt = %( equationNumbers: { autoNumber: "#{eqnums_val}" } )
225
225
  # IMPORTANT inspect calls on delimiter arrays are intentional for JavaScript compat (emulates JSON.stringify)
226
226
  result << %(<script type="text/x-mathjax-config">
@@ -321,15 +321,18 @@ MathJax.Hub.Config({
321
321
  htag = %(h#{slevel + 1})
322
322
  id_attr = anchor = link_start = link_end = nil
323
323
  if node.id
324
- id_attr = %( id="#{node.id}")
325
- if node.document.attr? 'sectanchors'
326
- anchor = %(<a class="anchor" href="##{node.id}"></a>)
324
+ id_attr = %( id="#{id = node.id}")
325
+ if (doc = node.document).attr? 'sectanchors'
326
+ anchor = %(<a class="anchor" href="##{id}"></a>)
327
327
  # possible idea - anchor icons GitHub-style
328
- #if node.document.attr? 'icons', 'font'
329
- # anchor = %(<a class="anchor" href="##{node.id}"><i class="fa fa-anchor"></i></a>)
328
+ #if doc.attr? 'icons', 'font'
329
+ # anchor = %(<a class="anchor" href="##{id}"><i class="fa fa-anchor"></i></a>)
330
330
  #else
331
- elsif node.document.attr? 'sectlinks'
332
- link_start = %(<a class="link" href="##{node.id}">)
331
+ # anchor = %(<a class="anchor" href="##{id}"></a>)
332
+ #end
333
+ end
334
+ if doc.attr? 'sectlinks'
335
+ link_start = %(<a class="link" href="##{id}">)
333
336
  link_end = '</a>'
334
337
  end
335
338
  end
@@ -377,9 +380,9 @@ MathJax.Hub.Config({
377
380
  end
378
381
 
379
382
  def audio node
380
- xml = node.document.attr? 'htmlsyntax', 'xml'
383
+ xml = @xml_mode
381
384
  id_attribute = node.id ? %( id="#{node.id}") : nil
382
- classes = ['audioblock', node.style, node.role].compact
385
+ classes = ['audioblock', node.role].compact
383
386
  class_attribute = %( class="#{classes * ' '}")
384
387
  title_element = node.title? ? %(<div class="title">#{node.captioned_title}</div>\n) : nil
385
388
  %(<div#{id_attribute}#{class_attribute}>
@@ -537,7 +540,7 @@ Your browser does not support the audio tag.
537
540
  target = node.attr 'target'
538
541
  width_attr = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : nil
539
542
  height_attr = (node.attr? 'height') ? %( height="#{node.attr 'height'}") : nil
540
- if ((node.attr? 'format', 'svg', false) || (target.include? '.svg')) && node.document.safe < SafeMode::SECURE
543
+ if ((node.attr? 'format', 'svg', false) || (target.include? '.svg')) && node.document.safe < SafeMode::SECURE &&
541
544
  ((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
542
545
  if svg
543
546
  img = (read_svg_contents node, target) || %(<span class="alt">#{node.attr 'alt'}</span>)
@@ -551,7 +554,7 @@ Your browser does not support the audio tag.
551
554
  img = %(<a class="image" href="#{link}">#{img}</a>)
552
555
  end
553
556
  id_attr = node.id ? %( id="#{node.id}") : nil
554
- classes = ['imageblock', node.style, node.role].compact
557
+ classes = ['imageblock', node.role].compact
555
558
  class_attr = %( class="#{classes * ' '}")
556
559
  styles = []
557
560
  styles << %(text-align: #{node.attr 'align'}) if node.attr? 'align'
@@ -645,7 +648,8 @@ Your browser does not support the audio tag.
645
648
 
646
649
  type_attribute = (keyword = node.list_marker_keyword) ? %( type="#{keyword}") : nil
647
650
  start_attribute = (node.attr? 'start') ? %( start="#{node.attr 'start'}") : nil
648
- result << %(<ol class="#{node.style}"#{type_attribute}#{start_attribute}>)
651
+ reversed_attribute = (node.option? 'reversed') ? (append_boolean_attribute 'reversed', @xml_mode) : nil
652
+ result << %(<ol class="#{node.style}"#{type_attribute}#{start_attribute}#{reversed_attribute}>)
649
653
 
650
654
  node.items.each do |item|
651
655
  result << '<li>'
@@ -666,19 +670,19 @@ Your browser does not support the audio tag.
666
670
  ''
667
671
  else
668
672
  id_attr = node.id ? %( id="#{node.id}") : nil
669
- title_el = node.title? ? %(<div class="title">#{node.title}</div>) : nil
673
+ title_el = node.title? ? %(<div class="title">#{node.title}</div>\n) : nil
670
674
  %(<div#{id_attr} class="quoteblock abstract#{(role = node.role) && " #{role}"}">
671
675
  #{title_el}<blockquote>
672
676
  #{node.content}
673
677
  </blockquote>
674
678
  </div>)
675
679
  end
676
- elsif style == 'partintro' && (node.level != 0 || node.parent.context != :section || node.document.doctype != 'book')
680
+ elsif style == 'partintro' && (node.level > 0 || node.parent.context != :section || node.document.doctype != 'book')
677
681
  warn 'asciidoctor: ERROR: partintro block can only be used when doctype is book and it\'s a child of a book part. Excluding block content.'
678
682
  ''
679
683
  else
680
684
  id_attr = node.id ? %( id="#{node.id}") : nil
681
- title_el = node.title? ? %(<div class="title">#{node.title}</div>) : nil
685
+ title_el = node.title? ? %(<div class="title">#{node.title}</div>\n) : nil
682
686
  %(<div#{id_attr} class="openblock#{style && style != 'open' ? " #{style}" : ''}#{(role = node.role) && " #{role}"}">
683
687
  #{title_el}<div class="content">
684
688
  #{node.content}
@@ -766,11 +770,11 @@ Your browser does not support the audio tag.
766
770
  id_attribute = node.id ? %( id="#{node.id}") : nil
767
771
  classes = ['tableblock', %(frame-#{node.attr 'frame', 'all'}), %(grid-#{node.attr 'grid', 'all'})]
768
772
  styles = []
769
- unless node.option? 'autowidth'
770
- if (tablepcwidth = node.attr 'tablepcwidth') == 100
773
+ unless (node.option? 'autowidth') && !(node.attr? 'width', nil, false)
774
+ if node.attr? 'tablepcwidth', 100
771
775
  classes << 'spread'
772
776
  else
773
- styles << %(width: #{tablepcwidth}%;)
777
+ styles << %(width: #{node.attr 'tablepcwidth'}%;)
774
778
  end
775
779
  end
776
780
  if (role = node.role)
@@ -867,7 +871,7 @@ Your browser does not support the audio tag.
867
871
  div_classes.insert 1, 'checklist'
868
872
  ul_class_attribute = ' class="checklist"'
869
873
  if node.option? 'interactive'
870
- if node.document.attr? 'htmlsyntax', 'xml'
874
+ if @xml_mode
871
875
  marker_checked = '<input type="checkbox" data-item-complete="1" checked="checked"/> '
872
876
  marker_unchecked = '<input type="checkbox" data-item-complete="0"/> '
873
877
  else
@@ -927,9 +931,9 @@ Your browser does not support the audio tag.
927
931
  end
928
932
 
929
933
  def video node
930
- xml = node.document.attr? 'htmlsyntax', 'xml'
934
+ xml = @xml_mode
931
935
  id_attribute = node.id ? %( id="#{node.id}") : nil
932
- classes = ['videoblock', node.style, node.role].compact
936
+ classes = ['videoblock', node.role].compact
933
937
  class_attribute = %( class="#{classes * ' '}")
934
938
  title_element = node.title? ? %(\n<div class="title">#{node.captioned_title}</div>) : nil
935
939
  width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : nil
@@ -1070,7 +1074,7 @@ Your browser does not support the video tag.
1070
1074
  def inline_image node
1071
1075
  if (type = node.type) == 'icon' && (node.document.attr? 'icons', 'font')
1072
1076
  class_attr_val = %(fa fa-#{node.target})
1073
- {'size' => 'fa-', 'rotate' => 'fa-rotate-', 'flip' => 'fa-flip-'}.each do |(key, prefix)|
1077
+ {'size' => 'fa-', 'rotate' => 'fa-rotate-', 'flip' => 'fa-flip-'}.each do |key, prefix|
1074
1078
  class_attr_val = %(#{class_attr_val} #{prefix}#{node.attr key}) if node.attr? key
1075
1079
  end
1076
1080
  title_attr = (node.attr? 'title') ? %( title="#{node.attr 'title'}") : nil
@@ -1146,16 +1150,17 @@ Your browser does not support the video tag.
1146
1150
 
1147
1151
  def read_svg_contents node, target
1148
1152
  if (svg = node.read_contents target, :start => (node.document.attr 'imagesdir'), :normalize => true, :label => 'SVG')
1149
- svg = svg.sub SvgPreambleRx, ''
1150
- start_tag = nil
1153
+ svg = svg.sub SvgPreambleRx, '' unless svg.start_with? '<svg'
1154
+ old_start_tag = new_start_tag = nil
1155
+ # NOTE width, height and style attributes are removed if either width or height is specified
1151
1156
  ['width', 'height'].each do |dim|
1152
1157
  if node.attr? dim
1153
- # NOTE width, height and style attributes are removed if either width or height is specified
1154
- start_tag ||= (svg.match SvgStartTagRx)[0].gsub DimensionAttributeRx, ''
1155
- start_tag = %(#{start_tag.chop} #{dim}="#{node.attr dim}px">)
1158
+ new_start_tag = (old_start_tag = (svg.match SvgStartTagRx)[0]).gsub DimensionAttributeRx, '' unless new_start_tag
1159
+ # QUESTION should we add px since it's already the default?
1160
+ new_start_tag = %(#{new_start_tag.chop} #{dim}="#{node.attr dim}px">)
1156
1161
  end
1157
1162
  end
1158
- svg = svg.sub SvgStartTagRx, start_tag if start_tag
1163
+ svg = %(#{new_start_tag}#{svg[old_start_tag.length..-1]}) if new_start_tag
1159
1164
  end
1160
1165
  svg
1161
1166
  end