Add clean method to QuestionForm to unwrap single <p> tags from TinyMCE HTML fields
This commit is contained in:
@@ -22,6 +22,7 @@ from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||
from django.forms.widgets import RadioSelect, TextInput, Textarea
|
||||
|
||||
from tinymce.widgets import TinyMCE
|
||||
import re
|
||||
|
||||
from dal import autocomplete
|
||||
from crispy_forms.helper import FormHelper
|
||||
@@ -160,6 +161,45 @@ class QuestionForm(ModelForm):
|
||||
|
||||
return instance
|
||||
|
||||
def clean(self):
|
||||
"""Strip a single wrapping <p>...</p> from TinyMCE-provided HTML fields.
|
||||
|
||||
This handles the common TinyMCE behaviour where the editor wraps
|
||||
inline content in a root <p>. We only unwrap when the entire value
|
||||
is a single <p> element (so multi-paragraph content is preserved).
|
||||
"""
|
||||
cleaned = super(QuestionForm, self).clean()
|
||||
|
||||
def _unwrap_single_p(html: str) -> str:
|
||||
if not html or not isinstance(html, str):
|
||||
return html
|
||||
# Match a single <p ...>...</p> that spans the whole string
|
||||
m = re.fullmatch(r"\s*<p\b[^>]*>(.*)</p>\s*", html, flags=re.DOTALL | re.IGNORECASE)
|
||||
if m:
|
||||
return m.group(1)
|
||||
return html
|
||||
|
||||
fields_to_unwrap = [
|
||||
"stem",
|
||||
"feedback",
|
||||
"a_answer",
|
||||
"a_feedback",
|
||||
"b_answer",
|
||||
"b_feedback",
|
||||
"c_answer",
|
||||
"c_feedback",
|
||||
"d_answer",
|
||||
"d_feedback",
|
||||
"e_answer",
|
||||
"e_feedback",
|
||||
]
|
||||
|
||||
for fname in fields_to_unwrap:
|
||||
if fname in cleaned:
|
||||
cleaned[fname] = _unwrap_single_p(cleaned.get(fname))
|
||||
|
||||
return cleaned
|
||||
|
||||
class Meta:
|
||||
model = Question
|
||||
|
||||
|
||||
Reference in New Issue
Block a user