| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-02-10 17:13:08 +01:00
										 |  |  |  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |  * Copyright (c) 2021, the SerenityOS developers. | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 1. Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |  *    list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |  *    this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |  *    and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
					
						
							|  |  |  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
					
						
							|  |  |  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
					
						
							|  |  |  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
					
						
							|  |  |  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
					
						
							|  |  |  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 18:47:21 +02:00
										 |  |  | #include <AK/QuickSort.h>
 | 
					
						
							| 
									
										
										
										
											2020-05-23 21:05:26 +02:00
										 |  |  | #include <AK/StringBuilder.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  | #include <AK/Utf8View.h>
 | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  | #include <LibWeb/CSS/CSSImportRule.h>
 | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  | #include <LibWeb/CSS/CSSRule.h>
 | 
					
						
							| 
									
										
										
										
											2021-03-07 15:00:02 +01:00
										 |  |  | #include <LibWeb/CSS/CSSStyleRule.h>
 | 
					
						
							| 
									
										
										
										
											2021-03-07 16:14:04 +01:00
										 |  |  | #include <LibWeb/CSS/CSSStyleSheet.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:32:51 +01:00
										 |  |  | #include <LibWeb/CSS/PropertyID.h>
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/Comment.h>
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/Document.h>
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/Element.h>
 | 
					
						
							| 
									
										
										
										
											2021-02-10 18:25:05 +01:00
										 |  |  | #include <LibWeb/DOM/ShadowRoot.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:32:51 +01:00
										 |  |  | #include <LibWeb/DOM/Text.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Dump.h>
 | 
					
						
							| 
									
										
										
										
											2020-08-19 22:30:33 +01:00
										 |  |  | #include <LibWeb/HTML/HTMLTemplateElement.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/BlockBox.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Layout/Node.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Layout/TextNode.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | namespace Web { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-26 19:37:56 +02:00
										 |  |  | void dump_tree(const DOM::Node& node) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     dump_tree(builder, node); | 
					
						
							|  |  |  |     dbgln("{}", builder.string_view()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void dump_tree(StringBuilder& builder, const DOM::Node& node) | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     static int indent = 0; | 
					
						
							|  |  |  |     for (int i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         builder.append("  "); | 
					
						
							| 
									
										
										
										
											2021-02-10 17:13:08 +01:00
										 |  |  |     if (is<DOM::Element>(node)) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         builder.appendff("<{}", downcast<DOM::Element>(node).local_name()); | 
					
						
							|  |  |  |         downcast<DOM::Element>(node).for_each_attribute([&](auto& name, auto& value) { | 
					
						
							|  |  |  |             builder.appendff(" {}={}", name, value); | 
					
						
							| 
									
										
										
										
											2019-06-15 21:08:36 +02:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         builder.append(">\n"); | 
					
						
							| 
									
										
										
										
											2020-07-26 19:37:56 +02:00
										 |  |  |     } else if (is<DOM::Text>(node)) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         builder.appendff("\"{}\"\n", downcast<DOM::Text>(node).data()); | 
					
						
							| 
									
										
										
										
											2021-02-10 17:13:08 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         builder.appendff("{}\n", node.node_name()); | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     ++indent; | 
					
						
							| 
									
										
										
										
											2021-02-10 18:25:05 +01:00
										 |  |  |     if (is<DOM::Element>(node) && downcast<DOM::Element>(node).shadow_root()) { | 
					
						
							|  |  |  |         dump_tree(*downcast<DOM::Element>(node).shadow_root()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-26 19:37:56 +02:00
										 |  |  |     if (is<DOM::ParentNode>(node)) { | 
					
						
							| 
									
										
										
										
											2020-08-19 22:30:33 +01:00
										 |  |  |         if (!is<HTML::HTMLTemplateElement>(node)) { | 
					
						
							|  |  |  |             static_cast<const DOM::ParentNode&>(node).for_each_child([](auto& child) { | 
					
						
							|  |  |  |                 dump_tree(child); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             auto& template_element = downcast<HTML::HTMLTemplateElement>(node); | 
					
						
							|  |  |  |             dump_tree(template_element.content()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     --indent; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  | void dump_tree(const Layout::Node& layout_node, bool show_box_model, bool show_specified_style) | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     dump_tree(builder, layout_node, show_box_model, show_specified_style, true); | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |     dbgln("{}", builder.string_view()); | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void dump_tree(StringBuilder& builder, const Layout::Node& layout_node, bool show_box_model, bool show_specified_style, bool interactive) | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |     static size_t indent = 0; | 
					
						
							|  |  |  |     for (size_t i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |         builder.append("  "); | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-22 19:10:43 +01:00
										 |  |  |     FlyString tag_name; | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  |     if (layout_node.is_anonymous()) | 
					
						
							|  |  |  |         tag_name = "(anonymous)"; | 
					
						
							| 
									
										
										
										
											2020-11-22 14:46:36 +01:00
										 |  |  |     else if (is<DOM::Element>(layout_node.dom_node())) | 
					
						
							|  |  |  |         tag_name = downcast<DOM::Element>(*layout_node.dom_node()).local_name(); | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2021-02-10 17:13:08 +01:00
										 |  |  |         tag_name = layout_node.dom_node()->node_name(); | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 21:05:26 +02:00
										 |  |  |     String identifier = ""; | 
					
						
							| 
									
										
										
										
											2020-11-22 14:46:36 +01:00
										 |  |  |     if (layout_node.dom_node() && is<DOM::Element>(*layout_node.dom_node())) { | 
					
						
							|  |  |  |         auto& element = downcast<DOM::Element>(*layout_node.dom_node()); | 
					
						
							| 
									
										
										
										
											2020-06-12 13:23:07 +02:00
										 |  |  |         StringBuilder builder; | 
					
						
							|  |  |  |         auto id = element.attribute(HTML::AttributeNames::id); | 
					
						
							| 
									
										
										
										
											2020-05-23 21:05:26 +02:00
										 |  |  |         if (!id.is_empty()) { | 
					
						
							|  |  |  |             builder.append('#'); | 
					
						
							|  |  |  |             builder.append(id); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-06-12 13:23:07 +02:00
										 |  |  |         for (auto& class_name : element.class_names()) { | 
					
						
							|  |  |  |             builder.append('.'); | 
					
						
							|  |  |  |             builder.append(class_name); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         identifier = builder.to_string(); | 
					
						
							| 
									
										
										
										
											2020-05-23 21:05:26 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |     const char* nonbox_color_on = ""; | 
					
						
							|  |  |  |     const char* box_color_on = ""; | 
					
						
							|  |  |  |     const char* positioned_color_on = ""; | 
					
						
							|  |  |  |     const char* floating_color_on = ""; | 
					
						
							|  |  |  |     const char* inline_block_color_on = ""; | 
					
						
							|  |  |  |     const char* line_box_color_on = ""; | 
					
						
							|  |  |  |     const char* fragment_color_on = ""; | 
					
						
							| 
									
										
										
										
											2021-01-18 17:32:34 +01:00
										 |  |  |     const char* flex_color_on = ""; | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |     const char* color_off = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (interactive) { | 
					
						
							|  |  |  |         nonbox_color_on = "\033[33m"; | 
					
						
							|  |  |  |         box_color_on = "\033[34m"; | 
					
						
							|  |  |  |         positioned_color_on = "\033[31;1m"; | 
					
						
							|  |  |  |         floating_color_on = "\033[32;1m"; | 
					
						
							|  |  |  |         inline_block_color_on = "\033[36;1m"; | 
					
						
							|  |  |  |         line_box_color_on = "\033[34;1m"; | 
					
						
							|  |  |  |         fragment_color_on = "\033[35;1m"; | 
					
						
							| 
									
										
										
										
											2021-01-18 17:32:34 +01:00
										 |  |  |         flex_color_on = "\033[34;1m"; | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |         color_off = "\033[0m"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  |     if (!is<Layout::Box>(layout_node)) { | 
					
						
							| 
									
										
										
										
											2021-02-23 09:57:02 +03:30
										 |  |  |         builder.appendff("{}{}{} <{}{}{}{}>", | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |             nonbox_color_on, | 
					
						
							| 
									
										
										
										
											2021-01-02 03:30:04 +01:00
										 |  |  |             layout_node.class_name().substring_view(13), | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |             color_off, | 
					
						
							|  |  |  |             tag_name, | 
					
						
							|  |  |  |             nonbox_color_on, | 
					
						
							|  |  |  |             identifier, | 
					
						
							|  |  |  |             color_off); | 
					
						
							|  |  |  |         if (interactive) | 
					
						
							|  |  |  |             builder.appendff(" @{:p}", &layout_node); | 
					
						
							|  |  |  |         builder.append("\n"); | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |         auto& box = downcast<Layout::Box>(layout_node); | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |         builder.appendff("{}{}{} <{}{}{}{}> ", | 
					
						
							|  |  |  |             box_color_on, | 
					
						
							| 
									
										
										
										
											2021-01-02 03:30:04 +01:00
										 |  |  |             box.class_name().substring_view(13), | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |             color_off, | 
					
						
							|  |  |  |             box_color_on, | 
					
						
							|  |  |  |             tag_name, | 
					
						
							|  |  |  |             color_off, | 
					
						
							|  |  |  |             identifier.characters()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (interactive) | 
					
						
							|  |  |  |             builder.appendff("@{:p} ", &layout_node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         builder.appendff("at ({},{}) size {}x{}", | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |             (int)box.absolute_x(), | 
					
						
							|  |  |  |             (int)box.absolute_y(), | 
					
						
							|  |  |  |             (int)box.width(), | 
					
						
							|  |  |  |             (int)box.height()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (box.is_positioned()) | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |             builder.appendff(" {}positioned{}", positioned_color_on, color_off); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |         if (box.is_floating()) | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |             builder.appendff(" {}floating{}", floating_color_on, color_off); | 
					
						
							|  |  |  |         if (box.is_inline_block()) | 
					
						
							|  |  |  |             builder.appendff(" {}inline-block{}", inline_block_color_on, color_off); | 
					
						
							| 
									
										
										
										
											2021-01-18 17:32:34 +01:00
										 |  |  |         if (box.computed_values().display() == CSS::Display::Flex) | 
					
						
							|  |  |  |             builder.appendff(" {}flex{}", flex_color_on, color_off); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (show_box_model) { | 
					
						
							|  |  |  |             // Dump the horizontal box properties
 | 
					
						
							| 
									
										
										
										
											2021-04-15 00:36:14 -07:00
										 |  |  |             builder.appendff(" [{}+{}+{} {} {}+{}+{}]", | 
					
						
							| 
									
										
										
										
											2020-12-12 21:02:06 +01:00
										 |  |  |                 box.box_model().margin.left, | 
					
						
							|  |  |  |                 box.box_model().border.left, | 
					
						
							|  |  |  |                 box.box_model().padding.left, | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |                 box.width(), | 
					
						
							| 
									
										
										
										
											2020-12-12 21:02:06 +01:00
										 |  |  |                 box.box_model().padding.right, | 
					
						
							|  |  |  |                 box.box_model().border.right, | 
					
						
							|  |  |  |                 box.box_model().margin.right); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // And the vertical box properties
 | 
					
						
							| 
									
										
										
										
											2021-04-15 00:36:14 -07:00
										 |  |  |             builder.appendff(" [{}+{}+{} {} {}+{}+{}]", | 
					
						
							| 
									
										
										
										
											2020-12-12 21:02:06 +01:00
										 |  |  |                 box.box_model().margin.top, | 
					
						
							|  |  |  |                 box.box_model().border.top, | 
					
						
							|  |  |  |                 box.box_model().padding.top, | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |                 box.height(), | 
					
						
							| 
									
										
										
										
											2020-12-12 21:02:06 +01:00
										 |  |  |                 box.box_model().padding.bottom, | 
					
						
							|  |  |  |                 box.box_model().border.bottom, | 
					
						
							|  |  |  |                 box.box_model().margin.bottom); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-08-18 08:09:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |         builder.append("\n"); | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-21 20:54:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  |     if (is<Layout::BlockBox>(layout_node) && static_cast<const Layout::BlockBox&>(layout_node).children_are_inline()) { | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |         auto& block = static_cast<const Layout::BlockBox&>(layout_node); | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |         for (size_t line_box_index = 0; line_box_index < block.line_boxes().size(); ++line_box_index) { | 
					
						
							| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  |             auto& line_box = block.line_boxes()[line_box_index]; | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |             for (size_t i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                 builder.append("  "); | 
					
						
							|  |  |  |             builder.appendff("  {}line {}{} width: {}\n", | 
					
						
							|  |  |  |                 line_box_color_on, | 
					
						
							|  |  |  |                 line_box_index, | 
					
						
							|  |  |  |                 color_off, | 
					
						
							|  |  |  |                 (int)line_box.width()); | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |             for (size_t fragment_index = 0; fragment_index < line_box.fragments().size(); ++fragment_index) { | 
					
						
							| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  |                 auto& fragment = line_box.fragments()[fragment_index]; | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |                 for (size_t i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                     builder.append("  "); | 
					
						
							|  |  |  |                 builder.appendff("    {}frag {}{} from {} ", | 
					
						
							|  |  |  |                     fragment_color_on, | 
					
						
							| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  |                     fragment_index, | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                     color_off, | 
					
						
							|  |  |  |                     fragment.layout_node().class_name()); | 
					
						
							|  |  |  |                 if (interactive) | 
					
						
							|  |  |  |                     builder.appendff("@{:p}, ", &fragment.layout_node()); | 
					
						
							|  |  |  |                 builder.appendff("start: {}, length: {}, rect: {}\n", | 
					
						
							| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  |                     fragment.start(), | 
					
						
							|  |  |  |                     fragment.length(), | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                     enclosing_int_rect(fragment.absolute_rect()).to_string()); | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  |                 if (is<Layout::TextNode>(fragment.layout_node())) { | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |                     for (size_t i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                         builder.append("  "); | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |                     auto& layout_text = static_cast<const Layout::TextNode&>(fragment.layout_node()); | 
					
						
							| 
									
										
										
										
											2019-11-19 18:36:33 +01:00
										 |  |  |                     auto fragment_text = layout_text.text_for_rendering().substring(fragment.start(), fragment.length()); | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                     builder.appendff("      \"{}\"\n", fragment_text); | 
					
						
							| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 12:44:58 +01:00
										 |  |  |     if (show_specified_style && layout_node.dom_node() && layout_node.dom_node()->is_element() && downcast<DOM::Element>(layout_node.dom_node())->specified_css_values()) { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |         struct NameAndValue { | 
					
						
							|  |  |  |             String name; | 
					
						
							|  |  |  |             String value; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         Vector<NameAndValue> properties; | 
					
						
							| 
									
										
										
										
											2021-01-06 12:44:58 +01:00
										 |  |  |         downcast<DOM::Element>(*layout_node.dom_node()).specified_css_values()->for_each_property([&](auto property_id, auto& value) { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |             properties.append({ CSS::string_from_property_id(property_id), value.to_string() }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         quick_sort(properties, [](auto& a, auto& b) { return a.name < b.name; }); | 
					
						
							| 
									
										
										
										
											2020-06-14 18:47:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |         for (auto& property : properties) { | 
					
						
							|  |  |  |             for (size_t i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                 builder.append("    "); | 
					
						
							|  |  |  |             builder.appendf("  (%s: %s)\n", property.name.characters(), property.value.characters()); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-06-14 18:47:21 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-09-21 15:32:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-28 21:17:34 +02:00
										 |  |  |     ++indent; | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |     layout_node.for_each_child([&](auto& child) { | 
					
						
							|  |  |  |         dump_tree(builder, child, show_box_model, show_specified_style, interactive); | 
					
						
							| 
									
										
										
										
											2019-06-28 21:17:34 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  |     --indent; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  | void dump_selector(const CSS::Selector& selector) | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     dump_selector(builder, selector); | 
					
						
							|  |  |  |     dbgln("{}", builder.string_view()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void dump_selector(StringBuilder& builder, const CSS::Selector& selector) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     builder.append("  CSS::Selector:\n"); | 
					
						
							| 
									
										
										
										
											2019-11-27 20:37:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |     for (auto& complex_selector : selector.complex_selectors()) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         builder.append("    "); | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const char* relation_description = ""; | 
					
						
							|  |  |  |         switch (complex_selector.relation) { | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |         case CSS::Selector::ComplexSelector::Relation::None: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:45:38 +02:00
										 |  |  |             relation_description = "None"; | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |         case CSS::Selector::ComplexSelector::Relation::ImmediateChild: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             relation_description = "ImmediateChild"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |         case CSS::Selector::ComplexSelector::Relation::Descendant: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             relation_description = "Descendant"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |         case CSS::Selector::ComplexSelector::Relation::AdjacentSibling: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             relation_description = "AdjacentSibling"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |         case CSS::Selector::ComplexSelector::Relation::GeneralSibling: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             relation_description = "GeneralSibling"; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-11-27 20:37:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |         if (*relation_description) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |             builder.appendff("{{{}}} ", relation_description); | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (size_t i = 0; i < complex_selector.compound_selector.size(); ++i) { | 
					
						
							|  |  |  |             auto& simple_selector = complex_selector.compound_selector[i]; | 
					
						
							|  |  |  |             const char* type_description = "Unknown"; | 
					
						
							|  |  |  |             switch (simple_selector.type) { | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::Type::Invalid: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |                 type_description = "Invalid"; | 
					
						
							| 
									
										
										
										
											2019-10-06 09:28:10 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::Type::Universal: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |                 type_description = "Universal"; | 
					
						
							| 
									
										
										
										
											2019-10-06 09:28:10 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::Type::Id: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |                 type_description = "Id"; | 
					
						
							| 
									
										
										
										
											2019-10-06 11:05:57 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::Type::Class: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |                 type_description = "Class"; | 
					
						
							| 
									
										
										
										
											2019-10-06 19:59:07 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::Type::TagName: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |                 type_description = "TagName"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const char* attribute_match_type_description = ""; | 
					
						
							|  |  |  |             switch (simple_selector.attribute_match_type) { | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::AttributeMatchType::None: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::AttributeMatchType::HasAttribute: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |                 attribute_match_type_description = "HasAttribute"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::AttributeMatchType::ExactValueMatch: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |                 attribute_match_type_description = "ExactValueMatch"; | 
					
						
							| 
									
										
										
										
											2019-11-21 20:07:43 +01:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::AttributeMatchType::Contains: | 
					
						
							| 
									
										
										
										
											2020-06-10 15:43:41 +02:00
										 |  |  |                 attribute_match_type_description = "Contains"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2019-11-21 20:07:43 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |             const char* pseudo_class_description = ""; | 
					
						
							|  |  |  |             switch (simple_selector.pseudo_class) { | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::Link: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "Link"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::Visited: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "Visited"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::None: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "None"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::Root: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "Root"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-04-06 12:23:32 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::FirstOfType: | 
					
						
							|  |  |  |                 pseudo_class_description = "FirstOfType"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-04-06 13:06:25 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::LastOfType: | 
					
						
							|  |  |  |                 pseudo_class_description = "LastOfType"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::Focus: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "Focus"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::Empty: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "Empty"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::Hover: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "Hover"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::LastChild: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "LastChild"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::FirstChild: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "FirstChild"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             case CSS::Selector::SimpleSelector::PseudoClass::OnlyChild: | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |                 pseudo_class_description = "OnlyChild"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |             builder.appendff("{}:{}", type_description, simple_selector.value); | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             if (simple_selector.pseudo_class != CSS::Selector::SimpleSelector::PseudoClass::None) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |                 builder.appendff(" pseudo_class={}", pseudo_class_description); | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  |             if (simple_selector.attribute_match_type != CSS::Selector::SimpleSelector::AttributeMatchType::None) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |                 builder.appendff(" [{}, name='{}', value='{}']", attribute_match_type_description, simple_selector.attribute_name, simple_selector.attribute_value); | 
					
						
							| 
									
										
										
										
											2019-11-21 20:07:43 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (i != complex_selector.compound_selector.size() - 1) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |                 builder.append(", "); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         builder.append("\n"); | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  | void dump_rule(const CSS::CSSRule& rule) | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     dump_rule(builder, rule); | 
					
						
							|  |  |  |     dbgln("{}", builder.string_view()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  | void dump_rule(StringBuilder& builder, const CSS::CSSRule& rule) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     builder.appendff("{}:\n", rule.class_name()); | 
					
						
							|  |  |  |     switch (rule.type()) { | 
					
						
							|  |  |  |     case CSS::CSSRule::Type::Style: | 
					
						
							| 
									
										
										
										
											2021-03-07 15:00:02 +01:00
										 |  |  |         dump_style_rule(builder, downcast<const CSS::CSSStyleRule>(rule)); | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  |     case CSS::CSSRule::Type::Import: | 
					
						
							|  |  |  |         dump_import_rule(builder, downcast<const CSS::CSSImportRule>(rule)); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  | void dump_import_rule(StringBuilder& builder, const CSS::CSSImportRule& rule) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     builder.appendff("  Document URL: {}\n", rule.url()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 15:00:02 +01:00
										 |  |  | void dump_style_rule(StringBuilder& builder, const CSS::CSSStyleRule& rule) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |     for (auto& selector : rule.selectors()) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         dump_selector(builder, selector); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |     builder.append("  Declarations:\n"); | 
					
						
							| 
									
										
										
										
											2019-09-30 20:06:17 +02:00
										 |  |  |     for (auto& property : rule.declaration().properties()) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         builder.appendff("    {}: '{}'\n", CSS::string_from_property_id(property.property_id), property.value->to_string()); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  | void dump_sheet(const CSS::StyleSheet& sheet) | 
					
						
							| 
									
										
										
										
											2019-06-21 20:54:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     dump_sheet(builder, sheet); | 
					
						
							|  |  |  |     dbgln("{}", builder.string_view()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void dump_sheet(StringBuilder& builder, const CSS::StyleSheet& sheet) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-07 16:14:04 +01:00
										 |  |  |     VERIFY(is<CSS::CSSStyleSheet>(sheet)); | 
					
						
							| 
									
										
										
										
											2019-06-25 06:31:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 16:14:04 +01:00
										 |  |  |     builder.appendff("CSSStyleSheet{{{}}}: {} rule(s)\n", &sheet, static_cast<const CSS::CSSStyleSheet&>(sheet).rules().size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto& rule : static_cast<const CSS::CSSStyleSheet&>(sheet).rules()) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |         dump_rule(builder, rule); | 
					
						
							| 
									
										
										
										
											2019-06-25 06:31:47 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-21 20:54:13 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | } |