Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactivity API: Allow more directives suffixes #65803

Open
wants to merge 12 commits into
base: trunk
Choose a base branch
from

Conversation

sirreal
Copy link
Member

@sirreal sirreal commented Oct 1, 2024

What?

https://core.trac.wordpress.org/ticket/62131 describes a case where the Interactivity API client does not correctly handle the class name part of a class directive. This class directive is correctly handled on the server, but will be ignored by the more restrictive client:

<div data-wp-class--bottom-[-24rem]="context.isEditCard">

Alternative

If we do not want to relax this restriction, the server should apply the same restriction on directive attributes (they should match the same Regexp). This would avoid a mismatch where the server sets a class the client would not remove.

Why?

The "suffix" can support more characters technically. It seems like some unusual class names may be reasonable.

A use case mentioned on the ticket is Tailwind, a popular CSS framework:

How?

Relax some client-side constraints on the directive names.

Testing Instructions

Tests are included.

@sirreal sirreal added [Type] Enhancement A suggestion for improvement. [Feature] Interactivity API API to add frontend interactivity to blocks. [Packages] Interactivity /packages/interactivity labels Oct 1, 2024
Comment on lines -358 to -368
const classFinder = new RegExp(
`(^|\\s)${ className }(\\s|$)`,
'g'
);
Copy link
Member Author

Choose a reason for hiding this comment

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

Independent of the other changes, this is likely a good change. Building a regex effectively from an input string like was done here is risky.

Copy link
Member Author

Choose a reason for hiding this comment

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

This change is necessary here because there are number of special characters that would need special processing in the Regexp like [].

@sirreal sirreal marked this pull request as ready for review October 2, 2024 15:23
Copy link

github-actions bot commented Oct 2, 2024

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.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: sirreal <[email protected]>
Co-authored-by: michalczaplinski <[email protected]>
Co-authored-by: DAreRodz <[email protected]>
Co-authored-by: gziolo <[email protected]>
Co-authored-by: luisherranz <[email protected]>

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

Copy link

github-actions bot commented Oct 2, 2024

Size Change: +37 B (0%)

Total Size: 1.77 MB

