| #
47a02a10 |
| 04-Jun-2026 |
Andreas Gohr <gohr@cosmocode.de> |
Parsing: make parse syntax a per-parse value, drop ModeInterface
The active parse's syntax flavour is a per-parse question, not process- global state: within a single request a plugin can render bun
Parsing: make parse syntax a per-parse value, drop ModeInterface
The active parse's syntax flavour is a per-parse question, not process- global state: within a single request a plugin can render bundled DokuWiki-syntax text inside an otherwise-Markdown page. Yet ModeRegistry was a singleton that read $conf['syntax'] and the $PARSER_MODES global, and every mode reached it through ModeRegistry::getInstance() — so the flavour lived in shared mutable state that two parses in one request would fight over.
Make the registry a short-lived value instead:
- ModeRegistry is constructed once per parse with an explicit $syntax and injected into Parser, Handler and every mode. getSyntax() / isDwPreferred() / isMdPreferred() consult $this->syntax; the DOKU_UNITTEST-gated mode-list cache hack is gone (each registry is fresh, nothing to invalidate). - p_get_instructions() is now the single place in the pipeline where $conf['syntax'] is read; from there the flavour travels as a parameter. No code under inc/Parsing/ reads $conf['syntax'] directly anymore — the five syntax-reading modes (Preformatted, GfmHr, GfmEscape, Externallink, GfmQuote) route through $this->registry.
Keep the two concepts apart, as documented in the ModeRegistry and AbstractMode docblocks: the user's configured *preference* stays in $conf['syntax'] for UI code (toolbar, settings), while the active parse's syntax is a parameter carried by the registry.
$PARSER_MODES is demoted to a deprecated, read-only mirror, published during loadPluginModes() — third-party syntax plugins (columnlist, alphalist2, phpwikify, skipentity) and the bundled info plugin read the global directly, often from their constructors, so the taxonomy must stay visible there. No core code reads the mirror.
Fold ModeInterface into AbstractMode while here: getSort()/handle() are abstract, the connect callbacks carry defaults, and the public $Lexer "FIXME should be done by setter" becomes setLexer()/getLexer() injected by Parser::addMode() alongside the registry. Nested-content resolution moves to the allowedCategories()/filterAllowedModes() hooks, resolved once when the registry is attached.
Tests build their own parser/registry through ParserTestBase::setSyntax() instead of mutating $conf and calling the removed ModeRegistry::reset().
show more ...
|
| #
65dd2042 |
| 26-May-2026 |
Andreas Gohr <gohr@cosmocode.de> |
GfmEscape: defer \\<EOL> to DW Linebreak in mixed-syntax modes
Both GfmEscape (sort 5) and DW Linebreak (sort 140) can claim the two backslashes of `\\` followed by space/tab/newline. The lexer's ti
GfmEscape: defer \\<EOL> to DW Linebreak in mixed-syntax modes
Both GfmEscape (sort 5) and DW Linebreak (sort 140) can claim the two backslashes of `\\` followed by space/tab/newline. The lexer's tie-breaker picked GfmEscape, so DW's forced linebreak silently lost its delimiter under dw+md and md+dw. Add a negative lookahead that declines `\\[ \t\n]` whenever DW syntax is loaded — pure md keeps GFM-spec behavior. Mid-line `\\` (UNC paths etc.) still escapes.
show more ...
|
| #
d331a839 |
| 12-May-2026 |
Andreas Gohr <andi@splitbrain.org> |
GFM modes: follow CATEGORY_SUBSTITION → CATEGORY_SUBSTITUTION rename
Constant was renamed on master (the typo'd 'substition' value is kept, but the constant name spells it correctly). Update GfmTabl
GFM modes: follow CATEGORY_SUBSTITION → CATEGORY_SUBSTITUTION rename
Constant was renamed on master (the typo'd 'substition' value is kept, but the constant name spells it correctly). Update GfmTable's use of the constant, plus stale docblock/comment references in GfmEscape, GfmHtmlEntity, GfmLinebreak, and GfmLinebreakTest.
show more ...
|
| #
74031e46 |
| 28-Apr-2026 |
Andreas Gohr <andi@splitbrain.org> |
add GfmEscape for GFM backslash escapes
Implements GFM §6.1 backslash-escape handling. GfmEscape is a sort-5 inline mode in CATEGORY_SUBSTITION that claims `\X` for any escapable ASCII punctuation c
add GfmEscape for GFM backslash escapes
Implements GFM §6.1 backslash-escape handling. GfmEscape is a sort-5 inline mode in CATEGORY_SUBSTITION that claims `\X` for any escapable ASCII punctuation char before competing delimiters can match. The shared character class lives on Helpers\Escape so the lexer pattern and the post-hoc unescape stay in lockstep.
Whole-span captures (GfmCode info string, GfmLink label/URL) bypass the lexer; those modes call Escape::unescapeBackslashes() on the relevant slot. GfmLink skips the unescape when the URL classifies as a windowssharelink so the leading \\host survives intact.
GfmTable cells get a separate per-cell `\|` to `|` pass in the rewriter to honour the tables-extension rule that pipes always unescape, even inside code spans where standard §6.1 escapes don't fire.
show more ...
|