mirror of
https://github.com/ae-utbm/sith.git
synced 2026-06-19 14:32:41 +00:00
move from mistune to aemark for markdown
This commit is contained in:
+35
-36
@@ -2,12 +2,9 @@
|
||||
<h1>Markdown-AE Documentation</h1>
|
||||
<p>Le Markdown le plus standard se trouve documenté ici:
|
||||
<a href="https://www.markdownguide.org/basic-syntax">https://www.markdownguide.org/basic-syntax</a>.<br />
|
||||
Si cette page n'est pas exhaustive vis à vis de la syntaxe du site AE,
|
||||
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.</p>
|
||||
<p>Le réel parseur du site AE est une version tunée de <a href="https://github.com/lepture/mistune">mistune</a>.<br />
|
||||
Les plus aventureux pourront aller lire ses <a href="https://github.com/lepture/mistune/blob/master/tests/fixtures">tests</a>
|
||||
afin d'en connaître la syntaxe le plus finement possible.<br />
|
||||
En pratique, cette page devrait déjà résumer une bonne partie.</p>
|
||||
<p>Le réel parseur du site AE est une version tunée de <a href="https://github.com/kivikakk/comrak">comrak</a>.</p>
|
||||
<h2>Basique</h2>
|
||||
<ul>
|
||||
<li>Mettre le texte en <strong>gras</strong> : <code>**texte**</code></li>
|
||||
@@ -15,8 +12,8 @@ En pratique, cette page devrait déjà résumer une bonne partie.</p>
|
||||
<li><u>Souligner</u> le texte : <code>__texte__</code></li>
|
||||
<li><del>Barrer du texte</del> : <code>~~texte~~</code></li>
|
||||
<li>On peut bien sûr tout <del><em><strong><u>combiner</u></strong></em></del> : <code>~~***__texte__***~~</code></li>
|
||||
<li>Mettre du texte^en exposant^ : <code><sup>texte</sup></code></li>
|
||||
<li>Mettre du texte~en indice~ : <code><sub>texte</sub></code></li>
|
||||
<li>Mettre du texte<sup>en exposant</sup> : <code><sup>texte</sup></code></li>
|
||||
<li>Mettre du texte<sub>en indice</sub> : <code><sub>texte</sub></code></li>
|
||||
</ul>
|
||||
<h2>Liens</h2>
|
||||
<ul>
|
||||
@@ -28,10 +25,10 @@ En pratique, cette page devrait déjà résumer une bonne partie.</p>
|
||||
</ul>
|
||||
<p><a href="http://www.site.com">nom du lien</a></p>
|
||||
<ul>
|
||||
<li>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 : <code>[nom du lien](page://nomDeLaPage)</code></li>
|
||||
<li>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 : <code>[nom du lien](page://nomDeLaPage)</code></li>
|
||||
</ul>
|
||||
<p><a href="/page/nomDeLaPage/">nom du lien</a></p>
|
||||
<p><a href="/page/nomDeLaPage">nom du lien</a></p>
|
||||
<ul>
|
||||
<li>On peut également utiliser une image pour les liens :
|
||||
<code>[nom du lien](options)</code></li>
|
||||
@@ -94,25 +91,25 @@ etc...
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Titre</th>
|
||||
<th>Titre2</th>
|
||||
<th>Titre3</th>
|
||||
<th>Titre</th>
|
||||
<th>Titre2</th>
|
||||
<th>Titre3</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
<td>test</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>L'alignement dans les cellules est géré comme suit, avec les ':' sur la ligne en dessous du titre:</p>
|
||||
<p>L’alignement dans les cellules est géré comme suit, avec les ‘:’ sur la ligne en dessous du titre:</p>
|
||||
<pre><code>| Titre | Titre2 | Titre3 |
|
||||
|:-------|:------:|-------:|
|
||||
| gauche | centre | droite |
|
||||
@@ -120,16 +117,16 @@ etc...
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:left">Titre</th>
|
||||
<th style="text-align:center">Titre2</th>
|
||||
<th style="text-align:right">Titre3</th>
|
||||
<th align="left">Titre</th>
|
||||
<th align="center">Titre2</th>
|
||||
<th align="right">Titre3</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align:left">gauche</td>
|
||||
<td style="text-align:center">centre</td>
|
||||
<td style="text-align:right">droite</td>
|
||||
<td align="left">gauche</td>
|
||||
<td align="center">centre</td>
|
||||
<td align="right">droite</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -141,11 +138,11 @@ etc...
|
||||

|
||||

|
||||
</code></pre>
|
||||
<p><img src="/static/core/img/logo.png" alt="image à 50%" title="Image à 50%" style="width:50%;" /><br />
|
||||
<p><img src="/static/core/img/logo.png" style="width:50%" alt="image à 50%" title="Image à 50%" /><br />
|
||||
Image à 50% de la largeur de la page.</p>
|
||||
<p><img src="/static/core/img/logo.png" alt="image de 350 pixels de large" title="Image de 350 pixels" style="width:350px;" /><br />
|
||||
<p><img src="/static/core/img/logo.png" style="width:350px" alt="image de 350 pixels de large" title="Image de 350 pixels" /><br />
|
||||
Image de 350 pixels de large.</p>
|
||||
<p><img src="/static/core/img/logo.png" alt="image de 350x100 pixels" title="Image de 350x100 pixels" style="width:350px;height:100px;" /><br />
|
||||
<p><img src="/static/core/img/logo.png" style="width:350px;height:100px" alt="image de 350x100 pixels" title="Image de 350x100 pixels" /><br />
|
||||
Image de 350x100 pixels.</p>
|
||||
<p>(devrait pouvoir détecter si vidéo ou non)</p>
|
||||
<h2>Blocs de citations</h2>
|
||||
@@ -159,9 +156,9 @@ Image de 350x100 pixels.</p>
|
||||
un bloc de
|
||||
citation</p>
|
||||
</blockquote>
|
||||
<p>Il est possible d'intégrer de la syntaxe Markdown-AE dans un tel bloc.</p>
|
||||
<p>Il est possible d’intégrer de la syntaxe Markdown-AE dans un tel bloc.</p>
|
||||
<h2>Note de bas de page</h2>
|
||||
<p>On les crée comme ça<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup>:</p>
|
||||
<p>On les crée comme ça<sup class="footnote-ref"><a href="#fn-key" id="fnref-key" data-footnote-ref>1</a></sup>:</p>
|
||||
<pre><code>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
|
||||
@@ -175,13 +172,15 @@ citation</p>
|
||||
</code></pre>
|
||||
<h2>Échapper des caractères</h2>
|
||||
<ul>
|
||||
<li>Il est possible d'ignorer un caractère spécial en l'échappant à l'aide d'un \</li>
|
||||
<li>L'échappement de blocs de codes complet se fera à l'aide de balises <nosyntax></nosyntax></li>
|
||||
<li>Il est possible d’ignorer un caractère spécial en l’échappant à l’aide d’un \</li>
|
||||
<li>L’échappement de blocs de codes complet se fera à l’aide de balises <nosyntax></nosyntax></li>
|
||||
</ul>
|
||||
<h2>Autres (hérité de l'ancien wiki)</h2>
|
||||
<h2>Autres (hérité de l’ancien wiki)</h2>
|
||||
<p>Une ligne peut être créée avec une ligne contenant 4 tirets (<code>----</code>).</p>
|
||||
<section class="footnotes">
|
||||
<section class="footnotes" data-footnotes>
|
||||
<ol>
|
||||
<li id="fn-1"><p>ceci est le contenu de ma clef<a href="#fnref-1" class="footnote">↩</a></p></li>
|
||||
<li id="fn-key">
|
||||
<p>ceci est le contenu de ma clef <a href="#fnref-key" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
@@ -7,10 +7,7 @@ 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](https://github.com/lepture/mistune).
|
||||
Les plus aventureux pourront aller lire ses [tests](https://github.com/lepture/mistune/blob/master/tests/fixtures)
|
||||
afin d'en connaître la syntaxe le plus finement possible.
|
||||
En pratique, cette page devrait déjà résumer une bonne partie.
|
||||
Le réel parseur du site AE est une version tunée de [comrak](https://github.com/kivikakk/comrak).
|
||||
|
||||
## Basique
|
||||
|
||||
|
||||
@@ -22,11 +22,10 @@
|
||||
#
|
||||
|
||||
|
||||
from aemark import markdown
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from core.markdown import markdown
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Output the fully rendered SYNTAX.md file"
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
#
|
||||
# Copyright 2023 © AE UTBM
|
||||
# ae@utbm.fr / ae.info@utbm.fr
|
||||
#
|
||||
# This file is part of the website of the UTBM Student Association (AE UTBM),
|
||||
# https://ae.utbm.fr.
|
||||
#
|
||||
# You can find the source code of the website at https://github.com/ae-utbm/sith
|
||||
#
|
||||
# LICENSED UNDER THE GNU GENERAL PUBLIC LICENSE VERSION 3 (GPLv3)
|
||||
# SEE : https://raw.githubusercontent.com/ae-utbm/sith/master/LICENSE
|
||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||
#
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import mistune
|
||||
from django.urls import reverse
|
||||
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"(?<!\\)(?:\\{2})*" # ignore if there is an odd number of backslashes before
|
||||
r"_{2}" # two underscores
|
||||
r"(?P<underlined>([^\\_]|\\.)+)" # the actual text
|
||||
r"_{2}" # closing underscores
|
||||
)
|
||||
|
||||
SITH_LINK_RE = (
|
||||
r"\[(?P<page_name>[\w\s]+)\]" # [nom du lien]
|
||||
r"\(page:\/\/" # (page://
|
||||
r"(?P<page_slug>[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])" # actual page name
|
||||
r"\)" # )
|
||||
)
|
||||
|
||||
CUSTOM_DIMENSIONS_IMAGE_RE = (
|
||||
r"\[(?P<img_name>[\w\s]+)\]" # [nom du lien]
|
||||
r"\(img:\/\/" # (img://
|
||||
r"(?P<img_slug>[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])" # actual page name
|
||||
r"\)" # )
|
||||
)
|
||||
|
||||
|
||||
def parse_underline(_inline: InlineParser, m: re.Match, state: InlineState):
|
||||
state.append_token({"type": "underline", "raw": m.group("underlined")})
|
||||
return m.end()
|
||||
|
||||
|
||||
def underline(md_instance: Markdown):
|
||||
md_instance.inline.register(
|
||||
"underline",
|
||||
UNDERLINED_RE,
|
||||
parse_underline,
|
||||
before="emphasis",
|
||||
)
|
||||
md_instance.renderer.register("underline", lambda _, text: f"<u>{text}</u>")
|
||||
|
||||
|
||||
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<width>\d+(%|px)?)(x(?P<height>\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",
|
||||
"footnotes",
|
||||
"table",
|
||||
"spoiler",
|
||||
"subscript",
|
||||
"superscript",
|
||||
"url",
|
||||
],
|
||||
)
|
||||
@@ -25,14 +25,13 @@
|
||||
import datetime
|
||||
|
||||
import phonenumbers
|
||||
from aemark import markdown as md
|
||||
from django import template
|
||||
from django.forms import BoundField
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ngettext
|
||||
|
||||
from core.markdown import markdown as md
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
|
||||
+9
-12
@@ -18,6 +18,7 @@ from smtplib import SMTPException
|
||||
|
||||
import freezegun
|
||||
import pytest
|
||||
from aemark import markdown
|
||||
from bs4 import BeautifulSoup
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.contrib.auth.models import Permission
|
||||
@@ -34,7 +35,6 @@ from pytest_django.asserts import assertInHTML, assertRedirects
|
||||
from antispam.models import ToxicDomain
|
||||
from club.models import Club
|
||||
from core.baker_recipes import subscriber_user
|
||||
from core.markdown import markdown
|
||||
from core.models import AnonymousUser, Group, Page, User, validate_promo
|
||||
from core.utils import get_last_promo, get_semester_code, get_start_of_semester
|
||||
from core.views import AllowFragment
|
||||
@@ -200,31 +200,28 @@ class TestUserLogin:
|
||||
[
|
||||
(
|
||||
"[nom du lien](page://nomDeLaPage)",
|
||||
'<a href="/page/nomDeLaPage/">nom du lien</a>',
|
||||
'<a href="/page/nomDeLaPage">nom du lien</a>',
|
||||
),
|
||||
("__texte__", "<u>texte</u>"),
|
||||
("~~***__texte__***~~", "<del><em><strong><u>texte</u></strong></em></del>"),
|
||||
(
|
||||
'',
|
||||
'<img src="/img.png" alt="tst_alt" title="tst_title" style="width:50%;" />',
|
||||
),
|
||||
(
|
||||
"[texte](page://tst-page)",
|
||||
'<a href="/page/tst-page/">texte</a>',
|
||||
'<img src="/img.png" style="width:50%" alt="tst_alt" title="tst_title" />',
|
||||
),
|
||||
("[texte](page://tst-page)", '<a href="/page/tst-page">texte</a>'),
|
||||
(
|
||||
"",
|
||||
'<img src="/img.png" alt="" style="width:50px;height:450px;" />',
|
||||
'<img src="/img.png" style="width:50px;height:450px" alt="" />',
|
||||
),
|
||||
("", '<img src="/img.png" alt="" />'),
|
||||
(
|
||||
"",
|
||||
'<img src="/img.png" alt="" style="width:50%;height:120%;" />',
|
||||
'<img src="/img.png" style="width:50%;height:120%" alt="" />',
|
||||
),
|
||||
("", '<img src="/img.png" alt="" style="width:50px;" />'),
|
||||
("", '<img src="/img.png" style="width:50px" alt="" />'),
|
||||
(
|
||||
"",
|
||||
'<img src="/img.png" alt="" style="width:50px;height:120%;" />',
|
||||
'<img src="/img.png" style="width:50px;height:120%" alt="" />',
|
||||
),
|
||||
# when the image dimension has a wrong format, don't touch the url
|
||||
("", '<img src="/img.png?50pxxxxxxxx" alt="" />'),
|
||||
@@ -350,7 +347,7 @@ http://git.an
|
||||
<p><a href="http://git.an">http://git.an</a></p>
|
||||
<h1>Swag</h1>
|
||||
<p><guy>Bibou</guy></p>
|
||||
<p><script>alert('Guy');</script></p>
|
||||
<script>alert('Guy');</script>
|
||||
"""
|
||||
assertInHTML(expected, response.text)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from datetime import timedelta
|
||||
|
||||
import freezegun
|
||||
import pytest
|
||||
from aemark import markdown
|
||||
from bs4 import BeautifulSoup
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import Permission
|
||||
@@ -13,7 +14,6 @@ from pytest_django.asserts import assertHTMLEqual, assertRedirects
|
||||
|
||||
from club.models import Club, Membership
|
||||
from core.baker_recipes import board_user, subscriber_user
|
||||
from core.markdown import markdown
|
||||
from core.models import AnonymousUser, Page, PageRev, User
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user