History log of /dokuwiki/inc/Parsing/ParserMode/GfmEmphasisStrong.php (Results 1 – 1 of 1)
Revision Date Author Comments
# 2bb62bca 20-Apr-2026 Andreas Gohr <gohr@cosmocode.de>

add GFM em-wrapping-strong modes for `***foo***` / `___foo___`

Two new inline formatting modes that render triple-delimiter runs as
em wrapping strong:

GfmEmphasisStrong `***text***`

add GFM em-wrapping-strong modes for `***foo***` / `___foo___`

Two new inline formatting modes that render triple-delimiter runs as
em wrapping strong:

GfmEmphasisStrong `***text***` → <em><strong>text</strong></em>
GfmEmphasisStrongUnderscore `___text___` → same (MD-preferred only)

Only the exact 3+3 symmetric case is handled. The other long-run and
asymmetric variants (4+4, 5+5, `***foo**`, etc.) require CommonMark's
stack-based delimiter-pairing algorithm with its flanking and
multiple-of-3 rules, which is explicitly out of scope; those examples
stay skipped in gfm-spec/skip.php.

Implementation notes:

* Patterns enforce exact 3+3 via `(?<!\*)` / `(?<!_)` lookbehinds
(preventing entry at the second `*` of a `****...` run) and
`(?!\*)` / `(?!_)` lookaheads after the closing triple (rejecting
`***foo****` etc.). Combined with the existing non-whitespace
adjacency lookaheads, all asymmetric cases cleanly fall through to
other modes or stay literal.

* GfmEmphasisStrong overrides handle() to emit two instructions on
entry (emphasis_open + strong_open) and two on exit (strong_close
+ emphasis_close). GfmEmphasisStrongUnderscore inherits that
handler — only delimiters and word-boundary rules differ.

* Sort 65 — below Strong (70) and GfmEmphasis (80) so the em+strong
modes win the lexer race for `***`/`___` runs. Underscore variant
is MD-preferred-only, matching the existing gating of
GfmEmphasisUnderscore and GfmStrongUnderscore.

Per-mode unit tests cover basic matching, single-char bodies,
whitespace flanking rejection, paragraph-boundary rejection,
longer-run rejection, asymmetric rejection, multibyte intraword
protection, and sort values. ModeRegistryTest's gating data provider
picks up the two new rules.

Net effect on GfmSpecTest: example #476 (`***foo***`) now passes;
473/474/475/477 remain skipped as documented in skip.php.

show more ...