all repos — hastyscribe @ accccb7c1903da7541eb4bc93c57ed23480766aa

A professional markdown compiler.

hastyscribe.nim

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
import os, parseopt, strutils, times, base64, markdown

let v = "0.1"
let usage = "  HastyScribe v" & v & " - Self-contained Markdown Compiler" & """

  (c) 2013 Fabio Cevasco
  
  Usage:
    hastyscribe markdown_file

  Arguments:
    markdown_file          the markdown file to compile into HTML."""

# Source
const src_css = "assets/hastyscribe.css".slurp


proc style_tag(css): string =
  result = "<style>$1</style>" % [css]

let css = src_css.style_tag

proc encode_image(file, format): string =
  let contents = file.readFile
  let enc_contents = contents.encode(contents.len*3) 
  return "data:image/$format;base64,$enc_contents" % ["format", format, "enc_contents", enc_contents]


### MAIN

var input_file = ""

var opt = initOptParser()

opt.next

if opt.kind == cmdArgument:
  # Input file name
  input_file = opt.key

if input_file == "":
  quit(usage, 1)

if input_file.existsFile == false:
  quit("Error: file \"$1\" does not exist" % [input_file], 2)

let inputsplit = input_file.splitFile

# Output file name
let output_file = inputsplit.dir/inputsplit.name & ".htm"

let source = input_file.readFile

# URL callback to base64-encode and embed images
proc callback(url: cstring, size: cint, p: pointer): cstring =
  let str_url = $url
  var target = str_url[0..size-1]
  let file = inputsplit.dir/target
  if file.existsFile:
    let filesplit = target.splitFile
    case filesplit.ext
    of ".png":
      target = encode_image(file, "png")
    of ".jpg":
      target = encode_image(file, "jpeg")
    of ".gif":
      target = encode_image(file, "gif")
    else: nil
  return target

# Document Variables
var metadata = TMDMetaData(title:"", author:"", date:"")
let body = source.md(MKD_DOTOC or MKD_EXTRA_FOOTNOTE, metadata, callback)


# Manage metadata
if metadata.author != "":
  metadata.author = "by <em>" & metadata.author & "</em> &ndash;"

var title_tag, header_tag, toc: string

if metadata.title != "":
  title_tag = "<title>" & metadata.title & "</title>"
  header_tag = "<div id=\"header\"><h1>" & metadata.title & "</h1></div>"
else:
  title_tag = ""
  header_tag = ""

if metadata.toc != "":
  toc = "<div id=\"toc\">" & metadata.toc & "</div>"
else:
  toc = ""

# Date parsing and validation
var timeinfo: TTimeInfo

proc parse_date(date: string, timeinfo: var TTimeInfo): bool = 
  var parts = metadata.date.split('-').map(proc(i:string): int = i.parseInt)
  try:
    timeinfo = TTimeInfo(year: parts[0], month: TMonth(parts[1]-1), monthday: parts[2])
    # Fix invalid dates (e.g. Feb 31st -> Mar 3rd)
    timeinfo = getLocalTime(timeinfo.TimeInfoToTime);
    return true
  except:
    return false

if metadata.date == "":
  discard parse_date(getDateStr(), timeinfo)
else:
  if parse_date(metadata.date, timeinfo) == false:
    discard parse_date(getDateStr(), timeinfo)

let document = """<!doctype html>
<html lang="en">
<head>
  $title_tag
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="author" content="$author">
  $css
</head> 
<body>
  $header_tag
  <div id="toc">
    $toc
  </div>
  <div id="main">
$body
  </div>
  <div id="footer">
    <p>$author Generated with <a href="https://github.com/h3rald/hastyscribe/">HastyScribe</a> on $date</p>
  </div>
</body>""" % ["title_tag", title_tag, "header_tag", header_tag, "author", metadata.author, "date", timeinfo.format("MMMM d, yyyy"), "toc", toc, "css", css, "body", body]

output_file.writeFile(document)