| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-03-09 23:53:41 +01:00
										 |  |  |  * Copyright (c) 2018-2022, 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>
 | 
					
						
							| 
									
										
										
										
											2022-03-28 20:30:26 +01:00
										 |  |  | #include <LibWeb/CSS/CSSFontFaceRule.h>
 | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  | #include <LibWeb/CSS/CSSImportRule.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  | #include <LibWeb/CSS/CSSMediaRule.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>
 | 
					
						
							| 
									
										
										
										
											2021-10-08 17:48:14 +01:00
										 |  |  | #include <LibWeb/CSS/CSSSupportsRule.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>
 | 
					
						
							| 
									
										
										
										
											2021-10-06 20:02:41 +02:00
										 |  |  | #include <LibWeb/Layout/BlockContainer.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/Node.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-17 23:03:36 +02:00
										 |  |  | #include <LibWeb/Layout/SVGBox.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/TextNode.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-10 23:13:37 +01:00
										 |  |  | #include <LibWeb/Painting/PaintableBox.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | namespace Web { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  | static void indent(StringBuilder& builder, int levels) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (int i = 0; i < levels; i++) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         builder.append("  "sv); | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         builder.append("  "sv); | 
					
						
							| 
									
										
										
										
											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
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         builder.append(">\n"sv); | 
					
						
							| 
									
										
										
										
											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()) { | 
					
						
							| 
									
										
										
										
											2021-09-12 12:58:17 +02:00
										 |  |  |         dump_tree(builder, *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-09-12 12:58:17 +02:00
										 |  |  |             static_cast<DOM::ParentNode const&>(node).for_each_child([&](auto& child) { | 
					
						
							|  |  |  |                 dump_tree(builder, child); | 
					
						
							| 
									
										
										
										
											2020-08-19 22:30:33 +01:00
										 |  |  |             }); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-06-24 19:53:42 +02:00
										 |  |  |             auto& template_element = verify_cast<HTML::HTMLTemplateElement>(node); | 
					
						
							| 
									
										
										
										
											2021-09-12 12:58:17 +02:00
										 |  |  |             dump_tree(builder, template_element.content()); | 
					
						
							| 
									
										
										
										
											2020-08-19 22:30:33 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         builder.append("  "sv); | 
					
						
							| 
									
										
										
										
											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
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |     StringView nonbox_color_on = ""sv; | 
					
						
							|  |  |  |     StringView box_color_on = ""sv; | 
					
						
							|  |  |  |     StringView svg_box_color_on = ""sv; | 
					
						
							|  |  |  |     StringView positioned_color_on = ""sv; | 
					
						
							|  |  |  |     StringView floating_color_on = ""sv; | 
					
						
							|  |  |  |     StringView inline_block_color_on = ""sv; | 
					
						
							|  |  |  |     StringView line_box_color_on = ""sv; | 
					
						
							|  |  |  |     StringView fragment_color_on = ""sv; | 
					
						
							|  |  |  |     StringView flex_color_on = ""sv; | 
					
						
							|  |  |  |     StringView color_off = ""sv; | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (interactive) { | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         nonbox_color_on = "\033[33m"sv; | 
					
						
							|  |  |  |         box_color_on = "\033[34m"sv; | 
					
						
							|  |  |  |         svg_box_color_on = "\033[31m"sv; | 
					
						
							|  |  |  |         positioned_color_on = "\033[31;1m"sv; | 
					
						
							|  |  |  |         floating_color_on = "\033[32;1m"sv; | 
					
						
							|  |  |  |         inline_block_color_on = "\033[36;1m"sv; | 
					
						
							|  |  |  |         line_box_color_on = "\033[34;1m"sv; | 
					
						
							|  |  |  |         fragment_color_on = "\033[35;1m"sv; | 
					
						
							|  |  |  |         flex_color_on = "\033[34;1m"sv; | 
					
						
							|  |  |  |         color_off = "\033[0m"sv; | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         builder.append("\n"sv); | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2021-09-17 23:03:36 +02:00
										 |  |  |         StringView color_on = is<Layout::SVGBox>(box) ? svg_box_color_on : box_color_on; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |         builder.appendff("{}{}{} <{}{}{}{}> ", | 
					
						
							| 
									
										
										
										
											2021-09-17 23:03:36 +02:00
										 |  |  |             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, | 
					
						
							| 
									
										
										
										
											2021-09-17 23:03:36 +02:00
										 |  |  |             color_on, | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |             tag_name, | 
					
						
							|  |  |  |             color_off, | 
					
						
							|  |  |  |             identifier.characters()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (interactive) | 
					
						
							|  |  |  |             builder.appendff("@{:p} ", &layout_node); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 22:12:03 +01:00
										 |  |  |         if (auto const* paint_box = box.paint_box()) { | 
					
						
							|  |  |  |             builder.appendff("at ({},{}) content-size {}x{}", | 
					
						
							|  |  |  |                 paint_box->absolute_x(), | 
					
						
							|  |  |  |                 paint_box->absolute_y(), | 
					
						
							|  |  |  |                 paint_box->content_width(), | 
					
						
							|  |  |  |                 paint_box->content_height()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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-10-21 00:29:31 +02:00
										 |  |  |         if (box.computed_values().display().is_flex_inside()) { | 
					
						
							|  |  |  |             StringView direction; | 
					
						
							|  |  |  |             switch (box.computed_values().flex_direction()) { | 
					
						
							|  |  |  |             case CSS::FlexDirection::Column: | 
					
						
							|  |  |  |                 direction = "column"sv; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CSS::FlexDirection::ColumnReverse: | 
					
						
							|  |  |  |                 direction = "column-reverse"sv; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CSS::FlexDirection::Row: | 
					
						
							|  |  |  |                 direction = "row"sv; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CSS::FlexDirection::RowReverse: | 
					
						
							|  |  |  |                 direction = "row-reverse"sv; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             builder.appendff(" {}flex-container({}){}", flex_color_on, direction, color_off); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-29 22:36:15 +02:00
										 |  |  |         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, | 
					
						
							| 
									
										
										
										
											2022-03-18 22:12:03 +01:00
										 |  |  |                 box.paint_box() ? box.paint_box()->content_width() : 0, | 
					
						
							| 
									
										
										
										
											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, | 
					
						
							| 
									
										
										
										
											2022-03-18 22:12:03 +01:00
										 |  |  |                 box.paint_box() ? box.paint_box()->content_height() : 0, | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 00:10:36 +01:00
										 |  |  |         builder.appendff(" children: {}", box.children_are_inline() ? "inline" : "not-inline"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         builder.append("\n"sv); | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-21 20:54:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-06 20:02:41 +02:00
										 |  |  |     if (is<Layout::BlockContainer>(layout_node) && static_cast<Layout::BlockContainer const&>(layout_node).children_are_inline()) { | 
					
						
							|  |  |  |         auto& block = static_cast<Layout::BlockContainer const&>(layout_node); | 
					
						
							| 
									
										
										
										
											2022-03-18 22:12:03 +01:00
										 |  |  |         for (size_t line_box_index = 0; block.paint_box() && line_box_index < block.paint_box()->line_boxes().size(); ++line_box_index) { | 
					
						
							| 
									
										
										
										
											2022-03-10 11:12:06 +01:00
										 |  |  |             auto& line_box = block.paint_box()->line_boxes()[line_box_index]; | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |             for (size_t i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                 builder.append("  "sv); | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  |             builder.appendff("  {}line {}{} width: {}, height: {}, bottom: {}, baseline: {}\n", | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                 line_box_color_on, | 
					
						
							|  |  |  |                 line_box_index, | 
					
						
							|  |  |  |                 color_off, | 
					
						
							| 
									
										
										
										
											2022-02-27 13:34:34 +01:00
										 |  |  |                 line_box.width(), | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  |                 line_box.height(), | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |                 line_box.bottom(), | 
					
						
							|  |  |  |                 line_box.baseline()); | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                     builder.append("  "sv); | 
					
						
							| 
									
										
										
										
											2020-12-08 22:11:02 +01:00
										 |  |  |                 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(), | 
					
						
							| 
									
										
										
										
											2021-09-21 12:42:42 +01:00
										 |  |  |                     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) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                         builder.append("  "sv); | 
					
						
							| 
									
										
										
										
											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
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-15 19:41:35 +01:00
										 |  |  |     if (show_specified_style && layout_node.dom_node() && layout_node.dom_node()->is_element() && verify_cast<DOM::Element>(layout_node.dom_node())->computed_css_values()) { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:36:13 +01:00
										 |  |  |         struct NameAndValue { | 
					
						
							|  |  |  |             String name; | 
					
						
							|  |  |  |             String value; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         Vector<NameAndValue> properties; | 
					
						
							| 
									
										
										
										
											2022-03-15 19:41:35 +01:00
										 |  |  |         verify_cast<DOM::Element>(*layout_node.dom_node()).computed_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) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                 builder.append("    "sv); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |     builder.append("  CSS::Selector:\n"sv); | 
					
						
							| 
									
										
										
										
											2019-11-27 20:37:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |     for (auto& relative_selector : selector.compound_selectors()) { | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         builder.append("    "sv); | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:13:29 +01:00
										 |  |  |         char const* relation_description = ""; | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |         switch (relative_selector.combinator) { | 
					
						
							|  |  |  |         case CSS::Selector::Combinator::None: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:45:38 +02:00
										 |  |  |             relation_description = "None"; | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |         case CSS::Selector::Combinator::ImmediateChild: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             relation_description = "ImmediateChild"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |         case CSS::Selector::Combinator::Descendant: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             relation_description = "Descendant"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |         case CSS::Selector::Combinator::NextSibling: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             relation_description = "AdjacentSibling"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |         case CSS::Selector::Combinator::SubsequentSibling: | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  |             relation_description = "GeneralSibling"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |         case CSS::Selector::Combinator::Column: | 
					
						
							| 
									
										
										
										
											2021-04-29 21:16:28 +02:00
										 |  |  |             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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |         for (size_t i = 0; i < relative_selector.simple_selectors.size(); ++i) { | 
					
						
							|  |  |  |             auto& simple_selector = relative_selector.simple_selectors[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::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
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 15:43:59 +00:00
										 |  |  |             builder.appendff("{}:", type_description); | 
					
						
							|  |  |  |             // FIXME: This is goofy
 | 
					
						
							|  |  |  |             if (simple_selector.value.has<FlyString>()) | 
					
						
							|  |  |  |                 builder.append(simple_selector.name()); | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass) { | 
					
						
							| 
									
										
										
										
											2022-03-21 15:43:59 +00:00
										 |  |  |                 auto const& pseudo_class = simple_selector.pseudo_class(); | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 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::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; | 
					
						
							| 
									
										
										
										
											2022-02-17 22:43:22 +01:00
										 |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::OnlyOfType: | 
					
						
							|  |  |  |                     pseudo_class_description = "OnlyOfType"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2022-02-26 13:53:13 +00:00
										 |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::NthOfType: | 
					
						
							|  |  |  |                     pseudo_class_description = "NthOfType"; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::NthLastOfType: | 
					
						
							|  |  |  |                     pseudo_class_description = "NthLastOfType"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  |                 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; | 
					
						
							| 
									
										
										
										
											2022-03-20 13:28:32 +00:00
										 |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::FocusWithin: | 
					
						
							|  |  |  |                     pseudo_class_description = "FocusWithin"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  |                 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; | 
					
						
							| 
									
										
										
										
											2022-03-17 15:28:42 +00:00
										 |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Is: | 
					
						
							|  |  |  |                     pseudo_class_description = "Is"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2022-03-17 16:13:13 +00:00
										 |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Where: | 
					
						
							|  |  |  |                     pseudo_class_description = "Where"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2022-03-20 12:39:11 +01:00
										 |  |  |                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Lang: | 
					
						
							|  |  |  |                     pseudo_class_description = "Lang"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-17 15:59:13 +01:00
										 |  |  |                 builder.appendff(" pseudo_class={}", pseudo_class_description); | 
					
						
							| 
									
										
										
										
											2022-03-20 12:39:11 +01:00
										 |  |  |                 if (pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Lang) { | 
					
						
							|  |  |  |                     builder.append('('); | 
					
						
							|  |  |  |                     builder.join(',', pseudo_class.languages); | 
					
						
							|  |  |  |                     builder.append(')'); | 
					
						
							|  |  |  |                 } else if (pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Not | 
					
						
							| 
									
										
										
										
											2022-03-17 16:13:13 +00:00
										 |  |  |                     || pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Is | 
					
						
							|  |  |  |                     || pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Where) { | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                     builder.append("(["sv); | 
					
						
							| 
									
										
										
										
											2022-03-17 15:28:42 +00:00
										 |  |  |                     for (auto& selector : pseudo_class.argument_selector_list) | 
					
						
							| 
									
										
										
										
											2021-07-12 17:58:47 +01:00
										 |  |  |                         dump_selector(builder, selector); | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                     builder.append("])"sv); | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  |                 } else if ((pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::NthChild) | 
					
						
							| 
									
										
										
										
											2022-03-17 19:13:51 +00:00
										 |  |  |                     || (pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::NthLastChild) | 
					
						
							|  |  |  |                     || (pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::NthOfType) | 
					
						
							|  |  |  |                     || (pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::NthLastOfType)) { | 
					
						
							|  |  |  |                     builder.appendff("(step={}, offset={}", pseudo_class.nth_child_pattern.step_size, pseudo_class.nth_child_pattern.offset); | 
					
						
							|  |  |  |                     if (!pseudo_class.argument_selector_list.is_empty()) { | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                         builder.append(", selectors=["sv); | 
					
						
							| 
									
										
										
										
											2022-03-17 19:13:51 +00:00
										 |  |  |                         for (auto const& child_selector : pseudo_class.argument_selector_list) | 
					
						
							|  |  |  |                             dump_selector(builder, child_selector); | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                         builder.append("]"sv); | 
					
						
							| 
									
										
										
										
											2022-03-17 19:13:51 +00:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                     builder.append(")"sv); | 
					
						
							| 
									
										
										
										
											2021-07-12 16:18:00 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											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 = ""; | 
					
						
							| 
									
										
										
										
											2022-03-21 15:43:59 +00:00
										 |  |  |                 switch (simple_selector.pseudo_element()) { | 
					
						
							| 
									
										
										
										
											2022-02-24 15:13:20 +00:00
										 |  |  |                 case CSS::Selector::PseudoElement::Before: | 
					
						
							| 
									
										
										
										
											2021-07-12 16:34:18 +01:00
										 |  |  |                     pseudo_element_description = "before"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2022-02-24 15:13:20 +00:00
										 |  |  |                 case CSS::Selector::PseudoElement::After: | 
					
						
							| 
									
										
										
										
											2021-07-12 16:34:18 +01:00
										 |  |  |                     pseudo_element_description = "after"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2022-02-24 15:13:20 +00:00
										 |  |  |                 case CSS::Selector::PseudoElement::FirstLine: | 
					
						
							| 
									
										
										
										
											2021-07-12 16:34:18 +01:00
										 |  |  |                     pseudo_element_description = "first-line"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2022-02-24 15:13:20 +00:00
										 |  |  |                 case CSS::Selector::PseudoElement::FirstLetter: | 
					
						
							| 
									
										
										
										
											2021-07-12 16:34:18 +01:00
										 |  |  |                     pseudo_element_description = "first-letter"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2022-02-25 17:29:38 +00:00
										 |  |  |                 case CSS::Selector::PseudoElement::Marker: | 
					
						
							|  |  |  |                     pseudo_element_description = "marker"; | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2021-07-12 16:34:18 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 builder.appendff(" pseudo_element={}", pseudo_element_description); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |             if (simple_selector.type == CSS::Selector::SimpleSelector::Type::Attribute) { | 
					
						
							| 
									
										
										
										
											2022-03-21 15:43:59 +00:00
										 |  |  |                 auto const& attribute = simple_selector.attribute(); | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                 char const* attribute_match_type_description = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 15:43:59 +00:00
										 |  |  |                 switch (attribute.match_type) { | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::HasAttribute: | 
					
						
							| 
									
										
										
										
											2021-07-24 13:28:45 +01:00
										 |  |  |                     attribute_match_type_description = "HasAttribute"; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::ExactValueMatch: | 
					
						
							| 
									
										
										
										
											2021-07-24 13:28:45 +01:00
										 |  |  |                     attribute_match_type_description = "ExactValueMatch"; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsWord: | 
					
						
							| 
									
										
										
										
											2021-07-24 13:28:45 +01:00
										 |  |  |                     attribute_match_type_description = "ContainsWord"; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsString: | 
					
						
							| 
									
										
										
										
											2021-07-24 13:28:45 +01:00
										 |  |  |                     attribute_match_type_description = "ContainsString"; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment: | 
					
						
							| 
									
										
										
										
											2021-07-24 13:28:45 +01:00
										 |  |  |                     attribute_match_type_description = "StartsWithSegment"; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithString: | 
					
						
							| 
									
										
										
										
											2021-07-24 13:28:45 +01:00
										 |  |  |                     attribute_match_type_description = "StartsWithString"; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 case CSS::Selector::SimpleSelector::Attribute::MatchType::EndsWithString: | 
					
						
							| 
									
										
										
										
											2021-07-24 13:28:45 +01:00
										 |  |  |                     attribute_match_type_description = "EndsWithString"; | 
					
						
							| 
									
										
										
										
											2021-07-12 14:58:03 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 15:43:59 +00:00
										 |  |  |                 builder.appendff(" [{}, name='{}', value='{}']", attribute_match_type_description, attribute.name, attribute.value); | 
					
						
							| 
									
										
										
										
											2019-11-21 20:07:43 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-03-29 22:24:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:24:33 +01:00
										 |  |  |             if (i != relative_selector.simple_selectors.size() - 1) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |                 builder.append(", "sv); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |         builder.append("\n"sv); | 
					
						
							| 
									
										
										
										
											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-09-29 12:48:04 +01:00
										 |  |  | void dump_rule(StringBuilder& builder, CSS::CSSRule const& rule, int indent_levels) | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  |     indent(builder, indent_levels); | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |     builder.appendff("{}:\n", rule.class_name()); | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |     switch (rule.type()) { | 
					
						
							| 
									
										
										
										
											2022-03-28 20:30:26 +01:00
										 |  |  |     case CSS::CSSRule::Type::FontFace: | 
					
						
							|  |  |  |         dump_font_face_rule(builder, verify_cast<CSS::CSSFontFaceRule const>(rule), indent_levels); | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  |     case CSS::CSSRule::Type::Import: | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  |         dump_import_rule(builder, verify_cast<CSS::CSSImportRule const>(rule), indent_levels); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case CSS::CSSRule::Type::Media: | 
					
						
							|  |  |  |         dump_media_rule(builder, verify_cast<CSS::CSSMediaRule const>(rule), indent_levels); | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2022-03-28 20:30:26 +01:00
										 |  |  |     case CSS::CSSRule::Type::Style: | 
					
						
							|  |  |  |         dump_style_rule(builder, verify_cast<CSS::CSSStyleRule const>(rule), indent_levels); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-08 17:48:14 +01:00
										 |  |  |     case CSS::CSSRule::Type::Supports: | 
					
						
							|  |  |  |         dump_supports_rule(builder, verify_cast<CSS::CSSSupportsRule const>(rule), indent_levels); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-02-21 13:45:26 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-28 20:30:26 +01:00
										 |  |  | void dump_font_face_rule(StringBuilder& builder, CSS::CSSFontFaceRule const& rule, int indent_levels) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto& font_face = rule.font_face(); | 
					
						
							|  |  |  |     indent(builder, indent_levels + 1); | 
					
						
							|  |  |  |     builder.appendff("font-family: {}\n", font_face.font_family()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     indent(builder, indent_levels + 1); | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |     builder.append("sources:\n"sv); | 
					
						
							| 
									
										
										
										
											2022-03-28 20:30:26 +01:00
										 |  |  |     for (auto const& source : font_face.sources()) { | 
					
						
							|  |  |  |         indent(builder, indent_levels + 2); | 
					
						
							| 
									
										
										
										
											2022-03-31 21:18:54 +01:00
										 |  |  |         builder.appendff("url={}, format={}\n", source.url, source.format.value_or("???")); | 
					
						
							| 
									
										
										
										
											2022-03-28 20:30:26 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-03-31 16:39:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     indent(builder, indent_levels + 1); | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |     builder.append("unicode-ranges:\n"sv); | 
					
						
							| 
									
										
										
										
											2022-03-31 16:39:52 +01:00
										 |  |  |     for (auto const& unicode_range : font_face.unicode_ranges()) { | 
					
						
							|  |  |  |         indent(builder, indent_levels + 2); | 
					
						
							|  |  |  |         builder.appendff("{}\n", unicode_range.to_string()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-03-28 20:30:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  | void dump_import_rule(StringBuilder& builder, CSS::CSSImportRule const& rule, int indent_levels) | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  |     indent(builder, indent_levels); | 
					
						
							| 
									
										
										
										
											2021-02-21 18:36:34 +02:00
										 |  |  |     builder.appendff("  Document URL: {}\n", rule.url()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  | void dump_media_rule(StringBuilder& builder, CSS::CSSMediaRule const& media, int indent_levels) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     indent(builder, indent_levels); | 
					
						
							|  |  |  |     builder.appendff("  Media: {}\n  Rules ({}):\n", media.condition_text(), media.css_rules().length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto& rule : media.css_rules()) { | 
					
						
							|  |  |  |         dump_rule(builder, rule, indent_levels + 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-08 17:48:14 +01:00
										 |  |  | void dump_supports_rule(StringBuilder& builder, CSS::CSSSupportsRule const& supports, int indent_levels) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     indent(builder, indent_levels); | 
					
						
							|  |  |  |     builder.appendff("  Supports: {}\n  Rules ({}):\n", supports.condition_text(), supports.css_rules().length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto& rule : supports.css_rules()) { | 
					
						
							|  |  |  |         dump_rule(builder, rule, indent_levels + 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  | void dump_style_rule(StringBuilder& builder, CSS::CSSStyleRule const& rule, int indent_levels) | 
					
						
							| 
									
										
										
										
											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-09-29 12:48:04 +01:00
										 |  |  |     indent(builder, indent_levels); | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |     builder.append("  Declarations:\n"sv); | 
					
						
							| 
									
										
										
										
											2021-11-30 16:23:35 +00:00
										 |  |  |     auto& style_declaration = verify_cast<CSS::PropertyOwningCSSStyleDeclaration>(rule.declaration()); | 
					
						
							|  |  |  |     for (auto& property : style_declaration.properties()) { | 
					
						
							| 
									
										
										
										
											2021-09-29 12:48:04 +01:00
										 |  |  |         indent(builder, indent_levels); | 
					
						
							| 
									
										
										
										
											2021-09-21 11:29:44 +02:00
										 |  |  |         builder.appendff("    {}: '{}'", CSS::string_from_property_id(property.property_id), property.value->to_string()); | 
					
						
							| 
									
										
										
										
											2022-02-12 14:53:59 +00:00
										 |  |  |         if (property.important == CSS::Important::Yes) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |             builder.append(" \033[31;1m!important\033[0m"sv); | 
					
						
							| 
									
										
										
										
											2021-09-21 11:29:44 +02:00
										 |  |  |         builder.append('\n'); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-30 16:23:35 +00:00
										 |  |  |     for (auto& property : style_declaration.custom_properties()) { | 
					
						
							|  |  |  |         indent(builder, indent_levels); | 
					
						
							|  |  |  |         builder.appendff("    {}: '{}'", property.key, property.value.value->to_string()); | 
					
						
							| 
									
										
										
										
											2022-02-12 14:53:59 +00:00
										 |  |  |         if (property.value.important == CSS::Important::Yes) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 |  |  |             builder.append(" \033[31;1m!important\033[0m"sv); | 
					
						
							| 
									
										
										
										
											2021-11-30 16:23:35 +00:00
										 |  |  |         builder.append('\n'); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											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-09-28 16:18:20 +01:00
										 |  |  |     builder.appendff("CSSStyleSheet{{{}}}: {} rule(s)\n", &sheet, css_stylesheet.rules().length()); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | } |