@pierre/diffs 1.3.6 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/dist/components/CodeView.d.ts +115 -68
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +189 -59
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +79 -15
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +244 -66
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +101 -21
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +432 -102
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.js +1 -1
  14. package/dist/components/UnresolvedFile.d.ts +2 -2
  15. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  16. package/dist/components/UnresolvedFile.js +2 -2
  17. package/dist/components/UnresolvedFile.js.map +1 -1
  18. package/dist/components/VirtualizedFile.d.ts +17 -7
  19. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  20. package/dist/components/VirtualizedFile.js +142 -53
  21. package/dist/components/VirtualizedFile.js.map +1 -1
  22. package/dist/components/VirtualizedFileDiff.d.ts +15 -8
  23. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  24. package/dist/components/VirtualizedFileDiff.js +186 -96
  25. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  26. package/dist/components/VirtulizerDevelopment.d.ts +1 -1
  27. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  28. package/dist/edit/index.d.ts +7 -4
  29. package/dist/edit/index.js +5 -1
  30. package/dist/editor/EditStateManager.d.ts +56 -0
  31. package/dist/editor/EditStateManager.d.ts.map +1 -0
  32. package/dist/editor/EditStateManager.js +135 -0
  33. package/dist/editor/EditStateManager.js.map +1 -0
  34. package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts +7 -0
  35. package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts.map +1 -0
  36. package/dist/editor/cloneRetainedDiffSessionSnapshot.js +16 -0
  37. package/dist/editor/cloneRetainedDiffSessionSnapshot.js.map +1 -0
  38. package/dist/editor/editPrediction.d.ts +76 -0
  39. package/dist/editor/editPrediction.d.ts.map +1 -0
  40. package/dist/editor/editPrediction.js +365 -0
  41. package/dist/editor/editPrediction.js.map +1 -0
  42. package/dist/editor/editStack.d.ts +19 -40
  43. package/dist/editor/editStack.d.ts.map +1 -1
  44. package/dist/editor/editStack.js +67 -4
  45. package/dist/editor/editStack.js.map +1 -1
  46. package/dist/editor/editor.d.ts +118 -29
  47. package/dist/editor/editor.d.ts.map +1 -1
  48. package/dist/editor/editor.js +1108 -384
  49. package/dist/editor/editor.js.map +1 -1
  50. package/dist/editor/editor2.js +1 -1
  51. package/dist/editor/languages.d.ts +3 -3
  52. package/dist/editor/languages.d.ts.map +1 -1
  53. package/dist/editor/languages.js.map +1 -1
  54. package/dist/editor/lineAnnotations.d.ts +3 -3
  55. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  56. package/dist/editor/lineAnnotations.js +16 -7
  57. package/dist/editor/lineAnnotations.js.map +1 -1
  58. package/dist/editor/marker.d.ts +2 -2
  59. package/dist/editor/marker.d.ts.map +1 -1
  60. package/dist/editor/marker.js.map +1 -1
  61. package/dist/editor/matchBrackets.d.ts +2 -2
  62. package/dist/editor/matchBrackets.d.ts.map +1 -1
  63. package/dist/editor/matchBrackets.js.map +1 -1
  64. package/dist/editor/pieceTable.d.ts +1 -1
  65. package/dist/editor/pieceTable.js.map +1 -1
  66. package/dist/editor/searchPanel.d.ts +2 -2
  67. package/dist/editor/searchPanel.js +1 -1
  68. package/dist/editor/searchPanel.js.map +1 -1
  69. package/dist/editor/selection.d.ts +32 -23
  70. package/dist/editor/selection.d.ts.map +1 -1
  71. package/dist/editor/selection.js +3 -3
  72. package/dist/editor/selection.js.map +1 -1
  73. package/dist/editor/selectionAction.d.ts +3 -3
  74. package/dist/editor/selectionAction.d.ts.map +1 -1
  75. package/dist/editor/selectionAction.js.map +1 -1
  76. package/dist/editor/textDocument.d.ts +11 -8
  77. package/dist/editor/textDocument.d.ts.map +1 -1
  78. package/dist/editor/textDocument.js +28 -5
  79. package/dist/editor/textDocument.js.map +1 -1
  80. package/dist/editor/textDocumentChangeTransaction.d.ts +15 -0
  81. package/dist/editor/textDocumentChangeTransaction.d.ts.map +1 -0
  82. package/dist/editor/textDocumentChangeTransaction.js +12 -0
  83. package/dist/editor/textDocumentChangeTransaction.js.map +1 -0
  84. package/dist/editor/textMeasure.d.ts +5 -0
  85. package/dist/editor/textMeasure.d.ts.map +1 -1
  86. package/dist/editor/textMeasure.js +10 -0
  87. package/dist/editor/textMeasure.js.map +1 -1
  88. package/dist/editor/tokenizer.d.ts +1 -1
  89. package/dist/editor/tokenizer.js.map +1 -1
  90. package/dist/editor/types.d.ts +267 -0
  91. package/dist/editor/types.d.ts.map +1 -0
  92. package/dist/editor/types.js +0 -0
  93. package/dist/editor/utils.d.ts +2 -1
  94. package/dist/editor/utils.d.ts.map +1 -1
  95. package/dist/editor/utils.js +4 -1
  96. package/dist/editor/utils.js.map +1 -1
  97. package/dist/highlighter/shared_highlighter.d.ts +6 -2
  98. package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
  99. package/dist/highlighter/shared_highlighter.js +7 -3
  100. package/dist/highlighter/shared_highlighter.js.map +1 -1
  101. package/dist/highlighter/themes/areThemesAttached.js +1 -1
  102. package/dist/index.d.ts +8 -6
  103. package/dist/index.js +22 -21
  104. package/dist/managers/InteractionManager.d.ts.map +1 -1
  105. package/dist/managers/InteractionManager.js +7 -0
  106. package/dist/managers/InteractionManager.js.map +1 -1
  107. package/dist/react/CodeView.d.ts +36 -25
  108. package/dist/react/CodeView.d.ts.map +1 -1
  109. package/dist/react/CodeView.js +15 -14
  110. package/dist/react/CodeView.js.map +1 -1
  111. package/dist/react/EditContext.d.ts +8 -11
  112. package/dist/react/EditContext.d.ts.map +1 -1
  113. package/dist/react/EditContext.js +2 -9
  114. package/dist/react/EditContext.js.map +1 -1
  115. package/dist/react/File.d.ts +10 -6
  116. package/dist/react/File.d.ts.map +1 -1
  117. package/dist/react/File.js +8 -4
  118. package/dist/react/File.js.map +1 -1
  119. package/dist/react/FileDiff.d.ts +10 -5
  120. package/dist/react/FileDiff.d.ts.map +1 -1
  121. package/dist/react/FileDiff.js +8 -4
  122. package/dist/react/FileDiff.js.map +1 -1
  123. package/dist/react/MultiFileDiff.d.ts +8 -5
  124. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  125. package/dist/react/MultiFileDiff.js +8 -12
  126. package/dist/react/MultiFileDiff.js.map +1 -1
  127. package/dist/react/PatchDiff.d.ts +7 -4
  128. package/dist/react/PatchDiff.d.ts.map +1 -1
  129. package/dist/react/PatchDiff.js +8 -4
  130. package/dist/react/PatchDiff.js.map +1 -1
  131. package/dist/react/UnresolvedFile.d.ts +3 -3
  132. package/dist/react/UnresolvedFile.d.ts.map +1 -1
  133. package/dist/react/UnresolvedFile.js.map +1 -1
  134. package/dist/react/index.d.ts +8 -5
  135. package/dist/react/types.d.ts +46 -9
  136. package/dist/react/types.d.ts.map +1 -1
  137. package/dist/react/utils/renderDiffChildren.d.ts +14 -12
  138. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  139. package/dist/react/utils/renderDiffChildren.js +2 -2
  140. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  141. package/dist/react/utils/renderFileChildren.d.ts +14 -12
  142. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  143. package/dist/react/utils/renderFileChildren.js +2 -2
  144. package/dist/react/utils/renderFileChildren.js.map +1 -1
  145. package/dist/react/utils/useFileDiffInstance.d.ts +22 -10
  146. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  147. package/dist/react/utils/useFileDiffInstance.js +112 -22
  148. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  149. package/dist/react/utils/useFileInstance.d.ts +15 -9
  150. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  151. package/dist/react/utils/useFileInstance.js +84 -25
  152. package/dist/react/utils/useFileInstance.js.map +1 -1
  153. package/dist/renderers/DiffHunksRenderer.d.ts +30 -15
  154. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  155. package/dist/renderers/DiffHunksRenderer.js +172 -109
  156. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  157. package/dist/renderers/FileRenderer.d.ts +27 -11
  158. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  159. package/dist/renderers/FileRenderer.js +141 -67
  160. package/dist/renderers/FileRenderer.js.map +1 -1
  161. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +2 -2
  162. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
  163. package/dist/renderers/UnresolvedFileHunksRenderer.js +2 -2
  164. package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
  165. package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
  166. package/dist/shiki-stream/tokenizer.js +2 -1
  167. package/dist/shiki-stream/tokenizer.js.map +1 -1
  168. package/dist/ssr/index.d.ts +2 -2
  169. package/dist/ssr/preloadDiffs.d.ts +21 -21
  170. package/dist/ssr/preloadDiffs.d.ts.map +1 -1
  171. package/dist/ssr/preloadDiffs.js +1 -1
  172. package/dist/ssr/preloadDiffs.js.map +1 -1
  173. package/dist/ssr/preloadFile.d.ts +6 -6
  174. package/dist/ssr/preloadFile.d.ts.map +1 -1
  175. package/dist/ssr/preloadFile.js.map +1 -1
  176. package/dist/ssr/preloadPatchFile.d.ts +4 -4
  177. package/dist/ssr/preloadPatchFile.d.ts.map +1 -1
  178. package/dist/ssr/preloadPatchFile.js.map +1 -1
  179. package/dist/style.js +1 -1
  180. package/dist/types.d.ts +13 -263
  181. package/dist/types.d.ts.map +1 -1
  182. package/dist/utils/appendItems.d.ts +5 -0
  183. package/dist/utils/appendItems.d.ts.map +1 -0
  184. package/dist/utils/appendItems.js +8 -0
  185. package/dist/utils/appendItems.js.map +1 -0
  186. package/dist/utils/areDiffTargetsEqual.js +1 -1
  187. package/dist/utils/areDiffTargetsEqual.js.map +1 -1
  188. package/dist/utils/areFileTargetsEqual.d.ts +7 -0
  189. package/dist/utils/areFileTargetsEqual.d.ts.map +1 -0
  190. package/dist/utils/areFileTargetsEqual.js +8 -0
  191. package/dist/utils/areFileTargetsEqual.js.map +1 -0
  192. package/dist/utils/areManagedSnapshotsEqual.d.ts +1 -1
  193. package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
  194. package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
  195. package/dist/utils/areOptionsEqual.d.ts +3 -3
  196. package/dist/utils/areOptionsEqual.d.ts.map +1 -1
  197. package/dist/utils/areOptionsEqual.js.map +1 -1
  198. package/dist/utils/cloneFileDiffMetadata.d.ts +3 -2
  199. package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -1
  200. package/dist/utils/cloneFileDiffMetadata.js +8 -5
  201. package/dist/utils/cloneFileDiffMetadata.js.map +1 -1
  202. package/dist/utils/composeCacheKey.d.ts +6 -0
  203. package/dist/utils/composeCacheKey.d.ts.map +1 -0
  204. package/dist/utils/composeCacheKey.js +10 -0
  205. package/dist/utils/composeCacheKey.js.map +1 -0
  206. package/dist/utils/editSessionAnnotations.d.ts +69 -0
  207. package/dist/utils/editSessionAnnotations.d.ts.map +1 -0
  208. package/dist/utils/editSessionAnnotations.js +64 -0
  209. package/dist/utils/editSessionAnnotations.js.map +1 -0
  210. package/dist/utils/editSessionHunks.d.ts +5 -3
  211. package/dist/utils/editSessionHunks.d.ts.map +1 -1
  212. package/dist/utils/editSessionHunks.js +7 -5
  213. package/dist/utils/editSessionHunks.js.map +1 -1
  214. package/dist/utils/getDiffHunksRendererOptions.d.ts +1 -1
  215. package/dist/utils/getDiffHunksRendererOptions.d.ts.map +1 -1
  216. package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
  217. package/dist/utils/getFileRendererOptions.d.ts +1 -1
  218. package/dist/utils/getFileRendererOptions.d.ts.map +1 -1
  219. package/dist/utils/getFileRendererOptions.js.map +1 -1
  220. package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
  221. package/dist/utils/hydratePartialDiff.js +2 -1
  222. package/dist/utils/hydratePartialDiff.js.map +1 -1
  223. package/dist/utils/lineAnnotationIdentity.d.ts +16 -0
  224. package/dist/utils/lineAnnotationIdentity.d.ts.map +1 -0
  225. package/dist/utils/lineAnnotationIdentity.js +17 -0
  226. package/dist/utils/lineAnnotationIdentity.js.map +1 -0
  227. package/dist/utils/parseDiffFromFile.d.ts +2 -2
  228. package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
  229. package/dist/utils/parseDiffFromFile.js +6 -6
  230. package/dist/utils/parseDiffFromFile.js.map +1 -1
  231. package/dist/utils/parsePatchFiles.d.ts +6 -3
  232. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  233. package/dist/utils/parsePatchFiles.js +34 -9
  234. package/dist/utils/parsePatchFiles.js.map +1 -1
  235. package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
  236. package/dist/utils/renderDiffWithHighlighter.js +6 -5
  237. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  238. package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
  239. package/dist/utils/renderFileWithHighlighter.js +7 -4
  240. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  241. package/dist/utils/trimPatchContext.d.ts.map +1 -1
  242. package/dist/utils/trimPatchContext.js +3 -2
  243. package/dist/utils/trimPatchContext.js.map +1 -1
  244. package/dist/utils/updateDiffHunks.js +1 -1
  245. package/dist/utils/virtualDiffLayout.js +1 -1
  246. package/dist/worker/WorkerPoolManager.d.ts +4 -3
  247. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  248. package/dist/worker/WorkerPoolManager.js +44 -6
  249. package/dist/worker/WorkerPoolManager.js.map +1 -1
  250. package/dist/worker/types.d.ts +5 -0
  251. package/dist/worker/types.d.ts.map +1 -1
  252. package/dist/worker/worker-portable.js +14 -6
  253. package/dist/worker/worker-portable.js.map +1 -1
  254. package/dist/worker/worker.js +14 -6
  255. package/dist/worker/worker.js.map +1 -1
  256. package/package.json +9 -1
  257. package/dist/editor/stateStorage.d.ts +0 -15
  258. package/dist/editor/stateStorage.d.ts.map +0 -1
  259. package/dist/editor/stateStorage.js +0 -65
  260. package/dist/editor/stateStorage.js.map +0 -1
