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