#!/usr/bin/env python3
import re
import os
from lektor.project import Project
from dataclasses import dataclass
domain = "gemini://gemini.schubisu.de"
@dataclass
class Link:
number: int
url: str
name: str
description: str
def to_gemtext(self):
return f"=> {self.url} {self.name} {[self.description]}\n"
class Post:
link_pattern = re.compile(r"^\[link:(.*)\]: (.*)")
link_inline_pattern = re.compile(r".*?\[(.*?)\]\[link:(.*?)\].*?")
def __init__(self, post):
self.post = post
self.link_count = 0
self.links = []
self.gemtext = ""
def __repr__(self):
return f"<Post: {self.post['title']}>"
def make_link(self, url, name, description):
self.link_count += 1
link = Link(self.link_count, url, name, description)
self.links.append(link)
return link
def link_by_name(self, name):
links = [l for l in self.links if l.name == name]
assert len(links) == 1, f"duplicate or missing link name: {name}, {links}"
return links[0]
def link_by_number(self, number):
links = [l for l in self.links if l.number == number]
assert len(links) == 1
return links[0]
def make_header(self):
self.gemtext += f"# {self.post['title']}\n\n"
self.gemtext += f"published: {str(self.post['pub_date'])}\n"
self.gemtext += f"tags: {', '.join(self.post['tags'])}\n"
self.gemtext += "\n"
siblings = self.post.get_siblings()
if siblings.next_page:
link = self.make_link(self.post.url_to(siblings.next_page), "previous", siblings.next_page['title'])
self.gemtext += link.to_gemtext()
if siblings.prev_page:
link = self.make_link(self.post.url_to(siblings.prev_page), "next", siblings.prev_page['title'])
self.gemtext += link.to_gemtext()
link = self.make_link(self.post.url_to(self.post.parent), "parent directory", self.post.parent['title'])
self.gemtext += link.to_gemtext()
self.gemtext += "\n"
def make_body(self):
self.convert_links()
self.format_body()
def make_footer(self):
for link in self.links:
self.gemtext = self.gemtext.replace(
f"[link:{link.name}]: {link.url}\n",
""
)
# self.gemtext = Post.link_pattern.sub('', self.gemtext)
def post_to_gemtext(self):
self.make_header()
self.make_body()
self.make_footer()
def convert_links(self):
for line in (self.post['body'].source.split("\n")):
match = Post.link_pattern.match(line)
if match is not None:
self.make_link(match[2], match[1], "")
def format_body(self):
for paragraph in (self.post['body'].source.split("\n")):
gemparagraph = paragraph + "\n"
matches = Post.link_inline_pattern.findall(paragraph)
if len(matches) > 0:
gemparagraph += "\n"
for description, name in matches:
link = self.link_by_name(name)
link.description = description
gemparagraph += link.to_gemtext()
gemparagraph = gemparagraph.replace(
f"[{link.description}][link:{link.name}]",
f"{link.description}[{link.number}]"
)
self.gemtext += gemparagraph
def title_page(blog):
page = Post(blog)
page.gemtext += "# Schubisu's Gemlog\n\n"
page.gemtext += "For now this is just a crappy conversion of my markdown blog :)\n\n"
page.gemtext += "## Posts:\n\n"
for post in blog.children.order_by('pub_date').all()[::-1]:
link = page.make_link(blog.url_to(post), str(post['pub_date']), post['title'])
page.gemtext += link.to_gemtext()
path = os.path.join(output_directory, blog.path.strip('/'))
print(f"path is {path}")
os.makedirs(path, exist_ok=True)
with open(os.path.join(path, 'index.gemini'), 'w') as fout:
fout.write(page.gemtext)
if __name__ == "__main__":
project = Project.discover('.')
env = project.make_env()
pad = env.new_pad()
blog = pad.get('blog')
output_directory = "/home/robin/gemini/content"
title_page(blog)
for post in blog.children.order_by('pub_date').all():
path = os.path.join(output_directory, post.path.strip('/'))
os.makedirs(path, exist_ok=True)
p = Post(post)
p.post_to_gemtext()
with open(os.path.join(path, 'index.gemini'), 'w') as fout:
fout.write(p.gemtext)