@hotwired/turbo 7.0.0-beta.3 → 7.0.0-beta.4

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.
Files changed (48) hide show
  1. package/dist/turbo.es2017-esm.js +647 -574
  2. package/dist/turbo.es2017-esm.js.map +1 -1
  3. package/dist/turbo.es2017-umd.js +647 -574
  4. package/dist/turbo.es2017-umd.js.map +1 -1
  5. package/dist/turbo.es5-umd.js +1153 -843
  6. package/dist/turbo.es5-umd.js.map +1 -1
  7. package/dist/types/core/drive/error_renderer.d.ts +7 -11
  8. package/dist/types/core/drive/form_submission.d.ts +11 -3
  9. package/dist/types/core/drive/head_snapshot.d.ts +21 -0
  10. package/dist/types/core/drive/history.d.ts +5 -6
  11. package/dist/types/core/drive/navigator.d.ts +7 -7
  12. package/dist/types/core/drive/page_renderer.d.ts +26 -0
  13. package/dist/types/core/drive/page_snapshot.d.ts +17 -0
  14. package/dist/types/core/drive/page_view.d.ts +21 -0
  15. package/dist/types/core/drive/snapshot_cache.d.ts +8 -9
  16. package/dist/types/core/drive/visit.d.ts +13 -15
  17. package/dist/types/core/frames/frame_controller.d.ts +11 -10
  18. package/dist/types/core/frames/frame_renderer.d.ts +8 -0
  19. package/dist/types/core/frames/frame_view.d.ts +7 -0
  20. package/dist/types/core/index.d.ts +1 -1
  21. package/dist/types/core/native/adapter.d.ts +1 -2
  22. package/dist/types/core/native/browser_adapter.d.ts +1 -2
  23. package/dist/types/core/renderer.d.ts +26 -0
  24. package/dist/types/core/session.d.ts +23 -21
  25. package/dist/types/core/snapshot.d.ts +11 -0
  26. package/dist/types/core/streams/stream_message.d.ts +1 -0
  27. package/dist/types/core/url.d.ts +7 -0
  28. package/dist/types/core/view.d.ts +27 -0
  29. package/dist/types/http/fetch_request.d.ts +8 -11
  30. package/dist/types/http/fetch_response.d.ts +1 -2
  31. package/dist/types/observers/link_click_observer.d.ts +3 -4
  32. package/dist/types/observers/stream_observer.d.ts +0 -1
  33. package/dist/types/tests/functional/form_submission_tests.d.ts +11 -3
  34. package/dist/types/tests/functional/frame_tests.d.ts +4 -0
  35. package/dist/types/tests/functional/navigation_tests.d.ts +1 -0
  36. package/dist/types/tests/functional/rendering_tests.d.ts +2 -0
  37. package/dist/types/tests/functional/stream_tests.d.ts +0 -2
  38. package/dist/types/tests/helpers/functional_test_case.d.ts +3 -0
  39. package/dist/types/tests/unit/deprecated_adapter_support_test.d.ts +21 -0
  40. package/dist/types/tests/unit/index.d.ts +1 -0
  41. package/dist/types/util.d.ts +2 -0
  42. package/package.json +1 -1
  43. package/dist/types/core/drive/head_details.d.ts +0 -22
  44. package/dist/types/core/drive/renderer.d.ts +0 -13
  45. package/dist/types/core/drive/snapshot.d.ts +0 -24
  46. package/dist/types/core/drive/snapshot_renderer.d.ts +0 -43
  47. package/dist/types/core/drive/view.d.ts +0 -34
  48. package/dist/types/core/location.d.ts +0 -22
@@ -1,5 +1,5 @@
1
1
  /*
2
- Turbo 7.0.0-beta.3
2
+ Turbo 7.0.0-beta.4
3
3
  Copyright © 2021 Basecamp, LLC
4
4
  */
5
5
  (function (global, factory) {
@@ -294,85 +294,53 @@ Copyright © 2021 Basecamp, LLC
294
294
  }
295
295
  }
296
296
 
297
- var Location = (function () {
298
- function Location(url) {
299
- var linkWithAnchor = document.createElement("a");
300
- linkWithAnchor.href = url;
301
- this.absoluteURL = linkWithAnchor.href;
302
- var anchorLength = linkWithAnchor.hash.length;
303
- if (anchorLength < 2) {
304
- this.requestURL = this.absoluteURL;
305
- }
306
- else {
307
- this.requestURL = this.absoluteURL.slice(0, -anchorLength);
308
- this.anchor = linkWithAnchor.hash.slice(1);
309
- }
297
+ function expandURL(locatable) {
298
+ var anchor = document.createElement("a");
299
+ anchor.href = locatable.toString();
300
+ return new URL(anchor.href);
301
+ }
302
+ function getAnchor(url) {
303
+ var anchorMatch;
304
+ if (url.hash) {
305
+ return url.hash.slice(1);
310
306
  }
311
- Object.defineProperty(Location, "currentLocation", {
312
- get: function () {
313
- return this.wrap(window.location.toString());
314
- },
315
- enumerable: false,
316
- configurable: true
317
- });
318
- Location.wrap = function (locatable) {
319
- if (typeof locatable == "string") {
320
- return new this(locatable);
321
- }
322
- else if (locatable != null) {
323
- return locatable;
324
- }
325
- };
326
- Location.prototype.getOrigin = function () {
327
- return this.absoluteURL.split("/", 3).join("/");
328
- };
329
- Location.prototype.getPath = function () {
330
- return (this.requestURL.match(/\/\/[^/]*(\/[^?;]*)/) || [])[1] || "/";
331
- };
332
- Location.prototype.getPathComponents = function () {
333
- return this.getPath().split("/").slice(1);
334
- };
335
- Location.prototype.getLastPathComponent = function () {
336
- return this.getPathComponents().slice(-1)[0];
337
- };
338
- Location.prototype.getExtension = function () {
339
- return (this.getLastPathComponent().match(/\.[^.]*$/) || [])[0] || "";
340
- };
341
- Location.prototype.isHTML = function () {
342
- return !!this.getExtension().match(/^(?:|\.(?:htm|html|xhtml))$/);
343
- };
344
- Location.prototype.isPrefixedBy = function (location) {
345
- var prefixURL = getPrefixURL(location);
346
- return this.isEqualTo(location) || stringStartsWith(this.absoluteURL, prefixURL);
347
- };
348
- Location.prototype.isEqualTo = function (location) {
349
- return location && this.absoluteURL === location.absoluteURL;
350
- };
351
- Location.prototype.toCacheKey = function () {
352
- return this.requestURL;
353
- };
354
- Location.prototype.toJSON = function () {
355
- return this.absoluteURL;
356
- };
357
- Location.prototype.toString = function () {
358
- return this.absoluteURL;
359
- };
360
- Location.prototype.valueOf = function () {
361
- return this.absoluteURL;
362
- };
363
- return Location;
364
- }());
365
- function getPrefixURL(location) {
366
- return addTrailingSlash(location.getOrigin() + location.getPath());
307
+ else if (anchorMatch = url.href.match(/#(.*)$/)) {
308
+ return anchorMatch[1];
309
+ }
310
+ else {
311
+ return "";
312
+ }
313
+ }
314
+ function getExtension(url) {
315
+ return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || "";
316
+ }
317
+ function isHTML(url) {
318
+ return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml))$/);
319
+ }
320
+ function isPrefixedBy(baseURL, url) {
321
+ var prefix = getPrefix(url);
322
+ return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix);
323
+ }
324
+ function toCacheKey(url) {
325
+ var anchorLength = url.hash.length;
326
+ if (anchorLength < 2) {
327
+ return url.href;
328
+ }
329
+ else {
330
+ return url.href.slice(0, -anchorLength);
331
+ }
332
+ }
333
+ function getPathComponents(url) {
334
+ return url.pathname.split("/").slice(1);
367
335
  }
368
- function addTrailingSlash(url) {
369
- return stringEndsWith(url, "/") ? url : url + "/";
336
+ function getLastPathComponent(url) {
337
+ return getPathComponents(url).slice(-1)[0];
370
338
  }
371
- function stringStartsWith(string, prefix) {
372
- return string.slice(0, prefix.length) === prefix;
339
+ function getPrefix(url) {
340
+ return addTrailingSlash(url.origin + url.pathname);
373
341
  }
374
- function stringEndsWith(string, suffix) {
375
- return string.slice(-suffix.length) === suffix;
342
+ function addTrailingSlash(value) {
343
+ return value.endsWith("/") ? value : value + "/";
376
344
  }
377
345
 
378
346
  var FetchResponse = (function () {
@@ -416,7 +384,7 @@ Copyright © 2021 Basecamp, LLC
416
384
  });
417
385
  Object.defineProperty(FetchResponse.prototype, "location", {
418
386
  get: function () {
419
- return Location.wrap(this.response.url);
387
+ return expandURL(this.response.url);
420
388
  },
421
389
  enumerable: false,
422
390
  configurable: true
@@ -476,9 +444,16 @@ Copyright © 2021 Basecamp, LLC
476
444
  function nextAnimationFrame() {
477
445
  return new Promise(function (resolve) { return requestAnimationFrame(function () { return resolve(); }); });
478
446
  }
447
+ function nextEventLoopTick() {
448
+ return new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 0); });
449
+ }
479
450
  function nextMicrotask() {
480
451
  return Promise.resolve();
481
452
  }
453
+ function parseHTMLDocument(html) {
454
+ if (html === void 0) { html = ""; }
455
+ return new DOMParser().parseFromString(html, "text/html");
456
+ }
482
457
  function unindent(strings) {
483
458
  var values = [];
484
459
  for (var _i = 1; _i < arguments.length; _i++) {
@@ -531,33 +506,28 @@ Copyright © 2021 Basecamp, LLC
531
506
  }
532
507
  var FetchRequest = (function () {
533
508
  function FetchRequest(delegate, method, location, body) {
509
+ if (body === void 0) { body = new URLSearchParams; }
534
510
  this.abortController = new AbortController;
535
511
  this.delegate = delegate;
536
512
  this.method = method;
537
- this.location = location;
538
- this.body = body;
513
+ if (this.isIdempotent) {
514
+ this.url = mergeFormDataEntries(location, __spread(body.entries()));
515
+ }
516
+ else {
517
+ this.body = body;
518
+ this.url = location;
519
+ }
539
520
  }
540
- Object.defineProperty(FetchRequest.prototype, "url", {
521
+ Object.defineProperty(FetchRequest.prototype, "location", {
541
522
  get: function () {
542
- var url = this.location.absoluteURL;
543
- var query = this.params.toString();
544
- if (this.isIdempotent && query.length) {
545
- return [url, query].join(url.includes("?") ? "&" : "?");
546
- }
547
- else {
548
- return url;
549
- }
523
+ return this.url;
550
524
  },
551
525
  enumerable: false,
552
526
  configurable: true
553
527
  });
554
528
  Object.defineProperty(FetchRequest.prototype, "params", {
555
529
  get: function () {
556
- return this.entries.reduce(function (params, _a) {
557
- var _b = __read(_a, 2), name = _b[0], value = _b[1];
558
- params.append(name, value.toString());
559
- return params;
560
- }, new URLSearchParams);
530
+ return this.url.searchParams;
561
531
  },
562
532
  enumerable: false,
563
533
  configurable: true
@@ -584,7 +554,7 @@ Copyright © 2021 Basecamp, LLC
584
554
  case 1:
585
555
  _a.trys.push([1, 4, 5, 6]);
586
556
  this.delegate.requestStarted(this);
587
- return [4, fetch(this.url, fetchOptions)];
557
+ return [4, fetch(this.url.href, fetchOptions)];
588
558
  case 2:
589
559
  response = _a.sent();
590
560
  return [4, this.receive(response)];
@@ -627,7 +597,7 @@ Copyright © 2021 Basecamp, LLC
627
597
  credentials: "same-origin",
628
598
  headers: this.headers,
629
599
  redirect: "follow",
630
- body: this.isIdempotent ? undefined : this.body,
600
+ body: this.body,
631
601
  signal: this.abortSignal
632
602
  };
633
603
  },
@@ -643,32 +613,59 @@ Copyright © 2021 Basecamp, LLC
643
613
  });
644
614
  Object.defineProperty(FetchRequest.prototype, "headers", {
645
615
  get: function () {
646
- return __assign({ "Accept": "text/html, application/xhtml+xml" }, this.additionalHeaders);
616
+ var headers = __assign({}, this.defaultHeaders);
617
+ if (typeof this.delegate.prepareHeadersForRequest == "function") {
618
+ this.delegate.prepareHeadersForRequest(headers, this);
619
+ }
620
+ return headers;
647
621
  },
648
622
  enumerable: false,
649
623
  configurable: true
650
624
  });
651
- Object.defineProperty(FetchRequest.prototype, "additionalHeaders", {
625
+ Object.defineProperty(FetchRequest.prototype, "abortSignal", {
652
626
  get: function () {
653
- if (typeof this.delegate.additionalHeadersForRequest == "function") {
654
- return this.delegate.additionalHeadersForRequest(this);
655
- }
656
- else {
657
- return {};
658
- }
627
+ return this.abortController.signal;
659
628
  },
660
629
  enumerable: false,
661
630
  configurable: true
662
631
  });
663
- Object.defineProperty(FetchRequest.prototype, "abortSignal", {
632
+ Object.defineProperty(FetchRequest.prototype, "defaultHeaders", {
664
633
  get: function () {
665
- return this.abortController.signal;
634
+ return {
635
+ "Accept": "text/html, application/xhtml+xml"
636
+ };
666
637
  },
667
638
  enumerable: false,
668
639
  configurable: true
669
640
  });
670
641
  return FetchRequest;
671
642
  }());
643
+ function mergeFormDataEntries(url, entries) {
644
+ var e_1, _a;
645
+ var currentSearchParams = new URLSearchParams(url.search);
646
+ try {
647
+ for (var entries_1 = __values(entries), entries_1_1 = entries_1.next(); !entries_1_1.done; entries_1_1 = entries_1.next()) {
648
+ var _b = __read(entries_1_1.value, 2), name_1 = _b[0], value = _b[1];
649
+ if (value instanceof File)
650
+ continue;
651
+ if (currentSearchParams.has(name_1)) {
652
+ currentSearchParams.delete(name_1);
653
+ url.searchParams.set(name_1, value);
654
+ }
655
+ else {
656
+ url.searchParams.append(name_1, value);
657
+ }
658
+ }
659
+ }
660
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
661
+ finally {
662
+ try {
663
+ if (entries_1_1 && !entries_1_1.done && (_a = entries_1.return)) _a.call(entries_1);
664
+ }
665
+ finally { if (e_1) throw e_1.error; }
666
+ }
667
+ return url;
668
+ }
672
669
 
673
670
  var AppearanceObserver = (function () {
674
671
  function AppearanceObserver(delegate, element) {
@@ -699,6 +696,66 @@ Copyright © 2021 Basecamp, LLC
699
696
  return AppearanceObserver;
700
697
  }());
701
698
 
699
+ var StreamMessage = (function () {
700
+ function StreamMessage(html) {
701
+ this.templateElement = document.createElement("template");
702
+ this.templateElement.innerHTML = html;
703
+ }
704
+ StreamMessage.wrap = function (message) {
705
+ if (typeof message == "string") {
706
+ return new this(message);
707
+ }
708
+ else {
709
+ return message;
710
+ }
711
+ };
712
+ Object.defineProperty(StreamMessage.prototype, "fragment", {
713
+ get: function () {
714
+ var e_1, _a;
715
+ var fragment = document.createDocumentFragment();
716
+ try {
717
+ for (var _b = __values(this.foreignElements), _c = _b.next(); !_c.done; _c = _b.next()) {
718
+ var element = _c.value;
719
+ fragment.appendChild(document.importNode(element, true));
720
+ }
721
+ }
722
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
723
+ finally {
724
+ try {
725
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
726
+ }
727
+ finally { if (e_1) throw e_1.error; }
728
+ }
729
+ return fragment;
730
+ },
731
+ enumerable: false,
732
+ configurable: true
733
+ });
734
+ Object.defineProperty(StreamMessage.prototype, "foreignElements", {
735
+ get: function () {
736
+ return this.templateChildren.reduce(function (streamElements, child) {
737
+ if (child.tagName.toLowerCase() == "turbo-stream") {
738
+ return __spread(streamElements, [child]);
739
+ }
740
+ else {
741
+ return streamElements;
742
+ }
743
+ }, []);
744
+ },
745
+ enumerable: false,
746
+ configurable: true
747
+ });
748
+ Object.defineProperty(StreamMessage.prototype, "templateChildren", {
749
+ get: function () {
750
+ return Array.from(this.templateElement.content.children);
751
+ },
752
+ enumerable: false,
753
+ configurable: true
754
+ });
755
+ StreamMessage.contentType = "text/vnd.turbo-stream.html";
756
+ return StreamMessage;
757
+ }());
758
+
702
759
  var FormSubmissionState;
703
760
  (function (FormSubmissionState) {
704
761
  FormSubmissionState[FormSubmissionState["initialized"] = 0] = "initialized";
@@ -708,15 +765,28 @@ Copyright © 2021 Basecamp, LLC
708
765
  FormSubmissionState[FormSubmissionState["stopping"] = 4] = "stopping";
709
766
  FormSubmissionState[FormSubmissionState["stopped"] = 5] = "stopped";
710
767
  })(FormSubmissionState || (FormSubmissionState = {}));
768
+ var FormEnctype;
769
+ (function (FormEnctype) {
770
+ FormEnctype["urlEncoded"] = "application/x-www-form-urlencoded";
771
+ FormEnctype["multipart"] = "multipart/form-data";
772
+ FormEnctype["plain"] = "text/plain";
773
+ })(FormEnctype || (FormEnctype = {}));
774
+ function formEnctypeFromString(encoding) {
775
+ switch (encoding.toLowerCase()) {
776
+ case FormEnctype.multipart: return FormEnctype.multipart;
777
+ case FormEnctype.plain: return FormEnctype.plain;
778
+ default: return FormEnctype.urlEncoded;
779
+ }
780
+ }
711
781
  var FormSubmission = (function () {
712
782
  function FormSubmission(delegate, formElement, submitter, mustRedirect) {
713
783
  if (mustRedirect === void 0) { mustRedirect = false; }
714
784
  this.state = FormSubmissionState.initialized;
715
785
  this.delegate = delegate;
716
786
  this.formElement = formElement;
717
- this.formData = buildFormData(formElement, submitter);
718
787
  this.submitter = submitter;
719
- this.fetchRequest = new FetchRequest(this, this.method, this.location, this.formData);
788
+ this.formData = buildFormData(formElement, submitter);
789
+ this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body);
720
790
  this.mustRedirect = mustRedirect;
721
791
  }
722
792
  Object.defineProperty(FormSubmission.prototype, "method", {
@@ -738,7 +808,37 @@ Copyright © 2021 Basecamp, LLC
738
808
  });
739
809
  Object.defineProperty(FormSubmission.prototype, "location", {
740
810
  get: function () {
741
- return Location.wrap(this.action);
811
+ return expandURL(this.action);
812
+ },
813
+ enumerable: false,
814
+ configurable: true
815
+ });
816
+ Object.defineProperty(FormSubmission.prototype, "body", {
817
+ get: function () {
818
+ if (this.enctype == FormEnctype.urlEncoded || this.method == FetchMethod.get) {
819
+ return new URLSearchParams(this.stringFormData);
820
+ }
821
+ else {
822
+ return this.formData;
823
+ }
824
+ },
825
+ enumerable: false,
826
+ configurable: true
827
+ });
828
+ Object.defineProperty(FormSubmission.prototype, "enctype", {
829
+ get: function () {
830
+ var _a;
831
+ return formEnctypeFromString(((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formenctype")) || this.formElement.enctype);
832
+ },
833
+ enumerable: false,
834
+ configurable: true
835
+ });
836
+ Object.defineProperty(FormSubmission.prototype, "stringFormData", {
837
+ get: function () {
838
+ return __spread(this.formData).reduce(function (entries, _a) {
839
+ var _b = __read(_a, 2), name = _b[0], value = _b[1];
840
+ return entries.concat(typeof value == "string" ? [[name, value]] : []);
841
+ }, []);
742
842
  },
743
843
  enumerable: false,
744
844
  configurable: true
@@ -764,15 +864,14 @@ Copyright © 2021 Basecamp, LLC
764
864
  return true;
765
865
  }
766
866
  };
767
- FormSubmission.prototype.additionalHeadersForRequest = function (request) {
768
- var headers = {};
769
- if (this.method != FetchMethod.get) {
867
+ FormSubmission.prototype.prepareHeadersForRequest = function (headers, request) {
868
+ if (!request.isIdempotent) {
770
869
  var token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token");
771
870
  if (token) {
772
871
  headers["X-CSRF-Token"] = token;
773
872
  }
873
+ headers["Accept"] = [StreamMessage.contentType, headers["Accept"]].join(", ");
774
874
  }
775
- return headers;
776
875
  };
777
876
  FormSubmission.prototype.requestStarted = function (request) {
778
877
  this.state = FormSubmissionState.waiting;
@@ -841,6 +940,54 @@ Copyright © 2021 Basecamp, LLC
841
940
  return response.statusCode == 200 && !response.redirected;
842
941
  }
843
942
 
943
+ var Snapshot = (function () {
944
+ function Snapshot(element) {
945
+ this.element = element;
946
+ }
947
+ Object.defineProperty(Snapshot.prototype, "children", {
948
+ get: function () {
949
+ return __spread(this.element.children);
950
+ },
951
+ enumerable: false,
952
+ configurable: true
953
+ });
954
+ Snapshot.prototype.hasAnchor = function (anchor) {
955
+ return this.getElementForAnchor(anchor) != null;
956
+ };
957
+ Snapshot.prototype.getElementForAnchor = function (anchor) {
958
+ try {
959
+ return this.element.querySelector("[id='" + anchor + "'], a[name='" + anchor + "']");
960
+ }
961
+ catch (_a) {
962
+ return null;
963
+ }
964
+ };
965
+ Object.defineProperty(Snapshot.prototype, "firstAutofocusableElement", {
966
+ get: function () {
967
+ return this.element.querySelector("[autofocus]");
968
+ },
969
+ enumerable: false,
970
+ configurable: true
971
+ });
972
+ Object.defineProperty(Snapshot.prototype, "permanentElements", {
973
+ get: function () {
974
+ return __spread(this.element.querySelectorAll("[id][data-turbo-permanent]"));
975
+ },
976
+ enumerable: false,
977
+ configurable: true
978
+ });
979
+ Snapshot.prototype.getPermanentElementById = function (id) {
980
+ return this.element.querySelector("#" + id + "[data-turbo-permanent]");
981
+ };
982
+ Snapshot.prototype.getPermanentElementsPresentInSnapshot = function (snapshot) {
983
+ return this.permanentElements.filter(function (_a) {
984
+ var id = _a.id;
985
+ return snapshot.getPermanentElementById(id);
986
+ });
987
+ };
988
+ return Snapshot;
989
+ }());
990
+
844
991
  var FormInterceptor = (function () {
845
992
  function FormInterceptor(delegate, element) {
846
993
  var _this = this;
@@ -867,64 +1014,372 @@ Copyright © 2021 Basecamp, LLC
867
1014
  return FormInterceptor;
868
1015
  }());
869
1016
 
870
- var LinkInterceptor = (function () {
871
- function LinkInterceptor(delegate, element) {
872
- var _this = this;
873
- this.clickBubbled = function (event) {
874
- if (_this.respondsToEventTarget(event.target)) {
875
- _this.clickEvent = event;
876
- }
877
- else {
878
- delete _this.clickEvent;
879
- }
880
- };
881
- this.linkClicked = (function (event) {
882
- if (_this.clickEvent && _this.respondsToEventTarget(event.target) && event.target instanceof Element) {
883
- if (_this.delegate.shouldInterceptLinkClick(event.target, event.detail.url)) {
884
- _this.clickEvent.preventDefault();
885
- event.preventDefault();
886
- _this.delegate.linkClickIntercepted(event.target, event.detail.url);
887
- }
888
- }
889
- delete _this.clickEvent;
890
- });
891
- this.willVisit = function () {
892
- delete _this.clickEvent;
893
- };
1017
+ var View = (function () {
1018
+ function View(delegate, element) {
894
1019
  this.delegate = delegate;
895
1020
  this.element = element;
896
1021
  }
897
- LinkInterceptor.prototype.start = function () {
898
- this.element.addEventListener("click", this.clickBubbled);
899
- document.addEventListener("turbo:click", this.linkClicked);
900
- document.addEventListener("turbo:before-visit", this.willVisit);
1022
+ View.prototype.scrollToAnchor = function (anchor) {
1023
+ var element = this.snapshot.getElementForAnchor(anchor);
1024
+ if (element) {
1025
+ this.scrollToElement(element);
1026
+ }
1027
+ else {
1028
+ this.scrollToPosition({ x: 0, y: 0 });
1029
+ }
901
1030
  };
902
- LinkInterceptor.prototype.stop = function () {
903
- this.element.removeEventListener("click", this.clickBubbled);
904
- document.removeEventListener("turbo:click", this.linkClicked);
905
- document.removeEventListener("turbo:before-visit", this.willVisit);
1031
+ View.prototype.scrollToElement = function (element) {
1032
+ element.scrollIntoView();
906
1033
  };
907
- LinkInterceptor.prototype.respondsToEventTarget = function (target) {
908
- var element = target instanceof Element
909
- ? target
910
- : target instanceof Node
911
- ? target.parentElement
912
- : null;
913
- return element && element.closest("turbo-frame, html") == this.element;
1034
+ View.prototype.scrollToPosition = function (_a) {
1035
+ var x = _a.x, y = _a.y;
1036
+ this.scrollRoot.scrollTo(x, y);
914
1037
  };
915
- return LinkInterceptor;
916
- }());
917
-
918
- var FrameController = (function () {
919
- function FrameController(element) {
920
- this.resolveVisitPromise = function () { };
921
- this.element = element;
922
- this.appearanceObserver = new AppearanceObserver(this, this.element);
923
- this.linkInterceptor = new LinkInterceptor(this, this.element);
924
- this.formInterceptor = new FormInterceptor(this, this.element);
925
- }
926
- FrameController.prototype.connect = function () {
927
- if (this.loadingStyle == FrameLoadingStyle.lazy) {
1038
+ Object.defineProperty(View.prototype, "scrollRoot", {
1039
+ get: function () {
1040
+ return window;
1041
+ },
1042
+ enumerable: false,
1043
+ configurable: true
1044
+ });
1045
+ View.prototype.render = function (renderer) {
1046
+ return __awaiter(this, void 0, void 0, function () {
1047
+ var isPreview, shouldRender, snapshot;
1048
+ return __generator(this, function (_a) {
1049
+ switch (_a.label) {
1050
+ case 0:
1051
+ if (this.renderer) {
1052
+ throw new Error("rendering is already in progress");
1053
+ }
1054
+ isPreview = renderer.isPreview, shouldRender = renderer.shouldRender, snapshot = renderer.newSnapshot;
1055
+ if (!shouldRender) return [3, 5];
1056
+ _a.label = 1;
1057
+ case 1:
1058
+ _a.trys.push([1, , 3, 4]);
1059
+ this.renderer = renderer;
1060
+ this.prepareToRenderSnapshot(renderer);
1061
+ this.delegate.viewWillRenderSnapshot(snapshot, isPreview);
1062
+ return [4, this.renderSnapshot(renderer)];
1063
+ case 2:
1064
+ _a.sent();
1065
+ this.delegate.viewRenderedSnapshot(snapshot, isPreview);
1066
+ this.finishRenderingSnapshot(renderer);
1067
+ return [3, 4];
1068
+ case 3:
1069
+ delete this.renderer;
1070
+ return [7];
1071
+ case 4: return [3, 6];
1072
+ case 5:
1073
+ this.invalidate();
1074
+ _a.label = 6;
1075
+ case 6: return [2];
1076
+ }
1077
+ });
1078
+ });
1079
+ };
1080
+ View.prototype.invalidate = function () {
1081
+ this.delegate.viewInvalidated();
1082
+ };
1083
+ View.prototype.prepareToRenderSnapshot = function (renderer) {
1084
+ this.markAsPreview(renderer.isPreview);
1085
+ renderer.prepareToRender();
1086
+ };
1087
+ View.prototype.markAsPreview = function (isPreview) {
1088
+ if (isPreview) {
1089
+ this.element.setAttribute("data-turbo-preview", "");
1090
+ }
1091
+ else {
1092
+ this.element.removeAttribute("data-turbo-preview");
1093
+ }
1094
+ };
1095
+ View.prototype.renderSnapshot = function (renderer) {
1096
+ return __awaiter(this, void 0, void 0, function () {
1097
+ return __generator(this, function (_a) {
1098
+ switch (_a.label) {
1099
+ case 0: return [4, renderer.render()];
1100
+ case 1:
1101
+ _a.sent();
1102
+ return [2];
1103
+ }
1104
+ });
1105
+ });
1106
+ };
1107
+ View.prototype.finishRenderingSnapshot = function (renderer) {
1108
+ renderer.finishRendering();
1109
+ };
1110
+ return View;
1111
+ }());
1112
+
1113
+ var FrameView = (function (_super) {
1114
+ __extends(FrameView, _super);
1115
+ function FrameView() {
1116
+ return _super !== null && _super.apply(this, arguments) || this;
1117
+ }
1118
+ FrameView.prototype.invalidate = function () {
1119
+ this.element.innerHTML = "";
1120
+ };
1121
+ Object.defineProperty(FrameView.prototype, "snapshot", {
1122
+ get: function () {
1123
+ return new Snapshot(this.element);
1124
+ },
1125
+ enumerable: false,
1126
+ configurable: true
1127
+ });
1128
+ return FrameView;
1129
+ }(View));
1130
+
1131
+ var LinkInterceptor = (function () {
1132
+ function LinkInterceptor(delegate, element) {
1133
+ var _this = this;
1134
+ this.clickBubbled = function (event) {
1135
+ if (_this.respondsToEventTarget(event.target)) {
1136
+ _this.clickEvent = event;
1137
+ }
1138
+ else {
1139
+ delete _this.clickEvent;
1140
+ }
1141
+ };
1142
+ this.linkClicked = (function (event) {
1143
+ if (_this.clickEvent && _this.respondsToEventTarget(event.target) && event.target instanceof Element) {
1144
+ if (_this.delegate.shouldInterceptLinkClick(event.target, event.detail.url)) {
1145
+ _this.clickEvent.preventDefault();
1146
+ event.preventDefault();
1147
+ _this.delegate.linkClickIntercepted(event.target, event.detail.url);
1148
+ }
1149
+ }
1150
+ delete _this.clickEvent;
1151
+ });
1152
+ this.willVisit = function () {
1153
+ delete _this.clickEvent;
1154
+ };
1155
+ this.delegate = delegate;
1156
+ this.element = element;
1157
+ }
1158
+ LinkInterceptor.prototype.start = function () {
1159
+ this.element.addEventListener("click", this.clickBubbled);
1160
+ document.addEventListener("turbo:click", this.linkClicked);
1161
+ document.addEventListener("turbo:before-visit", this.willVisit);
1162
+ };
1163
+ LinkInterceptor.prototype.stop = function () {
1164
+ this.element.removeEventListener("click", this.clickBubbled);
1165
+ document.removeEventListener("turbo:click", this.linkClicked);
1166
+ document.removeEventListener("turbo:before-visit", this.willVisit);
1167
+ };
1168
+ LinkInterceptor.prototype.respondsToEventTarget = function (target) {
1169
+ var element = target instanceof Element
1170
+ ? target
1171
+ : target instanceof Node
1172
+ ? target.parentElement
1173
+ : null;
1174
+ return element && element.closest("turbo-frame, html") == this.element;
1175
+ };
1176
+ return LinkInterceptor;
1177
+ }());
1178
+
1179
+ var Renderer = (function () {
1180
+ function Renderer(currentSnapshot, newSnapshot, isPreview) {
1181
+ var _this = this;
1182
+ this.currentSnapshot = currentSnapshot;
1183
+ this.newSnapshot = newSnapshot;
1184
+ this.isPreview = isPreview;
1185
+ this.promise = new Promise(function (resolve, reject) { return _this.resolvingFunctions = { resolve: resolve, reject: reject }; });
1186
+ }
1187
+ Object.defineProperty(Renderer.prototype, "shouldRender", {
1188
+ get: function () {
1189
+ return true;
1190
+ },
1191
+ enumerable: false,
1192
+ configurable: true
1193
+ });
1194
+ Renderer.prototype.prepareToRender = function () {
1195
+ return;
1196
+ };
1197
+ Renderer.prototype.finishRendering = function () {
1198
+ if (this.resolvingFunctions) {
1199
+ this.resolvingFunctions.resolve();
1200
+ delete this.resolvingFunctions;
1201
+ }
1202
+ };
1203
+ Renderer.prototype.createScriptElement = function (element) {
1204
+ if (element.getAttribute("data-turbo-eval") == "false") {
1205
+ return element;
1206
+ }
1207
+ else {
1208
+ var createdScriptElement = document.createElement("script");
1209
+ createdScriptElement.textContent = element.textContent;
1210
+ createdScriptElement.async = false;
1211
+ copyElementAttributes(createdScriptElement, element);
1212
+ return createdScriptElement;
1213
+ }
1214
+ };
1215
+ Renderer.prototype.preservingPermanentElements = function (callback) {
1216
+ var placeholders = relocatePermanentElements(this.currentSnapshot, this.newSnapshot);
1217
+ callback();
1218
+ replacePlaceholderElementsWithClonedPermanentElements(placeholders);
1219
+ };
1220
+ Renderer.prototype.focusFirstAutofocusableElement = function () {
1221
+ var element = this.newSnapshot.firstAutofocusableElement;
1222
+ if (elementIsFocusable(element)) {
1223
+ element.focus();
1224
+ }
1225
+ };
1226
+ Object.defineProperty(Renderer.prototype, "currentElement", {
1227
+ get: function () {
1228
+ return this.currentSnapshot.element;
1229
+ },
1230
+ enumerable: false,
1231
+ configurable: true
1232
+ });
1233
+ Object.defineProperty(Renderer.prototype, "newElement", {
1234
+ get: function () {
1235
+ return this.newSnapshot.element;
1236
+ },
1237
+ enumerable: false,
1238
+ configurable: true
1239
+ });
1240
+ return Renderer;
1241
+ }());
1242
+ function replaceElementWithElement(fromElement, toElement) {
1243
+ var parentElement = fromElement.parentElement;
1244
+ if (parentElement) {
1245
+ return parentElement.replaceChild(toElement, fromElement);
1246
+ }
1247
+ }
1248
+ function copyElementAttributes(destinationElement, sourceElement) {
1249
+ var e_1, _a;
1250
+ try {
1251
+ for (var _b = __values(__spread(sourceElement.attributes)), _c = _b.next(); !_c.done; _c = _b.next()) {
1252
+ var _d = _c.value, name_1 = _d.name, value = _d.value;
1253
+ destinationElement.setAttribute(name_1, value);
1254
+ }
1255
+ }
1256
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1257
+ finally {
1258
+ try {
1259
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1260
+ }
1261
+ finally { if (e_1) throw e_1.error; }
1262
+ }
1263
+ }
1264
+ function createPlaceholderForPermanentElement(permanentElement) {
1265
+ var element = document.createElement("meta");
1266
+ element.setAttribute("name", "turbo-permanent-placeholder");
1267
+ element.setAttribute("content", permanentElement.id);
1268
+ return { element: element, permanentElement: permanentElement };
1269
+ }
1270
+ function replacePlaceholderElementsWithClonedPermanentElements(placeholders) {
1271
+ var e_2, _a;
1272
+ try {
1273
+ for (var placeholders_1 = __values(placeholders), placeholders_1_1 = placeholders_1.next(); !placeholders_1_1.done; placeholders_1_1 = placeholders_1.next()) {
1274
+ var _b = placeholders_1_1.value, element = _b.element, permanentElement = _b.permanentElement;
1275
+ var clonedElement = permanentElement.cloneNode(true);
1276
+ replaceElementWithElement(element, clonedElement);
1277
+ }
1278
+ }
1279
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
1280
+ finally {
1281
+ try {
1282
+ if (placeholders_1_1 && !placeholders_1_1.done && (_a = placeholders_1.return)) _a.call(placeholders_1);
1283
+ }
1284
+ finally { if (e_2) throw e_2.error; }
1285
+ }
1286
+ }
1287
+ function relocatePermanentElements(currentSnapshot, newSnapshot) {
1288
+ return currentSnapshot.getPermanentElementsPresentInSnapshot(newSnapshot).reduce(function (placeholders, permanentElement) {
1289
+ var newElement = newSnapshot.getPermanentElementById(permanentElement.id);
1290
+ if (newElement) {
1291
+ var placeholder = createPlaceholderForPermanentElement(permanentElement);
1292
+ replaceElementWithElement(permanentElement, placeholder.element);
1293
+ replaceElementWithElement(newElement, permanentElement);
1294
+ return __spread(placeholders, [placeholder]);
1295
+ }
1296
+ else {
1297
+ return placeholders;
1298
+ }
1299
+ }, []);
1300
+ }
1301
+ function elementIsFocusable(element) {
1302
+ return element && typeof element.focus == "function";
1303
+ }
1304
+
1305
+ var FrameRenderer = (function (_super) {
1306
+ __extends(FrameRenderer, _super);
1307
+ function FrameRenderer() {
1308
+ return _super !== null && _super.apply(this, arguments) || this;
1309
+ }
1310
+ Object.defineProperty(FrameRenderer.prototype, "shouldRender", {
1311
+ get: function () {
1312
+ return true;
1313
+ },
1314
+ enumerable: false,
1315
+ configurable: true
1316
+ });
1317
+ FrameRenderer.prototype.render = function () {
1318
+ return __awaiter(this, void 0, void 0, function () {
1319
+ var _this = this;
1320
+ return __generator(this, function (_a) {
1321
+ switch (_a.label) {
1322
+ case 0: return [4, nextAnimationFrame()];
1323
+ case 1:
1324
+ _a.sent();
1325
+ this.preservingPermanentElements(function () {
1326
+ _this.loadFrameElement();
1327
+ });
1328
+ this.scrollFrameIntoView();
1329
+ return [4, nextAnimationFrame()];
1330
+ case 2:
1331
+ _a.sent();
1332
+ this.focusFirstAutofocusableElement();
1333
+ return [2];
1334
+ }
1335
+ });
1336
+ });
1337
+ };
1338
+ FrameRenderer.prototype.loadFrameElement = function () {
1339
+ var _a;
1340
+ var destinationRange = document.createRange();
1341
+ destinationRange.selectNodeContents(this.currentElement);
1342
+ destinationRange.deleteContents();
1343
+ var frameElement = this.newElement;
1344
+ var sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange();
1345
+ if (sourceRange) {
1346
+ sourceRange.selectNodeContents(frameElement);
1347
+ this.currentElement.appendChild(sourceRange.extractContents());
1348
+ }
1349
+ };
1350
+ FrameRenderer.prototype.scrollFrameIntoView = function () {
1351
+ if (this.currentElement.autoscroll || this.newElement.autoscroll) {
1352
+ var element = this.currentElement.firstElementChild;
1353
+ var block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end");
1354
+ if (element) {
1355
+ element.scrollIntoView({ block: block });
1356
+ return true;
1357
+ }
1358
+ }
1359
+ return false;
1360
+ };
1361
+ return FrameRenderer;
1362
+ }(Renderer));
1363
+ function readScrollLogicalPosition(value, defaultValue) {
1364
+ if (value == "end" || value == "start" || value == "center" || value == "nearest") {
1365
+ return value;
1366
+ }
1367
+ else {
1368
+ return defaultValue;
1369
+ }
1370
+ }
1371
+
1372
+ var FrameController = (function () {
1373
+ function FrameController(element) {
1374
+ this.resolveVisitPromise = function () { };
1375
+ this.element = element;
1376
+ this.view = new FrameView(this, this.element);
1377
+ this.appearanceObserver = new AppearanceObserver(this, this.element);
1378
+ this.linkInterceptor = new LinkInterceptor(this, this.element);
1379
+ this.formInterceptor = new FormInterceptor(this, this.element);
1380
+ }
1381
+ FrameController.prototype.connect = function () {
1382
+ if (this.loadingStyle == FrameLoadingStyle.lazy) {
928
1383
  this.appearanceObserver.start();
929
1384
  }
930
1385
  this.linkInterceptor.start();
@@ -975,29 +1430,32 @@ Copyright © 2021 Basecamp, LLC
975
1430
  };
976
1431
  FrameController.prototype.loadResponse = function (response) {
977
1432
  return __awaiter(this, void 0, void 0, function () {
978
- var fragment, _a, element;
1433
+ var html, body, snapshot, _a, renderer, error_1;
979
1434
  return __generator(this, function (_b) {
980
1435
  switch (_b.label) {
981
1436
  case 0:
982
- _a = fragmentFromHTML;
1437
+ _b.trys.push([0, 5, , 6]);
983
1438
  return [4, response.responseHTML];
984
1439
  case 1:
985
- fragment = _a.apply(void 0, [_b.sent()]);
986
- if (!fragment) return [3, 5];
987
- return [4, this.extractForeignFrameElement(fragment)];
1440
+ html = _b.sent();
1441
+ if (!html) return [3, 4];
1442
+ body = parseHTMLDocument(html).body;
1443
+ _a = Snapshot.bind;
1444
+ return [4, this.extractForeignFrameElement(body)];
988
1445
  case 2:
989
- element = _b.sent();
990
- return [4, nextAnimationFrame()];
1446
+ snapshot = new (_a.apply(Snapshot, [void 0, _b.sent()]))();
1447
+ renderer = new FrameRenderer(this.view.snapshot, snapshot, false);
1448
+ return [4, this.view.render(renderer)];
991
1449
  case 3:
992
1450
  _b.sent();
993
- this.loadFrameElement(element);
994
- this.scrollFrameIntoView(element);
995
- return [4, nextAnimationFrame()];
996
- case 4:
997
- _b.sent();
998
- this.focusFirstAutofocusableElement();
999
- _b.label = 5;
1000
- case 5: return [2];
1451
+ _b.label = 4;
1452
+ case 4: return [3, 6];
1453
+ case 5:
1454
+ error_1 = _b.sent();
1455
+ console.error(error_1);
1456
+ this.view.invalidate();
1457
+ return [3, 6];
1458
+ case 6: return [2];
1001
1459
  }
1002
1460
  });
1003
1461
  });
@@ -1020,14 +1478,14 @@ Copyright © 2021 Basecamp, LLC
1020
1478
  }
1021
1479
  this.formSubmission = new FormSubmission(this, element, submitter);
1022
1480
  if (this.formSubmission.fetchRequest.isIdempotent) {
1023
- this.navigateFrame(element, this.formSubmission.fetchRequest.url);
1481
+ this.navigateFrame(element, this.formSubmission.fetchRequest.url.href);
1024
1482
  }
1025
1483
  else {
1026
1484
  this.formSubmission.start();
1027
1485
  }
1028
1486
  };
1029
- FrameController.prototype.additionalHeadersForRequest = function (request) {
1030
- return { "Turbo-Frame": this.id };
1487
+ FrameController.prototype.prepareHeadersForRequest = function (headers, request) {
1488
+ headers["Turbo-Frame"] = this.id;
1031
1489
  };
1032
1490
  FrameController.prototype.requestStarted = function (request) {
1033
1491
  this.element.setAttribute("busy", "");
@@ -1072,13 +1530,18 @@ Copyright © 2021 Basecamp, LLC
1072
1530
  };
1073
1531
  FrameController.prototype.formSubmissionFinished = function (formSubmission) {
1074
1532
  };
1533
+ FrameController.prototype.viewWillRenderSnapshot = function (snapshot, isPreview) {
1534
+ };
1535
+ FrameController.prototype.viewRenderedSnapshot = function (snapshot, isPreview) {
1536
+ };
1537
+ FrameController.prototype.viewInvalidated = function () {
1538
+ };
1075
1539
  FrameController.prototype.visit = function (url) {
1076
1540
  return __awaiter(this, void 0, void 0, function () {
1077
- var location, request;
1541
+ var request;
1078
1542
  var _this = this;
1079
1543
  return __generator(this, function (_a) {
1080
- location = Location.wrap(url);
1081
- request = new FetchRequest(this, FetchMethod.get, location);
1544
+ request = new FetchRequest(this, FetchMethod.get, expandURL(url));
1082
1545
  return [2, new Promise(function (resolve) {
1083
1546
  _this.resolveVisitPromise = function () {
1084
1547
  _this.resolveVisitPromise = function () { };
@@ -1095,7 +1558,7 @@ Copyright © 2021 Basecamp, LLC
1095
1558
  };
1096
1559
  FrameController.prototype.findFrameElement = function (element) {
1097
1560
  var _a;
1098
- var id = element.getAttribute("data-turbo-frame");
1561
+ var id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
1099
1562
  return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
1100
1563
  };
1101
1564
  FrameController.prototype.extractForeignFrameElement = function (container) {
@@ -1121,36 +1584,6 @@ Copyright © 2021 Basecamp, LLC
1121
1584
  });
1122
1585
  });
1123
1586
  };
1124
- FrameController.prototype.loadFrameElement = function (frameElement) {
1125
- var _a;
1126
- var destinationRange = document.createRange();
1127
- destinationRange.selectNodeContents(this.element);
1128
- destinationRange.deleteContents();
1129
- var sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange();
1130
- if (sourceRange) {
1131
- sourceRange.selectNodeContents(frameElement);
1132
- this.element.appendChild(sourceRange.extractContents());
1133
- }
1134
- };
1135
- FrameController.prototype.focusFirstAutofocusableElement = function () {
1136
- var element = this.firstAutofocusableElement;
1137
- if (element) {
1138
- element.focus();
1139
- return true;
1140
- }
1141
- return false;
1142
- };
1143
- FrameController.prototype.scrollFrameIntoView = function (frame) {
1144
- if (this.element.autoscroll || frame.autoscroll) {
1145
- var element = this.element.firstElementChild;
1146
- var block = readScrollLogicalPosition(this.element.getAttribute("data-autoscroll-block"), "end");
1147
- if (element) {
1148
- element.scrollIntoView({ block: block });
1149
- return true;
1150
- }
1151
- }
1152
- return false;
1153
- };
1154
1587
  FrameController.prototype.shouldInterceptNavigation = function (element) {
1155
1588
  var id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
1156
1589
  if (!this.enabled || id == "_top") {
@@ -1164,14 +1597,6 @@ Copyright © 2021 Basecamp, LLC
1164
1597
  }
1165
1598
  return true;
1166
1599
  };
1167
- Object.defineProperty(FrameController.prototype, "firstAutofocusableElement", {
1168
- get: function () {
1169
- var element = this.element.querySelector("[autofocus]");
1170
- return element instanceof HTMLElement ? element : null;
1171
- },
1172
- enumerable: false,
1173
- configurable: true
1174
- });
1175
1600
  Object.defineProperty(FrameController.prototype, "id", {
1176
1601
  get: function () {
1177
1602
  return this.element.id;
@@ -1224,20 +1649,6 @@ Copyright © 2021 Basecamp, LLC
1224
1649
  }
1225
1650
  }
1226
1651
  }
1227
- function readScrollLogicalPosition(value, defaultValue) {
1228
- if (value == "end" || value == "start" || value == "center" || value == "nearest") {
1229
- return value;
1230
- }
1231
- else {
1232
- return defaultValue;
1233
- }
1234
- }
1235
- function fragmentFromHTML(html) {
1236
- if (html) {
1237
- var foreignDocument = document.implementation.createHTMLDocument();
1238
- return foreignDocument.createRange().createContextualFragment(html);
1239
- }
1240
- }
1241
1652
  function activateElement(element) {
1242
1653
  if (element && element.ownerDocument !== document) {
1243
1654
  element = document.importNode(element, true);
@@ -1516,9 +1927,11 @@ Copyright © 2021 Basecamp, LLC
1516
1927
  }());
1517
1928
  var templateObject_1$1;
1518
1929
 
1519
- var HeadDetails = (function () {
1520
- function HeadDetails(children) {
1521
- this.detailsByOuterHTML = children.reduce(function (result, element) {
1930
+ var HeadSnapshot = (function (_super) {
1931
+ __extends(HeadSnapshot, _super);
1932
+ function HeadSnapshot() {
1933
+ var _this = _super !== null && _super.apply(this, arguments) || this;
1934
+ _this.detailsByOuterHTML = _this.children.reduce(function (result, element) {
1522
1935
  var _a;
1523
1936
  var outerHTML = element.outerHTML;
1524
1937
  var details = outerHTML in result
@@ -1530,27 +1943,28 @@ Copyright © 2021 Basecamp, LLC
1530
1943
  };
1531
1944
  return __assign(__assign({}, result), (_a = {}, _a[outerHTML] = __assign(__assign({}, details), { elements: __spread(details.elements, [element]) }), _a));
1532
1945
  }, {});
1946
+ return _this;
1533
1947
  }
1534
- HeadDetails.fromHeadElement = function (headElement) {
1535
- var children = headElement ? __spread(headElement.children) : [];
1536
- return new this(children);
1537
- };
1538
- HeadDetails.prototype.getTrackedElementSignature = function () {
1539
- var _this = this;
1540
- return Object.keys(this.detailsByOuterHTML)
1541
- .filter(function (outerHTML) { return _this.detailsByOuterHTML[outerHTML].tracked; })
1542
- .join("");
1543
- };
1544
- HeadDetails.prototype.getScriptElementsNotInDetails = function (headDetails) {
1545
- return this.getElementsMatchingTypeNotInDetails("script", headDetails);
1948
+ Object.defineProperty(HeadSnapshot.prototype, "trackedElementSignature", {
1949
+ get: function () {
1950
+ var _this = this;
1951
+ return Object.keys(this.detailsByOuterHTML)
1952
+ .filter(function (outerHTML) { return _this.detailsByOuterHTML[outerHTML].tracked; })
1953
+ .join("");
1954
+ },
1955
+ enumerable: false,
1956
+ configurable: true
1957
+ });
1958
+ HeadSnapshot.prototype.getScriptElementsNotInSnapshot = function (snapshot) {
1959
+ return this.getElementsMatchingTypeNotInSnapshot("script", snapshot);
1546
1960
  };
1547
- HeadDetails.prototype.getStylesheetElementsNotInDetails = function (headDetails) {
1548
- return this.getElementsMatchingTypeNotInDetails("stylesheet", headDetails);
1961
+ HeadSnapshot.prototype.getStylesheetElementsNotInSnapshot = function (snapshot) {
1962
+ return this.getElementsMatchingTypeNotInSnapshot("stylesheet", snapshot);
1549
1963
  };
1550
- HeadDetails.prototype.getElementsMatchingTypeNotInDetails = function (matchedType, headDetails) {
1964
+ HeadSnapshot.prototype.getElementsMatchingTypeNotInSnapshot = function (matchedType, snapshot) {
1551
1965
  var _this = this;
1552
1966
  return Object.keys(this.detailsByOuterHTML)
1553
- .filter(function (outerHTML) { return !(outerHTML in headDetails.detailsByOuterHTML); })
1967
+ .filter(function (outerHTML) { return !(outerHTML in snapshot.detailsByOuterHTML); })
1554
1968
  .map(function (outerHTML) { return _this.detailsByOuterHTML[outerHTML]; })
1555
1969
  .filter(function (_a) {
1556
1970
  var type = _a.type;
@@ -1561,138 +1975,134 @@ Copyright © 2021 Basecamp, LLC
1561
1975
  return element;
1562
1976
  });
1563
1977
  };
1564
- HeadDetails.prototype.getProvisionalElements = function () {
1565
- var _this = this;
1566
- return Object.keys(this.detailsByOuterHTML).reduce(function (result, outerHTML) {
1567
- var _a = _this.detailsByOuterHTML[outerHTML], type = _a.type, tracked = _a.tracked, elements = _a.elements;
1568
- if (type == null && !tracked) {
1569
- return __spread(result, elements);
1570
- }
1571
- else if (elements.length > 1) {
1572
- return __spread(result, elements.slice(1));
1573
- }
1574
- else {
1575
- return result;
1576
- }
1577
- }, []);
1578
- };
1579
- HeadDetails.prototype.getMetaValue = function (name) {
1978
+ Object.defineProperty(HeadSnapshot.prototype, "provisionalElements", {
1979
+ get: function () {
1980
+ var _this = this;
1981
+ return Object.keys(this.detailsByOuterHTML).reduce(function (result, outerHTML) {
1982
+ var _a = _this.detailsByOuterHTML[outerHTML], type = _a.type, tracked = _a.tracked, elements = _a.elements;
1983
+ if (type == null && !tracked) {
1984
+ return __spread(result, elements);
1985
+ }
1986
+ else if (elements.length > 1) {
1987
+ return __spread(result, elements.slice(1));
1988
+ }
1989
+ else {
1990
+ return result;
1991
+ }
1992
+ }, []);
1993
+ },
1994
+ enumerable: false,
1995
+ configurable: true
1996
+ });
1997
+ HeadSnapshot.prototype.getMetaValue = function (name) {
1580
1998
  var element = this.findMetaElementByName(name);
1581
1999
  return element
1582
2000
  ? element.getAttribute("content")
1583
2001
  : null;
1584
2002
  };
1585
- HeadDetails.prototype.findMetaElementByName = function (name) {
2003
+ HeadSnapshot.prototype.findMetaElementByName = function (name) {
1586
2004
  var _this = this;
1587
2005
  return Object.keys(this.detailsByOuterHTML).reduce(function (result, outerHTML) {
1588
2006
  var _a = __read(_this.detailsByOuterHTML[outerHTML].elements, 1), element = _a[0];
1589
2007
  return elementIsMetaElementWithName(element, name) ? element : result;
1590
2008
  }, undefined);
1591
2009
  };
1592
- return HeadDetails;
1593
- }());
2010
+ return HeadSnapshot;
2011
+ }(Snapshot));
1594
2012
  function elementType(element) {
1595
2013
  if (elementIsScript(element)) {
1596
2014
  return "script";
1597
- }
1598
- else if (elementIsStylesheet(element)) {
1599
- return "stylesheet";
1600
- }
1601
- }
1602
- function elementIsTracked(element) {
1603
- return element.getAttribute("data-turbo-track") == "reload";
1604
- }
1605
- function elementIsScript(element) {
1606
- var tagName = element.tagName.toLowerCase();
1607
- return tagName == "script";
1608
- }
1609
- function elementIsStylesheet(element) {
1610
- var tagName = element.tagName.toLowerCase();
1611
- return tagName == "style" || (tagName == "link" && element.getAttribute("rel") == "stylesheet");
1612
- }
1613
- function elementIsMetaElementWithName(element, name) {
1614
- var tagName = element.tagName.toLowerCase();
1615
- return tagName == "meta" && element.getAttribute("name") == name;
1616
- }
1617
-
1618
- var Snapshot = (function () {
1619
- function Snapshot(headDetails, bodyElement) {
1620
- this.headDetails = headDetails;
1621
- this.bodyElement = bodyElement;
1622
- }
1623
- Snapshot.wrap = function (value) {
1624
- if (value instanceof this) {
1625
- return value;
1626
- }
1627
- else if (typeof value == "string") {
1628
- return this.fromHTMLString(value);
1629
- }
1630
- else {
1631
- return this.fromHTMLElement(value);
1632
- }
1633
- };
1634
- Snapshot.fromHTMLString = function (html) {
1635
- var documentElement = new DOMParser().parseFromString(html, "text/html").documentElement;
1636
- return this.fromHTMLElement(documentElement);
1637
- };
1638
- Snapshot.fromHTMLElement = function (htmlElement) {
1639
- var headElement = htmlElement.querySelector("head");
1640
- var bodyElement = htmlElement.querySelector("body") || document.createElement("body");
1641
- var headDetails = HeadDetails.fromHeadElement(headElement);
1642
- return new this(headDetails, bodyElement);
1643
- };
1644
- Snapshot.prototype.clone = function () {
1645
- var bodyElement = Snapshot.fromHTMLString(this.bodyElement.outerHTML).bodyElement;
1646
- return new Snapshot(this.headDetails, bodyElement);
1647
- };
1648
- Snapshot.prototype.getRootLocation = function () {
1649
- var root = this.getSetting("root", "/");
1650
- return new Location(root);
1651
- };
1652
- Snapshot.prototype.getCacheControlValue = function () {
1653
- return this.getSetting("cache-control");
1654
- };
1655
- Snapshot.prototype.getElementForAnchor = function (anchor) {
1656
- try {
1657
- return this.bodyElement.querySelector("[id='" + anchor + "'], a[name='" + anchor + "']");
1658
- }
1659
- catch (_a) {
1660
- return null;
1661
- }
1662
- };
1663
- Snapshot.prototype.getPermanentElements = function () {
1664
- return __spread(this.bodyElement.querySelectorAll("[id][data-turbo-permanent]"));
1665
- };
1666
- Snapshot.prototype.getPermanentElementById = function (id) {
1667
- return this.bodyElement.querySelector("#" + id + "[data-turbo-permanent]");
1668
- };
1669
- Snapshot.prototype.getPermanentElementsPresentInSnapshot = function (snapshot) {
1670
- return this.getPermanentElements().filter(function (_a) {
1671
- var id = _a.id;
1672
- return snapshot.getPermanentElementById(id);
1673
- });
1674
- };
1675
- Snapshot.prototype.findFirstAutofocusableElement = function () {
1676
- return this.bodyElement.querySelector("[autofocus]");
1677
- };
1678
- Snapshot.prototype.hasAnchor = function (anchor) {
1679
- return this.getElementForAnchor(anchor) != null;
2015
+ }
2016
+ else if (elementIsStylesheet(element)) {
2017
+ return "stylesheet";
2018
+ }
2019
+ }
2020
+ function elementIsTracked(element) {
2021
+ return element.getAttribute("data-turbo-track") == "reload";
2022
+ }
2023
+ function elementIsScript(element) {
2024
+ var tagName = element.tagName.toLowerCase();
2025
+ return tagName == "script";
2026
+ }
2027
+ function elementIsStylesheet(element) {
2028
+ var tagName = element.tagName.toLowerCase();
2029
+ return tagName == "style" || (tagName == "link" && element.getAttribute("rel") == "stylesheet");
2030
+ }
2031
+ function elementIsMetaElementWithName(element, name) {
2032
+ var tagName = element.tagName.toLowerCase();
2033
+ return tagName == "meta" && element.getAttribute("name") == name;
2034
+ }
2035
+
2036
+ var PageSnapshot = (function (_super) {
2037
+ __extends(PageSnapshot, _super);
2038
+ function PageSnapshot(element, headSnapshot) {
2039
+ var _this = _super.call(this, element) || this;
2040
+ _this.headSnapshot = headSnapshot;
2041
+ return _this;
2042
+ }
2043
+ PageSnapshot.fromHTMLString = function (html) {
2044
+ if (html === void 0) { html = ""; }
2045
+ return this.fromDocument(parseHTMLDocument(html));
1680
2046
  };
1681
- Snapshot.prototype.isPreviewable = function () {
1682
- return this.getCacheControlValue() != "no-preview";
2047
+ PageSnapshot.fromElement = function (element) {
2048
+ return this.fromDocument(element.ownerDocument);
1683
2049
  };
1684
- Snapshot.prototype.isCacheable = function () {
1685
- return this.getCacheControlValue() != "no-cache";
2050
+ PageSnapshot.fromDocument = function (_a) {
2051
+ var head = _a.head, body = _a.body;
2052
+ return new this(body, new HeadSnapshot(head));
1686
2053
  };
1687
- Snapshot.prototype.isVisitable = function () {
1688
- return this.getSetting("visit-control") != "reload";
2054
+ PageSnapshot.prototype.clone = function () {
2055
+ return new PageSnapshot(this.element.cloneNode(true), this.headSnapshot);
1689
2056
  };
1690
- Snapshot.prototype.getSetting = function (name, defaultValue) {
1691
- var value = this.headDetails.getMetaValue("turbo-" + name);
1692
- return value == null ? defaultValue : value;
2057
+ Object.defineProperty(PageSnapshot.prototype, "headElement", {
2058
+ get: function () {
2059
+ return this.headSnapshot.element;
2060
+ },
2061
+ enumerable: false,
2062
+ configurable: true
2063
+ });
2064
+ Object.defineProperty(PageSnapshot.prototype, "rootLocation", {
2065
+ get: function () {
2066
+ var _a;
2067
+ var root = (_a = this.getSetting("root")) !== null && _a !== void 0 ? _a : "/";
2068
+ return expandURL(root);
2069
+ },
2070
+ enumerable: false,
2071
+ configurable: true
2072
+ });
2073
+ Object.defineProperty(PageSnapshot.prototype, "cacheControlValue", {
2074
+ get: function () {
2075
+ return this.getSetting("cache-control");
2076
+ },
2077
+ enumerable: false,
2078
+ configurable: true
2079
+ });
2080
+ Object.defineProperty(PageSnapshot.prototype, "isPreviewable", {
2081
+ get: function () {
2082
+ return this.cacheControlValue != "no-preview";
2083
+ },
2084
+ enumerable: false,
2085
+ configurable: true
2086
+ });
2087
+ Object.defineProperty(PageSnapshot.prototype, "isCacheable", {
2088
+ get: function () {
2089
+ return this.cacheControlValue != "no-cache";
2090
+ },
2091
+ enumerable: false,
2092
+ configurable: true
2093
+ });
2094
+ Object.defineProperty(PageSnapshot.prototype, "isVisitable", {
2095
+ get: function () {
2096
+ return this.getSetting("visit-control") != "reload";
2097
+ },
2098
+ enumerable: false,
2099
+ configurable: true
2100
+ });
2101
+ PageSnapshot.prototype.getSetting = function (name) {
2102
+ return this.headSnapshot.getMetaValue("turbo-" + name);
1693
2103
  };
1694
- return Snapshot;
1695
- }());
2104
+ return PageSnapshot;
2105
+ }(Snapshot));
1696
2106
 
1697
2107
  var TimingMetric;
1698
2108
  (function (TimingMetric) {
@@ -1721,7 +2131,6 @@ Copyright © 2021 Basecamp, LLC
1721
2131
  })(SystemStatusCode || (SystemStatusCode = {}));
1722
2132
  var Visit = (function () {
1723
2133
  function Visit(delegate, location, restorationIdentifier, options) {
1724
- var _this = this;
1725
2134
  if (options === void 0) { options = {}; }
1726
2135
  this.identifier = uuid();
1727
2136
  this.timingMetrics = {};
@@ -1730,17 +2139,6 @@ Copyright © 2021 Basecamp, LLC
1730
2139
  this.scrolled = false;
1731
2140
  this.snapshotCached = false;
1732
2141
  this.state = VisitState.initialized;
1733
- this.performScroll = function () {
1734
- if (!_this.scrolled) {
1735
- if (_this.action == "restore") {
1736
- _this.scrollToRestoredPosition() || _this.scrollToTop();
1737
- }
1738
- else {
1739
- _this.scrollToAnchor() || _this.scrollToTop();
1740
- }
1741
- _this.scrolled = true;
1742
- }
1743
- };
1744
2142
  this.delegate = delegate;
1745
2143
  this.location = location;
1746
2144
  this.restorationIdentifier = restorationIdentifier || uuid();
@@ -1811,8 +2209,9 @@ Copyright © 2021 Basecamp, LLC
1811
2209
  }
1812
2210
  };
1813
2211
  Visit.prototype.changeHistory = function () {
2212
+ var _a;
1814
2213
  if (!this.historyChanged) {
1815
- var actionForHistory = this.location.isEqualTo(this.referrer) ? "replace" : this.action;
2214
+ var actionForHistory = this.location.href === ((_a = this.referrer) === null || _a === void 0 ? void 0 : _a.href) ? "replace" : this.action;
1816
2215
  var method = this.getHistoryMethodForAction(actionForHistory);
1817
2216
  this.history.update(method, this.location, this.restorationIdentifier);
1818
2217
  this.historyChanged = true;
@@ -1859,32 +2258,41 @@ Copyright © 2021 Basecamp, LLC
1859
2258
  var _this = this;
1860
2259
  if (this.response) {
1861
2260
  var _a = this.response, statusCode_1 = _a.statusCode, responseHTML_1 = _a.responseHTML;
1862
- this.render(function () {
1863
- _this.cacheSnapshot();
1864
- if (isSuccessful(statusCode_1) && responseHTML_1 != null) {
1865
- _this.view.render({ snapshot: Snapshot.fromHTMLString(responseHTML_1) }, _this.performScroll);
1866
- _this.adapter.visitRendered(_this);
1867
- _this.complete();
1868
- }
1869
- else {
1870
- _this.view.render({ error: responseHTML_1 }, _this.performScroll);
1871
- _this.adapter.visitRendered(_this);
1872
- _this.fail();
1873
- }
1874
- });
2261
+ this.render(function () { return __awaiter(_this, void 0, void 0, function () {
2262
+ return __generator(this, function (_a) {
2263
+ switch (_a.label) {
2264
+ case 0:
2265
+ this.cacheSnapshot();
2266
+ if (!(isSuccessful(statusCode_1) && responseHTML_1 != null)) return [3, 2];
2267
+ return [4, this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML_1))];
2268
+ case 1:
2269
+ _a.sent();
2270
+ this.adapter.visitRendered(this);
2271
+ this.complete();
2272
+ return [3, 4];
2273
+ case 2: return [4, this.view.renderError(PageSnapshot.fromHTMLString(responseHTML_1))];
2274
+ case 3:
2275
+ _a.sent();
2276
+ this.adapter.visitRendered(this);
2277
+ this.fail();
2278
+ _a.label = 4;
2279
+ case 4: return [2];
2280
+ }
2281
+ });
2282
+ }); });
1875
2283
  }
1876
2284
  };
1877
2285
  Visit.prototype.getCachedSnapshot = function () {
1878
2286
  var snapshot = this.view.getCachedSnapshotForLocation(this.location) || this.getPreloadedSnapshot();
1879
- if (snapshot && (!this.location.anchor || snapshot.hasAnchor(this.location.anchor))) {
1880
- if (this.action == "restore" || snapshot.isPreviewable()) {
2287
+ if (snapshot && (!getAnchor(this.location) || snapshot.hasAnchor(getAnchor(this.location)))) {
2288
+ if (this.action == "restore" || snapshot.isPreviewable) {
1881
2289
  return snapshot;
1882
2290
  }
1883
2291
  }
1884
2292
  };
1885
2293
  Visit.prototype.getPreloadedSnapshot = function () {
1886
2294
  if (this.snapshotHTML) {
1887
- return Snapshot.wrap(this.snapshotHTML);
2295
+ return PageSnapshot.fromHTMLString(this.snapshotHTML);
1888
2296
  }
1889
2297
  };
1890
2298
  Visit.prototype.hasCachedSnapshot = function () {
@@ -1895,14 +2303,22 @@ Copyright © 2021 Basecamp, LLC
1895
2303
  var snapshot = this.getCachedSnapshot();
1896
2304
  if (snapshot) {
1897
2305
  var isPreview_1 = this.shouldIssueRequest();
1898
- this.render(function () {
1899
- _this.cacheSnapshot();
1900
- _this.view.render({ snapshot: snapshot, isPreview: isPreview_1 }, _this.performScroll);
1901
- _this.adapter.visitRendered(_this);
1902
- if (!isPreview_1) {
1903
- _this.complete();
1904
- }
1905
- });
2306
+ this.render(function () { return __awaiter(_this, void 0, void 0, function () {
2307
+ return __generator(this, function (_a) {
2308
+ switch (_a.label) {
2309
+ case 0:
2310
+ this.cacheSnapshot();
2311
+ return [4, this.view.renderPage(snapshot)];
2312
+ case 1:
2313
+ _a.sent();
2314
+ this.adapter.visitRendered(this);
2315
+ if (!isPreview_1) {
2316
+ this.complete();
2317
+ }
2318
+ return [2];
2319
+ }
2320
+ });
2321
+ }); });
1906
2322
  }
1907
2323
  };
1908
2324
  Visit.prototype.followRedirect = function () {
@@ -1962,6 +2378,17 @@ Copyright © 2021 Basecamp, LLC
1962
2378
  Visit.prototype.requestFinished = function () {
1963
2379
  this.finishRequest();
1964
2380
  };
2381
+ Visit.prototype.performScroll = function () {
2382
+ if (!this.scrolled) {
2383
+ if (this.action == "restore") {
2384
+ this.scrollToRestoredPosition() || this.scrollToTop();
2385
+ }
2386
+ else {
2387
+ this.scrollToAnchor() || this.scrollToTop();
2388
+ }
2389
+ this.scrolled = true;
2390
+ }
2391
+ };
1965
2392
  Visit.prototype.scrollToRestoredPosition = function () {
1966
2393
  var scrollPosition = this.restorationData.scrollPosition;
1967
2394
  if (scrollPosition) {
@@ -1970,8 +2397,8 @@ Copyright © 2021 Basecamp, LLC
1970
2397
  }
1971
2398
  };
1972
2399
  Visit.prototype.scrollToAnchor = function () {
1973
- if (this.location.anchor != null) {
1974
- this.view.scrollToAnchor(this.location.anchor);
2400
+ if (getAnchor(this.location) != null) {
2401
+ this.view.scrollToAnchor(getAnchor(this.location));
1975
2402
  return true;
1976
2403
  }
1977
2404
  };
@@ -2006,11 +2433,23 @@ Copyright © 2021 Basecamp, LLC
2006
2433
  }
2007
2434
  };
2008
2435
  Visit.prototype.render = function (callback) {
2009
- var _this = this;
2010
- this.cancelRender();
2011
- this.frame = requestAnimationFrame(function () {
2012
- delete _this.frame;
2013
- callback.call(_this);
2436
+ return __awaiter(this, void 0, void 0, function () {
2437
+ var _this = this;
2438
+ return __generator(this, function (_a) {
2439
+ switch (_a.label) {
2440
+ case 0:
2441
+ this.cancelRender();
2442
+ return [4, new Promise(function (resolve) {
2443
+ _this.frame = requestAnimationFrame(function () { return resolve(); });
2444
+ })];
2445
+ case 1:
2446
+ _a.sent();
2447
+ callback();
2448
+ delete this.frame;
2449
+ this.performScroll();
2450
+ return [2];
2451
+ }
2452
+ });
2014
2453
  });
2015
2454
  };
2016
2455
  Visit.prototype.cancelRender = function () {
@@ -2198,11 +2637,10 @@ Copyright © 2021 Basecamp, LLC
2198
2637
  if (_this.shouldHandlePopState()) {
2199
2638
  var turbo = (event.state || {}).turbo;
2200
2639
  if (turbo) {
2201
- var location_1 = Location.currentLocation;
2202
- _this.location = location_1;
2640
+ _this.location = new URL(window.location.href);
2203
2641
  var restorationIdentifier = turbo.restorationIdentifier;
2204
2642
  _this.restorationIdentifier = restorationIdentifier;
2205
- _this.delegate.historyPoppedToLocationWithRestorationIdentifier(location_1, restorationIdentifier);
2643
+ _this.delegate.historyPoppedToLocationWithRestorationIdentifier(_this.location, restorationIdentifier);
2206
2644
  }
2207
2645
  }
2208
2646
  };
@@ -2224,7 +2662,7 @@ Copyright © 2021 Basecamp, LLC
2224
2662
  addEventListener("popstate", this.onPopState, false);
2225
2663
  addEventListener("load", this.onPageLoad, false);
2226
2664
  this.started = true;
2227
- this.replace(Location.currentLocation);
2665
+ this.replace(new URL(window.location.href));
2228
2666
  }
2229
2667
  };
2230
2668
  History.prototype.stop = function () {
@@ -2243,7 +2681,7 @@ Copyright © 2021 Basecamp, LLC
2243
2681
  History.prototype.update = function (method, location, restorationIdentifier) {
2244
2682
  if (restorationIdentifier === void 0) { restorationIdentifier = uuid(); }
2245
2683
  var state = { turbo: { restorationIdentifier: restorationIdentifier } };
2246
- method.call(history, state, "", location.absoluteURL);
2684
+ method.call(history, state, "", location.href);
2247
2685
  this.location = location;
2248
2686
  this.restorationIdentifier = restorationIdentifier;
2249
2687
  };
@@ -2326,7 +2764,7 @@ Copyright © 2021 Basecamp, LLC
2326
2764
  }
2327
2765
  };
2328
2766
  LinkClickObserver.prototype.getLocationForLink = function (link) {
2329
- return new Location(link.getAttribute("href") || "");
2767
+ return expandURL(link.getAttribute("href") || "");
2330
2768
  };
2331
2769
  return LinkClickObserver;
2332
2770
  }());
@@ -2341,16 +2779,21 @@ Copyright © 2021 Basecamp, LLC
2341
2779
  this.delegate.visitProposedToLocation(location, options);
2342
2780
  }
2343
2781
  };
2344
- Navigator.prototype.startVisit = function (location, restorationIdentifier, options) {
2782
+ Navigator.prototype.startVisit = function (locatable, restorationIdentifier, options) {
2345
2783
  if (options === void 0) { options = {}; }
2346
2784
  this.stop();
2347
- this.currentVisit = new Visit(this, Location.wrap(location), restorationIdentifier, __assign({ referrer: this.location }, options));
2785
+ this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, __assign({ referrer: this.location }, options));
2348
2786
  this.currentVisit.start();
2349
2787
  };
2350
2788
  Navigator.prototype.submitForm = function (form, submitter) {
2351
2789
  this.stop();
2352
2790
  this.formSubmission = new FormSubmission(this, form, submitter, true);
2353
- this.formSubmission.start();
2791
+ if (this.formSubmission.fetchRequest.isIdempotent) {
2792
+ this.proposeVisit(this.formSubmission.fetchRequest.url);
2793
+ }
2794
+ else {
2795
+ this.formSubmission.start();
2796
+ }
2354
2797
  };
2355
2798
  Navigator.prototype.stop = function () {
2356
2799
  if (this.formSubmission) {
@@ -2417,12 +2860,14 @@ Copyright © 2021 Basecamp, LLC
2417
2860
  case 0: return [4, fetchResponse.responseHTML];
2418
2861
  case 1:
2419
2862
  responseHTML = _a.sent();
2420
- if (responseHTML) {
2421
- snapshot = Snapshot.fromHTMLString(responseHTML);
2422
- this.view.render({ snapshot: snapshot }, function () { });
2423
- this.view.clearSnapshotCache();
2424
- }
2425
- return [2];
2863
+ if (!responseHTML) return [3, 3];
2864
+ snapshot = PageSnapshot.fromHTMLString(responseHTML);
2865
+ return [4, this.view.renderPage(snapshot)];
2866
+ case 2:
2867
+ _a.sent();
2868
+ this.view.clearSnapshotCache();
2869
+ _a.label = 3;
2870
+ case 3: return [2];
2426
2871
  }
2427
2872
  });
2428
2873
  });
@@ -2548,78 +2993,11 @@ Copyright © 2021 Basecamp, LLC
2548
2993
  return ScrollObserver;
2549
2994
  }());
2550
2995
 
2551
- var StreamMessage = (function () {
2552
- function StreamMessage(html) {
2553
- this.templateElement = document.createElement("template");
2554
- this.templateElement.innerHTML = html;
2555
- }
2556
- StreamMessage.wrap = function (message) {
2557
- if (typeof message == "string") {
2558
- return new this(message);
2559
- }
2560
- else {
2561
- return message;
2562
- }
2563
- };
2564
- Object.defineProperty(StreamMessage.prototype, "fragment", {
2565
- get: function () {
2566
- var e_1, _a;
2567
- var fragment = document.createDocumentFragment();
2568
- try {
2569
- for (var _b = __values(this.foreignElements), _c = _b.next(); !_c.done; _c = _b.next()) {
2570
- var element = _c.value;
2571
- fragment.appendChild(document.importNode(element, true));
2572
- }
2573
- }
2574
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2575
- finally {
2576
- try {
2577
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2578
- }
2579
- finally { if (e_1) throw e_1.error; }
2580
- }
2581
- return fragment;
2582
- },
2583
- enumerable: false,
2584
- configurable: true
2585
- });
2586
- Object.defineProperty(StreamMessage.prototype, "foreignElements", {
2587
- get: function () {
2588
- return this.templateChildren.reduce(function (streamElements, child) {
2589
- if (child.tagName.toLowerCase() == "turbo-stream") {
2590
- return __spread(streamElements, [child]);
2591
- }
2592
- else {
2593
- return streamElements;
2594
- }
2595
- }, []);
2596
- },
2597
- enumerable: false,
2598
- configurable: true
2599
- });
2600
- Object.defineProperty(StreamMessage.prototype, "templateChildren", {
2601
- get: function () {
2602
- return Array.from(this.templateElement.content.children);
2603
- },
2604
- enumerable: false,
2605
- configurable: true
2606
- });
2607
- return StreamMessage;
2608
- }());
2609
-
2610
2996
  var StreamObserver = (function () {
2611
2997
  function StreamObserver(delegate) {
2612
2998
  var _this = this;
2613
2999
  this.sources = new Set;
2614
3000
  this.started = false;
2615
- this.prepareFetchRequest = (function (event) {
2616
- var _a;
2617
- var fetchOptions = (_a = event.detail) === null || _a === void 0 ? void 0 : _a.fetchOptions;
2618
- if (fetchOptions) {
2619
- var headers = fetchOptions.headers;
2620
- headers.Accept = ["text/vnd.turbo-stream.html", headers.Accept].join(", ");
2621
- }
2622
- });
2623
3001
  this.inspectFetchResponse = (function (event) {
2624
3002
  var response = fetchResponseFromEvent(event);
2625
3003
  if (response && fetchResponseIsStream(response)) {
@@ -2637,14 +3015,12 @@ Copyright © 2021 Basecamp, LLC
2637
3015
  StreamObserver.prototype.start = function () {
2638
3016
  if (!this.started) {
2639
3017
  this.started = true;
2640
- addEventListener("turbo:before-fetch-request", this.prepareFetchRequest, true);
2641
3018
  addEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false);
2642
3019
  }
2643
3020
  };
2644
3021
  StreamObserver.prototype.stop = function () {
2645
3022
  if (this.started) {
2646
3023
  this.started = false;
2647
- removeEventListener("turbo:before-fetch-request", this.prepareFetchRequest, true);
2648
3024
  removeEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false);
2649
3025
  }
2650
3026
  };
@@ -2694,155 +3070,42 @@ Copyright © 2021 Basecamp, LLC
2694
3070
  function fetchResponseIsStream(response) {
2695
3071
  var _a;
2696
3072
  var contentType = (_a = response.contentType) !== null && _a !== void 0 ? _a : "";
2697
- return /^text\/vnd\.turbo-stream\.html\b/.test(contentType);
3073
+ return contentType.startsWith(StreamMessage.contentType);
2698
3074
  }
2699
3075
 
2700
3076
  function isAction(action) {
2701
3077
  return action == "advance" || action == "replace" || action == "restore";
2702
3078
  }
2703
3079
 
2704
- var Renderer = (function () {
2705
- function Renderer() {
2706
- }
2707
- Renderer.prototype.renderView = function (callback) {
2708
- this.delegate.viewWillRender(this.newBody);
2709
- callback();
2710
- this.delegate.viewRendered(this.newBody);
2711
- };
2712
- Renderer.prototype.invalidateView = function () {
2713
- this.delegate.viewInvalidated();
2714
- };
2715
- Renderer.prototype.createScriptElement = function (element) {
2716
- if (element.getAttribute("data-turbo-eval") == "false") {
2717
- return element;
2718
- }
2719
- else {
2720
- var createdScriptElement = document.createElement("script");
2721
- createdScriptElement.textContent = element.textContent;
2722
- createdScriptElement.async = false;
2723
- copyElementAttributes(createdScriptElement, element);
2724
- return createdScriptElement;
2725
- }
2726
- };
2727
- return Renderer;
2728
- }());
2729
- function copyElementAttributes(destinationElement, sourceElement) {
2730
- var e_1, _a;
2731
- try {
2732
- for (var _b = __values(__spread(sourceElement.attributes)), _c = _b.next(); !_c.done; _c = _b.next()) {
2733
- var _d = _c.value, name_1 = _d.name, value = _d.value;
2734
- destinationElement.setAttribute(name_1, value);
2735
- }
2736
- }
2737
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2738
- finally {
2739
- try {
2740
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2741
- }
2742
- finally { if (e_1) throw e_1.error; }
2743
- }
2744
- }
2745
-
2746
3080
  var ErrorRenderer = (function (_super) {
2747
3081
  __extends(ErrorRenderer, _super);
2748
- function ErrorRenderer(delegate, html) {
2749
- var _this = _super.call(this) || this;
2750
- _this.delegate = delegate;
2751
- _this.htmlElement = (function () {
2752
- var htmlElement = document.createElement("html");
2753
- htmlElement.innerHTML = html;
2754
- return htmlElement;
2755
- })();
2756
- _this.newHead = _this.htmlElement.querySelector("head") || document.createElement("head");
2757
- _this.newBody = _this.htmlElement.querySelector("body") || document.createElement("body");
2758
- return _this;
2759
- }
2760
- ErrorRenderer.render = function (delegate, callback, html) {
2761
- return new this(delegate, html).render(callback);
2762
- };
2763
- ErrorRenderer.prototype.render = function (callback) {
2764
- var _this = this;
2765
- this.renderView(function () {
2766
- _this.replaceHeadAndBody();
2767
- _this.activateBodyScriptElements();
2768
- callback();
2769
- });
2770
- };
2771
- ErrorRenderer.prototype.replaceHeadAndBody = function () {
2772
- var documentElement = document.documentElement, head = document.head, body = document.body;
2773
- documentElement.replaceChild(this.newHead, head);
2774
- documentElement.replaceChild(this.newBody, body);
2775
- };
2776
- ErrorRenderer.prototype.activateBodyScriptElements = function () {
2777
- var e_1, _a;
2778
- try {
2779
- for (var _b = __values(this.getScriptElements()), _c = _b.next(); !_c.done; _c = _b.next()) {
2780
- var replaceableElement = _c.value;
2781
- var parentNode = replaceableElement.parentNode;
2782
- if (parentNode) {
2783
- var element = this.createScriptElement(replaceableElement);
2784
- parentNode.replaceChild(element, replaceableElement);
2785
- }
2786
- }
2787
- }
2788
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2789
- finally {
2790
- try {
2791
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2792
- }
2793
- finally { if (e_1) throw e_1.error; }
2794
- }
2795
- };
2796
- ErrorRenderer.prototype.getScriptElements = function () {
2797
- return __spread(document.documentElement.querySelectorAll("script"));
2798
- };
2799
- return ErrorRenderer;
2800
- }(Renderer));
2801
-
2802
- var SnapshotCache = (function () {
2803
- function SnapshotCache(size) {
2804
- this.keys = [];
2805
- this.snapshots = {};
2806
- this.size = size;
2807
- }
2808
- SnapshotCache.prototype.has = function (location) {
2809
- return location.toCacheKey() in this.snapshots;
2810
- };
2811
- SnapshotCache.prototype.get = function (location) {
2812
- if (this.has(location)) {
2813
- var snapshot = this.read(location);
2814
- this.touch(location);
2815
- return snapshot;
2816
- }
2817
- };
2818
- SnapshotCache.prototype.put = function (location, snapshot) {
2819
- this.write(location, snapshot);
2820
- this.touch(location);
2821
- return snapshot;
2822
- };
2823
- SnapshotCache.prototype.clear = function () {
2824
- this.snapshots = {};
2825
- };
2826
- SnapshotCache.prototype.read = function (location) {
2827
- return this.snapshots[location.toCacheKey()];
2828
- };
2829
- SnapshotCache.prototype.write = function (location, snapshot) {
2830
- this.snapshots[location.toCacheKey()] = snapshot;
3082
+ function ErrorRenderer() {
3083
+ return _super !== null && _super.apply(this, arguments) || this;
3084
+ }
3085
+ ErrorRenderer.prototype.render = function () {
3086
+ return __awaiter(this, void 0, void 0, function () {
3087
+ return __generator(this, function (_a) {
3088
+ this.replaceHeadAndBody();
3089
+ this.activateScriptElements();
3090
+ return [2];
3091
+ });
3092
+ });
2831
3093
  };
2832
- SnapshotCache.prototype.touch = function (location) {
2833
- var key = location.toCacheKey();
2834
- var index = this.keys.indexOf(key);
2835
- if (index > -1)
2836
- this.keys.splice(index, 1);
2837
- this.keys.unshift(key);
2838
- this.trim();
3094
+ ErrorRenderer.prototype.replaceHeadAndBody = function () {
3095
+ var documentElement = document.documentElement, head = document.head, body = document.body;
3096
+ documentElement.replaceChild(this.newHead, head);
3097
+ documentElement.replaceChild(this.newElement, body);
2839
3098
  };
2840
- SnapshotCache.prototype.trim = function () {
3099
+ ErrorRenderer.prototype.activateScriptElements = function () {
2841
3100
  var e_1, _a;
2842
3101
  try {
2843
- for (var _b = __values(this.keys.splice(this.size)), _c = _b.next(); !_c.done; _c = _b.next()) {
2844
- var key = _c.value;
2845
- delete this.snapshots[key];
3102
+ for (var _b = __values(this.scriptElements), _c = _b.next(); !_c.done; _c = _b.next()) {
3103
+ var replaceableElement = _c.value;
3104
+ var parentNode = replaceableElement.parentNode;
3105
+ if (parentNode) {
3106
+ var element = this.createScriptElement(replaceableElement);
3107
+ parentNode.replaceChild(element, replaceableElement);
3108
+ }
2846
3109
  }
2847
3110
  }
2848
3111
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
@@ -2853,63 +3116,97 @@ Copyright © 2021 Basecamp, LLC
2853
3116
  finally { if (e_1) throw e_1.error; }
2854
3117
  }
2855
3118
  };
2856
- return SnapshotCache;
2857
- }());
3119
+ Object.defineProperty(ErrorRenderer.prototype, "newHead", {
3120
+ get: function () {
3121
+ return this.newSnapshot.headSnapshot.element;
3122
+ },
3123
+ enumerable: false,
3124
+ configurable: true
3125
+ });
3126
+ Object.defineProperty(ErrorRenderer.prototype, "scriptElements", {
3127
+ get: function () {
3128
+ return __spread(document.documentElement.querySelectorAll("script"));
3129
+ },
3130
+ enumerable: false,
3131
+ configurable: true
3132
+ });
3133
+ return ErrorRenderer;
3134
+ }(Renderer));
2858
3135
 
2859
- var SnapshotRenderer = (function (_super) {
2860
- __extends(SnapshotRenderer, _super);
2861
- function SnapshotRenderer(delegate, currentSnapshot, newSnapshot, isPreview) {
2862
- var _this = _super.call(this) || this;
2863
- _this.delegate = delegate;
2864
- _this.currentSnapshot = currentSnapshot;
2865
- _this.currentHeadDetails = currentSnapshot.headDetails;
2866
- _this.newSnapshot = newSnapshot;
2867
- _this.newHeadDetails = newSnapshot.headDetails;
2868
- _this.newBody = newSnapshot.bodyElement;
2869
- _this.isPreview = isPreview;
2870
- return _this;
3136
+ var PageRenderer = (function (_super) {
3137
+ __extends(PageRenderer, _super);
3138
+ function PageRenderer() {
3139
+ return _super !== null && _super.apply(this, arguments) || this;
2871
3140
  }
2872
- SnapshotRenderer.render = function (delegate, callback, currentSnapshot, newSnapshot, isPreview) {
2873
- return new this(delegate, currentSnapshot, newSnapshot, isPreview).render(callback);
3141
+ Object.defineProperty(PageRenderer.prototype, "shouldRender", {
3142
+ get: function () {
3143
+ return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
3144
+ },
3145
+ enumerable: false,
3146
+ configurable: true
3147
+ });
3148
+ PageRenderer.prototype.prepareToRender = function () {
3149
+ this.mergeHead();
2874
3150
  };
2875
- SnapshotRenderer.prototype.render = function (callback) {
2876
- var _this = this;
2877
- if (this.shouldRender()) {
2878
- this.mergeHead();
2879
- this.renderView(function () {
2880
- _this.replaceBody();
2881
- if (!_this.isPreview) {
2882
- _this.focusFirstAutofocusableElement();
2883
- }
2884
- callback();
3151
+ PageRenderer.prototype.render = function () {
3152
+ return __awaiter(this, void 0, void 0, function () {
3153
+ return __generator(this, function (_a) {
3154
+ this.replaceBody();
3155
+ return [2];
2885
3156
  });
2886
- }
2887
- else {
2888
- this.invalidateView();
3157
+ });
3158
+ };
3159
+ PageRenderer.prototype.finishRendering = function () {
3160
+ _super.prototype.finishRendering.call(this);
3161
+ if (this.isPreview) {
3162
+ this.focusFirstAutofocusableElement();
2889
3163
  }
2890
3164
  };
2891
- SnapshotRenderer.prototype.mergeHead = function () {
3165
+ Object.defineProperty(PageRenderer.prototype, "currentHeadSnapshot", {
3166
+ get: function () {
3167
+ return this.currentSnapshot.headSnapshot;
3168
+ },
3169
+ enumerable: false,
3170
+ configurable: true
3171
+ });
3172
+ Object.defineProperty(PageRenderer.prototype, "newHeadSnapshot", {
3173
+ get: function () {
3174
+ return this.newSnapshot.headSnapshot;
3175
+ },
3176
+ enumerable: false,
3177
+ configurable: true
3178
+ });
3179
+ Object.defineProperty(PageRenderer.prototype, "newElement", {
3180
+ get: function () {
3181
+ return this.newSnapshot.element;
3182
+ },
3183
+ enumerable: false,
3184
+ configurable: true
3185
+ });
3186
+ PageRenderer.prototype.mergeHead = function () {
2892
3187
  this.copyNewHeadStylesheetElements();
2893
3188
  this.copyNewHeadScriptElements();
2894
3189
  this.removeCurrentHeadProvisionalElements();
2895
3190
  this.copyNewHeadProvisionalElements();
2896
3191
  };
2897
- SnapshotRenderer.prototype.replaceBody = function () {
2898
- var placeholders = this.relocateCurrentBodyPermanentElements();
2899
- this.activateNewBody();
2900
- this.assignNewBody();
2901
- this.replacePlaceholderElementsWithClonedPermanentElements(placeholders);
2902
- };
2903
- SnapshotRenderer.prototype.shouldRender = function () {
2904
- return this.newSnapshot.isVisitable() && this.trackedElementsAreIdentical();
2905
- };
2906
- SnapshotRenderer.prototype.trackedElementsAreIdentical = function () {
2907
- return this.currentHeadDetails.getTrackedElementSignature() == this.newHeadDetails.getTrackedElementSignature();
3192
+ PageRenderer.prototype.replaceBody = function () {
3193
+ var _this = this;
3194
+ this.preservingPermanentElements(function () {
3195
+ _this.activateNewBody();
3196
+ _this.assignNewBody();
3197
+ });
2908
3198
  };
2909
- SnapshotRenderer.prototype.copyNewHeadStylesheetElements = function () {
3199
+ Object.defineProperty(PageRenderer.prototype, "trackedElementsAreIdentical", {
3200
+ get: function () {
3201
+ return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
3202
+ },
3203
+ enumerable: false,
3204
+ configurable: true
3205
+ });
3206
+ PageRenderer.prototype.copyNewHeadStylesheetElements = function () {
2910
3207
  var e_1, _a;
2911
3208
  try {
2912
- for (var _b = __values(this.getNewHeadStylesheetElements()), _c = _b.next(); !_c.done; _c = _b.next()) {
3209
+ for (var _b = __values(this.newHeadStylesheetElements), _c = _b.next(); !_c.done; _c = _b.next()) {
2913
3210
  var element = _c.value;
2914
3211
  document.head.appendChild(element);
2915
3212
  }
@@ -2922,10 +3219,10 @@ Copyright © 2021 Basecamp, LLC
2922
3219
  finally { if (e_1) throw e_1.error; }
2923
3220
  }
2924
3221
  };
2925
- SnapshotRenderer.prototype.copyNewHeadScriptElements = function () {
3222
+ PageRenderer.prototype.copyNewHeadScriptElements = function () {
2926
3223
  var e_2, _a;
2927
3224
  try {
2928
- for (var _b = __values(this.getNewHeadScriptElements()), _c = _b.next(); !_c.done; _c = _b.next()) {
3225
+ for (var _b = __values(this.newHeadScriptElements), _c = _b.next(); !_c.done; _c = _b.next()) {
2929
3226
  var element = _c.value;
2930
3227
  document.head.appendChild(this.createScriptElement(element));
2931
3228
  }
@@ -2938,10 +3235,10 @@ Copyright © 2021 Basecamp, LLC
2938
3235
  finally { if (e_2) throw e_2.error; }
2939
3236
  }
2940
3237
  };
2941
- SnapshotRenderer.prototype.removeCurrentHeadProvisionalElements = function () {
3238
+ PageRenderer.prototype.removeCurrentHeadProvisionalElements = function () {
2942
3239
  var e_3, _a;
2943
3240
  try {
2944
- for (var _b = __values(this.getCurrentHeadProvisionalElements()), _c = _b.next(); !_c.done; _c = _b.next()) {
3241
+ for (var _b = __values(this.currentHeadProvisionalElements), _c = _b.next(); !_c.done; _c = _b.next()) {
2945
3242
  var element = _c.value;
2946
3243
  document.head.removeChild(element);
2947
3244
  }
@@ -2954,10 +3251,10 @@ Copyright © 2021 Basecamp, LLC
2954
3251
  finally { if (e_3) throw e_3.error; }
2955
3252
  }
2956
3253
  };
2957
- SnapshotRenderer.prototype.copyNewHeadProvisionalElements = function () {
3254
+ PageRenderer.prototype.copyNewHeadProvisionalElements = function () {
2958
3255
  var e_4, _a;
2959
3256
  try {
2960
- for (var _b = __values(this.getNewHeadProvisionalElements()), _c = _b.next(); !_c.done; _c = _b.next()) {
3257
+ for (var _b = __values(this.newHeadProvisionalElements), _c = _b.next(); !_c.done; _c = _b.next()) {
2961
3258
  var element = _c.value;
2962
3259
  document.head.appendChild(element);
2963
3260
  }
@@ -2970,201 +3267,194 @@ Copyright © 2021 Basecamp, LLC
2970
3267
  finally { if (e_4) throw e_4.error; }
2971
3268
  }
2972
3269
  };
2973
- SnapshotRenderer.prototype.relocateCurrentBodyPermanentElements = function () {
2974
- var _this = this;
2975
- return this.getCurrentBodyPermanentElements().reduce(function (placeholders, permanentElement) {
2976
- var newElement = _this.newSnapshot.getPermanentElementById(permanentElement.id);
2977
- if (newElement) {
2978
- var placeholder = createPlaceholderForPermanentElement(permanentElement);
2979
- replaceElementWithElement(permanentElement, placeholder.element);
2980
- replaceElementWithElement(newElement, permanentElement);
2981
- return __spread(placeholders, [placeholder]);
2982
- }
2983
- else {
2984
- return placeholders;
2985
- }
2986
- }, []);
2987
- };
2988
- SnapshotRenderer.prototype.replacePlaceholderElementsWithClonedPermanentElements = function (placeholders) {
2989
- var e_5, _a;
2990
- try {
2991
- for (var placeholders_1 = __values(placeholders), placeholders_1_1 = placeholders_1.next(); !placeholders_1_1.done; placeholders_1_1 = placeholders_1.next()) {
2992
- var _b = placeholders_1_1.value, element = _b.element, permanentElement = _b.permanentElement;
2993
- var clonedElement = permanentElement.cloneNode(true);
2994
- replaceElementWithElement(element, clonedElement);
2995
- }
2996
- }
2997
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
2998
- finally {
2999
- try {
3000
- if (placeholders_1_1 && !placeholders_1_1.done && (_a = placeholders_1.return)) _a.call(placeholders_1);
3001
- }
3002
- finally { if (e_5) throw e_5.error; }
3003
- }
3004
- };
3005
- SnapshotRenderer.prototype.activateNewBody = function () {
3006
- document.adoptNode(this.newBody);
3270
+ PageRenderer.prototype.activateNewBody = function () {
3271
+ document.adoptNode(this.newElement);
3007
3272
  this.activateNewBodyScriptElements();
3008
3273
  };
3009
- SnapshotRenderer.prototype.activateNewBodyScriptElements = function () {
3010
- var e_6, _a;
3274
+ PageRenderer.prototype.activateNewBodyScriptElements = function () {
3275
+ var e_5, _a;
3011
3276
  try {
3012
- for (var _b = __values(this.getNewBodyScriptElements()), _c = _b.next(); !_c.done; _c = _b.next()) {
3277
+ for (var _b = __values(this.newBodyScriptElements), _c = _b.next(); !_c.done; _c = _b.next()) {
3013
3278
  var inertScriptElement = _c.value;
3014
3279
  var activatedScriptElement = this.createScriptElement(inertScriptElement);
3015
3280
  replaceElementWithElement(inertScriptElement, activatedScriptElement);
3016
3281
  }
3017
3282
  }
3018
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
3283
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
3019
3284
  finally {
3020
3285
  try {
3021
3286
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3022
3287
  }
3023
- finally { if (e_6) throw e_6.error; }
3288
+ finally { if (e_5) throw e_5.error; }
3024
3289
  }
3025
3290
  };
3026
- SnapshotRenderer.prototype.assignNewBody = function () {
3027
- if (document.body) {
3028
- replaceElementWithElement(document.body, this.newBody);
3291
+ PageRenderer.prototype.assignNewBody = function () {
3292
+ if (document.body && this.newElement instanceof HTMLBodyElement) {
3293
+ replaceElementWithElement(document.body, this.newElement);
3029
3294
  }
3030
3295
  else {
3031
- document.documentElement.appendChild(this.newBody);
3296
+ document.documentElement.appendChild(this.newElement);
3032
3297
  }
3033
3298
  };
3034
- SnapshotRenderer.prototype.focusFirstAutofocusableElement = function () {
3035
- var element = this.newSnapshot.findFirstAutofocusableElement();
3036
- if (elementIsFocusable(element)) {
3037
- element.focus();
3299
+ Object.defineProperty(PageRenderer.prototype, "newHeadStylesheetElements", {
3300
+ get: function () {
3301
+ return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot);
3302
+ },
3303
+ enumerable: false,
3304
+ configurable: true
3305
+ });
3306
+ Object.defineProperty(PageRenderer.prototype, "newHeadScriptElements", {
3307
+ get: function () {
3308
+ return this.newHeadSnapshot.getScriptElementsNotInSnapshot(this.currentHeadSnapshot);
3309
+ },
3310
+ enumerable: false,
3311
+ configurable: true
3312
+ });
3313
+ Object.defineProperty(PageRenderer.prototype, "currentHeadProvisionalElements", {
3314
+ get: function () {
3315
+ return this.currentHeadSnapshot.provisionalElements;
3316
+ },
3317
+ enumerable: false,
3318
+ configurable: true
3319
+ });
3320
+ Object.defineProperty(PageRenderer.prototype, "newHeadProvisionalElements", {
3321
+ get: function () {
3322
+ return this.newHeadSnapshot.provisionalElements;
3323
+ },
3324
+ enumerable: false,
3325
+ configurable: true
3326
+ });
3327
+ Object.defineProperty(PageRenderer.prototype, "newBodyScriptElements", {
3328
+ get: function () {
3329
+ return __spread(this.newElement.querySelectorAll("script"));
3330
+ },
3331
+ enumerable: false,
3332
+ configurable: true
3333
+ });
3334
+ return PageRenderer;
3335
+ }(Renderer));
3336
+
3337
+ var SnapshotCache = (function () {
3338
+ function SnapshotCache(size) {
3339
+ this.keys = [];
3340
+ this.snapshots = {};
3341
+ this.size = size;
3342
+ }
3343
+ SnapshotCache.prototype.has = function (location) {
3344
+ return toCacheKey(location) in this.snapshots;
3345
+ };
3346
+ SnapshotCache.prototype.get = function (location) {
3347
+ if (this.has(location)) {
3348
+ var snapshot = this.read(location);
3349
+ this.touch(location);
3350
+ return snapshot;
3038
3351
  }
3039
3352
  };
3040
- SnapshotRenderer.prototype.getNewHeadStylesheetElements = function () {
3041
- return this.newHeadDetails.getStylesheetElementsNotInDetails(this.currentHeadDetails);
3353
+ SnapshotCache.prototype.put = function (location, snapshot) {
3354
+ this.write(location, snapshot);
3355
+ this.touch(location);
3356
+ return snapshot;
3042
3357
  };
3043
- SnapshotRenderer.prototype.getNewHeadScriptElements = function () {
3044
- return this.newHeadDetails.getScriptElementsNotInDetails(this.currentHeadDetails);
3358
+ SnapshotCache.prototype.clear = function () {
3359
+ this.snapshots = {};
3045
3360
  };
3046
- SnapshotRenderer.prototype.getCurrentHeadProvisionalElements = function () {
3047
- return this.currentHeadDetails.getProvisionalElements();
3361
+ SnapshotCache.prototype.read = function (location) {
3362
+ return this.snapshots[toCacheKey(location)];
3048
3363
  };
3049
- SnapshotRenderer.prototype.getNewHeadProvisionalElements = function () {
3050
- return this.newHeadDetails.getProvisionalElements();
3364
+ SnapshotCache.prototype.write = function (location, snapshot) {
3365
+ this.snapshots[toCacheKey(location)] = snapshot;
3051
3366
  };
3052
- SnapshotRenderer.prototype.getCurrentBodyPermanentElements = function () {
3053
- return this.currentSnapshot.getPermanentElementsPresentInSnapshot(this.newSnapshot);
3367
+ SnapshotCache.prototype.touch = function (location) {
3368
+ var key = toCacheKey(location);
3369
+ var index = this.keys.indexOf(key);
3370
+ if (index > -1)
3371
+ this.keys.splice(index, 1);
3372
+ this.keys.unshift(key);
3373
+ this.trim();
3054
3374
  };
3055
- SnapshotRenderer.prototype.getNewBodyScriptElements = function () {
3056
- return __spread(this.newBody.querySelectorAll("script"));
3375
+ SnapshotCache.prototype.trim = function () {
3376
+ var e_1, _a;
3377
+ try {
3378
+ for (var _b = __values(this.keys.splice(this.size)), _c = _b.next(); !_c.done; _c = _b.next()) {
3379
+ var key = _c.value;
3380
+ delete this.snapshots[key];
3381
+ }
3382
+ }
3383
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3384
+ finally {
3385
+ try {
3386
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3387
+ }
3388
+ finally { if (e_1) throw e_1.error; }
3389
+ }
3057
3390
  };
3058
- return SnapshotRenderer;
3059
- }(Renderer));
3060
- function createPlaceholderForPermanentElement(permanentElement) {
3061
- var element = document.createElement("meta");
3062
- element.setAttribute("name", "turbo-permanent-placeholder");
3063
- element.setAttribute("content", permanentElement.id);
3064
- return { element: element, permanentElement: permanentElement };
3065
- }
3066
- function replaceElementWithElement(fromElement, toElement) {
3067
- var parentElement = fromElement.parentElement;
3068
- if (parentElement) {
3069
- return parentElement.replaceChild(toElement, fromElement);
3070
- }
3071
- }
3072
- function elementIsFocusable(element) {
3073
- return element && typeof element.focus == "function";
3074
- }
3391
+ return SnapshotCache;
3392
+ }());
3075
3393
 
3076
- var View = (function () {
3077
- function View(delegate) {
3078
- this.htmlElement = document.documentElement;
3079
- this.snapshotCache = new SnapshotCache(10);
3080
- this.delegate = delegate;
3394
+ var PageView = (function (_super) {
3395
+ __extends(PageView, _super);
3396
+ function PageView() {
3397
+ var _this = _super !== null && _super.apply(this, arguments) || this;
3398
+ _this.snapshotCache = new SnapshotCache(10);
3399
+ _this.lastRenderedLocation = new URL(location.href);
3400
+ return _this;
3081
3401
  }
3082
- View.prototype.getRootLocation = function () {
3083
- return this.getSnapshot().getRootLocation();
3402
+ PageView.prototype.renderPage = function (snapshot, isPreview) {
3403
+ if (isPreview === void 0) { isPreview = false; }
3404
+ var renderer = new PageRenderer(this.snapshot, snapshot, isPreview);
3405
+ return this.render(renderer);
3084
3406
  };
3085
- View.prototype.getElementForAnchor = function (anchor) {
3086
- return this.getSnapshot().getElementForAnchor(anchor);
3407
+ PageView.prototype.renderError = function (snapshot) {
3408
+ var renderer = new ErrorRenderer(this.snapshot, snapshot, false);
3409
+ this.render(renderer);
3087
3410
  };
3088
- View.prototype.getSnapshot = function () {
3089
- return Snapshot.fromHTMLElement(this.htmlElement);
3090
- };
3091
- View.prototype.clearSnapshotCache = function () {
3411
+ PageView.prototype.clearSnapshotCache = function () {
3092
3412
  this.snapshotCache.clear();
3093
3413
  };
3094
- View.prototype.shouldCacheSnapshot = function () {
3095
- return this.getSnapshot().isCacheable();
3096
- };
3097
- View.prototype.cacheSnapshot = function () {
3414
+ PageView.prototype.cacheSnapshot = function () {
3098
3415
  return __awaiter(this, void 0, void 0, function () {
3099
- var snapshot, location_1;
3100
- return __generator(this, function (_a) {
3101
- switch (_a.label) {
3416
+ var _a, snapshot, location_1;
3417
+ return __generator(this, function (_b) {
3418
+ switch (_b.label) {
3102
3419
  case 0:
3103
- if (!this.shouldCacheSnapshot()) return [3, 2];
3420
+ if (!this.shouldCacheSnapshot) return [3, 2];
3104
3421
  this.delegate.viewWillCacheSnapshot();
3105
- snapshot = this.getSnapshot();
3106
- location_1 = this.lastRenderedLocation || Location.currentLocation;
3107
- return [4, nextMicrotask()];
3422
+ _a = this, snapshot = _a.snapshot, location_1 = _a.lastRenderedLocation;
3423
+ return [4, nextEventLoopTick()];
3108
3424
  case 1:
3109
- _a.sent();
3425
+ _b.sent();
3110
3426
  this.snapshotCache.put(location_1, snapshot.clone());
3111
- _a.label = 2;
3427
+ _b.label = 2;
3112
3428
  case 2: return [2];
3113
3429
  }
3114
3430
  });
3115
3431
  });
3116
3432
  };
3117
- View.prototype.getCachedSnapshotForLocation = function (location) {
3433
+ PageView.prototype.getCachedSnapshotForLocation = function (location) {
3118
3434
  return this.snapshotCache.get(location);
3119
3435
  };
3120
- View.prototype.render = function (_a, callback) {
3121
- var snapshot = _a.snapshot, error = _a.error, isPreview = _a.isPreview;
3122
- this.markAsPreview(isPreview);
3123
- if (snapshot) {
3124
- this.renderSnapshot(snapshot, isPreview, callback);
3125
- }
3126
- else {
3127
- this.renderError(error, callback);
3128
- }
3129
- };
3130
- View.prototype.scrollToAnchor = function (anchor) {
3131
- var element = this.getElementForAnchor(anchor);
3132
- if (element) {
3133
- this.scrollToElement(element);
3134
- }
3135
- else {
3136
- this.scrollToPosition({ x: 0, y: 0 });
3137
- }
3138
- };
3139
- View.prototype.scrollToElement = function (element) {
3140
- element.scrollIntoView();
3141
- };
3142
- View.prototype.scrollToPosition = function (_a) {
3143
- var x = _a.x, y = _a.y;
3144
- window.scrollTo(x, y);
3145
- };
3146
- View.prototype.markAsPreview = function (isPreview) {
3147
- if (isPreview) {
3148
- this.htmlElement.setAttribute("data-turbo-preview", "");
3149
- }
3150
- else {
3151
- this.htmlElement.removeAttribute("data-turbo-preview");
3152
- }
3153
- };
3154
- View.prototype.renderSnapshot = function (snapshot, isPreview, callback) {
3155
- SnapshotRenderer.render(this.delegate, callback, this.getSnapshot(), snapshot, isPreview || false);
3156
- };
3157
- View.prototype.renderError = function (error, callback) {
3158
- ErrorRenderer.render(this.delegate, callback, error || "");
3159
- };
3160
- return View;
3161
- }());
3436
+ Object.defineProperty(PageView.prototype, "snapshot", {
3437
+ get: function () {
3438
+ return PageSnapshot.fromElement(this.element);
3439
+ },
3440
+ enumerable: false,
3441
+ configurable: true
3442
+ });
3443
+ Object.defineProperty(PageView.prototype, "shouldCacheSnapshot", {
3444
+ get: function () {
3445
+ return this.snapshot.isCacheable;
3446
+ },
3447
+ enumerable: false,
3448
+ configurable: true
3449
+ });
3450
+ return PageView;
3451
+ }(View));
3162
3452
 
3163
3453
  var Session = (function () {
3164
3454
  function Session() {
3165
3455
  this.navigator = new Navigator(this);
3166
3456
  this.history = new History(this);
3167
- this.view = new View(this);
3457
+ this.view = new PageView(this, document.documentElement);
3168
3458
  this.adapter = new BrowserAdapter(this);
3169
3459
  this.pageObserver = new PageObserver(this);
3170
3460
  this.linkClickObserver = new LinkClickObserver(this);
@@ -3209,7 +3499,7 @@ Copyright © 2021 Basecamp, LLC
3209
3499
  };
3210
3500
  Session.prototype.visit = function (location, options) {
3211
3501
  if (options === void 0) { options = {}; }
3212
- this.navigator.proposeVisit(Location.wrap(location), options);
3502
+ this.navigator.proposeVisit(expandURL(location), options);
3213
3503
  };
3214
3504
  Session.prototype.connectStreamSource = function (source) {
3215
3505
  this.streamObserver.connectStreamSource(source);
@@ -3258,15 +3548,17 @@ Copyright © 2021 Basecamp, LLC
3258
3548
  };
3259
3549
  Session.prototype.followedLinkToLocation = function (link, location) {
3260
3550
  var action = this.getActionForLink(link);
3261
- this.visit(location, { action: action });
3551
+ this.visit(location.href, { action: action });
3262
3552
  };
3263
3553
  Session.prototype.allowsVisitingLocation = function (location) {
3264
3554
  return this.applicationAllowsVisitingLocation(location);
3265
3555
  };
3266
3556
  Session.prototype.visitProposedToLocation = function (location, options) {
3557
+ extendURLWithDeprecatedProperties(location);
3267
3558
  this.adapter.visitProposedToLocation(location, options);
3268
3559
  };
3269
3560
  Session.prototype.visitStarted = function (visit) {
3561
+ extendURLWithDeprecatedProperties(visit.location);
3270
3562
  this.notifyApplicationAfterVisitingLocation(visit.location);
3271
3563
  };
3272
3564
  Session.prototype.visitCompleted = function (visit) {
@@ -3291,19 +3583,20 @@ Copyright © 2021 Basecamp, LLC
3291
3583
  Session.prototype.receivedMessageFromStream = function (message) {
3292
3584
  this.renderStreamMessage(message);
3293
3585
  };
3294
- Session.prototype.viewWillRender = function (newBody) {
3295
- this.notifyApplicationBeforeRender(newBody);
3586
+ Session.prototype.viewWillCacheSnapshot = function () {
3587
+ this.notifyApplicationBeforeCachingSnapshot();
3296
3588
  };
3297
- Session.prototype.viewRendered = function () {
3589
+ Session.prototype.viewWillRenderSnapshot = function (_a, isPreview) {
3590
+ var element = _a.element;
3591
+ this.notifyApplicationBeforeRender(element);
3592
+ };
3593
+ Session.prototype.viewRenderedSnapshot = function (snapshot, isPreview) {
3298
3594
  this.view.lastRenderedLocation = this.history.location;
3299
3595
  this.notifyApplicationAfterRender();
3300
3596
  };
3301
3597
  Session.prototype.viewInvalidated = function () {
3302
3598
  this.adapter.pageInvalidated();
3303
3599
  };
3304
- Session.prototype.viewWillCacheSnapshot = function () {
3305
- this.notifyApplicationBeforeCachingSnapshot();
3306
- };
3307
3600
  Session.prototype.applicationAllowsFollowingLinkToLocation = function (link, location) {
3308
3601
  var event = this.notifyApplicationAfterClickingLinkToLocation(link, location);
3309
3602
  return !event.defaultPrevented;
@@ -3313,13 +3606,13 @@ Copyright © 2021 Basecamp, LLC
3313
3606
  return !event.defaultPrevented;
3314
3607
  };
3315
3608
  Session.prototype.notifyApplicationAfterClickingLinkToLocation = function (link, location) {
3316
- return dispatch("turbo:click", { target: link, detail: { url: location.absoluteURL }, cancelable: true });
3609
+ return dispatch("turbo:click", { target: link, detail: { url: location.href }, cancelable: true });
3317
3610
  };
3318
3611
  Session.prototype.notifyApplicationBeforeVisitingLocation = function (location) {
3319
- return dispatch("turbo:before-visit", { detail: { url: location.absoluteURL }, cancelable: true });
3612
+ return dispatch("turbo:before-visit", { detail: { url: location.href }, cancelable: true });
3320
3613
  };
3321
3614
  Session.prototype.notifyApplicationAfterVisitingLocation = function (location) {
3322
- return dispatch("turbo:visit", { detail: { url: location.absoluteURL } });
3615
+ return dispatch("turbo:visit", { detail: { url: location.href } });
3323
3616
  };
3324
3617
  Session.prototype.notifyApplicationBeforeCachingSnapshot = function () {
3325
3618
  return dispatch("turbo:before-cache");
@@ -3332,7 +3625,7 @@ Copyright © 2021 Basecamp, LLC
3332
3625
  };
3333
3626
  Session.prototype.notifyApplicationAfterPageLoad = function (timing) {
3334
3627
  if (timing === void 0) { timing = {}; }
3335
- return dispatch("turbo:load", { detail: { url: this.location.absoluteURL, timing: timing } });
3628
+ return dispatch("turbo:load", { detail: { url: this.location.href, timing: timing } });
3336
3629
  };
3337
3630
  Session.prototype.getActionForLink = function (link) {
3338
3631
  var action = link.getAttribute("data-turbo-action");
@@ -3348,10 +3641,27 @@ Copyright © 2021 Basecamp, LLC
3348
3641
  }
3349
3642
  };
3350
3643
  Session.prototype.locationIsVisitable = function (location) {
3351
- return location.isPrefixedBy(this.view.getRootLocation()) && location.isHTML();
3644
+ return isPrefixedBy(location, this.snapshot.rootLocation) && isHTML(location);
3352
3645
  };
3646
+ Object.defineProperty(Session.prototype, "snapshot", {
3647
+ get: function () {
3648
+ return this.view.snapshot;
3649
+ },
3650
+ enumerable: false,
3651
+ configurable: true
3652
+ });
3353
3653
  return Session;
3354
3654
  }());
3655
+ function extendURLWithDeprecatedProperties(url) {
3656
+ Object.defineProperties(url, deprecatedLocationPropertyDescriptors);
3657
+ }
3658
+ var deprecatedLocationPropertyDescriptors = {
3659
+ absoluteURL: {
3660
+ get: function () {
3661
+ return this.toString();
3662
+ }
3663
+ }
3664
+ };
3355
3665
 
3356
3666
  var session = new Session;
3357
3667
  var navigator = session.navigator;