@pierre/diffs 1.3.0-beta.8 → 1.3.0-rc.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 (229) hide show
  1. package/dist/components/CodeView.d.ts +12 -12
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +51 -43
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +7 -2
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +36 -8
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +34 -6
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +198 -17
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.d.ts.map +1 -1
  14. package/dist/components/FileStream.js +2 -1
  15. package/dist/components/FileStream.js.map +1 -1
  16. package/dist/components/VirtualizedFile.d.ts +2 -1
  17. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  18. package/dist/components/VirtualizedFile.js +9 -5
  19. package/dist/components/VirtualizedFile.js.map +1 -1
  20. package/dist/components/VirtualizedFileDiff.d.ts +14 -0
  21. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  22. package/dist/components/VirtualizedFileDiff.js +61 -3
  23. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  24. package/dist/components/Virtualizer.d.ts +14 -2
  25. package/dist/components/Virtualizer.d.ts.map +1 -1
  26. package/dist/components/Virtualizer.js +29 -3
  27. package/dist/components/Virtualizer.js.map +1 -1
  28. package/dist/edit/index.d.ts +5 -0
  29. package/dist/edit/index.js +3 -0
  30. package/dist/editor/command.d.ts +1 -1
  31. package/dist/editor/command.d.ts.map +1 -1
  32. package/dist/editor/command.js +11 -0
  33. package/dist/editor/command.js.map +1 -1
  34. package/dist/editor/editStack.d.ts +6 -2
  35. package/dist/editor/editStack.d.ts.map +1 -1
  36. package/dist/editor/editStack.js +54 -13
  37. package/dist/editor/editStack.js.map +1 -1
  38. package/dist/editor/editor.d.ts +51 -23
  39. package/dist/editor/editor.d.ts.map +1 -1
  40. package/dist/editor/editor.js +995 -242
  41. package/dist/editor/editor.js.map +1 -1
  42. package/dist/editor/editor2.js +1 -1
  43. package/dist/editor/languages.d.ts +26 -0
  44. package/dist/editor/languages.d.ts.map +1 -0
  45. package/dist/editor/languages.js +363 -0
  46. package/dist/editor/languages.js.map +1 -0
  47. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  48. package/dist/editor/lineAnnotations.js +25 -26
  49. package/dist/editor/lineAnnotations.js.map +1 -1
  50. package/dist/editor/marker.d.ts +5 -3
  51. package/dist/editor/marker.d.ts.map +1 -1
  52. package/dist/editor/marker.js +111 -91
  53. package/dist/editor/marker.js.map +1 -1
  54. package/dist/editor/matchBrackets.d.ts +3 -2
  55. package/dist/editor/matchBrackets.d.ts.map +1 -1
  56. package/dist/editor/matchBrackets.js +2 -10
  57. package/dist/editor/matchBrackets.js.map +1 -1
  58. package/dist/editor/pieceTable.d.ts +2 -1
  59. package/dist/editor/pieceTable.d.ts.map +1 -1
  60. package/dist/editor/pieceTable.js +103 -39
  61. package/dist/editor/pieceTable.js.map +1 -1
  62. package/dist/editor/platform.js +2 -0
  63. package/dist/editor/platform.js.map +1 -1
  64. package/dist/editor/popover.d.ts +25 -5
  65. package/dist/editor/popover.d.ts.map +1 -1
  66. package/dist/editor/popover.js +60 -14
  67. package/dist/editor/popover.js.map +1 -1
  68. package/dist/editor/searchPanel.d.ts +1 -0
  69. package/dist/editor/searchPanel.d.ts.map +1 -1
  70. package/dist/editor/searchPanel.js +15 -8
  71. package/dist/editor/searchPanel.js.map +1 -1
  72. package/dist/editor/selection.d.ts +31 -11
  73. package/dist/editor/selection.d.ts.map +1 -1
  74. package/dist/editor/selection.js +198 -70
  75. package/dist/editor/selection.js.map +1 -1
  76. package/dist/editor/selectionAction.d.ts +4 -3
  77. package/dist/editor/selectionAction.d.ts.map +1 -1
  78. package/dist/editor/selectionAction.js +9 -5
  79. package/dist/editor/selectionAction.js.map +1 -1
  80. package/dist/editor/stateStorage.d.ts +15 -0
  81. package/dist/editor/stateStorage.d.ts.map +1 -0
  82. package/dist/editor/stateStorage.js +65 -0
  83. package/dist/editor/stateStorage.js.map +1 -0
  84. package/dist/editor/textDocument.d.ts +12 -77
  85. package/dist/editor/textDocument.d.ts.map +1 -1
  86. package/dist/editor/textDocument.js +76 -34
  87. package/dist/editor/textDocument.js.map +1 -1
  88. package/dist/editor/textMeasure.d.ts +7 -12
  89. package/dist/editor/textMeasure.d.ts.map +1 -1
  90. package/dist/editor/textMeasure.js +40 -32
  91. package/dist/editor/textMeasure.js.map +1 -1
  92. package/dist/editor/{tokenzier.d.ts → tokenizer.d.ts} +3 -3
  93. package/dist/editor/tokenizer.d.ts.map +1 -0
  94. package/dist/editor/{tokenzier.js → tokenizer.js} +91 -26
  95. package/dist/editor/tokenizer.js.map +1 -0
  96. package/dist/editor/utils.js +1 -1
  97. package/dist/editor/utils.js.map +1 -1
  98. package/dist/index.d.ts +5 -4
  99. package/dist/index.js +7 -6
  100. package/dist/managers/InteractionManager.d.ts +18 -7
  101. package/dist/managers/InteractionManager.d.ts.map +1 -1
  102. package/dist/managers/InteractionManager.js +154 -99
  103. package/dist/managers/InteractionManager.js.map +1 -1
  104. package/dist/managers/UniversalRenderingManager.d.ts +2 -1
  105. package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
  106. package/dist/managers/UniversalRenderingManager.js +7 -3
  107. package/dist/managers/UniversalRenderingManager.js.map +1 -1
  108. package/dist/react/CodeView.d.ts +13 -13
  109. package/dist/react/CodeView.d.ts.map +1 -1
  110. package/dist/react/CodeView.js +38 -29
  111. package/dist/react/CodeView.js.map +1 -1
  112. package/dist/react/EditContext.d.ts +20 -0
  113. package/dist/react/EditContext.d.ts.map +1 -0
  114. package/dist/react/EditContext.js +20 -0
  115. package/dist/react/EditContext.js.map +1 -0
  116. package/dist/react/File.d.ts +2 -1
  117. package/dist/react/File.d.ts.map +1 -1
  118. package/dist/react/File.js +3 -2
  119. package/dist/react/File.js.map +1 -1
  120. package/dist/react/FileDiff.d.ts +2 -2
  121. package/dist/react/FileDiff.d.ts.map +1 -1
  122. package/dist/react/FileDiff.js +3 -2
  123. package/dist/react/FileDiff.js.map +1 -1
  124. package/dist/react/MultiFileDiff.d.ts +2 -2
  125. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  126. package/dist/react/MultiFileDiff.js +3 -2
  127. package/dist/react/MultiFileDiff.js.map +1 -1
  128. package/dist/react/PatchDiff.d.ts +2 -2
  129. package/dist/react/PatchDiff.d.ts.map +1 -1
  130. package/dist/react/PatchDiff.js +3 -2
  131. package/dist/react/PatchDiff.js.map +1 -1
  132. package/dist/react/UnresolvedFile.d.ts +1 -1
  133. package/dist/react/UnresolvedFile.js.map +1 -1
  134. package/dist/react/index.d.ts +4 -4
  135. package/dist/react/index.js +3 -3
  136. package/dist/react/types.d.ts +9 -1
  137. package/dist/react/types.d.ts.map +1 -1
  138. package/dist/react/utils/useFileDiffInstance.d.ts +5 -3
  139. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  140. package/dist/react/utils/useFileDiffInstance.js +28 -27
  141. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  142. package/dist/react/utils/useFileInstance.d.ts +5 -3
  143. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  144. package/dist/react/utils/useFileInstance.js +29 -25
  145. package/dist/react/utils/useFileInstance.js.map +1 -1
  146. package/dist/react/utils/useUnresolvedFileInstance.js +3 -3
  147. package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
  148. package/dist/renderers/DiffHunksRenderer.d.ts +33 -1
  149. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  150. package/dist/renderers/DiffHunksRenderer.js +134 -21
  151. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  152. package/dist/renderers/FileRenderer.d.ts +2 -0
  153. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  154. package/dist/renderers/FileRenderer.js +33 -11
  155. package/dist/renderers/FileRenderer.js.map +1 -1
  156. package/dist/ssr/FileDiffReact.js +1 -1
  157. package/dist/ssr/index.d.ts +2 -2
  158. package/dist/ssr/preloadDiffs.js +1 -1
  159. package/dist/style.js +1 -1
  160. package/dist/types.d.ts +185 -42
  161. package/dist/types.d.ts.map +1 -1
  162. package/dist/utils/annotationHelpers.d.ts +20 -0
  163. package/dist/utils/annotationHelpers.d.ts.map +1 -0
  164. package/dist/utils/annotationHelpers.js +29 -0
  165. package/dist/utils/annotationHelpers.js.map +1 -0
  166. package/dist/utils/computeFileOffsets.d.ts.map +1 -1
  167. package/dist/utils/computeFileOffsets.js +34 -5
  168. package/dist/utils/computeFileOffsets.js.map +1 -1
  169. package/dist/utils/editSessionHunks.d.ts +66 -0
  170. package/dist/utils/editSessionHunks.d.ts.map +1 -0
  171. package/dist/utils/editSessionHunks.js +437 -0
  172. package/dist/utils/editSessionHunks.js.map +1 -0
  173. package/dist/utils/getHunkSideBoundaries.d.ts +7 -0
  174. package/dist/utils/getHunkSideBoundaries.d.ts.map +1 -0
  175. package/dist/utils/getHunkSideBoundaries.js +12 -0
  176. package/dist/utils/getHunkSideBoundaries.js.map +1 -0
  177. package/dist/utils/getTotalLineCountFromHunks.d.ts.map +1 -1
  178. package/dist/utils/getTotalLineCountFromHunks.js +2 -1
  179. package/dist/utils/getTotalLineCountFromHunks.js.map +1 -1
  180. package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
  181. package/dist/utils/hydratePartialDiff.js +4 -3
  182. package/dist/utils/hydratePartialDiff.js.map +1 -1
  183. package/dist/utils/isGutterUtilityPath.d.ts +5 -0
  184. package/dist/utils/isGutterUtilityPath.d.ts.map +1 -0
  185. package/dist/utils/isGutterUtilityPath.js +12 -0
  186. package/dist/utils/isGutterUtilityPath.js.map +1 -0
  187. package/dist/utils/iterateOverDiff.d.ts.map +1 -1
  188. package/dist/utils/iterateOverDiff.js +17 -12
  189. package/dist/utils/iterateOverDiff.js.map +1 -1
  190. package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
  191. package/dist/utils/parseMergeConflictDiffFromFile.js +9 -6
  192. package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
  193. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  194. package/dist/utils/parsePatchFiles.js +6 -3
  195. package/dist/utils/parsePatchFiles.js.map +1 -1
  196. package/dist/utils/realignChangeContent.d.ts +33 -0
  197. package/dist/utils/realignChangeContent.d.ts.map +1 -0
  198. package/dist/utils/realignChangeContent.js +148 -0
  199. package/dist/utils/realignChangeContent.js.map +1 -0
  200. package/dist/utils/renderDiffWithHighlighter.js +1 -1
  201. package/dist/utils/resolveRegion.d.ts.map +1 -1
  202. package/dist/utils/resolveRegion.js +18 -2
  203. package/dist/utils/resolveRegion.js.map +1 -1
  204. package/dist/utils/updateDiffHunks.d.ts +8 -2
  205. package/dist/utils/updateDiffHunks.d.ts.map +1 -1
  206. package/dist/utils/updateDiffHunks.js +9 -7
  207. package/dist/utils/updateDiffHunks.js.map +1 -1
  208. package/dist/utils/virtualDiffLayout.d.ts +42 -2
  209. package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
  210. package/dist/utils/virtualDiffLayout.js +101 -7
  211. package/dist/utils/virtualDiffLayout.js.map +1 -1
  212. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  213. package/dist/worker/WorkerPoolManager.js +4 -2
  214. package/dist/worker/WorkerPoolManager.js.map +1 -1
  215. package/dist/worker/types.d.ts +4 -0
  216. package/dist/worker/types.d.ts.map +1 -1
  217. package/dist/worker/worker-portable.js +60 -20
  218. package/dist/worker/worker-portable.js.map +1 -1
  219. package/dist/worker/worker.js +61 -19
  220. package/dist/worker/worker.js.map +1 -1
  221. package/package.json +13 -8
  222. package/dist/editor/index.d.ts +0 -3
  223. package/dist/editor/index.js +0 -3
  224. package/dist/editor/tokenzier.d.ts.map +0 -1
  225. package/dist/editor/tokenzier.js.map +0 -1
  226. package/dist/react/EditorContext.d.ts +0 -15
  227. package/dist/react/EditorContext.d.ts.map +0 -1
  228. package/dist/react/EditorContext.js +0 -23
  229. package/dist/react/EditorContext.js.map +0 -1
