Skip to content

Preserved HTML markup in excerpts - #4600

Merged
pirate-bot merged 5 commits into
developmentfrom
bugfix/4598
Aug 27, 2026
Merged

Preserved HTML markup in excerpts#4600
pirate-bot merged 5 commits into
developmentfrom
bugfix/4598

Conversation

@girishpanchal30

Copy link
Copy Markdown
Contributor

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

@pirate-bot

pirate-bot commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Plugin build for 88a94dc is ready 🛎️!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread inc/views/partials/excerpt.php
Comment thread inc/views/partials/excerpt.php Outdated
Comment thread inc/views/partials/excerpt.php Outdated
Comment on lines +196 to +202
// 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
);

@girishpanchal30 girishpanchal30 Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread e2e-tests/specs/customizer/layout/blog-archive-settings.spec.ts Outdated

@selul selul left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread inc/views/partials/excerpt.php Outdated
Comment thread inc/views/partials/excerpt.php
Comment thread inc/views/partials/excerpt.php Outdated
Comment thread inc/views/partials/excerpt.php Outdated
Comment thread inc/views/partials/excerpt.php Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

Comment thread inc/views/partials/excerpt.php Outdated
Comment thread inc/views/partials/excerpt.php
Comment thread e2e-tests/specs/customizer/layout/blog-archive-settings.spec.ts
Comment thread e2e-tests/specs/customizer/layout/blog-archive-settings.spec.ts
@girishpanchal30

Copy link
Copy Markdown
Contributor Author

@selul I have implemented it as you suggested. Please review it and let me know if any further changes are needed.

@pirate-bot
pirate-bot merged commit 8dba348 into development Aug 27, 2026
14 checks passed
@pirate-bot
pirate-bot deleted the bugfix/4598 branch August 27, 2026 12:02
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.

Manual excerpt hyperlinks are stripped on archive pages since Neve 4.2.9

4 participants