<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[58740] trunk: HTML API: Remove leading whitespace after removing class names.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/58740">58740</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/58740","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dmsnell</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2024-07-17 00:10:52 +0000 (Wed, 17 Jul 2024)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>HTML API: Remove leading whitespace after removing class names.

In part of a larger review of CSS semantics and behaviors, this patch
takes the opportunity to remove leading whitespace in an updated class
attribute after the first class in the attribute has been removed.

Previously, if the first class name had been removed, the whitespace
that formerly followed it would remain in the class attribute. This
stood in contrast to removing other class names, which removed their
associated whitespace.

There should be no semantic or functional changes in this patch, only
a slightly-large diff for modified HTML documents that looks prettier
when removing the first class name in a class attribute.

Developed in https://github.com/WordPress/wordpress-develop/pull/6933
Discussed in https://core.trac.wordpress.org/ticket/61531

Props dmsnell, jonsurrell.
See <a href="https://core.trac.wordpress.org/ticket/61531">#61531</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludeshtmlapiclasswphtmltagprocessorphp">trunk/src/wp-includes/html-api/class-wp-html-tag-processor.php</a></li>
<li><a href="#trunktestsphpunittestshtmlapiwpHtmlTagProcessorphp">trunk/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludeshtmlapiclasswphtmltagprocessorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/html-api/class-wp-html-tag-processor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/html-api/class-wp-html-tag-processor.php    2024-07-16 18:37:46 UTC (rev 58739)
+++ trunk/src/wp-includes/html-api/class-wp-html-tag-processor.php      2024-07-17 00:10:52 UTC (rev 58740)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2218,7 +2218,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                         * whitespace to a single space, which might appear cleaner
</span><span class="cx" style="display: block; padding: 0 10px">                         * in the output HTML but produce a noisier change.
</span><span class="cx" style="display: block; padding: 0 10px">                         */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $class .= substr( $existing_class, $ws_at, $ws_length );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( '' !== $class ) {
+                               $class .= substr( $existing_class, $ws_at, $ws_length );
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                         $class .= $name;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunktestsphpunittestshtmlapiwpHtmlTagProcessorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php 2024-07-16 18:37:46 UTC (rev 58739)
+++ trunk/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php   2024-07-17 00:10:52 UTC (rev 58740)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1376,12 +1376,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $processor->remove_class( 'main' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        '<div class=" with-border" id="first"><span class="not-main bold with-border" id="second">Text</span></div>',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 '<div class="with-border" id="first"><span class="not-main bold with-border" id="second">Text</span></div>',
</ins><span class="cx" style="display: block; padding: 0 10px">                         $processor->get_updated_html(),
</span><span class="cx" style="display: block; padding: 0 10px">                        'Updated HTML does not reflect class name removed from existing class attribute via remove_class()'
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        ' with-border',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'with-border',
</ins><span class="cx" style="display: block; padding: 0 10px">                         $processor->get_attribute( 'class' ),
</span><span class="cx" style="display: block; padding: 0 10px">                        "get_attribute( 'class' ) does not reflect class name removed from existing class attribute via remove_class()"
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1466,12 +1466,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $processor->add_class( 'foo-class' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        '<div class="   main   with-border foo-class" id="first"><span class="not-main bold with-border" id="second">Text</span></div>',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 '<div class="main   with-border foo-class" id="first"><span class="not-main bold with-border" id="second">Text</span></div>',
</ins><span class="cx" style="display: block; padding: 0 10px">                         $processor->get_updated_html(),
</span><span class="cx" style="display: block; padding: 0 10px">                        'Updated HTML does not reflect existing excessive whitespace after adding class name via add_class()'
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        '   main   with-border foo-class',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'main   with-border foo-class',
</ins><span class="cx" style="display: block; padding: 0 10px">                         $processor->get_attribute( 'class' ),
</span><span class="cx" style="display: block; padding: 0 10px">                        "get_attribute( 'class' ) does not reflect existing excessive whitespace after adding class name via add_class()"
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1490,12 +1490,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $processor->remove_class( 'with-border' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        '<div class="   main" id="first"><span class="not-main bold with-border" id="second">Text</span></div>',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 '<div class="main" id="first"><span class="not-main bold with-border" id="second">Text</span></div>',
</ins><span class="cx" style="display: block; padding: 0 10px">                         $processor->get_updated_html(),
</span><span class="cx" style="display: block; padding: 0 10px">                        'Updated HTML does not reflect existing excessive whitespace after removing class name via remove_class()'
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        '   main',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'main',
</ins><span class="cx" style="display: block; padding: 0 10px">                         $processor->get_attribute( 'class' ),
</span><span class="cx" style="display: block; padding: 0 10px">                        "get_attribute( 'class' ) does not reflect existing excessive whitespace after removing class name via removing_class()"
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1696,8 +1696,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $expected_output = <<<HTML
</span><span class="cx" style="display: block; padding: 0 10px"> <div data-details="{ &quot;key&quot;: &quot;value&quot; }" selected class="merge-message is-processed" checked>
</span><span class="cx" style="display: block; padding: 0 10px">        <div class="select-menu d-inline-block">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                <div checked class=" MixedCaseHTML position-relative button-group Another-Mixed-Case" />
-               <div checked class=" MixedCaseHTML position-relative button-group Another-Mixed-Case">
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         <div checked class="MixedCaseHTML position-relative button-group Another-Mixed-Case" />
+               <div checked class="MixedCaseHTML position-relative button-group Another-Mixed-Case">
</ins><span class="cx" style="display: block; padding: 0 10px">                         <button type="button" class="merge-box-button btn-group-merge rounded-left-2 btn  BtnGroup-item js-details-target hx_create-pr-button" aria-expanded="false" data-details-container=".js-merge-pr" disabled="">
</span><span class="cx" style="display: block; padding: 0 10px">                          Merge pull request
</span><span class="cx" style="display: block; padding: 0 10px">                        </button>
</span></span></pre>
</div>
</div>

</body>
</html>