Fork me on GitHub
#hoplon
<
2017-01-02
>
thedavidmeister01:01:22

@candera i was playing around with an svg animation myself, but ended up moving to pixi js instead >.<

candera01:01:59

Yeah, I was using canvas in my last version, but switched to SVG. I like how it’s declarative, and it’s a better fit with Hoplon. Based on looking at the API very briefly Pixi seems to be very imperative - do you find it so?

thedavidmeister01:01:14

yeah the svg/hoplon fit was really good

thedavidmeister01:01:05

my first pass with pixi is definitely full of imperative stuff, mutation and callbacks

thedavidmeister01:01:19

but the animation looks noticeably better when you a/b

candera01:01:35

I still have some imperative reaction to cells changing in order to get reasonable performance. But less than I did with canvas.

thedavidmeister01:01:53

i think i need to play around with it a bit

thedavidmeister01:01:13

there are certain things, like tweening, that make it look worse because they’re rather low level

candera01:01:45

It’s amazing any of it works in a browser at all, let alone approaches what we had in C++ a decade ago.

thedavidmeister01:01:09

but yeah, i’m using a lib for tweening but could probably use a cell= if i thought about it

candera01:01:24

Oh, I still owe Micha some perf tests.

candera01:01:35

I guess he can beat them out of me next week when I’m in the office.

candera01:01:39

Ah heck, I’ll run them now.

micha01:01:00

having a good lower level animation layer is key i think

candera01:01:03

85 ms on Hoplon 6.0.0 alpha 17.

micha01:01:24

with hoplon i think you can really make it nice, hide all of the imperative stuff really well

candera01:01:42

So, I don’t have a really good perf test suite, but it’s about the same.

micha01:01:12

interesting

candera01:01:30

Hard to say, though. It varies between 70 and 115 ms.

candera01:01:43

And that’s roughly what it did before. But the variation is pretty large.

micha01:01:05

you're testing with javelin 3.9.0 right?

micha01:01:40

cells should print with the #object [javelin.core/Cell ...] tagged literal now

micha01:01:54

vs the old #<Cell ...> way

micha01:01:32

i guess the bottleneck was not javelin

candera01:01:14

So, I think it’s entirely possible that Javelin itself is a tiny fraction of what I’m doing, and even a 10x speedup would be unnoticeable.

candera01:01:32

Like I said earlier, the gains I could get from going to WebGL have kept me from bothering to optimize.

candera01:01:37

Other than to make it useable at all.

thedavidmeister01:01:08

@candera try the timeline tab?

micha01:01:12

yeah i think you also have fewer cells than usual

candera01:01:27

If you mean the profiler chart, I’m looking at it now.

thedavidmeister01:01:47

ah, timeline is a different tab

thedavidmeister01:01:22

looks more like this

thedavidmeister01:01:59

you can see the rendering and painting

candera01:01:34

Yeah, I’m looking at something like that. Is that Chrome? Anyway, looks like the dominant costs are in DOM calls to update the grid. That’s the imperative bit I was talking about.

thedavidmeister01:01:59

there are two tabs next to each other

thedavidmeister01:01:02

profiles and timeline

candera01:01:20

Oh, yes, sorry - totally blind. Looking at that now.

thedavidmeister01:01:36

same animation, different approaches

thedavidmeister01:01:04

you can see more info about what’s going on with the dom rendering

candera01:01:13

I’ll let you know what it says on Thursday when it finishes analysis.

thedavidmeister01:01:04

a relatively even split

thedavidmeister01:01:33

you could try messing around with css transforms, etc?

candera01:01:02

I could. Or I could go add features. 🙂

candera01:01:25

It’s fast enough ATM. If I really want it to scream, I’ll start using WebGL.

jumblerg02:01:12

@thedavidmeister: were you doing some more work on the hoplon unit tests recently? i got some selenium unit tests running on sauce labs.

thedavidmeister02:01:00

ah actually i was going to suggest moving the hoplon tests to cljs tests

thedavidmeister02:01:18

i’ve got working code for that in my project, but haven’t put a PR up for it

jumblerg02:01:38

cljs tests?

thedavidmeister02:01:46

my tests look more like this now

thedavidmeister02:01:50

(deftest ??email
 (let [email? (fn [el a t]
               (is (dom.traversal/is? el (str "a[href=\"mailto:" a "\"]")))
               (is (dom.traversal/is? el "a.email"))
               (is (= t (dom.traversal/text el))))]
  (email? (email) el.email.config/default el.email.config/default)

  (let [a "as;lkfj"]
   (email? (email a) a a))))

thedavidmeister02:01:01

where dom.traversal is just a thin wrapper on jquery

thedavidmeister02:01:38

and the email function is just a defelem

thedavidmeister02:01:55

@jumblerg main advantages are speed, more “unit-y” and ability to directly inspect things like the state of cells

jumblerg02:01:22

looking at doo now.

jumblerg02:01:49

i've paid little attention to things that have been happening in this area.

thedavidmeister02:01:36

it’s basically the difference between firing up a browser that has a hoplon page in it and trying to inspect that with another tool like selenium

thedavidmeister02:01:58

and firing up phantomjs and using it to run tests against itself and report on what happened

jumblerg02:01:28

it looks like these might not be ideal for cross-browser testing though - are they just executing js in rhino or phantomjs?

thedavidmeister02:01:23

yeah no cross browser testing

thedavidmeister02:01:28

tradeoffs though

thedavidmeister02:01:13

the selenium tests i had were ~15 minutes and they now run in about 6s in phantom

thedavidmeister02:01:22

although, actually that’s a lie

jumblerg02:01:40

the tests i just added are for exactly that: i need to check the rendered output on each supported browser/os for ui. but i'm running them all remotely on sauce labs now.

thedavidmeister02:01:46

doo supports karma

jumblerg02:01:57

googles karma

thedavidmeister02:01:10

i did get it set up

thedavidmeister02:01:18

it just takes a little extra fiddling

thedavidmeister02:01:27

- karma-chrome-launcher
- karma-firefox-launcher
- karma-safari-launcher
- karma-opera-launcher
- karma-ie-launcher

thedavidmeister02:01:17

it worked fine for me, but at the time i wasn’t using it for cross browser testing per se

thedavidmeister02:01:25

moving away from selenium doesn’t mean losing other browsers, it’s just a different approach

thedavidmeister02:01:09

selenium is like a simulation of a user poking and prodding things in a browser to see what happens (but the user can only see the rendered result)

thedavidmeister02:01:34

doo is like running a script in that browser and the script happens to be a test

thedavidmeister02:01:26

so for unit tests, i’m suggesting doo is a better approach

thedavidmeister02:01:37

but for end to end tests, selenium is what i’d use

jumblerg02:01:16

does karma have a hosted service that runs the different browsers remotely?

thedavidmeister02:01:27

that i don’t know, sorry >.<

thedavidmeister02:01:23

it’s used by angular though, so i’m sure there’s decent support around the place

jumblerg02:01:45

so i'm reading. does it give you a practical way to run, say ie, on osx?

jumblerg02:01:31

or run multiple versions of, again, say ie, on the same machine?

jumblerg02:01:41

this is where the hosted services come in handy.

jumblerg02:01:16

so now i can:

$ boot test
Classpath conflict: org.clojure/clojure version 1.7.0 already loaded, NOT loading version 1.8.0
Starting reload server on 
Writing adzerk/boot_reload/init3863.cljs to connect to ...
env: loading "cnf/local.env"

Starting file watcher (CTRL-C to quit)...

Writing HTML files...
• index.html
Adding :require adzerk.boot-reload.init3863 to index.html.cljs.edn...
Compiling ClojureScript...
• index.html.js

Testing hoplon-test.ui
testing with (:chrome "26.0" :windows "7")
Jan 01, 2017 9:26:31 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Attempting bi-dialect session, assuming Postel's Law holds true on the remote end
Jan 01, 2017 9:26:39 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
testing with (:firefox "4.0" :windows "7")
Jan 01, 2017 9:26:44 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Attempting bi-dialect session, assuming Postel's Law holds true on the remote end
Jan 01, 2017 9:26:50 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
testing with (:iedge "11.0" :windows "7")
Jan 01, 2017 9:26:51 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Attempting bi-dialect session, assuming Postel's Law holds true on the remote end
Jan 01, 2017 9:26:56 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
testing with (:iedge "14.14393" :windows "10")
Jan 01, 2017 9:26:56 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Attempting bi-dialect session, assuming Postel's Law holds true on the remote end
Jan 01, 2017 9:27:15 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
testing with (:safari "7.0" :osx "10.9")
Jan 01, 2017 9:27:21 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Attempting bi-dialect session, assuming Postel's Law holds true on the remote end
Jan 01, 2017 9:27:36 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
Elapsed time: 90.233 sec

jumblerg02:01:34

and this all happens on sauce labs

thedavidmeister02:01:00

you can use them together

thedavidmeister02:01:27

they’re tackling different aspects of the problem

thedavidmeister02:01:49

looks like people use VMs with karma to get around the ie thing locally, fyi

jumblerg02:01:08

yeah, that's what i figured re ie, which i just don't want to f with: much easier to rely on a hosted service for this, where we can get just about any permutation of platform (to include mobile) and browser we want.

thedavidmeister02:01:36

"Karma is not a testing framework, nor an assertion library. Karma just launches a HTTP server, and generates the test runner HTML file you probably already know from your favourite testing framework. So for testing purposes you can use pretty much anything you like."

thedavidmeister02:01:54

yeah, you should totally keep using sauce labs

thedavidmeister02:01:02

they’ve been around forever too

jumblerg02:01:12

i actually kind of like that selenium is a java thing

thedavidmeister02:01:41

i’m just suggesting that selenium might not be the best tool for writing/managing unit tests specifically

jumblerg02:01:55

but i didn't really do my homework ahead of time. coded first, now i'm asking questions later.

thedavidmeister02:01:02

based on my personal experience of that being difficult, slow and flaky 😛

jumblerg02:01:58

they were pretty miserable when i was running them locally, and there was quite a bit of config-hell.

thedavidmeister02:01:43

yeah, i actually quite like selenium, it’s a messy tool but it’s doing a messy job

thedavidmeister02:01:19

but i only like it for what it’s designed to be used for...

jumblerg02:01:52

once i switched to sauce labs it really sped up. now i save a file and the watch task fires to run them; it takes about a minute for them to be tested on the minimum supported version of all five browsers.

jumblerg02:01:46

i haven't written any serious tests in practice yet though, mostly i'm just making sure google is there.

thedavidmeister02:01:54

you might as well keep doing what you’re doing

jumblerg02:01:54

when you say unit tests specifically, are you thinking more along the lines of testing an api as opposed to rendered dom output?

thedavidmeister02:01:33

no, i mean testing attributes of dom (hoplon) elements and cells individually, rather than testing a page holistically

thedavidmeister02:01:16

so, say i have a button that i pass a cell to, and clicking that button should change the value of that cell from false to true - i can actually check the value of the cell before/after

jumblerg02:01:00

i see what you mean

jumblerg02:01:11

in my case, for ui, the thing i'm most concerned about is layout - making sure that when an elem is vertically aligned to the center, for example, it is in fact in the center in all the browsers.

thedavidmeister02:01:37

aaah so you’re doing screenshots?

jumblerg02:01:42

sauce labs does this, yeah.

jumblerg02:01:00

it actually renders a photo and video for each browser tested. pretty nifty.

thedavidmeister02:01:28

i’ve heard good things about https://ghostinspector.com/ too

thedavidmeister02:01:38

haven’t used it personally yet

jumblerg02:01:17

i wasn't aware of that one.

jumblerg02:01:28

it produces that kind of report for each test run

jumblerg02:01:45

(ignore the fact i'm testing the hell out of google for the moment)

thedavidmeister02:01:37

yeah that’s much much nicer than raw selenium output

thedavidmeister02:01:44

i suppose you get what you pay for 😉

jumblerg02:01:55

they gave us a free os thing.

jumblerg02:01:58

for hoplon.

jumblerg02:01:41

i can add you as a user, i think, since you're working on this stuff.

jumblerg02:01:15

to do this right, we need to get it synced up with travis. esp for ui, where we need to catch any layout regressions asap associated with each contribution.

thedavidmeister02:01:48

well tbh, i was working on it, then i went off and did my own thing, learned a bunch about everything i was doing wrong, and am not sure quite how to proceed with hoplon now 😛

thedavidmeister02:01:48

i definitely now think that hoplon itself would benefit more from doo style tests than selenium, as you’d use something like ^^ to confirm visual and end to end things

jumblerg02:01:59

it would be great if we could coordinate something, and get the same basic solution in place for both.

thedavidmeister02:01:17

which makes more sense for a layout system like what you’re working on, or an actual user facing product

jumblerg02:01:38

clearly you know a lot more about this stuff than i do.

thedavidmeister02:01:05

but trying to write comprehensive tests against hoplon core without, for example, being able to inspect the state of a cell, would get messy real fast

thedavidmeister02:01:42

ok, well, in my mind atm:

thedavidmeister02:01:56

- i think you can use sauce labs for both doo and selenium, as it’s just hosted browsers at its core

thedavidmeister02:01:42

- selenium probably makes more sense for hoplon UI than hoplon core, where i think something more low level like doo is appropriate

thedavidmeister02:01:28

- i was wondering if we should move from travis to circle ci, as i’ve found debugging, etc. a bit easier on circle in general

jumblerg02:01:52

i was wondering the latter too... i've heard good similar things about circle.

thedavidmeister03:01:37

i’ve got examples of running clj, cljs and selenium tests in both travis and circle

thedavidmeister03:01:55

but i got confused about the way github/circle interacts across PRs on forks

thedavidmeister03:01:13

and stopped because i didn’t want to break anything

jumblerg03:01:10

i wonder if things cljs.test would be good to use at the interfaces of libs like javelin, castra, etc where there are programmatic apis, but selenium better for testing libs that produce user interfaces.

thedavidmeister03:01:26

some things maybe a split, like 90% cljs and 10% selenium

thedavidmeister03:01:35

there’s no reason you can’t mix and match

thedavidmeister03:01:45

i think the important thing to keep in mind is just that, while selenium gives you some super powers like videos and screenshots, it does come with significant time overhead and you lose visibility into low level state of the app

jumblerg03:01:00

i don't think visibility into the low level state of the app is necessarily something we want though, based on the assumption that the purpose of these tests is not to debug, but simply identify errors. i tend to think that, in the case of any unit tests, we only want to test whatever the interface of the library in question is.

thedavidmeister03:01:54

they can be whatever you want them to be

jumblerg03:01:35

i think the focus should be on covering an interface's surface area, but without going to much deeper than that.

thedavidmeister03:01:55

that’s certainly important

thedavidmeister03:01:40

i just test whatever i think might break 😛

thedavidmeister03:01:53

i don’t worry too much more about it than that

jumblerg03:01:09

i generally don't unit too many things at all, especially at the application level. i typically find the cost of the overhead to outweigh the benefits.

jumblerg03:01:17

even in the case of libraries, my applications happen to double as some pretty comprehensive tests (at least of the things i care about)

thedavidmeister03:01:41

i guess i just write things weirdly

thedavidmeister03:01:51

i’ve never not found a bug when i introduced tests to something

jumblerg03:01:56

if they miss an error, it isn't an error to me lol.

jumblerg03:01:17

if a tree falls in a forest...

thedavidmeister03:01:51

yeah well, i’d rather a robot trip over that tree than a user

jumblerg03:01:27

the bots might take code paths users never will.

thedavidmeister03:01:52

nah, it’s often pretty obvious stuff

thedavidmeister03:01:23

maybe i’m just bad at writing code 😉

thedavidmeister03:01:44

but also, it’s kind of like the whole live reloading thing

jumblerg03:01:53

but ui is a little different, because it is intensive to manually inspect and identify things like all the different layouts on each change to the box model.

thedavidmeister03:01:59

you can write code in a way that’s super easy to test certain things about it

thedavidmeister03:01:11

and you can write code that makes it near impossible

thedavidmeister03:01:47

i personally find that i have fewer bugs if i write code that would be easy to test, even if i don’t write the actual test

thedavidmeister03:01:09

so sprinkling some tests around keeps me from getting lazy

thedavidmeister03:01:34

i’ve definitely worked on codebases where, not only do they really need tests because of the complexity of the whole thing, but writing tests was so hard/time consuming that it took more time than the code

thedavidmeister03:01:42

it can be really depressing >.<

thedavidmeister03:01:10

but i really like hoplon because it’s actually super simple to unit test, if you feel so inclined 🙂

thedavidmeister03:01:55

definitely the intricacies around the box model are a great example of something complicated that you don’t want to test by hand 😕

jumblerg03:01:55

yeah, it is one of the cases where i think a tdd approach might actually prove to be the more efficient use of my time.

thedavidmeister03:01:07

or you can take the “write a test when it breaks” approach 😛

thedavidmeister03:01:36

on a totally different topic...

thedavidmeister03:01:50

how do you actually get rid of cells?

thedavidmeister03:01:21

trying to replace tween.js with a cell= tied to requestAnimationFrame

thedavidmeister03:01:35

i don’t really know how to deal with the tween finishing

alandipert03:01:18

@thedavidmeister can you elaborate a litle more? intrigued but don't know quite what you mean

thedavidmeister03:01:57

@alandipert aaah like, i made a thing with webgl that draws circles and i want to tween their scale

thedavidmeister03:01:17

looks something like this

thedavidmeister03:01:20

(doto (js/TWEEN.Tween. (-> c .-scale))
                                 (.to
                                  (clj->js {:x next-scale :y next-scale})
                                  animation-speed)
                                 (.onUpdate #(this-as this
                                              (-> c .-scale (.set (.-x this) (.-y this)))))
                                 (.onComplete tween-scale)
                                 (.start))))]

