turbo_reflex 0.0.7 → 0.0.8
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +9 -17
- data/README.md +1 -1
- data/app/assets/builds/turbo_reflex.js +1 -1
- data/app/assets/builds/turbo_reflex.js.map +4 -4
- data/app/javascript/drivers/window.js +12 -32
- data/app/javascript/lifecycle.js +5 -0
- data/app/javascript/renderer.js +23 -0
- data/app/javascript/turbo.js +19 -1
- data/lib/turbo_reflex/runner.rb +4 -1
- data/lib/turbo_reflex/version.rb +1 -1
- data/package.json +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a31a4a624ebc825d519458818b34735051ab4fefd4d03d8b3c974ec96cae27fd
|
|
4
|
+
data.tar.gz: 5e4df1345eeedcc08ef0ee5989575c38f38a4956495654f4f3416d596dd3c6b0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3139e5ce67c4035913b8c4690273ccb591afc30a856492b0bae56565654c8c8037df9f22565750786cb24a7e6632c3dc717dbc0490f6cc8aad8fef879b2010c3
|
|
7
|
+
data.tar.gz: c43dd944ef5c0ac1e60150471f5b4a172fe400c2e5f2e57f98735474f07a0204b34cfdf2123a12a157661042d3b518a5f0a6003b0c68dfc1cd6ca02b805d221b
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
turbo_reflex (0.0.
|
|
4
|
+
turbo_reflex (0.0.8)
|
|
5
5
|
rails (>= 6.1)
|
|
6
6
|
turbo-rails (>= 1.1)
|
|
7
7
|
turbo_ready (>= 0.1)
|
|
@@ -98,7 +98,6 @@ GEM
|
|
|
98
98
|
cuprite (0.13)
|
|
99
99
|
capybara (>= 2.1, < 4)
|
|
100
100
|
ferrum (~> 0.11.0)
|
|
101
|
-
digest (3.1.0)
|
|
102
101
|
erubi (1.11.0)
|
|
103
102
|
ferrum (0.11)
|
|
104
103
|
addressable (~> 2.5)
|
|
@@ -130,20 +129,14 @@ GEM
|
|
|
130
129
|
builder
|
|
131
130
|
minitest (>= 5.0)
|
|
132
131
|
ruby-progressbar
|
|
133
|
-
net-imap (0.
|
|
134
|
-
digest
|
|
132
|
+
net-imap (0.3.1)
|
|
135
133
|
net-protocol
|
|
136
|
-
|
|
137
|
-
net-pop (0.1.1)
|
|
138
|
-
digest
|
|
134
|
+
net-pop (0.1.2)
|
|
139
135
|
net-protocol
|
|
140
|
-
timeout
|
|
141
136
|
net-protocol (0.1.3)
|
|
142
137
|
timeout
|
|
143
|
-
net-smtp (0.3.
|
|
144
|
-
digest
|
|
138
|
+
net-smtp (0.3.2)
|
|
145
139
|
net-protocol
|
|
146
|
-
timeout
|
|
147
140
|
nio4r (2.5.8)
|
|
148
141
|
nokogiri (1.13.8-aarch64-linux)
|
|
149
142
|
racc (~> 1.4)
|
|
@@ -213,7 +206,7 @@ GEM
|
|
|
213
206
|
rubocop-ast (>= 0.4.0)
|
|
214
207
|
ruby-progressbar (1.11.0)
|
|
215
208
|
rubyzip (2.3.2)
|
|
216
|
-
selenium-webdriver (4.
|
|
209
|
+
selenium-webdriver (4.5.0)
|
|
217
210
|
childprocess (>= 0.5, < 5.0)
|
|
218
211
|
rexml (~> 3.2, >= 3.2.5)
|
|
219
212
|
rubyzip (>= 1.2.2, < 3.0)
|
|
@@ -225,14 +218,13 @@ GEM
|
|
|
225
218
|
actionpack (>= 5.2)
|
|
226
219
|
activesupport (>= 5.2)
|
|
227
220
|
sprockets (>= 3.0.0)
|
|
228
|
-
sqlite3 (1.5.
|
|
229
|
-
sqlite3 (1.5.
|
|
221
|
+
sqlite3 (1.5.2-aarch64-linux)
|
|
222
|
+
sqlite3 (1.5.2-arm64-darwin)
|
|
230
223
|
standard (1.16.1)
|
|
231
224
|
rubocop (= 1.35.1)
|
|
232
225
|
rubocop-performance (= 1.14.3)
|
|
233
226
|
standardrb (1.0.1)
|
|
234
227
|
standard
|
|
235
|
-
strscan (3.0.4)
|
|
236
228
|
tailwindcss-rails (2.0.14-aarch64-linux)
|
|
237
229
|
railties (>= 6.0.0)
|
|
238
230
|
tailwindcss-rails (2.0.14-arm64-darwin)
|
|
@@ -254,7 +246,7 @@ GEM
|
|
|
254
246
|
activemodel (>= 6.0.0)
|
|
255
247
|
bindex (>= 0.4.0)
|
|
256
248
|
railties (>= 6.0.0)
|
|
257
|
-
webdrivers (5.
|
|
249
|
+
webdrivers (5.2.0)
|
|
258
250
|
nokogiri (~> 1.6)
|
|
259
251
|
rubyzip (>= 1.3.0)
|
|
260
252
|
selenium-webdriver (~> 4.0)
|
|
@@ -264,7 +256,7 @@ GEM
|
|
|
264
256
|
websocket-extensions (0.1.5)
|
|
265
257
|
xpath (3.2.0)
|
|
266
258
|
nokogiri (~> 1.8)
|
|
267
|
-
zeitwerk (2.6.
|
|
259
|
+
zeitwerk (2.6.1)
|
|
268
260
|
|
|
269
261
|
PLATFORMS
|
|
270
262
|
aarch64-linux
|
data/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</h1>
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="http://blog.codinghorror.com/the-best-code-is-no-code-at-all/">
|
|
11
|
-
<img alt="Lines of Code" src="https://img.shields.io/badge/loc-
|
|
11
|
+
<img alt="Lines of Code" src="https://img.shields.io/badge/loc-694-47d299.svg" />
|
|
12
12
|
</a>
|
|
13
13
|
<a href="https://codeclimate.com/github/hopsoft/turbo_reflex/maintainability">
|
|
14
14
|
<img src="https://api.codeclimate.com/v1/badges/fe1162a742fe83a4fdfd/maintainability" />
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var S={frameAttribute:"data-turbo-frame",reflexAttribute:"data-turbo-reflex"},
|
|
1
|
+
var S={frameAttribute:"data-turbo-frame",reflexAttribute:"data-turbo-reflex"},f={...S};var b={};function j(e){b[e.id]=e}function D(e){delete b[e]}var v={add:j,remove:D,get reflexes(){return[...Object.values(b)]},get length(){return Object.keys(b).length}};var c={start:"turbo-reflex:start",success:"turbo-reflex:success",finish:"turbo-reflex:finish",abort:"turbo-reflex:abort",clientError:"turbo-reflex:client-error",serverError:"turbo-reflex:server-error"};function p(e,t=document,r={},n=!1){try{t=t||document;let s=new CustomEvent(e,{detail:r,cancelable:!1,bubbles:!0});t.dispatchEvent(s)}catch(s){if(n)throw s;p(c.clientError,t,{error:s,...r},!0)}}function H(e={}){p(lifecycle.events.clientError,window,e,!0)}function T(e){e.detail.endedAt=new Date().getTime(),e.detail.milliseconds=e.detail.endedAt-e.detail.startedAt,setTimeout(()=>p(c.finish,e.target,e.detail),10)}addEventListener(c.serverError,T);addEventListener(c.success,T);addEventListener(c.finish,e=>v.remove(e.detail.id),!0);var o={dispatch:p,dispatchClientError:H,events:c};function _(e){return e.closest(`[${f.reflexAttribute}]`)}function q(e){return e.closest("turbo-frame")}function P(e,t={}){if(e.tagName.toLowerCase()!=="select")return t.value=e.value;if(!e.multiple)return t.value=e.options[e.selectedIndex].value;t.values=Array.from(e.options).reduce((r,n)=>(n.selected&&r.push(n.value),r),[])}function V(e){let n=Array.from(e.attributes).reduce((s,u)=>{let d=u.value;return typeof d=="string"&&d.length>100&&(d=d.slice(0,100)+"..."),s[u.name]=d,s},{});return n.tag=e.tagName,n.checked=e.checked,n.disabled=e.disabled,P(e,n),typeof n.value=="string"&&n.value.length>500&&(n.value=n.value.slice(0,500)+"..."),delete n.class,delete n[f.reflexAttribute],delete n[f.frameAttribute],n}var i={buildAttributePayload:V,findClosestReflex:_,findClosestFrame:q,get metaElement(){return document.getElementById("turbo-reflex")},get metaElementToken(){return document.getElementById("turbo-reflex").getAttribute("content")}};function X(e){let t="<html",r="</html",n=e.indexOf(t),s=e.lastIndexOf(r);if(n>=0&&s>=0){let u=e.slice(e.indexOf(">",n)+1,s);document.documentElement.innerHTML=u}}function $(e){let t="<turbo-stream",r="</turbo-stream>",n=e.indexOf(t),s=e.lastIndexOf(r);if(n>=0&&s>=0){let u=e.slice(n,s+r.length);document.body.insertAdjacentHTML("beforeend",u)}}var l={renderDocument:X,renderStreams:$};var h={};addEventListener("turbo:before-fetch-request",e=>{let t=e.target.closest("turbo-frame"),{fetchOptions:r}=e.detail;r.headers["TurboReflex-Token"]=i.metaElementToken});addEventListener("turbo:before-fetch-response",e=>{let t=e.target.closest("turbo-frame"),{fetchResponse:r}=e.detail;if(t&&(h[t.id]=t.src,r.header("TurboReflex")==="true")){if(r.statusCode<200||r.statusCode>299){let n=`Server returned a ${r.statusCode} status code! TurboReflex requires 2XX status codes.`;o.dispatchClientError({...e.detail,error:n})}r.header("TurboReflex-Hijacked")==="true"&&(e.preventDefault(),r.responseText.then(n=>l.renderStreams(n)))}});addEventListener("turbo:frame-load",e=>{let t=e.target.closest("turbo-frame");t.dataset.turboReflexSrc=h[t.id]||t.src||t.dataset.turboReflexSrc,delete h[t.id]});var m={},L;function N(e,t){m[e]=t,document.addEventListener(e,L,!0)}function B(e,t){return t=t.toLowerCase(),m[e].includes(t)||!Object.values(m).flat().includes(t)&&m[e].includes("*")}var a={events:m,register:N,isRegistered:B,set handler(e){L=e}};function F(e,t={}){t.token=i.metaElementToken;let r=document.createElement("input");r.type="hidden",r.name="turbo_reflex",r.value=JSON.stringify(t),e.appendChild(r)}var w={invokeReflex:F};function M(e,t={}){let r=document.createElement("a");r.href=e;let n=new URL(r);return n.searchParams.set("turbo_reflex",JSON.stringify(t)),n}var g={build:M};function U(e,t){let r=t.src;t={...t},delete t.src,e.src=g.build(r,t)}var E={invokeReflex:U};function J(e){let t=e.target;o.dispatch(o.events.abort,window,{xhr:t,...e.detail})}function R(e){let t=e.target;t.getResponseHeader("TurboReflex-Hijacked")==="true"?l.renderStreams(t.responseText):l.renderDocument(t.responseText);let r=`Server returned a ${t.status} status code! TurboReflex requires 2XX status codes.`;o.dispatchClientError({xhr:t,...e.detail,error:r})}function G(e){let t=e.target;if(t.status<200||t.status>299)return R(e);let r=t.responseText;t.getResponseHeader("TurboReflex-Hijacked")==="true"?l.renderStreams(t.responseText):l.renderDocument(t.responseText)}function z(e){let t=e.src;e={...e},delete e.src;try{let r=new XMLHttpRequest;r.open("GET",g.build(t,e),!0),r.setRequestHeader("TurboReflex-Token",i.metaElementToken),r.addEventListener("abort",J),r.addEventListener("error",R),r.addEventListener("load",G),r.send()}catch(r){let n=`Unexpected error sending HTTP request! ${r.message}`;R(r,{detail:{message:n}})}}var y={invokeReflex:z};function k(e,t){return t=t||{dataset:{}},e.href||t.src||t.dataset.turboReflexSrc||location.href}function K(e){let t=i.findClosestFrame(e),r=e.dataset.turboFrame;return e.tagName.toLowerCase()==="form"?{name:"form",reason:"Element is a form.",frame:t,src:e.action,invokeReflex:w.invokeReflex}:r&&r!=="_self"?(t=document.getElementById(r),{name:"frame",reason:"element targets a frame that is not _self",frame:t,src:k(e,t),invokeReflex:E.invokeReflex}):(!r||r==="_self")&&t?{name:"frame",reason:"element does NOT target a frame or targets _self and is contained by a frame",frame:t,src:k(e,t),invokeReflex:E.invokeReflex}:{name:"window",reason:"element matches one or more of the following conditions (targets _top, does NOT target a frame, is NOT contained by a frame)",frame:null,src:k(e),invokeReflex:y.invokeReflex}}var A={find:K};var x="unknown",O={debug:Object.values(o.events),info:Object.values(o.events),warn:[o.events.abort,o.events.clientError,o.events.serverError],error:[o.events.clientError,o.events.serverError],unknown:[]};Object.values(o.events).forEach(e=>{addEventListener(e,t=>{O[x].includes(t.type)&&console[x==="debug"?"log":x](t.type,t.detail)})});var C={get level(){return x},set level(e){return Object.keys(O).includes(e)||(e="unknown"),x=e}};function Q(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}var I={v4:Q};function W(e){let t,r={};try{if(t=i.findClosestReflex(e.target),!t||!a.isRegistered(e.type,t.tagName))return;let n=A.find(t);switch(r={id:`reflex-${I.v4()}`,name:t.dataset.turboReflex,driver:n.name,src:n.src,frameId:n.frame?n.frame.id:null,elementId:t.id.length>0?t.id:null,elementAttributes:i.buildAttributePayload(t),startedAt:new Date().getTime()},v.add(r),o.dispatch(o.events.start,t,r),n.name!=="form"&&e.preventDefault(),n.name){case"form":return n.invokeReflex(t,r);case"frame":return n.invokeReflex(n.frame,r);case"window":return n.invokeReflex(r)}}catch(n){o.dispatch(o.events.clientError,t,{error:n,...r})}}a.handler=W;a.register("change",["input","select","textarea"]);a.register("submit",["form"]);a.register("click",["*"]);var Be={schema:f,logger:C,registerEventDelegate:a.register,get eventDelegates(){return{...a.events}},get lifecycleEvents(){return[...Object.values(o.events)]}};export{Be as default};
|
|
2
2
|
//# sourceMappingURL=turbo_reflex.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../javascript/schema.js", "../../javascript/activity.js", "../../javascript/lifecycle.js", "../../javascript/elements.js", "../../javascript/turbo.js", "../../javascript/delegates.js", "../../javascript/drivers/form.js", "../../javascript/urls.js", "../../javascript/drivers/frame.js", "../../javascript/drivers/window.js", "../../javascript/drivers/index.js", "../../javascript/logger.js", "../../javascript/uuids.js", "../../javascript/index.js"],
|
|
4
|
-
"sourcesContent": ["const schema = {\n frameAttribute: 'data-turbo-frame',\n reflexAttribute: 'data-turbo-reflex'\n}\n\nexport default { ...schema }\n", "const active = {}\n\nfunction add (payload) {\n active[payload.id] = payload\n}\n\nfunction remove (id) {\n delete active[id]\n}\n\nexport default {\n add,\n remove,\n get reflexes () {\n return [...Object.values(active)]\n },\n get length () {\n return Object.keys(active).length\n }\n}\n", "import activity from './activity'\n\nconst events = {\n start: 'turbo-reflex:start',\n success: 'turbo-reflex:success',\n finish: 'turbo-reflex:finish',\n abort: 'turbo-reflex:abort',\n clientError: 'turbo-reflex:client-error',\n serverError: 'turbo-reflex:server-error'\n}\n\nfunction dispatch (name, target = document, detail = {}, raise = false) {\n try {\n target = target || document\n const event = new CustomEvent(name, {\n detail,\n cancelable: false,\n bubbles: true\n })\n target.dispatchEvent(event)\n } catch (error) {\n if (raise) throw error\n dispatch(events.clientError, target, { error, ...detail }, true)\n }\n}\n\nfunction finish (event) {\n event.detail.endedAt = new Date().getTime()\n event.detail.milliseconds = event.detail.endedAt - event.detail.startedAt\n setTimeout(() => dispatch(events.finish, event.target, event.detail), 10)\n}\n\naddEventListener(events.serverError, finish)\naddEventListener(events.success, finish)\naddEventListener(events.finish, event => activity.remove(event.detail.id), true)\n\nexport default {\n dispatch,\n events\n}\n", "import schema from './schema.js'\nimport lifecycle from './lifecycle'\n\nfunction findClosestReflex (element) {\n return element.closest(`[${schema.reflexAttribute}]`)\n}\n\nfunction findClosestFrame (element) {\n return element.closest('turbo-frame')\n}\n\nfunction assignElementValueToPayload (element, payload = {}) {\n if (element.tagName.toLowerCase() !== 'select')\n return (payload.value = element.value)\n\n if (!element.multiple)\n return (payload.value = element.options[element.selectedIndex].value)\n\n payload.values = Array.from(element.options).reduce((memo, option) => {\n if (option.selected) memo.push(option.value)\n return memo\n }, [])\n}\n\nfunction buildAttributePayload (element) {\n // truncate long values to optimize payload size\n // TODO: revisit this decision\n const maxAttributeLength = 100\n const maxValueLength = 500\n\n const payload = Array.from(element.attributes).reduce((memo, attr) => {\n let value = attr.value\n if (typeof value === 'string' && value.length > maxAttributeLength)\n value = value.slice(0, maxAttributeLength) + '...'\n memo[attr.name] = value\n return memo\n }, {})\n\n payload.tag = element.tagName\n payload.checked = element.checked\n payload.disabled = element.disabled\n assignElementValueToPayload(element, payload)\n\n if (\n typeof payload.value === 'string' &&\n payload.value.length > maxValueLength\n )\n payload.value = payload.value.slice(0, maxValueLength) + '...'\n\n delete payload.class\n delete payload[schema.reflexAttribute]\n delete payload[schema.frameAttribute]\n return payload\n}\n\nexport default {\n buildAttributePayload,\n findClosestReflex,\n findClosestFrame,\n get metaElement () {\n return document.getElementById('turbo-reflex')\n },\n get metaElementToken () {\n return document.getElementById('turbo-reflex').getAttribute('content')\n }\n}\n", "import elements from './elements'\n\nconst frameSources = {}\n\n// fires before making a turbo HTTP request\naddEventListener('turbo:before-fetch-request', event => {\n const frame = event.target.closest('turbo-frame')\n const { fetchOptions } = event.detail\n fetchOptions.headers['TurboReflex-Token'] = elements.metaElementToken\n})\n\n// fires after receiving a turbo HTTP response\naddEventListener('turbo:before-fetch-response', event => {\n const frame = event.target.closest('turbo-frame')\n if (frame) frameSources[frame.id] = frame.src\n})\n\n// fires when a frame element is navigated and finishes loading\naddEventListener('turbo:frame-load', event => {\n const frame = event.target.closest('turbo-frame')\n frame.dataset.turboReflexSrc =\n frameSources[frame.id] || frame.src || frame.dataset.turboReflexSrc\n delete frameSources[frame.id]\n})\n", "const events = {}\nlet eventListener\n\nfunction register (eventName, tagNames) {\n events[eventName] = tagNames\n document.addEventListener(eventName, eventListener, true)\n}\n\nfunction isRegistered (eventName, tagName) {\n tagName = tagName.toLowerCase()\n return (\n events[eventName].includes(tagName) ||\n (!Object.values(events)\n .flat()\n .includes(tagName) &&\n events[eventName].includes('*'))\n )\n}\n\nexport default {\n events,\n register,\n isRegistered,\n set handler (fn) {\n eventListener = fn\n }\n}\n", "import elements from '../elements'\n\nfunction invokeReflex (form, payload = {}) {\n payload.token = elements.metaElementToken\n const input = document.createElement('input')\n input.type = 'hidden'\n input.name = 'turbo_reflex'\n input.value = JSON.stringify(payload)\n form.appendChild(input)\n}\n\nexport default { invokeReflex }\n", "function build (urlString, payload = {}) {\n const a = document.createElement('a')\n a.href = urlString\n const url = new URL(a)\n url.searchParams.set('turbo_reflex', JSON.stringify(payload))\n return url\n}\n\nexport default { build }\n", "import urls from '../urls'\nimport elements from '../elements'\n\nfunction invokeReflex (frame, payload) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n frame.src = urls.build(src, payload)\n}\n\nexport default { invokeReflex }\n", "import elements from '../elements'\nimport lifecycle from '../lifecycle'\nimport urls from '../urls'\n\nfunction aborted (event) {\n const xhr = event.target\n lifecycle.dispatch(lifecycle.events.abort, window, { xhr, ...event.detail })\n}\n\nfunction errored (event) {\n const xhr = event.target\n lifecycle.dispatch(\n lifecycle.events.clientError,\n window,\n {\n xhr,\n ...event.detail,\n error: `Server returned a ${xhr.status} status code! TurboReflex requires 2XX status codes. Server message: ${xhr.statusText}`\n },\n true\n )\n}\n\nfunction loaded (event) {\n const xhr = event.target\n const content = xhr.responseText\n const hijacked = xhr.getResponseHeader('TurboReflex-Hijacked') === 'true'\n if (xhr.status < 200 || xhr.status > 299) errored(event)\n\n if (hijacked) {\n const head = '<turbo-stream'\n const tail = '</turbo-stream>'\n const headIndex = content.indexOf(head)\n const tailIndex = content.lastIndexOf(tail)\n if (headIndex >= 0 && tailIndex >= 0) {\n const streams = content.slice(headIndex, tailIndex + tail.length)\n document.body.insertAdjacentHTML('beforeend', streams)\n }\n } else {\n const head = '<html'\n const tail = '</html'\n const headIndex = content.indexOf(head)\n const tailIndex = content.lastIndexOf(tail)\n if (headIndex >= 0 && tailIndex >= 0) {\n const html = content.slice(content.indexOf('>', headIndex) + 1, tailIndex)\n document.documentElement.innerHTML = html\n }\n }\n}\n\nfunction invokeReflex (payload) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n\n try {\n const xhr = new XMLHttpRequest()\n xhr.open('GET', urls.build(src, payload), true)\n xhr.setRequestHeader('TurboReflex-Token', elements.metaElementToken)\n xhr.addEventListener('abort', aborted)\n xhr.addEventListener('error', errored)\n xhr.addEventListener('load', loaded)\n xhr.send()\n } catch (ex) {\n const message = `Unexpected error sending HTTP request! ${ex.message}`\n errored(ex, { detail: { message } })\n }\n}\n\nexport default { invokeReflex }\n", "import elements from '../elements'\nimport formDriver from './form'\nimport frameDriver from './frame'\nimport windowDriver from './window'\n\nfunction src (element, frame) {\n frame = frame || { dataset: {} }\n return (\n element.href || frame.src || frame.dataset.turboReflexSrc || location.href\n )\n}\n\nfunction find (element) {\n let frame = elements.findClosestFrame(element)\n const targetId = element.dataset.turboFrame\n\n if (element.tagName.toLowerCase() === 'form')\n return {\n name: 'form',\n reason: 'Element is a form.',\n frame,\n src: element.action,\n invokeReflex: formDriver.invokeReflex\n }\n\n // element targets a frame that is not _self\n if (targetId && targetId !== '_self') {\n frame = document.getElementById(targetId)\n return {\n name: 'frame',\n reason: 'element targets a frame that is not _self',\n frame,\n src: src(element, frame),\n invokeReflex: frameDriver.invokeReflex\n }\n }\n\n // element does NOT target a frame or targets _self and is contained by a frame\n if ((!targetId || targetId === '_self') && frame)\n return {\n name: 'frame',\n reason:\n 'element does NOT target a frame or targets _self and is contained by a frame',\n frame,\n src: src(element, frame),\n invokeReflex: frameDriver.invokeReflex\n }\n\n // element matches one or more of the following conditions\n // - targets _top\n // - does NOT target a frame\n // - is NOT contained by a frame\n return {\n name: 'window',\n reason:\n 'element matches one or more of the following conditions (targets _top, does NOT target a frame, is NOT contained by a frame)',\n frame: null,\n src: src(element),\n invokeReflex: windowDriver.invokeReflex\n }\n}\n\nexport default { find }\n", "import lifecycle from './lifecycle'\n\nlet currentLevel = 'unknown'\n\nconst logLevels = {\n debug: Object.values(lifecycle.events),\n info: Object.values(lifecycle.events),\n warn: [\n lifecycle.events.abort,\n lifecycle.events.clientError,\n lifecycle.events.serverError\n ],\n error: [lifecycle.events.clientError, lifecycle.events.serverError],\n unknown: []\n}\n\nObject.values(lifecycle.events).forEach(name => {\n addEventListener(name, event => {\n if (logLevels[currentLevel].includes(event.type)) {\n const level = currentLevel === 'debug' ? 'log' : currentLevel\n console[level](event.type, event.detail)\n }\n })\n})\n\nexport default {\n get level () {\n return currentLevel\n },\n set level (value) {\n if (!Object.keys(logLevels).includes(value)) value = 'unknown'\n return (currentLevel = value)\n }\n}\n", "function v4 () {\n return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>\n (\n c ^\n (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))\n ).toString(16)\n )\n}\n\nexport default { v4 }\n", "import './turbo'\nimport schema from './schema.js'\nimport activity from './activity'\nimport delegates from './delegates'\nimport drivers from './drivers'\nimport elements from './elements'\nimport lifecycle from './lifecycle'\nimport logger from './logger'\nimport urls from './urls'\nimport uuids from './uuids'\n\nfunction invokeReflex (event) {\n let element\n let payload = {}\n\n try {\n element = elements.findClosestReflex(event.target)\n if (!element) return\n if (!delegates.isRegistered(event.type, element.tagName)) return\n\n const driver = drivers.find(element)\n\n // payload sent to server (also used for lifecycle event.detail)\n payload = {\n id: `reflex-${uuids.v4()}`,\n name: element.dataset.turboReflex,\n driver: driver.name,\n src: driver.src,\n frameId: driver.frame ? driver.frame.id : null,\n elementId: element.id.length > 0 ? element.id : null,\n elementAttributes: elements.buildAttributePayload(element),\n startedAt: new Date().getTime()\n }\n\n activity.add(payload)\n lifecycle.dispatch(lifecycle.events.start, element, payload)\n\n if (driver.name !== 'form') event.preventDefault()\n\n switch (driver.name) {\n case 'form':\n return driver.invokeReflex(element, payload)\n case 'frame':\n return driver.invokeReflex(driver.frame, payload)\n case 'window':\n return driver.invokeReflex(payload)\n }\n } catch (error) {\n lifecycle.dispatch(lifecycle.events.clientError, element, {\n error,\n ...payload\n })\n }\n}\n\n// wire things up and setup defaults for event delegation\ndelegates.handler = invokeReflex\ndelegates.register('change', ['input', 'select', 'textarea'])\ndelegates.register('submit', ['form'])\ndelegates.register('click', ['*'])\n\nexport default {\n schema,\n logger,\n registerEventDelegate: delegates.register,\n get eventDelegates () {\n return { ...delegates.events }\n },\n get lifecycleEvents () {\n return [...Object.values(lifecycle.events)]\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,IAAMA,EAAS,CACb,eAAgB,mBAChB,gBAAiB,mBACnB,EAEOC,EAAQ,CAAE,GAAGD,CAAO,ECL3B,IAAME,EAAS,CAAC,EAEhB,SAASC,EAAKC,EAAS,CACrBF,EAAOE,EAAQ,IAAMA,CACvB,CAEA,SAASC,EAAQC,EAAI,CACnB,OAAOJ,EAAOI,EAChB,CAEA,IAAOC,EAAQ,CACb,IAAAJ,EACA,OAAAE,EACA,IAAI,UAAY,CACd,MAAO,CAAC,GAAG,OAAO,OAAOH,CAAM,CAAC,CAClC,EACA,IAAI,QAAU,CACZ,OAAO,OAAO,KAAKA,CAAM,EAAE,MAC7B,CACF,ECjBA,IAAMM,EAAS,CACb,MAAO,qBACP,QAAS,uBACT,OAAQ,sBACR,MAAO,qBACP,YAAa,4BACb,YAAa,2BACf,EAEA,SAASC,EAAUC,EAAMC,EAAS,SAAUC,EAAS,CAAC,EAAGC,EAAQ,GAAO,CACtE,GAAI,CACFF,EAASA,GAAU,SACnB,IAAMG,EAAQ,IAAI,YAAYJ,EAAM,CAClC,OAAAE,EACA,WAAY,GACZ,QAAS,EACX,CAAC,EACDD,EAAO,cAAcG,CAAK,CAC5B,OAASC,EAAP,CACA,GAAIF,EAAO,MAAME,EACjBN,EAASD,EAAO,YAAaG,EAAQ,CAAE,MAAAI,EAAO,GAAGH,CAAO,EAAG,EAAI,CACjE,CACF,CAEA,SAASI,
|
|
6
|
-
"names": ["schema", "schema_default", "active", "add", "payload", "remove", "id", "activity_default", "events", "dispatch", "name", "target", "detail", "raise", "event", "error", "finish", "activity_default", "lifecycle_default", "findClosestReflex", "element", "schema_default", "findClosestFrame", "assignElementValueToPayload", "payload", "memo", "option", "buildAttributePayload", "attr", "value", "elements_default", "frameSources", "event", "frame", "fetchOptions", "elements_default", "events", "eventListener", "register", "eventName", "tagNames", "isRegistered", "tagName", "delegates_default", "fn", "invokeReflex", "form", "payload", "elements_default", "input", "form_default", "build", "urlString", "payload", "a", "url", "urls_default", "invokeReflex", "frame", "payload", "src", "urls_default", "frame_default", "aborted", "event", "xhr", "lifecycle_default", "errored", "
|
|
3
|
+
"sources": ["../../javascript/schema.js", "../../javascript/activity.js", "../../javascript/lifecycle.js", "../../javascript/elements.js", "../../javascript/renderer.js", "../../javascript/turbo.js", "../../javascript/delegates.js", "../../javascript/drivers/form.js", "../../javascript/urls.js", "../../javascript/drivers/frame.js", "../../javascript/drivers/window.js", "../../javascript/drivers/index.js", "../../javascript/logger.js", "../../javascript/uuids.js", "../../javascript/index.js"],
|
|
4
|
+
"sourcesContent": ["const schema = {\n frameAttribute: 'data-turbo-frame',\n reflexAttribute: 'data-turbo-reflex'\n}\n\nexport default { ...schema }\n", "const active = {}\n\nfunction add (payload) {\n active[payload.id] = payload\n}\n\nfunction remove (id) {\n delete active[id]\n}\n\nexport default {\n add,\n remove,\n get reflexes () {\n return [...Object.values(active)]\n },\n get length () {\n return Object.keys(active).length\n }\n}\n", "import activity from './activity'\n\nconst events = {\n start: 'turbo-reflex:start',\n success: 'turbo-reflex:success',\n finish: 'turbo-reflex:finish',\n abort: 'turbo-reflex:abort',\n clientError: 'turbo-reflex:client-error',\n serverError: 'turbo-reflex:server-error'\n}\n\nfunction dispatch (name, target = document, detail = {}, raise = false) {\n try {\n target = target || document\n const event = new CustomEvent(name, {\n detail,\n cancelable: false,\n bubbles: true\n })\n target.dispatchEvent(event)\n } catch (error) {\n if (raise) throw error\n dispatch(events.clientError, target, { error, ...detail }, true)\n }\n}\n\nfunction dispatchClientError (detail = {}) {\n dispatch(lifecycle.events.clientError, window, detail, true)\n}\n\nfunction finish (event) {\n event.detail.endedAt = new Date().getTime()\n event.detail.milliseconds = event.detail.endedAt - event.detail.startedAt\n setTimeout(() => dispatch(events.finish, event.target, event.detail), 10)\n}\n\naddEventListener(events.serverError, finish)\naddEventListener(events.success, finish)\naddEventListener(events.finish, event => activity.remove(event.detail.id), true)\n\nexport default {\n dispatch,\n dispatchClientError,\n events\n}\n", "import schema from './schema.js'\nimport lifecycle from './lifecycle'\n\nfunction findClosestReflex (element) {\n return element.closest(`[${schema.reflexAttribute}]`)\n}\n\nfunction findClosestFrame (element) {\n return element.closest('turbo-frame')\n}\n\nfunction assignElementValueToPayload (element, payload = {}) {\n if (element.tagName.toLowerCase() !== 'select')\n return (payload.value = element.value)\n\n if (!element.multiple)\n return (payload.value = element.options[element.selectedIndex].value)\n\n payload.values = Array.from(element.options).reduce((memo, option) => {\n if (option.selected) memo.push(option.value)\n return memo\n }, [])\n}\n\nfunction buildAttributePayload (element) {\n // truncate long values to optimize payload size\n // TODO: revisit this decision\n const maxAttributeLength = 100\n const maxValueLength = 500\n\n const payload = Array.from(element.attributes).reduce((memo, attr) => {\n let value = attr.value\n if (typeof value === 'string' && value.length > maxAttributeLength)\n value = value.slice(0, maxAttributeLength) + '...'\n memo[attr.name] = value\n return memo\n }, {})\n\n payload.tag = element.tagName\n payload.checked = element.checked\n payload.disabled = element.disabled\n assignElementValueToPayload(element, payload)\n\n if (\n typeof payload.value === 'string' &&\n payload.value.length > maxValueLength\n )\n payload.value = payload.value.slice(0, maxValueLength) + '...'\n\n delete payload.class\n delete payload[schema.reflexAttribute]\n delete payload[schema.frameAttribute]\n return payload\n}\n\nexport default {\n buildAttributePayload,\n findClosestReflex,\n findClosestFrame,\n get metaElement () {\n return document.getElementById('turbo-reflex')\n },\n get metaElementToken () {\n return document.getElementById('turbo-reflex').getAttribute('content')\n }\n}\n", "function renderDocument (content) {\n const head = '<html'\n const tail = '</html'\n const headIndex = content.indexOf(head)\n const tailIndex = content.lastIndexOf(tail)\n if (headIndex >= 0 && tailIndex >= 0) {\n const html = content.slice(content.indexOf('>', headIndex) + 1, tailIndex)\n document.documentElement.innerHTML = html\n }\n}\n\nfunction renderStreams (content) {\n const head = '<turbo-stream'\n const tail = '</turbo-stream>'\n const headIndex = content.indexOf(head)\n const tailIndex = content.lastIndexOf(tail)\n if (headIndex >= 0 && tailIndex >= 0) {\n const streams = content.slice(headIndex, tailIndex + tail.length)\n document.body.insertAdjacentHTML('beforeend', streams)\n }\n}\n\nexport default { renderDocument, renderStreams }\n", "import elements from './elements'\nimport renderer from './renderer'\nimport lifecycle from './lifecycle'\n\nconst frameSources = {}\n\n// fires before making a turbo HTTP request\naddEventListener('turbo:before-fetch-request', event => {\n const frame = event.target.closest('turbo-frame')\n const { fetchOptions } = event.detail\n fetchOptions.headers['TurboReflex-Token'] = elements.metaElementToken\n})\n\n// fires after receiving a turbo HTTP response\naddEventListener('turbo:before-fetch-response', event => {\n const frame = event.target.closest('turbo-frame')\n const { fetchResponse: response } = event.detail\n\n if (frame) {\n frameSources[frame.id] = frame.src\n\n if (response.header('TurboReflex') === 'true') {\n if (response.statusCode < 200 || response.statusCode > 299) {\n const error = `Server returned a ${response.statusCode} status code! TurboReflex requires 2XX status codes.`\n lifecycle.dispatchClientError({ ...event.detail, error })\n }\n\n if (response.header('TurboReflex-Hijacked') === 'true') {\n event.preventDefault()\n response.responseText.then(content => renderer.renderStreams(content))\n }\n }\n }\n})\n\n// fires when a frame element is navigated and finishes loading\naddEventListener('turbo:frame-load', event => {\n const frame = event.target.closest('turbo-frame')\n frame.dataset.turboReflexSrc =\n frameSources[frame.id] || frame.src || frame.dataset.turboReflexSrc\n delete frameSources[frame.id]\n})\n", "const events = {}\nlet eventListener\n\nfunction register (eventName, tagNames) {\n events[eventName] = tagNames\n document.addEventListener(eventName, eventListener, true)\n}\n\nfunction isRegistered (eventName, tagName) {\n tagName = tagName.toLowerCase()\n return (\n events[eventName].includes(tagName) ||\n (!Object.values(events)\n .flat()\n .includes(tagName) &&\n events[eventName].includes('*'))\n )\n}\n\nexport default {\n events,\n register,\n isRegistered,\n set handler (fn) {\n eventListener = fn\n }\n}\n", "import elements from '../elements'\n\nfunction invokeReflex (form, payload = {}) {\n payload.token = elements.metaElementToken\n const input = document.createElement('input')\n input.type = 'hidden'\n input.name = 'turbo_reflex'\n input.value = JSON.stringify(payload)\n form.appendChild(input)\n}\n\nexport default { invokeReflex }\n", "function build (urlString, payload = {}) {\n const a = document.createElement('a')\n a.href = urlString\n const url = new URL(a)\n url.searchParams.set('turbo_reflex', JSON.stringify(payload))\n return url\n}\n\nexport default { build }\n", "import urls from '../urls'\nimport elements from '../elements'\n\nfunction invokeReflex (frame, payload) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n frame.src = urls.build(src, payload)\n}\n\nexport default { invokeReflex }\n", "import elements from '../elements'\nimport lifecycle from '../lifecycle'\nimport urls from '../urls'\nimport renderer from '../renderer'\n\nfunction aborted (event) {\n const xhr = event.target\n lifecycle.dispatch(lifecycle.events.abort, window, { xhr, ...event.detail })\n}\n\nfunction errored (event) {\n const xhr = event.target\n\n xhr.getResponseHeader('TurboReflex-Hijacked') === 'true'\n ? renderer.renderStreams(xhr.responseText)\n : renderer.renderDocument(xhr.responseText)\n\n const error = `Server returned a ${xhr.status} status code! TurboReflex requires 2XX status codes.`\n lifecycle.dispatchClientError({ xhr, ...event.detail, error })\n}\n\nfunction loaded (event) {\n const xhr = event.target\n if (xhr.status < 200 || xhr.status > 299) return errored(event)\n const content = xhr.responseText\n xhr.getResponseHeader('TurboReflex-Hijacked') === 'true'\n ? renderer.renderStreams(xhr.responseText)\n : renderer.renderDocument(xhr.responseText)\n}\n\nfunction invokeReflex (payload) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n\n try {\n const xhr = new XMLHttpRequest()\n xhr.open('GET', urls.build(src, payload), true)\n xhr.setRequestHeader('TurboReflex-Token', elements.metaElementToken)\n xhr.addEventListener('abort', aborted)\n xhr.addEventListener('error', errored)\n xhr.addEventListener('load', loaded)\n xhr.send()\n } catch (ex) {\n const message = `Unexpected error sending HTTP request! ${ex.message}`\n errored(ex, { detail: { message } })\n }\n}\n\nexport default { invokeReflex }\n", "import elements from '../elements'\nimport formDriver from './form'\nimport frameDriver from './frame'\nimport windowDriver from './window'\n\nfunction src (element, frame) {\n frame = frame || { dataset: {} }\n return (\n element.href || frame.src || frame.dataset.turboReflexSrc || location.href\n )\n}\n\nfunction find (element) {\n let frame = elements.findClosestFrame(element)\n const targetId = element.dataset.turboFrame\n\n if (element.tagName.toLowerCase() === 'form')\n return {\n name: 'form',\n reason: 'Element is a form.',\n frame,\n src: element.action,\n invokeReflex: formDriver.invokeReflex\n }\n\n // element targets a frame that is not _self\n if (targetId && targetId !== '_self') {\n frame = document.getElementById(targetId)\n return {\n name: 'frame',\n reason: 'element targets a frame that is not _self',\n frame,\n src: src(element, frame),\n invokeReflex: frameDriver.invokeReflex\n }\n }\n\n // element does NOT target a frame or targets _self and is contained by a frame\n if ((!targetId || targetId === '_self') && frame)\n return {\n name: 'frame',\n reason:\n 'element does NOT target a frame or targets _self and is contained by a frame',\n frame,\n src: src(element, frame),\n invokeReflex: frameDriver.invokeReflex\n }\n\n // element matches one or more of the following conditions\n // - targets _top\n // - does NOT target a frame\n // - is NOT contained by a frame\n return {\n name: 'window',\n reason:\n 'element matches one or more of the following conditions (targets _top, does NOT target a frame, is NOT contained by a frame)',\n frame: null,\n src: src(element),\n invokeReflex: windowDriver.invokeReflex\n }\n}\n\nexport default { find }\n", "import lifecycle from './lifecycle'\n\nlet currentLevel = 'unknown'\n\nconst logLevels = {\n debug: Object.values(lifecycle.events),\n info: Object.values(lifecycle.events),\n warn: [\n lifecycle.events.abort,\n lifecycle.events.clientError,\n lifecycle.events.serverError\n ],\n error: [lifecycle.events.clientError, lifecycle.events.serverError],\n unknown: []\n}\n\nObject.values(lifecycle.events).forEach(name => {\n addEventListener(name, event => {\n if (logLevels[currentLevel].includes(event.type)) {\n const level = currentLevel === 'debug' ? 'log' : currentLevel\n console[level](event.type, event.detail)\n }\n })\n})\n\nexport default {\n get level () {\n return currentLevel\n },\n set level (value) {\n if (!Object.keys(logLevels).includes(value)) value = 'unknown'\n return (currentLevel = value)\n }\n}\n", "function v4 () {\n return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>\n (\n c ^\n (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))\n ).toString(16)\n )\n}\n\nexport default { v4 }\n", "import './turbo'\nimport schema from './schema.js'\nimport activity from './activity'\nimport delegates from './delegates'\nimport drivers from './drivers'\nimport elements from './elements'\nimport lifecycle from './lifecycle'\nimport logger from './logger'\nimport urls from './urls'\nimport uuids from './uuids'\n\nfunction invokeReflex (event) {\n let element\n let payload = {}\n\n try {\n element = elements.findClosestReflex(event.target)\n if (!element) return\n if (!delegates.isRegistered(event.type, element.tagName)) return\n\n const driver = drivers.find(element)\n\n // payload sent to server (also used for lifecycle event.detail)\n payload = {\n id: `reflex-${uuids.v4()}`,\n name: element.dataset.turboReflex,\n driver: driver.name,\n src: driver.src,\n frameId: driver.frame ? driver.frame.id : null,\n elementId: element.id.length > 0 ? element.id : null,\n elementAttributes: elements.buildAttributePayload(element),\n startedAt: new Date().getTime()\n }\n\n activity.add(payload)\n lifecycle.dispatch(lifecycle.events.start, element, payload)\n\n if (driver.name !== 'form') event.preventDefault()\n\n switch (driver.name) {\n case 'form':\n return driver.invokeReflex(element, payload)\n case 'frame':\n return driver.invokeReflex(driver.frame, payload)\n case 'window':\n return driver.invokeReflex(payload)\n }\n } catch (error) {\n lifecycle.dispatch(lifecycle.events.clientError, element, {\n error,\n ...payload\n })\n }\n}\n\n// wire things up and setup defaults for event delegation\ndelegates.handler = invokeReflex\ndelegates.register('change', ['input', 'select', 'textarea'])\ndelegates.register('submit', ['form'])\ndelegates.register('click', ['*'])\n\nexport default {\n schema,\n logger,\n registerEventDelegate: delegates.register,\n get eventDelegates () {\n return { ...delegates.events }\n },\n get lifecycleEvents () {\n return [...Object.values(lifecycle.events)]\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["schema", "schema_default", "active", "add", "payload", "remove", "id", "activity_default", "events", "dispatch", "name", "target", "detail", "raise", "event", "error", "dispatchClientError", "finish", "activity_default", "lifecycle_default", "findClosestReflex", "element", "schema_default", "findClosestFrame", "assignElementValueToPayload", "payload", "memo", "option", "buildAttributePayload", "attr", "value", "elements_default", "renderDocument", "content", "head", "tail", "headIndex", "tailIndex", "html", "renderStreams", "streams", "renderer_default", "frameSources", "event", "frame", "fetchOptions", "elements_default", "response", "error", "lifecycle_default", "content", "renderer_default", "events", "eventListener", "register", "eventName", "tagNames", "isRegistered", "tagName", "delegates_default", "fn", "invokeReflex", "form", "payload", "elements_default", "input", "form_default", "build", "urlString", "payload", "a", "url", "urls_default", "invokeReflex", "frame", "payload", "src", "urls_default", "frame_default", "aborted", "event", "xhr", "lifecycle_default", "errored", "renderer_default", "error", "loaded", "content", "invokeReflex", "payload", "src", "urls_default", "elements_default", "ex", "message", "window_default", "src", "element", "frame", "find", "elements_default", "targetId", "form_default", "frame_default", "window_default", "drivers_default", "currentLevel", "logLevels", "lifecycle_default", "name", "event", "logger_default", "value", "v4", "c", "uuids_default", "invokeReflex", "event", "element", "payload", "elements_default", "delegates_default", "driver", "drivers_default", "uuids_default", "activity_default", "lifecycle_default", "error", "javascript_default", "schema_default", "logger_default"]
|
|
7
7
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import elements from '../elements'
|
|
2
2
|
import lifecycle from '../lifecycle'
|
|
3
3
|
import urls from '../urls'
|
|
4
|
+
import renderer from '../renderer'
|
|
4
5
|
|
|
5
6
|
function aborted (event) {
|
|
6
7
|
const xhr = event.target
|
|
@@ -9,43 +10,22 @@ function aborted (event) {
|
|
|
9
10
|
|
|
10
11
|
function errored (event) {
|
|
11
12
|
const xhr = event.target
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
},
|
|
20
|
-
true
|
|
21
|
-
)
|
|
13
|
+
|
|
14
|
+
xhr.getResponseHeader('TurboReflex-Hijacked') === 'true'
|
|
15
|
+
? renderer.renderStreams(xhr.responseText)
|
|
16
|
+
: renderer.renderDocument(xhr.responseText)
|
|
17
|
+
|
|
18
|
+
const error = `Server returned a ${xhr.status} status code! TurboReflex requires 2XX status codes.`
|
|
19
|
+
lifecycle.dispatchClientError({ xhr, ...event.detail, error })
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
function loaded (event) {
|
|
25
23
|
const xhr = event.target
|
|
24
|
+
if (xhr.status < 200 || xhr.status > 299) return errored(event)
|
|
26
25
|
const content = xhr.responseText
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (hijacked) {
|
|
31
|
-
const head = '<turbo-stream'
|
|
32
|
-
const tail = '</turbo-stream>'
|
|
33
|
-
const headIndex = content.indexOf(head)
|
|
34
|
-
const tailIndex = content.lastIndexOf(tail)
|
|
35
|
-
if (headIndex >= 0 && tailIndex >= 0) {
|
|
36
|
-
const streams = content.slice(headIndex, tailIndex + tail.length)
|
|
37
|
-
document.body.insertAdjacentHTML('beforeend', streams)
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
const head = '<html'
|
|
41
|
-
const tail = '</html'
|
|
42
|
-
const headIndex = content.indexOf(head)
|
|
43
|
-
const tailIndex = content.lastIndexOf(tail)
|
|
44
|
-
if (headIndex >= 0 && tailIndex >= 0) {
|
|
45
|
-
const html = content.slice(content.indexOf('>', headIndex) + 1, tailIndex)
|
|
46
|
-
document.documentElement.innerHTML = html
|
|
47
|
-
}
|
|
48
|
-
}
|
|
26
|
+
xhr.getResponseHeader('TurboReflex-Hijacked') === 'true'
|
|
27
|
+
? renderer.renderStreams(xhr.responseText)
|
|
28
|
+
: renderer.renderDocument(xhr.responseText)
|
|
49
29
|
}
|
|
50
30
|
|
|
51
31
|
function invokeReflex (payload) {
|
data/app/javascript/lifecycle.js
CHANGED
|
@@ -24,6 +24,10 @@ function dispatch (name, target = document, detail = {}, raise = false) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function dispatchClientError (detail = {}) {
|
|
28
|
+
dispatch(lifecycle.events.clientError, window, detail, true)
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
function finish (event) {
|
|
28
32
|
event.detail.endedAt = new Date().getTime()
|
|
29
33
|
event.detail.milliseconds = event.detail.endedAt - event.detail.startedAt
|
|
@@ -36,5 +40,6 @@ addEventListener(events.finish, event => activity.remove(event.detail.id), true)
|
|
|
36
40
|
|
|
37
41
|
export default {
|
|
38
42
|
dispatch,
|
|
43
|
+
dispatchClientError,
|
|
39
44
|
events
|
|
40
45
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
function renderDocument (content) {
|
|
2
|
+
const head = '<html'
|
|
3
|
+
const tail = '</html'
|
|
4
|
+
const headIndex = content.indexOf(head)
|
|
5
|
+
const tailIndex = content.lastIndexOf(tail)
|
|
6
|
+
if (headIndex >= 0 && tailIndex >= 0) {
|
|
7
|
+
const html = content.slice(content.indexOf('>', headIndex) + 1, tailIndex)
|
|
8
|
+
document.documentElement.innerHTML = html
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function renderStreams (content) {
|
|
13
|
+
const head = '<turbo-stream'
|
|
14
|
+
const tail = '</turbo-stream>'
|
|
15
|
+
const headIndex = content.indexOf(head)
|
|
16
|
+
const tailIndex = content.lastIndexOf(tail)
|
|
17
|
+
if (headIndex >= 0 && tailIndex >= 0) {
|
|
18
|
+
const streams = content.slice(headIndex, tailIndex + tail.length)
|
|
19
|
+
document.body.insertAdjacentHTML('beforeend', streams)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default { renderDocument, renderStreams }
|
data/app/javascript/turbo.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import elements from './elements'
|
|
2
|
+
import renderer from './renderer'
|
|
3
|
+
import lifecycle from './lifecycle'
|
|
2
4
|
|
|
3
5
|
const frameSources = {}
|
|
4
6
|
|
|
@@ -12,7 +14,23 @@ addEventListener('turbo:before-fetch-request', event => {
|
|
|
12
14
|
// fires after receiving a turbo HTTP response
|
|
13
15
|
addEventListener('turbo:before-fetch-response', event => {
|
|
14
16
|
const frame = event.target.closest('turbo-frame')
|
|
15
|
-
|
|
17
|
+
const { fetchResponse: response } = event.detail
|
|
18
|
+
|
|
19
|
+
if (frame) {
|
|
20
|
+
frameSources[frame.id] = frame.src
|
|
21
|
+
|
|
22
|
+
if (response.header('TurboReflex') === 'true') {
|
|
23
|
+
if (response.statusCode < 200 || response.statusCode > 299) {
|
|
24
|
+
const error = `Server returned a ${response.statusCode} status code! TurboReflex requires 2XX status codes.`
|
|
25
|
+
lifecycle.dispatchClientError({ ...event.detail, error })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (response.header('TurboReflex-Hijacked') === 'true') {
|
|
29
|
+
event.preventDefault()
|
|
30
|
+
response.responseText.then(content => renderer.renderStreams(content))
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
16
34
|
})
|
|
17
35
|
|
|
18
36
|
// fires when a frame element is navigated and finishes loading
|
data/lib/turbo_reflex/runner.rb
CHANGED
|
@@ -88,8 +88,10 @@ class TurboReflex::Runner
|
|
|
88
88
|
reflex_instance.public_send reflex_method_name
|
|
89
89
|
hijack_response if reflex_class.should_hijack_response?(reflex_instance, reflex_method_name)
|
|
90
90
|
rescue => e
|
|
91
|
-
response.status = :internal_server_error
|
|
92
91
|
@reflex_errored = true
|
|
92
|
+
reflex_instance.turbo_streams.clear
|
|
93
|
+
response.status = :internal_server_error
|
|
94
|
+
hijack_response
|
|
93
95
|
message = "Error in #{reflex_name}! #{e.inspect}"
|
|
94
96
|
Rails.logger.error message
|
|
95
97
|
append_error_event_to_response_body message
|
|
@@ -102,6 +104,7 @@ class TurboReflex::Runner
|
|
|
102
104
|
end
|
|
103
105
|
|
|
104
106
|
def append_to_response
|
|
107
|
+
response.set_header "TurboReflex", true
|
|
105
108
|
append_turbo_streams_to_response_body
|
|
106
109
|
append_meta_tag_to_response_body
|
|
107
110
|
append_success_event_to_response_body
|
data/lib/turbo_reflex/version.rb
CHANGED
data/package.json
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: turbo_reflex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nate Hopkins (hopsoft)
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-10-
|
|
11
|
+
date: 2022-10-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -350,6 +350,7 @@ files:
|
|
|
350
350
|
- app/javascript/index.js
|
|
351
351
|
- app/javascript/lifecycle.js
|
|
352
352
|
- app/javascript/logger.js
|
|
353
|
+
- app/javascript/renderer.js
|
|
353
354
|
- app/javascript/schema.js
|
|
354
355
|
- app/javascript/turbo.js
|
|
355
356
|
- app/javascript/urls.js
|