talkdom 0.2.0 → 0.3.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 +5 -1
- package/dist/talkdom.min.js +1 -1
- package/dist/talkdom.min.js.map +1 -1
- package/index.js +48 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -248,7 +248,11 @@ IE is not supported.
|
|
|
248
248
|
|
|
249
249
|
Receiver lookups are cached and invalidated automatically via `MutationObserver`. Repeated dispatches to the same receiver name within a stable DOM hit the cache.
|
|
250
250
|
|
|
251
|
-
Polling is capped at 64 concurrent pollers by default (configurable via `talkDOM.maxPollers`). Pollers clean up automatically when their element is removed from the DOM.
|
|
251
|
+
Polling is capped at 64 concurrent pollers by default (configurable via `talkDOM.maxPollers`). Pollers clean up automatically when their element is removed from the DOM. Method lookups are cached at poll setup time.
|
|
252
|
+
|
|
253
|
+
The CSRF meta tag element is cached after the first lookup and only re-queried if removed from the DOM.
|
|
254
|
+
|
|
255
|
+
Whitespace regex patterns are precompiled and shared across the library. Internal helpers like `receiverName` and `resolveTarget` avoid unnecessary allocations.
|
|
252
256
|
|
|
253
257
|
For most pages, talkDOM adds negligible overhead. On pages with thousands of receivers, keep in mind that `querySelectorAll` runs once per unique receiver name per DOM mutation cycle.
|
|
254
258
|
|
package/dist/talkdom.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){function
|
|
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}}}();
|
package/dist/talkdom.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["parseMessage","str","trimmed","trim","tokens","split","receiver","body","substring","length","rest","slice","keywords","args","currentArg","i","token","endsWith","push","join","selector","receiverName","el","getAttribute","receiverCache","cacheValid","findReceivers","name","result","document","querySelectorAll","apply","op","content","
|
|
1
|
+
{"version":3,"names":["WS","parseMessage","str","trimmed","trim","tokens","split","receiver","body","substring","length","rest","slice","keywords","args","currentArg","i","token","endsWith","push","join","selector","receiverName","el","attr","getAttribute","sp","indexOf","receiverCache","Object","create","cacheValid","findReceivers","name","result","document","querySelectorAll","apply","op","content","accepts","innerHTML","textContent","insertAdjacentHTML","outerHTML","hasAttribute","key","localStorage","setItem","JSON","stringify","persist","console","error","MutationObserver","observe","childList","subtree","attributes","attributeFilter","csrfMeta","request","method","url","headers","location","href","isConnected","querySelector","warn","fetch","then","r","ok","status","Promise","reject","trigger","get","text","dispatchRaw","err","recName","methods","message","confirm","t","pushing","replayState","state","sender","resolveTarget","next","parent","previousElementSibling","lastElementChild","send","msg","piped","els","undefined","concat","forEach","detail","parentNode","nextElementSibling","target","dispatchEvent","CustomEvent","bubbles","run","raw","resolve","chains","map","chain","step","steps","s","filter","Boolean","reduce","prev","all","catch","dispatch","senderEl","first","colonIdx","pathname","search","history","pushState","pushUrl","window","addEventListener","e","activePollers","maxPollers","closest","preventDefault","getItem","parse","removeItem","interval","match","n","parseInt","parseInterval","cachedTargets","id","setInterval","clearInterval","talkDOM"],"sources":["index.js"],"mappings":"CAAC,WAEC,IAAIA,EAAK,MAIT,SAASC,EAAaC,GAUpB,IATA,IAAIC,EAAUD,EAAIE,OACdC,EAASF,EAAQG,MAAMN,GACvBO,EAAWF,EAAO,GAClBG,EAAOL,EAAQM,UAAUF,EAASG,QAAQN,OAC1CO,EAAON,EAAOO,MAAM,GACpBC,EAAW,GACXC,EAAO,GACPC,EAAa,GAERC,EAAI,EAAGA,EAAIL,EAAKD,OAAQM,IAAK,CACpC,IAAIC,EAAQN,EAAKK,GACbC,EAAMC,SAAS,MACbL,EAASH,OAAS,GAAKK,EAAWL,OAAS,GAC7CI,EAAKK,KAAKJ,EAAWK,KAAK,MAC1BL,EAAa,IACJF,EAASH,OAAS,GAC3BI,EAAKK,KAAK,IAEZN,EAASM,KAAKF,IAEdF,EAAWI,KAAKF,EAEpB,CAKA,OAJIJ,EAASH,OAAS,GACpBI,EAAKK,KAAKJ,EAAWK,KAAK,MAGrB,CAAEb,SAAUA,EAAUc,SAAUR,EAASO,KAAK,IAAKP,SAAUA,EAAUC,KAAMA,EAAMN,KAAMA,EAClG,CAGA,SAASc,EAAaC,GACpB,IAAIC,EAAOD,EAAGE,aAAa,YAAYrB,OACnCsB,EAAKF,EAAKG,QAAQ,KACtB,OAAe,IAARD,EAAYF,EAAOA,EAAKf,UAAU,EAAGiB,EAC9C,CAGA,IAAIE,EAAgBC,OAAOC,OAAO,MAC9BC,GAAa,EAMjB,SAASC,EAAcC,GAErB,GADKF,IAAcH,EAAgBC,OAAOC,OAAO,MAAOC,GAAa,GACjEH,EAAcK,GAAO,OAAOL,EAAcK,GAC9C,IAAIC,EAASC,SAASC,iBAAiB,eAAiBH,EAAO,MAE/D,OADAL,EAAcK,GAAQC,EACfA,CACT,CAwCA,SAASG,EAAMd,EAAIe,EAAIC,GACrB,GArCF,SAAiBhB,EAAIe,GACnB,IAAId,EAAOD,EAAGE,aAAa,WAC3B,OAAKD,IACkD,KAA/C,IAAMA,EAAO,KAAKG,QAAQ,IAAMW,EAAK,IAC/C,CAiCOE,CAAQjB,EAAIe,GAAjB,CAIA,OAAQA,GACN,IAAK,QAASf,EAAGkB,UAAYF,EAAS,MACtC,IAAK,OAAQhB,EAAGmB,YAAcH,EAAS,MACvC,IAAK,SAAUhB,EAAGoB,mBAAmB,YAAaJ,GAAU,MAC5D,IAAK,QAAShB,EAAGqB,UAAYL,EAG/B,OAzCF,SAAiBhB,EAAIe,GACnB,GAAKf,EAAGsB,aAAa,aAAgBtB,EAAGsB,aAAa,WAArD,CACA,IACIC,EAAM,WADCxB,EAAaC,GAEb,UAAPe,EACFS,aAAaC,QAAQF,EAAKG,KAAKC,UAAU,CAAEZ,GAAIA,EAAIC,QAAShB,EAAGqB,aAE/DG,aAAaC,QAAQF,EAAKG,KAAKC,UAAU,CAAEZ,GAAIA,EAAIC,QAAShB,EAAGkB,YANM,CAQzE,CA+BEU,CAAQ5B,EAAIe,GACLC,CARP,CAFEa,QAAQC,MAAM/B,EAAaC,GAAM,oBAAsBe,EAW3D,CA/DA,IAAIgB,iBAAiB,WAAcvB,GAAa,CAAO,GACpDwB,QAAQpB,SAAU,CAAEqB,WAAW,EAAMC,SAAS,EAAMC,YAAY,EAAMC,gBAAiB,CAAC,cAgE3F,IAAIC,EAAW,KAYf,SAASC,EAAQC,EAAQC,EAAKxD,GAC5B,IAAIyD,EAAU,CACZ,oBAAqB,OACrB,wBAAyBC,SAASC,MAKpC,GAHI3D,IACFyD,EAAQ,sBAAwBzD,GAEnB,QAAXuD,EAAkB,CACpB,IAAI7C,GAjBD2C,GAAaA,EAASO,cACzBP,EAAWzB,SAASiC,cAAc,4BAE7BR,EAAWA,EAASnC,aAAa,WAAa,IAe/CR,EAAO+C,EAAQ,gBAAkB/C,EAChCmC,QAAQiB,KAAK,oCAAsCP,EAAS,IAAMC,EACzE,CACA,OAAOO,MAAMP,EAAK,CAAED,OAAQA,EAAQE,QAASA,IAAWO,KAAK,SAAUC,GACrE,IAAKA,EAAEC,GAEL,OADArB,QAAQC,MAAM,YAAcS,EAAS,IAAMC,EAAM,IAAMS,EAAEE,QAClDC,QAAQC,OAAOJ,EAAEE,QAE1B,IAAIG,EAAUL,EAAER,QAAQc,IAAI,qBAC5B,OAAON,EAAEO,OAAOR,KAAK,SAAUQ,GAE7B,OADIF,GAASG,EAAYH,GAClBE,CACT,EACF,EAAG,SAAUE,GAEX,OADA7B,QAAQC,MAAM,YAAcS,EAAS,IAAMC,EAAM,UAAWkB,GACrDN,QAAQC,OAAOK,EACxB,EACF,CAEA,SAASC,EAAQ3D,GACf,OAAOA,EAAGsB,aAAa,YAAcvB,EAAaC,GAAM,EAC1D,CAIA,MAAM4D,EAAU,CACd,OAAQ,SAAU5D,EAAIwC,GAAO,OAAOF,EAAQ,MAAOE,EAAKmB,EAAQ3D,GAAM,EACtE,QAAS,SAAUA,EAAIwC,GAAO,OAAOF,EAAQ,OAAQE,EAAKmB,EAAQ3D,GAAM,EACxE,OAAQ,SAAUA,EAAIwC,GAAO,OAAOF,EAAQ,MAAOE,EAAKmB,EAAQ3D,GAAM,EACtE,UAAW,SAAUA,EAAIwC,GAAO,OAAOF,EAAQ,SAAUE,EAAKmB,EAAQ3D,GAAM,EAC5E,WAAY,SAAUA,EAAI6D,GAAW,IAAKC,QAAQD,GAAU,OAAOT,QAAQC,OAAO,YAAc,EAChG,SAAU,SAAUrD,EAAIgB,EAASD,GAAM,OAAOD,EAAMd,EAAIe,EAAIC,EAAU,EACtE,aAAc,SAAUhB,EAAIwC,EAAKzB,GAAM,OAAOuB,EAAQ,MAAOE,EAAKmB,EAAQ3D,IAAKgD,KAAK,SAAUe,GAAK,OAAOjD,EAAMd,EAAIe,EAAIgD,EAAI,EAAI,EAChI,cAAe,SAAU/D,EAAIwC,EAAKzB,GAAM,OAAOuB,EAAQ,OAAQE,EAAKmB,EAAQ3D,IAAKgD,KAAK,SAAUe,GAAK,OAAOjD,EAAMd,EAAIe,EAAIgD,EAAI,EAAI,EAClI,aAAc,SAAU/D,EAAIwC,EAAKzB,GAAM,OAAOuB,EAAQ,MAAOE,EAAKmB,EAAQ3D,IAAKgD,KAAK,SAAUe,GAAK,OAAOjD,EAAMd,EAAIe,EAAIgD,EAAI,EAAI,EAChI,gBAAiB,SAAU/D,EAAIwC,EAAKzB,GAAM,OAAOuB,EAAQ,SAAUE,EAAKmB,EAAQ3D,IAAKgD,KAAK,SAAUe,GAAK,OAAOjD,EAAMd,EAAIe,EAAIgD,EAAI,EAAI,GAGxI,IAAIC,GAAU,EAsBd,SAASC,EAAYC,GACdA,GAAUA,EAAMC,SACrBH,GAAU,EACVP,EAAYS,EAAMC,QAClBH,GAAU,EACZ,CASA,SAASI,EAAcpE,EAAIqE,EAAMC,EAAQ5D,GACvC,OAAIV,EAAG4C,YAAoB5C,GACXqE,GAAQA,EAAKzB,YAAcyB,EAAKE,uBAC5CD,GAAUA,EAAO1B,YAAc0B,EAAOE,iBAAmB,OACzC/D,EAAcC,GAAM,EAC1C,CAIA,SAAS+D,EAAKC,EAAKC,GACjB,IAAIC,EAAMnE,EAAciE,EAAI1F,UAC5B,GAAmB,IAAf4F,EAAIzF,OAAR,CAIA,IAAIoD,EAASqB,EAAQc,EAAI5E,UACzB,GAAKyC,EAAL,CAIA,IACI5B,EADApB,OAAiBsF,IAAVF,EAAsB,CAACA,GAAOG,OAAOJ,EAAInF,MAAQmF,EAAInF,KAwBhE,OAtBAqF,EAAIG,QAAQ,SAAU/E,GACpB,IAAIgF,EAAS,CAAEhG,SAAU0F,EAAI1F,SAAUc,SAAU4E,EAAI5E,SAAUP,KAAMmF,EAAInF,MAIrE+E,EAAStE,EAAGiF,WACZZ,EAAOrE,EAAGkF,mBAEd,IADAvE,EAAS4B,EAAOvC,KAAOT,KACc,mBAAhBoB,EAAOqC,KAC1BrC,EAAOqC,KAAK,WACV,IAAImC,EAASf,EAAcpE,EAAIqE,EAAMC,EAAQI,EAAI1F,UAC7CmG,GAAQA,EAAOC,cAAc,IAAIC,YAAY,eAAgB,CAAEC,SAAS,EAAMN,OAAQA,IAC5F,EAAG,SAAUtB,GACXsB,EAAOlD,MAAQ4B,EACf,IAAIyB,EAASf,EAAcpE,EAAIqE,EAAMC,EAAQI,EAAI1F,UAC7CmG,GAAQA,EAAOC,cAAc,IAAIC,YAAY,gBAAiB,CAAEC,SAAS,EAAMN,OAAQA,IAC7F,OACK,CACL,IAAIG,EAASf,EAAcpE,EAAIqE,EAAMC,EAAQI,EAAI1F,UAC7CmG,GAAQA,EAAOC,cAAc,IAAIC,YAAY,eAAgB,CAAEC,SAAS,EAAMN,OAAQA,IAC5F,CACF,GACOrE,CAzBP,CAFEkB,QAAQC,MAAM4C,EAAI1F,SAAW,wBAA0B0F,EAAI5E,SAH7D,MAFE+B,QAAQC,MAAM4C,EAAI1F,SAAW,aAiCjC,CAIA,SAASuG,EAAIC,GACX,IAAI5G,EAAU4G,EAAI3G,OAElB,IAA8B,IAA1BD,EAAQwB,QAAQ,OAAyC,IAA1BxB,EAAQwB,QAAQ,KACjD,OAAOgD,QAAQqC,QAAQhB,EAAK/F,EAAaE,KAAWoE,KAAK,SAAUC,GAAK,MAAO,CAACA,EAAI,GAGtF,IAAIyC,EAAS9G,EAAQG,MAAM,KAAK4G,IAAI,SAAUC,GAC5C,IAAIC,EAAOD,EAAM/G,OACjB,IAAKgH,EAAM,OAAOzC,QAAQqC,UAG1B,IAAIK,EAAQD,EAAK9G,MAAM,KAAK4G,IAAI,SAAUI,GAAK,OAAOA,EAAElH,MAAQ,GAAGmH,OAAOC,SAC1E,OAAqB,IAAjBH,EAAM3G,OACDiE,QAAQqC,QAAQhB,EAAK/F,EAAaoH,EAAM,MAI1CA,EAAMI,OAAO,SAAUC,EAAMN,GAClC,IAAInB,EAAMhG,EAAamH,GACvB,OAAOzC,QAAQqC,QAAQU,GAAMnD,KAAK,SAAU2B,GAC1C,OAAOF,EAAKC,EAAKC,EACnB,EACF,OAAGE,EACL,GAEA,OAAOzB,QAAQgD,IAAIV,EACrB,CAGA,SAASjC,EAAY+B,GACnBD,EAAIC,GAAKa,MAAM,SAAU3C,GAAO7B,QAAQiB,KAAK,WAAYY,EAAM,EACjE,CAGA,SAAS4C,EAASC,GAChB,IAAIf,EAAMe,EAASrG,aAAa,UAChCuD,EAAY+B,GACPxB,GAxHP,SAAiBuC,EAAUf,GACzB,GAAKe,EAASjF,aAAa,YAA3B,CACA,IAAIkB,EAAM+D,EAASrG,aAAa,YAChC,IAAKsC,EAAK,CAGR,IAAIgE,EAAQhB,EAAIzG,MAAM,KAAK,GAAGA,MAAM,KAAK,GAAGF,OACxC4H,EAAWD,EAAMpG,QAAQ,MACX,IAAdqG,IAEFjE,EADiBgE,EAAMtH,UAAUuH,EAAW,GAAG5H,OAC9BE,MAAM,MAAM,IAAM,GAEvC,CACIyD,GAAQE,SAASgE,SAAWhE,SAASiE,SAAYnE,GACnDoE,QAAQC,UAAU,CAAE1C,OAAQqB,GAAO,GAAIhD,EAbK,CAehD,CAwGgBsE,CAAQP,EAAUf,EAClC,CA/FAuB,OAAOC,iBAAiB,WAAY,SAAUC,GAC5ChD,EAAYgD,EAAE/C,MAChB,GAwGA,IAAIgD,EAAgB,EAChBC,EAAa,GAqCjBvG,SAASoG,iBAAiB,QAAS,SAAUC,GAC3C,MAAM9C,EAAS8C,EAAE9B,OAAOiC,QAAQ,YAC5BjD,IACF8C,EAAEI,iBACFf,EAASnC,GAEb,GA9QEvD,SAASC,iBAAiB,aAAakE,QAAQ,SAAU/E,GACvD,GAAKA,EAAGsB,aAAa,YAArB,CACA,IAAIZ,EAAOX,EAAaC,GACpBwF,EAAMhE,aAAa8F,QAAQ,WAAa5G,GAC5C,GAAK8E,EAAL,CACA,IAAItB,EACJ,IAAMA,EAAQxC,KAAK6F,MAAM/B,EAAM,CAAE,MAAOyB,GAAyD,YAA5CzF,aAAagG,WAAW,WAAa9G,EAAe,CACxF,UAAbwD,EAAMnD,GACRf,EAAGqB,UAAY6C,EAAMlD,QAErBhB,EAAGkB,UAAYgD,EAAMlD,OANP,CAHwB,CAW1C,GAqQFiD,EAAY2C,QAAQ1C,OACpBtD,SAASC,iBAAiB,cAAckE,QA7CxC,SAAsB/E,GACpB,IACI0E,EAAMhG,EADCsB,EAAGE,aAAa,aAE3B,GAA8C,UAA1CwE,EAAIpF,SAASoF,EAAIpF,SAASH,OAAS,GACvC,GAAI+H,GAAiBC,EACnBtF,QAAQiB,KAAK,yBAA2BqE,EAAa,uBAAyBzC,EAAI1F,cADpF,CAIA,IAAIyI,EApBN,SAAuB9I,GACrB,IAAI+I,EAAQ/I,EAAI+I,MAAM,iBACtB,IAAKA,EAAO,OAAO,KACnB,IAAIC,EAAIC,SAASF,EAAM,GAAI,IAC3B,MAAoB,MAAbA,EAAM,GAAiB,IAAJC,EAAWA,CACvC,CAeiBE,CAAcnD,EAAInF,KAAKmF,EAAInF,KAAKJ,OAAS,IACxD,GAAKsI,EAAL,CAIA,IAAI3H,EAAW4E,EAAIpF,SAASD,MAAM,GAAI,GAAGQ,KAAK,IAC1CN,EAAOmF,EAAInF,KAAKF,MAAM,GAAI,GAC1BqB,EAAOgE,EAAI1F,SACX8I,EAAgBrH,EAAcC,GAC9B6B,EAASqB,EAAQ9D,GACrBoH,IACA,IAAIa,EAAKC,YAAY,WACnB,IAAKhI,EAAG4C,YAAmD,OAApCqF,cAAcF,QAAKb,IACb,IAAzBY,EAAc3I,QAAiB2I,EAAc,GAAGlF,cAClDkF,EAAgBrH,EAAcC,IAEH,IAAzBoH,EAAc3I,SACboD,IAAQA,EAASqB,EAAQ9D,IACzByC,EAILuF,EAAc/C,QAAQ,SAAUI,GAAU5C,EAAO4C,KAAW5F,EAAO,GAHjEsC,QAAQC,MAAMpB,EAAO,wBAA0BZ,GAInD,EAAG2H,EAnBH,MAFE5F,QAAQC,MAAM,8BAAgC4C,EAAI1F,SAHpD,CAyBF,GAeA+H,OAAOmB,QAAU,CACftE,QAASA,EACTa,KAAMc,EACN,cAAI4B,GAAe,OAAOA,CAAY,EACtC,cAAIA,CAAWQ,GAAKR,EAAaQ,CAAG,EAGxC,CA7WA","ignoreList":[]}
|
package/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
+
var WS = /\s+/;
|
|
4
|
+
|
|
3
5
|
// Parse "receiver keyword: arg keyword: arg" into structured message object.
|
|
4
6
|
// Tokens ending with ":" are keywords, everything else fills args.
|
|
5
7
|
function parseMessage(str) {
|
|
6
8
|
var trimmed = str.trim();
|
|
7
|
-
var tokens = trimmed.split(
|
|
9
|
+
var tokens = trimmed.split(WS);
|
|
8
10
|
var receiver = tokens[0];
|
|
9
11
|
var body = trimmed.substring(receiver.length).trim();
|
|
10
12
|
var rest = tokens.slice(1);
|
|
@@ -35,11 +37,13 @@
|
|
|
35
37
|
|
|
36
38
|
// Extract the first word from the receiver attribute (the name).
|
|
37
39
|
function receiverName(el) {
|
|
38
|
-
|
|
40
|
+
var attr = el.getAttribute("receiver").trim();
|
|
41
|
+
var sp = attr.indexOf(" ");
|
|
42
|
+
return sp === -1 ? attr : attr.substring(0, sp);
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
// Receiver cache: maps name -> NodeList, invalidated by DOM mutations.
|
|
42
|
-
var receiverCache =
|
|
46
|
+
var receiverCache = Object.create(null);
|
|
43
47
|
var cacheValid = false;
|
|
44
48
|
|
|
45
49
|
new MutationObserver(function () { cacheValid = false; })
|
|
@@ -47,7 +51,7 @@
|
|
|
47
51
|
|
|
48
52
|
// Find all elements whose receiver attribute contains the given name.
|
|
49
53
|
function findReceivers(name) {
|
|
50
|
-
if (!cacheValid) { receiverCache =
|
|
54
|
+
if (!cacheValid) { receiverCache = Object.create(null); cacheValid = true; }
|
|
51
55
|
if (receiverCache[name]) return receiverCache[name];
|
|
52
56
|
var result = document.querySelectorAll('[receiver~="' + name + '"]');
|
|
53
57
|
receiverCache[name] = result;
|
|
@@ -59,7 +63,7 @@
|
|
|
59
63
|
function accepts(el, op) {
|
|
60
64
|
var attr = el.getAttribute("accepts");
|
|
61
65
|
if (!attr) return true;
|
|
62
|
-
return attr
|
|
66
|
+
return (" " + attr + " ").indexOf(" " + op + " ") !== -1;
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
// Save receiver content to localStorage after apply, keyed by receiver name.
|
|
@@ -107,9 +111,14 @@
|
|
|
107
111
|
return content;
|
|
108
112
|
}
|
|
109
113
|
|
|
114
|
+
var csrfMeta = null;
|
|
115
|
+
|
|
110
116
|
function csrfToken() {
|
|
111
|
-
|
|
112
|
-
|
|
117
|
+
// Cache the element reference; re-query only if not found yet or removed.
|
|
118
|
+
if (!csrfMeta || !csrfMeta.isConnected) {
|
|
119
|
+
csrfMeta = document.querySelector('meta[name="csrf-token"]');
|
|
120
|
+
}
|
|
121
|
+
return csrfMeta ? csrfMeta.getAttribute("content") : "";
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
// Perform a fetch with talkDOM headers. Returns a promise resolving to response text.
|
|
@@ -169,8 +178,14 @@
|
|
|
169
178
|
if (!senderEl.hasAttribute("push-url")) return;
|
|
170
179
|
var url = senderEl.getAttribute("push-url");
|
|
171
180
|
if (!url) {
|
|
172
|
-
|
|
173
|
-
|
|
181
|
+
// Extract the first arg from the first step without a full parseMessage call.
|
|
182
|
+
// Pattern: "receiver keyword: arg ..." -- grab the token after the first ":"
|
|
183
|
+
var first = raw.split(";")[0].split("|")[0].trim();
|
|
184
|
+
var colonIdx = first.indexOf(":");
|
|
185
|
+
if (colonIdx !== -1) {
|
|
186
|
+
var afterColon = first.substring(colonIdx + 1).trim();
|
|
187
|
+
url = afterColon.split(/\s/)[0] || "";
|
|
188
|
+
}
|
|
174
189
|
}
|
|
175
190
|
if (url && (location.pathname + location.search) !== url) {
|
|
176
191
|
history.pushState({ sender: raw }, "", url);
|
|
@@ -189,6 +204,16 @@
|
|
|
189
204
|
replayState(e.state);
|
|
190
205
|
});
|
|
191
206
|
|
|
207
|
+
// After an outer swap `el` is gone. Walk from the snapshotted sibling or
|
|
208
|
+
// parent to find the element that took its place; fall back to a fresh
|
|
209
|
+
// receiver query if the DOM was restructured.
|
|
210
|
+
function resolveTarget(el, next, parent, name) {
|
|
211
|
+
if (el.isConnected) return el;
|
|
212
|
+
var candidate = next && next.isConnected ? next.previousElementSibling
|
|
213
|
+
: parent && parent.isConnected ? parent.lastElementChild : null;
|
|
214
|
+
return candidate || findReceivers(name)[0];
|
|
215
|
+
}
|
|
216
|
+
|
|
192
217
|
// Deliver a parsed message to all matching receivers. Fires talkdom:done or talkdom:error
|
|
193
218
|
// lifecycle events on the receiver element (or its replacement if outer-swapped).
|
|
194
219
|
function send(msg, piped) {
|
|
@@ -212,26 +237,17 @@
|
|
|
212
237
|
var parent = el.parentNode;
|
|
213
238
|
var next = el.nextElementSibling;
|
|
214
239
|
result = method(el, ...args);
|
|
215
|
-
// After an outer swap `el` is gone. Walk from the snapshotted sibling or
|
|
216
|
-
// parent to find the element that took its place; fall back to a fresh
|
|
217
|
-
// receiver query if the DOM was restructured.
|
|
218
|
-
function resolveTarget() {
|
|
219
|
-
if (el.isConnected) return el;
|
|
220
|
-
var candidate = next && next.isConnected ? next.previousElementSibling
|
|
221
|
-
: parent && parent.isConnected ? parent.lastElementChild : null;
|
|
222
|
-
return candidate || findReceivers(msg.receiver)[0];
|
|
223
|
-
}
|
|
224
240
|
if (result && typeof result.then === "function") {
|
|
225
241
|
result.then(function () {
|
|
226
|
-
var target = resolveTarget();
|
|
242
|
+
var target = resolveTarget(el, next, parent, msg.receiver);
|
|
227
243
|
if (target) target.dispatchEvent(new CustomEvent("talkdom:done", { bubbles: true, detail: detail }));
|
|
228
244
|
}, function (err) {
|
|
229
245
|
detail.error = err;
|
|
230
|
-
var target = resolveTarget();
|
|
246
|
+
var target = resolveTarget(el, next, parent, msg.receiver);
|
|
231
247
|
if (target) target.dispatchEvent(new CustomEvent("talkdom:error", { bubbles: true, detail: detail }));
|
|
232
248
|
});
|
|
233
249
|
} else {
|
|
234
|
-
var target = resolveTarget();
|
|
250
|
+
var target = resolveTarget(el, next, parent, msg.receiver);
|
|
235
251
|
if (target) target.dispatchEvent(new CustomEvent("talkdom:done", { bubbles: true, detail: detail }));
|
|
236
252
|
}
|
|
237
253
|
});
|
|
@@ -241,13 +257,18 @@
|
|
|
241
257
|
// Programmatic API: parse and execute a raw message string (supports pipes and semicolons).
|
|
242
258
|
// Returns a promise that resolves when all chains complete.
|
|
243
259
|
function run(raw) {
|
|
260
|
+
var trimmed = raw.trim();
|
|
261
|
+
// Fast path: no pipes or semicolons (most common case).
|
|
262
|
+
if (trimmed.indexOf(";") === -1 && trimmed.indexOf("|") === -1) {
|
|
263
|
+
return Promise.resolve(send(parseMessage(trimmed))).then(function (r) { return [r]; });
|
|
264
|
+
}
|
|
244
265
|
// Semicolons split into independent chains that run in parallel.
|
|
245
|
-
var chains =
|
|
246
|
-
var
|
|
247
|
-
if (!
|
|
266
|
+
var chains = trimmed.split(";").map(function (chain) {
|
|
267
|
+
var step = chain.trim();
|
|
268
|
+
if (!step) return Promise.resolve();
|
|
248
269
|
// Pipes split a chain into sequential steps where each step's return
|
|
249
270
|
// value is fed as the first argument to the next step.
|
|
250
|
-
var steps =
|
|
271
|
+
var steps = step.split("|").map(function (s) { return s.trim(); }).filter(Boolean);
|
|
251
272
|
if (steps.length === 1) {
|
|
252
273
|
return Promise.resolve(send(parseMessage(steps[0])));
|
|
253
274
|
}
|
|
@@ -305,6 +326,7 @@
|
|
|
305
326
|
var args = msg.args.slice(0, -1);
|
|
306
327
|
var name = msg.receiver;
|
|
307
328
|
var cachedTargets = findReceivers(name);
|
|
329
|
+
var method = methods[selector];
|
|
308
330
|
activePollers++;
|
|
309
331
|
var id = setInterval(function () {
|
|
310
332
|
if (!el.isConnected) { clearInterval(id); activePollers--; return; }
|
|
@@ -312,7 +334,7 @@
|
|
|
312
334
|
cachedTargets = findReceivers(name);
|
|
313
335
|
}
|
|
314
336
|
if (cachedTargets.length === 0) return;
|
|
315
|
-
|
|
337
|
+
if (!method) method = methods[selector];
|
|
316
338
|
if (!method) {
|
|
317
339
|
console.error(name + " does not understand " + selector);
|
|
318
340
|
return;
|