talkdom 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -1
- package/dist/talkdom-ws.esm.js +2 -0
- package/dist/talkdom-ws.esm.js.map +7 -0
- package/dist/talkdom-ws.min.js +2 -0
- package/dist/talkdom-ws.min.js.map +7 -0
- package/dist/talkdom.esm.js +2 -0
- package/dist/talkdom.esm.js.map +7 -0
- package/dist/talkdom.min.js +2 -1
- package/dist/talkdom.min.js.map +7 -1
- package/package.json +19 -7
- package/src/index.js +415 -0
- package/src/websocket.js +223 -0
- package/index.js +0 -366
package/README.md
CHANGED
|
@@ -46,6 +46,10 @@ args: ["/partial", "inner"]
|
|
|
46
46
|
- Programmatic API via `talkDOM.send` (returns a promise)
|
|
47
47
|
- Extensible methods via `talkDOM.methods`
|
|
48
48
|
- Configurable max pollers via `talkDOM.maxPollers`
|
|
49
|
+
- `post-form:`, `put-form:`, `delete-form:` with form serialization
|
|
50
|
+
- `post-json:`, `put-json:` with JSON body
|
|
51
|
+
- `loading:` class toggle during async operations
|
|
52
|
+
- Dynamic polling via `MutationObserver` for late-added elements
|
|
49
53
|
|
|
50
54
|
## Usage
|
|
51
55
|
|
|
@@ -104,7 +108,9 @@ Receivers poll by adding `poll:` as the last keyword with an interval (`s` or `m
|
|
|
104
108
|
<div receiver="feed get:apply: /updates inner poll: 10s"></div>
|
|
105
109
|
```
|
|
106
110
|
|
|
107
|
-
Polling stops automatically when the element is removed from the DOM.
|
|
111
|
+
Polling stops automatically when the element is removed from the DOM. Elements added dynamically (e.g., via fragment injection or Alpine `x-if`) are picked up automatically by a `MutationObserver` — no manual setup needed.
|
|
112
|
+
|
|
113
|
+
A maximum of 64 concurrent pollers is enforced by default. Adjust via:
|
|
108
114
|
|
|
109
115
|
```js
|
|
110
116
|
talkDOM.maxPollers = 128;
|
|
@@ -208,6 +214,40 @@ talkDOM.send("#content get:apply: /bad-url inner").catch(function (err) {
|
|
|
208
214
|
});
|
|
209
215
|
```
|
|
210
216
|
|
|
217
|
+
## Form body
|
|
218
|
+
|
|
219
|
+
`post-form:`, `put-form:`, and `delete-form:` serialize a form's inputs as `application/x-www-form-urlencoded` and send them with the request. The `form:` keyword specifies the CSS selector for the form element.
|
|
220
|
+
|
|
221
|
+
```html
|
|
222
|
+
<form id="my-form">
|
|
223
|
+
<input name="name" value="test">
|
|
224
|
+
<input name="email" value="user@example.com">
|
|
225
|
+
</form>
|
|
226
|
+
<div receiver="result"></div>
|
|
227
|
+
<button sender="result post-form: /api/submit apply: inner form: #my-form">Submit</button>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## JSON body
|
|
231
|
+
|
|
232
|
+
`post-json:` and `put-json:` send a JSON payload with the request. The `json:` keyword specifies the JSON string (parsed at runtime).
|
|
233
|
+
|
|
234
|
+
```html
|
|
235
|
+
<div receiver="result"></div>
|
|
236
|
+
<button sender="result post-json: /api/data apply: inner json: {"name":"test"}">Send</button>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Loading state
|
|
240
|
+
|
|
241
|
+
The `loading:` keyword toggles a CSS class on the receiver while an async operation is in progress. The class is removed on both success and error.
|
|
242
|
+
|
|
243
|
+
```html
|
|
244
|
+
<style>
|
|
245
|
+
.is-loading { opacity: 0.5; pointer-events: none; }
|
|
246
|
+
</style>
|
|
247
|
+
<div receiver="content"></div>
|
|
248
|
+
<button sender="content get: /api/data apply: inner loading: is-loading">Load</button>
|
|
249
|
+
```
|
|
250
|
+
|
|
211
251
|
## Extending
|
|
212
252
|
|
|
213
253
|
```js
|
|
@@ -223,6 +263,100 @@ talkDOM.methods["show:"] = function (el, message) {
|
|
|
223
263
|
};
|
|
224
264
|
```
|
|
225
265
|
|
|
266
|
+
## WebSocket plugin
|
|
267
|
+
|
|
268
|
+
The optional `websocket.js` plugin adds server-push via WebSocket as an alternative to polling. Load it after the core library:
|
|
269
|
+
|
|
270
|
+
```html
|
|
271
|
+
<script src="https://cdn.jsdelivr.net/npm/talkdom/dist/talkdom.min.js"></script>
|
|
272
|
+
<script src="https://cdn.jsdelivr.net/npm/talkdom/dist/talkdom-ws.min.js"></script>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Receiving
|
|
276
|
+
|
|
277
|
+
Add `ws:` as the last keyword on a receiver with a WebSocket URL as its argument. The server pushes content — no client-side method keywords needed.
|
|
278
|
+
|
|
279
|
+
```html
|
|
280
|
+
<div receiver="feed ws: ws://localhost:3000/updates"></div>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The server sends JSON messages to control what gets applied:
|
|
284
|
+
|
|
285
|
+
```json
|
|
286
|
+
{"receiver": "feed", "content": "<p>New post</p>", "op": "append"}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
| Field | Required | Description |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| `receiver` | yes | Target receiver name |
|
|
292
|
+
| `content` | no | HTML or text content |
|
|
293
|
+
| `op` | no | `inner` (default), `text`, `append`, `outer` |
|
|
294
|
+
|
|
295
|
+
Omitting `receiver` broadcasts to all receivers on that connection.
|
|
296
|
+
|
|
297
|
+
The server can also send raw talkDOM message syntax instead of JSON:
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
feed apply: Updated! text
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
This dispatches through the same path as sender clicks and server triggers.
|
|
304
|
+
|
|
305
|
+
### Sending
|
|
306
|
+
|
|
307
|
+
The plugin registers a `ws:send:` method. The receiver element's value (for inputs/textareas/selects) or text content is sent over the WebSocket connection.
|
|
308
|
+
|
|
309
|
+
```html
|
|
310
|
+
<input receiver="chatbox" type="text">
|
|
311
|
+
<button sender="chatbox ws:send: ws://localhost:3000/chat">Send</button>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Shared connections
|
|
315
|
+
|
|
316
|
+
Multiple receivers pointing to the same URL share a single WebSocket connection. The server routes messages by the `receiver` field in JSON.
|
|
317
|
+
|
|
318
|
+
```html
|
|
319
|
+
<div receiver="messages ws: ws://localhost:3000/live"></div>
|
|
320
|
+
<div receiver="presence ws: ws://localhost:3000/live"></div>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Reconnection
|
|
324
|
+
|
|
325
|
+
Connections automatically reconnect with exponential backoff (1s initial, 30s max, ±25% jitter). Backoff resets on successful connection. Reconnection stops when all receivers for a URL are removed from the DOM.
|
|
326
|
+
|
|
327
|
+
### Lifecycle events
|
|
328
|
+
|
|
329
|
+
| Event | Detail |
|
|
330
|
+
|---|---|
|
|
331
|
+
| `talkdom:ws:open` | `{ url }` |
|
|
332
|
+
| `talkdom:ws:close` | `{ url, code, reason }` |
|
|
333
|
+
| `talkdom:ws:error` | `{ url }` |
|
|
334
|
+
|
|
335
|
+
Events fire on all receiver elements subscribed to the URL and bubble.
|
|
336
|
+
|
|
337
|
+
```js
|
|
338
|
+
document.addEventListener("talkdom:ws:open", function (e) {
|
|
339
|
+
console.log("connected to", e.detail.url);
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Incoming messages also fire the standard `talkdom:done` event on the target receiver after applying content.
|
|
344
|
+
|
|
345
|
+
### Programmatic API
|
|
346
|
+
|
|
347
|
+
```js
|
|
348
|
+
talkDOM.ws.connect("ws://localhost:3000/live");
|
|
349
|
+
talkDOM.ws.send("ws://localhost:3000/live", { action: "subscribe", channel: "news" });
|
|
350
|
+
talkDOM.ws.send("ws://localhost:3000/live", "plain string");
|
|
351
|
+
talkDOM.ws.disconnect("ws://localhost:3000/live");
|
|
352
|
+
|
|
353
|
+
talkDOM.ws.connections; // { "ws://...": { state: 1, receivers: 2 } }
|
|
354
|
+
talkDOM.ws.maxConnections; // default 16
|
|
355
|
+
talkDOM.ws.maxConnections = 32;
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
`talkDOM.ws.send` returns `true` if sent, `false` if the connection is not open.
|
|
359
|
+
|
|
226
360
|
## Security
|
|
227
361
|
|
|
228
362
|
talkDOM does **not** sanitize HTML. Content from `get:apply:`, `post:apply:`, server triggers, and piped `apply:` is inserted via `innerHTML` / `insertAdjacentHTML` / `outerHTML` as-is. You are responsible for ensuring that server responses do not contain untrusted markup.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var Y=/\s+/,x="talkDOM:";function w(e){let t=e.trim(),n=t.split(Y),r=n[0],o=t.substring(r.length).trim(),c=n.slice(1),s=[],i=[],a=[];for(let p=0;p<c.length;p++){let h=c[p];h.endsWith(":")?(s.length>0&&a.length>0?(i.push(a.join(" ")),a=[]):s.length>0&&i.push(""),s.push(h)):a.push(h)}return s.length>0&&i.push(a.join(" ")),{receiver:r,selector:s.join(""),keywords:s,args:i,body:o}}function T(e){let t=e.getAttribute("receiver").trim(),n=t.indexOf(" ");return n===-1?t:t.substring(0,n)}var k=Object.create(null),q=!1;new MutationObserver(()=>{q=!1}).observe(document,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["receiver"]});function S(e){if(q||(Object.keys(k).forEach(n=>delete k[n]),q=!0),k[e])return k[e];let t=document.querySelectorAll('[receiver~="'+e+'"]');return k[e]=t,t}function $(e,t){let n=e.getAttribute("accepts");return n?(" "+n+" ").includes(" "+t+" "):!0}function K(e,t){if(!e.hasAttribute("receiver")||!e.hasAttribute("persist"))return;let n=T(e),r=x+n,o=t==="outer"?e.outerHTML:e.innerHTML;localStorage.setItem(r,JSON.stringify({op:t,content:o}))}function Q(){document.querySelectorAll("[persist]").forEach(e=>{if(!e.hasAttribute("receiver"))return;let t=T(e),n=localStorage.getItem(x+t);if(!n)return;let r;try{r=JSON.parse(n)}catch{localStorage.removeItem(x+t);return}r.op==="outer"?e.outerHTML=r.content:e.innerHTML=r.content})}function m(e,t,n){if(!$(e,t)){console.error(T(e)+" does not accept "+t);return}switch(t){case"inner":e.innerHTML=n;break;case"text":e.textContent=n;break;case"append":e.insertAdjacentHTML("beforeend",n);break;case"outer":e.outerHTML=n;break}return K(e,t),n}var y=null;function Z(){return(!y||!y.isConnected)&&(y=document.querySelector('meta[name="csrf-token"]')),y?y.getAttribute("content"):""}function f(e,t,n,r){let o={"X-TalkDOM-Request":"true","X-TalkDOM-Current-URL":location.href};if(n&&(o["X-TalkDOM-Receiver"]=n),e!=="GET"){let c=Z();c?o["X-CSRF-Token"]=c:console.warn("talkDOM: no CSRF token found for "+e+" "+t)}return fetch(t,{method:e,headers:o,body:r}).then(c=>{if(!c.ok)return console.error("talkDOM: "+e+" "+t+" "+c.status),Promise.reject(c.status);let s=c.headers.get("X-TalkDOM-Trigger");return c.text().then(i=>(s&&W(s),i))})}function P(e){return new URLSearchParams(new FormData(e)).toString()}function l(e){return e.hasAttribute("receiver")?T(e):""}var b={"get:":function(e,t){return f("GET",t,l(e))},"post:":function(e,t){return f("POST",t,l(e))},"put:":function(e,t){return f("PUT",t,l(e))},"delete:":function(e,t){return f("DELETE",t,l(e))},"confirm:":function(e,t){if(!confirm(t))return Promise.reject("cancelled")},"apply:":function(e,t,n){return m(e,n,t)},"get:apply:":function(e,t,n){return f("GET",t,l(e)).then(function(r){return m(e,n,r)})},"post:apply:":function(e,t,n){return f("POST",t,l(e)).then(function(r){return m(e,n,r)})},"put:apply:":function(e,t,n){return f("PUT",t,l(e)).then(function(r){return m(e,n,r)})},"delete:apply:":function(e,t,n){return f("DELETE",t,l(e)).then(function(r){return m(e,n,r)})},"post-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("post-form: form not found: "+r);return}let c=P(o);return f("POST",t,l(e),c).then(function(s){return m(e,n,s)})},"put-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("put-form: form not found: "+r);return}let c=P(o);return f("PUT",t,l(e),c).then(function(s){return m(e,n,s)})},"delete-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("delete-form: form not found: "+r);return}let c=P(o);return f("DELETE",t,l(e),c).then(function(s){return m(e,n,s)})},"post-json:apply:json:":function(e,t,n,r){let o;try{o=JSON.parse(r)}catch{o={}}return f("POST",t,l(e),JSON.stringify(o)).then(function(c){return m(e,n,c)})},"put-json:apply:json:":function(e,t,n,r){let o;try{o=JSON.parse(r)}catch{o={}}return f("PUT",t,l(e),JSON.stringify(o)).then(function(c){return m(e,n,c)})}},I=!1;function ee(e,t){if(!e.hasAttribute("push-url"))return;let n=e.getAttribute("push-url");if(!n){let r=w(t.split(";")[0].split("|")[0].trim());r.args.length>0&&(n=r.args[0].split(/\s/)[0]||"")}n&&location.pathname+location.search!==n&&history.pushState({sender:t},"",n)}function G(e){!e||!e.sender||(I=!0,W(e.sender),I=!1)}window.addEventListener("popstate",function(e){G(e.state)});function L(e,t,n,r){return e.isConnected?e:(t&&t.isConnected?t.previousElementSibling:n&&n.isConnected?n.lastElementChild:null)||S(r)[0]}function j(e,t){let n=S(e.receiver);if(n.length===0){console.error(e.receiver+" not found");return}let r=null,o=e.keywords,c=e.args,s=o.indexOf("loading:");s!==-1&&(r=c[s],o=o.filter(function(d,v){return v!==s}),c=c.filter(function(d,v){return v!==s}));let i=o.join(""),a=b[i];if(!a){console.error(e.receiver+" does not understand "+i);return}let p=t!==void 0?[t].concat(c):c,h;return n.forEach(function(d){let v={receiver:e.receiver,selector:i,args:e.args},N=d.parentNode,C=d.nextElementSibling;if(r&&d.classList.add(r),h=a(d,...p),h&&typeof h.then=="function")h.then(function(){r&&d.classList.remove(r);let g=L(d,C,N,e.receiver);g&&g.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:v}))},function(g){r&&d.classList.remove(r),v.error=g;let F=L(d,C,N,e.receiver);F&&F.dispatchEvent(new CustomEvent("talkdom:error",{bubbles:!0,detail:v}))});else{r&&d.classList.remove(r);let g=L(d,C,N,e.receiver);g&&g.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:v}))}}),h}function z(e){let t=e.trim();if(t.indexOf(";")===-1&&t.indexOf("|")===-1)return Promise.resolve(j(w(t))).then(function(r){return[r]});let n=t.split(";").map(function(r){let o=r.trim();if(!o)return Promise.resolve();let c=o.split("|").map(function(s){return s.trim()}).filter(Boolean);return c.length===1?Promise.resolve(j(w(c[0]))):c.reduce(function(s,i){let a=w(i);return Promise.resolve(s).then(function(p){return j(a,p)})},void 0)});return Promise.all(n)}function W(e){z(e).catch(function(t){console.warn("talkDOM:",t)})}function te(e){let t=e.getAttribute("sender");W(t),I||ee(e,t)}function ne(e){let t=e.match(/^(\d+)(s|ms)$/);if(!t)return null;let n=parseInt(t[1],10);return t[2]==="s"?n*1e3:n}var D=0,O=64;function R(e){let t=e.getAttribute("receiver"),n=w(t);if(n.keywords[n.keywords.length-1]!=="poll:")return;if(D>=O){console.warn("talkDOM: max pollers ("+O+") reached, ignoring "+n.receiver);return}let r=ne(n.args[n.args.length-1]);if(!r){console.error("poll: invalid interval for "+n.receiver);return}let o=n.keywords.slice(0,-1).join(""),c=n.args.slice(0,-1),s=n.receiver,i=S(s),a=b[o];D++;let p=setInterval(function(){if(!e.isConnected){clearInterval(p),D--;return}if((i.length===0||!i[0].isConnected)&&(i=S(s)),i.length!==0){if(a||(a=b[o]),!a){console.error(s+" does not understand "+o);return}i.forEach(function(h){a(h,...c)})}},r)}document.addEventListener("click",function(e){let t=e.target.closest("[sender]");t&&(e.preventDefault(),te(t))});Q();G(history.state);document.querySelectorAll("[receiver]").forEach(R);new MutationObserver(function(e){for(let t=0;t<e.length;t++){let n=e[t].addedNodes;for(let r=0;r<n.length;r++){let o=n[r];if(o.nodeType===Node.ELEMENT_NODE){o.hasAttribute&&o.hasAttribute("receiver")&&R(o);let c=o.querySelectorAll?o.querySelectorAll("[receiver]"):[];for(let s=0;s<c.length;s++)R(c[s])}}}}).observe(document,{childList:!0,subtree:!0});var J={methods:b,send:z,get maxPollers(){return O},set maxPollers(e){O=e}};window.talkDOM=J;var re=/\s+/,_=1e3,B=3e4,V=5e3,E=16,u=Object.create(null);function oe(e){let t=e.trim().split(re);for(let n=1;n<t.length;n++)if(t[n]==="ws:"&&t[n+1])return t[n+1];return null}function M(e){return e.receivers.forEach(function(t){t.isConnected||e.receivers.delete(t)}),e.receivers.size>0}function U(e,t,n){e.receivers.forEach(function(r){r.isConnected&&r.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:n}))})}function ce(e,t){let n=t.receiver,r=t.op||"inner",o=t.content||"",c=n?document.querySelectorAll('[receiver~="'+n+'"]'):Array.from(e.receivers),s={receiver:n||"",selector:"apply:",args:[o,r]};for(let i=0;i<c.length;i++){let a=c[i];b["apply:"](a,o,r),a.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:s}))}}function se(e,t){let n=u[e];if(!n)return;M(n);let r=t.data;if(typeof r=="string")if(r.charAt(0)==="{")try{let o=JSON.parse(r);ce(n,o)}catch(o){console.error("talkdom-ws: invalid JSON from "+e,o)}else J.send(r).catch(function(o){console.warn("talkdom-ws:",o)})}function ie(e){let t=u[e];if(!t)return;if(!M(t)){A(e);return}let n=Math.min(t.backoff,B);n=n*(.75+Math.random()*.5),t.timer=setTimeout(function(){t.backoff=Math.min(t.backoff*2,B),H(e)},n)}function A(e){let t=u[e];t&&(t.timer&&clearTimeout(t.timer),t.checkTimer&&clearInterval(t.checkTimer),t.ws&&(t.ws.onclose=null,t.ws.close()),delete u[e])}function H(e){let t=u[e];if(!t||t.ws&&(t.ws.readyState===WebSocket.OPEN||t.ws.readyState===WebSocket.CONNECTING))return;let n=new WebSocket(e);n.onopen=function(){t.backoff=_,U(t,"talkdom:ws:open",{url:e})},n.onmessage=function(r){se(e,r)},n.onclose=function(r){U(t,"talkdom:ws:close",{url:e,code:r.code,reason:r.reason}),ie(e)},n.onerror=function(){U(t,"talkdom:ws:error",{url:e})},t.ws=n}function ue(e,t){let n=u[t];if(!n){if(Object.keys(u).length>=E){console.warn("talkdom-ws: max connections ("+E+") reached, ignoring "+t);return}n={ws:null,receivers:new Set,backoff:_,timer:null,checkTimer:null},u[t]=n,n.checkTimer=setInterval(function(){M(n)||A(t)},V)}n.receivers.add(e),H(t)}function X(e){let t=e.getAttribute("receiver");if(!t)return;let n=oe(t);n&&ue(e,n)}function ae(){document.querySelectorAll("[receiver]").forEach(X)}new MutationObserver(function(e){for(let t=0;t<e.length;t++){let n=e[t].addedNodes;for(let r=0;r<n.length;r++){let o=n[r];o.nodeType===1&&(o.hasAttribute&&o.hasAttribute("receiver")&&X(o),o.querySelectorAll&&o.querySelectorAll("[receiver]").forEach(X))}}}).observe(document,{childList:!0,subtree:!0});b["ws:send:"]=function(e,t){let n=u[t];if(!n||!n.ws||n.ws.readyState!==WebSocket.OPEN)return console.error("talkdom-ws: no open connection to "+t),Promise.reject("not connected");let r="value"in e?e.value:e.textContent;n.ws.send(r)};ae();var de={connect:function(e){if(!u[e]){if(Object.keys(u).length>=E){console.warn("talkdom-ws: max connections ("+E+") reached");return}u[e]={ws:null,receivers:new Set,backoff:_,timer:null,checkTimer:null},u[e].checkTimer=setInterval(function(){M(u[e])||A(e)},V)}H(e)},disconnect:function(e){A(e)},send:function(e,t){let n=u[e];return!n||!n.ws||n.ws.readyState!==WebSocket.OPEN?!1:(n.ws.send(typeof t=="string"?t:JSON.stringify(t)),!0)},get connections(){let e=Object.create(null);for(let t in u)e[t]={state:u[t].ws?u[t].ws.readyState:-1,receivers:u[t].receivers.size};return e},get maxConnections(){return E}};export{de as ws};
|
|
2
|
+
//# sourceMappingURL=talkdom-ws.esm.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.js", "../src/websocket.js"],
|
|
4
|
+
"sourcesContent": ["const WS = /\\s+/;\nconst STORAGE_PREFIX = \"talkDOM:\";\n\n// Parse \"receiver keyword: arg keyword: arg\" into structured message object.\n// Tokens ending with \":\" are keywords, everything else fills args.\nfunction parseMessage(str) {\n const trimmed = str.trim();\n const tokens = trimmed.split(WS);\n const receiver = tokens[0];\n const body = trimmed.substring(receiver.length).trim();\n const rest = tokens.slice(1);\n const keywords = [];\n const args = [];\n let currentArg = [];\n\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i];\n if (token.endsWith(\":\")) {\n if (keywords.length > 0 && currentArg.length > 0) {\n args.push(currentArg.join(\" \"));\n currentArg = [];\n } else if (keywords.length > 0) {\n args.push(\"\");\n }\n keywords.push(token);\n } else {\n currentArg.push(token);\n }\n }\n if (keywords.length > 0) {\n args.push(currentArg.join(\" \"));\n }\n\n return { receiver, selector: keywords.join(\"\"), keywords, args, body };\n}\n\n// Extract the first word from the receiver attribute (the name).\nfunction receiverName(el) {\n const attr = el.getAttribute(\"receiver\").trim();\n const sp = attr.indexOf(\" \");\n return sp === -1 ? attr : attr.substring(0, sp);\n}\n\n// Receiver cache: maps name -> NodeList, invalidated by DOM mutations.\nconst receiverCache = Object.create(null);\nlet cacheValid = false;\n\nnew MutationObserver(() => { cacheValid = false; })\n .observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: [\"receiver\"] });\n\n// Find all elements whose receiver attribute contains the given name.\nfunction findReceivers(name) {\n if (!cacheValid) {\n Object.keys(receiverCache).forEach(key => delete receiverCache[key]);\n cacheValid = true;\n }\n if (receiverCache[name]) return receiverCache[name];\n const result = document.querySelectorAll('[receiver~=\"' + name + '\"]');\n receiverCache[name] = result;\n return result;\n}\n\n// Check if a receiver allows a given apply operation (inner, text, append, outer).\n// No \"accepts\" attribute means everything is allowed.\nfunction accepts(el, op) {\n const attr = el.getAttribute(\"accepts\");\n if (!attr) return true;\n return (\" \" + attr + \" \").includes(\" \" + op + \" \");\n}\n\n// Save receiver content to localStorage after apply, keyed by receiver name.\nfunction persist(el, op) {\n if (!el.hasAttribute(\"receiver\") || !el.hasAttribute(\"persist\")) return;\n const name = receiverName(el);\n const key = STORAGE_PREFIX + name;\n const content = op === \"outer\" ? el.outerHTML : el.innerHTML;\n localStorage.setItem(key, JSON.stringify({ op, content }));\n}\n\n// On page load, restore persisted receiver content from localStorage.\nfunction restore() {\n document.querySelectorAll(\"[persist]\").forEach((el) => {\n if (!el.hasAttribute(\"receiver\")) return;\n const name = receiverName(el);\n const raw = localStorage.getItem(STORAGE_PREFIX + name);\n if (!raw) return;\n let state;\n try { state = JSON.parse(raw); } catch {\n localStorage.removeItem(STORAGE_PREFIX + name);\n return;\n }\n if (state.op === \"outer\") {\n el.outerHTML = state.content;\n } else {\n el.innerHTML = state.content;\n }\n });\n}\n\n// Apply content to an element using the specified operation (inner, text, append, outer).\nfunction apply(el, op, content) {\n if (!accepts(el, op)) {\n console.error(receiverName(el) + \" does not accept \" + op);\n return;\n }\n switch (op) {\n case \"inner\": el.innerHTML = content; break;\n case \"text\": el.textContent = content; break;\n case \"append\": el.insertAdjacentHTML(\"beforeend\", content); break;\n case \"outer\": el.outerHTML = content; break;\n }\n persist(el, op);\n return content;\n}\n\nlet csrfMeta = null;\n\nfunction csrfToken() {\n if (!csrfMeta || !csrfMeta.isConnected) {\n csrfMeta = document.querySelector('meta[name=\"csrf-token\"]');\n }\n return csrfMeta ? csrfMeta.getAttribute(\"content\") : \"\";\n}\n\n// Perform a fetch with talkDOM headers. Returns a promise resolving to response text.\n// Fires server-triggered messages from X-TalkDOM-Trigger header if present.\nfunction request(method, url, receiver, body) {\n const headers = {\n \"X-TalkDOM-Request\": \"true\",\n \"X-TalkDOM-Current-URL\": location.href,\n };\n if (receiver) {\n headers[\"X-TalkDOM-Receiver\"] = receiver;\n }\n if (method !== \"GET\") {\n const token = csrfToken();\n if (token) headers[\"X-CSRF-Token\"] = token;\n else console.warn(\"talkDOM: no CSRF token found for \" + method + \" \" + url);\n }\n return fetch(url, { method, headers, body }).then((r) => {\n if (!r.ok) {\n console.error(\"talkDOM: \" + method + \" \" + url + \" \" + r.status);\n return Promise.reject(r.status);\n }\n const trigger = r.headers.get(\"X-TalkDOM-Trigger\");\n return r.text().then((text) => {\n if (trigger) dispatchRaw(trigger);\n return text;\n });\n });\n}\n\nfunction serializeForm(form) {\n return new URLSearchParams(new FormData(form)).toString();\n}\n\nfunction recName(el) {\n return el.hasAttribute(\"receiver\") ? receiverName(el) : \"\";\n}\n\n// Built-in method table. Each method receives (el, ...args) from the parsed message.\n// Extensible via talkDOM.methods at runtime.\nconst methods = {\n \"get:\": function (el, url) { return request(\"GET\", url, recName(el)); },\n \"post:\": function (el, url) { return request(\"POST\", url, recName(el)); },\n \"put:\": function (el, url) { return request(\"PUT\", url, recName(el)); },\n \"delete:\": function (el, url) { return request(\"DELETE\", url, recName(el)); },\n \"confirm:\": function (el, message) { if (!confirm(message)) return Promise.reject(\"cancelled\"); },\n \"apply:\": function (el, content, op) { return apply(el, op, content); },\n \"get:apply:\": function (el, url, op) { return request(\"GET\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"post:apply:\": function (el, url, op) { return request(\"POST\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"put:apply:\": function (el, url, op) { return request(\"PUT\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"delete:apply:\": function (el, url, op) { return request(\"DELETE\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"post-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"post-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"POST\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"put-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"put-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"PUT\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"delete-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"delete-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"DELETE\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"post-json:apply:json:\": function (el, url, op, jsonStr) {\n let data;\n try { data = JSON.parse(jsonStr); } catch { data = {}; }\n return request(\"POST\", url, recName(el), JSON.stringify(data)).then(function (t) { return apply(el, op, t); });\n },\n \"put-json:apply:json:\": function (el, url, op, jsonStr) {\n let data;\n try { data = JSON.parse(jsonStr); } catch { data = {}; }\n return request(\"PUT\", url, recName(el), JSON.stringify(data)).then(function (t) { return apply(el, op, t); });\n },\n};\n\nlet pushing = false;\n\n// Push URL to browser history. Uses push-url attr value, or falls back to first message arg.\nfunction pushUrl(senderEl, raw) {\n if (!senderEl.hasAttribute(\"push-url\")) return;\n let url = senderEl.getAttribute(\"push-url\");\n if (!url) {\n const msg = parseMessage(raw.split(\";\")[0].split(\"|\")[0].trim());\n if (msg.args.length > 0) {\n url = msg.args[0].split(/\\s/)[0] || \"\";\n }\n }\n if (url && (location.pathname + location.search) !== url) {\n history.pushState({ sender: raw }, \"\", url);\n }\n}\n\n// Re-dispatch a sender message from history state (back/forward navigation).\nfunction replayState(state) {\n if (!state || !state.sender) return;\n pushing = true;\n dispatchRaw(state.sender);\n pushing = false;\n}\n\nwindow.addEventListener(\"popstate\", function (e) {\n replayState(e.state);\n});\n\n// After an outer swap `el` is gone. Walk from the snapshotted sibling or\n// parent to find the element that took its place; fall back to a fresh\n// receiver query if the DOM was restructured.\nfunction resolveTarget(el, next, parent, name) {\n if (el.isConnected) return el;\n const candidate = next && next.isConnected ? next.previousElementSibling\n : parent && parent.isConnected ? parent.lastElementChild : null;\n return candidate || findReceivers(name)[0];\n}\n\n// Deliver a parsed message to all matching receivers. Fires talkdom:done or talkdom:error\n// lifecycle events on the receiver element (or its replacement if outer-swapped).\nfunction send(msg, piped) {\n const els = findReceivers(msg.receiver);\n if (els.length === 0) {\n console.error(msg.receiver + \" not found\");\n return;\n }\n let loadingClass = null;\n let keywords = msg.keywords;\n let args = msg.args;\n const loadingIdx = keywords.indexOf(\"loading:\");\n if (loadingIdx !== -1) {\n loadingClass = args[loadingIdx];\n keywords = keywords.filter(function (_, i) { return i !== loadingIdx; });\n args = args.filter(function (_, i) { return i !== loadingIdx; });\n }\n const selector = keywords.join(\"\");\n const method = methods[selector];\n if (!method) {\n console.error(msg.receiver + \" does not understand \" + selector);\n return;\n }\n const finalArgs = piped !== undefined ? [piped].concat(args) : args;\n let result;\n els.forEach(function (el) {\n const detail = { receiver: msg.receiver, selector: selector, args: msg.args };\n const parent = el.parentNode;\n const next = el.nextElementSibling;\n if (loadingClass) el.classList.add(loadingClass);\n result = method(el, ...finalArgs);\n if (result && typeof result.then === \"function\") {\n result.then(function () {\n if (loadingClass) el.classList.remove(loadingClass);\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:done\", { bubbles: true, detail }));\n }, function (err) {\n if (loadingClass) el.classList.remove(loadingClass);\n detail.error = err;\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:error\", { bubbles: true, detail }));\n });\n } else {\n if (loadingClass) el.classList.remove(loadingClass);\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:done\", { bubbles: true, detail }));\n }\n });\n return result;\n}\n\n// Programmatic API: parse and execute a raw message string (supports pipes and semicolons).\n// Returns a promise that resolves when all chains complete.\nfunction run(raw) {\n const trimmed = raw.trim();\n if (trimmed.indexOf(\";\") === -1 && trimmed.indexOf(\"|\") === -1) {\n return Promise.resolve(send(parseMessage(trimmed))).then(function (r) { return [r]; });\n }\n const chains = trimmed.split(\";\").map(function (chain) {\n const step = chain.trim();\n if (!step) return Promise.resolve();\n const steps = step.split(\"|\").map(function (s) { return s.trim(); }).filter(Boolean);\n if (steps.length === 1) {\n return Promise.resolve(send(parseMessage(steps[0])));\n }\n return steps.reduce(function (prev, step) {\n const msg = parseMessage(step);\n return Promise.resolve(prev).then(function (piped) {\n return send(msg, piped);\n });\n }, undefined);\n });\n return Promise.all(chains);\n}\n\n// Fire-and-forget dispatch used by declarative senders and server triggers.\nfunction dispatchRaw(raw) {\n run(raw).catch(function (err) { console.warn(\"talkDOM:\", err); });\n}\n\n// Entry point for a sender click: dispatch its message and optionally push URL.\nfunction dispatch(senderEl) {\n const raw = senderEl.getAttribute(\"sender\");\n dispatchRaw(raw);\n if (!pushing) pushUrl(senderEl, raw);\n}\n\nfunction parseInterval(str) {\n const match = str.match(/^(\\d+)(s|ms)$/);\n if (!match) return null;\n const n = parseInt(match[1], 10);\n return match[2] === \"s\" ? n * 1000 : n;\n}\n\n// Set up a repeating interval for receivers with a poll: keyword.\nlet activePollers = 0;\nlet maxPollers = 64;\n\nfunction startPolling(el) {\n const attr = el.getAttribute(\"receiver\");\n const msg = parseMessage(attr);\n if (msg.keywords[msg.keywords.length - 1] !== \"poll:\") return;\n if (activePollers >= maxPollers) {\n console.warn(\"talkDOM: max pollers (\" + maxPollers + \") reached, ignoring \" + msg.receiver);\n return;\n }\n const interval = parseInterval(msg.args[msg.args.length - 1]);\n if (!interval) {\n console.error(\"poll: invalid interval for \" + msg.receiver);\n return;\n }\n const selector = msg.keywords.slice(0, -1).join(\"\");\n const args = msg.args.slice(0, -1);\n const name = msg.receiver;\n let cachedTargets = findReceivers(name);\n let method = methods[selector];\n activePollers++;\n const id = setInterval(function () {\n if (!el.isConnected) { clearInterval(id); activePollers--; return; }\n if (cachedTargets.length === 0 || !cachedTargets[0].isConnected) {\n cachedTargets = findReceivers(name);\n }\n if (cachedTargets.length === 0) return;\n if (!method) method = methods[selector];\n if (!method) {\n console.error(name + \" does not understand \" + selector);\n return;\n }\n cachedTargets.forEach(function (target) { method(target, ...args); });\n }, interval);\n}\n\n// Global click handler: delegate to any element with a sender attribute.\ndocument.addEventListener(\"click\", function (e) {\n const sender = e.target.closest(\"[sender]\");\n if (sender) {\n e.preventDefault();\n dispatch(sender);\n }\n});\n\nrestore();\nreplayState(history.state);\ndocument.querySelectorAll(\"[receiver]\").forEach(startPolling);\n\nnew MutationObserver(function (mutations) {\n for (let i = 0; i < mutations.length; i++) {\n const added = mutations[i].addedNodes;\n for (let j = 0; j < added.length; j++) {\n const node = added[j];\n if (node.nodeType === Node.ELEMENT_NODE) {\n if (node.hasAttribute && node.hasAttribute(\"receiver\")) {\n startPolling(node);\n }\n const children = node.querySelectorAll ? node.querySelectorAll(\"[receiver]\") : [];\n for (let k = 0; k < children.length; k++) {\n startPolling(children[k]);\n }\n }\n }\n };\n}).observe(document, { childList: true, subtree: true });\n\nconst talkDOM = {\n methods,\n send: run,\n get maxPollers() { return maxPollers; },\n set maxPollers(n) { maxPollers = n; },\n};\n\nwindow.talkDOM = talkDOM;\n\nexport { parseMessage, receiverName, findReceivers, accepts, persist, restore, apply, request, methods, run, dispatchRaw, talkDOM };\n", "import { methods, talkDOM } from \"./index.js\";\n\nconst WS = /\\s+/;\nconst BASE_DELAY = 1000;\nconst MAX_DELAY = 30000;\nconst CLEANUP_INTERVAL = 5000;\nconst MAX_CONNECTIONS = 16;\n\nconst connections = Object.create(null);\n\n// Parse receiver attribute to extract ws: URL.\nfunction parseWsUrl(attr) {\n const tokens = attr.trim().split(WS);\n for (let i = 1; i < tokens.length; i++) {\n if (tokens[i] === \"ws:\" && tokens[i + 1]) return tokens[i + 1];\n }\n return null;\n}\n\n// Remove disconnected elements from a connection's receiver set.\nfunction pruneReceivers(conn) {\n conn.receivers.forEach(function (el) {\n if (!el.isConnected) conn.receivers.delete(el);\n });\n return conn.receivers.size > 0;\n}\n\n// Fire a custom event on all connected receivers for a URL.\nfunction fireEvent(conn, name, detail) {\n conn.receivers.forEach(function (el) {\n if (el.isConnected) {\n el.dispatchEvent(new CustomEvent(name, { bubbles: true, detail }));\n }\n });\n}\n\n// Route a parsed JSON message to matching receiver elements.\nfunction routeJson(conn, msg) {\n const name = msg.receiver;\n const op = msg.op || \"inner\";\n const content = msg.content || \"\";\n const targets = name\n ? document.querySelectorAll('[receiver~=\"' + name + '\"]')\n : Array.from(conn.receivers);\n\n const detail = { receiver: name || \"\", selector: \"apply:\", args: [content, op] };\n for (let i = 0; i < targets.length; i++) {\n const el = targets[i];\n methods[\"apply:\"](el, content, op);\n el.dispatchEvent(new CustomEvent(\"talkdom:done\", { bubbles: true, detail }));\n }\n}\n\n// Handle an incoming WebSocket message.\nfunction onMessage(url, event) {\n const conn = connections[url];\n if (!conn) return;\n pruneReceivers(conn);\n const data = event.data;\n if (typeof data !== \"string\") return;\n if (data.charAt(0) === \"{\") {\n try {\n const msg = JSON.parse(data);\n routeJson(conn, msg);\n } catch (e) {\n console.error(\"talkdom-ws: invalid JSON from \" + url, e);\n }\n } else {\n talkDOM.send(data).catch(function (err) {\n console.warn(\"talkdom-ws:\", err);\n });\n }\n}\n\nfunction scheduleReconnect(url) {\n const conn = connections[url];\n if (!conn) return;\n if (!pruneReceivers(conn)) { cleanup(url); return; }\n let delay = Math.min(conn.backoff, MAX_DELAY);\n delay = delay * (0.75 + Math.random() * 0.5);\n conn.timer = setTimeout(function () {\n conn.backoff = Math.min(conn.backoff * 2, MAX_DELAY);\n connectWs(url);\n }, delay);\n}\n\nfunction cleanup(url) {\n const conn = connections[url];\n if (!conn) return;\n if (conn.timer) clearTimeout(conn.timer);\n if (conn.checkTimer) clearInterval(conn.checkTimer);\n if (conn.ws) {\n conn.ws.onclose = null;\n conn.ws.close();\n }\n delete connections[url];\n}\n\nfunction connectWs(url) {\n const conn = connections[url];\n if (!conn) return;\n if (conn.ws && (conn.ws.readyState === WebSocket.OPEN || conn.ws.readyState === WebSocket.CONNECTING)) return;\n\n const ws = new WebSocket(url);\n\n ws.onopen = function () {\n conn.backoff = BASE_DELAY;\n fireEvent(conn, \"talkdom:ws:open\", { url });\n };\n\n ws.onmessage = function (e) {\n onMessage(url, e);\n };\n\n ws.onclose = function (e) {\n fireEvent(conn, \"talkdom:ws:close\", { url, code: e.code, reason: e.reason });\n scheduleReconnect(url);\n };\n\n ws.onerror = function () {\n fireEvent(conn, \"talkdom:ws:error\", { url });\n };\n\n conn.ws = ws;\n}\n\n// Subscribe an element to a WebSocket URL.\nfunction subscribe(el, url) {\n let conn = connections[url];\n if (!conn) {\n const count = Object.keys(connections).length;\n if (count >= MAX_CONNECTIONS) {\n console.warn(\"talkdom-ws: max connections (\" + MAX_CONNECTIONS + \") reached, ignoring \" + url);\n return;\n }\n conn = { ws: null, receivers: new Set(), backoff: BASE_DELAY, timer: null, checkTimer: null };\n connections[url] = conn;\n conn.checkTimer = setInterval(function () {\n if (!pruneReceivers(conn)) cleanup(url);\n }, CLEANUP_INTERVAL);\n }\n conn.receivers.add(el);\n connectWs(url);\n}\n\n// Scan a single element for ws: keyword and subscribe.\nfunction initElement(el) {\n const attr = el.getAttribute(\"receiver\");\n if (!attr) return;\n const url = parseWsUrl(attr);\n if (!url) return;\n subscribe(el, url);\n}\n\n// Scan all existing receiver elements.\nfunction initWsReceivers() {\n document.querySelectorAll(\"[receiver]\").forEach(initElement);\n}\n\n// Watch for dynamically added ws: receivers.\nnew MutationObserver(function (mutations) {\n for (let i = 0; i < mutations.length; i++) {\n const added = mutations[i].addedNodes;\n for (let j = 0; j < added.length; j++) {\n const node = added[j];\n if (node.nodeType !== 1) continue;\n if (node.hasAttribute && node.hasAttribute(\"receiver\")) initElement(node);\n if (node.querySelectorAll) {\n node.querySelectorAll(\"[receiver]\").forEach(initElement);\n }\n }\n }\n}).observe(document, { childList: true, subtree: true });\n\n// ws:send: method\nmethods[\"ws:send:\"] = function (el, url) {\n const conn = connections[url];\n if (!conn || !conn.ws || conn.ws.readyState !== WebSocket.OPEN) {\n console.error(\"talkdom-ws: no open connection to \" + url);\n return Promise.reject(\"not connected\");\n }\n const payload = (\"value\" in el) ? el.value : el.textContent;\n conn.ws.send(payload);\n};\n\ninitWsReceivers();\n\nconst ws = {\n connect: function (url) {\n if (!connections[url]) {\n const count = Object.keys(connections).length;\n if (count >= MAX_CONNECTIONS) {\n console.warn(\"talkdom-ws: max connections (\" + MAX_CONNECTIONS + \") reached\");\n return;\n }\n connections[url] = { ws: null, receivers: new Set(), backoff: BASE_DELAY, timer: null, checkTimer: null };\n connections[url].checkTimer = setInterval(function () {\n if (!pruneReceivers(connections[url])) cleanup(url);\n }, CLEANUP_INTERVAL);\n }\n connectWs(url);\n },\n disconnect: function (url) { cleanup(url); },\n send: function (url, data) {\n const conn = connections[url];\n if (!conn || !conn.ws || conn.ws.readyState !== WebSocket.OPEN) return false;\n conn.ws.send(typeof data === \"string\" ? data : JSON.stringify(data));\n return true;\n },\n get connections() {\n const out = Object.create(null);\n for (const url in connections) {\n out[url] = {\n state: connections[url].ws ? connections[url].ws.readyState : -1,\n receivers: connections[url].receivers.size,\n };\n }\n return out;\n },\n get maxConnections() { return MAX_CONNECTIONS; },\n};\n\nexport { ws };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["WS", "STORAGE_PREFIX", "parseMessage", "str", "trimmed", "tokens", "receiver", "body", "rest", "keywords", "args", "currentArg", "i", "token", "receiverName", "el", "attr", "sp", "receiverCache", "cacheValid", "findReceivers", "name", "key", "result", "accepts", "op", "persist", "content", "restore", "raw", "state", "apply", "csrfMeta", "csrfToken", "request", "method", "url", "headers", "r", "trigger", "text", "dispatchRaw", "serializeForm", "form", "recName", "methods", "message", "t", "formSelector", "jsonStr", "data", "pushing", "pushUrl", "senderEl", "msg", "replayState", "resolveTarget", "next", "parent", "send", "piped", "els", "loadingClass", "loadingIdx", "_", "selector", "finalArgs", "detail", "target", "err", "run", "chains", "chain", "step", "steps", "prev", "dispatch", "parseInterval", "match", "activePollers", "maxPollers", "startPolling", "interval", "cachedTargets", "id", "sender", "mutations", "added", "j", "node", "children", "k", "talkDOM", "n", "WS", "BASE_DELAY", "MAX_DELAY", "CLEANUP_INTERVAL", "MAX_CONNECTIONS", "connections", "parseWsUrl", "attr", "tokens", "i", "pruneReceivers", "conn", "el", "fireEvent", "name", "detail", "routeJson", "msg", "op", "content", "targets", "methods", "onMessage", "url", "event", "data", "e", "talkDOM", "err", "scheduleReconnect", "cleanup", "delay", "connectWs", "ws", "subscribe", "initElement", "initWsReceivers", "mutations", "added", "j", "node", "payload", "out"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(()=>{var Y=/\s+/,x="talkDOM:";function w(e){let t=e.trim(),n=t.split(Y),r=n[0],o=t.substring(r.length).trim(),c=n.slice(1),s=[],i=[],a=[];for(let p=0;p<c.length;p++){let h=c[p];h.endsWith(":")?(s.length>0&&a.length>0?(i.push(a.join(" ")),a=[]):s.length>0&&i.push(""),s.push(h)):a.push(h)}return s.length>0&&i.push(a.join(" ")),{receiver:r,selector:s.join(""),keywords:s,args:i,body:o}}function T(e){let t=e.getAttribute("receiver").trim(),n=t.indexOf(" ");return n===-1?t:t.substring(0,n)}var k=Object.create(null),q=!1;new MutationObserver(()=>{q=!1}).observe(document,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["receiver"]});function S(e){if(q||(Object.keys(k).forEach(n=>delete k[n]),q=!0),k[e])return k[e];let t=document.querySelectorAll('[receiver~="'+e+'"]');return k[e]=t,t}function $(e,t){let n=e.getAttribute("accepts");return n?(" "+n+" ").includes(" "+t+" "):!0}function K(e,t){if(!e.hasAttribute("receiver")||!e.hasAttribute("persist"))return;let n=T(e),r=x+n,o=t==="outer"?e.outerHTML:e.innerHTML;localStorage.setItem(r,JSON.stringify({op:t,content:o}))}function Q(){document.querySelectorAll("[persist]").forEach(e=>{if(!e.hasAttribute("receiver"))return;let t=T(e),n=localStorage.getItem(x+t);if(!n)return;let r;try{r=JSON.parse(n)}catch{localStorage.removeItem(x+t);return}r.op==="outer"?e.outerHTML=r.content:e.innerHTML=r.content})}function m(e,t,n){if(!$(e,t)){console.error(T(e)+" does not accept "+t);return}switch(t){case"inner":e.innerHTML=n;break;case"text":e.textContent=n;break;case"append":e.insertAdjacentHTML("beforeend",n);break;case"outer":e.outerHTML=n;break}return K(e,t),n}var y=null;function Z(){return(!y||!y.isConnected)&&(y=document.querySelector('meta[name="csrf-token"]')),y?y.getAttribute("content"):""}function f(e,t,n,r){let o={"X-TalkDOM-Request":"true","X-TalkDOM-Current-URL":location.href};if(n&&(o["X-TalkDOM-Receiver"]=n),e!=="GET"){let c=Z();c?o["X-CSRF-Token"]=c:console.warn("talkDOM: no CSRF token found for "+e+" "+t)}return fetch(t,{method:e,headers:o,body:r}).then(c=>{if(!c.ok)return console.error("talkDOM: "+e+" "+t+" "+c.status),Promise.reject(c.status);let s=c.headers.get("X-TalkDOM-Trigger");return c.text().then(i=>(s&&W(s),i))})}function P(e){return new URLSearchParams(new FormData(e)).toString()}function l(e){return e.hasAttribute("receiver")?T(e):""}var b={"get:":function(e,t){return f("GET",t,l(e))},"post:":function(e,t){return f("POST",t,l(e))},"put:":function(e,t){return f("PUT",t,l(e))},"delete:":function(e,t){return f("DELETE",t,l(e))},"confirm:":function(e,t){if(!confirm(t))return Promise.reject("cancelled")},"apply:":function(e,t,n){return m(e,n,t)},"get:apply:":function(e,t,n){return f("GET",t,l(e)).then(function(r){return m(e,n,r)})},"post:apply:":function(e,t,n){return f("POST",t,l(e)).then(function(r){return m(e,n,r)})},"put:apply:":function(e,t,n){return f("PUT",t,l(e)).then(function(r){return m(e,n,r)})},"delete:apply:":function(e,t,n){return f("DELETE",t,l(e)).then(function(r){return m(e,n,r)})},"post-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("post-form: form not found: "+r);return}let c=P(o);return f("POST",t,l(e),c).then(function(s){return m(e,n,s)})},"put-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("put-form: form not found: "+r);return}let c=P(o);return f("PUT",t,l(e),c).then(function(s){return m(e,n,s)})},"delete-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("delete-form: form not found: "+r);return}let c=P(o);return f("DELETE",t,l(e),c).then(function(s){return m(e,n,s)})},"post-json:apply:json:":function(e,t,n,r){let o;try{o=JSON.parse(r)}catch{o={}}return f("POST",t,l(e),JSON.stringify(o)).then(function(c){return m(e,n,c)})},"put-json:apply:json:":function(e,t,n,r){let o;try{o=JSON.parse(r)}catch{o={}}return f("PUT",t,l(e),JSON.stringify(o)).then(function(c){return m(e,n,c)})}},I=!1;function ee(e,t){if(!e.hasAttribute("push-url"))return;let n=e.getAttribute("push-url");if(!n){let r=w(t.split(";")[0].split("|")[0].trim());r.args.length>0&&(n=r.args[0].split(/\s/)[0]||"")}n&&location.pathname+location.search!==n&&history.pushState({sender:t},"",n)}function G(e){!e||!e.sender||(I=!0,W(e.sender),I=!1)}window.addEventListener("popstate",function(e){G(e.state)});function L(e,t,n,r){return e.isConnected?e:(t&&t.isConnected?t.previousElementSibling:n&&n.isConnected?n.lastElementChild:null)||S(r)[0]}function j(e,t){let n=S(e.receiver);if(n.length===0){console.error(e.receiver+" not found");return}let r=null,o=e.keywords,c=e.args,s=o.indexOf("loading:");s!==-1&&(r=c[s],o=o.filter(function(d,v){return v!==s}),c=c.filter(function(d,v){return v!==s}));let i=o.join(""),a=b[i];if(!a){console.error(e.receiver+" does not understand "+i);return}let p=t!==void 0?[t].concat(c):c,h;return n.forEach(function(d){let v={receiver:e.receiver,selector:i,args:e.args},N=d.parentNode,C=d.nextElementSibling;if(r&&d.classList.add(r),h=a(d,...p),h&&typeof h.then=="function")h.then(function(){r&&d.classList.remove(r);let g=L(d,C,N,e.receiver);g&&g.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:v}))},function(g){r&&d.classList.remove(r),v.error=g;let F=L(d,C,N,e.receiver);F&&F.dispatchEvent(new CustomEvent("talkdom:error",{bubbles:!0,detail:v}))});else{r&&d.classList.remove(r);let g=L(d,C,N,e.receiver);g&&g.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:v}))}}),h}function z(e){let t=e.trim();if(t.indexOf(";")===-1&&t.indexOf("|")===-1)return Promise.resolve(j(w(t))).then(function(r){return[r]});let n=t.split(";").map(function(r){let o=r.trim();if(!o)return Promise.resolve();let c=o.split("|").map(function(s){return s.trim()}).filter(Boolean);return c.length===1?Promise.resolve(j(w(c[0]))):c.reduce(function(s,i){let a=w(i);return Promise.resolve(s).then(function(p){return j(a,p)})},void 0)});return Promise.all(n)}function W(e){z(e).catch(function(t){console.warn("talkDOM:",t)})}function te(e){let t=e.getAttribute("sender");W(t),I||ee(e,t)}function ne(e){let t=e.match(/^(\d+)(s|ms)$/);if(!t)return null;let n=parseInt(t[1],10);return t[2]==="s"?n*1e3:n}var D=0,O=64;function R(e){let t=e.getAttribute("receiver"),n=w(t);if(n.keywords[n.keywords.length-1]!=="poll:")return;if(D>=O){console.warn("talkDOM: max pollers ("+O+") reached, ignoring "+n.receiver);return}let r=ne(n.args[n.args.length-1]);if(!r){console.error("poll: invalid interval for "+n.receiver);return}let o=n.keywords.slice(0,-1).join(""),c=n.args.slice(0,-1),s=n.receiver,i=S(s),a=b[o];D++;let p=setInterval(function(){if(!e.isConnected){clearInterval(p),D--;return}if((i.length===0||!i[0].isConnected)&&(i=S(s)),i.length!==0){if(a||(a=b[o]),!a){console.error(s+" does not understand "+o);return}i.forEach(function(h){a(h,...c)})}},r)}document.addEventListener("click",function(e){let t=e.target.closest("[sender]");t&&(e.preventDefault(),te(t))});Q();G(history.state);document.querySelectorAll("[receiver]").forEach(R);new MutationObserver(function(e){for(let t=0;t<e.length;t++){let n=e[t].addedNodes;for(let r=0;r<n.length;r++){let o=n[r];if(o.nodeType===Node.ELEMENT_NODE){o.hasAttribute&&o.hasAttribute("receiver")&&R(o);let c=o.querySelectorAll?o.querySelectorAll("[receiver]"):[];for(let s=0;s<c.length;s++)R(c[s])}}}}).observe(document,{childList:!0,subtree:!0});var J={methods:b,send:z,get maxPollers(){return O},set maxPollers(e){O=e}};window.talkDOM=J;var re=/\s+/,_=1e3,B=3e4,V=5e3,E=16,u=Object.create(null);function oe(e){let t=e.trim().split(re);for(let n=1;n<t.length;n++)if(t[n]==="ws:"&&t[n+1])return t[n+1];return null}function M(e){return e.receivers.forEach(function(t){t.isConnected||e.receivers.delete(t)}),e.receivers.size>0}function U(e,t,n){e.receivers.forEach(function(r){r.isConnected&&r.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:n}))})}function ce(e,t){let n=t.receiver,r=t.op||"inner",o=t.content||"",c=n?document.querySelectorAll('[receiver~="'+n+'"]'):Array.from(e.receivers),s={receiver:n||"",selector:"apply:",args:[o,r]};for(let i=0;i<c.length;i++){let a=c[i];b["apply:"](a,o,r),a.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:s}))}}function se(e,t){let n=u[e];if(!n)return;M(n);let r=t.data;if(typeof r=="string")if(r.charAt(0)==="{")try{let o=JSON.parse(r);ce(n,o)}catch(o){console.error("talkdom-ws: invalid JSON from "+e,o)}else J.send(r).catch(function(o){console.warn("talkdom-ws:",o)})}function ie(e){let t=u[e];if(!t)return;if(!M(t)){A(e);return}let n=Math.min(t.backoff,B);n=n*(.75+Math.random()*.5),t.timer=setTimeout(function(){t.backoff=Math.min(t.backoff*2,B),H(e)},n)}function A(e){let t=u[e];t&&(t.timer&&clearTimeout(t.timer),t.checkTimer&&clearInterval(t.checkTimer),t.ws&&(t.ws.onclose=null,t.ws.close()),delete u[e])}function H(e){let t=u[e];if(!t||t.ws&&(t.ws.readyState===WebSocket.OPEN||t.ws.readyState===WebSocket.CONNECTING))return;let n=new WebSocket(e);n.onopen=function(){t.backoff=_,U(t,"talkdom:ws:open",{url:e})},n.onmessage=function(r){se(e,r)},n.onclose=function(r){U(t,"talkdom:ws:close",{url:e,code:r.code,reason:r.reason}),ie(e)},n.onerror=function(){U(t,"talkdom:ws:error",{url:e})},t.ws=n}function ue(e,t){let n=u[t];if(!n){if(Object.keys(u).length>=E){console.warn("talkdom-ws: max connections ("+E+") reached, ignoring "+t);return}n={ws:null,receivers:new Set,backoff:_,timer:null,checkTimer:null},u[t]=n,n.checkTimer=setInterval(function(){M(n)||A(t)},V)}n.receivers.add(e),H(t)}function X(e){let t=e.getAttribute("receiver");if(!t)return;let n=oe(t);n&&ue(e,n)}function ae(){document.querySelectorAll("[receiver]").forEach(X)}new MutationObserver(function(e){for(let t=0;t<e.length;t++){let n=e[t].addedNodes;for(let r=0;r<n.length;r++){let o=n[r];o.nodeType===1&&(o.hasAttribute&&o.hasAttribute("receiver")&&X(o),o.querySelectorAll&&o.querySelectorAll("[receiver]").forEach(X))}}}).observe(document,{childList:!0,subtree:!0});b["ws:send:"]=function(e,t){let n=u[t];if(!n||!n.ws||n.ws.readyState!==WebSocket.OPEN)return console.error("talkdom-ws: no open connection to "+t),Promise.reject("not connected");let r="value"in e?e.value:e.textContent;n.ws.send(r)};ae();var de={connect:function(e){if(!u[e]){if(Object.keys(u).length>=E){console.warn("talkdom-ws: max connections ("+E+") reached");return}u[e]={ws:null,receivers:new Set,backoff:_,timer:null,checkTimer:null},u[e].checkTimer=setInterval(function(){M(u[e])||A(e)},V)}H(e)},disconnect:function(e){A(e)},send:function(e,t){let n=u[e];return!n||!n.ws||n.ws.readyState!==WebSocket.OPEN?!1:(n.ws.send(typeof t=="string"?t:JSON.stringify(t)),!0)},get connections(){let e=Object.create(null);for(let t in u)e[t]={state:u[t].ws?u[t].ws.readyState:-1,receivers:u[t].receivers.size};return e},get maxConnections(){return E}};})();
|
|
2
|
+
//# sourceMappingURL=talkdom-ws.min.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.js", "../src/websocket.js"],
|
|
4
|
+
"sourcesContent": ["const WS = /\\s+/;\nconst STORAGE_PREFIX = \"talkDOM:\";\n\n// Parse \"receiver keyword: arg keyword: arg\" into structured message object.\n// Tokens ending with \":\" are keywords, everything else fills args.\nfunction parseMessage(str) {\n const trimmed = str.trim();\n const tokens = trimmed.split(WS);\n const receiver = tokens[0];\n const body = trimmed.substring(receiver.length).trim();\n const rest = tokens.slice(1);\n const keywords = [];\n const args = [];\n let currentArg = [];\n\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i];\n if (token.endsWith(\":\")) {\n if (keywords.length > 0 && currentArg.length > 0) {\n args.push(currentArg.join(\" \"));\n currentArg = [];\n } else if (keywords.length > 0) {\n args.push(\"\");\n }\n keywords.push(token);\n } else {\n currentArg.push(token);\n }\n }\n if (keywords.length > 0) {\n args.push(currentArg.join(\" \"));\n }\n\n return { receiver, selector: keywords.join(\"\"), keywords, args, body };\n}\n\n// Extract the first word from the receiver attribute (the name).\nfunction receiverName(el) {\n const attr = el.getAttribute(\"receiver\").trim();\n const sp = attr.indexOf(\" \");\n return sp === -1 ? attr : attr.substring(0, sp);\n}\n\n// Receiver cache: maps name -> NodeList, invalidated by DOM mutations.\nconst receiverCache = Object.create(null);\nlet cacheValid = false;\n\nnew MutationObserver(() => { cacheValid = false; })\n .observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: [\"receiver\"] });\n\n// Find all elements whose receiver attribute contains the given name.\nfunction findReceivers(name) {\n if (!cacheValid) {\n Object.keys(receiverCache).forEach(key => delete receiverCache[key]);\n cacheValid = true;\n }\n if (receiverCache[name]) return receiverCache[name];\n const result = document.querySelectorAll('[receiver~=\"' + name + '\"]');\n receiverCache[name] = result;\n return result;\n}\n\n// Check if a receiver allows a given apply operation (inner, text, append, outer).\n// No \"accepts\" attribute means everything is allowed.\nfunction accepts(el, op) {\n const attr = el.getAttribute(\"accepts\");\n if (!attr) return true;\n return (\" \" + attr + \" \").includes(\" \" + op + \" \");\n}\n\n// Save receiver content to localStorage after apply, keyed by receiver name.\nfunction persist(el, op) {\n if (!el.hasAttribute(\"receiver\") || !el.hasAttribute(\"persist\")) return;\n const name = receiverName(el);\n const key = STORAGE_PREFIX + name;\n const content = op === \"outer\" ? el.outerHTML : el.innerHTML;\n localStorage.setItem(key, JSON.stringify({ op, content }));\n}\n\n// On page load, restore persisted receiver content from localStorage.\nfunction restore() {\n document.querySelectorAll(\"[persist]\").forEach((el) => {\n if (!el.hasAttribute(\"receiver\")) return;\n const name = receiverName(el);\n const raw = localStorage.getItem(STORAGE_PREFIX + name);\n if (!raw) return;\n let state;\n try { state = JSON.parse(raw); } catch {\n localStorage.removeItem(STORAGE_PREFIX + name);\n return;\n }\n if (state.op === \"outer\") {\n el.outerHTML = state.content;\n } else {\n el.innerHTML = state.content;\n }\n });\n}\n\n// Apply content to an element using the specified operation (inner, text, append, outer).\nfunction apply(el, op, content) {\n if (!accepts(el, op)) {\n console.error(receiverName(el) + \" does not accept \" + op);\n return;\n }\n switch (op) {\n case \"inner\": el.innerHTML = content; break;\n case \"text\": el.textContent = content; break;\n case \"append\": el.insertAdjacentHTML(\"beforeend\", content); break;\n case \"outer\": el.outerHTML = content; break;\n }\n persist(el, op);\n return content;\n}\n\nlet csrfMeta = null;\n\nfunction csrfToken() {\n if (!csrfMeta || !csrfMeta.isConnected) {\n csrfMeta = document.querySelector('meta[name=\"csrf-token\"]');\n }\n return csrfMeta ? csrfMeta.getAttribute(\"content\") : \"\";\n}\n\n// Perform a fetch with talkDOM headers. Returns a promise resolving to response text.\n// Fires server-triggered messages from X-TalkDOM-Trigger header if present.\nfunction request(method, url, receiver, body) {\n const headers = {\n \"X-TalkDOM-Request\": \"true\",\n \"X-TalkDOM-Current-URL\": location.href,\n };\n if (receiver) {\n headers[\"X-TalkDOM-Receiver\"] = receiver;\n }\n if (method !== \"GET\") {\n const token = csrfToken();\n if (token) headers[\"X-CSRF-Token\"] = token;\n else console.warn(\"talkDOM: no CSRF token found for \" + method + \" \" + url);\n }\n return fetch(url, { method, headers, body }).then((r) => {\n if (!r.ok) {\n console.error(\"talkDOM: \" + method + \" \" + url + \" \" + r.status);\n return Promise.reject(r.status);\n }\n const trigger = r.headers.get(\"X-TalkDOM-Trigger\");\n return r.text().then((text) => {\n if (trigger) dispatchRaw(trigger);\n return text;\n });\n });\n}\n\nfunction serializeForm(form) {\n return new URLSearchParams(new FormData(form)).toString();\n}\n\nfunction recName(el) {\n return el.hasAttribute(\"receiver\") ? receiverName(el) : \"\";\n}\n\n// Built-in method table. Each method receives (el, ...args) from the parsed message.\n// Extensible via talkDOM.methods at runtime.\nconst methods = {\n \"get:\": function (el, url) { return request(\"GET\", url, recName(el)); },\n \"post:\": function (el, url) { return request(\"POST\", url, recName(el)); },\n \"put:\": function (el, url) { return request(\"PUT\", url, recName(el)); },\n \"delete:\": function (el, url) { return request(\"DELETE\", url, recName(el)); },\n \"confirm:\": function (el, message) { if (!confirm(message)) return Promise.reject(\"cancelled\"); },\n \"apply:\": function (el, content, op) { return apply(el, op, content); },\n \"get:apply:\": function (el, url, op) { return request(\"GET\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"post:apply:\": function (el, url, op) { return request(\"POST\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"put:apply:\": function (el, url, op) { return request(\"PUT\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"delete:apply:\": function (el, url, op) { return request(\"DELETE\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"post-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"post-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"POST\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"put-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"put-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"PUT\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"delete-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"delete-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"DELETE\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"post-json:apply:json:\": function (el, url, op, jsonStr) {\n let data;\n try { data = JSON.parse(jsonStr); } catch { data = {}; }\n return request(\"POST\", url, recName(el), JSON.stringify(data)).then(function (t) { return apply(el, op, t); });\n },\n \"put-json:apply:json:\": function (el, url, op, jsonStr) {\n let data;\n try { data = JSON.parse(jsonStr); } catch { data = {}; }\n return request(\"PUT\", url, recName(el), JSON.stringify(data)).then(function (t) { return apply(el, op, t); });\n },\n};\n\nlet pushing = false;\n\n// Push URL to browser history. Uses push-url attr value, or falls back to first message arg.\nfunction pushUrl(senderEl, raw) {\n if (!senderEl.hasAttribute(\"push-url\")) return;\n let url = senderEl.getAttribute(\"push-url\");\n if (!url) {\n const msg = parseMessage(raw.split(\";\")[0].split(\"|\")[0].trim());\n if (msg.args.length > 0) {\n url = msg.args[0].split(/\\s/)[0] || \"\";\n }\n }\n if (url && (location.pathname + location.search) !== url) {\n history.pushState({ sender: raw }, \"\", url);\n }\n}\n\n// Re-dispatch a sender message from history state (back/forward navigation).\nfunction replayState(state) {\n if (!state || !state.sender) return;\n pushing = true;\n dispatchRaw(state.sender);\n pushing = false;\n}\n\nwindow.addEventListener(\"popstate\", function (e) {\n replayState(e.state);\n});\n\n// After an outer swap `el` is gone. Walk from the snapshotted sibling or\n// parent to find the element that took its place; fall back to a fresh\n// receiver query if the DOM was restructured.\nfunction resolveTarget(el, next, parent, name) {\n if (el.isConnected) return el;\n const candidate = next && next.isConnected ? next.previousElementSibling\n : parent && parent.isConnected ? parent.lastElementChild : null;\n return candidate || findReceivers(name)[0];\n}\n\n// Deliver a parsed message to all matching receivers. Fires talkdom:done or talkdom:error\n// lifecycle events on the receiver element (or its replacement if outer-swapped).\nfunction send(msg, piped) {\n const els = findReceivers(msg.receiver);\n if (els.length === 0) {\n console.error(msg.receiver + \" not found\");\n return;\n }\n let loadingClass = null;\n let keywords = msg.keywords;\n let args = msg.args;\n const loadingIdx = keywords.indexOf(\"loading:\");\n if (loadingIdx !== -1) {\n loadingClass = args[loadingIdx];\n keywords = keywords.filter(function (_, i) { return i !== loadingIdx; });\n args = args.filter(function (_, i) { return i !== loadingIdx; });\n }\n const selector = keywords.join(\"\");\n const method = methods[selector];\n if (!method) {\n console.error(msg.receiver + \" does not understand \" + selector);\n return;\n }\n const finalArgs = piped !== undefined ? [piped].concat(args) : args;\n let result;\n els.forEach(function (el) {\n const detail = { receiver: msg.receiver, selector: selector, args: msg.args };\n const parent = el.parentNode;\n const next = el.nextElementSibling;\n if (loadingClass) el.classList.add(loadingClass);\n result = method(el, ...finalArgs);\n if (result && typeof result.then === \"function\") {\n result.then(function () {\n if (loadingClass) el.classList.remove(loadingClass);\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:done\", { bubbles: true, detail }));\n }, function (err) {\n if (loadingClass) el.classList.remove(loadingClass);\n detail.error = err;\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:error\", { bubbles: true, detail }));\n });\n } else {\n if (loadingClass) el.classList.remove(loadingClass);\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:done\", { bubbles: true, detail }));\n }\n });\n return result;\n}\n\n// Programmatic API: parse and execute a raw message string (supports pipes and semicolons).\n// Returns a promise that resolves when all chains complete.\nfunction run(raw) {\n const trimmed = raw.trim();\n if (trimmed.indexOf(\";\") === -1 && trimmed.indexOf(\"|\") === -1) {\n return Promise.resolve(send(parseMessage(trimmed))).then(function (r) { return [r]; });\n }\n const chains = trimmed.split(\";\").map(function (chain) {\n const step = chain.trim();\n if (!step) return Promise.resolve();\n const steps = step.split(\"|\").map(function (s) { return s.trim(); }).filter(Boolean);\n if (steps.length === 1) {\n return Promise.resolve(send(parseMessage(steps[0])));\n }\n return steps.reduce(function (prev, step) {\n const msg = parseMessage(step);\n return Promise.resolve(prev).then(function (piped) {\n return send(msg, piped);\n });\n }, undefined);\n });\n return Promise.all(chains);\n}\n\n// Fire-and-forget dispatch used by declarative senders and server triggers.\nfunction dispatchRaw(raw) {\n run(raw).catch(function (err) { console.warn(\"talkDOM:\", err); });\n}\n\n// Entry point for a sender click: dispatch its message and optionally push URL.\nfunction dispatch(senderEl) {\n const raw = senderEl.getAttribute(\"sender\");\n dispatchRaw(raw);\n if (!pushing) pushUrl(senderEl, raw);\n}\n\nfunction parseInterval(str) {\n const match = str.match(/^(\\d+)(s|ms)$/);\n if (!match) return null;\n const n = parseInt(match[1], 10);\n return match[2] === \"s\" ? n * 1000 : n;\n}\n\n// Set up a repeating interval for receivers with a poll: keyword.\nlet activePollers = 0;\nlet maxPollers = 64;\n\nfunction startPolling(el) {\n const attr = el.getAttribute(\"receiver\");\n const msg = parseMessage(attr);\n if (msg.keywords[msg.keywords.length - 1] !== \"poll:\") return;\n if (activePollers >= maxPollers) {\n console.warn(\"talkDOM: max pollers (\" + maxPollers + \") reached, ignoring \" + msg.receiver);\n return;\n }\n const interval = parseInterval(msg.args[msg.args.length - 1]);\n if (!interval) {\n console.error(\"poll: invalid interval for \" + msg.receiver);\n return;\n }\n const selector = msg.keywords.slice(0, -1).join(\"\");\n const args = msg.args.slice(0, -1);\n const name = msg.receiver;\n let cachedTargets = findReceivers(name);\n let method = methods[selector];\n activePollers++;\n const id = setInterval(function () {\n if (!el.isConnected) { clearInterval(id); activePollers--; return; }\n if (cachedTargets.length === 0 || !cachedTargets[0].isConnected) {\n cachedTargets = findReceivers(name);\n }\n if (cachedTargets.length === 0) return;\n if (!method) method = methods[selector];\n if (!method) {\n console.error(name + \" does not understand \" + selector);\n return;\n }\n cachedTargets.forEach(function (target) { method(target, ...args); });\n }, interval);\n}\n\n// Global click handler: delegate to any element with a sender attribute.\ndocument.addEventListener(\"click\", function (e) {\n const sender = e.target.closest(\"[sender]\");\n if (sender) {\n e.preventDefault();\n dispatch(sender);\n }\n});\n\nrestore();\nreplayState(history.state);\ndocument.querySelectorAll(\"[receiver]\").forEach(startPolling);\n\nnew MutationObserver(function (mutations) {\n for (let i = 0; i < mutations.length; i++) {\n const added = mutations[i].addedNodes;\n for (let j = 0; j < added.length; j++) {\n const node = added[j];\n if (node.nodeType === Node.ELEMENT_NODE) {\n if (node.hasAttribute && node.hasAttribute(\"receiver\")) {\n startPolling(node);\n }\n const children = node.querySelectorAll ? node.querySelectorAll(\"[receiver]\") : [];\n for (let k = 0; k < children.length; k++) {\n startPolling(children[k]);\n }\n }\n }\n };\n}).observe(document, { childList: true, subtree: true });\n\nconst talkDOM = {\n methods,\n send: run,\n get maxPollers() { return maxPollers; },\n set maxPollers(n) { maxPollers = n; },\n};\n\nwindow.talkDOM = talkDOM;\n\nexport { parseMessage, receiverName, findReceivers, accepts, persist, restore, apply, request, methods, run, dispatchRaw, talkDOM };\n", "import { methods, talkDOM } from \"./index.js\";\n\nconst WS = /\\s+/;\nconst BASE_DELAY = 1000;\nconst MAX_DELAY = 30000;\nconst CLEANUP_INTERVAL = 5000;\nconst MAX_CONNECTIONS = 16;\n\nconst connections = Object.create(null);\n\n// Parse receiver attribute to extract ws: URL.\nfunction parseWsUrl(attr) {\n const tokens = attr.trim().split(WS);\n for (let i = 1; i < tokens.length; i++) {\n if (tokens[i] === \"ws:\" && tokens[i + 1]) return tokens[i + 1];\n }\n return null;\n}\n\n// Remove disconnected elements from a connection's receiver set.\nfunction pruneReceivers(conn) {\n conn.receivers.forEach(function (el) {\n if (!el.isConnected) conn.receivers.delete(el);\n });\n return conn.receivers.size > 0;\n}\n\n// Fire a custom event on all connected receivers for a URL.\nfunction fireEvent(conn, name, detail) {\n conn.receivers.forEach(function (el) {\n if (el.isConnected) {\n el.dispatchEvent(new CustomEvent(name, { bubbles: true, detail }));\n }\n });\n}\n\n// Route a parsed JSON message to matching receiver elements.\nfunction routeJson(conn, msg) {\n const name = msg.receiver;\n const op = msg.op || \"inner\";\n const content = msg.content || \"\";\n const targets = name\n ? document.querySelectorAll('[receiver~=\"' + name + '\"]')\n : Array.from(conn.receivers);\n\n const detail = { receiver: name || \"\", selector: \"apply:\", args: [content, op] };\n for (let i = 0; i < targets.length; i++) {\n const el = targets[i];\n methods[\"apply:\"](el, content, op);\n el.dispatchEvent(new CustomEvent(\"talkdom:done\", { bubbles: true, detail }));\n }\n}\n\n// Handle an incoming WebSocket message.\nfunction onMessage(url, event) {\n const conn = connections[url];\n if (!conn) return;\n pruneReceivers(conn);\n const data = event.data;\n if (typeof data !== \"string\") return;\n if (data.charAt(0) === \"{\") {\n try {\n const msg = JSON.parse(data);\n routeJson(conn, msg);\n } catch (e) {\n console.error(\"talkdom-ws: invalid JSON from \" + url, e);\n }\n } else {\n talkDOM.send(data).catch(function (err) {\n console.warn(\"talkdom-ws:\", err);\n });\n }\n}\n\nfunction scheduleReconnect(url) {\n const conn = connections[url];\n if (!conn) return;\n if (!pruneReceivers(conn)) { cleanup(url); return; }\n let delay = Math.min(conn.backoff, MAX_DELAY);\n delay = delay * (0.75 + Math.random() * 0.5);\n conn.timer = setTimeout(function () {\n conn.backoff = Math.min(conn.backoff * 2, MAX_DELAY);\n connectWs(url);\n }, delay);\n}\n\nfunction cleanup(url) {\n const conn = connections[url];\n if (!conn) return;\n if (conn.timer) clearTimeout(conn.timer);\n if (conn.checkTimer) clearInterval(conn.checkTimer);\n if (conn.ws) {\n conn.ws.onclose = null;\n conn.ws.close();\n }\n delete connections[url];\n}\n\nfunction connectWs(url) {\n const conn = connections[url];\n if (!conn) return;\n if (conn.ws && (conn.ws.readyState === WebSocket.OPEN || conn.ws.readyState === WebSocket.CONNECTING)) return;\n\n const ws = new WebSocket(url);\n\n ws.onopen = function () {\n conn.backoff = BASE_DELAY;\n fireEvent(conn, \"talkdom:ws:open\", { url });\n };\n\n ws.onmessage = function (e) {\n onMessage(url, e);\n };\n\n ws.onclose = function (e) {\n fireEvent(conn, \"talkdom:ws:close\", { url, code: e.code, reason: e.reason });\n scheduleReconnect(url);\n };\n\n ws.onerror = function () {\n fireEvent(conn, \"talkdom:ws:error\", { url });\n };\n\n conn.ws = ws;\n}\n\n// Subscribe an element to a WebSocket URL.\nfunction subscribe(el, url) {\n let conn = connections[url];\n if (!conn) {\n const count = Object.keys(connections).length;\n if (count >= MAX_CONNECTIONS) {\n console.warn(\"talkdom-ws: max connections (\" + MAX_CONNECTIONS + \") reached, ignoring \" + url);\n return;\n }\n conn = { ws: null, receivers: new Set(), backoff: BASE_DELAY, timer: null, checkTimer: null };\n connections[url] = conn;\n conn.checkTimer = setInterval(function () {\n if (!pruneReceivers(conn)) cleanup(url);\n }, CLEANUP_INTERVAL);\n }\n conn.receivers.add(el);\n connectWs(url);\n}\n\n// Scan a single element for ws: keyword and subscribe.\nfunction initElement(el) {\n const attr = el.getAttribute(\"receiver\");\n if (!attr) return;\n const url = parseWsUrl(attr);\n if (!url) return;\n subscribe(el, url);\n}\n\n// Scan all existing receiver elements.\nfunction initWsReceivers() {\n document.querySelectorAll(\"[receiver]\").forEach(initElement);\n}\n\n// Watch for dynamically added ws: receivers.\nnew MutationObserver(function (mutations) {\n for (let i = 0; i < mutations.length; i++) {\n const added = mutations[i].addedNodes;\n for (let j = 0; j < added.length; j++) {\n const node = added[j];\n if (node.nodeType !== 1) continue;\n if (node.hasAttribute && node.hasAttribute(\"receiver\")) initElement(node);\n if (node.querySelectorAll) {\n node.querySelectorAll(\"[receiver]\").forEach(initElement);\n }\n }\n }\n}).observe(document, { childList: true, subtree: true });\n\n// ws:send: method\nmethods[\"ws:send:\"] = function (el, url) {\n const conn = connections[url];\n if (!conn || !conn.ws || conn.ws.readyState !== WebSocket.OPEN) {\n console.error(\"talkdom-ws: no open connection to \" + url);\n return Promise.reject(\"not connected\");\n }\n const payload = (\"value\" in el) ? el.value : el.textContent;\n conn.ws.send(payload);\n};\n\ninitWsReceivers();\n\nconst ws = {\n connect: function (url) {\n if (!connections[url]) {\n const count = Object.keys(connections).length;\n if (count >= MAX_CONNECTIONS) {\n console.warn(\"talkdom-ws: max connections (\" + MAX_CONNECTIONS + \") reached\");\n return;\n }\n connections[url] = { ws: null, receivers: new Set(), backoff: BASE_DELAY, timer: null, checkTimer: null };\n connections[url].checkTimer = setInterval(function () {\n if (!pruneReceivers(connections[url])) cleanup(url);\n }, CLEANUP_INTERVAL);\n }\n connectWs(url);\n },\n disconnect: function (url) { cleanup(url); },\n send: function (url, data) {\n const conn = connections[url];\n if (!conn || !conn.ws || conn.ws.readyState !== WebSocket.OPEN) return false;\n conn.ws.send(typeof data === \"string\" ? data : JSON.stringify(data));\n return true;\n },\n get connections() {\n const out = Object.create(null);\n for (const url in connections) {\n out[url] = {\n state: connections[url].ws ? connections[url].ws.readyState : -1,\n receivers: connections[url].receivers.size,\n };\n }\n return out;\n },\n get maxConnections() { return MAX_CONNECTIONS; },\n};\n\nexport { ws };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["WS", "STORAGE_PREFIX", "parseMessage", "str", "trimmed", "tokens", "receiver", "body", "rest", "keywords", "args", "currentArg", "i", "token", "receiverName", "el", "attr", "sp", "receiverCache", "cacheValid", "findReceivers", "name", "key", "result", "accepts", "op", "persist", "content", "restore", "raw", "state", "apply", "csrfMeta", "csrfToken", "request", "method", "url", "headers", "r", "trigger", "text", "dispatchRaw", "serializeForm", "form", "recName", "methods", "message", "t", "formSelector", "jsonStr", "data", "pushing", "pushUrl", "senderEl", "msg", "replayState", "resolveTarget", "next", "parent", "send", "piped", "els", "loadingClass", "loadingIdx", "_", "selector", "finalArgs", "detail", "target", "err", "run", "chains", "chain", "step", "steps", "prev", "dispatch", "parseInterval", "match", "activePollers", "maxPollers", "startPolling", "interval", "cachedTargets", "id", "sender", "mutations", "added", "j", "node", "children", "k", "talkDOM", "n", "WS", "BASE_DELAY", "MAX_DELAY", "CLEANUP_INTERVAL", "MAX_CONNECTIONS", "connections", "parseWsUrl", "attr", "tokens", "i", "pruneReceivers", "conn", "el", "fireEvent", "name", "detail", "routeJson", "msg", "op", "content", "targets", "methods", "onMessage", "url", "event", "data", "e", "talkDOM", "err", "scheduleReconnect", "cleanup", "delay", "connectWs", "ws", "subscribe", "initElement", "initWsReceivers", "mutations", "added", "j", "node", "payload", "out"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var H=/\s+/,D="talkDOM:";function y(e){let t=e.trim(),n=t.split(H),r=n[0],o=t.substring(r.length).trim(),s=n.slice(1),i=[],c=[],u=[];for(let p=0;p<s.length;p++){let d=s[p];d.endsWith(":")?(i.length>0&&u.length>0?(c.push(u.join(" ")),u=[]):i.length>0&&c.push(""),i.push(d)):u.push(d)}return i.length>0&&c.push(u.join(" ")),{receiver:r,selector:i.join(""),keywords:i,args:c,body:o}}function O(e){let t=e.getAttribute("receiver").trim(),n=t.indexOf(" ");return n===-1?t:t.substring(0,n)}var v=Object.create(null),C=!1;new MutationObserver(()=>{C=!1}).observe(document,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["receiver"]});function k(e){if(C||(Object.keys(v).forEach(n=>delete v[n]),C=!0),v[e])return v[e];let t=document.querySelectorAll('[receiver~="'+e+'"]');return v[e]=t,t}function U(e,t){let n=e.getAttribute("accepts");return n?(" "+n+" ").includes(" "+t+" "):!0}function F(e,t){if(!e.hasAttribute("receiver")||!e.hasAttribute("persist"))return;let n=O(e),r=D+n,o=t==="outer"?e.outerHTML:e.innerHTML;localStorage.setItem(r,JSON.stringify({op:t,content:o}))}function J(){document.querySelectorAll("[persist]").forEach(e=>{if(!e.hasAttribute("receiver"))return;let t=O(e),n=localStorage.getItem(D+t);if(!n)return;let r;try{r=JSON.parse(n)}catch{localStorage.removeItem(D+t);return}r.op==="outer"?e.outerHTML=r.content:e.innerHTML=r.content})}function h(e,t,n){if(!U(e,t)){console.error(O(e)+" does not accept "+t);return}switch(t){case"inner":e.innerHTML=n;break;case"text":e.textContent=n;break;case"append":e.insertAdjacentHTML("beforeend",n);break;case"outer":e.outerHTML=n;break}return F(e,t),n}var b=null;function X(){return(!b||!b.isConnected)&&(b=document.querySelector('meta[name="csrf-token"]')),b?b.getAttribute("content"):""}function a(e,t,n,r){let o={"X-TalkDOM-Request":"true","X-TalkDOM-Current-URL":location.href};if(n&&(o["X-TalkDOM-Receiver"]=n),e!=="GET"){let s=X();s?o["X-CSRF-Token"]=s:console.warn("talkDOM: no CSRF token found for "+e+" "+t)}return fetch(t,{method:e,headers:o,body:r}).then(s=>{if(!s.ok)return console.error("talkDOM: "+e+" "+t+" "+s.status),Promise.reject(s.status);let i=s.headers.get("X-TalkDOM-Trigger");return s.text().then(c=>(i&&N(i),c))})}function M(e){return new URLSearchParams(new FormData(e)).toString()}function f(e){return e.hasAttribute("receiver")?O(e):""}var T={"get:":function(e,t){return a("GET",t,f(e))},"post:":function(e,t){return a("POST",t,f(e))},"put:":function(e,t){return a("PUT",t,f(e))},"delete:":function(e,t){return a("DELETE",t,f(e))},"confirm:":function(e,t){if(!confirm(t))return Promise.reject("cancelled")},"apply:":function(e,t,n){return h(e,n,t)},"get:apply:":function(e,t,n){return a("GET",t,f(e)).then(function(r){return h(e,n,r)})},"post:apply:":function(e,t,n){return a("POST",t,f(e)).then(function(r){return h(e,n,r)})},"put:apply:":function(e,t,n){return a("PUT",t,f(e)).then(function(r){return h(e,n,r)})},"delete:apply:":function(e,t,n){return a("DELETE",t,f(e)).then(function(r){return h(e,n,r)})},"post-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("post-form: form not found: "+r);return}let s=M(o);return a("POST",t,f(e),s).then(function(i){return h(e,n,i)})},"put-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("put-form: form not found: "+r);return}let s=M(o);return a("PUT",t,f(e),s).then(function(i){return h(e,n,i)})},"delete-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("delete-form: form not found: "+r);return}let s=M(o);return a("DELETE",t,f(e),s).then(function(i){return h(e,n,i)})},"post-json:apply:json:":function(e,t,n,r){let o;try{o=JSON.parse(r)}catch{o={}}return a("POST",t,f(e),JSON.stringify(o)).then(function(s){return h(e,n,s)})},"put-json:apply:json:":function(e,t,n,r){let o;try{o=JSON.parse(r)}catch{o={}}return a("PUT",t,f(e),JSON.stringify(o)).then(function(s){return h(e,n,s)})}},j=!1;function G(e,t){if(!e.hasAttribute("push-url"))return;let n=e.getAttribute("push-url");if(!n){let r=y(t.split(";")[0].split("|")[0].trim());r.args.length>0&&(n=r.args[0].split(/\s/)[0]||"")}n&&location.pathname+location.search!==n&&history.pushState({sender:t},"",n)}function R(e){!e||!e.sender||(j=!0,N(e.sender),j=!1)}window.addEventListener("popstate",function(e){R(e.state)});function A(e,t,n,r){return e.isConnected?e:(t&&t.isConnected?t.previousElementSibling:n&&n.isConnected?n.lastElementChild:null)||k(r)[0]}function P(e,t){let n=k(e.receiver);if(n.length===0){console.error(e.receiver+" not found");return}let r=null,o=e.keywords,s=e.args,i=o.indexOf("loading:");i!==-1&&(r=s[i],o=o.filter(function(l,m){return m!==i}),s=s.filter(function(l,m){return m!==i}));let c=o.join(""),u=T[c];if(!u){console.error(e.receiver+" does not understand "+c);return}let p=t!==void 0?[t].concat(s):s,d;return n.forEach(function(l){let m={receiver:e.receiver,selector:c,args:e.args},S=l.parentNode,w=l.nextElementSibling;if(r&&l.classList.add(r),d=u(l,...p),d&&typeof d.then=="function")d.then(function(){r&&l.classList.remove(r);let g=A(l,w,S,e.receiver);g&&g.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:m}))},function(g){r&&l.classList.remove(r),m.error=g;let q=A(l,w,S,e.receiver);q&&q.dispatchEvent(new CustomEvent("talkdom:error",{bubbles:!0,detail:m}))});else{r&&l.classList.remove(r);let g=A(l,w,S,e.receiver);g&&g.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:m}))}}),d}function I(e){let t=e.trim();if(t.indexOf(";")===-1&&t.indexOf("|")===-1)return Promise.resolve(P(y(t))).then(function(r){return[r]});let n=t.split(";").map(function(r){let o=r.trim();if(!o)return Promise.resolve();let s=o.split("|").map(function(i){return i.trim()}).filter(Boolean);return s.length===1?Promise.resolve(P(y(s[0]))):s.reduce(function(i,c){let u=y(c);return Promise.resolve(i).then(function(p){return P(u,p)})},void 0)});return Promise.all(n)}function N(e){I(e).catch(function(t){console.warn("talkDOM:",t)})}function _(e){let t=e.getAttribute("sender");N(t),j||G(e,t)}function W(e){let t=e.match(/^(\d+)(s|ms)$/);if(!t)return null;let n=parseInt(t[1],10);return t[2]==="s"?n*1e3:n}var L=0,E=64;function x(e){let t=e.getAttribute("receiver"),n=y(t);if(n.keywords[n.keywords.length-1]!=="poll:")return;if(L>=E){console.warn("talkDOM: max pollers ("+E+") reached, ignoring "+n.receiver);return}let r=W(n.args[n.args.length-1]);if(!r){console.error("poll: invalid interval for "+n.receiver);return}let o=n.keywords.slice(0,-1).join(""),s=n.args.slice(0,-1),i=n.receiver,c=k(i),u=T[o];L++;let p=setInterval(function(){if(!e.isConnected){clearInterval(p),L--;return}if((c.length===0||!c[0].isConnected)&&(c=k(i)),c.length!==0){if(u||(u=T[o]),!u){console.error(i+" does not understand "+o);return}c.forEach(function(d){u(d,...s)})}},r)}document.addEventListener("click",function(e){let t=e.target.closest("[sender]");t&&(e.preventDefault(),_(t))});J();R(history.state);document.querySelectorAll("[receiver]").forEach(x);new MutationObserver(function(e){for(let t=0;t<e.length;t++){let n=e[t].addedNodes;for(let r=0;r<n.length;r++){let o=n[r];if(o.nodeType===Node.ELEMENT_NODE){o.hasAttribute&&o.hasAttribute("receiver")&&x(o);let s=o.querySelectorAll?o.querySelectorAll("[receiver]"):[];for(let i=0;i<s.length;i++)x(s[i])}}}}).observe(document,{childList:!0,subtree:!0});var z={methods:T,send:I,get maxPollers(){return E},set maxPollers(e){E=e}};window.talkDOM=z;export{U as accepts,h as apply,N as dispatchRaw,k as findReceivers,T as methods,y as parseMessage,F as persist,O as receiverName,a as request,J as restore,I as run,z as talkDOM};
|
|
2
|
+
//# sourceMappingURL=talkdom.esm.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.js"],
|
|
4
|
+
"sourcesContent": ["const WS = /\\s+/;\nconst STORAGE_PREFIX = \"talkDOM:\";\n\n// Parse \"receiver keyword: arg keyword: arg\" into structured message object.\n// Tokens ending with \":\" are keywords, everything else fills args.\nfunction parseMessage(str) {\n const trimmed = str.trim();\n const tokens = trimmed.split(WS);\n const receiver = tokens[0];\n const body = trimmed.substring(receiver.length).trim();\n const rest = tokens.slice(1);\n const keywords = [];\n const args = [];\n let currentArg = [];\n\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i];\n if (token.endsWith(\":\")) {\n if (keywords.length > 0 && currentArg.length > 0) {\n args.push(currentArg.join(\" \"));\n currentArg = [];\n } else if (keywords.length > 0) {\n args.push(\"\");\n }\n keywords.push(token);\n } else {\n currentArg.push(token);\n }\n }\n if (keywords.length > 0) {\n args.push(currentArg.join(\" \"));\n }\n\n return { receiver, selector: keywords.join(\"\"), keywords, args, body };\n}\n\n// Extract the first word from the receiver attribute (the name).\nfunction receiverName(el) {\n const attr = el.getAttribute(\"receiver\").trim();\n const sp = attr.indexOf(\" \");\n return sp === -1 ? attr : attr.substring(0, sp);\n}\n\n// Receiver cache: maps name -> NodeList, invalidated by DOM mutations.\nconst receiverCache = Object.create(null);\nlet cacheValid = false;\n\nnew MutationObserver(() => { cacheValid = false; })\n .observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: [\"receiver\"] });\n\n// Find all elements whose receiver attribute contains the given name.\nfunction findReceivers(name) {\n if (!cacheValid) {\n Object.keys(receiverCache).forEach(key => delete receiverCache[key]);\n cacheValid = true;\n }\n if (receiverCache[name]) return receiverCache[name];\n const result = document.querySelectorAll('[receiver~=\"' + name + '\"]');\n receiverCache[name] = result;\n return result;\n}\n\n// Check if a receiver allows a given apply operation (inner, text, append, outer).\n// No \"accepts\" attribute means everything is allowed.\nfunction accepts(el, op) {\n const attr = el.getAttribute(\"accepts\");\n if (!attr) return true;\n return (\" \" + attr + \" \").includes(\" \" + op + \" \");\n}\n\n// Save receiver content to localStorage after apply, keyed by receiver name.\nfunction persist(el, op) {\n if (!el.hasAttribute(\"receiver\") || !el.hasAttribute(\"persist\")) return;\n const name = receiverName(el);\n const key = STORAGE_PREFIX + name;\n const content = op === \"outer\" ? el.outerHTML : el.innerHTML;\n localStorage.setItem(key, JSON.stringify({ op, content }));\n}\n\n// On page load, restore persisted receiver content from localStorage.\nfunction restore() {\n document.querySelectorAll(\"[persist]\").forEach((el) => {\n if (!el.hasAttribute(\"receiver\")) return;\n const name = receiverName(el);\n const raw = localStorage.getItem(STORAGE_PREFIX + name);\n if (!raw) return;\n let state;\n try { state = JSON.parse(raw); } catch {\n localStorage.removeItem(STORAGE_PREFIX + name);\n return;\n }\n if (state.op === \"outer\") {\n el.outerHTML = state.content;\n } else {\n el.innerHTML = state.content;\n }\n });\n}\n\n// Apply content to an element using the specified operation (inner, text, append, outer).\nfunction apply(el, op, content) {\n if (!accepts(el, op)) {\n console.error(receiverName(el) + \" does not accept \" + op);\n return;\n }\n switch (op) {\n case \"inner\": el.innerHTML = content; break;\n case \"text\": el.textContent = content; break;\n case \"append\": el.insertAdjacentHTML(\"beforeend\", content); break;\n case \"outer\": el.outerHTML = content; break;\n }\n persist(el, op);\n return content;\n}\n\nlet csrfMeta = null;\n\nfunction csrfToken() {\n if (!csrfMeta || !csrfMeta.isConnected) {\n csrfMeta = document.querySelector('meta[name=\"csrf-token\"]');\n }\n return csrfMeta ? csrfMeta.getAttribute(\"content\") : \"\";\n}\n\n// Perform a fetch with talkDOM headers. Returns a promise resolving to response text.\n// Fires server-triggered messages from X-TalkDOM-Trigger header if present.\nfunction request(method, url, receiver, body) {\n const headers = {\n \"X-TalkDOM-Request\": \"true\",\n \"X-TalkDOM-Current-URL\": location.href,\n };\n if (receiver) {\n headers[\"X-TalkDOM-Receiver\"] = receiver;\n }\n if (method !== \"GET\") {\n const token = csrfToken();\n if (token) headers[\"X-CSRF-Token\"] = token;\n else console.warn(\"talkDOM: no CSRF token found for \" + method + \" \" + url);\n }\n return fetch(url, { method, headers, body }).then((r) => {\n if (!r.ok) {\n console.error(\"talkDOM: \" + method + \" \" + url + \" \" + r.status);\n return Promise.reject(r.status);\n }\n const trigger = r.headers.get(\"X-TalkDOM-Trigger\");\n return r.text().then((text) => {\n if (trigger) dispatchRaw(trigger);\n return text;\n });\n });\n}\n\nfunction serializeForm(form) {\n return new URLSearchParams(new FormData(form)).toString();\n}\n\nfunction recName(el) {\n return el.hasAttribute(\"receiver\") ? receiverName(el) : \"\";\n}\n\n// Built-in method table. Each method receives (el, ...args) from the parsed message.\n// Extensible via talkDOM.methods at runtime.\nconst methods = {\n \"get:\": function (el, url) { return request(\"GET\", url, recName(el)); },\n \"post:\": function (el, url) { return request(\"POST\", url, recName(el)); },\n \"put:\": function (el, url) { return request(\"PUT\", url, recName(el)); },\n \"delete:\": function (el, url) { return request(\"DELETE\", url, recName(el)); },\n \"confirm:\": function (el, message) { if (!confirm(message)) return Promise.reject(\"cancelled\"); },\n \"apply:\": function (el, content, op) { return apply(el, op, content); },\n \"get:apply:\": function (el, url, op) { return request(\"GET\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"post:apply:\": function (el, url, op) { return request(\"POST\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"put:apply:\": function (el, url, op) { return request(\"PUT\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"delete:apply:\": function (el, url, op) { return request(\"DELETE\", url, recName(el)).then(function (t) { return apply(el, op, t); }); },\n \"post-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"post-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"POST\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"put-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"put-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"PUT\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"delete-form:apply:form:\": function (el, url, op, formSelector) {\n const form = document.querySelector(formSelector);\n if (!form) { console.error(\"delete-form: form not found: \" + formSelector); return; }\n const body = serializeForm(form);\n return request(\"DELETE\", url, recName(el), body).then(function (t) { return apply(el, op, t); });\n },\n \"post-json:apply:json:\": function (el, url, op, jsonStr) {\n let data;\n try { data = JSON.parse(jsonStr); } catch { data = {}; }\n return request(\"POST\", url, recName(el), JSON.stringify(data)).then(function (t) { return apply(el, op, t); });\n },\n \"put-json:apply:json:\": function (el, url, op, jsonStr) {\n let data;\n try { data = JSON.parse(jsonStr); } catch { data = {}; }\n return request(\"PUT\", url, recName(el), JSON.stringify(data)).then(function (t) { return apply(el, op, t); });\n },\n};\n\nlet pushing = false;\n\n// Push URL to browser history. Uses push-url attr value, or falls back to first message arg.\nfunction pushUrl(senderEl, raw) {\n if (!senderEl.hasAttribute(\"push-url\")) return;\n let url = senderEl.getAttribute(\"push-url\");\n if (!url) {\n const msg = parseMessage(raw.split(\";\")[0].split(\"|\")[0].trim());\n if (msg.args.length > 0) {\n url = msg.args[0].split(/\\s/)[0] || \"\";\n }\n }\n if (url && (location.pathname + location.search) !== url) {\n history.pushState({ sender: raw }, \"\", url);\n }\n}\n\n// Re-dispatch a sender message from history state (back/forward navigation).\nfunction replayState(state) {\n if (!state || !state.sender) return;\n pushing = true;\n dispatchRaw(state.sender);\n pushing = false;\n}\n\nwindow.addEventListener(\"popstate\", function (e) {\n replayState(e.state);\n});\n\n// After an outer swap `el` is gone. Walk from the snapshotted sibling or\n// parent to find the element that took its place; fall back to a fresh\n// receiver query if the DOM was restructured.\nfunction resolveTarget(el, next, parent, name) {\n if (el.isConnected) return el;\n const candidate = next && next.isConnected ? next.previousElementSibling\n : parent && parent.isConnected ? parent.lastElementChild : null;\n return candidate || findReceivers(name)[0];\n}\n\n// Deliver a parsed message to all matching receivers. Fires talkdom:done or talkdom:error\n// lifecycle events on the receiver element (or its replacement if outer-swapped).\nfunction send(msg, piped) {\n const els = findReceivers(msg.receiver);\n if (els.length === 0) {\n console.error(msg.receiver + \" not found\");\n return;\n }\n let loadingClass = null;\n let keywords = msg.keywords;\n let args = msg.args;\n const loadingIdx = keywords.indexOf(\"loading:\");\n if (loadingIdx !== -1) {\n loadingClass = args[loadingIdx];\n keywords = keywords.filter(function (_, i) { return i !== loadingIdx; });\n args = args.filter(function (_, i) { return i !== loadingIdx; });\n }\n const selector = keywords.join(\"\");\n const method = methods[selector];\n if (!method) {\n console.error(msg.receiver + \" does not understand \" + selector);\n return;\n }\n const finalArgs = piped !== undefined ? [piped].concat(args) : args;\n let result;\n els.forEach(function (el) {\n const detail = { receiver: msg.receiver, selector: selector, args: msg.args };\n const parent = el.parentNode;\n const next = el.nextElementSibling;\n if (loadingClass) el.classList.add(loadingClass);\n result = method(el, ...finalArgs);\n if (result && typeof result.then === \"function\") {\n result.then(function () {\n if (loadingClass) el.classList.remove(loadingClass);\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:done\", { bubbles: true, detail }));\n }, function (err) {\n if (loadingClass) el.classList.remove(loadingClass);\n detail.error = err;\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:error\", { bubbles: true, detail }));\n });\n } else {\n if (loadingClass) el.classList.remove(loadingClass);\n const target = resolveTarget(el, next, parent, msg.receiver);\n if (target) target.dispatchEvent(new CustomEvent(\"talkdom:done\", { bubbles: true, detail }));\n }\n });\n return result;\n}\n\n// Programmatic API: parse and execute a raw message string (supports pipes and semicolons).\n// Returns a promise that resolves when all chains complete.\nfunction run(raw) {\n const trimmed = raw.trim();\n if (trimmed.indexOf(\";\") === -1 && trimmed.indexOf(\"|\") === -1) {\n return Promise.resolve(send(parseMessage(trimmed))).then(function (r) { return [r]; });\n }\n const chains = trimmed.split(\";\").map(function (chain) {\n const step = chain.trim();\n if (!step) return Promise.resolve();\n const steps = step.split(\"|\").map(function (s) { return s.trim(); }).filter(Boolean);\n if (steps.length === 1) {\n return Promise.resolve(send(parseMessage(steps[0])));\n }\n return steps.reduce(function (prev, step) {\n const msg = parseMessage(step);\n return Promise.resolve(prev).then(function (piped) {\n return send(msg, piped);\n });\n }, undefined);\n });\n return Promise.all(chains);\n}\n\n// Fire-and-forget dispatch used by declarative senders and server triggers.\nfunction dispatchRaw(raw) {\n run(raw).catch(function (err) { console.warn(\"talkDOM:\", err); });\n}\n\n// Entry point for a sender click: dispatch its message and optionally push URL.\nfunction dispatch(senderEl) {\n const raw = senderEl.getAttribute(\"sender\");\n dispatchRaw(raw);\n if (!pushing) pushUrl(senderEl, raw);\n}\n\nfunction parseInterval(str) {\n const match = str.match(/^(\\d+)(s|ms)$/);\n if (!match) return null;\n const n = parseInt(match[1], 10);\n return match[2] === \"s\" ? n * 1000 : n;\n}\n\n// Set up a repeating interval for receivers with a poll: keyword.\nlet activePollers = 0;\nlet maxPollers = 64;\n\nfunction startPolling(el) {\n const attr = el.getAttribute(\"receiver\");\n const msg = parseMessage(attr);\n if (msg.keywords[msg.keywords.length - 1] !== \"poll:\") return;\n if (activePollers >= maxPollers) {\n console.warn(\"talkDOM: max pollers (\" + maxPollers + \") reached, ignoring \" + msg.receiver);\n return;\n }\n const interval = parseInterval(msg.args[msg.args.length - 1]);\n if (!interval) {\n console.error(\"poll: invalid interval for \" + msg.receiver);\n return;\n }\n const selector = msg.keywords.slice(0, -1).join(\"\");\n const args = msg.args.slice(0, -1);\n const name = msg.receiver;\n let cachedTargets = findReceivers(name);\n let method = methods[selector];\n activePollers++;\n const id = setInterval(function () {\n if (!el.isConnected) { clearInterval(id); activePollers--; return; }\n if (cachedTargets.length === 0 || !cachedTargets[0].isConnected) {\n cachedTargets = findReceivers(name);\n }\n if (cachedTargets.length === 0) return;\n if (!method) method = methods[selector];\n if (!method) {\n console.error(name + \" does not understand \" + selector);\n return;\n }\n cachedTargets.forEach(function (target) { method(target, ...args); });\n }, interval);\n}\n\n// Global click handler: delegate to any element with a sender attribute.\ndocument.addEventListener(\"click\", function (e) {\n const sender = e.target.closest(\"[sender]\");\n if (sender) {\n e.preventDefault();\n dispatch(sender);\n }\n});\n\nrestore();\nreplayState(history.state);\ndocument.querySelectorAll(\"[receiver]\").forEach(startPolling);\n\nnew MutationObserver(function (mutations) {\n for (let i = 0; i < mutations.length; i++) {\n const added = mutations[i].addedNodes;\n for (let j = 0; j < added.length; j++) {\n const node = added[j];\n if (node.nodeType === Node.ELEMENT_NODE) {\n if (node.hasAttribute && node.hasAttribute(\"receiver\")) {\n startPolling(node);\n }\n const children = node.querySelectorAll ? node.querySelectorAll(\"[receiver]\") : [];\n for (let k = 0; k < children.length; k++) {\n startPolling(children[k]);\n }\n }\n }\n };\n}).observe(document, { childList: true, subtree: true });\n\nconst talkDOM = {\n methods,\n send: run,\n get maxPollers() { return maxPollers; },\n set maxPollers(n) { maxPollers = n; },\n};\n\nwindow.talkDOM = talkDOM;\n\nexport { parseMessage, receiverName, findReceivers, accepts, persist, restore, apply, request, methods, run, dispatchRaw, talkDOM };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["WS", "STORAGE_PREFIX", "parseMessage", "str", "trimmed", "tokens", "receiver", "body", "rest", "keywords", "args", "currentArg", "i", "token", "receiverName", "el", "attr", "sp", "receiverCache", "cacheValid", "findReceivers", "name", "key", "result", "accepts", "op", "persist", "content", "restore", "raw", "state", "apply", "csrfMeta", "csrfToken", "request", "method", "url", "headers", "r", "trigger", "text", "dispatchRaw", "serializeForm", "form", "recName", "methods", "message", "t", "formSelector", "jsonStr", "data", "pushing", "pushUrl", "senderEl", "msg", "replayState", "resolveTarget", "next", "parent", "send", "piped", "els", "loadingClass", "loadingIdx", "_", "selector", "finalArgs", "detail", "target", "err", "run", "chains", "chain", "step", "steps", "s", "prev", "dispatch", "parseInterval", "match", "activePollers", "maxPollers", "startPolling", "interval", "cachedTargets", "id", "sender", "mutations", "added", "j", "node", "children", "k", "talkDOM", "n"]
|
|
7
|
+
}
|
package/dist/talkdom.min.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(()=>{var H=/\s+/,D="talkDOM:";function y(e){let t=e.trim(),n=t.split(H),r=n[0],o=t.substring(r.length).trim(),s=n.slice(1),i=[],c=[],u=[];for(let p=0;p<s.length;p++){let d=s[p];d.endsWith(":")?(i.length>0&&u.length>0?(c.push(u.join(" ")),u=[]):i.length>0&&c.push(""),i.push(d)):u.push(d)}return i.length>0&&c.push(u.join(" ")),{receiver:r,selector:i.join(""),keywords:i,args:c,body:o}}function O(e){let t=e.getAttribute("receiver").trim(),n=t.indexOf(" ");return n===-1?t:t.substring(0,n)}var v=Object.create(null),C=!1;new MutationObserver(()=>{C=!1}).observe(document,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["receiver"]});function k(e){if(C||(Object.keys(v).forEach(n=>delete v[n]),C=!0),v[e])return v[e];let t=document.querySelectorAll('[receiver~="'+e+'"]');return v[e]=t,t}function U(e,t){let n=e.getAttribute("accepts");return n?(" "+n+" ").includes(" "+t+" "):!0}function F(e,t){if(!e.hasAttribute("receiver")||!e.hasAttribute("persist"))return;let n=O(e),r=D+n,o=t==="outer"?e.outerHTML:e.innerHTML;localStorage.setItem(r,JSON.stringify({op:t,content:o}))}function J(){document.querySelectorAll("[persist]").forEach(e=>{if(!e.hasAttribute("receiver"))return;let t=O(e),n=localStorage.getItem(D+t);if(!n)return;let r;try{r=JSON.parse(n)}catch{localStorage.removeItem(D+t);return}r.op==="outer"?e.outerHTML=r.content:e.innerHTML=r.content})}function h(e,t,n){if(!U(e,t)){console.error(O(e)+" does not accept "+t);return}switch(t){case"inner":e.innerHTML=n;break;case"text":e.textContent=n;break;case"append":e.insertAdjacentHTML("beforeend",n);break;case"outer":e.outerHTML=n;break}return F(e,t),n}var b=null;function X(){return(!b||!b.isConnected)&&(b=document.querySelector('meta[name="csrf-token"]')),b?b.getAttribute("content"):""}function a(e,t,n,r){let o={"X-TalkDOM-Request":"true","X-TalkDOM-Current-URL":location.href};if(n&&(o["X-TalkDOM-Receiver"]=n),e!=="GET"){let s=X();s?o["X-CSRF-Token"]=s:console.warn("talkDOM: no CSRF token found for "+e+" "+t)}return fetch(t,{method:e,headers:o,body:r}).then(s=>{if(!s.ok)return console.error("talkDOM: "+e+" "+t+" "+s.status),Promise.reject(s.status);let i=s.headers.get("X-TalkDOM-Trigger");return s.text().then(c=>(i&&N(i),c))})}function M(e){return new URLSearchParams(new FormData(e)).toString()}function f(e){return e.hasAttribute("receiver")?O(e):""}var T={"get:":function(e,t){return a("GET",t,f(e))},"post:":function(e,t){return a("POST",t,f(e))},"put:":function(e,t){return a("PUT",t,f(e))},"delete:":function(e,t){return a("DELETE",t,f(e))},"confirm:":function(e,t){if(!confirm(t))return Promise.reject("cancelled")},"apply:":function(e,t,n){return h(e,n,t)},"get:apply:":function(e,t,n){return a("GET",t,f(e)).then(function(r){return h(e,n,r)})},"post:apply:":function(e,t,n){return a("POST",t,f(e)).then(function(r){return h(e,n,r)})},"put:apply:":function(e,t,n){return a("PUT",t,f(e)).then(function(r){return h(e,n,r)})},"delete:apply:":function(e,t,n){return a("DELETE",t,f(e)).then(function(r){return h(e,n,r)})},"post-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("post-form: form not found: "+r);return}let s=M(o);return a("POST",t,f(e),s).then(function(i){return h(e,n,i)})},"put-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("put-form: form not found: "+r);return}let s=M(o);return a("PUT",t,f(e),s).then(function(i){return h(e,n,i)})},"delete-form:apply:form:":function(e,t,n,r){let o=document.querySelector(r);if(!o){console.error("delete-form: form not found: "+r);return}let s=M(o);return a("DELETE",t,f(e),s).then(function(i){return h(e,n,i)})},"post-json:apply:json:":function(e,t,n,r){let o;try{o=JSON.parse(r)}catch{o={}}return a("POST",t,f(e),JSON.stringify(o)).then(function(s){return h(e,n,s)})},"put-json:apply:json:":function(e,t,n,r){let o;try{o=JSON.parse(r)}catch{o={}}return a("PUT",t,f(e),JSON.stringify(o)).then(function(s){return h(e,n,s)})}},j=!1;function G(e,t){if(!e.hasAttribute("push-url"))return;let n=e.getAttribute("push-url");if(!n){let r=y(t.split(";")[0].split("|")[0].trim());r.args.length>0&&(n=r.args[0].split(/\s/)[0]||"")}n&&location.pathname+location.search!==n&&history.pushState({sender:t},"",n)}function R(e){!e||!e.sender||(j=!0,N(e.sender),j=!1)}window.addEventListener("popstate",function(e){R(e.state)});function A(e,t,n,r){return e.isConnected?e:(t&&t.isConnected?t.previousElementSibling:n&&n.isConnected?n.lastElementChild:null)||k(r)[0]}function P(e,t){let n=k(e.receiver);if(n.length===0){console.error(e.receiver+" not found");return}let r=null,o=e.keywords,s=e.args,i=o.indexOf("loading:");i!==-1&&(r=s[i],o=o.filter(function(l,m){return m!==i}),s=s.filter(function(l,m){return m!==i}));let c=o.join(""),u=T[c];if(!u){console.error(e.receiver+" does not understand "+c);return}let p=t!==void 0?[t].concat(s):s,d;return n.forEach(function(l){let m={receiver:e.receiver,selector:c,args:e.args},S=l.parentNode,w=l.nextElementSibling;if(r&&l.classList.add(r),d=u(l,...p),d&&typeof d.then=="function")d.then(function(){r&&l.classList.remove(r);let g=A(l,w,S,e.receiver);g&&g.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:m}))},function(g){r&&l.classList.remove(r),m.error=g;let q=A(l,w,S,e.receiver);q&&q.dispatchEvent(new CustomEvent("talkdom:error",{bubbles:!0,detail:m}))});else{r&&l.classList.remove(r);let g=A(l,w,S,e.receiver);g&&g.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:m}))}}),d}function I(e){let t=e.trim();if(t.indexOf(";")===-1&&t.indexOf("|")===-1)return Promise.resolve(P(y(t))).then(function(r){return[r]});let n=t.split(";").map(function(r){let o=r.trim();if(!o)return Promise.resolve();let s=o.split("|").map(function(i){return i.trim()}).filter(Boolean);return s.length===1?Promise.resolve(P(y(s[0]))):s.reduce(function(i,c){let u=y(c);return Promise.resolve(i).then(function(p){return P(u,p)})},void 0)});return Promise.all(n)}function N(e){I(e).catch(function(t){console.warn("talkDOM:",t)})}function _(e){let t=e.getAttribute("sender");N(t),j||G(e,t)}function W(e){let t=e.match(/^(\d+)(s|ms)$/);if(!t)return null;let n=parseInt(t[1],10);return t[2]==="s"?n*1e3:n}var L=0,E=64;function x(e){let t=e.getAttribute("receiver"),n=y(t);if(n.keywords[n.keywords.length-1]!=="poll:")return;if(L>=E){console.warn("talkDOM: max pollers ("+E+") reached, ignoring "+n.receiver);return}let r=W(n.args[n.args.length-1]);if(!r){console.error("poll: invalid interval for "+n.receiver);return}let o=n.keywords.slice(0,-1).join(""),s=n.args.slice(0,-1),i=n.receiver,c=k(i),u=T[o];L++;let p=setInterval(function(){if(!e.isConnected){clearInterval(p),L--;return}if((c.length===0||!c[0].isConnected)&&(c=k(i)),c.length!==0){if(u||(u=T[o]),!u){console.error(i+" does not understand "+o);return}c.forEach(function(d){u(d,...s)})}},r)}document.addEventListener("click",function(e){let t=e.target.closest("[sender]");t&&(e.preventDefault(),_(t))});J();R(history.state);document.querySelectorAll("[receiver]").forEach(x);new MutationObserver(function(e){for(let t=0;t<e.length;t++){let n=e[t].addedNodes;for(let r=0;r<n.length;r++){let o=n[r];if(o.nodeType===Node.ELEMENT_NODE){o.hasAttribute&&o.hasAttribute("receiver")&&x(o);let s=o.querySelectorAll?o.querySelectorAll("[receiver]"):[];for(let i=0;i<s.length;i++)x(s[i])}}}}).observe(document,{childList:!0,subtree:!0});var z={methods:T,send:I,get maxPollers(){return E},set maxPollers(e){E=e}};window.talkDOM=z;})();
|
|
2
|
+
//# sourceMappingURL=talkdom.min.js.map
|