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.freeze
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.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.freeze

Instance Method Summary collapse

Instance Method Details

#initObject



77
78
79
80
81
82
83
84
85
86
# File 'lib/metanorma/standoc/macros.rb', line 77

def init
  pass = true # process as passthrough: init = true until
  # hit end of doc header
  is_delim = false # current line is a no-substititon block delimiter
  pass_delim = false # current line is a passthrough delimiter
  delimln = "" # delimiter line of current block(s);
  # init value looks for end of doc header
  { pass: pass, is_delim: is_delim, pass_delim: pass_delim,
    delimln: delimln }
end


147
148
149
150
151
152
153
# File 'lib/metanorma/standoc/macros.rb', line 147

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


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

def inlinelink_escape(text)
  text.gsub(InlineLinkRx) do
    body, suffix = $4.nil? ? [$3 + $6, "[]"] : [$3, ""]
    p = $1 and s = $2 and b = $4
    if p == "link:" then "#{p}++#{s}#{body}++#{b}#{suffix}"
    elsif p == "<"
      "#{p}link:++#{s}#{body.sub(/>$/, '')}++#{b}#{suffix}>"
    else "#{p}link:++#{s}#{body}++#{b}#{suffix}"
    end
  end
end

#inlinelinkmacro(text) ⇒ Object



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

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}"
    end
  end.join
end

#pass_inline_split(text) ⇒ Object



137
138
139
140
141
# File 'lib/metanorma/standoc/macros.rb', line 137

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

#pass_status(status, text) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/metanorma/standoc/macros.rb', line 98

def pass_status(status, text)
  text == "++++" && !status[:delimln] and status[:pass] = !status[:pass]
  status[:midline_docattr] && !/^:[^ :]+: /.match?(text) and
    status[:midline_docattr] = false
  if (status[:is_delim] && /^(-+|\*+|=+|_+)$/.match?(text)) ||
      (!status[:is_delim] && !status[:delimln] && text == "----")
    status[:delimln] = text
    status[:pass] = true
  elsif status[:pass_delim]
    status[:delimln] = "" # end of paragraph for paragraph with [pass]
  elsif status[:delimln] && text == status[:delimln]
    status[:pass] = false
    status[:delimln] = nil
  elsif /^:[^ :]+: /.match?(text) &&
      (status[:prev_line].empty? || status[:midline_docattr])
    status[:pass] = true
    status[:midline_docattr] = true
  end
  status[:is_delim] = /^\[(source|listing|literal|pass)\b/.match?(text)
  status[:pass_delim] = /^\[(pass)\b/.match?(text)
  status[:prev_line] = text.strip
  status
end

#process(document, reader) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/metanorma/standoc/macros.rb', line 88

def process(document, reader)
  p = init
  lines = reader.lines.map do |t|
    p = pass_status(p, t.rstrip)
    !p[:pass] && t.include?(":") and t = inlinelinkmacro(inlinelink(t))
    t
  end
  ::Asciidoctor::PreprocessorReader.new document, lines
end