Fork me on GitHub
#clojurescript
<
2021-08-26
>
sova-soars-the-sora11:08:29

Hi I want to make a chrome extension and it would basically take a paragraph of text and add bounded boxen to different words. Anyone have any experience working on chrome/firefox extensions leveraging CLJS? Part of what stumps me is the fact that I could potentially use regex to figure out what's what, but the box-drawing has got to be pretty flexible... so imagine you have a sentence like "the elephant goes to school" .. I want to draw a box around "the elephant" and "to school." But I also want it to work on partial inputs / not crash because sentences are incomplete... so "the elephant goe" would get a box around "the elephant" and it could somehow wait for more useful input.

Adam Stokes12:08:53

Hey @U3ES97LAC! I came across this that uses clojurescript https://github.com/jiacai2050/gooreplacer not sure if this could help for reference

sova-soars-the-sora12:08:35

Oh awesome, really appreciate the link!

sova-soars-the-sora12:08:59

I don't read Chinese [yet]...

sova-soars-the-sora12:08:20

Ah, luckily there's an Ainglish version ^.^

🙂 3
dnolen12:08:06

@borkdude just reiterating that the requires as string is not necessary

dnolen12:08:32

in ClojureScript we simply allow that in the cases where the import includes chars that cannot be in a symbol

dnolen12:08:52

$ is valid in symbols and the convention was taken from Clojure usage of inner classes

borkdude12:08:47

@dnolen yeah cool, I kind of knew that but in clj-kondo it's used as a way to differentiate between JS libs and clojure namespaces. I should probably rethink that.

borkdude12:08:59

Now that I've actually got more experience with this myself, I know where the problems are.

dnolen14:08:23

@borkdude right, so clj-kondo would be wrong here

dnolen14:08:00

there is no distinction between CLJS and JS libs using the string require format

borkdude14:08:01

yes, understood. it's not invalid to use strings only for JS libs though, and that's what people have been doing to satisfy the static analysis. I will see if there's a better solution though.

andrzejsliwa14:08:17

Hey, I’m looking for example how to use directly firebase (recent, ver. 9) from ClojureScript (shadow-cljs). I have problem with requiring of right functions directly (without using fancy wrapper). Do you have maybe working examples with using v9?

andrzejsliwa14:08:28

following the documentation https://firebase.google.com/docs/database/web/read-and-write?hl=en&amp;authuser=0#web-version-9_1

import { getDatabase, ref, set } from "firebase/database";

const db = getDatabase();
set(ref(db, 'users/' + userId), {
  username: name,
  email: email,
  profile_picture : imageUrl
})
.then(() => {
  // Data saved successfully!
})
.catch((error) => {
  // The write failed...
});
I should be able to “require” the getDatabase functions directly right?

andrzejsliwa14:08:58

(ns some.fb.db
  (:require ["firebase/database" :refer [getDatabase]])
?

andrzejsliwa14:08:06

I’m able to initialize firebase via:

(ns giggin.fb.init
  (:require ["firebase/app" :as firebase]))

(defn firebase-init
  []
  (firebase/initializeApp {...}) 
but “importing” of database is failing

p-himik14:08:50

Have you seen this section? https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages Not just the table but also what follows.

andrzejsliwa14:08:45

Perfect! Thank you!

👍 3
Ryan14:08:19

Ok, time to try and use some Specter in this clojurescript project.. How do I properly add it to the project? So far I've only added node modules (using shadow-cljs)

Ryan14:08:04

also is there a convention for naming the import since using s as the documentation suggests seems to collide with accepted practice for spec.

p-himik14:08:35

Just as you would add a regular Clojure dependency. Shadow-cljs has examples in its documentation. Haven't seen any convention, just use whatever you prefer. Do note that using Specter will significantly increase the bundle size.

dnolen14:08:39

@rdonahue there is no convention, and using s for spec is not a convention - you can do whatever you like

dnolen14:08:22

it's the whole point of ns aliases - you're free to pick names best suited to your project

dnolen14:08:42

@rdonahue as to adding stuff to Clojure projects it depends largely on the tool - I think shadow has it's own way of doing it

borkdude15:08:27

Continuing on the cljs vs js lib "namespace", are there any heuristics that can be applied whether to detect a cljs namespace vs js lib, beyond just trying to load the js lib, catch and then try the cljs lib? can also first check the classpath for the cljs lib and then try the js lib This is more a question about how CLJS itself implements it. I can also just go read the source.

dnolen16:08:08

@borkdude note that there are significant differences here between what ClojureScript does and what shadow-cljs does

dnolen16:08:25

but what ClojureScript does is index node-modules

dnolen16:08:05

there is no other way detect whether a library is one or the other

borkdude16:08:46

right, because CLJS is a compiler and you can't just try something at runtime

borkdude16:08:01

(unless you generate that code but that gets messy)

dnolen16:08:07

this was true always

dnolen16:08:10

long before node_modules

dnolen16:08:30

we indexed Closure Library - you can requires a Closure Library just like a normal CLJ namespace

dnolen16:08:45

nothing to distinguish one kind of require from the other

borkdude16:08:27

right. in nbb I have the luxury that I can use resolve (on a require created with createRequire) to lookup the JS source first. I just wonder if that would be correct: JS and if that fails, then try CLJS, in that order.

borkdude16:08:52

I guess a conflict is really rare

dnolen16:08:59

pretty sure that's not the order we use

dnolen16:08:02

I think it's something like

dnolen16:08:14

CLJS, node_modules, Google Closure, classpath JS

👍 3
borkdude16:08:10

classpath JS, I can't remember I've ever used that

dnolen16:08:43

for the case where you're writing Google Closure JS

dnolen16:08:50

transit-js works this way

dnolen16:08:25

again the whole point of the ClojureScript design is "who cares where this stuff comes from?"

dnolen16:08:35

it's just some namespace with something you want to use

dnolen16:08:50

it's also why we ended up with $

dnolen16:08:00

because all this ESM stuff is nothing we care about

dnolen16:08:17

all JavaScript libraries are simply nested objects

dnolen16:08:34

and we've supported using that pattern since day 1 - that's how Closure works

borkdude16:08:53

yes, it makes sense, I just have never used it myself, but I can imagine that there's a use case for it (like you've mentioned). this is helpful, thanks

borkdude16:08:54

does the async ESM stuff complicate stuff for CLJS or is it just a matter of setting the right JS language target and it generates import stuff?

dnolen16:08:30

we simply don't support dynamic require

borkdude16:08:46

I mean, e.g. CLJS on deno, loading "namespaces" from web resources

dnolen16:08:16

what I'm saying is we don't support this thing at all - and are probably unlikely too

dnolen16:08:41

unless Closure does

dnolen16:08:15

it's my opinion that all the JS changes over the years has a net negative

dnolen16:08:30

and the more stuff happens the more likely we're not going to do anything about it

dnolen16:08:52

this is the strategy around :bundle

dnolen16:08:09

somebody else's problem chasing low-value stuff

😆 3
lilactown16:08:29

yeah. right now CLJS uses google closure's way of bundling and loading modules, which is distinct from async import. you can use async import to get external JS to load, but that isn't something that involves the compiler in any way. you would just call (js/import ,,,) or whatever

dnolen16:08:56

exactly it's not our intention to make things impossible

dnolen16:08:15

but my experience w/ interop heavy stuff in Clojure & ClojureScript is it's a losing game

dnolen16:08:47

in that some things are better written in Java and JavaScript (rather than adding features to achieve parity which is always a moving target)

borkdude16:08:56

maybe CLJS can add its own module standard to the mix 😆

borkdude16:08:11

(not serious)

borkdude16:08:08

do you still think Closure was (and is) a good decision?

dnolen16:08:38

it's still state of the art far as I can tell

dnolen16:08:18

my primary complaint - though it's somewhat of our creation is that Closure doesn't follow a Hickey-esque approach to development

dnolen16:08:36

removals, renaming, signature changes you name it

dnolen16:08:28

I think in the old days Closure development was slower because they were a lot of consumers of the APIs

dnolen16:08:35

but I think we're probably the biggest one now by far

lilactown16:08:01

it's also hard to go back in time to 8 (?) years ago and think to pick any other solution

dnolen16:08:31

but more importantly ESM is not a good answer

lilactown16:08:32

it really was the best at the time, and any solution built on top of other existing tech back would have seen at least as much churn and discrepancies with current bleeding edge tech

dnolen16:08:43

Google Closure namespaces are effectively late bound environments

dnolen16:08:01

this is what lets the REPL work w/o Clojure Var stuff

dnolen16:08:16

all the Dead Code Elimination stuff works around ESM modules from what I can tell

dnolen16:08:19

anyways, I don't think the calculus has changed at all

dnolen16:08:39

because JS people don't have proper live programming and they're never going to

lilactown16:08:46

yeah ESM essentially cemented the status quo a lot of other bundlers set w/ using closures as modules rather than object namespaces

lilactown16:08:14

that requires reloading the entire app from the root when any dependency changes

dnolen16:08:48

not saying that Racket is bad - but that where ESM comes from, people that worked on Racket

dnolen16:08:21

One of the very best ideas that Rich Hickey had (among all the others) is form-at-time compile

dnolen16:08:11

and avoiding modules as compilation unit

lilactown16:08:37

interesting, didn't know the Racket lineage there

lilactown16:08:07

I guess module-at-time compilation makes some mechanical sense, since pragmas set at the beginning of a module can radically change the way compilation is done. is that how most schemes work?

dnolen16:08:48

Smalltalk didn't work that way, Lisp didn't work that way

dnolen16:08:07

then you had Self - which continued Smalltalk

dnolen16:08:34

StrongTalk / Self laid the foundation for proving you could optimize all kinds of wild thing at runtime

dnolen16:08:55

whereas previously people believed you had to do this whole program optimization up front

dnolen16:08:40

Clojure whole idea was that you have runtime optimizing compiler and fast GC - so just focus on the stuff that matters

dnolen16:08:02

ClojureScript was created right at the time that was becoming true for JavaScript - and the design is based on the same principles

winsome18:08:59

Is there a canonical way to tell at runtime whether you're in the browser or in node?

winsome18:08:35

Basically, I need to figure out whether to use goog.net.XhrIo or node's http lib for making a request.

lilactown19:08:58

I think typical practice is to check for either window or process

🙌 3