all repos — hastysite @ 1e77065565a49f578429f3abf9dd58a44f5052a4

A high-performance static site generator.

Improved modified files detection; fixed moustachu check for empty
sections.
h3rald h3rald@h3rald.com
Sat, 25 Feb 2017 16:43:00 +0100
commit

1e77065565a49f578429f3abf9dd58a44f5052a4

parent

3a83cc4accd34c12b70fd667b70baef076995d14

5 files changed, 42 insertions(+), 250 deletions(-)

jump to
M hastysite.nimhastysite.nim

@@ -10,16 +10,10 @@ critbits,

streams, logging -when defined(nifty): - import +import packages/NimYAML/yaml, packages/minim/minim, packages/hastyscribe/hastyscribe -else: - import - yaml, - minim, - hastyscribe import vendor/moustachu,

@@ -199,6 +193,16 @@ var newChecksum = $secureHashFile(file)

obj["assets"][fileid] = %newChecksum return oldChecksum != newChecksum +proc checkTemplate(dir, file: string, obj: var JsonNode): bool = + var dir = dir & DirSep + let fileid = file.replace(dir, "") + var oldChecksum = "" + if obj["templates"].hasKey(fileid): + oldChecksum = obj["templates"][fileid].getStr + var newChecksum = $secureHashFile(file) + obj["templates"][fileid] = %newChecksum + return oldChecksum != newChecksum + proc get(json: JsonNode, key, default: string): string = if json.hasKey(key): return json[key].getStr

@@ -222,6 +226,8 @@ if not result.hasKey("contents"):

result["contents"] = newJObject() if not result.hasKey("assets"): result["assets"] = newJObject() + if not result.hasKey("templates"): + result["templates"] = newJObject() proc contentMetadata(f, dir: string, meta: JsonNode): JsonNode = result = newJObject()

@@ -279,12 +285,21 @@ hs.files.modified = newSeq[JsonNode](0)

var cs = hs.initChecksums() let contents = toSeq(hs.dirs.tempContents.walkDirRec()) let assets = toSeq(hs.dirs.assets.walkDirRec()) + let templates = toSeq(hs.dirs.templates.walkDirRec()) let assetDir = hs.dirs.assets let contentDir = hs.dirs.tempContents + let templateDir = hs.dirs.templates hs.metadata = hs.files.metadata.parseFile let meta = hs.metadata - let modContentFiles = filter(contents) do (f: string) -> bool: checkContent(contentDir, f, cs) - let modAssetFiles = filter(assets) do (f: string) -> bool: checkAsset(assetDir, f, cs) + let modTemplateFiles = filter(templates) do (f: string) -> bool: checkTemplate(templateDir, f, cs) + var modContentFiles, modAssetFiles: seq[string] + if modTemplateFiles.len > 0: + # Templates may affect all contents and assets + modContentFiles = contents + modAssetFiles = assets + else: + modContentFiles = filter(contents) do (f: string) -> bool: checkContent(contentDir, f, cs) + modAssetFiles = filter(assets) do (f: string) -> bool: checkAsset(assetDir, f, cs) let modContents = modContentFiles.map(proc (f: string): JsonNode = return contentMetadata(f, contentDir, meta)) let modAssets = modAssetFiles.map(proc (f: string): JsonNode = return assetMetadata(f, assetDir)) hs.files.modified = modContents & modAssets

@@ -320,11 +335,11 @@

