diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index cce26a60c5350..a47fcc0260019 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -1544,6 +1544,165 @@ private function insert_html_element( $token ) { * HTML Specification Helpers */ + /** + * Returns whether a given element is an HTML tag name. + * + * @todo Verify this list. + * + * @since 6.5.0 + * + * @param string $tag_name Tag name to check. + * @return bool Whether the element is defined in the HTML specification. + */ + public static function is_html_tag( $tag_name ) { + $tag_name = strtoupper( $tag_name ); + + return ( + 'A' === $tag_name || + 'ABBR' === $tag_name || + 'ACRONYM' === $tag_name || // Neutralized. + 'ADDRESS' === $tag_name || + 'APPLET' === $tag_name || // Deprecated. + 'AREA' === $tag_name || + 'ARTICLE' === $tag_name || + 'ASIDE' === $tag_name || + 'AUDIO' === $tag_name || + 'B' === $tag_name || + 'BASE' === $tag_name || + 'BDI' === $tag_name || + 'BDO' === $tag_name || + 'BGSOUND' === $tag_name || // Deprecated; self-closing if self-closing flag provided, otherwise normal. + 'BIG' === $tag_name || + 'BLINK' === $tag_name || // Deprecated. + 'BLOCKQUOTE' === $tag_name || + 'BODY' === $tag_name || + 'BR' === $tag_name || + 'BUTTON' === $tag_name || + 'CANVAS' === $tag_name || + 'CAPTION' === $tag_name || + 'CENTER' === $tag_name || // Neutralized. + 'CITE' === $tag_name || + 'CODE' === $tag_name || + 'COL' === $tag_name || + 'COLGROUP' === $tag_name || + 'DATA' === $tag_name || + 'DATALIST' === $tag_name || + 'DD' === $tag_name || + 'DEL' === $tag_name || + 'DETAILS' === $tag_name || + 'DFN' === $tag_name || + 'DIALOG' === $tag_name || + 'DIR' === $tag_name || + 'DIV' === $tag_name || + 'DL' === $tag_name || + 'DT' === $tag_name || + 'EM' === $tag_name || + 'EMBED' === $tag_name || + 'FIELDSET' === $tag_name || + 'FIGCAPTION' === $tag_name || + 'FIGURE' === $tag_name || + 'FONT' === $tag_name || + 'FOOTER' === $tag_name || + 'FORM' === $tag_name || + 'FRAME' === $tag_name || + 'FRAMESET' === $tag_name || + 'H1' === $tag_name || + 'H2' === $tag_name || + 'H3' === $tag_name || + 'H4' === $tag_name || + 'H5' === $tag_name || + 'H6' === $tag_name || + 'HEAD' === $tag_name || + 'HEADER' === $tag_name || + 'HGROUP' === $tag_name || + 'HR' === $tag_name || + 'HTML' === $tag_name || + 'I' === $tag_name || + 'IFRAME' === $tag_name || + 'IMAGE' === $tag_name || + 'IMG' === $tag_name || + 'INPUT' === $tag_name || + 'INS' === $tag_name || + 'ISINDEX' === $tag_name || // Deprecated. + 'KBD' === $tag_name || + 'KEYGEN' === $tag_name || // Deprecated; void. + 'LABEL' === $tag_name || + 'LEGEND' === $tag_name || + 'LI' === $tag_name || + 'LINK' === $tag_name || + 'LISTING' === $tag_name || // Deprecated, use PRE instead. + 'MAIN' === $tag_name || + 'MAP' === $tag_name || + 'MARK' === $tag_name || + 'MARQUEE' === $tag_name || // Deprecated. + 'MATH' === $tag_name || + 'MENU' === $tag_name || + 'META' === $tag_name || + 'METER' === $tag_name || + 'MULTICOL' === $tag_name || // Deprecated. + 'NAV' === $tag_name || + 'NEXTID' === $tag_name || // Deprecated. + 'NOBR' === $tag_name || // Neutralized. + 'NOEMBED' === $tag_name || // Neutralized. + 'NOFRAMES' === $tag_name || // Neutralized. + 'NOSCRIPT' === $tag_name || + 'OBJECT' === $tag_name || + 'OL' === $tag_name || + 'OPTGROUP' === $tag_name || + 'OPTION' === $tag_name || + 'OUTPUT' === $tag_name || + 'P' === $tag_name || + 'PARAM' === $tag_name || + 'PICTURE' === $tag_name || + 'PLAINTEXT' === $tag_name || // Neutralized. + 'PRE' === $tag_name || + 'PROGRESS' === $tag_name || + 'Q' === $tag_name || + 'RB' === $tag_name || // Neutralized. + 'RP' === $tag_name || + 'RT' === $tag_name || + 'RTC' === $tag_name || // Neutralized. + 'RUBY' === $tag_name || + 'S' === $tag_name || + 'SAMP' === $tag_name || + 'SCRIPT' === $tag_name || + 'SEARCH' === $tag_name || + 'SECTION' === $tag_name || + 'SELECT' === $tag_name || + 'SLOT' === $tag_name || + 'SMALL' === $tag_name || + 'SOURCE' === $tag_name || + 'SPACER' === $tag_name || // Deprecated. + 'SPAN' === $tag_name || + 'STRIKE' === $tag_name || + 'STRONG' === $tag_name || + 'STYLE' === $tag_name || + 'SUB' === $tag_name || + 'SUMMARY' === $tag_name || + 'SUP' === $tag_name || + 'SVG' === $tag_name || + 'TABLE' === $tag_name || + 'TBODY' === $tag_name || + 'TD' === $tag_name || + 'TEMPLATE' === $tag_name || + 'TEXTAREA' === $tag_name || + 'TFOOT' === $tag_name || + 'TH' === $tag_name || + 'THEAD' === $tag_name || + 'TIME' === $tag_name || + 'TITLE' === $tag_name || + 'TR' === $tag_name || + 'TRACK' === $tag_name || + 'TT' === $tag_name || + 'U' === $tag_name || + 'UL' === $tag_name || + 'VAR' === $tag_name || + 'VIDEO' === $tag_name || + 'WBR' === $tag_name || + 'XMP' === $tag_name // Deprecated, use PRE instead. + ); + } + /** * Returns whether an element of a given name is in the HTML special category. * diff --git a/src/wp-includes/html-api/class-wp-html-tag-processor.php b/src/wp-includes/html-api/class-wp-html-tag-processor.php index ee6209c69e0ae..9aa44353fd97d 100644 --- a/src/wp-includes/html-api/class-wp-html-tag-processor.php +++ b/src/wp-includes/html-api/class-wp-html-tag-processor.php @@ -2286,15 +2286,16 @@ public function is_tag_closer() { * * For boolean attributes special handling is provided: * - When `true` is passed as the value, then only the attribute name is added to the tag. - * - When `false` is passed, the attribute gets removed if it existed before. + * - When `false` or `null` is passed, the attribute gets removed if it existed before. * * For string attributes, the value is escaped using the `esc_attr` function. * * @since 6.2.0 * @since 6.2.1 Fix: Only create a single update for multiple calls with case-variant attribute names. + * @since 6.5.0 Allows passing `null` to remove attribute. * - * @param string $name The attribute name to target. - * @param string|bool $value The new attribute value. + * @param string $name The attribute name to target. + * @param string|bool|null $value The new attribute value. * @return bool Whether an attribute value was set. */ public function set_attribute( $name, $value ) { @@ -2354,7 +2355,7 @@ public function set_attribute( $name, $value ) { * > To represent a false value, the attribute has to be omitted altogether. * - HTML5 spec, https://html.spec.whatwg.org/#boolean-attributes */ - if ( false === $value ) { + if ( null === $value || false === $value ) { return $this->remove_attribute( $name ); } diff --git a/src/wp-includes/html-api/class-wp-html.php b/src/wp-includes/html-api/class-wp-html.php new file mode 100644 index 0000000000000..189ebf44de134 --- /dev/null +++ b/src/wp-includes/html-api/class-wp-html.php @@ -0,0 +1,154 @@ + 'is-safe' ), 'Hello, world!' ); + * //
Is this > that?
+ * + * echo WP_HTML::tag( 'wp-emoji', array( 'name' => ':smile:' ), null, 'self-closing' ); + * //