Skip to content

Commit

Permalink
Happyx support (#212)
Browse files Browse the repository at this point in the history
* Update jsutils.nim

create backend for happyx: API is analogous to karax backend but since happyx uses Jester-style routing syntax in the front-end DSL, we use happyxRoutes instead of happyxHtml

* Update nimib.nim

create block for embedding happyx code analagously to the one for embedding karax code

* Update interactivity.nim

Added example for happyX to parallel one for karax.  Also gave  a brief explanation of the problem with syntax like @click: ...
and why @click() was used instead.

* Update nimib.nimble

**reminder**: this is planned to be moved in nimibex sometime in the future (along with nbKarax, nbPython, ...)
  • Loading branch information
quimt authored Aug 16, 2023
1 parent 6a54f1c commit dc89060
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 2 deletions.
51 changes: 50 additions & 1 deletion docsrc/interactivity.nim
Original file line number Diff line number Diff line change
Expand Up @@ -253,4 +253,53 @@ And here the problem lies: `counter_2` is generated both times we compile the bl
The solution is stated above: don't name multiple separate variables the same in a `nbKaraxCode` or `nbJsFromCodeOwnFile` block!
This isn't a problem for the other nbJs blocks luckily.
"""
nbSave
nbText: hlMd"""
### nbHappyxCode
HappyX is an emerging alternative to Jester (on the back-end) and Karax(on the front end). It aims to streamline the syntax for writing full-stack applications and to allow more flexibility in its single page applications, which use a routing mechanism to switch between different pages for the app. It is being actively developed and some of the syntax for the DSL may change, so the introduction will be brief.
The system for HappyX in nimib is analogous to the system for Karax. Note the parts of a typical Karax code block.
```nim
template karaxExample =
let x = 3.14
nbKaraxCode(x):
var message = "Pi is roughly " & $x
karaxHtml:
p:
text message
button:
text "Click me!"
proc onClick() =
message = "Poof! Gone!"
```
Here's how it changes for HappyX:
"""
nimibCode:
template happyxExample =
let x = 3.14
nbHappyxCode(x):
var message = remember fmt"pi is roughly {x}"
happyxRoutes:
"/":
p:
{message}
tButton:
"Click me!"
@click(
message.set("Poof! Gone!"))

nbText: "This is the output this code produces when called:"

happyxExample()

nbText: hlMd"""
There are many differences worth noticing, like use embedding of `fmt`'s `{}` to make a text node from data or the more prolific use of the prefix `t` before html tags (which is stylistic, as it's an optional disambiguator in happyX. The key thing to get you going, though, is that:
`nbKaraxCode` becomes `nbHappyxCode` -- obviously
`karaxHtml` becomes `happyxRoutes` -- this is due to differences in the DSLs. Karax uses a `buildHtml()` macro directly when creating VNodes and components. Happyx, on the other hand, enters into the front end DSL with an `appRoutes()` macro since the blocks beneath it like `"/":` define the different routes or 'subpages' of the app. So `happyxRoutes` imitates the `appRoutes` that it is meant to replace.
There is **one other note for users of happyX**. The event handlers beginning in `@` must be called unambiguously. The more normal block declaration with `:` will not work in the current commit. HappyX does some massaging with its macros to make the syntax work in either case but plain Nim doesn't recognize `@click: <do stuff>` as a call. The best strategy for resolving the inconsistency hasn't been decided yet, and a potential refactor as happyX continues development may resolve it spontaneously.
"""
nbSave
2 changes: 1 addition & 1 deletion nimib.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ requires "parsetoml >= 0.7.0"
requires "jsony >= 1.1.5"

task docsdeps, "install dependendencies required for doc building":
exec "nimble -y install [email protected] [email protected] nimoji nimpy [email protected]"
exec "nimble -y install [email protected] [email protected] nimoji nimpy [email protected] [email protected]"

task test, "General tests":
for file in ["tsources.nim", "tblocks.nim", "tnimib.nim", "trenders.nim"]:
Expand Down
6 changes: 6 additions & 0 deletions src/nimib.nim
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@ when moduleAvailable(karax/kbase):
nbRawHtml: "<div id=\"" & rootId & "\"></div>"
nbKaraxCodeBackend(rootId, args)

when moduleAvailable(happyx):
template nbHappyxCode*(args: varargs[untyped]) =
let rootId = "happyx-" & $nb.newId()
nbRawHtml: "<div id=\"" & rootId & "\"></div>"
nbHappyxCodeBackend(rootId, args)

template nbJsShowSource*(message: string = "") {.deprecated: "Use nbCodeDisplay instead".} =
nb.blk.context["js_show_nim_source"] = true
if message.len > 0:
Expand Down
42 changes: 42 additions & 0 deletions src/nimib/jsutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,48 @@ macro nbKaraxCodeBackend*(rootId: untyped, args: varargs[untyped]) =

result = call

macro nbHappyxCodeBackend*(rootId: untyped, args: varargs[untyped]) =
if args.len == 0:
error("nbHappyxCode needs a code block to be passed", args)
let body = args[^1]
let captureVars =
if args.len == 1:
@[]
else:
args[0 ..< ^1]

let caller = body[^1][0]
if caller != ident"happyxRoutes":
error(fmt "{caller} != happyxRoutes: a happyxRoutes: block must terminate the nbHappyxCode block")

let happyxRoutesBody = body[^1][1]

let preHappyxRoutes =
if body.len == 1:
@[]
else:
body[0 ..< ^1]

var preRoutesCode = newStmtList()
for i in preHappyxRoutes.items:
preRoutesCode.add(i)

let imports = quote do:
import happyx, std/ strformat

let newBody = quote do:
`imports`
`preRoutesCode`
appRoutes(`rootId`):
`happyxRoutesBody`

var callArgs = @[rootId]
callArgs.add captureVars
callArgs.add newBody

let call = newCall(ident"nbJsFromCodeOwnFile", callArgs)
result = call

proc compileNimToJs*(doc: var NbDoc, blk: var NbBlock) =
let tempdir = getTempDir() / "nimib"
createDir(tempdir)
Expand Down

0 comments on commit dc89060

Please sign in to comment.