@@ -1,5 +1,10 @@
1
1
  import { CUSTOM_HEADER_SLOT_ID, DEFAULT_THEMES, EMPTY_RENDER_RANGE, HEADER_FILENAME_SUFFIX_SLOT_ID, HEADER_METADATA_SLOT_ID, HEADER_PREFIX_SLOT_ID } from "../constants.js";
2
+ import { dequeueRender, queueRender } from "../managers/UniversalRenderingManager.js";
2
3
  import { areThemesEqual } from "../utils/areThemesEqual.js";
4
+ import { getHunkSideStartBoundary } from "../utils/getHunkSideBoundaries.js";
5
+ import { parseDiffFromFile } from "../utils/parseDiffFromFile.js";
6
+ import { getExpandedRegion, getHunkAdditionLineRange, getNearestRenderableAdditionLine, getTrailingExpandedRegion, isAdditionLineRenderable } from "../utils/virtualDiffLayout.js";
7
+ import { captureExpansionAnchors, finishEditSessionForDiff, rebuildExpansionFromAnchors } from "../utils/editSessionHunks.js";
3
8
  import { isStyleNode } from "../utils/isStyleNode.js";
4
9
  import { areFilesEqual } from "../utils/areFilesEqual.js";
5
10
  import { InteractionManager, pluckInteractionOptions } from "../managers/InteractionManager.js";
