asciidoctor 2.0.7 → 2.0.12

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +169 -7
  3. data/LICENSE +2 -1
  4. data/README-de.adoc +5 -15
  5. data/README-fr.adoc +4 -14
  6. data/README-jp.adoc +234 -186
  7. data/README-zh_CN.adoc +7 -17
  8. data/README.adoc +18 -18
  9. data/asciidoctor.gemspec +4 -4
  10. data/data/locale/attributes-ar.adoc +4 -3
  11. data/data/locale/attributes-bg.adoc +4 -3
  12. data/data/locale/attributes-ca.adoc +6 -5
  13. data/data/locale/attributes-cs.adoc +4 -3
  14. data/data/locale/attributes-da.adoc +6 -5
  15. data/data/locale/attributes-de.adoc +4 -4
  16. data/data/locale/attributes-en.adoc +4 -4
  17. data/data/locale/attributes-es.adoc +6 -5
  18. data/data/locale/attributes-fa.adoc +4 -3
  19. data/data/locale/attributes-fi.adoc +4 -3
  20. data/data/locale/attributes-fr.adoc +6 -5
  21. data/data/locale/attributes-hu.adoc +4 -3
  22. data/data/locale/attributes-id.adoc +4 -3
  23. data/data/locale/attributes-it.adoc +4 -3
  24. data/data/locale/attributes-ja.adoc +4 -3
  25. data/data/locale/{attributes-kr.adoc → attributes-ko.adoc} +4 -3
  26. data/data/locale/attributes-nb.adoc +4 -3
  27. data/data/locale/attributes-nl.adoc +4 -3
  28. data/data/locale/attributes-nn.adoc +4 -3
  29. data/data/locale/attributes-pl.adoc +8 -7
  30. data/data/locale/attributes-pt.adoc +6 -5
  31. data/data/locale/attributes-pt_BR.adoc +6 -5
  32. data/data/locale/attributes-ro.adoc +4 -3
  33. data/data/locale/attributes-ru.adoc +6 -5
  34. data/data/locale/attributes-sr.adoc +4 -4
  35. data/data/locale/attributes-sr_Latn.adoc +4 -4
  36. data/data/locale/attributes-sv.adoc +4 -4
  37. data/data/locale/attributes-tr.adoc +4 -3
  38. data/data/locale/attributes-uk.adoc +6 -5
  39. data/data/locale/attributes-zh_CN.adoc +4 -3
  40. data/data/locale/attributes-zh_TW.adoc +4 -3
  41. data/data/stylesheets/asciidoctor-default.css +33 -30
  42. data/lib/asciidoctor.rb +89 -791
  43. data/lib/asciidoctor/abstract_block.rb +19 -11
  44. data/lib/asciidoctor/abstract_node.rb +21 -15
  45. data/lib/asciidoctor/attribute_list.rb +59 -67
  46. data/lib/asciidoctor/cli/invoker.rb +2 -0
  47. data/lib/asciidoctor/cli/options.rb +3 -3
  48. data/lib/asciidoctor/convert.rb +167 -162
  49. data/lib/asciidoctor/converter.rb +14 -13
  50. data/lib/asciidoctor/converter/docbook5.rb +10 -26
  51. data/lib/asciidoctor/converter/html5.rb +62 -43
  52. data/lib/asciidoctor/converter/manpage.rb +13 -12
  53. data/lib/asciidoctor/converter/template.rb +6 -3
  54. data/lib/asciidoctor/document.rb +25 -41
  55. data/lib/asciidoctor/extensions.rb +3 -3
  56. data/lib/asciidoctor/helpers.rb +38 -39
  57. data/lib/asciidoctor/inline.rb +1 -1
  58. data/lib/asciidoctor/load.rb +101 -101
  59. data/lib/asciidoctor/parser.rb +30 -25
  60. data/lib/asciidoctor/path_resolver.rb +35 -25
  61. data/lib/asciidoctor/reader.rb +14 -7
  62. data/lib/asciidoctor/rx.rb +722 -0
  63. data/lib/asciidoctor/substitutors.rb +61 -39
  64. data/lib/asciidoctor/syntax_highlighter.rb +22 -8
  65. data/lib/asciidoctor/syntax_highlighter/coderay.rb +1 -1
  66. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +12 -4
  67. data/lib/asciidoctor/syntax_highlighter/prettify.rb +7 -4
  68. data/lib/asciidoctor/syntax_highlighter/pygments.rb +2 -3
  69. data/lib/asciidoctor/syntax_highlighter/rouge.rb +15 -7
  70. data/lib/asciidoctor/table.rb +52 -23
  71. data/lib/asciidoctor/version.rb +1 -1
  72. data/man/asciidoctor.1 +6 -6
  73. data/man/asciidoctor.adoc +4 -3
  74. metadata +10 -9
