Skip to content

Instantly share code, notes, and snippets.

@Vindaar
Last active February 3, 2020 18:05
Show Gist options
  • Save Vindaar/683e783ca2a61c99651eee2fc09523b1 to your computer and use it in GitHub Desktop.
Save Vindaar/683e783ca2a61c99651eee2fc09523b1 to your computer and use it in GitHub Desktop.
import strformat
import karax / [karaxdsl, vdom]
# want to use this like so
# linkItem:
# a(href="/"): text "Main Page"
template linkItem(body: untyped): VNode =
buildHtml(li(class="hover:underline text-center")):
h4:
li: body
proc layout(inner : VNode) : string =
let vnode = buildHtml(html):
head:
meta(charset="utf-8")
link(href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css", rel="stylesheet")
body:
tdiv(class=""):
inner
"<!DOCTYPE html>\n" & $vnode
import macros, options, sequtils
proc isMagic(name, stmts: NimNode, magics: seq[string]): Option[(NimNode, NimNode)] =
## If `name` is a magic, we return a `some` of a temporary var with the
## magic evaluated and the temporary symbol
if name.repr in magics:
let tmp = genSym(nskLet, "tmp")
let replaced = quote do:
let `tmp` = `name`:
`stmts`
# and the new replacement is `tmp`
result = some((replaced, tmp))
else:
result = none[(NimNode, NimNode)]()
proc findMagics(n: NimNode, magics: seq[string]): (NimNode, NimNode) =
## checks each child of `n` for magics. Returns a `StmtList` of temporaries
## and a body with magics replaced by those temporaries
result[1] = copyNimTree(n)
result[0] = newStmtList()
var i = 0
for ch in n:
case ch.kind
of nnkCall:
let maybeMagic = isMagic(ch[0], ch[1], magics)
if maybeMagic.isSome:
let magic = maybeMagic.get
result[1][i] = magic[1]
result[0].add magic[0]
else:
var tmp = findMagics(ch, magics)
result[1][i] = tmp[1]
result[0].add tmp[0]
else:
var tmp = findMagics(ch, magics)
result[1][i] = tmp[1]
result[0].add tmp[0]
inc i
macro customBuildHtml(arg: untyped, magics: varargs[typed], body: untyped): untyped =
## first expands the code blocks of all `magics`, puts them into
## temporary variables, which are then inserted into the appropriate places.
## Finally calls `buildHtml`
let (tmps, replacedNodes) = findMagics(body, magics.mapIt(it.repr))
result = quote do:
`tmps`
buildHtml(`arg`, `replacedNodes`)
proc tweetThread*(author : string,
tweets : seq[string]): string =
let title = fmt"Thread by {author}"
let vnode = customBuildHtml(tdiv, linkItem):
h4: text title
ul:
linkItem:
li: a(href="/"): text "Main Page"
li: a(href=fmt"/author/{author}/threads"): text (fmt"See all of {author}'s threads")
ul:
for tweet in tweets:
li: text tweet
result = $vnode.layout
proc checkBack*() : string =
let vnode = buildHtml(tdiv):
h4: text "Check back later please"
result = $vnode.layout
proc listThreads*(author : string,
threads : seq[string]) : string =
let title = fmt"Threads for {author}"
let vnode = buildHtml(tdiv):
a(href="/"): text "Main Page"
h4: text title
ul:
for thread in threads:
li: a(href=fmt"/thread/{author}/status/{thread}"): text thread
result = $vnode.layout
# Main page
proc listAuthors*(authors : seq[string]) : VNode =
let title = "Authors"
let vnode = buildHtml(tdiv):
h1(class="uppercase text-center"): text title
ul:
for author in authors:
li:
a(href = fmt"/author/{author}/threads"):
text author
result = vnode
proc submitThread() : VNode =
let vnode = buildHtml(tdiv):
form(action = "/thread", `method`="POST", class="submit-thread"):
tdiv:
label(`for`="tweetUrl"):
text "Tweet URL"
input(`type`="text", name="tweetURL", id="tweeturl", required="true")
result = vnode
proc mainPage*(authors : seq[string]) : string =
let vnode = buildHtml(tdiv):
listAuthors(authors)
submitThread()
result = $vnode.layout
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment