Browse Source

LibWeb: Add ol start and li value attributes support

Bastiaan van der Plaat 1 year ago
parent
commit
1cdbfc2ff1

+ 27 - 12
Base/res/html/misc/lists.html

@@ -106,6 +106,21 @@
         <li>Third</li>
         <li>Third</li>
     </ol>
     </ol>
 
 
+    <p>with start offset</p>
+    <ol start="20">
+        <li>Item 20</li>
+        <li>Item 21</li>
+        <li>Item 22</li>
+    </ol>
+
+    <p>with different order</p>
+    <ol>
+        <li>Item 1</li>
+        <li value="5">Item 5</li>
+        <li value="2">Item 2</li>
+        <li>Item 3</li>
+    </ol>
+
     <p>list-style: decimal</p>
     <p>list-style: decimal</p>
     <ol style="list-style: decimal;">
     <ol style="list-style: decimal;">
         <li>First</li>
         <li>First</li>
@@ -118,8 +133,8 @@
         <li>First</li>
         <li>First</li>
         <li>Second</li>
         <li>Second</li>
         <li>Third</li>
         <li>Third</li>
-        <li>Another Entry</li>
-        <li>Another Entry</li>
+        <li value="5">Another Entry</li>
+        <li value="2">Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
@@ -132,8 +147,8 @@
         <li>First</li>
         <li>First</li>
         <li>Second</li>
         <li>Second</li>
         <li>Third</li>
         <li>Third</li>
-        <li>Another Entry</li>
-        <li>Another Entry</li>
+        <li value="5">Another Entry</li>
+        <li value="2">Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
@@ -166,8 +181,8 @@
         <li>First</li>
         <li>First</li>
         <li>Second</li>
         <li>Second</li>
         <li>Third</li>
         <li>Third</li>
-        <li>Another Entry</li>
-        <li>Another Entry</li>
+        <li value="5">Another Entry</li>
+        <li value="2">Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
@@ -200,8 +215,8 @@
         <li>First</li>
         <li>First</li>
         <li>Second</li>
         <li>Second</li>
         <li>Third</li>
         <li>Third</li>
-        <li>Another Entry</li>
-        <li>Another Entry</li>
+        <li value="5">Another Entry</li>
+        <li value="2">Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
@@ -223,8 +238,8 @@
         <li>First</li>
         <li>First</li>
         <li>Second</li>
         <li>Second</li>
         <li>Third</li>
         <li>Third</li>
-        <li>Another Entry</li>
-        <li>Another Entry</li>
+        <li value="5">Another Entry</li>
+        <li value="2">Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
@@ -246,8 +261,8 @@
         <li>First</li>
         <li>First</li>
         <li>Second</li>
         <li>Second</li>
         <li>Third</li>
         <li>Third</li>
-        <li>Another Entry</li>
-        <li>Another Entry</li>
+        <li value="5">Another Entry</li>
+        <li value="2">Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>
         <li>Another Entry</li>

+ 107 - 0
Tests/LibWeb/Layout/expected/ordered-list.txt

