• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
2
3include ::Asciidoctor
4
5module Asciidoctor
6
7# This addition to the parser class overrides the "is_delimited_block?"
8# method of the core parser, adding a new block delimiter of "~~~~" for open
9# blocks, which can be extended to an arbitrary number of braces to allow
10# nesting them, which is a limitation of the existing "only two dashes"
11# delimiter: https://github.com/asciidoctor/asciidoctor/issues/1121
12# The choice of tildes is based on comments in that bug.
13
14class Parser
15  # Storing the original method so we can still call it from the overriding
16  # version
17  @OLD_is_delimited_block = method(:is_delimited_block?)
18
19  # Logic here matches the original Parser#is_delimited_block? method, see
20  # there for details of base implementation.
21  def self.is_delimited_block? line, return_match_data = false
22    # Quick check for a single brace character before forwarding to the
23    # original parser method.
24    if line[0] != '~'
25      return @OLD_is_delimited_block.(line, return_match_data)
26    else
27      line_len = line.length
28      if line_len <= 4
29        tip = line
30        tl = line_len
31      else
32        tip = line[0..3]
33        tl = 4
34      end
35
36      # Hardcoded tilde delimiter, since that's the only thing this
37      # function deals with.
38      if tip == '~~~~'
39        # tip is the full line when delimiter is minimum length
40        if tl < 4 || tl == line_len
41          if return_match_data
42            context = :open
43            masq = ['comment', 'example', 'literal', 'listing', 'pass', 'quote', 'sidebar', 'source', 'verse', 'admonition', 'abstract', 'partintro'].to_set
44            BlockMatchData.new(context, masq, tip, tip)
45          else
46            true
47          end
48        elsif %(#{tip}#{tip[-1..-1] * (line_len - tl)}) == line
49          if return_match_data
50            context = :open
51            masq = ['comment', 'example', 'literal', 'listing', 'pass', 'quote', 'sidebar', 'source', 'verse', 'admonition', 'abstract', 'partintro'].to_set
52            BlockMatchData.new(context, masq, tip, line)
53          else
54            true
55          end
56        else
57          nil
58        end
59      else
60        nil
61      end
62    end
63  end
64end
65
66end