Class: Metanorma::Standoc::MonospaceProtectPreprocessor
- Inherits:
-
Asciidoctor::Extensions::Preprocessor
- Object
- Asciidoctor::Extensions::Preprocessor
- Metanorma::Standoc::MonospaceProtectPreprocessor
- Defined in:
- lib/metanorma/converter/macros_nosub.rb
Overview
protect monospace text from character substitutions
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: [^\\s\\[]* # any span: macro (e.g. span:uri, # span:note.display): protect its # bracketed content from URL/link # rewriting so an injected link:[] # can't close the span early ) \\[.*?(?<!\\\\)\\] # [ ... ] not preceded by \\ ) REGEX
- PASS_INLINE_MACRO_RX =
/#{PASS_INLINE_MACRO_STR}/xo- MonospaceRx =
Regex to match single or double backticks with content Matches:
textortextAvoids: escaped backticks ` Avoids: the backticks of Asciidoc smart-quote markup "...", where a backtick abuts an enclosing " (the leading (?<![\"]) and the (?!") guard). The (?!") guard is suppressed when the backtick run sits at a genuine monospace boundary (start, whitespace, or opening bracket), so monospace whose content itself begins with " — e.g."quote" A's— is still protected from character replacements. / (?<![\\"]) (`{1,2}) (?: (?!") | (?<=[\s(\[{<]`) | (?<=[\s(\[{<]``) | (?<=\A`) | (?<=\A``) ) (.+?) (?<!\\) \1 /x
Instance Method Summary collapse
- #inlinemonospace(text) ⇒ Object
- #monospace_escape(text) ⇒ Object
- #pass_inline_split(text) ⇒ Object
- #process(document, reader) ⇒ Object
Instance Method Details
#inlinemonospace(text) ⇒ Object
168 169 170 171 172 173 174 |
# File 'lib/metanorma/converter/macros_nosub.rb', line 168 def inlinemonospace(text) /(?<!")`(?!")/.match?(text) or return text /^\[.*\]\s*$/.match?(text) and return text pass_inline_split(text) do |x| monospace_escape(x) end.join end |
#monospace_escape(text) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/metanorma/converter/macros_nosub.rb', line 176 def monospace_escape(text) text.gsub(MonospaceRx) do backticks = $1 content = $2 # Skip if content already starts with ++ (already protected) if content.start_with?("++") && content.end_with?("++") "#{backticks}#{content}#{backticks}" else # Protect content from character replacements but allow quotes substitution # Escape unescaped ] to prevent premature closing of pass:[...] protected_content = content.gsub(/(?<!\\)\]/, "\\]") "pass:c,q,a,m,p[#{backticks}#{protected_content}#{backticks}]" end end end |
#pass_inline_split(text) ⇒ Object
147 148 149 150 151 |
# File 'lib/metanorma/converter/macros_nosub.rb', line 147 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
119 120 121 122 123 124 125 126 |
# File 'lib/metanorma/converter/macros_nosub.rb', line 119 def process(document, reader) p = Metanorma::Utils::LineStatus.new lines = reader.lines.map do |t| p.process(t) !p.pass && /(?<!")`(?!")/.match?(t) ? inlinemonospace(t) : t end ::Asciidoctor::PreprocessorReader.new document, lines end |