Filename Size Change
build-module/interactivity/debug.min.js 16.7 kB +22 B (+0.13%)
build-module/interactivity/index.min.js 13.4 kB +15 B (+0.11%)
ℹ️ View Unchanged
Filename Size
build-module/a11y/index.min.js 482 B
build-module/block-library/file/view.min.js 447 B
build-module/block-library/image/view.min.js 1.78 kB
build-module/block-library/navigation/view.min.js 1.16 kB
build-module/block-library/query/view.min.js 743 B
build-module/block-library/search/view.min.js 616 B
build-module/interactivity-router/index.min.js 3 kB
build/a11y/index.min.js 952 B
build/annotations/index.min.js 2.26 kB
build/api-fetch/index.min.js 2.32 kB
build/autop/index.min.js 2.12 kB
build/blob/index.min.js 579 B
build/block-directory/index.min.js 7.26 kB
build/block-directory/style-rtl.css 1.07 kB
build/block-directory/style.css 1.07 kB
build/block-editor/content-rtl.css 4.45 kB
build/block-editor/content.css 4.45 kB
build/block-editor/default-editor-styles-rtl.css 394 B
build/block-editor/default-editor-styles.css 394 B
build/block-editor/index.min.js 256 kB
build/block-editor/style-rtl.css 15.5 kB
build/block-editor/style.css 15.5 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 149 B
build/block-library/blocks/audio/editor.css 151 B
build/block-library/blocks/audio/style-rtl.css 132 B
build/block-library/blocks/audio/style.css 132 B
build/block-library/blocks/audio/theme-rtl.css 134 B
build/block-library/blocks/audio/theme.css 134 B
build/block-library/blocks/avatar/editor-rtl.css 115 B
build/block-library/blocks/avatar/editor.css 115 B
build/block-library/blocks/avatar/style-rtl.css 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/button/editor-rtl.css 265 B
build/block-library/blocks/button/editor.css 265 B
build/block-library/blocks/button/style-rtl.css 538 B
build/block-library/blocks/button/style.css 538 B
build/block-library/blocks/buttons/editor-rtl.css 291 B
build/block-library/blocks/buttons/editor.css 291 B
build/block-library/blocks/buttons/style-rtl.css 345 B
build/block-library/blocks/buttons/style.css 345 B
build/block-library/blocks/calendar/style-rtl.css 240 B
build/block-library/blocks/calendar/style.css 240 B
build/block-library/blocks/categories/editor-rtl.css 132 B
build/block-library/blocks/categories/editor.css 131 B
build/block-library/blocks/categories/style-rtl.css 152 B
build/block-library/blocks/categories/style.css 152 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 122 B
build/block-library/blocks/code/theme.css 122 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 420 B
build/block-library/blocks/columns/style.css 420 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 124 B
build/block-library/blocks/comment-author-avatar/editor.css 124 B
build/block-library/blocks/comment-author-name/style-rtl.css 72 B
build/block-library/blocks/comment-author-name/style.css 72 B
build/block-library/blocks/comment-content/style-rtl.css 120 B
build/block-library/blocks/comment-content/style.css 120 B
build/block-library/blocks/comment-date/style-rtl.css 65 B
build/block-library/blocks/comment-date/style.css 65 B
build/block-library/blocks/comment-edit-link/style-rtl.css 70 B
build/block-library/blocks/comment-edit-link/style.css 70 B
build/block-library/blocks/comment-reply-link/style-rtl.css 71 B
build/block-library/blocks/comment-reply-link/style.css 71 B
build/block-library/blocks/comment-template/style-rtl.css 200 B
build/block-library/blocks/comment-template/style.css 199 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 228 B
build/block-library/blocks/comments-pagination/editor.css 217 B
build/block-library/blocks/comments-pagination/style-rtl.css 234 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 832 B
build/block-library/blocks/comments/editor.css 832 B
build/block-library/blocks/comments/style-rtl.css 632 B
build/block-library/blocks/comments/style.css 631 B
build/block-library/blocks/cover/editor-rtl.css 641 B
build/block-library/blocks/cover/editor.css 642 B
build/block-library/blocks/cover/style-rtl.css 1.62 kB
build/block-library/blocks/cover/style.css 1.6 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 86 B
build/block-library/blocks/details/style.css 86 B
build/block-library/blocks/embed/editor-rtl.css 331 B
build/block-library/blocks/embed/editor.css 331 B
build/block-library/blocks/embed/style-rtl.css 419 B
build/block-library/blocks/embed/style.css 419 B
build/block-library/blocks/embed/theme-rtl.css 133 B
build/block-library/blocks/embed/theme.css 133 B
build/block-library/blocks/file/editor-rtl.css 326 B
build/block-library/blocks/file/editor.css 326 B
build/block-library/blocks/file/style-rtl.css 278 B
build/block-library/blocks/file/style.css 279 B
build/block-library/blocks/file/view.min.js 324 B
build/block-library/blocks/footnotes/style-rtl.css 198 B
build/block-library/blocks/footnotes/style.css 197 B
build/block-library/blocks/form-input/editor-rtl.css 229 B
build/block-library/blocks/form-input/editor.css 229 B
build/block-library/blocks/form-input/style-rtl.css 357 B
build/block-library/blocks/form-input/style.css 357 B
build/block-library/blocks/form-submission-notification/editor-rtl.css 344 B
build/block-library/blocks/form-submission-notification/editor.css 341 B
build/block-library/blocks/form-submit-button/style-rtl.css 69 B
build/block-library/blocks/form-submit-button/style.css 69 B
build/block-library/blocks/form/view.min.js 470 B
build/block-library/blocks/freeform/editor-rtl.css 2.6 kB
build/block-library/blocks/freeform/editor.css 2.6 kB
build/block-library/blocks/gallery/editor-rtl.css 946 B
build/block-library/blocks/gallery/editor.css 951 B
build/block-library/blocks/gallery/style-rtl.css 1.83 kB
build/block-library/blocks/gallery/style.css 1.82 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 334 B
build/block-library/blocks/group/editor.css 334 B
build/block-library/blocks/group/style-rtl.css 103 B
build/block-library/blocks/group/style.css 103 B
build/block-library/blocks/group/theme-rtl.css 79 B
build/block-library/blocks/group/theme.css 79 B
build/block-library/blocks/heading/style-rtl.css 188 B
build/block-library/blocks/heading/style.css 188 B
build/block-library/blocks/html/editor-rtl.css 346 B
build/block-library/blocks/html/editor.css 347 B
build/block-library/blocks/image/editor-rtl.css 785 B
build/block-library/blocks/image/editor.css 787 B
build/block-library/blocks/image/style-rtl.css 1.59 kB
build/block-library/blocks/image/style.css 1.59 kB
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/image/view.min.js 1.65 kB
build/block-library/blocks/latest-comments/style-rtl.css 355 B
build/block-library/blocks/latest-comments/style.css 354 B
build/block-library/blocks/latest-posts/editor-rtl.css 179 B
build/block-library/blocks/latest-posts/editor.css 179 B
build/block-library/blocks/latest-posts/style-rtl.css 509 B
build/block-library/blocks/latest-posts/style.css 510 B
build/block-library/blocks/list/style-rtl.css 107 B
build/block-library/blocks/list/style.css 107 B
build/block-library/blocks/loginout/style-rtl.css 61 B
build/block-library/blocks/loginout/style.css 61 B
build/block-library/blocks/media-text/editor-rtl.css 321 B
build/block-library/blocks/media-text/editor.css 320 B
build/block-library/blocks/media-text/style-rtl.css 558 B
build/block-library/blocks/media-text/style.css 556 B
build/block-library/blocks/more/editor-rtl.css 427 B
build/block-library/blocks/more/editor.css 427 B
build/block-library/blocks/navigation-link/editor-rtl.css 644 B
build/block-library/blocks/navigation-link/editor.css 645 B
build/block-library/blocks/navigation-link/style-rtl.css 192 B
build/block-library/blocks/navigation-link/style.css 191 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 295 B
build/block-library/blocks/navigation-submenu/editor.css 294 B
build/block-library/blocks/navigation/editor-rtl.css 2.19 kB
build/block-library/blocks/navigation/editor.css 2.2 kB
build/block-library/blocks/navigation/style-rtl.css 2.25 kB
build/block-library/blocks/navigation/style.css 2.23 kB
build/block-library/blocks/navigation/view.min.js 1.03 kB
build/block-library/blocks/nextpage/editor-rtl.css 392 B
build/block-library/blocks/nextpage/editor.css 392 B
build/block-library/blocks/page-list/editor-rtl.css 378 B
build/block-library/blocks/page-list/editor.css 378 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 236 B
build/block-library/blocks/paragraph/editor.css 236 B
build/block-library/blocks/paragraph/style-rtl.css 341 B
build/block-library/blocks/paragraph/style.css 340 B
build/block-library/blocks/post-author-biography/style-rtl.css 74 B
build/block-library/blocks/post-author-biography/style.css 74 B
build/block-library/blocks/post-author-name/style-rtl.css 69 B
build/block-library/blocks/post-author-name/style.css 69 B
build/block-library/blocks/post-author/editor-rtl.css 107 B
build/block-library/blocks/post-author/editor.css 107 B
build/block-library/blocks/post-author/style-rtl.css 188 B
build/block-library/blocks/post-author/style.css 189 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 527 B
build/block-library/blocks/post-comments-form/style.css 528 B
build/block-library/blocks/post-content/style-rtl.css 61 B
build/block-library/blocks/post-content/style.css 61 B
build/block-library/blocks/post-date/style-rtl.css 62 B
build/block-library/blocks/post-date/style.css 62 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 155 B
build/block-library/blocks/post-excerpt/style.css 155 B
build/block-library/blocks/post-featured-image/editor-rtl.css 729 B
build/block-library/blocks/post-featured-image/editor.css 726 B
build/block-library/blocks/post-featured-image/style-rtl.css 347 B
build/block-library/blocks/post-featured-image/style.css 347 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 399 B
build/block-library/blocks/post-template/style.css 398 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 70 B
build/block-library/blocks/post-time-to-read/style.css 70 B
build/block-library/blocks/post-title/style-rtl.css 162 B
build/block-library/blocks/post-title/style.css 162 B
build/block-library/blocks/preformatted/style-rtl.css 125 B
build/block-library/blocks/preformatted/style.css 125 B
build/block-library/blocks/pullquote/editor-rtl.css 134 B
build/block-library/blocks/pullquote/editor.css 134 B
build/block-library/blocks/pullquote/style-rtl.css 342 B
build/block-library/blocks/pullquote/style.css 342 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 121 B
build/block-library/blocks/query-pagination-numbers/editor.css 118 B
build/block-library/blocks/query-pagination/editor-rtl.css 154 B
build/block-library/blocks/query-pagination/editor.css 154 B
build/block-library/blocks/query-pagination/style-rtl.css 237 B
build/block-library/blocks/query-pagination/style.css 237 B
build/block-library/blocks/query-title/style-rtl.css 64 B
build/block-library/blocks/query-title/style.css 64 B
build/block-library/blocks/query/editor-rtl.css 452 B
build/block-library/blocks/query/editor.css 451 B
build/block-library/blocks/query/view.min.js 958 B
build/block-library/blocks/quote/style-rtl.css 238 B
build/block-library/blocks/quote/style.css 238 B
build/block-library/blocks/quote/theme-rtl.css 233 B
build/block-library/blocks/quote/theme.css 236 B
build/block-library/blocks/read-more/style-rtl.css 138 B
build/block-library/blocks/read-more/style.css 138 B
build/block-library/blocks/rss/editor-rtl.css 101 B
build/block-library/blocks/rss/editor.css 101 B
build/block-library/blocks/rss/style-rtl.css 288 B
build/block-library/blocks/rss/style.css 287 B
build/block-library/blocks/search/editor-rtl.css 199 B
build/block-library/blocks/search/editor.css 199 B
build/block-library/blocks/search/style-rtl.css 672 B
build/block-library/blocks/search/style.css 671 B
build/block-library/blocks/search/theme-rtl.css 113 B
build/block-library/blocks/search/theme.css 113 B
build/block-library/blocks/search/view.min.js 475 B
build/block-library/blocks/separator/editor-rtl.css 100 B
build/block-library/blocks/separator/editor.css 100 B
build/block-library/blocks/separator/style-rtl.css 248 B
build/block-library/blocks/separator/style.css 248 B
build/block-library/blocks/separator/theme-rtl.css 195 B
build/block-library/blocks/separator/theme.css 195 B
build/block-library/blocks/shortcode/editor-rtl.css 286 B
build/block-library/blocks/shortcode/editor.css 286 B
build/block-library/blocks/site-logo/editor-rtl.css 806 B
build/block-library/blocks/site-logo/editor.css 803 B
build/block-library/blocks/site-logo/style-rtl.css 218 B
build/block-library/blocks/site-logo/style.css 218 B
build/block-library/blocks/site-tagline/editor-rtl.css 87 B
build/block-library/blocks/site-tagline/editor.css 87 B
build/block-library/blocks/site-tagline/style-rtl.css 65 B
build/block-library/blocks/site-tagline/style.css 65 B
build/block-library/blocks/site-title/editor-rtl.css 85 B
build/block-library/blocks/site-title/editor.css 85 B
build/block-library/blocks/site-title/style-rtl.css 143 B
build/block-library/blocks/site-title/style.css 143 B
build/block-library/blocks/social-link/editor-rtl.css 338 B
build/block-library/blocks/social-link/editor.css 338 B
build/block-library/blocks/social-links/editor-rtl.css 729 B
build/block-library/blocks/social-links/editor.css 727 B
build/block-library/blocks/social-links/style-rtl.css 1.51 kB
build/block-library/blocks/social-links/style.css 1.5 kB
build/block-library/blocks/spacer/editor-rtl.css 346 B
build/block-library/blocks/spacer/editor.css 346 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table-of-contents/style-rtl.css 83 B
build/block-library/blocks/table-of-contents/style.css 83 B
build/block-library/blocks/table/editor-rtl.css 394 B
build/block-library/blocks/table/editor.css 394 B
build/block-library/blocks/table/style-rtl.css 640 B
build/block-library/blocks/table/style.css 639 B
build/block-library/blocks/table/theme-rtl.css 152 B
build/block-library/blocks/table/theme.css 152 B
build/block-library/blocks/tag-cloud/editor-rtl.css 144 B
build/block-library/blocks/tag-cloud/editor.css 144 B
build/block-library/blocks/tag-cloud/style-rtl.css 266 B
build/block-library/blocks/tag-cloud/style.css 265 B
build/block-library/blocks/template-part/editor-rtl.css 368 B
build/block-library/blocks/template-part/editor.css 368 B
build/block-library/blocks/template-part/theme-rtl.css 113 B
build/block-library/blocks/template-part/theme.css 113 B
build/block-library/blocks/term-description/style-rtl.css 126 B
build/block-library/blocks/term-description/style.css 126 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 165 B
build/block-library/blocks/text-columns/style.css 165 B
build/block-library/blocks/verse/style-rtl.css 98 B
build/block-library/blocks/verse/style.css 98 B
build/block-library/blocks/video/editor-rtl.css 396 B
build/block-library/blocks/video/editor.css 397 B
build/block-library/blocks/video/style-rtl.css 192 B
build/block-library/blocks/video/style.css 192 B
build/block-library/blocks/video/theme-rtl.css 134 B
build/block-library/blocks/video/theme.css 134 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.1 kB
build/block-library/common.css 1.1 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.7 kB
build/block-library/editor.css 11.7 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 219 kB
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/style-rtl.css 14.9 kB
build/block-library/style.css 14.9 kB
build/block-library/theme-rtl.css 708 B
build/block-library/theme.css 712 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 52.5 kB
build/commands/index.min.js 16.1 kB
build/commands/style-rtl.css 955 B
build/commands/style.css 952 B
build/components/index.min.js 227 kB
build/components/style-rtl.css 12.3 kB
build/components/style.css 12.3 kB
build/compose/index.min.js 12.7 kB
build/core-commands/index.min.js 3.11 kB
build/core-data/index.min.js 73.4 kB
build/customize-widgets/index.min.js 11 kB
build/customize-widgets/style-rtl.css 1.35 kB
build/customize-widgets/style.css 1.35 kB
build/data-controls/index.min.js 641 B
build/data/index.min.js 8.98 kB
build/date/index.min.js 18 kB
build/deprecated/index.min.js 458 B
build/dom-ready/index.min.js 325 B
build/dom/index.min.js 4.66 kB
build/edit-post/classic-rtl.css 578 B
build/edit-post/classic.css 580 B
build/edit-post/index.min.js 13.6 kB
build/edit-post/style-rtl.css 2.54 kB
build/edit-post/style.css 2.54 kB
build/edit-site/index.min.js 218 kB
build/edit-site/posts-rtl.css 7.35 kB
build/edit-site/posts.css 7.35 kB
build/edit-site/style-rtl.css 12.6 kB
build/edit-site/style.css 12.6 kB
build/edit-widgets/index.min.js 17.8 kB
build/edit-widgets/style-rtl.css 4.19 kB
build/edit-widgets/style.css 4.19 kB
build/editor/index.min.js 103 kB
build/editor/style-rtl.css 9.33 kB
build/editor/style.css 9.34 kB
build/element/index.min.js 4.83 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 8.11 kB
build/format-library/style-rtl.css 476 B
build/format-library/style.css 476 B
build/hooks/index.min.js 1.65 kB
build/html-entities/index.min.js 445 B
build/i18n/index.min.js 3.58 kB
build/is-shallow-equal/index.min.js 526 B
build/keyboard-shortcuts/index.min.js 1.31 kB
build/keycodes/index.min.js 1.46 kB
build/list-reusable-blocks/index.min.js 2.19 kB
build/list-reusable-blocks/style-rtl.css 852 B
build/list-reusable-blocks/style.css 852 B
build/media-utils/index.min.js 3.2 kB
build/notices/index.min.js 946 B
build/nux/index.min.js 1.62 kB
build/nux/style-rtl.css 749 B
build/nux/style.css 745 B
build/patterns/index.min.js 7.34 kB
build/patterns/style-rtl.css 687 B
build/patterns/style.css 685 B
build/plugins/index.min.js 1.81 kB
build/preferences-persistence/index.min.js 2.06 kB
build/preferences/index.min.js 2.9 kB
build/preferences/style-rtl.css 554 B
build/preferences/style.css 554 B
build/primitives/index.min.js 829 B
build/priority-queue/index.min.js 1.54 kB
build/private-apis/index.min.js 960 B
build/react-i18n/index.min.js 630 B
build/react-refresh-entry/index.min.js 9.47 kB
build/react-refresh-runtime/index.min.js 6.76 kB
build/redux-routine/index.min.js 2.69 kB
build/reusable-blocks/index.min.js 2.55 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.1 kB
build/router/index.min.js 1.96 kB
build/server-side-render/index.min.js 1.94 kB
build/shortcode/index.min.js 1.4 kB
build/style-engine/index.min.js 2.04 kB
build/token-list/index.min.js 581 B
build/url/index.min.js 3.9 kB
build/vendors/react-dom.min.js 41.7 kB
build/vendors/react-jsx-runtime.min.js 560 B
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 965 B
build/warning/index.min.js 250 B
build/widgets/index.min.js 7.17 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.03 kB

