geminer/geminer.py

187 lines
6.0 KiB
Python
Raw Normal View History

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-02 17:16:29 +01:00
md_path = os.path.expanduser(config.md_dir)
gmi_path = os.path.expanduser(config.gmi_dir)
tpl_path = os.path.expanduser(config.tpl_dir)
2020-12-03 20:24:20 +01:00
meta_path = os.path.expanduser(config.meta_dir)
2020-12-04 09:27:29 +01:00
# Initiate meta lists
posts = []
2020-12-04 20:21:34 +01:00
posts_prop_index = {}
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
os.chdir(md_path)
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
return link + ".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-05 08:52:18 +01:00
for dirname, subdirlist, mdlist in os.walk("."):
2020-12-03 09:01:30 +01:00
# Create same hierarchy in GMI directory
2020-12-05 08:52:18 +01:00
gmi_subpath = os.path.abspath(gmi_path + "/" + dirname)
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)
extension = extension[1:]
2020-12-04 08:26:23 +01:00
2020-12-04 09:27:29 +01:00
post = {}
gmifile = basename
if config.gmi_extension:
gmifile += ".gmi"
# We need the relative path without the "./"
simpledirname = dirname[2:]
if simpledirname == "":
post["path"] = gmifile
else:
2020-12-05 08:52:18 +01:00
post["path"] = simpledirname + "/" + gmifile
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-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
# 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-05 08:52:18 +01:00
gmitext = template.render(content=gmitext, meta=post)
2020-12-03 09:01:30 +01:00
# Dirty fix a weird bug where some lines are CRLF-terminated
2020-12-05 08:52:18 +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-02 17:16:29 +01:00
gmi.write(gmitext)
2020-12-03 20:24:20 +01:00
2020-12-03 22:07:38 +01:00
# Generate home page
2020-12-05 08:52:18 +01:00
with open(tpl_path + "/index.tpl", "r") as tpl:
2020-12-03 20:24:20 +01:00
template = Template(tpl.read())
2020-12-04 09:27:29 +01:00
text = template.render(posts=posts)
2020-12-05 08:52:18 +01:00
with open(meta_path + "/index.gmi", "w") as gmi:
2020-12-04 08:26:23 +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-05 08:52:18 +01:00
with open(meta_path + "/" + prop_dict["index_name"] + ".gmi", "w") as gmi:
2020-12-04 20:21:34 +01:00
gmi.write(text)
2020-12-05 08:52:18 +01:00
os.makedirs(meta_path + "/" + prop_dict.get("item_dir", prop), exist_ok=True)
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(
meta_path + "/" + prop_dict.get("item_dir", prop) + "/" + item + ".gmi", "w"
) as gmi:
2020-12-04 20:21:34 +01:00
gmi.write(text)
2020-12-04 08:26:23 +01:00
# Generate posts list page
2020-12-05 08:52:18 +01:00
with open(tpl_path + "/posts_list.tpl", "r") as tpl:
2020-12-03 22:07:38 +01:00
template = Template(tpl.read())
2020-12-04 09:27:29 +01:00
text = template.render(posts=posts)
2020-12-05 08:52:18 +01:00
with open(meta_path + "/posts.gmi", "w") as gmi:
2020-12-04 08:26:23 +01:00
gmi.write(text)