2020-12-02 17:16:29 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
from md2gemini import md2gemini
|
|
|
|
import frontmatter
|
2020-12-04 13:38:35 +01:00
|
|
|
from slugify import slugify
|
2020-12-02 17:16:29 +01:00
|
|
|
from jinja2 import Template
|
|
|
|
import os
|
2020-12-03 11:35:13 +01:00
|
|
|
import locale
|
2020-12-03 20:24:20 +01:00
|
|
|
from datetime import datetime
|
2020-12-02 17:16:29 +01:00
|
|
|
|
|
|
|
import config
|
|
|
|
|
2020-12-03 11:35:13 +01:00
|
|
|
# locale (for templates, for example dates rendering)
|
2020-12-03 16:35:08 +01:00
|
|
|
locale.setlocale(locale.LC_ALL, config.locale)
|
2020-12-03 11:35:13 +01:00
|
|
|
|
2020-12-07 16:24:33 +01:00
|
|
|
md_path = os.path.abspath(os.path.expanduser(config.md_path))
|
2020-12-07 16:31:17 +01:00
|
|
|
gmi_path = os.path.abspath(os.path.expanduser(config.gmi_path))
|
2020-12-07 16:24:33 +01:00
|
|
|
tpl_path = os.path.abspath(os.path.expanduser(config.tpl_path))
|
|
|
|
|
|
|
|
posts_path = os.path.abspath(gmi_path + "/" + config.posts_dir)
|
2020-12-03 20:24:20 +01:00
|
|
|
|
2020-12-04 09:27:29 +01:00
|
|
|
# Initiate meta lists
|
2020-12-07 16:24:33 +01:00
|
|
|
posts = [] # This is a flat, unsorted list of posts
|
|
|
|
posts_prop_index = {} # This is a dict containing posts sorted by properties
|
|
|
|
|
2020-12-04 21:22:40 +01:00
|
|
|
for prop_dict in config.index_props:
|
|
|
|
posts_prop_index[prop_dict["property"]] = {}
|
2020-12-02 17:16:29 +01:00
|
|
|
|
2020-12-05 08:52:18 +01:00
|
|
|
|
2020-12-03 16:37:48 +01:00
|
|
|
def add_ext_gmi(link):
|
2020-12-03 18:36:35 +01:00
|
|
|
# Custom function to apply to links
|
2020-12-05 08:52:18 +01:00
|
|
|
if "://" not in link: # apply only on local links
|
2020-12-07 16:24:33 +01:00
|
|
|
return os.path.splitext(link)[0] + ".gmi"
|
2020-12-03 18:46:43 +01:00
|
|
|
else:
|
|
|
|
return link
|
2020-12-03 16:37:48 +01:00
|
|
|
|
2020-12-05 08:52:18 +01:00
|
|
|
|
2020-12-03 09:01:30 +01:00
|
|
|
# Walk through markdown directories
|
2020-12-07 16:24:33 +01:00
|
|
|
for dirname, subdirlist, mdlist in os.walk(md_path):
|
2020-12-05 08:52:18 +01:00
|
|
|
|
2020-12-03 09:01:30 +01:00
|
|
|
# Create same hierarchy in GMI directory
|
2020-12-07 16:24:33 +01:00
|
|
|
gmi_subpath = os.path.abspath(posts_path + "/" + os.path.relpath(dirname, md_path))
|
2020-12-02 17:16:29 +01:00
|
|
|
os.makedirs(gmi_subpath, exist_ok=True)
|
2020-12-03 09:01:30 +01:00
|
|
|
|
2020-12-02 17:16:29 +01:00
|
|
|
for mdfile in mdlist:
|
|
|
|
basename, extension = os.path.splitext(mdfile)
|
2020-12-04 09:27:29 +01:00
|
|
|
|
2020-12-03 09:01:30 +01:00
|
|
|
# We want to ignore the file if this isn't a markdown file
|
2020-12-02 17:16:29 +01:00
|
|
|
if extension not in config.md_extensions:
|
2020-12-05 08:52:18 +01:00
|
|
|
print(
|
|
|
|
'Ignoring file {}: "{}" not in markdown extensions list'.format(
|
|
|
|
mdfile, extension
|
|
|
|
)
|
|
|
|
)
|
2020-12-02 17:16:29 +01:00
|
|
|
pass
|
2020-12-05 08:52:18 +01:00
|
|
|
|
2020-12-07 16:24:33 +01:00
|
|
|
post = {}
|
|
|
|
|
2020-12-08 16:55:04 +01:00
|
|
|
gmifile = basename + config.gmi_extension
|
2020-12-07 16:24:33 +01:00
|
|
|
|
2020-12-08 18:30:48 +01:00
|
|
|
post["path"] = config.posts_dir + "/" + os.path.relpath(dirname + "/" + gmifile, md_path)
|
2020-12-07 16:24:33 +01:00
|
|
|
|
2020-12-03 09:01:30 +01:00
|
|
|
# Read the Markdown file
|
2020-12-05 08:52:18 +01:00
|
|
|
with open(dirname + "/" + mdfile, "r") as md:
|
2020-12-02 17:16:29 +01:00
|
|
|
mdtext = md.read()
|
2020-12-05 08:52:18 +01:00
|
|
|
|
2020-12-03 09:01:30 +01:00
|
|
|
# Parse the YAML header
|
2020-12-02 17:16:29 +01:00
|
|
|
meta = frontmatter.parse(mdtext)[0]
|
2020-12-05 08:52:18 +01:00
|
|
|
|
2020-12-04 17:19:34 +01:00
|
|
|
# Extract template
|
|
|
|
post["template"] = meta.get("template", config.default_post_template)
|
|
|
|
|
2020-12-04 17:07:57 +01:00
|
|
|
# Extract post properties
|
|
|
|
for prop in config.post_props:
|
|
|
|
post[prop] = meta.get(prop, None)
|
|
|
|
|
|
|
|
# Extract index properties
|
|
|
|
for prop_dict in config.index_props:
|
|
|
|
prop = prop_dict["property"]
|
2020-12-04 22:05:02 +01:00
|
|
|
prop_raw = meta.get(prop, None)
|
2020-12-04 22:14:14 +01:00
|
|
|
if prop_dict.get("list", False) and prop_raw:
|
2020-12-05 08:52:18 +01:00
|
|
|
post[prop] = [
|
|
|
|
{"name": word, "slug": slugify(word)}
|
|
|
|
for word in prop_raw.split(",")
|
|
|
|
]
|
2020-12-04 20:21:34 +01:00
|
|
|
for item in post[prop]:
|
2020-12-04 22:05:02 +01:00
|
|
|
slug = item["slug"]
|
2020-12-04 20:21:34 +01:00
|
|
|
if slug in posts_prop_index[prop]:
|
|
|
|
posts_prop_index[prop][slug]["posts"].append(post)
|
|
|
|
else:
|
2020-12-05 08:52:18 +01:00
|
|
|
posts_prop_index[prop][slug] = {
|
|
|
|
"name": item["name"],
|
|
|
|
"posts": [post],
|
|
|
|
}
|
2020-12-04 20:21:34 +01:00
|
|
|
else:
|
2020-12-04 22:15:15 +01:00
|
|
|
post[prop] = {"name": prop_raw, "slug": slugify(prop_raw)}
|
2020-12-04 22:05:02 +01:00
|
|
|
slug = post[prop]["slug"]
|
2020-12-04 20:21:34 +01:00
|
|
|
if slug in posts_prop_index[prop]:
|
|
|
|
posts_prop_index[prop][slug]["posts"].append(post)
|
|
|
|
else:
|
2020-12-05 08:52:18 +01:00
|
|
|
posts_prop_index[prop][slug] = {
|
|
|
|
"name": post[prop]["name"],
|
|
|
|
"posts": [post],
|
|
|
|
}
|
2020-12-04 20:21:34 +01:00
|
|
|
|
|
|
|
posts.append(post)
|
2020-12-04 17:07:57 +01:00
|
|
|
|
2020-12-04 20:21:34 +01:00
|
|
|
# For now, list properties must be comma-separated strings.
|
|
|
|
# TODO: make possible to list values as a YAML list
|
2020-12-03 20:24:20 +01:00
|
|
|
|
2020-12-04 09:27:29 +01:00
|
|
|
# Replace stuff
|
2020-12-02 17:16:29 +01:00
|
|
|
for item in config.replace:
|
2020-12-05 08:52:18 +01:00
|
|
|
mdtext = mdtext.replace(item[0], item[1])
|
2020-12-03 09:01:30 +01:00
|
|
|
|
|
|
|
# Convert the post into GMI
|
2020-12-05 08:52:18 +01:00
|
|
|
gmitext = md2gemini(
|
|
|
|
mdtext,
|
|
|
|
code_tag=config.code_tag,
|
|
|
|
img_tag=config.img_tag,
|
|
|
|
indent=config.indent,
|
|
|
|
ascii_table=config.ascii_table,
|
|
|
|
frontmatter=True,
|
|
|
|
links=config.links,
|
|
|
|
plain=config.plain,
|
|
|
|
strip_html=config.strip_html,
|
|
|
|
base_url=config.base_url,
|
|
|
|
link_func=add_ext_gmi,
|
|
|
|
table_tag=config.table_tag,
|
|
|
|
)
|
2020-12-03 09:01:30 +01:00
|
|
|
|
2020-12-06 15:23:48 +01:00
|
|
|
post["content"] = gmitext
|
|
|
|
|
2020-12-03 09:01:30 +01:00
|
|
|
# Read template file
|
2020-12-05 08:52:18 +01:00
|
|
|
with open(tpl_path + "/" + post["template"] + ".tpl", "r") as tpl:
|
2020-12-02 17:16:29 +01:00
|
|
|
template = Template(tpl.read())
|
2020-12-04 09:27:29 +01:00
|
|
|
|
2020-12-03 09:01:30 +01:00
|
|
|
# Integrate the GMI content in the template
|
2020-12-06 15:54:26 +01:00
|
|
|
gmitext = template.render(post=post)
|
2020-12-05 08:52:18 +01:00
|
|
|
|
2020-12-03 09:01:30 +01:00
|
|
|
# Dirty fix a weird bug where some lines are CRLF-terminated
|
2020-12-06 15:54:26 +01:00
|
|
|
gmitext = gmitext.replace("\r\n", "\n")
|
2020-12-03 21:17:21 +01:00
|
|
|
|
2020-12-04 09:27:29 +01:00
|
|
|
# Time to write the GMI file
|
2020-12-05 08:52:18 +01:00
|
|
|
with open(gmi_subpath + "/" + gmifile, "w") as gmi:
|
2020-12-06 15:54:26 +01:00
|
|
|
gmi.write(gmitext)
|
2020-12-03 20:24:20 +01:00
|
|
|
|
2020-12-08 16:43:56 +01:00
|
|
|
# Generate custom extra pages
|
2020-12-08 16:45:53 +01:00
|
|
|
for page_dict in config.custom_pages:
|
2020-12-08 16:43:56 +01:00
|
|
|
rel_path, filename = os.path.split(page_dict["name"])
|
2020-12-08 16:50:41 +01:00
|
|
|
if rel_path:
|
|
|
|
os.makedirs(rel_path, exist_ok=True)
|
2020-12-08 17:03:59 +01:00
|
|
|
basename, extension = os.path.splitext(filename)
|
2020-12-08 17:04:54 +01:00
|
|
|
if extension == "":
|
2020-12-08 17:03:59 +01:00
|
|
|
filename = basename + config.gmi_extension
|
|
|
|
else:
|
|
|
|
filename = basename + extension
|
2020-12-08 16:50:41 +01:00
|
|
|
filepath = os.path.join(rel_path, filename)
|
2020-12-08 16:56:42 +01:00
|
|
|
with open(tpl_path + "/" + page_dict.get("tpl", basename) + ".tpl", "r") as tpl:
|
2020-12-08 16:43:56 +01:00
|
|
|
template = Template(tpl.read())
|
2020-12-08 19:39:45 +01:00
|
|
|
template.globals['now'] = datetime.now
|
2020-12-08 16:43:56 +01:00
|
|
|
text = template.render(posts=posts)
|
2020-12-08 19:50:44 +01:00
|
|
|
text = text.replace("\r\n", "\n")
|
2020-12-08 17:06:25 +01:00
|
|
|
with open(gmi_path + "/" + filepath, "w") as gmi:
|
2020-12-08 16:43:56 +01:00
|
|
|
gmi.write(text)
|
2020-12-03 22:07:38 +01:00
|
|
|
|
2020-12-04 21:42:07 +01:00
|
|
|
# Generate custom meta pages
|
2020-12-04 20:21:34 +01:00
|
|
|
for prop_dict in config.index_props:
|
|
|
|
prop = prop_dict["property"]
|
|
|
|
if "index_name" in prop_dict:
|
2020-12-05 08:52:18 +01:00
|
|
|
with open(
|
|
|
|
tpl_path + "/" + prop_dict.get("index_tpl", prop) + ".tpl", "r"
|
|
|
|
) as tpl:
|
2020-12-04 20:21:34 +01:00
|
|
|
template = Template(tpl.read())
|
|
|
|
text = template.render(prop=posts_prop_index[prop])
|
2020-12-08 16:55:04 +01:00
|
|
|
with open(gmi_path + "/" + prop_dict["index_name"] + config.gmi_extension, "w") as gmi:
|
2020-12-04 20:21:34 +01:00
|
|
|
gmi.write(text)
|
2020-12-07 16:24:33 +01:00
|
|
|
os.makedirs(gmi_path + "/" + prop_dict.get("item_dir", prop), exist_ok=True)
|
2020-12-05 08:52:18 +01:00
|
|
|
with open(tpl_path + "/" + prop_dict.get("item_tpl", prop) + ".tpl", "r") as tpl:
|
2020-12-04 20:21:34 +01:00
|
|
|
template = Template(tpl.read())
|
|
|
|
for item in posts_prop_index[prop]:
|
|
|
|
text = template.render(prop_item=posts_prop_index[prop][item])
|
2020-12-05 08:52:18 +01:00
|
|
|
with open(
|
2020-12-08 16:55:04 +01:00
|
|
|
gmi_path + "/" + prop_dict.get("item_dir", prop) + "/" + item + config.gmi_extension, "w"
|
2020-12-05 08:52:18 +01:00
|
|
|
) as gmi:
|
2020-12-04 20:21:34 +01:00
|
|
|
gmi.write(text)
|