From 774119bb57a002bfd793095819aed0512b91fd53 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Sat, 10 Feb 2024 15:23:19 +0000 Subject: [PATCH] LibWeb: Implement `document.designMode` Setting this attribute to "on" makes the entire document editable. --- .../expected/DOM/Document-set-designMode.txt | 6 +++ .../input/DOM/Document-set-designMode.html | 17 ++++++++ Userland/Libraries/LibWeb/DOM/Document.cpp | 41 +++++++++++++++++++ Userland/Libraries/LibWeb/DOM/Document.h | 7 ++++ Userland/Libraries/LibWeb/DOM/Document.idl | 2 + 5 files changed, 73 insertions(+) create mode 100644 Tests/LibWeb/Text/expected/DOM/Document-set-designMode.txt create mode 100644 Tests/LibWeb/Text/input/DOM/Document-set-designMode.html diff --git a/Tests/LibWeb/Text/expected/DOM/Document-set-designMode.txt b/Tests/LibWeb/Text/expected/DOM/Document-set-designMode.txt new file mode 100644 index 0000000000..64e8bd2beb --- /dev/null +++ b/Tests/LibWeb/Text/expected/DOM/Document-set-designMode.txt @@ -0,0 +1,6 @@ +document.designMode initial value: off +document.designMode after setting to "invalid": off +document.designMode after setting to "on": on +document.designMode after setting to "off": off +document.designMode after setting to "ON": on +document.designMode after setting to "OFF": off diff --git a/Tests/LibWeb/Text/input/DOM/Document-set-designMode.html b/Tests/LibWeb/Text/input/DOM/Document-set-designMode.html new file mode 100644 index 0000000000..df7cb3335e --- /dev/null +++ b/Tests/LibWeb/Text/input/DOM/Document-set-designMode.html @@ -0,0 +1,17 @@ + + diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 747183156c..0ca92769e3 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -3735,6 +3735,47 @@ void Document::remove_form_associated_element_with_form_attribute(HTML::FormAsso }); } +void Document::set_design_mode_enabled_state(bool design_mode_enabled) +{ + m_design_mode_enabled = design_mode_enabled; + set_editable(design_mode_enabled); +} + +// https://html.spec.whatwg.org/multipage/interaction.html#making-entire-documents-editable:-the-designmode-idl-attribute +String Document::design_mode() const +{ + // The designMode getter steps are to return "on" if this's design mode enabled is true; otherwise "off". + return design_mode_enabled_state() ? "on"_string : "off"_string; +} + +WebIDL::ExceptionOr Document::set_design_mode(String const& design_mode) +{ + // 1. Let value be the given value, converted to ASCII lowercase. + auto value = MUST(design_mode.to_lowercase()); + + // 2. If value is "on" and this's design mode enabled is false, then: + if (value == "on"sv && !m_design_mode_enabled) { + // 1. Set this's design mode enabled to true. + set_design_mode_enabled_state(true); + // 2. Reset this's active range's start and end boundary points to be at the start of this. + if (auto selection = get_selection(); selection) { + if (auto active_range = selection->range(); active_range) { + TRY(active_range->set_start(*this, 0)); + TRY(active_range->set_end(*this, 0)); + update_layout(); + } + } + // 3. Run the focusing steps for this's document element, if non-null. + if (auto* document_element = this->document_element(); document_element) + HTML::run_focusing_steps(document_element); + } + // 3. If value is "off", then set this's design mode enabled to false. + else if (value == "off"sv) { + set_design_mode_enabled_state(false); + } + return {}; +} + // https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint Element const* Document::element_from_point(double x, double y) { diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index a6cb496716..d86f7f9dfd 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -561,6 +561,11 @@ public: void add_form_associated_element_with_form_attribute(HTML::FormAssociatedElement&); void remove_form_associated_element_with_form_attribute(HTML::FormAssociatedElement&); + bool design_mode_enabled_state() const { return m_design_mode_enabled; } + void set_design_mode_enabled_state(bool); + String design_mode() const; + WebIDL::ExceptionOr set_design_mode(String const&); + Element const* element_from_point(double x, double y); void set_needs_to_resolve_paint_only_properties() { m_needs_to_resolve_paint_only_properties = true; } @@ -789,6 +794,8 @@ private: Vector m_form_associated_elements_with_form_attribute; + bool m_design_mode_enabled { false }; + bool m_needs_to_resolve_paint_only_properties { true }; }; diff --git a/Userland/Libraries/LibWeb/DOM/Document.idl b/Userland/Libraries/LibWeb/DOM/Document.idl index 287cc822c8..7a0e7483ef 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.idl +++ b/Userland/Libraries/LibWeb/DOM/Document.idl @@ -114,6 +114,8 @@ interface Document : Node { Selection? getSelection(); + [CEReactions] attribute DOMString designMode; + // https://www.w3.org/TR/web-animations-1/#extensions-to-the-document-interface readonly attribute DocumentTimeline timeline;