Browse Source

Docs - Improve hooks & extending pages with CSP compliant examples

- Avoid `mark_safe` and use `format_html` where possible
- Avoid inline scripts, instead ensure the example shows external script usage
Aayushman Singh 4 months ago
parent
commit
7f6e7d4062
2 changed files with 44 additions and 31 deletions
  1. 2 2
      docs/extending/extending_client_side.md
  2. 42 29
      docs/reference/hooks.md

+ 2 - 2
docs/extending/extending_client_side.md

@@ -103,13 +103,13 @@ Finally, load the JavaScript file into Wagtail's admin with a hook.
 ```python
 # myapp/wagtail_hooks.py
 from django.templatetags.static import static
-from django.utils.safestring import mark_safe
+from django.utils.html import format_html
 
 from wagtail import hooks
 
 @hooks.register('insert_global_admin_js')
 def global_admin_js():
-    return mark_safe(
+    return format_html(
         f'<script src="{static("js/example.js")}"></script>',
     )
 ```

+ 42 - 29
docs/reference/hooks.md

@@ -113,7 +113,7 @@ Hooks for building new areas of the admin interface (alongside pages, images, do
 Add or remove panels from the Wagtail admin homepage. The callable passed into this hook should take a `request` object and a list of panel objects and should modify this list in place as required. Panel objects are [](template_components) with an additional `order` property, an integer that determines the panel's position in the final ordered list. The default panels use integers between `100` and `300`.
 
 ```python
-from django.utils.safestring import mark_safe
+from django.utils.html import format_html
 
 from wagtail.admin.ui.components import Component
 from wagtail import hooks
@@ -122,11 +122,13 @@ class WelcomePanel(Component):
     order = 50
 
     def render_html(self, parent_context):
-        return mark_safe("""
-        <section class="panel summary nice-padding">
-          <h3>No, but seriously -- welcome to the admin homepage.</h3>
-        </section>
-        """)
+        return format_html(
+            """
+            <section class="panel summary nice-padding">
+              <h3>No, but seriously -- welcome to the admin homepage.</h3>
+            </section>
+            """
+        )
 
 @hooks.register('construct_homepage_panels')
 def add_another_welcome_panel(request, panels):
@@ -473,6 +475,7 @@ Rich text fields in Wagtail work with a list of 'feature' identifiers that deter
 Add additional CSS files or snippets to all admin pages.
 
 ```python
+# wagtail_hooks.py
 from django.utils.html import format_html
 from django.templatetags.static import static
 
@@ -490,35 +493,44 @@ def global_admin_css():
 Add additional JavaScript files or code snippets to the page editor.
 
 ```python
-from django.utils.html import format_html_join
-from django.utils.safestring import mark_safe
+# wagtail_hooks.py
 from django.templatetags.static import static
+from django.utils.html import format_html, format_html_join
 
 from wagtail import hooks
 
-@hooks.register('insert_editor_js')
+@hooks.register("insert_editor_js")
 def editor_js():
     js_files = [
-        'js/fireworks.js', # https://fireworks.js.org
+        'js/fireworks.js', # See https://fireworks.js.org for CDN import URLs
+        'js/init-fireworks.js',
     ]
-    js_includes = format_html_join('\n', '<script src="{0}"></script>',
+    return format_html_join(
+        '\n',
+        '<script src="{}"></script>',
         ((static(filename),) for filename in js_files)
     )
-    return js_includes + mark_safe(
-        """
-        <script>
-            window.addEventListener('DOMContentLoaded', (event) => {
-                var container = document.createElement('div');
-                container.style.cssText = 'position: fixed; width: 100%; height: 100%; z-index: 100; top: 0; left: 0; pointer-events: none;';
-                container.id = 'fireworks';
-                document.getElementById('main').prepend(container);
-                var options = { "acceleration": 1.2, "autoresize": true, "mouse": { "click": true, "max": 3 } };
-                var fireworks = new Fireworks(document.getElementById('fireworks'), options);
-                fireworks.start();
-            });
-        </script>
-        """
-    )
+```
+
+```javascript
+// js/init-fireworks.js
+window.addEventListener('DOMContentLoaded', (event) => {
+    var container = document.createElement('div');
+    container.style.cssText =
+        'position: fixed; width: 100%; height: 100%; z-index: 100; top: 0; left: 0; pointer-events: none;';
+    container.id = 'fireworks';
+    document.getElementById('main').prepend(container);
+    var options = {
+        acceleration: 1.2,
+        autoresize: true,
+        mouse: { click: true, max: 3 },
+    };
+    var fireworks = new Fireworks(
+        document.getElementById('fireworks'),
+        options,
+    );
+    fireworks.start();
+});
 ```
 
 (insert_global_admin_js)=
@@ -528,14 +540,15 @@ def editor_js():
 Add additional JavaScript files or code snippets to all admin pages.
 
 ```python
-from django.utils.safestring import mark_safe
+from django.utils.html import format_html
 
 from wagtail import hooks
 
 @hooks.register('insert_global_admin_js')
 def global_admin_js():
-    return mark_safe(
-        '<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.js"></script>',
+    return format_html(
+        '<script src="{}"></script>',
+        "https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.js"
     )
 ```