Small code org question for the squint repo. I really like the simplicity of your squint playground and was going to fork/copy it. After looking at the code I notice that there is the squint.edn , vite and other config file but that none of them seem to be used or necessary and that most of the commits are directly against the public/js/main_js.mjs as opposed to the cljs file. I suppose I was wondering which direction you evolving towards - e.g. total use of js in MJS or a squint compilation step before loading.
code link here https://github.com/squint-cljs/squint/tree/main/playground
( Also if you are def heading one way or the other I'd be happy to work on it )
I think the .mjs code started small and then grew out of proportion ;)
next time I'd start in squint probably, but it's kind of done now
hey guys i played around with snabbdom cause i was thinking about building a framework around this virtual dom implementation due to the fact that it only does the rendering part nothing more. And i was curious if i could it working with squint and jsx syntax and what should i say it works like a charm. So here is a little gist if you would be interested in how it would work for you https://gist.github.com/m3tti/7d5bf262b952df4f9059c772ea361449
@borkdude somehow snabbdom uses the props to transfere classnames do you know if it would be possible for the #jsx meta to produce something like that i'm currently figuring out why it does that but this look ugly if you use it with hiccup style 😄
(render (js/document.getElementById "app")
#jsx [:div {:props {:className "reveal"}}
[:div {:props {:className "slides"}}
[:section "Hello"]
[:section "World"]]])in squint JSX you can write [:div.reveal ...] to generate a class on the JSX, but I don't know why snabbdom expects it in a different way?
yeah i'm currntly trying to figure it out i was thinking about leveraging it to create something like the elm architecture but for squint 😄
i guess i can write a helper function to traverse the vector on my own and generate the stuff but you know i'm lazy 😄
but than if i do it you don't even need to transpile the jsx 🤔
perhaps their "just use a function to produce a dom node" isn't too bad?
yeah i'm working on something where you can still paste "hiccupy" syntax and it produces the functions
or better calls the functions
cause you have to use the newly created vnode with patch
so patch gives you a new vnode and this has to be used in the next patch
aren't I passing the new vnode?
oooh like that
one way or
thanks
👍
so in general the idea afaik 😄 is that you define the new dom and use patch create the new dom and than overwrite it as soon as you want to do something
makes sense
i like it cause i'm a simple man and now you are free to create something on your own 😄 and the dom patching is done for you
there is even a repo that has the elm architecture allready but i don't like it 😄 cause its not clojuresq enough 😄
i would like to use atoms and build something with that and messages so basically just keywords that trigger functions (maybe?)
yeah
btw before that i'm playing with reveal js 😄
and snabbdom 😄 would be cool to have something like defslide and drop some html code there
so you can do a talk on borkweb or squint? ;)
exactly if i'm once that proficient that i have something to tell thats at least as interesting as stuff you do
I heard a podcast about htmx and they talked about a library called "morph" or something. Are you familiar with it?
NOT YET 😉
right
and datastar must be using something like that too
yeah datastar look pretty cool but had to little time lately to really look into it but it looks quite promising
OK
Idiomorph.morph(existingNode, "<div>New Content</div>");
that looks cool i guess the #html can be handy hereone of the datastar authors is also in here: https://clojurians.slack.com/archives/C03U8L2NXNC/p1745366662164029?thread_ts=1740906547.043039&cid=C03U8L2NXNC
borkweb is still my number one thing i want to get better but after playing also a lot with bun and squint i'm also looking into something for clojurescript. I was inspired by #defnpodcast where they talked once that clojure is settled on react and that there is nothing "clojure native" for spas so why not trying to build something 😄
#replicant is AFAIK react-free and works kinda like react, but not exactly sure. the author @christian767 has also been on several podcasts
oh he mentions snabbdom in the README: > https://github.com/snabbdom taught me that components are not a necessary feature of a virtual DOM renderer. Life-cycle hooks can just as easily be attached to DOM nodes.
Yes, I made https://github.com/cjohansen/dumdom before I made Replicant. Dumdom is based on snabbdom. I wrote Replicant because I wanted something pure Clojure(Script) 🙂
cool so in general its the same idea as far as i see
which is really cool cause the rendering is one part but the architecture and updating mechanism is another
Replicant is roughly "React in ClojureScript", except it only does rendering, and does not allow component-local state. I wrote kind of a lot about it at https://replicant.fun 😅
@christian767 I must admit that I've listened to at least one or more podcasts about replicant, but I still can't remember how replicant does efficient updates to the dom
It basically implements a vdom-style diffing algorithm
It stores a representation of the rendered DOM, and on the next render, it diffs your hiccup against what's already rendered
so closer to snabbdom than the idiomorph stuff
Probably - given that I know nothing about idiomorph 😅
we discussed it briefly above. idiomorph doesn't use vdom, just direct dom
it's part of htmx
Aha, I see
You're right then 🙂
Thanks for coming all the way to this channel btw :)
You summoned me, of course I show up 😄
thank you @christian767 for clarifying and showing up 😄
shadow-cljs also has something "native" right? are you aware of this and does it use a similar approach?
Yes, https://github.com/thheller/shadow-grove is an even more true "Clojure-native React". I wasn't aware of it when I started working on Replicant.
I think shadow-grove basically supports all of what React supports, while Replicant is more narrow and opinionated.
and replicant has a better marketing department :)
Hehe 😄
I suspect shadow-grove has actively not been marketed
The marketing will continue until morale improves!
Yes, keep going with it, you're doing a great job :)
Thanks 😊
so one simple question 😄 how hard would it be to transfere replicant to squint 😄
I don't know enough about Squint to answer that, but the code is just cljc without any dependencies, if that helps.
he that would mean it could just work right @borkdude
Replicant can just run in ClojureScript alone right? without any server component. Perhaps it's possible to transfer it to squint then, although data structures in squint are just JS data structures, no immutable collection like CLJS. I guess that would break things, since you can't easily diff them like in CLJS?
Maybe put it another way: if you would rewrite replicant in pure JS, would there be any challenges?
Replicant runs fine in ClojureScript, no server needed. But yes, it does rely quite a bit on comparing data structures.
If it can't diff compare data, it will end up doing more work than necessary, but it should still technically work. It might get very slow.
I mean, (= data1 data2) doesn't work like you'd expect from CLJS in squint
you could use immutable.js for this but that would maybe defeat the purpose
right
Yeah, I lurk... if you have any D* questions happy to answer
I've been thinking alot about being used for webcomponents lately
So yes we started with idiomorph, in fact it's been the default since the first commit. However we've worked with the Turbo guys and thoses that have taken over the idiomorph. In the v1 coming out soon we have our on version that's about 60% smaller and about 3.5x faster.
Stuck on macros. Looks like my compiled macro namespace retains fns from clojure core. I would appreciate any pointers/examples.
git clone
cd squint-mol
npm i
npx squint compile
node dist/mvsj/tests.mjs
squint-mol % node dist/mvsj/tests.mjs
file:///Users/zcpowers/Downloads/squint-mol/dist/mvsj/core.mjs:33
const G__209 = ({ "kind": clojure.core.name(name176) });
^
ReferenceError: clojure is not definedre: (mapv nodize ~children-sym)
you can't use a macro as a higher order function, it must always appear in call position
but if you can do it with a function, even better
I'm going to try a few simple macros first. One issue I have is that I amtrying to be recursive (see nodize on last line ) :
(defmacro nodize
"Transforms a hiccup-like vector [:name props children] into a node map."
[form]
(let [name-sym (gensym "name")
props-sym (gensym "props")
children-sym (gensym "children")]
`(let [[~name-sym ~props-sym ~children-sym] ~form]
(cond-> {"kind" (name ~name-sym)}
(not (empty? ~props-sym)) (assoc "params" ~props-sym)
(seq ~children-sym) (assoc "children" (mapv nodize ~children-sym))))))also thinking this can be a fn which makes the compilation simpler...
fns to the rescue: Okay this is simple and works great. back the main project! 🙂
(defn nodize
"Transforms a hiccup-like vector [:name props children] into a node map."
[form]
(let [[name-val props-val children-val] form]
(cond-> {"kind" name-val}
(not (empty? props-val)) (assoc "params" props-val)
(seq children-val) (assoc "children" (mapv nodize children-val)))))
[mvsj.macros :refer [nodize]]))
(assert (=
(str (nodize [:test {:param 1} []]))
(str {:kind "test" :params {:param 1}})))
(assert (=
(str (nodize [:test {:param 1} [[:test2 {:param 2}]]]))
(str {:kind "test" :params {:param 1} :children [{:kind "test2" :params {:param 2}}]})))