141 lines
3.5 KiB
Python
141 lines
3.5 KiB
Python
|
import re
|
||
|
import glob
|
||
|
import html
|
||
|
import email
|
||
|
import logging
|
||
|
import datetime
|
||
|
from string import Template
|
||
|
|
||
|
import markdown
|
||
|
from markdown.extensions.toc import TocExtension
|
||
|
|
||
|
destpath_re = re.compile(r'\.md$')
|
||
|
logging.basicConfig(encoding='utf-8', level=logging.INFO)
|
||
|
|
||
|
def render_post(fpath):
|
||
|
destpath = destpath_re.sub('.html', fpath)
|
||
|
logging.info("opening %s for parsing, dest %s", fpath, destpath)
|
||
|
# from: https://python-markdown.github.io/reference/
|
||
|
with open(fpath, "r", encoding="utf-8") as input_file:
|
||
|
logging.info("reading %s", fpath)
|
||
|
text = input_file.read()
|
||
|
|
||
|
md = markdown.Markdown(extensions = ['extra', 'meta', TocExtension(anchorlink=True)])
|
||
|
|
||
|
logging.info("parsing %s", fpath)
|
||
|
out = md.convert(text)
|
||
|
|
||
|
title = md.Meta.get('title')[0]
|
||
|
date = md.Meta.get('date')[0]
|
||
|
|
||
|
out = markdown.markdown('# ' + title) + out
|
||
|
|
||
|
logging.info("writing to %s", destpath)
|
||
|
render_template('index.html.tmpl', destpath, {'content': out, 'more_title': ' - ' + title})
|
||
|
|
||
|
return {
|
||
|
'title': title,
|
||
|
'date': date,
|
||
|
'fpath': fpath,
|
||
|
'destpath': destpath,
|
||
|
}
|
||
|
|
||
|
def render_posts():
|
||
|
files = glob.glob('posts/*.md')
|
||
|
logging.info('found post files %s', files)
|
||
|
posts = []
|
||
|
for fname in files:
|
||
|
p = render_post(fname)
|
||
|
posts.append(p)
|
||
|
logging.info('rendered post: %s', p)
|
||
|
|
||
|
return posts
|
||
|
|
||
|
def posts_list_html(posts):
|
||
|
post_tpl = """<li>
|
||
|
<a href="{href}">{title}</a>
|
||
|
<time datetime="{date}">{disp_date}</time>
|
||
|
</li>"""
|
||
|
out = '<ul class="blog-posts-list">'
|
||
|
for post in posts:
|
||
|
disp_date = datetime.datetime.fromisoformat(post.get('date')).strftime('%Y-%m-%d')
|
||
|
out += post_tpl.format(href=post.get('destpath'),
|
||
|
title=post.get('title'),
|
||
|
date=post.get('date'),
|
||
|
disp_date=disp_date)
|
||
|
return out + '</ul>'
|
||
|
|
||
|
def render_template(tpl_fname, out_fname, subs):
|
||
|
with open(tpl_fname, 'r', encoding='utf-8') as inf:
|
||
|
tmpl = Template(inf.read())
|
||
|
|
||
|
out = tmpl.substitute(subs)
|
||
|
|
||
|
with open(out_fname, 'w', encoding='utf-8') as outf:
|
||
|
outf.write(out)
|
||
|
|
||
|
def render_index(posts):
|
||
|
content_html = posts_list_html(posts)
|
||
|
render_template('index.html.tmpl', 'index.html', {'content': content_html, 'more_title': ''})
|
||
|
|
||
|
def rss_post_xml(post):
|
||
|
tpl = """
|
||
|
<item>
|
||
|
<title>{title}</title>
|
||
|
<link>{link}</link>
|
||
|
<pubDate>{pubdate}</pubDate>
|
||
|
<guid>{link}</guid>
|
||
|
<description>{description}</description>
|
||
|
</item>
|
||
|
"""
|
||
|
link = "https://cfebs.com/" + post['destpath']
|
||
|
|
||
|
with open(post['fpath'], 'r', encoding='utf-8') as inf:
|
||
|
text = inf.read()
|
||
|
|
||
|
|
||
|
md = markdown.Markdown(extensions=['extra', 'meta', 'toc'])
|
||
|
converted = md.convert(text)
|
||
|
|
||
|
pubdate = email.utils.format_datetime(datetime.datetime.fromisoformat(post['date']))
|
||
|
subs = {
|
||
|
'title': post['title'],
|
||
|
'link': link,
|
||
|
'pubdate': pubdate,
|
||
|
'description': converted
|
||
|
}
|
||
|
|
||
|
for k,v in subs.items():
|
||
|
subs[k] = html.escape(v)
|
||
|
|
||
|
return tpl.format(**subs)
|
||
|
|
||
|
def render_rss_index(posts):
|
||
|
items = ''
|
||
|
for post in posts[:5]:
|
||
|
items += rss_post_xml(post)
|
||
|
|
||
|
subs = {
|
||
|
'site_title': 'cfebs.com',
|
||
|
'site_link': 'https://cfebs.com',
|
||
|
'self_full_link': 'https://cfebs.com/index.xml',
|
||
|
'description': 'Recent content from cfebs.com',
|
||
|
'last_build_date': email.utils.format_datetime(datetime.datetime.now()),
|
||
|
}
|
||
|
for k,v in subs.items():
|
||
|
subs[k] = html.escape(v)
|
||
|
|
||
|
subs['items'] = items
|
||
|
render_template('index.xml.tmpl', 'index.xml', subs)
|
||
|
|
||
|
def main():
|
||
|
posts = render_posts()
|
||
|
logging.info('rendered posts: %s', posts)
|
||
|
sorted_posts = sorted(posts,
|
||
|
key=lambda p: datetime.datetime.fromisoformat(p['date']), reverse=True)
|
||
|
render_index(sorted_posts)
|
||
|
render_rss_index(sorted_posts)
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main()
|