Last active
February 3, 2020 18:05
-
-
Save Vindaar/683e783ca2a61c99651eee2fc09523b1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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