diff --git a/core/templates/core/doku_to_markdown.jinja b/core/templates/core/doku_to_markdown.jinja new file mode 100644 index 00000000..ede16ee5 --- /dev/null +++ b/core/templates/core/doku_to_markdown.jinja @@ -0,0 +1,27 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Doku to Markdown{% endtrans %} +{% endblock %} + +{% block content %} +
+ {% csrf_token %} + +

+
+
+
{% trans %}Markdown{% endtrans %}
+
{{- text_md -}}
+
+
+
{% trans %}Render{% endtrans %}
+
+{{ text_md|markdown }} +
+{% endblock %} + + + diff --git a/core/templates/core/user_tools.jinja b/core/templates/core/user_tools.jinja index c406a040..878d5759 100644 --- a/core/templates/core/user_tools.jinja +++ b/core/templates/core/user_tools.jinja @@ -108,6 +108,7 @@

{% trans %}Other tools{% endtrans %}

diff --git a/core/urls.py b/core/urls.py index 1b9133f0..b5541dea 100644 --- a/core/urls.py +++ b/core/urls.py @@ -28,6 +28,7 @@ from core.views import * urlpatterns = [ url(r'^$', index, name='index'), + url(r'^doku_to_markdown$', DokuToMarkdownView.as_view(), name='doku_to_markdown'), url(r'^notifications$', NotificationList.as_view(), name='notification_list'), url(r'^notification/(?P[0-9]+)$', notification, name='notification'), diff --git a/core/utils.py b/core/utils.py index cfc9c3eb..970ba9e0 100644 --- a/core/utils.py +++ b/core/utils.py @@ -22,6 +22,8 @@ # # +import re + # Image utils from io import BytesIO @@ -62,3 +64,69 @@ def exif_auto_rotate(image): image=image.rotate(90, expand=True) return image + +def doku_to_markdown(text): + text = re.sub(r'([^:]|^)\/\/(.*?)\/\/', r'*\2*', text) # Italic (prevents protocol:// conflict) + text = re.sub(r'(.*?)<\/del>', r'~~\1~~', text, flags=re.DOTALL) # Strike (may be multiline) + text = re.sub(r'(.*?)<\/sup>', r'^\1^', text) # Superscript (multiline not supported, because almost never used) + text = re.sub(r'(.*?)<\/sub>', r'_\1_', text) # Subscript (idem) + + text = re.sub(r'^======(.*?)======', r'#\1', text, flags=re.MULTILINE) # Titles + text = re.sub(r'^=====(.*?)=====', r'##\1', text, flags=re.MULTILINE) + text = re.sub(r'^====(.*?)====', r'###\1', text, flags=re.MULTILINE) + text = re.sub(r'^===(.*?)===', r'####\1', text, flags=re.MULTILINE) + text = re.sub(r'^==(.*?)==', r'#####\1', text, flags=re.MULTILINE) + text = re.sub(r'^=(.*?)=', r'######\1', text, flags=re.MULTILINE) + + text = re.sub(r'', r'', text) + text = re.sub(r'', r'', text) + text = re.sub(r'', r'```\n', text) + text = re.sub(r'', r'\n```', text) + text = re.sub(r'article://', r'page://', text) + text = re.sub(r'dfile://', r'file://', text) + + i = 1 + for fn in re.findall(r'\(\((.*?)\)\)', text): # Footnotes + text = re.sub(r'\(\((.*?)\)\)', r'[^%s]' % i, text, count=1) + text += "\n[^%s]: %s\n" % (i, fn) + i += 1 + + text = re.sub(r'\\{2,}[\s]', r' \n', text) # Carriage return + + text = re.sub(r'\[\[(.*?)(\|(.*?))?\]\]', r'[\3](\1)', text) # Links + text = re.sub(r'{{(.*?)(\|(.*?))?}}', r'![\3](\1 "\3")', text) # Images + text = re.sub(r'{\[(.*?)(\|(.*?))?\]}', r'[\1](\1)', text) # Video (transform to classic links, since we can't integrate them) + + text = re.sub(r'###(\d*?)###', r'[[[\1]]]', text) # Progress bar + + text = re.sub(r'(\n +[^* -][^\n]*(\n +[^* -][^\n]*)*)', r'```\1\n```', text, flags=re.DOTALL) # Block code without lists + + text = re.sub(r'( +)-(.*)', r'1.\2', text) # Ordered lists + + new_text = [] + quote_level = 0 + for line in text.splitlines(): # Tables and quotes + enter = re.finditer(r'\[quote(=(.+?))?\]', line) + quit = re.finditer(r'\[/quote\]', line) + if re.search(r'\A\s*\^(([^\^]*?)\^)*', line): # Table part + line = line.replace('^', '|') + new_text.append("> " * quote_level + line) + new_text.append("> " * quote_level + "|---|") # Don't keep the text alignement in tables it's really too complex for what it's worth + elif enter or quit: # Quote part + for quote in enter: # Enter quotes (support multiple at a time) + quote_level += 1 + try: + new_text.append("> " * quote_level + "##### " + quote.group(2)) + line = line.replace(quote.group(0), '') + except: + new_text.append("> " * quote_level) + final_quote_level = quote_level # Store quote_level to use at the end, since it will be modified during quit iteration + for quote in quit: # Quit quotes (support multiple at a time) + line = line.replace(quote.group(0), '') + quote_level -= 1 + new_text.append("> " * final_quote_level + line) # Finally append the line + else: + new_text.append(line) + + return "\n".join(new_text) + diff --git a/core/views/site.py b/core/views/site.py index 9d3081d4..f0f99096 100644 --- a/core/views/site.py +++ b/core/views/site.py @@ -28,7 +28,7 @@ from django.http import JsonResponse from django.core import serializers from django.db.models import Q from django.contrib.auth.decorators import login_required -from django.views.generic import ListView +from django.views.generic import ListView, TemplateView import os import json @@ -37,6 +37,7 @@ from itertools import chain from haystack.query import SearchQuerySet from core.models import User, Notification +from core.utils import doku_to_markdown from club.models import Club def index(request, context=None): @@ -97,3 +98,22 @@ def search_json(request): } return JsonResponse(result) +class DokuToMarkdownView(TemplateView): + template_name = "core/doku_to_markdown.jinja" + + def post(self, request, *args, **kwargs): + self.text = request.POST['text'] + self.text_md = doku_to_markdown(self.text) + context = self.get_context_data(**kwargs) + return self.render_to_response(context) + + def get_context_data(self, **kwargs): + kwargs = super(DokuToMarkdownView, self).get_context_data(**kwargs) + try: + kwargs['text'] = self.text + kwargs['text_md'] = self.text_md + except: + kwargs['text'] = "" + kwargs['text_md'] = "" + return kwargs + diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index d5606a87..315cc8c0 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-05-13 18:31+0200\n" +"POT-Creation-Date: 2017-05-14 03:16+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -1973,6 +1973,22 @@ msgstr "Confirmation" msgid "Cancel" msgstr "Annuler" +#: core/templates/core/doku_to_markdown.jinja:4 +msgid "Doku to Markdown" +msgstr "Doku vers Markdown" + +#: core/templates/core/doku_to_markdown.jinja:13 +msgid "Convert" +msgstr "Convertir" + +#: core/templates/core/doku_to_markdown.jinja:16 +msgid "Markdown" +msgstr "Markdown" + +#: core/templates/core/doku_to_markdown.jinja:20 +msgid "Render" +msgstr "Rendu" + #: core/templates/core/edit.jinja:5 core/templates/core/edit.jinja.py:13 #: core/templates/core/file_edit.jinja:4 #: counter/templates/counter/cash_register_summary.jinja:4 @@ -2678,6 +2694,10 @@ msgid "Other tools" msgstr "Autres outils" #: core/templates/core/user_tools.jinja:111 +msgid "Convert dokuwiki syntax to Markdown" +msgstr "Convertir de la syntaxe dokuwiki vers Markdown" + +#: core/templates/core/user_tools.jinja:112 msgid "Trombi tools" msgstr "Outils Trombi"