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:uri \\b [^\\s\\[]* # span:uri, third key ) \\[.*?(?<!\\\\)\\] # [ ... ] not preceded by \\ ) REGEX
- PASS_INLINE_MACRO_RX =
/#{PASS_INLINE_MACRO_STR}/xo- MonospaceRx =
Regex to match single or double backticks with content Matches: ‘text` or “text“ Avoids: 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
160 161 162 163 164 165 166 |
# File 'lib/metanorma/converter/macros_nosub.rb', line 160 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
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/metanorma/converter/macros_nosub.rb', line 168 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
139 140 141 142 143 |
# File 'lib/metanorma/converter/macros_nosub.rb', line 139 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
115 116 117 118 119 120 121 122 |
# File 'lib/metanorma/converter/macros_nosub.rb', line 115 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 |