| 
									
										
										
										
											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
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_tree(DOM::Node const& node) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     dump_tree(builder, node); | 
					
						
							|  |  |  |     dbgln("{}", builder.string_view()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_tree(StringBuilder& builder, DOM::Node const& 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-06-24 19:53:42 +02:00
										 |  |  |         builder.appendff("<{}", verify_cast<DOM::Element>(node).local_name()); | 
					
						
							|  |  |  |         verify_cast<DOM::Element>(node).for_each_attribute([&](auto& name, auto& value) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |             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-06-24 19:53:42 +02:00
										 |  |  |         builder.appendff("\"{}\"\n", verify_cast<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-06-24 19:53:42 +02:00
										 |  |  |     if (is<DOM::Element>(node) && verify_cast<DOM::Element>(node).shadow_root()) { | 
					
						
							|  |  |  |         dump_tree(*verify_cast<DOM::Element>(node).shadow_root()); | 
					
						
							| 
									
										
										
										
											2021-02-10 18:25:05 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											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)) { | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  |             static_cast<DOM::ParentNode const&>(node).for_each_child([](auto& child) { | 
					
						
							| 
									
										
										
										
											2020-08-19 22:30:33 +01:00
										 |  |  |                 dump_tree(child); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-06-24 19:53:42 +02:00
										 |  |  |             auto& template_element = verify_cast<HTML::HTMLTemplateElement>(node); | 
					
						
							| 
									
										
										
										
											2020-08-19 22:30:33 +01:00
										 |  |  |             dump_tree(template_element.content()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     --indent; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_tree(Layout::Node const& 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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_tree(StringBuilder& builder, Layout::Node const& 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())) | 
					
						
							| 
									
										
										
										
											2021-06-24 19:53:42 +02:00
										 |  |  |         tag_name = verify_cast<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())) { | 
					
						
							| 
									
										
										
										
											2021-06-24 19:53:42 +02:00
										 |  |  |         auto& element = verify_cast<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
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  |     char const* nonbox_color_on = ""; | 
					
						
							|  |  |  |     char const* box_color_on = ""; | 
					
						
							|  |  |  |     char const* positioned_color_on = ""; | 
					
						
							|  |  |  |     char const* floating_color_on = ""; | 
					
						
							|  |  |  |     char const* inline_block_color_on = ""; | 
					
						
							|  |  |  |     char const* line_box_color_on = ""; | 
					
						
							|  |  |  |     char const* fragment_color_on = ""; | 
					
						
							|  |  |  |     char const* flex_color_on = ""; | 
					
						
							|  |  |  |     char const* color_off = ""; | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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 { | 
					
						
							| 
									
										
										
										
											2021-06-24 19:53:42 +02:00
										 |  |  |         auto& box = verify_cast<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) | 
					
						
							| 
									
										
										
										
											2021-05-29 22:36:15 +02:00
										 |  |  |             builder.appendff(" {}flex-container{}", flex_color_on, color_off); | 
					
						
							|  |  |  |         if (box.is_flex_item()) | 
					
						
							|  |  |  |             builder.appendff(" {}flex-item{}", 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-07-12 14:13:29 +01:00
										 |  |  |     if (is<Layout::BlockBox>(layout_node) && static_cast<Layout::BlockBox const&>(layout_node).children_are_inline()) { | 
					
						
							|  |  |  |         auto& block = static_cast<Layout::BlockBox const&>(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("  "); | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  |                     auto& layout_text = static_cast<Layout::TextNode const&>(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-06-24 19:53:42 +02:00
										 |  |  |     if (show_specified_style && layout_node.dom_node() && layout_node.dom_node()->is_element() && verify_cast<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-06-24 19:53:42 +02:00
										 |  |  |         verify_cast<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("    "); | 
					
						
							| 
									
										
										
										
											2021-05-07 20:47:25 +02:00
										 |  |  |             builder.appendff("  ({}: {})\n", property.name, property.value); | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_selector(CSS::Selector const& 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()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_selector(StringBuilder& builder, CSS::Selector const& selector) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  |         char const* relation_description = ""; | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |         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; | 
					
						
							| 
									
										
										
										
											2021-04-29 21:16:28 +02:00
										 |  |  |         case CSS::Selector::ComplexSelector::Relation::Column: | 
					
						
							|  |  |  |             relation_description = "Column"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											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]; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  |             char const* type_description = "Unknown"; | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             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; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |             case CSS::Selector::SimpleSelector::Type::Attribute: | 
					
						
							|  |  |  |                 type_description = "Attribute"; | 
					
						
							| 
									
										
										
										
											2021-04-29 21:16:28 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  |             case CSS::Selector::SimpleSelector::Type::PseudoClass: | 
					
						
							|  |  |  |                 type_description = "PseudoClass"; | 
					
						
							| 
									
										
										
										
											2021-05-23 20:59:26 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-07-12 16:34:18 +01:00
										 |  |  |             case CSS::Selector::SimpleSelector::Type::PseudoElement: | 
					
						
							|  |  |  |                 type_description = "PseudoElement"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-06-13 00:43:06 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |             builder.appendff("{}:{}", type_description, simple_selector.value); | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass) { | 
					
						
							|  |  |  |                 auto const& pseudo_class = simple_selector.pseudo_class; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 char const* pseudo_class_description = ""; | 
					
						
							|  |  |  |                 switch (pseudo_class.type) { | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Link: | 
					
						
							|  |  |  |                     pseudo_class_description = "Link"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Visited: | 
					
						
							|  |  |  |                     pseudo_class_description = "Visited"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Active: | 
					
						
							|  |  |  |                     pseudo_class_description = "Active"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::None: | 
					
						
							|  |  |  |                     pseudo_class_description = "None"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Root: | 
					
						
							|  |  |  |                     pseudo_class_description = "Root"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::FirstOfType: | 
					
						
							|  |  |  |                     pseudo_class_description = "FirstOfType"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::LastOfType: | 
					
						
							|  |  |  |                     pseudo_class_description = "LastOfType"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::NthChild: | 
					
						
							|  |  |  |                     pseudo_class_description = "NthChild"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::NthLastChild: | 
					
						
							|  |  |  |                     pseudo_class_description = "NthLastChild"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Focus: | 
					
						
							|  |  |  |                     pseudo_class_description = "Focus"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Empty: | 
					
						
							|  |  |  |                     pseudo_class_description = "Empty"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Hover: | 
					
						
							|  |  |  |                     pseudo_class_description = "Hover"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::LastChild: | 
					
						
							|  |  |  |                     pseudo_class_description = "LastChild"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::FirstChild: | 
					
						
							|  |  |  |                     pseudo_class_description = "FirstChild"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::OnlyChild: | 
					
						
							|  |  |  |                     pseudo_class_description = "OnlyChild"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Disabled: | 
					
						
							|  |  |  |                     pseudo_class_description = "Disabled"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Enabled: | 
					
						
							|  |  |  |                     pseudo_class_description = "Enabled"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Checked: | 
					
						
							|  |  |  |                     pseudo_class_description = "Checked"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Not: | 
					
						
							|  |  |  |                     pseudo_class_description = "Not"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |                 builder.appendff(" pseudo_class={}", pseudo_class_description); | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  |                 if (pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Not) { | 
					
						
							|  |  |  |                     builder.appendff("({})", pseudo_class.not_selector); | 
					
						
							|  |  |  |                 } else if ((pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::NthChild) | 
					
						
							|  |  |  |                     || (pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::NthLastChild)) { | 
					
						
							|  |  |  |                     builder.appendff("(step={}, offset={})", pseudo_class.nth_child_pattern.step_size, pseudo_class.nth_child_pattern.offset); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 16:34:18 +01:00
										 |  |  |             if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoElement) { | 
					
						
							|  |  |  |                 char const* pseudo_element_description = ""; | 
					
						
							|  |  |  |                 switch (simple_selector.pseudo_element) { | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoElement::None: | 
					
						
							|  |  |  |                     pseudo_element_description = "None"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoElement::Before: | 
					
						
							|  |  |  |                     pseudo_element_description = "before"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoElement::After: | 
					
						
							|  |  |  |                     pseudo_element_description = "after"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoElement::FirstLine: | 
					
						
							|  |  |  |                     pseudo_element_description = "first-line"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoElement::FirstLetter: | 
					
						
							|  |  |  |                     pseudo_element_description = "first-letter"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 builder.appendff(" pseudo_element={}", pseudo_element_description); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |             if (simple_selector.type == CSS::Selector::SimpleSelector::Type::Attribute) { | 
					
						
							|  |  |  |                 char const* attribute_match_type_description = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 switch (simple_selector.attribute.match_type) { | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::None: | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::HasAttribute: | 
					
						
							|  |  |  |                     type_description = "HasAttribute"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::ExactValueMatch: | 
					
						
							|  |  |  |                     type_description = "ExactValueMatch"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsWord: | 
					
						
							|  |  |  |                     type_description = "ContainsWord"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsString: | 
					
						
							|  |  |  |                     type_description = "ContainsString"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment: | 
					
						
							|  |  |  |                     type_description = "StartsWithSegment"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithString: | 
					
						
							|  |  |  |                     type_description = "StartsWithString"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::EndsWithString: | 
					
						
							|  |  |  |                     type_description = "EndsWithString"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 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-07-12 14:13:29 +01:00
										 |  |  | void dump_rule(CSS::CSSRule const& 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-07-12 14:13:29 +01:00
										 |  |  | void dump_rule(StringBuilder& builder, CSS::CSSRule const& rule) | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     builder.appendff("{}:\n", rule.class_name()); | 
					
						
							|  |  |  |     switch (rule.type()) { | 
					
						
							|  |  |  |     case CSS::CSSRule::Type::Style: | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  |         dump_style_rule(builder, verify_cast<CSS::CSSStyleRule const>(rule)); | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  |     case CSS::CSSRule::Type::Import: | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  |         dump_import_rule(builder, verify_cast<CSS::CSSImportRule const>(rule)); | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_import_rule(StringBuilder& builder, CSS::CSSImportRule const& rule) | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     builder.appendff("  Document URL: {}\n", rule.url()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_style_rule(StringBuilder& builder, CSS::CSSStyleRule const& 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
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  | void dump_sheet(CSS::StyleSheet const& 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()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:13:09 +02:00
										 |  |  | void dump_sheet(StringBuilder& builder, CSS::StyleSheet const& sheet) | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-24 21:13:09 +02:00
										 |  |  |     auto& css_stylesheet = verify_cast<CSS::CSSStyleSheet>(sheet); | 
					
						
							| 
									
										
										
										
											2019-06-25 06:31:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:13:09 +02:00
										 |  |  |     builder.appendff("CSSStyleSheet{{{}}}: {} rule(s)\n", &sheet, css_stylesheet.rules().size()); | 
					
						
							| 
									
										
										
										
											2021-03-07 16:14:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:13:09 +02:00
										 |  |  |     for (auto& rule : css_stylesheet.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
										 |  |  | 
 | 
					
						
							|  |  |  | } |