compressed-size-action

@michalczaplinski michalczaplinski self-requested a review October 7, 2024 15:51
Copy link
Contributor

@michalczaplinski michalczaplinski left a comment

Choose a reason for hiding this comment

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

Nice work, just had one comment in #65803 (comment)

Otherwise this looks good to go 🙂

@DAreRodz
Copy link
Contributor

DAreRodz commented Oct 7, 2024

This one is tricky! I see using tailwindcss classes with arbitrary values with data-wp-class as a legitimate use case. However, AFAIK, those characters are not allowed in HTML attribute names, which is where developers need to specify the class name... 🤔

I don't want to push back this PR, but maybe we need to revisit data-wp-class and come up with another syntax that allows the target class name to be defined inside the attribute value instead of changing the allowed characters in suffixes.

@sirreal, @michalczaplinski, do you agree? Any comments or ideas?

Copy link

github-actions bot commented Oct 7, 2024

Flaky tests detected in c5b8aed.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/11221440574
📝 Reported issues:

@michalczaplinski
Copy link
Contributor

@DAreRodz Thanks for bringing this up! I completely agree.

We gotta think it through. Perhaps a new syntax can be added that supports those characters. In any case, let's discuss before moving forward with the PR 🙂 .

@sirreal
Copy link
Member Author

