diff --git a/core/markdown.py b/core/markdown.py index 42726a74..8146ca54 100644 --- a/core/markdown.py +++ b/core/markdown.py @@ -12,161 +12,125 @@ # OR WITHIN THE LOCAL FILE "LICENSE" # # +from __future__ import annotations import os import re +from typing import TYPE_CHECKING +import mistune from django.urls import reverse -from mistune import InlineGrammar, InlineLexer, Markdown, Renderer, escape, escape_link +from mistune import HTMLRenderer, Markdown + +if TYPE_CHECKING: + from mistune import InlineParser, InlineState + +# match __text__, without linebreak in the text, nor backslash prepending an underscore +# Examples : +# - "__text__" : OK +# - "__te xt__" : OK +# - "__te_xt__" : nope (underscore in the middle) +# - "__te\_xt__" : Ok (the middle underscore is escaped) +# - "__te\nxt__" : nope (there is a linebreak in the text) +# - "\__text__" : nope (one of the underscores have a backslash prepended) +# - "\\__text__" : Ok (the backslash is ignored, because there is another backslash before) +UNDERLINED_RE = ( + r"(?([^\\_]|\\.)+)" # the actual text + r"_{2}" # closing underscores +) + +SITH_LINK_RE = ( + r"\[(?P[\w\s]+)\]" # [nom du lien] + r"\(page:\/\/" # (page:// + r"(?P[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])" # actual page name + r"\)" # ) +) + +CUSTOM_DIMENSIONS_IMAGE_RE = ( + r"\[(?P[\w\s]+)\]" # [nom du lien] + r"\(img:\/\/" # (img:// + r"(?P[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])" # actual page name + r"\)" # ) +) -class SithRenderer(Renderer): - def file_link(self, pk, suffix): - return reverse("core:file_detail", kwargs={"file_id": pk}) + suffix - - def exposant(self, text): - return """%s""" % text - - def indice(self, text): - return """%s""" % text - - def underline(self, text): - return """%s""" % text - - def image(self, original_src, title, text): - """Rendering a image with title and text. - :param src: source link of the image. - :param title: title text of the image. - :param text: alt text of the image. - """ - style = None - if "?" in original_src: - src, params = original_src.rsplit("?", maxsplit=1) - m = re.search(r"(\d+%?)(x(\d+%?))?", params) - if not m: - src = original_src - else: - width = m.group(1) - if not width.endswith("%"): - width += "px" - style = "width: %s; " % width - height = m.group(3) - if height is not None: - if not height.endswith("%"): - height += "px" - style += "height: %s; " % height - else: - params = None - src = original_src - src = escape_link(src) - text = escape(text, quote=True) - if title: - title = escape(title, quote=True) - html = '%s" % html - return "%s>" % html +def parse_underline(_inline: InlineParser, m: re.Match, state: InlineState): + state.append_token({"type": "underline", "raw": m.group("underlined")}) + return m.end() -class SithInlineGrammar(InlineGrammar): - double_emphasis = re.compile(r"^\*{2}([\s\S]+?)\*{2}(?!\*)") # **word** - emphasis = re.compile(r"^\*((?:\*\*|[^\*])+?)\*(?!\*)") # *word* - underline = re.compile(r"^_{2}([\s\S]+?)_{2}(?!_)") # __word__ - exposant = re.compile(r"^([\s\S]+?)") # text - indice = re.compile(r"^([\s\S]+?)") # text - - -class SithInlineLexer(InlineLexer): - grammar_class = SithInlineGrammar - - default_rules = [ - "escape", - # 'inline_html', - "autolink", - "url", - "footnote", - "link", - "reflink", - "nolink", - "exposant", - "double_emphasis", - "emphasis", +def underline(md_instance: Markdown): + md_instance.inline.register( "underline", - "indice", - "code", - "linebreak", + UNDERLINED_RE, + parse_underline, + before="emphasis", + ) + md_instance.renderer.register("underline", lambda _, text: f"{text}") + + +def parse_sith_link(_inline: InlineParser, m: re.Match, state: InlineState): + page_name = m.group("page_name") + page_slug = m.group("page_slug") + state.append_token( + { + "type": "link", + "children": [{"type": "text", "raw": page_name}], + "attrs": {"url": reverse("core:page", kwargs={"page_name": page_slug})}, + } + ) + return m.end() + + +def sith_link(md_instance: Markdown): + md_instance.inline.register( + "sith_link", + SITH_LINK_RE, + parse_sith_link, + before="emphasis", + ) + # no custom renderer here. + # we just add another parsing rule, but render it as if it was + # a regular markdown link + + +class SithRenderer(HTMLRenderer): + def image(self, text: str, url: str, title=None) -> str: + if "?" not in url: + return super().image(text, url, title) + + new_url, params = url.rsplit("?", maxsplit=1) + m = re.match(r"^(?P\d+(%|px)?)(x(?P\d+(%|px)?))?$", params) + if not m: + return super().image(text, url, title) + + width, height = m.group("width"), m.group("height") + if not width.endswith(("%", "px")): + width += "px" + style = f"width:{width};" + if height is not None: + if not height.endswith(("%", "px")): + height += "px" + style += f"height:{height};" + return super().image(text, new_url, title).replace("/>", f'style="{style}" />') + + +markdown = mistune.create_markdown( + renderer=SithRenderer(escape=True), + plugins=[ + underline, + sith_link, "strikethrough", - "text", - ] - inline_html_rules = [ - "escape", - "autolink", + "footnotes", + "table", + "spoiler", + "subscript", + "superscript", "url", - "link", - "reflink", - "nolink", - "exposant", - "double_emphasis", - "emphasis", - "underline", - "indice", - "code", - "linebreak", - "strikethrough", - "text", - ] - - def output_underline(self, m): - text = m.group(1) - return self.renderer.underline(text) - - def output_exposant(self, m): - text = m.group(1) - return self.renderer.exposant(text) - - def output_indice(self, m): - text = m.group(1) - return self.renderer.indice(text) - - # Double emphasis rule changed - def output_double_emphasis(self, m): - text = m.group(1) - text = self.output(text) - return self.renderer.double_emphasis(text) - - # Emphasis rule changed - def output_emphasis(self, m): - text = m.group(1) - text = self.output(text) - return self.renderer.emphasis(text) - - def _process_link(self, m, link, title=None): - try: # Add page:// support for links - page = re.compile(r"^page://(\S*)") # page://nom_de_ma_page - match = page.search(link) - page = match.group(1) or "" - link = reverse("core:page", kwargs={"page_name": page}) - except: - pass - try: # Add file:// support for links - file_link = re.compile(r"^file://(\d*)/?(\S*)?") # file://4000/download - match = file_link.search(link) - pk = match.group(1) - suffix = match.group(2) or "" - link = reverse("core:file_detail", kwargs={"file_id": id}) + suffix - except: - pass - return super()._process_link(m, link, title) - - -renderer = SithRenderer(escape=True) -inline = SithInlineLexer(renderer) - -markdown = Markdown(renderer, inline=inline) + ], +) if __name__ == "__main__": root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/core/tests.py b/core/tests.py index bb78f4b6..b476c588 100644 --- a/core/tests.py +++ b/core/tests.py @@ -13,8 +13,8 @@ # # -import os from datetime import date, timedelta +from pathlib import Path import freezegun import pytest @@ -22,7 +22,7 @@ from django.core.cache import cache from django.test import TestCase from django.urls import reverse from django.utils.timezone import now -from pytest_django.asserts import assertRedirects +from pytest_django.asserts import assertInHTML, assertRedirects from club.models import Membership from core.markdown import markdown @@ -108,12 +108,51 @@ class TestUserLogin: assertRedirects(response, reverse("core:index")) +@pytest.mark.parametrize( + ("md", "html"), + [ + ( + "[nom du lien](page://nomDeLaPage)", + 'nom du lien', + ), + ("__texte__", "texte"), + ("~~***__texte__***~~", "texte"), + ( + '![tst_alt](/img.png?50% "tst_title")', + 'tst_alt', + ), + ( + "[texte](page://tst-page)", + 'texte', + ), + ( + "![](/img.png?50x450)", + '', + ), + ("![](/img.png)", ''), + ( + "![](/img.png?50%x120%)", + '', + ), + ("![](/img.png?50px)", ''), + ( + "![](/img.png?50pxx120%)", + '', + ), + # when the image dimension has a wrong format, don't touch the url + ("![](/img.png?50pxxxxxxxx)", ''), + ("![](/img.png?azerty)", ''), + ], +) +def test_custom_markdown_syntax(md, html): + """Test the homemade markdown syntax""" + assert markdown(md) == f"

