asciidoctor 2.0.10 → 2.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +89 -5
  3. data/LICENSE +1 -1
  4. data/README-de.adoc +4 -4
  5. data/README-fr.adoc +4 -4
  6. data/README-jp.adoc +4 -4
  7. data/README-zh_CN.adoc +6 -6
  8. data/README.adoc +14 -10
  9. data/asciidoctor.gemspec +3 -3
  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 +22 -20
  42. data/lib/asciidoctor.rb +33 -7
  43. data/lib/asciidoctor/abstract_block.rb +9 -4
  44. data/lib/asciidoctor/abstract_node.rb +16 -6
  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 +13 -12
  50. data/lib/asciidoctor/converter/docbook5.rb +3 -7
  51. data/lib/asciidoctor/converter/html5.rb +59 -42
  52. data/lib/asciidoctor/converter/manpage.rb +12 -11
  53. data/lib/asciidoctor/converter/template.rb +3 -0
  54. data/lib/asciidoctor/document.rb +23 -38
  55. data/lib/asciidoctor/extensions.rb +2 -2
  56. data/lib/asciidoctor/helpers.rb +17 -9
  57. data/lib/asciidoctor/load.rb +101 -101
  58. data/lib/asciidoctor/parser.rb +26 -23
  59. data/lib/asciidoctor/path_resolver.rb +14 -12
  60. data/lib/asciidoctor/reader.rb +14 -7
  61. data/lib/asciidoctor/rx.rb +5 -4
  62. data/lib/asciidoctor/substitutors.rb +57 -38
  63. data/lib/asciidoctor/syntax_highlighter.rb +8 -5
  64. data/lib/asciidoctor/syntax_highlighter/coderay.rb +1 -1
  65. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +12 -4
  66. data/lib/asciidoctor/syntax_highlighter/prettify.rb +7 -4
  67. data/lib/asciidoctor/syntax_highlighter/pygments.rb +2 -3
  68. data/lib/asciidoctor/syntax_highlighter/rouge.rb +15 -7
  69. data/lib/asciidoctor/table.rb +49 -20
  70. data/lib/asciidoctor/version.rb +1 -1
  71. data/man/asciidoctor.1 +6 -6
  72. data/man/asciidoctor.adoc +3 -3
  73. metadata +8 -8
@@ -570,17 +570,18 @@ class Reader
570
570
  #
571
571
  # data - A String Array or String of source data to be normalized.
572
572
  # opts - A Hash of options to control how lines are prepared.
573
- # :normalize - Enables line normalization, which coerces the encoding to UTF-8 and removes trailing whitespace
574
- # (optional, default: false).
573
+ # :normalize - Enables line normalization, which coerces the encoding to UTF-8 and removes trailing whitespace;
574
+ # :rstrip removes all trailing whitespace; :chomp removes trailing newline only (optional, not set).
575
575
  #
576
576
  # Returns A String Array of source lines. If the source data is an Array, this method returns a copy.
577
577
  def prepare_lines data, opts = {}
578
- if opts[:normalize]
579
- ::Array === data ? (Helpers.prepare_source_array data) : (Helpers.prepare_source_string data)
578
+ if (normalize = opts[:normalize])
579
+ trim_end = normalize == :chomp ? false : true
580
+ ::Array === data ? (Helpers.prepare_source_array data, trim_end) : (Helpers.prepare_source_string data, trim_end)
580
581
  elsif ::Array === data
581
582
  data.drop 0
582
583
  elsif data
583
- data.split LF, -1
584
+ data.chomp.split LF, -1
584
585
  else
585
586
  []
586
587
  end
@@ -717,7 +718,7 @@ class PreprocessorReader < Reader
717
718
  end
718
719
 
719
720
  # effectively fill the buffer
720
- if (@lines = prepare_lines data, normalize: true, condense: false, indent: attributes['indent']).empty?
721
+ if (@lines = prepare_lines data, normalize: @process_lines || :chomp, condense: @process_lines, indent: attributes['indent']).empty?
721
722
  pop_include
722
723
  else
723
724
  # FIXME we eventually want to handle leveloffset without affecting the lines
@@ -1060,7 +1061,13 @@ class PreprocessorReader < Reader
1060
1061
  return inc_path
1061
1062
  end
1062
1063
 
