Last active
August 29, 2015 13:57
-
-
Save lericson/9761314 to your computer and use it in GitHub Desktop.
Assignment PDF creator tool automator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# encoding: utf-8 | |
"""Make an assignment pdf file from assignment.md + src directory | |
First run this: | |
sudo easy_install markdown pygments | |
Also, you have to have a title in the markdown file, i.e. a line starting with # | |
""" | |
import os | |
import sys | |
import optparse | |
import pygments | |
from pygments.lexers import guess_lexer_for_filename | |
from pygments.lexers.special import TextLexer | |
from pygments.formatters.html import HtmlFormatter | |
from markdown import markdown as html_markdown | |
p = optparse.OptionParser() | |
p.add_option('--readme', '-r', help="README file, guessed automatically") | |
p.add_option('--sources', '-s', default='src') | |
opts, args = p.parse_args() | |
if not opts.readme: | |
for fn in ('assignment.md', 'README.md'): | |
if os.path.isfile(fn): | |
opts.readme = fn | |
break | |
else: | |
raise RuntimeError('no readme file found! use --readme to set a non-standard README filenames') | |
with open(opts.readme) as fp: | |
body = html_markdown(fp.read().decode('utf-8'), output_format='html5') | |
title = body.split('<h1>', 1)[1].split('</h1>', 1)[0] | |
print u""" | |
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> | |
<style> | |
h1, | |
h2, | |
h3, | |
h4, | |
h5, | |
h6, | |
p, | |
blockquote { | |
line-height: 1.125em; | |
margin: 0.5em 0 1em 0; | |
padding: 0; | |
} | |
img { | |
max-width: 100%; | |
/*max-height: 105mm;*/ | |
} | |
* { | |
tab-size: 2; | |
} | |
body { | |
font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif; | |
font-size: 13px; | |
line-height: 18px; | |
color: #737373; | |
width: 170mm; | |
padding: 0 20mm; | |
} | |
@media only screen { | |
body { | |
margin: 0 auto; | |
} | |
} | |
table { | |
margin: 10px 0 15px 0; | |
border-collapse: collapse; | |
} | |
td,th { | |
border: 1px solid #ddd; | |
padding: 3px 10px; | |
} | |
th { | |
padding: 5px 10px; | |
} | |
a { | |
color: #0069d6; | |
} | |
a:hover { | |
color: #0050a3; | |
text-decoration: none; | |
} | |
a img { | |
border: none; | |
} | |
h1, | |
h2, | |
h3, | |
h4, | |
h5, | |
h6 { | |
color: #404040; | |
} | |
h1 { | |
font-size: 30px; | |
line-height: 1.125em; | |
text-align: center; | |
} | |
h2 { | |
font-size: 24px; | |
line-height: 1.125em; | |
} | |
h3 { | |
font-size: 18px; | |
line-height: 1.125em; | |
} | |
h4 { | |
font-size: 16px; | |
line-height: 1.125em; | |
} | |
h5 { | |
font-size: 14px; | |
line-height: 1.125em; | |
} | |
h6 { | |
font-size: 13px; | |
line-height: 1.125em; | |
} | |
p { | |
line-height: 1.25em; | |
} | |
hr { | |
margin: 0 0 19px; | |
border: 0; | |
border-bottom: 1px solid #ccc; | |
} | |
blockquote { | |
padding: 13px 13px 21px 15px; | |
margin-bottom: 18px; | |
font-family:georgia,serif; | |
font-style: italic; | |
} | |
blockquote:before { | |
content:"\\201C"; | |
font-size:40px; | |
margin-left:-10px; | |
font-family:georgia,serif; | |
color:#eee; | |
} | |
blockquote p { | |
font-size: 14px; | |
font-weight: 300; | |
line-height: 18px; | |
margin-bottom: 0; | |
font-style: italic; | |
} | |
code, pre { | |
font-family: Monaco, Andale Mono, Courier New, monospace; | |
} | |
code { | |
background-color: #fee9cc; | |
color: rgba(0, 0, 0, 0.75); | |
padding: 1px 3px; | |
font-size: 12px; | |
-webkit-border-radius: 3px; | |
-moz-border-radius: 3px; | |
border-radius: 3px; | |
} | |
pre { | |
display: block; | |
padding: 14px; | |
margin: 0 0 18px; | |
line-height: 16px; | |
font-size: 11px; | |
border: 1px solid #d9d9d9; | |
white-space: pre-wrap; | |
word-wrap: break-word; | |
} | |
pre code { | |
background-color: #fff; | |
color:#737373; | |
font-size: 11px; | |
padding: 0; | |
} | |
@media print { | |
body,code,pre code,h1,h2,h3,h4,h5,h6 { | |
color: black; | |
} | |
h1, h2, h3, h4, blockquote { | |
page-break-before: avoid; | |
page-break-inside: avoid; | |
page-break-after: avoid; | |
} | |
table, .attachment { | |
page-break-inside: avoid; | |
overflow: hidden; | |
} | |
} | |
.sourcetable .linenos { | |
padding: 0 5px 0 0; | |
} | |
.sourcetable pre { | |
font: 13px monospace; | |
line-height: 13px; | |
word-wrap: normal; | |
white-space: pre; | |
margin: 0; | |
padding: 0; | |
border: 0; | |
} | |
.sourcetable td, .sourcetable th, .sourcetable div { | |
border: 0; | |
padding: 0; | |
} | |
.source .c { color: #408080; font-style: italic } /* Comment */ | |
.source .err { border: 1px solid #FF0000 } /* Error */ | |
.source .k { color: #008000; font-weight: bold } /* Keyword */ | |
.source .o { color: #666666 } /* Operator */ | |
.source .cm { color: #408080; font-style: italic } /* Comment.Multiline */ | |
.source .cp { color: #BC7A00 } /* Comment.Preproc */ | |
.source .c1 { color: #408080; font-style: italic } /* Comment.Single */ | |
.source .cs { color: #408080; font-style: italic } /* Comment.Special */ | |
.source .gd { color: #A00000 } /* Generic.Deleted */ | |
.source .ge { font-style: italic } /* Generic.Emph */ | |
.source .gr { color: #FF0000 } /* Generic.Error */ | |
.source .gh { color: #000080; font-weight: bold } /* Generic.Heading */ | |
.source .gi { color: #00A000 } /* Generic.Inserted */ | |
.source .go { color: #808080 } /* Generic.Output */ | |
.source .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ | |
.source .gs { font-weight: bold } /* Generic.Strong */ | |
.source .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ | |
.source .gt { color: #0040D0 } /* Generic.Traceback */ | |
.source .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ | |
.source .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ | |
.source .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ | |
.source .kp { color: #008000 } /* Keyword.Pseudo */ | |
.source .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ | |
.source .kt { color: #B00040 } /* Keyword.Type */ | |
.source .m { color: #666666 } /* Literal.Number */ | |
.source .s { color: #BA2121 } /* Literal.String */ | |
.source .na { color: #7D9029 } /* Name.Attribute */ | |
.source .nb { color: #008000 } /* Name.Builtin */ | |
.source .nc { color: #0000FF; font-weight: bold } /* Name.Class */ | |
.source .no { color: #880000 } /* Name.Constant */ | |
.source .nd { color: #AA22FF } /* Name.Decorator */ | |
.source .ni { color: #999999; font-weight: bold } /* Name.Entity */ | |
.source .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ | |
.source .nf { color: #0000FF } /* Name.Function */ | |
.source .nl { color: #A0A000 } /* Name.Label */ | |
.source .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ | |
.source .nt { color: #008000; font-weight: bold } /* Name.Tag */ | |
.source .nv { color: #19177C } /* Name.Variable */ | |
.source .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ | |
.source .w { color: #bbbbbb } /* Text.Whitespace */ | |
.source .mf { color: #666666 } /* Literal.Number.Float */ | |
.source .mh { color: #666666 } /* Literal.Number.Hex */ | |
.source .mi { color: #666666 } /* Literal.Number.Integer */ | |
.source .mo { color: #666666 } /* Literal.Number.Oct */ | |
.source .sb { color: #BA2121 } /* Literal.String.Backtick */ | |
.source .sc { color: #BA2121 } /* Literal.String.Char */ | |
.source .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ | |
.source .s2 { color: #BA2121 } /* Literal.String.Double */ | |
.source .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ | |
.source .sh { color: #BA2121 } /* Literal.String.Heredoc */ | |
.source .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ | |
.source .sx { color: #008000 } /* Literal.String.Other */ | |
.source .sr { color: #BB6688 } /* Literal.String.Regex */ | |
.source .s1 { color: #BA2121 } /* Literal.String.Single */ | |
.source .ss { color: #19177C } /* Literal.String.Symbol */ | |
.source .bp { color: #008000 } /* Name.Builtin.Pseudo */ | |
.source .vc { color: #19177C } /* Name.Variable.Class */ | |
.source .vg { color: #19177C } /* Name.Variable.Global */ | |
.source .vi { color: #19177C } /* Name.Variable.Instance */ | |
.source .il { color: #666666 } /* Literal.Number.Integer.Long */ | |
</style> | |
<script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax:{inlineMath:[['$$$','$$$']]}});</script><script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> | |
""".encode('utf-8') | |
print u'<title>{title}</title>'.format(title=title).encode('utf-8') | |
print u'</head><body>{body}'.format(body=body).encode('utf-8') | |
formatter = HtmlFormatter(cssclass="source", linenos=True, encoding='utf-8') | |
def print_code_file(fn): | |
with open(fn) as fp: | |
try: | |
contents = fp.read().decode('utf-8') | |
except: | |
print >>sys.stderr, 'failed reading', fn | |
raise | |
try: | |
lexer = guess_lexer_for_filename(fn, contents) | |
except pygments.util.ClassNotFound: | |
lexer = TextLexer() | |
print '<div class="attachment">' | |
print '<h3>' + fn + ' (' + lexer.name + ')</h3>' | |
pygments.highlight(contents, lexer, formatter, outfile=sys.stdout) | |
print '</div>' | |
if not args: | |
args = [os.path.join(root, fn) for root, dns, fns in os.walk(opts.sources) for fn in fns] | |
if args: | |
print u'<h2>Bilagor</h2>'.encode('utf-8') | |
for arg in args: | |
print_code_file(arg) | |
print u"</body></html>".encode('utf-8') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment