105
105
* - Formatting elements: B, BIG, CODE, EM, FONT, I, SMALL, STRIKE, STRONG, TT, U.
106
106
* - Heading elements: H1, H2, H3, H4, H5, H6, HGROUP.
107
107
* - Links: A.
108
- * - Lists: DL .
108
+ * - Lists: DD, DL, DT, LI, OL, LI .
109
109
* - Media elements: AUDIO, CANVAS, FIGCAPTION, FIGURE, IMG, MAP, PICTURE, VIDEO.
110
110
* - Paragraph: P.
111
111
* - Phrasing elements: ABBR, BDI, BDO, CITE, DATA, DEL, DFN, INS, MARK, OUTPUT, Q, SAMP, SUB, SUP, TIME, VAR.
@@ -648,10 +648,12 @@ private function step_in_body() {
648
648
case '+MAIN ' :
649
649
case '+MENU ' :
650
650
case '+NAV ' :
651
+ case '+OL ' :
651
652
case '+P ' :
652
653
case '+SEARCH ' :
653
654
case '+SECTION ' :
654
655
case '+SUMMARY ' :
656
+ case '+UL ' :
655
657
if ( $ this ->state ->stack_of_open_elements ->has_p_in_button_scope () ) {
656
658
$ this ->close_a_p_element ();
657
659
}
@@ -685,9 +687,11 @@ private function step_in_body() {
685
687
case '-MAIN ' :
686
688
case '-MENU ' :
687
689
case '-NAV ' :
690
+ case '-OL ' :
688
691
case '-SEARCH ' :
689
692
case '-SECTION ' :
690
693
case '-SUMMARY ' :
694
+ case '-UL ' :
691
695
if ( ! $ this ->state ->stack_of_open_elements ->has_element_in_scope ( $ tag_name ) ) {
692
696
// @todo Report parse error.
693
697
// Ignore the token.
@@ -755,6 +759,109 @@ private function step_in_body() {
755
759
$ this ->state ->stack_of_open_elements ->pop_until ( '(internal: H1 through H6 - do not use) ' );
756
760
return true ;
757
761
762
+ /*
763
+ * > A start tag whose tag name is "li"
764
+ * > A start tag whose tag name is one of: "dd", "dt"
765
+ */
766
+ case '+DD ' :
767
+ case '+DT ' :
768
+ case '+LI ' :
769
+ $ this ->state ->frameset_ok = false ;
770
+ $ node = $ this ->state ->stack_of_open_elements ->current_node ();
771
+ $ is_li = 'LI ' === $ tag_name ;
772
+
773
+ in_body_list_loop:
774
+ /*
775
+ * The logic for LI and DT/DD is the same except for one point: LI elements _only_
776
+ * close other LI elements, but a DT or DD element closes _any_ open DT or DD element.
777
+ */
778
+ if ( $ is_li ? 'LI ' === $ node ->node_name : ( 'DD ' === $ node ->node_name || 'DT ' === $ node ->node_name ) ) {
779
+ $ node_name = $ is_li ? 'LI ' : $ node ->node_name ;
780
+ $ this ->generate_implied_end_tags ( $ node_name );
781
+ if ( $ node_name !== $ this ->state ->stack_of_open_elements ->current_node ()->node_name ) {
782
+ // @todo Indicate a parse error once it's possible. This error does not impact the logic here.
783
+ }
784
+
785
+ $ this ->state ->stack_of_open_elements ->pop_until ( $ node_name );
786
+ goto in_body_list_done;
787
+ }
788
+
789
+ if (
790
+ 'ADDRESS ' !== $ node ->node_name &&
791
+ 'DIV ' !== $ node ->node_name &&
792
+ 'P ' !== $ node ->node_name &&
793
+ $ this ->is_special ( $ node ->node_name )
794
+ ) {
795
+ /*
796
+ * > If node is in the special category, but is not an address, div,
797
+ * > or p element, then jump to the step labeled done below.
798
+ */
799
+ goto in_body_list_done;
800
+ } else {
801
+ /*
802
+ * > Otherwise, set node to the previous entry in the stack of open elements
803
+ * > and return to the step labeled loop.
804
+ */
805
+ foreach ( $ this ->state ->stack_of_open_elements ->walk_up ( $ node ) as $ item ) {
806
+ $ node = $ item ;
807
+ break ;
808
+ }
809
+ goto in_body_list_loop;
810
+ }
811
+
812
+ in_body_list_done:
813
+ if ( $ this ->state ->stack_of_open_elements ->has_p_in_button_scope () ) {
814
+ $ this ->close_a_p_element ();
815
+ }
816
+
817
+ $ this ->insert_html_element ( $ this ->state ->current_token );
818
+ return true ;
819
+
820
+ /*
821
+ * > An end tag whose tag name is "li"
822
+ * > An end tag whose tag name is one of: "dd", "dt"
823
+ */
824
+ case '-DD ' :
825
+ case '-DT ' :
826
+ case '-LI ' :
827
+ if (
828
+ /*
829
+ * An end tag whose tag name is "li":
830
+ * If the stack of open elements does not have an li element in list item scope,
831
+ * then this is a parse error; ignore the token.
832
+ */
833
+ (
834
+ 'LI ' === $ tag_name &&
835
+ ! $ this ->state ->stack_of_open_elements ->has_element_in_list_item_scope ( 'LI ' )
836
+ ) ||
837
+ /*
838
+ * An end tag whose tag name is one of: "dd", "dt":
839
+ * If the stack of open elements does not have an element in scope that is an
840
+ * HTML element with the same tag name as that of the token, then this is a
841
+ * parse error; ignore the token.
842
+ */
843
+ (
844
+ 'LI ' !== $ tag_name &&
845
+ ! $ this ->state ->stack_of_open_elements ->has_element_in_scope ( $ tag_name )
846
+ )
847
+ ) {
848
+ /*
849
+ * This is a parse error, ignore the token.
850
+ *
851
+ * @todo Indicate a parse error once it's possible.
852
+ */
853
+ return $ this ->step ();
854
+ }
855
+
856
+ $ this ->generate_implied_end_tags ( $ tag_name );
857
+
858
+ if ( $ tag_name !== $ this ->state ->stack_of_open_elements ->current_node ()->node_name ) {
859
+ // @todo Indicate a parse error once it's possible. This error does not impact the logic here.
860
+ }
861
+
862
+ $ this ->state ->stack_of_open_elements ->pop_until ( $ tag_name );
863
+ return true ;
864
+
758
865
/*
759
866
* > An end tag whose tag name is "p"
760
867
*/
@@ -1223,6 +1330,9 @@ private function close_a_p_element() {
1223
1330
*/
1224
1331
private function generate_implied_end_tags ( $ except_for_this_element = null ) {
1225
1332
$ elements_with_implied_end_tags = array (
1333
+ 'DD ' ,
1334
+ 'DT ' ,
1335
+ 'LI ' ,
1226
1336
'P ' ,
1227
1337
);
1228
1338
@@ -1248,6 +1358,9 @@ private function generate_implied_end_tags( $except_for_this_element = null ) {
1248
1358
*/
1249
1359
private function generate_implied_end_tags_thoroughly () {
1250
1360
$ elements_with_implied_end_tags = array (
1361
+ 'DD ' ,
1362
+ 'DT ' ,
1363
+ 'LI ' ,
1251
1364
'P ' ,
1252
1365
);
1253
1366
0 commit comments