{html}

\n" + + def test_full_markdown_syntax(): - root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - with open(os.path.join(root_path) + "/doc/SYNTAX.md", "r") as md_file: - md = md_file.read() - with open(os.path.join(root_path) + "/doc/SYNTAX.html", "r") as html_file: - html = html_file.read() + doc_path = Path(settings.BASE_DIR) / "doc" + md = (doc_path / "SYNTAX.md").read_text() + html = (doc_path / "SYNTAX.html").read_text() result = markdown(md) assert result == html @@ -218,12 +257,15 @@ http://git.an ) response = self.client.get(reverse("core:page", kwargs={"page_name": "guy"})) assert response.status_code == 200 - assert ( - '

Guy bibou

\\n

http://git.an

\\n' - + "

Swag

\\n<guy>Bibou</guy>" - + "<script>alert(\\'Guy\\');</script>" - in str(response.content) - ) + print(response.content.decode()) + expected = """ +

Guy bibou

+

http://git.an

+

Swag

+

<guy>Bibou</guy>

+

<script>alert('Guy');</script>

+ """ + assertInHTML(expected, response.content.decode()) class UserToolsTest: diff --git a/doc/SYNTAX.html b/doc/SYNTAX.html index 9db2aca3..7b41e07c 100644 --- a/doc/SYNTAX.html +++ b/doc/SYNTAX.html @@ -1,29 +1,22 @@

Cette page vise à documenter la syntaxe Markdown utilisée sur le site.

Markdown-AE Documentation

Le Markdown le plus standard se trouve documenté ici: -https://daringfireball.net/projects/markdown/syntax .
+https://www.markdownguide.org/basic-syntax.
Si cette page n'est pas exhaustive vis à vis de la syntaxe du site AE, elle a au moins le mérite de bien documenter le Markdown original.

-

Le réel parseur du site AE est une version tunée de mistune.
+

Le réel parseur du site AE est une version tunée de mistune.
Les plus aventureux pourront aller lire ses tests -afin d'en connaître la syntaxe le plus finement possible.
+afin d'en connaître la syntaxe le plus finement possible.
En pratique, cette page devrait déjà résumer une bonne partie.

Basique

    -
  • Mettre le texte en gras : **texte**

    -
  • -
  • Mettre le texte en italique : *texte*

    -
  • -
  • Souligner le texte : __texte__

    -
  • -
  • Barrer du texte : ~~texte~~

    -
  • -
  • On peut bien sûr tout combiner : ~~***__texte__***~~

    -
  • -
  • Mettre du texte en exposant : <sup>texte</sup>

    -
  • -
  • Mettre du texte en indice : <sub>texte</sub>

    -
  • +
  • Mettre le texte en gras : **texte**
  • +
  • Mettre le texte en italique : *texte*
  • +
  • Souligner le texte : __texte__
  • +
  • Barrer du texte : ~~texte~~
  • +
  • On peut bien sûr tout combiner : ~~***__texte__***~~
  • +
  • Mettre du texte^en exposant^ : <sup>texte</sup>
  • +
  • Mettre du texte~en indice~ : <sub>texte</sub>

Liens

    @@ -43,7 +36,7 @@ l'adresse complète d'une page : [nom du lien](page://nomDeLaPage)<
  • On peut également utiliser une image pour les liens : [nom du lien]![images/imageDuSiteAE.png](/chemin/vers/image.png titre optionnel)(options)
-

[nom du lien]images/imageDuSiteAE.png(options)

+

[nom du lien]![images/imageDuSiteAE.png](/chemin/vers/image.png titre optionnel)(options)

Titres

  • Plusieurs niveaux de titres sont possibles
  • @@ -56,17 +49,12 @@ etc...

    Titre de niveau 1

    Titre de niveau 2

    Titre de niveau 3

    -

    Si le titre de votre section commence par un tilde (~) alors le texte sous la section est -affiché par défaut caché et il est consultable grace à un bouton +/-

    -

    ~Test

    Paragraphes et sauts de ligne

    Un nouveau paragraphe se fait avec deux retours à la ligne.

    Un saut de ligne se force avec au moins deux espaces en fin de ligne.

    Listes

    Il est possible de créer des listes :

    -
      -
    • ordonnées :
    • -
    +

    ordonnées :

    1. élément
     2. élément
     3. élément
    @@ -86,12 +74,10 @@ affiché par défaut caché et il est consultable grace à un bouton +/-

  • élément
  • élément
  • -
      -
    • non ordonnées :
    • -
    -
     * élément
    - * élément
    - * élément
    +

    non ordonnées :

    +
    - élément
    +- élément
    +- élément
     
    • élément
    • @@ -106,22 +92,23 @@ affiché par défaut caché et il est consultable grace à un bouton +/-

      | test | test | test |
    - - - - + + + + + - - - + + + - - - + + +
    TitreTitre2Titre3
    TitreTitre2Titre3
    testtesttesttesttesttest
    testtesttesttesttesttest
    @@ -131,76 +118,70 @@ affiché par défaut caché et il est consultable grace à un bouton +/-

    | gauche | centre | droite |
    - - - - + + + + + - - - + + +
    TitreTitre2Titre3
    TitreTitre2Titre3
    gauchecentredroitegauchecentredroite

    Images et contenus

    -

    Une image est insérée ainsi : ![texte alternatif](/chemin/vers/image.png "titre optionnel") -texte alternatif

    -

    On peut lui spécifier ses dimensions de plusieurs manières:

    -
    ![image à 50%](/static/core/img/logo.png?50% "Image à 50%")
    -![image de  350 pixels de large](/static/core/img/logo.png?350 "Image de 350 pixels")
    -![image de 350x100 pixels](/static/core/img/logo.png?350x100 "Image de 350x100 pixels")
    +

    Une image est insérée ainsi : ![texte alternatif](/chemin/vers/image.png "titre optionnel") +texte alternatif

    +

    On peut lui spécifier ses dimensions de plusieurs manières :

    +
    ![image à 50%](/static/core/img/logo.png?50% "Image à 50%")
    +![image de 350 pixels de large](/static/core/img/logo.png?350 "Image de 350 pixels")
    +![image de 350x100 pixels](/static/core/img/logo.png?350x100 "Image de 350x100 pixels")
     
    -

    image à 50%
    +

    image à 50%
    Image à 50% de la largeur de la page.

    -

    image de 350 pixels de large
    +

    image de 350 pixels de large
    Image de 350 pixels de large.

    -

    image de 350x100 pixels
    +

    image de 350x100 pixels
    Image de 350x100 pixels.

    -

    ( devrait pouvoir détecter si vidéo ou non )

    +

    (devrait pouvoir détecter si vidéo ou non)

    Blocs de citations

    Un bloc de citation se crée ainsi :

    > Ceci est
     > un bloc de
     > citation
     
    -

    Ceci est +

    +

    Ceci est un bloc de citation

    Il est possible d'intégrer de la syntaxe Markdown-AE dans un tel bloc.

    Note de bas de page

    -

    On les créer comme ça1:

    -

    échapper des caractères

    +

    On les crée comme ça1:

    +
    Je fais une note[^clef].
    +
    +[^clef]: je note ensuite où je veux le contenu de ma clef qui apparaîtra quand même en bas
    +
    +

    Vous pouvez aussi utiliser des numéros pour nommer vos clefs.

    +
    Note plus complexe[^1]
    +
    +[^1]:
    +    je peux même faire des blocs
    +    sur plusieurs lignes, comme d'habitude!
    +
    +

    Échapper des caractères

    • Il est possible d'ignorer un caractère spécial en l'échappant à l'aide d'un \
    • L'échappement de blocs de codes complet se fera à l'aide de balises <nosyntax></nosyntax>
    -

    Autres ( hérité de l'ancien wiki )

    -
      -
    • Une ligne peut être crée avec une ligne contenant 4 tirets ( - ).
    • -
    • Une barre de progression est crée ainsi :

      [[[70]]]

      -
      -
    • -
    • Notes en pied de page :

      ((note))

      -
      -
    • -
    -
    -
    -
    1. ceci est le contenu de ma clef

      -
      Je fais une note[^clef].
      -
      -[^clef]: je note ensuite ou je veux le contenu de ma clef qui apparaîtra quand même en bas
      -
      -

      Vous pouvez utiliser des numéros pour nommer vos clef si vous avez la flemme.

      -
      Note plus complexe[^1]
      -
      -[^1]:
      -    je peux même faire des blocks   
      -    sur plusieurs lignes, comme d'habitude!
      -

    2. +

      Autres (hérité de l'ancien wiki)

      +

      Une ligne peut être créée avec une ligne contenant 4 tirets (----).

      +
      +
        +
      1. ceci est le contenu de ma clef

      -
    + diff --git a/doc/SYNTAX.md b/doc/SYNTAX.md index 0515f05c..dc1badf4 100644 --- a/doc/SYNTAX.md +++ b/doc/SYNTAX.md @@ -3,7 +3,7 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site. # Markdown-AE Documentation Le Markdown le plus standard se trouve documenté ici: -https://daringfireball.net/projects/markdown/syntax . +https://www.markdownguide.org/basic-syntax. Si cette page n'est pas exhaustive vis à vis de la syntaxe du site AE, elle a au moins le mérite de bien documenter le Markdown original. @@ -14,37 +14,31 @@ En pratique, cette page devrait déjà résumer une bonne partie. ## Basique -* Mettre le texte en **gras** : `**texte**` - -* Mettre le texte en *italique* : `*texte*` - -* __Souligner__ le texte : `__texte__` - -* ~~Barrer du texte~~ : `~~texte~~` - -* On peut bien sûr tout ~~***__combiner__***~~ : `~~***__texte__***~~` - -* Mettre du texte en exposant : `texte` - -* Mettre du texte en indice : `texte` +- Mettre le texte en **gras** : `**texte**` +- Mettre le texte en *italique* : `*texte*` +- __Souligner__ le texte : `__texte__` +- ~~Barrer du texte~~ : `~~texte~~` +- On peut bien sûr tout ~~***__combiner__***~~ : `~~***__texte__***~~` +- Mettre du texte^en exposant^ : `texte` +- Mettre du texte~en indice~ : `texte` ## Liens -* Les liens simples sont détectés automatiquement : `http://www.site.com` +- Les liens simples sont détectés automatiquement : `http://www.site.com` http://www.site.com -* Il est possible de nommer son lien : `[nom du lien](http://www.site.com)` +- Il est possible de nommer son lien : `[nom du lien](http://www.site.com)` [nom du lien](http://www.site.com) -* Les liens peuvent être internes au site de l'AE, on peut dès lors éviter d'entrer +- Les liens peuvent être internes au site de l'AE, on peut dès lors éviter d'entrer l'adresse complète d'une page : `[nom du lien](page://nomDeLaPage)` [nom du lien](page://nomDeLaPage) -* On peut également utiliser une image pour les liens : +- On peut également utiliser une image pour les liens : `[nom du lien]![images/imageDuSiteAE.png](/chemin/vers/image.png titre optionnel)(options)` [nom du lien]![images/imageDuSiteAE.png](/chemin/vers/image.png titre optionnel)(options) @@ -53,7 +47,7 @@ l'adresse complète d'une page : `[nom du lien](page://nomDeLaPage)` ## Titres -* Plusieurs niveaux de titres sont possibles +- Plusieurs niveaux de titres sont possibles ``` # Titre de niveau 1 @@ -65,11 +59,6 @@ etc... ## Titre de niveau 2 ### Titre de niveau 3 -Si le titre de votre section commence par un tilde (~) alors le texte sous la section est -affiché par défaut caché et il est consultable grace à un bouton +/- - -## ~Test - ## Paragraphes et sauts de ligne Un nouveau paragraphe se fait avec deux retours à la ligne. @@ -81,7 +70,7 @@ Un saut de ligne se force avec au moins deux espaces en fin de ligne. Il est possible de créer des listes : -* ordonnées : +### ordonnées : ``` 1. élément @@ -104,16 +93,16 @@ Vous pouvez marquer plus simplement comme suit, les numéros se faisant tout seu 1. élément -* non ordonnées : +### non ordonnées : ``` - * élément - * élément - * élément +- élément +- élément +- élément ``` -* élément -* élément -* élément +- élément +- élément +- élément ## Tableaux @@ -148,11 +137,11 @@ L'alignement dans les cellules est géré comme suit, avec les ':' sur la ligne Une image est insérée ainsi : `![texte alternatif](/chemin/vers/image.png "titre optionnel")` ![texte alternatif](/static/core/img/logo.png "titre optionnel") -On peut lui spécifier ses dimensions de plusieurs manières: +On peut lui spécifier ses dimensions de plusieurs manières : ``` ![image à 50%](/static/core/img/logo.png?50% "Image à 50%") -![image de 350 pixels de large](/static/core/img/logo.png?350 "Image de 350 pixels") +![image de 350 pixels de large](/static/core/img/logo.png?350 "Image de 350 pixels") ![image de 350x100 pixels](/static/core/img/logo.png?350x100 "Image de 350x100 pixels") ``` @@ -166,7 +155,7 @@ Image de 350 pixels de large. ![image de 350x100 pixels](/static/core/img/logo.png?350x100 "Image de 350x100 pixels") Image de 350x100 pixels. -( devrait pouvoir détecter si vidéo ou non ) +(devrait pouvoir détecter si vidéo ou non) ## Blocs de citations @@ -185,39 +174,29 @@ Il est possible d'intégrer de la syntaxe Markdown-AE dans un tel bloc. ## Note de bas de page -On les créer comme ça[^key]: +On les crée comme ça[^key]: [^key]: ceci est le contenu de ma clef - ``` - Je fais une note[^clef]. +``` +Je fais une note[^clef]. - [^clef]: je note ensuite ou je veux le contenu de ma clef qui apparaîtra quand même en bas - ``` - Vous pouvez utiliser des numéros pour nommer vos clef si vous avez la flemme. - - ``` - Note plus complexe[^1] +[^clef]: je note ensuite où je veux le contenu de ma clef qui apparaîtra quand même en bas +``` +Vous pouvez aussi utiliser des numéros pour nommer vos clefs. - [^1]: - je peux même faire des blocks - sur plusieurs lignes, comme d'habitude! +``` +Note plus complexe[^1] - ``` +[^1]: + je peux même faire des blocs + sur plusieurs lignes, comme d'habitude! +``` -## échapper des caractères - -* Il est possible d'ignorer un caractère spécial en l'échappant à l'aide d'un \ -* L'échappement de blocs de codes complet se fera à l'aide de balises - - - -## Autres ( hérité de l'ancien wiki ) - -* Une ligne peut être crée avec une ligne contenant 4 tirets ( - ). -* Une barre de progression est crée ainsi : -> [[[70]]] -* Notes en pied de page : -> ((note)) +## Échapper des caractères +- Il est possible d'ignorer un caractère spécial en l'échappant à l'aide d'un \ +- L'échappement de blocs de codes complet se fera à l'aide de balises +## Autres (hérité de l'ancien wiki) +Une ligne peut être créée avec une ligne contenant 4 tirets (`----`). diff --git a/poetry.lock b/poetry.lock index 32fcaf72..1595f01a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -888,13 +888,13 @@ traitlets = "*" [[package]] name = "mistune" -version = "0.8.4" -description = "The fastest markdown parser in pure Python" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "mistune-0.8.4-py2.py3-none-any.whl", hash = "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4"}, - {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] [[package]] @@ -1865,5 +1865,5 @@ filelock = ">=3.4" [metadata] lock-version = "2.0" -python-versions = "^3.10,<3.12" -content-hash = "c33378496709848054a8e4ecd1ebf74df12f15a1bb66ab61d2958e6a3c40f812" +python-versions = "^3.10" +content-hash = "e01f649e4ed95bc01a4a72a3ea90dc13a83e6e21d6e77d84b7adcdb2ca68dec8" diff --git a/pyproject.toml b/pyproject.toml index 07f823dd..f73fec34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,10 +20,10 @@ homepage = "https://ae.utbm.fr/" license = "GPL-3.0-only" [tool.poetry.dependencies] -python = "^3.10,<3.12" # Version is held back by mistune +python = "^3.10" Django = "^4.2.13" Pillow = "^10.4.0" -mistune = "^0.8.4" +mistune = "^3.0.2" django-jinja = "^2.11" cryptography = "^42.0.8" pytz = "^2021.1"