-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compiling nim to javascript #88
Conversation
I've been able to get a Karax template to work by doing the import std/random
template karaxButton() =
echo "CReating a new button!"
block:
let root {.inject.} = "root" & $rand(int.high)
nbRawOutput: """<div id="$1"></div>""" % [root]
let script = nbNewCode: hlNim"""
include karax / prelude
"""
script.addCode(root):
var counter = 0
proc createDom(): VNode =
result = buildHtml(tdiv):
p:
text "Hello world"
label:
text "Counter: " & $counter
button:
text "Click me (karax)"
proc onClick() =
counter += 1
setRenderer(createDom, root=root.cstring)
script.addToDocAsJs() The problem I have though which I didn't have in the raw-dom example at the top, is that the So it's partially working if you don't have any global variables that you update. |
Upon further experimenting by adding a third button to the first example is also exhibiting this same behavior. The reason it didn't at first was that for some reason the first time we call the macro the code is treated as untyped but the second time as typed. And this resulted in two slightly different codes which had different names in the js. But adding a third button made the second and third button share the same names in the js. So we will have to do some manual name mangling ourselves to make this work. The complicating part is that we only have a string in the end and not the AST anymore. |
Well, one thing is that we could make explicit the limitation that you could have a single js or Karax section in the page and you should have all the logic there. Another option that comes to mind (but I know very little about this and not so sure if it would work) is to see if an iframe would work in sandboxing different parts of JavaScript (found this ref, have not had time to read it in detail: https://web.dev/sandboxed-iframes/) |
That is way too limiting in my eyes, plus for Karax to work we have to compile the different blocks in separate files for them to get their own Karax instances (it was just recently implemented support for this, see karaxnim/karax#221). So putting them each into a block doesn't work (I've tried and only one of them rendered).
Perhaps, but I have an idea for how to do the mangling. It involves a CT table to keep track of the variable names for all variables in a specific script. And then when a new script is created the table is reset. This way we would keep the flexibility but isolate each script. |
My solution actually seems to work 🤯 Now Karax should be fully working (if used with string imports and includes). |
@pietroppeter Now we can start discussion namings and where to put this code. Do you have any preferences? |
Wow! I will need to digest that a moment in order to get reasonable advice on naming and stuff. You know that merging this makes you an official maintainer now? ;) I will need you to get whatever rights you need for the repo (or we could move this and other repos to a nimib organization). Anyway, let me get to basics. The feature we want to provide with this is a way to embed Nim derived js scripts in a page AND this would work also for Karax's framework, correct? Can you add an example doc (or more than one if it works better) where we can see both in action (standard Nim to js and an example with Karax)? You should in this case merge current master (or rebase on top of it) so that you have the new structure where the example sources for docs are in docsrc. |
My only idea so far is that the templates are still kept in
What?! :O What an honor! 😄 Or does this just mean I can't just dump my code here and expect you to maintain it for me? 🤣
Exactly! Allowing us to finally add interactive elements to the output without inlining javascript (nor HTML). If you want to add a button that does something, this is exactly what you should use.
Will do! Does it suffice if I add the counter buttons I have shown here or do you want to add something more spectacular as well? 😄 I don't have anything specific in mind but if you do, I could try implementing it. |
agree on that. the non essential (non public api) should be moved to a on naming:
I would also make another change and use the standard I still have to review more but ideally I would try to avoid as possible adding other global objects, for example I am missing at the moment what is the role of
well, yeah. Once we merge this I would definitely need your help in maintaining it (as it is indeed the case for nimibCodeAsSource) so let's make it official :) regarding not being recognized for originating nimib I do not care very much and I see the project as long term sustainable only if others join the effort.
I have seen you already added an interactivity document that looks fine, maybe too many details in there but we can streamline it later. The counter examples are fine, it could be a |
Those names and structure sounds good to me 👍
Yes, that sounds like a good idea. So
I'm not sure what you mean here. Or I think you mean that we want this to work: nbCode:
nbCodeToJs:
echo "Hello world!" but I'm not sure how this would help. For example, if we do: nbCode:
nbText: "Hello world" The output I get is neither a code block nor a text block but the
So nestability of blocks doesn't work regardless.
I agree that using a global variable isn't good in this case. Building upon the
💯 Sounds like a good plan and wise words👌 I'll happily help out where I can.
Hehe yeah I wasn't sure how much to say about the details, especially since |
yes, correct
yes, nestability of blocks is a separate issue. what I meant is that we could provide a nbCodeToJs:
discard
nbCodeToJsShowSource and the implementation could be something like this part (to be added in doc.partials["nbCodeToJs"] = """
{{>nbJsScriptNimSource}}
{{>nbJsScript}}"""
doc.partials["nbJsScriptNimSource"] = "{{#js_show_nim_source}}{{>nbCodeSource}}{{/js_show_nim_source}}"
doc.partials["nbJsScript"] = "<script>{{&output}}</script>" (note: you will need to highlight nim code) and this part: template nbCodeToJsShowSource =
nb.blk.context["js_show_nim_source"] = true
ah yes, probably better! in principle as an id you could even take
even better :) |
Ah ok, then I understand what you mean. Thanks for the tips :D
If two scripts are created right after each other and then the I'll start implementing all this tomorrow |
You are right about that. Getting back to this PR. We agree that theme we do it later? For the name we could use:
|
No you just are thinking in less convoluted ways than me often. I'm making things a bit took complicated to what they have to be sometimes :D
Yes, the theme can come later. But tbh I actually prefer the autostyling of water.css over manually having to assign classes using bulma (the CSS framework included by karun).
Yes, that sounds about right. And if we want to add Btw, I got the use-case for which I wanted to create all of this working now. |
TODO (I've found a few bugs):
|
It feels kinda pointless to have tests that aren't run by the CI because it doesn't have karax installed. Would you mind if I added so |
Yes sure |
If it passes the build now and the resulting pages seem to function as they should, I'd say it's finished now 🎊 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor points
fix typo "iqbqt" Co-authored-by: Pietro Peterlongo <[email protected]>
checked everything and also gave a quick read on the docs preview to see if there were regression. everything seems fine. |
Did the same and everything seems fine. Yes it has been fun and we have more fun to await now that we have the power of javascript at our fingertips. What an honor! ❤️ Which method of merging do you prefer for PRs? Saw that it was 54 commits so perhaps squashing is the best option? |
yes, squash and merge (for any PR in general) |
Said and done! That felt nice 🥳🎉 |
fixes #85 (last step before tagging and releasing) - improve changelog - make sure all important changes (recent and older) are documented details: - [x] improving changelog and integrating thanks in changelog - [x] 0.1 - [x] 0.1.x - [x] 0.2 - [x] 0.2.x - [x] 0.3 - [x] move changelog to separate file - [x] improve documentation for some of the recent changes (from 0.2.0 until now) - [x] stuff in 0.2.0 that went un(der)documented - [x] add list of command line options generated with `nbInit` - [x] changes in 0.2.x - [x] 0.2.2: nbFile - [x] other 0.3 improvements by Hugo #80 - [x] nbRawOutput - [x] nbClearOutput - [x] release 0.3 stuff #81 - [x] newNbCodeBlock - [x] newNbSlimBlock - [x] new nbTextWithCode that does read code - [x] example files.nim for File - [x] nbPython # 83 - [x] nbInitPython and nbPython - [x] nim to javascript #88 - added a section - [x] nbCodeToJs (or by pieces nbInitToJs, addCodeToJs, addToDocAsJs) - [x] nbKaraxCode - [x] CodeAsInSource now the default: - [x] remove bullet point in API section - [x] add section "Code Capture" - [x] make sure to rerun nimble readme to have readme updated (currently missing the interactivity docs) - [x] other changes - [x] turned off warning for unused imports in `nimib.nim` (#103) - [x] fix md output of index.nim (bug in markdown backend?) - some other improvements that could be done later: #110
This is still bit of a mess but it's a somewhat working mess at least. Here's a fully working example:
Feedback is welcome 😄 Especially on where to put all of this code, it feels like it deserves it's own file to not clutter
nimib.nim
TODO
std /
in imports nim-lang/Nim#19904 I think) Can be worked around by usingnbNewCode
API with string"include karax / prelude"
and adding body withscript.addCode
. Manually importing all karax modules does work, it's only the include which isn't working.Pietroppeter's suggestions
nimib/jsutils
nbCodeToJs
,nbCodeToJsInit
,addCodeToJs
,addToDocAsJs
.NbBlock
instead ofNbCodeScript
nbCodeToJsShowSource
which should change a switch to show the Nim code.kxi_id
instead of global counter. (define a nimib-specific rng innbInit
)randomCounter
anymore, just check if key in cachetable and reuse it.counters.nim
showcasing reusable widgetscaesar.nim
showcasing input handling