hotwire-spark 0.1.9 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04d3314e939e32bc7f34e2d83cf3f09d03ed20aa5628974783882667a639e78b
4
- data.tar.gz: 5d379a4109419edb48274cecebd6e920eca4ae010ca69c9d4f1927d9b934ba54
3
+ metadata.gz: a60c3dbc696c19fcf78bd3812bf58af629f7dfefa67d6274245453fefbbdbf4a
4
+ data.tar.gz: a14f7ad1b6d4071e3b2e274597a069a34a90e59b2ff7e4eaeb1ddbb3ede86994
5
5
  SHA512:
6
- metadata.gz: f6f6f40a7c2e0fa8c5820681787800734a584047d83b59905c7203a318a7293b6819470995da0bc68e9e3712930569d4268285e940384914b1b81b62ff10a2cc
7
- data.tar.gz: 836c7825604bb9c77ab87550ec29cbcf80e1289d0968f12eab0c19ee30ec2d3e56f59814e9a99689b52f6040fe6b09c9f11d4d48f567e84c05e6d4ec41f2cc91
6
+ metadata.gz: 869ea5cbfe198c1a9f88bd11c1941ac5b2f55941b2d702ca60c8f921ade65923dba230fbe0e9b6e5b9f0ff5fb6f76aaad66785aaa975756399d661089c895bcf
7
+ data.tar.gz: 2063ea1ede77efcf9747c1b31615c613f9a8ae633d1bec48b76e00a269ef148201a6888e97083b8356adb36fa9877d0e2dc873771835e167b3ae1dce5609d4ec
data/README.md CHANGED
@@ -24,12 +24,25 @@ That's it!
24
24
 
25
25
  The system will listen for three kinds of changes and will take action depending on each:
26
26
 
27
- * **HTML change:** it fetches the new document body and updates the current body with morphing. It uses [`idiomorph`](https://github.com/bigskysoftware/idiomorph) under the hood.
27
+ * HTML contents
28
+ * CSS
29
+ * Stimulus controllers
30
+
31
+ Depending on your setup, the default behavior will be different.
32
+
33
+ ### Importmaps
34
+
35
+ Importmaps allows for the smoother updates because it supports hot-reloading for Stimulus controllers:
36
+
37
+ * **HTML change:** it fetches the new document body and updates the current body with morphing, then it reloads the Stimulus controllers in the page. It uses [`idiomorph`](https://github.com/bigskysoftware/idiomorph) under the hood.
28
38
  * **CSS change:** it fetches and reloads the stylesheet that changed.
29
39
  * **Stimulus controller change:** it fetches the Stimulus controller that changed and reloads all the controllers in the page.
30
40
 
31
- > [!NOTE]
32
- > Hotwire Spark currently does not support `jsbundling`, only import maps.
41
+ ### JavaScript Bundling
42
+
43
+ * **HTML change:** it reloads the page with a Turbo visit.
44
+ * **CSS change:** it fetches and reloads the stylesheet that changed.
45
+ * **Stimulus controller change:** it reloads the page with a Turbo visit.
33
46
 
34
47
  ## Configuration
35
48
 
@@ -39,13 +52,24 @@ You can set configuration options on your `development.rb`. For example:
39
52
  config.hotwire.spark.html_paths += %w[ lib ]
40
53
  ```
41
54
 
42
- | Name | Description |
43
- |------------------|------------------------------------------------------------------------------------------------------------------------------|
44
- | `html_paths` | Paths where file changes trigger a content refresh. By default: `app/controllers`, `app/helpers`, `app/models`, `app/views`. |
45
- | `css_paths` | Paths where file changes trigger a CSS refresh. By default: `app/assets/stylesheets` or `app/assets/builds` if exists. |
46
- | `stimulus_paths` | Paths where file changes trigger a Stimulus controller refresh. By default: `app/javascript/controllers`. |
47
- | `enabled` | Enable or disable live reloading. By default, it's only enabled in `development`. |
48
- | `logging` | Show logs in the browser console when reloading happens. It's false by default. |
55
+ ### General
56
+
57
+ | Name | Description |
58
+ |-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
59
+ | `enabled` | Enable or disable live reloading. By default, it's only enabled in `development`. |
60
+ | `logging` | Show logs in the browser console when reloading happens. It's false by default. |
61
+ | `html_reload_method` | How to perform reloads when HTML content changes: `:morph` or `:replace`. By default, it is `:morph` and it will morph the `<body>` of the page and reload all the stimulus controllers. Set to `:replace` to reload the page with a regular Turbo navigation that will replace the `<body>` and keep the scroll. |
62
+
63
+ ### Monitored paths
64
+
65
+ | Name | Description |
66
+ |-----------------------|------------------------------------------------------------------------------------------------------------------------------|
67
+ | `html_paths` | Paths where file changes trigger a content refresh. By default: `app/controllers`, `app/helpers`, `app/models`, `app/views`. |
68
+ | `html_extensions` | The extensions to monitor for HTML content changes. By default: `rb`, `erb`. | |
69
+ | `css_paths` | Paths where file changes trigger a CSS refresh. By default: `app/assets/stylesheets` or `app/assets/builds` if exists. |
70
+ | `css_extensions` | The extensions to monitor for CSS changes. By default: `css`. | |
71
+ | `stimulus_paths` | Paths where file changes trigger a Stimulus controller refresh. By default: `app/javascript/controllers`. |
72
+ | `stimulus_extensions` | The extensions to monitor for Stimulus changes. By default: `js`. | |
49
73
 
50
74
  ## License
51
75
 
@@ -1387,7 +1387,7 @@ var HotwireSpark = (function () {
1387
1387
  })();
1388
1388
 
1389
1389
  function log() {
1390
- if (HotwireSpark.config.loggingEnabled) {
1390
+ if (HotwireSpark$1.config.loggingEnabled) {
1391
1391
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1392
1392
  args[_key] = arguments[_key];
1393
1393
  }
@@ -1396,14 +1396,20 @@ var HotwireSpark = (function () {
1396
1396
  }
1397
1397
 
1398
1398
  class StimulusReloader {
1399
- static async reload(filePattern) {
1399
+ static async reload(changedFilePath) {
1400
1400
  const document = await reloadHtmlDocument();
1401
- return new StimulusReloader(document, filePattern).reload();
1401
+ return new StimulusReloader(document, changedFilePath).reload();
1402
1402
  }
1403
- constructor(document) {
1404
- let filePattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : /./;
1403
+ static async reloadAll() {
1404
+ Stimulus.controllers.forEach(controller => {
1405
+ Stimulus.unload(controller.identifier);
1406
+ Stimulus.register(controller.identifier, controller.constructor);
1407
+ });
1408
+ return Promise.resolve();
1409
+ }
1410
+ constructor(document, changedFilePath) {
1405
1411
  this.document = document;
1406
- this.filePattern = filePattern;
1412
+ this.changedFilePath = changedFilePath;
1407
1413
  this.application = window.Stimulus;
1408
1414
  }
1409
1415
  async reload() {
@@ -1424,7 +1430,11 @@ var HotwireSpark = (function () {
1424
1430
  return Object.keys(this.#stimulusPathsByModule).filter(path => path.endsWith("_controller"));
1425
1431
  }
1426
1432
  #shouldReloadController(path) {
1427
- return this.filePattern.test(path);
1433
+ return this.#extractControllerName(path) === this.#changedControllerIdentifier;
1434
+ }
1435
+ get #changedControllerIdentifier() {
1436
+ this.changedControllerIdentifier = this.changedControllerIdentifier || this.#extractControllerName(this.changedFilePath);
1437
+ return this.changedControllerIdentifier;
1428
1438
  }
1429
1439
  get #stimulusPathsByModule() {
1430
1440
  this.pathsByModule = this.pathsByModule || this.#parseImportmapJson();
@@ -1448,7 +1458,7 @@ var HotwireSpark = (function () {
1448
1458
  if (this.#didChangeTriggerAReload) {
1449
1459
  return [];
1450
1460
  } else {
1451
- return this.application.controllers.filter(controller => this.filePattern.test(`${controller.identifier}_controller`));
1461
+ return this.application.controllers.filter(controller => this.#changedControllerIdentifier === controller.identifier);
1452
1462
  }
1453
1463
  }
1454
1464
  get #didChangeTriggerAReload() {
@@ -1458,7 +1468,7 @@ var HotwireSpark = (function () {
1458
1468
  return this.#stimulusPathsByModule[moduleName];
1459
1469
  }
1460
1470
  #extractControllerName(path) {
1461
- return path.replace(/^.*\//, "").replace("_controller", "").replace(/\//g, "--").replace(/_/g, "-");
1471
+ return path.replace(/^\/+/, "").replace(/^controllers\//, "").replace("_controller", "").replace(/\//g, "--").replace(/_/g, "-").replace(/\.js$/, "");
1462
1472
  }
1463
1473
  #registerController(name, module) {
1464
1474
  this.application.unload(name);
@@ -1470,16 +1480,16 @@ var HotwireSpark = (function () {
1470
1480
  }
1471
1481
  }
1472
1482
 
1473
- class HtmlReloader {
1483
+ class MorphHtmlReloader {
1474
1484
  static async reload() {
1475
- return new HtmlReloader().reload();
1485
+ return new MorphHtmlReloader().reload();
1476
1486
  }
1477
1487
  async reload() {
1478
- const reloadedDocument = await this.#reloadHtml();
1479
- await this.#reloadStimulus(reloadedDocument);
1488
+ await this.#reloadHtml();
1489
+ await this.#reloadStimulus();
1480
1490
  }
1481
1491
  async #reloadHtml() {
1482
- log("Reload html...");
1492
+ log("Reload html with morph...");
1483
1493
  const reloadedDocument = await reloadHtmlDocument();
1484
1494
  this.#updateBody(reloadedDocument.body);
1485
1495
  return reloadedDocument;
@@ -1487,8 +1497,8 @@ var HotwireSpark = (function () {
1487
1497
  #updateBody(newBody) {
1488
1498
  Idiomorph.morph(document.body, newBody);
1489
1499
  }
1490
- async #reloadStimulus(reloadedDocument) {
1491
- return new StimulusReloader(reloadedDocument).reload();
1500
+ async #reloadStimulus() {
1501
+ await StimulusReloader.reloadAll();
1492
1502
  }
1493
1503
  }
1494
1504
 
@@ -1548,6 +1558,35 @@ var HotwireSpark = (function () {
1548
1558
  }
1549
1559
  }
1550
1560
 
1561
+ class ReplaceHtmlReloader {
1562
+ static async reload() {
1563
+ return new ReplaceHtmlReloader().reload();
1564
+ }
1565
+ async reload() {
1566
+ await this.#reloadHtml();
1567
+ }
1568
+ async #reloadHtml() {
1569
+ log("Reload html with Turbo...");
1570
+ this.#keepScrollPosition();
1571
+ await this.#visitCurrentPage();
1572
+ }
1573
+ #keepScrollPosition() {
1574
+ document.addEventListener("turbo:before-render", () => {
1575
+ Turbo.navigator.currentVisit.scrolled = true;
1576
+ }, {
1577
+ once: true
1578
+ });
1579
+ }
1580
+ #visitCurrentPage() {
1581
+ return new Promise(resolve => {
1582
+ document.addEventListener("turbo:load", () => resolve(document), {
1583
+ once: true
1584
+ });
1585
+ window.Turbo.visit(window.location);
1586
+ });
1587
+ }
1588
+ }
1589
+
1551
1590
  consumer.subscriptions.create({
1552
1591
  channel: "Hotwire::Spark::Channel"
1553
1592
  }, {
@@ -1566,38 +1605,47 @@ var HotwireSpark = (function () {
1566
1605
  action,
1567
1606
  path
1568
1607
  } = _ref;
1569
- const fileName = assetNameFromPath(path);
1570
1608
  switch (action) {
1571
1609
  case "reload_html":
1572
1610
  return this.reloadHtml();
1573
1611
  case "reload_css":
1574
- return this.reloadCss(fileName);
1612
+ return this.reloadCss(path);
1575
1613
  case "reload_stimulus":
1576
- return this.reloadStimulus(fileName);
1614
+ return this.reloadStimulus(path);
1577
1615
  default:
1578
1616
  throw new Error(`Unknown action: ${action}`);
1579
1617
  }
1580
1618
  },
1581
1619
  reloadHtml() {
1582
- return HtmlReloader.reload();
1620
+ const htmlReloader = HotwireSpark.config.htmlReloadMethod == "morph" ? MorphHtmlReloader : ReplaceHtmlReloader;
1621
+ return htmlReloader.reload();
1583
1622
  },
1584
- reloadCss(fileName) {
1623
+ reloadCss(path) {
1624
+ const fileName = assetNameFromPath(path);
1585
1625
  return CssReloader.reload(new RegExp(fileName));
1586
1626
  },
1587
- reloadStimulus(fileName) {
1588
- return StimulusReloader.reload(new RegExp(fileName));
1627
+ reloadStimulus(path) {
1628
+ return StimulusReloader.reload(path);
1589
1629
  }
1590
1630
  });
1591
1631
 
1592
- const HotwireSpark = {
1632
+ const HotwireSpark$1 = {
1593
1633
  config: {
1594
- loggingEnabled: false
1634
+ loggingEnabled: false,
1635
+ htmlReloadMethod: "morph"
1595
1636
  }
1596
1637
  };
1638
+ const configProperties = {
1639
+ loggingEnabled: "logging",
1640
+ htmlReloadMethod: "html-reload-method"
1641
+ };
1597
1642
  document.addEventListener("DOMContentLoaded", function () {
1598
- HotwireSpark.config.loggingEnabled = getConfigurationProperty("logging");
1643
+ Object.entries(configProperties).forEach(_ref => {
1644
+ let [key, property] = _ref;
1645
+ HotwireSpark$1.config[key] = getConfigurationProperty(property);
1646
+ });
1599
1647
  });
1600
1648
 
1601
- return HotwireSpark;
1649
+ return HotwireSpark$1;
1602
1650
 
1603
1651
  })();
@@ -1,2 +1,2 @@
1
- var HotwireSpark=function(){"use strict";var e={logger:"undefined"!=typeof console?console:void 0,WebSocket:"undefined"!=typeof WebSocket?WebSocket:void 0},t={log(...t){this.enabled&&(t.push(Date.now()),e.logger.log("[ActionCable]",...t))}};const n=()=>(new Date).getTime(),o=e=>(n()-e)/1e3;class i{constructor(e){this.visibilityDidChange=this.visibilityDidChange.bind(this),this.connection=e,this.reconnectAttempts=0}start(){this.isRunning()||(this.startedAt=n(),delete this.stoppedAt,this.startPolling(),addEventListener("visibilitychange",this.visibilityDidChange),t.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`))}stop(){this.isRunning()&&(this.stoppedAt=n(),this.stopPolling(),removeEventListener("visibilitychange",this.visibilityDidChange),t.log("ConnectionMonitor stopped"))}isRunning(){return this.startedAt&&!this.stoppedAt}recordMessage(){this.pingedAt=n()}recordConnect(){this.reconnectAttempts=0,delete this.disconnectedAt,t.log("ConnectionMonitor recorded connect")}recordDisconnect(){this.disconnectedAt=n(),t.log("ConnectionMonitor recorded disconnect")}startPolling(){this.stopPolling(),this.poll()}stopPolling(){clearTimeout(this.pollTimeout)}poll(){this.pollTimeout=setTimeout((()=>{this.reconnectIfStale(),this.poll()}),this.getPollInterval())}getPollInterval(){const{staleThreshold:e,reconnectionBackoffRate:t}=this.constructor;return 1e3*e*Math.pow(1+t,Math.min(this.reconnectAttempts,10))*(1+(0===this.reconnectAttempts?1:t)*Math.random())}reconnectIfStale(){this.connectionIsStale()&&(t.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${o(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`),this.reconnectAttempts++,this.disconnectedRecently()?t.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${o(this.disconnectedAt)} s`):(t.log("ConnectionMonitor reopening"),this.connection.reopen()))}get refreshedAt(){return this.pingedAt?this.pingedAt:this.startedAt}connectionIsStale(){return o(this.refreshedAt)>this.constructor.staleThreshold}disconnectedRecently(){return this.disconnectedAt&&o(this.disconnectedAt)<this.constructor.staleThreshold}visibilityDidChange(){"visible"===document.visibilityState&&setTimeout((()=>{!this.connectionIsStale()&&this.connection.isOpen()||(t.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`),this.connection.reopen())}),200)}}i.staleThreshold=6,i.reconnectionBackoffRate=.15;var r={message_types:{welcome:"welcome",disconnect:"disconnect",ping:"ping",confirmation:"confirm_subscription",rejection:"reject_subscription"},disconnect_reasons:{unauthorized:"unauthorized",invalid_request:"invalid_request",server_restart:"server_restart",remote:"remote"},default_mount_path:"/cable",protocols:["actioncable-v1-json","actioncable-unsupported"]};const{message_types:s,protocols:l}=r,c=l.slice(0,l.length-1),a=[].indexOf;class u{constructor(e){this.open=this.open.bind(this),this.consumer=e,this.subscriptions=this.consumer.subscriptions,this.monitor=new i(this),this.disconnected=!0}send(e){return!!this.isOpen()&&(this.webSocket.send(JSON.stringify(e)),!0)}open(){if(this.isActive())return t.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`),!1;{const n=[...l,...this.consumer.subprotocols||[]];return t.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${n}`),this.webSocket&&this.uninstallEventHandlers(),this.webSocket=new e.WebSocket(this.consumer.url,n),this.installEventHandlers(),this.monitor.start(),!0}}close({allowReconnect:e}={allowReconnect:!0}){if(e||this.monitor.stop(),this.isOpen())return this.webSocket.close()}reopen(){if(t.log(`Reopening WebSocket, current state is ${this.getState()}`),!this.isActive())return this.open();try{return this.close()}catch(e){t.log("Failed to reopen WebSocket",e)}finally{t.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`),setTimeout(this.open,this.constructor.reopenDelay)}}getProtocol(){if(this.webSocket)return this.webSocket.protocol}isOpen(){return this.isState("open")}isActive(){return this.isState("open","connecting")}triedToReconnect(){return this.monitor.reconnectAttempts>0}isProtocolSupported(){return a.call(c,this.getProtocol())>=0}isState(...e){return a.call(e,this.getState())>=0}getState(){if(this.webSocket)for(let t in e.WebSocket)if(e.WebSocket[t]===this.webSocket.readyState)return t.toLowerCase();return null}installEventHandlers(){for(let e in this.events){const t=this.events[e].bind(this);this.webSocket[`on${e}`]=t}}uninstallEventHandlers(){for(let e in this.events)this.webSocket[`on${e}`]=function(){}}}u.reopenDelay=500,u.prototype.events={message(e){if(!this.isProtocolSupported())return;const{identifier:n,message:o,reason:i,reconnect:r,type:l}=JSON.parse(e.data);switch(this.monitor.recordMessage(),l){case s.welcome:return this.triedToReconnect()&&(this.reconnectAttempted=!0),this.monitor.recordConnect(),this.subscriptions.reload();case s.disconnect:return t.log(`Disconnecting. Reason: ${i}`),this.close({allowReconnect:r});case s.ping:return null;case s.confirmation:return this.subscriptions.confirmSubscription(n),this.reconnectAttempted?(this.reconnectAttempted=!1,this.subscriptions.notify(n,"connected",{reconnected:!0})):this.subscriptions.notify(n,"connected",{reconnected:!1});case s.rejection:return this.subscriptions.reject(n);default:return this.subscriptions.notify(n,"received",o)}},open(){if(t.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`),this.disconnected=!1,!this.isProtocolSupported())return t.log("Protocol is unsupported. Stopping monitor and disconnecting."),this.close({allowReconnect:!1})},close(e){if(t.log("WebSocket onclose event"),!this.disconnected)return this.disconnected=!0,this.monitor.recordDisconnect(),this.subscriptions.notifyAll("disconnected",{willAttemptReconnect:this.monitor.isRunning()})},error(){t.log("WebSocket onerror event")}};class d{constructor(e,t={},n){this.consumer=e,this.identifier=JSON.stringify(t),function(e,t){if(null!=t)for(let n in t){const o=t[n];e[n]=o}}(this,n)}perform(e,t={}){return t.action=e,this.send(t)}send(e){return this.consumer.send({command:"message",identifier:this.identifier,data:JSON.stringify(e)})}unsubscribe(){return this.consumer.subscriptions.remove(this)}}class h{constructor(e){this.subscriptions=e,this.pendingSubscriptions=[]}guarantee(e){-1==this.pendingSubscriptions.indexOf(e)?(t.log(`SubscriptionGuarantor guaranteeing ${e.identifier}`),this.pendingSubscriptions.push(e)):t.log(`SubscriptionGuarantor already guaranteeing ${e.identifier}`),this.startGuaranteeing()}forget(e){t.log(`SubscriptionGuarantor forgetting ${e.identifier}`),this.pendingSubscriptions=this.pendingSubscriptions.filter((t=>t!==e))}startGuaranteeing(){this.stopGuaranteeing(),this.retrySubscribing()}stopGuaranteeing(){clearTimeout(this.retryTimeout)}retrySubscribing(){this.retryTimeout=setTimeout((()=>{this.subscriptions&&"function"==typeof this.subscriptions.subscribe&&this.pendingSubscriptions.map((e=>{t.log(`SubscriptionGuarantor resubscribing ${e.identifier}`),this.subscriptions.subscribe(e)}))}),500)}}class p{constructor(e){this.consumer=e,this.guarantor=new h(this),this.subscriptions=[]}create(e,t){const n="object"==typeof e?e:{channel:e},o=new d(this.consumer,n,t);return this.add(o)}add(e){return this.subscriptions.push(e),this.consumer.ensureActiveConnection(),this.notify(e,"initialized"),this.subscribe(e),e}remove(e){return this.forget(e),this.findAll(e.identifier).length||this.sendCommand(e,"unsubscribe"),e}reject(e){return this.findAll(e).map((e=>(this.forget(e),this.notify(e,"rejected"),e)))}forget(e){return this.guarantor.forget(e),this.subscriptions=this.subscriptions.filter((t=>t!==e)),e}findAll(e){return this.subscriptions.filter((t=>t.identifier===e))}reload(){return this.subscriptions.map((e=>this.subscribe(e)))}notifyAll(e,...t){return this.subscriptions.map((n=>this.notify(n,e,...t)))}notify(e,t,...n){let o;return o="string"==typeof e?this.findAll(e):[e],o.map((e=>"function"==typeof e[t]?e[t](...n):void 0))}subscribe(e){this.sendCommand(e,"subscribe")&&this.guarantor.guarantee(e)}confirmSubscription(e){t.log(`Subscription confirmed ${e}`),this.findAll(e).map((e=>this.guarantor.forget(e)))}sendCommand(e,t){const{identifier:n}=e;return this.consumer.send({command:t,identifier:n})}}class f{constructor(e){this._url=e,this.subscriptions=new p(this),this.connection=new u(this),this.subprotocols=[]}get url(){return function(e){"function"==typeof e&&(e=e());if(e&&!/^wss?:/i.test(e)){const t=document.createElement("a");return t.href=e,t.href=t.href,t.protocol=t.protocol.replace("http","ws"),t.href}return e}(this._url)}send(e){return this.connection.send(e)}connect(){return this.connection.open()}disconnect(){return this.connection.close({allowReconnect:!1})}ensureActiveConnection(){if(!this.connection.isActive())return this.connection.open()}addSubProtocol(e){this.subprotocols=[...this.subprotocols,e]}}var m=function(e=function(e){const t=document.head.querySelector(`meta[name='action-cable-${e}']`);if(t)return t.getAttribute("content")}("url")||r.default_mount_path){return new f(e)}("/hotwire-spark");function g(e){return e.replace(/-[a-z0-9]+\.(\w+)(\?.*)?$/,".$1")}function b(e,t){const n=new URL(e,window.location.origin);return Object.entries(t).forEach((e=>{let[t,o]=e;n.searchParams.set(t,o)})),n.toString()}function v(e){return b(e,{reload:Date.now()})}async function y(){let e=v(b(window.location.href,{hotwire_spark:"true"}));const t=await fetch(e,{headers:{Accept:"text/html"}});if(!t.ok)throw new Error(`${t.status} when fetching ${e}`);const n=await t.text();return(new DOMParser).parseFromString(n,"text/html")}var S=function(){let e=new Set,t={morphStyle:"outerHTML",callbacks:{beforeNodeAdded:a,afterNodeAdded:a,beforeNodeMorphed:a,afterNodeMorphed:a,beforeNodeRemoved:a,afterNodeRemoved:a,beforeAttributeUpdated:a},head:{style:"merge",shouldPreserve:function(e){return"true"===e.getAttribute("im-preserve")},shouldReAppend:function(e){return"true"===e.getAttribute("im-re-append")},shouldRemove:a,afterHeadMorphed:a}};function n(e,t,o){if(o.head.block){let i=e.querySelector("head"),r=t.querySelector("head");if(i&&r){let s=c(r,i,o);return void Promise.all(s).then((function(){n(e,t,Object.assign(o,{head:{block:!1,ignore:!0}}))}))}}if("innerHTML"===o.morphStyle)return r(t,e,o),e.children;if("outerHTML"===o.morphStyle||null==o.morphStyle){let n=function(e,t,n){let o;o=e.firstChild;let i=o,r=0;for(;o;){let e=m(o,t,n);e>r&&(i=o,r=e),o=o.nextSibling}return i}(t,e,o),r=n?.previousSibling,s=n?.nextSibling,l=i(e,n,o);return n?function(e,t,n){let o=[],i=[];for(;null!=e;)o.push(e),e=e.previousSibling;for(;o.length>0;){let e=o.pop();i.push(e),t.parentElement.insertBefore(e,t)}i.push(t);for(;null!=n;)o.push(n),i.push(n),n=n.nextSibling;for(;o.length>0;)t.parentElement.insertBefore(o.pop(),t.nextSibling);return i}(r,l,s):[]}throw"Do not understand how to morph style "+o.morphStyle}function o(e,t){return t.ignoreActiveValue&&e===document.activeElement}function i(e,t,n){if(!n.ignoreActive||e!==document.activeElement)return null==t?!1===n.callbacks.beforeNodeRemoved(e)?e:(e.remove(),n.callbacks.afterNodeRemoved(e),null):d(e,t)?(!1===n.callbacks.beforeNodeMorphed(e,t)||(e instanceof HTMLHeadElement&&n.head.ignore||(e instanceof HTMLHeadElement&&"morph"!==n.head.style?c(t,e,n):(!function(e,t,n){let i=e.nodeType;if(1===i){const o=e.attributes,i=t.attributes;for(const e of o)s(e.name,t,"update",n)||t.getAttribute(e.name)!==e.value&&t.setAttribute(e.name,e.value);for(let o=i.length-1;0<=o;o--){const r=i[o];s(r.name,t,"remove",n)||(e.hasAttribute(r.name)||t.removeAttribute(r.name))}}8!==i&&3!==i||t.nodeValue!==e.nodeValue&&(t.nodeValue=e.nodeValue);o(t,n)||function(e,t,n){if(e instanceof HTMLInputElement&&t instanceof HTMLInputElement&&"file"!==e.type){let o=e.value,i=t.value;l(e,t,"checked",n),l(e,t,"disabled",n),e.hasAttribute("value")?o!==i&&(s("value",t,"update",n)||(t.setAttribute("value",o),t.value=o)):s("value",t,"remove",n)||(t.value="",t.removeAttribute("value"))}else if(e instanceof HTMLOptionElement)l(e,t,"selected",n);else if(e instanceof HTMLTextAreaElement&&t instanceof HTMLTextAreaElement){let o=e.value,i=t.value;if(s("value",t,"update",n))return;o!==i&&(t.value=o),t.firstChild&&t.firstChild.nodeValue!==o&&(t.firstChild.nodeValue=o)}}(e,t,n)}(t,e,n),o(e,n)||r(t,e,n))),n.callbacks.afterNodeMorphed(e,t)),e):!1===n.callbacks.beforeNodeRemoved(e)||!1===n.callbacks.beforeNodeAdded(t)?e:(e.parentElement.replaceChild(t,e),n.callbacks.afterNodeAdded(t),n.callbacks.afterNodeRemoved(e),t)}function r(e,t,n){let o,r=e.firstChild,s=t.firstChild;for(;r;){if(o=r,r=o.nextSibling,null==s){if(!1===n.callbacks.beforeNodeAdded(o))return;t.appendChild(o),n.callbacks.afterNodeAdded(o),y(n,o);continue}if(u(o,s,n)){i(s,o,n),s=s.nextSibling,y(n,o);continue}let l=p(e,t,o,s,n);if(l){s=h(s,l,n),i(l,o,n),y(n,o);continue}let c=f(e,t,o,s,n);if(c)s=h(s,c,n),i(c,o,n),y(n,o);else{if(!1===n.callbacks.beforeNodeAdded(o))return;t.insertBefore(o,s),n.callbacks.afterNodeAdded(o),y(n,o)}}for(;null!==s;){let e=s;s=s.nextSibling,g(e,n)}}function s(e,t,n,o){return!("value"!==e||!o.ignoreActiveValue||t!==document.activeElement)||!1===o.callbacks.beforeAttributeUpdated(e,t,n)}function l(e,t,n,o){if(e[n]!==t[n]){let i=s(n,t,"update",o);i||(t[n]=e[n]),e[n]?i||t.setAttribute(n,e[n]):s(n,t,"remove",o)||t.removeAttribute(n)}}function c(e,t,n){let o=[],i=[],r=[],s=[],l=n.head.style,c=new Map;for(const t of e.children)c.set(t.outerHTML,t);for(const e of t.children){let t=c.has(e.outerHTML),o=n.head.shouldReAppend(e),a=n.head.shouldPreserve(e);t||a?o?i.push(e):(c.delete(e.outerHTML),r.push(e)):"append"===l?o&&(i.push(e),s.push(e)):!1!==n.head.shouldRemove(e)&&i.push(e)}s.push(...c.values());let a=[];for(const e of s){let i=document.createRange().createContextualFragment(e.outerHTML).firstChild;if(!1!==n.callbacks.beforeNodeAdded(i)){if(i.href||i.src){let e=null,t=new Promise((function(t){e=t}));i.addEventListener("load",(function(){e()})),a.push(t)}t.appendChild(i),n.callbacks.afterNodeAdded(i),o.push(i)}}for(const e of i)!1!==n.callbacks.beforeNodeRemoved(e)&&(t.removeChild(e),n.callbacks.afterNodeRemoved(e));return n.head.afterHeadMorphed(t,{added:o,kept:r,removed:i}),a}function a(){}function u(e,t,n){return null!=e&&null!=t&&(e.nodeType===t.nodeType&&e.tagName===t.tagName&&(""!==e.id&&e.id===t.id||S(n,e,t)>0))}function d(e,t){return null!=e&&null!=t&&(e.nodeType===t.nodeType&&e.tagName===t.tagName)}function h(e,t,n){for(;e!==t;){let t=e;e=e.nextSibling,g(t,n)}return y(n,t),t.nextSibling}function p(e,t,n,o,i){let r=S(i,n,t);if(r>0){let t=o,s=0;for(;null!=t;){if(u(n,t,i))return t;if(s+=S(i,t,e),s>r)return null;t=t.nextSibling}}return null}function f(e,t,n,o,i){let r=o,s=n.nextSibling,l=0;for(;null!=r;){if(S(i,r,e)>0)return null;if(d(n,r))return r;if(d(s,r)&&(l++,s=s.nextSibling,l>=2))return null;r=r.nextSibling}return r}function m(e,t,n){return d(e,t)?.5+S(n,e,t):0}function g(e,t){y(t,e),!1!==t.callbacks.beforeNodeRemoved(e)&&(e.remove(),t.callbacks.afterNodeRemoved(e))}function b(e,t){return!e.deadIds.has(t)}function v(t,n,o){return(t.idMap.get(o)||e).has(n)}function y(t,n){let o=t.idMap.get(n)||e;for(const e of o)t.deadIds.add(e)}function S(t,n,o){let i=t.idMap.get(n)||e,r=0;for(const e of i)b(t,e)&&v(t,e,o)&&++r;return r}function A(e,t){let n=e.parentElement,o=e.querySelectorAll("[id]");for(const e of o){let o=e;for(;o!==n&&null!=o;){let n=t.get(o);null==n&&(n=new Set,t.set(o,n)),n.add(e.id),o=o.parentElement}}}function w(e,t){let n=new Map;return A(e,n),A(t,n),n}return{morph:function(e,o,i={}){e instanceof Document&&(e=e.documentElement),"string"==typeof o&&(o=function(e){let t=new DOMParser,n=e.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim,"");if(n.match(/<\/html>/)||n.match(/<\/head>/)||n.match(/<\/body>/)){let o=t.parseFromString(e,"text/html");if(n.match(/<\/html>/))return o.generatedByIdiomorph=!0,o;{let e=o.firstChild;return e?(e.generatedByIdiomorph=!0,e):null}}{let n=t.parseFromString("<body><template>"+e+"</template></body>","text/html").body.querySelector("template").content;return n.generatedByIdiomorph=!0,n}}(o));let r=function(e){if(null==e){return document.createElement("div")}if(e.generatedByIdiomorph)return e;if(e instanceof Node){const t=document.createElement("div");return t.append(e),t}{const t=document.createElement("div");for(const n of[...e])t.append(n);return t}}(o),s=function(e,n,o){return o=function(e){let n={};return Object.assign(n,t),Object.assign(n,e),n.callbacks={},Object.assign(n.callbacks,t.callbacks),Object.assign(n.callbacks,e.callbacks),n.head={},Object.assign(n.head,t.head),Object.assign(n.head,e.head),n}(o),{target:e,newContent:n,config:o,morphStyle:o.morphStyle,ignoreActive:o.ignoreActive,ignoreActiveValue:o.ignoreActiveValue,idMap:w(e,n),deadIds:new Set,callbacks:o.callbacks,head:o.head}}(e,r,i);return n(e,r,s)},defaults:t}}();function A(){if(R.config.loggingEnabled){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];console.log("[hotwire_spark]",...t)}}class w{static async reload(e){const t=await y();return new w(t,e).reload()}constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:/./;this.document=e,this.filePattern=t,this.application=window.Stimulus}async reload(){A("Reload Stimulus controllers..."),this.application.stop(),await this.#e(),this.#t(),this.application.start()}async#e(){await Promise.all(this.#n.map((async e=>this.#o(e))))}get#n(){return this.controllerPathsToReload=this.controllerPathsToReload||this.#i.filter((e=>this.#r(e))),this.controllerPathsToReload}get#i(){return Object.keys(this.#s).filter((e=>e.endsWith("_controller")))}#r(e){return this.filePattern.test(e)}get#s(){return this.pathsByModule=this.pathsByModule||this.#l(),this.pathsByModule}#l(){const e=this.document.querySelector("script[type=importmap]");return JSON.parse(e.text).imports}async#o(e){A(`\t${e}`);const t=this.#c(e),n=v(this.#a(e)),o=await import(n);this.#u(t,o)}#t(){this.#d.forEach((e=>this.#h(e.identifier)))}get#d(){return this.#p?[]:this.application.controllers.filter((e=>this.filePattern.test(`${e.identifier}_controller`)))}get#p(){return this.#n.length>0}#a(e){return this.#s[e]}#c(e){return e.replace(/^.*\//,"").replace("_controller","").replace(/\//g,"--").replace(/_/g,"-")}#u(e,t){this.application.unload(e),this.application.register(e,t.default)}#h(e){A(`\tRemoving controller ${e}`),this.application.unload(e)}}class k{static async reload(){return(new k).reload()}async reload(){const e=await this.#f();await this.#m(e)}async#f(){A("Reload html...");const e=await y();return this.#g(e.body),e}#g(e){S.morph(document.body,e)}async#m(e){return new w(e).reload()}}class C{static async reload(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return new C(...t).reload()}constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:/./;this.filePattern=e}async reload(){A("Reload css..."),await Promise.all(await this.#b())}async#b(){return(await this.#v()).map((e=>this.#y(e)))}async#v(){const e=await y();return Array.from(e.head.querySelectorAll("link[rel='stylesheet']"))}#y(e){return this.#S(e)?this.#A(e):Promise.resolve()}#S(e){return this.filePattern.test(e.getAttribute("href"))}async#A(e){return new Promise((t=>{const n=e.getAttribute("href"),o=this.#w(e)||this.#k(e);o.setAttribute("href",v(e.getAttribute("href"))),o.onload=()=>{A(`\t${n}`),t()}}))}#w(e){return this.#C.find((t=>g(e.href)===g(t.href)))}get#C(){return Array.from(document.querySelectorAll("link[rel='stylesheet']"))}#k(e){return document.head.append(e),e}}m.subscriptions.create({channel:"Hotwire::Spark::Channel"},{connected(){document.body.setAttribute("data-hotwire-spark-ready","")},async received(e){try{await this.dispatch(e)}catch(t){console.log(`Error on ${e.action}`,t)}},dispatch(e){let{action:t,path:n}=e;const o=function(e){return e.split("/").pop().split(".")[0]}(n);switch(t){case"reload_html":return this.reloadHtml();case"reload_css":return this.reloadCss(o);case"reload_stimulus":return this.reloadStimulus(o);default:throw new Error(`Unknown action: ${t}`)}},reloadHtml:()=>k.reload(),reloadCss:e=>C.reload(new RegExp(e)),reloadStimulus:e=>w.reload(new RegExp(e))});const R={config:{loggingEnabled:!1}};return document.addEventListener("DOMContentLoaded",(function(){var e;R.config.loggingEnabled=(e="logging",document.querySelector(`meta[name="hotwire-spark:${e}"]`)?.content)})),R}();
1
+ var HotwireSpark=function(){"use strict";var e={logger:"undefined"!=typeof console?console:void 0,WebSocket:"undefined"!=typeof WebSocket?WebSocket:void 0},t={log(...t){this.enabled&&(t.push(Date.now()),e.logger.log("[ActionCable]",...t))}};const n=()=>(new Date).getTime(),o=e=>(n()-e)/1e3;class i{constructor(e){this.visibilityDidChange=this.visibilityDidChange.bind(this),this.connection=e,this.reconnectAttempts=0}start(){this.isRunning()||(this.startedAt=n(),delete this.stoppedAt,this.startPolling(),addEventListener("visibilitychange",this.visibilityDidChange),t.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`))}stop(){this.isRunning()&&(this.stoppedAt=n(),this.stopPolling(),removeEventListener("visibilitychange",this.visibilityDidChange),t.log("ConnectionMonitor stopped"))}isRunning(){return this.startedAt&&!this.stoppedAt}recordMessage(){this.pingedAt=n()}recordConnect(){this.reconnectAttempts=0,delete this.disconnectedAt,t.log("ConnectionMonitor recorded connect")}recordDisconnect(){this.disconnectedAt=n(),t.log("ConnectionMonitor recorded disconnect")}startPolling(){this.stopPolling(),this.poll()}stopPolling(){clearTimeout(this.pollTimeout)}poll(){this.pollTimeout=setTimeout((()=>{this.reconnectIfStale(),this.poll()}),this.getPollInterval())}getPollInterval(){const{staleThreshold:e,reconnectionBackoffRate:t}=this.constructor;return 1e3*e*Math.pow(1+t,Math.min(this.reconnectAttempts,10))*(1+(0===this.reconnectAttempts?1:t)*Math.random())}reconnectIfStale(){this.connectionIsStale()&&(t.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${o(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`),this.reconnectAttempts++,this.disconnectedRecently()?t.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${o(this.disconnectedAt)} s`):(t.log("ConnectionMonitor reopening"),this.connection.reopen()))}get refreshedAt(){return this.pingedAt?this.pingedAt:this.startedAt}connectionIsStale(){return o(this.refreshedAt)>this.constructor.staleThreshold}disconnectedRecently(){return this.disconnectedAt&&o(this.disconnectedAt)<this.constructor.staleThreshold}visibilityDidChange(){"visible"===document.visibilityState&&setTimeout((()=>{!this.connectionIsStale()&&this.connection.isOpen()||(t.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`),this.connection.reopen())}),200)}}i.staleThreshold=6,i.reconnectionBackoffRate=.15;var r={message_types:{welcome:"welcome",disconnect:"disconnect",ping:"ping",confirmation:"confirm_subscription",rejection:"reject_subscription"},disconnect_reasons:{unauthorized:"unauthorized",invalid_request:"invalid_request",server_restart:"server_restart",remote:"remote"},default_mount_path:"/cable",protocols:["actioncable-v1-json","actioncable-unsupported"]};const{message_types:s,protocols:l}=r,c=l.slice(0,l.length-1),a=[].indexOf;class d{constructor(e){this.open=this.open.bind(this),this.consumer=e,this.subscriptions=this.consumer.subscriptions,this.monitor=new i(this),this.disconnected=!0}send(e){return!!this.isOpen()&&(this.webSocket.send(JSON.stringify(e)),!0)}open(){if(this.isActive())return t.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`),!1;{const n=[...l,...this.consumer.subprotocols||[]];return t.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${n}`),this.webSocket&&this.uninstallEventHandlers(),this.webSocket=new e.WebSocket(this.consumer.url,n),this.installEventHandlers(),this.monitor.start(),!0}}close({allowReconnect:e}={allowReconnect:!0}){if(e||this.monitor.stop(),this.isOpen())return this.webSocket.close()}reopen(){if(t.log(`Reopening WebSocket, current state is ${this.getState()}`),!this.isActive())return this.open();try{return this.close()}catch(e){t.log("Failed to reopen WebSocket",e)}finally{t.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`),setTimeout(this.open,this.constructor.reopenDelay)}}getProtocol(){if(this.webSocket)return this.webSocket.protocol}isOpen(){return this.isState("open")}isActive(){return this.isState("open","connecting")}triedToReconnect(){return this.monitor.reconnectAttempts>0}isProtocolSupported(){return a.call(c,this.getProtocol())>=0}isState(...e){return a.call(e,this.getState())>=0}getState(){if(this.webSocket)for(let t in e.WebSocket)if(e.WebSocket[t]===this.webSocket.readyState)return t.toLowerCase();return null}installEventHandlers(){for(let e in this.events){const t=this.events[e].bind(this);this.webSocket[`on${e}`]=t}}uninstallEventHandlers(){for(let e in this.events)this.webSocket[`on${e}`]=function(){}}}d.reopenDelay=500,d.prototype.events={message(e){if(!this.isProtocolSupported())return;const{identifier:n,message:o,reason:i,reconnect:r,type:l}=JSON.parse(e.data);switch(this.monitor.recordMessage(),l){case s.welcome:return this.triedToReconnect()&&(this.reconnectAttempted=!0),this.monitor.recordConnect(),this.subscriptions.reload();case s.disconnect:return t.log(`Disconnecting. Reason: ${i}`),this.close({allowReconnect:r});case s.ping:return null;case s.confirmation:return this.subscriptions.confirmSubscription(n),this.reconnectAttempted?(this.reconnectAttempted=!1,this.subscriptions.notify(n,"connected",{reconnected:!0})):this.subscriptions.notify(n,"connected",{reconnected:!1});case s.rejection:return this.subscriptions.reject(n);default:return this.subscriptions.notify(n,"received",o)}},open(){if(t.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`),this.disconnected=!1,!this.isProtocolSupported())return t.log("Protocol is unsupported. Stopping monitor and disconnecting."),this.close({allowReconnect:!1})},close(e){if(t.log("WebSocket onclose event"),!this.disconnected)return this.disconnected=!0,this.monitor.recordDisconnect(),this.subscriptions.notifyAll("disconnected",{willAttemptReconnect:this.monitor.isRunning()})},error(){t.log("WebSocket onerror event")}};class u{constructor(e,t={},n){this.consumer=e,this.identifier=JSON.stringify(t),function(e,t){if(null!=t)for(let n in t){const o=t[n];e[n]=o}}(this,n)}perform(e,t={}){return t.action=e,this.send(t)}send(e){return this.consumer.send({command:"message",identifier:this.identifier,data:JSON.stringify(e)})}unsubscribe(){return this.consumer.subscriptions.remove(this)}}class h{constructor(e){this.subscriptions=e,this.pendingSubscriptions=[]}guarantee(e){-1==this.pendingSubscriptions.indexOf(e)?(t.log(`SubscriptionGuarantor guaranteeing ${e.identifier}`),this.pendingSubscriptions.push(e)):t.log(`SubscriptionGuarantor already guaranteeing ${e.identifier}`),this.startGuaranteeing()}forget(e){t.log(`SubscriptionGuarantor forgetting ${e.identifier}`),this.pendingSubscriptions=this.pendingSubscriptions.filter((t=>t!==e))}startGuaranteeing(){this.stopGuaranteeing(),this.retrySubscribing()}stopGuaranteeing(){clearTimeout(this.retryTimeout)}retrySubscribing(){this.retryTimeout=setTimeout((()=>{this.subscriptions&&"function"==typeof this.subscriptions.subscribe&&this.pendingSubscriptions.map((e=>{t.log(`SubscriptionGuarantor resubscribing ${e.identifier}`),this.subscriptions.subscribe(e)}))}),500)}}class p{constructor(e){this.consumer=e,this.guarantor=new h(this),this.subscriptions=[]}create(e,t){const n="object"==typeof e?e:{channel:e},o=new u(this.consumer,n,t);return this.add(o)}add(e){return this.subscriptions.push(e),this.consumer.ensureActiveConnection(),this.notify(e,"initialized"),this.subscribe(e),e}remove(e){return this.forget(e),this.findAll(e.identifier).length||this.sendCommand(e,"unsubscribe"),e}reject(e){return this.findAll(e).map((e=>(this.forget(e),this.notify(e,"rejected"),e)))}forget(e){return this.guarantor.forget(e),this.subscriptions=this.subscriptions.filter((t=>t!==e)),e}findAll(e){return this.subscriptions.filter((t=>t.identifier===e))}reload(){return this.subscriptions.map((e=>this.subscribe(e)))}notifyAll(e,...t){return this.subscriptions.map((n=>this.notify(n,e,...t)))}notify(e,t,...n){let o;return o="string"==typeof e?this.findAll(e):[e],o.map((e=>"function"==typeof e[t]?e[t](...n):void 0))}subscribe(e){this.sendCommand(e,"subscribe")&&this.guarantor.guarantee(e)}confirmSubscription(e){t.log(`Subscription confirmed ${e}`),this.findAll(e).map((e=>this.guarantor.forget(e)))}sendCommand(e,t){const{identifier:n}=e;return this.consumer.send({command:t,identifier:n})}}class f{constructor(e){this._url=e,this.subscriptions=new p(this),this.connection=new d(this),this.subprotocols=[]}get url(){return function(e){"function"==typeof e&&(e=e());if(e&&!/^wss?:/i.test(e)){const t=document.createElement("a");return t.href=e,t.href=t.href,t.protocol=t.protocol.replace("http","ws"),t.href}return e}(this._url)}send(e){return this.connection.send(e)}connect(){return this.connection.open()}disconnect(){return this.connection.close({allowReconnect:!1})}ensureActiveConnection(){if(!this.connection.isActive())return this.connection.open()}addSubProtocol(e){this.subprotocols=[...this.subprotocols,e]}}var m=function(e=function(e){const t=document.head.querySelector(`meta[name='action-cable-${e}']`);if(t)return t.getAttribute("content")}("url")||r.default_mount_path){return new f(e)}("/hotwire-spark");function g(e){return e.replace(/-[a-z0-9]+\.(\w+)(\?.*)?$/,".$1")}function b(e,t){const n=new URL(e,window.location.origin);return Object.entries(t).forEach((e=>{let[t,o]=e;n.searchParams.set(t,o)})),n.toString()}function v(e){return b(e,{reload:Date.now()})}async function S(){let e=v(b(window.location.href,{hotwire_spark:"true"}));const t=await fetch(e,{headers:{Accept:"text/html"}});if(!t.ok)throw new Error(`${t.status} when fetching ${e}`);const n=await t.text();return(new DOMParser).parseFromString(n,"text/html")}var y=function(){let e=new Set,t={morphStyle:"outerHTML",callbacks:{beforeNodeAdded:a,afterNodeAdded:a,beforeNodeMorphed:a,afterNodeMorphed:a,beforeNodeRemoved:a,afterNodeRemoved:a,beforeAttributeUpdated:a},head:{style:"merge",shouldPreserve:function(e){return"true"===e.getAttribute("im-preserve")},shouldReAppend:function(e){return"true"===e.getAttribute("im-re-append")},shouldRemove:a,afterHeadMorphed:a}};function n(e,t,o){if(o.head.block){let i=e.querySelector("head"),r=t.querySelector("head");if(i&&r){let s=c(r,i,o);return void Promise.all(s).then((function(){n(e,t,Object.assign(o,{head:{block:!1,ignore:!0}}))}))}}if("innerHTML"===o.morphStyle)return r(t,e,o),e.children;if("outerHTML"===o.morphStyle||null==o.morphStyle){let n=function(e,t,n){let o;o=e.firstChild;let i=o,r=0;for(;o;){let e=m(o,t,n);e>r&&(i=o,r=e),o=o.nextSibling}return i}(t,e,o),r=n?.previousSibling,s=n?.nextSibling,l=i(e,n,o);return n?function(e,t,n){let o=[],i=[];for(;null!=e;)o.push(e),e=e.previousSibling;for(;o.length>0;){let e=o.pop();i.push(e),t.parentElement.insertBefore(e,t)}i.push(t);for(;null!=n;)o.push(n),i.push(n),n=n.nextSibling;for(;o.length>0;)t.parentElement.insertBefore(o.pop(),t.nextSibling);return i}(r,l,s):[]}throw"Do not understand how to morph style "+o.morphStyle}function o(e,t){return t.ignoreActiveValue&&e===document.activeElement}function i(e,t,n){if(!n.ignoreActive||e!==document.activeElement)return null==t?!1===n.callbacks.beforeNodeRemoved(e)?e:(e.remove(),n.callbacks.afterNodeRemoved(e),null):u(e,t)?(!1===n.callbacks.beforeNodeMorphed(e,t)||(e instanceof HTMLHeadElement&&n.head.ignore||(e instanceof HTMLHeadElement&&"morph"!==n.head.style?c(t,e,n):(!function(e,t,n){let i=e.nodeType;if(1===i){const o=e.attributes,i=t.attributes;for(const e of o)s(e.name,t,"update",n)||t.getAttribute(e.name)!==e.value&&t.setAttribute(e.name,e.value);for(let o=i.length-1;0<=o;o--){const r=i[o];s(r.name,t,"remove",n)||(e.hasAttribute(r.name)||t.removeAttribute(r.name))}}8!==i&&3!==i||t.nodeValue!==e.nodeValue&&(t.nodeValue=e.nodeValue);o(t,n)||function(e,t,n){if(e instanceof HTMLInputElement&&t instanceof HTMLInputElement&&"file"!==e.type){let o=e.value,i=t.value;l(e,t,"checked",n),l(e,t,"disabled",n),e.hasAttribute("value")?o!==i&&(s("value",t,"update",n)||(t.setAttribute("value",o),t.value=o)):s("value",t,"remove",n)||(t.value="",t.removeAttribute("value"))}else if(e instanceof HTMLOptionElement)l(e,t,"selected",n);else if(e instanceof HTMLTextAreaElement&&t instanceof HTMLTextAreaElement){let o=e.value,i=t.value;if(s("value",t,"update",n))return;o!==i&&(t.value=o),t.firstChild&&t.firstChild.nodeValue!==o&&(t.firstChild.nodeValue=o)}}(e,t,n)}(t,e,n),o(e,n)||r(t,e,n))),n.callbacks.afterNodeMorphed(e,t)),e):!1===n.callbacks.beforeNodeRemoved(e)||!1===n.callbacks.beforeNodeAdded(t)?e:(e.parentElement.replaceChild(t,e),n.callbacks.afterNodeAdded(t),n.callbacks.afterNodeRemoved(e),t)}function r(e,t,n){let o,r=e.firstChild,s=t.firstChild;for(;r;){if(o=r,r=o.nextSibling,null==s){if(!1===n.callbacks.beforeNodeAdded(o))return;t.appendChild(o),n.callbacks.afterNodeAdded(o),S(n,o);continue}if(d(o,s,n)){i(s,o,n),s=s.nextSibling,S(n,o);continue}let l=p(e,t,o,s,n);if(l){s=h(s,l,n),i(l,o,n),S(n,o);continue}let c=f(e,t,o,s,n);if(c)s=h(s,c,n),i(c,o,n),S(n,o);else{if(!1===n.callbacks.beforeNodeAdded(o))return;t.insertBefore(o,s),n.callbacks.afterNodeAdded(o),S(n,o)}}for(;null!==s;){let e=s;s=s.nextSibling,g(e,n)}}function s(e,t,n,o){return!("value"!==e||!o.ignoreActiveValue||t!==document.activeElement)||!1===o.callbacks.beforeAttributeUpdated(e,t,n)}function l(e,t,n,o){if(e[n]!==t[n]){let i=s(n,t,"update",o);i||(t[n]=e[n]),e[n]?i||t.setAttribute(n,e[n]):s(n,t,"remove",o)||t.removeAttribute(n)}}function c(e,t,n){let o=[],i=[],r=[],s=[],l=n.head.style,c=new Map;for(const t of e.children)c.set(t.outerHTML,t);for(const e of t.children){let t=c.has(e.outerHTML),o=n.head.shouldReAppend(e),a=n.head.shouldPreserve(e);t||a?o?i.push(e):(c.delete(e.outerHTML),r.push(e)):"append"===l?o&&(i.push(e),s.push(e)):!1!==n.head.shouldRemove(e)&&i.push(e)}s.push(...c.values());let a=[];for(const e of s){let i=document.createRange().createContextualFragment(e.outerHTML).firstChild;if(!1!==n.callbacks.beforeNodeAdded(i)){if(i.href||i.src){let e=null,t=new Promise((function(t){e=t}));i.addEventListener("load",(function(){e()})),a.push(t)}t.appendChild(i),n.callbacks.afterNodeAdded(i),o.push(i)}}for(const e of i)!1!==n.callbacks.beforeNodeRemoved(e)&&(t.removeChild(e),n.callbacks.afterNodeRemoved(e));return n.head.afterHeadMorphed(t,{added:o,kept:r,removed:i}),a}function a(){}function d(e,t,n){return null!=e&&null!=t&&(e.nodeType===t.nodeType&&e.tagName===t.tagName&&(""!==e.id&&e.id===t.id||y(n,e,t)>0))}function u(e,t){return null!=e&&null!=t&&(e.nodeType===t.nodeType&&e.tagName===t.tagName)}function h(e,t,n){for(;e!==t;){let t=e;e=e.nextSibling,g(t,n)}return S(n,t),t.nextSibling}function p(e,t,n,o,i){let r=y(i,n,t);if(r>0){let t=o,s=0;for(;null!=t;){if(d(n,t,i))return t;if(s+=y(i,t,e),s>r)return null;t=t.nextSibling}}return null}function f(e,t,n,o,i){let r=o,s=n.nextSibling,l=0;for(;null!=r;){if(y(i,r,e)>0)return null;if(u(n,r))return r;if(u(s,r)&&(l++,s=s.nextSibling,l>=2))return null;r=r.nextSibling}return r}function m(e,t,n){return u(e,t)?.5+y(n,e,t):0}function g(e,t){S(t,e),!1!==t.callbacks.beforeNodeRemoved(e)&&(e.remove(),t.callbacks.afterNodeRemoved(e))}function b(e,t){return!e.deadIds.has(t)}function v(t,n,o){return(t.idMap.get(o)||e).has(n)}function S(t,n){let o=t.idMap.get(n)||e;for(const e of o)t.deadIds.add(e)}function y(t,n,o){let i=t.idMap.get(n)||e,r=0;for(const e of i)b(t,e)&&v(t,e,o)&&++r;return r}function w(e,t){let n=e.parentElement,o=e.querySelectorAll("[id]");for(const e of o){let o=e;for(;o!==n&&null!=o;){let n=t.get(o);null==n&&(n=new Set,t.set(o,n)),n.add(e.id),o=o.parentElement}}}function A(e,t){let n=new Map;return w(e,n),w(t,n),n}return{morph:function(e,o,i={}){e instanceof Document&&(e=e.documentElement),"string"==typeof o&&(o=function(e){let t=new DOMParser,n=e.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim,"");if(n.match(/<\/html>/)||n.match(/<\/head>/)||n.match(/<\/body>/)){let o=t.parseFromString(e,"text/html");if(n.match(/<\/html>/))return o.generatedByIdiomorph=!0,o;{let e=o.firstChild;return e?(e.generatedByIdiomorph=!0,e):null}}{let n=t.parseFromString("<body><template>"+e+"</template></body>","text/html").body.querySelector("template").content;return n.generatedByIdiomorph=!0,n}}(o));let r=function(e){if(null==e){return document.createElement("div")}if(e.generatedByIdiomorph)return e;if(e instanceof Node){const t=document.createElement("div");return t.append(e),t}{const t=document.createElement("div");for(const n of[...e])t.append(n);return t}}(o),s=function(e,n,o){return o=function(e){let n={};return Object.assign(n,t),Object.assign(n,e),n.callbacks={},Object.assign(n.callbacks,t.callbacks),Object.assign(n.callbacks,e.callbacks),n.head={},Object.assign(n.head,t.head),Object.assign(n.head,e.head),n}(o),{target:e,newContent:n,config:o,morphStyle:o.morphStyle,ignoreActive:o.ignoreActive,ignoreActiveValue:o.ignoreActiveValue,idMap:A(e,n),deadIds:new Set,callbacks:o.callbacks,head:o.head}}(e,r,i);return n(e,r,s)},defaults:t}}();function w(){if(M.config.loggingEnabled){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];console.log("[hotwire_spark]",...t)}}class A{static async reload(e){const t=await S();return new A(t,e).reload()}static async reloadAll(){return Stimulus.controllers.forEach((e=>{Stimulus.unload(e.identifier),Stimulus.register(e.identifier,e.constructor)})),Promise.resolve()}constructor(e,t){this.document=e,this.changedFilePath=t,this.application=window.Stimulus}async reload(){w("Reload Stimulus controllers..."),this.application.stop(),await this.#e(),this.#t(),this.application.start()}async#e(){await Promise.all(this.#n.map((async e=>this.#o(e))))}get#n(){return this.controllerPathsToReload=this.controllerPathsToReload||this.#i.filter((e=>this.#r(e))),this.controllerPathsToReload}get#i(){return Object.keys(this.#s).filter((e=>e.endsWith("_controller")))}#r(e){return this.#l(e)===this.#c}get#c(){return this.changedControllerIdentifier=this.changedControllerIdentifier||this.#l(this.changedFilePath),this.changedControllerIdentifier}get#s(){return this.pathsByModule=this.pathsByModule||this.#a(),this.pathsByModule}#a(){const e=this.document.querySelector("script[type=importmap]");return JSON.parse(e.text).imports}async#o(e){w(`\t${e}`);const t=this.#l(e),n=v(this.#d(e)),o=await import(n);this.#u(t,o)}#t(){this.#h.forEach((e=>this.#p(e.identifier)))}get#h(){return this.#f?[]:this.application.controllers.filter((e=>this.#c===e.identifier))}get#f(){return this.#n.length>0}#d(e){return this.#s[e]}#l(e){return e.replace(/^\/+/,"").replace(/^controllers\//,"").replace("_controller","").replace(/\//g,"--").replace(/_/g,"-").replace(/\.js$/,"")}#u(e,t){this.application.unload(e),this.application.register(e,t.default)}#p(e){w(`\tRemoving controller ${e}`),this.application.unload(e)}}class k{static async reload(){return(new k).reload()}async reload(){await this.#m(),await this.#g()}async#m(){w("Reload html with morph...");const e=await S();return this.#b(e.body),e}#b(e){y.morph(document.body,e)}async#g(){await A.reloadAll()}}class C{static async reload(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return new C(...t).reload()}constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:/./;this.filePattern=e}async reload(){w("Reload css..."),await Promise.all(await this.#v())}async#v(){return(await this.#S()).map((e=>this.#y(e)))}async#S(){const e=await S();return Array.from(e.head.querySelectorAll("link[rel='stylesheet']"))}#y(e){return this.#w(e)?this.#A(e):Promise.resolve()}#w(e){return this.filePattern.test(e.getAttribute("href"))}async#A(e){return new Promise((t=>{const n=e.getAttribute("href"),o=this.#k(e)||this.#C(e);o.setAttribute("href",v(e.getAttribute("href"))),o.onload=()=>{w(`\t${n}`),t()}}))}#k(e){return this.#R.find((t=>g(e.href)===g(t.href)))}get#R(){return Array.from(document.querySelectorAll("link[rel='stylesheet']"))}#C(e){return document.head.append(e),e}}class R{static async reload(){return(new R).reload()}async reload(){await this.#m()}async#m(){w("Reload html with Turbo..."),this.#M(),await this.#T()}#M(){document.addEventListener("turbo:before-render",(()=>{Turbo.navigator.currentVisit.scrolled=!0}),{once:!0})}#T(){return new Promise((e=>{document.addEventListener("turbo:load",(()=>e(document)),{once:!0}),window.Turbo.visit(window.location)}))}}m.subscriptions.create({channel:"Hotwire::Spark::Channel"},{connected(){document.body.setAttribute("data-hotwire-spark-ready","")},async received(e){try{await this.dispatch(e)}catch(t){console.log(`Error on ${e.action}`,t)}},dispatch(e){let{action:t,path:n}=e;switch(t){case"reload_html":return this.reloadHtml();case"reload_css":return this.reloadCss(n);case"reload_stimulus":return this.reloadStimulus(n);default:throw new Error(`Unknown action: ${t}`)}},reloadHtml:()=>("morph"==HotwireSpark.config.htmlReloadMethod?k:R).reload(),reloadCss(e){const t=function(e){return e.split("/").pop().split(".")[0]}(e);return C.reload(new RegExp(t))},reloadStimulus:e=>A.reload(e)});const M={config:{loggingEnabled:!1,htmlReloadMethod:"morph"}},T={loggingEnabled:"logging",htmlReloadMethod:"html-reload-method"};return document.addEventListener("DOMContentLoaded",(function(){Object.entries(T).forEach((e=>{let[t,n]=e;var o;M.config[t]=(o=n,document.querySelector(`meta[name="hotwire-spark:${o}"]`)?.content)}))})),M}();
2
2
  //# sourceMappingURL=hotwire_spark.min.js.map