#59209 closed enhancement (fixed)
HTML API: Add class name utilities has_class() and class_list()
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 6.4 | Priority: | normal |
Severity: | normal | Version: | 6.4 |
Component: | HTML API | Keywords: | has-patch has-unit-tests commit |
Focuses: | Cc: |
Description
This patch adds two new public methods to the HTML Tag Processor:
has_class()
indicates if a matched tag contains a given CSS class name.class_list()
returns a generator to iterate over all the class names in a matched tag.
Included in this patch is a refactoring of the internal logic when matching a tag to reuse the new has_class()
function. Previously it was relying on optimized code in the matches()
function which performed byte-for-byte class name comparison. With the change in this patch it will perform class name matching on the decoded value, which might differ if a class attribute contains character references.
These methods may be useful for running more complicated queries based on the presence or absence of CSS class names. The use of these methods avoids the need to manually decode the class attribute as reported by $process->get_attribute( 'class' )
.
Change History (12)
This ticket was mentioned in PR #5096 on WordPress/wordpress-develop by @dmsnell.
4 months ago
#1
- Keywords has-unit-tests added
@Bernhard Reiter commented on PR #5096:
3 months ago
#2
Unit tests are currently failing with what seems to be related to this change.
<details>
1) Tests_Blocks_Render::test_do_block_output with data set #9 ('core__columns.html', 'core__columns.server.html') File '/var/www/tests/phpunit/includes/../data/blocks/fixtures/core__columns.html' does not match expected value Failed asserting that two strings are identical. --- Expected +++ Actual @@ @@ ' -<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1 wp-block-columns-is-layout-flex"> +<div class="wp-block-columns has-3-columns"> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <p>Column One, Paragraph One</p> <p>Column One, Paragraph Two</p> /var/www/tests/phpunit/tests/blocks/render.php:237 phpvfscomposer:///var/www/vendor/phpunit/phpunit/phpunit:106 /var/www/vendor/bin/phpunit:118 2) Tests_Blocks_Render::test_do_block_output with data set #10 ('core__columns__deprecated.html', 'core__columns__deprecated.server.html') File '/var/www/tests/phpunit/includes/../data/blocks/fixtures/core__columns__deprecated.html' does not match expected value Failed asserting that two strings are identical. --- Expected +++ Actual @@ @@ ' -<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1 wp-block-columns-is-layout-flex"> +<div class="wp-block-columns has-3-columns"> <p class="layout-column-1">Column One, Paragraph One</p> <p class="layout-column-1">Column One, Paragraph Two</p> <p class="layout-column-2">Column Two, Paragraph One</p> <p class="layout-column-3">Column Three, Paragraph One</p> </div>' /var/www/tests/phpunit/tests/blocks/render.php:237 phpvfscomposer:///var/www/vendor/phpunit/phpunit/phpunit:106 /var/www/vendor/bin/phpunit:118 3) Tests_Blocks_Render::test_do_block_output with data set #21 ('core__gallery-with-caption.html', 'core__gallery-with-caption.server.html') File '/var/www/tests/phpunit/includes/../data/blocks/fixtures/core__gallery-with-caption.html' does not match expected value Failed asserting that two strings are identical. --- Expected +++ Actual @@ @@ ' <figure - class="wp-block-gallery has-nested-images columns-default is-cropped columns-2 wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex" + class="wp-block-gallery has-nested-images columns-default is-cropped columns-2 wp-block-gallery-1" > <figure class="wp-block-image size-large"> <img data-id="1421" /var/www/tests/phpunit/tests/blocks/render.php:237 phpvfscomposer:///var/www/vendor/phpunit/phpunit/phpunit:106 /var/www/vendor/bin/phpunit:118 4) Tests_Blocks_Render::test_do_block_output with data set #22 ('core__gallery.html', 'core__gallery.server.html') File '/var/www/tests/phpunit/includes/../data/blocks/fixtures/core__gallery.html' does not match expected value Failed asserting that two strings are identical. --- Expected +++ Actual @@ @@ ' <figure - class="wp-block-gallery has-nested-images columns-default is-cropped columns-2 wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex" + class="wp-block-gallery has-nested-images columns-default is-cropped columns-2 wp-block-gallery-1" > <figure class="wp-block-image size-large"> <img data-id="1421" /var/www/tests/phpunit/tests/blocks/render.php:237 phpvfscomposer:///var/www/vendor/phpunit/phpunit/phpunit:106 /var/www/vendor/bin/phpunit:118 5) Tests_Blocks_Render::test_do_block_output with data set #23 ('core__gallery__columns.html', 'core__gallery__columns.server.html') File '/var/www/tests/phpunit/includes/../data/blocks/fixtures/core__gallery__columns.html' does not match expected value Failed asserting that two strings are identical. --- Expected +++ Actual @@ @@ ' -<figure class="wp-block-gallery has-nested-images columns-1 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex"> +<figure class="wp-block-gallery has-nested-images columns-1 is-cropped wp-block-gallery-1"> <figure class="wp-block-image size-large"> [[Image(https://i0.wp.com/sergioestevaofolio.files.wordpress.com/2016/09/cropped-img_9054-1.jpg?w=190)]] +<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1"> <figure class="wp-block-image size-large"><a href="http://wptest.local/wp-content/uploads/2020/09/test-image-edited-1-[https://github.com/WordPress/wordpress-develop/actions/runs/5982522041/job/16231701670?pr=5096#step:14:683 682]x1024.jpg">[[Image(https://i0.wp.com/wptest.local/wp-content/uploads/2020/09/test-image-edited-1-682x1024.jpg)]]</a></figure> <figure class="wp-block-image size-large"><a href="http://wptest.local/wp-content/uploads/2020/09/test-image-edited-1024x682.jpg">[[Image(https://i0.wp.com/wptest.local/wp-content/uploads/2020/09/test-image-edited-1024x682.jpg)]]</a></figure> <figure class="wp-block-image size-large"><a href="http://wptest.local/wp-content/uploads/2020/04/test-image-1024x[https://github.com/WordPress/wordpress-develop/actions/runs/5982522041/job/16231701670?pr=5096#step:14:684 683].jpg">[[Image(https://i0.wp.com/wptest.local/wp-content/uploads/2020/04/test-image-1024x683.jpg)]]</a></figure> </figure> -<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex"> +<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1"> <figure class="wp-block-image size-large"><a href="http://wptest.local/wp-content/uploads/2020/09/test-image-edited-1-682x1024.jpg">[[Image(https://i0.wp.com/wptest.local/wp-content/uploads/2020/09/test-image-edited-1-682x1024.jpg)]]</a></figure> <figure class="wp-block-image size-large"><a href="http://wptest.local/wp-content/uploads/2020/09/test-image-edited-1024x682.jpg">[[Image(https://i0.wp.com/wptest.local/wp-content/uploads/2020/09/test-image-edited-1024x682.jpg)]]</a></figure> <figure class="wp-block-image size-large"><a href="http://wptest.local/wp-content/uploads/2020/04/test-image-1024x683.jpg">[[Image(https://i0.wp.com/wptest.local/wp-content/uploads/2020/04/test-image-1024x683.jpg)]]</a></figure> <figcaption class="blocks-gallery-caption">This gallery has a caption</figcaption> </figure>' /var/www/tests/phpunit/tests/blocks/render.php:237 phpvfscomposer:///var/www/vendor/phpunit/phpunit/phpunit:106 /var/www/vendor/bin/phpunit:118
</details>
3 months ago
#3
@ockham I saw those errors but assumed they were unrelated. I'm running them again rebased against an updated trunk
and will investigate further if they still fail
3 months ago
#4
@ockham quick update: I found some code calling the Tag Processor to search by class name, but it was searching for the whole class attribute including multiple class names. this is something we ran into early on in the adoption: the expectation that add_class
(singular) works with classes (plural).
so what broke is that when _improving_ the class_name
query parameter to focus on actual class names, it broke code that relied on doing a full byte-for-byte comparison of the value. not only did it perform byte-for-byte comparison before, but it wasn't breaking apart the sought-after class, so whitespace inside that should be splitting class names was treated as one big class name.
I believe we want to maintain the new behavior as it's going to be a faulty endeavor to search by class name with multiple classes. simple reordering of class names will break that. I'm going to update the code that depends on this behavior.
2 months ago
#6
Unit tests are currently failing with what seems to be related to this change.
oh darn I missed this, and I won't be able to address it before you're active. I'll try and prioritize it tomorrow and see if it's something small
@Bernhard Reiter commented on PR #5096:
2 months ago
#8
I was curious if class_list()
would pick up classes added via add_class()
(which are only flushed into the class
attribute when class_name_updates_to_attributes_updates()
is run), remembering this problem we had in a similar scenario with attributes.
Fortunately, it seems to work:
-
tests/phpunit/tests/html-api/wpHtmlTagProcessor.php
diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index 4469f90c4f..4db85070e7 100644
a b HTML; 2070 2070 $this->assertSame( array( 'one' ), $found_classes, 'Visited multiple copies of the same class name when it should have skipped the duplicates.' ); 2071 2071 } 2072 2072 2073 public function test_class_list_finds_unflushed_class_names() { 2074 $p = new WP_HTML_Tag_Processor( '<div class="one">' ); 2075 $p->next_tag(); 2076 2077 $p->add_class( 'two' ); 2078 2079 $found_classes = array(); 2080 foreach ( $p->class_list() as $class ) { 2081 $found_classes[] = $class; 2082 } 2083 $this->assertSame( array( 'one', 'two' ), $found_classes, 'Failed to report class names added via add_class.' ); 2084 } 2085 2086 2073 2087 /** 2074 2088 * @ticket 59209 2075 2089 *
I won't add this test for now, but we might want to consider adding a bit of coverage in a follow-up for how changes made by add_class
and remove_class
are picked up by class_list
and has_class
.
#10
@
2 months ago
- Owner set to Bernhard Reiter
- Resolution set to fixed
- Status changed from new to closed
In 56703:
@Bernhard Reiter commented on PR #5096:
2 months ago
#11
Committed to Core in https://core.trac.wordpress.org/changeset/56703.
2 months ago
#12
Fortunately, it seems to work:
this is the OO principle of delegation at work here. by the way, I had the same thought and double-checked at some point early on. as long as don't reach into our own internals _inside our internals_ then all these invariants should remain in place.
good thinking for double-checking this.
Trac ticket: #59209
This patch adds two new public methods to the HTML Tag Processor:
has_class()
indicates if a matched tag contains a given CSS class name.class_list()
returns a generator to iterate over all the class names in a matched tag.Included in this patch is a refactoring of the internal logic when matching a tag to reuse the new
has_class()
function. Previously it was relying on optimized code in thematches()
function which performed byte-for-byte class name comparison. With the change in this patch it will perform class name matching on the decoded value, which might differ if a class attribute contains character references.These methods may be useful for running more complicated queries based on the presence or absence of CSS class names. The use of these methods avoids the need to manually decode the class attribute as reported by
$process->get_attribute( 'class' )
.