@@ -422,7 +422,10 @@ module Substitutors
422
422
  end
423
423
  target = $1
424
424
  attrs = parse_attributes $2, posattrs, unescape_input: true
425
- doc.register :images, [target, (attrs['imagesdir'] = doc_attrs['imagesdir'])] unless type == 'icon'
425
+ unless type == 'icon'
426
+ doc.register :images, target
427
+ attrs['imagesdir'] = doc_attrs['imagesdir']
428
+ end
426
429
  attrs['alt'] ||= (attrs['default-alt'] = Helpers.basename(target, true).tr('_-', ' '))
427
430
  Inline.new(self, :image, nil, type: type, target: target, attributes: attrs).convert
428
431
  end
@@ -539,14 +542,17 @@ module Substitutors
539
542
  end
540
543
 
541
544
  prefix, suffix = $1, ''
542
- # NOTE if $4 is set, then we're looking at a formal macro
545
+ # NOTE if $4 is set, we're looking at a formal macro (e.g., https://example.org[])
543
546
  if $4
544
547
  prefix = '' if prefix == 'link:'
545
548
  text = $4
546
549
  else
547
- # invalid macro syntax (link: prefix w/o trailing square brackets)
548
- # FIXME we probably shouldn't even get here...our regex is doing too much
549
- next $& if prefix == 'link:'
550
+ # invalid macro syntax (link: prefix w/o trailing square brackets or enclosed in double quotes)
551
+ # FIXME we probably shouldn't even get here when the link: prefix is present; the regex is doing too much
552
+ case prefix
553
+ when 'link:', ?", ?'
554
+ next $&
555
+ end
550
556
  text = ''
551
557
  case $3
552
558
  when ')'
@@ -588,7 +594,8 @@ module Substitutors
588
594
  unless text.empty?
589
595
  text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
590
596
  if !doc.compat_mode && (text.include? '=')
591
- text = (attrs = (AttributeList.new text, self).parse)[1] || ''
597
+ # NOTE if an equals sign (=) is present, extract attributes from text
598
+ text, attrs = extract_attributes_from_text text, ''
592
599
  link_opts[:id] = attrs['id']
593
600
  end
594
601
 
@@ -634,7 +641,8 @@ module Substitutors
634
641
  text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
635
642
  if mailto
636
643
  if !doc.compat_mode && (text.include? ',')
637
- text = (attrs = (AttributeList.new text, self).parse)[1] || ''
644
+ # NOTE if a comma (,) is present, extract attributes from text
645
+ text, attrs = extract_attributes_from_text text, ''
638
646
  link_opts[:id] = attrs['id']
639
647
  if attrs.key? 2
640
648
  if attrs.key? 3
@@ -645,7 +653,8 @@ module Substitutors
645
653
  end
646
654
  end
647
655
  elsif !doc.compat_mode && (text.include? '=')
648
- text = (attrs = (AttributeList.new text, self).parse)[1] || ''
656
+ # NOTE if an equals sign (=) is present, extract attributes from text
657
+ text, attrs = extract_attributes_from_text text, ''
649
658
  link_opts[:id] = attrs['id']
650
659
  end
651
660
 
@@ -736,8 +745,8 @@ module Substitutors
736
745
  refid = $2
737
746
  if (text = $3)
738
747
  text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
739
- # NOTE if an equal sign (=) is present, parse text as attributes
740
- text = ((AttributeList.new text, self).parse_into attrs)[1] if !doc.compat_mode && (text.include? '=')
748
+ # NOTE if an equals sign (=) is present, extract attributes from text
749
+ text, attrs = extract_attributes_from_text text if !doc.compat_mode && (text.include? '=')
741
750
  end
742
751
  end
743
752
 
@@ -801,7 +810,7 @@ module Substitutors
801
810
  # handles: id (in compat mode or when natural xrefs are disabled)
802
811
  elsif doc.compat_mode || !Compliance.natural_xrefs