thedavidmeister03:01:41

(letfn [(frame [t]
           (.requestAnimationFrame js/window frame)
           (.update js/TWEEN t)
           (.render renderer stage))]
   (.requestAnimationFrame js/window frame))

thedavidmeister03:01:38

my gut tells me this could be replaced with something along the lines of

thedavidmeister03:01:41

(defn position-cell
 [t duration]
 {:pre [(cell? t)]}
 (let [start @t
       end (+ start duration)]
  (cell= (when t (/ (- t start) (- end start))))))

(defn interpolation-cell
 [from to position]
 (cell= (+ from
           (* position (- to from)))))

thedavidmeister03:01:18

something, something...

alandipert03:01:24

so iirc RAF takes a callback as an argument, right? and the callback is called with a timestamp

alandipert03:01:38

looks like thi TWEEN library helps generate the callback?

thedavidmeister03:01:39

yeah, it’s pretty much like setTimeout

thedavidmeister03:01:55

but it gives you a timestamp when it feels like it, rather than you giving it a delay

thedavidmeister03:01:57

so the tween lib’s main thing is to take a timestamp on “update” and then it interpolates numbers for you

thedavidmeister03:01:15

based on how close the timestamp you give it on update is to the timestamp that is when you want the tween to finish

thedavidmeister03:01:58

and then some callback when it finishes, which in my case i’m using to immediately setup a new tween

thedavidmeister03:01:10

so you get a looping animation

thedavidmeister03:01:42

i’m not tooo bothered about the whole timestamp management stuff, anything that keeps y in a fixed ratio with x as i vary x is good enough, as long as i can “finish” somehow when x goes out of bounds

alandipert03:01:01

i can see how separating reads and writes by making the callback dumb, ie it just resets a cell, is maybe good

alandipert03:01:10

and then the interpolation logic is hung off that cell

alandipert03:01:35

it can do fancier interpolations

thedavidmeister03:01:09

ooh i’ll check this out

thedavidmeister03:01:13

this is as far as i’ve got

thedavidmeister03:01:16

(defn animation-cell
 [from to duration]
 (let [t (cell nil)
       p (position-cell t duration)
       i (interpolation-cell from to p)]
  (letfn [(frame [tick]
           (reset! t tick)
           (.requestAnimationFrame js/window frame))]
   (.requestAnimationFrame js/window frame))))

alandipert03:01:58

altho i can imagine, you just need one cell and one RAF thunk thing

alandipert03:01:09

and then all your animations can be hung off that one global cell?

thedavidmeister03:01:27

i want everything to be local to the circle

thedavidmeister03:01:33

i’ll probs have a few hundred circles

alandipert03:01:59

i imagine it would be private in the NS you dedicate to this

alandipert03:01:12

the thing it that approach helps with is latency

alandipert03:01:20

since you only have one thunk enqueue at any given time

alandipert03:01:24

vs. at least 1 per animation-cell

alandipert03:01:42

i used similar technique recently for basic interpreter w/ settimeout

thedavidmeister03:01:49

i’ve been using the ndarray from http://thi.ng to build a grid of circles so far

thedavidmeister03:01:05

i could tie the interpolation logic into rebuilding that grid

thedavidmeister03:01:06

as in… i could make a cell= that is just a map of the above logic, essentially

thedavidmeister03:01:30

across a seq of position and interpolation cells that all have the same t

thedavidmeister03:01:06

so yeah, let’s say that t is global but the other cells are specific to the individual circle 🙂

thedavidmeister03:01:24

(def t (cell nil))
(letfn [(frame [tick]
         (reset! t tick)
         (.requestAnimationFrame js/window frame))]
 (.requestAnimationFrame js/window frame))

