asciidoctor 2.0.16 → 2.0.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -89,10 +89,10 @@ class Parser
89
89
  #
90
90
  # returns the Document object
91
91
  def self.parse(reader, document, options = {})
92
- block_attributes = parse_document_header(reader, document)
92
+ block_attributes = parse_document_header(reader, document, (header_only = options[:header_only]))
93
93
 
94
94
  # NOTE don't use a postfix conditional here as it's known to confuse JRuby in certain circumstances
95
- unless options[:header_only]
95
+ unless header_only
96
96
  while reader.has_more_lines?
97
97
  new_section, block_attributes = next_section(reader, document, block_attributes)
98
98
  if new_section
@@ -117,7 +117,7 @@ class Parser
117
117
  # which are automatically removed by the reader.
118
118
  #
119
119
  # returns the Hash of orphan block attributes captured above the header
120
- def self.parse_document_header(reader, document)
120
+ def self.parse_document_header(reader, document, header_only = false)
121
121
  # capture lines of block-level metadata and plow away comment lines that precede first block
122
122
  block_attrs = reader.skip_blank_lines ? (parse_block_metadata_lines reader, document) : {}
123
123
  doc_attrs = document.attributes
@@ -125,6 +125,7 @@ class Parser
125
125
  # special case, block title is not allowed above document title,
126
126
  # carry attributes over to the document body
127
127
  if (implicit_doctitle = is_next_line_doctitle? reader, block_attrs, doc_attrs['leveloffset']) && block_attrs['title']
128
+ doc_attrs['authorcount'] = 0
128
129
  return document.finalize_header block_attrs, false
129
130
  end
130
131
 
@@ -168,7 +169,7 @@ class Parser
168
169
  end
169
170
  block_attrs.clear
170
171
  (modified_attrs = document.instance_variable_get :@attributes_modified).delete 'doctitle'
171
- parse_header_metadata reader, document
172
+ parse_header_metadata reader, document, nil
172
173
  if modified_attrs.include? 'doctitle'
173
174
  if (val = doc_attrs['doctitle']).nil_or_empty? || val == doctitle_attr_val
174
175
  doc_attrs['doctitle'] = doctitle_attr_val
@@ -179,10 +180,19 @@ class Parser
179
180
  modified_attrs << 'doctitle'
180
181
  end
181
182
  document.register :refs, [doc_id, document] if doc_id
183
+ elsif (author = doc_attrs['author'])
184
+ author_metadata = process_authors author, true, false
185
+ author_metadata.delete 'authorinitials' if doc_attrs['authorinitials']
186
+ doc_attrs.update author_metadata
187
+ elsif (author = doc_attrs['authors'])
188
+ author_metadata = process_authors author, true
189
+ doc_attrs.update author_metadata
190
+ else
191
+ doc_attrs['authorcount'] = 0
182
192
  end
183
193
 
184
194
  # parse title and consume name section of manpage document
185
- parse_manpage_header reader, document, block_attrs if document.doctype == 'manpage'
195
+ parse_manpage_header reader, document, block_attrs, header_only if document.doctype == 'manpage'
186
196
 
187
197
  # NOTE block_attrs are the block-level attributes (not document attributes) that
188
198
  # precede the first line of content (document title, first section or first block)
@@ -192,7 +202,7 @@ class Parser
192
202
  # Public: Parses the manpage header of the AsciiDoc source read from the Reader
193
203
  #
194
204
  # returns Nothing
195
- def self.parse_manpage_header(reader, document, block_attributes)
205
+ def self.parse_manpage_header(reader, document, block_attributes, header_only = false)
196
206
  if ManpageTitleVolnumRx =~ (doc_attrs = document.attributes)['doctitle']
197
207
  doc_attrs['manvolnum'] = manvolnum = $2
198
208
  doc_attrs['mantitle'] = (((mantitle = $1).include? ATTR_REF_HEAD) ? (document.sub_attributes mantitle) : mantitle).downcase
@@ -209,6 +219,8 @@ class Parser
209
219
  doc_attrs['docname'] = manname