803
812
  refid, target = fragment, %(##{fragment})
804
- logger.info %(possible invalid reference: #{refid}) if logger.info? && doc.catalog[:refs][refid]
813
+ logger.info %(possible invalid reference: #{refid}) if logger.info? && !doc.catalog[:refs][refid]
805
814
  # handles: id
806
815
  elsif doc.catalog[:refs][fragment]
807
816
  refid, target = fragment, %(##{fragment})
@@ -840,19 +849,17 @@ module Substitutors
840
849
  end
841
850
 
842
851
  if id
843
- if text
852
+ if (footnote = doc.footnotes.find {|candidate| candidate.id == id })
853
+ index, text = footnote.index, footnote.text
854
+ type, target, id = :xref, id, nil
855
+ elsif text
844
856
  text = restore_passthroughs(normalize_text text, true, true)
845
857
  index = doc.counter('footnote-number')
846
858
  doc.register(:footnotes, Document::Footnote.new(index, id, text))
847
859
  type, target = :ref, nil
848
860
  else
849
- if (footnote = doc.footnotes.find {|candidate| candidate.id == id })
850
- index, text = footnote.index, footnote.text
851
- else
852
- logger.warn %(invalid footnote reference: #{id})
853
- index, text = nil, id
854
- end
855
- type, target, id = :xref, id, nil
861
+ logger.warn %(invalid footnote reference: #{id})
862
+ type, target, text, id = :xref, id, id, nil
856
863
  end
857
864
  elsif text
858
865
  text = restore_passthroughs(normalize_text text, true, true)
@@ -914,7 +921,7 @@ module Substitutors
914
921
  # use sub since it might be behind a line comment
915
922
  $&.sub RS, ''
916
923
  else
917
- Inline.new(self, :callout, $4 == '.' ? (autonum += 1).to_s : $4, id: @document.callouts.read_next_id, attributes: { 'guard' => $1 }).convert
924
+ Inline.new(self, :callout, $4 == '.' ? (autonum += 1).to_s : $4, id: @document.callouts.read_next_id, attributes: { 'guard' => $1 || ($3 == '--' ? ['<!--', '-->'] : nil) }).convert
918
925
  end
919
926
  end
920
927
  end
@@ -942,7 +949,7 @@ module Substitutors
942
949
  if (linenums_mode = (attr? 'linenums') ? (doc_attrs[%(#{syntax_hl_name}-linenums-mode)] || :table).to_sym : nil)
943
950
  start_line_number = 1 if (start_line_number = (attr 'start', 1).to_i) < 1
944
951
  end
945
- highlight_lines = resolve_lines_to_highlight source, (attr 'highlight') if attr? 'highlight'
952
+ highlight_lines = resolve_lines_to_highlight source, (attr 'highlight'), start_line_number if attr? 'highlight'
946
953
 
947
954
  highlighted, source_offset = syntax_hl.highlight self, source, (attr 'language'),
948
955
  callouts: callout_marks,
@@ -965,9 +972,10 @@ module Substitutors
965
972
  #
966
973
  # source - The String source.
967
974
  # spec - The lines specifier (e.g., "1-5, !2, 10" or "1..5;!2;10")
975
+ # start - The line number of the first line (optional, default: false)
968
976
  #
969
977
  # Returns an [Array] of unique, sorted line numbers.
970
- def resolve_lines_to_highlight source, spec
978
+ def resolve_lines_to_highlight source, spec, start = nil
971
979
  lines = []
972
980
  spec = spec.delete ' ' if spec.include? ' '
973
981
  ((spec.include? ',') ? (spec.split ',') : (spec.split ';')).map do |entry|
@@ -978,21 +986,22 @@ module Substitutors
978
986
  if (delim = (entry.include? '..') ? '..' : ((entry.include? '-') ? '-' : nil))
979
987
  from, delim, to = entry.partition delim
980
988
  to = (source.count LF) + 1 if to.empty? || (to = to.to_i) < 0
981
- line_nums = (from.to_i..to).to_a
982
989
  if negate
983
- lines -= line_nums
990
+ lines -= (from.to_i..to).to_a
984
991
  else
985
- lines.concat line_nums
986
- end
987
- else
988
- if negate
989
- lines.delete entry.to_i
990
- else
991
- lines << entry.to_i
992
+ lines |= (from.to_i..to).to_a
992
993
  end
994
+ elsif negate
995
+ lines.delete entry.to_i
996
+ elsif !lines.include?(line = entry.to_i)
997
+ lines << line
993
998
  end
994
999
  end
995
- lines.sort.uniq
1000
+ # If the start attribute is defined, then the lines to highlight specified by the provided spec should be relative to the start value.
1001
+ unless (shift = start ? start - 1 : 0) == 0
1002
+ lines = lines.map {|it| it - shift }
1003
+ end
1004
+ lines.sort
996
1005
  end
997
1006
 
998
1007
  # Public: Extract the passthrough text from the document for reinsertion after processing.
@@ -1318,10 +1327,23 @@ module Substitutors
1318
1327
 
1319
1328
  private
1320
1329
 
1330
+ # This method is used in cases when the attrlist can be mixed with the text of a macro.
1331
+ # If no attributes are detected aside from the first positional attribute, and the first positional
1332
+ # attribute matches the attrlist, then the original text is returned.
1333
+ def extract_attributes_from_text text, default_text = nil
1334
+ attrlist = (text.include? LF) ? (text.tr LF, ' ') : text
1335
+ if (resolved_text = (attrs = (AttributeList.new attrlist, self).parse)[1])
1336
+ # NOTE if resolved text remains unchanged, clear attributes and return unparsed text
1337
+ resolved_text == attrlist ? [text, attrs.clear] : [resolved_text, attrs]
1338
+ else
1339
+ [default_text, attrs]
1340
+ end
1341
+ end
1342
+
1321
1343
  # Internal: Extract the callout numbers from the source to prepare it for syntax highlighting.
1322
1344
  def extract_callouts source
1323
1345
  callout_marks = {}
1324
- lineno = 0
1346
+ autonum = lineno = 0
1325
1347
  last_lineno = nil
1326
1348
  callout_rx = (attr? 'line-comment') ? CalloutExtractRxMap[attr 'line-comment'] : CalloutExtractRx
1327
1349
  # extract callout marks, indexed by line number
@@ -1333,7 +1355,7 @@ module Substitutors
1333
1355
  # use sub since it might be behind a line comment
1334
1356
  $&.sub RS, ''
1335
1357
  else
1336
- (callout_marks[lineno] ||= []) << [$1, $4]
1358
+ (callout_marks[lineno] ||= []) << [$1 || ($3 == '--' ? ['<!--', '-->'] : nil), $4 == '.' ? (autonum += 1).to_s : $4]
1337
1359
  last_lineno = lineno
1338
1360
  ''
1339
1361
  end
@@ -1355,15 +1377,15 @@ module Substitutors
1355
1377
  else
1356
1378
  preamble = ''
1357
1379
  end
1358
- autonum = lineno = 0
1380
+ lineno = 0
1359
1381
  preamble + ((source.split LF, -1).map do |line|
1360
1382
  if (conums = callout_marks.delete lineno += 1)
1361
1383
  if conums.size == 1
1362
- guard, conum = conums[0]
1363
- %(#{line}#{Inline.new(self, :callout, conum == '.' ? (autonum += 1).to_s : conum, id: @document.callouts.read_next_id, attributes: { 'guard' => guard }).convert})
1384
+ guard, numeral = conums[0]
1385
+ %(#{line}#{Inline.new(self, :callout, numeral, id: @document.callouts.read_next_id, attributes: { 'guard' => guard }).convert})
1364
1386
  else
1365
- %(#{line}#{conums.map do |guard_it, conum_it|
1366
- Inline.new(self, :callout, conum_it == '.' ? (autonum += 1).to_s : conum_it, id: @document.callouts.read_next_id, attributes: { 'guard' => guard_it }).convert
1387
+ %(#{line}#{conums.map do |guard_it, numeral_it|
1388
+ Inline.new(self, :callout, numeral_it, id: @document.callouts.read_next_id, attributes: { 'guard' => guard_it }).convert
1367
1389
  end.join ' '})
1368
1390
  end
1369
1391
  else
@@ -20,19 +20,25 @@ module SyntaxHighlighter
20
20
  end
21
21
 
22
22
  # Public: Indicates whether this syntax highlighter has docinfo (i.e., markup) to insert into the output document at
23
- # the specified location.
23
+ # the specified location. Should be called by converter after main content has been converted.
24
24
  #
25
25
  # location - The Symbol representing the location slot (:head or :footer).
26
26
  #
27
27
  # Returns a [Boolean] indicating whether the docinfo method should be called for this location.
28
28
  def docinfo? location; end
29
29
 
30
- # Public: Generates docinfo markup to insert in the output document at the specified location.
30
+ # Public: Generates docinfo markup for this syntax highlighter to insert at the specified location in the output document.
31
+ # Should be called by converter after main content has been converted.
31
32
  #
32
33
  # location - The Symbol representing the location slot (:head or :footer).
34
+ # doc - The Document in which this syntax highlighter is being used.
35
+ # opts - A Hash of options that configure the syntax highlighting:
36
+ # :linkcss - A Boolean indicating whether the stylesheet should be linked instead of embedded (optional).
37
+ # :cdn_base_url - The String base URL for assets loaded from the CDN.
38
+ # :self_closing_tag_slash - The String '/' if the converter calling this method emits self-closing tags.
33
39
  #
34
40
  # Return the [String] markup to insert.
35
- def docinfo location
41
+ def docinfo location, doc, opts
36
42
  raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method since #docinfo? returns true)
37
43
  end
38
44
 
@@ -100,15 +106,21 @@ module SyntaxHighlighter
100
106
  module Config
101
107
  # Public: Statically register the current class in the registry for the specified names.
102
108
  #
109
+ # names - one or more String or Symbol names with which to register the current class as a syntax highlighter
110
+ # implementation. Symbol arguments are coerced to Strings.
111
+ #
103
112
  # Returns nothing.
104
113
  def register_for *names
105
- SyntaxHighlighter.register self, *names
114
+ SyntaxHighlighter.register self, *(names.map {|name| name.to_s })
106
115
  end
107
116
  end
108
117
 
109
118
  module Factory
110
119
  # Public: Associates the syntax highlighter class or object with the specified names.
111
120
  #
121
+ # syntax_highlighter - the syntax highlighter implementation to register
122
+ # names - one or more String names with which to register this syntax highlighter implementation.
123
+ #
112
124
  # Returns nothing.
113
125
  def register syntax_highlighter, *names
114
126
  names.each {|name| registry[name] = syntax_highlighter }
@@ -128,7 +140,7 @@ module SyntaxHighlighter
128
140
  # name - The String name of the syntax highlighter to create.
129
141
  # backend - The String name of the backend for which this syntax highlighter is being used (default: 'html5').
130
142
  # opts - A Hash of options providing information about the context in which this syntax highlighter is used:
131
- # :doc - The Document for which this syntax highlighter was created.
143
+ # :document - The Document for which this syntax highlighter was created.
132
144
  #
133
145
  # Returns a [SyntaxHighlighter] instance for the specified name.
134
146
  def create name, backend = 'html5', opts = {}
@@ -224,9 +236,11 @@ module SyntaxHighlighter
224
236
  def format node, lang, opts
225
237
  class_attr_val = opts[:nowrap] ? %(#{@pre_class} highlight nowrap) : %(#{@pre_class} highlight)
226
238
  if (transform = opts[:transform])
227
- pre = { 'class' => class_attr_val }
228
- code = lang ? { 'data-lang' => lang } : {}
229
- transform[pre, code]
239
+ transform[(pre = { 'class' => class_attr_val }), (code = lang ? { 'data-lang' => lang } : {})]
240
+ # NOTE: make sure data-lang is the last attribute on the code tag to remain consistent with 1.5.x
241
+ if (lang = code.delete 'data-lang')
242
+ code['data-lang'] = lang
243
+ end
230
244
  %(<pre#{pre.map {|k, v| %[ #{k}="#{v}"] }.join}><code#{code.map {|k, v| %[ #{k}="#{v}"] }.join}>#{node.content}</code></pre>)
231
245
  else
232
246
  %(<pre class="#{class_attr_val}"><code#{lang ? %[ data-lang="#{lang}"] : ''}>#{node.content}</code></pre>)
@@ -32,7 +32,7 @@ class SyntaxHighlighter::CodeRayAdapter < SyntaxHighlighter::Base
32
32
  end
33
33
 
34
34
  def docinfo? location
35
- @requires_stylesheet && location == :footer
35
+ @requires_stylesheet && location == :head
36
36
  end
37
37
 
38
38
  def docinfo location, doc, opts
@@ -13,14 +13,22 @@ class SyntaxHighlighter::HighlightJsAdapter < SyntaxHighlighter::Base
13
13
  end
14
14
 
15
15
  def docinfo? location
16
- location == :footer
16
+ true
17
17
  end
18
18
 
19
19
  def docinfo location, doc, opts
20
20
  base_url = doc.attr 'highlightjsdir', %(#{opts[:cdn_base_url]}/highlight.js/#{HIGHLIGHT_JS_VERSION})
21
- %(<link rel="stylesheet" href="#{base_url}/styles/#{doc.attr 'highlightjs-theme', 'github'}.min.css"#{opts[:self_closing_tag_slash]}>
22
- <script src="#{base_url}/highlight.min.js"></script>
23
- #{(doc.attr? 'highlightjs-languages') ? ((doc.attr 'highlightjs-languages').split ',').map {|lang| %[<script src="#{base_url}/languages/#{lang.lstrip}.min.js"></script>\n] }.join : ''}<script>hljs.initHighlighting()</script>)
21
+ if location == :head
22
+ %(<link rel="stylesheet" href="#{base_url}/styles/#{doc.attr 'highlightjs-theme', 'github'}.min.css"#{opts[:self_closing_tag_slash]}>)
23
+ else # :footer
24
+ %(<script src="#{base_url}/highlight.min.js"></script>
25
+ #{(doc.attr? 'highlightjs-languages') ? ((doc.attr 'highlightjs-languages').split ',').map {|lang| %[<script src="#{base_url}/languages/#{lang.lstrip}.min.js"></script>\n] }.join : ''}<script>
26
+ if (!hljs.initHighlighting.called) {
27
+ hljs.initHighlighting.called = true
28
+ ;[].slice.call(document.querySelectorAll('pre.highlight > code')).forEach(function (el) { hljs.highlightBlock(el) })
29
+ }
30
+ </script>)
31
+ end
24
32
  end
25
33
  end
26
34
  end
@@ -14,14 +14,17 @@ class SyntaxHighlighter::PrettifyAdapter < SyntaxHighlighter::Base
14
14
  end
15
15
 
16
16
  def docinfo? location
17
- location == :footer
17
+ true
18
18
  end
19
19
 
20
20
  def docinfo location, doc, opts
21
21
  base_url = doc.attr 'prettifydir', %(#{opts[:cdn_base_url]}/prettify/r298)
22
- prettify_theme_url = ((prettify_theme = doc.attr 'prettify-theme', 'prettify').start_with? 'http://', 'https://') ? prettify_theme : %(#{base_url}/#{prettify_theme}.min.css)
23
- %(<link rel="stylesheet" href="#{prettify_theme_url}"#{opts[:self_closing_tag_slash]}>
24
- <script src="#{base_url}/run_prettify.min.js"></script>)
22
+ if location == :head
23
+ prettify_theme_url = ((prettify_theme = doc.attr 'prettify-theme', 'prettify').start_with? 'http://', 'https://') ? prettify_theme : %(#{base_url}/#{prettify_theme}.min.css)
24
+ %(<link rel="stylesheet" href="#{prettify_theme_url}"#{opts[:self_closing_tag_slash]}>)
25
+ else # :footer
26
+ %(<script src="#{base_url}/run_prettify.min.js"></script>)
27
+ end
25
28
  end
26
29
  end
27
30
  end
@@ -5,8 +5,7 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
5
5
 
6
6
  def initialize *args
7
7
  super
8
- @requires_stylesheet = nil
9
- @style = nil
8
+ @requires_stylesheet = @style = nil
10
9
  end
11
10
 
12
11
  def highlight?
@@ -53,7 +52,7 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
53
52
  end
54
53
 
55
54
  def docinfo? location
56
- @requires_stylesheet && location == :footer
55
+ @requires_stylesheet && location == :head
57
56
  end
58
57
 
59
58
  def docinfo location, doc, opts
@@ -13,8 +13,17 @@ class SyntaxHighlighter::RougeAdapter < SyntaxHighlighter::Base
13
13
  end
14
14
 
15
15
  def highlight node, source, lang, opts
16
- lexer = (::Rouge::Lexer.find_fancy lang) || ::Rouge::Lexers::PlainText
17
- lexer_opts = lexer.tag == 'php' && !(node.option? 'mixed') ? { start_inline: true } : {}
16
+ if lang.include? '?'
17
+ # NOTE cgi-style options only properly supported in Rouge >= 2.1
18
+ if (lexer = ::Rouge::Lexer.find_fancy lang)
19
+ unless lexer.tag != 'php' || (node.option? 'mixed') || ((lexer_opts = lexer.options).key? 'start_inline')
20
+ lexer = lexer.class.new lexer_opts.merge 'start_inline' => true
21
+ end
22
+ end
23
+ elsif (lexer = ::Rouge::Lexer.find lang)
24
+ lexer = lexer.tag == 'php' && !(node.option? 'mixed') ? (lexer.new start_inline: true) : lexer.new
25
+ end if lang
26
+ lexer ||= ::Rouge::Lexers::PlainText.new
18
27
  @style ||= (style = opts[:style]) && (style_available? style) || DEFAULT_STYLE
19
28
  if opts[:css_mode] == :class
20
29
  @requires_stylesheet = true
@@ -28,25 +37,24 @@ class SyntaxHighlighter::RougeAdapter < SyntaxHighlighter::Base
28
37
  if opts[:number_lines]
29
38
  formatter = RougeExt::Formatters::HTMLTable.new formatter, start_line: opts[:start_line_number]
30
39
  if opts[:callouts]
31
- return [(highlighted = formatter.format lexer.lex source, lexer_opts), (idx = highlighted.index CodeCellStartTagCs) ? idx + CodeCellStartTagCs.length : nil]
40
+ return [(highlighted = formatter.format lexer.lex source), (idx = highlighted.index CodeCellStartTagCs) ? idx + CodeCellStartTagCs.length : nil]
32
41
  end
33
42
  end
34
- formatter.format lexer.lex source, lexer_opts
43
+ formatter.format lexer.lex source
35
44
  end
36
45
 
37
46
  def format node, lang, opts
38
47
  if (query_idx = lang && (lang.index '?'))
39
48
  lang = lang.slice 0, query_idx
40
49
  end
41
- if opts[:css_mode] != :class && (@style = (style = opts[:style]) && (style_available? style) || DEFAULT_STYLE) &&
42
- (pre_style_attr_val = base_style @style)
50
+ if opts[:css_mode] != :class && (@style = (style = opts[:style]) && (style_available? style) || DEFAULT_STYLE) && (pre_style_attr_val = base_style @style)
43
51
  opts[:transform] = proc {|pre| pre['style'] = pre_style_attr_val }
44
52
  end
45
53
  super
46
54
  end
47
55
 
48
56
  def docinfo? location
49
- @requires_stylesheet && location == :footer
57
+ @requires_stylesheet && location == :head
50
58
  end
51
59
 
52
60
  def docinfo location, doc, opts
@@ -58,7 +58,7 @@ class Table < AbstractBlock
58
58
  @rows = Rows.new
59
59
  @columns = []
60
60
 
61
- @has_header_option = attributes['header-option'] ? true : false
61
+ @has_header_option = false
62
62
 
63
63
  # smells like we need a utility method here
64
64
  # to resolve an integer width from potential bogus input
@@ -78,10 +78,10 @@ class Table < AbstractBlock
78
78
  @attributes['orientation'] = 'landscape' if attributes['rotate-option']
79
79
  end
80
80
 
81
- # Internal: Returns whether the current row being processed is
82
- # the header row
81
+ # Internal: Returns the current state of the header option (true or :implicit) if
82
+ # the row being processed is (or is assumed to be) the header row, otherwise nil
83
83
  def header_row?
84
- @has_header_option && @rows.body.empty?
84
+ (val = @has_header_option) && @rows.body.empty? ? val : nil
85
85
  end
86
86
 
87
87
  # Internal: Creates the Column objects from the column spec
@@ -154,22 +154,19 @@ class Table < AbstractBlock
154
154
  # returns nothing
155
155
  def partition_header_footer(attrs)
156
156
  # set rowcount before splitting up body rows
157
- @attributes['rowcount'] = @rows.body.size
158
-
159
- num_body_rows = @rows.body.size
160
- if num_body_rows > 0 && @has_header_option
161
- head = @rows.body.shift
162
- num_body_rows -= 1
163
- # styles aren't applied to header row
164
- head.each {|c| c.style = nil }
165
- # QUESTION why does AsciiDoc use an array for head? is it
166
- # possible to have more than one based on the syntax?
167
- @rows.head = [head]
157
+ num_body_rows = @attributes['rowcount'] = (body = @rows.body).size
158
+
159
+ if num_body_rows > 0
160
+ if @has_header_option
161
+ @rows.head = [body.shift.map {|cell| cell.reinitialize true }]
162
+ num_body_rows -= 1
163
+ elsif @has_header_option.nil?
164
+ @has_header_option = false
165
+ body.unshift(body.shift.map {|cell| cell.reinitialize false })
166
+ end
168
167
  end
169
168
 
170
- if num_body_rows > 0 && attrs['footer-option']
171
- @rows.foot = [@rows.body.pop]
172
- end
169
+ @rows.foot = [body.pop] if num_body_rows > 0 && attrs['footer-option']
173
170
 
174
171
  nil
175
172
  end
@@ -232,14 +229,23 @@ class Table::Cell < AbstractBlock
232
229
  # Public: An alias to the parent block (which is always a Column)
233
230
  alias column parent
234
231
 
235
- # Internal: Returns the nested Document in an AsciiDoc table cell (only set when style is :asciidoc)
232
+ # Public: Returns the nested Document in an AsciiDoc table cell (only set when style is :asciidoc)
236
233
  attr_reader :inner_document
237
234
 
238
235
  def initialize column, cell_text, attributes = {}, opts = {}
239
236
  super column, :table_cell
237
+ @cursor = @reinitialize_args = nil
240
238
  @source_location = opts[:cursor].dup if @document.sourcemap
239
+ # NOTE: column is always set when parsing; may not be set when building table from the API
241
240
  if column
242
- cell_style = column.attributes['style'] unless (in_header_row = column.table.header_row?)
241
+ if (in_header_row = column.table.header_row?)
242
+ if in_header_row == :implicit && (cell_style = column.style || (attributes && attributes['style']))
243
+ @reinitialize_args = [column, cell_text, attributes && attributes.merge, opts] if cell_style == :asciidoc || cell_style == :literal
244
+ cell_style = nil
245
+ end
246
+ else
247
+ cell_style = column.style
248
+ end
243
249
  # REVIEW feels hacky to inherit all attributes from column
244
250
  update_attributes column.attributes
245
251
  end
@@ -306,8 +312,12 @@ class Table::Cell < AbstractBlock
306
312
  @content_model = :verbatim
307
313
  @subs = BASIC_SUBS
308
314
  else
309
- if normal_psv && (cell_text.start_with? '[[') && LeadingInlineAnchorRx =~ cell_text
310
- Parser.catalog_inline_anchor $1, $2, self, opts[:cursor], @document
315
+ if normal_psv
316
+ if in_header_row
317
+ @cursor = opts[:cursor] # used in deferred catalog_inline_anchor call
318
+ else
319
+ catalog_inline_anchor cell_text, opts[:cursor]
320
+ end
311
321
  end
312
322
  @content_model = :simple
313
323
  @subs = NORMAL_SUBS
@@ -316,6 +326,25 @@ class Table::Cell < AbstractBlock
316
326
  @style = cell_style
317
327
  end
318
328
 
329
+ def reinitialize has_header
330
+ if has_header
331
+ @reinitialize_args = nil
332
+ elsif @reinitialize_args
333
+ return Table::Cell.new(*@reinitialize_args)
334
+ else
335
+ @style = @attributes['style']
336
+ end
337
+ catalog_inline_anchor if @cursor
338
+ self
339
+ end
340
+
341
+ def catalog_inline_anchor cell_text = @text, cursor = nil
342
+ cursor, @cursor = @cursor, nil unless cursor
343
+ if (cell_text.start_with? '[[') && LeadingInlineAnchorRx =~ cell_text
344
+ Parser.catalog_inline_anchor $1, $2, self, cursor, @document
345
+ end
346
+ end
347
+
319
348
  # Public: Get the String text of this cell with substitutions applied.
320
349
  #
321
350
  # Used for cells in the head row as well as text-only (non-AsciiDoc) cells in
@@ -339,7 +368,7 @@ class Table::Cell < AbstractBlock
339
368
 
340
369
  # Public: Handles the body data (tbody, tfoot), applying styles and partitioning into paragraphs
341
370
  #
342
- # This method should not be used for cells in the head row or that have the literal or verse style.
371
+ # This method should not be used for cells in the head row or that have the literal style.
343
372
  #
344
373
  # Returns the converted String for this Cell
345
374
  def content