lektura

lektura.git
git clone git://git.lenczewski.org/lektura.git
Log | Files | Refs

template.py (3344B)


      1 #!/usr/bin/env python3
      2 
      3 import argparse
      4 import datetime
      5 import html
      6 import html.parser
      7 import os
      8 import pathlib
      9 
     10 
     11 argparser = argparse.ArgumentParser(
     12         description='Templates html fragments into full html pages')
     13 
     14 argparser.add_argument('src', type=argparse.FileType('r'),
     15                        help='The source html fragment')
     16 argparser.add_argument('dst', type=argparse.FileType('w'),
     17                        help='The destination html file')
     18 argparser.add_argument('tpl', type=argparse.FileType('r'),
     19                        help='The source html template')
     20 argparser.add_argument('kwargs', nargs='*',
     21                        help='A list of custom \'key=val\' pairs to replace in the template')
     22 
     23 
     24 def map_kwargs(kwargs):
     25     return dict([arg.split('=', maxsplit=1) for arg in kwargs])
     26 
     27 
     28 def titleify(srcpath):
     29     slug, ext = srcpath.rsplit('.', maxsplit=1)
     30 
     31     seps = ['-', '_']
     32     for sep in seps:
     33         slug = slug.replace(sep, ' ')
     34 
     35     frags = [substr.capitalize() for substr in slug.split(' ')]
     36     title = ' '.join(frags)
     37 
     38     return title
     39 
     40 
     41 def created(srcpath):
     42     info = os.stat(srcpath)
     43     return datetime.datetime.fromtimestamp(info.st_ctime)
     44 
     45 
     46 def edited(srcpath):
     47     info = os.stat(srcpath)
     48     return datetime.datetime.fromtimestamp(info.st_mtime)
     49 
     50 
     51 def fromisodate(isodate):
     52     return datetime.datetime.fromisoformat(isodate)
     53 
     54 
     55 TIMESTAMP = '%d %B %Y'
     56 
     57 METADATA_SEPARATOR = '---'
     58 
     59 
     60 def readfile(srcpath):
     61     data = ''
     62     with open(srcpath, 'r') as src:
     63         data = src.read()
     64 
     65     if METADATA_SEPARATOR in data:
     66         return data.split(METADATA_SEPARATOR, maxsplit=1)
     67 
     68     return '', data
     69 
     70 
     71 def metadata(srcpath):
     72     [metadata, *_] = readfile(srcpath)
     73 
     74     keys = {}
     75     for line in metadata.split('\n'):
     76         line = line.strip()
     77         if line:
     78             [key, *val] = line.split(':', maxsplit=1)
     79             keys[key] = ''.join(val).strip()
     80 
     81     return keys
     82 
     83 
     84 def content(srcpath):
     85     [_, *contents] = readfile(srcpath)
     86 
     87     return ' '.join(contents)
     88 
     89 
     90 def article_keys(srcpath):
     91     name = pathlib.Path(srcpath).name
     92 
     93     keys = {
     94         'title': titleify(name),
     95         'created-iso': created(srcpath).isoformat(),
     96         'edited-iso': edited(srcpath).isoformat(),
     97         'content': content(srcpath),
     98     }
     99 
    100     keys |= metadata(srcpath)
    101 
    102     keys |= {
    103         'created-str': fromisodate(keys['created-iso']).strftime(TIMESTAMP),
    104         'edited-str': fromisodate(keys['edited-iso']).strftime(TIMESTAMP),
    105     }
    106 
    107     # print(srcpath, keys)
    108 
    109     return keys
    110 
    111 
    112 def instantiate(tpl, kwargs):
    113     splits = []
    114 
    115     cur = 0
    116     end = len(tpl)
    117     while cur < end:
    118         key_start = tpl.find('%', cur)
    119         key_end = tpl.find('%', key_start + 1)
    120 
    121         if key_start == -1:
    122             splits.append([cur, end, ''])
    123             break
    124         else:
    125             splits.append([cur, key_start, tpl[key_start + 1:key_end]])
    126 
    127         cur = key_end + 1
    128 
    129     out = ''
    130     for [tpl_start, tpl_end, key] in splits:
    131         out += tpl[tpl_start:tpl_end]
    132         out += kwargs.get(key, '')
    133 
    134     return out
    135 
    136 
    137 if __name__ == '__main__':
    138     args = argparser.parse_args()
    139 
    140     template = ''
    141     with args.tpl as tpl:
    142         template = tpl.read()
    143 
    144     with args.dst as dst:
    145         keys = article_keys(args.src.name)
    146         keys |= map_kwargs(args.kwargs)
    147 
    148         dst.write(instantiate(template, keys))
    149