From d26fe4709d71e05f304d65c5a2b02a90791a36a0 Mon Sep 17 00:00:00 2001
From: Alexander Petros
Date: Thu, 12 Oct 2023 18:01:34 -0400
Subject: [PATCH] Remove the last of the go code (#1890)
Update the website tests with the latest tests on master, deleting the
mirrored go code in the process.
---
www/static/src/ext/client-side-templates.js | 22 +-
www/static/test/ext/client-side-templates.js | 8 +-
www/static/test/realtime/README.md | 57 ---
www/static/test/realtime/go.mod | 22 --
www/static/test/realtime/go.sum | 52 ---
www/static/test/realtime/server.go | 350 ------------------
www/static/test/realtime/static/index.html | 52 ---
.../test/realtime/static/sse-simple-ext.html | 26 --
.../test/realtime/static/sse-simple.html | 26 --
.../realtime/static/sse-triggers-ext.html | 26 --
.../test/realtime/static/sse-triggers.html | 26 --
www/static/test/servers/ws/README.md | 15 -
www/static/test/servers/ws/go.mod | 23 --
www/static/test/servers/ws/go.sum | 52 ---
www/static/test/servers/ws/server.go | 76 ----
.../servers/ws/static/black_transparent.svg | 9 -
www/static/test/servers/ws/static/index.html | 63 ----
.../test/servers/ws/static/stylesheet.css | 112 ------
.../servers/ws/static/white_transparent.svg | 9 -
www/static/test/ws-sse/README.md | 41 ++
www/static/test/ws-sse/server.js | 244 ++++++++++++
.../static/black_transparent.svg | 0
.../{realtime => ws-sse}/static/data.json | 0
www/static/test/ws-sse/static/index.html | 12 +
www/static/test/ws-sse/static/site-base.html | 37 ++
.../static/sse-about.html | 2 +
.../static/sse-multichannel-ext.html | 10 +-
.../static/sse-multichannel.html | 10 +-
.../static/sse-multiple-ext.html | 12 +-
.../static/sse-multiple.html | 12 +-
.../static/sse-settle-ext.html | 10 +-
.../static/sse-settle.html | 10 +-
.../test/ws-sse/static/sse-simple-ext.html | 28 ++
www/static/test/ws-sse/static/sse-simple.html | 28 ++
.../static/sse-target-ext.html | 8 +-
.../static/sse-target.html | 8 +-
.../test/ws-sse/static/sse-triggers-ext.html | 28 ++
.../test/ws-sse/static/sse-triggers.html | 28 ++
.../static/stylesheet.css | 4 +-
.../static/white_transparent.svg | 0
.../{realtime => ws-sse}/static/ws-about.html | 2 +
.../static/ws-echo-ext.html | 10 +-
.../{realtime => ws-sse}/static/ws-echo.html | 10 +-
.../static/ws-heartbeat-ext.html | 10 +-
.../static/ws-heartbeat.html | 12 +-
.../static/ws-reconnect-ext.html | 0
.../static/ws-reconnect.html | 0
47 files changed, 546 insertions(+), 1056 deletions(-)
delete mode 100644 www/static/test/realtime/README.md
delete mode 100644 www/static/test/realtime/go.mod
delete mode 100644 www/static/test/realtime/go.sum
delete mode 100644 www/static/test/realtime/server.go
delete mode 100644 www/static/test/realtime/static/index.html
delete mode 100644 www/static/test/realtime/static/sse-simple-ext.html
delete mode 100644 www/static/test/realtime/static/sse-simple.html
delete mode 100644 www/static/test/realtime/static/sse-triggers-ext.html
delete mode 100644 www/static/test/realtime/static/sse-triggers.html
delete mode 100644 www/static/test/servers/ws/README.md
delete mode 100644 www/static/test/servers/ws/go.mod
delete mode 100644 www/static/test/servers/ws/go.sum
delete mode 100644 www/static/test/servers/ws/server.go
delete mode 100644 www/static/test/servers/ws/static/black_transparent.svg
delete mode 100644 www/static/test/servers/ws/static/index.html
delete mode 100644 www/static/test/servers/ws/static/stylesheet.css
delete mode 100644 www/static/test/servers/ws/static/white_transparent.svg
create mode 100644 www/static/test/ws-sse/README.md
create mode 100644 www/static/test/ws-sse/server.js
rename www/static/test/{realtime => ws-sse}/static/black_transparent.svg (100%)
rename www/static/test/{realtime => ws-sse}/static/data.json (100%)
create mode 100644 www/static/test/ws-sse/static/index.html
create mode 100644 www/static/test/ws-sse/static/site-base.html
rename www/static/test/{realtime => ws-sse}/static/sse-about.html (98%)
rename www/static/test/{realtime => ws-sse}/static/sse-multichannel-ext.html (78%)
rename www/static/test/{realtime => ws-sse}/static/sse-multichannel.html (79%)
rename www/static/test/{realtime => ws-sse}/static/sse-multiple-ext.html (55%)
rename www/static/test/{realtime => ws-sse}/static/sse-multiple.html (55%)
rename www/static/test/{realtime => ws-sse}/static/sse-settle-ext.html (83%)
rename www/static/test/{realtime => ws-sse}/static/sse-settle.html (84%)
create mode 100644 www/static/test/ws-sse/static/sse-simple-ext.html
create mode 100644 www/static/test/ws-sse/static/sse-simple.html
rename www/static/test/{realtime => ws-sse}/static/sse-target-ext.html (87%)
rename www/static/test/{realtime => ws-sse}/static/sse-target.html (63%)
create mode 100644 www/static/test/ws-sse/static/sse-triggers-ext.html
create mode 100644 www/static/test/ws-sse/static/sse-triggers.html
rename www/static/test/{realtime => ws-sse}/static/stylesheet.css (98%)
rename www/static/test/{realtime => ws-sse}/static/white_transparent.svg (100%)
rename www/static/test/{realtime => ws-sse}/static/ws-about.html (98%)
rename www/static/test/{realtime => ws-sse}/static/ws-echo-ext.html (81%)
rename www/static/test/{realtime => ws-sse}/static/ws-echo.html (82%)
rename www/static/test/{realtime => ws-sse}/static/ws-heartbeat-ext.html (64%)
rename www/static/test/{realtime => ws-sse}/static/ws-heartbeat.html (64%)
rename www/static/test/{realtime => ws-sse}/static/ws-reconnect-ext.html (100%)
rename www/static/test/{realtime => ws-sse}/static/ws-reconnect.html (100%)
diff --git a/www/static/src/ext/client-side-templates.js b/www/static/src/ext/client-side-templates.js
index 64e3ce88..2bace419 100644
--- a/www/static/src/ext/client-side-templates.js
+++ b/www/static/src/ext/client-side-templates.js
@@ -28,15 +28,27 @@ htmx.defineExtension('client-side-templates', {
var handlebarsTemplate = htmx.closest(elt, "[handlebars-template]");
if (handlebarsTemplate) {
var data = JSON.parse(text);
- var templateName = handlebarsTemplate.getAttribute('handlebars-template');
- return Handlebars.partials[templateName](data);
+ var templateId = handlebarsTemplate.getAttribute('handlebars-template');
+ var templateElement = htmx.find('#' + templateId).innerHTML;
+ var renderTemplate = Handlebars.compile(templateElement);
+ if (renderTemplate) {
+ return renderTemplate(data);
+ } else {
+ throw "Unknown handlebars template: " + templateId;
+ }
}
var handlebarsArrayTemplate = htmx.closest(elt, "[handlebars-array-template]");
if (handlebarsArrayTemplate) {
var data = JSON.parse(text);
- var templateName = handlebarsArrayTemplate.getAttribute('handlebars-array-template');
- return Handlebars.partials[templateName]({"data": data});
+ var templateId = handlebarsArrayTemplate.getAttribute('handlebars-array-template');
+ var templateElement = htmx.find('#' + templateId).innerHTML;
+ var renderTemplate = Handlebars.compile(templateElement);
+ if (renderTemplate) {
+ return renderTemplate(data);
+ } else {
+ throw "Unknown handlebars template: " + templateId;
+ }
}
var nunjucksTemplate = htmx.closest(elt, "[nunjucks-template]");
@@ -50,7 +62,7 @@ htmx.defineExtension('client-side-templates', {
return nunjucks.render(templateName, data);
}
}
-
+
var xsltTemplate = htmx.closest(elt, "[xslt-template]");
if (xsltTemplate) {
var templateId = xsltTemplate.getAttribute('xslt-template');
diff --git a/www/static/test/ext/client-side-templates.js b/www/static/test/ext/client-side-templates.js
index 3a808a65..c6fdd326 100644
--- a/www/static/test/ext/client-side-templates.js
+++ b/www/static/test/ext/client-side-templates.js
@@ -29,16 +29,16 @@ describe("client-side-templates extension", function() {
it('works on basic handlebars template', function () {
this.server.respondWith("GET", "/test", '{"foo":"bar"}');
var btn = make('')
- Handlebars.partials["hb1"] = Handlebars.compile("*{{foo}}*");
+ make('')
btn.click();
this.server.respond();
btn.innerHTML.should.equal("*bar*");
});
it('works on handlebars array template', function () {
- this.server.respondWith("GET", "/test", '{"foo":"bar"}');
+ this.server.respondWith("GET", "/test", '[{"foo":"bar"}]');
var btn = make('')
- Handlebars.partials["hb1"] = Handlebars.compile("*{{data.foo}}*");
+ make('')
btn.click();
this.server.respond();
btn.innerHTML.should.equal("*bar*");
@@ -56,4 +56,4 @@ describe("client-side-templates extension", function() {
this.server.respond();
btn.innerHTML.should.equal("*bar*");
});
-});
\ No newline at end of file
+});
diff --git a/www/static/test/realtime/README.md b/www/static/test/realtime/README.md
deleted file mode 100644
index 0f9b1c17..00000000
--- a/www/static/test/realtime/README.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Htmx - Realtime Test Suite
-
-This package implements a realtime server for testing WebSockets and Server Sent Events (SSE) in htmx.
-
-## How to Use This Server
-
-1. If you do not already have Go (version 1.17 or higher) installed on your machine, you can download an installation for your machine from [https://golang.org](the Go website)
-
-2. Open up a terminal window and navigate to this directory. Start up the WebSocket server by typing `go run server.go`
-
-3. Your browser should open the test suite web page automatically. If it doesn't, then navigate to [http://localhost](http://localhost) to run the manual tests. Huzzah!
-
-## Web Sockets
-
-This listens for incoming WebSocket connections coming in to ws://localhost:1323/echo and ws://localhost:1323/heartbeat. When it receives messages from any WebSocket client, it responds with that same content in a way that htmx can process. This means, that the response message will look like this: `
{your message here}
`
-
-### Echo
-
-The echo endpoint listens for incoming WebSocket connections coming in to `ws://localhost:1323/echo`. When it receives messages from any WebSocket client, it responds with that same content wrapped as an OOB Swap. So, if you post the message `Hello There. General Kenobi.` the server will respond with this: `
Hello There. General Kenobi.
`
-
-### Heartbeat
-
-The heartbeat endpoint `ws://localhost:1323/heartbeat`. It does not process any messages that are sent to it, but it does send messages containing random numbers to every listener at random intervals. Heartbeat message will look like this: `
12345678901234567890
`
-
-## Server Sent Events
-
-This package implements a simple server that generates Server Sent Events for your test pages to read. It streams fake data from [jsonplaceholder](https://jsonplaceholder.typicode.com) to your website on a semi-regular schedule.
-
-### JSON Event Streams
-
-Streams random JSON records every second (or so) to your client.
-
-* `/posts.json`
-* `/comments.json`
-* `/albums.json`
-* `/photos.json`
-* `/todos.json`
-* `/users.json`
-
-### HTML Event Streams
-
-Streams random HTML fragments every second (or so) to your client. These streams are used by the manual htmx tests.
-
-* `/posts.html`
-* `/comments.html`
-* `/albums.html`
-* `/photos.html`
-* `/todos.html`
-* `/users.html`
-
-### Specifying Event Types
-
-You can add a `type=` parameter to your URLs to specify the event name(s) that you want the server to use. You can specify multiple names in a comma separated list and the server will alternate between them. If you do not specify a type, then the default message name of `message` is used.
-
-## Credits
-
-It is inspired by [jsonplaceholder](https://jsonplaceholder.typicode.com) -- *"a free online REST API that you can use whenever you need some fake data."*
diff --git a/www/static/test/realtime/go.mod b/www/static/test/realtime/go.mod
deleted file mode 100644
index fa01fd9b..00000000
--- a/www/static/test/realtime/go.mod
+++ /dev/null
@@ -1,22 +0,0 @@
-module github.com/bigskysoftware/htmx/test/realtime
-
-go 1.17
-
-require (
- github.com/benpate/derp v0.20.0
- github.com/benpate/htmlconv v0.3.0
- github.com/labstack/echo/v4 v4.9.0
- github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
- golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f
-)
-
-require (
- github.com/labstack/gommon v0.3.1 // indirect
- github.com/mattn/go-colorable v0.1.11 // indirect
- github.com/mattn/go-isatty v0.0.14 // indirect
- github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.1 // indirect
- golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
- golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
- golang.org/x/text v0.3.7 // indirect
-)
diff --git a/www/static/test/realtime/go.sum b/www/static/test/realtime/go.sum
deleted file mode 100644
index aeb442d8..00000000
--- a/www/static/test/realtime/go.sum
+++ /dev/null
@@ -1,52 +0,0 @@
-github.com/benpate/derp v0.20.0 h1:birPylsYOKkSMrcvNQEp+CmB7Dr1jnum8UXKv4oJvY8=
-github.com/benpate/derp v0.20.0/go.mod h1:ENjMpkMmxn9gAulMAggElVcD2kNrsbjFhoZK8fUlCxY=
-github.com/benpate/htmlconv v0.3.0 h1:UzIONnBJWtzBB3pYfKxlkq5JCsMq/+ImpAqNEmvFGcQ=
-github.com/benpate/htmlconv v0.3.0/go.mod h1:9P8tQ62E5L/KF2wTNI0szRTKs3b9WlOHj4Gxmp66rf4=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
-github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
-github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
-github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
-github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
-github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
-github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
-github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
-golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
-golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/www/static/test/realtime/server.go b/www/static/test/realtime/server.go
deleted file mode 100644
index fb847219..00000000
--- a/www/static/test/realtime/server.go
+++ /dev/null
@@ -1,350 +0,0 @@
-package main
-
-import (
- "bytes"
- _ "embed"
- "encoding/json"
- "fmt"
- "html/template"
- "log"
- "math/rand"
- "net/http"
- "strconv"
- "strings"
- "time"
-
- "github.com/benpate/derp"
- "github.com/benpate/htmlconv"
- "github.com/labstack/echo/v4"
- "github.com/pkg/browser"
- "golang.org/x/net/websocket"
-)
-
-type formatFunc func(interface{}) string
-
-//go:embed static/data.json
-var dataBytes []byte
-
-func main() {
-
- rand.Seed(time.Now().UnixNano())
-
- /// Load configuration file
- var data map[string][]interface{}
-
- if err := json.Unmarshal(dataBytes, &data); err != nil {
- panic("Could not unmarshal data: " + err.Error())
- }
-
- /// Configure Web Server
-
- e := echo.New()
-
- e.Static("/", "static")
- e.Static("/htmx", "../../src")
-
- // Web Socket Handlers
- e.GET("/echo", wsEcho)
- e.GET("/heartbeat", wsHeartbeat)
-
- // SSE - JSON Event Streams
- e.GET("/posts.json", handleStream(makeStream(data["posts"], jsonFormatFunc)))
- e.GET("/comments.json", handleStream(makeStream(data["comments"], jsonFormatFunc)))
- e.GET("/photos.json", handleStream(makeStream(data["comments"], jsonFormatFunc)))
- e.GET("/albums.json", handleStream(makeStream(data["albums"], jsonFormatFunc)))
- e.GET("/todos.json", handleStream(makeStream(data["todos"], jsonFormatFunc)))
- e.GET("/users.json", handleStream(makeStream(data["users"], jsonFormatFunc)))
-
- // SSE - HTML Event Streams (with HTMX extension tags)
- e.GET("/posts.html", handleStream(makeStream(data["posts"], postTemplate())))
- e.GET("/comments.html", handleStream(makeStream(data["comments"], commentTemplate())))
- e.GET("/photos.json", handleStream(makeStream(data["comments"], jsonFormatFunc)))
- e.GET("/albums.html", handleStream(makeStream(data["albums"], albumTemplate())))
- e.GET("/todos.html", handleStream(makeStream(data["todos"], todoTemplate())))
- e.GET("/users.html", handleStream(makeStream(data["users"], userTemplate())))
-
- e.OPTIONS("/page/random", func(ctx echo.Context) error {
- ctx.Response().Header().Add("Connection", "keep-alive") // CORS headers
- ctx.Response().Header().Add("Access-Control-Allow-Origin", "*") // CORS headers
- ctx.Response().Header().Add("Access-Control-Allow-Methods", "GET") // CORS headers
- ctx.Response().Header().Add("Access-Control-Allow-Credentials", "true") // CORS headers
- ctx.Response().Header().Add("Access-Control-Allow-Headers", "*") // CORS headers
- ctx.NoContent(200)
- return nil
- })
-
- e.GET("/page/random", func(ctx echo.Context) error {
- return pageHandler(ctx, rand.Int())
- })
-
- e.GET("/page/:number", func(ctx echo.Context) error {
-
- pageNumber, err := strconv.Atoi(ctx.Param("number"))
-
- if err != nil {
- pageNumber = 1
- }
-
- return pageHandler(ctx, pageNumber)
- })
-
- e.GET("/revealed/:number", func(ctx echo.Context) error {
-
- pageNumber, err := strconv.Atoi(ctx.Param("number"))
-
- if err != nil {
- pageNumber = 1
- }
-
- thisPage := strconv.Itoa(pageNumber)
- nextPage := strconv.Itoa(pageNumber + 1)
- random := strconv.Itoa(rand.Int())
-
- template := htmlconv.CollapseWhitespace(`
-
- This is page %s
- Randomly generated HTML %s
- I wish I were a haiku.
-
`)
-
- content := fmt.Sprintf(template, nextPage, thisPage, random)
- return ctx.HTML(200, content)
- })
-
- // On first run, open web browser in admin mode
- browser.OpenURL("http://localhost/")
-
- e.Logger.Fatal(e.Start(":80"))
-}
-
-/*******************************************
- * Web Socket Handlers
- *******************************************/
-
-func wsHeartbeat(c echo.Context) error {
-
- handler := websocket.Handler(func(ws *websocket.Conn) {
-
- defer ws.Close()
-
- for i := 0; ; i = i + 1 {
-
- time.Sleep(1 * time.Second)
-
- random := rand.Int()
- message := `
As of version 1.7, we have created two new extensions ws.js and sse.js to support realtime development in htmx. All new effort on WebSockets and Server Sent Events will occur in these extensions.
-
-
Old Tags Deprecated
-
The existing hx-ws and hx-sse tags have been deprecated and will not receive any more updates. We plan to remove these two tags from the core library in htmx version 2.0.
-
-
Try It For Yourself
-
Because extensions use a different calling syntax, there are minor differences in the way that this new code is invoked. This test server includes several demos / manual tests for each extension that you can try out for yourself. Each is presented side-by-side with test cases for the original code so that you can see the difference.
-
-
-
-
\ No newline at end of file
diff --git a/www/static/test/realtime/static/sse-simple-ext.html b/www/static/test/realtime/static/sse-simple-ext.html
deleted file mode 100644
index 8c785af7..00000000
--- a/www/static/test/realtime/static/sse-simple-ext.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
- This page connects to several different Server Sent Event (SSE) streams, listening on the default event name "message".
- Each stream should populate its own container.
-
-
Example HTML
-
-<div hx-ext="sse" sse-connect="http://localhost/posts.html" sse-swap="message">Waiting for Posts...</div>
-
-
-
Test Cases
-
-
-
Waiting for Posts...
-
Waiting for Comments...
-
Waiting for Albums...
-
Waiting for ToDos...
-
Waiting for Users...
-
\ No newline at end of file
diff --git a/www/static/test/realtime/static/sse-simple.html b/www/static/test/realtime/static/sse-simple.html
deleted file mode 100644
index a1233e0e..00000000
--- a/www/static/test/realtime/static/sse-simple.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
- This page connects to several different Server Sent Event (SSE) streams, listening on the default event name "message".
- Each stream should populate its own container.
-
-
Example HTML
-
-<div hx-sse="connect:http://localhost/posts.html swap:message">Waiting for Posts...</div>
-
-
-
Test Cases
-
-
-
Waiting for Posts...
-
Waiting for Comments...
-
Waiting for Albums...
-
Waiting for ToDos...
-
Waiting for Users...
-
\ No newline at end of file
diff --git a/www/static/test/realtime/static/sse-triggers-ext.html b/www/static/test/realtime/static/sse-triggers-ext.html
deleted file mode 100644
index 87237caa..00000000
--- a/www/static/test/realtime/static/sse-triggers-ext.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
- This page connects to a single different Server Sent Event (SSE) streams, listening on events named "Event1", "Event2", "Event3", and "Event4".
- Each event is used as a trigger for hx-get to load a random page from the server.
-
- This page connects to a single different Server Sent Event (SSE) streams, listening on events named "Event1", "Event2", "Event3", and "Event4".
- Each event is used as a trigger for hx-get to load a random page from the server.
-
-
Example HTML
-
-<div hx-sse="connect:http://localhost/posts.html?types=Event1%2cEvent2%2cEvent3%2cEvent4">
- <div hx-get="http://localhost/page/random" hx-trigger="sse:Event1">Waiting for Posts...</div>
-</div>
-
-
-
-
Test Cases
-
Waiting for Posts in Event1 channel...
-
Waiting for Posts in Event2 channel...
-
Waiting for Posts in Event3 channel...
-
Waiting for Posts in Event4 channel...
-
diff --git a/www/static/test/servers/ws/README.md b/www/static/test/servers/ws/README.md
deleted file mode 100644
index b12c91ab..00000000
--- a/www/static/test/servers/ws/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Htmx Realtime Test Server
-
-This package implements a realtime server for testing WebSockets and Server Sent Events (SSE) in htmx.
-
-## What It Does
-
-This server listens for incoming WebSocket connections coming in to ws://localhost:1323/echo. When it receives messages from any WebSocket client, it responds with that same content in a way that htmx can process. This means, that the response message will look like this: `
{your message here}
`
-
-## How to Use This Server
-
-1. If you do not already have Go (version 1.17 or higher) installed on your machine, you can download an installation for your machine from [the Go website](https://golang.org)
-
-2. Open up a terminal window and navigate to this directory. Start up the WebSocket server by typing `go run server.go`
-
-3. Open your web browser to [http://localhost](http://localhost) to run the manual tests. Huzzah!
diff --git a/www/static/test/servers/ws/go.mod b/www/static/test/servers/ws/go.mod
deleted file mode 100644
index 0b30769d..00000000
--- a/www/static/test/servers/ws/go.mod
+++ /dev/null
@@ -1,23 +0,0 @@
-module github.com/benpate/ghost
-
-go 1.17
-
-require (
- github.com/labstack/echo/v4 v4.3.0
- golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
-)
-
-require (
- github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
- github.com/labstack/gommon v0.3.0 // indirect
- github.com/mattn/go-colorable v0.1.8 // indirect
- github.com/mattn/go-isatty v0.0.12 // indirect
- github.com/stretchr/testify v1.7.0 // indirect
- github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.1 // indirect
- golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
- golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
- golang.org/x/text v0.3.6 // indirect
- golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
-)
diff --git a/www/static/test/servers/ws/go.sum b/www/static/test/servers/ws/go.sum
deleted file mode 100644
index 731271f9..00000000
--- a/www/static/test/servers/ws/go.sum
+++ /dev/null
@@ -1,52 +0,0 @@
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/labstack/echo/v4 v4.3.0 h1:DCP6cbtT+Zu++K6evHOJzSgA2115cPMuCx0xg55q1EQ=
-github.com/labstack/echo/v4 v4.3.0/go.mod h1:PvmtTvhVqKDzDQy4d3bWzPjZLzom4iQbAZy2sgZ/qI8=
-github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
-github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
-github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
-github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
-github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
-github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
-github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
-golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/www/static/test/servers/ws/server.go b/www/static/test/servers/ws/server.go
deleted file mode 100644
index 5d06c5a1..00000000
--- a/www/static/test/servers/ws/server.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package main
-
-import (
- "math/rand"
- "strconv"
- "time"
-
- "github.com/labstack/echo/v4"
- "github.com/labstack/echo/v4/middleware"
- "golang.org/x/net/websocket"
-)
-
-func wsHeartbeat(c echo.Context) error {
-
- handler := websocket.Handler(func(ws *websocket.Conn) {
-
- defer ws.Close()
-
- for i := 0; ; i = i + 1 {
-
- time.Sleep(1 * time.Second)
-
- random := rand.Int()
- message := `
As of version 1.7, WebSocket support has been moved out of the core htmx library and into an extension. This server runs a test suite for the htmx WebSocket extension.
-
This extension connects to a WebSocket echo server and can send and receive messages to and from the server.
-
-
Required Attributes
-
-
-
hx-ext
-
Make sure the SSE extension is initialized on every page or page fragment where you use SSE streams.
-
-
-
ws-connect
-
Connects to a WebSocket server. Attribute value must begin with ws:// wss://
-
-
-
ws-send
-
Add to a form to submit form data to the websocket server instead of to an HTTP server.
-
-
\ No newline at end of file
diff --git a/www/static/test/servers/ws/static/stylesheet.css b/www/static/test/servers/ws/static/stylesheet.css
deleted file mode 100644
index adccb158..00000000
--- a/www/static/test/servers/ws/static/stylesheet.css
+++ /dev/null
@@ -1,112 +0,0 @@
-*{
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
- box-sizing: border-box;
-}
-
-body {
- background-color: white;
- padding:0px;
- margin:0px;
- width:100%;
-}
-
-#header {
- width:100%;
- height: 100px;
- background-image:url('white_transparent.svg');
- background-position:left 50px center;
- background-repeat:no-repeat;
- background-size: 300px;
- background-color:black;
-}
-
-#navigation {
- position:absolute;
- width:150px;
- margin-top:50px;
- margin-left:20px;
- white-space: nowrap;
-}
-
-#navigation > a {
- display:block;
- cursor: pointer;
- text-decoration:none;
- padding:10px 20px;
-}
-
-#navigation > a:hover {
- background-color:#eee;
-}
-
-#navigation > a.selected {
- font-weight:bold;
-}
-
-#page {
- margin: 50px;
- padding-left:150px;
-}
-
-.container {
- padding: 10px;
- border: solid 1px gray;
- margin-bottom: 20px;
- background-color:#f7f7f7;
-}
-
-.container.htmx-settling {
- border:solid 3px red!important;
- padding:8px!important;
-}
-
-pre.code {
- font-family:'Courier New', Courier, monospace;
- background-color: #444440;
- color: #0f0;
- padding:30px 5px 30px 15px;
- overflow-y:scroll;
- display:block;
-}
-
-.bold {
- font-weight:bold;
-}
-
-.nowrap {
- white-space: nowrap;
-}
-
-table {
- border-collapse: collapse;
-}
-
-td {
- padding:10px 20px;
- border:solid 1px #ddd;
- vertical-align: top;
-}
-
-.demo {
- padding:10px;
- margin:20px 0px;
- color:white;
- background-color: #999;
- height:100px;
-}
-
-a, a:visited {
- color:#3465a4;
-}
-
-
-.btn {
- padding:5px 10px;
- border:none;
- border-radius:5px;
-}
-
-.btn.primary {
- background-color:#3465a4;
- color:white;
-}
\ No newline at end of file
diff --git a/www/static/test/servers/ws/static/white_transparent.svg b/www/static/test/servers/ws/static/white_transparent.svg
deleted file mode 100644
index be885d68..00000000
--- a/www/static/test/servers/ws/static/white_transparent.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
diff --git a/www/static/test/ws-sse/README.md b/www/static/test/ws-sse/README.md
new file mode 100644
index 00000000..5da1e13d
--- /dev/null
+++ b/www/static/test/ws-sse/README.md
@@ -0,0 +1,41 @@
+# WebSocket and Server-Side Events live test suite
+This package implements a realtime server for testing WebSockets and Server Sent Events (SSE) in htmx.
+
+## How to Use This Server
+From this directory, run `node server.js`.
+
+If you want to hotreload, I recommend using `nodemon`, which you can install with `npm install -g
+nodemon`, and then run `nodemon -e js,html server.js`.
+
+## Web Sockets
+When htmx receives messages from any WebSocket client, it responds with that same content in a way that htmx can process. This means, that the response message will look like this: `
{your message here}
`
+
+### Echo
+When the echo endpoint receives messages from any WebSocket client, it responds with that same content wrapped as an OOB Swap. So, if you post the message `Hello There. General Kenobi.` the server will respond with this: `
Hello There. General Kenobi.
`
+
+### Heartbeat
+The heartbeat endpoint does not process any messages that are sent to it, but it does send messages containing random numbers to every listener at random intervals. Heartbeat message will look like this: `
12345678901234567890
`
+
+## Server Sent Events
+
+This package implements a simple server that generates Server Sent Events for your test pages to read. It streams fake data from [jsonplaceholder](https://jsonplaceholder.typicode.com) to your website on a semi-regular schedule.
+
+### HTML Event Streams
+
+Streams random HTML fragments every second (or so) to your client. These streams are used by the manual htmx tests.
+
+* `/posts.html`
+* `/comments.html`
+* `/albums.html`
+* `/photos.html`
+* `/todos.html`
+* `/users.html`
+
+### Specifying Event Types
+
+You can add a `type=` parameter to your URLs to specify the event name(s) that you want the server to use. You can specify multiple names in a comma separated list and the server will alternate between them. If you do not specify a type, then the default message name of `message` is used.
+
+## Credits
+This test suite was originally written by Ben Pate, and updated to run in nodeJS by Alex Petros.
+
+It is inspired by [jsonplaceholder](https://jsonplaceholder.typicode.com) -- *"a free online REST API that you can use whenever you need some fake data."*
diff --git a/www/static/test/ws-sse/server.js b/www/static/test/ws-sse/server.js
new file mode 100644
index 00000000..0cbe53c3
--- /dev/null
+++ b/www/static/test/ws-sse/server.js
@@ -0,0 +1,244 @@
+import * as http from 'node:http'
+import * as path from 'node:path'
+import * as fs from 'node:fs/promises'
+
+import { WebSocketServer } from 'ws'
+
+// Define some string and number constants
+const HOSTNAME = '127.0.0.1';
+const PORT = 8080;
+const DATA = JSON.parse(await fs.readFile('./static/data.json'))
+const SITE_BASE = (await fs.readFile('./static/site-base.html')).toString()
+
+// Define the websockets
+const ECHO_WS = createWebSocket((ws) => {
+ ws.on('message', (message) => {
+ const data = JSON.parse(message.toString())
+ ws.send(`
+ `
+}
+
diff --git a/www/static/test/realtime/static/black_transparent.svg b/www/static/test/ws-sse/static/black_transparent.svg
similarity index 100%
rename from www/static/test/realtime/static/black_transparent.svg
rename to www/static/test/ws-sse/static/black_transparent.svg
diff --git a/www/static/test/realtime/static/data.json b/www/static/test/ws-sse/static/data.json
similarity index 100%
rename from www/static/test/realtime/static/data.json
rename to www/static/test/ws-sse/static/data.json
diff --git a/www/static/test/ws-sse/static/index.html b/www/static/test/ws-sse/static/index.html
new file mode 100644
index 00000000..6d8fc754
--- /dev/null
+++ b/www/static/test/ws-sse/static/index.html
@@ -0,0 +1,12 @@
+
+
Realtime Test Server
+
+
New Extensions
+
As of version 1.7, we have created two new extensions ws.js and sse.js to support realtime development in htmx. All new effort on WebSockets and Server Sent Events will occur in these extensions.
+
+
Old Tags Deprecated
+
The existing hx-ws and hx-sse tags have been deprecated and will not receive any more updates. We plan to remove these two tags from the core library in htmx version 2.0.
+
+
Try It For Yourself
+
Because extensions use a different calling syntax, there are minor differences in the way that this new code is invoked. This test server includes several demos / manual tests for each extension that you can try out for yourself. Each is presented side-by-side with test cases for the original code so that you can see the difference.
+
diff --git a/www/static/test/ws-sse/static/site-base.html b/www/static/test/ws-sse/static/site-base.html
new file mode 100644
index 00000000..715734ad
--- /dev/null
+++ b/www/static/test/ws-sse/static/site-base.html
@@ -0,0 +1,37 @@
+
+
+</> htmx Realtime Test Server
+
+
+
+
+
+
+
+
diff --git a/www/static/test/realtime/static/sse-about.html b/www/static/test/ws-sse/static/sse-about.html
similarity index 98%
rename from www/static/test/realtime/static/sse-about.html
rename to www/static/test/ws-sse/static/sse-about.html
index 5c2c4094..f9d62d86 100644
--- a/www/static/test/realtime/static/sse-about.html
+++ b/www/static/test/ws-sse/static/sse-about.html
@@ -1,3 +1,4 @@
+
Server Sent Events (SSE)
SSE create a lightweight, uni-directional connection from your server to a client's web browser. They are often easier to manage than WebSockets, and are built on top ofHTTP connections (making them less likely to be blocked by firewalls).
- This page connects to a single Server Sent Event (SSE) streams, but listens to multiple events.
+ This page connects to a single Server Sent Event (SSE) streams, but listens to multiple events.
Example HTML
@@ -17,6 +18,7 @@
Test Cases
-
Waiting for Posts...
+
Waiting for Posts...
-
\ No newline at end of file
+
+
diff --git a/www/static/test/realtime/static/sse-multiple.html b/www/static/test/ws-sse/static/sse-multiple.html
similarity index 55%
rename from www/static/test/realtime/static/sse-multiple.html
rename to www/static/test/ws-sse/static/sse-multiple.html
index 9411d2d2..e23baec8 100644
--- a/www/static/test/realtime/static/sse-multiple.html
+++ b/www/static/test/ws-sse/static/sse-multiple.html
@@ -1,13 +1,14 @@
+
- This page connects to a single Server Sent Event (SSE) streams, but listens to multiple events.
+ This page connects to a single Server Sent Event (SSE) streams, but listens to multiple events.
Example HTML
@@ -17,6 +18,7 @@
Test Cases
-
Waiting for Posts...
+
Waiting for Posts...
-
\ No newline at end of file
+
+
diff --git a/www/static/test/realtime/static/sse-settle-ext.html b/www/static/test/ws-sse/static/sse-settle-ext.html
similarity index 83%
rename from www/static/test/realtime/static/sse-settle-ext.html
rename to www/static/test/ws-sse/static/sse-settle-ext.html
index 588dc866..9c9bc23e 100644
--- a/www/static/test/realtime/static/sse-settle-ext.html
+++ b/www/static/test/ws-sse/static/sse-settle-ext.html
@@ -1,13 +1,14 @@
+
- This page connects to a single different Server Sent Event (SSE) stream.
+ This page connects to a single different Server Sent Event (SSE) stream.
Multiple containers all listen for the same default "message" event name, but using different values for hx-swap.
Example HTML
@@ -18,7 +19,7 @@
Test Cases
-
+
Waiting for Comments...
Waiting for Comments...
Waiting for Comments...
@@ -26,3 +27,4 @@
Waiting for Comments...
+
diff --git a/www/static/test/realtime/static/sse-settle.html b/www/static/test/ws-sse/static/sse-settle.html
similarity index 84%
rename from www/static/test/realtime/static/sse-settle.html
rename to www/static/test/ws-sse/static/sse-settle.html
index 08426b36..3f35aca4 100644
--- a/www/static/test/realtime/static/sse-settle.html
+++ b/www/static/test/ws-sse/static/sse-settle.html
@@ -1,13 +1,14 @@
+
- This page connects to a single different Server Sent Event (SSE) stream.
+ This page connects to a single different Server Sent Event (SSE) stream.
Multiple containers all listen for the same default "message" event name, but using different values for hx-swap.
+ This page connects to several different Server Sent Event (SSE) streams, listening on the default event name "message".
+ Each stream should populate its own container.
+
+
Example HTML
+
+<div hx-ext="sse" sse-connect="http://localhost/posts.html" sse-swap="message">Waiting for Posts...</div>
+
+ This page connects to several different Server Sent Event (SSE) streams, listening on the default event name "message".
+ Each stream should populate its own container.
+
+
Example HTML
+
+<div hx-sse="connect:http://localhost/posts.html swap:message">Waiting for Posts...</div>
+
+
+
Test Cases
+
+
+
Waiting for Posts...
+
Waiting for Comments...
+
Waiting for Albums...
+
Waiting for ToDos...
+
Waiting for Users...
+
+
diff --git a/www/static/test/realtime/static/sse-target-ext.html b/www/static/test/ws-sse/static/sse-target-ext.html
similarity index 87%
rename from www/static/test/realtime/static/sse-target-ext.html
rename to www/static/test/ws-sse/static/sse-target-ext.html
index 55c531b1..2cf52461 100644
--- a/www/static/test/realtime/static/sse-target-ext.html
+++ b/www/static/test/ws-sse/static/sse-target-ext.html
@@ -1,13 +1,14 @@
+
- This page connects to several different different Server Sent Event (SSE) stream.
+ This page connects to several different different Server Sent Event (SSE) stream.
Contents from each stream are sent to a single DOM element.
Example HTML
@@ -27,3 +28,4 @@
Waiting for records from any of: Posts/Comments/Albums/ToDos/Users
+
diff --git a/www/static/test/realtime/static/sse-target.html b/www/static/test/ws-sse/static/sse-target.html
similarity index 63%
rename from www/static/test/realtime/static/sse-target.html
rename to www/static/test/ws-sse/static/sse-target.html
index b014c5be..9435e87e 100644
--- a/www/static/test/realtime/static/sse-target.html
+++ b/www/static/test/ws-sse/static/sse-target.html
@@ -1,12 +1,14 @@
+
+ This page connects to a single different Server Sent Event (SSE) streams, listening on events named "Event1", "Event2", "Event3", and "Event4".
+ Each event is used as a trigger for hx-get to load a random page from the server.
+
+ This page connects to a single different Server Sent Event (SSE) streams, listening on events named "Event1", "Event2", "Event3", and "Event4".
+ Each event is used as a trigger for hx-get to load a random page from the server.
+
+
Example HTML
+
+<div hx-sse="connect:http://localhost/posts.html?types=Event1%2cEvent2%2cEvent3%2cEvent4">
+ <div hx-get="http://localhost/page/random" hx-trigger="sse:Event1">Waiting for Posts...</div>
+</div>
+
+
+
+
Test Cases
+
Waiting for Posts in Event1 channel...
+
Waiting for Posts in Event2 channel...
+
Waiting for Posts in Event3 channel...
+
Waiting for Posts in Event4 channel...
+
+
diff --git a/www/static/test/realtime/static/stylesheet.css b/www/static/test/ws-sse/static/stylesheet.css
similarity index 98%
rename from www/static/test/realtime/static/stylesheet.css
rename to www/static/test/ws-sse/static/stylesheet.css
index 402d9fe5..8b689394 100644
--- a/www/static/test/realtime/static/stylesheet.css
+++ b/www/static/test/ws-sse/static/stylesheet.css
@@ -117,7 +117,7 @@ body {
font-weight:bold;
}
-#page {
+main {
margin: 50px;
padding-left:200px;
}
@@ -158,7 +158,7 @@ body {
background-color:var(--gray05);
border:solid 1px var(--gray30);
border-bottom: solid 1px var(--gray40);
- border-radius: 4px 4px 0px 0px;
+ border-radius: 4px 4px 0px 0px;
color: var(--gray50);
font-family: inherit;
font-size:1.1rem;
diff --git a/www/static/test/realtime/static/white_transparent.svg b/www/static/test/ws-sse/static/white_transparent.svg
similarity index 100%
rename from www/static/test/realtime/static/white_transparent.svg
rename to www/static/test/ws-sse/static/white_transparent.svg
diff --git a/www/static/test/realtime/static/ws-about.html b/www/static/test/ws-sse/static/ws-about.html
similarity index 98%
rename from www/static/test/realtime/static/ws-about.html
rename to www/static/test/ws-sse/static/ws-about.html
index 2da65d62..bee0f6f7 100644
--- a/www/static/test/realtime/static/ws-about.html
+++ b/www/static/test/ws-sse/static/ws-about.html
@@ -1,3 +1,4 @@
+
WebSockets
WebSockets create a fast, bi-directional connection between your server and a client's web browser.
Each message just contains a random number generated by the server
-
Waiting...
-
\ No newline at end of file
+
Connecting...
+
+
diff --git a/www/static/test/realtime/static/ws-reconnect-ext.html b/www/static/test/ws-sse/static/ws-reconnect-ext.html
similarity index 100%
rename from www/static/test/realtime/static/ws-reconnect-ext.html
rename to www/static/test/ws-sse/static/ws-reconnect-ext.html
diff --git a/www/static/test/realtime/static/ws-reconnect.html b/www/static/test/ws-sse/static/ws-reconnect.html
similarity index 100%
rename from www/static/test/realtime/static/ws-reconnect.html
rename to www/static/test/ws-sse/static/ws-reconnect.html