Opened 4 months ago
Closed 3 months ago
#65482 closed enhancement (fixed)
Strip inline note markers from rendered block output
| Reported by: | adamsilverstein | Owned by: | adamsilverstein |
|---|---|---|---|
| Priority: | normal | Milestone: | 7.1 |
| Component: | Editor | Version: | |
| Severity: | normal | Keywords: | has-patch has-unit-tests commit |
| Cc: | Focuses: |
Description
Summary
Block comments (Notes) shipped in WordPress 6.9. The next milestone adds inline (partial-text) Notes — notes anchored to a text selection within a block rather than to the whole block.
An inline note's anchor is an in-content marker:
<mark class="wp-note" data-id="N">…marked text…</mark>
The data-id identifies the note, and because the marker lives in the content its position follows edits — no separate selection offset metadata has to be stored. The marker is kept in the raw post_content (and the REST raw view, revisions, and exports) so the editor can re-attach the note on reload.
The public front end, however, should never expose note metadata. This ticket adds a server-side filter that strips the marker from rendered output only.
Proposed change
Add wp_strip_inline_note_markers(), hooked on render_block, which unwraps each note <mark> and its matching closer while preserving the marked text and any nested formatting.
src/wp-includes/comment.php— the new function.src/wp-includes/default-filters.php— registers it onrender_block.tests/phpunit/tests/comment/stripInlineNoteMarkers.php— unit coverage.
Why the HTML API instead of a regex
Matching is done with WP_HTML_Tag_Processor::has_class() so only the exact wp-note class token is targeted. This avoids three classes of bug a regex would introduce:
- An unrelated user or plugin
<mark>(acore/text-colorhighlight, or an unrelatedwp-note-fooclass) survives byte-for-byte with all attributes intact. A\bwp-note\bword boundary would wrongly matchwp-note-foo. - A
</mark>-looking sequence inside an HTML comment or attribute value is never mistaken for a real closing tag. - A nesting stack pairs each note opener with its own closer, so overlapping notes and nested highlight
<mark>s resolve correctly.
The HTML API has no public token-removal method yet, so an anonymous WP_HTML_Tag_Processor subclass removes the marker token directly on the parsed token stream.
Testing
Run the unit tests:
phpunit --filter Tests_Comment_StripInlineNoteMarkers
Or manually:
- Add an inline note to part of a paragraph in the editor and save.
- View the post on the front end.
- Confirm the
<mark class="wp-note">wrapper is absent while the marked text remains. - Confirm a non-note
<mark>highlight (e.g. from text color) is left untouched.
Change History (8)
This ticket was mentioned in PR #12215 on WordPress/wordpress-develop by @adamsilverstein.
4 months ago
#1
#2
@
4 months ago
@adamsilverstein I guess this isn’t the ticket for it, but did we consider using data-note-id instead of data-id? it might be more resilient against mismatches if we could more concretely identify the MARK elements by this instead of overloading the generic data-id or dataset.id (vs. dataset.noteId)
@adamsilverstein commented on PR #12215:
4 months ago
#3
Thanks for the reviews! Addressed both pieces of feedback in a79faec71d..e605cbf345:
@mukeshpanchal27 - added @ticket 65482 to all of the test methods.
@dmsnell - two follow-ups:
- Converted the multi-line
//comments to/* */block syntax. - On the HTML Processor: I dug into it and ended up keeping
WP_HTML_Tag_Processordeliberately.WP_HTML_Processordoes guarantee well-formed nesting, but on certain ill-formed nesting - e.g. a note marker crossed with other inline formatting like<mark class="wp-note">a<i>b</mark>c</i>- it setslast_error = 'unsupported'and aborts, which for this filter would leave the note marker (and itsdata-idmetadata) in the rendered output. Since the whole point is to *not* leak note metadata to the front end, abort-on-malformed is the wrong failure mode. Token scanning instead strips everywp-notemarker it encounters and degrades gracefully: an unbalanced or stray tag is left exactly as it was rather than corrupting the surrounding markup.
I documented that reasoning in the docblock and added tests for the ill-formed cases (unclosed marker, stray closer, improper nesting) to lock the behavior in.
@wildworks commented on PR #12215:
3 months ago
#4
I would appreciate it if you could proceed with this PR and commit it in time for the 7.1 Beta1 release on July 15.
@adamsilverstein commented on PR #12215:
3 months ago
#5
I would appreciate it if you could proceed with this PR and commit it in time for the 7.1 Beta1 release on July 15.
@t-hamano yes will do, I added it to the php backport list.
#6
@
3 months ago
- Keywords commit added
- Owner set to
- Status new → assigned
Approved and ready for commit.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
## Summary
Backports the server-side piece of Gutenberg PR WordPress/gutenberg#78218, which adds inline (partial-text) Notes - notes anchored to a text selection within a block rather than to the whole block.
An inline note's anchor is an in-content
<mark class="wp-note" data-id="N">…</mark>marker. Thedata-ididentifies the note and the marker's position follows edits, so no separate selection metadata is stored. The marker stays in the rawpost_content(and the RESTrawview, revisions, and exports) so the editor can re-attach the note on reload, but the public front-end HTML should not expose note metadata.This change strips that marker from rendered output only.
## What changed
src/wp-includes/comment.phpwp_strip_inline_note_markers()— unwraps each note<mark>and its matching closer onrender_block, keeping the marked text and any nested formatting.src/wp-includes/default-filters.phprender_block.tests/phpunit/tests/comment/stripInlineNoteMarkers.php## Why the HTML API, not a regex
Matching goes through
WP_HTML_Tag_Processor::has_class()so only the exactwp-noteclass token is targeted:<mark>(acore/text-colorhighlight, or awp-note-fooclass) survives byte-for-byte with all attributes intact. A\bwp-note\bregex word boundary would wrongly matchwp-note-foo.</mark>-looking sequence inside an HTML comment or attribute value is never mistaken for a real tag.<mark>s resolve correctly.The HTML API has no public token-removal method yet, so an anonymous
WP_HTML_Tag_Processorsubclass unwraps the marker directly on the parsed token stream.## Testing instructions
Run the new unit tests:
Or manually: add an inline note to a paragraph in the editor, view the post on the front end, and confirm the
<mark class="wp-note">wrapper is absent while the text remains, and that any non-note<mark>highlight is untouched.