Skip to content

Instantly share code, notes, and snippets.

@jpstacey
Last active December 26, 2015 19:39
Show Gist options
  • Save jpstacey/7202922 to your computer and use it in GitHub Desktop.
Save jpstacey/7202922 to your computer and use it in GitHub Desktop.
Parse a markdown-based contract and replace tokens in square brackets.
#!/usr/bin/env python
"""
Parse a markdown contract and replace selected [tokens] with custom values.
Define some custom tokens and default values in a file ~/.contract-builder.yml,
but permit command-line overrides.
Example usage:
contract-builder.py < my_contract_template.md > contract_for_ann.md --customer-name "Ann Other"
* Tokens are represented as YAML keys. Please only use alphanumerics and
spaces, as any other value could cause everything to explode
* Default values are represented as string YAML values: "Brian Blessed"
* Required values are represented as NULL YAML values: !!null
* Each command-line argument will be the same as its token, but with spaces
replaced by hyphens, and two hyphens at the beginning.
"""
import sys, os
import codecs
import argparse
import markdown
from yaml import load, dump
try:
from yaml import CLoader as Loader
except ImportError:
from yaml import Loader
def get_schema():
"""
Get the schema for our replacement tokens from ~/.contract-builder.yml
"""
# Load the raw YAML, or return a simple schema
try:
schema_yml = open(os.path.expanduser('~/.contract-builder.yml'))
except IOError:
return {'--my-name': {}, '--customer-name': {},}
schema_raw = load(schema_yml, Loader=Loader)
schema_yml.close()
# Turn the raw YAML data into an argparse-style schema
schema = {}
for k in schema_raw:
if schema_raw[k] is None:
schema['--%s' % k.replace(' ', '-')] = {'required': True}
else:
schema['--%s' % k.replace(' ', '-')] = {'default': schema_raw[k]}
return schema
def get_config(schema):
"""
Combine the YAML schema with any command-line arguments
"""
parser = argparse.ArgumentParser()
for arg, config in schema.items():
# Remove any of our extensions
for key in config.keys():
if key[0] == "#":
del config[key]
parser.add_argument(*[arg], **config)
return vars(parser.parse_args(sys.argv[1:]))
sys.stdin = codecs.getreader('utf-8')(sys.stdin)
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
# Get command-line config and template from stdin
schema = get_schema()
replacements = get_config(schema)
template = "".join(sys.stdin)
document = template
# For each token, replace in the template
for replacement in replacements:
if replacements[replacement] is not None:
document = document.replace('[%s]'
% replacement.replace('_', ' '), replacements[replacement])
document = open("header.html", "r").read() + \
markdown.markdown(document) + \
open("footer.html", "r").read()
# Print document on stdout
print document
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:700italic,700|Slabo+27px' rel='stylesheet' type='text/css'>
<style type="text/css">
body {
width: 540px;
margin: 0 auto;
font-family: 'Slabo 27px', serif;
}
hr {
margin-top: 3em;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Open Sans', sans-serif;
}
h4, h5, h6 {
margin-bottom: 0.25em;
}
p {
margin: 0.5em 0;
}
</style>
</head>
<body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment