Skip to content

Commit

Permalink
Make empty actually empty
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiask committed Apr 18, 2024
1 parent d50b938 commit 0967490
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Next version
~~~~~~~~~~~~

- Allowed installing the package in Python 3.10 environments too.
- Tweaked the cleaning methods of ``ProseEditorField`` and
``SanitizedProseEditorField`` to produce empty strings when no content is
entered. Previously they would produce an empty paragraph (``<p></p>``) since
our ProseMirror schema says that there exists always one or more block nodes.


0.3 (2024-04-09)
Expand Down
14 changes: 12 additions & 2 deletions django_prose_editor/fields.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import re

from django import forms
from django.db import models
from django.utils.html import strip_tags
Expand All @@ -6,13 +8,21 @@
from django_prose_editor.widgets import ProseEditorWidget


def _identity(x):
def _actually_empty(x):
"""
ProseMirror's schema always adds at least one empty paragraph
We want empty fields to actually be empty strings so that those field
values evaluate as ``False`` in a boolean context.
"""
if re.match(r"^<(?P<tag>\w+)></(?P=tag)>$", x):
return ""
return x


class ProseEditorField(models.TextField):
def __init__(self, *args, **kwargs):
self.sanitize = kwargs.pop("sanitize", _identity)
self.sanitize = kwargs.pop("sanitize", _actually_empty)
self.config = kwargs.pop("config", {})
super().__init__(*args, **kwargs)

Expand Down
12 changes: 8 additions & 4 deletions django_prose_editor/sanitized.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from django_prose_editor.fields import ProseEditorField
from django_prose_editor.fields import ProseEditorField, _actually_empty


def _nh3_sanitizer():
from nh3 import clean

return lambda x: _actually_empty(clean(x))


class SanitizedProseEditorField(ProseEditorField):
def __init__(self, *args, **kwargs):
if "sanitize" not in kwargs:
from nh3 import clean

kwargs["sanitize"] = clean
kwargs["sanitize"] = _nh3_sanitizer()
super().__init__(*args, **kwargs)
35 changes: 34 additions & 1 deletion tests/testapp/test_prose_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,33 @@
from django.db import models
from django.test.utils import isolate_apps

from django_prose_editor.fields import ProseEditorField
from django_prose_editor.sanitized import SanitizedProseEditorField


class Test(test.TestCase):
@isolate_apps()
def test_field(self):
def test_standard_field(self):
class Model(models.Model):
description = ProseEditorField()

def __str__(self):
return self.description

m = Model(description="<p></p>")
m.full_clean()
self.assertEqual(m.description, "")

m = Model(description="<h1></h1>")
m.full_clean()
self.assertEqual(m.description, "")

m = Model(description="<p>hello</p>")
m.full_clean()
self.assertEqual(m.description, "<p>hello</p>")

@isolate_apps()
def test_sanitized_field(self):
class Model(models.Model):
description = SanitizedProseEditorField()

Expand All @@ -17,3 +38,15 @@ def __str__(self):
m = Model(description="<style>h1{color:red}</style><h1>Hello</h1>")
m.full_clean()
self.assertEqual(m.description, "<h1>Hello</h1>")

m = Model(description="<p></p>")
m.full_clean()
self.assertEqual(m.description, "")

m = Model(description="<h1></h1>")
m.full_clean()
self.assertEqual(m.description, "")

m = Model(description="<p>hello</p>")
m.full_clean()
self.assertEqual(m.description, "<p>hello</p>")

0 comments on commit 0967490

Please sign in to comment.