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