@@ -1,4 +1,7 @@
1
1
  import { DEFAULT_CODE_VIEW_FILE_METRICS, DEFAULT_CODE_VIEW_LAYOUT, DEFAULT_SMOOTH_SCROLL_SETTINGS, DEFAULT_THEMES, DIFFS_DEVELOPMENT_BUILD, DIFFS_TAG_NAME } from "../constants.js";
2
+ import { getThemes } from "../utils/getThemes.js";
3
+ import { areThemesAttached } from "../highlighter/themes/areThemesAttached.js";
4
+ import { isHighlighterLoaded, preloadHighlighter } from "../highlighter/shared_highlighter.js";
2
5
  import { dequeueRender, queueRender } from "../managers/UniversalRenderingManager.js";
3
6
  import { areManagedSnapshotsEqual } from "../utils/areManagedSnapshotsEqual.js";
4
7
  import { areObjectsEqual } from "../utils/areObjectsEqual.js";
@@ -7,7 +10,6 @@ import { areOptionsEqual } from "../utils/areOptionsEqual.js";
7
10
  import { areSelectionsEqual } from "../utils/areSelectionsEqual.js";
8
11
  import { createCodeViewHeaderFooterHostElement } from "../utils/createCodeViewHeaderFooterHostElement.js";
9
12
  import { createWindowFromScrollPosition } from "../utils/createWindowFromScrollPosition.js";
