easafe / purescript-flame Goto Github PK
View Code? Open in Web Editor NEWFast & simple framework for building web applications
Home Page: https://flame.asafe.dev
License: MIT License
Fast & simple framework for building web applications
Home Page: https://flame.asafe.dev
License: MIT License
Good job on converting to Spago. But I'm afraid there're old versions of Argonaut dependencies in the current package set. It would be fair to pin them for the moment, like:
let overrides =
{ argonaut = upstream.argonaut // { version = "v7.0.0" }
, argonaut-codecs = upstream.argonaut-codecs // { version = "v7.0.0" }
, argonaut-traversals = upstream.argonaut-traversals // { version = "v8.0.0" }
, argonaut-generic = upstream.argonaut-generic // { version = "v6.0.0" }
}
Also, there are two lines to add in spago.dhall
:
, license = "MIT"
, repository = "https://github.com/easafe/purescript-flame"
I wouldn't interfere with my own PR right now, as I'm now working with the library using symlinks into my src
. 😅
Currently, the library outsources dom patching to snabbdom. This has a few issues (that may or may not be worth being worked on):
As an external npm dependency, it adds friction to the development process
We can't update snabbdom at all since newer versions use ES modules which the PureScript compiler doesn't support yet
These might be eased by the latest changes (e.g., keyed), somehow managing to upgrade snabbdom, or just some work around code in our part, but there are many things that the current snabbdom implementation doesn't play nice with. From the top of my head: externally modifying nodes (in cases where hooks don't apply, usually with server side rendering), conditional rendering (e.g., if and else in views), content editable usage...
There is something to be said about improving bundle size and performance, but I am still looking into these (and snabbdom doesn't really maintain benchmarks)
A couple solutions come to mind:
This is the easiest course of action, for obvious reasons. There is no time frame guarantee, though, or that all points will improve.
This one could solve most of the outlined problems. I don't know how much the associated maintenance cost would increase, however.
Likely a lot of work. We can just fork any other JavaScript library -- as long the library current user facing API stays the same -- no need to go full NIHS. Feature matching might be a concern (e.g., if the new implementation doesn't use a virtual dom), specially given all of @chekoopa recent work 🙃.
Right now the user-facing elements/attributes text, alt, placeholder, and any others are hard-coded to String
.
If you want to localise an application you need access to the current language everywhere to make the proper translation. It would be better if Html
had a second type hole so you can define your views something like Html message text
. Then a Flame provided function localise :: (text -> a) -> Html message text -> Html message a
can be used to translate everything into Html message String
which can be returned from the view
function of the application. If you do not need internationalisation you can just keep using String
and no changes are required.
I can't afford to renew flamepurs.org
which has now expired. Github does not accept projects to use username.github.io/project if a custom domain is enabled for the user, so the likely best solution is just to create an organization.
Have as an option to Html
a Fragment
constructor with same function as React </>
.
Is it possible to give Html a
a Monoid instance like React.Basic is doing for JSX
?
Hello,
I'm trying the ServerSide Rendering example but I have multiple problems. I tried to fix them, now I can build but I still have an error:
npm run server-side-rendering
> server-side-rendering
> npm run example-server-side-rendering && node examples/ServerSideRendering/dist/server-side-rendering-server.js
> example-server-side-rendering
> npm run example-server-side-rendering-server && npm run example-server-side-rendering-client
> example-server-side-rendering-server
> parcel build examples/ServerSideRendering/Server/server-side-rendering-server.js --dist-dir examples/ServerSideRendering/dist
✨ Built in 148ms
examples/ServerSideRendering/dist/server-side-rendering-server.js 178.73 KB 2.01s
> example-server-side-rendering-client
> parcel build examples/ServerSideRendering/Client/server-side-rendering-client.js --dist-dir examples/ServerSideRendering/dist
✨ Built in 115ms
examples/ServerSideRendering/dist/server-side-rendering-client.js 43.69 KB 1.41s
/Users/tcy/Documents/dev/workspaces/purescript/purescript-flame/examples/ServerSideRendering/dist/server-side-rendering-server.js:2
[...]
{return jc(i)(e)}))}(),Uc=function(e){return Mc(e.path)([Pc])?Ic:Lc};pc(3e3)(Uc)(Go("Server running on http://localhost:3000"))()})();
TypeError: n(...).createServer is not a function
at /Users/tcy/Documents/dev/workspaces/purescript/purescript-flame/examples/ServerSideRendering/dist/server-side-rendering-server.js:2:159278
at /Users/tcy/Documents/dev/workspaces/purescript/purescript-flame/examples/ServerSideRendering/dist/server-side-rendering-server.js:2:159320
at /Users/tcy/Documents/dev/workspaces/purescript/purescript-flame/examples/ServerSideRendering/dist/server-side-rendering-server.js:2:161358
at Object.<anonymous> (/Users/tcy/Documents/dev/workspaces/purescript/purescript-flame/examples/ServerSideRendering/dist/server-side-rendering-server.js:2:161362)
at Module._compile (node:internal/modules/cjs/loader:1103:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
at node:internal/main/run_main_module:17:47
Few informations:
spago --version
0.20.9
node --version
v16.14.2
Thanks a lot for this project, I'm looking forward to be able to play with the SSR :)
Having Html a
it be a real type will enable traversing the hierarchy and make modifications to it.
For example;
a
tags can be hijacked to use a custom on click handler to trigger a message
that uses pushState
and some internal routing state instead of reloading the entire pageimg
tags can be modified to add the loading="lazy"
attributeAs Flame becomes mature, it should be published at least in the registry and, ideally, in package sets.
The only concern is unstable API, but right now the framework is pretty usable to be declared about.
UPD: I've double-checked, Flame is already in registry as Bower-published. Still, the point about package sets is up.
Trying to render the example from https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g using;
svg
[ viewBox "0 0 100 100"
, createAttribute "xmlns" "http://www.w3.org/2000/svg"
]
[ g
[ fill "white", stroke "green", strokeWidth "5" ]
[ circle' [ cx "40", cy "40", r "25" ]
, circle' [ cx "60", cy "60", r "25" ]
]
]
Fails and gives back a blank SVG. The problem appears to be the nesting of the circles inside the g
tag, without the grouping the circles render fine.
Hi, thank you for this neat framework. I’m coming from Elm and I’m currently evaluating Flame to rewrite an Elm app in PureScript.
Is there a way to have HTML elements with an empty array of attributes and/or children?
p [] […children…]
must be replaced by p_ […children…]
p […attributes…] []
must be replaced by p' […attributes…]
p [] []
is impossible to obtain (am I wrong?)For readability reasons I want to avoid the HE.
prefix everywhere before my tags so I import my elements one by one, and having to import p, p', p_
etc. is redundant.
For the same readability reason I really wish we could use explicit empty arrays rather than one character suffixes that completely change the usage of the element. Is there a way to do that without monkey-patching Flame? If not then you can consider this issue as a feature request 😉
Cheers,
Laurent
As it is, raising an external event (i.e., not originated from the view) demands having the Channel
created by mount
or resumeMount
.
This suffices for document
or window
events (or anything that can be set up right after mounting an application). It might be cleaner however to ditch channels altogether in favor of something like CustomEvent
that would allows us to raise arbitrary messages from anywhere. One scenario where this is useful is having several mount points in a single app.
I am studying the example at https://github.com/easafe/purescript-flame/blob/master/examples/EffectfulAffjax/Affjax.purs
and I think there is a racing condition which concerns model being stale while there are multiple model update in AffUpdate
using display
.
I have created a short video to capture this racing condition:
So when user click Fetch for https://hub.dummyapis.com/delay?seconds=10 and then before the response is returned,
user changed it to https://hub.dummyapis.com/delay?seconds=1 and click Fetch again.
Second request is resolved first and displayed
then first request gets resolved and displayed as an outdated state now
Looking at the code
purescript-flame/examples/EffectfulAffjax/Affjax.purs
Lines 33 to 42 in 5749e56
model.url
is still the same as what we have requested.update ∷ AffUpdate Model Message
update { display, model, message } =
case message of
UpdateUrl url → FAE.diff { url, result: NotFetched }
Fetch → do
display $ FAE.diff' { result: Fetching }
response ← A.get AR.string model.url
pure $ \m ->
if m.url /= model.url then
m
else
m { result = _ } $ case response of
Left error → Error $ A.printError error
Right payload → Ok payload.body
Is this idiomatic in this package?
Did I miss out anything?
Anyway to make this easier?
Current Flame's behaviour on styles is overwriting, so the latter style
or even styleAttr
property only matters.
On other hand, Hedwig and Elm merge style attributes, giving us a single style list.
So, we should have that too. The most rational implementation is utilizing style
module of Snabbdom. It also would enable us delayed
, destroy
and remove
properties for basic animation features (not transitions, it would require more tinkering). And also, a challenge about CSS variables (such as --colorPrimary
).
The only concerns are:
styleAttr
behaviour on module-based style
s (would it still overwrite these styles?)I'm on trying style
module implementation. The current test case for this feature looks like:
test "style merging" do
let html = HE.a [ HA.style { mystyle: "test", mylife: "good" }, HA.style { mystyle: "check" } ] [HE.text "TEST"]
html' <- liftEffect $ FRS.render html
TUA.equal """<a style="mystyle:check;mylife:good">TEST</a>""" html'
let html2 = HE.a [HA.style { width: "23px", display: "none" }, HA.style { height: "10px" } ] [HE.text "TEST"]
html2' <- liftEffect $ FRS.render html2
TUA.equal """<a style="width:23px;display:none;height:10px">TEST</a>""" html2'
Thank you very much for this package.
When I play around this package, I stumbled upon this case.
Can I use this "widget" without reimplementing the JavaScript code? Where should I start?
At some point, I was wondering about server-side rendering examples. Is this a good start?
What options do I have for this case?
Thank you.
Hello,
Maybe I did something wrong, but it seams that is not possible anymore to compile examples.
spago build
npm ci
npm run build-examples
There is no output/Examples.*
so parcel can't build. And I have a lot of errors like this:
Build failed.
@parcel/core: Failed to resolve '../../output/Examples.EffectList.Affjax.Main' from './examples/Affjax/affjax.js'
/private/tmp/purescript-flame/examples/Affjax/affjax.js:1:22
> 1 | import { main } from '../../output/Examples.EffectList.Affjax.Main';
> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | main();
I updated the spago.dhall
to add the examples folder to try to fix the problem.
purs --version
0.15.6
spago --version
0.20.9
node --version
v18.12.0
Hi, thanks for the great library!
I am confused as to why is there a :>
for Tuple operator in this library instead of using the "official" /\
from https://pursuit.purescript.org/packages/purescript-tuples/7.0.0/docs/Data.Tuple.Nested#v:(/\)
Is there any issue if I use /\
instead of :>
for my update?
The benchmarks web page is showing as blank for me:
Similar to http://hackage.haskell.org/package/blaze-from-html to convert HTML to the markup DSL used by purescript-flame.
Currently, there is no way to specify a doctype. This mainly affects server side rendered applications, which end up in quirks mode.
A doctype tag could be added, but it either would have to allow children or always be used with a fragment.
Now handleRawEvent
under Flame.Renderer.toVNode
just calls handler and gives its result to updater function, so when you're writing event handlers you have to return message regardless of the event's content.
For example, we would want to have a conditional event, like "on Enter key pressed", which now is implemented like this:
{- ... -}
import Flame.HTML.Attribute (createRawEvent)
import Web.Event.Event as Event
-- | Tries to extract a keycode from the event.
keyCode :: Event -> Maybe Int
onEnterPressed :: ∀ msg. msg -> msg -> NodeData msg
onEnterPressed onFail onEnter = HA.createRawEvent "keyup" $ \event -> do
Event.preventDefault event
case keyCode event of
Just 13 -> pure $ onEnter
_ -> pure $ onFail -- notice we can't just suppress it
The only possible alternative is just using onKeyup
and filtering the pressed key in update
function, but it mostly adds bloat in the application's logic (if you need to catch only one particular key).
One could try throwing an error to break the event handling, but it also breaks toVNode
execution, too. Yes, we could just wrap handler into try
, but it either prevents us from handling real errors or forces unpleasant trace messages in the console.
Therefore, the proposal is to change event handler's type to Event -> Effect (Maybe msg)
, so we could filter the event right in the handler. Also, it would look more consistent considering how EffectList update
function deals with events (using Aff (Maybe msg)
) and channel message types (either Array msg
or Maybe msg
).
The updated example code would look like this:
onEnterPressed :: ∀ msg. msg -> NodeData msg
onEnterPressed onEnter = HA.createFilteredEvent "keyup" $ \event -> do
Event.preventDefault event
case keyCode event of
Just 13 -> pure $ Just onEnter
_ -> pure $ Nothing
The proposed changes wouldn't break existing API, as already placed event constructors only get an additional Just
wrapper under the hood. But additionally, we'd get a createRawEvent'
or createFilteredEvent
(the naming is a point of discussion).
I was attempting to build a view
function that included an <input>
. That <input>
made use of a <datalist>
so it would autocomplete. Here's a cut down example of what I was trying to do:
view :: Model -> Html Message
view model =
HE.main "main"
$ [ HE.label [ HA.for "broken-input" ] "Broken input"
, HE.input [ HA.type' "search", HA.name "broken-input", HA.id "broken-input", HA.list "search-results", HA.value model.searchResult, HA.onInput SearchStuff ]
, HE.datalist [ HA.id "search-results" ] [ HE.option_ "Search..." ]
]
On Chrome this generates a runtime error: Uncaught TypeError: Cannot set property list of #<HTMLInputElement> which has only a getter
On Firefox this generates the same error (with a different message): Uncaught TypeError: setting getter-only property "list"
Seems the problem is Flame creates the Input and attempts to set the list
attribute after, but since it's read-only this cannot work.
Hello. The examples in the aptly-named folder are great and very useful, but they're all kind of toy examples. Same can be said for the documentation. Ideal to grasp the general concepts but not quite enough to understand what would it be to build a life-scale front-end application, with dozens of views/pages, dozens of state elements synchronized with a backend API, complex interactions between "components" etc.
Would there be anything available that demonstrates (or documents) the recommended way to structure Flame applications in a more real-life fashion?
I'd be particularly interested in:
purescript-routing
for this? how to integrate it with purescript-flame
?subscribe
/emit
are fine for a few items but things become unbearable quickly without a global storeMany thanks.
HE.img default should be having no inner element
I have initialized a new project with pulp init
and added flame with bower install purescript-flame
.
Doing pulp build
produces these errors:
[1/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/EffectList.purs:19:1
19 import Data.Argonaut.Decode.Generic.Rep (class DecodeRep)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Decode.Generic.Rep was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
[2/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/Effectful.purs:20:1
20 import Data.Argonaut.Decode.Generic.Rep (class DecodeRep)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Decode.Generic.Rep was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
[3/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/NoEffects.purs:14:1
14 import Data.Argonaut.Decode.Generic.Rep (class DecodeRep)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Decode.Generic.Rep was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
[4/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/PreMount.purs:7:1
7 import Data.Argonaut.Core as DAC
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Core was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
[5/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/PreMount.purs:8:1
8 import Data.Argonaut.Decode.Generic.Rep (class DecodeRep)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Decode.Generic.Rep was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
[6/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/PreMount.purs:9:1
9 import Data.Argonaut.Decode.Generic.Rep as DADEGR
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Decode.Generic.Rep was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
[7/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/PreMount.purs:10:1
10 import Data.Argonaut.Encode.Generic.Rep (class EncodeRep)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Encode.Generic.Rep was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
[8/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/PreMount.purs:11:1
11 import Data.Argonaut.Encode.Generic.Rep as DAEGR
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Encode.Generic.Rep was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
[9/9 ModuleNotFound] bower_components/purescript-flame/src/Flame/Application/PreMount.purs:12:1
12 import Data.Argonaut.Parser as DAP
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Module Data.Argonaut.Parser was not found.
Make sure the source file exists, and that it has been provided as an input to the compiler.
Src Lib All
Warnings 0 0 0
Errors 0 9 9
* ERROR: Subcommand terminated with exit code 1
Am I doing something wrong?
Using conditionals with fragments (e.g. HE.div_ [ if condition then element else fragment, ...]
) results in a runtime error
The minimal reproducible example would be this.
module Main where
import Prelude
import Effect (Effect)
import Flame.Application.NoEffects (mount_)
import Flame.Html.Element as HE
import Flame.Types (Html, Subscription)
import Flame.Html.Attribute as HA
import Flame (QuerySelector(..))
type Model = Int
type Message = Model -> Model
init :: Model
init = 0
subscribe :: Array (Subscription Message)
subscribe = []
view :: Model -> Html Message
view model = HE.button [HA.onClick ((+) 1)] (show model)
update :: Model -> Message -> Model
update model message = message model
main :: Effect Unit
main = do
mount_ (QuerySelector "body") { init, subscribe, view, update}
I get that the point of messages is to limit the type of mutations one can do on the model. But I was playing around with that, since it allows me to try some things faster while i decide how to structure the state and its mutations. Trying this however fails, and when the button is clicked the following error is logged
caught TypeError: h(...) is not a function
at F.runHandlers (index.js:2273:51)
at F.runEvent (index.js:2264:14)
Is this known?
Snabbdom has a really powerful feature to inject functions into VNodes (https://github.com/snabbdom/snabbdom#hooks), and we use hooks in Hedwig (I even had to fork it to add them) for some tricks, such as Markdown rendering.
We consider switching to Flame (as Hedwig seems to be discontinued), but for now, it misses some low-level features, such as hooks, keyed, and thunks (however, we don't use it, but laziness is a great perk).
hooks
attribute is situated in VNodeData, so it seems to enable hooks being treated as a NodeData, like NodeHook string (VNode -> Effect message)
(but it actually needs an additional for update hooks with two VNode parameters), and therefore being used as a node attribute (like, ToNodeHook1 and ToNodeHook2, or something more static).
The tabIndex
attribute does not do anything because Flame spells it with a lowercase i.
By "does not do anything" I mean that when I inspect the generated HTML in the browser, the attribute does not appear at all (disregarding capitalization). For some reason, it worked fine after I replaced all occurrences of tabindex
with tabIndex
in src/Flame/Html/Attribute.purs and src/Flame/Html/Attribute/Internal.purs.
Currently if one wants to check out this library and isn't familiar with spago, the readme inside the examples folder is not too helpful:
purescript-flame/examples/README.md
Lines 3 to 6 in a5cef59
This command doesn't actually build the purs files and running it without installing and building with spago results in an error. Maybe the readme could contain all the steps to build the examples or the npm run scripts should be setup differently like
"example-counter" : "spago build -p examples/Counter/Counter.purs && parcel build examples/Counter/counter.js --dist-dir examples/Counter/dist && parcel serve examples/Counter/counter.html"
to build and serve an example for an effortless setup.
I understand this exact solution wouldn't work with `npm run build-examples' and tests, just making a general suggestion.
Hello,
I'm coming from elm and scala and I'm just trying out purescript and found this library. I'm quite lost with all the build tools used in purescript. So I'm sorry if this sounds completely stupid: The tutorials I went through made me use spago. Now this lib mentions bower. Can I install this lib via spago somehow? Or can I use both togehter?
Thank you!
Heya! I've been looking into this issue for a bit and it has stumped me, but I've narrowed it down to a reasonably small example.
In this example I have a "counter component" with it's own model, update, view, etc. I wrap the view function of this component in lazy
. As this component is nested deep in a large application, the CounterMsg
is lifted up multiple layers via PageMsg <$> CounterMsg <$> counterView model.counter
.
However, it appears when a lazy node is mapped in this way (specifically two layers upwards), it will error in response to any event that dispatches a message within that node. In this case I see v is undefined
(upon further inspection, "v" being the message type passed to updateCounter
), though in our larger application we see Failed pattern match
import Flame.Application.NoEffects (mount_)
import Flame.Html.Element (lazy)
import Flame.Html.Element as H
import Flame.Html.Event as E
data CounterMsg
= Increment Int
type CounterModel
= { count :: Int }
initCounter :: CounterModel
initCounter = { count: 1 }
updateCounter :: CounterModel -> CounterMsg -> CounterModel
updateCounter model (Increment val) = model { count = model.count + val }
counterView :: CounterModel -> Html CounterMsg
counterView = lazy Nothing counterView_
counterView_ :: CounterModel -> Html CounterMsg
counterView_ model =
H.div_
[ H.button
[ E.onClick $ Increment 1000 ]
[ H.text $ "Current Value: " <> show model.count ]
]
data Msg
= PageMsg PageMsg
data PageMsg
= CounterMsg CounterMsg
type Model
= { counter :: CounterModel }
init :: Model
init = { counter: initCounter }
update :: Model -> Msg -> Model
update model (PageMsg (CounterMsg msg)) = model { counter = updateCounter model.counter msg }
view :: Model -> Html Msg
view model =
H.div_
[ PageMsg <$> CounterMsg <$> counterView model.counter
]
main :: Effect Unit
main =
mount_ (QuerySelector "#app")
{ subscribe: []
, init
, update
, view
}
Removing a layer of mapping in the view fixes this problem. If I redefine
data Msg
= PageMsg PageMsg
data PageMsg
= CounterMsg CounterMsg
to
data Msg
= CounterMsg CounterMsg
And remove the extraneous mapping then things work as expected
We already have ToClassList instances for string and record, both of which are implemented by transforming them into Array String
. Meanwhile, it seems that it could be good idea to add a trivial instance ToClassList (Array String)
so that we can save time while avoid long lines when handling with libraries like TailwindCSS. Alternatively, we can add a classList
attribute to handle things.
To be exact, we could add
instance ToClassList (Array String) where
to = identity
here for the former idea.
What would you think?
Minimal reproducible example:
spago init
spago install flame
cd flame micro
# counter example from https://github.com/easafe/purescript-flame to src/Main.purs
spago run
Output:
[501 of 501] Compiling Main
[info] Build succeeded.
file:///Users/benjamin/repos/experiments/flame-micro/output/Flame.Application.Internal.Dom/foreign.js:3
return document.querySelector(selector);
^
ReferenceError: document is not defined
at Module.querySelector_ (file:///Users/benjamin/repos/experiments/flame-micro/output/Flame.Application.Internal.Dom/foreign.js:3:5)
at __do (file:///Users/benjamin/repos/experiments/flame-micro/output/Flame.Application.Internal.Dom/index.js:9:33)
at __do (file:///Users/benjamin/repos/experiments/flame-micro/output/Flame.Application.EffectList/index.js:144:87)
at file:///Users/benjamin/repos/experiments/flame-micro/.spago/run.js:3:1
at ModuleJob.run (node:internal/modules/esm/module_job:192:25)
at async DefaultModuleLoader.import (node:internal/modules/esm/loader:228:24)
at async loadESM (node:internal/process/esm_loader:40:7)
at async handleMainPromise (node:internal/modules/run_main:66:12)
Node.js v20.5.0
[error] Running failed; exit code: 1
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.