diff --git a/config/settings/base.py b/config/settings/base.py
index d9020e14eb2..89619fab25a 100644
--- a/config/settings/base.py
+++ b/config/settings/base.py
@@ -51,7 +51,6 @@
"citext",
"django_bootstrap5",
"django_select2",
- "easymde",
"formtools",
"huey.contrib.djhuey",
"markdownify",
diff --git a/itou/templates/companies/create_siae.html b/itou/templates/companies/create_siae.html
index f3e77561efd..9fea7dfe762 100644
--- a/itou/templates/companies/create_siae.html
+++ b/itou/templates/companies/create_siae.html
@@ -4,8 +4,6 @@
{% block title %}Créer une nouvelle structure {{ block.super }}{% endblock %}
-{% block extra_head %}{{ block.super }}{{ form.media.css }}{% endblock %}
-
{% block title_content %}
Créer/rejoindre une nouvelle structure
Vous souhaitez rejoindre une structure :
@@ -66,8 +64,3 @@ Créer/rejoindre une nouvelle structure
{% endblock %}
-
-{% block script %}
- {{ block.super }}
- {{ form.media.js }}
-{% endblock %}
diff --git a/itou/templates/companies/edit_job_description_details.html b/itou/templates/companies/edit_job_description_details.html
index 698a46b007f..e9482e45f9b 100644
--- a/itou/templates/companies/edit_job_description_details.html
+++ b/itou/templates/companies/edit_job_description_details.html
@@ -5,8 +5,6 @@
{% block title %}Modifier les détails de la fiche de poste {{ block.super }}{% endblock %}
-{% block extra_head %}{{ block.super }}{{ form.media.css }}{% endblock %}
-
{% block content %}
{% endblock %}
-
-{% block script %}
- {{ block.super }}
- {{ form.media.js }}
-{% endblock %}
diff --git a/itou/templates/companies/edit_siae_description.html b/itou/templates/companies/edit_siae_description.html
index c5cb113422e..602de1e0a99 100644
--- a/itou/templates/companies/edit_siae_description.html
+++ b/itou/templates/companies/edit_siae_description.html
@@ -6,8 +6,6 @@
{% block title %}Modifier les coordonnées de votre structure {{ block.super }}{% endblock %}
-{% block extra_head %}{{ block.super }}{{ form.media.css }}{% endblock %}
-
{% block content %}
{% endblock %}
-
-{% block script %}
- {{ block.super }}
- {{ form.media.js }}
-{% endblock %}
diff --git a/itou/templates/layout/base.html b/itou/templates/layout/base.html
index 1e0eddb7b40..c81bf42b14c 100644
--- a/itou/templates/layout/base.html
+++ b/itou/templates/layout/base.html
@@ -35,6 +35,7 @@
+
{% block extra_head %}{% endblock %}
@@ -105,6 +106,7 @@
+
@@ -114,6 +116,7 @@
{% endif %}
+
diff --git a/itou/templates/prescribers/edit_organization.html b/itou/templates/prescribers/edit_organization.html
index 9d75c12fe3e..8a897db6e9d 100644
--- a/itou/templates/prescribers/edit_organization.html
+++ b/itou/templates/prescribers/edit_organization.html
@@ -4,8 +4,6 @@
{% block title %}Modifier cette organisation {{ block.super }}{% endblock %}
-{% block extra_head %}{{ block.super }}{{ form.media.css }}{% endblock %}
-
{% block title_prevstep %}
{% include "layout/previous_step.html" with back_url=back_url only %}
{% endblock %}
@@ -46,8 +44,3 @@
{% endblock %}
-
-{% block script %}
- {{ block.super }}
- {{ form.media.js }}
-{% endblock %}
diff --git a/itou/utils/staticfiles.py b/itou/utils/staticfiles.py
index a914251b22c..d8bd211c3b9 100644
--- a/itou/utils/staticfiles.py
+++ b/itou/utils/staticfiles.py
@@ -76,6 +76,21 @@
],
},
},
+ "easymde": {
+ "download": {
+ "url": "https://registry.npmjs.org/easymde/-/easymde-2.18.0.tgz",
+ "sha256": "8b2747047c8381f1eade4533bcb67ad70daf98b6bcf5ca5ac3514ecde0f6552d",
+ },
+ "extract": {
+ "origin": "package",
+ "destination": "vendor/easymde",
+ "files": [
+ "LICENSE",
+ ("dist/easymde.min.js", "easymde.min.js"),
+ ("dist/easymde.min.css", "easymde.min.css"),
+ ],
+ },
+ },
"tiny-slider": {
"download": {
"url": "https://github.com/ganlanyuan/tiny-slider/archive/refs/tags/v2.9.4.zip",
diff --git a/itou/utils/widgets.py b/itou/utils/widgets.py
index a8a533ac435..e3f8830992b 100644
--- a/itou/utils/widgets.py
+++ b/itou/utils/widgets.py
@@ -11,7 +11,6 @@
from django.db.models import Q
from django.forms.models import ModelChoiceIterator
from django_select2.forms import Select2Widget
-from easymde.widgets import EasyMDEEditor
from itou.utils.validators import get_max_birthdate, get_min_birthdate
@@ -196,8 +195,16 @@ def create_option(self, name, value, *args, **kwargs):
return option
-class EasyMDEEditorWithConfig(EasyMDEEditor):
- class Media:
- extend = False
- js = ("easymde/easymde.min.js", "js/easymde_config.js")
- css = {"all": ("easymde/easymde.min.css",)}
+class EasyMDEEditor(forms.Textarea):
+ def build_attrs(self, base_attrs, extra_attrs=None):
+ attrs = super().build_attrs(base_attrs, extra_attrs)
+ easymde_class = "easymde-box"
+ try:
+ classes = attrs["class"].split(" ")
+ except KeyError:
+ classes = [easymde_class]
+ else:
+ if easymde_class not in classes:
+ classes.append(easymde_class)
+ attrs["class"] = " ".join(classes)
+ return attrs
diff --git a/itou/www/companies_views/forms.py b/itou/www/companies_views/forms.py
index a77dd77959e..bfa111d212e 100644
--- a/itou/www/companies_views/forms.py
+++ b/itou/www/companies_views/forms.py
@@ -10,7 +10,7 @@
from itou.companies.models import Company, CompanyMembership, JobDescription
from itou.jobs.models import Appellation
from itou.utils.urls import get_external_link_markup
-from itou.utils.widgets import EasyMDEEditorWithConfig, RemoteAutocompleteSelect2Widget
+from itou.utils.widgets import EasyMDEEditor, RemoteAutocompleteSelect2Widget
class CreateCompanyForm(forms.ModelForm):
@@ -39,7 +39,7 @@ class Meta:
"description": "Texte de présentation de votre structure.",
}
widgets = {
- "description": EasyMDEEditorWithConfig,
+ "description": EasyMDEEditor,
}
def __init__(self, current_company, current_user, *args, **kwargs):
@@ -151,8 +151,8 @@ class Meta:
}
widgets = {
- "description": EasyMDEEditorWithConfig,
- "provided_support": EasyMDEEditorWithConfig,
+ "description": EasyMDEEditor,
+ "provided_support": EasyMDEEditor,
}
def __init__(self, *args, **kwargs):
@@ -353,8 +353,8 @@ class Meta:
"bénéficier en priorité aux publics résidant en Quartier Prioritaire de la Ville.",
}
widgets = {
- "description": EasyMDEEditorWithConfig,
- "profile_description": EasyMDEEditorWithConfig,
+ "description": EasyMDEEditor,
+ "profile_description": EasyMDEEditor,
}
def __init__(self, current_company: Company, *args, **kwargs):
diff --git a/itou/www/prescribers_views/forms.py b/itou/www/prescribers_views/forms.py
index 42e5a26ee68..ab7a6a879c6 100644
--- a/itou/www/prescribers_views/forms.py
+++ b/itou/www/prescribers_views/forms.py
@@ -2,7 +2,7 @@
from itou.prescribers.enums import PrescriberOrganizationKind
from itou.prescribers.models import PrescriberOrganization
-from itou.utils.widgets import EasyMDEEditorWithConfig
+from itou.utils.widgets import EasyMDEEditor
class EditPrescriberOrganizationForm(forms.ModelForm):
@@ -56,7 +56,7 @@ def __init__(self, *args, **kwargs):
for field in self.fields.values():
field.disabled = True
else:
- self.fields["description"].widget = EasyMDEEditorWithConfig()
+ self.fields["description"].widget = EasyMDEEditor()
def clean_siret(self):
siret = self.cleaned_data["siret"]
diff --git a/requirements/base.in b/requirements/base.in
index de6ade37f0c..2c0414034d3 100644
--- a/requirements/base.in
+++ b/requirements/base.in
@@ -54,9 +54,6 @@ django-redis # https://github.com/jazzband/django-redis
# django-markdownify (to render only a set of HTML tags)
django-markdownify # https://github.com/erwinmatijsen/django-markdownify
-# Markdown editor
-django-easymde # https://github.com/WPI-LNL/django-easymde
-
# Pillow (image manipulation)
pillow # https://python-pillow.org/
diff --git a/requirements/base.txt b/requirements/base.txt
index 7e4bc260b46..71b33e07b8f 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -327,10 +327,6 @@ django-datadog-logger==0.7.3 \
--hash=sha256:4361bb068a4b188fa14135398f9b747728464a291757e6adf8c95c9215dcd602 \
--hash=sha256:87838cd868f407e050831c536413de6b2ece31433b28c952c0fd90be1d66486a
# via -r requirements/base.in
-django-easymde==1.0.4 \
- --hash=sha256:0690902bde591461138e174e47f58363f1f7b7fb637ebae7401e7a6449177e26 \
- --hash=sha256:5b2fd94953b76cb69aebd5d6169056084188e079609bee1300174ad54cfa346a
- # via -r requirements/base.in
django-filter==24.3 \
--hash=sha256:c4852822928ce17fb699bcfccd644b3574f1a2d80aeb2b4ff4f16b02dd49dc64 \
--hash=sha256:d8ccaf6732afd21ca0542f6733b11591030fa98669f8d15599b358e24a2cd9c3
@@ -1187,10 +1183,6 @@ sentry-sdk==2.19.0 \
--hash=sha256:7b0b3b709dee051337244a09a30dbf6e95afe0d34a1f8b430d45e0982a7c125b \
--hash=sha256:ee4a4d2ae8bfe3cac012dcf3e4607975904c137e1738116549fc3dbbb6ff0e36
# via -r requirements/base.in
-setuptools==75.6.0 \
- --hash=sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6 \
- --hash=sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d
- # via django-easymde
six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
diff --git a/requirements/dev.txt b/requirements/dev.txt
index 9eeb4b990a2..d93ea00bb76 100644
--- a/requirements/dev.txt
+++ b/requirements/dev.txt
@@ -389,10 +389,6 @@ django-debug-toolbar==4.4.6 \
--hash=sha256:36e421cb908c2f0675e07f9f41e3d1d8618dc386392ec82d23bcfcd5d29c7044 \
--hash=sha256:3beb671c9ec44ffb817fad2780667f172bd1c067dbcabad6268ce39a81335f45
# via -r requirements/dev.in
-django-easymde==1.0.4 \
- --hash=sha256:0690902bde591461138e174e47f58363f1f7b7fb637ebae7401e7a6449177e26 \
- --hash=sha256:5b2fd94953b76cb69aebd5d6169056084188e079609bee1300174ad54cfa346a
- # via -r requirements/test.txt
django-extensions==3.2.3 \
--hash=sha256:44d27919d04e23b3f40231c4ab7af4e61ce832ef46d610cc650d53e68328410a \
--hash=sha256:9600b7562f79a92cbf1fde6403c04fee314608fefbb595502e34383ae8203401
@@ -1608,12 +1604,6 @@ sentry-sdk==2.19.0 \
--hash=sha256:7b0b3b709dee051337244a09a30dbf6e95afe0d34a1f8b430d45e0982a7c125b \
--hash=sha256:ee4a4d2ae8bfe3cac012dcf3e4607975904c137e1738116549fc3dbbb6ff0e36
# via -r requirements/test.txt
-setuptools==75.6.0 \
- --hash=sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6 \
- --hash=sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d
- # via
- # -r requirements/test.txt
- # django-easymde
shellcheck-py==0.10.0.1 \
--hash=sha256:390826b340b8c19173922b0da5ef7b66ef34d4d087dc48aad3e01f7e77e164d9 \
--hash=sha256:48f08965cafbb3363b265c4ef40628ffced19cb6fc7c4bb5ce72d32cbcfb4bb9 \
diff --git a/requirements/test.txt b/requirements/test.txt
index 661207d514e..e5162b85f0f 100644
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -359,10 +359,6 @@ django-datadog-logger==0.7.3 \
--hash=sha256:4361bb068a4b188fa14135398f9b747728464a291757e6adf8c95c9215dcd602 \
--hash=sha256:87838cd868f407e050831c536413de6b2ece31433b28c952c0fd90be1d66486a
# via -r requirements/base.txt
-django-easymde==1.0.4 \
- --hash=sha256:0690902bde591461138e174e47f58363f1f7b7fb637ebae7401e7a6449177e26 \
- --hash=sha256:5b2fd94953b76cb69aebd5d6169056084188e079609bee1300174ad54cfa346a
- # via -r requirements/base.txt
django-filter==24.3 \
--hash=sha256:c4852822928ce17fb699bcfccd644b3574f1a2d80aeb2b4ff4f16b02dd49dc64 \
--hash=sha256:d8ccaf6732afd21ca0542f6733b11591030fa98669f8d15599b358e24a2cd9c3
@@ -1491,12 +1487,6 @@ sentry-sdk==2.19.0 \
--hash=sha256:7b0b3b709dee051337244a09a30dbf6e95afe0d34a1f8b430d45e0982a7c125b \
--hash=sha256:ee4a4d2ae8bfe3cac012dcf3e4607975904c137e1738116549fc3dbbb6ff0e36
# via -r requirements/base.txt
-setuptools==75.6.0 \
- --hash=sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6 \
- --hash=sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d
- # via
- # -r requirements/base.txt
- # django-easymde
shellcheck-py==0.10.0.1 \
--hash=sha256:390826b340b8c19173922b0da5ef7b66ef34d4d087dc48aad3e01f7e77e164d9 \
--hash=sha256:48f08965cafbb3363b265c4ef40628ffced19cb6fc7c4bb5ce72d32cbcfb4bb9 \
diff --git a/tests/utils/test_widgets.py b/tests/utils/test_widgets.py
new file mode 100644
index 00000000000..a2ee5c04d62
--- /dev/null
+++ b/tests/utils/test_widgets.py
@@ -0,0 +1,36 @@
+from django import forms
+from pytest_django.asserts import assertHTMLEqual
+
+from itou.utils.widgets import EasyMDEEditor
+
+
+class TestEasyMDEEditor:
+ def test_basic(self):
+ class MyForm(forms.Form):
+ description = forms.CharField(widget=EasyMDEEditor)
+
+ form = MyForm()
+ assertHTMLEqual(
+ str(form),
+ """
+
+
+
+ """,
+ )
+
+ def test_custom_class(self):
+ class MyForm(forms.Form):
+ description = forms.CharField(widget=EasyMDEEditor(attrs={"class": "foo"}))
+
+ form = MyForm()
+ assertHTMLEqual(
+ str(form),
+ """
+
+
+
+ """,
+ )