Skip to content

Interactivity API: Preserve colons and semicolons in existing style attributes - #12733

Open
itzmekhokan wants to merge 1 commit into
WordPress:trunkfrom
itzmekhokan:fix/interactivity-api-style-attribute-colon
Open

Interactivity API: Preserve colons and semicolons in existing style attributes#12733
itzmekhokan wants to merge 1 commit into
WordPress:trunkfrom
itzmekhokan:fix/interactivity-api-style-attribute-colon

Conversation

@itzmekhokan

Copy link
Copy Markdown

WP_Interactivity_API::merge_style_property() re-serializes the entire style attribute every time a data-wp-style--* directive is processed. Two defects sit in that loop, both on the same line.

1. Values containing a colon are truncated. explode( ':', $style_assignment ) is called without a limit, so everything after the first colon is discarded. This corrupts valid CSS silently, with no warning:

in:  <div style="background-image:url(https://example.com/a.png)"
          data-wp-style--color="myPlugin::state.green">Text</div>

out: <div style="background-image:url(https;color:green;"
          data-wp-style--color="myPlugin::state.green">Text</div>

The background image is destroyed on the front end. Any url() with a scheme triggers it, as does any custom property holding one.

2. Segments containing no colon raise PHP diagnostics. They yield no $value, so list() raises Undefined array key 1 and the subsequent trim( null ) is deprecated on PHP 8.1+. This is the half originally reported on the ticket.

There is a third, related symptom: declarations are split on ; before anything knows where strings begin and end, so a semicolon inside a quoted string or a url() cuts a value in two. font-family:"Foo;Bar",serif and url(data:image/gif;base64,…) both split, and the tail then hits the colon-less path above and picks up a stray :.

Changes

  • explode( ':', $style_assignment, 2 ), so only the first colon separates a property name from its value.
  • A guard for segments containing no colon, resolving the reported warning and deprecation.

The guard preserves such segments verbatim and untrimmed rather than dropping them. This also repairs the semicolon cases: because segments are re-joined with ;, preserving the tail restores font-family:"Foo;Bar",serif and url(data:image/gif;base64,…) intact. Dropping them would emit font-family:"Foo — an unterminated string, which is worse than the original bug. Leaving them untrimmed matters too, or the space in "Foo; Bar" is lost.

Trac ticket: https://core.trac.wordpress.org/ticket/63899

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Ticket analysis, tests cases and writing PR description. All changes were reviewed and validated by me.


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

Copilot AI review requested due to automatic review settings July 28, 2026 09:54
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props khokansardar.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

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

This PR fixes WP_Interactivity_API::merge_style_property() so it no longer corrupts existing style attribute content when processing data-wp-style--* directives, specifically for CSS values containing colons and for segments that contain no colon.

Changes:

  • Split style declarations on the first colon only (explode( ':', ..., 2 )) to preserve colons inside valid CSS values (e.g., url(https://...), data URIs).
  • Add a guard to preserve colon-less segments verbatim to avoid PHP diagnostics and to allow semicolon-split tails (from quoted strings/url()) to re-join correctly.
  • Add PHPUnit coverage for colon/semicolon cases, colon-less segments, and an end-to-end data-wp-style scenario.

Reviewed changes

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

File Description
src/wp-includes/interactivity-api/class-wp-interactivity-api.php Fixes parsing in merge_style_property() to preserve colon-containing values and safely handle colon-less segments.
tests/phpunit/tests/interactivity-api/wpInteractivityAPI-wp-style.php Adds tests covering colon/semicolon preservation, colon-less segments, and directive behavior with URL-containing styles.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

…ttributes.

`merge_style_property()` re-serializes the whole `style` attribute each time a
`data-wp-style--*` directive is processed. It split each declaration with
`explode( ':', $style_assignment )` and no limit, truncating any value that
contained a colon, so `background-image:url(https://example.com/a.png)` became
`background-image:url(https`. Segments containing no colon at all reached
`list()` and raised `Undefined array key 1` plus a `trim()` deprecation notice.

Splits on the first colon only, and preserves a segment that contains none
verbatim, so that a value split by a semicolon inside a quoted string or a
`url()` is restored when the segments are re-joined.

Props khokansardar, tkay01, sabernhardt.

Trac ticket: https://core.trac.wordpress.org/ticket/63899
Copilot AI review requested due to automatic review settings July 28, 2026 10:00
@itzmekhokan
itzmekhokan force-pushed the fix/interactivity-api-style-attribute-colon branch from ff790dc to cd457f5 Compare July 28, 2026 10:00

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 no new comments.

Comments suppressed due to low confidence (1)

src/wp-includes/interactivity-api/class-wp-interactivity-api.php:1176

  • The docblock note references “See #65738.”, but this PR (and the added tests) are scoped to Trac ticket 63899. If this note is meant to point to the current issue, the ticket number should match to avoid confusion when backporting or searching history.
	 * Declarations are separated on semicolons without regard for quoted strings or
	 * `url()` values, so the property being replaced is not recognized when its own
	 * value contains a semicolon. Resolving that requires tokenizing the declaration
	 * list rather than splitting it. See #65738.

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