Class: Metanorma::Standoc::LinkProtectPreprocessor

Inherits:
Asciidoctor::Extensions::Preprocessor
  • Object
show all
Defined in:
lib/metanorma/standoc/macros.rb

Overview

refer github.com/asciidoctor/asciidoctor/blob/main/lib/asciidoctor/substitutors.rb Not using TreeProcessor because that is still too close to inline expressions being processed on access (e.g. titles)

Constant Summary collapse

PASS_INLINE_MACROS =
%w(pass pass-format identifier std-link stem)
.join("|").freeze
PASS_INLINE_MACRO_STR =
<<~REGEX.freeze
  (
    \\b(?<![-\\\\])                        # word-separator, no hyphen or backslash
    (?:                                    # don't capture these!
      (?:#{PASS_INLINE_MACROS}):[^\\s\\[]* | # macro name, :, second key. OR:
      span:uri \\b [^\\s\\[]*              # span:uri, third key
    )
    \\[.*?(?<!\\\\)\\]                     # [ ... ] not preceded by \\
  )
REGEX
PASS_INLINE_MACRO_RX =
/#{PASS_INLINE_MACRO_STR}/xo
InlineLinkRx =

InlineLinkRx = %r((^|link:|#CG_BLANK|&lt;|[>();“‘])(\?(?:https?|file|ftp|irc)://)(?:([^s]+)[(|#CC_ALL*?[^\])]|([^s<]*([^s,.?!<)]))))m

%r((^|(?<![-\\])\blink:(?!\+)|\p{Blank}|&lt;|[<>\(\)\[\];"'])((?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)(?:(\[(|.*?[^\\])\])|([^\s\[\]<]*([^\s,.?!\[\]<\)])))))m
BRACKETS =
{
  "<" => ">",
  "&lt;" => "&gt;",
  "[" => "]",
  '"' => '"',
  "'" => "'",
}.freeze
InlineLinkMacroRx1 =

InlineLinkMacroRx = /\?(?:link|(mailto)):(|[^:s[^s[]*)[(|#CC_ALL*?)]/m

<<~REGEX.freeze
  (\\\\?)(\\b(?<!-)                  # optional backslash, no hyphen, word boundary
    (?:link|mailto):)              # link: or mailto:
  (?!\\+)                          # no link:+ passthrough
  (|[^:\\s\\[][^\\s\\[]*)          # link: ... up to [
  (\\[(|.*?[^\\\\])\\])            # [ ... ], no ]
REGEX
InlineLinkMacroRx =
/#{InlineLinkMacroRx1}/x

Instance Method Summary collapse

Instance Method Details



119
120
121
122
123
124
125
# File 'lib/metanorma/standoc/macros.rb', line 119

def inlinelink(text)
  text.include?("://") or return text
  /^\[.*\]\s*$/.match?(text) and return text
  pass_inline_split(text) do |x|
    inlinelink_escape(x)
  end.join
end


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/metanorma/standoc/macros.rb', line 127

def inlinelink_escape(text)
  text.gsub(InlineLinkRx) do
    p = $1 and s = $2 and body = $3
    suffix = $4.nil? ? "[]" : ""
    wrapper = $6
    if (!/^(&lt;|[<\(\["'])$/.match?($1) || $6 != BRACKETS[$1]) && $4.nil?
      body += $6
      wrapper = ""
    end
    # body, suffix = $4.nil? ? [$3 + $6, "[]"] : [$3, ""]
    b = linkcontents_escape($4)
    if p == "link:"
      "#{p}++#{s}#{body}++#{b}#{suffix}"
    else
      "#{p}link:++#{s}#{body}++#{b}#{suffix}#{wrapper}"
    end
  end
end

#inlinelinkmacro(text) ⇒ Object



179
180
181
182
183
184
185
186
187
# File 'lib/metanorma/standoc/macros.rb', line 179

def inlinelinkmacro(text)
  (text.include?("[") &&
    ((text.include? "link:") || (text.include? "ilto:"))) or return text
  pass_inline_split(text) do |x|
    x.gsub(InlineLinkMacroRx) do
      "#{$1}#{$2}++#{$3}++#{linkcontents_escape($4)}"
    end
  end.join
end

#linkcontents_escape(text) ⇒ Object

because links are escaped, https within link text also need to be escaped, # otherwise they will be treated as links themselves



156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/metanorma/standoc/macros.rb', line 156

def linkcontents_escape(text)
  text.nil? and return nil
  text
    # .gsub(InlineLinkMacroRx) do
    # $1.empty? ? "\\#{$2}#{$3}#{$4}" : text
    # end
    .gsub(InlineLinkRx) do
    esc = $1 == "link:" ? "" : "\\"
    x = $4 || "#{$5}#{$6}"
    "#{$1}#{esc}#{$2}#{$3}#{x}"
  end
end

#pass_inline_split(text) ⇒ Object



109
110
111
112
113
# File 'lib/metanorma/standoc/macros.rb', line 109

def pass_inline_split(text)
  text.split(PASS_INLINE_MACRO_RX).each.map do |x|
    PASS_INLINE_MACRO_RX.match?(x) ? x : yield(x)
  end
end

#process(document, reader) ⇒ Object



84
85
86
87
88
89
90
91
92
# File 'lib/metanorma/standoc/macros.rb', line 84

def process(document, reader)
  p = Metanorma::Utils::LineStatus.new
  lines = reader.lines.map do |t|
    p.process(t)
    !p.pass && t.include?(":") and t = inlinelinkmacro(inlinelink(t))
    t
  end
  ::Asciidoctor::PreprocessorReader.new document, lines
end