Skip to content

Commit 89a226f

Browse files
committed
WIP: Add support for the rest of the common IN BODY tags.
1 parent 85de4aa commit 89a226f

6 files changed

Lines changed: 95 additions & 56 deletions

File tree

src/wp-includes/html-api/class-wp-html-active-formatting-elements.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ public function current_node() {
8686
return $current_node ? $current_node : null;
8787
}
8888

89+
/**
90+
* Inserts a marker at the end of the list of active formatting elements.
91+
*
92+
* @since 6.5.0
93+
*/
94+
public function insert_marker() {
95+
$marker = new WP_HTML_Token( null, 'marker', false );
96+
$this->push( $marker );
97+
}
98+
8999
/**
90100
* Pushes a node onto the stack of active formatting elements.
91101
*

src/wp-includes/html-api/class-wp-html-open-elements.php

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,9 @@ public function has_element_in_scope( $tag_name ) {
150150
return $this->has_element_in_specific_scope(
151151
$tag_name,
152152
array(
153-
154-
/*
155-
* Because it's not currently possible to encounter
156-
* one of the termination elements, they don't need
157-
* to be listed here. If they were, they would be
158-
* unreachable and only waste CPU cycles while
159-
* scanning through HTML.
160-
*/
153+
'APPLET',
154+
'MARQUEE',
155+
'OBJECT',
161156
)
162157
);
163158
}
@@ -421,7 +416,10 @@ public function after_element_push( $item ) {
421416
* cases where the precalculated value needs to change.
422417
*/
423418
switch ( $item->node_name ) {
419+
case 'APPLET':
424420
case 'BUTTON':
421+
case 'MARQUEE':
422+
case 'OBJECT':
425423
$this->has_p_in_button_scope = false;
426424
break;
427425

src/wp-includes/html-api/class-wp-html-processor.php

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,26 @@ public function step( $node_to_process = self::PROCESS_NEXT_NODE ) {
516516
* is provided in the opening tag, otherwise it expects a tag closer.
517517
*/
518518
$top_node = $this->state->stack_of_open_elements->current_node();
519-
if ( $top_node && self::is_void( $top_node->node_name ) ) {
519+
if (
520+
$top_node &&
521+
(
522+
self::is_void( $top_node->node_name ) ||
523+
524+
// Special: Skips SCRIPT data in Tag Processor.
525+
'SCRIPT' === $top_node->node_name ||
526+
527+
// Special: Skips RCDATA data in Tag Processor.
528+
'TEXTAREA' === $top_node->node_name ||
529+
'TITLE' === $top_node->node_name ||
530+
531+
// Special: Skips RAWTEXT data in Tag Processor.
532+
'IFRAME' === $top_node->node_name ||
533+
'NOEMBED' === $top_node->node_name ||
534+
'NOFRAMES' === $top_node->node_name ||
535+
'STYLE' === $top_node->node_name ||
536+
'XMP' === $top_node->node_name
537+
)
538+
) {
520539
$this->state->stack_of_open_elements->pop();
521540
}
522541

@@ -948,6 +967,18 @@ private function step_in_body() {
948967
$this->run_adoption_agency_algorithm();
949968
return true;
950969

970+
/*
971+
* > A start tag whose tag name is one of: "applet", "marquee", "object"
972+
*/
973+
case '+APPLET':
974+
case '+MARQUEE':
975+
case '+OBJECT':
976+
$this->reconstruct_active_formatting_elements();
977+
$this->insert_html_element( $this->state->current_token );
978+
$this->state->active_formatting_elements->insert_marker();
979+
$this->state->frameset_ok = false;
980+
return true;
981+
951982
/*
952983
* > An end tag whose tag name is "br"
953984
* > Parse error. Drop the attributes from the token, and act as described in the next
@@ -982,6 +1013,39 @@ private function step_in_body() {
9821013
$this->insert_html_element( $this->state->current_token );
9831014
$this->state->frameset_ok = false;
9841015
return true;
1016+
1017+
/*
1018+
* > A start tag whose tag name is "textarea"
1019+
*/
1020+
case '+TEXTAREA':
1021+
$this->insert_html_element( $this->state->current_token );
1022+
$this->state->frameset_ok = false;
1023+
return true;
1024+
1025+
/*
1026+
* > A start tag whose tag name is "xmp"
1027+
*/
1028+
case '+XMP':
1029+
if ( $this->state->stack_of_open_elements->has_p_in_button_scope() ) {
1030+
$this->close_a_p_element();
1031+
}
1032+
$this->reconstruct_active_formatting_elements();
1033+
$this->insert_html_element( $this->state->current_token );
1034+
$this->state->frameset_ok = false;
1035+
return true;
1036+
1037+
/*
1038+
* > A start tag whose tag name is "iframe"
1039+
*/
1040+
case '+IFRAME':
1041+
$this->state->frameset_ok = false;
1042+
return true;
1043+
1044+
/*
1045+
* > A start tag whose tag name is "noembed"
1046+
*/
1047+
case '+NOEMBED':
1048+
return true;
9851049
}
9861050

9871051
/*
@@ -1001,7 +1065,6 @@ private function step_in_body() {
10011065
* @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody
10021066
*/
10031067
switch ( $tag_name ) {
1004-
case 'APPLET':
10051068
case 'AREA':
10061069
case 'BASE':
10071070
case 'BASEFONT':
@@ -1010,26 +1073,18 @@ private function step_in_body() {
10101073
case 'CAPTION':
10111074
case 'COL':
10121075
case 'COLGROUP':
1013-
case 'DD':
1014-
case 'DT':
10151076
case 'FORM':
10161077
case 'FRAME':
10171078
case 'FRAMESET':
10181079
case 'HEAD':
10191080
case 'HTML':
1020-
case 'IFRAME':
10211081
case 'INPUT':
1022-
case 'LI':
10231082
case 'LINK':
1024-
case 'MARQUEE':
10251083
case 'MATH':
10261084
case 'META':
10271085
case 'NOBR':
1028-
case 'NOEMBED':
10291086
case 'NOFRAMES':
10301087
case 'NOSCRIPT':
1031-
case 'OBJECT':
1032-
case 'OL':
10331088
case 'OPTGROUP':
10341089
case 'OPTION':
10351090
case 'PARAM':
@@ -1048,15 +1103,13 @@ private function step_in_body() {
10481103
case 'TBODY':
10491104
case 'TD':
10501105
case 'TEMPLATE':
1051-
case 'TEXTAREA':
10521106
case 'TFOOT':
10531107
case 'TH':
10541108
case 'THEAD':
10551109
case 'TITLE':
10561110
case 'TR':
10571111
case 'TRACK':
10581112
case 'UL':
1059-
case 'XMP':
10601113
$this->last_error = self::ERROR_UNSUPPORTED;
10611114
throw new WP_HTML_Unsupported_Exception( "Cannot process {$tag_name} element." );
10621115
}

tests/phpunit/tests/html-api/wpHtmlProcessor.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ public function test_step_in_body_fails_on_unsupported_tags( $tag_name ) {
238238
*/
239239
public function data_unsupported_special_in_body_tags() {
240240
return array(
241-
'APPLET' => array( 'APPLET' ),
242241
'BASE' => array( 'BASE' ),
243242
'BASEFONT' => array( 'BASEFONT' ),
244243
'BGSOUND' => array( 'BGSOUND' ),
@@ -251,17 +250,13 @@ public function data_unsupported_special_in_body_tags() {
251250
'FRAMESET' => array( 'FRAMESET' ),
252251
'HEAD' => array( 'HEAD' ),
253252
'HTML' => array( 'HTML' ),
254-
'IFRAME' => array( 'IFRAME' ),
255253
'INPUT' => array( 'INPUT' ),
256254
'LINK' => array( 'LINK' ),
257-
'MARQUEE' => array( 'MARQUEE' ),
258255
'MATH' => array( 'MATH' ),
259256
'META' => array( 'META' ),
260257
'NOBR' => array( 'NOBR' ),
261-
'NOEMBED' => array( 'NOEMBED' ),
262258
'NOFRAMES' => array( 'NOFRAMES' ),
263259
'NOSCRIPT' => array( 'NOSCRIPT' ),
264-
'OBJECT' => array( 'OBJECT' ),
265260
'OPTGROUP' => array( 'OPTGROUP' ),
266261
'OPTION' => array( 'OPTION' ),
267262
'PARAM' => array( 'PARAM' ),
@@ -280,14 +275,12 @@ public function data_unsupported_special_in_body_tags() {
280275
'TBODY' => array( 'TBODY' ),
281276
'TD' => array( 'TD' ),
282277
'TEMPLATE' => array( 'TEMPLATE' ),
283-
'TEXTAREA' => array( 'TEXTAREA' ),
284278
'TFOOT' => array( 'TFOOT' ),
285279
'TH' => array( 'TH' ),
286280
'THEAD' => array( 'THEAD' ),
287281
'TITLE' => array( 'TITLE' ),
288282
'TR' => array( 'TR' ),
289283
'TRACK' => array( 'TRACK' ),
290-
'XMP' => array( 'XMP' ),
291284
);
292285
}
293286
}

tests/phpunit/tests/html-api/wpHtmlProcessorBreadcrumbs.php

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public function data_single_tag_of_supported_elements() {
4040
'ABBR',
4141
'ACRONYM', // Neutralized.
4242
'ADDRESS',
43+
'APPLET', // Deprecated.
44+
'AREA',
4345
'ARTICLE',
4446
'ASIDE',
4547
'AUDIO',
@@ -48,6 +50,7 @@ public function data_single_tag_of_supported_elements() {
4850
'BDO',
4951
'BIG',
5052
'BLINK', // Deprecated.
53+
'BR',
5154
'BUTTON',
5255
'CANVAS',
5356
'CENTER', // Neutralized.
@@ -65,6 +68,7 @@ public function data_single_tag_of_supported_elements() {
6568
'DL',
6669
'DT',
6770
'EM',
71+
'EMBED',
6872
'FIELDSET',
6973
'FIGCAPTION',
7074
'FIGURE',
@@ -78,26 +82,30 @@ public function data_single_tag_of_supported_elements() {
7882
'H6',
7983
'HEADER',
8084
'HGROUP',
85+
'HR',
8186
'I',
8287
'IMG',
8388
'INS',
84-
'LI',
8589
'ISINDEX', // Deprecated
90+
'LI',
8691
'KBD',
8792
'LABEL',
8893
'LEGEND',
8994
'MAIN',
9095
'MAP',
9196
'MARK',
97+
'MARQUEE', // Deprecated.
9298
'MENU',
9399
'METER',
94100
'MULTICOL', // Deprecated
95101
'NAV',
96102
'NEXTID', // Deprecated
103+
'OBJECT',
97104
'OL',
98105
'OUTPUT',
99106
'P',
100107
'PICTURE',
108+
'PRE',
101109
'PROGRESS',
102110
'Q',
103111
'RUBY',
@@ -119,14 +127,19 @@ public function data_single_tag_of_supported_elements() {
119127
'UL',
120128
'VAR',
121129
'VIDEO',
130+
'WBR',
122131
);
123132

124133
$data = array();
125134
foreach ( $supported_elements as $tag_name ) {
126135
$data[ $tag_name ] = array( "<{$tag_name}>", $tag_name );
127136
}
128137

138+
$data['IFRAME'] = array( '<iframe></iframe>', 'IFRAME' );
129139
$data['IMAGE (treated as an IMG)'] = array( '<image>', 'IMG' );
140+
$data['NOEMBED'] = array( '<noembed></noembed>', 'NOEMBED' ); // Neutralized.
141+
$data['TEXTAREA'] = array( '<textarea></textarea>', 'TEXTAREA' );
142+
$data['XMP'] = array( '<xmp></xmp>', 'XMP' ); // Deprecated, use PRE instead.
130143

131144
return $data;
132145
}
@@ -161,7 +174,6 @@ public function test_fails_when_encountering_unsupported_tag( $html ) {
161174
*/
162175
public function data_unsupported_elements() {
163176
$unsupported_elements = array(
164-
'APPLET', // Deprecated.
165177
'BASE',
166178
'BGSOUND', // Deprecated; self-closing if self-closing flag provided, otherwise normal.
167179
'BODY',
@@ -173,17 +185,13 @@ public function data_unsupported_elements() {
173185
'FRAMESET',
174186
'HEAD',
175187
'HTML',
176-
'IFRAME',
177188
'INPUT',
178189
'LINK',
179-
'MARQUEE', // Deprecated.
180190
'MATH',
181191
'META',
182192
'NOBR', // Neutralized.
183-
'NOEMBED', // Neutralized.
184193
'NOFRAMES', // Neutralized.
185194
'NOSCRIPT',
186-
'OBJECT',
187195
'OPTGROUP',
188196
'OPTION',
189197
'PLAINTEXT', // Neutralized.
@@ -200,14 +208,12 @@ public function data_unsupported_elements() {
200208
'TBODY',
201209
'TD',
202210
'TEMPLATE',
203-
'TEXTAREA',
204211
'TFOOT',
205212
'TH',
206213
'THEAD',
207214
'TITLE',
208215
'TR',
209216
'TRACK',
210-
'XMP', // Deprecated, use PRE instead.
211217
);
212218

213219
$data = array();

0 commit comments

Comments
 (0)