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 %}
@@ -92,8 +90,3 @@

{% 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 %}
@@ -78,8 +76,3 @@

{% 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), + """ +
+ +