From 3c2dcfbfa20023ffd13dec528a6c90b3a361b465 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Mon, 1 Jul 2024 17:33:05 +0200 Subject: [PATCH 1/4] update mistune --- core/markdown.py | 250 ++++++++++++++++++++--------------------------- core/tests.py | 68 ++++++++++--- doc/SYNTAX.html | 151 +++++++++++++--------------- doc/SYNTAX.md | 103 ++++++++----------- poetry.lock | 14 +-- pyproject.toml | 4 +- 6 files changed, 278 insertions(+), 312 deletions(-) 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" From 02ec3607b2c5c9339801f1013c46f1e1c1df3d13 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Mon, 8 Jul 2024 15:02:05 +0200 Subject: [PATCH 2/4] fix install_xapian.sh --- core/management/commands/install_xapian.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/management/commands/install_xapian.sh b/core/management/commands/install_xapian.sh index ae183f6e..908a53f7 100755 --- a/core/management/commands/install_xapian.sh +++ b/core/management/commands/install_xapian.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Originates from https://gist.github.com/jorgecarleitao/ab6246c86c936b9c55fd # first argument of the script is Xapian version (e.g. 1.2.19) -VERSION=$1 +VERSION="$1" # Cleanup env vars for auto discovery mechanism export CPATH= From 30948f1701587c1de7b766190519cc295579255a Mon Sep 17 00:00:00 2001 From: thomas girod Date: Mon, 8 Jul 2024 15:04:11 +0200 Subject: [PATCH 3/4] better style for rendered markdown --- core/static/core/markdown.scss | 75 ++++++++++++++++++++++++++++++++++ core/static/core/style.scss | 61 +++++---------------------- core/templates/core/base.jinja | 1 + 3 files changed, 87 insertions(+), 50 deletions(-) create mode 100644 core/static/core/markdown.scss diff --git a/core/static/core/markdown.scss b/core/static/core/markdown.scss new file mode 100644 index 00000000..e9772d64 --- /dev/null +++ b/core/static/core/markdown.scss @@ -0,0 +1,75 @@ +.markdown { + --bg-lightgrey: rgb(240, 241, 245); + --border-lightgrey: rgb(215, 216, 220); + + h1, + h2, + h3, + h4, + h5, + h6 { + padding-top: 20px; + } + + ul, + ol, + p { + line-height: 22px; + } + + code { + overflow: auto; + max-width: 100%; + font-family: Consolas; + font-size: 14px; + border-radius: 4px; + border: 1px solid var(--border-lightgrey); + background-color: var(--bg-lightgrey); + padding: 1px 2px; + } + + pre code { + // code that is not inlined + margin: 15px; + padding: 10px; + display: block; + border-radius: 5px; + font-size: 1em; + + @media screen and (max-width: 500px) { + margin: 10px 0; + } + } + + blockquote { + background-color: var(--bg-lightgrey); + border: unset; + border-left: 5px solid #ccc; + border-radius: 4px; + margin: 15px; + padding: 10px 15px; + display: block; + width: fit-content; + + p:first-of-type { + margin-top: 0; + } + + @media screen and (max-width: 500px) { + margin: 10px 0; + padding: 8px 10px; + } + } + + table { + width: auto; + min-width: 30%; + } + + a:hover { + text-decoration: underline; + } + .footnotes { + font-size: 85%; + } +} diff --git a/core/static/core/style.scss b/core/static/core/style.scss index 9ba72e7d..c5de097b 100644 --- a/core/static/core/style.scss +++ b/core/static/core/style.scss @@ -357,7 +357,7 @@ a:not(.button) { @media (max-width: 800px) { flex-direction: column; } - + .news_column { display: inline-block; margin: 0; @@ -947,22 +947,6 @@ dt { margin-top: 25px; } -code { - font-family: monospace; - overflow: auto; - max-width: 100%; -} - -blockquote { - margin: 5px; - padding: 2px; - border: solid 1px $black-color; -} - -blockquote h5:first-child { - font-size: 100%; -} - .edit-bar { display: block; margin: 4px; @@ -979,17 +963,18 @@ blockquote h5:first-child { } table { - width: 100%; + width: 90%; margin: 15px auto; border-collapse: collapse; border-spacing: 0; border-radius: 5px; -moz-border-radius: 5px; overflow: hidden; - box-shadow: rgba(60, 64, 67, .3) 0 1px 3px 0, rgba(60, 64, 67, .15) 0 4px 8px 3px; + box-shadow: rgba(60, 64, 67, 0.3) 0 1px 3px 0, + rgba(60, 64, 67, 0.15) 0 4px 8px 3px; } -@media screen and (max-width: 500px){ +@media screen and (max-width: 500px) { table { width: 100%; } @@ -999,7 +984,8 @@ th { padding: 4px; } -td, th { +td, +th { vertical-align: middle; text-align: center; padding: 5px 10px; @@ -1009,7 +995,6 @@ td, th { } td { - padding: 4px; margin: 5px; border-collapse: collapse; vertical-align: top; @@ -1020,7 +1005,8 @@ td { } } -th, thead td { +th, +thead td { text-align: center; border-top: none; } @@ -1421,7 +1407,7 @@ footer { > .version { margin-top: 3px; - color: rgba(0, 0, 0, .3) + color: rgba(0, 0, 0, 0.3); } } @@ -1485,31 +1471,6 @@ label { } } -/*-------------------------------MARKDOWN------------------------------*/ - -.markdown { - margin: 0; - padding: 0; - code { - font-family: monospace; - color: $white-color; - background: $black-color; - display: inline-block; - padding: 4px; - line-height: 120%; - vertical-align: middle; - } - a { - color: $primary-dark-color; - } - a:hover { - text-decoration: underline; - } - .footnotes { - font-size: 85%; - } -} - /*--------------------------------JQuery-------------------------------*/ .ui-state-active, @@ -2045,4 +2006,4 @@ $pedagogy-white-text: #f0f0f0; } } } -} \ No newline at end of file +} diff --git a/core/templates/core/base.jinja b/core/templates/core/base.jinja index c45d30e0..2cdccfdf 100644 --- a/core/templates/core/base.jinja +++ b/core/templates/core/base.jinja @@ -9,6 +9,7 @@ + From 7f6c4f623697c7838013c6d66c3cf5b8f1e48ca8 Mon Sep 17 00:00:00 2001 From: thomas girod Date: Mon, 8 Jul 2024 17:04:18 +0200 Subject: [PATCH 4/4] change sup and sub in mde editor --- core/templates/core/markdown_textarea.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/templates/core/markdown_textarea.jinja b/core/templates/core/markdown_textarea.jinja index 5d769011..c33a45a0 100644 --- a/core/templates/core/markdown_textarea.jinja +++ b/core/templates/core/markdown_textarea.jinja @@ -74,7 +74,7 @@ name: "superscript", action: function customFunction(editor){ let cm = editor.codemirror; - cm.replaceSelection('' + cm.getSelection() + ''); + cm.replaceSelection('^' + cm.getSelection() + '^'); }, className: "fa fa-superscript", title: "{{ translations.superscript }}" @@ -83,7 +83,7 @@ name: "subscript", action: function customFunction(editor){ let cm = editor.codemirror; - cm.replaceSelection('' + cm.getSelection() + ''); + cm.replaceSelection('~' + cm.getSelection() + '~'); }, className: "fa fa-subscript", title: "{{ translations.subscript }}"