@@ -0,0 +1,107 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
+    BlockContainer <body> at (8,16) content-size 784x138.28125 children: not-inline
+      BlockContainer <ol> at (48,16) content-size 744x52.40625 children: not-inline
+        BlockContainer <(anonymous)> at (48,16) content-size 744x0 children: inline
+          TextNode <#text>
+        ListItemBox <li> at (48,16) content-size 744x17.46875 children: inline
+          line 0 width: 58.78125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 7, rect: [48,16 58.78125x17.46875]
+              "Item 20"
+          TextNode <#text>
+          ListItemMarkerBox <(anonymous)> at (13.25,16.234375) content-size 22.75x17 children: not-inline
+        BlockContainer <(anonymous)> at (48,33.46875) content-size 744x0 children: inline
+          TextNode <#text>
+        ListItemBox <li> at (48,33.46875) content-size 744x17.46875 children: inline
+          line 0 width: 55.53125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 7, rect: [48,33.46875 55.53125x17.46875]
+              "Item 21"
+          TextNode <#text>
+          ListItemMarkerBox <(anonymous)> at (16.5,33.703125) content-size 19.5x17 children: not-inline
+        BlockContainer <(anonymous)> at (48,50.9375) content-size 744x0 children: inline
+          TextNode <#text>
+        ListItemBox <li> at (48,50.9375) content-size 744x17.46875 children: inline
+          line 0 width: 58, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 7, rect: [48,50.9375 58x17.46875]
+              "Item 22"
+          TextNode <#text>
+          ListItemMarkerBox <(anonymous)> at (14.03125,51.171875) content-size 21.96875x17 children: not-inline
+        BlockContainer <(anonymous)> at (48,68.40625) content-size 744x0 children: inline
+          TextNode <#text>
+      BlockContainer <(anonymous)> at (8,84.40625) content-size 784x0 children: inline
+        TextNode <#text>
+      BlockContainer <ol> at (48,84.40625) content-size 744x69.875 children: not-inline
+        BlockContainer <(anonymous)> at (48,84.40625) content-size 744x0 children: inline
+          TextNode <#text>
+        ListItemBox <li> at (48,84.40625) content-size 744x17.46875 children: inline
+          line 0 width: 46.71875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 6, rect: [48,84.40625 46.71875x17.46875]
+              "Item 1"
+          TextNode <#text>
+          ListItemMarkerBox <(anonymous)> at (25.3125,84.640625) content-size 10.6875x17 children: not-inline
+        BlockContainer <(anonymous)> at (48,101.875) content-size 744x0 children: inline
+          TextNode <#text>
+        ListItemBox <li> at (48,101.875) content-size 744x17.46875 children: inline
+          line 0 width: 48.828125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 6, rect: [48,101.875 48.828125x17.46875]
+              "Item 5"
+          TextNode <#text>
+          ListItemMarkerBox <(anonymous)> at (23.203125,102.109375) content-size 12.796875x17 children: not-inline
+        BlockContainer <(anonymous)> at (48,119.34375) content-size 744x0 children: inline
+          TextNode <#text>
+        ListItemBox <li> at (48,119.34375) content-size 744x17.46875 children: inline
+          line 0 width: 49.109375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 6, rect: [48,119.34375 49.109375x17.46875]
+              "Item 6"
+          TextNode <#text>
+          ListItemMarkerBox <(anonymous)> at (22.921875,119.578125) content-size 13.078125x17 children: not-inline
+        BlockContainer <(anonymous)> at (48,136.8125) content-size 744x0 children: inline
+          TextNode <#text>
+        ListItemBox <li> at (48,136.8125) content-size 744x17.46875 children: inline
+          line 0 width: 49.09375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 6, rect: [48,136.8125 49.09375x17.46875]
+              "Item 7"
+          TextNode <#text>
+          ListItemMarkerBox <(anonymous)> at (22.9375,137.046875) content-size 13.0625x17 children: not-inline
+        BlockContainer <(anonymous)> at (48,154.28125) content-size 744x0 children: inline
+          TextNode <#text>
+      BlockContainer <(anonymous)> at (8,170.28125) content-size 784x0 children: inline
+        TextNode <#text>
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
+    PaintableWithLines (BlockContainer<BODY>) [8,16 784x138.28125] overflow: [8,16 784x154.28125]
+      PaintableWithLines (BlockContainer<OL>) [8,16 784x52.40625]
+        PaintableWithLines (BlockContainer(anonymous)) [48,16 744x0]
+        PaintableWithLines (ListItemBox<LI>) [48,16 744x17.46875]
+          TextPaintable (TextNode<#text>)
+          MarkerPaintable (ListItemMarkerBox(anonymous)) [13.25,16.234375 22.75x17]
+        PaintableWithLines (BlockContainer(anonymous)) [48,33.46875 744x0]
+        PaintableWithLines (ListItemBox<LI>) [48,33.46875 744x17.46875]
+          TextPaintable (TextNode<#text>)
+          MarkerPaintable (ListItemMarkerBox(anonymous)) [16.5,33.703125 19.5x17]
+        PaintableWithLines (BlockContainer(anonymous)) [48,50.9375 744x0]
+        PaintableWithLines (ListItemBox<LI>) [48,50.9375 744x17.46875]
+          TextPaintable (TextNode<#text>)
+          MarkerPaintable (ListItemMarkerBox(anonymous)) [14.03125,51.171875 21.96875x17]
+        PaintableWithLines (BlockContainer(anonymous)) [48,68.40625 744x0]
+      PaintableWithLines (BlockContainer(anonymous)) [8,84.40625 784x0]
+      PaintableWithLines (BlockContainer<OL>) [8,84.40625 784x69.875]
+        PaintableWithLines (BlockContainer(anonymous)) [48,84.40625 744x0]
+        PaintableWithLines (ListItemBox<LI>) [48,84.40625 744x17.46875]
+          TextPaintable (TextNode<#text>)
+          MarkerPaintable (ListItemMarkerBox(anonymous)) [25.3125,84.640625 10.6875x17]
+        PaintableWithLines (BlockContainer(anonymous)) [48,101.875 744x0]
+        PaintableWithLines (ListItemBox<LI>) [48,101.875 744x17.46875]
+          TextPaintable (TextNode<#text>)
+          MarkerPaintable (ListItemMarkerBox(anonymous)) [23.203125,102.109375 12.796875x17]
+        PaintableWithLines (BlockContainer(anonymous)) [48,119.34375 744x0]
+        PaintableWithLines (ListItemBox<LI>) [48,119.34375 744x17.46875]
+          TextPaintable (TextNode<#text>)
+          MarkerPaintable (ListItemMarkerBox(anonymous)) [22.921875,119.578125 13.078125x17]
+        PaintableWithLines (BlockContainer(anonymous)) [48,136.8125 744x0]
+        PaintableWithLines (ListItemBox<LI>) [48,136.8125 744x17.46875]
+          TextPaintable (TextNode<#text>)
+          MarkerPaintable (ListItemMarkerBox(anonymous)) [22.9375,137.046875 13.0625x17]
+        PaintableWithLines (BlockContainer(anonymous)) [48,154.28125 744x0]
+      PaintableWithLines (BlockContainer(anonymous)) [8,170.28125 784x0]

+ 11 - 0
Tests/LibWeb/Layout/input/ordered-list.html

@@ -0,0 +1,11 @@
+<ol start="20">
+    <li>Item 20</li>
+    <li>Item 21</li>
+    <li>Item 22</li>
+</ol>
+<ol>
+    <li>Item 1</li>
+    <li value="5">Item 5</li>
+    <li>Item 6</li>
+    <li>Item 7</li>
+</ol>

+ 1 - 0
Userland/Libraries/LibWeb/HTML/AttributeNames.h

@@ -223,6 +223,7 @@ namespace AttributeNames {
     __ENUMERATE_HTML_ATTRIBUTE(srclang)                    \
     __ENUMERATE_HTML_ATTRIBUTE(srclang)                    \
     __ENUMERATE_HTML_ATTRIBUTE(srcset)                     \
     __ENUMERATE_HTML_ATTRIBUTE(srcset)                     \
     __ENUMERATE_HTML_ATTRIBUTE(standby)                    \
     __ENUMERATE_HTML_ATTRIBUTE(standby)                    \
+    __ENUMERATE_HTML_ATTRIBUTE(start)                      \
     __ENUMERATE_HTML_ATTRIBUTE(step)                       \
     __ENUMERATE_HTML_ATTRIBUTE(step)                       \
     __ENUMERATE_HTML_ATTRIBUTE(style)                      \
     __ENUMERATE_HTML_ATTRIBUTE(style)                      \
     __ENUMERATE_HTML_ATTRIBUTE(summary)                    \
     __ENUMERATE_HTML_ATTRIBUTE(summary)                    \

+ 6 - 0
Userland/Libraries/LibWeb/HTML/HTMLLIElement.h

@@ -20,6 +20,12 @@ public:
     // https://www.w3.org/TR/html-aria/#el-li
     // https://www.w3.org/TR/html-aria/#el-li
     virtual Optional<ARIA::Role> default_role() const override { return ARIA::Role::listitem; }
     virtual Optional<ARIA::Role> default_role() const override { return ARIA::Role::listitem; }
 
 
+    i32 value() { return get_attribute(AttributeNames::value).value_or("0"_string).to_number<i32>().value_or(0); }
+    void set_value(i32 value)
+    {
+        set_attribute(AttributeNames::value, MUST(String::number(value))).release_value_but_fixme_should_propagate_errors();
+    }
+
 private:
 private:
     HTMLLIElement(DOM::Document&, DOM::QualifiedName);
     HTMLLIElement(DOM::Document&, DOM::QualifiedName);
 
 

+ 1 - 1
Userland/Libraries/LibWeb/HTML/HTMLLIElement.idl

@@ -6,7 +6,7 @@ interface HTMLLIElement : HTMLElement {
 
 
     [HTMLConstructor] constructor();
     [HTMLConstructor] constructor();
 
 
-    // FIXME: [CEReactions] attribute long value;
+    [CEReactions] attribute long value;
 
 
     // Obsolete
     // Obsolete
     [CEReactions, Reflect] attribute DOMString type;
     [CEReactions, Reflect] attribute DOMString type;

+ 6 - 0
Userland/Libraries/LibWeb/HTML/HTMLOListElement.h

@@ -20,6 +20,12 @@ public:
     // https://www.w3.org/TR/html-aria/#el-ol
     // https://www.w3.org/TR/html-aria/#el-ol
     virtual Optional<ARIA::Role> default_role() const override { return ARIA::Role::list; }
     virtual Optional<ARIA::Role> default_role() const override { return ARIA::Role::list; }
 
 
+    i32 start() { return get_attribute(AttributeNames::start).value_or("1"_string).to_number<i32>().value_or(1); }
+    void set_start(i32 start)
+    {
+        set_attribute(AttributeNames::start, MUST(String::number(start))).release_value_but_fixme_should_propagate_errors();
+    }
+
 private:
 private:
     HTMLOListElement(DOM::Document&, DOM::QualifiedName);
     HTMLOListElement(DOM::Document&, DOM::QualifiedName);
 
 

+ 1 - 1
Userland/Libraries/LibWeb/HTML/HTMLOListElement.idl

@@ -7,7 +7,7 @@ interface HTMLOListElement : HTMLElement {
     [HTMLConstructor] constructor();
     [HTMLConstructor] constructor();
 
 
     [CEReactions, Reflect] attribute boolean reversed;
     [CEReactions, Reflect] attribute boolean reversed;
-    // FIXME: [CEReactions] attribute long start;
+    [CEReactions] attribute long start;
     [CEReactions, Reflect] attribute DOMString type;
     [CEReactions, Reflect] attribute DOMString type;
 
 
     // Obsolete
     // Obsolete

+ 27 - 2
Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp

@@ -20,6 +20,8 @@
 #include <LibWeb/Dump.h>
 #include <LibWeb/Dump.h>
 #include <LibWeb/HTML/HTMLButtonElement.h>
 #include <LibWeb/HTML/HTMLButtonElement.h>
 #include <LibWeb/HTML/HTMLInputElement.h>
 #include <LibWeb/HTML/HTMLInputElement.h>
+#include <LibWeb/HTML/HTMLLIElement.h>
+#include <LibWeb/HTML/HTMLOListElement.h>
 #include <LibWeb/HTML/HTMLProgressElement.h>
 #include <LibWeb/HTML/HTMLProgressElement.h>
 #include <LibWeb/HTML/HTMLSlotElement.h>
 #include <LibWeb/HTML/HTMLSlotElement.h>
 #include <LibWeb/Layout/ListItemBox.h>
 #include <LibWeb/Layout/ListItemBox.h>
@@ -251,6 +253,30 @@ static bool is_ignorable_whitespace(Layout::Node const& node)
     return false;
     return false;
 }
 }
 
 
+i32 TreeBuilder::calculate_list_item_index(DOM::Node& dom_node)
+{
+    if (is<HTML::HTMLLIElement>(dom_node)) {
+        auto& li = static_cast<HTML::HTMLLIElement&>(dom_node);
+        if (li.value() != 0)
+            return li.value();
+    }
+
+    if (dom_node.previous_sibling() != nullptr) {
+        DOM::Node* current = dom_node.previous_sibling();
+        while (current != nullptr) {
+            if (is<HTML::HTMLLIElement>(*current))
+                return calculate_list_item_index(*current) + 1;
+            current = current->previous_sibling();
+        }
+    }
+
+    if (is<HTML::HTMLOListElement>(*dom_node.parent())) {
+        auto& ol = static_cast<HTML::HTMLOListElement&>(*dom_node.parent());
+        return ol.start();
+    }
+    return 1;
+}
+
 ErrorOr<void> TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& context)
 ErrorOr<void> TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& context)
 {
 {
     JS::GCPtr<Layout::Node> layout_node;
     JS::GCPtr<Layout::Node> layout_node;
@@ -349,9 +375,8 @@ ErrorOr<void> TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::
 
 
     if (is<ListItemBox>(*layout_node)) {
     if (is<ListItemBox>(*layout_node)) {
         auto& element = static_cast<DOM::Element&>(dom_node);
         auto& element = static_cast<DOM::Element&>(dom_node);
-        int child_index = layout_node->parent()->index_of_child<ListItemBox>(*layout_node).value();
         auto marker_style = TRY(style_computer.compute_style(element, CSS::Selector::PseudoElement::Marker));
         auto marker_style = TRY(style_computer.compute_style(element, CSS::Selector::PseudoElement::Marker));
-        auto list_item_marker = document.heap().allocate_without_realm<ListItemMarkerBox>(document, layout_node->computed_values().list_style_type(), layout_node->computed_values().list_style_position(), child_index + 1, *marker_style);
+        auto list_item_marker = document.heap().allocate_without_realm<ListItemMarkerBox>(document, layout_node->computed_values().list_style_type(), layout_node->computed_values().list_style_position(), calculate_list_item_index(dom_node), *marker_style);
         static_cast<ListItemBox&>(*layout_node).set_marker(list_item_marker);
         static_cast<ListItemBox&>(*layout_node).set_marker(list_item_marker);
         element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::Marker, list_item_marker);
         element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::Marker, list_item_marker);
         layout_node->append_child(*list_item_marker);
         layout_node->append_child(*list_item_marker);

+ 2 - 0
Userland/Libraries/LibWeb/Layout/TreeBuilder.h

@@ -25,6 +25,8 @@ private:
         bool has_svg_root = false;
         bool has_svg_root = false;
     };
     };
 
 
+    i32 calculate_list_item_index(DOM::Node&);
+
     ErrorOr<void> create_layout_tree(DOM::Node&, Context&);
     ErrorOr<void> create_layout_tree(DOM::Node&, Context&);
 
 
     void push_parent(Layout::NodeWithStyle& node) { m_ancestor_stack.append(node); }
     void push_parent(Layout::NodeWithStyle& node) { m_ancestor_stack.append(node); }