Preserved HTML markup in excerpts - #4600
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Updates excerpt rendering to preserve HTML markup when trimming manual excerpts, and adds an end-to-end test to ensure links/formatting remain intact.
Changes:
- Replaces
wp_trim_words()usage for manual excerpts with a custom HTML-preserving trim implementation. - Adds
trim_words_keep_html()helper to keep markup while word-trimming. - Adds a Playwright e2e spec that validates trimming preserves
<a>and<strong>elements.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| inc/views/partials/excerpt.php | Introduces HTML-preserving excerpt trimming and wires it into manual excerpt handling. |
| e2e-tests/specs/customizer/layout/blog-archive-settings.spec.ts | Adds an e2e test ensuring excerpt trimming keeps HTML markup. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| private function trim_words_keep_html( $text, $num_words, $more = '...' ) { | ||
| $num_words = (int) $num_words; | ||
|
|
||
| if ( $num_words <= 0 || '' === $text ) { |
There was a problem hiding this comment.
wp_trim_words() only does normalization through wp_strip_all_tags() (script/style regex, strip_tags(), and trim()). It doesn't call strip_shortcodes(). Also, when $num_words is 0, WordPress doesn't return an empty string. preg_split() returns one element, which is then removed by array_pop(). implode() returns an empty string, and WordPress finally appends $more, resulting in a single ….
So the actual difference here is an empty string vs. a single ellipsis. This situation requires neve_post_excerpt_length to be 0, but the range control doesn't allow that because its minimum is 5, its step is 5, and the value is passed through absint(). If the value is forced to 0 through a filter, I think returning nothing is better than showing a single ellipsis, so I kept the current behavior.
| // If this is a text, split it into words and add them to the output. | ||
| $parts = preg_split( | ||
| '/(\s+)/u', | ||
| $token, | ||
| -1, | ||
| PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY | ||
| ); |
There was a problem hiding this comment.
wp_trim_excerpt() calls strip_shortcodes() only in the '' === trim( $text ) branch, where it generates an excerpt from the post content.
Here, we are in the has_excerpt() branch, so that code is never executed. The behavior is therefore unchanged, so no changes were made.
selul
left a comment
There was a problem hiding this comment.
This is a ~190-line pure string function in a repo with a green PHPUnit job, but it only gets Playwright coverage — the tokenizer edge cases in the comments below are exactly what a unit test pins down cheaply.
|
@selul I have implemented it as you suggested. Please review it and let me know if any further changes are needed. |
Summary
Preserves HTML markup when excerpts are trimmed, and adds corresponding end-to-end tests to ensure the new behavior works as expected.
Check before Pull Request is ready:
Closes #4598