all repos — hastyscribe @ 806f3bd08605a4cbd5a789f1f5858fdd969a56a6

A professional markdown compiler.

Add option to specify a CSS file to embed into generated HTML.
Philip Wernersbach philip.wernersbach@gmail.com
Sun, 26 Apr 2015 18:22:30 -0400
commit

806f3bd08605a4cbd5a789f1f5858fdd969a56a6

parent

dfeace2d71407f7d60c951681ff2f55f34c07c8a

1 files changed, 42 insertions(+), 27 deletions(-)

jump to
M hastyscribe.nimhastyscribe.nim

@@ -5,17 +5,19 @@

let usage* = " HastyScribe v" & v & " - Self-contained Markdown Compiler" & """ (c) 2013-2014 Fabio Cevasco - + Usage: - hastyscribe markdown_file_or_glob.md [--notoc] + hastyscribe markdown_file_or_glob.md [options] Arguments: markdown_file_or_glob The markdown (or glob expression) file to compile into HTML. Options: - --notoc Do not generate a Table of Contents.""" + --notoc Do not generate a Table of Contents. + --user-css=<file> Insert contents of <file> as a CSS stylesheet.""" var generate_toc* = true +var user_css*: string = nil const stylesheet* = "assets/styles/hastyscribe.css".slurp const hastyscribe_font* = "assets/fonts/hastyscribe.woff".slurp const fontawesome_font* = "assets/fonts/fontawesome-webfont.woff".slurp

@@ -28,8 +30,8 @@

# Procedures -proc parse_date*(date: string, timeinfo: var TimeInfo): bool = - var parts = date.split('-').map(proc(i:string): int = +proc parse_date*(date: string, timeinfo: var TimeInfo): bool = + var parts = date.split('-').map(proc(i:string): int = try: i.parseInt except:

@@ -49,19 +51,19 @@ proc style_tag*(css): string =

result = "<style>$1</style>" % [css] proc encode_image*(contents, format): string = - let enc_contents = contents.encode(contents.len*3) + let enc_contents = contents.encode(contents.len*3) return "data:image/$format;base64,$enc_contents" % ["format", format, "enc_contents", enc_contents] proc encode_image_file*(file, format): string = if (file.existsFile): let contents = file.readFile return encode_image(contents, format) - else: + else: echo("Warning: image '"& file &"' not found.") return file proc encode_font*(font, format): string = - let enc_contents = font.encode(font.len*3) + let enc_contents = font.encode(font.len*3) return "data:application/$format;charset=utf-8;base64,$enc_contents" % ["format", format, "enc_contents", enc_contents] proc embed_images*(document, dir): string =

@@ -70,7 +72,7 @@ if dir.len == 0:

current_dir = "" else: current_dir = dir & "/" - type + type TImgTagStart = array[0..0, string] let img_peg = peg""" image <- '<img' \s+ 'src=' ["] {file} ["]

@@ -106,7 +108,7 @@ -moz-osx-font-smoothing: grayscale;

} """ % ["family", family, "font", encode_font(font, "x-font-woff"), "style", style, "weight", $weight] -var fonts* = [ +var fonts* = [ create_font_face(hastyscribe_font, "HastyScribe", "normal", 400), create_font_face(fontawesome_font, "FontAwesome", "normal", 400), create_font_face(sourcecodepro_font, "Source Code Pro", "normal", 400),

@@ -121,7 +123,7 @@ return style_tag(fonts.join);

# Snippet Definition: # {{test -> My test snippet}} -# +# # Snippet Usage: # {{test}}

@@ -151,7 +153,7 @@ var matches:TSnippet

discard snippet.match(peg_snippet, matches) var id = matches[0].strip if snippets[id] == nil: - echo "Warning: Snippet '" & id & "' not defined." + echo "Warning: Snippet '" & id & "' not defined." doc = doc.replace(snippet, "") else: doc = doc.replace(snippet, snippets[id])

@@ -170,7 +172,8 @@

# Document Variables var metadata = TMDMetaData(title:"", author:"", date:"") var body = source.md(MKD_DOTOC or MKD_EXTRA_FOOTNOTE, metadata) - var main_css = stylesheet.style_tag + var main_css_tag = stylesheet.style_tag + var user_css_tag = "" var headings = " class=\"headings\"" var author_footer = ""

@@ -193,6 +196,9 @@ else:

headings = "" toc = "" + if user_css != nil: + user_css_tag = user_css.readFile.style_tag + # Date parsing and validation var timeinfo: TimeInfo = getLocalTime(getTime())

@@ -207,9 +213,10 @@ <meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="$author"> <meta name="generator" content="HastyScribe"> - $fonts_css - $main_css -</head> + $fonts_css_tag + $main_css_tag + $user_css_tag +</head> <body$headings> <a id="document-top"></a> $header_tag

@@ -221,23 +228,23 @@ <div id="footer">

<p>$author_footer $date</p> <p><span>Powered by</span> <a href="https://h3rald.com/hastyscribe"><span class="hastyscribe"></span></a></p> </div> -</body>""" % ["title_tag", title_tag, "header_tag", header_tag, "author", metadata.author, "author_footer", author_footer, "date", timeinfo.format("MMMM d, yyyy"), "toc", toc, "main_css", main_css, "headings", headings, "body", body, -"fonts_css", embed_fonts()] +</body>""" % ["title_tag", title_tag, "header_tag", header_tag, "author", metadata.author, "author_footer", author_footer, "date", timeinfo.format("MMMM d, yyyy"), "toc", toc, "main_css_tag", main_css_tag, "user_css_tag", user_css_tag, "headings", headings, "body", body, +"fonts_css_tag", embed_fonts()] document = embed_images(document, inputsplit.dir) document = add_jump_to_top_links(document) output_file.writeFile(document) - + ### MAIN when isMainModule: var input = "" var files = @[""] - + discard files.pop - + # Parse Parameters - + for kind, key, val in getopt(): case kind of cmdArgument:

@@ -245,16 +252,24 @@ input = key

of cmdLongOption: if key == "notoc": generate_toc = false + elif key == "user-css": + user_css = val else: discard - + if input == "": quit(usage, 1) - + elif user_css == "": + quit(usage, 4) + for file in walkFiles(input): files.add(file) - + if files.len == 0: quit("Error: \"$1\" does not match any file" % [input], 2) else: - for file in files: - compile(file) + try: + for file in files: + compile(file) + except IOError: + let msg = getCurrentExceptionMsg() + quit("Error: $1" % [msg], 3)