(defn animation-cell
 [from to duration]
 (let [p (position-cell t duration)
       i (interpolation-cell from to p)]))

thedavidmeister03:01:55

@alandipert so i can probably make new animation cells with callbacks

thedavidmeister04:01:30

(defn animation-cell
 [from to duration cb]
 (let [p (position-cell t duration)
       i (interpolation-cell from to p)]
  (cell= (when (< 1 p) (cb)))))

alandipert04:01:50

seems good, although, i'm wondering

alandipert04:01:04

is it important that the RAF callback does the work?

thedavidmeister04:01:08

but then how do i stop animation cells piling up everywhere?

alandipert04:01:14

oh nvm i just realized, it still is .even if all it does is update a cell

alandipert04:01:40

oh the animation cells are ephemeral?

thedavidmeister04:01:45

well i don’t know

thedavidmeister04:01:00

that’s the bit i’m unsure of the best way to tackle

alandipert04:01:16

if they should be, maybe they somehow destroy themselves depending on some condition

thedavidmeister04:01:33

like, do i try to make them reusable as a lens somehow, or try to make new ones and throw the old ones away, or something else entirely?

alandipert04:01:08

not sure, tho it's not clear to me cells are a great fit for this problem

alandipert04:01:17

but i've never used RAF or even done animations in browser other than via svg

thedavidmeister04:01:37

cell= seems like a great fit for the tweening part to me

thedavidmeister04:01:03

locking a ratio of some value (scale) to another (timestamp)

thedavidmeister04:01:13

i just don’t know what to do at the end 😛

alandipert04:01:48

i guess the animation knows when it's done, right? it has stopped moving

thedavidmeister04:01:03

as soon as p = 1

alandipert04:01:11

so maybe when the prev val was equal to the new one, it destroys itself

alandipert04:01:21

a cell that destroyed itself would be a new one

thedavidmeister04:01:33

actually, now that i think about it, that might cause chaos downstream 😛

thedavidmeister04:01:44

it should just be the final value forever

alandipert04:01:03

maybe it detaches itself from the cell graph but keeps its last value?

thedavidmeister04:01:13

but also not incur calculation overhead recalculating the same final value every frame

alandipert04:01:16

ie becomes constant

thedavidmeister04:01:32

like, it converts from a cell= to a cell

thedavidmeister04:01:57

maybe a lens is what i want

thedavidmeister04:01:50

so the setter is the start/end vals and delay/duration ms, + a callback

thedavidmeister04:01:27

and the getter is the interpolated values from the global t, or a constant if p >= 1

thedavidmeister04:01:11

@alandipert cheers for talking that through with me 🙂

thedavidmeister04:01:14

i’ll see how i go

alandipert04:01:38

sure! fun problem

alandipert04:01:54

still not confident i'd use cells for this, but it's fun to think about 🙂

alandipert04:01:14

experience has shown that it's hard to make things worse by adding cells

thedavidmeister04:01:03

@alandipert think of it like “cell that you can reset! but it takes its time to get there"

thedavidmeister04:01:18

actually, that might be simpler, not worrying about a from...

thedavidmeister06:01:27

seems to work ok

thedavidmeister06:01:54

woah, very slow though

thedavidmeister08:01:28

@micha welp, i just made something that thrashes javelin pretty hard if you want profiling info ^^

yogthos23:01:43

I'm adding a Hoplon profile for Luminus, and I got a bit stumped on how to render an HTML string directly here https://github.com/luminus-framework/luminus-template/blob/41f90139eb7cc038d5643effcdf6278304a3b956/resources/leiningen/new/luminus/hoplon/src/cljs/core.cljs#L52 also, if anybody could let me know whether I'm doing anything else that's not idiomatic that would be appreciated as well 🙂

flyboarder23:01:00

@yogthos (h/div :html (cell= (md->html docs))

flyboarder23:01:12

I also recommend using defelem any time you want a "template" of elements

flyboarder23:01:20

instead of defn

flyboarder23:01:49

although in cases defn is fine, when you make elements more complex you want the features of defelem

yogthos23:01:12

that doesn't seem to work for me

yogthos23:01:39

I noticed that passing params seems to work differently?

yogthos23:01:26

that's what I get with (h/div :html (cell= (md->html docs)))

flyboarder23:01:48

what version of hoplon?