Scripts to translate Pelican content to Zola content.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

222 lines
7.3 KiB

#!/usr/bin/python3.8
# (requires python3.8)
import sys
import os
import toml
from datetime import date
STATIC_PREFIX = "/PELICAN" # to replace {static}
INTERNAL_PREFIX = {
"{filename}../pages/": "/wiki/", # wiki pages
"{filename}/pages/": "/wiki/",
"{filename}201": "/blog/201", # article pages
"{attach}/": "/PELICAN/",
"{attach}installer": ".",
}
# zola only uses absolute links, so relative break
OTHER_LINKS = {
"{filename}contribuer/": "@/wiki/contribuer/",
"{filename}chapitre": "@/wiki/contribuer/blockchain-nodejs/tutoriel-dev/chapitre",
"{filename}monnaie-libre-g1": "@/wiki/monnaie-libre-g1",
"{filename}modules": "@/wiki/forger-des-blocs/modules",
"{filename}duniter-est-il-energivore": "@/wiki/duniter-est-il-energivore",
"{filename}credits": "@/wiki/credits",
"{filename}../toile-de-confiance": "@/wiki/toile-de-confiance",
"{filename}licence-g1": "@/wiki/monnaie-libre-g1/licence-g1",
"{filename}monnaies-libres.md": "@/wiki/monnaies-libres/_index.md",
"{filename}../monnaie-libre-g1": "@/wiki/monnaie-libre-g1",
"{filename}../contribuer": "@/wiki/contribuer",
"{filename}../blockchain-rust": "@/wiki/contribuer/blockchain-rust",
"{filename}faq-tdc": "@/wiki/toile-de-confiance/faq-tdc",
"{filename}certifier-de-nouveaux-membres": "@/wiki/toile-de-confiance/certifier-de-nouveaux-membres",
"{filename}installer.md": "@/wiki/forger-des-blocs/installer/index.md",
"{filename}lancement-au-boot": "@/wiki/forger-des-blocs/lancement-au-boot",
"{filename}commandes.md": "@/wiki/forger-des-blocs/commandes.md",
"{filename}liste-modules.md": "@/wiki/forger-des-blocs/liste-modules.md",
"{filename}cles-partagees.md": "@/wiki/forger-des-blocs/cles-partagees.md",
"{filename}blockchain-rust": "@/wiki/contribuer/blockchain-rust",
"{filename}tutoriel-dev.md": "@/wiki/contribuer/blockchain-nodejs/tutoriel-dev/_index.md",
"{filename}toile-de-confiance": "@/wiki/toile-de-confiance",
"{filename}blockchain-nodejs": "@/wiki/contribuer/blockchain-nodejs",
"{filename}financements.md": "@/wiki/financements.md",
"tutoriel-dev.md": "tutoriel-dev/_index.md",
"{filename}tutoriel-dev/chapitre": "@/wiki/contribuer/blockchain-nodejs/tutoriel-dev/chapitre",
"{filename}wiki.md": "@/wiki/_index.md",
"{filename}fonctionnement": "@/wiki/fonctionnement",
"{filename}blockchain.md": "@/wiki/blockchain.md",
"{filename}miner-des-blocs": "@/wiki/forger-des-blocs",
"installer.md": "installer/index.md",
"{filename}monnaies-libres": "@/wiki/monnaies-libres",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
# "{filename}": "@/",
"{filename}": "@/",
}
ADD_TITLE = True
MAIN_HEAD = {
"Title": "title",
"Summary": "description",
}
TAXONOMIES_HEAD = {
"Author": "authors",
"Authors": "authors",
"Category": "category",
"Tags": "tags",
"BodyClass": "tags",
"Lang": "lang",
}
EXTRA_HEAD = {
"Thumbnail": "thumbnail",
}
IGNORED_HEAD = ["Status", "Breadcrumb", "location", "save_as", "URL", "name", "BodyId"]
CUSTOM_CONTENT_REPLACE = {
'<img src="../images/': '<img src="/PELICAN/images/',
"<center>": '<span class="center-content">', # fix for website migration
"</center>": "</span>",
}
class UnknownKey(Exception):
pass
def split_head_content(text):
sp = text.split("\n\n", maxsplit=1)
return (sp[0], sp[1])
def parse_head(head):
lines = head.split("\n")
head = {}
for line in lines:
parts = line.split(":", maxsplit=1)
key = parts[0]
value = parts[1].strip()
head.update({key: value})
return head
def parse_as_list(value):
values = value.split(",")
for (i,v) in enumerate(values):
values[i] = v.strip()
return values
def convert_head(head):
new_head = {}
while len(head):
(k,v) = head.popitem()
if k in MAIN_HEAD.keys():
new_head[MAIN_HEAD[k]] = v
elif k == "Date":
new_head["date"] = date.fromisoformat(v)
elif k == "Modified":
new_head["updated"] = date.fromisoformat(v)
elif k == "Order":
new_head["weight"] = int(v)
elif k == "Slug":
if "aliases" not in new_head.keys():
new_head["aliases"] = []
new_head["aliases"].append(v)
elif k in EXTRA_HEAD.keys():
if k == "Thumbnail":
if v.startswith("/"): # absolute path
v = os.path.join(STATIC_PREFIX, "." + v)
else: # relative path
v = os.path.join(STATIC_PREFIX, v)
v = os.path.normpath(v) # normalize path
if not "extra" in new_head.keys():
new_head["extra"] = {}
new_head["extra"][EXTRA_HEAD[k]] = v
elif k in TAXONOMIES_HEAD.keys():
if not "taxonomies" in new_head.keys(): # no taxonomies yet
new_head["taxonomies"] = {}
if not TAXONOMIES_HEAD[k] in new_head["taxonomies"]: # not this key yet
new_head["taxonomies"][TAXONOMIES_HEAD[k]] = []
v = parse_as_list(v)
new_head["taxonomies"][TAXONOMIES_HEAD[k]].extend(v)
elif k in IGNORED_HEAD:
if k == "Status" and v == "draft":
new_head["draft"] = True
else:
print(f"ignored key {k}")
else:
raise UnknownKey(k)
return new_head
def replace_internal_links(content):
for (prefix, replacement) in INTERNAL_PREFIX.items():
content = content.replace(prefix, replacement)
return content
def replace_other_links(content):
for (link, replacement) in OTHER_LINKS.items():
content = content.replace(link, replacement)
return content
def replace_static_media(content):
content = content.replace("{static}", STATIC_PREFIX)
return content
def replace_custom(content):
for (k,v) in CUSTOM_CONTENT_REPLACE.items():
content = content.replace(k, v)
return content
def translate_head(head):
head = parse_head(head)
head = convert_head(head)
return head
def translate_content(content):
content = replace_internal_links(content)
content = replace_other_links(content)
content = replace_static_media(content)
content = replace_custom(content)
return content
def translate(source):
head, content = split_head_content(source)
head = translate_head(head)
content = translate_content(content)
if ADD_TITLE:
content = "# " + head["title"] + "\n\n" + content
return f"""+++
{toml.dumps(head)}+++
{content}
"""
def write_translated(source_file, dest_file):
source_fid = open(source_file)
source = source_fid.read()
dest_fid = open(dest_file, "w")
transformed = translate(source) # translate from Pelican to Zola
dest_fid.write(transformed)
source_fid.close()
dest_fid.close()
if __name__ == "__main__":
source_file = sys.argv[1]
dest_file = sys.argv[2]
write_translated(source_file, dest_file)