@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,10 +1,13 @@
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 { getThemes } from "../utils/getThemes.js";
3
+ import { getHighlighterIfLoaded, getSharedHighlighter } from "../highlighter/shared_highlighter.js";
2
4
  import { areThemesEqual } from "../utils/areThemesEqual.js";
3
5
  import { isStyleNode } from "../utils/isStyleNode.js";
4
- import { areFilesEqual } from "../utils/areFilesEqual.js";
6
+ import { areFileTargetsEqual } from "../utils/areFileTargetsEqual.js";
5
7
  import { InteractionManager, pluckInteractionOptions } from "../managers/InteractionManager.js";
6
8
  import { ResizeManager } from "../managers/ResizeManager.js";
7
9
  import { areRenderRangesEqual } from "../utils/areRenderRangesEqual.js";
10
+ import { getFiletypeFromFileName } from "../utils/getFiletypeFromFileName.js";
8
11
  import { getLineAnnotationName } from "../utils/getLineAnnotationName.js";
9
12
  import { isFilePlainText } from "../utils/isFilePlainText.js";
10
13
  import { FileRenderer } from "../renderers/FileRenderer.js";
@@ -16,6 +19,7 @@ import { createGutterUtilityContentNode } from "../utils/createGutterUtilityCont
16
19
  import { createUnsafeCSSStyleNode } from "../utils/createUnsafeCSSStyleNode.js";
17
20
  import { getMeasuredScrollbarGutter } from "../utils/scrollbarGutter.js";
18
21
  import { patchScrollbarGutterSize, wrapThemeCSS, wrapUnsafeCSS } from "../utils/cssWrappers.js";
22
+ import { adoptEditSessionAnnotations, resolveEditSessionSlotName, writeEditSessionAnnotations } from "../utils/editSessionAnnotations.js";
19
23
  import { getFileRendererOptions } from "../utils/getFileRendererOptions.js";
20
24
  import { getOrCreateCodeNode } from "../utils/getOrCreateCodeNode.js";
21
25
  import { guardWebKitScrollDuringRebuild } from "../utils/guardWebKitScrollDuringRebuild.js";
@@ -27,6 +31,11 @@ import "./web-components.js";
27
31
  import { toHtml } from "hast-util-to-html";
28
32
  //#region src/components/File.ts
29
33
  const EMPTY_STRINGS = [""];
34
+ function createEditSessionFile(file) {
35
+ const editSessionFile = { ...file };
36
+ delete editSessionFile.cacheKey;
37
+ return editSessionFile;
38
+ }
30
39
  let instanceId = -1;
31
40
  var File = class {
32
41
  options;
@@ -66,6 +75,8 @@ var File = class {
66
75
  lineAnnotations = [];
67
76
  managersDirty = false;
68
77
  file;
78
+ editSession;
79
+ renderedFile;
69
80
  renderRange;
70
81
  enabled = true;
71
82
  editor;
@@ -73,11 +84,14 @@ var File = class {
73
84
  this.options = options;
74
85
  this.workerManager = workerManager;
75
86
  this.isContainerManaged = isContainerManaged;
76
- this.fileRenderer = new FileRenderer(options, this.handleHighlightRender, this.workerManager);
87
+ this.fileRenderer = new FileRenderer(options, this.getAnnotationSlotName, this.handleHighlightRender, this.workerManager);
77
88
  this.resizeManager = new ResizeManager();
78
89
  this.interactionManager = new InteractionManager("file", pluckInteractionOptions(options));
79
90
  this.workerManager?.subscribeToThemeChanges(this);
80
91
  }
92
+ getAnnotationSlotName = (annotation) => {
93
+ return resolveEditSessionSlotName(this.editSession?.annotations, annotation, getLineAnnotationName);
94
+ };
81
95
  handleHighlightRender = () => {
82
96
  this.rerender();
83
97
  };
@@ -89,8 +103,44 @@ var File = class {
89
103
  renderRange: this.renderRange
90
104
  });
91
105
  }
