summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ishtar_common/ishtar_utils/__init__.py0
-rwxr-xr-xishtar_common/ishtar_utils/spip_to_markdown.py146
2 files changed, 146 insertions, 0 deletions
diff --git a/ishtar_common/ishtar_utils/__init__.py b/ishtar_common/ishtar_utils/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ishtar_common/ishtar_utils/__init__.py
diff --git a/ishtar_common/ishtar_utils/spip_to_markdown.py b/ishtar_common/ishtar_utils/spip_to_markdown.py
new file mode 100755
index 000000000..20e71dabf
--- /dev/null
+++ b/ishtar_common/ishtar_utils/spip_to_markdown.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# Copyright (C) 2026 Étienne Loks <etienne.loks at iggdrasil dot net>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+import re
+import sys
+
+
+def int_to_superscript(s):
+ return ''.join(dict(zip("0123456789", "⁰¹²³⁴⁵⁶⁷⁸⁹")).get(c, c) for c in s)
+
+
+def convert_title(s):
+ r = re.compile(r"^{{{([^}]*)}}}")
+ return r.sub(r"### \1\n", s)
+
+
+def convert_bold(s):
+ r = re.compile(r"{{([^}]*)}}")
+ return r.sub(r"**\1**", s)
+
+
+def convert_italic(s):
+ r = re.compile(r"{([^}]*)}")
+ return r.sub(r"*\1*", s)
+
+
+def convert_list4(s):
+ r = re.compile(r"^\-\*\*\*\*")
+ return r.sub(r" -", s)
+
+
+def convert_list3(s):
+ r = re.compile(r"^\-\*\*\*")
+ return r.sub(r" -", s)
+
+
+def convert_list2(s):
+ r = re.compile(r"^\-\*\*")
+ return r.sub(r" -", s)
+
+
+def convert_list1(s):
+ r = re.compile(r"^\-\*")
+ return r.sub(r"-", s)
+
+
+def convert_list_num(s):
+ r = re.compile(r"^\-\#")
+ return r.sub(r"1.", s)
+
+
+def convert_link(s):
+ r = re.compile(r"\[([^-]*[^ ]+)[ ]*\->(.*)\]")
+ return r.sub(r"[\1](\2)", s)
+
+
+def convert_superscript(s):
+ r = re.compile(r"\[\[(\d+)\]\]")
+ return r.sub(lambda x: int_to_superscript(x.group(1)), s)
+
+
+def convert_quote(s):
+ r = re.compile(r"<quote>([^<]+)</quote>")
+ return r.sub(r"> \1\n", s)
+
+
+def spip_to_markdown(s):
+ # do not modify the modifiers order
+ modifiers = [convert_title, convert_bold, convert_italic,
+ convert_list4, convert_list3, convert_list2,
+ convert_list1, convert_list_num, convert_link,
+ convert_superscript, convert_quote]
+ res = []
+ for line in s.split("\n"):
+ for modifier in modifiers:
+ line = modifier(line)
+ res.append(line)
+ return "\n".join(res)
+
+
+TEST = """
+{{{Titre}}}
+{{{Titre32}}}
+{{Gras}} {{Gras 2}}
+{Italique}
+-* liste 1
+-** liste niveau2
+-*** liste niveau3
+-**** liste niveau4
+-# liste numerotée 1
+-# liste numerotée 2
+[Lien web ->https://ishtar-archeo.net/]
+élément[[12]] # exposant 12
+<quote>Citation</quote>
+"""
+
+RES = """
+### Titre
+
+### Titre32
+
+**Gras** **Gras 2**
+*Italique*
+- liste 1
+ - liste niveau2
+ - liste niveau3
+ - liste niveau4
+1. liste numerotée 1
+1. liste numerotée 2
+[Lien web](https://ishtar-archeo.net/)
+élément¹² # exposant 12
+> Citation
+
+"""
+
+
+if __name__ == '__main__':
+ # test
+ if len(sys.argv) < 2:
+ res = spip_to_markdown(TEST)
+ if res == RES:
+ sys.stdout.write("* Test OK\n")
+ else:
+ sys.stdout.write("* Test NOK\n")
+ sys.exit(0)
+ with open(sys.argv[1], "r") as s:
+ sys.stdout.write(spip_to_markdown(s))
+ sys.exit(0)
+
+