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 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. A maximum of 64 concurrent pollers is enforced by default. Adjust via:
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: {&quot;name&quot;:&quot;test&quot;}">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
+ }
@@ -1 +1,2 @@
1
- !function(){var e=/\s+/;function t(t){for(var r=t.trim(),n=r.split(e),o=n[0],i=r.substring(o.length).trim(),c=n.slice(1),u=[],s=[],a=[],l=0;l<c.length;l++){var f=c[l];f.endsWith(":")?(u.length>0&&a.length>0?(s.push(a.join(" ")),a=[]):u.length>0&&s.push(""),u.push(f)):a.push(f)}return u.length>0&&s.push(a.join(" ")),{receiver:o,selector:u.join(""),keywords:u,args:s,body:i}}function r(e){var t=e.getAttribute("receiver").trim(),r=t.indexOf(" ");return-1===r?t:t.substring(0,r)}var n=Object.create(null),o=!1;function i(e){if(o||(n=Object.create(null),o=!0),n[e])return n[e];var t=document.querySelectorAll('[receiver~="'+e+'"]');return n[e]=t,t}function c(e,t,n){if(function(e,t){var r=e.getAttribute("accepts");return!r||-1!==(" "+r+" ").indexOf(" "+t+" ")}(e,t)){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}return function(e,t){if(e.hasAttribute("receiver")&&e.hasAttribute("persist")){var n="talkDOM:"+r(e);"outer"===t?localStorage.setItem(n,JSON.stringify({op:t,content:e.outerHTML})):localStorage.setItem(n,JSON.stringify({op:t,content:e.innerHTML}))}}(e,t),n}console.error(r(e)+" does not accept "+t)}new MutationObserver(function(){o=!1}).observe(document,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["receiver"]});var u=null;function s(e,t,r){var n={"X-TalkDOM-Request":"true","X-TalkDOM-Current-URL":location.href};if(r&&(n["X-TalkDOM-Receiver"]=r),"GET"!==e){var o=(u&&u.isConnected||(u=document.querySelector('meta[name="csrf-token"]')),u?u.getAttribute("content"):"");o?n["X-CSRF-Token"]=o:console.warn("talkDOM: no CSRF token found for "+e+" "+t)}return fetch(t,{method:e,headers:n}).then(function(r){if(!r.ok)return console.error("talkDOM: "+e+" "+t+" "+r.status),Promise.reject(r.status);var n=r.headers.get("X-TalkDOM-Trigger");return r.text().then(function(e){return n&&m(n),e})},function(r){return console.error("talkDOM: "+e+" "+t+" failed",r),Promise.reject(r)})}function a(e){return e.hasAttribute("receiver")?r(e):""}const l={"get:":function(e,t){return s("GET",t,a(e))},"post:":function(e,t){return s("POST",t,a(e))},"put:":function(e,t){return s("PUT",t,a(e))},"delete:":function(e,t){return s("DELETE",t,a(e))},"confirm:":function(e,t){if(!confirm(t))return Promise.reject("cancelled")},"apply:":function(e,t,r){return c(e,r,t)},"get:apply:":function(e,t,r){return s("GET",t,a(e)).then(function(t){return c(e,r,t)})},"post:apply:":function(e,t,r){return s("POST",t,a(e)).then(function(t){return c(e,r,t)})},"put:apply:":function(e,t,r){return s("PUT",t,a(e)).then(function(t){return c(e,r,t)})},"delete:apply:":function(e,t,r){return s("DELETE",t,a(e)).then(function(t){return c(e,r,t)})}};var f=!1;function v(e){e&&e.sender&&(f=!0,m(e.sender),f=!1)}function d(e,t,r,n){return e.isConnected?e:(t&&t.isConnected?t.previousElementSibling:r&&r.isConnected?r.lastElementChild:null)||i(n)[0]}function h(e,t){var r=i(e.receiver);if(0!==r.length){var n=l[e.selector];if(n){var o,c=void 0!==t?[t].concat(e.args):e.args;return r.forEach(function(t){var r={receiver:e.receiver,selector:e.selector,args:e.args},i=t.parentNode,u=t.nextElementSibling;if((o=n(t,...c))&&"function"==typeof o.then)o.then(function(){var n=d(t,u,i,e.receiver);n&&n.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:r}))},function(n){r.error=n;var o=d(t,u,i,e.receiver);o&&o.dispatchEvent(new CustomEvent("talkdom:error",{bubbles:!0,detail:r}))});else{var s=d(t,u,i,e.receiver);s&&s.dispatchEvent(new CustomEvent("talkdom:done",{bubbles:!0,detail:r}))}}),o}console.error(e.receiver+" does not understand "+e.selector)}else console.error(e.receiver+" not found")}function p(e){var r=e.trim();if(-1===r.indexOf(";")&&-1===r.indexOf("|"))return Promise.resolve(h(t(r))).then(function(e){return[e]});var n=r.split(";").map(function(e){var r=e.trim();if(!r)return Promise.resolve();var n=r.split("|").map(function(e){return e.trim()}).filter(Boolean);return 1===n.length?Promise.resolve(h(t(n[0]))):n.reduce(function(e,r){var n=t(r);return Promise.resolve(e).then(function(e){return h(n,e)})},void 0)});return Promise.all(n)}function m(e){p(e).catch(function(e){console.warn("talkDOM:",e)})}function g(e){var t=e.getAttribute("sender");m(t),f||function(e,t){if(e.hasAttribute("push-url")){var r=e.getAttribute("push-url");if(!r){var n=t.split(";")[0].split("|")[0].trim(),o=n.indexOf(":");-1!==o&&(r=n.substring(o+1).trim().split(/\s/)[0]||"")}r&&location.pathname+location.search!==r&&history.pushState({sender:t},"",r)}}(e,t)}window.addEventListener("popstate",function(e){v(e.state)});var b=0,k=64;document.addEventListener("click",function(e){const t=e.target.closest("[sender]");t&&(e.preventDefault(),g(t))}),document.querySelectorAll("[persist]").forEach(function(e){if(e.hasAttribute("receiver")){var t=r(e),n=localStorage.getItem("talkDOM:"+t);if(n){var o;try{o=JSON.parse(n)}catch(e){return void localStorage.removeItem("talkDOM:"+t)}"outer"===o.op?e.outerHTML=o.content:e.innerHTML=o.content}}}),v(history.state),document.querySelectorAll("[receiver]").forEach(function(e){var r=t(e.getAttribute("receiver"));if("poll:"===r.keywords[r.keywords.length-1])if(b>=k)console.warn("talkDOM: max pollers ("+k+") reached, ignoring "+r.receiver);else{var n=function(e){var t=e.match(/^(\d+)(s|ms)$/);if(!t)return null;var r=parseInt(t[1],10);return"s"===t[2]?1e3*r:r}(r.args[r.args.length-1]);if(n){var o=r.keywords.slice(0,-1).join(""),c=r.args.slice(0,-1),u=r.receiver,s=i(u),a=l[o];b++;var f=setInterval(function(){if(!e.isConnected)return clearInterval(f),void b--;0!==s.length&&s[0].isConnected||(s=i(u)),0!==s.length&&(a||(a=l[o]),a?s.forEach(function(e){a(e,...c)}):console.error(u+" does not understand "+o))},n)}else console.error("poll: invalid interval for "+r.receiver)}}),window.talkDOM={methods:l,send:p,get maxPollers(){return k},set maxPollers(e){k=e}}}();
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