nextjournal

mkvlr 2021-10-08T08:56:28.002400Z

Hey ๐Ÿ‘‹ Sorry for the long wait. Clerk is finally ready for testing! See https://nextjournal.com/mk/clerk-preview for how to get started.

mkvlr 2021-10-08T08:58:59.003700Z

I still would like to polish it a bit and open source it then. In the meantime https://clojars.org/io.github.nextjournal/clerk. The quickest way to try it out is to clone the http://github.com/nextjournal/clerk-demo.

๐ŸŽ‰ 7
dgb23 2021-10-08T09:06:24.005Z

this is so incredibly simple and cool, canโ€™t wait to try it out! one obvious use-case would be to use this for documentation, examples and tutorials.

๐Ÿ–ค 2
dgb23 2021-10-08T09:08:48.006600Z

There are a bunch of developers around here who have uploaded example/starter repositories on github and are interested in teaching and guidance to some degree or another. I think this might be a very valuable tool for these use-cases.

borkdude 2021-10-08T09:10:34.007Z

yeah, I look forward to using this for docs

โž• 1
mkvlr 2021-10-08T09:11:51.007700Z

not yet documented but Clerk also supports generating a static html bundle, hereโ€™s an example https://storage.googleapis.com/nextjournal-cas-eu/data/8VwPbq6xWQadigCghK7KH5Q3WhUdCNU1d3LCgBnDNUJPyNH1Qw1JfDGFcBmCodHTY8rQDZDTS6UobY3dTLw4suxpGK

1
borkdude 2021-10-08T09:14:38.008600Z

@mkvlr Github doesn't allow you to embed this kind of stuff directly in a README right, so you would have to use Github pages for docs I guess?

borkdude 2021-10-08T09:14:53.008800Z

Perhaps cljdoc can play a role here

mkvlr 2021-10-08T09:17:09.009400Z

@borkdude yep, Clerk should obviously generate its own homepage ๐Ÿ˜ผ

dgb23 2021-10-08T09:22:01.010800Z

never used github pages, but I was under the impression that it doesnโ€™t do a build-step and you are supposed to check in the compiled (html) target?

borkdude 2021-10-08T09:37:30.011100Z

yeah, I think that would be the way to go

2021-10-08T10:17:15.011700Z

I tried it quickly and first impression was good.

2021-10-08T10:18:17.012800Z

I put it into docker now, and was wondering which port is needed for websocket to work ? I get the 7777 forwarded, but I hnk I need to open as well for websocket

mkvlr 2021-10-08T10:32:43.014100Z

@carsten.behring websocket is using the same port and address. You should see the connection code in the page source const ws = new WebSocket(document.location.origin.replace(/^http/, 'ws') + '/_ws')

mkvlr 2021-10-08T10:43:42.014400Z

would appreciate a RT https://twitter.com/mkvlr/status/1446425912321392640

2021-10-08T11:35:50.016300Z

I saw that

(def x (make-very-large-map)) 
will render the map. Can I prevent this ?

mkvlr 2021-10-08T11:55:45.018100Z

@carsten.behring are you sure? it should only render the first 20 elements. If not, it's a bug. Not at the computer atm so I can't check.

2021-10-08T12:03:03.022500Z

Ok , I have not tried with a normal "map". I have used with a "dataset", which is a custom deftype, representing a columnar table. It implements a lot of standart Clojure interfaces, so in this sense it is a map. https://github.com/techascent/tech.ml.dataset/blob/a730e652117bb538e9ba5b4513a3a0cb29384765/src/tech/v3/dataset/impl/dataset.clj#L125 It is "big".... I would never think about "printing" it in a browser. So doing "(def x .....) of one of it (reading it from a csv file, for example) will try to show it in the browser. It behaves ok in a repl, because it implements some stuff to be repl friendly

mkvlr 2021-10-08T12:13:55.025Z

ok, in that case it's not a map in the map? sense? This should be a good example for a custom viewer, will look into this when I'm back at my computer later

2021-10-08T12:19:09.025200Z

It is a "map?"

2021-10-08T12:19:40.025600Z

It implements java.util.Map

2021-10-08T12:19:50.025900Z

I tired a custom viewer.

2021-10-08T12:20:05.026300Z

But what should be the predicate ?

2021-10-08T12:20:34.026900Z

We have a clojure fn "dataset?", but that does not run in sci.

2021-10-08T12:23:49.027700Z

In "reality" I want to have this result in browser, for example:

(->
 (tc/dataset "data/AOP non dogmatic. KE4dev5 210928.xlsx" {:key-fn csk/->kebab-case-keyword})
 (tc/column-names data))

2021-10-08T12:24:01.028Z

so just the column names.

2021-10-08T12:24:35.028700Z

But usualy, I define the data instance first via def

2021-10-08T12:25:09.029Z

(def data
  (tc/dataset "data/AOP non dogmatic. KE4dev5 210928.xlsx" {:key-fn csk/->kebab-case-keyword}))

(->
 data 
 (tc/column-names data))

2021-10-08T12:26:27.030300Z

I will try some more things. It is for sure an edge case (large data structure, but implementing most clojure standard interfaces)

2021-10-08T12:26:54.030600Z

Currently it "hangs"

mkvlr 2021-10-08T12:37:49.031200Z

I'll take a look in a bit

2021-10-08T12:49:04.032300Z

Thanks.

mkvlr 2021-10-08T12:57:35.033Z

@carsten.behring do you have a minimal repro for me maybe? deps.edn + a code snippet?

2021-10-08T13:01:36.033200Z

deps.edn: org.clojure/clojure {:mvn/version "1.10.3"} io.github.nextjournal/clerk {:mvn/version "0.1.164"} scicloj/tablecloth {:mvn/version "6.012"}

๐Ÿ™ 1
2021-10-08T13:01:42.033400Z

notebook:

2021-10-08T13:01:44.033600Z

(require '[tablecloth.api :as tc] '[tech.v3.dataset.impl.dataset :refer [dataset?]] '[tech.v3.libs.fastexcel] '[nextjournal.clerk :as clerk] '[camel-snake-kebab.core :as csk]) (def data (tc/dataset "data/AOP non dogmatic. KE4dev5 210928.xlsx" {:key-fn csk/->kebab-case-keyword})) (-> data (tc/column-names data))

2021-10-08T13:02:01.033900Z

the file to load can be any csv or xlsx file

2021-10-08T13:02:47.034300Z

(inlining 'data' will make it work)

2021-10-08T13:03:07.034700Z

as then the data is never printed in browser

mkvlr 2021-10-08T13:28:13.035500Z

@carsten.behring thanks, seems to work ok here, notice that the values are only partially loaded

๐Ÿ‘€ 1
๐Ÿ™‚ 1
2021-10-08T14:06:09.039700Z

So had a quick play. All the notebooks render nicely for me except how-clerk-works which had no access to next.jdbc and weavejester dependency. Added some likely looking lines to deps.edn- this leads to SQL error or missing database (no such table: tracks)

2021-10-08T14:12:39.041100Z

Commenting out 59-63 fixes the issue at the cost of losing the query-results function

mkvlr 2021-10-08T14:14:45.042200Z

the rendering error with the dependency graph is something I still need to look into, now need to enjoy a bit of the โ˜€๏ธ

๐Ÿ‘ 1
Daniel Slutsky 2021-10-08T18:58:29.050400Z

Hi, I'm enjoying Clerk very much! ๐Ÿ™ Also, the code is nice and enlightening. One question, looking at the code: I see that nextjournal.clerk.webserver/broadcast! can be used to update all clients with all the values to be viewed. Is it possible to broadcast a partial update, without passing all the values? This can affect the experience when some values are big data structures. (In Notespace we handle it by broadcasting not the actual values but rather some corresponding ids. Then, the client can check which ids are new, and request the server for the corresponding actual values.) (Another approach is representing everything as Datascript transactions. The Literate tool by @pedrorgirardi does that, and it is amazingly simple and elegant. https://github.com/pedrorgirardi/literate .)

mkvlr 2021-10-08T19:05:28.053300Z

@daslu great to hear, thanks! Regarding the broadcasting of large values: for results Clerk doesnโ€™t send the whole to the client, but only ids (hash of the content) and a description of the values (the shape, viewers and counts). Then the client fetches the data it wants to display and only if the data changed.

Daniel Slutsky 2021-10-08T19:20:19.053600Z

Oh, thanks!

mkvlr 2021-10-08T19:23:51.055700Z

note that not all viewers do partial loading, the table viewer still needs work in this regard. And plotly and vega always load the complete result (but only if it changed) because you wouldnโ€™t want to plot a subset. ๐Ÿ™ƒ

๐Ÿ™ 1
2021-10-08T19:57:09.056800Z

@mkvlr Seems to depend on dataset and browser. My dataset is larger then iris, and it works on Firefox, not on Chrome

2021-10-08T19:59:05.057400Z

Has long strings as well.

mkvlr 2021-10-08T19:59:21.058Z

@carsten.behring strings should also be shortened.

2021-10-08T19:59:22.058100Z

Will find a tricky one which is online and send you link.

๐Ÿ‘ 1
2021-10-08T19:59:53.058700Z

Om Chromium screen stays blank.

mkvlr 2021-10-08T20:00:27.059300Z

strange, Iโ€™m using Brave for development so should be the same. Any errors in the console?

2021-10-08T20:15:20.060Z

Chromium behaves far worse, for sure. No errors in concole, just blank screen

2021-10-08T20:15:28.060300Z

On Linux.

2021-10-08T20:15:40.060500Z

Version 94.0.4606.61 (Official Build) Arch Linux (64-bit)

2021-10-08T20:35:57.061200Z

Clearly a chromium problem, on Firefox it works very well !

mkvlr 2021-10-08T20:43:43.061800Z

๐Ÿ˜ž browsers, Iโ€™ll try to reproduce it tomorrow

mkvlr 2021-10-08T20:44:19.062400Z

any extensions that could be causing issues? Can you try without them or in a private window in chromium?

2021-10-08T21:11:31.063100Z

For my larger dataset it makes sense to wrap it in the "result" viewer:

(clerk/with-viewer :clerk/result
  (def data (tc/dataset "/workdir/data/AOP non dogmatic. KE4dev5 210928.xlsx" {:key-fn csk/->kebab-case-keyword
                                                                                      :file-type :xlsx})))

2021-10-08T21:12:01.063700Z

This outputs "nil", and makes the whole rendering faster

2021-10-08T21:25:43.064100Z

Alterantively:

(def _
  (def data (-> (tc/dataset "/workdir/data/AOP non dogmatic. KE4dev5 210928.xlsx" {:key-fn csk/->kebab-case-keyword
                                                                                   :file-type :xlsx})
                (tc/head 1000))))