Skip to content

[BUGFIX] Render class info modal from plain-text data attributes#1345

Open
CybotTM wants to merge 1 commit into
mainfrom
task/structured-modal-details
Open

[BUGFIX] Render class info modal from plain-text data attributes#1345
CybotTM wants to merge 1 commit into
mainfrom
task/structured-modal-details

Conversation

@CybotTM

@CybotTM CybotTM commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Proposal for option a in #1344 — something concrete to compare against the sanitizer route. Merge only if that is the option you want.

What it does

PhpTextRole::getClassCodeNode() no longer assembles HTML. Signature, flags and summary travel as separate plain-text data-* values, and the modal writes the markup around them:

if (item.dataset.signature) {
  detailParts.push(`<code>${htmlEscape(item.dataset.signature)}</code>`);
}

Every value is escaped exactly once, and no markup crosses the attribute boundary — nothing to sanitize, no allowlist to maintain.

The API summary is decoded on read, so plain text is what travels internally:

$apiInfo['summary'] = html_entity_decode($apiInfo['summary'], ENT_QUOTES | ENT_HTML5, 'UTF-8');

Rendered result for the example from the issue:

data-signature="final class ModifyPageLinkConfigurationEvent"
data-summary="A generic PSR 14 Event … when building a &quot;page link&quot;."

The &quot; there is Twig escaping one real " for the attribute; element.dataset hands the modal a plain quote.

Two deliberate behaviour changes

  • The details block for :php-short: loses its second FQN line. data-fqn already carries the FQN and the modal renders it in its own section.
  • The zero-width-space entity that str_replace('\\', '&#8203;\\', …) inserted around backslashes goes with the HTML blob. It only ever applied to the details string.

Both are visible in the diff and are why this is a proposal rather than something I would merge on my own.

Verification

npm test                          6 files, 27 tests passed
make test-integration ENV=local   Tests: 115, Assertions: 1150, Skipped: 2   OK
make test-unit ENV=local          OK (83 tests, 183 assertions)
make phpstan ENV=local            No errors
make code-style ENV=local         0 of 147 files

PHP 8.5.8. One integration fixture changes, the changelog one; the typo3-file fixture is a non-API role and keeps the escaped plain text from #1343.

ModalDetails.test.js covers what the modal renders, which is the gap #1344 describes: signature and summary become <code> / <em> elements, a quote in the summary stays a quote, plain data-details still works for roles without API info, and markup arriving in either field stays inert. The XSS regression tests from ab24ff7 pass unchanged.

@linawolf

Copy link
Copy Markdown
Member

I think transporting the plain text values is much cleaner. Does this work for all kind of supported languages or only for PHP?

The class information for :php: and :php-short: was assembled as an HTML
string in PhpTextRole and shipped through data-details. Since ab24ff7
escapes that attribute in Twig and in the modal JS, the markup reached
the user as visible text, and summaries from api.typo3.org, which are
already HTML encoded, gained a second layer so &quot; became readable.

Pass signature, flags and summary as separate plain-text attributes and
let the modal write the markup around them. Every value is escaped
exactly once, and no markup crosses the attribute boundary. Decode the
API summary on read so plain text is what travels internally.

The duplicate FQN line drops out of the details block for :php-short:;
data-fqn already carries it and the modal renders it in its own section.
The zero-width-space entity around backslashes goes with the HTML blob.

Fixes #1344

Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
@CybotTM
CybotTM force-pushed the task/structured-modal-details branch from 681584a to a9b77e3 Compare July 25, 2026 14:03
@CybotTM

CybotTM commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

Hi @linawolf ,

Does this work for all kind of supported languages or only for PHP?

works for all.
nothing in the template or the modal JS is PHP-specific. The other roles just have no metadata to put in signature / flags / summary yet, only a static sentence.

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