210
220
  doc_attrs['outfilesuffix'] = %(.#{manvolnum})
211
221
  end
222
+ elsif header_only
223
+ # done
212
224
  else
213
225
  reader.skip_blank_lines
214
226
  reader.save
@@ -452,7 +464,7 @@ class Parser
452
464
  end
453
465
 
454
466
  # The attributes returned here are orphaned attributes that fall at the end
455
- # of a section that need to get transfered to the next section
467
+ # of a section that need to get transferred to the next section
456
468
  # see "trailing block attributes transfer to the following section" in
457
469
  # test/attributes_test.rb for an example
458
470
  [section == parent ? nil : section, attributes.merge]
@@ -647,7 +659,7 @@ class Parser
647
659
  if (default_attrs = ext_config[:default_attrs])
648
660
  attributes.update(default_attrs) {|_, old_v| old_v }
649
661
  end
650
- if (block = extension.process_method[parent, target, attributes])
662
+ if (block = extension.process_method[parent, target, attributes]) && block != parent
651
663
  attributes.replace block.attributes
652
664
  break
653
665
  else
@@ -1038,12 +1050,12 @@ class Parser
1038
1050
  if (extension = options[:extension])
1039
1051
  # QUESTION do we want to delete the style?
1040
1052
  attributes.delete('style')
1041
- if (block = extension.process_method[parent, block_reader || (Reader.new lines), attributes.merge])
1053
+ if (block = extension.process_method[parent, block_reader || (Reader.new lines), attributes.merge]) && block != parent
1042
1054
  attributes.replace block.attributes
1043
- # FIXME if the content model is set to compound, but we only have simple in this context, then
1044
- # forcefully set the content_model to simple to prevent parsing blocks from children
1045
- # TODO document this behavior!!
1046
- if block.content_model == :compound && !(lines = block.lines).empty?
1055
+ # NOTE an extension can change the content model from :simple to :compound. It's up to the extension
1056
+ # to decide which one to use. The extension can consult the cloaked-context attribute to determine
1057
+ # if the input is a paragraph or delimited block.
1058
+ if block.content_model == :compound && Block === block && !(lines = block.lines).empty?
1047
1059
  content_model = :compound
1048
1060
  block_reader = Reader.new lines
1049
1061
  end
@@ -1510,7 +1522,7 @@ class Parser
1510
1522
  break
1511
1523
  end
1512
1524
  else # only dlist in need of item text, so slurp it up!
1513
- # pop the blank line so it's not interpretted as a list continuation
1525
+ # pop the blank line so it's not interpreted as a list continuation
1514
1526
  buffer.pop unless within_nested_list
1515
1527
  buffer << this_line
1516
1528
  has_text = true
@@ -1769,38 +1781,31 @@ class Parser
1769
1781
  # parse_header_metadata(Reader.new data, nil, normalize: true)
1770
1782
  # # => { 'author' => 'Author Name', 'firstname' => 'Author', 'lastname' => 'Name', 'email' => 'author@example.org',
1771
1783
  # # 'revnumber' => '1.0', 'revdate' => '2012-12-21', 'revremark' => 'Coincide w/ end of world.' }
1772
- def self.parse_header_metadata(reader, document = nil)
1784
+ def self.parse_header_metadata reader, document = nil, retrieve = true
1773
1785
  doc_attrs = document && document.attributes
1774
1786
  # NOTE this will discard any comment lines, but not skip blank lines
1775
1787
  process_attribute_entries reader, document
1776
1788
 
1777
- metadata, implicit_author, implicit_authorinitials = implicit_authors = {}, nil, nil
1778
-
1779
1789
  if reader.has_more_lines? && !reader.next_line_empty?
1780
- unless (author_metadata = process_authors reader.read_line).empty?
1781
- if document
1782
- # apply header subs and assign to document
1783
- author_metadata.each do |key, val|
1784
- # NOTE the attributes substitution only applies for the email record
1785
- doc_attrs[key] = ::String === val ? (document.apply_header_subs val) : val unless doc_attrs.key? key
1786
- end
1787
-
1788
- implicit_author = doc_attrs['author']
1789
- implicit_authorinitials = doc_attrs['authorinitials']
1790
- implicit_authors = doc_attrs['authors']
1790
+ authorcount = (implicit_author_metadata = process_authors reader.read_line).delete 'authorcount'
1791
+ if document && (doc_attrs['authorcount'] = authorcount) > 0
1792
+ implicit_author_metadata.each do |key, val|
1793
+ # apply header subs and assign to document; attributes substitution only relevant for email
1794
+ doc_attrs[key] = document.apply_header_subs val unless doc_attrs.key? key
1791
1795
  end
1792
-
1793
- metadata = author_metadata
1796
+ implicit_author = doc_attrs['author']
1797
+ implicit_authorinitials = doc_attrs['authorinitials']
1798
+ implicit_authors = doc_attrs['authors']
1794
1799
  end
1800
+ implicit_author_metadata['authorcount'] = authorcount
1795
1801
 
1796
1802
  # NOTE this will discard any comment lines, but not skip blank lines
1797
1803
  process_attribute_entries reader, document
1798
1804
 
1799
- rev_metadata = {}
1800
-
1801
1805
  if reader.has_more_lines? && !reader.next_line_empty?
1802
1806
  rev_line = reader.read_line
1803
- if (match = RevisionInfoLineRx.match(rev_line))
1807
+ if (match = RevisionInfoLineRx.match rev_line)
1808
+ rev_metadata = {}
1804
1809
  rev_metadata['revnumber'] = match[1].rstrip if match[1]
1805
1810
  unless (component = match[2].strip).empty?
1806
1811
  # version must begin with 'v' if date is absent
@@ -1811,31 +1816,24 @@ class Parser
1811
1816
  end
1812
1817
  end
1813
1818
  rev_metadata['revremark'] = match[3].rstrip if match[3]
1819
+ if document && !rev_metadata.empty?
1820
+ # apply header subs and assign to document
1821
+ rev_metadata.each do |key, val|
1822
+ doc_attrs[key] = document.apply_header_subs val unless doc_attrs.key? key
1823
+ end
1824
+ end
1814
1825
  else
1815
1826
  # throw it back
1816
1827
  reader.unshift_line rev_line
1817
1828
  end
1818
1829
  end
1819
1830
 
1820
- unless rev_metadata.empty?
1821
- if document
1822
- # apply header subs and assign to document
1823
- rev_metadata.each do |key, val|
1824
- unless doc_attrs.key? key
1825
- doc_attrs[key] = document.apply_header_subs val
1826
- end
1827
- end
1828
- end
1829
-
1830
- metadata.update rev_metadata
1831
- end
1832
-
1833
1831
  # NOTE this will discard any comment lines, but not skip blank lines
1834
1832
  process_attribute_entries reader, document
1835
1833
 
1836
1834
  reader.skip_blank_lines
1837
1835
  else
1838
- author_metadata = {}
1836
+ implicit_author_metadata = {}
1839
1837
  end
1840
1838
 
1841
1839
  # process author attribute entries that override (or stand in for) the implicit author line
@@ -1852,7 +1850,7 @@ class Parser
1852
1850
  while doc_attrs.key? author_key
1853
1851
  # only use indexed author attribute if value is different
1854
1852
  # leaves corner case if line matches with underscores converted to spaces; use double space to force
1855
- if (author_override = doc_attrs[author_key]) == author_metadata[author_key]
1853
+ if (author_override = doc_attrs[author_key]) == implicit_author_metadata[author_key]
1856
1854
  authors << nil
1857
1855
  sparse = true
1858
1856
  else
@@ -1866,20 +1864,24 @@ class Parser
1866
1864
  authors.each_with_index do |author, idx|
1867
1865
  next if author
1868
1866
  authors[idx] = [
1869
- author_metadata[%(firstname_#{name_idx = idx + 1})],
1870
- author_metadata[%(middlename_#{name_idx})],
1871
- author_metadata[%(lastname_#{name_idx})]
1867
+ implicit_author_metadata[%(firstname_#{name_idx = idx + 1})],
1868
+ implicit_author_metadata[%(middlename_#{name_idx})],
1869
+ implicit_author_metadata[%(lastname_#{name_idx})]
1872
1870
  ].compact.map {|it| it.tr ' ', '_' }.join ' '
1873
1871
  end if sparse
1874
1872
  # process as names only
1875
1873
  author_metadata = process_authors authors, true, false
1876
1874
  else
1877
- author_metadata = {}
1875
+ author_metadata = { 'authorcount' => 0 }
1878
1876
  end
1879
1877
  end
1880
1878
 
1881
- if author_metadata.empty?
1882
- metadata['authorcount'] ||= (doc_attrs['authorcount'] = 0)
1879
+ if author_metadata['authorcount'] == 0
1880
+ if authorcount
1881
+ author_metadata = nil
1882
+ else
1883
+ doc_attrs['authorcount'] = 0
1884
+ end
1883
1885
  else
1884
1886
  doc_attrs.update author_metadata
1885
1887
 
@@ -1890,7 +1892,7 @@ class Parser
1890
1892
  end
1891
1893
  end
1892
1894
 
1893
- metadata
1895
+ implicit_author_metadata.merge rev_metadata.to_h, author_metadata.to_h if retrieve
1894
1896
  end
1895
1897
 
1896
1898
  # Internal: Parse the author line into a Hash of author metadata
@@ -690,7 +690,7 @@ class PreprocessorReader < Reader
690
690
  # only process lines in AsciiDoc files
691
691
  if (@process_lines = file.end_with?(*ASCIIDOC_EXTENSIONS.keys))
692
692
  # NOTE registering the include with a nil value tracks it while not making it visible to interdocument xrefs
693
- @includes[path.slice 0, (path.rindex '.')] = attributes['partial-option'] ? nil : true
693
+ @includes[path.slice 0, (path.rindex '.')] ||= attributes['partial-option'] ? nil : true
694
694
  end
695
695
  else
696
696
  @dir = '.'
@@ -698,7 +698,7 @@ class PreprocessorReader < Reader
698
698
  @process_lines = true
699
699
  if (@path = path)
700
700
  # NOTE registering the include with a nil value tracks it while not making it visible to interdocument xrefs
701
- @includes[Helpers.rootname path] = attributes['partial-option'] ? nil : true
701
+ @includes[Helpers.rootname path] ||= attributes['partial-option'] ? nil : true
702
702
  else
703
703
  @path = '<stdin>'
704
704
  end
@@ -949,7 +949,7 @@ class PreprocessorReader < Reader
949
949
  if no_target
950
950
  # the text in brackets must match a conditional expression
951
951
  if text && EvalExpressionRx =~ text.strip
952
- # NOTE assignments must happen before call to resolve_expr_val for compatiblity with Opal
952
+ # NOTE assignments must happen before call to resolve_expr_val for compatibility with Opal
953
953
  lhs = $1
954
954
  # regex enforces a restricted set of math-related operations (==, !=, <=, >=, <, >)
955
955
  op = $2
@@ -1035,7 +1035,7 @@ class PreprocessorReader < Reader
1035
1035
  # however, be friendly and at least make it a link to the source document
1036
1036
  elsif doc.safe >= SafeMode::SECURE
1037
1037
  # FIXME we don't want to use a link macro if we are in a verbatim context
1038
- replace_next_line %(link:#{expanded_target}[])
1038
+ replace_next_line %(link:#{expanded_target}[role=include])
1039
1039
  elsif @maxdepth
1040
1040
  if @include_stack.size >= @maxdepth[:curr]
1041
1041
  logger.error message_with_context %(maximum include depth of #{@maxdepth[:rel]} exceeded), source_location: cursor
@@ -1125,7 +1125,7 @@ class PreprocessorReader < Reader
1125
1125
  push_include inc_lines, inc_path, relpath, inc_offset, parsed_attrs
1126
1126
  end
1127
1127
  elsif inc_tags
1128
- inc_lines, inc_offset, inc_lineno, tag_stack, tags_used, active_tag = [], nil, 0, [], ::Set.new, nil
1128
+ inc_lines, inc_offset, inc_lineno, tag_stack, tags_selected, active_tag = [], nil, 0, [], ::Set.new, nil
1129
1129
  if inc_tags.key? '**'
1130
1130
  select = base_select = inc_tags.delete '**'
1131
1131
  if inc_tags.key? '*'
@@ -1164,9 +1164,9 @@ class PreprocessorReader < Reader
1164
1164
  end
1165
1165
  end
1166
1166
  elsif inc_tags.key? this_tag
1167
- tags_used << this_tag
1167
+ tags_selected << this_tag if (select = inc_tags[this_tag])
1168
1168
  # QUESTION should we prevent tag from being selected when enclosing tag is excluded?
1169
- tag_stack << [(active_tag = this_tag), (select = inc_tags[this_tag]), inc_lineno]
1169
+ tag_stack << [(active_tag = this_tag), select, inc_lineno]
1170
1170
  elsif !wildcard.nil?
1171
1171
  select = active_tag && !select ? false : wildcard
1172
1172
  tag_stack << [(active_tag = this_tag), select, inc_lineno]
@@ -1187,7 +1187,7 @@ class PreprocessorReader < Reader
1187
1187
  logger.warn message_with_context %(detected unclosed tag '#{tag_name}' starting at line #{tag_lineno} of include #{target_type}: #{inc_path}), source_location: cursor, include_location: (create_include_cursor inc_path, expanded_target, tag_lineno)
1188
1188
  end
1189
1189
  end
1190
- unless (missing_tags = inc_tags.keys - tags_used.to_a).empty?
1190
+ unless (missing_tags = inc_tags.keep_if {|_, v| v }.keys - tags_selected.to_a).empty?
1191
1191
  logger.warn message_with_context %(tag#{missing_tags.size > 1 ? 's' : ''} '#{missing_tags.join ', '}' not found in include #{target_type}: #{inc_path}), source_location: cursor
1192
1192
  end
1193
1193
  shift
@@ -1232,7 +1232,7 @@ class PreprocessorReader < Reader
1232
1232
  def resolve_include_path target, attrlist, attributes
1233
1233
  doc = @document
1234
1234
  if (Helpers.uriish? target) || (::String === @dir ? nil : (target = %(#{@dir}/#{target})))
1235
- return replace_next_line %(link:#{target}[#{attrlist}]) unless doc.attr? 'allow-uri-read'
1235
+ return replace_next_line %(link:#{target}[role=include]) unless doc.attr? 'allow-uri-read'
1236
1236
  if doc.attr? 'cache-uri'
1237
1237
  # caching requires the open-uri-cached gem to be installed
1238
1238
  # processing will be automatically aborted if these libraries can't be opened
@@ -1280,27 +1280,22 @@ class PreprocessorReader < Reader
1280
1280
 
1281
1281
  # Private: Ignore front-matter, commonly used in static site generators
1282
1282
  def skip_front_matter! data, increment_linenos = true
1283
- front_matter = nil
1284
- if data[0] == '---'
1285
- original_data = data.drop 0
1286
- data.shift
1287
- front_matter = []
1283
+ return unless (delim = data[0]) == '---'
1284
+ original_data = data.drop 0
1285
+ data.shift
1286
+ front_matter = []
1287
+ @lineno += 1 if increment_linenos
1288
+ until (eof = data.empty?) || data[0] == delim
1289
+ front_matter << data.shift
1288
1290
  @lineno += 1 if increment_linenos
1289
- while !data.empty? && data[0] != '---'
1290
- front_matter << data.shift
1291
- @lineno += 1 if increment_linenos
1292
- end
1293
-
1294
- if data.empty?
1295
- data.unshift(*original_data)
1296
- @lineno = 0 if increment_linenos
1297
- front_matter = nil
1298
- else
1299
- data.shift
1300
- @lineno += 1 if increment_linenos
1301
- end
1302
1291
  end
1303
-
1292
+ if eof
1293
+ data.unshift(*original_data)
1294
+ @lineno -= original_data.size if increment_linenos
1295
+ return
1296
+ end
1297
+ data.shift
1298
+ @lineno += 1 if increment_linenos
1304
1299
  front_matter
1305
1300
  end
1306
1301
 
@@ -407,7 +407,7 @@ module Asciidoctor
407
407
  # gist::123456[]
408
408
  #
409
409
  #--
410
- # NOTE we've relaxed the match for target to accomodate the short format (e.g., name::[attrlist])
410
+ # NOTE we've relaxed the match for target to accommodate the short format (e.g., name::[attrlist])
411
411
  CustomBlockMacroRx = /^(#{CG_WORD}[#{CC_WORD}-]*)::(|\S|\S#{CC_ANY}*?\S)\[(#{CC_ANY}+)?\]$/
412
412
 
413
413
  # Matches an image, video or audio block macro.
@@ -716,7 +716,11 @@ module Asciidoctor
716
716
  #
717
717
  # not c:/sample.adoc or c:\sample.adoc
718
718
  #
719
- UriSniffRx = %r(^#{CG_ALPHA}[#{CC_ALNUM}.+-]+:/{0,2})
719
+ if RUBY_ENGINE == 'opal'
720
+ UriSniffRx = %r(^#{CG_ALPHA}[#{CC_ALNUM}.+-]+:/{0,2})
721
+ else
722
+ UriSniffRx = %r(\A#{CG_ALPHA}[#{CC_ALNUM}.+-]+:/{0,2})
723
+ end
720
724
 
721
725
  # Detects XML tags
722
726
  XmlSanitizeRx = /<[^>]+>/
@@ -64,6 +64,13 @@ class Section < AbstractBlock
64
64
  Section.generate_id title, @document
65
65
  end
66
66
 
67
+ # Public: Check whether this Section has any child Section objects.
68
+ #
69
+ # Returns A [Boolean] to indicate whether this Section has child Section objects
70
+ def sections?
71
+ @next_section_index > 0
72
+ end
73
+
67
74
  # Public: Get the section number for the current Section
68
75
  #
69
76
  # The section number is a dot-separated String that uniquely describes the position of this
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Asciidoctor
3
3
  # Public: Methods to perform substitutions on lines of AsciiDoc text. This module
4
- # is intented to be mixed-in to Section and Block to provide operations for performing
4
+ # is intended to be mixed-in to Section and Block to provide operations for performing
5
5
  # the necessary substitutions.
6
6
  module Substitutors
7
7
  SpecialCharsRx = /[<&>]/
@@ -940,7 +940,7 @@ module Substitutors
940
940
  # process_callouts - a Boolean flag indicating whether callout marks should be located and substituted
941
941
  #
942
942
  # Returns the highlighted source code, if a syntax highlighter is defined on the document, otherwise the source with
943
- # verbatim substituions applied
943
+ # verbatim substitutions applied
944
944
  def highlight_source source, process_callouts
945
945
  # NOTE the call to highlight? is a defensive check since, normally, we wouldn't arrive here unless it returns true
946
946
  return sub_source source, process_callouts unless (syntax_hl = @document.syntax_highlighter) && syntax_hl.highlight?
@@ -1010,7 +1010,7 @@ module Substitutors
1010
1010
 
1011
1011
  # Public: Extract the passthrough text from the document for reinsertion after processing.
1012
1012
  #
1013
- # text - The String from which to extract passthrough fragements
1013
+ # text - The String from which to extract passthrough fragments
1014
1014
  #
1015
1015
  # Returns the String text with passthrough regions substituted with placeholders
1016
1016
  def extract_passthroughs text
@@ -1217,7 +1217,7 @@ module Substitutors
1217
1217
  end
1218
1218
  end
1219
1219
  return unless candidates
1220
- # weed out invalid options and remove duplicates (order is preserved; first occurence wins)
1220
+ # weed out invalid options and remove duplicates (order is preserved; first occurrence wins)
1221
1221
  resolved = candidates & SUB_OPTIONS[type]
1222
1222
  unless (candidates - resolved).empty?
1223
1223
  invalid = candidates - resolved
@@ -25,7 +25,7 @@ class SyntaxHighlighter::HighlightJsAdapter < SyntaxHighlighter::Base
25
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
26
  if (!hljs.initHighlighting.called) {
27
27
  hljs.initHighlighting.called = true
28
- ;[].slice.call(document.querySelectorAll('pre.highlight > code')).forEach(function (el) { hljs.highlightBlock(el) })
28
+ ;[].slice.call(document.querySelectorAll('pre.highlight > code[data-lang]')).forEach(function (el) { hljs.highlightBlock(el) })
29
29
  }
30
30
  </script>)
31
31
  end
@@ -36,7 +36,13 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
36
36
  node.sub_source source, false # handles nil response from ::Pygments::Lexer#highlight
37
37
  end
38
38
  elsif (highlighted = lexer.highlight source, options: highlight_opts)
39
- highlighted = highlighted.gsub StyledLinenoSpanTagRx, LinenoSpanTagCs if linenos && noclasses
39
+ if linenos
40
+ if noclasses
41
+ highlighted = highlighted.gsub StyledLinenoSpanTagRx, LinenoSpanTagCs
42
+ elsif highlighted.include? LegacyLinenoSpanStartTagCs
43
+ highlighted = highlighted.gsub LegacyLinenoSpanTagRx, LinenoSpanTagCs
44
+ end
45
+ end
40
46
  highlighted.sub WrapperTagRx, '\1'
41
47
  else
42
48
  node.sub_source source, false # handles nil response from ::Pygments::Lexer#highlight
@@ -114,6 +120,7 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
114
120
  end
115
121
  @@stylesheet_cache = ::Hash.new do |cache, key|
116
122
  if (stylesheet = ::Pygments.css BASE_SELECTOR, classprefix: TOKEN_CLASS_PREFIX, style: key)
123
+ stylesheet = stylesheet.slice (stylesheet.index BASE_SELECTOR), stylesheet.length unless stylesheet.start_with? BASE_SELECTOR
117
124
  @@stylesheet_cache = cache.merge key => stylesheet
118
125
  stylesheet
119
126
  end
@@ -122,7 +129,6 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
122
129
  DEFAULT_STYLE = 'default'
123
130
  BASE_SELECTOR = 'pre.pygments'
124
131
  TOKEN_CLASS_PREFIX = 'tok-'
125
-
126
132
  BaseStyleRx = /^#{BASE_SELECTOR.gsub '.', '\\.'} +\{([^}]+?)\}/
127
133
 
128
134
  private_constant :BASE_SELECTOR, :TOKEN_CLASS_PREFIX, :BaseStyleRx
@@ -133,8 +139,10 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
133
139
  include Loader # adds methods to instance
134
140
 
135
141
  CodeCellStartTagCs = '<td class="code">'
142
+ LegacyLinenoSpanStartTagCs = '<span class="lineno">'
143
+ LegacyLinenoSpanTagRx = %r(#{LegacyLinenoSpanStartTagCs}( *\d+) ?</span>)
136
144
  LinenoColumnStartTagsCs = '<td class="linenos"><div class="linenodiv"><pre>'
137
- LinenoSpanTagCs = '<span class="lineno">\1 </span>'
145
+ LinenoSpanTagCs = '<span class="linenos">\1</span>'
138
146
  PreTagCs = '<pre>\1</pre>'
139
147
  StyledLinenoColumnStartTagsRx = /<td><div class="linenodiv" style="[^"]+?"><pre style="[^"]+?">/
140
148
  StyledLinenoSpanTagRx = %r((?<=^|<span></span>)<span style="[^"]+">( *\d+) ?</span>)
@@ -144,6 +152,6 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
144
152
  # NOTE initial <span></span> preserves leading blank lines
145
153
  WrapperTagRx = %r(<div class="#{WRAPPER_CLASS}"><pre\b[^>]*?>(.*)</pre></div>\n*)m
146
154
 
147
- private_constant :CodeCellStartTagCs, :LinenoColumnStartTagsCs, :LinenoSpanTagCs, :PreTagCs, :StyledLinenoColumnStartTagsRx, :StyledLinenoSpanTagRx, :WrapperTagRx, :WRAPPER_CLASS
155
+ private_constant :CodeCellStartTagCs, :LegacyLinenoSpanStartTagCs, :LegacyLinenoSpanTagRx, :LinenoColumnStartTagsCs, :LinenoSpanTagCs, :PreTagCs, :StyledLinenoColumnStartTagsRx, :StyledLinenoSpanTagRx, :WrapperTagRx, :WRAPPER_CLASS
148
156
  end
149
157
  end
@@ -411,7 +411,7 @@ end
411
411
  # class are primarily responsible for tracking the buffer of a cell as the parser
412
412
  # moves through the lines of the table using tail recursion. When a cell boundary
413
413
  # is located, the previous cell is closed, an instance of Table::Cell is
414
- # instantiated, the row is closed if the cell satisifies the column count and,
414
+ # instantiated, the row is closed if the cell satisfies the column count and,
415
415
  # finally, a new buffer is allocated to track the next cell.
416
416
  class Table::ParserContext
417
417
  include Logging
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Asciidoctor
3
- VERSION = '2.0.16'
3
+ VERSION = '2.0.18'
4
4
  end
data/man/asciidoctor.1 CHANGED
@@ -1,13 +1,13 @@
1
1
  '\" t
2
2
  .\" Title: asciidoctor
3
- .\" Author: Dan Allen, Sarah White, Ryan Waldron
4
- .\" Generator: Asciidoctor 2.0.16
5
- .\" Date: 2021-08-03
3
+ .\" Author: Dan Allen, Sarah White
4
+ .\" Generator: Asciidoctor 2.0.17
5
+ .\" Date: 2022-01-05
6
6
  .\" Manual: Asciidoctor Manual
7
- .\" Source: Asciidoctor 2.0.16
7
+ .\" Source: Asciidoctor 2.0.17
8
8
  .\" Language: English
9
9
  .\"
10
- .TH "ASCIIDOCTOR" "1" "2021-08-03" "Asciidoctor 2.0.16" "Asciidoctor Manual"
10
+ .TH "ASCIIDOCTOR" "1" "2022-01-05" "Asciidoctor 2.0.17" "Asciidoctor Manual"
11
11
  .ie \n(.g .ds Aq \(aq
12
12
  .el .ds Aq '
13
13
  .ss \n[.ss] 0
@@ -171,8 +171,8 @@ Matching templates found in subsequent directories override ones previously disc
171
171
  .sp
172
172
  \fB\-\-failure\-level\fP=\fILEVEL\fP
173
173
  .RS 4
174
- The minimum logging level that triggers a non\-zero exit code (failure).
175
- If this option is not set (default: FATAL), the program exits with exit code zero even if warnings or errors have been logged.
174
+ Set the minimum logging level (default: FATAL) that yields a non\-zero exit code (i.e., failure).
175
+ If this option is not set, the program exits with a zero exit code even if warnings or errors have been logged.
176
176
  .RE
177
177
  .sp
178
178
  \fB\-q, \-\-quiet\fP
@@ -206,6 +206,7 @@ Print timings report to stderr (time to read, parse, and convert).
206
206
  Print a help message.
207
207
  Show the command usage if \fITOPIC\fP is not specified or recognized.
208
208
  Dump the Asciidoctor man page (in troff/groff format) if \fITOPIC\fP is \fImanpage\fP.
209
+ Print an AsciiDoc syntax crib sheet (in AsciiDoc) if \fITOPIC\fP is \fIsyntax\fP.
209
210
  .RE
210
211
  .sp
211
212
  \fB\-V, \-\-version\fP
@@ -238,30 +239,28 @@ Refer to the \fBAsciidoctor\fP issue tracker at \c
238
239
  .URL "https://github.com/asciidoctor/asciidoctor/issues?q=is%3Aopen" "" "."
239
240
  .SH "AUTHORS"
240
241
  .sp
241
- \fBAsciidoctor\fP was written by Dan Allen, Ryan Waldron, Jason Porter, Nick Hengeveld, and other contributors.
242
+ \fBAsciidoctor\fP is led and maintained by Dan Allen and Sarah White and has received contributions from many individuals in the Asciidoctor community.
243
+ The project was started in 2012 by Ryan Waldron based on a prototype written by Nick Hengeveld for the Git website.
244
+ Jason Porter wrote the first implementation of the CLI interface provided by this command.
242
245
  .sp
243
- \fBAsciiDoc\fP was written by Stuart Rackham and has received contributions from many other individuals.
246
+ \fBAsciiDoc.py\fP was created by Stuart Rackham and has received contributions from many individuals in the AsciiDoc.py community.
244
247
  .SH "RESOURCES"
245
248
  .sp
246
- \fBProject web site:\fP \c
249
+ \fBProject website:\fP \c
247
250
  .URL "https://asciidoctor.org" "" ""
248
251
  .sp
249
- \fBGit source repository on GitHub:\fP \c
250
- .URL "https://github.com/asciidoctor/asciidoctor" "" ""
251
- .sp
252
- \fBGitHub organization:\fP \c
253
- .URL "https://github.com/asciidoctor" "" ""
252
+ \fBProject documentation:\fP \c
253
+ .URL "https://docs.asciidoctor.org" "" ""
254
254
  .sp
255
- \fBDiscussion list / forum:\fP \c
256
- .URL "http://discuss.asciidoctor.org" "" ""
257
- .SH "COPYING"
255
+ \fBCommunity chat:\fP \c
256
+ .URL "https://chat.asciidoctor.org" "" ""
258
257
  .sp
259
- Copyright (C) 2012\-present Dan Allen, Ryan Waldron, and the Asciidoctor Project.
260
- Free use of this software is granted under the terms of the MIT License.
261
- .SH "AUTHORS"
262
- .sp
263
- Dan Allen
258
+ \fBSource repository:\fP \c
259
+ .URL "https://github.com/asciidoctor/asciidoctor" "" ""
264
260
  .sp
265
- Sarah White
261
+ \fBMailing list archive:\fP \c
262
+ .URL "https://discuss.asciidoctor.org" "" ""
263
+ .SH "COPYING"
266
264
  .sp
267
- Ryan Waldron
265
+ Copyright (C) 2012\-present Dan Allen, Sarah White, Ryan Waldron, and the individual contributors to Asciidoctor.
266
+ Use of this software is granted under the terms of the MIT License.