when isMainModule: import - vendor/commandeer + packages/commandeer/commandeer proc usage(): string = return """ $1 v$2 - a tiny static site generator - (c) 2016 Fabio Cevasco + (c) 2016-2017 Fabio Cevasco Usage: hastysite command
M nifty.jsonnifty.json

@@ -42,6 +42,12 @@ {

"name": "minim", "git": true, "src": "https://github.com/h3rald/minim.git" + }, + "commandeer": + { + "name": "commandeer", + "src": "https://github.com/fenekku/commandeer.git", + "git": true } } }
D vendor/commandeer.nim

@@ -1,236 +0,0 @@

- -import parseopt2 -import strutils -import strtabs - - -var - argumentList = newSeq[string]() - shortOptions = newStringTable(modeCaseSensitive) - longOptions = newStringTable(modeCaseSensitive) - argumentIndex = 0 - errorMsgs : seq[string] = @[] - customErrorMsg : string - inSubcommand = false - subcommandSelected = false - - -## String conversion -proc convert(s : string, t : char): char = - result = s[0] -proc convert(s : string, t : int): int = - result = parseInt(s) -proc convert(s : string, t : float): float = - result = parseFloat(s) -proc convert(s : string, t : bool): bool = - ## will accept "yes", "true" as true values - if s == "": - ## the only way we get an empty string here is because of a key - ## with no value, in which case the presence of the key is enough - ## to return true - result = true - else: - result = parseBool(s) -proc convert(s : string, t : string): string = - result = s.strip - - -template argumentIMPL(identifier : untyped, t : typeDesc): untyped = - - var identifier : t - - if (inSubcommand and subcommandSelected) or not inSubcommand: - if len(argumentList) <= argumentIndex: - let eMsg = "Missing command line arguments" - if len(errorMsgs) == 0: - errorMsgs.add(eMsg) - else: - if not (errorMsgs[high(errorMsgs)][0] == 'M'): - errorMsgs.add(eMsg) - else: - var typeVar : t - try: - identifier = convert(argumentList[argumentIndex], typeVar) - except ValueError: - let eMsg = capitalizeAscii(getCurrentExceptionMsg()) & - " for argument " & $(argumentIndex+1) - errorMsgs.add(eMsg) - - inc(argumentIndex) - - -template argumentsIMPL(identifier : untyped, t : typeDesc, atLeast1 : bool): untyped = - - var identifier = newSeq[t]() - - if (inSubcommand and subcommandSelected) or not inSubcommand: - if len(argumentList) <= argumentIndex: - if atLeast1: - let eMsg = "Missing command line arguments" - if len(errorMsgs) == 0: - errorMsgs.add(eMsg) - else: - if not (errorMsgs[high(errorMsgs)][0] == 'M'): - errorMsgs.add(eMsg) - else: - discard - else: - var typeVar : t - var firstError = true - while true: - if len(argumentList) == argumentIndex: - break - try: - let argument = argumentList[argumentIndex] - inc(argumentIndex) - identifier.add(convert(argument, typeVar)) - firstError = false - except ValueError: - if atLeast1 and firstError: - let eMsg = capitalizeAscii(getCurrentExceptionMsg()) & - " for argument " & $(argumentIndex+1) - errorMsgs.add(eMsg) - break - - -template optionDefaultIMPL(identifier : untyped, t : typeDesc, longName : string, - shortName : string, default : t): untyped = - - var identifier : t - - if (inSubcommand and subcommandSelected) or not inSubcommand: - var typeVar : t - if strtabs.hasKey(longOptions, longName): - try: - identifier = convert(longOptions[longName], typeVar) - except ValueError: - let eMsg = capitalizeAscii(getCurrentExceptionMsg()) & - " for option --" & longName - errorMsgs.add(eMsg) - elif strtabs.hasKey(shortOptions, shortName): - try: - identifier = convert(shortOptions[shortName], typeVar) - except ValueError: - let eMsg = capitalizeAscii(getCurrentExceptionMsg()) & - " for option -" & shortName - errorMsgs.add(eMsg) - else: - #default values - identifier = default - - -template optionIMPL(identifier : untyped, t : typeDesc, longName : string, - shortName : string): untyped = - - var identifier : t - - if (inSubcommand and subcommandSelected) or not inSubcommand: - var typeVar : t - if strtabs.hasKey(longOptions, longName): - try: - identifier = convert(longOptions[longName], typeVar) - except ValueError: - let eMsg = capitalizeAscii(getCurrentExceptionMsg()) & - " for option --" & longName - errorMsgs.add(eMsg) - elif strtabs.hasKey(shortOptions, shortName): - try: - identifier = convert(shortOptions[shortName], typeVar) - except ValueError: - let eMsg = capitalizeAscii(getCurrentExceptionMsg()) & - " for option -" & shortName - errorMsgs.add(eMsg) - -template exitoptionIMPL(longName, shortName, msg : string): untyped = - - if (inSubcommand and subcommandSelected) or not inSubcommand: - if strtabs.hasKey(longOptions, longName): - quit msg, QuitSuccess - elif strtabs.hasKey(shortOptions, shortName): - quit msg, QuitSuccess - - -template errormsgIMPL(msg : string): untyped = - - if (inSubcommand and subcommandSelected) or not inSubcommand: - customErrorMsg = msg - - -template subcommandIMPL(identifier : untyped, subcommandName : string, stmts : untyped): untyped = - - var identifier : bool = false - inSubcommand = true - - if len(argumentList) > 0 and argumentList[0] == subcommandName: - identifier = true - inc(argumentIndex) - subcommandSelected = true - - stmts - - subcommandSelected = false - inSubcommand = false - - -template commandline*(statements : untyped): untyped = - - template argument(identifier : untyped, t : typeDesc): untyped = - argumentIMPL(identifier, t) - - template arguments(identifier : untyped, t : typeDesc, atLeast1 : bool = true): untyped = - argumentsIMPL(identifier, t, atLeast1) - - template option(identifier : untyped, t : typeDesc, longName : string, - shortName : string, default : untyped): untyped = - optionDefaultIMPL(identifier, t, longName, shortName, default) - - template option(identifier : untyped, t : typeDesc, longName : string, - shortName : string): untyped = - optionIMPL(identifier, t, longName, shortName) - - template exitoption(longName, shortName, msg : string): untyped = - exitoptionIMPL(longName, shortName, msg) - - template errormsg(msg : string): untyped = - errormsgIMPL(msg) - - template subcommand(identifier : untyped, subcommandName : string, stmts : untyped): untyped = - subcommandIMPL(identifier, subcommandName, stmts) - - for kind, key, value in parseopt2.getopt(): - case kind - of parseopt2.cmdArgument: - argumentList.add(key) - of parseopt2.cmdLongOption: - longOptions[key] = value - of parseopt2.cmdShortOption: - shortOptions[key] = value - else: - discard - - #Call the passed statements so that the above templates are called - statements - - if len(errorMsgs) > 0: - if not customErrorMsg.isNil: - errorMsgs.add(customErrorMsg) - quit join(errorMsgs, "\n") - - -when isMainModule: - import unittest - - test "convert() returns converted type value from strings": - var intVar : int - var floatVar : float - var boolVar : bool - var stringVar : string - var charVar : char - - check convert("10", intVar) == 10 - check convert("10.0", floatVar) == 10 - check convert("10", floatVar) == 10 - check convert("yes", boolVar) == true - check convert("false", boolVar) == false - check convert("no ", stringVar) == "no" - check convert("*", charVar) == '*'
M vendor/moustachu.nimvendor/moustachu.nim

@@ -115,8 +115,12 @@ index = ignore(token.value, tokens, index)

continue elif ctx.kind == CObject: # enter a new section - contextStack.add(ctx) - sections.add(token.value) + if ctx.len == 0: + index = ignore(token.value, tokens, index) + continue + else: + contextStack.add(ctx) + sections.add(token.value) elif ctx.kind == CArray: # update the array loop stacks if ctx.len == 0:
M vendor/moustachupkg/context.nimvendor/moustachupkg/context.nim

@@ -164,7 +164,10 @@ else:

return "" proc len*(c: Context): int = - if c.kind == CArray: result = c.elems.len + if c.kind == CArray: + result = c.elems.len + elif c.kind == CObject: + result = c.fields.len else: discard converter toBool*(c: Context): bool =