10
- import { finishEditSessionForDiff } from "../utils/editSessionHunks.js";
11
13
  import { isStyleNode } from "../utils/isStyleNode.js";
12
14
  import { prefersReducedMotion } from "../utils/prefersReducedMotion.js";
13
15
  import { roundToDevicePixel } from "../utils/roundToDevicePixel.js";
@@ -198,6 +200,7 @@ var CodeView = class CodeView {
198
200
  options;
199
201
  workerManager;
200
202
  isReadySubscription;
203
+ pendingHighlighterTheme;
201
204
  isContainerManaged;
202
205
  constructor(options = { theme: DEFAULT_THEMES }, workerManager, isContainerManaged = false) {
203
206
  this.options = options;
@@ -402,13 +405,31 @@ var CodeView = class CodeView {
402
405
  this.clearReadySubscription();
403
406
  this.restoreScrollInteractions();
404
407
  this.cleanAllRenderedItems();
405
- for (const record of this.itemEditors.values()) record.editor.cleanUp();
408
+ const teardownSessions = [...this.itemEditors.values()].map((record) => {
409
+ const item = this.idToItem.get(record.state.id);
410
+ if (item != null) record.state.removedItem = item.item;
411
+ return {
412
+ record,
413
+ instance: item?.instance
414
+ };
415
+ });
406
416
  this.itemEditors.clear();
407
417
  this.attachedEditors.clear();
408
418
  this.selectedLines = null;
409
419
  this.items.length = 0;
410
420
  this.idToItem.clear();
411
421
  this.instanceToItem.clear();
422
+ let failed = false;
423
+ let failure;
424
+ for (const { record, instance } of teardownSessions) try {
425
+ record.editor.cleanUp("discard");
426
+ instance?.cleanUp();
427
+ } catch (error) {
428
+ if (!failed) {
429
+ failed = true;
430
+ failure = error;
431
+ }
432
+ }
412
433
  this.layoutDirtyIndex = void 0;
413
434
  this.pendingLayoutReset = void 0;
414
435
  this.stickyContainer.textContent = "";
@@ -429,9 +450,17 @@ var CodeView = class CodeView {
429
450
  this.heightDirty = true;
430
451
  this.resetRenderState();
431
452
  if (!this.isContainerManaged) this.flushSlotCoordinator();
453
+ if (failed) throw failure;
432
454
  }
433
455
  cleanUp() {
434
- this.reset();
456
+ let resetFailed = false;
457
+ let resetFailure;
458
+ try {
459
+ this.reset();
460
+ } catch (error) {
461
+ resetFailed = true;
462
+ resetFailure = error;
463
+ }
435
464
  this.clearElementPool();
436
465
  this.restoreScrollInteractions();
437
466
  this.workerManager?.unsubscribeToThemeChanges(this);
@@ -457,6 +486,7 @@ var CodeView = class CodeView {
457
486
  this.footer.height = 0;
458
487
  this.root = void 0;
459
488
  this.container = void 0;
489
+ if (resetFailed) throw resetFailure;
460
490
  }
461
491
  cleanAllRenderedItems() {
462
492
  if (this.renderState.firstIndex === -1) return;
@@ -585,7 +615,8 @@ var CodeView = class CodeView {
585
615
  /**
586
616
  * Get the live editor for an item currently in edit mode. Use this to drive
587
617
  * editor APIs CodeView does not wrap (applyEdits, undo, setMarkers, …).
588
- * Returns undefined once the item leaves edit mode.
618
+ * Returns undefined once the item's session ends (edit off or removal); a
619
+ * collapsed item keeps its suspended editor.
589
620
  */
590
621
  getEditor(itemId) {
591
622
  return this.itemEditors.get(itemId)?.editor;
@@ -628,7 +659,6 @@ var CodeView = class CodeView {
628
659
  }
629
660
  const editorRecord = this.itemEditors.get(oldId);
630
661
  if (editorRecord != null) {
631
- editorRecord.state.id = newId;
632
662
  this.itemEditors.delete(oldId);
633
663
  this.itemEditors.set(newId, editorRecord);
634
664
  if (this.attachedEditors.delete(oldId)) this.attachedEditors.add(newId);
@@ -741,7 +771,8 @@ var CodeView = class CodeView {
741
771
  }
742
772
  isReady() {
743
773
  const { workerManager } = this;
744
- if (workerManager == null || workerManager.isInitialized() || workerManager.getStats().workersFailed) {
774
+ if (workerManager == null || workerManager.getStats().workersFailed) return this.isSharedHighlighterReady();
775
+ if (workerManager.isInitialized()) {
745
776
  this.clearReadySubscription();
746
777
  return true;
747
778
  }
@@ -757,6 +788,36 @@ var CodeView = class CodeView {
757
788
  if (this.isReadySubscription == null) return;
758
789
  this.isReadySubscription();
759
790
  this.isReadySubscription = void 0;
791
+ this.pendingHighlighterTheme = void 0;
792
+ }
793
+ isSharedHighlighterReady() {
794
+ const theme = this.workerManager?.getFileRenderOptions().theme ?? this.options.theme ?? DEFAULT_THEMES;
795
+ if (isHighlighterLoaded() && areThemesAttached(theme)) {
796
+ this.clearReadySubscription();
797
+ return true;
798
+ }
799
+ if (!areThemesEqual(this.pendingHighlighterTheme, theme)) this.clearReadySubscription();
800
+ this.isReadySubscription ??= (() => {
801
+ this.pendingHighlighterTheme = theme;
802
+ let cancelled = false;
803
+ preloadHighlighter({
804
+ themes: getThemes(theme),
805
+ langs: [],
806
+ preferredHighlighter: this.options.preferredHighlighter
807
+ }).then(() => {
808
+ if (cancelled) return;
809
+ this.clearReadySubscription();
810
+ this.render(true);
811
+ }, (error) => {
812
+ if (cancelled) return;
813
+ this.clearReadySubscription();
814
+ console.error(error);
815
+ });
816
+ return () => {
817
+ cancelled = true;
818
+ };
819
+ })();
820
+ return false;
760
821
  }
761
822
  instanceChanged(instance, layoutDirty) {
762
823
  const item = this.instanceToItem.get(instance);
@@ -888,58 +949,63 @@ var CodeView = class CodeView {
888
949
  return item.item.edit === true && item.item.collapsed !== true;
889
950
  }
890
951
  /**
891
- * Attach (or lazily create) the editor for a mounted edit-mode item. Called
952
+ * Lazily create and attach the editor for a mounted edit-mode item. Called
892
953
  * from the render loop so every mounted item passes through it: fresh
893
954
  * mounts, remounts after virtualization released the item, and items whose
894
955
  * edit flag was just turned on. Editors persist across unmounts, so a
895
- * remounted item re-attaches its existing editor and resumes the retained
896
- * document; the renderers keep the host's file/diff data in sync with the
897
- * session so the remount paints the edited text.
956
+ * remounted item resumes its existing editor and retained document; the
957
+ * instance retains its private session model so the remount
958
+ * paints the edited text without changing the host input.
898
959
  */
899
960
  attachItemEditor(item) {
900
961
  const { id } = item.item;
901
962
  const { createEditor } = this.options;
902
963
  if (item.element == null || this.attachedEditors.has(id) || !this.isItemInEditMode(item)) return;
903
- let record = this.itemEditors.get(id);
904
- let createdEditor = false;
964
+ const record = this.itemEditors.get(id);
965
+ let createdEditor;
905
966
  try {
906
967
  if (record == null) {
907
968
  assertEditorFactory(createEditor);
908
- const state = { id };
909
- const editor = createEditor({ onChange: (file, lineAnnotations) => {
969
+ const state = getItemOptionsState(item.instance.options);
970
+ if (state == null) throw new Error("CodeView.attachItemEditor: instance options are missing their state");
971
+ const onChange = (event) => {
910
972
  const latest = this.idToItem.get(state.id);
911
973
  if (latest == null) return;
912
- state.lastChange = {
913
- item: latest.item,
914
- file,
915
- lineAnnotations
916
- };
917
- this.options.onItemEditChange?.(latest.item, file, lineAnnotations);
918
- } });
919
- if (editor == null) return;
920
- record = {
921
- editor,
922
- state
974
+ this.options.onItemEditChange?.(event, latest.item);
923
975
  };
924
- this.itemEditors.set(id, record);
925
- createdEditor = true;
926
- }
927
- record.editor.edit(item.instance);
976
+ const editStateKey = this.options.getEditStateKey?.(item.item);
977
+ if (item.type === "diff") {
978
+ const editor = createEditor("file-diff", { onChange }, editStateKey);
979
+ createdEditor = editor;
980
+ this.itemEditors.set(id, {
981
+ editor,
982
+ state,
983
+ dispose: editor.edit(item.instance)
984
+ });
985
+ } else {
986
+ const editor = createEditor("file", { onChange }, editStateKey);
987
+ createdEditor = editor;
988
+ this.itemEditors.set(id, {
989
+ editor,
990
+ state,
991
+ dispose: editor.edit(item.instance)
992
+ });
993
+ }
994
+ } else if (item.type === "diff") record.dispose = record.editor.edit(item.instance);
995
+ else record.dispose = record.editor.edit(item.instance);
928
996
  this.attachedEditors.add(id);
929
997
  } catch (error) {
930
- if (createdEditor && record != null) {
931
- this.itemEditors.delete(id);
932
- record.editor.cleanUp();
933
- }
998
+ createdEditor?.cleanUp();
934
999
  this.releaseRenderedItem(item);
935
1000
  throw error;
936
1001
  }
937
1002
  }
938
1003
  /**
939
- * Drop editors for items that can no longer be edited: removed, edit turned
940
- * off, or collapsed. Attachment happens in the render loop via
941
- * attachItemEditor, so this only reconciles editors CodeView is already
942
- * holding.
1004
+ * Reconcile the editors CodeView is holding: complete sessions for items
1005
+ * whose edit turned off or that were removed, and suspend sessions for
1006
+ * collapsed items (the editor tears down, the record and the instance's
1007
+ * session stay for the next expand). Attachment happens in the render loop
1008
+ * via attachItemEditor.
943
1009
  */
944
1010
  syncItemEditors(removedItems) {
945
1011
  if (this.itemEditors.size === 0) return;
@@ -947,25 +1013,77 @@ var CodeView = class CodeView {
947
1013
  for (const [id, record] of this.itemEditors) {
948
1014
  const item = this.idToItem.get(id);
949
1015
  const removedItem = removedItems?.get(id);
950
- if (removedItem == null && item != null && this.isItemInEditMode(item)) continue;
951
- record.editor.cleanUp();
1016
+ if (removedItem == null && item != null) {
1017
+ const { edit = false, collapsed = false } = item.item;
1018
+ if (edit) {
1019
+ if (collapsed && this.attachedEditors.delete(id)) record.editor.cleanUp("recycle");
1020
+ continue;
1021
+ }
1022
+ } else if (removedItem != null) record.state.removedItem = removedItem.item;
952
1023
  this.itemEditors.delete(id);
953
1024
  this.attachedEditors.delete(id);
954
- const { lastChange } = record.state;
955
- const itemSnapshot = removedItem == null ? item?.item ?? lastChange?.item : lastChange?.item ?? removedItem.item;
956
- if (itemSnapshot?.type === "diff") {
957
- if (removedItem == null && item != null && item.type === "diff" && item.instance.completeEditSession()) {
958
- this.markItemLayoutDirty(item);
959
- this.render();
1025
+ completions.push(record);
1026
+ }
1027
+ if (completions.length === 0) return;
1028
+ let failed = false;
1029
+ let failure;
1030
+ for (const record of completions) {
1031
+ try {
1032
+ record.dispose();
1033
+ } catch (error) {
1034
+ if (!failed) {
1035
+ failed = true;
1036
+ failure = error;
960
1037
  }
961
- finishEditSessionForDiff(itemSnapshot.fileDiff);
962
1038
  }
963
- if (lastChange != null) completions.push(removedItem != null || item == null ? lastChange : {
964
- ...lastChange,
965
- item: item.item
966
- });
1039
+ const item = this.idToItem.get(record.state.id);
1040
+ if (item != null) this.markItemLayoutDirty(item);
967
1041
  }
968
- for (const { item, file, lineAnnotations } of completions) this.options.onItemEditComplete?.(item, file, lineAnnotations);
1042
+ this.render();
1043
+ if (failed) throw failure;
1044
+ }
1045
+ requireItemFromState(state) {
1046
+ const item = this.idToItem.get(state.id)?.item ?? state.removedItem;
1047
+ if (item == null) throw new Error(`CodeView.onItemEditComplete: unknown item "${state.id}"`);
1048
+ return item;
1049
+ }
1050
+ /**
1051
+ * Item-instance `onEditComplete` adapter for file items: builds the
1052
+ * accepted next item, hands it to `onItemEditComplete` alongside the event
1053
+ * and the owning item, and translates the identity of the returned item to
1054
+ * the component return contract.
1055
+ */
1056
+ completeFileItemEdit(state, event) {
1057
+ const item = this.requireItemFromState(state);
1058
+ if (item.type !== "file") throw new Error(`CodeView.onItemEditComplete: item "${state.id}" is not a file item`);
1059
+ const nextItem = {
1060
+ ...item,
1061
+ file: event.file,
1062
+ annotations: event.lineAnnotations,
1063
+ edit: false,
1064
+ version: (item.version ?? 0) + 1
1065
+ };
1066
+ if ((this.options.onItemEditComplete?.(event, item, nextItem) ?? "reject") === "reject") return "reject";
1067
+ if (this.idToItem.has(item.id)) this.updateItem(nextItem);
1068
+ return "accept";
1069
+ }
1070
+ /**
1071
+ * Item-instance `onEditComplete` adapter for diff items; see
1072
+ * completeFileItemEdit.
1073
+ */
1074
+ completeDiffItemEdit(state, event) {
1075
+ const item = this.requireItemFromState(state);
1076
+ if (item.type !== "diff") throw new Error(`CodeView.onItemEditComplete: item "${state.id}" is not a diff item`);
1077
+ const nextItem = {
1078
+ ...item,
1079
+ fileDiff: event.fileDiff,
1080
+ annotations: event.lineAnnotations,
1081
+ edit: false,
1082
+ version: (item.version ?? 0) + 1
1083
+ };
1084
+ if ((this.options.onItemEditComplete?.(event, item, nextItem) ?? "reject") === "reject") return "reject";
1085
+ if (this.idToItem.has(item.id)) this.updateItem(nextItem);
1086
+ return "accept";
969
1087
  }
970
1088
  renamePendingScrollTarget(oldId, newId) {
971
1089
  const { pendingScrollTarget } = this;
@@ -987,6 +1105,12 @@ var CodeView = class CodeView {
987
1105
  if (state == null) return;
988
1106
  return this.getItemOptions(state, "file")?.item.collapsed;
989
1107
  });
1108
+ defineItemOption(prototype, "onEditComplete", (receiver) => {
1109
+ if (this.options.onItemEditComplete == null) return;
1110
+ const state = getItemOptionsState(receiver);
1111
+ if (state == null) return;
1112
+ return (event) => this.completeFileItemEdit(state, event);
1113
+ });
990
1114
  for (const key of CODE_VIEW_SHARED_CALLBACK_KEYS) this.defineItemSharedCallback(prototype, "file", key);
991
1115
  for (const key of CODE_VIEW_SELECTION_CALLBACK_KEYS) this.defineItemSelectionCallback(prototype, "file", key);
992
1116
  return prototype;
@@ -1001,6 +1125,12 @@ var CodeView = class CodeView {
1001
1125
  if (state == null) return;
1002
1126
  return this.getItemOptions(state, "diff")?.item.collapsed;
1003
1127
  });
1128
+ defineItemOption(prototype, "onEditComplete", (receiver) => {
1129
+ if (this.options.onItemEditComplete == null) return;
1130
+ const state = getItemOptionsState(receiver);
1131
+ if (state == null) return;
1132
+ return (event) => this.completeDiffItemEdit(state, event);
1133
+ });
1004
1134
  for (const key of CODE_VIEW_SHARED_CALLBACK_KEYS) this.defineItemSharedCallback(prototype, "diff", key);
1005
1135
  for (const key of CODE_VIEW_SELECTION_CALLBACK_KEYS) this.defineItemSelectionCallback(prototype, "diff", key);
1006
1136
  return prototype;
@@ -1598,7 +1728,10 @@ var CodeView = class CodeView {
1598
1728
  syncPagedScrollScaffolding(windowSpecs) {
1599
1729
  this.syncContainerHeight();
1600
1730
  const stickyBounds = this.getStickyBounds(windowSpecs);
1601
- if (stickyBounds == null) return;
1731
+ if (stickyBounds == null) {
1732
+ this.stickyOffset.style.height = `${this.getPagedLayoutTop(windowSpecs.top)}px`;
1733
+ return;
1734
+ }
1602
1735
  this.applyStickyPositioning(stickyBounds);
1603
1736
  }
1604
1737
  reconcileRenderedItems(updatedItems) {
@@ -1910,11 +2043,8 @@ var CodeView = class CodeView {
1910
2043
  const item = this.items[index];
1911
2044
  if (item == null) throw new Error("CodeView.recomputeLayout: invalid item index");
1912
2045
  item.top = runningTop;
1913
- if (item.type === "diff") {
1914
- const fileDiff = item.instance.consumeCodeViewLayoutChanges(item.item.fileDiff);
1915
- if (fileDiff != null) Object.assign(item.item.fileDiff, fileDiff);
1916
- item.height = item.instance.prepareCodeViewItem(item.item.fileDiff, runningTop, reset, item.item.annotations ?? []);
1917
- } else item.height = item.instance.prepareCodeViewItem(item.item.file, runningTop, reset, item.item.annotations ?? []);
2046
+ if (item.type === "diff") item.height = item.instance.updateCodeViewLayout(item.item.fileDiff, runningTop, reset, item.item.annotations ?? []);
2047
+ else item.height = item.instance.updateCodeViewLayout(item.item.file, runningTop, reset, item.item.annotations ?? []);
1918
2048
  runningTop += item.height;
1919
2049
  if (index < this.items.length - 1) runningTop += layout.gap;
1920
2050
  }
@@ -1935,8 +2065,8 @@ var CodeView = class CodeView {
1935
2065
  };
1936
2066
  function prepareItemInstance(item) {
1937
2067
  item.instance.cleanUp(true);
1938
- if (item.type === "diff") return item.instance.prepareCodeViewItem(item.item.fileDiff, item.top, void 0, item.item.annotations ?? []);
1939
- else return item.instance.prepareCodeViewItem(item.item.file, item.top, void 0, item.item.annotations ?? []);
2068
+ if (item.type === "diff") return item.instance.updateCodeViewLayout(item.item.fileDiff, item.top, void 0, item.item.annotations ?? []);
2069
+ else return item.instance.updateCodeViewLayout(item.item.file, item.top, void 0, item.item.annotations ?? []);
1940
2070
  }
1941
2071
  function shouldClearPool(previousOptions, nextOptions) {
1942
2072
  return !areThemesEqual(previousOptions.theme ?? DEFAULT_THEMES, nextOptions.theme ?? DEFAULT_THEMES) || (previousOptions.themeType ?? "system") !== (nextOptions.themeType ?? "system") || previousOptions.unsafeCSS !== nextOptions.unsafeCSS;