import os import re import glob import html import email import logging import datetime from multiprocessing import Pool 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) md = markdown.Markdown(extensions=['extra', 'meta', TocExtension(anchorlink=True)]) cpu_count = os.cpu_count() def convert(text): md.reset() return md.convert(text) 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() logging.info("parsing %s", fpath) out = convert(text) title = md.Meta.get('title')[0] date = md.Meta.get('date')[0] draft = False if md.Meta.get('draft'): draft = True out = convert('# ' + 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, 'draft': draft, } def render_posts(): files = glob.glob('posts/*.md') logging.info('found post files %s', files) posts = [] logging.info('starting render posts with cpu_count: %d', cpu_count) with Pool(processes=cpu_count) as pool: posts = pool.map(render_post, files) logging.info("render_posts result: %s", posts) return posts def posts_list_html(posts): post_tpl = """
  • {title}
  • """ out = '' 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 = """ {title} {link} {pubdate} {link} {description} """ link = "https://cfebs.com/" + post['destpath'] with open(post['fpath'], 'r', encoding='utf-8') as inf: text = inf.read() converted = 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) posts = filter(lambda p: not p['draft'], 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()