1064
+ if (enc = parsed_attrs['encoding']) && (::Encoding.find enc rescue nil)
1065
+ (read_mode_params = read_mode.split ':')[1] = enc
1066
+ read_mode = read_mode_params.join ':'
1067
+ end unless RUBY_ENGINE_OPAL
1068
+
1063
1069
  inc_linenos = inc_tags = nil
1070
+ # NOTE attrlist is nil if missing from include directive
1064
1071
  if attrlist
1065
1072
  if parsed_attrs.key? 'lines'
1066
1073
  inc_linenos = []
@@ -1148,7 +1155,7 @@ class PreprocessorReader < Reader
1148
1155
  active_tag, select = tag_stack.empty? ? [nil, base_select] : tag_stack[-1]
1149
1156
  elsif inc_tags.key? this_tag
1150
1157
  include_cursor = create_include_cursor inc_path, expanded_target, inc_lineno
1151
- if (idx = tag_stack.rindex {|key, _| key == this_tag })
1158
+ if (idx = tag_stack.rindex {|key,| key == this_tag })
1152
1159
  idx == 0 ? tag_stack.shift : (tag_stack.delete_at idx)
1153
1160
  logger.warn message_with_context %(mismatched end tag (expected '#{active_tag}' but found '#{this_tag}') at line #{inc_lineno} of include #{target_type}: #{inc_path}), source_location: cursor, include_location: include_cursor
1154
1161
  else
@@ -269,7 +269,7 @@ module Asciidoctor
269
269
  #
270
270
  # NOTE we only have to check as far as the blank character because we know it means non-whitespace follows.
271
271
  # IMPORTANT if this regexp does not agree with the regexp for each list type, the parser will hang.
272
- AnyListRx = %r(^(?:[ \t]*(?:-|\*\**|\.\.*|\u2022|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]|(?!//[^/])[ \t]*[^ \t]#{CC_ANY}*?(?::::{0,2}|;;)(?:$|[ \t])|<?\d+>[ \t]))
272
+ AnyListRx = %r(^(?:[ \t]*(?:-|\*\**|\.\.*|\u2022|\d+\.|[a-zA-Z]\.|[IVXivx]+\))[ \t]|(?!//[^/])[ \t]*[^ \t]#{CC_ANY}*?(?::::{0,2}|;;)(?:$|[ \t])|<(?:\d+|\.)>[ \t]))
273
273
 
274
274
  # Matches an unordered list item (one level for hyphens, up to 5 levels for asterisks).
275
275
  #
@@ -469,7 +469,7 @@ module Asciidoctor
469
469
  # footnoteref:[id,text] (legacy)
470
470
  # footnoteref:[id] (legacy)
471
471
  #
472
- InlineFootnoteMacroRx = /\\?footnote(?:(ref):|:([#{CC_WORD}-]+)?)\[(?:|(#{CC_ALL}*?[^\\]))\]/m
472
+ InlineFootnoteMacroRx = /\\?footnote(?:(ref):|:([#{CC_WORD}-]+)?)\[(?:|(#{CC_ALL}*?[^\\]))\](?!<\/a>)/m
473
473
 
474
474
  # Matches an image or icon inline macro.
475
475
  #
@@ -514,9 +514,10 @@ module Asciidoctor
514
514
  # https://github.com[GitHub]
515
515
  # <https://github.com>
516
516
  # link:https://github.com[]
517
+ # "https://github.com[]"
517
518
  #
518
519
  # FIXME revisit! the main issue is we need different rules for implicit vs explicit
519
- InlineLinkRx = %r((^|link:|#{CG_BLANK}|&lt;|[>\(\)\[\];])(\\?(?:https?|file|ftp|irc)://[^\s\[\]<]*([^\s.,\[\]<]))(?:\[(|#{CC_ALL}*?[^\\])\])?)m
520
+ InlineLinkRx = %r((^|link:|#{CG_BLANK}|&lt;|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://[^\s\[\]<]*([^\s.,\[\]<]))(?:\[(|#{CC_ALL}*?[^\\])\])?)m
520
521
 
521
522
  # Match a link or e-mail inline macro.
522
523
  #
@@ -551,7 +552,7 @@ module Asciidoctor
551
552
  # menu:View[Page Style > No Style]
552
553
  # menu:View[Page Style, No Style]
553
554
  #
554
- InlineMenuMacroRx = /\\?menu:(#{CG_WORD}|[#{CC_WORD}&][^\n\[]*[^\s\[])\[ *(?:|(#{CC_ALL}*?[^\\]))?\]/m
555
+ InlineMenuMacroRx = /\\?menu:(#{CG_WORD}|[#{CC_WORD}&][^\n\[]*[^\s\[])\[ *(?:|(#{CC_ALL}*?[^\\]))\]/m
555
556
 
556
557
  # Matches an implicit menu inline macro.
557
558
  #
@@ -542,14 +542,17 @@ module Substitutors
542
542
  end
543
543
 
544
544
  prefix, suffix = $1, ''
545
- # 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[])
546
546
  if $4
547
547
  prefix = '' if prefix == 'link:'
548
548
  text = $4
549
549
  else
550
- # invalid macro syntax (link: prefix w/o trailing square brackets)
551
- # FIXME we probably shouldn't even get here...our regex is doing too much
552
- 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
553
556
  text = ''
554
557
  case $3
555
558
  when ')'
@@ -591,7 +594,8 @@ module Substitutors
591
594
  unless text.empty?
592
595
  text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
593
596
  if !doc.compat_mode && (text.include? '=')
594
- 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, ''
595
599
  link_opts[:id] = attrs['id']
596
600
  end
597
601
 
@@ -637,7 +641,8 @@ module Substitutors
637
641
  text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
638
642
  if mailto
639
643
  if !doc.compat_mode && (text.include? ',')
640
- 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, ''
641
646
  link_opts[:id] = attrs['id']
642
647
  if attrs.key? 2
643
648
  if attrs.key? 3
@@ -648,7 +653,8 @@ module Substitutors
648
653
  end
649
654
  end
650
655
  elsif !doc.compat_mode && (text.include? '=')
651
- 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, ''
652
658
  link_opts[:id] = attrs['id']
653
659
  end
654
660
 
@@ -739,8 +745,8 @@ module Substitutors
739
745
  refid = $2
740
746
  if (text = $3)
741
747
  text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
742
- # NOTE if an equal sign (=) is present, parse text as attributes
743
- 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? '=')
744
750
  end
745
751
  end
746
752
 
@@ -804,7 +810,7 @@ module Substitutors
804
810
  # handles: id (in compat mode or when natural xrefs are disabled)
805
811
  elsif doc.compat_mode || !Compliance.natural_xrefs
806
812
  refid, target = fragment, %(##{fragment})
807
- 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]
808
814
  # handles: id
809
815
  elsif doc.catalog[:refs][fragment]
810
816
  refid, target = fragment, %(##{fragment})
@@ -843,19 +849,17 @@ module Substitutors
843
849
  end
844
850
 
845
851
  if id
846
- 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
847
856
  text = restore_passthroughs(normalize_text text, true, true)
848
857
  index = doc.counter('footnote-number')
849
858
  doc.register(:footnotes, Document::Footnote.new(index, id, text))
850
859
  type, target = :ref, nil
851
860
  else
852
- if (footnote = doc.footnotes.find {|candidate| candidate.id == id })
853
- index, text = footnote.index, footnote.text
854
- else
855
- logger.warn %(invalid footnote reference: #{id})
856
- index, text = nil, id
857
- end
858
- type, target, id = :xref, id, nil
861
+ logger.warn %(invalid footnote reference: #{id})
862
+ index, text = nil, id
859
863
  end
860
864
  elsif text
861
865
  text = restore_passthroughs(normalize_text text, true, true)
@@ -917,7 +921,7 @@ module Substitutors
917
921
  # use sub since it might be behind a line comment
918
922
  $&.sub RS, ''
919
923
  else
920
- 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
921
925
  end
922
926
  end
923
927
  end
@@ -945,7 +949,7 @@ module Substitutors
945
949
  if (linenums_mode = (attr? 'linenums') ? (doc_attrs[%(#{syntax_hl_name}-linenums-mode)] || :table).to_sym : nil)
946
950
  start_line_number = 1 if (start_line_number = (attr 'start', 1).to_i) < 1
947
951
  end
948
- 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'
949
953
 
950
954
  highlighted, source_offset = syntax_hl.highlight self, source, (attr 'language'),
951
955
  callouts: callout_marks,
@@ -968,9 +972,10 @@ module Substitutors
968
972
  #
969
973
  # source - The String source.
970
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)
971
976
  #
972
977
  # Returns an [Array] of unique, sorted line numbers.
973
- def resolve_lines_to_highlight source, spec
978
+ def resolve_lines_to_highlight source, spec, start = nil
974
979
  lines = []
975
980
  spec = spec.delete ' ' if spec.include? ' '
976
981
  ((spec.include? ',') ? (spec.split ',') : (spec.split ';')).map do |entry|
@@ -981,21 +986,22 @@ module Substitutors
981
986
  if (delim = (entry.include? '..') ? '..' : ((entry.include? '-') ? '-' : nil))
982
987
  from, delim, to = entry.partition delim
983
988
  to = (source.count LF) + 1 if to.empty? || (to = to.to_i) < 0
984
- line_nums = (from.to_i..to).to_a
985
- if negate
986
- lines -= line_nums
987
- else
988
- lines.concat line_nums
989
- end
990
- else
991
989
  if negate
992
- lines.delete entry.to_i
990
+ lines -= (from.to_i..to).to_a
993
991
  else
994
- lines << entry.to_i
992
+ lines |= (from.to_i..to).to_a
995
993
  end
994
+ elsif negate
995
+ lines.delete entry.to_i
996
+ elsif !lines.include?(line = entry.to_i)
997
+ lines << line
996
998
  end
997
999
  end
998
- 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
999
1005
  end
1000
1006
 
1001
1007
  # Public: Extract the passthrough text from the document for reinsertion after processing.
@@ -1321,10 +1327,23 @@ module Substitutors
1321
1327
 
1322
1328
  private
1323
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
+
1324
1343
  # Internal: Extract the callout numbers from the source to prepare it for syntax highlighting.
1325
1344
  def extract_callouts source
1326
1345
  callout_marks = {}
1327
- lineno = 0
1346
+ autonum = lineno = 0
1328
1347
  last_lineno = nil
1329
1348
  callout_rx = (attr? 'line-comment') ? CalloutExtractRxMap[attr 'line-comment'] : CalloutExtractRx
1330
1349
  # extract callout marks, indexed by line number
@@ -1336,7 +1355,7 @@ module Substitutors
1336
1355
  # use sub since it might be behind a line comment
1337
1356
  $&.sub RS, ''
1338
1357
  else
1339
- (callout_marks[lineno] ||= []) << [$1, $4]
1358
+ (callout_marks[lineno] ||= []) << [$1 || ($3 == '--' ? ['<!--', '-->'] : nil), $4 == '.' ? (autonum += 1).to_s : $4]
1340
1359
  last_lineno = lineno
1341
1360
  ''
1342
1361
  end
@@ -1358,15 +1377,15 @@ module Substitutors
1358
1377
  else
1359
1378
  preamble = ''
1360
1379
  end
1361
- autonum = lineno = 0
1380
+ lineno = 0
1362
1381
  preamble + ((source.split LF, -1).map do |line|
1363
1382
  if (conums = callout_marks.delete lineno += 1)
1364
1383
  if conums.size == 1
1365
- guard, conum = conums[0]
1366
- %(#{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})
1367
1386
  else
1368
- %(#{line}#{conums.map do |guard_it, conum_it|
1369
- 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
1370
1389
  end.join ' '})
1371
1390
  end
1372
1391
  else
@@ -20,7 +20,7 @@ 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
  #
@@ -28,6 +28,7 @@ module SyntaxHighlighter
28
28
  def docinfo? location; end
29
29
 
30
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).
33
34
  # doc - The Document in which this syntax highlighter is being used.
@@ -139,7 +140,7 @@ module SyntaxHighlighter
139
140
  # name - The String name of the syntax highlighter to create.
140
141
  # backend - The String name of the backend for which this syntax highlighter is being used (default: 'html5').
141
142
  # opts - A Hash of options providing information about the context in which this syntax highlighter is used:
142
- # :doc - The Document for which this syntax highlighter was created.
143
+ # :document - The Document for which this syntax highlighter was created.
143
144
  #
144
145
  # Returns a [SyntaxHighlighter] instance for the specified name.
145
146
  def create name, backend = 'html5', opts = {}
@@ -235,9 +236,11 @@ module SyntaxHighlighter
235
236
  def format node, lang, opts
236
237
  class_attr_val = opts[:nowrap] ? %(#{@pre_class} highlight nowrap) : %(#{@pre_class} highlight)
237
238
  if (transform = opts[:transform])
238
- pre = { 'class' => class_attr_val }
239
- code = lang ? { 'data-lang' => lang } : {}
240
- 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
241
244
  %(<pre#{pre.map {|k, v| %[ #{k}="#{v}"] }.join}><code#{code.map {|k, v| %[ #{k}="#{v}"] }.join}>#{node.content}</code></pre>)
242
245
  else
243
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