Skip to content

[BUGFIX] Resolve double-backslash escape in code text roles#1189

Closed
CybotTM wants to merge 1 commit intoTYPO3-Documentation:mainfrom
CybotTM:fix/code-textrole-escape
Closed

[BUGFIX] Resolve double-backslash escape in code text roles#1189
CybotTM wants to merge 1 commit intoTYPO3-Documentation:mainfrom
CybotTM:fix/code-textrole-escape

Conversation

@CybotTM
Copy link
Contributor

@CybotTM CybotTM commented Feb 24, 2026

Summary

Demonstrates a possible fix for #1188:rst: (and all other code-type text roles) display \\ literally instead of resolving to \.

All 20 code-type text roles pass $rawContent to CodeInlineNode, which preserves RST escape sequences literally. This means \\ in the RST source stays as \\ in the rendered output instead of resolving to \ as the author intended.

Approach: Add str_replace('\\\\', '\\', $value) in the CodeInlineNode constructor to resolve double-backslash escape sequences.

Changes

  • CodeInlineNode.php — one line added in constructor
  • New integration test code-textrole-escape covering :rst:, :shell:, :typoscript:, :yaml: with \\ and plain content
  • Render-test examples added to Inline-code-and-textroles/Index.rst

Scope

This PR addresses Test B from the issue (double backslash). Tests A, D, E involve the upstream InlineLexer in phpDocumentor/guides consuming \` as ESCAPED_SIGN before text role boundaries are resolved — that requires a separate upstream fix.

⚠️ Known limitation — this is a demonstration, not a complete fix

The str_replace approach is blind — it cannot distinguish between:

  • \\ meaning "RST escaped backslash → display \" (the bug we're fixing)
  • \\ meaning "literal double backslash in code that should stay as \\"

PHP code samples that would break:

RST source Before this PR After this PR Problem
:php:'/\d+/'`` '/\\d+/' '/\d+/' Lost the PHP string escape
:php:"hello\nworld"`` "hello\\nworld" "hello\nworld" Looks like a newline now
:php:preg_match('/\\/')`` preg_match('/\\\\/') preg_match('/\\/') Regex completely wrong

This is the fundamental tension identified in the issue: $rawContent was introduced by phpDocumentor/guides#533 to preserve literal backslashes for PHP namespaces (\TYPO3\CMS\Core), but that same literalness prevents \\ from resolving to \.

A proper fix needs to happen upstream in the parser/lexer layer where ESCAPED_SIGN tokens are available — only the parser knows which \\ came from an intentional RST escape vs which \ was just a literal backslash character in code.

Test plan

  • make test-integration ENV=local — all 113 tests pass
  • make code-style ENV=local — 0 issues
  • make phpstan ENV=local — no errors
  • make rendertest ENV=local — inspect "Escape handling in code text roles" section
  • Verify :php: namespace paths still render correctly (existing code-php test)

All 20 code-type text roles pass $rawContent to CodeInlineNode,
which preserves RST escape sequences literally. This means \\
stays as \\ instead of resolving to \ as the author intended.

Add str_replace('\\\\', '\\') in the CodeInlineNode constructor
to resolve double-backslash sequences. This is safe for PHP
namespace paths (\TYPO3\CMS\Core) which use single backslashes
and are not affected by this replacement.

Resolves: TYPO3-Documentation#1188

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
@linawolf
Copy link
Member

linawolf commented Mar 1, 2026

Did you note there was a change in the guide on friday? Not sure we would still need this change?

phpDocumentor/guides#1312

@CybotTM
Copy link
Contributor Author

CybotTM commented Mar 1, 2026

@linawolf ,

yes I know, was initiated by phpDocumentor/guides#1308

@CybotTM
Copy link
Contributor Author

CybotTM commented Mar 1, 2026

so, yes, should make this "demonstration" obsolete.

@linawolf
Copy link
Member

linawolf commented Mar 2, 2026

@CybotTM would you like to close this pr then? Or maybe just keep the tests?

@CybotTM CybotTM closed this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants