Added support for scripting and loglevel; added build and clean scripts.
h3rald h3rald@h3rald.com
Sun, 11 Jun 2017 22:21:18 +0200
3 files changed,
168 insertions(+),
123 deletions(-)
M
hastysite.nim
→
hastysite.nim
@@ -25,114 +25,25 @@ templates*: string
output*: string temp*: string tempContents: string + scripts*: string HastyFiles = object rules*: string - scripts*: string metadata: string contents: seq[JsonNode] assets: seq[JsonNode] HastySite* = object settings*: JsonNode metadata*: JsonNode + scripts*: JsonNode dirs*: HastyDirs files*: HastyFiles NoMetadataException* = ref Exception DictionaryRequiredException* = ref Exception MetadataRequiredException* = ref Exception -#### min Library - -proc hastysite_module*(i: In, hs: HastySite) = - let def = i.define() - - def.symbol("metadata") do (i: In): - i.push i.fromJson(hs.metadata) - - def.symbol("settings") do (i: In): - i.push i.fromJson(hs.settings) - - def.symbol("contents") do (i: In): - var contents = newSeq[MinValue](0) - for j in hs.files.contents: - contents.add i.fromJson(j) - i.push contents.newVal(i.scope) - - def.symbol("assets") do (i: In): - var assets = newSeq[MinValue](0) - for j in hs.files.assets: - assets.add i.fromJson(j) - i.push assets.newVal(i.scope) - - def.symbol("output") do (i: In): - i.push hs.dirs.output.newVal - - def.symbol("input-fread") do (i: In): - var d: MinValue - i.reqDictionary d - let t = d.dget("type".newVal).getString - let path = d.dget("path".newVal).getString - var contents = "" - if t == "content": - contents = readFile(hs.dirs.tempContents/path) - else: - contents = readFile(hs.dirs.assets/path) - i.push contents.newVal - - def.symbol("output-fwrite") do (i: In): - var d: MinValue - i.reqDictionary d - let id = d.dget("id".newVal).getString - let ext = d.dget("ext".newVal).getString - var contents = "" - try: - contents = d.dget("contents".newVal).getString - except: - raise MetadataRequiredException(msg: "Metadata key 'contents' not found in dictionary.") - let outfile = hs.dirs.output/id&ext - outfile.parentDir.createDir - writeFile(outfile, contents) - - def.symbol("copy2output") do (i: In): - var d: MinValue - i.reqDictionary d - let t = d.dget("type".newVal).getString - let path = d.dget("path".newVal).getString - var infile, outfile: string - if t == "content": - infile = hs.dirs.tempContents/path - outfile = hs.dirs.output/path - else: - infile = hs.dirs.assets/path - outfile = hs.dirs.output/path - notice " - Copying: ", infile, " -> ", outfile - outfile.parentDir.createDir - copyFileWithPermissions(infile, outfile) - - def.symbol("mustache") do (i: In): - var t, c: MinValue - i.reqQuotationAndString c, t - if not c.isDictionary: - raise DictionaryRequiredException(msg: "No dictionary provided as template context.") - let ctx = newContext(%c) - let tplname = t.getString & ".mustache" - let tpl = readFile(hs.dirs.templates/tplname) - i.push tpl.render(ctx, hs.dirs.templates).newval +const SCRIPT_BUILD = "./scripts/build.min".slurp +const SCRIPT_CLEAN = "./scripts/clean.min".slurp - def.symbol("markdown") do (i: In): - var t, c: MinValue - i.reqQuotationAndString c, t - if not c.isDictionary: - raise DictionaryRequiredException(msg: "No dictionary provided for markdown processor fields.") - let options = HastyOptions(toc: false, output: nil, css: nil, watermark: nil, fragment: true) - var fields = initTable[string, proc():string]() - for item in c.qVal: - fields[item.qVal[0].getString] = proc(): string = return $$item.qVal[1] - var hastyscribe = newHastyScribe(options, fields) - let file = t.getString() - i.push hastyscribe.compileFragment(file, hs.dirs.contents).newVal - - def.finalize("hastysite") - #### Helper Functions proc preprocessContent(file, dir: string, obj: var JsonNode): string =@@ -189,10 +100,6 @@ return json[key].getStr
else: return default -proc quitIfNotExists(file: string) = - if not file.fileExists: - quit("Error: File '$1' not found." % file) - proc contentMetadata(f, dir: string, meta: JsonNode): JsonNode = result = newJObject() let fdata = f.splitFile@@ -214,6 +121,8 @@ result["type"] = %"asset"
result["id"] = %path.changeFileExt("") result["ext"] = %fdata.ext +proc hastysite_module*(i: In, hs1: HastySite) + proc interpret(hs: HastySite, file: string) = var i = newMinInterpreter(file, file.parentDir) i.hastysite_module(hs)@@ -230,9 +139,17 @@ result.dirs.templates = json.get("templates", "templates")
result.dirs.output = json.get("output", "output") result.dirs.temp = json.get("temp", "temp") result.dirs.tempContents = result.dirs.temp / result.dirs.contents + result.dirs.scripts = json.get("scripts", "scripts") result.files.rules = json.get("rules", "rules.min") - result.files.scripts = json.get("scripts", "scripts.min") result.files.metadata = result.dirs.temp / "metadata.json" + result.scripts = newJObject() + for f in result.dirs.scripts.walkDir(true): + let path = result.dirs.scripts/f.path + let file = path.open() + let desc = file.readLine.replace(";", "") + let key = f.path.replace(".min", "") + file.close() + result.scripts[key] = %desc proc preprocess*(hs: var HastySite) = var meta = newJObject()@@ -259,25 +176,122 @@ json["assets"] = %"assets"
json["templates"] = %"templates" json["temp"] = %"temp" json["output"] = %"output" + json["scripts"] = %"scripts" for key, value in json.pairs: createDir(dir/value.getStr) json["title"] = %"My Web Site" json["rules"] = %"rules.min" - json["scripts"] = %"scripts.min" writeFile(dir/json["rules"].getStr, "") writeFile(dir/"settings.json", json.pretty) + writeFile(dir/"scripts/build.min", SCRIPT_BUILD) + writeFile(dir/"scripts/clean.min", SCRIPT_CLEAN) + +#### min Library + +proc hastysite_module*(i: In, hs1: HastySite) = + var hs = hs1 + let def = i.define() + + def.symbol("preprocess") do (i: In): + hs.preprocess() + + def.symbol("process-rules") do (i: In): + hs.interpret(hs.files.rules) + + def.symbol("clean-output") do (i: In): + hs.dirs.output.removeDir + + def.symbol("clean-temp") do (i: In): + hs.dirs.temp.removeDir + + def.symbol("metadata") do (i: In): + i.push i.fromJson(hs.metadata) -proc clean*(hs: HastySite) = - hs.dirs.temp.removeDir - hs.dirs.output.removeDir + def.symbol("settings") do (i: In): + i.push i.fromJson(hs.settings) + + def.symbol("contents") do (i: In): + var contents = newSeq[MinValue](0) + for j in hs.files.contents: + contents.add i.fromJson(j) + i.push contents.newVal(i.scope) + + def.symbol("assets") do (i: In): + var assets = newSeq[MinValue](0) + for j in hs.files.assets: + assets.add i.fromJson(j) + i.push assets.newVal(i.scope) + + def.symbol("output") do (i: In): + i.push hs.dirs.output.newVal + + def.symbol("input-fread") do (i: In): + var d: MinValue + i.reqDictionary d + let t = d.dget("type".newVal).getString + let path = d.dget("path".newVal).getString + var contents = "" + if t == "content": + contents = readFile(hs.dirs.tempContents/path) + else: + contents = readFile(hs.dirs.assets/path) + i.push contents.newVal + + def.symbol("output-fwrite") do (i: In): + var d: MinValue + i.reqDictionary d + let id = d.dget("id".newVal).getString + let ext = d.dget("ext".newVal).getString + var contents = "" + try: + contents = d.dget("contents".newVal).getString + except: + raise MetadataRequiredException(msg: "Metadata key 'contents' not found in dictionary.") + let outfile = hs.dirs.output/id&ext + outfile.parentDir.createDir + writeFile(outfile, contents) + + def.symbol("copy2output") do (i: In): + var d: MinValue + i.reqDictionary d + let t = d.dget("type".newVal).getString + let path = d.dget("path".newVal).getString + var infile, outfile: string + if t == "content": + infile = hs.dirs.tempContents/path + outfile = hs.dirs.output/path + else: + infile = hs.dirs.assets/path + outfile = hs.dirs.output/path + notice " - Copying: ", infile, " -> ", outfile + outfile.parentDir.createDir + copyFileWithPermissions(infile, outfile) + + def.symbol("mustache") do (i: In): + var t, c: MinValue + i.reqQuotationAndString c, t + if not c.isDictionary: + raise DictionaryRequiredException(msg: "No dictionary provided as template context.") + let ctx = newContext(%c) + let tplname = t.getString & ".mustache" + let tpl = readFile(hs.dirs.templates/tplname) + i.push tpl.render(ctx, hs.dirs.templates).newval -proc build*(hs: var HastySite) = - notice "Preprocessing..." - hs.preprocess() - notice "Processing rules..." - hs.interpret(hs.files.rules) - notice "All done." + def.symbol("markdown") do (i: In): + var t, c: MinValue + i.reqQuotationAndString c, t + if not c.isDictionary: + raise DictionaryRequiredException(msg: "No dictionary provided for markdown processor fields.") + let options = HastyOptions(toc: false, output: nil, css: nil, watermark: nil, fragment: true) + var fields = initTable[string, proc():string]() + for item in c.qVal: + fields[item.qVal[0].getString] = proc(): string = return $$item.qVal[1] + var hastyscribe = newHastyScribe(options, fields) + let file = t.getString() + i.push hastyscribe.compileFragment(file, hs.dirs.contents).newVal + def.finalize("hastysite") + when isMainModule: import@@ -285,41 +299,56 @@ parseopt2
setLogFilter(lvlNotice) - let usage = """ $1 v$2 - a tiny static site generator + proc usage(scripts: bool, hs: HastySite): string = + var text = """ $1 v$2 - a tiny static site generator (c) 2016-2017 Fabio Cevasco Usage: hastysite command Commands: - init Initializes a new site in the current directory. - build Builds the site. - clean Cleans temporary files. - Options: + init - Initializes a new site in the current directory. +""" + if scripts: + for key, value in hs.scripts.pairs: + text &= " " & key & " - " & value.getStr & "\n" + text &= """ Options: -h, --help Print this help + -l, --loglevel Sets the log level (one of: debug, info, notice, + warn, error, fatal). Default: notice -v, --version Print the program version""" % [appname, version] + return text let pwd = getCurrentDir() let cfg = pwd/"settings.json" + var hs: HastySite + var scripts = false + + if cfg.fileExists: + hs = newHastySite(cfg) + scripts = true + for kind, key, val in getopt(): case kind: of cmdArgument: case key: of "init": pwd.init() - of "clean": - quitIfNotExists(cfg) - var hs = newHastySite(cfg) - hs.clean() - of "build": - quitIfNotExists(cfg) - var hs = newHastySite(cfg) - hs.clean() - hs.build() + else: + if scripts: + if hs.scripts.hasKey(key): + hs.interpret(hs.dirs.scripts/key & ".min") + else: + fatal "Script '$1' not found" % key + else: + fatal "This directory does not contain a valid HastySite site" of cmdLongOption, cmdShortOption: case key: + of "loglevel", "l": + var v = val + setLogLevel(v) of "help", "h": - echo usage + echo usage(scripts, hs) quit(0) of "version", "v": echo version
A
scripts/build.min
@@ -0,0 +1,8 @@
+;Builds a site by processing contents and assets. +'hastysite import + +"Preprocessing..." notice +preprocess +"Processing rules.." notice +process-rules +"All done." notice
A
scripts/clean.min
@@ -0,0 +1,8 @@
+;Deletes all temporary and output files. +'hastysite import + +"Cleaning temporary folder..." notice +clean-temp +"Cleaning output folder..." notice +clean-output +"All done." notice