Hwaro::Content::Processors::InlineMarkdown
Constants
A CommonMark URI autolink (<https://…>) as HTML.escape left it.
Math span patterns — canonical home for the whole pipeline (MarkdownExtensions aliases these, mirroring INLINE_STRIKETHROUGH_RE).
Display math must not cross a blank line (the tempered dot refuses
to consume a newline that starts one, whitespace-only lines
included): a stray unmatched $$ would otherwise pair with a
legitimate $$ several paragraphs later and swallow all the prose
in between. Blank lines are invalid inside LaTeX display math
anyway, so no real formula is lost.
Inline math admits backslash escapes in the body ($x = \$5$) and
requires an unescaped, non-space-preceded closer. A body ending
in a literal \ won't close — meaningless in LaTeX at the end of
a formula.
A backslash before ASCII punctuation (shown HTML-escaped, so \"
is \") is a CommonMark escape: the character is literal.
An entity or numeric character reference as HTML.escape left it.
{width=300} / {width=300 height=200} right after an image is its
size, the attribute block ![[pic.png|300]] is rewritten to.
Flanking guards ((?=\S) … (?<=\S)): a delimiter run that touches
whitespace on the inside must NOT open/close emphasis, so literal
2 * 3 and 4 * 5 (arithmetic in a table cell or footnote) is left
alone instead of becoming 2 <em> 3 and 4 </em> 5. This approximates
CommonMark's left/right-flanking rule that the body markd uses.
CommonMark code spans: a run of N backticks opens, and the next run
of EXACTLY N backticks closes. The single-backtick-only form this
replaced could not see `tick` or a`b at all — it matched
the inner backticks instead, shredding the span into stray <code>
tags and literal delimiters inside table cells, footnote bodies, and
definition lists (the three callers of render).
The opening run is POSSESSIVE (`++) and BOTH delimiters are
fenced by (?<!)/(?!) so each is a whole run: without those,
\1 would happily match two of a three-backtick run and pair
mismatched delimiters. The opener's lookbehind matters twice over:
- correctness — without it, an unmatched longer run bleeds into a
later shorter one:
abecame<code> </code>a(the scan restarted on the SECOND backtick of the), where CommonMark givesa``; - cost — without it, every backtick of a run is a fresh start
position that possessively re-consumes the rest of the run, so
an unclosed run of N backticks cost O(N²): a 200 KB cell of
backticks did not finish in ten minutes. With it, positions
inside a run are rejected in O(1) and the scan is linear again.
[\s\S](not.) because a footnote or definition body may still carry a newline at this point.
Link/image openers up to and including (; the destination and
optional title are read by scan_link_tail.
Opt-in inline markup (F10) — all gated behind their own
[markdown] flags (see Flags), so with every flag off these
patterns are never even consulted.
++ins++: same flanking-guard shape as strikethrough. A lone
++ (as in C++) never gets a second delimiter to pair with, so
it's left alone without any special-casing.
The italic delimiter must be a LONE */_ (not part of a **/__
run) — (?<!\*)…(?!\*) and [^\s*] neighbours — otherwise a spaced
2 ** 3 and 4 ** 5 (which the bold regex correctly declines) would be
re-matched across the two ** runs into <em>* 3 and 4 *</em>.
==mark==: the (?<!=)/(?!=) outer guards and the
[^\s=] inner guards keep a run of = (a setext heading
underline, a ==== divider) from ever matching — there's no
non-= character for the inner lookaround to anchor on.
A ~~ right after an unescaped backslash is literal (\~~not\~~):
rewriting it would leave \<del>, which Markd escapes into visible
<del> text. \\~~x~~ (escaped backslash) still strikes.
~sub~: single tilde, deliberately disjoint from the double-tilde
strikethrough delimiter (which always runs first and consumes any
~~...~~ pair before this pattern gets a chance to see it).
^sup^: the (?<![\^\[]) guard specifically excludes a ^ that
immediately follows [ — i.e. a footnote reference's [^key] —
so sup and footnotes can both be enabled without sup mangling
a footnote marker before the footnotes pass gets to it.
CommonMark allows 32 levels of balanced parentheses in a destination.
ponytail: a title longer than this is not read (keeps a run of
unterminated [a](x " openers linear); such a link keeps the
first-) fallback.
Placeholder comments left by Core::Build::ShortcodeProcessor for
already-rendered shortcodes (canonical home here, next to the other
inline patterns; the shortcode processor aliases it and emits the
matching text). They must ride through render untouched: the
HTML.escape at the top would otherwise turn them into
<!--…-->, which the post-Markdown replacement pass cannot
find — leaking the escaped comment into table cells, definition
bodies, and footnotes.
Schemes that must be blocked in <a href="…"> / <img src="…"> even
when Markd's safe option is off. data: is allowed only for image
MIME types (matching Markd's own UNSAFE_DATA_PROTOCOL).
Instance methods
Render a small inline-markdown subset over already-HTML-escaped or raw text. Code spans are extracted first so their content survives the other passes verbatim.
With flags.math, $…$/$$…$$ spans are stashed too and restored
UNtransformed: emphasis/strikethrough/link passes must not rewrite
formula internals ($~~x~~$, $f([x])(y)$), and the math
preprocess wraps the still-raw span afterwards.
flags also controls the F10 opt-in inline markup (ins/mark/sub/sup).
Returns true for URLs we're willing to emit in a generated href/src.
Reject javascript:, vbscript:, file:, and non-image data: URIs.
Percent-decode first so encodings like java%73cript: don't slip past.
Also strip ASCII control/whitespace bytes (NUL–space and DEL) anywhere
in the decoded value: browsers ignore tabs/newlines/NULs inside a URL
scheme, so java%09script: would otherwise execute as javascript:.
The unsafe regexes are anchored at ^, so stripping these from the
whole string only affects scheme detection, never legitimate URLs.