Compare commits

...

992 Commits

Author SHA1 Message Date
Glen De Cauwsemaecker 7830ea7bae
change rust repo link to monorepo (#855)
also bump version to 0.1.3
and bump alpha version of rama
2025-04-18 17:09:27 -06:00
Ben Croker 9b76b0ae44
Fix link 2025-04-18 13:57:13 -06:00
Ben Croker f1fa1cba71
Max 5 keywords allowed 2025-04-18 13:52:29 -06:00
Glen De Cauwsemaecker 3afa2c098e
improve quality of rust sdk and add tooling (#854)
also bump version to 0.1.2

- add makefile with all commands for rust sdk developers
  to run all relevant checks and test,
  which also auto formatting of code and toml deps
- fixed broken clippy rules
  (this also required fixing some stuff in consts)

Also fixed the docs.rs attributes to ensure _all_
modules and symbols get published in docs,
instead of only those that are available in default features
(which was missing the framework specific stuff in docs)

Only nitpick issue left: in generated code (consts.rs)
some descriptions can contain 'html' code which is not escaped,
pretty certain this html will be rendered in docs.rs
as rust docs renders docs as markdown (which includes html),
but given that's auto generated I have left that for now as-is.
2025-04-18 13:48:30 -06:00
Ben Croker 47a095f04a
Update Cargo.toml 2025-04-18 11:21:00 -06:00
Ben Croker 3fe8157a09
Revert version number 2025-04-18 11:14:19 -06:00
Glen De Cauwsemaecker 104e77e1e8
update version to 0.1.0-beta.1 for rust sdk (#849)
ready for publish

- changelogs per sdk's is not done it seems,
  so I did not add that

Once this is merged we should be able to run

> cargo publish

and all should be ok
2025-04-18 10:29:17 -06:00
Lucian 6be5ad2fbc
fix(python): uncomment fasthtml, use correct name (#852)
Co-authored-by: Lucian Knock <git@lucianknock.com>
2025-04-18 10:21:09 -06:00
Glen De Cauwsemaecker 10b29846ae
add rama support to datastar rust sdk (#847)
* add rama support to datastar rust sdk

Closes #845

* bump rama alpha version
2025-04-16 21:05:33 -06:00
Glen De Cauwsemaecker 6b2d488ae6
Update "join discord link" in README.md (#846)
The current link is a link to a channel in a server which only works if you are already in the discord. This PR Replaces it with the invite link <https://discord.com/invite/bnRNgZjgPh> which I found on the datastar website: <https://data-star.dev/>
2025-04-15 15:52:26 -06:00
Brandon Bennett 83c120a3b1
Update README.md (#841)
Small spelling changes to make `datastar-py` consistent.
2025-04-15 09:34:14 -06:00
Dmitry Kotik d81ea1aef9
add missing WithMergeFragmentsEventID option (#842)
The merge fragments call configuration struct had an EventID field and
logic that added it to the SSE call, but no option to configure it.
Added that missing option.
2025-04-15 08:48:25 -06:00
Chase Sterling 3c5974c2e1
Python SDK: Allow objects with the __html__ protocol to be used for merge_fragments (#837)
* Allow objects with the __html__ protocol to be used for merge_fragments

* Clarify what HasHtml is for with a docstring
2025-04-14 19:31:20 -06:00
Dmitry Kotik b758fb3e06
Expand Golang SDK documentation by adding comments to every method. (#838)
* externalize interface compatibility for two optional template engines

Templ and GoStar are currently module dependencies for Golang SDK. They
should not be required for 1.0 release. This step replaces two component
interfaces with copies that ensure compatibility without having to
include various optional engines as dependencies with each Datastar
deployment.

* update comments and documentation for Golang SDK

Added comments to `execute.go` file. I will make similar changes to
other files. I submit those as a way of getting feedback.

The only public API change is the removal of execute script options
struct. It is changed to private by letter case because the options
pattern is used to configure script execution. The struct serves no
purpose and pollutes the public API.

* add hot reload example to Golang SDK

Updated the Golang SDK README.md file to include a list of examples that
will be expanded in the future. A basic example is moved into its own
directory. A hot reload example is added alongside it.

* expand Golang SDK documentation by adding comments to every method

Added a comment to every public method. Removed inaccessible options
structs from public API by letter case change. Exposed one hidden option
to public API. Refactored fragment merge mode parsing and added a
matching validation test.

* reinstate ValidFragmentMergeTypes because the website documentation depends on it
2025-04-14 10:40:01 -06:00
Chase Sterling a705eb7044
Add redirect helper on python ServerSentEventGenerator (#836) 2025-04-14 10:33:12 -06:00
Alex Bozhenko a4145207f0
chore: update go modules in go example (#835)
* chore: update go modules in go example

* unbreak tests
2025-04-12 11:42:35 -06:00
Alex Bozhenko 439c71341b
upd (#833) 2025-04-12 08:29:27 -06:00
Dmitry Kotik c4a99869cb
Add hot reload example to Golang SDK (#834)
* externalize interface compatibility for two optional template engines

Templ and GoStar are currently module dependencies for Golang SDK. They
should not be required for 1.0 release. This step replaces two component
interfaces with copies that ensure compatibility without having to
include various optional engines as dependencies with each Datastar
deployment.

* update comments and documentation for Golang SDK

Added comments to `execute.go` file. I will make similar changes to
other files. I submit those as a way of getting feedback.

The only public API change is the removal of execute script options
struct. It is changed to private by letter case because the options
pattern is used to configure script execution. The struct serves no
purpose and pollutes the public API.

* add hot reload example to Golang SDK

Updated the Golang SDK README.md file to include a list of examples that
will be expanded in the future. A basic example is moved into its own
directory. A hot reload example is added alongside it.
2025-04-12 08:29:05 -06:00
Alex Bozhenko aa138d5a19
Fix go tools (#829)
* update to go 1.24

* run go mod tidy

* make qtc a go tool

* remove tools installation from dockerfile dev

since it is now taken care of by the go tool command

* update makefile to use go tool task
2025-04-12 08:27:49 -06:00
Ben Croker 3869f09f5a
Add star history chart [deploy-site] 2025-04-12 08:01:48 -06:00
Dmitry Kotik 686d12ad2a
Update comments and documentation for Golang SDK (#827)
* externalize interface compatibility for two optional template engines

Templ and GoStar are currently module dependencies for Golang SDK. They
should not be required for 1.0 release. This step replaces two component
interfaces with copies that ensure compatibility without having to
include various optional engines as dependencies with each Datastar
deployment.

* update comments and documentation for Golang SDK

Added comments to `execute.go` file. I will make similar changes to
other files. I submit those as a way of getting feedback.

The only public API change is the removal of execute script options
struct. It is changed to private by letter case because the options
pattern is used to configure script execution. The struct serves no
purpose and pollutes the public API.
2025-04-11 18:34:15 -06:00
Alex Bozhenko 5a894a0139
Use go tools (#828)
* go get  go@latest

* go get -tool github.com/go-task/task/v3/cmd/task@latest

* go get -tool github.com/a-h/templ/cmd/templ@latest

* upd task file to use go tool templ
2025-04-11 18:33:29 -06:00
Dmitry Kotik 7b706e126b
externalize interface compatibility for two optional template engines (#826)
Templ and GoStar are currently module dependencies for Golang SDK. They
should not be required for 1.0 release. This step replaces two component
interfaces with copies that ensure compatibility without having to
include various optional engines as dependencies with each Datastar
deployment.
2025-04-11 13:07:41 -06:00
Chase Sterling 16fa3cdd90
Python SDK: change `merge_fragments` to take a string rather than list (#822)
* python sdk: change merge_fragments to take a string rather than list

* Change merge_fragments for fasthtml to accept a string rather than list
2025-04-11 13:01:09 -06:00
Jérémy 8b84986410
Fix: added proper clj-kondo config fixing unresolved vars warnings (#817)
Fix: handling of the HTTP keep-alive header
Refactor: simpler concurrency handling in one test.
2025-04-07 10:50:42 -06:00
Ben Croker 3b18b23a1f
Preconnect to youtube [deploy-site] 2025-04-04 17:11:28 -06:00
Ben Croker c780ded239
Add play button [deploy-site] 2025-04-04 11:03:11 -06:00
Ben Croker 72a3e28fea
Add video titles [deploy-site] 2025-04-04 08:44:04 -06:00
Ben Croker 23da089235
Add Videos page [deploy-site] 2025-04-03 21:43:40 -06:00
Ben Croker ffc98aa905
Fix bundler toggle buttons 2025-04-03 19:50:09 -06:00
Greg H 44bd907f44
sdk/dotnet-1.0.0-beta.5 (#812)
* sdk/dotnet-1.0.0-beta.5 - version bump for updated Nuget

* bugfix - corrected retry value

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-03-31 18:17:34 -06:00
Ben Croker 83b4af8299
Fix example [deploy-site] 2025-03-31 17:55:00 -06:00
Jérémy 7f7b555998
Change: removed deprecated api. (#810) 2025-03-31 10:41:32 -06:00
Ben Croker 3379e822fb
Fix docs [deploy-site] 2025-03-30 12:39:18 -06:00
Ben Croker f1e0f80922
Add wildcard support to persist plugin (#807) 2025-03-30 10:58:39 -06:00
Ben Croker ccc7ea427a
Add single/double asterisk wildcards (#806)
* Add single/double asterisk wildcards

* Update release note
2025-03-29 18:37:40 -06:00
Ben Croker 9c36bae809
1.0.0-beta.11 2025-03-29 12:15:41 -06:00
Ben Croker 5f10252adb
Reorder 2025-03-29 11:17:45 -06:00
Ben Croker aed0b3a228
Update release notes 2025-03-29 11:15:24 -06:00
Ben Croker 5ba9759fba
Add wildcard support (#805)
* Dispatch `datastar-sse` event on `document`

* Release note

* Fix

* Modify view transition

* Fixes

* Fixes

* Add wildcard support

* Add wildcard to OnSignalChange
2025-03-29 11:11:18 -06:00
Ben Croker 05c751770b
Modify view transition (#804)
* Dispatch `datastar-sse` event on `document`

* Release note

* Fix

* Modify view transition

* Fixes

* Fixes
2025-03-29 10:25:57 -06:00
Ben Croker 024111f67e
Dispatch `datastar-sse` event on `document` (#803)
* Dispatch `datastar-sse` event on `document`

* Release note

* Fix

* Fixes
2025-03-29 10:15:21 -06:00
Jacob Østergaard Nielsen 4cc46524d8
Go SDK WithCompression option for NewSSE (#756)
* add compression

make compression work

update compression logic

* made compression configurable

* allow for compression strategy

cleanup api

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2025-03-29 08:19:24 -06:00
Chase Sterling e422bbdecc
Split various python SDK frameworks to different modules (#770)
* Allow passing arguments to the generator function in fastapi sdk

* Allow passing extra headers in FastAPI streaming response

* Keep method signature of upstream FastAPI streaming response

* Split out python sdk frameworks into their own modules
Make all python sdk frameworks mirror the native way of streaming responses

* Rename the sanic helper in python sdk to match sanic convention.
Add some type hinting to sanic helper

* ruff format new python sdk files
2025-03-29 08:05:42 -06:00
Greg H 00d4e87a01
task/doco-dotnet-load_more - added how_tos/load_more.csharpsnippet and corrected dotnet README (#801)
Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-03-28 19:50:48 -06:00
Jason Oppel f754ada278
Fix WSGI/ASGI issues in Django Example Project (#787)
* fix: support connection header over WSGI

Per spec, WSGI doesn't allow the connection header:
https://peps.python.org/pep-0333/#other-http-features

This commit works around that limitation and permits the connection
header over a WSGI connection.

* feat: add WSGI views/urls to Django example

* build(py-sdk): add django/datastar_py/daphne pkgs

Other related changes:
* Added "daphne" to INSTALLED_APPS to provide us with an ASGI runserver.
* Changed a setting to make ASGI the default.

* docs: add a README to the example Django project

The docs explain why Django devs should use ASGI and explain how to use
WSGI if needed.
2025-03-28 19:49:13 -06:00
dpc 48e7a124a4
fix(docs): Clarify file input type derived signals (#800) 2025-03-28 08:35:24 -06:00
Ryan Riley dba88cb2fb
feat(fsharp/sdk): apply language guidelines (#797)
Proposed changes to internals to align with F# language guidelines for
static classes. See

- [F# component design guidelines](
https://learn.microsoft.com/en-us/dotnet/fsharp/style-guide/component-design-guidelines#use-namespaces-types-and-members-as-the-primary-organizational-structure-for-your-components)
- [Interop discussion](
https://github.com/fsharp/fslang-suggestions/issues/906)
2025-03-26 07:03:18 -06:00
Ben Croker 3c34e03b3d
Add timing modifiers (#795) 2025-03-25 08:26:55 -06:00
Ben Croker 41f87ae7b2
Remove link 2025-03-24 18:25:40 -06:00
Delaney 67ed84ca2a
Trigger SSE error event after retries finished (#794)
* Trigger SSE error event after retries finished
Fixes #785

* Add error event test

* Clean up

* Add release note and docs

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-03-24 18:20:06 -06:00
Ben Croker b676dea6eb
Docs fixes 2025-03-24 16:16:36 -06:00
Ben Croker a18dbfc539
Break up `on` plugin (#789)
* Break out plugins

* Rename to `data-signal-change`

* Rename plugins

* Break out `on` plugins

* `data-init` → `data-on-load`

* Fixes and errors

* Fix example

* Fix example

* Fix tests

* Fix tooling

* Add release notes

* Fix docs

* Remove `ctx.signals` docs

* Link text

* Update plugin icons

* Icon

* Update editor settings

* Remove expression context page

* Improve docs

* Tweak wording
2025-03-23 21:51:07 -06:00
Ben Croker d7fba2787e
1.0.0-beta.10 2025-03-23 10:15:43 -06:00
Ben Croker e28bb58eee
Remove ability to use key with `data-persist` (#788)
* Remove ability to use key with `data-persist`

* Fix example and test

* Update link
2025-03-23 08:35:42 -06:00
Ben Croker 09bd26ccd2
Persist key default to kebab-case 2025-03-21 21:47:28 -06:00
Ben Croker ea74aa41a5
Delay removing event listener to next macrotask (#784)
* Set indicator signal to `false` on error

* Delay removing event listener to next macrotask

* Add comment
2025-03-21 19:15:42 -06:00
Ben Croker 2534471565
Mark the target as a fragment merge target (#786)
* Mark the target as a fragment merge target

* Fix test
2025-03-21 19:11:18 -06:00
Casey Link 433bb6e5ab
Clarify that data-computed is a pure function (#778)
* Clarify that data-computed is a pure function

Also make explicit that `data-on-signals-change` is the alternative for
side effects.

* Update attribute_plugins.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-03-20 09:41:41 -06:00
Casey Link c6b1eaca30
Improve casing and modifier docs (#779)
* Emphasize two of the most important facts about d* attributes.

* Expand the attribute casing documentation

The previous top-line message "data-* attributes are case-insensitive", while
true, was very confusing for new users because it is not immedietly clear that
sentence is referring to the HTML spec and not the library of the docs they are reading.

So I've clarified the top-line message, and then expanded the explanation in a
way I hope makes it easier to understand the first time.

* Explain how to use modifiers with `data-signals`

(the object notation variant)

* Clarify it is possible to set both data-signals__ifmissing= and data-signals on the same element

* Update attribute_plugins.md

* Update attribute_plugins.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-03-20 08:08:17 -06:00
Casey Link e991742383
Improve the datastar expression guide (#776)
* Improve the datastar expression guide

After chatting with Anders, I got a list of "things to know" about D* expressions.

This commit expands upon the current docs, adding more facts, examples and some structure.

* Remove redundant heading

* Document usage of common js operators

* Update datastar_expressions.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-03-20 07:58:05 -06:00
Ben Croker 90b8b1cf35
Fix merge fragments with multiple targets (#781)
* Clone fragment before merging

* Add comment

* Add test

* Add release note
2025-03-19 17:49:03 -06:00
Chase Sterling d8dacf01d7
make python sdk compatible with python <3.11 (#777) 2025-03-18 10:49:11 -06:00
Chase Sterling 59c5221b7a
Make consts in python SDK more idiomatic. fix #767 (#773)
* Make consts in python SDK more idiomatic. fix #767

* Make python sdk consts match ruff formatting
2025-03-18 07:36:38 -06:00
Ben Croker db376dfbe4
Rename aliased bundle to `data-star-*` (#772)
* Rename alised bundle to `data-star-*`

* Add release note
2025-03-16 19:46:43 -06:00
Ben Croker 55a3f01318
Ignore keys with plugin names as prefixes (#771)
* Ignore keys with the plugin name as a prefix

* Tweak test

* PR number
2025-03-16 19:37:17 -06:00
Ben Croker a98f3b78ad
Tweak release note 2025-03-16 09:09:04 -06:00
Ben Croker 07fd37c9e5
Use svg logo 2025-03-16 08:05:18 -06:00
Ben Croker 6311779c40
Emoji logo 2025-03-16 07:21:12 -06:00
Ben Croker 56011be1ce
Cleanup 2025-03-16 07:17:08 -06:00
Ben Croker 08b5ac5e3a
Minor improvements 2025-03-16 05:48:47 -06:00
Ben Croker 5a3ee74bf5
Improve docs 2025-03-16 05:05:05 -06:00
Ben Croker 666a45827e
Revert 2025-03-15 20:18:37 -06:00
Ben Croker 1bd119caf6
Default to kebab-case and dispatch `datastar-sse` on element (#761)
* Rename event and dispatch on element

* Add release note

* Upate docs

* Fix test

* Make events bubble up

* Default to kebab-case

* Kebab

* Fix docs

* Default to kebab-case for `data-class-*`

* Fix missing argument

* Finalise docs
2025-03-15 19:32:29 -06:00
Ben Croker c35b85ce4e
Remove settling from SSE events and SDKs (#764)
* Remove settling

* Add release note

* Bump PHP SDK version

* Remove from composer
2025-03-15 16:25:33 -06:00
Peter Humulock 39cb56db3e
Java Example (#577)
* Java Example

* Fixing Java Example

* Fixing Java Example, removing thread.sleep. fixing dependencies
2025-03-15 07:29:33 -06:00
Ben Croker 9fbd96caed
More improvements 2025-03-13 13:13:38 -06:00
Ben Croker 0ada59177b
Tweak docs 2025-03-13 13:06:10 -06:00
Casey Link 1cb3d0118a
Add index for reference documentation (#763)
* Add index for reference documentation

* Rename index.md to overview.md

* Update routes_reference.go

* Update overview.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-03-13 12:54:19 -06:00
Jérémy 3a561c2faa
Clojure SDK - Ability to gzip sse streams - improvements - new how to code snippet (#747)
* Feature: gzip

Docs: changelog, removed todos
Feature: locking macro for sse generators.
Feature: flowstorm setup
Refactor: the SSE event writing code is now generic
Chore: bumped http-kit version
Feature: new malli schemas + fixes
Docs: adding the how to load more list items doc

* Fix: forgotten closing call

* Docs: fixed text

* Refactor: using write profiles to configure compression and buffering

Docs: modified the docs to reflect the new write profile mechanism
Refactor: changed the malli schema to go with the write profiles

* Feature: better error handling

* Docs: fixed unbalanced brackets / typos

* Docs: fixed example

* Docs: better write profiles docs

* Refactor: consistent namespaced keyword for all option

`:on-open` and `:on-close` options are deprecated

Docs: all callbacks are documented in docstrings
Calling context, return values and exception behavior are documented

* Refactor: using the new callback name everywhere

* Docs: Readme is redone and more docstrings
2025-03-13 09:41:49 -06:00
Ben Croker 92a7a92939
Add `data-on-resize` (#759)
* Add `data-on-resize`

* Add docs and release note

* Revert removals

* Rename element ID

* Fix `package.json` code gen

* Cleanup
2025-03-13 09:41:33 -06:00
Ben Croker ab1d5f11b1
Fix recursive error in SSE requests (#760)
* Fix recursive error

* Fix retry max count
2025-03-13 07:37:28 -06:00
Ben Croker d898f92cb9
Improve docs 2025-03-12 18:57:12 -06:00
Ismael Celis 2d1cf0ce54
Update Rack to 3.1.12 (#758)
Security patch
2025-03-12 07:32:11 -06:00
Casey Link 0201fc6a2e
Add double underscore naming constraint to signal docs (#757)
related to #753
2025-03-12 07:25:30 -06:00
Ben Croker 70376416fc
Fix 2025-03-11 16:42:30 -06:00
Ben Croker be186f3849
Add issue templates 2025-03-11 16:41:04 -06:00
Ismael Celis f17c99d50f
Update Rack dependency to 3.1.11 (#752) 2025-03-10 07:58:31 -06:00
Ben Croker 1c1e52ccce
Improve signal match (#751) 2025-03-09 17:04:26 -06:00
Ben Croker d3aac79e98
Add custom build page to docs (#750)
* Add custom build page to docs

* Improve wording
2025-03-09 17:04:13 -06:00
Mateusz Knapik 986ed894c1
Add exports for bundles and plugins (#748) 2025-03-09 09:12:52 -06:00
Ben Croker 65ea56a2e2
Reset indicator on element remove (#749)
* Fix indicator when element removed

* Add test

* Add release note
2025-03-09 09:03:38 -06:00
Ben Croker 100e4ac64c
Add `getEventOutput()` method (#739)
* Add `getEventOutput` method

* Comment

* Move get output method into event trait

* Clean up imports
2025-03-07 16:05:51 -06:00
Ben Croker bf1a64d697
Delay applying plugins (#743)
* Delay applying plugins

* Update readme

* Add passing test

* Use `queueMicrotask`

* Add release note
2025-03-07 16:02:01 -06:00
Ben Croker bceefa2122
Update Idiomorph to v0.7.3 (#746)
* Update Idiomorph to v0.7.3

* Add release note
2025-03-07 13:12:33 -06:00
Johnathan Stevers 685c033cf4
Zig SDK remove use of deprecated `ArrayList` (#745)
* remove use of deprecated `ArrayList`

* bump version
2025-03-07 08:33:34 -06:00
Johnathan Stevers eb825e2b7d
Zig SDK match new `build.zig.zon` format (#728)
* update build.zig.zon and comment out tk

* update tokamak and add framework option to build.zig

* update readme
2025-03-06 17:38:14 -06:00
Ben Croker 4322b99559
Allow a settle duration of `0` in Go SDK (#741) 2025-03-06 17:34:46 -06:00
Ben Croker 4c0bf6dfbd
Fix typos [deploy-site] 2025-03-05 21:22:27 -06:00
Ben Croker 750883a2d1
Fix typos [deploy-site] 2025-03-05 20:35:18 -06:00
Ben Croker 94a691e059
Reduce settle duration [deploy-site] 2025-03-05 20:22:12 -06:00
Ben Croker bebd836f45
Add load more how to [deploy-site] 2025-03-05 19:53:43 -06:00
Lucian d60f326230
Fix fasthtml simple example (#736) (#737)
* fix(python sdk): fasthtml simple example import from responses

* fasthtml examples: URLs use latest datastar version

Replace versioned CDN URLs with unversioned ones in FastHTML examples to
automatically use the latest Datastar bundle.

* fix(python examples): fasthtml use repo datastar bundles

---------

Co-authored-by: Lucian Knock <git@lucianknock.com>
2025-03-05 09:17:24 -06:00
Greg H 7d20db71f6
sdk/dotnet-v1 (#734)
* sdk/dotnet-v1 - simplified API surface with static members; fixed a bug with remove signals; fix to caching when retrieving signals mutiple times; removed Datastar prefix from filenames

* sdk/dotnet-v1-beta.4

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-03-04 16:21:46 -06:00
Ben Croker 42acbff4a2
Fix example [deploy-site] 2025-03-03 08:36:23 -06:00
Tom D. 182610e046
Don't send retry unless explicitely specified (#729) 2025-03-02 09:16:12 -06:00
Ben Croker 72e1c2c07e
Improve tests 2025-03-01 17:38:28 -06:00
Delaney Gillilan 69bf92b634 fix removal of unused parameters 2025-03-01 14:57:39 -08:00
Delaney 256dad1ba6
Add missing go merge helpers (#727)
* Add missing go merge helpers
Fixes #726

* strip helper in changelog
2025-03-01 16:28:48 -06:00
Ben Croker 750cd44740
Cleanup redundant code (#725)
* Cleanup redundant code

* Build
2025-03-01 16:20:06 -06:00
Ben Croker 2925230e34
Rename tests 2025-03-01 13:33:33 -06:00
Ben Croker d8b22b58fa
Fix typo 2025-03-01 13:15:41 -06:00
Ben Croker 3d16cabd5a
Fix checkbox array values (#724)
* Fix checkbox array values

* Rename functions
2025-03-01 13:12:48 -06:00
Ben Croker 45db7d9d29
Add `BindSelectMultiple` error 2025-02-28 22:15:22 -06:00
Ben Croker 978598f52d
Prep for 1.0.0-beta.9 2025-02-28 11:14:22 -06:00
Ben Croker 8f1a8d6b75
Tweak docs 2025-02-28 11:12:13 -06:00
Ben Croker 0d07c77ef4
Add release note 2025-02-28 10:34:04 -06:00
Ben Croker 42a2384666
Fix the `__delay` modifier (#721) 2025-02-28 10:16:01 -06:00
Delaney edc0b5b8d3
Bind Array Text/Number/Boolean (#716)
* Bind Array Text/Number/Boolean
Fixes #715

* cleanup

* Improve tests

* Remove `BindUnsupportedSignalType`

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-02-28 08:50:06 -06:00
Johnathan Stevers 641774ea66
Zig SDK Changes (#718)
* convert to writer and change mergeSignals api

* add snippets

* add redirect and errdefers

* fix writer

* bump version

* fix typo

* update readme
2025-02-28 07:16:09 -06:00
Ben Croker e40db72ed5
Fix merge fragments (#711)
* Restore elUniqId, removeOnLoad

* Store cleanup function only if not removed

* Restore elUniqId (again)

* Fix empty value being replaced

* Rehash the cleanup functions

* Cleanup

* Fix persist example

* Use el.id

* Remove `removeOnLoad`

* Restore check for existing mutationObserver

* Move

* Add release notes

* Improve tests
2025-02-27 21:16:50 -06:00
Johnathan Stevers a7df17505f
Update Zig SDK dependencies (#712)
* update deps

* add config to test

* swap to debug allocator

* bump version

* update example deps
2025-02-26 20:05:16 -06:00
Ben Croker cab1456bd1
Fix action 2025-02-26 12:19:36 -06:00
Ben Croker 8685255430
Improve security docs [deploy-site] 2025-02-26 07:42:04 -06:00
Patrick Marchand 14dab8a652
Typescript sdk standardization (#700)
* Bring typescript sdk in line with sdk api's

But still allow passing of stricter types when it makes sense

* fix bug introduced in https://github.com/starfederation/datastar/pull/698

we want the stream to be ended only if keepalive is not present

* Remove close method from typescript sdk and improve comments

The stream is closed automatically after the callback runs.
The only situation where we want to use keepalive is if we
want an infinite stream, in which case we dont want to close it.

* improve package.json for typescript sdk

* Use consts VERSION in typescript sdk tests

* Improve method comments in typescript sdk

this sdk is also used in javascript where there's less type information
2025-02-26 07:33:57 -06:00
Ben Croker e44f446eea
Specify branches 2025-02-25 21:06:41 -06:00
Ben Croker ff56adcc40
Remove section from docs [deploy-site] 2025-02-25 21:01:51 -06:00
Ben Croker 57a0f468ac
Remove line break 2025-02-25 09:30:30 -06:00
Ben Croker 116a1362f9
Fix code sample in readme 2025-02-25 09:29:28 -06:00
Ben Croker a454c450c6
Allow push events 2025-02-25 09:22:12 -06:00
Ben Croker 73d86f27b7
Remove legacy `removeOnLoad` 2025-02-25 09:17:20 -06:00
Ben Croker c6567508e3
Bump PHP SDK version 2025-02-25 09:14:03 -06:00
Ben Croker 87b200f764
v1.0.0-beta.8 2025-02-25 09:06:18 -06:00
Patrick Marchand 624d24b2f6
fix sdk npm package (#705) 2025-02-25 08:58:02 -06:00
Ben Croker 3cf9802bae
Document SSE events
Fixes #581
2025-02-24 21:40:01 -06:00
Johnathan Stevers 1e5c238690
Order independent testing (#593)
* normalize output and test output and then compare

* separate ordered data lines from unordered data lines + only remove space after colon if its after a key at the beginning of the line

* don't remove space after colon

* only sort unordered fields

* update readme

* add gitignore to sdk/.test folder
2025-02-24 21:22:40 -06:00
Ben Croker 41ee5b7de5
Document alias and remove `prefix` (#704)
* Document alias and remove `prefix`

* Remove example
2025-02-24 21:06:06 -06:00
Ben Croker 2c0cc510e1
No longer run callable on init (#703)
* No longer run callable on init

* Add release note
2025-02-24 19:57:34 -06:00
Delaney 9e12b9076c
695-Embrace-our-functional-overlords (#702)
* Replace legacy call to `applyAttributePlugin`
Fixes #699

* Ignore when alias prefix missing

* Remove merge fragment callbacks

* add bundler support

* Embrace our functional overlords
Fixes #695

* change to djb2 hash

* Replace reference page

* Add reference docs pages

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-02-24 18:00:01 -06:00
Delaney 391de46e08
699-Replace-legacy-call-to-`applyAttributePlugin` (#701)
* Replace legacy call to `applyAttributePlugin`
Fixes #699

* Ignore when alias prefix missing

* Remove merge fragment callbacks

* add bundler support

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-02-24 11:31:25 -06:00
Ben Croker a4c2e87473
Refactor SDK snippets and add title 2025-02-23 17:48:01 -06:00
Patrick Marchand 2db7468cd5
Typescript sdk improvements (#698)
* improvements to node sdk

Add abort handling to node sdk, make onError simpler and close stream by default

 - closes https://github.com/starfederation/datastar/pull/667
 - closes https://github.com/starfederation/datastar/issues/602

* Improvements to typescript sdk readme

Ben Croker wanted a mergeSignals example

* Make typescript sdk pass tests

* add missing typescript snippets and use same name as sdk folder

* update datastar version in typescript sdk test servers
2025-02-23 17:11:35 -06:00
Ben Croker 32d4f920f6
Add `aliased` test 2025-02-23 10:41:48 -06:00
Ben Croker 0942459599
Fix `data-attr` not removing element attribute (#697)
* Fix `data-attr` not removing element attribute

* Typo
2025-02-22 17:39:28 -06:00
Ben Croker 17f22018ba
Ensure plugins not reapplied (#691)
* Update to 0.7.2

* Fix indicator and remove auto ID generation

* Setup

* Data-* attributes hash their contents

* Update release notes

* Revert star.ts and remove test

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2025-02-22 17:05:47 -06:00
Ben Croker 0c085c320d
Update Idiomorph to 0.7.2 (#688)
* Update to 0.7.2

* Fix indicator and remove auto ID generation
2025-02-22 13:00:52 -06:00
Ben Croker e77a68f6a6
Debounce applying plugins on page load (#690)
* Debounce applying plugins on page load

* Fix action
2025-02-22 11:37:27 -06:00
Ben Croker 657c1c8492
Fix and add tests 2025-02-22 10:56:47 -06:00
Ben Croker 440ac29fb2
Update branch policy 2025-02-22 10:33:09 -06:00
Ben Croker 4f84035efc
Add new docs for `data-bind` 2025-02-22 10:29:38 -06:00
Ben Croker b7caf5e41c
Test command runs unit tests only (#689)
* Test command runs unit tests only

* Update paths in action

* Enforce branch policy

* Add passing check
2025-02-22 09:57:27 -06:00
Ben Croker 1e7f0dd8d2
Add release note 2025-02-21 20:43:30 -06:00
Ben Croker 8f17404aae
Default to element value using `data-bind` (#687)
* Default to element value using `data-bind`

* Fix tests

* Destructure result

* Destructure again
2025-02-21 20:28:05 -06:00
Delaney 2012286f8f
DatastarNaN added to datastar elements without ids (#684) 2025-02-21 16:22:38 -06:00
Ben Croker 821bdfd7ee
Add checkbox value behaviour based on signal type (#674)
* Modify checkbox and radio behaviour

* Add array and string types

* Move code into block

* Refactor and add tests

* Add release note
2025-02-21 12:35:38 -06:00
Ben Croker bc395f4932
Add `develop` branch 2025-02-21 11:12:10 -06:00
Ben Croker d245ab10a5
Fix example link 2025-02-21 11:10:10 -06:00
Ben Croker 7a24033982
JavaScript 2025-02-21 11:00:35 -06:00
Akash Gill 7ee8d30e11
Fix text overflow on buttons (#681) [deploy-site] 2025-02-19 20:16:18 -06:00
Ben Croker 3bc1f28019
Improve wording 2025-02-19 13:26:38 -06:00
Lucian b85a6b1241
feat(SDK): FastHTML SSE response and example (#576) (#624)
* feat(SDK): FastHTML SSE response and example (#576)

* feat(sdk): add simple fasthtml example

* remove comments

---------

Co-authored-by: Lucian Knock <git@lucianknock.com>
2025-02-19 10:40:30 -06:00
Ben Croker c86c69d072
Better fix [deploy-site] 2025-02-19 09:45:53 -06:00
Ben Croker a9c8e6ed11
Fix #677 [deploy-site] 2025-02-19 09:25:30 -06:00
Ben Croker 03d36e849c
Maintain whitespace (#678) 2025-02-18 19:54:50 -06:00
Ben Croker de567de237
Fix code samples [deploy-site] 2025-02-18 11:18:34 -06:00
Jérémy f500e93183
Clojure sdk: Fixes, clojure snippets (#672)
* Clojure sdk: Fixes, new website snippets

Docs: corrected the readme's example
Fix: changed return value in the jetty implementation
Chore: Changed dependency coordinate of http-kit to a newer maven dependency
Fix: using setTimeout in the redirect sugar function
Fix: mistake in http-kit management in examples
Docs: redirect example
Feature: added another testing utility
Docs: added missing snippets for the Datastar website

* Fix: typo
2025-02-17 12:34:58 -06:00
Claes Ström d20737a75c
A typo in getting_started.md (#673)
Closing tag for the  data-computed example has an extra ">"
2025-02-16 11:56:01 -06:00
Ben Croker 9cda19db84
Update PHP SDK 2025-02-14 10:29:51 -06:00
Ben Croker 47afc9e01e
v1.0.0-beta.7 2025-02-14 09:10:45 -06:00
Ben Croker 3cd4a5d079
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2025-02-14 09:08:15 -06:00
Ben Croker 23134b4b8e
Update to Idiomorph 0.7.1 (#668)
* Update to Idiomorph 0.7.0

* Add release note
2025-02-14 09:06:53 -06:00
Ben Croker 0d544431ed
Rename signal 2025-02-14 09:05:40 -06:00
Ben Croker fbea7b1d71
Add local signals test 2025-02-14 08:49:31 -06:00
Ben Croker e90319dad3
Remove year 2025-02-13 13:50:23 -06:00
Ben Croker 5e06342a3a
Link to repo root [deploy-site] 2025-02-13 13:15:19 -06:00
Greg H a44f86d051
sdk/dotnet - ReadSignals<T>(JsonSerializerOptions) (#666)
* sdk/dotnet - reduced abstraction. SSE header response moved out of constructor

* sdk/dotnet - removed support for .NET 6 and 7

* sdk/dotnet - IReadSignals.ReadSignals<T> will accept JsonSerializerOptions

* sdk/dotnet - bumped the version to 1.0.0-beta.3

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-02-13 09:46:42 -06:00
Ben Croker 1e9c7a820b
Fix remove fragment (#665)
* Replace delay function call

* Add test

* Improve tests

* Add release note
2025-02-13 09:38:29 -06:00
Ben Croker 2a16577829
Document key with on-signals-change [deploy-site] 2025-02-13 07:55:04 -06:00
Felix Hofmann-Oggier 2f8cfea9ba
data-class with hyphenated className (#662)
s/bold/'font-bold'
2025-02-12 17:30:09 -06:00
Ben Croker ee1b2e460d
Re-add missing example [deploy-site] 2025-02-12 17:13:07 -06:00
Ben Croker e822f2c416
Prep for v1.0.0-beta.6 2025-02-12 16:37:12 -06:00
Ben Croker 8b1c46bd7b
Improve docs example 2025-02-12 15:51:11 -06:00
Ben Croker f36327c36d
Add assignment to test 2025-02-12 15:45:12 -06:00
Ben Croker 8b4e750986
Improve test 2025-02-12 15:40:54 -06:00
Ben Croker 6b2130b1bf
Cleanup and fix test (#660)
* Clean up code comments

* Fix test
2025-02-12 15:20:39 -06:00
Ben Croker 18a69f44ce
Delay the `on-load` callback to the next microtask (#659)
* Delay the `on-load` callback to the next microtask

* Add release note
2025-02-12 10:52:23 -06:00
Ben Croker 54dab9a2a7
Remove legacy function (#657) 2025-02-12 09:59:05 -06:00
Ben Croker 6e677ad352
Build 2025-02-12 09:52:45 -06:00
Ben Croker faaf52f5ee
Add release note 2025-02-12 09:50:12 -06:00
Michael Bolli b9dc373e63
README.md: fix button links (#652)
* README.md: fix button links

Buttons referenced themselves

* Update README.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-02-12 09:47:10 -06:00
Ismael Celis f87279552a
Bump version in Gemfile too (#656) 2025-02-12 09:44:03 -06:00
Delaney 2fd150f56c
643-Stop-catching-error-in-`preact-corets` (#651)
* Stop catching error in `preact-core.ts`
Fixes #643

* cleanup
2025-02-12 09:43:42 -06:00
Ben Croker 752b91d9b9
Add release note 2025-02-12 09:42:33 -06:00
Delaney e4ad61c5c5
Website Inline Validation Demo loses focus (#653)
Fixes #645
2025-02-12 09:21:41 -06:00
Ismael Celis defedfa44d
Ruby heartbeats (#654)
* :heartbeat option

* Make heartbeat global configuration

* Document heartbeat

* Bump version to 1.0.0.beta2
2025-02-12 09:21:19 -06:00
Ben Croker 5c890ecf09
Fix sending headers 2025-02-11 19:18:10 -06:00
Ismael Celis 7c696b15a3
Remove reduntant example (#649) 2025-02-11 18:21:48 -06:00
Ismael Celis 0e3a4c980b
Add LICENSE.md (#648) 2025-02-11 15:37:54 -06:00
Aleš Vaupotič 5ea8fd7fc4
Update sdks.md to point to correct examples for Typescript (#647)
Link is 404 as all other languages live in /examples, while TS examples are in its own SDK folder. They should probably be moved with the others, but for now, at least links should point to where they are available currently.
2025-02-11 13:51:09 -06:00
Ben Croker 781ea7764b
Remove cleanup function in `ref.ts` (#644)
* Remove cleanup function in `ref.ts`

* Add release note
2025-02-11 11:26:30 -06:00
Ben Croker 14b2dd351a
Merge branch 'tests' into develop 2025-02-11 11:10:13 -06:00
Ben Croker dcf1d00810
Add tests and standard test setup 2025-02-11 10:24:38 -06:00
Ben Croker 2b5e59c418
Ignore dist folder 2025-02-11 08:45:12 -06:00
Ben Croker a685ec5d5b
Merge branch 'intellij-plugin-updates' into develop 2025-02-11 08:42:39 -06:00
Ben Croker 8a9a7f2630
Update IntelliJ plugin 2025-02-11 08:42:13 -06:00
Ben Croker f29f3fb98c
Add test 2025-02-10 22:02:44 -06:00
Ben Croker b3a5dbbfdb
Add tests 2025-02-10 19:42:40 -06:00
Ben Croker a76d3ecb2d
Add modifiers 2025-02-10 10:43:16 -06:00
Ben Croker fa679aa40c
Add release note 2025-02-10 10:34:32 -06:00
Ben Croker e89639050d
Fix test to confirm bugfix 2025-02-10 10:31:54 -06:00
Delaney Gillilan cc75d774e9 needs testing 2025-02-10 08:08:17 -08:00
Ben Croker 86e07b3a6b
Add `ctx.signals` to docs [deploy-site] 2025-02-10 08:54:10 -06:00
Ben Croker 1acef4efc3
Add local signals to docs [deploy-site] 2025-02-10 08:44:43 -06:00
Ben Croker ad47bdfb85
Revert `data-on-signals-change` example 2025-02-10 08:16:26 -06:00
Ben Croker ea71691061
Fix CDN link [deploy-site] 2025-02-10 08:10:18 -06:00
Ben Croker 0480644851
Fix typo 2025-02-09 20:33:54 -06:00
Ben Croker dc3c406346
Update release note 2025-02-09 17:43:23 -06:00
Ben Croker c8a7e58b50
Fix PHP snippets 2025-02-09 17:31:46 -06:00
Ben Croker 31b0c51a76
Prep for beta.5 2025-02-09 17:29:43 -06:00
Delaney afa40c83aa
Idiomorph v0.5.0 breakage (#638)
Fixes #637
2025-02-09 17:27:40 -06:00
Ben Croker 2e9570f0ae
Bump PHP SDK version 2025-02-08 21:17:23 -06:00
Ben Croker 0a00bed483
Revert "update changelog"
This reverts commit bbdb8d6652.
2025-02-08 21:13:32 -06:00
Delaney Gillilan bbdb8d6652 update changelog 2025-02-08 19:11:18 -08:00
Delaney Gillilan 4042dc0e25 fix in memory fuzzy search embedded pathing 2025-02-08 19:11:01 -08:00
Ben Croker 860aa9e46d
Add videos link 2025-02-08 19:55:02 -06:00
Ben Croker c89da30a6d
Update version numbers 2025-02-08 19:49:01 -06:00
Ben Croker 1004107c93
Prep for 1.0.0-beta.4 2025-02-08 19:10:38 -06:00
Delaney 9945394a79
Idiomorph v0.5.0 (#634)
* Idiomorph v0.5.0
Fixes #633

* Build

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-02-08 17:40:34 -06:00
Ben Croker 8a0fedf30b
Merge Zig README 2025-02-08 17:22:27 -06:00
ravenclaw900 ed9f5748ac
Minor fixes for the Rust SDK (#632)
* Add necessary dev-dependencies for testing

* Update some crate metadata

* Replace all implementations of `Into` with `From`

* Replace `write!` with `writeln!` when applicable

* Replace `futures` crate with slightly more minimal `futures_util` crate

* Clarify uses of `Default::default()`
2025-02-08 17:16:39 -06:00
sdenovan 65b017d65f
docs: include byte[] casts for MergeSignals golang examples (#635) 2025-02-08 17:16:17 -06:00
Ben Croker c90c09e741
Add `viewtransition` modifier to `data-on` (#631)
* Add `viewtransition` modifier to `data-on`

* Refactor to use util

* Add example

* fix morty mistakes

* Add release note and docs

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2025-02-08 17:14:26 -06:00
Ben Croker ef05be33a8
Improve `data-on` docs 2025-02-08 09:25:50 -06:00
Johnathan Stevers 6d16a23999
Prepare Zig SDK for standalone repo (#628)
* prepare zig sdk for its own repo

* fix missing opts

* update dependencies

* add option for http1

* update readme
2025-02-08 08:11:49 -06:00
Greg H 16714ed0ad
sdk/dotnet updates (#630)
* sdk/dotnet-updates - added ability to append custom headers to sse response

* sdk/dotnet-updates - updated README with Model Binding examples

* sdk/dotnet-updates - nuget package version should reflect properly. no release made in github

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-02-08 08:10:04 -06:00
Ben Croker 91f5f07413
Observe DOM only after loading core plugins (#629) 2025-02-08 07:47:15 -06:00
Ben Croker 305b8eca89
Tweak spacing 2025-02-07 21:16:30 -06:00
Ben Croker 4fb2aa5b6a
Fix typo 2025-02-07 17:58:46 -06:00
zangster300 bd17ab4809
update to smoketests, reducing failure rates (#626) 2025-02-07 08:29:30 -08:00
Ben Croker 01702f0fde
Fix file extension not file extension 2025-02-06 17:42:47 -06:00
Henry Laxen 18ea30972e
Haskell SDK (#622)
* ready for pull request

* I had the consts_haskell.qtpl in the wrong place

* made changes requested by Ben

* made changes requested by Ben

* fixed license and version in cabal

* more changes per Ben

* renamed dstar.cabal to datastar.cabal

* Update LICENSE

* Rename LICENSE to LICENSE.md

* Update datastar.cabal

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-02-06 17:30:14 -06:00
Ben Croker 467aeb4312
Clarify that SDKs are optional 2025-02-06 09:04:56 -06:00
Ben Croker b874aa16e2
en-US 2025-02-06 08:03:31 -06:00
Ben Croker e1fb273cd8
Clarify SDK 2025-02-06 07:51:20 -06:00
Ben Croker 7314357d2e
Minor improvements 2025-02-05 21:43:29 -06:00
Ben Croker 39a4e1553c
Language fixes 2025-02-05 21:11:10 -06:00
Ismael Celis 229183f136
Ruby SDK support rails render_in interface (#617)
* Support Rails' #render_in(view_context) interface

So render arbitrary objects, including component libs like ViewComponent and Phlex Rails.

* Render anything that supports #to_s, including Rails' safe buffers

* Make sure Rails view_context is an ActionView::Base

* Document
2025-02-05 20:48:51 -06:00
Ben Croker 3e5f1aaa09
Revert removal of links 2025-02-05 20:42:04 -06:00
Ben Croker 0d08df81ec
Add release notes 2025-02-05 20:41:09 -06:00
Ben Croker ead432fe04
Tweak styling 2025-02-05 19:24:28 -06:00
Delaney b6319e9b1d
data-on-signals-change-foo (fixes #587) (#592)
* Add optional key to `data-on-signals-change`
Fixes #587

* support files

* Listen for changes to signal path

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-02-05 19:10:23 -06:00
Ben Croker c0adef6eea
Remove code comment
Build
2025-02-05 17:58:50 -06:00
Ben Croker 84a31ca6a0
Fix signals `__ifmissing` (#621)
* Add casing modifiers to attributes

* Lower case key

* Refactor text utils

* cleanup ternary

* fix case example

* Finish

* Upsert signals with `ifmissing`

* Add release note

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2025-02-05 17:51:15 -06:00
Ben Croker d97cd5f40a
Add key casing modifiers (#618)
* Add casing modifiers to attributes

* Lower case key

* Refactor text utils

* cleanup ternary

* fix case example

* Finish

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2025-02-05 17:39:52 -06:00
zangster300 4aafd4262f
update setup_test.go to change dir before kicking things off (#619) 2025-02-05 16:55:15 -06:00
Ben Croker d45517ffbb
Fix fragment morph (#608)
* Add example to demonstrate

* upgrade to latest idiomorph

* Remove test file

* fix possible removal on apply

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2025-02-05 16:02:57 -06:00
JeremS 32a14d985a
Doc: fixed improper coordinates for using the clojure SDK (#613)
I mistakenly provided the wrong url in the docs, generating
an error for users wanting to use the sdk. It is now fixed.
2025-02-05 12:32:36 -06:00
Ismael Celis 5d46096dc2
Ruby SDK (#600)
* WiP initial setup, ServerSentEventGenerator class

* WiP working merge_fragments in Rails

* #merge_fragments and #merge_signals

* Handle SSE vs Data* options

* Test that #merge_fragments works with a #call(view_context:) interface

* Test Dispatcher#stream

* #remove_fragments

* #remove_signals

* #execute_script

* execute_script with attributes Hash

* Connection: keep-alive

* Use 2 line-breaks as message end, plus last line's 1 line break (3 total)

* Connection callbacks. #on_connect, #on_disconnect, #on_error

* Dispatcher#signals

* Omit retry if using default value (1000)

* Omit defaults

* Multiline scripts

* Test Rack endpoint

* Document test Rack endpoint

* Add missing defaults

* Spawn multiple streams in threads, client_disconnect and server_disconnect handlers

* Move ThreadSpawner to configuration

* Configure a RailsThreadSpawner when Rails detected

* Move Railtie one dir up

* Global error callback

Datastar.config.on_error { |err| Sentry.notify(err) }

* Catch exception from stream threads in main thread

* Linearlize exception handling

* Refactor dispatcher to handle single stream in main thread, multi streams in separate threads

* spawner => executor. Rails Async executor using fibers.

* Support Async for fiber-based concurrency

* Finalize response for Rack and Rails

* test Rack app

* Threaded demo

* Test Dispatcher#sse?

Also do not check for SSE Accept on stream.
Leave it up to the user.

* Do not check Accept header in test app. Test scripts don't send it properly.

* Document code

* Example progress bar Rack app

* README

* Link to D* SSE docs

* See examples

* Document callbacks

* List Ruby SDK in SDKs.md

* Ruby struct in consts.go

* Document running tasks with arguments via Docker

* Code-gen Ruby constants from shared data via template

* Make test rely on constants

* Datastar.from_rack_env(env) => Datastar::Dispatcher

* Ruby example snippets

* #redirect(location)

* Ruby snippet using #redirect(new_path)

* Add X-Accel-Buffering: no header

To disable response buffering by NGinx and other proxies.

* Clarify linearisation of updates in Readme

* Tidy-up progress example

* Move examples to /examples/ruby

* Document Rails and Phlex

* Version 1.0.0.beta.1

* Version 1.0.0.beta.1

* Do not set Connection header if not HTTP/1.1

* Don't touch BUILDING.md docs in this PR

* Remove Changelog for now

* Sort Ruby alphabetically (just "ruby", not the entire line)

* Add hello world example, remove progress bar one.

* Add hello-world example to code-gen

* Typos
2025-02-05 12:02:18 -06:00
Ben Croker ca5414c358
Stop kebabizing class (#611) 2025-02-05 10:02:10 -06:00
Roman Frołow 5a4b4d699e
Accomodate Zig SDK and examples to test runner changes (#601)
* update zig to work on master

* Updated deps, fixed to use tests.zig as root, add datastar as module, refactoring

* Update test_runner.zig. Move tests to root.zig.

* tokamak: use post0 when no body
2025-02-05 09:39:00 -06:00
zangster300 bc21b05164
switching tests back to one web server, many pages (#609) 2025-02-05 08:53:24 -06:00
Ben Croker d3b50bc3a9
Fix TypeScript snippets (#597)
* Fix snippets

* Use proper casing
2025-02-05 07:10:04 -06:00
Patrick Marchand 7a994bdff3
Add Accept: text/event-stream to bash tests (#607)
Datastar responses are also valid SSE responses, and the D* client already sends `Accept: text/event-stream` to the server, so tests should replicate that.

Some servers might rely on this for content negotiation.

Co-authored-by: Ismael Celis <ismaelct@gmail.com>
2025-02-04 16:41:41 -06:00
Patrick Marchand 1d74d2328a
Sdk ts web improvements (#551)
* sdk/typescript add support for ResponseInit in web stream method

This allows setting custom headers

* sdk/ts elide datalines with default values

* sdk/ts run deno fmt

* sdk/typescript deno lint

* sdk/typescript better error handling for streams

* sdk/typescript improve deno request abortion support and async completion

* sdk/typescript fix type error in error usage
2025-02-04 16:39:41 -06:00
Ben Croker 552c55939d
Dispatch `RETRYING` SSE event (#585) 2025-02-04 15:41:10 -06:00
Ben Croker 437f8bcf53
Add release note 2025-02-04 15:14:07 -06:00
Ben Croker 0c33439fa6
Restructuring 2025-02-04 12:32:42 -06:00
Ben Croker b4a11683fb
Add `run.go` 2025-02-04 12:31:21 -06:00
Ben Croker 71b95c8949
Wording 2025-02-04 12:28:29 -06:00
Ben Croker 0975e24224
Improve wording 2025-02-04 12:25:06 -06:00
Ben Croker b00c6d160e
Add SDK Contribution Guidelines [deploy-site] 2025-02-04 12:19:08 -06:00
JeremS 65a301da9e
Fixing issue #571 / minor changes, improvements (#590)
* Refactor: Ring jetty adapter is now a generic ring adapter

Minor changes:

- Properly eliding SSE retry duration
- Added a small utility in the main api.
- Added a new option to the ->sse-response functions to support
  modifying the HTTP response status.
- Fixed typos and errors in the docs.
- using consts version number.
- Prepared tests for rj9a
- Properly killing webrivers when shutting down tests

* Docs: fixing the fixed typo
2025-02-04 08:15:06 -06:00
Johnathan Stevers bca69f6a57
rust and zig snippets (#594) 2025-02-04 08:05:43 -06:00
Ben Croker ff52c94fb5
Improve SDKs [deploy-site] 2025-02-04 08:02:14 -06:00
Greg H 41198f3479
sdk/dotnet-nuget_version (#589)
* sdk/dotnet-nuget_version - updated the nuget version to 1.0.0-beta.3

* sdk/dotnet-nuget_version - updated the nuget version to 1.0.0-beta.1

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-02-03 20:31:19 -06:00
Greg H 77700d2e2f
task/dotnet-howtos - added polling and redirect howtos #517 (#591)
Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-02-03 19:28:02 -06:00
Greg H 9b61ee4f67
sdk/dotnet model binding (#574)
* sdk/dotnet - more renaming, doco, and code shortening; caching of signals

* sdk/dotnet - added model binding

* sdk/dotnet-model_binding - FromSignals behaves more like other From* attributes

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-02-03 17:55:05 -06:00
Johnathan Stevers 284c42d981
Fix typo in how_to_bind_keydown_events_to_specific_keys.md (#586)
Changes `whenver` -> `whenever`
2025-02-03 14:01:09 -06:00
Josh 6b726a340e
Add search to the website (#522)
* add description to the markdownRenders func

* add /api/search using bleve

* wrap search functionality in a basic feature flag

* remove some comments that are not needed

* add desktop styling for search

* undo add feature flag

* mobile styling

* fix: merge correct fragment

* fix: menu item being cut off on mobile

* Add keyboard shortcut to add focus

* fix: loading indicator jank

* Styling tweaks

* remove un-neccessary ids

* Update site.css

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-02-03 10:10:33 -06:00
Delaney 9901ae7f4d
Attribute Order issue (#582)
Fixes #580 by adding alias to hash
2025-02-03 09:43:46 -06:00
Ben Croker fe409baf4c
How-to Guides (#517)
* Add polling

* Rename file

* Add `how_to_redirect_the_page_from_the_backend`

* Add Hello World example guide

* Add to nav, start on polling

* Remove `.leading` from code snippets

* Fix typo

* How to bind keydown events to specific keys

* How to redirect from the backend (#565)

* Add how tos with demos

* Fixes

* Fixes

* Add snippets

* Rename to location in snippet

* Wording

* Tweaks

* Prep for merging

* Improve wording

---------

Co-authored-by: Dominik Tarnowski <dom@tdom.dev>
2025-02-03 08:39:38 -06:00
Ben Croker cbbb640533
Fix URLs [deploy-site] 2025-02-03 08:29:15 -06:00
Ismael Celis 97c0760a48
Make SDK tests use bash exit instead of return (#579)
* Use exit instead of return in bash scripts

Return is to return from functions, not scripts.

* Test scripts: exit 1 y files differ
2025-02-03 07:16:49 -06:00
Johnathan Stevers 1d8105af11
elide retry if default (#578) 2025-02-02 21:19:32 -06:00
Lucian 38c0547dfa
Fix overflow issues and add menus (#567) (#575)
* mobile: fix overflow issues (#567)

* add dropdown

---------

Co-authored-by: Lucian Knock <git@lucianknock.com>
Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2025-02-02 20:51:43 -06:00
Johnathan Stevers 93852fc1ad
Rust SDK framework integration + hello-world examples (#558)
* remove infinite scroll example

* add rocket and axum example

* rework how framework integration works

* rocket integration

* add .gitignore

* dont elide `retry`

* add "read signals" to rocket hello-world example

* don't elide `retry` in display

* remove mime dependency

* update cargo.toml

* add underscore to unused consts

* formatting

* use `async_stream` instead of "hand writing" streams

* add axum test

* fix errors

* implement custom sse stream for axum and rocket

* generate hello-world.html

* update readme

* don't track cargo.lock
2025-02-02 18:14:20 -06:00
Ben Croker 539152a127
Fix SDK formatting 2025-02-02 12:12:09 -06:00
Ben Croker ed980b3d4c
Update SDKs to ignore `retry` if set to default (#573)
* Update SDKs to ignore `retry` if set to default

* Remove from test output

* Build
2025-02-02 11:31:39 -06:00
Prateek Rungta 854ce6ed30
Fix missing `}` (#569) 2025-02-02 07:35:00 -06:00
Ben Croker 16161d8309
Update PHP SDK 2025-02-01 19:49:59 -06:00
Ben Croker 652fd1e130
Improve redirects in SDKs 2025-02-01 18:54:50 -06:00
Ben Croker 2ee3ad21a4
Update JetBrains plugin 2025-02-01 10:15:53 -06:00
Ben Croker 9b2d620499
Remove danglish URI [deploy-site] 2025-02-01 09:53:43 -06:00
Ben Croker dbff015dc9
Update again 2025-02-01 09:28:16 -06:00
Ben Croker fb8325c583
Update VSCode extension 2025-02-01 09:21:01 -06:00
Delaney Gillilan 3f95087783
fix ts pub task 2025-02-01 08:55:29 -06:00
Ben Croker eb8b3b1c5b
Clear out changelog 2025-02-01 08:54:58 -06:00
Ben Croker c25cbec470
Update CDN links 2025-02-01 08:41:17 -06:00
Ben Croker 701370246f
Prep for 1.0.0-beta.3 2025-02-01 08:35:20 -06:00
Ben Croker d7b527f39e
Add release notes 2025-01-31 20:12:24 -06:00
Delaney 51671c666d
Bundler aliasing (#555)
* Bundler aliasing
Fixes #554

* Bundler aliasing
Fixes #554

* Add release note

* Improve alias prefix handling

* Check using `startsWith`

* Use raw key in removals

* Update JavaScript API docs

* Add aliased bundle

* Fix example

* Fix wording

* Fix logic

* skip flaky tests

* Fix and simplify logic

* Rewrite condition

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-01-31 20:03:53 -06:00
Ben Croker a5c2e8624b
Add missing runtime errors 2025-01-31 19:59:06 -06:00
Ben Croker 31d2080741
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2025-01-31 19:05:34 -06:00
Ben Croker 93e8e1405c
Fix example 2025-01-31 18:04:05 -06:00
Ismael Celis e5ccf1242d
Use `retry` in SSE output examples instead of `retryDuration` (#561)
The SDKs expect `retryDuration` as an option, but it maps to `retry` in the SSE output.
2025-01-31 18:00:58 -06:00
Greg H 34556125ae
Sdk/dotnet updates (#560)
* sdk/dotnet-cleanup - removed all non-standard example and library code for dotnet

* sdk/dotnet - signals are request-based; missing trailing newline added; refactoring

* sdk/dotnet-cleanup - documentation updates

* sdk/dotnet-bugfix - no longer starting streaming response if only accessing signals

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-01-31 11:27:16 -06:00
Ben Croker 62fe77741b
Library legacy code cleanup (#559)
* Remove unused function

* Remove `version.ts`

* Remove version from build process
2025-01-31 09:56:56 -06:00
Ben Croker 65a84c6602
PHP SDK 1.0.0-beta.8 2025-01-31 09:38:32 -06:00
Ben Croker 2234f3926f
Add more examples to SDKs page 2025-01-30 22:12:13 -06:00
Ben Croker d1fe079520
Add TextValueRequired error 2025-01-30 19:58:04 -06:00
Ben Croker 805993a9b7
Remove file size from `consts.clj` 2025-01-30 12:46:00 -06:00
Delaney ba6fba2b25
Revamp apply and cleanup to be based primarily on MutationObserver (#528)
* Revamp apply and cleanup to be based primarily on MutationObserver

* Improve `data-on` timing functions
Fixes #519

* inline cast

* Update library/src/engine/engine.ts

Co-authored-by: Thomas Threadgold <2460166+Regaez@users.noreply.github.com>

* cleanup and merge with develop

* Add timing example

* remove apply

---------

Co-authored-by: Thomas Threadgold <2460166+Regaez@users.noreply.github.com>
Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-01-30 11:06:20 -06:00
Ben Croker 0e241426e9
Add Clojure to homepage, remove language labels 2025-01-29 17:50:12 -06:00
JeremS 1e55dcf6d5
Clojure SDK (#540)
* Feature: added clojure sdk

Chore: rebasing on latest
(last commit from clojure-sdk d6259824908c)

* Fix: alphabetical order

* Docs: Actual broadcast example

* Test: adding shell test support

Fix: order of options in data-lines for execute scripts events

Fix: fixed signal handling / missing options

Refactor: using the generated constants for boolean options

* Test: passing shell tests

Chore: task build
2025-01-29 16:28:08 -06:00
Patrick Marchand f333707293
sdk/test improving formatting and handle defaults better (#550)
* sdk/test improving formatting and handle defaults better

The test suite was not handling defaults in the right way, they're supposed
to be elided.  Add new tests to check that the response is correct in cases
where all defaults are provided and cases where they are not.

Also formats the input's with jq(1) since it got too complicated to edit.

* sdk/test remove merge artefacts

* sdk/test fixed the last merge artefact
2025-01-29 07:10:27 -06:00
Ben Croker 50472e2782
Update examples 2025-01-28 20:50:58 -06:00
Ben Croker ca6c591aef
Add podcast icon [deploy-site] 2025-01-28 20:50:44 -06:00
Greg H 39a93a4d50
example/dotnet-hello_world (#542)
Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-01-28 15:55:23 -06:00
Johnathan Stevers afa6e930fa
Fix incorrect hello-world example path for zig tokamak example (#548) 2025-01-28 15:51:48 -06:00
Johnathan Stevers c8e77a619d
Fix up hello-world example css (#547)
* fix scroll bar appearing

* use explicit height and width for img

* add `cursor-pointer` to button and darken text on hover

* remove unnecessary classes and do gradient in oklch

* text-gray-100

* Update consts_hello_world.qtpl

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-01-28 13:24:02 -06:00
Dominik Tarnowski d4f11e77aa
Fix signal value out of sync when input populated by chrome's back/forward cache (#530)
* fix bfcache causing data-bind signals to be out of sync

* changelog, comments, fix build

* Update CHANGELOG.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-01-28 13:14:59 -06:00
Johnathan Stevers a9cfaf8a78
Zig SDK framework integration + hello-world examples (#546)
* zig sdk framework integration

* hello-world examples

* update code snippets

* fix readme typo

* fix run.go path

* generated `hello-world.html`
2025-01-28 12:48:06 -06:00
Ben Croker c40f43bc9a
Fix bundler [deploy-site] 2025-01-28 11:51:53 -06:00
Ben Croker a2e4181450
Rename `helloWorldExample` 2025-01-28 11:15:23 -06:00
Ben Croker 7385cb0abf
Add `helloWorldStandard` 2025-01-28 11:08:34 -06:00
Ben Croker 490a26fa78
Remove version from source code (#545)
* Remove version from source code

* Remove from JS API

* Add release note
2025-01-28 10:42:56 -06:00
Ben Croker a1fcf54752
Fix element check in `custom-validity` plugin (#544)
* Fix hello world source

* Fix element check in `custom-validity` plugin

* Add HTMLSelectElement

* Update release note
2025-01-28 10:24:54 -06:00
Ben Croker 820f1795fa
Update hello world image 2025-01-28 10:12:53 -06:00
Ben Croker 4708c24da0
Fix hello world source 2025-01-28 08:12:42 -06:00
Ben Croker ea1c1326fe
Add step and min to example 2025-01-27 19:24:20 -06:00
Roman Frołow 433c2e0cac
Update README.md: add languages to code blocks (#539) 2025-01-27 19:22:01 -06:00
Roman Frołow 929c32af4e
Update sdks.md - node.ts -> node.js (#537) 2025-01-27 17:23:25 -06:00
Roman Frołow 420559dd66
Update README.md: cant -> can't (#538) 2025-01-27 16:39:49 -06:00
Ben Croker 78f1adeab9
Remove header requirement from Go SDK 2025-01-27 16:37:05 -06:00
Ben Croker ee5150fa4e
Add hello world HTML to the build process 2025-01-27 16:31:05 -06:00
Ben Croker 5244040041
Add release note 2025-01-27 15:45:26 -06:00
Dominik Tarnowski 9b5a788ada
fix custom validity plugin being too restrictive (#534) 2025-01-27 15:43:26 -06:00
Delaney 7036bffb0f
add go hello-world example (#536)
Fixes #535
2025-01-27 15:41:53 -06:00
Anders Murphy 65beaaab41
Fix recurring back through a ancestors to find an id to hash (#533)
* Fix recurring back through a ancestors to find an id to hash

When we recur through ancestors of a node to generate an id we were
skipping back two parent nodes instead of one on the most common
branch in the recursion.

This would mean html structure like this would not produce unique ids:

```
...
<div id="3">
    <div>
        <div>
            <div id="datastar1pyvig">hello</div>
            <div id="datastargves4o">hello</div>
        </div>
    </div>
</div>
<div id="4">
    <div>
        <div>
            <div id="datastar1pyvig">hello</div>
            <div id="datastargves4o">hello</div>
        </div>
    </div>
</div>
...
```

Where as html structure like this would (even layer of nesting):

```
...
<div id="1">
    <div>
        <div>
            <div>
                <div id="datastar1d">hello</div>
                <div id="datastarsx">hello</div>
            </div>
        </div>
    </div>
</div>
<div id="2">
    <div>
        <div>
            <div>
                <div id="datastar1t">hello</div>
                <div id="datastarsr">hello</div>
            </div>
        </div>
    </div>
</div>
...
```

Ideally we want to find any unique user generated id when recurring
back through ancestors to avoid duplicate ids. Which looks like the
original intention of this code (as that way users don't have to
manually give ids to inner elements like buttons).

* Add release notes

* Fix order of release notes

* IDs

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-01-27 15:39:56 -06:00
Ben Croker 4bafc8b250
Add Hello World PHP example 2025-01-27 12:01:25 -06:00
Johnathan Stevers 3850a0cb84
Fix Rust and Zig SDK Typos (#532)
* fix rust related typos

* swap zig and rust links to main
2025-01-27 07:37:02 -06:00
Ben Croker 1177a2d3ab
Improve SDK docs 2025-01-26 21:08:37 -06:00
Johnathan Stevers 44d758a1ca
Zig SDK (#531)
* zig sdk

* add Zig to `sdks.md`
2025-01-26 20:12:49 -06:00
Ben Croker 46773b5602
Document changes to expressions (#527)
* Add release note

* Add docs

* Add default value and trim

* Add multiline suggestion to error

* Join using semicolon only

* Revert removing line break

* Improve code comments

* Fix typo

* Fix

* Use button element

* Build
2025-01-26 09:00:44 -06:00
Ben Croker cf7807b39b
Improve SDK docs 2025-01-25 17:56:24 -06:00
Johnathan Stevers 081178321f
Rust SDK (#520)
* rust sdk

* add settle duration an use view transition to `RemoveFragments`

* replace `std::time::Duration` with `core::time::Duration`

* add `settle_duration` and `use_view_transition` setters to `RemoveFragments`

* remove `workspace` from `Cargo.toml`

* update `Cargo.lock`

* align documentation with official documentation

* change description

* use consts

* fix typo in `consts.go`

* code snippets

* add semi colons to bool consts

* fix example

* always include `retry_duration` in event body

* fix typo

* add extra newline to every event

* remove unnecessary `.as_ref()`

* remove `datastar-request: true` validation from `ReadSignals`

* add retry and extra newline to doc tests

* add tests and update package files
2025-01-25 16:25:48 -06:00
Patrick Marchand 43449e1e3a
sdk/typescript add taskfile building tasks (#507) 2025-01-25 16:25:23 -06:00
Patrick Marchand c825bacb3c
sdk/test eventId should be string and send datastar-request header (#526) 2025-01-25 16:25:00 -06:00
Anders Murphy b51853d464
Only support `;` statement delimiter (#525)
This means we don't need to write a JS parser in regex and keeps
things simple.

I haven't updated the docs to mention this or added specific error
handling. Figured that could be done in a separate PR.

This PR does fix all the tests where \n was used as a statement delimiter
2025-01-25 13:10:34 -06:00
Ben Croker efd38eaf8d
Fix `inner` merge mode bug (#524)
* Replace outer HTML of fragment

* Add release note
2025-01-24 17:36:23 -06:00
Patrick Marchand f082567d8e
sdk/test error message improvements (#521)
* sdk/test error message improvements

* sdk/ts forgot to commit the better error messages

* Update README.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-01-24 17:07:10 -06:00
Patrick Marchand 2b767131cf
Bring typescript snippets into line with other examples (#487)
* site sdk/typescript bring snippets into line with other examples

* sdk/typescript remove mention of readSignals in getting started snippet

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-01-24 09:27:26 -06:00
Anders Murphy 29e7f9fcab
Handle the cases where javascript really wants a semicolon (#518)
Adds `;` back to `stmts.join(';\n')` as sometimes javascript really
needs a `;`.

The following expression would cause an error due to the leading/trailing `;`
being removed.

```
:data-on-click "var somthing = 1 + 3
    ;(5) + 4;
@post('/send'); $message = ''"
```

This code would cause an error too:

```
:data-on-click "var somthing = 1 + 3;
    (5) + 4;
@post('/send'); $message = ''"
```

By making sure we always add a semicolon we ensure this can't happen.
The `\n` has been kept for error message readability.
2025-01-24 07:19:48 -06:00
Ben Croker b91d183b8c
Add SDKs to homepage [deploy-site] 2025-01-23 21:47:58 -06:00
Ben Croker 72375ae91c
Tweak red [deploy-site] 2025-01-23 21:22:33 -06:00
Ben Croker 30743468dd
Add videos [deploy-site] 2025-01-23 21:08:41 -06:00
Ben Croker f57703254d
Add release note 2025-01-23 08:15:03 -06:00
Anders Murphy 451b62ef1b
Support nested regex and strings in expressions (#508)
* Support nested regex and strings in expressions

This regex allows Datastar expressions to support nested
regex and strings that contain ; and/or \n without breaking.

Full regex for testing on regex101.com

```
((?:\/(?:\\\/|[^\/])*\/|"(?:\\"|[^\"])*"|'(?:\\'|[^'])*'|`(?:\\`|[^`])*`|[^;\n])*)([;\n]+)
```

Only valid ; and \n should be in the second capture group Each of these regex ignore a block type:

```
regex            \/(?:\\\/|[^\/])*\/
double quotes     "(?:\\"|[^\"])*"
single quotes     '(?:\\'|[^'])*'
ticks             `(?:\\`|[^`])*`
```
We want to ignore the non delimiter part of statements too:

`[^;\n]`

Once all the blocks we want to ignore are captured we then find
the statement delimiters in the second capture group:

`([;\n]+)`

Note: the reason why this regex isn't broken down into strings is that
doing so adds an extra layer of escapes which makes it even harder to
reason about, harder to check in external regex apps and leads to
worse compression.

The ignore block model allows us to extend this and validate each
component separately.

Effectively, an ignore block is a regex that skips the content of the
block. For example we want to skip the contents of a `''` block then
we need to match the open quote and the close quote and ignore the
contents including escaped quotes.

That's the theory anyway. You can go mad testing this, just remember
the it needs to be valid JS! A few times I thought I'd broken
it and it would have broken the JS parser.

I don't expect this to be perfect, but I do expect it to be easy to
fix any edge cases we find by design (what I'm aiming for with this).

There might be a combination of nested strings that break this.

I've run the test (sort is still failing but it was before) and
I've built and tested the todo app.

* Simplify regex

* Fix typo

* Support nested regex and strings in expressions #508

/(?:\/(?:\\\/|[^\/])*\/|"(?:\\"|[^\"])*"|'(?:\\'|[^'])*'|`(?:\\`|[^`])*`|[^;\n])+/gm

This regex allows Datastar expressions to support nested
regex and strings that contain ; and/or \n without breaking.

Each of these regex defines a block type we want to capture:

regex            \/(?:\\\/|[^\/])*\/
double quotes     "(?:\\"|[^\"])*"
single quotes     '(?:\\'|[^'])*'
ticks             `(?:\\`|[^`])*`

We want to capture the non delimiter part of statements too:

[^;\n]

The regex above will not work in regex101.com as javascript
regex handles single and double quotes for us.

The test cases bellow can be pasted into the developer console to
check the regex.

Note we need the `trim`, before we `match`.

```
var statementRe = /(?:\/(?:\\\/|[^\/])*\/|"(?:\\"|[^\"])*"|'(?:\\'|[^'])*'|`(?:\\`|[^`])*`|[^;\n])+/gm

var testStringSingle = '["foo", "\n", \';\', `"fo ; \' \\\' \\" bam"`]map((x) => x.match(/regex;/); "goat;" + y'

testStringSingle.match(statementRe)

var testStringDouble = "['foo', \"\\n\", ';',`'fo ; \" \\\" \\' bam'`]map((x) => x.match(/regex;/)); 'goat;' + y"

testStringDouble.match(statementRe)

// trailing space after a colon breaks this so we need to add trim
var testStringDoubleTrailingSpace = "['foo', \"\\n\", ';',`'fo ; \" \\\" \\' bam'`]map((x) => x.match(/regex;/)); 'goat;' + y;   "

testStringDoubleTrailingSpace.match(statementRe)

testStringDoubleTrailingSpace.trim().match(statementRe)
```

p

* build the bundle

* Removed the ignore capture groups as they are not needed with match

* Use newline as separator for more readable error messages

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2025-01-23 08:11:55 -06:00
Yaroslav Lapin 937c7ccec4
fix htttp -> http in sdk reference (#512) 2025-01-22 20:03:18 -06:00
Ben Croker 0fa34d99ce
Change `__delay` to `__duration` on `data-on-interval` (#513)
* Start fix

* Finish fix

* Add release note

* Remove `leading` modifier

* Add release note

* Remove from docs

* Fin

* Tweak example

* Change to `__duration` modifier

* Add `.leading` back in with cleanup

* Better comment
2025-01-22 19:57:36 -06:00
Ben Croker c78114b960
Ensure `onLoad` is removed (#511) 2025-01-22 16:05:31 -06:00
Darric Heng 5992480a97
fix: use matching quotes (#510) 2025-01-22 08:49:13 -06:00
Ben Croker 55ec85bc9e
Revert version number 2025-01-21 16:43:06 -06:00
Ben Croker 3992f254d7
Bump PHP SDK version 2025-01-21 16:41:21 -06:00
Ben Croker 1ac2d8ac79
Improve polling example [deploy-site] 2025-01-21 16:39:11 -06:00
Ben Croker 44004a89e5
Fix sortable example [deploy-site]
Fixes #506
2025-01-21 12:17:03 -06:00
Ben Croker 0f2d428cbc
1.0.0-beta.2 2025-01-21 09:25:57 -06:00
Ben Croker 07b01321f7
Change behaviour of `data-star-ignore` (#505)
* Change behaviour of `data-star-ignore`, add mod

* Improve example
2025-01-21 09:10:30 -06:00
Ben Croker fdb41f3a0d
Add `data-on-interval` and `__delay` modifier (#504)
* Add `on-interval` and `__delay` modifier

* Add docs, fix example

* Improve code comment

* Add `.leading` to `__delay`

* Add release note
2025-01-21 08:23:40 -06:00
Tom D. ceabb783e6
Optimize event handling and implement modularity for plugins (#491) 2025-01-20 20:39:35 -06:00
Ben Croker 9244e530ae
Tweak wording 2025-01-20 17:56:41 -06:00
Delaney 326f039e03
Create README.md for Go SDK (#503)
* Create README.md for Go SDK
Fixes #419

* Update README.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-01-20 17:54:44 -06:00
Ben Croker 3a65035b0a
Add release note 2025-01-20 17:51:51 -06:00
Ben Croker c4b2c2364b
Add context to error messages 2025-01-20 17:49:32 -06:00
Delaney 7c8e2551b4
View transitions API demo doesn't transition (#502)
Fixes #501
2025-01-20 17:17:13 -06:00
Ben Croker 2e2ef7ddec
Remove redundant check in `bind` plugin 2025-01-20 17:12:48 -06:00
Ben Croker 91483ab6ff
Revert "Simplify making the last statement an expression a return (#500)"
This reverts commit aa45410ed1.
2025-01-20 17:10:14 -06:00
Delaney e99c9e0654
Make plugin order depth-first per element, then per `data` attribute (#499)
* define plugin order depth first per element, then per data-* attribute
 remove vestigial macros

* Completely remove raw value

* Improve computed example in guide

* fix animation test

* Add release note

* Add release note

* Fix release note

* Document evaluation order

* Improve docs

* Add release note

* Remove `frontend`

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-01-20 12:08:34 -08:00
Anders Murphy aa45410ed1
Simplify making the last statement an expression a return (#500)
From the conversation on discord `replace` can be used to simplify
making the last statement in an expression a return.

Note:

- This version doesn't do any trimming.
- This does not fix #497

Ran tests and build step locally, but wasn't sure if PRs
should only be the code change (rather than artefacts).
2025-01-20 12:08:13 -08:00
Ben Croker a79fb963b3
Fix fix [deploy-site] 2025-01-19 22:31:54 -06:00
Ben Croker b218e2115d
Fix typos in file upload example [deploy-site] 2025-01-19 21:39:53 -06:00
Ben Croker 8b43f29224
Add SDK page to docs (#486)
* Start SDK page

* Reorganise links

* Tweaks

* Fix link

* Add packages and examples

* Add link to reference

* Link authors

* Improve TS

* Fix path to consts

* Add PyPI package

* Fix spacing

* Add links to SDKs page

* Cleanup
2025-01-18 19:22:18 -06:00
Ben Croker 4d6ca33b23
Add suggestion for undefined string error 2025-01-18 17:11:45 -06:00
Ben Croker e9d0885c6d
Finish last fix 2025-01-18 16:57:51 -06:00
Ben Croker ea19292f95
SDK fixes 2025-01-18 16:56:37 -06:00
Greg H 48151b593c
sdk/dotnet - corrections to doco. fixed sample. keep-alive only if 1.1 (#496)
Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2025-01-18 10:08:24 -06:00
Ben Croker 723fca3395
Fixes #492 [deploy-site] 2025-01-17 09:11:35 -06:00
Ben Croker 0a67e27077
Fixes #489 2025-01-17 07:27:46 -06:00
Yizong ZHOU 76da175516
Fixed the frontend final example in the getting_started guide (#494) 2025-01-17 07:24:31 -06:00
Patrick Marchand 1ea565a34f
Ts sdk snippets (#483)
* sdk/ts add warning about http1

* sdk/ts improve readme example

and add snippets to go site

* sdk/ts fix type and import errors

* ts/sdk fix type error in node readme example

* sdk/ts improve snippets and examples

Slimmed down the snippets setup example and added it to the readme, then
moved the readme examples to their own files in a new examples folder to
make place for other examples.

Also fixed md links in readme.

* sdk/ts --unstable-sloppy-imports is no longer required

* sdk/ts fixed some type / import errors

* Rename sdk/ts to sdk/typescript

* sdk/typescript simplify setup snippet
2025-01-15 11:10:47 -06:00
Ben Croker d1f3e19acb
Fix build 2025-01-15 10:02:40 -06:00
Thomas Threadgold 7824c07223
Add signal prefix to code examples (#485) [deploy-site] 2025-01-15 07:08:50 -06:00
Patrick Marchand ffbec7025d
Ts sdk (#402)
* Ts sdk

Does not  contain node code, working on that now. But all tests pass.

* Initial concrete impl of ts serverSentEventGenerator

This can do cross-runtime parsing of signals, but I havent figured out
yet how to do the streaming cross-runtime, the current code is for node only.

I will probably figure this out tomorrow.

* ts-sdk: make the sdk cross-runtime

this should support node, deno and most other runtime.

* Create concrete serverSentEventGenerator for node and web standard runtimes

They both get their own version of the class. Also move building from vite to esbuild.
Unit tests are still in vitest though. You can also run `node bundle/node/node.js` or
 `deno run --allow-net --unstable-sloppy-imports sdk/ts/src/web/deno.ts` to test
 them manually. Automatic curl based tests for these two are my next focus.

* new sh based test  suite for sdk

along with changes to sdk/ts after testing.

some tests are still failing
    node: reading post signals
    deno: all get-cases (some problem with the deno buffering I think)

readme changes will come in a later commit

* Improve sdk/test/test-all.sh

following suggestions by King of Mods on discord
https://discord.com/channels/1296224603642925098/1299058221390102528/1325511650543013888

* sdk/test make get and post tests less noisy

* sdk/ts fix deno streaming

I wasnt closing the stream properly

* sdk/ts Fix parsing of json body in node sdk

using code from https://github.com/starfederation/datastar/pull/391 by https://github.com/jmcudd

* sdk/ts add jsdocs to public methods

* sdk/test Readme

* sdk/ts Readme

* sdk/ts fix error in controller code for web stream

* sdk/ts fix error with async handling in web standard sse

* sdk/ts fix same async problems with node

also remove the need to add res.end() after calling stream

* sdk/ts remove unit tests and vite

The sdk/test suite does a much better job of testing the sdk.
Sure we lose the fuzzing, but we can always add that into sdk/test

* sdk/ts improve typings and async usage

Most of the `unkwown` objects are not wholly unknown, we know that
they can be de/serialized from/to JSON.

Make non async streams easier to use.

* sdk/ts improve node readSignals method

less code duplication

* sdk/ts build the npm package with deno dnt

It's hard to write a library that typechecks and run for
both deno and node. The chief reason is that node esm
does not accept file extensions and deno requires them.

By using dnt, I can bypass this problem and have deno
package the esm version directly.

* sdk/ts format with deno fmt

* remove sdk/ts from esbuild

since we're using deno to package it anyway.
2025-01-14 08:14:45 -06:00
Delaney fa24bd44e4
Rename nested signals in library (#480)
Fixes #478
2025-01-13 19:19:58 -06:00
Ben Croker 9572b867a3
Fix docs links 2025-01-13 19:13:29 -06:00
Ben Croker 161d9fedc7
Fix sample code indentation 2025-01-13 19:07:34 -06:00
Ben Croker c36a7227b8
Rename image 2025-01-13 18:52:23 -06:00
Ben Croker 6b59265dc1
nested → namespaced 2025-01-12 21:07:25 -06:00
Delaney eee4e3c981
Better error on invalid expressions and signals (#466)
* Better error messages for nested signals
Fixes #452

* Add explicit check for invalid signal

* move to generic errors

* working towards better error pages

* Tweak errors

* more complete example

* bad templ

* Start porting over errors

* Better error messages for nested signals
Fixes #452

* fix nil pointers

* Migrate remaining errors

* Fix init errors

* Tweaks

* Add suggested signal names

* Improve styling and close input elements

* Cleanup

* syntax highlight

* Fixes

* More fixes

* Tweaks

* Update library size approximation

* fix lines and escaping

* add if

* Finish default error messages

* Finish PR

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-01-12 20:16:25 -06:00
Ben Croker 9f88878f04
Remove Node and Python examples [deploy-site] 2025-01-12 09:38:46 -06:00
Ben Croker 9a31383e2f
Tweak SDK docs [deploy-site] 2025-01-11 21:07:38 -06:00
Ben Croker e149f38be1
Tweak example [deploy-site] 2025-01-11 10:14:50 -06:00
Ben Croker 34d95080f3
Minor docs improvements [deploy-site] 2025-01-11 10:08:10 -06:00
Anders Murphy 39849bf23a
First draft of renaming nest/ed to namespace/d (#477)
* First draft of renaming nest/ed to namespace/d

After a lengthy discussion on discord it was suggested that we rename
`nested` signals to `namespaced` signals. For a few reasons:

1. Nested signals are used for namespacing.
2. We don't support or plan to support root nodes being signals
3. Nested signals should not be used to recreate SPAs and are there
   for namespacing convenience (bulk add/remove) not
   lookup (read/watch).
4. The naming was causing confusion.

Not sure if we still need to specify that only nodes are signals now
that nested signals are called namespaced signals.

I haven't renamed the implementation's yet as that's an implementation
detail we can address later.

Link to discord conversation:
https://discord.com/channels/1296224603642925098/1296225503610671224/1327365393563783238

* Fix persist example test

* Update datastar_expressions.md

* Update attribute_plugins.md

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2025-01-11 09:32:54 -06:00
Jason Oppel 12273efe44
Fix typos __outsite in docs (#476)
Should read `__outside` instead

Fixes #475
2025-01-11 07:23:09 -06:00
Kenneth Ormandy ddcc835b8a
Fixes link to SSE docs (#472) 2025-01-10 17:45:07 -06:00
Delaney 5736b4ae75
Update Go SDK to latest SDK protocol (#471)
Fixes #470
2025-01-10 08:33:52 -06:00
Ben Croker 337b81a8d8
Use `static` keyword 2025-01-10 07:34:30 -06:00
Ben Croker e2c24d20c3
Add enterkeyhint to TODO demo [deploy-site] 2025-01-09 07:57:56 -06:00
Ben Croker ae4b836431
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2025-01-09 07:53:21 -06:00
Andrew Schreiber 1dcbab9558
Update Templ Version (#467)
Updates to latest templ version (v0.3.819)
2025-01-08 20:16:55 -06:00
Ben Croker f6bc599b85
Add rocket to readme 2025-01-08 19:53:55 -06:00
Ben Croker e43fe54b83
Add badges to readme 2025-01-08 16:32:44 -06:00
Ben Croker 11c2c86a30
Fix readme 2025-01-08 16:27:17 -06:00
Ben Croker 60db7e2959
Only send `Connection` header with HTTP/1.1 2025-01-08 16:10:23 -06:00
Ben Croker 81a9b4cf31
Improve wording [deploy-site] 2025-01-08 12:55:15 -06:00
Ben Croker 753412539d
Disable `lazy_load_test` 2025-01-08 12:35:04 -06:00
Ben Croker 953df608fe
Disable lazy_tabs_test to get tests passing 2025-01-08 12:30:42 -06:00
Ben Croker 0ed8abf34d
Add `Look ma’` to readme 2025-01-08 12:22:00 -06:00
Ben Croker e1d30aebdb
Add `@clipboard` to docs [deploy-site] 2025-01-08 12:09:37 -06:00
Ben Croker 13da358729
Improve nestable signals explanation [deploy-site] 2025-01-08 08:18:34 -06:00
Ben Croker 755a5db9b8
Add links to guide [deploy-site] 2025-01-06 09:20:06 -06:00
Ben Croker cf60cab386
Fixes #460 [deploy-site] 2025-01-06 08:03:49 -06:00
Ben Croker a706cebb2d
Tweaks to docs [deploy-site] 2025-01-05 20:37:11 -06:00
Peter Humulock d851e049eb
Chore/java sdk submodules (#458)
* Updated README

* Added retryDuration to ServerSentEventGenerator

* Added options to readme

* Moved core sdk to submodule

* Moved core sdk to submodule

* Added more explanations to readme

* Fixed java directory structure in build/run.go
2025-01-05 19:48:17 -06:00
Ben Croker 192900c7eb
Fix typo [deploy-site] 2025-01-05 18:47:08 -06:00
Ben Croker beef6b3602
Add clarification [deploy-site] 2025-01-05 18:37:37 -06:00
Felix Ingram 3c6c29f3b9
SDK for python (#250) 2025-01-05 10:35:33 -06:00
Ben Croker c0bdb00f39
Add Datastar Expressions to guide (#456) 2025-01-05 10:33:08 -06:00
Ben Croker 0875d74810
Add release notes 2025-01-05 08:56:35 -06:00
Ben Croker 19ad9ceada
Fix key conversion (#451)
* Fix key conversion

* Build
2025-01-05 08:54:35 -06:00
Ben Croker 5defce5cc1
Remove `method` option (#443) 2025-01-05 08:49:49 -06:00
Peter Humulock 9db6d03dc8
Chore/java sdk updates (#454)
* Updated README

* Added retryDuration to ServerSentEventGenerator
2025-01-05 08:49:15 -06:00
Anders Murphy 1aeb613970
Animation docs say htmx when they should say Datastar (#457) 2025-01-05 08:47:57 -06:00
Ben Croker e5c6ec4b3d
Explain only leaf nodes are signals [deploy-site] 2025-01-04 16:17:31 -06:00
Ben Croker ac9a44b803
Update Contributing guidelines 2025-01-04 09:16:55 -06:00
Ben Croker 3cf498e171
JetBrains plugin 1.0.0 2025-01-04 08:16:56 -06:00
Ben Croker d12241a812
VSCode extension 1.0.0 2025-01-04 08:09:02 -06:00
Ben Croker 182765419c
Update CDN URLs [deploy-site] 2025-01-03 21:25:44 -06:00
Ben Croker 05eaa113cd
Fix #447 [deploy-site] 2025-01-03 11:40:54 -06:00
Ben Croker 0483fa80c2
Fix #446 [deploy-site] 2025-01-03 10:26:44 -06:00
Ben Croker 4f70926469
Fix typo in example 2025-01-03 09:31:24 -06:00
Ben Croker f02da62231
Add specific CDN link 2025-01-02 18:31:05 -06:00
Ben Croker 4d27ea199b
Update readme 2025-01-02 11:38:18 -06:00
Ben Croker 891764569c
Fix links 2025-01-02 11:05:11 -06:00
Ben Croker 6fa8900f68
Fix PHP SDK readme 2025-01-02 09:40:58 -06:00
Ben Croker 5030f1428e
Fix PHP SDK 2025-01-02 09:39:26 -06:00
Ben Croker f72e78ba6f
Move regex into class 2025-01-02 08:42:02 -06:00
Ben Croker 7934512a99
Fix regex (#442) 2025-01-02 08:39:37 -06:00
Ben Croker ae2f033926
Update PHP SDK 2025-01-02 07:36:34 -06:00
Ben Croker dfb650011c
More docs fixes 2025-01-02 07:28:18 -06:00
Ben Croker c47574f70c
Fix version 2025-01-01 20:35:14 -06:00
Ben Croker bcf016b538
Fix docs, examples and error messages 2025-01-01 20:33:23 -06:00
Delaney Gillilan e96e4a216c over optimized during cleanup, ironically deleting cleanup step... lol 2025-01-01 16:17:43 -08:00
Ben Croker 0e6c6baeb6
Left trim dollar sign (#441)
* Left trim dollar sign

* “Trim”
2025-01-01 14:55:36 -08:00
Delaney f72d906ba2
Delaneyj/issue437 (#439)
* Biome Lint/Format (#396)

* Add `javascript_api` [deploy-site]

* Add note about JSON [deploy-site]

* Mark SDKs done

* Move conditional statement (#389)

* Add release note

* Add troubleshooting tips [deploy-site]

* Replace http.Flusher with http.ResponseController for SSE in Go SDK  (#392)

* refactor: replace http.Flusher with http.ResponseController

* refactor: replace http.Flusher with http.ResponseController reintroduced panic justification

---------

Co-authored-by: drahtzieher <admax@vmi2173525.contaboserver.net>

* Improve SDKs in docs [deploy-site]

* Improve `retry` option descriptions [deploy-site]

* Wording improvements [deploy-site]

* Improve wording [deploy-site]

* Fix & unify CDN in docs/examples (#394)

* Try Biome
Fixes #395

* format all

* more

* fix ignores

* Add comment to bundles (#401)

* Add comment to bundles

* One-liner

* Build

* Add `retryInterval` option to `sse()` action (#393)

* Add `retryInterval` option to `sse()` action

* Add to `sse` plugin too

* Build

* Add release note

* Add `Datastar's philosophy` [deploy-site]

* Use `path/to/datastar.js` [deploy-site]

* Fix local signals (#407)

* Fix bundler not exporting module (#406)

* Add Banner and Format

* Export Datastar in bundler

* Release note

* Fix export

* Add ref usage example [deploy-site]

* updatego deps

* Bump org.eclipse.jetty:jetty-server in /examples/java (#408)

Bumps org.eclipse.jetty:jetty-server from 11.0.15 to 11.0.24.

---
updated-dependencies:
- dependency-name: org.eclipse.jetty:jetty-server
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add example to error page [deploy-site]

* fix const usage in Go

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Ben Croker <ben@putyourlightson.com>
Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
Co-authored-by: drahtzieher <josuah@rechtsteiner.net>
Co-authored-by: drahtzieher <admax@vmi2173525.contaboserver.net>
Co-authored-by: David Linke <dalito@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Revert "Biome Lint/Format (#396)"

This reverts commit 251f1391cf.

* PHP SDK 1.0.0-beta.4

* signals for mime types and names work

* Change import paths back to relative paths
Fixes #437

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Ben Croker <ben@putyourlightson.com>
Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
Co-authored-by: drahtzieher <josuah@rechtsteiner.net>
Co-authored-by: drahtzieher <admax@vmi2173525.contaboserver.net>
Co-authored-by: David Linke <dalito@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ian Smith <iansmith@iorca.ai>
2025-01-01 15:59:06 -06:00
Delaney f8bb417405
Get rid of `@sse` (#440)
Fixes #438
2025-01-01 15:54:20 -06:00
Delaney Gillilan b74e2bfbb8 update filesize comparison 2025-01-01 13:34:09 -08:00
Ben Croker fdb00bdcb4
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2025-01-01 13:00:18 -06:00
Ben Croker ba3c10fde7
Fix persist docs and tests 2025-01-01 13:00:10 -06:00
Ian Smith a22dafc057
Fix file upload signals (#432)
Co-authored-by: Ian Smith <iansmith@iorca.ai>
2025-01-01 10:32:27 -08:00
Ben Croker daf00c49c0
Improve poor example 2025-01-01 12:15:00 -06:00
Ben Croker 843e5848ef
Add release note 2025-01-01 12:07:01 -06:00
Delaney abff1d05de
Can `.value` go away? (#429)
* Can .value be removed?
Fixes #428

* get dialog working

* add } to terminators

* Add fujs.svg

* whackamole

* sigh

* recursive regex tag template literals, lol

* Regex example

* (jacks|lack|of|complete|surprise)

* persist fixed

* fix current regex example

* current state

* Update all examples

* regex version of signals, actions and escapement

* Fix Go examples

* fix templates

* Add `@` to actions in examples

* Revert `.Value`

* frontpage

* all test pass

* move to @get/post/put/patch/delete

* Fix up docs and examples

* Add true client size to readme

* Add v1.0.0-beta.1 release notes

* @ → $

* Add space

* Fix more docs and examples

* missed files in merge

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2025-01-01 12:02:26 -06:00
Ben Croker ff6cdce6d1
Add `outside` modifier to IntelliJ plugin 2024-12-30 19:13:25 -06:00
Tom D. ff09c67a0e
fix the constant generator path (#433) 2024-12-29 17:51:02 -06:00
Tom D. cac77adf27
refactor(java-sdk): Rewrite the Java SDK (#430)
- Rewrite the entire API to leverage JDK 17 features and implement a fluent API design.
- Updated the minimal JDK version requirement to 17.
- Temporarily removed examples as they are not yet aligned with the new API.

BREAKING CHANGE: The API has been completely redesigned and requires JDK 17 or higher.
BREAKING CHANGE: Previous examples and usages are no longer compatible.
2024-12-29 15:43:32 -06:00
Ben Croker 6e11ff8f74
More tweaks 2024-12-29 13:00:46 -06:00
Ben Croker 05121d96f2
Docs improvements 2024-12-29 12:11:51 -06:00
Ben Croker 1d7a2009fd
Add `Stop Overcomplicating It` to the guide (#431)
* Add `Stop Overcomplicating It` page

* Tweaks

* Add `data-bind` example

* Dispatch `change` event

* Finalise
2024-12-29 10:03:43 -06:00
Ben Croker 5d1b59a2b4
attributes → attr 2024-12-28 10:57:14 -06:00
Ben Croker 07c21e92ed
Fix VSCode extension 2024-12-28 10:56:39 -06:00
Ben Croker bffbcf47d6
Add `data-star-ignore` to IntelliJ plugin 2024-12-28 10:52:14 -06:00
Ben Croker 9a21366110
Update VSCode extension 2024-12-28 10:14:24 -06:00
Ben Croker 86b65595e2
Fix `outside` modifier (#425)
* Fix outside modifier

* Add release note
2024-12-25 12:41:27 -06:00
Ben Croker 72fefafe7a
Add release note 2024-12-25 11:58:53 -06:00
Ben Croker 2243144a52
Add custom validity plugin (#423)
* Add custom validity plugin and demo

* Add reference docs

* Add error pages
2024-12-25 11:49:09 -06:00
Ben Croker 6a999c2d7e
Rename `data-attributes` to `data-attr` (#422)
* Rename plugin

* Update examples, errors, tools, tests

* Rename error

* Add release note
2024-12-25 11:48:14 -06:00
Ben Croker ae5791fb5f
PHP SDK 1.0.0-beta.4 2024-12-24 08:53:33 -06:00
Ben Croker b3f9a18a4d
Remove unused consts 2024-12-23 19:57:03 -06:00
Greg H 30e47767a5
sdk/dotnet nuget (#372)
* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* On workflow_dispatch

* Use GITHUB_TOKEN

* Replace variables

* sdk/dotnet-nuget

* sdk/dotnet-nuget

* sdk/dotnet-nuget - README updates

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2024-12-23 12:39:25 -06:00
Ben Croker 51c79816dc
Update deploy-site.yml 2024-12-23 12:29:44 -06:00
Ben Croker 9dbece08f5
Update deploy-site.yml 2024-12-23 12:12:20 -06:00
Ben Croker f7fb1c8af0
Update deploy-site.yml 2024-12-23 12:11:16 -06:00
Ben Croker 161c2dbfc9
[deploy-site] 2024-12-23 11:44:22 -06:00
Ben Croker 49e7153131
0.21.4 2024-12-23 11:31:45 -06:00
Delaney Gillilan 945c213320 fix up some tests and wrong initial header setup in sse plugin 2024-12-23 09:09:53 -08:00
Ben Croker 1a0b9d29e5
Dispatch an SSE error event (#412)
* Dispatch an SSE error event

* Add `SseMaxRetries` error
2024-12-23 08:56:08 -06:00
Delaney 702a81af58
Tags back to modifiers (#421)
Fixes #420
2024-12-23 08:54:34 -06:00
Ben Croker 1325eec587
Clarify 2024-12-22 20:27:38 -06:00
Ben Croker c8fc7fd238
Improve `data-star-ignore` example 2024-12-22 20:26:46 -06:00
Ben Croker 48fce4f01c
Add release note 2024-12-22 20:23:44 -06:00
Ben Croker 170824e772
Fix typo in signals plugin 2024-12-22 19:55:23 -06:00
datashaman 5d52df0ba2
Fix first quiz example (#416)
In the first example, there is no `answer2` signal, resulting in an error on the console.
2024-12-22 18:45:15 -06:00
Ben Croker 47043504ab
Remove colon from example 2024-12-22 18:39:07 -06:00
Delaney 72b28b2a97
Modifiers need to be renamed tags (#415)
* Modifiers need to be renamed tags
Fixes #414

* fix merge
2024-12-21 17:13:18 -06:00
Delaney 519db9a954
Persist doesn't maintain value after page reload (#413) 2024-12-21 10:26:17 -06:00
Ben Croker 56ae15a56f
Add tooling to docs 2024-12-21 09:21:07 -06:00
Ben Croker e446b3eedc
Add note about `data-on-submit` 2024-12-20 19:51:52 -06:00
Ben Croker 44f114c53f
Add `form` option to `sse()` action (#400)
* Start form mode

* Require closest form

* Validate form

* Use query selector if string

* Use `for` loop

* Create temporary form if none exists

* Better wording

* Change to `contentType` and `selector` options

* Add release note

* Improve wording

* Remove event listener on invalid form

* Add stricter types, don’t remove event listener

* Prevent default on submit events

* cleanup event listeners

* cleanupFns → cleanupFn

* i hate forms

* Add explanation to example

* Finish docs

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2024-12-20 19:47:07 -06:00
Delaney b1de35a4f6
Biome Delaneyj/issue395 (#409)
* Try Biome
Fixes #395

* format all

* more

* fix ignores

* fix const usage in Go

* Fixes #395

* cleanup go.mod
2024-12-20 10:06:33 -08:00
Ben Croker d2c56ef730
Add example to error page [deploy-site] 2024-12-19 21:03:54 -06:00
dependabot[bot] 6412661082
Bump org.eclipse.jetty:jetty-server in /examples/java (#408)
Bumps org.eclipse.jetty:jetty-server from 11.0.15 to 11.0.24.

---
updated-dependencies:
- dependency-name: org.eclipse.jetty:jetty-server
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 06:55:34 -08:00
Delaney Gillilan 949e56f3e0 updatego deps 2024-12-19 06:53:05 -08:00
Ben Croker 6b501be16c
Add ref usage example [deploy-site] 2024-12-19 08:23:03 -06:00
Ben Croker a7aabb49ff
Fix bundler not exporting module (#406)
* Add Banner and Format

* Export Datastar in bundler

* Release note

* Fix export
2024-12-19 07:42:59 -06:00
Ben Croker de45cdfabf
Fix local signals (#407) 2024-12-19 06:58:24 -06:00
Ben Croker 66c0aa4fcf
Use `path/to/datastar.js` [deploy-site] 2024-12-18 19:36:05 -06:00
Ben Croker f1bfa080dc
Add `Datastar's philosophy` [deploy-site] 2024-12-18 19:31:52 -06:00
Ben Croker b411e9ed72
Add `retryInterval` option to `sse()` action (#393)
* Add `retryInterval` option to `sse()` action

* Add to `sse` plugin too

* Build

* Add release note
2024-12-18 10:39:26 -06:00
Ben Croker dc41488154
Add comment to bundles (#401)
* Add comment to bundles

* One-liner

* Build
2024-12-18 10:21:10 -06:00
David Linke 2103f602ae
Fix & unify CDN in docs/examples (#394) 2024-12-17 16:34:16 -06:00
Ben Croker 46960ec505
Improve wording [deploy-site] 2024-12-17 16:31:55 -06:00
Ben Croker 2ad2457c93
Wording improvements [deploy-site] 2024-12-17 16:19:39 -06:00
Ben Croker 31e3648cc0
Improve `retry` option descriptions [deploy-site] 2024-12-17 11:06:17 -06:00
Ben Croker 685da484ad
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2024-12-17 11:00:08 -06:00
Ben Croker b3750b832a
Improve SDKs in docs [deploy-site] 2024-12-17 10:59:58 -06:00
drahtzieher 1f0a93fe00
Replace http.Flusher with http.ResponseController for SSE in Go SDK (#392)
* refactor: replace http.Flusher with http.ResponseController

* refactor: replace http.Flusher with http.ResponseController reintroduced panic justification

---------

Co-authored-by: drahtzieher <admax@vmi2173525.contaboserver.net>
2024-12-17 08:58:13 -08:00
Ben Croker 910c604045
Add troubleshooting tips [deploy-site] 2024-12-17 10:36:22 -06:00
Ben Croker c3370186b5
Add release note 2024-12-17 10:26:13 -06:00
Ben Croker 761a0fb3d6
Move conditional statement (#389) 2024-12-17 10:05:22 -06:00
Ben Croker b4f6372c84
Mark SDKs done 2024-12-17 07:18:59 -06:00
Ben Croker 82369bc516
Add note about JSON [deploy-site] 2024-12-17 06:44:50 -06:00
Ben Croker b42c8c2c88
Merge branch 'main' into develop 2024-12-16 19:35:53 -06:00
Delaney Gillilan 8c5edc7ee7 update bundles 2024-12-16 08:34:43 -08:00
Ben Croker d11108f933
Add `javascript_api` [deploy-site] 2024-12-16 10:31:58 -06:00
Ben Croker 67a05b0779
Finish reference [deploy-site] 2024-12-16 10:20:48 -06:00
Ben Croker 56059c5019
v0.21.3 (#386) 2024-12-16 10:18:15 -06:00
Ben Croker 192c27c59b
Add `data-star-ignore` attribute (#384)
* Add `data-star-ignore` attribute

* Update CHANGELOG.md

---------

Co-authored-by: Delaney <delaneygillilan@gmail.com>
2024-12-16 09:18:40 -06:00
zangster300 77e71c75f5
adds an alias map to the esbuild config to resolve lib files (#385) [deploy-site] 2024-12-16 08:11:05 -06:00
Ben Croker f8e93f1ac9
Fix action [deploy-site] 2024-12-16 07:07:54 -06:00
Ben Croker ba6ef70d40
Update social preview image [deploy-site] 2024-12-16 06:58:43 -06:00
Felix Ingram 040cfe3059
Make SDK icons wrap (#380)
Added `flex-wrap` as otherwise the SDK icons go off screen on mobile.
2024-12-16 02:14:41 -08:00
Ben Croker 0ea0f3cf37
Update `deploy-site.yml` 2024-12-15 19:07:04 -06:00
Ben Croker daa5c0496c
Fix broken link [deploy-site] 2024-12-15 18:46:41 -06:00
Ben Croker 634e28b594
Script include on single line [deploy-site] 2024-12-15 18:42:42 -06:00
Ben Croker fed87f584b
Tweaks [deploy-site] 2024-12-15 18:39:43 -06:00
Ben Croker d341409758
Redirect `datastar.fly.dev` [deploy-site] 2024-12-15 18:32:59 -06:00
Ben Croker c02f056d96
Better wording [deploy-site] 2024-12-15 17:23:47 -06:00
Ben Croker d99bdc3c39
Fix typo [deploy-site] 2024-12-15 17:06:49 -06:00
Ben Croker 94e81ec04e
Simplify [deploy-site] 2024-12-15 16:57:45 -06:00
Ben Croker 2f8533cd0b
Fix [deploy-site] 2024-12-15 16:39:42 -06:00
Ben Croker 7b9e60a834
Require [deploy-site] 2024-12-15 16:36:04 -06:00
Ben Croker c6dbc96153
Improve wording (deploy-site) 2024-12-15 16:35:07 -06:00
Ben Croker 1f1cd4bd4c
Test deploy-site 2024-12-15 16:31:55 -06:00
Ben Croker e594204813
Test deploy-site 2024-12-15 16:30:32 -06:00
Ben Croker 12953172ac
Test deploy-site 2024-12-15 16:24:31 -06:00
Ben Croker 2b64f9da03
Add `deploy-site` keyword on commit messages 2024-12-15 16:20:08 -06:00
Ben Croker 062753e1f5
Improve wording 2024-12-15 16:07:22 -06:00
Ben Croker 35aaa72c64
Update file size comparison 2024-12-15 13:18:29 -06:00
Ben Croker bb76da59cc
Update core bundle size 2024-12-15 13:03:17 -06:00
Ben Croker 494f0d4191
Add sample output headings 2024-12-15 12:43:22 -06:00
Ben Croker 636b203455
Hide JavaScript API page and clean up old pages 2024-12-15 12:41:18 -06:00
Ben Croker dbfdd77a94
Minor tweaks 2024-12-15 12:36:55 -06:00
Ben Croker a2fe65a9a1
Reorder content 2024-12-15 12:22:45 -06:00
Ben Croker 9d6443921b
Rewrite docs (#367)
* Rewrite reference docs

* Tweaks

* More concise

* Make modifier arguments lowercase

* Fix modifier arguments

* Document modifiers, rename `args` to `tags`

* Add social sharing image

* Add JS API page

* Formatting

* Skip element

* Rewrite Going Deeper

* Minor improvements

* Add to Unlearning

* Finish Going Deeper

* Redirect legacy pages

* Finish PR

* add 301s

* Consolidate redirects

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2024-12-15 12:12:16 -06:00
Delaney d4a7d4af44
Bundler appears broken (#378)
Fixes #375
2024-12-15 12:04:23 -06:00
Ben Croker cd9ea6d4ce
Remove from consts (#371) 2024-12-15 07:50:53 -06:00
Ben Croker f649ab1bd3
Natively 2024-12-14 20:33:33 -06:00
Patrick Marchand 2f3bb704ca
Re-add manual building instructions (#376)
* Readd manual building instructions

Useful for building with docker as well since it gives indications
about the main task commands.

* Improve wording of BUILDING.md

* Break up  list in  BUILDING.md

* Remove mention of git-lfs from BUILDING.md

* Fix typo

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2024-12-14 20:32:12 -06:00
Ben Croker 0c7ab4f921
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2024-12-13 19:06:04 -06:00
Ben Croker dc2768d44f
PHP SDK 1.0.0-beta.3 2024-12-13 19:05:46 -06:00
Ben Croker 9ca42b340e
Fix effect error (#373)
* Throw Datastar error

* Fix wording
2024-12-13 19:00:46 -06:00
Andrew Welch 4c73f53690 Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2024-12-13 19:54:30 -05:00
Andrew Welch 9069f510a8 chore: Whitespace 2024-12-13 19:53:10 -05:00
Andrew Welch dcf1a39092 refactor: Run tests on all PRs regardless of branch 2024-12-13 19:53:00 -05:00
zangster300 72fbff06ec
new approach working for all smoke tests (#369)
* Working on #353 new approach

* new approach working for all smoke tests

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2024-12-13 16:44:45 -08:00
Delaney 791651073a
Lowercase modifiers and arguments (#370)
Fixes #368

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2024-12-13 15:10:54 -06:00
Delaney 6fca8a7c72
Road to v1 essay (#325)
* Write essay: The Road to 1.0
Fixes #315

* add to essays

* Editing

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2024-12-13 11:59:16 -06:00
Delaney dcffccd3ae
Private variables (#366)
Fixes #365
2024-12-13 11:39:22 -06:00
Ben Croker f2db306540
Change wording of release note 2024-12-13 11:38:05 -06:00
Delaney Gillilan 40ba9f1268 Merge branch 'develop' of github.com:starfederation/datastar into develop 2024-12-13 07:20:33 -08:00
Delaney Gillilan d9a2e6cef0 private mean private, except when it doesn't 2024-12-13 07:20:30 -08:00
Greg H 0568bd7214
sdk/dotnet-fix_js_ref - fix the script ref src in shared html #363 (#364)
Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2024-12-13 08:21:18 -06:00
Ben Croker 777fb9b41f
Uppercase DS 2024-12-12 18:57:59 -06:00
Ben Croker 66dd1c1d7b
Export Datastar in main bundle 2024-12-12 18:45:07 -06:00
Ben Croker c302246cd9
Add release note 2024-12-12 16:24:45 -06:00
Patrick Marchand 76789e8f0d
BSD support and better taskfile formatting (#357)
* Clearer formatting of platform dependent commands in taskfile

* BSD support

* Fix merge error
2024-12-12 16:11:43 -06:00
Delaney Gillilan e33cd26f45 Merge branch 'main' of github.com:starfederation/datastar into develop 2024-12-12 10:00:28 -08:00
Delaney c5ba1a9c8e
Cleanup Typescript codebase (#361)
Fixes #360 #336 #337
2024-12-12 09:52:37 -08:00
Delaney dbdfffc1c1
Module doesn’t export Datastar (#359)
* Module doesn’t export Datastar
Fixes #358

* fix build mode
2024-12-12 09:51:59 -08:00
Ben Croker 57c7f2d8ac
Add `selectorOrID` to error message 2024-12-11 19:06:46 -06:00
Ben Croker fe67174373
Add `SignalNotFound` error 2024-12-11 17:16:32 -06:00
Ben Croker 35a4f55562
Bump PHP SDK version 2024-12-11 16:26:08 -06:00
Ben Croker dc06f31b77
v0.21.2 2024-12-11 16:16:40 -06:00
Ben Croker 2c87ee3bfa
Reverse logic 2024-12-11 15:45:12 -06:00
Ben Croker 34a04770be
Improve modifier docs 2024-12-11 15:36:11 -06:00
Greg H 2c02121ed4
sdk/dotnet-v0_21 (#344)
* sdk/dotnet-v0_21 - updates for the Falco implementation; everything adjusted for v0.21

* sdk/dotnet-v0_21 - consts

* sdk/dotnet-v0_21 - store -> signals stragglers

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2024-12-11 15:24:45 -06:00
Delaney Gillilan 4b7993d409 missed bundles 2024-12-11 13:23:26 -08:00
Delaney 941109e55b
Delaneyj/issue354 (#355)
* `data-on-keydown` preventing default
Fixes #354

* fix bulk example
2024-12-11 12:14:51 -08:00
Ben Croker 1c15dc1453
Fix links to library 2024-12-11 12:56:03 -06:00
Andrew Welch 940f09b3c4 refactor: Remove `git lfs` from `Docker-dev` & GitHub CI actions 2024-12-11 13:29:14 -05:00
Ben Croker 418cc3a80f
Fix modifier syntax in examples 2024-12-11 11:20:55 -06:00
Ben Croker f15bd3b87a
Improve error messages 2024-12-11 11:16:27 -06:00
Ben Croker 436e4ddbd8
Fix scroll into view example 2024-12-11 11:16:12 -06:00
Ben Croker 6ccc9e9c94
Uppercase first character in errors 2024-12-11 11:05:28 -06:00
Ben Croker 9a0e74112a
v0.21.1 2024-12-11 10:45:26 -06:00
Ben Croker f0327340fa
Update reference 2024-12-11 10:41:09 -06:00
Delaney 1f823de4a1
Path prefix test not working in `setAll()` and `toggleAll()` actions (#351)
Fixes #350
2024-12-11 10:37:28 -06:00
Ben Croker 424cfd87ba
Start v0.21.1 release notes 2024-12-11 07:39:29 -06:00
Ben Croker edf9ec6143
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2024-12-11 06:55:34 -06:00
Ben Croker 79041854e0
Improve getting started demos 2024-12-11 06:54:56 -06:00
Delaney Gillilan 80abc3a667 Merge branch 'main' of github.com:starfederation/datastar into develop 2024-12-10 22:07:38 -08:00
Delaney Gillilan 6a591acdcf fix image 2024-12-10 21:59:23 -08:00
Delaney Gillilan f8780010ae Restore file contents that were previously in LFS 2024-12-10 21:17:41 -08:00
Ben Croker 2a14ac7ebe
Add IntelliJ plugin link 2024-12-10 20:22:23 -06:00
Ben Croker 8b7fe09c1f
Fix Java SDK constant 2024-12-10 20:21:14 -06:00
Ben Croker 0b4725caec
PHP SDK 1.0.0-beta.1 2024-12-10 20:19:19 -06:00
Andrew Welch b59db9e980 refactor: Updated changelog 2024-12-10 20:56:57 -05:00
Andrew Welch ebd3e23575 refactor: Remove `pluginUntilBuild` property so the plugin will not expire on future IDE releases 2024-12-10 20:56:24 -05:00
Andrew Welch 8624f45276 feat: Add license 2024-12-10 20:55:54 -05:00
Andrew Welch e6138a2698 chore: Delete vestigial file 2024-12-10 20:55:45 -05:00
Ben Croker 6a1c061715
Fix loading order of Attributes plugin 2024-12-10 19:32:25 -06:00
Ben Croker e8671d8c88
Prep for 0.21.0 2024-12-10 19:04:48 -06:00
Ben Croker 2be4e5ef7b
Intellij Plugin (#313)
* Add folder

* feat: Initial plugin check-in under monorepo

* refactor: Add `test.css`

* refactor: Use latest `web-types` schema

* refactor: Better dynamic autocomplete for `data-on-*`, `data-class-*`, and `data-attributes-*`

Some of the other attributes are still a WIP

* refactor: Remove workflows that build/release/test the plugin

tbd if we want to figure out how they work and re-implement them in the future

* refactor: Remove vestigial tests

* refactor: Rename in preparation for multiple `web-types` files

* feat: Add `data-bind-*` autocomplete only on user input elements

* feat: Add singular completions

* feat: Add data-computed

* feat: Add data-signals-*

* feat: Add `raf` & `signal-change` events

* feat: Add `data-ref`

* feat: Add `data-indicator`

* feat: Finish attributes

* refactor: Code cleanup

* refactor: Namespace to `starfederation`

* feat: Add `data-on-*` modifiers

* feat: Add data-persist modifiers

* refactor: Make our attributes virtual

* refactor: Make modifiers sticky

* Revert "refactor: Remove workflows that build/release/test the plugin"

This reverts commit 126c2b33e0.

* docs: Add a description

* feat: Add plugin icon

* docs: Update docs to add Errata, add screenshot

* refactor: Version 0.21.0 to match the D* release

* docs: Show how to get the documentation window alongside the autocomplete

* refactor: Switch to `__` modifier separator, add full set of modifiers for all tags

---------

Co-authored-by: Andrew Welch <andrew@nystudio107.com>
2024-12-10 18:18:51 -06:00
Delaney 20ad2ff9ac
Release/0.21.0 (#348)
* scratch no longer has a /tmp dir, move to alpine
we need all the files cause Docker COPY doesn't support glob

* Update routes_home.templ (#319)

Remove two typos

* toggleAll & setAll use path instead of regex (#318)

* toggleAll & setAll use path instead of regex
Fixes #317

* Fix wording

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>

* Update release note

* Update go_deeper.md (#320)

Minor edits to Signals section, for grammar, clarity

* Make retries and backoff configurable (#316)

Fixes #190

* Fix links to SDKs

* Tweak intro code

* Improve getting started guide

* Fix and improve getting started guide

* Add web components

* evt.detail.value not working for third party libs (#326)

* evt.detail.value not working for third party libs
Fixes #324

* regex is never fun

* fix possible xss on errors

* Add circular logo

* fix clipboard usage on front page

* Support closing SSE connection from client side (#327)

Fixes #276

* Fix link in readme

* refactor: `nodejs`, `npm`, and `pnpm` are needed for the `libpub` task

* data-ref bug (#333)

* data-ref bug
Fixes #331

* Merge branch 'develop' of github.com:starfederation/datastar into delaneyj/issue331

* adds context.WithTimeout to site smoketests (#334)

removes got lib refs

* Java SDK (#321)

* Examples

* SDK and Readme

* Added build files

* Fixed Readme

* add SDKs to frontpage

* TODONE: BEN!

* Importing Datastar (#335)

Fixes #329

* bad link

* Rename default constant (#330)

* Rename default constant

* Fix PHP usage

* Build

* Remove Teleport from docs

* Bundler bug (#347)

Fixes #339

* make modifiers spec compliant (#346)

* make modifiers spec compliant
Fixes #345

* `_` for modifier args is now back to `.`. Please let it end

* remove unused error

* bump version

* Release notes and VSCode release

* Update VSCode version number

* Fix up modifier docs

---------

Co-authored-by: Wm Talcott <32972881+codetalcott@users.noreply.github.com>
Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
Co-authored-by: Ben Croker <ben@putyourlightson.com>
Co-authored-by: Andrew Welch <andrew@nystudio107.com>
Co-authored-by: zangster300 <nick0xbb8@gmail.com>
Co-authored-by: Peter Humulock <rphumulock@gmail.com>
2024-12-10 17:21:06 -06:00
Ben Croker 326445dc43
Fix up modifier docs 2024-12-10 17:18:06 -06:00
Ben Croker fffdc0fe64
Update VSCode version number 2024-12-10 17:11:52 -06:00
Ben Croker 0a5e19eaa8
Release notes and VSCode release 2024-12-10 17:07:41 -06:00
Delaney Gillilan 35bfc89a42 remove unused error 2024-12-10 14:46:45 -08:00
Delaney 0551551c62
make modifiers spec compliant (#346)
* make modifiers spec compliant
Fixes #345

* `_` for modifier args is now back to `.`. Please let it end
2024-12-10 14:32:27 -08:00
Delaney c5389419ae
Bundler bug (#347)
Fixes #339
2024-12-10 16:28:46 -06:00
Ben Croker 6f0293dec4
Remove Teleport from docs 2024-12-10 15:39:39 -06:00
Ben Croker 0892104623
Rename default constant (#330)
* Rename default constant

* Fix PHP usage

* Build
2024-12-10 10:22:27 -06:00
Delaney Gillilan 6b8110671a bad link 2024-12-09 16:08:36 -08:00
Delaney 9ca90807ad
Importing Datastar (#335)
Fixes #329
2024-12-09 16:59:24 -06:00
Ben Croker b3ec534a5d
Merge branch 'docs/improvements' into develop 2024-12-09 16:47:33 -06:00
Ben Croker 82d669a42e
TODONE: BEN! 2024-12-09 16:47:05 -06:00
Delaney Gillilan e3dd27e10b Merge branch 'develop' of github.com:starfederation/datastar into develop 2024-12-09 12:10:18 -08:00
Delaney Gillilan b26e4c1415 add SDKs to frontpage 2024-12-09 12:10:06 -08:00
Peter Humulock 6172fbd43d
Java SDK (#321)
* Examples

* SDK and Readme

* Added build files

* Fixed Readme
2024-12-09 10:59:24 -08:00
zangster300 d6826ca92d
adds context.WithTimeout to site smoketests (#334)
removes got lib refs
2024-12-09 10:58:30 -08:00
Delaney 4c20476b47
data-ref bug (#333)
* data-ref bug
Fixes #331

* Merge branch 'develop' of github.com:starfederation/datastar into delaneyj/issue331
2024-12-09 08:43:51 -08:00
Andrew Welch 2fe3713f39 refactor: `nodejs`, `npm`, and `pnpm` are needed for the `libpub` task 2024-12-09 00:11:53 -05:00
Ben Croker 255a699f7d
Fix link in readme 2024-12-08 07:51:23 -06:00
Delaney 41fb2df3a8
Support closing SSE connection from client side (#327)
Fixes #276
2024-12-07 20:17:56 -08:00
Delaney Gillilan 14839abfb5 fix clipboard usage on front page 2024-12-07 15:02:35 -08:00
Ben Croker 75701f70d6
Add circular logo 2024-12-07 13:57:23 -06:00
Delaney Gillilan 208b94aefb Merge branch 'develop' of github.com:starfederation/datastar into develop 2024-12-07 11:34:09 -08:00
Delaney Gillilan afcd51126c fix possible xss on errors 2024-12-07 11:33:36 -08:00
Delaney 09a5c9017c
evt.detail.value not working for third party libs (#326)
* evt.detail.value not working for third party libs
Fixes #324

* regex is never fun
2024-12-07 11:03:49 -08:00
Ben Croker cbdae3de93
Add web components 2024-12-07 07:34:45 -06:00
Ben Croker 7c0c37fb0f
Fix and improve getting started guide 2024-12-07 00:03:39 -06:00
Ben Croker 21749ef0d3
Improve getting started guide 2024-12-06 23:50:10 -06:00
Ben Croker 1000e2e95a
Tweak intro code 2024-12-06 20:02:47 -06:00
Ben Croker 80728114b8
Fix links to SDKs 2024-12-06 19:57:35 -06:00
Delaney 39268eda93
Make retries and backoff configurable (#316)
Fixes #190
2024-12-06 13:50:49 -08:00
Delaney Gillilan f50a04ae4f Merge branch 'main' of github.com:starfederation/datastar into develop 2024-12-06 13:48:37 -08:00
Wm Talcott 2759382e7c
Update go_deeper.md (#320)
Minor edits to Signals section, for grammar, clarity
2024-12-06 15:15:28 -06:00
Ben Croker 3595708a40
Update release note 2024-12-06 15:11:55 -06:00
Delaney 26d0e5ca20
toggleAll & setAll use path instead of regex (#318)
* toggleAll & setAll use path instead of regex
Fixes #317

* Fix wording

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2024-12-06 15:11:06 -06:00
Delaney Gillilan 06fb18fb3a Fix types errors and NPM build 2024-12-06 12:54:30 -08:00
Wm Talcott b6128b5dde
Update routes_home.templ (#319)
Remove two typos
2024-12-06 14:54:20 -06:00
Delaney Gillilan 57dd46aaad scratch no longer has a /tmp dir, move to alpine
we need all the files cause Docker COPY doesn't support glob
2024-12-06 10:08:46 -08:00
Ben Croker eeb0e03d0a
Fix cmd path 2024-12-06 11:01:37 -06:00
Ben Croker 328577fc2a
Attempt fix 2024-12-06 10:57:57 -06:00
Ben Croker bd34006c42
Attempt to fix Docker path 2024-12-06 10:53:07 -06:00
Ben Croker bac182f5d6
Add VSCode extension to release notes 2024-12-06 10:34:40 -06:00
Ben Croker 5d7afc0245
VSCode 0.21.0 2024-12-06 10:27:40 -06:00
Ben Croker fff41075d4
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2024-12-06 10:23:23 -06:00
Ben Croker 5708dfb20f
Release v0.21.0-beta1 2024-12-06 10:22:58 -06:00
Delaney Gillilan a6e9fe6e71 fix png pointer 2024-12-06 08:06:28 -08:00
Ben Croker 0b7fbcf341
Tweak intro 2024-12-06 08:47:09 -06:00
Ben Croker c104da0371
Fix link in readme 2024-12-06 08:42:13 -06:00
Ben Croker 885830304b
Fix GitHub link 2024-12-06 08:36:45 -06:00
Ben Croker 1a129e3951
Fix computed plugin (#314) 2024-12-06 08:27:07 -06:00
Ben Croker ce895445e0
Add options to example 2024-12-05 21:43:00 -06:00
Peter Humulock 378468ee56
Added Example output (#312)
* Added Example output

* Tweaks

* Indentation

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2024-12-05 20:55:16 -06:00
Ben Croker abd96a9139
Fix SDK spec 2024-12-05 20:40:47 -06:00
Ben Croker 48a8ff572f
Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2024-12-05 20:26:19 -06:00
Ben Croker 8caecab717
Finish pre release version 2024-12-05 20:20:12 -06:00
Ben Croker bb3a0a718a
Update README.md 2024-12-05 20:12:25 -06:00
Ben Croker 2546b3a624
Use pre release version number (beta not allowed) 2024-12-05 19:56:17 -06:00
Ben Croker 78de4e3014
VSCode extension 0.21.0-beta1 2024-12-05 19:47:34 -06:00
Ben Croker 887b9f7293
Add default sse method 2024-12-05 12:53:14 -06:00
Delaney ccdd0d79db
add Datatstar.apply as public (#310)
Fixes #298
2024-12-05 10:43:21 -08:00
Delaney df109f91d2
Keep SSE connection while tab is inactive (#311)
Fixes #246
Add better sse handles and docs
2024-12-05 10:42:36 -08:00
Delaney 093aeac21a
v0.21.0-beta1
* Fix newline in SDK protocol for paths. (#281)

* Fix newline in SDK protocol for paths.
Fixes #272

* Update PHP SDK

* Fix newline in SDK protocol for paths in Go SDK #272

* Tweak wording

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>

* Rename data-store to data-merge-signals. (#280)

* Make title dynamic in site (#277)

* Make title dynamic in site
Fixes #263

* Update meta tags

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>

* Add release note

* Rename data-store to data-merge-signals.
Fixes #269

* Fix backend reference docs and example

* feat: Add fly-deploy.yaml, manually triggered via GH only for now

* Rename data-store to data-merge-signals.
Fixes #269

* Update SDK #269

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
Co-authored-by: Andrew Welch <andrew@nystudio107.com>
Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>

* side effects

* Delaneyj/issue270 (#282)

* Start work on data-model removal #270

* move files  #270

* move all test and examples to data-bind from data-model

* merge consts

* Add release note

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>

* Move to `@` for actions (#283)

* move to @ for actions

* Rename store to signals for #284  (#289)

* Rename store to signals #284 passes tests

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>

* Update CHANGELOG.md

* Release notes

* Preprocessor to macro (#290)

* Preprocessor to macro Fixes #285

---------

Co-authored-by: Andrew Welch <andrew@nystudio107.com>

* Remove RefMacro

* Tweka wording

* Fix docs

* Support explicit syntax (#297)

* refactor: Use Docker-dev for the base image, and build all the things

* refactor: Log in to the registry

* refactor: Run on workflow changes

* chore: revert changes

* Improve homepage title

* delete everything first

* add top level sdk folder
move go SDK
add back bundles and stuff to make tsbuild work

* update go SDK url

* fix: Fix issue with `make task`

* fix: Fix multiple linux arch’s, add `support` as a `deploy` dep

* refactor: Install `flyctl`

* refactor: Output to the current directory

* refactor: ignore .out

* refactor: Run via Docker container

* refactor: Use `flyctl` instead of the alias

* refactor: Docker-in-Docker

As per “The Socket Solution” here: https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/

* refactor: Fix comment

* refactor: Make fly alias

* refactor: Use fly alias

* add vendored back in

* fix: Revert relative paths

* refactor: Revert ignoring `.out`

* refactor: Run flyctl in the CI container

* refactor: Remove flyctl

* refactor: Remove socket bind mount

* refactor: Add `flyctl` back in so `make task deploy` can be done locally

* add types and nested signals

* Add canonical meta tag

* add more stuff back in

* add ( i think ) the rest of the plugins

* lazy generation ReactiveExpresison, get click to edit working

* data-merge-signals to data-signals
start @action to action

* Add WIP release notes

* update more examples removing @ syntax and moving to sse action

* remove deprecated examples

* The great $ purge of 2024

* Add error codes

* working on v21 syntax  #296
fix bind/intersect lazy reactiveExpression gen

* Fix todo demo

* Reorder plugins

* Start markdown errors

* Finish markdown errors

* Update release notes

* Add release note

* Update release note

* remove dup and require checks

* fix signals JSON usage
fix throttle/debounce lead/trail port

* make js obj helper
auto formatting
signal value needed explicit period prefix for value
data-signals lazy generates due to possible expressons
removeSignal applies after eval

* update test, 127/127

* Create VSCode extension (#295)

* Add attributes

* Finish attributes

* Fix repo URL

* Finish

* change attributes

* fix attributes

* VSCode extension improvements

* fix data-attributes example

* Fix a BEN!

* support individual data-class-foo calls

* error page

* Rework error pages

* Simplify

* Rework errors

* Fixes

* Delete `console.log` from library

* #296 persist back in

* Add missing error

* remove mouse move until I implement correctly

* i hate javascript

* . syntax for modifiers now :

* Extract plugin rules

* Add clarification comment

* support xor key or value for bind/ref/indicator

* Add KeyValRules

* Remove unused properties

* Update VSCode extension

* Update docs

* Improve getting started guide

* logic restored

* autogen error sidebar links

* fixed Restructure folders #287

* fix scroll test
* Prep docs for release

* Fixed check for exclusive requirements

* Build

* img diff

* add errors to nested signals
fix getting started

---------

Co-authored-by: Andrew Welch <andrew@nystudio107.com>
Co-authored-by: Ben Croker <ben@putyourlightson.com>
Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>

* fix signals type elision

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
Co-authored-by: Andrew Welch <andrew@nystudio107.com>
Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2024-12-05 09:09:04 -08:00
Delaney ee215e5fc0
Redirect `fly.dev` site (#306)
Fixes #299
2024-12-04 18:43:18 -06:00
Ben Croker d5350b0b5b
Add canonical meta tag 2024-12-01 19:20:45 -06:00
Andrew Welch fdc73d5d9c refactor: Add `flyctl` back in so `make task deploy` can be done locally 2024-12-01 19:05:16 -05:00
Andrew Welch 57be12a943 refactor: Remove socket bind mount 2024-12-01 19:04:09 -05:00
Andrew Welch d165916b49 refactor: Remove flyctl 2024-12-01 18:54:20 -05:00
Andrew Welch c2c7dea7cd refactor: Run flyctl in the CI container 2024-12-01 18:48:46 -05:00
Andrew Welch 42a596f753 refactor: Revert ignoring `.out` 2024-12-01 18:42:32 -05:00
Andrew Welch 75068e68e4 fix: Revert relative paths 2024-12-01 18:41:50 -05:00
Andrew Welch 2ff246c7d2 refactor: Use fly alias 2024-12-01 18:10:32 -05:00
Andrew Welch 5cfec4ea7a refactor: Make fly alias 2024-12-01 18:10:24 -05:00
Andrew Welch 559436c092 refactor: Fix comment 2024-12-01 18:00:00 -05:00
Andrew Welch d6e744632e refactor: Docker-in-Docker
As per “The Socket Solution” here: https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/
2024-12-01 17:35:17 -05:00
Andrew Welch 38d038dd4d refactor: Use `flyctl` instead of the alias 2024-12-01 17:21:28 -05:00
Andrew Welch bdac0f31e8 refactor: Run via Docker container 2024-12-01 17:14:37 -05:00
Andrew Welch d61381f7c4 refactor: ignore .out 2024-12-01 17:08:52 -05:00
Andrew Welch 6899db0c19 refactor: Output to the current directory 2024-12-01 17:08:42 -05:00
Andrew Welch 093b4bdcfa refactor: Install `flyctl` 2024-12-01 17:07:40 -05:00
Andrew Welch e1874e3bfc fix: Fix multiple linux arch’s, add `support` as a `deploy` dep 2024-12-01 17:01:05 -05:00
Andrew Welch 66d44bc7f3 fix: Fix issue with `make task` 2024-12-01 17:00:32 -05:00
Ben Croker 23aafbaa56
Improve homepage title 2024-11-30 07:50:23 -06:00
Andrew Welch c0d8fdb583 chore: revert changes 2024-11-29 13:11:06 -05:00
Andrew Welch 0fa2405728 refactor: Run on workflow changes 2024-11-29 13:04:15 -05:00
Andrew Welch 3fe8e6ce2e refactor: Log in to the registry 2024-11-29 13:03:11 -05:00
Andrew Welch 1b541e5e35 refactor: Use Docker-dev for the base image, and build all the things 2024-11-29 12:59:10 -05:00
Greg H 26b947b8d1
sdk/dotnet-code_snippets (#247)
* sdk/dotnet-code_snippets - csharp snippets: multiple_events and setup

* sdk/dotnet-code_snippets - setup updated to be more terse

* Update multiple_events.csharpsnippet

* Update README.md

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2024-11-29 06:45:30 -06:00
Delaney Gillilan 1b4b228f48 Merge branch 'develop' of ssh://github.com/starfederation/datastar into develop 2024-11-28 16:46:06 -08:00
Delaney Gillilan ca1e3b5888 fix example in dotnet 2024-11-28 16:46:04 -08:00
Andrew Welch 837832f3d0 feat: Add fly-deploy.yaml, manually triggered via GH only for now 2024-11-28 17:16:32 -05:00
Ben Croker b3d8e50edc
Fix backend reference docs and example 2024-11-28 16:03:23 -06:00
Delaney f0eea03171
Make title dynamic in site (#277)
* Make title dynamic in site
Fixes #263

* Update meta tags

---------

Co-authored-by: Ben Croker <ben@putyourlightson.com>
2024-11-28 12:23:34 -06:00
Andrew Welch 63482a9912 refactor: `build` -> `tests` 2024-11-28 09:56:02 -05:00
Andrew Welch f3d04d5385 refactor: Set up git-lfs 2024-11-28 09:51:04 -05:00
Andrew Welch 37b201622b refactor: Run task tools 2024-11-28 09:47:44 -05:00
Andrew Welch 1679ad2d45 refactor: Fix working directory 2024-11-28 09:44:14 -05:00
Andrew Welch 7934b385bd refactor: Fix name 2024-11-28 09:39:13 -05:00
Andrew Welch 206a3c13f8 feat: Initial tests workflow 2024-11-28 09:37:47 -05:00
Andrew Welch 4219f2ed58 refactor: Re-run on changes to the workflow itself as well 2024-11-28 09:13:30 -05:00
Andrew Welch 030f93048b refactor: Remove OWNER from tags 2024-11-28 09:04:48 -05:00
Delaney Gillilan 99f8ef2a05 Merge branch 'develop' of github.com:starfederation/datastar into develop 2024-11-28 05:23:02 -08:00
Delaney Gillilan 1714295db7 remove unused code 2024-11-28 05:22:59 -08:00
Ben Croker ba10b96f10
Fix meta tags (#273)
* Delete `site.webmanifest`

* Use absolute path
2024-11-28 06:50:05 -06:00
Delaney a74e754d96
Upsert consistent ID for `data-indicator` #223 (#275) 2024-11-27 21:28:03 -08:00
Andrew Welch 12f8b4d5db refactor: Only automatically run the action if `Dockerfile-dev` has changed (or via manual trigger) 2024-11-27 23:03:38 -05:00
Andrew Welch 42e061cb1b refactor: Remove final target 2024-11-27 22:57:35 -05:00
Andrew Welch c496647ebe refactor: Fix env var access 2024-11-27 22:56:50 -05:00
Andrew Welch 3a6eee09a1 refactor: `env` must be applied to the job, not the step 2024-11-27 22:54:25 -05:00
Andrew Welch 93679364d0 refactor: Tag `latest` 2024-11-27 22:50:31 -05:00
Andrew Welch c303ac0da0 refactor: Fix reference tag format 2024-11-27 20:11:09 -05:00
Andrew Welch 8380a7224b refactor: Fix action version 2024-11-27 20:08:45 -05:00
Andrew Welch 5b14f9f174 feat: Add `CODEOWNERS` and build docker images GH action 2024-11-27 20:07:10 -05:00
Delaney 2cce474a85
Delaneyj/issue255 (#267)
* Issue getting throttling to work on event listeners #255

* Can't reproduce Issue getting throttling to work on event listeners, made /examples/debounce_and_throttle fixes #255
2024-11-27 15:44:57 -08:00
Delaney Gillilan a69f019731 merged icons and fixed GoSDK usage 2024-11-27 14:23:41 -08:00
Ben Croker 18c9a457e1
`DeleteFromStore` → `RemoveSignals` (#264) 2024-11-27 14:08:10 -08:00
Delaney 99cc5c9640
Delaneyj/issue262 (#266)
* Headers not merging correctly
Fixes #258

* add dep update

* Fix dialog test
Add helper for testing

* move csrf to a helper as well

* side effects

* deflake offline sync test

* cleanup merge options

* fix redirect test

* fix wait order for merge options

* fix scroll into view test, do not do float equality!

* fix lazy tabs and helpers

* add idle checks, cleanup helpers
2024-11-27 14:07:52 -08:00
Ben Croker 17c01af5e2
Fix `settleDuration` in example 2024-11-27 14:56:54 -06:00
Ben Croker 387bbd8c40
Fix typo in example 2024-11-27 14:55:49 -06:00
Ben Croker 2d53463b6e
Add favicons and social media sharing meta tags (#257)
* Add favicons and social media sharing meta tags

* Fix paths
2024-11-27 14:48:57 -06:00
Delaney fee32181cc
Click to load test failing (#261)
Fixes #260
2024-11-27 10:55:56 -08:00
Ben Croker f87ad44151
`fragment` → `fragments` in docs 2024-11-27 12:08:11 -06:00
Ben Croker fbc5eeaae3
Fix it in the right place! 2024-11-27 12:00:06 -06:00
Ben Croker 0fa9d93913
Update readme template 2024-11-27 11:18:37 -06:00
Ben Croker 600fca2ff0
Add GitHub stars badge 2024-11-26 19:48:21 -06:00
zangster300 a9bc6f5aa0
Automated Site Smoketesting (#254)
* adds automated smoketests for the site
2024-11-26 16:10:57 -08:00
Felix Ingram a02c0f15a9
Add platforms to taskfile (#251)
* Add platforms to taskfile

Means that we download the correct version of tailwindcli for the
current platform.

* Remove comment

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2024-11-26 15:23:32 -06:00
Ben Croker 303beaf7da
gitignore 2024-11-26 08:03:44 -06:00
Delaney Gillilan 8ebedce27f Merge branch 'main' of github.com:starfederation/datastar into develop 2024-11-25 17:30:49 -08:00
Delaney Gillilan 07d8628f4a fix change log 2024-11-25 17:28:56 -08:00
Delaney 207f1205b2
V0.20.1 (#244)
# Release Notes for Datastar

## 0.20.0 - 2024-11-22

VersionClientByteSize     = 35970->35789
VersionClientByteSizeGzip = 12647->12568

> [!WARNING]
> This update contains breaking changes to attributes, actions and SSE events.

### Added
- SDKs
  - .NET
    - Initial SDK release! #231
  - PHP
    - Allow KV pairs
    - Author
- DevOps
  - added `make test` & `make clean` to development Dockerfile

### Changed
- Client
  - Function expression optimizations #234
  - Truthy Attributes were not getting set correctly #234
  - Fix invalid headers sent via SSE #241
  - Added hooks so NPM will package the correct files
- SDKs
  - updated README for clarity around contributing
  - Go
    - Fix inverted logic for ViewTransitions #238
  - PHP
    - tagged SDK 1.0.0-alpha.1
    - fixed retry duration
    - general cleanup
- Website
  - Bundler getting create valid zip for Windows #228
  - General site improvements
  - Actions section in getting started
  - Fixed broken links for SDKs and CDN #225
  - Try to fix Safari bug around caching SSE connections #239
- Devops
  - fix `make dev` to work cross-platform
  - moved development Dockerfile from Alpine to Ubuntu


### Removed
- DevOps
  - Removed broken Github Actions
2024-11-25 17:21:18 -08:00
Delaney Gillilan 5283522909 make checkbox labels clickable 2024-11-25 16:35:51 -08:00
Ben Croker e1c3590698
Rocket man 2024-11-25 18:28:12 -06:00
Ben Croker 636e87fe14
Merge branch 'develop' of https://github.com/delaneyj/datastar into develop 2024-11-25 18:28:00 -06:00
Ben Croker 836de8b2f3
Merge branch 'docs/guide-indicator-actions' into develop 2024-11-25 18:26:14 -06:00
Delaney 8aac732c28
Fix invalid headers (#241)
Fixes #240
2024-11-25 16:05:31 -08:00
Ben Croker 8a91477cae
Merge branch 'develop' of https://github.com/delaneyj/datastar into develop 2024-11-25 18:03:58 -06:00
Ben Croker 1e99ba988a
Add links to SDKs 2024-11-25 18:03:01 -06:00
Delaney acba200de8
Full on double streaming SSEs in Safari (#239)
Fixes #226
2024-11-25 15:45:26 -08:00
zangster300 b0fde462de
update to swap with and without vt bools (#238) 2024-11-25 15:11:13 -08:00
Ben Croker 29282a7983
Fix get store method 2024-11-25 15:53:07 -06:00
Ben Croker 4d29fdf78b
Merge branch 'develop' of https://github.com/delaneyj/datastar into develop 2024-11-25 15:52:20 -06:00
Ben Croker 37444e2305
Remove workflows 2024-11-25 15:23:10 -06:00
Andrew Welch 91b58933e7
feat: Preliminary work to switch to Ubuntu, so headless chrome can work (#232) 2024-11-24 21:46:02 -08:00
Greg H b9bee9623e
C# SDK (#231)
* sdk/dotnet-v2

* sdk/dotnet-v2 - Build.ps1 builds a nuget now. Added Samples.sln. Removed cruft files from SDK project

---------

Co-authored-by: Greg Holden <SpiralOSS@users.noreply.github.com>
2024-11-24 21:45:35 -08:00
Ben Croker 4c78e43460
Optimise error handling in engine (#234)
* wip

* Finish optimising
2024-11-24 21:44:11 -08:00
Ben Croker 95b31b0453
Merge branch 'sdk/php' into develop 2024-11-24 18:13:16 -05:00
Ben Croker 5eaac19ec4
Better attribute support (#236) 2024-11-24 14:33:36 -08:00
Ben Croker 9af0ffae44
Clean up SDK 2024-11-24 17:17:12 -05:00
Ben Croker 8895df60c3
Finish feature 2024-11-24 17:05:48 -05:00
Ben Croker cdbbf6af92
Add actions section 2024-11-24 15:12:01 +01:00
Ben Croker bca5eba9d7
Improve execute script 2024-11-24 14:02:59 +01:00
Ben Croker 321079e3ae
Add author 2024-11-23 18:20:11 +01:00
Ben Croker 35ff45604a
Accept array of signals 2024-11-23 18:16:58 +01:00
Ben Croker 3a55047a08
Allow KV pairs in PHP SDK 2024-11-23 17:12:18 +01:00
Ben Croker b481d60313
Fix dataline in PHP SDK 2024-11-23 14:30:49 +01:00
Ben Croker 269fdfd131
Fix retry duration in PHP SDK 2024-11-23 13:55:03 +01:00
Ben Croker b027422eaf
Fix guide example 2024-11-23 07:08:45 +01:00
Ben Croker 3b1a79b82e
Fix link in docs 2024-11-23 06:42:47 +01:00
Andrew Welch 48134fe0ff refactor: Add targets to PHONY 2024-11-22 16:14:51 -05:00
Andrew Welch 787bb7044f feat: Add `make clean` 2024-11-22 16:12:54 -05:00
Andrew Welch afa0ec5bd6 docs: Add docs for `make test` & `make clean` 2024-11-22 16:12:44 -05:00
Andrew Welch 00107ab323 Merge branch 'develop' of https://github.com/starfederation/datastar into develop 2024-11-22 15:33:59 -05:00
Andrew Welch ddbd0804d1 feat: Add `make test` & remove vestigial “npm” references in the comments 2024-11-22 15:21:59 -05:00
Andrew Welch f696d693ac fix: Fix default `make dev` task 2024-11-22 15:19:28 -05:00
Delaney 9e61275e1c
Bundler zip doesn't work on Windows (#228)
Fixes #227
2024-11-22 12:10:14 -08:00
Delaney e1ecf57198
Website navigation is broken on Firefox (#225)
Fixes #224
2024-11-22 09:19:31 -08:00
Ben Croker f4d0ecf328
Fix link to core 2024-11-22 16:24:18 +01:00
Ben Croker 299424b0f4
Fix GitHub link 2024-11-22 16:22:25 +01:00
Ben Croker 7b798fe7c4
Update readme 2024-11-22 16:19:40 +01:00
Ben Croker c5d024bde5
Update package description 2024-11-22 16:05:06 +01:00
Ben Croker f2f8c1271d
Fix PHP SDK readme 2024-11-22 11:31:34 +01:00
Ben Croker b09cacee33
Tag PHP SDK 1.0.0-alpha.1 2024-11-22 11:16:17 +01:00
Delaney Gillilan 150a961d33 add webp rocket back in 2024-11-22 01:24:42 -08:00
Ben Croker 5764b53eb9
Fix readme 2024-11-22 10:19:20 +01:00
Delaney Gillilan 802bf0309f add back in extra tag push 2024-11-22 01:14:27 -08:00
Delaney Gillilan 345d417041 v0.20.0 RELEASE!!! 2024-11-22 01:08:49 -08:00
Ben Croker 55d68879f5
Merge branch 'develop' 2024-11-22 10:05:04 +01:00
Ben Croker 21857de541
Star first 2024-11-22 10:04:24 +01:00
Ben Croker a19821ff36
Minor tweaks 2024-11-22 09:42:42 +01:00
Delaney Gillilan 94b8c6a494 version bump to test npm 2024-11-22 00:39:20 -08:00
Delaney Gillilan 41b8d05dff cleanup NPM package build 2024-11-22 00:37:22 -08:00
Delaney Gillilan af1205a298 bad points 2024-11-22 00:23:17 -08:00
Delaney 6b5b3a62a6
Reorg the project, c/p from https://github.com/starfederation/datastar-restructure-interim #211 (#212) 2024-11-22 00:11:04 -08:00
Ben Croker 379730c21a
Remove `data-fetch-url` from example code (#205) 2024-11-06 07:18:31 -08:00
Ben Croker e3da825170
Minor improvement 2024-11-04 10:21:01 +01:00
Ben Croker 53431df523
Merge pull request #206 from khalwat/feature/docker-dev
Fix Feature/docker dev
2024-11-04 10:18:06 +01:00
Ben Croker df7cd11f13
Merge branch 'main' into feature/docker-dev 2024-11-04 10:17:13 +01:00
Andrew Welch 3fea94bbb6 fix: Remove library dependency from serve-hot so HMR works 2024-11-03 20:13:20 -05:00
Andrew Welch b6b0593891 refactor: Add templ as a dep 2024-11-03 19:31:31 -05:00
Andrew Welch 909fd4cdaf refactor: Add library as dep 2024-11-03 19:20:31 -05:00
Andrew Welch 706344fa14 feat: Install templ cli 2024-11-03 19:08:02 -05:00
Andrew Welch a623df49bd fix: Build the necessary components inside the running container rather than in the Dockerfile 2024-11-03 18:44:54 -05:00
Andrew Welch 8ccc8bd33a
Feature/docker dev (#203)
* feat: Initial docker-dev work

* refactor: Use -c

* refactor: do a fetch & pull too

* feat: Use the vite devserver when doing local development

* refactor: Add taskfile

* feat: Build the backend ahead of time so it’s cached

* feat: Clean up clean

* docs: Add documentation for Datastar Docker dev

* refactor: Add the package.json since the Taskfile tries to read it
2024-11-03 05:13:57 -08:00
Andrew Welch 4fc8a74b86 refactor: Add the package.json since the Taskfile tries to read it 2024-11-03 05:19:35 -05:00
Ben Croker c6b711177e
Fix file upload example (#204) 2024-11-02 11:22:47 -07:00
Andrew Welch 67ef5a0211 docs: Add documentation for Datastar Docker dev 2024-11-02 00:55:42 -04:00
Andrew Welch 78cd6d94df feat: Clean up clean 2024-11-02 00:55:25 -04:00
Andrew Welch 5ddb55b0ad feat: Build the backend ahead of time so it’s cached 2024-11-02 00:15:53 -04:00
Andrew Welch 839446db67 refactor: Add taskfile 2024-11-01 23:58:14 -04:00
Andrew Welch 559a10bfea feat: Use the vite devserver when doing local development 2024-11-01 23:57:44 -04:00
Andrew Welch 1e6558168e refactor: do a fetch & pull too 2024-11-01 19:39:15 -04:00
Andrew Welch 816e3410a1 refactor: Use -c 2024-11-01 19:30:42 -04:00
Andrew Welch 1c4eff6e21 feat: Initial docker-dev work 2024-11-01 19:18:41 -04:00
Ben Croker d3a939ed8c
Document `evt` variable (#202)
* Document `evt` variable

* Add example
2024-11-01 14:19:32 -07:00
Ben Croker b7baab20b7
Docs: fill in the gaps (#200)
* Add note about underscore

* Add note about `script` tags

* List event listeners

* Add Contributing guidelines
2024-11-01 02:53:18 -07:00
Ben Croker fe71830ffc
Update web_component.md (#201) 2024-11-01 02:52:49 -07:00
Ben Croker 3ba49ebe18
Merge pull request #191 from delaneyj/example/improve-sortable
Use custom event in Sortable example
2024-10-30 09:42:05 +01:00
Ben Croker 25940275fd
Merge branch 'main' into example/improve-sortable 2024-10-30 09:41:19 +01:00
Delaney Gillilan 3d6ec86881 typo 2024-10-29 07:10:53 -07:00
Ben Croker 2b7be994e0
Add web component example (#192)
* Add web component example

* Compact spacing
2024-10-29 07:08:42 -07:00
Ben Croker dcf572def2
Document `data-computed-*` (#194) 2024-10-29 07:06:20 -07:00
Ben Croker 2c752ac328
Grammatical improvements & fixes to docs (#193)
* Improvements

* Make apostrophes consistent
2024-10-29 07:05:50 -07:00
M f8f18494c9
Fix `onlyIfMissing` docs (#197)
* refs #143

* fixing docs to match code
2024-10-29 07:05:00 -07:00
Patrick Marchand d35a053cea HACKING.md add link to playwright system requirements 2024-10-28 10:32:38 -04:00
Patrick Marchand 978411f619 Better docs for hackers 2024-10-28 10:21:40 -04:00
Ben Croker 28f0aa3933
Use custom event 2024-10-28 09:19:18 +01:00
Ben Croker b61bcea05e
Improve modifier docs 2024-10-26 21:07:34 +02:00
Ben Croker ce0c4e9e4f
Document `.window` modifier 2024-10-26 21:02:40 +02:00
Ben Croker b27e7a105f
Update routes_examples.go 2024-10-25 20:17:04 +02:00
Ben Croker acebb6977f
Create cloak.md 2024-10-25 20:09:42 +02:00
Delaney Gillilan 4a91f8eb20 fix TS error 2024-10-25 05:28:50 -07:00
Ben Croker 0be1ed6057
Merge pull request #181 from human154/patch-2
Improve wording of getting_started.md "copy locally" section
2024-10-25 11:54:09 +02:00
Ben Croker 975752cff1
Merge pull request #180 from human154/patch-1
Improve wording in routes_home.templ opening paragraph.
2024-10-25 11:53:41 +02:00
human154 784af7543a
Improve wording of getting_started.md "copy locally" section 2024-10-24 19:10:07 -04:00
human154 d8a3e5d5da
Improve wording in routes_home.templ
Improve the wording in the opening paragraph.
2024-10-24 18:38:51 -04:00
Ben Croker 74b637889d
Fix `data-ref` processing (#172)
* fix data-ref
2024-10-24 11:04:05 -07:00
Ben Croker 34fffab63d
Update plugins_attributes.md 2024-10-24 16:53:07 +02:00
Delaney Gillilan ddf281fd16 Add data-computed and data-class intial implementation 2024-10-24 06:55:16 -07:00
Ben Croker a92aa3f6b9
Merge pull request #177 from githubUser982/main
Update README.md
2024-10-24 14:35:52 +02:00
githubUser982 38d51ab355
Update README.md
fix typo
2024-10-24 12:26:34 +02:00
Delaney Gillilan a74f4be540 update discord 2024-10-23 15:29:13 -07:00
Delaney Gillilan 3da57f1c30 cleanup 2024-10-22 14:42:16 -07:00
Delaney Gillilan afec038131 add data-header-* support back in 2024-10-22 10:53:24 -07:00
Delaney Gillilan 3643084b1b add github action for discord 2024-10-22 09:08:12 -07:00
Delaney Gillilan 714e4bca20 add rickroll to infinite scroll 2024-10-21 12:27:10 -07:00
Ben Croker 4f92bc7545
Fix script URL 2024-10-20 19:58:27 +02:00
Ben Croker 0a577e3e8e
Fix script tag 2024-10-20 19:41:12 +02:00
Delaney c21d9d390d
Delete from store (#170)
* add DeleteFromStore support

* update docs
2024-10-20 09:36:19 -07:00
Delaney Gillilan 00b8e6ba8f back to inspector 2024-10-19 07:40:54 -07:00
Delaney Gillilan 91e5e432ea add multi select support 2024-10-19 07:40:20 -07:00
Ben Croker 59e70fc7bd
Merge pull request #164 from 2a5A1Ghu1/patch-1
[EXAMPLES] Fix Spelling/Grammar
2024-10-19 12:10:33 +02:00
Crypto Plisskin 0dc938e4bb
[EXAMPLES] Fix Spelling/Grammar 2024-10-19 02:11:53 -07:00
Delaney Gillilan 45223e9728 add more clarity to redirect example 2024-10-18 20:24:34 -07:00
Delaney Gillilan 37cc8555a7 fix redirect protocol 2024-10-18 20:18:03 -07:00
Ben Croker 39df52f344
Fix version numbers in CDN URL 2024-10-18 22:23:29 +02:00
Delaney Gillilan d15c821ceb version bump 2024-10-17 16:16:41 -07:00
Ben Croker d9552e5143
Add `error` console mode (#160)
* Update backend.ts

* Update plugins_backend.md

* Update plugins_backend.md

* Update backend.ts
2024-10-17 16:10:03 -07:00
M 686f4ad4ae
Fix/attributes 1 (#159)
* refs #143

* attributes fix for web components

---------

Co-authored-by: BlinkingLight <into@ituoga.lt>
2024-10-17 16:09:33 -07:00
Ben Croker 7e4cbd91c6
Fix console event (#158)
* Fix console event

* Update backend.ts
2024-10-17 16:08:48 -07:00
potatotech fd20dd9869
Remove old single fragment limit from docs (#156) 2024-10-17 16:08:13 -07:00
Delaney Gillilan 54dcd69a36 fix signal processing 2024-10-17 04:51:43 -07:00
Delaney Gillilan 59f1ce8732 fix data-model bad check 2024-10-17 04:41:30 -07:00
Ben Croker 322ddbf646
Update event syntax 2024-10-17 13:37:50 +02:00
Ben Croker fe46056a18
Update event syntax 2024-10-17 13:35:23 +02:00
Delaney 740eef306e
v19 Backend cleanup (#155)
* * remove _element suffix
* redircet, error, console are there own events
* fragments now take multi fragments
* delete removed from fragments

* fix backend plugin's delete to make test pass

* all tests pass

* cleanup old routes

* added default consts to backend.ts top of file

* Update docs for Backend Plugins (#154)

* Update plugins_backend.md

* remove bad limit for data-model on type

* add new discord server

* memes

* bump and cleanup

* remove _element from docs

* cleanup

---------

Co-authored-by: Ben Croker <57572400+bencroker@users.noreply.github.com>
2024-10-17 03:10:10 -07:00
potatotech 311b13779d
Fix errors in plugin reference (#150)
* Fix typo in docs for `clampFit` plugin

* Replace isLoading plugin with $$isFetching in docs
2024-10-15 06:28:49 -07:00
Felix Ingram aedbf553c9
Move context to run() (#149) 2024-10-15 06:28:13 -07:00
Delaney Gillilan 1350755474 fix #152 2024-10-14 14:42:32 -07:00
Delaney Gillilan dcf7dbabdd add subreddit 2024-10-10 12:07:18 -07:00
Delaney Gillilan 352cdc3e23 add mouse move and minor throttle change 2024-10-09 18:03:04 -07:00
Delaney Gillilan 79c2e3a397 version bump 2024-10-09 13:25:41 -07:00
Delaney Gillilan 9a07618ac4 add sortable example 2024-10-09 13:23:05 -07:00
M 9f3ffc685f
refs #143 (#148) 2024-10-09 10:19:22 -07:00
Alec Gargett d84c653e84
Fixed minor website examples bug ">" --> ">=" and changed minimum character number to 2 (#147)
* ag-greater-than-fix

* ag-gt-or-equal-2

* ag-gt-or-equal-2-templ
2024-10-07 21:38:35 -07:00
Delaney Gillilan ad644574f8 fix orbitron and meme 2024-10-07 06:24:54 -07:00
Ben Croker a9ae426c13
Update plugins_backend.md (#146) 2024-10-07 06:24:23 -07:00
BK Flister 880e44f1b8
Add headers and media_type to python.md example (#145) 2024-10-05 12:34:42 -07:00
Delaney Gillilan 1ad6a7c4c6 memes 2024-10-05 12:11:56 -07:00
Delaney Gillilan 823ce74401 fix enter key and other on-modifiers 2024-10-05 12:11:46 -07:00
Delaney Gillilan 1d274b181e more memes 2024-10-03 09:02:57 -07:00
M 75d2bfc416
Fix/examples 1 (#142)
* removed start from attribute

* Update model_binding.md
2024-10-03 08:34:23 -07:00
Delaney Gillilan defeddc9b2 turn inspector back on 2024-10-02 17:55:20 -07:00
Delaney Gillilan e15b0cfa44 fix function generation issue 2024-10-02 17:30:56 -07:00
Delaney Gillilan ca2e064206 add evt to arguments 2024-10-02 17:21:16 -07:00
Delaney Gillilan 797c4b6bd2 try to fix inline validation example 2024-10-01 14:53:21 -07:00
Delaney Gillilan 0bad12cc5f add warning it backend plugin docs 2024-10-01 13:01:59 -07:00
Delaney Gillilan a6d1e6a914 more memes and fix link 2024-09-30 20:13:21 -07:00
Delaney Gillilan 3e54e533d1 add meme 2024-09-30 10:53:11 -07:00
Delaney Gillilan 85285df468 add memes 2024-09-30 10:47:36 -07:00
Delaney Gillilan 3eb2eb210b add multi-line store support 2024-09-30 09:53:00 -07:00
Delaney Gillilan 63f164685b fix single letter signals 2024-09-28 12:47:21 -07:00
Delaney Gillilan 4cb5ca5f63 fix bad link 2024-09-27 11:42:16 -07:00
Delaney Gillilan 8fc53b14a9 fix edit_row demo 2024-09-24 10:05:17 -07:00
Delaney Gillilan 4276889448 fix animation example 2024-09-18 07:53:02 -07:00
Delaney Gillilan ab0bc92946 cleanup fetch indicator 2024-09-15 11:58:41 -07:00
Patrick Marchand 805748209a actually commit readme changes 2024-09-14 09:52:26 -04:00
Patrick Marchand 28719283c0 add build instructions to readme
Also remove a duplicated line from taskfile
2024-09-14 09:18:42 -04:00
Delaney Gillilan f16163080d fix bad behavior of ifmissing merge 2024-09-10 23:28:19 -07:00
Delaney Gillilan 0bce22f9c2 Add .ifmissing to data-store and datastar-signal-ifmissing event type
Turn off inspector
2024-09-10 21:46:42 -07:00
Delaney Gillilan 578cb14922 bump version 2024-09-10 11:48:05 -07:00
Delaney 9c9340e76e
capture targets because JS is WAT (#135) 2024-09-10 11:46:19 -07:00
Delaney b32804ebf5
add exponential backoff (#134)
* add backoff
2024-09-10 10:30:58 -07:00
Delaney Gillilan 72680008f0 remove snake for now 2024-09-09 06:40:18 -07:00
Delaney Gillilan 3951381f08 fix inspector examples 2024-09-08 22:21:49 -07:00
Delaney Gillilan ba6edcf359 move to v18 2024-09-08 21:51:46 -07:00
Delaney c4605ef411
Session storage (#129)
* initial implementation
* add example
2024-09-08 21:35:40 -07:00
Delaney Gillilan e5bf5be13c update store example 2024-09-08 21:32:42 -07:00
Patrick Marchand 1eb5b5d8c8
Datastar Inspector (#127)
* Trying to get the attribute evaluation inspection to work

* Improve inspector expression visualization

Keep expression snapshots on all state changes and fix idiomorph not
triggering attribute removals.

* inspector: Keep more events by default

* inspector: cleanup expression list on data-store removal

* Inspector: Improve dom viewer and add events

Work on events for plugin registration, the backend plugin and dom mutations.

Make a tree of Details viewer for the html.

* inspector-extension: improve types and allow devtools to message content

* inspector: add limit tree to rootId and add highlight on hover

* inspector: changes to version viewer

shows the versioned dom in an iframe and shows versioned dom references
to the store. Also allow highlight of ref element on hover (probably should happen
in the iframe instead though)

* commit current inspector work

* fix message for expr construction in inspector

* Replace TemplSignalStoreView with inspector component

Remove some things that werent satisfactory like the dom versioning in the iframe,
improve formatting of some messages and reduce the noise ratio by ignoring
certain datastar classes for animations and expr_construction messages (those show up in the expressions list anyways)

* add sidebar for inspector
cleanup css

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2024-09-08 21:28:23 -07:00
Delaney Gillilan 13d11ece39 add snake example 2024-09-08 15:30:23 -07:00
Delaney Gillilan 92837cacac update other framework numbers 2024-09-02 09:26:31 -07:00
Delaney Gillilan 38e301e9f2 cleanup website, update svelte numbers 2024-08-31 06:34:22 -07:00
Delaney 89b3228c87
remove data-headers plugin (#123) 2024-08-25 16:25:42 -07:00
Delaney 1cbdb6e985
Bad apple ascii example (#122)
* bad apple example

* add zst

* more detail
2024-08-23 20:30:15 -07:00
Peter Humulock 4914e9d4bf
Fix for the style being repeatedly appended from repeated events being sent (#120) 2024-08-20 10:54:06 -07:00
Delaney Gillilan b3bd304321 add dbmon example 2024-08-19 12:29:40 -07:00
Delaney Gillilan 44ef446c33 fix twitter link 2024-08-16 16:41:05 -07:00
Peter Humulock 962e8fe0b9
Added vt option in documentation (#114) 2024-08-16 13:16:48 -07:00
Delaney Gillilan 5c0865d4a6 fix iconify change 2024-08-13 17:18:51 -07:00
Delaney Gillilan 2dcecfcca8 fix front page css 2024-08-13 13:44:19 -07:00
BK Flister e721a5261d
Add Python Fastapi Hypermedia example (#111) 2024-08-12 17:59:06 -07:00
BK Flister c53bc221e1
Add Python FastHTML example (#112)
* Add Python Fastapi Hypermedia example

* Add Python FastHTML example
2024-08-12 17:58:45 -07:00
Peter Humulock 64aea9aba3
Fixing link in guide (#110) 2024-08-12 17:58:16 -07:00
Delaney Gillilan 8a3db108e5 fix localhost reference 2024-08-11 08:52:50 -07:00
Delaney Gillilan 6add96537e add star 2024-08-06 17:11:09 -07:00
Delaney Gillilan e1b6bdcdbc fix graph 2024-08-06 17:05:41 -07:00
Delaney Gillilan e1c164ba9a fix charts 2024-08-06 12:28:28 -07:00
Delaney Gillilan d0a396136a change rocket from midjourney to vector 2024-08-06 11:55:17 -07:00
Delaney Gillilan effc4edaa3 remove console.log bumt po v0.16.2 2024-07-24 05:29:01 -07:00
Delaney Gillilan 434189464a bump to v0.16.1 2024-07-23 08:45:31 -07:00
Delaney Gillilan 71cac90d9e bump to v0.16.0 2024-07-23 08:12:02 -07:00
Delaney cd51af92a2
initial implementation (#109) 2024-07-23 08:00:56 -07:00
Justin Moon bebbdcf556
Fix some copy-pasta (#107)
Thanks @justinmoon !
Python and Haskell examples have copy-pasted title and headers
2024-07-23 07:57:16 -07:00
Peter Humulock 7a06c65939
Added modifiers to data-show (#105)
Fixes #70

* Added modifiers to data-show
Added examples for modifiers and data-show
* Re-added show link
* Added requestAnimationFrame to show animation on first click
* Added better documentation. Added default value if duration value not provided.
* Tweaked duration time

---------

Co-authored-by: Delaney <delaneygillilan@gmail.com>
2024-07-23 07:56:43 -07:00
Delaney b0243e99c7
fix bind string double encode (#108)
add fit actions
2024-07-23 07:54:43 -07:00
Peter Humulock 1cd9f396a7
Merge branch 'main' of https://github.com/delaneyj/datastar into chore/100/rename-core-to-engine (#102) 2024-07-12 10:21:47 -07:00
Peter Humulock 6ca0a5b3d4
Test for todos (#99)
* Test for todos
Fixes #99 

---------

Co-authored-by: Delaney Gillilan <delaneygillilan@gmail.com>
2024-07-12 09:03:12 -07:00
Delaney Gillilan 7222691493 sse is now thread safe
fix fnContent generation
2024-07-08 17:54:32 -07:00
Delaney Gillilan f1392fc6f0 fix indicator test 2024-07-07 09:10:01 -07:00
Delaney Gillilan 3c85a1321c fix fetch indicator
update go deps
2024-07-07 08:54:28 -07:00
Patrick Marchand 98d177630f
inspector: library: add events for expr construction and eval 2024-07-05 18:24:23 -04:00
Patrick Marchand 27ee6aa5d7
inspector-extension: inspector: finalize port to wxt and fix most remaining issues
this commit fixes most of the remaining issues with the inspector as well as adding
better logging of state and a only showing state diffs in the event log.
2024-07-05 10:13:08 -04:00
Patrick Marchand c66bd8b5fb
inspector: add back the test page
not sure how it got removed again
2024-07-05 10:11:42 -04:00
Patrick Marchand f608cc65e1
Initial port of extension code to wxt
It can load the extension in the browser, but the panel is not showing yet.
2024-07-02 22:47:27 -04:00
Delaney c084402921
Targets #97 (#98) 2024-07-02 09:22:26 -07:00
Delaney Gillilan 94838262af fix reference page names 2024-06-29 07:49:55 -07:00
Delaney Gillilan 457c90204a add LICENSE 2024-06-29 07:38:18 -07:00
Delaney Gillilan 350ceb9585 update home page to show clear cookie warning 2024-06-27 08:45:50 -07:00
Delaney Gillilan be67208a72 fix store change 2024-06-27 08:25:59 -07:00
Delaney e98e951342
initial wxt commit (#95) 2024-06-26 18:02:26 -07:00
Delaney Gillilan 688d136740 Merge branch 'main' of ssh://github.com/delaneyj/datastar 2024-06-26 13:32:36 -07:00
Delaney Gillilan 0c9a00c2bf move back to v15
change cookie expiration to a day
2024-06-26 13:32:33 -07:00
Patrick Marchand 3b71ac7af9
inspector: last poke at chrome support 2024-06-26 15:41:52 -04:00
Patrick Marchand 1bcb4564f8
inspector: fix broken test page 2024-06-26 15:33:23 -04:00
Patrick Marchand 14c55a225f
inspector: get devtool to work across page changes
Also initial work on chrome compat
2024-06-26 13:52:55 -04:00
Patrick Marchand 2e7f28f88f
Merge branch 'main' of github.com:delaneyj/datastar into main-up 2024-06-26 10:30:38 -04:00
Patrick Marchand 61db33f779
fix typo in animation test name and reduce flakyness in bulkupdate test 2024-06-26 10:28:36 -04:00
Patrick Marchand 4a65bef0ed
Merge branch 'main-up' into inspector 2024-06-26 10:26:46 -04:00
Delaney Gillilan 496c94a3aa fix raf callbacks 2024-06-25 14:55:54 -07:00
Patrick Marchand a3af7bf07d
make it possible to load inspector extension in chrome
doesnt make it work though
2024-06-25 17:53:11 -04:00
Patrick Marchand d1e7d7ab18
Make inspector work in both the browser and the devtools 2024-06-21 18:01:17 -04:00
Patrick Marchand 8dce4ff728
Try to fix cyclic type error on certain events in inspector 2024-06-21 18:00:43 -04:00
Delaney Gillilan 9c315d7b47 move sse after session store 2024-06-20 06:42:10 -07:00
Delaney Gillilan 657fc04149 move stylesheet 2024-06-20 06:32:10 -07:00
Delaney Gillilan 3b2b54b479 cleanup and add essay 2024-06-19 19:51:52 -07:00
Delaney Gillilan 78c63320d5 remove autofocus 2024-06-19 19:11:53 -07:00
Delaney d30a0a9f64
Data store.offline (#75)
* fix #74 
* offline + sync

---------

Co-authored-by: Patrick Marchand <mail@patrickmarchand.com>
2024-06-19 12:21:59 -07:00
Delaney Gillilan 9b53eac285 homepage css fixes and proper links in reference
fix #69
2024-06-19 11:19:09 -07:00
Delaney Gillilan 2b0a8f05ec fix mobile viewport meta tag 2024-06-19 10:38:42 -07:00
Delaney Gillilan c3c69ff9f8 better mobile view 2024-06-18 17:25:47 -07:00
Delaney Gillilan 9622e659d8 have to bump because taskfile create wrong version 2024-06-18 13:09:47 -07:00
Delaney 440ee21dd6
Todo example for front page (#85)
* more styling
* move frontend packages to "packages"
* move large file out of static assets
* fix refs
* better mobile support
* add data-on-*.outside modifier

---------

Co-authored-by: Patrick Marchand <mail@patrickmarchand.com>
2024-06-18 13:04:21 -07:00
Delaney Gillilan 9cf9615bac bump version 2024-06-17 17:56:42 -07:00
Delaney Gillilan 3b22e2612a fix refs 2024-06-17 17:53:21 -07:00
Delaney Gillilan b4d011c9d3 up version to 0.15.2 2024-06-17 16:28:46 -07:00
Delaney 9c34156fda
support multiline expressions, fix #56 (#84) 2024-06-17 16:25:17 -07:00
Delaney 953396d4d5
fixes #73 data-ref should use signals (#83) 2024-06-17 10:42:08 -07:00
Patrick Marchand 12b0b69fe5
inspector: only add the panel if datastar is detected 2024-06-14 21:10:55 -04:00
Patrick Marchand 58222160bb
fix inspector not saving state 2024-06-14 20:16:38 -04:00
Patrick Marchand d64041fc5d
Upgrade to manifest v3 2024-06-14 20:15:44 -04:00
Patrick Marchand 8d2826365e
fix path of library package in Taskfile 2024-06-14 16:27:09 -04:00
Patrick Marchand 789ebb1f61
turn inspector into a devtool panel
still some bugs in regards to the initial events and the store
inspector not being updated. The event logs also persists across
page changes. The extension console complains that
theres a cyclic object. Probably doesnt work on chrome yet, I've
only tested on firefox.
2024-06-12 09:50:08 -04:00
Patrick Marchand 6153d6aff2
remove question marks from inspector switch inputs
kind of redundant
2024-06-09 21:10:16 -04:00
Patrick Marchand 27074e88cb
fix readme symlink 2024-06-09 21:08:32 -04:00
Delaney Gillilan 12bc908f79 move frontend packages to "packages" 2024-06-09 11:13:12 -07:00
Delaney Gillilan 11460ff360 more styling 2024-06-07 12:29:21 -07:00
Delaney Gillilan 14d70e7713 initial setup 2024-06-07 12:15:05 -07:00
1167 changed files with 54370 additions and 24885 deletions

View File

@ -1,36 +0,0 @@
# flyctl launch added from .gitignore
**/debug_bin*
**/gen
**/node_modules
# flyctl launch added from library/.gitignore
# Logs
library/**/logs
library/**/*.log
library/**/npm-debug.log*
library/**/yarn-debug.log*
library/**/yarn-error.log*
library/**/pnpm-debug.log*
library/**/lerna-debug.log*
library/**/node_modules
library/**/dist
library/**/dist-ssr
library/**/*.local
# Editor directories and files
library/**/stats.html
# flyctl launch added from library/node_modules/.pnpm/tailwindcss@3.3.3/node_modules/tailwindcss/stubs/.gitignore
!library/node_modules/.pnpm/tailwindcss@3.3.3/node_modules/tailwindcss/stubs/**/*
# flyctl launch added from library/node_modules/.pnpm/vite-plugin-webfont-dl@3.7.6_vite@4.4.5/node_modules/vite-plugin-webfont-dl/dist/.gitignore
library/node_modules/.pnpm/vite-plugin-webfont-dl@3.7.6_vite@4.4.5/node_modules/vite-plugin-webfont-dl/dist/**/*
!library/node_modules/.pnpm/vite-plugin-webfont-dl@3.7.6_vite@4.4.5/node_modules/vite-plugin-webfont-dl/dist/**/.gitignore
# flyctl launch added from node_modules/.pnpm/tailwindcss@3.3.3/node_modules/tailwindcss/stubs/.gitignore
!node_modules/.pnpm/tailwindcss@3.3.3/node_modules/tailwindcss/stubs/**/*
# flyctl launch added from webui/assetgen/css/node_modules/.pnpm/tailwindcss@3.3.2/node_modules/tailwindcss/stubs/.gitignore
!webui/assetgen/css/node_modules/.pnpm/tailwindcss@3.3.2/node_modules/tailwindcss/stubs/**/*
fly.toml

10
.gitattributes vendored
View File

@ -1,8 +1,2 @@
*.gif filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.blend* filter=lfs diff=lfs merge=lfs -text
*.hdr* filter=lfs diff=lfs merge=lfs -text
*.wav* filter=lfs diff=lfs merge=lfs -text
*.ttf* filter=lfs diff=lfs merge=lfs -text
bundles linguist-generated=true

1
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1 @@
* @delaneyj @bencroker

31
.github/ISSUE_TEMPLATE/bug-report.yaml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Bug Report
description: Create a bug report for Datastar.
labels:
- bug
body:
- type: markdown
attributes:
value: |
So you think youve discovered a bug in Datastar? To ensure this hasnt already been reported, please first search [existing issues](https://github.com/starfederation/datastar/issues?q=is%3Aissue) and ensure youre running the [latest release](https://github.com/starfederation/datastar/releases). The `#bug-report` channel in the [Discord server](https://discord.gg/bnRNgZjgPh) is also a great place to report bugs.
To rule out that this isnt a setup or configuration issue, please read the [guide](https://data-star.dev/guide) and the [reference](https://data-star.dev/reference/attribute_plugins) docs.
If you still believe youve found a bug, please provide a clear and concise description, including:
- What is happening and what you expected to happen.
- Steps to reproduce the issue.
- Screenshots, if applicable.
- type: textarea
id: body
attributes:
label: Bug Report
description: Please provide a clear and concise description of the bug.
validations:
required: true
- type: input
id: version
attributes:
label: Datastar Version
description: Provide the Datastar version that this relates to, ideally the [latest release](https://github.com/starfederation/datastar/releases).
placeholder: v1.0.0
validations:
required: true

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1 @@
blank_issues_enabled: false

View File

@ -0,0 +1,26 @@
name: Feature Request
description: Suggest a new feature for Datastar.
labels:
- enhancement
body:
- type: markdown
attributes:
value: |
So you have a feature request for Datastar? To ensure this isnt already on our radar, please first search [existing issues](https://github.com/starfederation/datastar/issues?q=is%3Aissue). The `#general` channel in the [Discord server](https://discord.gg/bnRNgZjgPh) is also a great place to suggest features.
If you still believe you have a new suggestion, please provide a clear and concise description, including:
- What problem you believe your feature request can solve.
- Any alternative solutions or features you have already considered.
- type: textarea
id: body
attributes:
label: Feature Request
description: Please provide a clear and concise suggestion for a feature.
validations:
required: true
- type: input
id: version
attributes:
label: Datastar Version
description: Provide the Datastar version that this relates to, ideally the [latest release](https://github.com/starfederation/datastar/releases).
placeholder: v1.0.0

View File

@ -0,0 +1,24 @@
name: Support Request
description: Ask a question about Datastar.
labels:
- question
body:
- type: markdown
attributes:
value: |
So you have a question about Datastar? To ensure your question hasnt already been answered, please first search [existing issues](https://github.com/starfederation/datastar/issues?q=is%3Aissue). The `#help` channel in the [Discord server](https://discord.gg/bnRNgZjgPh) is also a great place to ask questions.
If your question is still unanswered, please provide a clear and concise description. Note that we are diligent about documentation, so please check whether your question is answered in the [guide](https://data-star.dev/guide) or the [reference](https://data-star.dev/reference/attribute_plugins) docs before submitting.
- type: textarea
id: body
attributes:
label: Support Request
description: Please provide a clear and concise question.
validations:
required: true
- type: input
id: version
attributes:
label: Datastar Version
description: Provide the Datastar version that this relates to, ideally the [latest release](https://github.com/starfederation/datastar/releases).
placeholder: v1.0.0

View File

@ -0,0 +1,34 @@
name: Build Docker Images
on:
push:
branches: develop
paths:
- 'Dockerfile-dev'
- '.github/workflows/build-docker-images.yml'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}-dev
steps:
- name: Checkout the repository
uses: actions/checkout@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v4
with:
context: ./.github
file: ./Dockerfile-dev
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
build-args: |
ENVIRONMENT=development

29
.github/workflows/deploy-site.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Deploy Site
on:
push:
branches:
- main
workflow_dispatch:
jobs:
deploy:
name: Deploy app
if: github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[deploy-site]')
runs-on: ubuntu-latest
concurrency: deploy-group
steps:
- name: Checkout the repository
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Deploy to fly.io
uses: superfly/flyctl-actions/setup-flyctl@master
- run: |
docker container run --rm -t -v "${{ github.workspace }}":/app -v go-modules:/go/pkg/mod ghcr.io/starfederation/datastar-dev -c 'go tool task tools'
docker container run --rm -t -v "${{ github.workspace }}":/app -v go-modules:/go/pkg/mod ghcr.io/starfederation/datastar-dev -c 'go tool task support'
flyctl deploy --local-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

View File

@ -0,0 +1,23 @@
name: Enforce Branch Policy
on:
pull_request:
branches:
- main
push:
branches:
- main
workflow_dispatch:
jobs:
enforce-branch-policy:
runs-on: ubuntu-latest
steps:
- name: Enforce main branch pull request policy
if: github.event_name == 'pull_request' && github.ref == 'refs/heads/main'
run: |
echo "Pull requests to the main branch are not allowed."
exit 1
- name: Enforce main branch push policy
run: |
echo "Push events to the main branch are allowed."
exit 0

45
.github/workflows/sdk-dotnet-nuget.yml vendored Normal file
View File

@ -0,0 +1,45 @@
name: Build & Publish NuGet to GitHub Registry
on:
workflow_dispatch:
env:
NuGetDirectory: ${{ github.workspace }}/nuget
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Build and Pack NuGet package with versioning
run: dotnet pack sdk/dotnet/src/Datastar.fsproj --configuration Release --output ${{ env.NuGetDirectory }}
- name: Upload NuGet package to GitHub
uses: actions/upload-artifact@v4
with:
name: nugetPackage
path: ${{ env.NuGetDirectory }}/*.nupkg
release:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download nuget package artifact
uses: actions/download-artifact@v4
with:
name: nugetPackage
path: nugetPackage
- name: Publish to NuGet.org
run: dotnet nuget push nugetPackage/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate

30
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: Run Tests
on:
push:
branches:
- develop
paths:
- 'bundles/*.js'
- 'library/src/**/*.ts'
- 'site/smoketests/*.go'
- 'site/static/md/tests/*.md'
- '.github/workflows/tests.yml'
pull_request:
workflow_dispatch:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run CI tests
run: |
docker container run --rm -t -v "${{ github.workspace }}":/app -v go-modules:/go/pkg/mod ghcr.io/starfederation/datastar-dev -c 'go tool task tools'
docker container run --rm -t -v "${{ github.workspace }}":/app -v go-modules:/go/pkg/mod ghcr.io/starfederation/datastar-dev -c 'go tool task test'

21
.gitignore vendored
View File

@ -1,6 +1,17 @@
debug_bin*
node_modules
site_bin
tailwindcli
datastar_site
data
.task
*_templ.go
.idea
.DS_Store
node_modules
datastar-website
*_bin
*.qtpl.go
*/java/*/target/
*.pyc
__pycache__
__debug_bin*
# search index
/data-star.bleve

7
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"recommendations": [
"jdinabox.quicktemplate-vscode",
"golang.go",
"a-h.templ"
]
}

10
.vscode/launch.json vendored
View File

@ -9,14 +9,16 @@
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/backends/go/cmd/site/main.go"
"program": "${workspaceFolder}/site/cmd/site/main.go",
"preLaunchTask": "build datastar"
},
{
"name": "Go test example",
"name": "Build Library",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/backends/example/go/main.go"
"program": "${workspaceFolder}/build/cmd/build/main.go",
"cwd": "${workspaceFolder}"
}
]
}
}

30
.vscode/settings.json vendored
View File

@ -1,12 +1,20 @@
{
"cSpell.words": [
"datastar",
"HTMX",
"hyperscript",
"idiomorph",
"Neato",
"sudodevnull",
"TLDR",
"Websockets"
]
}
"go.testTimeout": "200s",
"go.coverOnSingleTestFile": true,
"go.coverOnSingleTest": true,
"editor.foldingStrategy": "indentation",
"makefile.configureOnOpen": false,
"editor.formatOnSave": true,
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[html]": {
"editor.formatOnSave": false
},
"[markdown]": {
"editor.formatOnSave": false
}
}

13
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,13 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "build datastar",
"command": "task",
"args": [
"support"
]
}
]
}

38
BUILDING.md Normal file
View File

@ -0,0 +1,38 @@
# Building Datastar using Docker
Datastar comes with a development environment for developing Datastar via a Docker container.
It takes care of the setup listed here for you in a Dockerized environment, which allows you to get it up and running quickly & easily.
See [DOCKER.md](DOCKER.md) for detailed instructions on using it.
# Building Datastar Natively
To run the examples website you will need the following:
- [Go](https://go.dev/)
- [Taskfile](https://taskfile.dev/)
To publish the library or if you're using a BSD operating system, you will also need:
- [pnpm](https://pnpm.io/)
- [Node and npm](https://nodejs.org/)
`task tools` will install all required tools
`task build` will build the library as well as sdk constant templates
The compiled files can be found in `./bundles`
Finally, `task` will build the library and serve the reference documentation website.
The website should be available on http://localhost:8080 with hot-reloading enabled.
## End to end tests
Once you have the website running, you should be able to run the
[rod](https://go-rod.github.io) tests.
```
$ task test
```

23
CHANGELOG.md Normal file
View File

@ -0,0 +1,23 @@
# Release Notes for Datastar
Each tagged version of Datastar is accompanied by a release note. Read the [release notes »](https://github.com/starfederation/datastar/releases)
# WIP Release Notes
## v1.0.0-beta.11
### Added
- Added the `__debounce`, `__throttle` and `__viewtransition` modifiers to `data-on-intersect`.
- Added the `__debounce`, `__throttle` and `__viewtransition` modifiers to `data-on-signal-change`.
- Added the `__viewtransition` modifier to `data-on-interval`.
- Added the `__viewtransition` modifier to `data-on-load`.
- Added the `__viewtransition` modifier to `data-on-raf`.
### Changed
- The `datastar-sse` event is now dispatched on the `document` element, and using `data-on-datastar-sse` automatically listens for the event on the `document` ([#802](https://github.com/starfederation/datastar/issues/802)).
- The `data-on-signals-change-*` attribute key now accepts a path in which `*` matches a single path segment and `**` matches multiple path segments (`data-on-signals-change-foo.*.baz`, `data-on-signals-change-foo.**`).
- The `data-persist` attribute now accepts one or more space-separated paths in which `*` matches a single path segment and `**` matches multiple path segments (`data-persist="foo.*.baz"`, `data-persist="foo.**"`).
- The `@setAll` action now accepts one or more space-separated paths in which `*` matches a single path segment and `**` matches multiple path segments (`@setAll('foo.*.baz', true)`, `@setAll('foo.**', true)`) ([#793](https://github.com/starfederation/datastar/issues/793)).
- The `@toggleAll` action now accepts one or more space-separated paths in which `*` matches a single path segment and `**` matches multiple path segments (`@toggleAll('foo.*.baz')`, `@toggleAll('foo.**')`) ([#793](https://github.com/starfederation/datastar/issues/793)).

39
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,39 @@
# Contributing to Datastar
Thanks for thinking about contributing to Datastar 🚀
## Before You Contribute
Before you contribute, please consider that Datastar is a lightweight JavaScript framework that aims to simplify reactive web apps by using a minimalist, attribute-based approach for state management and event handling directly in HTML.
Anything outside of this scope may not be accepted. If you have a need for a feature that is not within the scope of Datastar, consider using a Web Component or writing your own Datastar plugin.
## Bug Reports & Feature Requests
Before submitting bug reports and feature requests, please search the [open issues](https://github.com/starfederation/datastar/issues) and the _#help_ channel in the [Discord server](https://discord.gg/bnRNgZjgPh) to see if it has already been addressed. When submitting a [new issue](https://github.com/starfederation/datastar/issues/new), please use a descriptive title and include a clear description and as much relevant information as possible.
## Pull Requests
Always open an issue to discuss your idea _before_ submitting a pull request. Pull requests must be made to the `develop` branch, have a descriptive title and clearly describe the problem and solution. If the pull request adds or changes behavior, documentation and examples should be updated accordingly.
## Documentation
Datastars documentation is written in markdown files that live in [this folder](https://github.com/starfederation/datastar/tree/develop/site/static/md). Improvements to them can be submitted via pull requests.
## SDKs
We are currently only accepting SDKs from people willing to contribute _and_ maintain them.
SDKs must follow the [Architecture Decision Record](https://github.com/starfederation/datastar/blob/develop/sdk/README.md). Pull requests for new SDKs must also include the following (use alphabetical order, where appropriate):
- A README file that explains how to use the SDK.
- An entry in the [SDKs reference guide](https://github.com/starfederation/datastar/blob/develop/site/static/md/reference/sdks.md).
- A value in `SDKLanguages` in [`consts.go`](https://github.com/starfederation/datastar/blob/develop/build/consts.go).
- A `consts_[language].qtpl` file for generating [constants and defaults](https://github.com/starfederation/datastar/blob/develop/build).
- Sample [code snippets](https://github.com/starfederation/datastar/tree/develop/site/static/code_snippets) in the language of your SDK.
- An implementation of each of the [examples](https://github.com/starfederation/datastar/tree/develop/examples).
- Template values for consts and examples in [`run.go`](https://github.com/starfederation/datastar/blob/develop/build/run.go).
## Building
Datastar comes with instructions for building, either manually or via Docker. Read the [Building Guidelines »](BUILDING.md)

60
DOCKER.md Normal file
View File

@ -0,0 +1,60 @@
# Building Datastar using Docker
Datastar comes with a development environment for developing Datastar via a Docker container.
It takes care of the setup listed in the for you in a Dockerized environment, which allows you to get it up and running quickly & easily.
The only requirement is that you have [Docker](https://www.docker.com/products/docker-desktop) installed (you do not need `golang`, `tmpl`, `npm`, `pnpm` or any other project dependencies installed locally).
## Why Docker?
Developers who have adopted [Docker](https://www.docker.com/) for a containerized approach to development are used to not having to install a matching development infrastructure each time they approach a project.
This allows you to "shrink-wrap" the devops needed to run a project in a container, which will run anywhere, on any machine, without having to do any meticulous setup.
It also allows you to easily swap between basic things like Go versions, without affecting your local computer.
## Quick Start
In terminal, `cd` to the `datastar/` directory, and then type:
```
make dev
```
The first time you run this command, it may take a bit of time to build the Docker image, and download all of the appropriate packages, and cache them locally.
Then just navigate to `http://localhost:8080` in your browser, and Datastar site from `site` will be up and running.
You can freely make changes to the `library` Datastar codebase, and the changes will be rebuilt and reload automatically.
You can also make changes to the `site` Datastar website backend, and the backend will be rebuilt and reload automatically.
## Using Datastar Docker Dev
Datastar Docker Dev uses the venerable `make` command to automate setup and access to the Docker containers used.
It uses `make` because it's available pre-installed on any development machine.
See the [Using Make & Makefiles to Automate your Frontend Workflow](https://nystudio107.com/blog/using-make-makefiles-to-automate-your-frontend-workflow) article for more on `make`.
The make tool is available for just about every platform you can imagine, and is installed with the [XCode CLI Tools](https://www.embarcadero.com/starthere/xe5/mobdevsetup/ios/en/installing_the_commandline_tools.html) on the Mac, and [WSL2](https://docs.microsoft.com/en-us/windows/wsl/install-win10) on Windows. Probably you have these installed already if youre doing development.
Below are details and options available in each of the provided `make` commands:
* `make dev` - starts up the Go website server for the backend with hot reloading as you make changes
* `make test` - run the project tests inside the Docker container
* `make task xxx` - runs the specified task from the `Taskfile.yml` inside of the Docker container
* `make ssh` - gives you a shell inside of the Docker container
* `make image-build` - rebuilds the Docker image from scratch (you will probably never need this)
* `make clean` - removes all build artifacts, including the Docker image & volumes, to start from scratch
### CLI Arguments
You can pass in optional CLI arguments to override the default settings Datastar dev uses:
* `TAG=` (default is defined in `Dockerfile-dev`) - allows you to specify the official [golang Docker image](https://hub.docker.com/_/golang) tag that should be used. Using this, you can change the version of Go the container runs, e.g.: `make image-build TAG="1.24"` will use the latest patch version of Go 1.24 official Docker image.
### Terminating
To terminate the `datastar-dev` Docker container, enter `Control-C` in the terminal.

View File

@ -1,16 +1,17 @@
FROM docker.io/golang:1.22.1-alpine AS build
FROM docker.io/golang:1.24.2-alpine AS build
RUN apk add --no-cache upx
ENV PORT=8080
WORKDIR /src
COPY go.* *.go ./
COPY . .
RUN go mod download
COPY backends/go/. ./backends/go/
COPY site ./site
RUN --mount=type=cache,target=/root/.cache/go-build \
go build -o /out/site backends/go/cmd/site/main.go
RUN upx /out/site
go build -ldflags="-s" -o /out/site site/cmd/site/main.go
RUN upx -9 -k /out/site
FROM scratch
FROM alpine
RUN chmod a=rwx,u+t /tmp
COPY --from=build /out/site /
ENTRYPOINT ["/site"]

48
Dockerfile-dev Normal file
View File

@ -0,0 +1,48 @@
ARG TAG=1.24
FROM golang:$TAG
WORKDIR /app
# Install packages
RUN apt update && sudo apt upgrade \
&& \
set -eux; \
# Packages to install
apt install -y \
git \
jq \
rsync \
nodejs \
npm \
# Needed for headless chrome/tests
libglib2.0-dev \
libnss3-dev \
libdbus-1-dev \
libatk1.0-0 \
libatk-bridge2.0-0 \
libcups2 \
libxcomposite-dev \
libxdamage1 \
libxrandr2 \
libgbm-dev \
libxkbcommon-x11-0 \
libpangocairo-1.0-0 \
libasound2 \
&& \
# Clean out directories that don't need to be part of the image
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& \
# Install node packages \
npm install -g npm@^10.0.0 \
npm install -g pnpm \
&& \
# Install flyctl cli \
curl -L https://fly.io/install.sh | sh \
&& \
ln -s /root/.fly/bin/flyctl /usr/local/bin/fly \
&& \
# Make this a safe .git directory
git config --global --add safe.directory /app
ENTRYPOINT ["/bin/sh"]

19
LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) Delaney Gillilan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

41
Makefile Normal file
View File

@ -0,0 +1,41 @@
TAG?=1.24
CONTAINER?=$(shell basename $(CURDIR))-dev
DEV_PORT?=8080
IMAGE_INFO=$(shell docker image inspect $(CONTAINER):$(TAG))
IMAGE_NAME=${CONTAINER}:${TAG}
DOCKER_RUN=docker container run --rm -it -v "${CURDIR}":/app -v go-modules:/go/pkg/mod
ARCH=$(shell uname -m)
.PHONY: build clean dev image-build task test ssh
# Perform a dist build
build: image-check
${DOCKER_RUN} --name ${CONTAINER}-$@ ${IMAGE_NAME} build
# Clean up all build artifacts to start from scratch
clean:
docker image rm ${IMAGE_NAME}
docker volume rm go-modules
# Run the development server
dev: --image-check
${DOCKER_RUN} --name ${CONTAINER}-$@ -e DEV_PORT="${DEV_PORT}" -p ${DEV_PORT}:${DEV_PORT} ${IMAGE_NAME} -c 'go tool task -w'
# Build the Docker image
image-build:
docker build -f Dockerfile-dev . -t ${IMAGE_NAME} --build-arg TAG=${TAG} --no-cache
${DOCKER_RUN} --name ${CONTAINER}-$@ ${IMAGE_NAME} -c 'go tool task tools'
# Run the passed in task command
task: --image-check
${DOCKER_RUN} --name ${CONTAINER}-$@ -e DEV_PORT="${DEV_PORT}" -p ${DEV_PORT}:${DEV_PORT} ${IMAGE_NAME} -c 'go tool task $(filter-out $@,$(MAKECMDGOALS)) $(MAKEFLAGS)'
# Run the test suite
test: --image-check
${DOCKER_RUN} --name ${CONTAINER}-$@ -e DEV_PORT="${DEV_PORT}" -p ${DEV_PORT}:${DEV_PORT} ${IMAGE_NAME} -c 'go tool task test'
# Open a shell inside of the container
ssh: --image-check
${DOCKER_RUN} --name ${CONTAINER}-$@ --entrypoint=/bin/sh ${IMAGE_NAME}
# Ensure the image has been created
--image-check:
ifeq ($(IMAGE_INFO), [])
--image-check: image-build
endif
%:
@:
# ref: https://stackoverflow.com/questions/6273608/how-to-pass-argument-to-makefile-from-command-line

View File

@ -1 +0,0 @@
library/README.md

62
README.md Normal file
View File

@ -0,0 +1,62 @@
[![Version](https://img.shields.io/github/package-json/v/starfederation/datastar?filename=library/package.json)](https://github.com/starfederation/datastar/releases)
[![License](https://img.shields.io/github/license/starfederation/datastar)](https://github.com/starfederation/datastar/blob/main/LICENSE)
[![Stars](https://img.shields.io/github/stars/starfederation/datastar?style=flat)](https://github.com/starfederation/datastar/stargazers)
<p align="center"><img width="200" src="https://data-star.dev/static/images/rocket.webp"></p>
# Datastar
### The hypermedia framework.
Datastar helps you build reactive web applications with the simplicity of server-side rendering and the power of a full-stack SPA framework.
Getting started is as easy as adding a single 14.5 KiB script tag to your HTML.
```html
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.11/bundles/datastar.js"></script>
```
Then start adding frontend reactivity using declarative <code>data-*</code> attributes.
```html
<input data-bind-title />
<div data-text="$title.toUpperCase()"></div>
<button data-on-click="@post('/endpoint')">Save</button>
```
Visit the [Datastar Website »](https://data-star.dev/)
Watch the [Videos »](https://www.youtube.com/@data-star)
Join the [Discord Server »](https://discord.com/invite/bnRNgZjgPh)
## Getting Started
Read the [Getting Started Guide »](https://data-star.dev/guide/getting_started)
## Contributing
Read the [Contribution Guidelines »](https://github.com/starfederation/datastar/blob/develop/CONTRIBUTING.md)
## Custom Plugins
You can manually add your own plugins to the core:
```html
<script type="importmap">
{
"imports": {
"datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.11/bundles/datastar.js"
}
}
</script>
<script type="module">
import { load } from 'datastar'
load(
// Look ma, I made a plugin!
)
</script>
```
[![Star History Chart](https://api.star-history.com/svg?repos=starfederation/datastar&type=Date)](https://www.star-history.com/#starfederation/datastar&Date)

View File

@ -2,120 +2,203 @@
version: "3"
interval: 100ms
interval: 1000ms
vars:
NAME: "site"
BIN_NAME: "{{.NAME}}_bin"
VERSION:
sh: cat library/package.json| jq -r .version
sh: cat VERSION
tasks:
tools:
platforms:
[
windows,
linux,
darwin/arm64,
darwin/amd64,
openbsd,
dragonfly,
freebsd,
netbsd,
]
cmds:
- go install github.com/a-h/templ/cmd/templ@latest
- go install github.com/go-task/task/v3/cmd/task@latest
- platforms: [linux/amd64]
cmd: test -f site/tailwindcli || wget -O site/tailwindcli https://github.com/dobicinaitis/tailwind-cli-extra/releases/download/v1.7.21/tailwindcss-extra-linux-x64
- platforms: [linux/arm64]
cmd: test -f site/tailwindcli || wget -O site/tailwindcli https://github.com/dobicinaitis/tailwind-cli-extra/releases/download/v1.7.21/tailwindcss-extra-linux-arm64
- platforms: [darwin/arm64]
cmd: test -f site/tailwindcli || wget -O site/tailwindcli https://github.com/dobicinaitis/tailwind-cli-extra/releases/download/v1.7.21/tailwindcss-extra-macos-arm64
- platforms: [darwin/amd64]
cmd: test -f site/tailwindcli || wget -O site/tailwindcli https://github.com/dobicinaitis/tailwind-cli-extra/releases/download/v1.7.21/tailwindcss-extra-macos-x64
- platforms: [windows]
cmd: test -f site/tailwindcli || wget -O site/tailwindcli https://github.com/dobicinaitis/tailwind-cli-extra/releases/download/v1.7.21/tailwindcss-extra-windows-x64.exe
- platforms: [openbsd, dragonfly, freebsd, netbsd]
cmd: pnpm add tailwindcss @tailwindcss/container-queries @tailwindcss/typography daisyui
- platforms: [openbsd, dragonfly, freebsd, netbsd]
cmd: test -f site/tailwindcli || (echo "#!/bin/sh" > site/tailwindcli && echo "tailwindcss $@" >> site/tailwindcli)
- chmod +x site/tailwindcli
version:
cmds:
- echo {{.VERSION}}
libpub:
dir: ./library
qtc:
sources:
- "**/*.qtpl"
generates:
- "**/*.qtpl.go"
cmds:
- go tool qtc
build:
deps:
- qtc
sources:
- VERSION
- "**/*.qtpl"
- "**/package.json"
- "**/*.ts"
generates:
- "bundles/**/*"
cmds:
- go run build/cmd/build/main.go
- cp -r bundles/* site/static/js/
- mkdir -p library/dist/
- cp -r bundles/* library/dist/
- mkdir -p site/static/librarySource
- rm -rf site/static/librarySource/*
- cp -r library/src/* site/static/librarySource/
library:
dir: library
requires:
vars: [VERSION]
sources:
- "**/*.ts"
- "**/*.js"
- "**/*.json"
generates:
- "dist/**/*"
cmds:
- pnpm i
- pnpm build
libpub:
dir: library
requires:
vars: [VERSION]
deps:
- build
- library
cmds:
- git push origin
- git tag v{{.VERSION}}
- git push origin --tags
- npm publish --access public
- git push --tags
- GOPROXY=proxy.golang.org go list -m github.com/delaneyj/datastar@v{{.VERSION}}
- curl https://purge.jsdelivr.net/gh/starfederation/datastar/bundles/datastar.js
- git push origin --tags
- GOPROXY=proxy.golang.org go list -m github.com/starfederation/datastar@v{{.VERSION}}
- task: deploy
library:
vars:
BACKEND_STATIC_DIR: "../backends/go/{{.NAME}}/static/library"
dir: library
generates:
- "dist/**/*"
sources:
- "src/**/*.ts"
- "package.json"
sdktspub:
dir: sdk/typescript
requires:
vars: [VERSION]
cmds:
# - echo "{{.BACKEND_STATIC_DIR}}"
- pnpm i
# - pnpm vitest --watch=false
- pnpm prettier -w .
- pnpm build
- rsync -av dist/ {{.BACKEND_STATIC_DIR}}
- rsync -av package.json {{.BACKEND_STATIC_DIR}}
- git push origin
- git tag sdktsv{{.VERSION}}
- git push origin --tags
- deno run -A build.ts {{.VERSION}}
- cd npm && npm publish --access public
- curl https://purge.jsdelivr.net/gh/starfederation/datastar/sdk/typescript/npm/esm/web/serverSentEventGenerator.js
- curl https://purge.jsdelivr.net/gh/starfederation/datastar/sdk/typescript/npm/esm/abstractServerSentEventGenerator.js
- curl https://purge.jsdelivr.net/gh/starfederation/datastar/sdk/typescript/npm/esm/node/serverSentEventGenerator.js
- git push origin --tags
css:
dir: backends/go/site/css
generates:
- "../static/css/site.css"
sources:
- "../**/*.md"
# - "../**/*.go"
- "../**/*.templ"
idiomorph:
dir: library/src/vendored
cmds:
- pnpm tailwindcss build -o ../static/css/site.css
- wget -O idiomorph.esm.js https://raw.githubusercontent.com/bigskysoftware/idiomorph/refs/heads/main/dist/idiomorph.esm.js
- npx -p typescript tsc *.js --declaration --allowJs --emitDeclarationOnly --outDir .
css:
dir: site
sources:
- "**/*.templ"
- "**/*.md"
- "**/*.go"
generates:
- "static/css/site.css"
cmds:
- ./tailwindcli build -i src/css/site.css -o static/css/site.css
templ:
env:
TEMPL_EXPERIMENT: rawgo
# deps:
# - library
generates:
- "**/*_templ.go"
sources:
- "**/*.templ"
cmds:
- templ generate .
- go tool templ generate .
kill:
method: none
cmds:
- killall -q {{.BIN_NAME}} || echo "Process was not running."
- fuser -k 8080/tcp > /dev/null 2>&1 || true
tests:
dir: playwright
cmds:
- pnpm i
- pnpm playwright
hot:
desc: Server hot reload
dir: backends/go
env:
ENV: dev
support:
sources:
- "**/*.templ"
- "**/*.go"
- "**/*.md"
- "{{.NAME}}/static/**/*"
- site/static/**/*
generates:
- ./datastar-website
deps:
- library
- kill
- build
- templ
# - css
- css
site:
method: none
desc: build and run site
deps:
- support
cmds:
- go mod tidy
- go build -o ./{{.BIN_NAME}} cmd/{{.NAME}}/main.go
- ./{{.BIN_NAME}}
test:
dir: playwright
cmds:
- curl -o - -I http://localhost:8080
- pnpm i
- pnpm playwright install
- pnpm playwright test --ui
- go build -o ./datastar-website "site/cmd/site/main.go"
deploy:
method: none
deps:
- library
- support
cmds:
- fly deploy --local-only
default:
test:
deps:
- hot
silent: true
- support
cmds:
- go test -v github.com/starfederation/datastar/site/smoketests -run '^TestUnit' -count=1 -timeout=1m
test-all:
deps:
- support
cmds:
- go test -v github.com/starfederation/datastar/site/smoketests -count=1 -timeout=1m
default:
cmds:
- task: site
- ./datastar-website

1
VERSION Normal file
View File

@ -0,0 +1 @@
1.0.0-beta.11

View File

@ -1 +0,0 @@
static/library/*

View File

@ -1 +0,0 @@
static/library

View File

@ -1,5 +0,0 @@
{
"semi": false,
"singleQuote": true,
"tabWidth": 2
}

View File

@ -1,25 +0,0 @@
{
"name": "datastar-css",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^10.4.19",
"daisyui": "^4.11.1",
"postcss": "^8.4.38",
"prettier": "^3.3.0",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.3",
"vite": "^5.2.12"
},
"dependencies": {
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/typography": "^0.5.13"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
package site
import "github.com/goccy/go-json"
func UnmarshalPackageJSON(data []byte) (PackageJSON, error) {
var r PackageJSON
err := json.Unmarshal(data, &r)
return r, err
}
func (r *PackageJSON) Marshal() ([]byte, error) {
return json.Marshal(r)
}
type PackageJSON struct {
Name string `json:"name"`
Version string `json:"version"`
Type string `json:"type"`
Repository string `json:"repository"`
Files []string `json:"files"`
Private bool `json:"private"`
Main string `json:"main"`
Module string `json:"module"`
Types string `json:"types"`
DevDependencies map[string]string
Dependencies map[string]string
}
var packageJSON PackageJSON

View File

@ -1,155 +0,0 @@
package site
import (
"bytes"
"context"
"embed"
"errors"
"fmt"
"io"
"net/http"
"github.com/a-h/templ"
"github.com/alecthomas/chroma"
"github.com/alecthomas/chroma/formatters/html"
"github.com/alecthomas/chroma/lexers"
"github.com/alecthomas/chroma/styles"
"github.com/benbjohnson/hashfs"
"github.com/delaneyj/toolbelt"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/gomarkdown/markdown/ast"
mdhtml "github.com/gomarkdown/markdown/html"
)
//go:embed static/*
var staticFS embed.FS
var (
staticSys = hashfs.NewFS(staticFS)
highlightCSS templ.Component
mdRenderer func() *mdhtml.Renderer
)
func staticPath(path string) string {
return "/" + staticSys.HashName("static/"+path)
}
func RunBlocking(port int) toolbelt.CtxErrFunc {
upsertIIfeBuildSize()
return func(ctx context.Context) error {
b, err := staticFS.ReadFile("static/library/package.json")
if err != nil {
return fmt.Errorf("error reading package.json: %w", err)
}
packageJSON, err = UnmarshalPackageJSON(b)
if err != nil {
return fmt.Errorf("error unmarshaling package.json: %w", err)
}
router := chi.NewRouter()
router.Use(
middleware.Logger,
middleware.Recoverer,
// toolbelt.CompressMiddleware(),
)
setupRoutes(router)
srv := &http.Server{
Addr: fmt.Sprintf(":%d", port),
Handler: router,
}
go func() {
<-ctx.Done()
srv.Shutdown(context.Background())
}()
return srv.ListenAndServe()
}
}
func setupRoutes(router chi.Router) error {
defer router.Handle("/static/*", hashfs.FileServer(staticSys))
// defer router.Get("/hotreload", func(w http.ResponseWriter, r *http.Request) {
// sse := datastar.NewSSE(w, r)
// <-r.Context().Done()
// sse.Send("reload", datastar.WithSSERetry(250))
// })
htmlFormatter := html.New(html.WithClasses(true), html.TabWidth(2))
if htmlFormatter == nil {
return fmt.Errorf("couldn't create html formatter")
}
styleName := "nord"
highlightStyle := styles.Get(styleName)
if highlightStyle == nil {
return fmt.Errorf("couldn't find style %s", styleName)
}
highlightCSSBuffer := &bytes.Buffer{}
if err := htmlFormatter.WriteCSS(highlightCSSBuffer, highlightStyle); err != nil {
return fmt.Errorf("error writing highlight css: %w", err)
}
highlightCSS = templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
_, err := io.WriteString(w, fmt.Sprintf(`<style>%s</style>`, highlightCSSBuffer.String()))
return err
})
mdRenderer = func() *mdhtml.Renderer {
return mdhtml.NewRenderer(mdhtml.RendererOptions{
Flags: mdhtml.CommonFlags | mdhtml.HrefTargetBlank,
RenderNodeHook: func(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
// based on https://github.com/alecthomas/chroma/blob/master/quick/quick.go
htmlHighlight := func(w io.Writer, source, lang, defaultLang string) error {
if lang == "" {
lang = defaultLang
}
l := lexers.Get(lang)
if l == nil {
l = lexers.Analyse(source)
}
if l == nil {
l = lexers.Fallback
}
l = chroma.Coalesce(l)
it, err := l.Tokenise(nil, source)
if err != nil {
return err
}
return htmlFormatter.Format(w, highlightStyle, it)
}
renderCode := func(w io.Writer, codeBlock *ast.CodeBlock) {
defaultLang := ""
lang := string(codeBlock.Info)
htmlHighlight(w, string(codeBlock.Literal), lang, defaultLang)
}
if code, ok := node.(*ast.CodeBlock); ok {
renderCode(w, code)
return ast.GoToNext, true
}
return ast.GoToNext, false
},
})
}
if err := errors.Join(
setupHome(router),
setupGuide(router),
setupReferenceRoutes(router),
setupExamples(router),
setupEssays(router),
); err != nil {
return fmt.Errorf("error setting up routes: %w", err)
}
return nil
}

View File

@ -1,339 +0,0 @@
package site
import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/a-h/templ"
"github.com/go-chi/chi/v5"
"github.com/go-sanitize/sanitize"
"github.com/gorilla/sessions"
"github.com/samber/lo"
)
var (
sanitizer *sanitize.Sanitizer
)
func setupExamples(router chi.Router) (err error) {
mdElementRenderers, _, err := markdownRenders("examples")
if err != nil {
return err
}
sanitizer, err = sanitize.New()
if err != nil {
return fmt.Errorf("error creating sanitizer: %w", err)
}
sidebarGroups := []*SidebarGroup{
{
Label: "Ported HTMX Examples",
Links: []*SidebarLink{
{ID: "click_to_edit"},
{ID: "bulk_update"},
{ID: "click_to_load"},
{ID: "delete_row"},
{ID: "edit_row"},
{ID: "lazy_load"},
{ID: "fetch_indicator"},
{ID: "inline_validation"},
{ID: "infinite_scroll"},
{ID: "active_search"},
{ID: "progress_bar"},
{ID: "value_select"},
{ID: "animations"},
{ID: "file_upload"},
{ID: "dialogs_browser"},
{ID: "lazy_tabs"},
},
},
{
Label: "Web Components Examples",
Links: []*SidebarLink{
{ID: "shoelace_kitchensink"},
},
},
{
Label: "Reactive Examples",
Links: []*SidebarLink{
{ID: "multiline_fragments"},
{ID: "scroll_into_view"},
{ID: "on_load"},
{ID: "model_binding"},
{ID: "disable_button"},
{ID: "merge_options"},
{ID: "redirects"},
{ID: "view_transition_api"},
{ID: "title_update_backend"},
{ID: "store_changed"},
{ID: "raf_update"},
{ID: "update_store"},
},
},
{
Label: "Backend Examples",
Links: []*SidebarLink{
{ID: "node"},
{ID: "python"},
{ID: "quick_primer_go"},
{ID: "templ_counter"},
},
},
}
lo.ForEach(sidebarGroups, func(group *SidebarGroup, grpIdx int) {
lo.ForEach(group.Links, func(link *SidebarLink, linkIdx int) {
link.URL = templ.SafeURL("/examples/" + link.ID)
link.Label = strings.ToUpper(strings.ReplaceAll(link.ID, "_", " "))
if linkIdx > 0 {
link.Prev = group.Links[linkIdx-1]
} else if grpIdx > 0 {
prvGrp := sidebarGroups[grpIdx-1]
link.Prev = prvGrp.Links[len(prvGrp.Links)-1]
}
if linkIdx < len(group.Links)-1 {
link.Next = group.Links[linkIdx+1]
} else if grpIdx < len(sidebarGroups)-1 {
nxtGrp := sidebarGroups[grpIdx+1]
link.Next = nxtGrp.Links[0]
}
})
})
router.Route("/examples", func(examplesRouter chi.Router) {
examplesRouter.Get("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, string(sidebarGroups[0].Links[0].URL), http.StatusFound)
})
examplesRouter.Get("/{name}", func(w http.ResponseWriter, r *http.Request) {
name := chi.URLParam(r, "name")
contents, ok := mdElementRenderers[name]
if !ok {
http.Error(w, "not found", http.StatusNotFound)
return
}
var currentLink *SidebarLink
for _, group := range sidebarGroups {
for _, link := range group.Links {
if link.ID == name {
currentLink = link
break
}
}
}
SidebarPage(r, sidebarGroups, currentLink, contents).Render(r.Context(), w)
})
// mdElementRenderers, _, err := markdownRenders("examples")
// if err != nil {
// return err
// }
// type Example struct {
// URL string
// Label string
// Description string
// Prev, Next *Example
// }
// type ExampleGroup struct {
// Label string
// Examples []*Example
// }
// var (
// prevExample *Example
// examplesByURL = map[string]*Example{}
// )
// examples := lo.Map([]ExampleGroup{
// {
// Label: "Ported HTMX Examples",
// Examples: []*Example{
// {Label: "Click to Edit", Description: "inline editing of a data object"},
// {Label: "Bulk Update", Description: "bulk updating of multiple rows of data"},
// {Label: "Click to Load", Description: "loading data on demand"},
// {Label: "Delete Row", Description: "row deletion in a table"},
// {Label: "Edit Row", Description: "how to edit rows in a table"},
// {Label: "Lazy Load", Description: "how to lazy load content"},
// {Label: "Fetch Indicator", Description: "show a loading indicator when fetching data"},
// {Label: "Inline Validation", Description: "how to do inline field validation"},
// {Label: "Infinite Scroll", Description: "infinite scrolling of a page"},
// {Label: "Active Search", Description: "the active search box pattern"},
// {Label: "Progress Bar", Description: "a job-runner like progress bar"},
// {Label: "Value Select", Description: "making the values of a select dependent on another select"},
// {Label: "Animations", Description: "various animation techniques"},
// {Label: "File Upload", Description: "how to upload a file via ajax with a progress bar"},
// {Label: "Dialogs Browser", Description: "the prompt and confirm dialogs"},
// {Label: "Lazy Tabs", Description: "how to lazy load tabs"},
// },
// },
// {
// Label: "Web Components Examples",
// Examples: []*Example{
// {Label: "Shoelace Kitchensink", Description: "the Shoelace Web Components library"},
// },
// },
// {
// Label: "Reactive Examples",
// Examples: []*Example{
// {Label: "Multiline Fragments", Description: "multiline fragments"},
// {Label: "Scroll Into View", Description: "scrolling an element into view"},
// {Label: "On Load", Description: "how to load data on page load"},
// {Label: "Model Binding", Description: "two-way data binding to signals"},
// {Label: "Disable Button", Description: "how to disable a button while processing"},
// {Label: "Merge Options", Description: "how to merge options in a select"},
// {Label: "Redirects", Description: "how to redirect to another page"},
// {Label: "View Transition API", Description: "using the view transition API"},
// {Label: "Title Update Backend", Description: "target a specific element for updates"},
// {Label: "Store Changed", Description: "detect when a store has changed"},
// {Label: "RAF Update", Description: "update a signal on requestAnimationFrame"},
// {Label: "Update Store", Description: "update a store from an SSE event"},
// },
// },
// {
// Label: "Backend Examples",
// Examples: []*Example{
// {Label: "Node", Description: "example backend in node"},
// {Label: "Python", Description: "example backend in python"},
// {Label: "Quick Primer Go", Description: "The getting started guide in Go"},
// {Label: "Templ Counter", Description: "a simple counter example for Templ"},
// },
// },
// }, func(g ExampleGroup, i int) ExampleGroup {
// for j, example := range g.Examples {
// g.Examples[j].URL = "/examples/" + toolbelt.Cased(g.Examples[j].Label, toolbelt.Snake, toolbelt.Lower)
// if prevExample != nil {
// example.Prev = prevExample
// prevExample.Next = example
// }
// prevExample = example
// examplesByURL[example.URL] = example
// }
// return g
// })
// router.Route("/examples", func(examplesRouter chi.Router) {
// examplesRouter.Get("/", func(w http.ResponseWriter, r *http.Request) {
// http.Redirect(w, r, examples[0].Examples[0].URL, http.StatusFound)
// })
// examplesRouter.Get("/{exampleName}", func(w http.ResponseWriter, r *http.Request) {
// exampleName := chi.URLParam(r, "exampleName")
// contents, ok := mdElementRenderers[exampleName]
// if !ok {
// http.Error(w, "not found", http.StatusNotFound)
// return
// }
// example, ok := examplesByURL[r.URL.Path]
// if !ok {
// http.Error(w, "not found", http.StatusNotFound)
// }
// contentGroup := []ElementRenderer{}
// if example.Prev != nil {
// contentGroup = append(contentGroup,
// buttonLink().
// CLASS("w-full").
// HREF(example.Prev.URL).
// Text("Back to "+example.Prev.Label).
// CLASS("flex flex-col justify-center items-center no-underline"))
// }
// contentGroup = append(contentGroup, contents)
// nextHREF := "/reference"
// nextLabel := "Dive deeper"
// if example.Next != nil {
// nextHREF = example.Next.URL
// nextLabel = "Next " + example.Next.Label
// }
// contentGroup = append(contentGroup,
// buttonLink().
// CLASS("w-full").
// HREF(nextHREF).
// Text(nextLabel).
// CLASS("flex flex-col justify-center items-center no-underline"))
// sidebarContents := Group(
// Range(examples, func(g ExampleGroup) ElementRenderer {
// return DIV(
// DIV(
// DIV().CLASS("text-2xl font-bold text-primary").Text(g.Label),
// HR().CLASS("divider border-primary"),
// ),
// TABLE().
// CLASS("table w-full").
// Children(
// THEAD(
// TR(
// TH().Text("Pattern"),
// TH().Text("Description"),
// ),
// ),
// TBODY(
// Range(g.Examples, func(e *Example) ElementRenderer {
// return TR().
// CLASS("hover").
// Children(
// TD(link(e.URL, e.Label, e.URL == r.URL.Path)),
// TD().CLASS("text-xs").Text(e.Description),
// )
// }),
// ),
// ),
// )
// }),
// )
// pp := prosePage(r, sidebarContents, Group(contentGroup...), nil)
// pp.Render(w)
// })
examplesSessionStore := sessions.NewCookieStore([]byte("ExampleSession"))
if err := errors.Join(
setupExamplesClickToEdit(examplesRouter),
setupExamplesBulkUpdate(examplesRouter),
setupExamplesClickToLoad(examplesRouter),
setupExamplesEditRow(examplesRouter),
setupExamplesDeleteRow(examplesRouter),
setupExamplesLazyLoad(examplesRouter),
setupExamplesFetchIndicator(examplesRouter),
setupExamplesOnLoad(examplesRouter, examplesSessionStore),
setupExamplesDisableButton(examplesRouter),
setupExampleInlineValidation(examplesRouter),
setupExamplesInfiniteScroll(examplesRouter),
setupExamplesActiveSearch(examplesRouter),
setupExamplesProgressBar(examplesRouter),
setupExamplesValueSelect(examplesRouter),
setupExamplesAnimations(examplesRouter),
setupExamplesFileUpload(examplesRouter),
setupExamplesDialogsBrowser(examplesRouter),
setupExamplesLazyTabs(examplesRouter),
setupExamplesMergeOptions(examplesRouter),
setupExamplesRedirects(examplesRouter),
setupExamplesMultilineFragments(examplesRouter),
setupExamplesUpdateStore(examplesRouter),
//
setupExamplesShoelaceKitchensink(examplesRouter),
//
setupExamplesViewTransitionAPI(examplesRouter),
setupExamplesModelBinding(examplesRouter),
setupExamplesTitleUpdateBackend(examplesRouter),
setupExamplesStoreChanged(examplesRouter, examplesSessionStore),
setupExamplesScrollIntoView(examplesRouter),
setupExamplesQuickPrimerGo(examplesRouter),
setupExamplesTemplCounter(examplesRouter, examplesSessionStore),
); err != nil {
panic(fmt.Sprintf("error setting up examples routes: %s", err))
}
})
return nil
}

View File

@ -1,64 +0,0 @@
package site
import (
goaway "github.com/TwiN/go-away"
)
type ClickToEditContactStore struct {
FirstName string `json:"firstName,omitempty" san:"trim,xss,max=128"`
LastName string `json:"lastName,omitempty" san:"trim,xss,max=128"`
Email string `json:"email,omitempty" san:"trim,xss,max=128"`
}
templ setupExamplesClickToEditUserComponent(store *ClickToEditContactStore) {
<div id="contact_1" class="flex flex-col max-w-sm gap-2">
<label>First Name: { goaway.Censor(store.FirstName) }</label>
<label>Last Name: { goaway.Censor(store.LastName) }</label>
<label>Email: { goaway.Censor(store.Email) }</label>
<div class="flex gap-4">
<button
class="btn btn-primary"
data-on-click="$$get('/examples/click_to_edit/contact/1/edit')"
>
Edit
</button>
<button
class="btn btn-secondary"
data-on-click="$$patch('/examples/click_to_edit/contact/1/reset')"
>
Reset
</button>
</div>
</div>
}
templ setupExamplesClickToEditUserEdit(store *ClickToEditContactStore) {
<div id="contact_1" class="flex flex-col gap-2" data-store={ templ.JSONString(store) }>
<label class="flex items-center gap-2 input input-bordered">
First Name
<input type="text" class="grow" data-model="firstName"/>
</label>
<label class="flex items-center gap-2 input input-bordered">
Last Name
<input type="text" class="grow" data-model="lastName"/>
</label>
<label class="flex items-center gap-2 input input-bordered">
Email
<input type="text" class="grow" data-model="email"/>
</label>
<div class="flex gap-4">
<button
class="btn btn-primary"
data-on-click="$$put('/examples/click_to_edit/contact/1')"
>
Save
</button>
<button
class="btn btn-secondary"
data-on-click="$$get('/examples/click_to_edit/contact/1')"
>
Cancel
</button>
</div>
</div>
}

View File

@ -1,46 +0,0 @@
package site
import (
"log"
"net/http"
"github.com/delaneyj/datastar"
"github.com/go-chi/chi/v5"
)
func setupExamplesClickToLoad(examplesRouter chi.Router) error {
examplesRouter.Get("/click_to_load/data", func(w http.ResponseWriter, r *http.Request) {
store := &ClickToLoadStore{}
if err := datastar.QueryStringUnmarshal(r, store); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
if store.Limit < 1 {
store.Limit = 10
} else if store.Limit > 100 {
store.Limit = 100
}
if store.Offset < 0 {
store.Offset = 0
}
sse := datastar.NewSSE(w, r)
if store.Offset == 0 {
datastar.RenderFragmentTempl(sse, ClickToEditAgentsTable(store))
} else {
datastar.RenderFragmentTempl(sse, ClickToLoadMoreButton(store))
for i := 0; i < store.Limit; i++ {
log.Printf("ClickToLoadAgentRow: %d", store.Offset+i)
datastar.RenderFragmentTempl(
sse,
ClickToLoadAgentRow(store.Offset+i),
datastar.WithQuerySelectorID("click_to_load_rows"),
datastar.WithMergeAppendElement(),
)
}
}
})
return nil
}

View File

@ -1,13 +0,0 @@
package site
import (
"time"
)
templ fetchIndicatorEmpty() {
<div id="greeting">No data</div>
}
templ fetchIndicatorGreeting() {
<div id="greeting">Hello, the time is { time.Now().Format(time.RFC3339) }</div>
}

View File

@ -1,40 +0,0 @@
package site
import (
"net/http"
"github.com/delaneyj/datastar"
"github.com/go-chi/chi/v5"
)
func setupExamplesInfiniteScroll(examplesRouter chi.Router) error {
examplesRouter.Get("/infinite_scroll/data", func(w http.ResponseWriter, r *http.Request) {
store := &infiniteScrollStore{}
if err := datastar.QueryStringUnmarshal(r, store); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if store.Limit < 1 || store.Limit > 100 {
store.Limit = 10
}
sse := datastar.NewSSE(w, r)
if store.Offset == 0 {
datastar.RenderFragmentTempl(sse, infiniteScrollAgents(store))
} else {
datastar.RenderFragmentTempl(sse, infiniteScrollMore(store))
for i := 0; i < store.Limit; i++ {
datastar.RenderFragmentTempl(
sse, infiniteScrollAgent(store.Offset+i),
datastar.WithQuerySelectorID("click_to_load_rows"),
datastar.WithMergeAppendElement(),
)
}
}
})
return nil
}

View File

@ -1,59 +0,0 @@
package site
import (
"fmt"
"github.com/delaneyj/toolbelt"
)
type infiniteScrollStore struct {
Limit int `json:"limit"`
Offset int `json:"offset"`
}
templ infiniteScrollMore(store *infiniteScrollStore) {
<div
id="loading_message"
class="alert alert-info"
data-intersects={ fmt.Sprintf(
"$offset=%d;$limit=%d;$$get('/examples/infinite_scroll/data')",
store.Offset+store.Limit,
store.Limit,
) }
>
@icon("svg-spinners:blocks-wave")
Loading...
</div>
}
templ infiniteScrollAgent(i int) {
<tr id={ fmt.Sprintf("agent_%d", i) }>
<td>Agent Smith { fmt.Sprint(i) }</td>
<td>{ fmt.Sprintf("void%d@null.org", i+1) }</td>
<td class="uppercase">{ fmt.Sprintf("%x", toolbelt.AliasHash(fmt.Sprint(i))) }</td>
</tr>
}
templ infiniteScrollAgents(store *infiniteScrollStore) {
<div
id="infinite_scroll"
data-store={ templ.JSONString(store) }
class="flex flex-col gap-2"
>
<table class="table w-full table-zebra">
<caption>Agents</caption>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>ID</th>
</tr>
</thead>
<tbody id="click_to_load_rows">
for i := 0; i < store.Limit; i++ {
@infiniteScrollAgent(store.Offset + i)
}
</tbody>
</table>
@infiniteScrollMore(store)
</div>
}

View File

@ -1,49 +0,0 @@
package site
import (
"fmt"
"github.com/delaneyj/datastar"
)
type ModelBindingStore struct {
BindText string `json:"bindText"`
BindNumber int `json:"bindNumber"`
BindBool bool `json:"bindBool"`
BindSelection int `json:"bindSelection"`
}
templ ModelBindingView(optionCount int, store *ModelBindingStore) {
<div
id="container"
class="flex flex-col gap-4"
data-store={ templ.JSONString(store) }
>
<input class="input input-bordered" data-model="bindText"/>
<input class="input input-bordered" type="number" data-model="bindNumber"/>
<textarea class="textarea textarea-bordered" data-model="bindText"></textarea>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Checkbox</span>
<input type="checkbox" checked="checked" class="checkbox" data-model="bindBool"/>
</label>
</div>
<select class="select select-bordered" data-model="bindSelection">
for i :=1 ; i <= optionCount; i++ {
{{ str := fmt.Sprint( i) }}
<option value={ str }>Option { str }</option>
}
</select>
<div class="flex flex-col">
for i := 1; i <= optionCount; i++ {
{{ str := fmt.Sprint( i) }}
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Option { str }</span>
<input type="radio" class="radio" data-model="bindSelection" value={ str }/>
</label>
</div>
}
</div>
@datastar.TemplSignalStoreView()
</div>
}

View File

@ -1,26 +0,0 @@
package site
import (
"net/http"
"github.com/delaneyj/datastar"
"github.com/go-chi/chi/v5"
)
func setupExamplesMultilineFragments(examplesRouter chi.Router) error {
examplesRouter.Get("/multiline_fragments/data", func(w http.ResponseWriter, r *http.Request) {
sse := datastar.NewSSE(w, r)
datastar.RenderFragmentString(sse, `
<div id="replaceMe">
<pre>
This is a multiline fragment.
Used when you are writing a lot of text by hand
</pre>
</div>
`)
})
return nil
}

View File

@ -1,15 +0,0 @@
package site
type RedirectsStore struct {
RedirectTo string `json:"redirectTo"`
}
templ redirectsView(store *RedirectsStore) {
<div id="demo" class="flex w-full gap-4" data-store={ templ.JSONString(store) }>
<label class="flex items-center flex-1 gap-2">
<span>Redirect to: </span>
<input data-model="redirectTo" class="flex-1 input input-bordered"/>
</label>
<button class="btn btn-success" data-on-click="$$post('/examples/redirects/data')">Redirect</button>
</div>
}

View File

@ -1,53 +0,0 @@
package site
import (
"fmt"
"log"
"math"
"math/rand"
"net/http"
"github.com/delaneyj/datastar"
"github.com/delaneyj/toolbelt"
"github.com/go-chi/chi/v5"
"github.com/samber/lo"
)
func setupExamplesShoelaceKitchensink(examplesRouter chi.Router) error {
examplesRouter.Route("/shoelace_kitchensink/data", func(dataRouter chi.Router) {
options := lo.Map(lo.Range(7), func(i, index int) ShoelaceKitchensinkOption {
offset := toolbelt.NextID()
return ShoelaceKitchensinkOption{
Label: fmt.Sprintf("Option %d", i),
Value: uint32(offset % math.MaxUint32),
}
})
dataRouter.Get("/", func(w http.ResponseWriter, r *http.Request) {
sse := datastar.NewSSE(w, r)
store := &ShoelaceKitchensinkStore{
Nested: &ShoelaceKitchensinkNested{
Label: fmt.Sprintf("Hello World %d", rand.Intn(100)),
Selection: options[rand.Intn(len(options))].Value,
IsChecked: true,
},
}
datastar.RenderFragmentTempl(sse, ShoelaceKitchensinkView(r, options, store))
})
dataRouter.Post("/", func(w http.ResponseWriter, r *http.Request) {
var res any
if err := datastar.BodyUnmarshal(r, &res); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
log.Printf("res: %v", res)
sse := datastar.NewSSE(w, r)
datastar.RenderFragmentString(sse, "<div></div>")
})
})
return nil
}

View File

@ -1,53 +0,0 @@
package site
import (
"fmt"
"net/http"
"github.com/delaneyj/datastar"
)
type ShoelaceKitchensinkStore struct {
Nested *ShoelaceKitchensinkNested `json:"nested"`
}
type ShoelaceKitchensinkNested struct {
Label string `json:"label"`
Selection uint32 `json:"selection"`
IsChecked bool `json:"isChecked"`
}
type ShoelaceKitchensinkOption struct {
Label string `json:"label"`
Value uint32 `json:"value"`
}
templ ShoelaceKitchensinkView(r *http.Request, options []ShoelaceKitchensinkOption, store *ShoelaceKitchensinkStore) {
<div
id="shoelace_kitchensink"
class="flex flex-col gap-4 sl-theme-dark"
data-store={ templ.JSONString(store) }
>
<sl-input label="Label" data-model="nested.label"></sl-input>
<sl-select
label="Select"
data-model="nested.selection"
data-on-sl-change="console.log('change')"
>
for _, o := range options {
<sl-option value={ fmt.Sprint(o.Value) }>{ o.Label } ({ fmt.Sprint(o.Value) })</sl-option>
}
</sl-select>
<sl-radio-group label="Radio Group" data-bind-value="$nested.selection" data-on-sl-change="$nested.selection = ctx.el.value">
for _, o := range options {
<sl-radio value={ fmt.Sprint(o.Value) }>{ o.Label } ({ fmt.Sprint(o.Value) })</sl-radio>
}
</sl-radio-group>
<sl-checkbox data-model="nested.isChecked">Checkbox</sl-checkbox>
<sl-button
variant="primary"
data-on-click={ fmt.Sprintf("$$post('%s')", r.URL.Path) }
>Submit</sl-button>
@datastar.TemplSignalStoreView()
</div>
}

View File

@ -1,31 +0,0 @@
package site
import (
"net/http"
"time"
"github.com/delaneyj/datastar"
"github.com/delaneyj/toolbelt"
"github.com/go-chi/chi/v5"
)
func setupExamplesUpdateStore(examplesRouter chi.Router) error {
examplesRouter.Route("/update_store/data", func(dataRouter chi.Router) {
dataRouter.Post("/patch", func(w http.ResponseWriter, r *http.Request) {
store := map[string]any{}
if err := datastar.BodyUnmarshal(r, &store); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
randKey := toolbelt.NextEncodedID()
store[randKey] = time.Now().Format(time.RFC3339Nano)
sse := datastar.NewSSE(w, r)
datastar.PatchStore(sse, store)
})
})
return nil
}

View File

@ -1,104 +0,0 @@
package site
import (
"bytes"
"math/rand"
"net/http"
"sync/atomic"
"github.com/a-h/templ"
"github.com/delaneyj/datastar"
"github.com/delaneyj/toolbelt"
"github.com/dustin/go-humanize"
"github.com/go-chi/chi/v5"
"github.com/wcharczuk/go-chart/v2"
"github.com/wcharczuk/go-chart/v2/drawing"
)
var homePageChartSVG string
func setupHome(router chi.Router) error {
chartWidth := 480
graph := chart.BarChart{
Title: "File Size (Hello World) first load",
Width: chartWidth,
Height: chartWidth,
Background: chart.Style{
FillColor: drawing.Color{R: 1, G: 1, B: 1, A: 0},
FontColor: drawing.ColorWhite,
},
Canvas: chart.Style{
FillColor: drawing.Color{R: 1, G: 1, B: 1, A: 0},
FontColor: drawing.ColorWhite,
FontSize: 6,
},
TitleStyle: chart.Style{
FontColor: drawing.ColorWhite,
},
XAxis: chart.Style{
FontColor: drawing.ColorWhite,
},
YAxis: chart.YAxis{
Style: chart.Style{
FontColor: drawing.ColorWhite,
},
ValueFormatter: func(v any) string {
return humanize.Bytes(uint64(v.(float64)))
},
},
Bars: []chart.Value{
{Label: "Next.js", Value: 86221},
{Label: "SvelteKit", Value: 81920},
{Label: "HTMX+\nhyperscript", Value: 40653},
{Label: "HTMX+\nAlpine", Value: 37980},
{Label: "Datastar", Value: 10445},
{Label: "Datastar Core", Value: 4526},
},
}
buffer := bytes.NewBuffer([]byte{})
err := graph.Render(chart.SVG, buffer)
if err != nil {
panic(err)
}
homePageChartSVG = buffer.String()
var globalCount = new(int32)
c := int32(toolbelt.Fit(rand.Float32(), 0, 1, -100, 100))
globalCount = &c
globalCountExample := func() templ.Component {
store := &GlobalCountStore{
Count: atomic.LoadInt32(globalCount),
}
return HomeGlobalCountExample(*store)
}
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
Home().Render(r.Context(), w)
})
router.Route("/api", func(apiRouter chi.Router) {
apiRouter.Route("/globalCount", func(globalCountRouter chi.Router) {
globalCountRouter.Get("/", func(w http.ResponseWriter, r *http.Request) {
sse := datastar.NewSSE(w, r)
datastar.RenderFragmentTempl(sse, globalCountExample())
})
globalCountRouter.Post("/", func(w http.ResponseWriter, r *http.Request) {
store := &GlobalCountStore{}
if err := datastar.BodyUnmarshal(r, store); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
atomic.StoreInt32(globalCount, store.Count)
sse := datastar.NewSSE(w, r)
datastar.RenderFragmentTempl(sse, globalCountExample())
})
})
})
return nil
}

View File

@ -1,114 +0,0 @@
package site
import (
"fmt"
)
templ Home() {
{{ cdnText := `<script type="module" defer src="https://cdn.jsdelivr.net/npm/@sudodevnull/datastar" ></script>` }}
@Page() {
<div class="flex flex-col items-center min-h-screen gap-4 p-16 bg-gradient-to-br from-base-300 to-base-100">
<div class="flex flex-col items-center max-w-lg gap-8">
<img
class="w-24 border-4 rounded-full shadow-xl md:w-96 border-primary"
src={ staticPath("/images/rocket.png") }
/>
<div class="text-4xl font-bold uppercase font-brand md:text-6xl text-primary">Datastar</div>
<div class="text-center font-brand">
<div class="text-xl">Real-time hypermedia framework</div>
</div>
<p>
Using a single
<span class="text-lg font-bold text-primary">{ iifeBuildSize }</span>
CDN link and have access to everything needed to rival a full-stack SPA framework; all in the language of your choice.
</p>
<div class="flex flex-wrap w-full gap-4">
<a
class="flex items-center justify-center flex-1 btn btn-secondary"
href="https://discord.gg/CHvPMrAp6F"
>
@icon("simple-icons:discord")
Join the conversation
</a>
<a
class="flex items-center justify-center flex-1 btn btn-accent"
href="https://github.com/delaneyj/datastar/tree/main/library/src/lib"
>
@icon("simple-icons:github")
View the source
</a>
</div>
<div class="w-full shadow-xl card bg-base-100">
<div class="card-body">
<div class="flex items-center gap-4">
<button
class="btn btn-primary btn-ghost"
data-on-click={ fmt.Sprintf("$$clipboard('%s')", cdnText) }
>
@icon("material-symbols:content-copy")
</button>
<code
class="flex-1 overflow-hidden text-xs text-primary text-ellipsis"
>
{ cdnText }
</code>
</div>
</div>
</div>
@templ.Raw(homePageChartSVG)
<div class="w-full shadow-xl card bg-base-100">
<div class="card-body">
<h2 class="card-title">Example of a dynamically loaded area of page with shared global state</h2>
<div
id="global-count-example"
class="flex items-center justify-center gap-4 p-4"
data-on-load="$$get('/api/globalCount')"
data-fetch-indicator="'#spinner'"
>
<span class="text-2xl">Loading example on delay...</span>
@icon("svg-spinners:eclipse", "id", "spinner")
</div>
</div>
</div>
<a
class="flex items-center w-full gap-1 btn btn-primary btn-outline btn-lg"
href={ templ.SafeURL("/guide") }
>
@icon("simple-icons:rocket")
Let's Get Started!
</a>
</div>
</div>
}
}
type GlobalCountStore struct {
Count int32 `json:"count"`
}
templ HomeGlobalCountExample(store GlobalCountStore) {
<div
id="global-count-example"
class="flex flex-col gap-4"
data-store={ templ.JSONString(store) }
>
<div class="flex gap-4">
<a class="flex-1 btn btn-success" data-on-click="$count++">Increment Local +</a>
<a class="flex-1 btn btn-error" data-on-click="$count--">Decrement Local -</a>
</div>
<div class="flex flex-col gap-2">
<div data-text="`Count is ${$count % 2 === 0 ? 'even' : 'odd'}`"></div>
<input
class="flex-1 input input-bordered"
type="number"
name="count"
data-model="count"
data-testid="localcount_input"
/>
</div>
<div class="flex gap-4">
<a class="flex-1 btn btn-info" data-on-click="$$get('/api/globalCount')">Load global</a>
<a class="flex-1 btn btn-warning" data-on-click="$$post('/api/globalCount')">Store global</a>
</div>
</div>
}

View File

@ -1,227 +0,0 @@
package site
import (
"net/http"
"strings"
)
templ Page() {
<!DOCTYPE html>
<html lang="en">
<head>
<title>DATASTAR</title>
<link rel="icon" href={ staticPath("images/datastar_icon.svg") }/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=Inter:wght@100..900&family=Gideon+Roman:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400;1,700;1,900&display=swap" rel="stylesheet"/>
<script src="https://code.iconify.design/iconify-icon/2.1.0/iconify-icon.min.js"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-QZ4RYHJW6X"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-QZ4RYHJW6X');
</script>
<script type="module" defer src={ staticPath("library/datastar.js") }></script>
// <script defer>
// function initHotReload() {
// console.log("Hot reload initializing")
// if (typeof(EventSource) !== "undefined") {
// const es = new EventSource("/hotreload");
// es.onmessage = function(event) {
// location.reload();
// }
// es.onerror = function(err) {
// console.log("lost connection to server, reloading");
// setTimeout(() => {
// location.reload();
// }, 500);
// };
// }
// }
// initHotReload();
// </script>
<link href={ staticPath("css/site.css") } rel="stylesheet" type="text/css"/>
</head>
<body class="flex flex-col w-full h-full min-h-screen overflow-y-scroll scrollbar scrollbar-thumb-primary scrollbar-track-accent">
{ children... }
</body>
</html>
}
templ icon(icon string, attrs ...string) {
<iconify-icon icon={ icon } { KVPairsAttrs(attrs...)... }></iconify-icon>
}
templ headerIconLink(iconName, href string) {
<a target="_blank" rel="noopener noreferrer" href={ templ.SafeURL(href) }>
@icon(iconName)
</a>
}
templ headerTopLevelLink(r *http.Request, text string) {
{{ url := templ.SafeURL("/"+ strings.ToLower(text)) }}
<a
href={ url }
class={
"font-bold uppercase link-hover",
templ.KV("link-primary", strings.HasPrefix(r.URL.Path, string(url))),
}
>{ text }</a>
}
templ headerExternalLinks() {
@headerIconLink("simple-icons:discord", "https://discord.gg/CHvPMrAp6F")
@headerIconLink("simple-icons:github", "https://github.com/delaneyj/datastar/tree/main/library")
@headerIconLink("simple-icons:npm", "https://www.npmjs.com/package/@sudodevnull/datastar")
@headerIconLink("simple-icons:twitter", "https://twitter.com/delaneyj")
}
templ headerTopLevelLinks(r *http.Request) {
@headerTopLevelLink(r, "Guide")
@headerTopLevelLink(r, "Reference")
@headerTopLevelLink(r, "Examples")
@headerTopLevelLink(r, "Essays")
}
templ header(r *http.Request) {
<div class="navbar bg-base-200">
<div class="flex justify-between w-full gap-4">
<div class="flex items-baseline gap-1">
<a
class="flex gap-1 text-2xl font-bold uppercase font-brand"
href="/"
>
<span>Datastar</span>
<img src={ staticPath("images/datastar_icon.svg") } class="h-8"/>
</a>
<div class="font-mono text-xs text-accent">v{ packageJSON.Version }</div>
</div>
<div class="hidden md:text-md lg:text-lg md:flex md:gap-4 md:visible ">
@headerTopLevelLinks(r)
</div>
<div class="hidden text-xl md:flex md:gap-4 md:visible">
@headerExternalLinks()
</div>
</div>
</div>
<div class="flex flex-wrap justify-around visible gap-2 pb-8 text-sm bg-base-200 md:hidden">
@headerTopLevelLinks(r)
</div>
<div class="visible navbar bg-base-300 md:hidden">
<div class="navbar-start">
<label for="sidebar-drawer" class="btn btn-ghost drawer-button">
@icon("material-symbols:menu")
</label>
</div>
<div class="gap-4 navbar-end">
@headerExternalLinks()
</div>
</div>
}
type SidebarLink struct {
ID string
Label string
URL templ.SafeURL
Prev *SidebarLink
Next *SidebarLink
IsDisabled bool
}
type SidebarGroup struct {
Label string
Links []*SidebarLink
}
templ SidebarPage(r *http.Request, sidebarGroups []*SidebarGroup, current *SidebarLink, contents string) {
@Page() {
@highlightCSS
<div class="drawer">
<input id="sidebar-drawer" type="checkbox" class="drawer-toggle"/>
<div class="flex flex-col min-h-screen drawer-content">
@header(r)
<div class="flex flex-1">
<aside class="flex-col hidden gap-4 px-4 py-8 overflow-y-auto md:flex min-w-64 bg-base-300 md:visible">
@SidebarContents(sidebarGroups, current)
</aside>
<div class="flex flex-col items-center w-full gap-16 p-4 md:p-16">
@SidebarPrevNextLinks(sidebarGroups, current)
<article
class={
"flex-1",
"prose prose-primary prose-sm md:prose lg:prose-lg p-4",
"prose-a:link-primary",
}
>
@templ.Raw(contents)
</article>
@SidebarPrevNextLinks(sidebarGroups, current)
</div>
</div>
</div>
<aside class="drawer-side">
<label for="sidebar-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
<ul class="min-h-full p-4 menu w-80 bg-base-300 text-base-content">
@SidebarContents(sidebarGroups, current)
</ul>
</aside>
</div>
}
}
templ SidebarContents(sidebarGroups []*SidebarGroup, current *SidebarLink) {
<div class="flex flex-col gap-8 uppercase">
for i, grp := range sidebarGroups {
<div class="flex flex-col gap-2">
<h3 class="text-xs font-bold text-primary">{ grp.Label }</h3>
for _, link := range grp.Links {
if link.IsDisabled {
<div class="opacity-25">{ link.Label }</div>
} else {
<a
class="link-secondary link-hover"
href={ link.URL }
>{ link.Label }</a>
}
}
if i != len(sidebarGroups)-1 {
<div class="divider"></div>
}
</div>
}
</div>
}
templ SidebarPrevNextLinks(essayGroups []*SidebarGroup, current *SidebarLink) {
<div class="flex flex-wrap justify-between w-full gap-4">
<div>
if current.Prev != nil {
<a
class="btn btn-sm btn-ghost"
disabled?={ current.Prev.IsDisabled }
href={ current.Prev.URL }
>
@icon("material-symbols:arrow-back-ios")
{ current.Prev.Label }
</a>
}
</div>
<div>
if current.Next != nil {
<a
class="btn btn-sm btn-ghost"
disabled?={ current.Next.IsDisabled }
href={ current.Next.URL }
>
{ current.Next.Label }
@icon("material-symbols:arrow-forward-ios")
</a>
}
</div>
</div>
}

View File

@ -1,92 +0,0 @@
package site
import (
"bytes"
"compress/gzip"
"fmt"
"log"
"strings"
"github.com/a-h/templ"
"github.com/dustin/go-humanize"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/parser"
)
var iifeBuildSize string
func upsertIIfeBuildSize() string {
if iifeBuildSize != "" {
return iifeBuildSize
}
build, err := staticFS.ReadFile("static/library/datastar.iife.js")
if err != nil {
panic(err)
}
buf := bytes.NewBuffer(nil)
w, err := gzip.NewWriterLevel(buf, gzip.BestCompression)
if err != nil {
panic(err)
}
if _, err := w.Write(build); err != nil {
panic(err)
}
w.Close()
log.Printf("iife build size: %s", humanize.IBytes(uint64(buf.Len())))
iifeBuildSize = humanize.IBytes(uint64(buf.Len()))
return iifeBuildSize
}
func markdownRenders(staticMdPath string) (mdElementRenderers map[string]string, mdAnchors map[string][]string, err error) {
mdDir := "static/md/" + staticMdPath
docs, err := staticFS.ReadDir(mdDir)
if err != nil {
return nil, nil, fmt.Errorf("error reading docs dir: %w", err)
}
// regExpImg := regexp.MustCompile(`(?P<whole>!\[[^\]]+]\((?P<path>[^)]+)\))`)
// prefix := []byte("/static/")
mdElementRenderers = map[string]string{}
mdAnchors = map[string][]string{}
for _, de := range docs {
fullPath := mdDir + "/" + de.Name()
b, err := staticFS.ReadFile(fullPath)
if err != nil {
return nil, nil, fmt.Errorf("error reading doc %s: %w", de.Name(), err)
}
anchors := []string{}
lines := strings.Split(string(b), "\n")
for _, line := range lines {
if strings.HasPrefix(line, "#") {
parts := strings.Split(line, " ")
anchor := strings.Join(parts[1:], " ")
anchors = append(anchors, anchor)
}
}
mdParser := parser.NewWithExtensions(parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock | parser.Footnotes)
doc := mdParser.Parse(b)
renderedHTML := string(markdown.Render(doc, mdRenderer()))
name := de.Name()[0 : len(de.Name())-3]
mdElementRenderers[name] = renderedHTML
mdAnchors[name] = anchors
}
return mdElementRenderers, mdAnchors, nil
}
func KVPairsAttrs(kvPairs ...string) templ.Attributes {
if len(kvPairs)%2 != 0 {
panic("kvPairs must be a multiple of 2")
}
attrs := templ.Attributes{}
for i := 0; i < len(kvPairs); i += 2 {
attrs[kvPairs[i]] = kvPairs[i+1]
}
return attrs
}

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3dcb2b1820e15ee93b35c4825ef62649cd3ae1978b4db33ffcc61c1dab85d1f9
size 129778

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e7d99edcb59f0299ff4ed5ad00baefe0b4e937008c7a9a297bc832654b04a8b7
size 22011

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:694e57fbc74689f5929069de2d8dcd311c052e30b488547fe34e5fc01ed90b0d
size 51314

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ded8c96be2a77738ddbd2f43b9d6c49e2e4c40756c8fb12ee2a60d64d4a1a0ec
size 34557

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:877715a68505229029a7d08627225f98ab5fd7feede8b6945e17abdb4f10a0fe
size 748508

View File

@ -1,21 +0,0 @@
# Why another framework?
## What's different?
There are many things I find wonderful about Alpine.js and HTMX. However there are a few things that I think could be improved. The biggest challenge it both is plugins (called `directives`/`magic` in Alpine and `extensions` in HTMX). I tried writing in both of them as was disappointed by the breadth of monkey patching and lack of type safety. In general you don't have access to what other plugins do nor can you build a DAG of dependencies. This means you have to be very careful about the order you load plugins and what they do. This is especially true if you want to use a plugin in a plugin. I think this is a big problem and I wanted to solve it. Because Datastar started with the notion **_EVERYTHING_** is a plugin you could theoretically build both Alpine and HTMX inside of Datastar. I don't think that is a good idea but it is possible.
Beyond that I want the backend to be the _source of truth_ when it comes to state. [HATEOAS](https://en.wikipedia.org/wiki/HATEOAS) is a great way to structure your applications but you still need some client side state. Datstar does not use FormData; it lacks the ability to define nested data structures simply. So in general you send up JSON (automatically) and down HTML. This is more prescriptive than HTMX, but again this is with just the included plugins. You can build your own plugins to do whatever you want.
## Background
I love what [Caleb Porzio](https://calebporzio.com/) has done with [Alpine.js](https://alpinejs.dev/) and likewise with [Carson Gross](https://bigsky.software/cv/) with [HTMX](https://htmx.org/). However after trying to make extensions in both I got disappointed with the limitations. Both are pure Javascript which is fine but leads to having to either keep the whole state in your head and or be prepared for lots of runtime errors. Personally I think the best way to do this is to use Typescript and have the build step and compiler catch as many errors as possible. Plus it makes it easier to extend and create optimized builds.
### Why not just use Vue/React/Svelte?
[HTMX Essays](https://htmx.org/essays/) are a great place to start.
### Why not just use HTMX+Alpine?
There was a bit of a rant here before. TL;DR tried to show HTMX v2 could do all these things and it wasn't accepted by the community. I think HTMX is great and I will continue to recommend it. In general I think the some of the choices are throwing the baby out with the bathwater when it comes to things like Vite/TS/etc. Good news is that everything I, and some other lurkers, wanted are available in Datastar or can be added easily via plugins.
[Let's move on to the docs and see what Datastar can do](/docs)

View File

@ -1,82 +0,0 @@
# Yes, you want a build step
## In response to the HTMX essay [No Build Step](https://htmx.org/essays/no-build-step/)
This is making the counter argument that a build step are extremely valuable when building a frontend framework. Lack of builds might be the right choice for HTMX but in my eyes its a self full-filling prophecy. The author concurrently wary of progress yet works on a library about extending the HTML spec to do more than it was designed for. The essay is written by a core contributor and not the author of HTMX. In general, its filled with so many fallacies but the real culprit is the _false dilemma fallacy_.
> This common fallacy misleads by presenting complex issues in terms of two inherently opposed sides. Instead of acknowledging that most (if not all) issues can be thought of on a spectrum of possibilities and stances, the false dilemma fallacy asserts that there are only two mutually exclusive outcomes.
> This fallacy is particularly problematic because it can lend false credence to extreme stances, ignoring opportunities for compromise or chances to re-frame the issue in a new way.
The whole discussion is framed as a false dilemma. Almost every point he makes is demonstrably false by the counter example of Datastar. Its smaller, faster, supports more features, isn't written in Javascript, targets multiple browser versions, and has a build step. If he is trying to prove his point it needs to be done with more rigor. In general I find the HTMX essays to be a beacon for well articulated arguments; this one is not and does a disservice to the community exploring hypermedia.
## TED Talk
In the first paragraph he says both:
> A recurring question from some htmx contributors is why htmx isnt written in TypeScript, or, for that matter, why htmx **_lacks any build step at all_**. The full htmx source is a single 3,500-line JavaScript file; if you want to contribute to htmx, you do so by modifying the htmx.js file, the same file that gets sent to browsers in production, **_give or take minification and compression_**.
So before the essay starts he's given up the ghost. Even in as close to pure Javascript as you can get you still need a build step. Thank you, this has been my TED talk.
## Write once, run forever
> The best reason to write a library in plain JavaScript is that it lasts forever.
This is just not the world we live in. ES5 is dead, IE11 is dead, ECMAScript doesn't look anything like it did a decade ago, let alone 20 years ago. ECMAScript has been around for 25 years and has changed a lot in that time, let alone the APIs you are interfacing with. The web is a moving target and you need to keep up with it. If you don't you will be left behind.
## Reduction in labor
> Maintenance is a cost paid for with labor, and open-source code bases are the projects that can least afford to pay it. Opting not to use a build step drastically minimizes the labor required to keep htmx up-to-date.
No, just no. Much like CI/CD pipelines you set it up and largely forget about it. You can even automate the updates. The build step is a one time cost that pays dividends for the life of the project. If you don't have a build step you are going to be spending a lot of time manually updating your codebase. This is a false dichotomy. Datastar supports IIFE, UMD, & Modules and took all of adding the options to the build step. I've seen the crazy wrapper that HTMX uses to support all the different module types. It's a lot of code and a lot of maintenance. I'm not saying that HTMX is doing it wrong, just that it's a lot of work to support all the different module types. I'm not sure how much time it saves in the long run.
> But htmx is written in JavaScript, with no dependencies, so it will run unmodified for as long as web browsers remain relevant. Let the browser vendors do the hard work for you.
Every Datastar build or CDN version is a single Javascript file with no dependencies. The FUD here doesn't match reality at sets up a narrative of purity that is just not true. If fact oddly **because** of our build step we have full source mapping supported so you can debug your the production minified version in the browser looking at the original source and stack. This is a huge win for developers. I'm not sure why you would want to give that up.
## Source Maps and Hot Module Reloading
> Build step advocates point out that TypeScript can generate source maps, which tell your browser what TypeScript corresponds to what JavaScript, and thats true! But now you have another thing to keep track of—the TypeScript you wrote, the JavaScript it generated, and the source map that connects these two. The hot-reloading development server youre now dependent on will keep these up to date for you on localhost
Yes you have **_the same build folder_** with more static files that reference each other. This is not a big deal, a weird straw man, non-issue. You have to run a dev server to test your code anyway for things like CORS to work. This is just a weird argument, especially in light of things like hot module reloading for both code and styles. Modern tooling is now in the _sub milliseconds_ for rebuilds. Want to run your tests in parallel, well now you are just missing out on the real DX that modern tooling provides.
> ...but what about on your staging server? What about in production? Bugs that appear in these environments will be harder to track down, because youve lost a lot of information about where they come from.
Github actions for `bun build` or `vite build` are dead easy, and with weird arguments that are just not an issue nowadays. Like complaining about Makefiles when you have Visual Studio.
## The DX
> The htmx DX is very simple—your browser loads a single file, which in every environment is the exact same file you wrote. The tradeoffs required to maintain that experience are real, but theyre tradeoffs that make sense for this project.
The DX is why I personally moved on. The core monkey patches the DOM and that's just not a good DX. The core is not very extendable and you have to keep all 3000 LOC in your head to understand the ramification of your changes let alone the changes that other people make. You are giving up a lot of the DX that you get with a build step.
> Requiring that htmx remain in a single file (again, around 3,500 LOC) enforces a degree of intention on the library; there is a real pressure when working on the htmx source to justify the addition of new code, a pressure which maintains an equilibrium of relative simplicity.
Or... make everything an extension and allow them to rely on each other at there discretion. Making it a single file doesn't do anything but make harder to maintain.
## Amalgamation is a build step
> the lack of places for functionality to hide makes working on htmx a lot more approachable. Far, far more complex projects use aspects of this approach as well: SQLite3 compiles from a single-file source amalgamation (though they use separate files for development, theyre not crazy) which makes hacking on it significantly easier. You could never build the linux kernel this way—but htmx is not the linux kernel.
This is one of the worst takes in the whole essay. SQLite is **developed** as a set of files and **deployed** as an amalgamation. Just like Datastar, Alpine, HTMX, Zod, etc. You are conflating distribution with development and even making examples against you're own position.
> The htmx code does have to be written in JavaScript, though, because browsers run JavaScript. And as long as JavaScript is dynamically typed, the tradeoffs required to get true static typing in the htmx source are not worth it (htmx users can still take advantage of typed APIs, declared with .d.ts files).
The declaration (.d.ts) he point do are not accurate and aren't maintained last I checked. Also they are filled with `any` escape hatches which don't say anything. Separating definition into documentation seems to always cause this to happen. Conflating a build target with a language target. Like saying you have write in Assembly because x86 run assembly. Javascript can be a runtime target just like C can compile to assembly. You can write in Typescript and compile to Javascript. Another fallacy.
## Legacy targets stop progress
> Because htmx maintains support for Internet Explorer 11, and because it does not have a build step, every line of htmx has to be written in IE11-compatible JavaScript, which means no ES6.
This is certainly a choice and have seems as a hot button debate in the HTMX discord channel. If you had a build step, let alone used Typescript, you could target both **with the same codebase**. The false dilemma fallacy.
> This point is obvious, but its worth re-stating: the htmx source would be a lot tidier if it could be split it into modules. There are other factors that affect code quality besides tidiness, but to the extent that the htmx source is high-quality, it is not because it is tidy.
This is just a weird argument. You can split it into modules and still have tidiness. You can still split up into extensions, I know because I did it. To be clear, this isn't a declaration of minimal code sizes, but it _should_ be broken up into at least a per module/extension basis.
> Once you no longer have an enormous codebase of frontend JavaScript, there is far less pressure to adopt JavaScript on the backend. You can write backends in Python, Go, even NodeJS, and it doesnt matter to htmx—every mainstream language has mature solutions for formatting HTML. This is the principle of Hypermedia On Whatever youd Like (HOWL).
This essay is about HTMX build step, not the backend. It appears to me that not only is it clear you are throwing out the baby with the bathwater but demolishing the whole house. Just because SPA's are not the right tool for every job doesn't mean that you should throw out the whole tool box. We are talking about the best way to build a frontend library, not the backend.
## Conclusion
Even HTMX has a build step, and if they embraced it they could support multiple targets while still keeping their single un-tree shakeable amalgamation that they enjoy developing with.

View File

@ -1,26 +0,0 @@
## Active Search
[Original HTMX Version](https://htmx.org/examples/active-search/)
## Explanation
This example actively searches a contacts database as the user enters text.
## Demo
<div>
<div id="active_search" data-on-load="$$get('/examples/active_search/data')"></div>
</div>
The interesting part is the input field:
```html
<input
data-model="search"
data-on-input.debounce_1000ms="$$get('/examples/active_search/data')"
placeholder="Search..."
type="text"
/>
```
The input issues a `GET` to `/active_search/data` with the input value bound to `$search`. The `debounce_1000ms` modifier ensures that the search is not issued on every keystroke, but only after the user has stopped typing for 1 second. This modifiers will be covered in more detail in the [reference section](/reference).

View File

@ -1,73 +0,0 @@
# Animations
[Original HTMX Version](https://htmx.org/examples/animations/)
# Explanation
Datastar is designed to allow you to use CSS transitions to add smooth animations and transitions to your web page using only CSS and HTML. Below are a few examples of various animation techniques.
Datastar also allows you to use the new View Transitions API for creating animations.
<div id="animations" data-on-load="$$get('/examples/animations/data')"></div>
## Basic CSS Animations
### Color Throb
<div>
<div id="color_throb">Color Throb Demo</div>
</div>
The simplest animation technique in Datastar is to keep the id of an element stable across a content swap. If the id of an element is kept stable, htmx will swap it in such a way that CSS transitions can be written between the old version of the element and the new one.
Consider this div:
```html
<div
id="color_throb"
class="transition-all duration-1000 font-bold text-2xl text-center rounded-box p-4 uppercase"
style="background-color:#b57614;color:#83a598"
>
blue on yellow
</div>
```
With SSE we just update the style every second:
### Smooth Progress Bar
The [Progress Bar](/examples/progress_bar) demo uses this basic CSS animation technique as well, by updating the `length` property of a progress bar element, allowing for a smooth animation.
## Swap Transitions
### Fade Out On Swap
<div id="fade_out_swap">Fade out swap Demo</div>
If you want to fade out an element that is going to be removed when the request ends, just send a SSE event with the opacity set to 0 and set a transition duration. This will fade out the element before it is removed.
## Settling Transitions
### Fade In On Addition
<div id="fade_me_in">Fade in Demo</div>
Building on the last example, we can fade in the new content the same way, starting from an opacity of 0 and transitioning to an opacity of 1.
## Request In Flight Animation
<div id="request_in_flight">Request in Flight Demo</div>
One of the nice features for reactivity is to show a spinner when a request is in flight. On any element that is using backend actions you can add a `data-indicator` attribute to show a spinner when the request is in flight. This can be done like so:
```html
<button
data-fetch-indicator="'#request_in_flight_indicator'"
data-on-click="$$post('/examples/animations/data/request_in_flight')"
id="submit_request_in_flight"
>
Submit
</button>
```
This will show the element with the id `request_in_flight_indicator` when the request is in flight and hide it when the request is complete.

View File

@ -1,56 +0,0 @@
## Bulk Update
[Original HTMX Version](https://htmx.org/examples/bulk-update/)
## Demo
<style>
tr.deactivate.datastar-settling td {
background: lightcoral;
}
tr.activate.datastar-settling td {
background: darkseagreen;
}
tr td {
transition: all 1.2s;
}
</style>
<div
id="bulk_update"
data-on-load="$$get('/examples/bulk_update/data')"
>
</div>
## Explanation
This demo shows how to implement a common pattern where rows are selected and then bulk updated. This is accomplished by putting a form around a table, with checkboxes in the table, and then including the checked values in PUTs to two different endpoints: `activate` and `deactivate`:
Added to the page in this way:
```html
<style>
tr.deactivate.datastar-settling td {
background: lightcoral;
}
tr.activate.datastar-settling td {
background: darkseagreen;
}
tr td {
transition: all 1.2s;
}
</style>
```
The server will either activate or deactivate the checked users and then rerender the tbody tag with updated rows. It will apply the class activate or deactivate to rows that have been mutated. This allows us to use a bit of CSS to flash a color helping the user see what happened. The server events look like this:
```go
event: datastar-fragment
id: 129798448043016254
data: selector
data: merge upsert_attributes
data: settle 500
data: fragment ...
```
Notice the `settle` value is 500. This means the `datastar-settling` class will be added immediately and removed after 500ms. This is a nice way to show the user that something is happening.

View File

@ -1,77 +0,0 @@
## Click to Edit
[Original HTMX Version](https://htmx.org/examples/click-to-edit/)
## Demo
<div
id="contact_1"
data-on-load="$$get('/examples/click_to_edit/contact/1')"
>
</div>
## Explanation
The click to edit pattern provides a way to offer inline editing of all or part of a record without a page refresh. This pattern starts with a UI that shows the details of a contact. The div has a button that will get the editing UI for the contact from `/contact/1/edit`
```html
<!-- Removed styling -->
<div id="contact_1">
<label>First Name: John</label>
<label>Last Name: Doe</label>
<label>Email: joe@blow.com</label>
<div>
<button data-on-click="$$get('/examples/click_to_edit/contact/1/edit')">
Edit
</button>
<button data-on-click="$$get('/examples/click_to_edit/contact/1/reset')">
Reset
</button>
</div>
</div>
```
This returns a form that can be used to edit the contact
```html
<!-- Removed styling and escaping for brevity -->
<div
id="contact_1"
data-store="{
id: 1,
firstName: 'John',
lastName: 'Doe',
email: 'joe@blow.com'
}"
>
<div class="form-control">
<label>First Name</label>
<input type="text" data-model="firstName" />
</div>
<div>
<label>Last Name</label>
<input type="text" data-model="lastName" />
</div>
<div>
<label>Email</label>
<input type="text" data-model="email" />
</div>
<div>
<button data-on-click="$$put('/examples/click_to_edit/contact/1')">
Save
</button>
<button data-on-click="$$get('/examples/click_to_edit/contact/1')">
Cancel
</button>
</div>
</div>
```
### There is no form
If you compare to HTMX you'll notice there is no form, you can use one but its unnecessary. This is because you are already using signals and when you use a `PUT` to `/contact/1/edit`, the body is the entire contents of the store and its available to handle errors and validation holistically. There is also a profanity filter on the normal rendering of the contact that is not applied to the edit form. Controlling the rendering complete on the server allows you to have a single source of truth for the data and the rendering.
### There is no client validation
On the backend we've also added a quick santizer on the input to avoid bad actors (to some degree). You already have to deal with the data on the server so you might as well do the validation there. In this case its just modifying how the text is rendered when not editing. This is a simple example but you can see how you can extend it to more complex forms.

View File

@ -1,28 +0,0 @@
## Dialogs
[Original HTMX Version](https://htmx.org/examples/dialogs/)
## Demo
<div
id="dialogs"
data-on-load="$$get('/examples/dialogs_browser/data')"
>
</div>
## Explanation
Dialogs can be triggered with the standard browser `prompt` and `confirm` within an expression. These are triggered by the user interaction that would trigger the fetch, but the request is only sent if the dialog is accepted.
```html
<button
id="dialogs"
data-store="{prompt:'foo',confirm:false}"
data-fetch-url=""
data-on-click="$prompt=prompt('Enter a string',$prompt);$confirm=confirm('Are you sure?');$confirm && $$get('/examples/dialogs___browser/sure')"
>
Click Me
</button>
```
The value provided by the user to the prompt dialog is fed back into the store, and the confirm dialog is used to determine whether the request should be sent.

View File

@ -1,46 +0,0 @@
## Edit Row
[Original HTMX Version](https://htmx.org/examples/edit-row/)
## Demo
<div
id="edit_row"
data-on-load="$$get('/examples/edit_row/data')"
>
</div>
## Explanation
This example shows how to implement editable rows. First lets look at the row prior to editing:
```html
<tr id="contact_0">
<td>Joe Smith<//td>
<td>joe@smith.org</td>
<td>
<button data-on-click="$editRowIndex=0;$$get('/examples/edit_row/edit')" >Edit</button>
</td>
</tr>
```
This will tell trigger a whole table replacement as we are going to remove the `Edit` buttons from other rows as well as change out to inputs to allow editing. The `data-on-click` attribute sets a variable `$editRowIndex` to the index of the row that is being edited. This is used to determine which row to edit on the server side. Again we don't need alpine or hyperscript to do this, signals and actions are built-in.
Finally, here is what the row looks like when the data is being edited:
```html
<tr id="contact_0">
<td>
<input data-model="name" type="text" />
</td>
<td>
<input data-model="email" type="text" />
</td>
<td>
<button data-on-click="$$get('/examples/edit_row/data')">Cancel</button>
<button data-on-click="$$patch('/examples/edit_row/edit')">Save</button>
</td>
</tr>
```
Here we have a few things going on, clicking `Cancel` will bring back the read-only version of the row. Finally, there is a save button that issues a `PATCH` to update the contact.

View File

@ -1,38 +0,0 @@
## Fetch Indicator
## Demo
<div>
<div id="ind">Loading Indicator</div>
<button
class="bg-success-300 hover:bg-success-500 text-success-800 font-bold py-2 px-4 rounded"
data-on-click="$$get('/examples/fetch_indicator/greet')"
data-fetch-indicator="'#ind'"
data-testid="greeting_button"
data-bind-disabled="$$isFetching('#ind')"
>
Click me for a greeting
</button>
<div id="greeting"></div>
</div>
## Explanation
```html
<div id="ind">Loading Indicator</div>
<button
data-on-click="$$get('/examples/fetch_indicator/greet')"
data-fetch-indicator="'#ind'"
data-bind-disabled="$$isFetching('#ind')"
>
Click me for a greeting
</button>
<div id="greeting"></div>
```
The `data-fetch-indicator` attribute is used to specify the elements that should be made visible when the fetch request is in progress. The value of the attribute is a CSS selector that can represent multiple elements. The same `data-fetch-indicator` selector can be used by different elements at the same time.
The `$$isFetching("#ind")` action returns a computed value that allows you to easily react to the state of the indicator.
**Note:** The contents of the `data-fetch-indicator` is an expression. In this case, the expression is a string literal, hence the single quotes around the CSS selector.

View File

@ -1,42 +0,0 @@
## File Upload
[Original HTMX Version](https://htmx.org/examples/file-upload/)
## Demo
<div
id="file_upload"
data-on-load="$$get('/examples/file_upload/data')"
>
</div>
## Explanation
In this example we show how to create a file upload form that will be submitted via fetch.
```html
<!-- Removed styling for brevity -->
<div
id="file_upload" data-on-load="$$get"
data-store="{"files": [],"filesMimes": [],"filesNames": []}"
>
<div>
<label>
<span class="label-text">Pick anything reasonably sized</span>
</label>
<input type="file" data-model="files" multiple>
<button
data-fetch-url="'/examples/file_upload/upload'"
data-on-click="$$post">
Submit
</button>
</div>
</div>
```
We don't need a form because everything is encoded as signals and automatically sent to the server.
We `POST` the form to /upload, since the `input` is using `data-model` the file will be automatically encoded as base64. If your store includes `${signalName}Mimes` and `${signalName}Names` then those will be sent as well. All three signals are arrays and files / metainfo will be appended in the order of selection.
## Differences from HTMX
Since HTMX uses standard forms the [file upload is lost](https://htmx.org/examples/file-upload-input/) when the form is submitted. This is a limitation of the browser and not HTMX. However, since we are using signals we can send the file back down to the client and hook up to the signal if desired.

View File

@ -1,47 +0,0 @@
## Infinite Scroll
[Original HTMX Version](https://htmx.org/examples/infinite-scroll/)
## Explanation
The infinite scroll pattern provides a way to load content dynamically on user scrolling action.
Lets focus on the final row (or the last element of your content):
```html
<div
data-intersects="$offset=0;$limit=10;$$get('/examples/infinite_scroll/data')"
id="more_btn"
>
<div>Loading...</div>
</div>
```
This last element contains a listener which, when scrolled into view, will trigger a request. The result is then appended after it. The last element of the results will itself contain the listener to load the next page of results, and so on. `data-intersects` is a custom attribute that triggers a request when the element is scrolled into view. The `$offset` and `$limit` parameters are used to control the pagination of the results. The server sents back a new `more_btn` element with a new offset and the results to be appended.
```bash
event: datastar-fragment
data: selector #more_btn
data: merge morph_element
data: settle 500
data: fragment <div data-intersects="$offset=10;$limit=10;$$get('/examples/infinite_scroll/data')" id="more_btn"><div>Loading...</div></div>
event: datastar-fragment
data: selector #click_to_load_rows
data: merge append_element
data: settle: 500
data: fragment <<tr id=\"agent_60\"><td>Agent Smith 3c</td><td>void61@null.org</td><td class=\"uppercase\">39b02fcf39c047c5</td></tr>"
....More rows to be appended
```
## Demo
<div>
<div
id="infinite_scroll"
data-on-load="$$get('/examples/infinite_scroll/data')"
>
</div>
<div id="more_btn"></div>
</div>

View File

@ -1,17 +0,0 @@
## Inline Validation
[Original HTMX Version](https://htmx.org/examples/inline-validation/)
## Demo
The only email that will be accepted is test@test.com.
<div
id="inline_validation"
data-on-load="$$get('/examples/inline_validation/data')"
>
</div>
## Explanation
This example shows how to do inline field validation, in this case of an email address. To do this we need to create a form with an input that POSTs back to the server with the value to be validated and updates the DOM with the validation results. Since its easy to replace the whole form the logic for displaying the validation results is kept simple.

View File

@ -1,32 +0,0 @@
## Lazy Load
[Original HTMX Version](https://htmx.org/examples/lazy-load/)
## Demo
<style>
.datastar-settling {
opacity: 0;
}
</style>
<div id="lazy_load" data-on-load="$$get('/examples/lazy_load/data')">
</div>
## Explanation
This example shows how to lazily load an element on a page. We start with an initial state that looks like this:
```html
<div data-fetch-url="" data-on-load="$$get('/examples/lazy_load/graph')">
Loading...
</div>
```
Which shows a progress indicator as we are loading the graph. The graph is then loaded and faded gently into view via a settling CSS transition:
```css
.datastar-settling {
opacity: 0;
}
```

View File

@ -1,15 +0,0 @@
## Lazy Tabs
[Original HTMX Version](https://htmx.org/examples/tabs-hateoas/)
## Demo
<div
id="lazy_tabs"
data-on-load="$$get('/examples/lazy_tabs/data')"
>
</div>
## Explanation
This example shows how easy it is to implement tabs using Datastar. Following the principle of [Hypertext As The Engine Of Application State](https://en.wikipedia.org/wiki/HATEOAS), the selected tab is a part of the application state. Therefore, to display and select tabs in your application, simply include the tab markup in the returned HTML fragment.

View File

@ -1,11 +0,0 @@
## Merge Options
## Demo
<div id="contents" data-on-load="$$get('/examples/merge_options/reset')"></div>
## Explanation
Shows the current merge options available. For best understanding open up your dev tools and look at the contents of `#contents` to see how the merge options effect the DOM.
** Note:** This uses `#target` and can create multiple elements with the same ID (which is [not valid HTML](https://html.spec.whatwg.org/#the-id-attribute)) but is fine for this example. In actual use be sure to make IDs unique.

View File

@ -1,57 +0,0 @@
## Model Binding
## Demo
<div id="container" data-on-load="$$get('/examples/model_binding/data')"></div>
## Explanation
```html
<div
id="container"
data-store="{bindText:'foo',bindNumber:42,bindBool:true,bindSelection:1}"
>
<input type="text" data-model="bindText" />
<input type="number" data-model="bindNumber" />
<textarea data-model="bindText"></textarea>
<label>
<span>Checkbox</span>
<input type="checkbox" data-model="bindBool" />
</label>
<select data-model="bindSelection">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<div class="flex flex-col">
<label>
<input type="radio" data-model="bindSelection" value="1" />
<span>Option 1</span>
</label>
<label>
<input type="radio" data-model="bindSelection" value="2" />
<span>Option 2</span>
</label>
<label>
<input type="radio" data-model="bindSelection" value="3" />
<span>Option 3</span>
</label>
...
</div>
<code>
<pre data-star-text="JSON.stringify(ctx.store(),null,2)"></pre>
</code>
</div>
```
Current the two-way data binding generated by `data-model` supports
- `input`
- `textarea`
- `select`
- `checkbox`
- `radio`
**Note**: For radio buttons if you don't include a name for grouping the radio button will get the name of the signal as their name.
If there are more types that you need support for please [reach out](https://github.com/delaneyj/datastar)!

View File

@ -1,24 +0,0 @@
## Multiline Fragments
## Demo
<div id="replaceMe" data-on-load="$$get('/examples/multiline_fragments/data')">
</div>
## Explanation
As long as the fragment has a newline at the end of the line it will be treated as a multiline fragment. This is useful when you are writing a lot of text by hand.
```text
event: datastar-fragment
data: merge morph_element
data: settle 500
data: fragment
data: <div id="replaceMe">
data: <pre>
data: This is a multiline fragment.
data:
data: Used when you are writing a lot of text by hand
data: </pre>
data: </div>
```

View File

@ -1,125 +0,0 @@
## Explanation
An example backend in Node.
```js
const express = require("express");
const { randomBytes } = require("crypto");
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const backendData = {};
function indexPage() {
const indexPage = `
<!doctype html><html>
<head>
<title>Node/Express + Datastar Example</title>
<script type="module" defer src="https://cdn.jsdelivr.net/npm/@sudodevnull/datastar"></script></head>
<body>
<h2>Node/Express + Datastar Example</h2>
<main class="container" id="main" data-store='{ input: "", show: false }'>
<input type="text" placeholder="Type here!" data-model="input" />
<button data-on-click="$$put('/put')">Send State</button>
<div id="output"></div>
<button data-on-click="$$get('/get')">Get Backend State</button>
<div id="output2"></div>
<button data-on-click="$show=!$show">Toggle</button>
<div data-show="$show">
<span>Hello From Datastar!</span>
</div>
<div>
<span>Feed from server: </span>
<span id="feed" data-on-load="$$get('/feed')"></span>
</div>
</body>
</html>`;
return indexPage;
}
app.get("/", (req, res) => {
res.send(indexPage()).end();
});
function setHeaders(res) {
res.set({
"Cache-Control": "no-cache",
"Content-Type": "text/event-stream",
Connection: "keep-alive",
});
res.flushHeaders();
}
function sendSSE({ res, frag, selector, merge, mergeType, end }) {
res.write("event: datastar-fragment\n");
if (selector) res.write(`data: selector ${selector}\n`);
if (merge) res.write(`data: merge ${mergeType}\n`);
res.write(`data: fragment ${frag}\n\n`);
if (end) res.end();
}
app.put("/put", (req, res) => {
setHeaders(res);
const { input } = req.body;
backendData.input = input;
const output = `Your input: ${input}, is ${input.length} long.`;
let frag = `<div id="output">${output}</div>`;
sendSSE({
res,
frag,
selector: null,
merge: true,
mergeType: "morph_element",
end: true,
});
});
app.get("/get", (req, res) => {
setHeaders(res);
const output = `Backend State: ${JSON.stringify(backendData)}.`;
let frag = `<div id="output2">${output}</div>`;
sendSSE({
res,
frag,
selector: null,
merge: true,
mergeType: "morph_element",
end: false,
});
frag = `<div id="output3">Check this out!</div>;`;
sendSSE({
res,
frag,
selector: "#main",
merge: true,
mergeType: "prepend_element",
end: true,
});
});
app.get("/feed", async (req, res) => {
setHeaders(res);
while (res.writable) {
const rand = randomBytes(8).toString("hex");
const frag = `<span id="feed">${rand}</span>`;
sendSSE({
res,
frag,
selector: null,
merge: false,
mergeType: null,
end: false,
});
await new Promise((resolve) => setTimeout(resolve, 1000));
}
res.end();
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
```

View File

@ -1,22 +0,0 @@
## On load
## Demo
<div>
<div
id="replaceMe"
data-on-load="$$post('/examples/on_load/data')"
>No session data</div>
</div>
## Explanation
```html
<div id="replaceMe" data-on-load="$$post('/examples/on_load/data')">
No session data
</div>
```
The `data-on-load` attribute is used to specify a fetch request that should be made when the element is loaded. The value of the attribute is a JavaScript expression that is evaluated when the element is loaded. This example comes from a [Github issue](https://github.com/delaneyj/datastar/issues/15) where the user wanted to load session data when the page was loaded.
**Note:** In this case its targeting the `#replaceMe` element but its up to the SSE returned to how the page is updated.

View File

@ -1,15 +0,0 @@
## Progress Bar
[Original HTMX Version](https://htmx.org/examples/progress-bar/)
## Demo
<div
id="progress_bar"
data-on-load="$$get('/examples/progress_bar/data')"
>
</div>
## Explanation
This example shows how to implement an updating progress graphic. Since Datastar is using SSE this is very easy to implement. The server sends a progress value every 500 milliseconds, and the client updates the progress bar accordingly sending down a new SVG. After the progress is complete, the server a button to restart the job.

View File

@ -1,78 +0,0 @@
## Explanation
An example backend in Python.
```python
import os, json, time, secrets, uvicorn
from starlette.applications import Starlette
from starlette.responses import HTMLResponse, StreamingResponse
app = Starlette()
target = 'target'
def send_index():
store = {'input': '', 'output': '', 'show': True}
index_page = f'''
<!doctype html><html>
<head>
<title>Node/Express + Datastar Example</title>
<script type="module" defer src="https://cdn.jsdelivr.net/npm/@sudodevnull/datastar"></script></head>
<body>
<h2>Node/Express + Datastar Example</h2>
<main class="container" id="main" data-store=\'{json.dumps(store)}\'>
<input type="text" placeholder="Send to server..." data-model="input"/>
<button data-on-click="$$get('/get')">Send State Roundtrip</button>
<button data-on-click="$$get('/target')">Target HTML Element</button>
<button data-on-click="$show=!$show">Toggle Feed</button>
<div id="output" data-text="$output"></div>
<div id="{target}"></div>
<div data-show="$show">
<span>Feed from server: </span>
<span id="feed" data-on-load="$$get('/feed')"></span>
</div></main></body></html>
'''
return HTMLResponse(index_page)
def send_event(frag, merge=False):
yield 'event: datastar-fragment\n'
if merge:
yield 'data: merge upsert_attributes\n'
yield f'data: fragment {frag}\n\n'
def send_stream():
while True:
rand = secrets.token_hex(8)
frag = f'<span id="feed">{rand}</span>'
yield from send_event(frag)
time.sleep(1)
@app.route('/')
async def homepage(request):
return send_index()
@app.route('/get')
async def get_data(request):
store = json.loads(dict(request.query_params)['datastar'])
store['output'] = f"Your input: {store['input']}, is {len(store['input'])} long."
frag = f'<main id="main" data-store=\'{json.dumps(store)}\'></main>'
return StreamingResponse(send_event(frag, True))
@app.route('/target')
async def target_element(request):
today = time.strftime("%Y-%m-%d %H:%M:%S")
frag = f'<div id="{target}"><b>{today}</b></div>'
return StreamingResponse(send_event(frag))
@app.route('/feed')
async def feed(request):
return StreamingResponse(send_stream())
if __name__ == "__main__":
uvicorn.run(app, host="localhost", port=int(os.environ.get('PORT', 3000)))
```
```html
<div class="container">
<img src="foo.img" />
</div>
```

View File

@ -1,31 +0,0 @@
## Request Animation Frame Update
## Demo
<div data-store="{currentTime:Date.now()}" data-on-raf="$currentTime = Date.now()">
<div id="time">Current Time: <span data-text="new Date($currentTime).toLocaleString()">will be replaced by current time</span></div>
<pre data-text="JSON.stringify(ctx.store().value, null,2)"></pre>
</div>
## Explanation
In the [Title Update Backend](/examples/title_update_backend) example we showed how to update the title of the page using a server sent event fragment. In this example we show how to update the title of the page using a requestAnimationFrame event on the client side.
```html
<div
data-store="{currentTime:Date.now()}"
data-on-raf="$currentTime = Date.now()"
>
<div id="time">
Current Time:
<span data-text="new Date($currentTime).toLocaleString()"
>will be replaced by current time</span
>
</div>
<pre data-text="JSON.stringify(ctx.store().value, null,2)"></pre>
</div>
```
`data-on-raf` is a special event that is triggered on every requestAnimationFrame event. This is useful for updating the UI at maximum at the rendering refresh rate of the browser. In this example we update the currentTime store with a new Date object. This triggers a re-render of the currentTime span element. You can still use the `throttle` and `debounce` modifiers to control the rate of updates even further.
In this case we are updating the currentTime store with the current time. This triggers a re-render of the `currentTime` span element, however if you inspect with the browser debugger you will notice that `#time`'s `<span>` element is not updated every frame. This is because the signals are smartly updated only when the value changes. This is a performance optimization that is done by default.

View File

@ -1,10 +0,0 @@
## Redirects
## Demo
<div id="update" data-on-load="$$get('/examples/redirects/data')">
</div>
## Explanation
As part of SSE updates you may want to redirect the user to a different page. This can be done by returning a `data: redirect` event from the server. The client will then redirect the user to the specified URL.

View File

@ -1,18 +0,0 @@
## Scroll into View
## Explanation
We are highlighting the middle paragraph of the page to make it easier to see the scroll into view effect. Depending on the size of your browser window, you may need to scroll to see the effect. In this specific example the options are sent to the server to then send down the scroll command but normally you would just send the scroll command directly from the server.
**Note:** The defaults are to have smooth centered scroll. If you want to also focus() the element just add the `.focus` modifier.
```html
<p data-scroll-into-view.instant.vstart.hcenter id="p10"></p>
```
## Demo
<div
id="replaceMe"
data-on-load="$$get('/examples/scroll_into_view/data')"
>No session data</div>

View File

@ -1,18 +0,0 @@
## Shoelace Kitchensink
## Demo
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/themes/dark.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/shoelace-autoloader.js"></script>
<div
id="shoelace_kitchensink"
data-on-load="$$get('/examples/shoelace_kitchensink/data')"
>
</div>
## Explanation
[Shoelace](https://shoelace.style/) is a wonderful webcomponent library. It is a great fit for Datastar, because it is designed to be used with plain HTML. All the Datastar built-in plugins just work with Shoelace.
Note this is using a `nested` data store just to verify that works. The store gets sent will get sent to the server as the whole context of the client should be available to the server.

View File

@ -1,78 +0,0 @@
## Store Changed
## Demo
<div
data-store="{clicks:0, _localState: { bar: 1234}, _anotherLocalVar: 'hello'}"
data-on-store-change.remote="$$post('/examples/store_changed/updates')"
>
<div class="flex gap-4">
<button
id="increment"
class="btn btn-success"
data-on-click="$clicks++"
>Click Me</button>
<button
id="clear"
class="btn btn-warning"
data-on-click="$clicks=0; $$delete('/examples/store_changed/updates')"
>Clear Local & Server</button>
<button
id="reload"
class="btn btn-error"
data-on-click="window.location.reload()"
>Reload Page</button>
</div>
<div id="local_clicks">Local Clicks: <span data-text="$clicks"></span></div>
<div id="from_server"></div>
</div>
## Explanation
```html
<div
data-store="{clicks:0, _localState: { bar: 1234}, _anotherLocalVar: 'hello'}"
data-on-store-change.remote="$$post('/examples/store_changed/updates')"
>
<div>
<button id="increment" data-on-click="$clicks++">Click Me</button>
<button
id="clear"
data-on-click="$clicks=0; $$delete('/examples/store_changed/updates')"
>
Clear Local & Server
</button>
<button id="reload" data-on-click="window.location.reload()">
Reload Page
</button>
</div>
<div>Local Clicks: <span data-text="$clicks"></span></div>
<div id="from_server"></div>
</div>
```
`data-on-store-change` is a special event that is triggered when the store changes. This is useful for updating the UI when the store changes. In this example we update the `clicks` store with a new value. This triggers a re-render of the `clicks` span element. You can still use the `throttle` and `debounce` modifiers to control the rate of updates even further. In this case we are sending the store changes to the server to update the lifetime total clicks the server has seen.
**Note**: The `.remote` modifier is used to only trigger this event when remotely viewable signals are updated. This is useful for not sending data that is not needed to the server. To look at the details run `console.log(JSON.stringify(ds.store.value,null,2))` in the browser console. You should see something like
```json
{
"_dsPlugins": {
"on": {}
},
"_sidebarOpen": false,
"clicks": 0,
"_localState": {
"bar": 1234
},
"_anotherLocalVar": "hello"
}
```
Whereas if you look at the Network tab in the browser you should see the following request payload
```json
{ "clicks": 0 }
```
Any signal (or nested set of signals) starting with an underscore `_` is considered local and will not be sent to the server. In this example `_localState` and `_anotherLocalVar` are local only.

View File

@ -1,19 +0,0 @@
## Title Update Backend
## Demo
Look at the title change in the browser tab!
<div data-on-load="$$get('/examples/title_update_backend/updates')"></div>
## Explanation
A user [in the Discord channel](https://discord.com/channels/725789699527933952/1180902694999838752) was asking about needing a plugin similar to [HTMX's head support](https://v1.htmx.org/extensions/head-support/) to update title or head elements. With Datastar this is unneccessary as you can just update the title directly with a SSE fragment
```
event: datastar-fragment
data: selector title
data: fragment <title>08:30:36 from server</title>
```
In a similar fashion you can append, prepend directly to the HEAD element using [Merge Options](/examples/merge_options)

View File

@ -1,31 +0,0 @@
## Update Store directly
## Demo
<div
data-store='{"stuffAlreadyInStore":"this is already in the store"}'
>
<button
class="btn btn-success"
data-on-click="$$post('/examples/update_store/data/patch')"
>
Apply random signal patch
</button>
<pre
class="bg-accent border-2 border-accent text-accent text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5"
data-text="JSON.stringify(ctx.store(),null,2)"
>
Stuff in store
</pre>
</div>
## Explanation
This example demonstrates how to update the store directly from the frontend. This is using a SSE event
```text/event-stream
event: datastar-signal,
data: { HYAAA4BK7IFQE: "2024-05-23T10:33:14.167189214-07:00", stuffAlreadyInStore: "this is already in the store"}
```
It will accept anything that is also accepted by the `data-store` attribute.

View File

@ -1,51 +0,0 @@
# Batteries Included
## Build modular, think globally
Datastar was originally a branch of HTMX that was meant to make it more modular and easier to write plugins for. What was not expected is in creating what felt like essential plugins was actually able to recreate all the needed features of a full SPA frameworks, HTMX and Alpine and do it all in smaller package. While you can still build your own plugins, the core set of plugins is enough to build a full application. Let's explore some more features
## Evaluating data-\* attributes
Before we had used something like `data-text="$foo"` attribute. What this is actually doing under the hood is turning the string into a function that is evaluated safely into `(ctx)=> ctx.store.foo.value` where `ctx` is the Datastar object that was injected into the page. In this case its connected directly to the contents of a signal but you could do any javascript that is valid. This also means you could eval to a constant string but that would looks something like `data-text="'hello world'"`, notice the quotes, otherwise it would be looking for variable `hello world` which isn't valid and would fail to evaluate. This is the one major gotcha of declarative code, you have to be careful about the context.
## More attributes
So far we've seen `data-store`, `data-model` and `data-text`. There are many more attributes that can be used to make your page more reactive. Check out the API for a full list of attributes but here are a few more that get used the most.
### `data-show`
This is a simple way to show and hide elements. It's a simple way to do `v-if` in Vue or `x-show` in Alpine.
```html
<div data-show="$foo">Hello World</div>
```
When the `foo` signal is truthy the div will be shown, otherwise it will be hidden.
### `data-on`
This is a way to add event listeners to elements. It's a simple way to do `v-on` in Vue or `x-on` in Alpine.
```html
<button data-on-click="console.log('hello world')">Click me</button>
```
When the button is clicked it will log `hello world` to the console.
## Actions
Actions are helper functions that are made available during a data-\* attribute evaluation. They are a way to do more complex operations without having to write a lot of javascript. Here are a few of the most common actions. They are prefixed with `$$` to avoid any conflicts with other attributes.
### `$$setAll`
Sometimes you want to set multiple values at once. It takes a prefix regexp and a set of signals. For example if you have a form with a bunch of inputs and you want to set them all at once you could do something like this.
```html
data-text="$$setAll('contact_',true)`
```
### `$$toggleAll`
Works the same as `$$setAll` but will flip the value of the signals.
There can be many more actions and you can even write your own. But the majority of the time you'll be using the actions that allow for backend integration, which we'll cover in the next section.

View File

@ -1,359 +0,0 @@
# Getting Started
## A Birds Eye View
If you are familiar with libraries like [HTMX](https://htmx.org/) or [AlpineJs](https://alpinejs.dev/); Datastar brings them together. This breaks down essentially to:
1. Send the current UI from your backend via HTML fragments like HTMX.
2. Manage client side state that wouldn't make sense to be managed by your backend like AlpineJS.
I've had [thoughts](/essays/why_another_framework) on both of these in the past. TLDR; While both libraries are great, I wanted to go in a different direction.
Datastar accomplishes both tasks in a unified manner and it's [tiny](https://bundlephobia.com/package/@sudodevnull/datastar).
## Installation
To get started you must first get a copy of Datastar. There are a few ways to do this.
**Remotely**
You can include it directly into your html using a script tag:
```html
<script
type="module"
defer
src="https://cdn.jsdelivr.net/npm/@sudodevnull/datastar"
></script>
```
**NPM**
For npm-style build systems, you can install Datastar via npm and then import this in your server file.
```bash
npm i @sudodevnull/datastar
```
## A Quick Primer
Now let's get our feet wet. We'll walk through some ways to use Datastar with a quick example. For our example we'll just spin up an [Express](https://expressjs.com/en/starter/hello-world.html) server on Node. We'll have the server prepare a template for us when we first navigate to it.
You can copy the code below to get started. Don't worry, we've already installed Datastar for you using a [CDN](#remotely).
```js
const express = require("express");
const { randomBytes } = require("crypto");
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const backendData = {};
function indexPage() {
const indexPage = `
<!doctype html><html>
<head>
<title>Node/Express + Datastar Example</title>
<script type="module" defer src="https://cdn.jsdelivr.net/npm/@sudodevnull/datastar"></script></head>
<body>
<h2>Node/Express + Datastar Example</h2>
<main class="container" id="main"></main>
</body>
</html>`;
return indexPage;
}
app.get("/", (req, res) => {
res.send(indexPage()).end();
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
```
We have basic server set up. Now let's get to the fun part. Let's add some Datastar functionality.
## Handling State
Let's start out with how Datastar handles state. Enter the [store](/reference/plugins_core#merge-store) attribute.
Go ahead and add this as a data attribute to the `<main>` element:
```html
<main class="container" id="main" data-store='{ "input": "" }'></main>
```
This is the global store, if you make multiple stores they will actually merge into one store behind the scenes. If there are two fields with the same name, Datastar will resolve as last in wins.
The store is great and all but how can we use it? There are many ways. Let's check some of them out.
## Some Reactivity
If you had a keen eye, you noticed we put `input` as a field on our store. What's that about? Glad you asked! It's Datastar's way to sets up two-way data binding on an element. In our case this `input` element. Say hi to the [Model](/reference/plugins_attributes#model) attribute.
Stick this inside of your `<main>` element:
```html
<input type="text" placeholder="Type here!" data-model="input" />
```
This binds to a signal so our store can stay up to date with whatever is typed into this input. You can even nest your state like this `{"nested":{"label":"foo"}}` and use `data-model="nested.label"` or access it from the backend as needed.
Good stuff so far. How can we see this? We can check the changes locally using the [data-text](/reference/plugins_attributes#text) attribute.
Create a div in your `<main>` Element:
```html
<div data-text="$input"></div>
```
Sets the text content of an element to the value of the signal. Now check it out, client-side reactivity! We can have different types of state as well. We can even do fun stuff like `data-text="$value.toUpperCase()"`.
Speaking of which, let's do some more! Let's play hide 'n seek with the [data-show](/reference/plugins_visibility#show) attribute.
Add this to your store:
```js
{ input: "", show: false };
```
We can hide elements and show them without using JavaScript! How will we trigger this though?
## Events
We bring in the [On](/reference/plugins_attributes#on) attribute. This sets up an event listener on an element. In this example, we're using `data-on-click`. You will later see there are other `data-on` actions we can utilize. You can also do silly things like `data-on-click="console.log('hello world')"`.
Add this inside of your `<main>` element:
```html
<button data-on-click="$show=!$show">Toggle</button>
<div data-show="$show">
<span>Hello From Datastar!</span>
</div>
```
So what else can we do? You can mess around and do some fun stuff with expressions. For instance, something like: `"$prompt=prompt('Enter something',$prompt);$confirm=confirm('Sure?');$confirm && $$get('/sure')"` is totally feasible.
Anyhow, we haven't really even scratched the surface. Let's keep going.
## Backend Plumbing
Now, let's send some data. To do this there's a few things we must understand but it's all fun and easy and you'll want to know it if you do not already!
Datastar uses [Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) or SSE. To use SSE, we have to set our backend up for it. Luckily it's extremely simple and [provides us with many advantages](/essays/event_streams_all_the_way_down).
Let's set things up. Copy the below code to your server.
Copy this to your server code:
```js
function setHeaders(res) {
res.set({
"Cache-Control": "no-cache",
"Content-Type": "text/event-stream",
Connection: "keep-alive",
});
res.flushHeaders();
}
```
`setHeaders` is simple a utility function we will use on our endpoints to set our headers to use SSE.
Copy this to your server code:
```js
function sendSSE({ res, frag, selector, merge, mergeType, end }) {
res.write("event: datastar-fragment\n");
if (selector) res.write(`data: selector ${selector}\n`);
if (merge) res.write(`data: merge ${mergeType}\n`);
res.write(`data: fragment ${frag}\n\n`);
if (end) res.end();
}
```
We will use `sendSSE` as another utility function that will help us configure our response to fit SSE and Datastar formats. Let's check that out real quick.
## Stay In Formation
SSE messages are text-based and consist of one or more "events". Each event is separated by a pair (`\n\n`) of newline characters. An individual event consists of one or more lines of text, each followed by a newline character (`\n)`), and uses a simple key-value pair [format](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format).
For our Datastar example:
```
event: datastar-fragment // \n
id: 129618219840307262 // \n
data: merge morph_element // \n
data: fragment <div id="id">...</div> // \n\n
```
**NOTE** in the real message the comments and newlines wouldn't be visible
Each data message in the event is separated by a (`\n`) newline and each event is separated by a pair of (`\n\n`) newlines. If you notice that is what we are doing in `sendSSE` except with a little flavor added so we can tell Datastar what we want to do using [Datastar's format](/reference/plugins_backend#datastar-sse-event).
Now let's make our route.
Copy this to your server code:
```js
app.put("/put", (req, res) => {
setHeaders(res);
const { input } = req.body;
backendData.input = input;
const output = `Your input: ${input}, is ${input.length} long.`;
let frag = `<div id="output">${output}</div>`;
sendSSE({
res,
frag,
selector: null,
merge: true,
mergeType: "morph_element",
end: true,
});
});
```
So here you see we're setting our headers with `setHeaders`. We modify state that's stored specifically on the backend. This can be anything you want, like a database. Then we construct the response string much like HTMX and include the store attribute. We send the response with the `morph_element` merge type.
We need to make some changes now to reflect this.
Go ahead and modify your html.
Change this in your `<main>` element:
```html
<div data-text="$input"></div>
```
To this:
```html
<div id="output"></div>
```
Give ourselves a button to perform this action.
Add this to your `<main>` element:
```html
<button data-on-click="$$put('/put')">Send State</button>
```
...and give ourselves a place to show our new state on the client.
Voila! Now if you check out what you've done, you'll find you're able to send data to your `/put` endpoint and respond with HTML updating the output `div`. Neato!
Let's retrieve the backend data we're now storing.
Add this to your server code:
```js
app.get("/get", (req, res) => {
setHeaders(res);
const output = `Backend State: ${JSON.stringify(backendData)}.`;
let frag = `<div id="output2">${output}</div>`;
sendSSE({
res,
frag,
selector: null,
merge: true,
mergeType: "morph_element",
end: true,
});
});
```
And this to your HTML:
```html
<button data-on-click="$$get('/get')">Get Backend State</button>
<div id="output2"></div>
```
We're now fetching state that's stored on the backend.
Let's try something for fun. In your `/get` route, change your call to `sendSSE` so that we do not immediately end the request connection.
Change your `sendSSE` function call in your `\get` route.
```js
sendSSE({
...
end: false,
});
```
Add this to your `sendSSE` function below the first call:
```js
frag = `<div id="output3">Check this out!</div>;`;
sendSSE({
res,
frag,
selector: "#main",
merge: true,
mergeType: "prepend_element",
end: true,
});
```
Now you'll notice you're sending two events in one call. That's because Datastar uses SSE. So using `prepend_element` we're able to prepend what we want to a target element. We do this using a `selector` and in our case this is the `<main>` element. Good stuff! You can check out all of Datastar's event types [here](http://localhost:8080/reference/plugins_backend).
There's one last thing we're going to do. Let's add a simple data feed upon loading the page.
Copy this to your server code:
```js
app.get("/feed", async (req, res) => {
setHeaders(res);
while (res.writable) {
const rand = randomBytes(8).toString("hex");
const frag = `<span id="feed">${rand}</span>`;
sendSSE({
res,
frag,
selector: null,
merge: false,
mergeType: null,
end: false,
});
await new Promise((resolve) => setTimeout(resolve, 1000));
}
res.end();
});
```
Add this inside your `<main>` element:
```html
<div>
<span>Feed from server: </span>
<span id="feed" data-on-load="$$get('/feed')"></span>
</div>
```
I told you we would use another `data-on` action earlier and here it is. `data-on-load` will perform this request when the page loads. If you check things out now you should see a feed that updates using SSE upon loading. Cool!
Datastar supports all the verbs without requiring a `<form>` element: `GET, POST, PUT, PATCH, DELETE`.
So that concludes our primer! Check out the full code for our Node example [here](/examples/node).
If you're still here I imagine you want to know more. Let's define things a little better.
## A Better View
To be more precise, think of Datastar as an extension to HTML's [data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes). Using attributes, you can introduce state to your frontend, then access it anywhere in your DOM, or a backend of your choice. You can also setup events that trigger endpoints, then respond with HTML that targets fragments of your DOM.
- Declare global state: `data-store = "{foo: ''}"`
- Link-up HTML elements to state slots: `data-model = "foo"`
- Adjust HTML elements text content: `data-text = "$foo"`
- Hookup other effects on your DOM to the state: `data-show= "$foo"`
- Setup events using `data-on-(load or click) = "$$get(/endpoint)"`
- Respond in HTML wrapped in SSE with a target element ID to update
It's that simple. To dive deeper check out some of the other links or just click below.

View File

@ -1,134 +0,0 @@
# Go Deeper
## Javascript Fatigue
Web development has become a technical occultism activity, in which the focus is on JavaScript and the capabilities of making HTML content dynamic instead of making a better job of delivering HTML. This JavaScript religion has led to the rise of frontend frameworks such as React, Vue, Svelte, Solid, etc. In turn those were not enough for full application and progress led the industry to full-stack JavaScript frameworks like Next.js, Nuxt, Svelte and Solid Start. Once you need a framework for reactivity it makes sense to embrace it in the backend too for consistency.
In reality almost all frameworks come down to updating the DOM as fast and as simply as possible with some effort around improving developer experience.
## Philosophy
- **Be declarative**
- **Use signals**
- **Supply a set of plugins that handle 99% of problems**
Datastar started as just a plugin framework but found that by having no overlap in features, it was possible to replace any SPA framework and even hypermedia focused libraries like HTMX while being much smaller and _(we think)_ easier to use.
With Datastar, even if you have never coded before, with a few examples, you can easily create high interconnected web assets. It doesn't matter if you are a making a user interface for bank or a simple blog. The approach is simplicity through declarative HTML.
If Datastar doesn't match your needs, you still might be interested in using it as originally intended [and write your own library](https://github.com/delaneyj/datastar/tree/main/library/src/lib/plugins).
## Time to think declaratively
Declarative code is amazing.
```sql
SELECT *
FROM orders
WHERE state='completed'
ORDER BY time DESC
LIMIT 10
```
This is SQL. As a user you don't have to know how the query will get executed, its up to the engine used. Sure you can read the query plan or introspect indexes but you can start at a high level and drill down only when necessary.
HTML work in a similar fashion. You don't have to worry about how a `<div>Hello</div>` turned into pixels nor how the page uses resources when you tab away. This is wonderful for the majority of cases but at least in modern HTML is a bit limiting.
For example:
```html
...PSEUDO CODE..
<div>
<label>HELLO WORLD</label>
<input value="hello world" />
</div>
```
if you want to use the result of changing the input to modify the label you have to write code. What if we could extend HTML to make that process declarative? Well funny you ask...
## Custom data attributes
Luckily HTML5 has the concept of [data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes) which allows anyone to add thier own attributes and still be valid HTML. The only real requirement is they be kebab-cased and start with `data-*`. Data star... that'd be a clever name... oh I get it!
Before we can actually use the `data-*` we need a quick aside about signals.
## Signals
Signals are a way to do fine grain reactivity in a very efficient way. They are similar to formulas in Excel. Instead of doing something like:
```js
let a = 2;
let b = 2;
let c = a * b;
console.log(c);
```
You can do:
```js
const a = signal(2);
const b = signal(2);
const c = computed(() => a() * b());
effect(() => {
console.log(c());
});
```
The difference is if you change `a` or `b`, `c` will auto schedule for updates. So you spend your time declaring relationships more than procedures. They have been popularized by [Solid,js](https://www.solidjs.com/) but are now used by many frameworks.
## The Store
Ok so back to our hypothetical framework let's have a way to declare stuff that can setup signals on the page using `data-*` attributes.
```html
<div data-store="{value:'hello world'}"></div>
```
The contents is just a set of data that can evaluated by [JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) and will convert this data into a tree of signals and merge into a store that tracks all of the reactivity on the page. In this case we want there to be a a single `value` signal with the contents of `'hello world'`.
## Models
Let's replace the hard coded value in the input with another attribute
```html
<div data-store="{value:'hello world'}">
<label>HELLO WORLD</label>
<input data-model="value" />
</div>
```
Here we've created a new attribute `data-model` with the contents of `value`. We are just saying when the signal `value` changes **or** input is edited on the page make sure you keep them in sync. We don't care how, just do it.
## Contents
Now we want to update the label relationship.
```html
<div data-store="{value:'hello world'}">
<label data-text="$value"></label>
<input data-model="value" />
</div>
```
Here we've added another attribute `data-text` but the content has a `$` prefix. Remember that `data-*` attributes _are just strings_, which means we can give any semantics we want as long as it's consistent. It this case we are designating the use of a signal by adding a `$` prefix. Now went the `value` signal updates, so will the `innerHTML` of the label. Pretty neat.
However it doesn't yet match the original intent, which was to make it uppercase, so let's make a quick adjustment.
```html
<div data-store="{value:'hello world'}">
<label data-text="$value.toUpperCase()"></label>
<input data-model="value" />
</div>
```
So with this change and in a declarative nature you'd be able extend HTML and focus on relationships.
Our HTML looks pretty neat but what would it take to make it actually work? Well just add:
```html
<script src="https://cdn.jsdelivr.net/npm/@sudodevnull/datastar"></script>
```
somewhere on your page and it should **_just work_**. If you look at the dev tools of your browser you'll also see its tiny compared to any other full framework and we haven't scratched the surface of what's included.
So far looking a lot like [Alpine.js](https://alpinejs.dev/) which is great, but as we add more features will diverge.

View File

@ -1,15 +0,0 @@
# Hypermedia, lost knowledge and H.A.T.E.O.A.S.
The rise of the frontend framework wars makes sense. When compared with full page reloads, the ability to update only the parts of the page that need to change is a huge win. However, the way this is done is often at odds with the declarative nature of HTML. This has led to a lot of lost knowledge and a lot of confusion. When your application logic lives in both browser and backend your synchronization state is in constant flux.
One of the biggest loses of knowledge is the concept of hypermedia. Hypermedia is the idea that the web is a set resources that are interconnected. This is the basis of the web and the reason it has been so successful. However, the rise of the frontend framework wars has led to a lot of confusion about how to use hypermedia. This is where H.A.T.E.O.A.S. comes in.
## Hypermedia as the Engine of Application State (H.A.T.E.O.A.S.)
Browsers don't care about your application, they care about the rendering hypermedia. For example if you have a bank website you can go to the home page and then click on a link to go to the login page, only then are valid links to your accounts available. This has huge benefits.
1. Each interaction fuels the valid next state.
2. When implemented correctly this means the backend is where all your logic lives, leading to no client side routers, validation, etc.
3. HTML can be generated in any language.
## Hypermedia on whatever you Like (HOWL)
[Carson Gross](https://hypermedia.systems/) coined the term [HOWL stack](https://htmx.org/essays/hypermedia-on-whatever-youd-like/) which is really just getting back to the roots of the web. People make fun of HTML not being a real language but its a wonderful way of exchanging interconnect assets. The HOWL stack is about leveraging the web's capabilities and with just a thin set of shims make it as powerful as any SPA framework. This is the basis of Datastar.

View File

@ -1,65 +0,0 @@
# Streaming Backend
HTMX is amazing for resurrecting the server rendered web. In general its far easier and faster than SPA development but there are still a few issues.
- For any larger page you have to add [hyperscript](https://hyperscript.org/) or [Alpine.js](https://alpinejs.dev/) to make the page reactive.
- There are multiple ways to target the elements on the page with `hx-target` and [out of band swaps](https://htmx.org/attributes/hx-swap-oob/). This if flexible but leads to a ton of ways to do the same thing.
- Responses are still single responses. If you want to have multiple updates as soon as possible you need to use plugins that aren't well supported (at this time).
- The list of `hx-*` attributes is growing quickly and think it points to a bigger issue with scope.
None of these are deal breakers but starting from first principles we can do better. The first thing we need to do is make the page reactive. We can do this by using [SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) or [Websockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). We'll use version of SSE because
- At the end of the day its "just" a HTTP request. All your sessions, cookies, etc are still valid.
- Websockets are harder to deal with depending on sticky sessions and load balancers.
- Websockets aren't compatible with HTTP2/3. Datastar will probably move to [WebTransport](https://web.dev/webtransport/) when its more available (looking at you Apple).
- HTTP2/3 is already multiplexed so you can have multiple SSE streams open at once.
## SSE
If you aren't familiar with SSE its a way to a chunked response to the browser. The browser will automatically reconnect if the connection is lost. The server can also send a `retry` header to tell the browser how often to reconnect. The browser will also automatically reconnect if the connection is lost. The nice part of having a chunked response is you can send multiple updates or a single update and the browser will handle it. A modern backend HTTP server framework should allow for easy SSE support (it's just a few headers and a specific text format for content).
## SSE backend, fetch on the frontend
For a reason that I still haven't figured out, the SSE spec and [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) only supports GET requests. This seems like a huge oversight, but we can work around it. From the backend's perspective they can send a `Content-Type: text/event-stream` from any request. This means we can use a normal `fetch` request to get the SSE stream. The only downside is we have to manually handle the reconnects. This is handled by Datastar but it's good to be aware of.
## Let's get some data
On the [home page](/) there is a global store example. When you first load the page the contents is basically empty.
```html
<div id="global-count-example" data-on-load="$$get('/api/globalCount')">
<span>Loading example on delay...</span>
<div class="spinner datastar-indicator"></div>
</div>
```
Normally you don't need to do this but its trying to show that you can load a page and then have the data update. The `$$get` action is a helper function that will make a fetch request and update the store with the results. The `datastar-indicator` class is a helper class that will show a spinner when the request is in flight.
On the backend (Go in this case) we return a set of render fragments in the form of a set of `text/event-stream` events. In this case it's just a single event.
```go
event: datastar-fragment
id: 129618219840307262
data: selector
data: merge morph_element
data: settle 0
data: fragment <div ...>...</div>
```
The `selector` is the CSS selector that the fragment will be inserted into. The `merge` decides how the element is added to the page. `morph_element` uses [idiomorph](https://github.com/bigskysoftware/idiomorph) to merge into the page intelligently. The `settle` is the time in milliseconds that the fragment will be inserted. The `fragment` is the HTML that will be inserted into the page. If you are familiar with HTMX and the the structure of SSE messages this should look quite familiar. Nice thing is most of these are optional (except for `fragment`) and can be optionally added to the response. In the case of the Go implementation it includes all for the sake of completeness.
This is still a lot to explore but the main point is that we can have a reactive page without having to write any Javascript. This is the power of declarative code. I'd suggest you check out the [examples](/examples) to see how this all fits together. Then when you have a specific question check out the [reference](/reference) for more details.
# Conclusion
Please don't hesitate to reach out if you have any questions. We are always looking for feedback and ways to improve. If you are interested in contributing please check out the [Github](https://github.com/delaneyj/datastar)
# Choose your own adventure
<div class="flex gap-4 items-center">
<a href="/examples" class="flex-1 no-underline p-4 rounded-md bg-primary-600 text-center hover:bg-primary-500">Show me</a>
<a href="/reference" class="flex-1 no-underline p-4 rounded-md bg-primary-600 text-center hover:bg-primary-500">Let me dig in</a>
<a href="/essays" class="flex-1 no-underline p-4 rounded-md bg-primary-600 text-center hover:bg-primary-500">Pontificating</a>
</div>

View File

@ -1,67 +0,0 @@
# Attribute Plugins
[Source](https://github.com/delaneyj/datastar/blob/main/library/src/lib/plugins/attributes.ts)
Primarily used to help hook up the store and the DOM.
## Attributes Plugins
### Bind
```html
<div data-bind-disabled="$iShouldBeDisabled"></div>
```
Allows any valid attribute to be bound to an expression. This is useful for making elements reactive. Also can be used as a fallback for any attribute that is not supported by a plugin currently.
### Model
```html
<input data-model="foo" />
```
Sets up two-way data-binding on an element.
**Note:** Always binds to a signal and therefore should exclude the `$` prefix from the signal name. Only allowed on `input`,`textarea`, `select`, `checkbox` and `radio` elements.
### Text
```html
<div data-text="$foo"></div>
```
Sets the text content of an element to the value of the signal. This is useful for setting the text content of an element to a signal value. Can use any expression that is valid in the system. For example, `data-text="$foo + 'bar'"` would set the text content to the value of `$foo` plus the string `bar`.
### On
```html
<button data-on-click="$$fn('foo','bar',1234)">Click Me</button>
```
Sets up an event listener on an element. The event listener will trigger the action specified in the expression. The expression can be any valid expression in the system. For example, `data-on-click="$$fn('foo','bar',1234)"` would trigger the action `fn` with the arguments `'foo','bar',1234` when the button is clicked.
If any signal in the expression changes, the event listener will be updated to reflect the new value of the signal automatically.
**Note:** the `data-on-*` matches DOM events, however there are currently a few special cases for custom events.
1. `data-on-load` which is triggered when the element is loaded into the DOM.
2. `data-on-store-change` which is triggered when the store changes.
3. `data-on-raf` which is triggered on every requestAnimationFrame event.
#### Modifiers
- `.once`\* - Only trigger the event once
- `.passive`\* - Do not call `preventDefault` on the event
- `.capture`\* - Use a capture event listener
- `.debounce` - Debounce the event listener
- `_1000ms` - Debounce for 1000ms
- `_1s` - Debounce for 1s
- `_leading` - Debounce with leading edge
- `_noTrail` - Debounce without trailing edge
- `.throttle` - Throttle the event listener
- `_1000ms` - Throttle for 1000ms
- `_1s` - Throttle for 1s
- `_noLead` - Throttle without leading edge
- `_noTrail` - Throttle without trailing edge
\*only works currently on native events

View File

@ -1,84 +0,0 @@
# Backend Plugins
[Source](https://github.com/delaneyj/datastar/blob/main/library/src/lib/plugins/backend.ts)
A set of plugins that allow for the integration of any backend services that supports SSE with Datastar.
## Attribute Plugins
Request for data from the server via SSE and merge with the page.
## Action Plugins
### `$$get`, `$$post`, `$$put`, `$$patch`, `$$delete`
```html
<div data-on-click="$$get('/examples/click_to_edit/contact/1')"></div>
```
Makes an HTML_VERB request to the server and merges the response with the current DOM and store. The URL can be any valid URL but the response must be a Datastar formatted SSE event.
Every request will be sent with a `{datastar: *}` object containing the current store. When using `$$get` the store will be sent as a query parameter, otherwise it will be sent as a JSON body.
## Datastar SSE Event
An example of a minimal valid response would be:
```go
event: datastar-fragment
data: fragment <div id="foo">Hello!</div>
```
Addtional `data` lines can be added to the response to override the default behavior.
| Key | Description | Default | |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | --- |
| `data: selector #foo` | Select the target element using a CSS selector. Will be come the target of the `merge` process, otherwise it will use the target of the initiating element's id. | |
| `data: merge morph_element` | Merge the fragment using [Idiomorph](https://github.com/bigskysoftware/idiomorph). | \* |
| `data: merge inner_html` | Replace target's innerHTML with fragment | |
| `data: merge outer_html` | Replace target's outerHTML with fragment | |
| `data: merge prepend_element` | Prepend fragment to target's children | |
| `data: merge append_element` | Append fragment to target's children | |
| `data: merge before_element` | Insert fragment before target as sibling | |
| `data: merge after_element` | Insert fragment after target as sibling | |
| `data: merge delete_element` | Remove target from the DOM | |
| `data: merge upsert_attributes` | Merge attributes from fragment into target, useful when wanting to just update a store | |
| `data: settle 1000` | Settle the element after 1000ms, useful for transitions. Defaults to `500` if missing | \* |
| `data: fragment` | The HTML fragment to merge into the DOM. **_Should only be one per event_** | \* |
| `data: redirect /foo` | Redirect the page to `/foo`. Can be used in place of a `data: fragment` **_Should only be one per event_** | |
| `data: error oh noes` | Will throw an error with the message `oh noes` and stop the request. Can be used in place of a `data: fragment` **_Should only be one per event_** | |
## Attribute Plugins
### Header
```html
<div data-header-X-My-Header="foo"></div>
```
Add a header to the request. This can be used to send additional information to the server.
### Fetch Indicator
```html
<svg id="foo">Spinner</svg>
<div
data-on-click="$$get('/examples/click_to_edit/contact/1')"
data-fetch-indicator="#foo"
></div>
```
Show a spinner when the request is in flight. The `data-fetch-indicator` attribute should be a CSS selector to the element(s). When the attribute is present, the element will be hidden when requests are not in flight and shown when they are.
### Is Loading Identifier
```html
<svg data-show="$isLoading.includes('edit-contact')">Spinner</svg>
<div
data-on-click="$$get('/examples/click_to_edit/contact/1')"
data-is-loading-id="edit-contact"
></div>
```
The `data-is-loading-id` attribute is used to specify the name of the identifier that will be present in the store's isLoading array when an element is fetching.

View File

@ -1,37 +0,0 @@
# Core Plugins
[Source](https://github.com/delaneyj/datastar/blob/main/library/src/lib/plugins/core.ts)
These are the only plugins that are required in order to have a working system. In the default build all (including core) plugins are included as they cover the most common use cases.
## Attributes Plugins
### MergeStore
```html
<div data-store="{foo:1234}"></div>
```
Takes the contents of the attribute and runs a BigInt aware JSON parse on it. It then merges the contents into the store. This can be used anywhere as the store is a global singleton. All keys are converted into signals, works with nested objects.
### Ref
```html
<div data-ref="foo"></div>
```
Makes an element available in the `ctx.refs` object. This is useful for accessing elements in the DOM. Can be accessed in scripts via `~foo`.
## Preprocessor Plugins
### SignalProcessor
Takes a `$var` and converts into a `ctx.store().var.value`. Since all expressions are evaluated within an effect it setups of a reactive system.
### ActionProcessor
Takes a `$$fn('foo','bar',1234)` and converts into a `ctx.actions.fn('foo','bar',1234()`. This is used to trigger actions plugins.
### RefProcessor
Takes a `~foo` and converts into a `ctx.refs.foo`. This is used to access refs similar to how you would in a Vue or Svlete components.

View File

@ -1,9 +0,0 @@
# Expressions
Expressions are the building blocks of Datastar. In fact, Datastar started as just a way to take `data-*` attributes and turn them into expressions. For exact `data-*` attribute found
1. All `Preprocesser` plugins are run. This allows for a custom DSL. The included plugins use `$` for signals, `$$` for actions, and `~` for refs. The plugins check for regular expressions and replace them with the appropriate value. Some plugins will setup extra state on load like adding CSS classes or setting up event listeners.
2. All Datastar `AttributePlugin` plugins are run in order. Most of the time these plugins are creating `effect()` signals so that that changes to the expression with automatically update the DOM and other parts of the system.
3. Check for any elemen removals and cancel any effects that are no longer needed.
Each expression is evaluated in a new Function declaration and not in a call to `eval()`. This is done to prevent access to the global scope and to prevent access to the `Function` constructor. This is done to prevent XSS attacks. Its also why all expressions take a `ctx` which has access to the store, actions, and refs, but not the global scope. This was gleamed from how Alpine.js works but with a different reactive model.

View File

@ -1,27 +0,0 @@
# Action Plugins
[Source](https://github.com/delaneyj/datastar/blob/main/library/src/lib/plugins/helpers.ts)
## `$$setAll(regexp: string, value: any)`
```html
<div data-on-change="$$setAll('contact_', $selections.all)"></div>
```
Sets all the signals that start with the prefix to the value of the second argument. This is useful for setting all the values of a form at once.
## `$$toggleAll(regexp: string)`
```html
<div data-on-click="$$toggleAll('contact_')"></div>
```
Toggles all the signals that start with the prefix. This is useful for toggling all the values of a form at once.
## `$$clipboard(text: string)`
```html
<div data-on-click="$$clipboard('Hello, world!')"></div>
```
Copies the text to the clipboard. This is useful for copying text to the clipboard.

View File

@ -1,73 +0,0 @@
# Visibility Plugins
[Source](https://github.com/delaneyj/datastar/blob/main/library/src/lib/plugins/visibility.ts)
Focused on showing and hiding elements based on signals. Most of the time you want to send updates from the server but is useful for things like modals, dropdowns, and other UI elements.
## Attributes Plugins
### Show
```html
<div data-show="$showMe"></div>
```
Shows the element when the expression is true.
### Intersects
```html
<div data-intersects="console.log('I am intersecting!')"></div>
```
Runs the expression when the element intersects with the viewport.
#### Modifiers
- `.once` - Only trigger the event once
- `.half` - Trigger when half of the element is visible
- `.full` - Trigger when the full element is visible
### Teleport
```html
<div data-teleport="#foo"></div>
```
Moves the element to the target.
#### Modifiers
- `.prepend` - Prepend the element to the target
- `.append` - Append the element to the target
### Scroll Into View
```html
<div data-scroll-into-view></div>
```
Scrolls the element into view. Useful when updating DOM from the server and you want to scroll to the new content.
#### Modifiers
- `.smooth` - Scrolling should be animate smoothly
- `.instant` - Scrolling should be instant
- `.auto` - Scrolling is determined by the computed `scroll-behavior` CSS property
- `.hstart` - Scroll to the left of the element
- `.hcenter` - Scroll to the horizontal center of the element
- `.hend` - Scroll to the right of the element
- `.hnearest` - Scroll to the nearest horizontal edge of the element
- `.vstart` - Scroll to the top of the element
- `.vcenter` - Scroll to the vertical center of the element
- `.vend` - Scroll to the bottom of the element
- `.vnearest` - Scroll to the nearest vertical edge of the element
- `.focus` - Focus the element after scrolling
### View Transition
```html
<div data-view-transition="foo"></div>
```
Page level transitions are automatically handled by an injected meta tag. Inter-page elements are automatically transitioned if the [View Transition API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) is available. To set the `view-transition-name` style attribute explictily you use the `data-view-transition` attribute. The spec is still in draft and not available in all browsers but Datastar will do best effort.

View File

@ -1,6 +0,0 @@
# Revision history for data-star
## 0.1.0.0 -- 2024-05-13
* First version. Reproduce datastar server.js example in Haskell

View File

@ -1,5 +0,0 @@
You should be able to run this with just a:
cabal run

View File

@ -1,207 +0,0 @@
module Main where
import Control.Applicative ( Alternative((<|>)) )
import Control.Concurrent ( threadDelay )
import Control.Exception ( SomeException, handle, throw )
import Control.Monad ( when )
import Control.Monad.IO.Class ( MonadIO(..) )
import Data.Aeson ( FromJSON, ToJSON, encode, decodeStrict )
import Data.ByteString.Builder ( Builder, hPutBuilder, byteString )
import Data.ByteString.Builder.Extra ( flush )
import Data.Convertible.Utf8 ( Convertible(..) )
import Data.Maybe ( fromMaybe )
import Data.String ( IsString )
import Data.Time.Clock ( getCurrentTime )
import GHC.Generics ( Generic )
import NeatInterpolation ( trimming )
import Snap
import Snap.Util.FileServe ( serveDirectory )
import System.IO
( hSetBuffering, stderr, stdout, BufferMode(NoBuffering) )
import System.Random ( RandomGen, mkStdGen, Random(randomR) )
import qualified System.IO.Streams as Streams
( OutputStream, write )
data Datastar = Datastar {
input :: !String
, output :: !String
, show :: !Bool
} deriving (Show, Generic)
instance FromJSON Datastar
instance ToJSON Datastar
target :: String -- like const target = "target"; in server.js
target = "target"
makeIndexPage :: String -> Builder
makeIndexPage x = byteString . convert $ [trimming|
<head>
<title>Node/Express + Datastar Example</title>
<script type="module" defer src="/datastar.js"></script>
</head>
<body>
<h2>Node/Express + Datastar Example</h2>
<main class="container" id="main" data-store="{input:'', output:'', show: true}">
<input type="text" placeholder="Send to server..." data-model="input"/>
<button data-on-click="$$$$get('/get')">Send State Roundtrip</button>
<button data-on-click="$$$$get('/target')">Target HTML Element</button>
<button data-on-click="$$show=!$$show">Toggle Feed</button>
<div id="output" data-text="$$output"></div>
<div id="$y"></div>
<div data-show="$$show">
<span>Feed from server: </span>
<span id="feed" data-on-load="$$$$get('/feed')"></span>
</div>
<h5>Datastar Store</h5>
<pre data-text="JSON.stringify(ctx.store(),null,2)"></pre>
</main>
</body>
</html>|]
where y = convert x
htmlify :: ToJSON p => p -> String
htmlify x = go (convert . encode $ x) []
where
go [] acc = acc -- I could have used regexp, bud it isn't the "Haskell way"
go (a:as) acc = if a == '"' then go as (acc <> "&quot;") else go as (acc <> [a])
setHeaders :: MonadSnap m => (Streams.OutputStream Builder -> IO ()) -> m ()
setHeaders f = do
escapeHttp $ \tickle _ writeEnd -> do
tickle (max (60*60))
writeStream (WriteBuilder sseHeaders) writeEnd
f writeEnd
sseHeaders :: Builder
sseHeaders = byteString . convert $ [trimming|
HTTP/1.1 200 OK
server: Snap/1.1.2.1
cache-control: no-cache
connection: keep-alive
Content-type: text/event-stream; charset=utf-8
|] <> "\n\n"
data SSE = SSE { -- A little data type to decode the store
frag :: !String
, merge :: !Bool
, end :: !Bool
} deriving Show
datastarSetupFragment :: MonadIO m => SSE -> Streams.OutputStream Builder -> m ()
datastarSetupFragment sse writeEnd = do
liftIO $ handle handleSSEexception $ do
writeStream (WriteBuilder "event: datastar-fragment\n") writeEnd
when (merge sse)
(writeStream (WriteList ["data: merge upsert_attributes\n"]) writeEnd)
writeStream (WriteList ["data: fragment ", frag sse, "\n\n"]) writeEnd
writeStream Flush writeEnd
when (end sse) (writeStream Stop writeEnd)
where
handleSSEexception :: SomeException -> IO ()
handleSSEexception e = print e >> throw e
-- A little DSL so I can watch the messages
data SW = Flush | WriteBuilder !Builder | WriteList ![String] | Stop
writeStream :: SW -> Streams.OutputStream Builder -> IO ()
writeStream Flush writeEnd = do
putStrLn "Flush"
Streams.write (Just flush) writeEnd
writeStream Stop writeEnd = do
putStrLn "Stop"
Streams.write Nothing writeEnd
writeStream (WriteBuilder builder) writeEnd = do
putStr "WriteBuilder "
hPutBuilder stdout builder
Streams.write (Just builder) writeEnd
writeStream (WriteList strs) writeEnd = do
putStr "WriteList "
putStr . mconcat $ strs
Streams.write (Just (toBuilder strs)) writeEnd
decodeDatastar :: Snap Datastar
decodeDatastar = do
mbBS <- getParam "datastar"
let
bs = fromMaybe (error "In decodeDatastar, expected parameter datastar to exits") mbBS
ds = fromMaybe (error ("bad decoding in decodeDatastar " <> Prelude.show bs)) (decodeStrict bs)
return ds
handlerGet :: Snap ()
handlerGet = do
store <- decodeDatastar
let
storeInput = input store
storeOutput = mconcat ["Yout input: ", storeInput, ", is ", Prelude.show . length $ storeInput, " long."]
newStore = store { output = storeOutput }
frag1 = mconcat ["<main id=\"main\" data-store=\"", htmlify newStore, "\"></main>" ]
sse = SSE frag1 True True
setHeaders (datastarSetupFragment sse)
-- This example is a little silly in haskell because of the lack of string interprolation that
-- is present in javascript. In the JS example, target is a variable which contains the string
-- "target". In haskell, while you can do interpolation with template haskell, it is more of
-- a hassle, so I am just using the monoid instance
handlerTarget :: Snap ()
handlerTarget = do
stamp <- liftIO $ Prelude.show <$> getCurrentTime
let
frag1 = mconcat ["<div id=\"", target , "\"><b>", stamp, "</b></div>"]
sse = SSE frag1 False True
setHeaders (datastarSetupFragment sse)
handlerFeed :: Snap ()
handlerFeed = do
liftIO $ putStrLn "enter handlerFeed"
let
loop g writeEnd = do
let
(str, g') = randomHex g
msg = mconcat ["<span id=\"feed\">", str, "</span>"]
sse = SSE msg False False
datastarSetupFragment sse writeEnd
liftIO $ threadDelay 1000000 -- Delay for 1 second
_ <- loop g' writeEnd
return ()
setHeaders (loop (mkStdGen 0))
where
-- randomR :: RandomGen g => (a, a) -> g -> (a, g)
-- iterate :: (a -> a) -> a -> [a]
randomHex :: RandomGen g => g -> (String,g)
randomHex g = (str,newG)
where
hex = "0123456789ABCDEF"
f x = randomR (0,15) (snd x)
f8 = take 8 . drop 1 $ iterate f (0,g)
asChar (i,_) = hex !! i
str = map asChar f8
newG = snd . last $ f8
toBuilder :: (Convertible a Builder, Monoid a, IsString a) => [a] -> Builder
toBuilder = convert . mconcat
main :: IO ()
main = do
hSetBuffering stdout NoBuffering
hSetBuffering stderr NoBuffering
let
mbPort = getPort (defaultConfig :: Config Snap a)
newConfig = setPort (fromMaybe 3000 mbPort) (defaultConfig :: Config Snap a)
conf <- commandLineConfig newConfig
print conf
simpleHttpServe conf site
site :: Snap ()
site =
ifTop (writeBuilder $ makeIndexPage target) <|> -- writeBuilder defined in Snap.Core
route [
("favicon.ico" , return ())
, ("get" , handlerGet)
, ("feed" , handlerFeed)
, ("target" , handlerTarget)
] <|> (serveDirectory "www")

Some files were not shown because too many files have changed in this diff Show More