@@ -21,8 +26,9 @@ import "./web-components.js";
21
26
  import { awaitWithTimeout } from "../utils/awaitWithTimeout.js";
22
27
  import { getDiffFileInput } from "../utils/getDiffFileInput.js";
23
28
  import { hydratePartialDiff } from "../utils/hydratePartialDiff.js";
24
- import { parseDiffFromFile } from "../utils/parseDiffFromFile.js";
29
+ import { iterateOverDiff } from "../utils/iterateOverDiff.js";
25
30
  import { ScrollSyncManager } from "../managers/ScrollSyncManager.js";
31
+ import { isDefaultRenderRange } from "../utils/isDefaultRenderRange.js";
26
32
  import { isDiffPlainText } from "../utils/isDiffPlainText.js";
27
33
  import { DiffHunksRenderer } from "../renderers/DiffHunksRenderer.js";
28
34
  import { areDiffLineAnnotationsEqual } from "../utils/areDiffLineAnnotationsEqual.js";
@@ -83,7 +89,9 @@ var FileDiff = class {
83
89
  enabled = true;
84
90
  editor;
85
91
  refreshViewTimeout;
86
- deferSetSelection;
92
+ lineStateRefreshPending = false;
93
+ deferredSelectedLines;
94
+ deferredEditorActiveLine;
87
95
  constructor(options = { theme: DEFAULT_THEMES }, workerManager, isContainerManaged = false) {
88
96
  this.options = options;
89
97
  this.workerManager = workerManager;
@@ -111,8 +119,9 @@ var FileDiff = class {
111
119
  let targetUnifiedIndex;
112
120
  let targetSplitIndex;
113
121
  hunkIterator: for (const hunk of fileDiff.hunks) {
114
- let currentLineNumber = side === "deletions" ? hunk.deletionStart : hunk.additionStart;
122
+ const hunkStart = side === "deletions" ? hunk.deletionStart : hunk.additionStart;
115
123
  const hunkCount = side === "deletions" ? hunk.deletionCount : hunk.additionCount;
124
+ let currentLineNumber = getHunkSideStartBoundary(hunkStart, hunkCount) + 1;
116
125
  let splitIndex = hunk.splitLineStart;
117
126
  let unifiedIndex = hunk.unifiedLineStart;
118
127
  if (lineNumber < currentLineNumber) {
@@ -200,9 +209,24 @@ var FileDiff = class {
200
209
  return true;
201
210
  }
202
211
  setSelectedLines(range, options) {
203
- if (this.refreshViewTimeout != null) this.deferSetSelection = [range, options];
212
+ if (this.lineStateRefreshPending) this.deferredSelectedLines = [range, options];
204
213
  else this.interactionManager.setSelection(range, options);
205
214
  }
215
+ setEditorActiveLine(lineNumber, options) {
216
+ if (this.lineStateRefreshPending) this.deferredEditorActiveLine = [lineNumber, options];
217
+ else this.interactionManager.setEditorActiveLine(lineNumber, {
218
+ lineNumberOnly: options?.lineNumberOnly,
219
+ side: options?.side ?? "additions"
220
+ });
221
+ }
222
+ flushDeferredLineState() {
223
+ const { deferredEditorActiveLine: editorActiveLine, deferredSelectedLines: selectedLines } = this;
224
+ this.lineStateRefreshPending = false;
225
+ this.deferredEditorActiveLine = void 0;
226
+ this.deferredSelectedLines = void 0;
227
+ if (editorActiveLine != null) this.setEditorActiveLine(...editorActiveLine);
228
+ if (selectedLines != null) this.interactionManager.setSelection(...selectedLines);
229
+ }
206
230
  flushManagers() {
207
231
  if (!this.managersDirty || this.pre == null) {
208
232
  this.managersDirty = false;
@@ -222,8 +246,19 @@ var FileDiff = class {
222
246
  if (typeof this.options.hunkSeparators === "function") return true;
223
247
  return overflow === "scroll" && (this.lineAnnotations.length > 0 || this.pre?.hasAttribute("data-has-merge-conflict") === true);
224
248
  }
249
+ getCodeScrollLeft() {
250
+ return Math.max(this.codeUnified?.scrollLeft ?? 0, this.codeDeletions?.scrollLeft ?? 0, this.codeAdditions?.scrollLeft ?? 0);
251
+ }
252
+ setCodeScrollLeft(position) {
253
+ if (this.codeUnified != null) this.codeUnified.scrollLeft = position;
254
+ if (this.codeAdditions != null) this.codeAdditions.scrollLeft = position;
255
+ if (this.codeDeletions != null) this.codeDeletions.scrollLeft = position;
256
+ }
225
257
  cleanUp(recycle = false) {
258
+ dequeueRender(this.handleEditSessionRender);
226
259
  this.emitPostRender(true);
260
+ this.editor?.cleanUp(recycle);
261
+ this.editor = void 0;
227
262
  this.resizeManager.cleanUp();
228
263
  this.interactionManager.cleanUp();
229
264
  this.scrollSyncManager.cleanUp();
@@ -272,13 +307,14 @@ var FileDiff = class {
272
307
  this.deletionFile = void 0;
273
308
  this.additionFile = void 0;
274
309
  }
275
- this.enabled = false;
276
- this.editor?.cleanUp(recycle);
277
- this.editor = void 0;
278
310
  if (this.refreshViewTimeout != null) {
279
311
  clearTimeout(this.refreshViewTimeout);
280
312
  this.refreshViewTimeout = void 0;
281
313
  }
314
+ this.lineStateRefreshPending = false;
315
+ this.deferredEditorActiveLine = void 0;
316
+ this.deferredSelectedLines = void 0;
317
+ this.enabled = false;
282
318
  }
283
319
  virtualizedSetup() {
284
320
  this.enabled = true;
@@ -449,6 +485,10 @@ var FileDiff = class {
449
485
  if (diffDidChange) this.cachedHeaderHTML = void 0;
450
486
  if (lineAnnotations != null) this.setLineAnnotations(lineAnnotations);
451
487
  if (this.fileDiff == null) return false;
488
+ if (this.fileDiff.editSessionDirty === true && this.shouldSelfHealEditSession()) {
489
+ finishEditSessionForDiff(this.fileDiff, this.options.parseDiffOptions);
490
+ this.hunksRenderer.refreshHighlightedResult();
491
+ }
452
492
  if (expandUnchanged) this.loadFilesIfNecessary();
453
493
  this.hunksRenderer.setOptions(this.getHunksRendererOptions(this.options));
454
494
  this.syncInteractionOptions();
@@ -538,22 +578,82 @@ var FileDiff = class {
538
578
  const fileContainer = this.fileContainer;
539
579
  const fileDiff = this.fileDiffCache;
540
580
  const lineAnnotations = this.lineAnnotations;
541
- const renderRange = this.renderRange;
581
+ const renderRange = this.computeEditorRenderRange(this.renderRange);
542
582
  if (editor != null && fileContainer != null && fileDiff != null && !fileDiff.isPartial) this.hunksRenderer.initializeHighlighter().then((highlighter) => {
543
583
  if (!this.enabled || this.editor !== editor || this.fileContainer !== fileContainer || this.fileDiffCache !== fileDiff) return;
544
584
  editor.__syncRenderView(highlighter, fileContainer, fileDiff, lineAnnotations, renderRange);
545
585
  });
546
586
  }
587
+ computeEditorRenderRange(renderRange) {
588
+ const fileDiff = this.fileDiffCache;
589
+ if (renderRange == null || fileDiff == null || isDefaultRenderRange(renderRange)) return renderRange;
590
+ const { diffStyle = "split", expandUnchanged = false, collapsedContextThreshold = 1 } = this.options;
591
+ let firstLineNumber;
592
+ let lastLineNumber;
593
+ iterateOverDiff({
594
+ diff: fileDiff,
595
+ diffStyle,
596
+ startingLine: renderRange.startingLine,
597
+ totalLines: renderRange.totalLines,
598
+ expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
599
+ collapsedContextThreshold,
600
+ callback: ({ additionLine }) => {
601
+ if (additionLine != null) {
602
+ firstLineNumber ??= additionLine.lineNumber;
603
+ lastLineNumber = additionLine.lineNumber;
604
+ }
605
+ }
606
+ });
607
+ if (firstLineNumber == null || lastLineNumber == null) return {
608
+ ...renderRange,
609
+ startingLine: 0,
610
+ totalLines: 0
611
+ };
612
+ return {
613
+ ...renderRange,
614
+ startingLine: firstLineNumber - 1,
615
+ totalLines: lastLineNumber - firstLineNumber + 1
616
+ };
617
+ }
547
618
  attachEditor(editor) {
619
+ if (this.type !== "file-diff") throw new Error(`FileDiff.attachEditor: cannot attach an editor to a "${this.type}" diff`);
548
620
  this.editor?.cleanUp();
549
621
  this.editor = editor;
550
- this.interactionManager.setEditorAttached(true);
622
+ this.hunksRenderer.beginEditSession();
623
+ if (this.fileDiff?.isPartial === true) this.loadFilesIfNecessary();
551
624
  this.syncRenderViewToEditor();
552
- return () => {
625
+ return (recycle) => {
553
626
  this.editor = void 0;
554
- this.interactionManager.setEditorAttached(false);
627
+ if (recycle !== true) this.finishEditSession();
555
628
  };
556
629
  }
630
+ finishEditSession() {
631
+ this.hunksRenderer.endEditSession();
632
+ this.completeEditSession();
633
+ }
634
+ /**
635
+ * Run the genuine session-end recompute: restore recompute-shaped hunks (a
636
+ * context-only region collapses away, boundaries re-derive), preserve
637
+ * expansion state best-effort via old-side anchors, and repaint through
638
+ * the session render path — which also invalidates virtualized layout,
639
+ * since nothing else does at exit now that editing does not flip
640
+ * expandUnchanged. Marker-guarded and idempotent; CodeView also calls this
641
+ * when reaping a session whose detach closure was consumed by a recycle.
642
+ * Safe on a cleaned-up instance: the recompute is pure metadata work and
643
+ * the deferred rerender is enabled-guarded. Returns true when a recompute
644
+ * ran.
645
+ */
646
+ completeEditSession() {
647
+ const fileDiff = this.fileDiffCache;
648
+ if (fileDiff == null || fileDiff.editSessionDirty !== true) return false;
649
+ const { collapsedContextThreshold = 1 } = this.options;
650
+ const anchors = captureExpansionAnchors(fileDiff, this.hunksRenderer.getExpandedHunksMap(), collapsedContextThreshold);
651
+ finishEditSessionForDiff(fileDiff, this.options.parseDiffOptions);
652
+ this.hunksRenderer.setExpandedHunksMap(rebuildExpansionFromAnchors(fileDiff, anchors));
653
+ this.hunksRenderer.refreshHighlightedResult();
654
+ this.escalateEditSessionRender();
655
+ return true;
656
+ }
557
657
  applyDocumentChange(textDocument, newLineAnnotations) {
558
658
  this.hunksRenderer.applyDocumentChange(textDocument);
559
659
  const fileDiff = this.hunksRenderer.diffCache;
@@ -570,21 +670,99 @@ var FileDiff = class {
570
670
  this.rerender();
571
671
  this.interactionManager.setSelectionDirty();
572
672
  }
573
- updateRenderCache(dirtyLines, themeType, shouldRefreshView) {
574
- this.hunksRenderer.updateRenderCache(dirtyLines, themeType);
673
+ updateRenderCache(dirtyLines, themeType, shouldRefreshView, lineCountChangeInFlight = false) {
674
+ if (this.hunksRenderer.updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight)) {
675
+ if (this.refreshViewTimeout != null) {
676
+ clearTimeout(this.refreshViewTimeout);
677
+ this.refreshViewTimeout = void 0;
678
+ }
679
+ this.lineStateRefreshPending = true;
680
+ this.escalateEditSessionRender();
681
+ return;
682
+ }
575
683
  if (shouldRefreshView) {
576
684
  if (this.refreshViewTimeout != null) clearTimeout(this.refreshViewTimeout);
685
+ this.lineStateRefreshPending = true;
577
686
  this.refreshViewTimeout = setTimeout(() => {
578
687
  this.refreshViewTimeout = void 0;
579
688
  if (this.options.diffStyle === "split") this.refreshSplitDiffView();
580
689
  else this.refreshUnifiedDiffView();
581
- if (this.deferSetSelection != null) {
582
- this.interactionManager.setSelection(...this.deferSetSelection);
583
- this.deferSetSelection = void 0;
584
- }
690
+ this.flushDeferredLineState();
585
691
  }, 150);
586
692
  }
587
693
  }
694
+ isLineRenderable(lineNumber) {
695
+ const fileDiff = this.fileDiffCache;
696
+ if (fileDiff == null) return true;
697
+ const { expandUnchanged = false, collapsedContextThreshold = 1 } = this.options;
698
+ return isAdditionLineRenderable({
699
+ fileDiff,
700
+ lineNumber,
701
+ expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
702
+ collapsedContextThreshold
703
+ });
704
+ }
705
+ getNearestRenderableLine(lineNumber, direction) {
706
+ const fileDiff = this.fileDiffCache;
707
+ if (fileDiff == null) return lineNumber;
708
+ const { expandUnchanged = false, collapsedContextThreshold = 1 } = this.options;
709
+ return getNearestRenderableAdditionLine({
710
+ fileDiff,
711
+ lineNumber,
712
+ direction,
713
+ expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
714
+ collapsedContextThreshold
715
+ });
716
+ }
717
+ revealLine(lineNumber) {
718
+ const fileDiff = this.fileDiffCache;
719
+ const { expandUnchanged = false, collapsedContextThreshold = 1, expansionLineCount = 100 } = this.options;
720
+ if (fileDiff == null || fileDiff.isPartial || expandUnchanged) return false;
721
+ const expandedHunks = this.hunksRenderer.getExpandedHunksMap();
722
+ for (const [hunkIndex, hunk] of fileDiff.hunks.entries()) {
723
+ const [hunkStart, hunkEnd] = getHunkAdditionLineRange(hunk);
724
+ if (lineNumber < hunkStart) {
725
+ const region = getExpandedRegion({
726
+ isPartial: fileDiff.isPartial,
727
+ rangeSize: hunk.collapsedBefore,
728
+ expandedHunks,
729
+ hunkIndex,
730
+ collapsedContextThreshold
731
+ });
732
+ const gapStart = hunkStart - region.rangeSize;
733
+ if (region.renderAll || lineNumber < gapStart + region.fromStart || lineNumber >= hunkStart - region.fromEnd) return false;
734
+ const fromStartDistance = lineNumber - (gapStart + region.fromStart) + 1;
735
+ const fromEndDistance = hunkStart - region.fromEnd - lineNumber;
736
+ if (fromStartDistance <= fromEndDistance) this.expandHunk(hunkIndex, "up", fromStartDistance + expansionLineCount);
737
+ else this.expandHunk(hunkIndex, "down", fromEndDistance + expansionLineCount);
738
+ return true;
739
+ }
740
+ if (lineNumber < hunkEnd) return false;
741
+ }
742
+ const trailingRegion = getTrailingExpandedRegion({
743
+ fileDiff,
744
+ hunkIndex: fileDiff.hunks.length - 1,
745
+ expandedHunks,
746
+ collapsedContextThreshold,
747
+ errorPrefix: "FileDiff.revealLine"
748
+ });
749
+ if (trailingRegion == null || trailingRegion.renderAll) return false;
750
+ const lastHunk = fileDiff.hunks[fileDiff.hunks.length - 1];
751
+ const [, trailingStart] = getHunkAdditionLineRange(lastHunk);
752
+ if (lineNumber < trailingStart + trailingRegion.fromStart || lineNumber >= trailingStart + trailingRegion.rangeSize) return false;
753
+ this.expandHunk(fileDiff.hunks.length, "up", lineNumber - (trailingStart + trailingRegion.fromStart) + 1 + expansionLineCount);
754
+ return true;
755
+ }
756
+ shouldSelfHealEditSession() {
757
+ return this.editor == null;
758
+ }
759
+ escalateEditSessionRender() {
760
+ queueRender(this.handleEditSessionRender);
761
+ }
762
+ handleEditSessionRender = () => {
763
+ this.rerender();
764
+ this.flushDeferredLineState();
765
+ };
588
766
  removeRenderedCode() {
589
767
  this.resizeManager.cleanUp();
590
768
  this.scrollSyncManager.cleanUp();
@@ -761,6 +939,7 @@ var FileDiff = class {
761
939
  const { fileContainer: previousContainer } = this;
762
940
  const nextContainer = fileContainer ?? previousContainer ?? document.createElement("diffs-container");
763
941
  const containerChanged = previousContainer !== nextContainer;
942
+ if (previousContainer != null && containerChanged) this.editor?.__captureFocusForDOMReplacement();
764
943
  if (containerChanged) this.emitPostRender(true);
765
944
  this.fileContainer = nextContainer;
766
945
  if (previousContainer != null && containerChanged) {
@@ -804,6 +983,7 @@ var FileDiff = class {
804
983
  this.codeAdditions = void 0;
805
984
  shadowRoot.appendChild(this.pre);
806
985
  } else if (this.pre.parentNode !== shadowRoot) {
986
+ this.editor?.__captureFocusForDOMReplacement();
807
987
  shadowRoot.appendChild(this.pre);
808
988
  this.appliedPreAttributes = void 0;
809
989
  }
@@ -959,6 +1139,7 @@ var FileDiff = class {
959
1139
  const unifiedAST = this.hunksRenderer.renderCodeAST("unified", result);
960
1140
  const deletionsAST = this.hunksRenderer.renderCodeAST("deletions", result);
961
1141
  const additionsAST = this.hunksRenderer.renderCodeAST("additions", result);
1142
+ this.editor?.__captureFocusForDOMReplacement();
962
1143
  if (unifiedAST != null) {
963
1144
  shouldReplace = this.codeUnified == null || this.codeAdditions != null || this.codeDeletions != null;
964
1145
  this.codeDeletions?.remove();