sirreal commented Oct 7, 2024

The HTML standard on data- attributes says:

A custom data attribute is an attribute in no namespace whose name starts with the string "data-", has at least one character after the hyphen, is XML-compatible, and contains no ASCII upper alphas.

According to that, the implementation was wrong before because it allowed uppercase letters.


It's likely more interesting to look at what browers actually support. HTML parsing rules about attributes are more relaxed, I believe it's closer to "data attribute names cannot contain the characters "'=". The server-side implementation (powered by HTML API) currently supports much more than the client side. I believe all the tailwind examples in the description are supported by the server and are supported by browsers.

Here's a good demo to try on different browsers with some of the more interesting data attribute names

@michalczaplinski
Copy link
Contributor

Indeed, browsers might support those characters in the attribute names.

On the other hand, we faced a very similar question regarding directive naming data-wp—* vs. just wp—*. Browsers are permissive there as well, but we opted to follow the spec. I cannot find the reference to where that decision was made. Do happen to have a link, @DAreRodz ?

Two alternatives came up to the current PR:

  1. Use an object to pass the class name and the store reference:

    <div data-wp-class--edit-card='{ "bottom-[-24rem]": "context.isEditCard" }'>...</div>
  2. Create a new data-wp-class-name directive which would be used together with the

    <div data-wp-class-name="bottom-[-24rem]" data-wp-class="context.isEditCard">...</div>