92
- __getCurrentFile() {
93
- return this.file;
106
+ getTheme() {
107
+ return this.workerManager?.getFileRenderOptions().theme ?? this.options.theme ?? DEFAULT_THEMES;
108
+ }
109
+ getLatestFile(file = this.file) {
110
+ return this.editSession?.file ?? file;
111
+ }
112
+ getRenderedFile() {
113
+ return this.renderedFile;
114
+ }
115
+ getLatestAnnotations() {
116
+ return this.editSession?.annotations?.current ?? this.lineAnnotations;
117
+ }
118
+ isNewAnnotations(lineAnnotations) {
119
+ const session = this.editSession?.annotations;
120
+ if (lineAnnotations === this.lineAnnotations) return false;
121
+ return session == null || lineAnnotations !== session.provided && lineAnnotations !== session.current;
122
+ }
123
+ updateExternalFile(incomingFile, lineAnnotations) {
124
+ if (areFileTargetsEqual(this.file, incomingFile)) return false;
125
+ const hadSession = this.editSession != null;
126
+ this.file = incomingFile;
127
+ if (hadSession || this.editor != null) this.installEditSession(incomingFile, hadSession ? void 0 : this.editor?.__getDocumentContents(incomingFile), true);
128
+ else this.editSession = void 0;
129
+ if (this.editSession?.annotations != null && lineAnnotations != null) {
130
+ this.lineAnnotations = lineAnnotations;
131
+ this.editSession.annotations = adoptEditSessionAnnotations(lineAnnotations, getLineAnnotationName, this.editSession.annotations);
132
+ }
133
+ return true;
134
+ }
135
+ installEditSession(externalFile, retainedDocument, hostReplacement = false) {
136
+ const usesExternalDocument = retainedDocument == null || retainedDocument.name === externalFile.name && retainedDocument.lang === externalFile.lang && retainedDocument.contents === externalFile.contents;
137
+ const file = createEditSessionFile(retainedDocument ?? externalFile);
138
+ this.editSession = {
139
+ file,
140
+ externalReplacement: hostReplacement && usesExternalDocument,
141
+ annotations: this.editSession?.annotations ?? adoptEditSessionAnnotations(this.lineAnnotations, getLineAnnotationName)
142
+ };
143
+ this.fileRenderer.beginEditSession(file, usesExternalDocument ? externalFile : void 0);
94
144
  }
95
145
  onThemeChange() {
96
146
  this.fileRenderer.clearRenderCache();
@@ -124,13 +174,28 @@ var File = class {
124
174
  return true;
125
175
  }
126
176
  hasThemeChanged() {
127
- return this.appliedThemeCSS != null && !areThemesEqual(this.appliedThemeCSS.theme, this.options.theme ?? DEFAULT_THEMES);
177
+ return this.appliedThemeCSS != null && !areThemesEqual(this.appliedThemeCSS.theme, this.getTheme());
128
178
  }
129
179
  getHoveredLine = () => {
130
180
  return this.interactionManager.getHoveredLine();
131
181
  };
132
182
  setLineAnnotations(lineAnnotations) {
183
+ const sessionAnnotations = this.editSession?.annotations;
184
+ if (sessionAnnotations == null) {
185
+ this.lineAnnotations = lineAnnotations;
186
+ return;
187
+ }
188
+ if (!this.isNewAnnotations(lineAnnotations)) return;
133
189
  this.lineAnnotations = lineAnnotations;
190
+ writeEditSessionAnnotations(sessionAnnotations, lineAnnotations, getLineAnnotationName);
191
+ }
192
+ syncEditSessionAnnotationsFromEditor(lineAnnotations) {
193
+ const session = this.editSession?.annotations;
194
+ if (session == null || lineAnnotations === session.current) return false;
195
+ session.current = lineAnnotations;
196
+ this.fileRenderer.setLineAnnotations(lineAnnotations);
197
+ this.renderAnnotations();
198
+ return true;
134
199
  }
135
200
  setSelectedLines(range, options) {
136
201
  this.interactionManager.setSelection(range, options);
@@ -167,12 +232,13 @@ var File = class {
167
232
  this.managersDirty = false;
168
233
  }
169
234
  shouldApplyColumnVariables(overflow) {
170
- return overflow === "scroll" && this.lineAnnotations.length > 0;
235
+ return overflow === "scroll" && this.getLatestAnnotations().length > 0;
171
236
  }
172
237
  cleanUp(recycle = false) {
238
+ const editor = this.editor;
173
239
  this.emitPostRender(true);
174
- this.editor?.cleanUp(recycle);
175
- this.editor = void 0;
240
+ editor?.cleanUp(recycle ? "recycle" : "discard");
241
+ if (!recycle) this.editor = void 0;
176
242
  this.resizeManager.cleanUp();
177
243
  this.interactionManager.cleanUp();
178
244
  this.managersDirty = false;
@@ -213,6 +279,8 @@ var File = class {
213
279
  this.fileRenderer.cleanUp();
214
280
  this.workerManager = void 0;
215
281
  this.file = void 0;
282
+ this.editSession = void 0;
283
+ this.renderedFile = void 0;
216
284
  }
217
285
  this.enabled = false;
218
286
  }
@@ -225,8 +293,10 @@ var File = class {
225
293
  if (!this.enabled) throw new Error("File.hydrate: attempting to call hydrate after cleaned up");
226
294
  if (this.fileContainer != null) throw new Error("File.hydrate: hydrate can only be called before the instance has rendered or hydrated");
227
295
  this.hydrateElements(fileContainer, prerenderedHTML);
228
- if (shouldRenderCode(this.pre, file, this.options.collapsed) || shouldRenderHeader(this.headerElement, file, this.options.disableFileHeader)) this.render({
296
+ const forceEditorRender = this.editor != null;
297
+ if (forceEditorRender || shouldRenderCode(this.pre, file, this.options.collapsed) || shouldRenderHeader(this.headerElement, file, this.options.disableFileHeader)) this.render({
229
298
  ...props,
299
+ forceRender: forceEditorRender || props.forceRender,
230
300
  preventEmit: true
231
301
  });
232
302
  else this.hydrationSetup({
@@ -278,82 +348,185 @@ var File = class {
278
348
  this.syncInteractionOptions();
279
349
  if (this.pre == null) return;
280
350
  this.fileRenderer.hydrate(file);
351
+ this.renderedFile = file;
281
352
  this.renderAnnotations();
282
353
  this.renderGutterUtility();
283
354
  this.injectUnsafeCSS();
284
355
  this.managersDirty = true;
285
356
  this.flushManagers();
286
357
  }
287
- getOrCreateLineCache(file = this.file) {
358
+ getOrCreateLineCache(file = this.getLatestFile()) {
288
359
  return file != null ? this.fileRenderer.getOrCreateLineCache(file) : EMPTY_STRINGS;
289
360
  }
290
361
  updateBuffers(renderRange) {
291
362
  if (this.pre != null) this.applyBuffers(this.pre, renderRange);
292
363
  }
293
364
  syncRenderViewToEditor() {
294
- const editor = this.editor;
295
- const fileContainer = this.fileContainer;
296
- const file = this.file;
297
- const lineAnnotations = this.lineAnnotations;
298
- const renderRange = this.renderRange;
299
- if (editor != null && fileContainer != null && file != null) this.fileRenderer.initializeHighlighter().then((highlighter) => {
300
- if (!this.enabled || this.editor !== editor || this.fileContainer !== fileContainer || this.file !== file) return;
301
- editor.__syncRenderView(highlighter, fileContainer, file, lineAnnotations, renderRange);
365
+ const { editor, fileContainer, renderRange } = this;
366
+ const lineAnnotations = this.getLatestAnnotations();
367
+ const file = this.getLatestFile();
368
+ if (editor == null || fileContainer == null || file == null) return;
369
+ const syncEditor = (highlighter) => {
370
+ if (!this.enabled || this.editor !== editor || this.fileContainer !== fileContainer || this.getLatestFile() !== file) return;
371
+ editor.__syncRenderView({
372
+ highlighter,
373
+ fileContainer,
374
+ file,
375
+ lineAnnotations,
376
+ renderRange,
377
+ externalDocument: this.editSession?.externalReplacement === true
378
+ });
379
+ };
380
+ const theme = this.getTheme();
381
+ const lang = file.lang ?? getFiletypeFromFileName(file.name);
382
+ const highlighter = getHighlighterIfLoaded({
383
+ theme,
384
+ lang
302
385
  });
303
- }
304
- attachEditor(editor) {
305
- this.editor?.cleanUp();
386
+ if (highlighter != null) syncEditor(highlighter);
387
+ else getSharedHighlighter({
388
+ themes: getThemes(theme),
389
+ langs: Array.from(/* @__PURE__ */ new Set(["text", lang])),
390
+ preferredHighlighter: this.workerManager?.getPreferredHighlighter() ?? this.options.preferredHighlighter
391
+ }).then(syncEditor);
392
+ }
393
+ /** @internal The editor applied or edited past the pending external replacement. */
394
+ __acknowledgeDocumentUpdate() {
395
+ if (this.editSession != null) this.editSession.externalReplacement = false;
396
+ }
397
+ /** @internal Settle annotations */
398
+ __acceptEditorChange(event) {
399
+ const { lineAnnotations } = event;
400
+ if (lineAnnotations != null) this.syncEditSessionAnnotationsFromEditor(lineAnnotations);
401
+ }
402
+ emitEditChange(event) {
403
+ const { onEditChange } = this.options;
404
+ onEditChange?.(event);
405
+ }
406
+ /** @internal Plain files have no component-owned diff session state. */
407
+ __captureDocumentSessionState() {}
408
+ /** @internal Associate this component with its editor for a render lifecycle. */
409
+ __attachEditor(editor) {
410
+ if (this.editor != null) throw new Error("File.__attachEditor: an editor is already attached");
306
411
  this.editor = editor;
307
- this.fileRenderer.beginEditSession();
308
- const preparedFile = this.file == null ? void 0 : editor.__prepareFile?.(this.file);
309
- if (preparedFile !== void 0 && preparedFile !== this.file) this.renderPreparedFile({
310
- file: preparedFile,
311
- forceRender: true,
312
- preventEmit: true,
313
- renderRange: this.renderRange
314
- });
315
- else if (this.fileRenderer.editorRenderReady()) this.syncRenderViewToEditor();
316
- else this.rerender();
317
- return () => {
412
+ const detach = () => {
318
413
  this.editor = void 0;
319
414
  this.fileRenderer.endEditSession();
320
415
  };
416
+ try {
417
+ this.resumeEditorRendering(editor);
418
+ return detach;
419
+ } catch (error) {
420
+ detach();
421
+ throw error;
422
+ }
423
+ }
424
+ /** @internal Resume rendering for the editor already associated with this component. */
425
+ __resumeEditor(editor) {
426
+ if (this.editor !== editor) throw new Error("File.__resumeEditor: editor association changed");
427
+ this.resumeEditorRendering(editor);
428
+ }
429
+ resumeEditorRendering(editor) {
430
+ if (this.editSession != null) this.fileRenderer.beginEditSession(this.editSession.file);
431
+ else if (this.file != null) this.installEditSession(this.file, editor.__getDocumentContents(this.file));
432
+ const editSessionFile = this.editSession?.file;
433
+ if (this.fileRenderer.editorRenderReady()) {
434
+ if (this.fileRenderer.fileCache === editSessionFile) this.renderedFile = editSessionFile;
435
+ this.syncRenderViewToEditor();
436
+ } else this.rerender();
437
+ }
438
+ /**
439
+ * @internal
440
+ *
441
+ * Ends the edit session and settles which file this component renders.
442
+ * Requires the editor to be detached first. Does nothing when no session
443
+ * exists, so callers can invoke it again safely after it has settled.
444
+ *
445
+ * `onEditComplete` receives the completed file, current external file, and
446
+ * both annotation collections even when the final text is unchanged. In
447
+ * `install` mode, accepting installs the completed file and its annotations;
448
+ * rejecting or having no handler restores the external values. `discard`
449
+ * mode always restores the external values. An accepted file cannot reuse
450
+ * the replaced file's `cacheKey`.
451
+ */
452
+ __completeEditSession(editor, mode) {
453
+ this.settleEditSession(mode === "install", editor);
454
+ }
455
+ settleEditSession(installResult, editor) {
456
+ const { editSession, file: externalFile, lineAnnotations: externalAnnotations } = this;
457
+ if (editSession == null || externalFile == null) return;
458
+ const { file: editSessionFile, annotations: editSessionAnnotations } = editSession;
459
+ if (this.editor != null) throw new Error("File.__completeEditSession: detach the editor before completing the session");
460
+ const sessionAnnotationsCurrent = editSessionAnnotations?.current;
461
+ let acceptedFile;
462
+ let failed = false;
463
+ let failure;
464
+ if (editor == null) throw new Error("File.__completeEditSession: editor is required for completion");
465
+ const completedFile = { ...editSessionFile };
466
+ const event = {
467
+ file: completedFile,
468
+ editor,
469
+ originalFile: externalFile,
470
+ lineAnnotations: sessionAnnotationsCurrent,
471
+ originalLineAnnotations: externalAnnotations
472
+ };
473
+ Object.freeze(event);
474
+ try {
475
+ editor.__emitEditComplete(event);
476
+ if (this.options.onEditComplete?.(event) === "accept") {
477
+ if (completedFile.cacheKey != null && completedFile.cacheKey === externalFile.cacheKey) throw new Error("File.__completeEditSession: an accepted file must not reuse the replaced file cacheKey");
478
+ acceptedFile = completedFile;
479
+ }
480
+ } catch (error) {
481
+ failed = true;
482
+ failure = error;
483
+ }
484
+ if (installResult && acceptedFile != null) {
485
+ this.file = acceptedFile;
486
+ if (sessionAnnotationsCurrent != null) this.lineAnnotations = sessionAnnotationsCurrent;
487
+ }
488
+ this.editSession = void 0;
489
+ const { renderedFile, file: settledFile } = this;
490
+ this.fileRenderer.endEditSession(settledFile);
491
+ if (renderedFile != null && settledFile != null && renderedFile !== settledFile && areFileTargetsEqual(renderedFile, settledFile)) this.renderedFile = settledFile;
492
+ if (installResult && this.fileContainer != null) this.rerender();
493
+ if (failed) throw failure;
321
494
  }
322
495
  applyDocumentChange(textDocument, newLineAnnotations) {
496
+ const editSessionFile = this.editSession?.file;
497
+ if (editSessionFile == null) throw new Error("File.applyDocumentChange: requires an active edit session");
498
+ this.fileRenderer.beginEditSession(editSessionFile);
323
499
  this.fileRenderer.applyDocumentChange(textDocument);
324
- if (newLineAnnotations != null && newLineAnnotations !== this.lineAnnotations && this.file != null) {
325
- this.setLineAnnotations(newLineAnnotations);
326
- this.fileRenderer.setLineAnnotations(this.lineAnnotations);
327
- this.renderAnnotations();
328
- }
500
+ if (newLineAnnotations != null) this.syncEditSessionAnnotationsFromEditor(newLineAnnotations);
329
501
  }
330
502
  updateRenderCache(dirtyLines, themeType, options) {
503
+ const editSessionFile = this.editSession?.file;
504
+ if (editSessionFile == null) throw new Error("File.updateRenderCache: requires an active edit session");
505
+ this.fileRenderer.beginEditSession(editSessionFile);
331
506
  this.fileRenderer.updateRenderCache(dirtyLines, themeType, options?.lineCountChangeInFlight);
332
507
  }
333
- render(props) {
508
+ render({ file, fileContainer, forceRender = false, preventEmit = false, containerWrapper, deferManagers = false, lineAnnotations, renderRange }) {
334
509
  if (!this.enabled) throw new Error("File.render: attempting to call render after cleaned up");
335
- const file = this.editor?.__prepareFile?.(props.file) ?? props.file;
336
- return this.renderPreparedFile(file === props.file ? props : {
337
- ...props,
338
- file
339
- });
340
- }
341
- renderPreparedFile({ file, fileContainer, forceRender = false, preventEmit = false, containerWrapper, deferManagers = false, lineAnnotations, renderRange }) {
342
510
  this.editor?.__postponeBgTokenizeToNextFrame();
343
511
  const { collapsed = false, themeType = "system" } = this.options;
344
512
  const nextRenderRange = collapsed ? void 0 : renderRange;
345
513
  const previousRenderRange = this.renderRange;
346
514
  const themeChanged = this.hasThemeChanged();
347
- const annotationsChanged = lineAnnotations != null && (lineAnnotations.length > 0 || this.lineAnnotations.length > 0) ? lineAnnotations !== this.lineAnnotations : false;
348
- const didFileChange = !areFilesEqual(this.file, file) || this.fileRenderer.hasUnkeyedFileContentsChanged(file);
349
- if (!collapsed && !forceRender && areRenderRangesEqual(nextRenderRange, this.renderRange) && !didFileChange && !annotationsChanged && !themeChanged) return this.applyCachedThemeState(themeType);
515
+ const annotationsChanged = lineAnnotations != null && (lineAnnotations.length > 0 || this.getLatestAnnotations().length > 0) ? this.isNewAnnotations(lineAnnotations) : false;
516
+ const didFileChange = !areFileTargetsEqual(this.file, file);
517
+ if (didFileChange) this.updateExternalFile(file, lineAnnotations);
518
+ const latestFile = this.getLatestFile(file) ?? file;
519
+ if (!collapsed && !forceRender && areRenderRangesEqual(nextRenderRange, this.renderRange) && !didFileChange && !annotationsChanged && !themeChanged) {
520
+ const rendered = this.applyCachedThemeState(themeType);
521
+ if (rendered) this.finalizeRender();
522
+ return rendered;
523
+ }
350
524
  this.renderRange = nextRenderRange;
351
525
  if (didFileChange) this.cachedHeaderHTML = void 0;
352
- this.file = file;
353
526
  this.fileRenderer.setOptions(getFileRendererOptions(this.options));
354
527
  this.syncInteractionOptions();
355
528
  if (lineAnnotations != null) this.setLineAnnotations(lineAnnotations);
356
- this.fileRenderer.setLineAnnotations(this.lineAnnotations);
529
+ this.fileRenderer.setLineAnnotations(this.getLatestAnnotations());
357
530
  const { disableErrorHandling = false, disableFileHeader = false } = this.options;
358
531
  if (disableFileHeader) {
359
532
  if (this.headerElement != null) {
@@ -369,29 +542,32 @@ var File = class {
369
542
  this.removeRenderedCode();
370
543
  this.clearAuxiliaryNodes();
371
544
  try {
372
- const fileResult = this.fileRenderer.renderFile(file, EMPTY_RENDER_RANGE);
545
+ const fileResult = this.fileRenderer.renderFile(latestFile, EMPTY_RENDER_RANGE);
373
546
  if (fileResult != null) this.applyThemeState(fileContainer, fileResult.themeStyles, themeType, fileResult.baseThemeType);
374
- if (fileResult?.headerAST != null) this.applyHeaderToDOM(fileResult.headerAST, fileContainer);
547
+ if (fileResult?.headerAST != null) this.applyHeaderToDOM(fileResult.headerAST, fileContainer, fileResult.file);
548
+ this.renderedFile = fileResult?.file ?? latestFile;
375
549
  this.injectUnsafeCSS();
376
550
  } catch (error) {
377
551
  if (disableErrorHandling) throw error;
378
552
  console.error(error);
379
553
  if (error instanceof Error) this.applyErrorToDOM(error, fileContainer);
380
554
  }
555
+ this.finalizeRender();
381
556
  if (!preventEmit) this.emitPostRender();
382
557
  return true;
383
558
  }
384
559
  try {
385
560
  const pre = this.getOrCreatePreNode(fileContainer);
386
- if (!this.canPartiallyRender(forceRender, annotationsChanged, didFileChange || themeChanged) || !this.applyPartialRender(previousRenderRange, nextRenderRange)) {
387
- const fileResult = this.fileRenderer.renderFile(file, nextRenderRange);
561
+ if (!this.canPartiallyRender(forceRender, annotationsChanged, didFileChange || themeChanged || !areFileTargetsEqual(this.renderedFile, latestFile)) || !this.applyPartialRender(latestFile, previousRenderRange, nextRenderRange)) {
562
+ const fileResult = this.fileRenderer.renderFile(latestFile, nextRenderRange);
388
563
  if (fileResult == null) {
389
- if (this.workerManager?.isInitialized() === false) this.workerManager.initialize().then(() => this.rerender());
564
+ if (this.workerManager?.isInitialized() === false && this.workerManager.isWorkingPool()) this.workerManager.initialize().catch(() => {}).then(() => this.rerender());
390
565
  return false;
391
566
  }
392
567
  this.applyThemeState(fileContainer, fileResult.themeStyles, themeType, fileResult.baseThemeType);
393
- if (fileResult.headerAST != null) this.applyHeaderToDOM(fileResult.headerAST, fileContainer);
568
+ if (fileResult.headerAST != null) this.applyHeaderToDOM(fileResult.headerAST, fileContainer, fileResult.file);
394
569
  this.applyFullRender(fileResult, pre);
570
+ this.renderedFile = fileResult.file;
395
571
  }
396
572
  this.applyBuffers(pre, nextRenderRange);
397
573
  this.injectUnsafeCSS();
@@ -399,6 +575,7 @@ var File = class {
399
575
  this.renderGutterUtility();
400
576
  this.managersDirty = true;
401
577
  if (!deferManagers) this.flushManagers();
578
+ this.finalizeRender();
402
579
  if (this.editor != null) this.syncRenderViewToEditor();
403
580
  } catch (error) {
404
581
  if (disableErrorHandling) throw error;
@@ -408,6 +585,7 @@ var File = class {
408
585
  if (!preventEmit) this.emitPostRender();
409
586
  return true;
410
587
  }
588
+ finalizeRender() {}
411
589
  emitPostRender(unmount = false) {
412
590
  const { fileContainer, options: { onPostRender } } = this;
413
591
  if (unmount) {
@@ -513,15 +691,17 @@ var File = class {
513
691
  }
514
692
  const staleAnnotations = new Map(this.annotationCache);
515
693
  const { renderAnnotation } = this.options;
516
- if (renderAnnotation != null && this.lineAnnotations.length > 0) for (const [index, annotation] of this.lineAnnotations.entries()) {
517
- const id = `${index}-${getLineAnnotationName(annotation)}`;
694
+ const lineAnnotations = this.getLatestAnnotations();
695
+ if (renderAnnotation != null && lineAnnotations.length > 0) for (const [index, annotation] of lineAnnotations.entries()) {
696
+ const name = this.getAnnotationSlotName(annotation);
697
+ const id = `${index}-${name}`;
518
698
  let cache = this.annotationCache.get(id);
519
699
  if (cache == null || !areLineAnnotationsEqual(annotation, cache.annotation)) {
520
700
  cache?.element.remove();
521
701
  const content = renderAnnotation(annotation);
522
702
  if (content == null) continue;
523
703
  cache = {
524
- element: createAnnotationWrapperNode(getLineAnnotationName(annotation)),
704
+ element: createAnnotationWrapperNode(name),
525
705
  annotation
526
706
  };
527
707
  cache.element.appendChild(content);
@@ -575,7 +755,7 @@ var File = class {
575
755
  applyThemeState(container, themeStyles, themeType, baseThemeType) {
576
756
  const shadowRoot = container.shadowRoot ?? container.attachShadow({ mode: "open" });
577
757
  const effectiveThemeType = baseThemeType ?? themeType;
578
- const currentTheme = this.options.theme ?? DEFAULT_THEMES;
758
+ const currentTheme = this.getTheme();
579
759
  const theme = typeof currentTheme === "string" ? currentTheme : { ...currentTheme };
580
760
  const scrollbarGutter = getMeasuredScrollbarGutter(shadowRoot);
581
761
  if (this.themeCSSStyle?.parentNode === shadowRoot && this.appliedThemeCSS?.themeStyles === themeStyles && this.appliedThemeCSS.themeType === effectiveThemeType && this.appliedThemeCSS.scrollbarGutter === scrollbarGutter) {
@@ -634,11 +814,11 @@ var File = class {
634
814
  else applyColumns();
635
815
  this.lastRowCount = result.rowCount;
636
816
  }
637
- applyPartialRender(previousRenderRange, renderRange) {
817
+ applyPartialRender(file, previousRenderRange, renderRange) {
638
818
  if (previousRenderRange == null || renderRange == null) return false;
639
- const { file, code } = this;
819
+ const { code } = this;
640
820
  const columns = code != null ? this.getColumns(code) : void 0;
641
- if (file == null || code == null || columns == null) return false;
821
+ if (code == null || columns == null) return false;
642
822
  const previousStart = previousRenderRange.startingLine;
643
823
  const nextStart = renderRange.startingLine;
644
824
  const previousEnd = previousRenderRange.totalLines === Infinity ? Number.POSITIVE_INFINITY : previousStart + previousRenderRange.totalLines;
@@ -771,9 +951,7 @@ var File = class {
771
951
  shouldDisableVirtualizationBuffers() {
772
952
  return this.options.disableVirtualizationBuffers ?? false;
773
953
  }
774
- applyHeaderToDOM(headerAST, container) {
775
- const { file } = this;
776
- if (file == null) return;
954
+ applyHeaderToDOM(headerAST, container, file) {
777
955
  this.cleanupErrorWrapper();
778
956
  this.placeHolder?.remove();
779
957
  this.placeHolder = void 0;