module

Hwaro::Content::Processors::InlineMarkdown

Constants

DISPLAY_MATH_RE = /\$\$((?:(?!\n[ \t\r]*\n).)*?)\$\$/m

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.

INLINE_BOLD_ASTERISK_RE = /\*\*(?=\S)(.+?)(?<=\S)\*\*/

Flanking guards ((?=\S)(?&lt;=\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 &lt;em&gt; 3 and 4 &lt;/em&gt; 5. This approximates CommonMark's left/right-flanking rule that the body markd uses.

INLINE_BOLD_UNDERSCORE_RE = /__(?=\S)(.+?)(?<=\S)__/
INLINE_CODE_SPAN_RE = /`([^`]+)`/
INLINE_IMAGE_RE = /!\[([^\]]*)\]\(([^)]*)\)/
INLINE_INS_RE = /\+\+(?=\S)(.+?)(?<=\S)\+\+/

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.

INLINE_ITALIC_ASTERISK_RE = /(?<!\*)\*(?=[^\s*])(.+?)(?<=[^\s*])\*(?!\*)/

The italic delimiter must be a LONE */_ (not part of a **/__ run) — (?&lt;!\*)…(?!\*) 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 &lt;em&gt;* 3 and 4 *&lt;/em&gt;.

INLINE_ITALIC_UNDERSCORE_RE = /(?<![a-zA-Z0-9_])_(?=[^\s_])(.+?)(?<=[^\s_])_(?![a-zA-Z0-9_])/
INLINE_LINK_RE = /\[([^\]]+)\]\(([^)]*)\)/
INLINE_MARK_RE = /(?<!=)==(?=[^\s=])(.+?)(?<=[^\s=])==(?!=)/

==mark==: the (?&lt;!=)/(?!=) 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.

INLINE_MATH_RE = /(?<![\\$])\$(?!\s)((?:[^\n$\\]|\\[^\n])+?)(?<![\s\\])\$(?!\d)/
INLINE_STRIKETHROUGH_RE = /~~(?=\S)(.+?)(?<=\S)~~/
INLINE_SUB_RE = /(?<!~)~([^~\s]+)~(?!~)/

~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).

INLINE_SUP_RE = /(?<![\^\[])\^([^\^\s]+)\^(?!\^)/

^sup^: the (?&lt;![\^\[]) 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.

SCPH_TOKEN_RE = /\x00SCPH(\d+)\x00/
SHORTCODE_PLACEHOLDER_RE = /<!--HWARO-SHORTCODE-PLACEHOLDER-\d+-->/

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 &amp;lt;!--…--&amp;gt;, which the post-Markdown replacement pass cannot find — leaking the escaped comment into table cells, definition bodies, and footnotes.

UNSAFE_DATA_PROTOCOL_RE = /^\s*data:image\/(?:png|gif|jpeg|webp)/i
UNSAFE_PROTOCOL_RE = /^\s*(javascript|vbscript|file|data):/i

Schemes that must be blocked in &lt;a href=&quot;…&quot;&gt; / &lt;img src=&quot;…&quot;&gt; 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(text : String, *, flags : Flags) : String

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 math: true, $…$/$$…$$ 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 controls the F10 opt-in inline markup (ins/mark/sub/sup) in addition to math — see render(text, *, math:) below, which is the pre-F10 signature every existing caller/spec still uses.

Source
render(text : String, *, math : Bool = false) : String

Pre-F10 signature — delegates to the Flags overload with every new transform off, so every existing caller/spec keeps compiling and rendering exactly as before.

Source
safe_url?(url : String) : Bool

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.

Source

Nested types