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;