Skip to content

Commit dc89060

Browse files
authored
Happyx support (#212)
* 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, ...)
1 parent 6a54f1c commit dc89060

File tree

4 files changed

+99
-2
lines changed

4 files changed

+99
-2
lines changed

docsrc/interactivity.nim

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,53 @@ And here the problem lies: `counter_2` is generated both times we compile the bl
253253
The solution is stated above: don't name multiple separate variables the same in a `nbKaraxCode` or `nbJsFromCodeOwnFile` block!
254254
This isn't a problem for the other nbJs blocks luckily.
255255
"""
256-
nbSave
256+
nbText: hlMd"""
257+
### nbHappyxCode
258+
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.
259+
260+
The system for HappyX in nimib is analogous to the system for Karax. Note the parts of a typical Karax code block.
261+
262+
```nim
263+
template karaxExample =
264+
let x = 3.14
265+
nbKaraxCode(x):
266+
var message = "Pi is roughly " & $x
267+
karaxHtml:
268+
p:
269+
text message
270+
button:
271+
text "Click me!"
272+
proc onClick() =
273+
message = "Poof! Gone!"
274+
```
275+
Here's how it changes for HappyX:
276+
277+
"""
278+
nimibCode:
279+
template happyxExample =
280+
let x = 3.14
281+
nbHappyxCode(x):
282+
var message = remember fmt"pi is roughly {x}"
283+
happyxRoutes:
284+
"/":
285+
p:
286+
{message}
287+
tButton:
288+
"Click me!"
289+
@click(
290+
message.set("Poof! Gone!"))
291+
292+
nbText: "This is the output this code produces when called:"
293+
294+
happyxExample()
295+
296+
nbText: hlMd"""
297+
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:
298+
299+
`nbKaraxCode` becomes `nbHappyxCode` -- obviously
300+
301+
`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.
302+
303+
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.
304+
"""
305+
nbSave

nimib.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ requires "parsetoml >= 0.7.0"
1616
requires "jsony >= 1.1.5"
1717

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

2121
task test, "General tests":
2222
for file in ["tsources.nim", "tblocks.nim", "tnimib.nim", "trenders.nim"]:

src/nimib.nim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,12 @@ when moduleAvailable(karax/kbase):
217217
nbRawHtml: "<div id=\"" & rootId & "\"></div>"
218218
nbKaraxCodeBackend(rootId, args)
219219

220+
when moduleAvailable(happyx):
221+
template nbHappyxCode*(args: varargs[untyped]) =
222+
let rootId = "happyx-" & $nb.newId()
223+
nbRawHtml: "<div id=\"" & rootId & "\"></div>"
224+
nbHappyxCodeBackend(rootId, args)
225+
220226
template nbJsShowSource*(message: string = "") {.deprecated: "Use nbCodeDisplay instead".} =
221227
nb.blk.context["js_show_nim_source"] = true
222228
if message.len > 0:

src/nimib/jsutils.nim

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,48 @@ macro nbKaraxCodeBackend*(rootId: untyped, args: varargs[untyped]) =
137137

138138
result = call
139139

140+
macro nbHappyxCodeBackend*(rootId: untyped, args: varargs[untyped]) =
141+
if args.len == 0:
142+
error("nbHappyxCode needs a code block to be passed", args)
143+
let body = args[^1]
144+
let captureVars =
145+
if args.len == 1:
146+
@[]
147+
else:
148+
args[0 ..< ^1]
149+
150+
let caller = body[^1][0]
151+
if caller != ident"happyxRoutes":
152+
error(fmt "{caller} != happyxRoutes: a happyxRoutes: block must terminate the nbHappyxCode block")
153+
154+
let happyxRoutesBody = body[^1][1]
155+
156+
let preHappyxRoutes =
157+
if body.len == 1:
158+
@[]
159+
else:
160+
body[0 ..< ^1]
161+
162+
var preRoutesCode = newStmtList()
163+
for i in preHappyxRoutes.items:
164+
preRoutesCode.add(i)
165+
166+
let imports = quote do:
167+
import happyx, std/ strformat
168+
169+
let newBody = quote do:
170+
`imports`
171+
`preRoutesCode`
172+
appRoutes(`rootId`):
173+
`happyxRoutesBody`
174+
175+
var callArgs = @[rootId]
176+
callArgs.add captureVars
177+
callArgs.add newBody
178+
179+
let call = newCall(ident"nbJsFromCodeOwnFile", callArgs)
180+
result = call
181+
140182
proc compileNimToJs*(doc: var NbDoc, blk: var NbBlock) =
141183
let tempdir = getTempDir() / "nimib"
142184
createDir(tempdir)

0 commit comments

Comments
 (0)