The authoring experience of 1. (the object syntax) could be better (as @sirreal pointed out). It's true, but AI tooling makes the syntax question a bit less important in the future. AI-enabled editors can autocomplete with the right syntax without the user having to think about it.


That said, I am slightly in favor of allowing the special characters in suffixes (the current PR) if they turn out to be supported by all major browsers.

@sirreal
Copy link
Member Author

sirreal commented Oct 8, 2024

This gets more interesting the more time I spend on it. The most important thing is that the client and server agree, behavior should be indistinguishable. For me that's an essential principle of this API.


Because the HTML is read and injected from the attribute name (where HTML character references are not processed) and these HTML encodings can be part of attribute names, and because HTML character references are processed in attribute values, HTML character references mean that many things can be used as class names. The dev ex starts to get horrible here, but this is all supported by the server right now.

Did you know we can set multiple class values in a single directive on the server right now? I just realized it 🙂

The server handles this:

<div
	data-wp-class--class-with-space-FOO&#32;BAR="context.val"
></div>

Setting the class value to class-with-space-foo bar… is technically 2 classes. The client doesn't support this. This was also a problem on the client (I've just addressed) because classList implements DOMTokenList (space-delimited strings), so adding a value with a space in it is not allowed — it's 2 values!

Here's another interesting example using HTML character references:

<div
	data-wp-class--att&#61;&quot;value"="context.val"
></div>

The class set by the server here decodes to att="value"!

These character references also give us access to capital letters in class names, for example this gets the class name FOO:

<div
	data-wp-class--&#70;&#79;&#79;="context.val"
></div>

@sirreal
Copy link
Member Author

sirreal commented Oct 8, 2024

Obviously the developer experience becomes awful when you're using a directive like data-wp-class--&#70;&#79;&#79;="context.val" 🙂 I'm not advocating for that to be an advanced class syntax, although I'm also not sure whether artificial restrictions should be put in place 🤷

I simply want to point out that this behavior should either be supported or not supported, but the client and server should not support different things.

@DAreRodz
Copy link
Contributor

DAreRodz commented Oct 8, 2024

Browsers are permissive there as well, but we opted to follow the spec. I cannot find the reference to where that decision was made. Do happen to have a link, DAreRodz?

There was a discussion back in the days of the Block Hydration Experiments. Here's the link:

@DAreRodz
Copy link
Contributor

DAreRodz commented Oct 8, 2024

@sirreal, those examples you shared are really interesting. 🤔 Do you know if that syntax works in browsers as well? Asking because I did a quick test, and the attribute name seems to keep the escape characters. E.g., let's take the following example:

<div
	data-wp-class--class-with-space-FOO&#32;BAR="context.val&#32;bar"
></div>

You can see the escape characters remain in the nodeName string.

 $0.attributes[0].nodeName
// 'data-wp-class--class-with-space-foo&#32;bar'

The same characters in the attribute seem to be parsed, though.

$0.attributes[0].nodeValue
// 'context.val bar'

@sirreal
Copy link
Member Author

sirreal commented Oct 8, 2024

Yes, all of those examples already worked on the server and work on the client as of this PR (matching server behavior). Tested across latest Chrome, Firefox, and Safari.

HTML character references are not processed in HTML attribute names but they are in values. The HTML API backing the server implementation gets this right and its why we have this interesting behavior now.

@sirreal
Copy link
Member Author

sirreal commented Oct 8, 2024

Here's some basic demo code to play with:

<div data-wp-interactive="demo" data-wp-context='{"val": true}' id="demo-6213">
	<style >
		#demo-6213 {
			div { min-width: 10px; min-height: 10px; background: cyan; }
			div::before {
				content: 'class name: ' attr(class);
			}
			.att\=\"value\" { border-top: 2px solid yellow; }
			.class-with-space-FOO {  border-right: 2px solid yellow; }
			.BAR {  border-bottom: 2px solid yellow; }
		}
	</style>
	<div data-wp-class--default="context.val"></div>
	<div
		data-wp-class--&#70;&#79;&#79="context.val"
	></div>
	<div
		data-wp-class--att&#61;&quot;value"="context.val"
	></div>
	<button type="button" data-wp-on--click="handleTest">toggle val</button>
</div>
import * as I from '@wordpress/interactivity';
const store = I.createStore("demo", {
	handleTest() {
		I.getContext().val = ! I.getContext().val;
	},
});

@gziolo
Copy link
Member

gziolo commented Oct 22, 2024

@sirreal, I have just tested the HTML you provided in #65803 (comment) with the less privileged user – author. Unfortunately, data attributes with special characters like data-wp-class--&#70;&#79;&#79 or data-wp-class--att&#61;&quot;value" get filtered out when saving to the database. For consistency, we would have to update kses implementation to ensure that these HTML snippets work everywhere.

@sirreal
Copy link
Member Author

sirreal commented Oct 22, 2024

https://core.trac.wordpress.org/ticket/61501 and WordPress/wordpress-develop#6429 propose allowing more data attribute names through kses. With a reasonable motivation we may be able to move those forward.

Not everything goes through kses. Things like post content and blocks will, but plugins may have custom HTML that doesn't pass through kses but is processed by the Interactivity API.

I'm not sure what that means for these changes. Should the Interactivity API inherit limitations and restrictions from other systems?

@gziolo
Copy link
Member

gziolo commented Oct 23, 2024

Should the Interactivity API inherit limitations and restrictions from other systems?

That’s an perfect question. It looks like you need to be an user with special permissions to save the advanced Tailwind syntax to the database. That also applies to Interactivity API which might be a good middle ground. It's mostly the question whether we should relax the kses implementation to support more common use cases discussed in this PR.

@luisherranz
Copy link
Member

Since this conversation, I'm opposed to introducing APIs that promote the use of invalid HTML in WordPress, even if browsers support them.

I think it's important for WordPress to remain spec-compliant when there are API alternatives that ensure it will work in all cases, like this one from @Potherca:

Regarding HTML validity (from an accessibility perspective) and working for (semi-)government agencies...

Although the EN 301 549 en WCAG do not specify anything regarding "valid" HTML, there are still government agencies that require HTML output to pass validation.

In this respect, it might be ill-advised to use : in attributes names (as that would trigger validation errors) if valid alternatives are available.

So, my proposal is not to add support for attributes that have characters other than hyphens, underscores or dots (disregarded because of lack of JSX support). I guess we should probably fix that in the server.

For the specific case of classes with unusual characters, we can leverage the suffix "default" for data-wp-class, which we have carefully reserved until now.

My idea is that passing an object to data-wp-class would allow you to control multiple classes from the state. In that scenario, you could include all kinds of characters. It would work as follows.

Instead of:

<div
  data-wp-class--some-class="state.isSomeClass"
  data-wp-class---some-tailwaind-[-24rem]="state.isTailwindClass"
></div>

You would use:

<div data-wp-class="state.someClasses"></div>

And then define state.someClasses as an object:

store('...', {
  state: {
    someClasses: {
      'some-class': true,
      'some-tailwind-[-24rem]': false,
    },
  },
});

And toggle the object properties:

const { state } = store('...', {
  actions: {
    toggleTailwindClass() {
      state.someClasses['some-tailwaind-[-24rem]'] =
        !state.someClasses['some-tailwaind-[-24rem]'];
    },
  },
});

This API wouldn't be only a way to solve this particular edge case since its uses go beyond just this (like aggregating a bunch of classes into a single directive), but it would help solve this edge case (and others, like uppercase class names fooBar).

So the mental model for data-wp-class would become:

  • data-wp-class--{prefix}: for simple, lowercase, class names.
  • data-wp-class: for more complex cases with multiple classes and less conventional class names.

@sirreal
Copy link
Member Author

sirreal commented Nov 14, 2024

That seems like reasonable opposition to supporting these non-standard data attributes.

In that case this should absolutely be addressed on the server so that the behaviors match. I've created a trac ticket for that: https://core.trac.wordpress.org/ticket/62426

If this PR doesn't move ahead, it's likely a good idea to extract this change to avoid relying on a fragile regex: https://github.com/WordPress/gutenberg/pull/65803/files#r1783979043

@sirreal
Copy link
Member Author

sirreal commented Dec 27, 2024

WordPress/wordpress-develop#8048 restricts server-side directives.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Interactivity API API to add frontend interactivity to blocks. [Packages] Interactivity /packages/interactivity [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants