@pierre/diffs 1.3.3 → 1.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","names":[],"sources":["../../src/editor/editor.ts"],"mappings":";;;;;;;;;UAwLiB,aAAA;;EAEf,iBAAA;EAF4B;EAI5B,MAAA,GAAS,YAAA;EAAA;;;;EAKT,YAAA;EAgCkC;;;;EA3BlC,mBAAA,GAAsB,mBAAA;EAgCiB;EA9BvC,gBAAA;EAkCQ;EAhCR,aAAA;EAkCM;;;;EA7BN,YAAA,GAAe,YAAA;EAgCW;EA9B1B,qBAAA,GAAwB,iBAAA;EAzBK;;;;EA8B7B,sBAAA;EAhBA;;;;;EAsBA,SAAA;IACE,QAAA,GAAW,IAAA,cAAkB,OAAA;EAAA;EAP/B;EAUA,qBAAA,IACE,OAAA,EAAS,sBAAA,CAAuB,WAAA,MAC7B,WAAA;EALH;EAOF,QAAA,IACE,MAAA,EAAQ,MAAA,CAAO,WAAA,GACf,YAAA,EAAc,sBAAA,CAAuB,WAAA;EATR;EAY/B,QAAA,IACE,IAAA,EAAM,YAAA,EACN,eAAA,EACI,cAAA,CAAe,WAAA,MACf,kBAAA,CAAmB,WAAA,iBAEvB,KAAA,EAAO,iBAAA,CAAkB,WAAA;EAdhB;EAiBX,OAAA;EAjBE;EAmBF,MAAA;EAEA,OAAA;AAAA;AAAA,UAGe,kBAAA,SAA2B,YAAY;EApBpD;EAsBF,UAAA;EArBuC;EAuBvC,SAAA;EApBA;EAsBA,MAAA;AAAA;AAAA,cAmBW,MAAA,yBAA+B,WAAA,CAAY,WAAA;EAAA;EAkJtD,WAAA,CAAY,OAAA,GAAS,aAAA,CAAc,WAAA;EAInC,UAAA,CAAW,OAAA,EAAS,aAAA,CAAc,WAAA;EAkClC,IAAA,WAAe,sBAAA,CAAuB,WAAA,GACpC,YAAA,EAAc,gBAAA,CAAiB,CAAA;EA5NxB;;;;;;;AAOF;AAGT;;EA4OE,UAAA,CAAW,KAAA,EAAO,QAAA,IAAY,aAAA;EA5OwB;EAAA,IA+SlD,OAAA;EA7SJ;EAAA,IAkTI,OAAA;EA9SJ;EAmTA,IAAA;EAnTM;EAwTN,IAAA;EAIA,OAAA,IAAW,YAAA;EAcX,OAAA;EAIA,QAAA,IAAY,WAAA;EAaZ,QAAA;IAAW,UAAA;IAAY;EAAA,GAAQ,WAAA;EAgB/B,aAAA,CACE,UAAA,GAAa,KAAA;IAAU,SAAA;EAAA;EAoCzB,UAAA,CAAW,OAAA,EAAS,MAAA;EA6BpB,KAAA,CAAM,OAAA,GAAU,kBAAA;EAmChB,IAAA;EAOA,OAAA,CAAQ,OAAA;EAjPU;EAoUlB,aAAA,CAAc,IAAA,EAAM,YAAA,GAAe,YAAA;EA5NvB;EAwPZ,+BAAA;EA3OuB;EAsPvB,+BAAA;EArOe;EAoPf,gBAAA,EAAkB,WAAA,CAAY,WAAA;AAAA"}
1
+ {"version":3,"file":"editor.d.ts","names":[],"sources":["../../src/editor/editor.ts"],"mappings":";;;;;;;;;UA8LiB,aAAA;;EAEf,iBAAA;EAF4B;EAI5B,MAAA,GAAS,YAAA;EAAA;;;;EAKT,YAAA;EAgCkC;;;;EA3BlC,mBAAA,GAAsB,mBAAA;EAgCiB;EA9BvC,gBAAA;EAkCQ;EAhCR,aAAA;EAkCM;;;;EA7BN,YAAA,GAAe,YAAA;EAgCW;EA9B1B,qBAAA,GAAwB,iBAAA;EAzBK;;;;EA8B7B,sBAAA;EAhBA;;;;;EAsBA,SAAA;IACE,QAAA,GAAW,IAAA,cAAkB,OAAA;EAAA;EAP/B;EAUA,qBAAA,IACE,OAAA,EAAS,sBAAA,CAAuB,WAAA,MAC7B,WAAA;EALH;EAOF,QAAA,IACE,MAAA,EAAQ,MAAA,CAAO,WAAA,GACf,YAAA,EAAc,sBAAA,CAAuB,WAAA;EATR;EAY/B,QAAA,IACE,IAAA,EAAM,YAAA,EACN,eAAA,EACI,cAAA,CAAe,WAAA,MACf,kBAAA,CAAmB,WAAA,iBAEvB,KAAA,EAAO,iBAAA,CAAkB,WAAA;EAdhB;EAiBX,OAAA;EAjBE;EAmBF,MAAA;EAEA,OAAA;AAAA;AAAA,UAGe,kBAAA,SAA2B,YAAY;EApBpD;EAsBF,UAAA;EArBuC;EAuBvC,SAAA;EApBA;EAsBA,MAAA;AAAA;AAAA,cAmBW,MAAA,yBAA+B,WAAA,CAAY,WAAA;EAAA;EAkJtD,WAAA,CAAY,OAAA,GAAS,aAAA,CAAc,WAAA;EAInC,UAAA,CAAW,OAAA,EAAS,aAAA,CAAc,WAAA;EAkClC,IAAA,WAAe,sBAAA,CAAuB,WAAA,GACpC,YAAA,EAAc,gBAAA,CAAiB,CAAA;EA5NxB;;;;;;;AAOF;AAGT;;EA4OE,UAAA,CAAW,KAAA,EAAO,QAAA,IAAY,aAAA;EA5OwB;EAAA,IA+SlD,OAAA;EA7SJ;EAAA,IAkTI,OAAA;EA9SJ;EAmTA,IAAA;EAnTM;EAwTN,IAAA;EAIA,OAAA,IAAW,YAAA;EAcX,OAAA;EAIA,QAAA,IAAY,WAAA;EAcZ,QAAA;IAAW,UAAA;IAAY;EAAA,GAAQ,WAAA;EAqB/B,aAAA,CACE,UAAA,GAAa,KAAA;IAAU,SAAA;EAAA;EAoCzB,UAAA,CAAW,OAAA,EAAS,MAAA;EA6BpB,KAAA,CAAM,OAAA,GAAU,kBAAA;EAmChB,IAAA;EAOA,OAAA,CAAQ,OAAA;EAvPU;EA0UlB,aAAA,CAAc,IAAA,EAAM,YAAA,GAAe,YAAA;EAlOvB;EA8PZ,+BAAA;EAhPuB;EA2PvB,+BAAA;EArOe;EAoPf,gBAAA,EAAkB,WAAA,CAAY,WAAA;AAAA"}
@@ -7,7 +7,7 @@ import { resolveEditorCommandFromKeyboardEvent, resolveFindAgainShortcut } from
7
7
  import editor_default from "./editor2.js";
8
8
  import { EditStack } from "./editStack.js";
9
9
  import { resolveBlockCommentEdits, resolveCommentConfig, resolveLineCommentEdits } from "./languages.js";
10
- import { addEventListener, clampDomOffset, extend, getLineNumberAttr, h, round } from "./utils.js";
10
+ import { addEventListener, clampDomOffset, extend, getLineNumberAttr, h, lookupScrollContainer, round } from "./utils.js";
11
11
  import { applyDocumentChangeToLineAnnotations, renderLineAnnotations } from "./lineAnnotations.js";
12
12
  import { PopoverManager } from "./popover.js";
13
13
  import { applyDeleteCharacterToSelections, applyDeleteHardLineForwardToSelections, applyDeleteSoftLineBackwardToSelections, applyDeleteWordBackwardToSelections, applyTextChangeToSelections, applyTextReplaceToSelections, applyTransposeToSelections, comparePosition, convertSelection, createSelectionFrom, createSelectionFromAnchorAndFocusOffsets, expandCollapsedSelectionToWord, extendSelection, extendSelections, findNextMatch, getAutoSurroundReplacementTexts, getCaretPosition, getDocumentBoundarySelection, getDocumentFullSelection, getSelectedLineBlocks, getSelectionAnchor, getSelectionClipboardTexts, getSelectionText, isCollapsedSelection, isLineEditable, mapCursorMove, mapSelectionShift, mergeOverlappingSelections, remapSelectionsAfterEdits, resolveIndentEdits, resolveSelectionCut, selectionIntersects, shiftSelectionLines } from "./selection.js";
@@ -222,7 +222,10 @@ var Editor = class {
222
222
  const fileInstance = this.#fileInstance;
223
223
  return {
224
224
  selections: this.#selections,
225
- view: fileInstance != null ? { scrollLeft: fileInstance.getCodeScrollLeft() } : void 0
225
+ view: fileInstance != null ? {
226
+ scrollLeft: fileInstance.getCodeScrollLeft(),
227
+ scrollTop: this.#getViewportScrollTop()
228
+ } : void 0
226
229
  };
227
230
  }
228
231
  setState({ selections, view }) {
@@ -231,6 +234,7 @@ var Editor = class {
231
234
  this.#updateSelections(selections ?? []);
232
235
  if (view != null) {
233
236
  this.#fileInstance.setCodeScrollLeft(view.scrollLeft);
237
+ if (view.scrollTop !== void 0) this.#setViewportScrollTop(view.scrollTop);
234
238
  return;
235
239
  }
236
240
  this.#scrollToPrimaryCaret();
@@ -311,7 +315,7 @@ var Editor = class {
311
315
  this.#invalidateOnAttach();
312
316
  if (!recycle) this.#attachState.delivered = false;
313
317
  const hadFileInstance = this.#fileInstance != null;
314
- const shouldRestoreState = this.#isStatePersistenceEnabled;
318
+ const shouldRestoreState = this.#options.persistState === true;
315
319
  this.#stateRestoreGeneration++;
316
320
  this.#persistCurrentState();
317
321
  if (hadFileInstance) this.#restoreStateOnNextSync = shouldRestoreState;
@@ -432,7 +436,7 @@ var Editor = class {
432
436
  if (this.#spriteElement !== void 0) shadowRoot.prepend(this.#spriteElement);
433
437
  }
434
438
  const shouldRebuildDocument = this.#textDocument === void 0 || this.#fileInfo === void 0 || this.#fileInfo.name !== fileOrDiff.name || this.#fileInfo.lang !== fileOrDiff.lang || this.#fileInfo.cacheKey !== fileOrDiff.cacheKey;
435
- const persistedCacheKey = this.#isStatePersistenceEnabled ? requirePersistedCacheKey(fileOrDiff) : void 0;
439
+ const persistedCacheKey = this.#options.persistState === true ? requirePersistedCacheKey(fileOrDiff) : void 0;
436
440
  let persistedStateTarget;
437
441
  if (shouldRebuildDocument) {
438
442
  this.#invalidateOnAttach();
@@ -442,7 +446,9 @@ var Editor = class {
442
446
  const editStack = new EditStack({ maxEntries: this.#options.historyMaxEntries });
443
447
  const { name, lang, cacheKey } = fileOrDiff;
444
448
  const languageId = lang ?? getFiletypeFromFileName(fileOrDiff.name);
445
- const textDocument = (persistedCacheKey !== void 0 ? this.#getCachedTextDocument(fileOrDiff, persistedCacheKey) : void 0) ?? new TextDocument(fileOrDiff.name, contents, languageId, 0, editStack);
449
+ const cachedTextDocument = persistedCacheKey !== void 0 ? this.#getCachedTextDocument(fileOrDiff, persistedCacheKey) : void 0;
450
+ const reusableTextDocument = fileInstance.type === "file" || cachedTextDocument?.getText() === contents ? cachedTextDocument : void 0;
451
+ const textDocument = reusableTextDocument ?? new TextDocument(fileOrDiff.name, contents, languageId, 0, editStack);
446
452
  this.#fileInfo = {
447
453
  name,
448
454
  lang,
@@ -461,7 +467,7 @@ var Editor = class {
461
467
  this.#resetState();
462
468
  this.#wrapLineOffsetsCache.clear();
463
469
  this.#selections = this.#initSelections;
464
- if (this.#textDocument !== void 0 && this.#options.__debug === true) console.log("[diffs/editor] text document rebuilt from", fileOrDiff.name);
470
+ if (this.#options.__debug === true) console.log(reusableTextDocument !== void 0 ? "[diffs/editor] cached text document reused for" : "[diffs/editor] text document rebuilt from", fileOrDiff.name);
465
471
  }
466
472
  if (persistedStateTarget === void 0 && this.#restoreStateOnNextSync && persistedCacheKey !== void 0 && this.#textDocument !== void 0) persistedStateTarget = {
467
473
  cacheKey: persistedCacheKey,
@@ -530,9 +536,6 @@ var Editor = class {
530
536
  }
531
537
  this.#scheduleOnAttach(fileInstance);
532
538
  };
533
- get #isStatePersistenceEnabled() {
534
- return this.#options.persistState === true && this.#fileInstance?.type === "file";
535
- }
536
539
  #getCachedTextDocument(file, cacheKey) {
537
540
  const textDocument = this.#textDocumentCache.get(cacheKey);
538
541
  const languageId = file.lang ?? getFiletypeFromFileName(file.name);
@@ -549,7 +552,7 @@ var Editor = class {
549
552
  #persistCurrentState() {
550
553
  const fileInfo = this.#fileInfo;
551
554
  const textDocument = this.#textDocument;
552
- if (!this.#isStatePersistenceEnabled || fileInfo === void 0 || textDocument === void 0) return;
555
+ if (this.#options.persistState !== true || this.#fileInstance === void 0 || fileInfo === void 0 || textDocument === void 0) return;
553
556
  const cacheKey = requirePersistedCacheKey(fileInfo);
554
557
  this.#textDocumentCache.set(cacheKey, textDocument);
555
558
  let storage;
@@ -562,7 +565,7 @@ var Editor = class {
562
565
  const pendingRestore = this.#pendingStateRestore;
563
566
  if (pendingRestore?.cacheKey === cacheKey && pendingRestore.textDocument === textDocument) {
564
567
  this.#pendingStateRestore = void 0;
565
- if (textDocument.version === pendingRestore.documentVersion && this.#selections === pendingRestore.selections && state.view?.scrollLeft === pendingRestore.view?.scrollLeft) return;
568
+ if (textDocument.version === pendingRestore.documentVersion && this.#selections === pendingRestore.selections && state.view?.scrollLeft === pendingRestore.view?.scrollLeft && state.view?.scrollTop === pendingRestore.view?.scrollTop) return;
566
569
  this.#writeState(storage, cacheKey, state, pendingRestore.completion);
567
570
  return;
568
571
  }
@@ -597,10 +600,19 @@ var Editor = class {
597
600
  const documentVersion = textDocument.version;
598
601
  const selections = this.#selections;
599
602
  const view = this.getState().view;
603
+ let inputWatch;
600
604
  const applyState = (state) => {
601
605
  const currentView = this.getState().view;
602
- if (state === void 0 || generation !== this.#stateRestoreGeneration || this.#textDocument !== textDocument || textDocument.version !== documentVersion || this.#selections !== selections || currentView?.scrollLeft !== view?.scrollLeft || this.#fileInfo === void 0 || requirePersistedCacheKey(this.#fileInfo) !== cacheKey) return;
603
- this.setState(cloneEditorState(state));
606
+ if (generation !== this.#stateRestoreGeneration || this.#textDocument !== textDocument || textDocument.version !== documentVersion || this.#selections !== selections || currentView?.scrollLeft !== view?.scrollLeft || this.#fileInfo === void 0 || requirePersistedCacheKey(this.#fileInfo) !== cacheKey) return;
607
+ const userScrolled = inputWatch?.userScrolled() === true;
608
+ if (state === void 0) {
609
+ this.#fileInstance?.setCodeScrollLeft(0);
610
+ if (!userScrolled) this.#setViewportScrollTop(0);
611
+ return;
612
+ }
613
+ const restored = cloneEditorState(state);
614
+ if (userScrolled && restored.view !== void 0) restored.view = { scrollLeft: restored.view.scrollLeft };
615
+ this.setState(restored);
604
616
  };
605
617
  const readState = () => {
606
618
  let result;
@@ -617,6 +629,7 @@ var Editor = class {
617
629
  const pendingWrite = this.#pendingStateWrites.get(cacheKey);
618
630
  const result = pendingWrite === void 0 ? readState() : pendingWrite.then(readState);
619
631
  if (isPromise(result)) {
632
+ inputWatch = this.#watchViewportUserInput();
620
633
  const pendingRestore = {
621
634
  cacheKey,
622
635
  textDocument,
@@ -627,10 +640,36 @@ var Editor = class {
627
640
  };
628
641
  this.#pendingStateRestore = pendingRestore;
629
642
  pendingRestore.completion.finally(() => {
643
+ inputWatch?.dispose();
630
644
  if (this.#pendingStateRestore === pendingRestore) this.#pendingStateRestore = void 0;
631
645
  });
632
646
  }
633
647
  }
648
+ #watchViewportUserInput() {
649
+ const viewport = this.#getScrollViewport();
650
+ if (!(viewport instanceof HTMLElement)) return;
651
+ let scrolled = false;
652
+ const eventTypes = [
653
+ "wheel",
654
+ "touchstart",
655
+ "mousedown"
656
+ ];
657
+ const dispose = () => {
658
+ for (const type of eventTypes) viewport.removeEventListener(type, onInput, { capture: true });
659
+ };
660
+ const onInput = () => {
661
+ scrolled = true;
662
+ dispose();
663
+ };
664
+ for (const type of eventTypes) viewport.addEventListener(type, onInput, {
665
+ capture: true,
666
+ passive: true
667
+ });
668
+ return {
669
+ userScrolled: () => scrolled,
670
+ dispose
671
+ };
672
+ }
634
673
  #isLineRenderable(line) {
635
674
  return this.#fileInstance?.isLineRenderable?.(line + 1) ?? true;
636
675
  }
@@ -713,6 +752,23 @@ var Editor = class {
713
752
  attachState.callback = callback;
714
753
  queueRender(callback);
715
754
  }
755
+ #getScrollViewport() {
756
+ const viewport = this.#fileInstance?.getEditorViewport?.();
757
+ if (viewport !== void 0) return viewport;
758
+ const fileContainer = this.#fileContainer;
759
+ if (this.#fileInstance == null || fileContainer == null) return;
760
+ return lookupScrollContainer(fileContainer);
761
+ }
762
+ #getViewportScrollTop() {
763
+ const viewport = this.#getScrollViewport();
764
+ if (viewport instanceof HTMLElement) return viewport.scrollTop;
765
+ return viewport?.defaultView?.scrollY ?? 0;
766
+ }
767
+ #setViewportScrollTop(scrollTop) {
768
+ const viewport = this.#getScrollViewport();
769
+ if (viewport instanceof HTMLElement) viewport.scrollTop = scrollTop;
770
+ else if (viewport instanceof Document) viewport.defaultView?.scrollTo({ top: scrollTop });
771
+ }
716
772
  #initialize() {
717
773
  this.#globalStyleElement = h("style", {
718
774
  dataset: "editorGlobalCss",
@@ -1747,7 +1803,8 @@ var Editor = class {
1747
1803
  const contentElement = this.#contentElement;
1748
1804
  const fileContainer = this.#fileContainer;
1749
1805
  if (this.#textDocument == null || contentElement == null || fileContainer == null) return;
1750
- const viewport = this.#fileInstance?.getEditorViewport?.() ?? this.#getDefaultEditorViewport(fileContainer);
1806
+ const viewport = this.#getScrollViewport();
1807
+ if (viewport === void 0) return;
1751
1808
  let viewportTop;
1752
1809
  let viewportBottom;
1753
1810
  if (viewport instanceof HTMLElement) {
@@ -1755,10 +1812,8 @@ var Editor = class {
1755
1812
  viewportTop = viewportRect.top;
1756
1813
  viewportBottom = viewportRect.bottom;
1757
1814
  } else {
1758
- const viewportWindow = viewport.defaultView;
1759
- if (viewportWindow == null) return;
1760
1815
  viewportTop = 0;
1761
- viewportBottom = viewportWindow.innerHeight;
1816
+ viewportBottom = viewport.defaultView?.innerHeight ?? 0;
1762
1817
  }
1763
1818
  const stickyHeader = fileContainer.shadowRoot?.querySelector("[data-diffs-header][data-sticky]");
1764
1819
  if (stickyHeader != null) viewportTop = Math.max(viewportTop, stickyHeader.getBoundingClientRect().bottom);
@@ -1774,16 +1829,6 @@ var Editor = class {
1774
1829
  if (rowRect.top >= viewportTop && rowRect.top < viewportBottom) return lineNumber;
1775
1830
  }
1776
1831
  }
1777
- #getDefaultEditorViewport(fileContainer) {
1778
- const ownerDocument = fileContainer.ownerDocument;
1779
- let element = fileContainer.parentElement;
1780
- while (element != null && element !== ownerDocument.body && element !== ownerDocument.documentElement) {
1781
- const overflowY = element.ownerDocument.defaultView?.getComputedStyle(element).overflowY;
1782
- if (overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay") return element;
1783
- element = element.parentElement;
1784
- }
1785
- return ownerDocument;
1786
- }
1787
1832
  #focusAtPosition(position, preventScroll) {
1788
1833
  const selection = {
1789
1834
  start: position,