@pierre/diffs 1.6.0-beta.1 → 1.6.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 (151) hide show
  1. package/dist/components/CodeView.d.ts +3 -2
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +18 -14
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +31 -9
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +165 -84
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +32 -9
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +213 -124
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/UnresolvedFile.d.ts +14 -4
  14. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  15. package/dist/components/UnresolvedFile.js +35 -16
  16. package/dist/components/UnresolvedFile.js.map +1 -1
  17. package/dist/components/VirtualizedFile.d.ts +3 -2
  18. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  19. package/dist/components/VirtualizedFile.js +28 -20
  20. package/dist/components/VirtualizedFile.js.map +1 -1
  21. package/dist/components/VirtualizedFileDiff.d.ts +3 -2
  22. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  23. package/dist/components/VirtualizedFileDiff.js +31 -24
  24. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  25. package/dist/constants.d.ts +2 -1
  26. package/dist/constants.d.ts.map +1 -1
  27. package/dist/constants.js +2 -1
  28. package/dist/constants.js.map +1 -1
  29. package/dist/editor/platform.d.ts +1 -1
  30. package/dist/editor/platform.js +5 -4
  31. package/dist/editor/platform.js.map +1 -1
  32. package/dist/editor/selection.d.ts +2 -2
  33. package/dist/editor/selection.d.ts.map +1 -1
  34. package/dist/editor/selection.js +31 -6
  35. package/dist/editor/selection.js.map +1 -1
  36. package/dist/highlighter/shared_highlighter.d.ts +2 -1
  37. package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
  38. package/dist/highlighter/shared_highlighter.js +2 -2
  39. package/dist/highlighter/shared_highlighter.js.map +1 -1
  40. package/dist/index.d.ts +10 -5
  41. package/dist/index.js +8 -3
  42. package/dist/react/CodeView.d.ts +4 -3
  43. package/dist/react/CodeView.d.ts.map +1 -1
  44. package/dist/react/CodeView.js +48 -39
  45. package/dist/react/CodeView.js.map +1 -1
  46. package/dist/react/File.js +3 -3
  47. package/dist/react/File.js.map +1 -1
  48. package/dist/react/FileDiff.js +3 -3
  49. package/dist/react/FileDiff.js.map +1 -1
  50. package/dist/react/MultiFileDiff.js +2 -2
  51. package/dist/react/MultiFileDiff.js.map +1 -1
  52. package/dist/react/PatchDiff.js +3 -3
  53. package/dist/react/PatchDiff.js.map +1 -1
  54. package/dist/react/UnresolvedFile.js +2 -2
  55. package/dist/react/UnresolvedFile.js.map +1 -1
  56. package/dist/react/index.d.ts +2 -2
  57. package/dist/react/types.d.ts +4 -2
  58. package/dist/react/types.d.ts.map +1 -1
  59. package/dist/react/utils/renderDiffChildren.js +1 -1
  60. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  61. package/dist/react/utils/renderFileChildren.js +1 -1
  62. package/dist/react/utils/renderFileChildren.js.map +1 -1
  63. package/dist/react/utils/useFileDiffInstance.d.ts +1 -0
  64. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  65. package/dist/react/utils/useFileDiffInstance.js +29 -24
  66. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  67. package/dist/react/utils/useFileInstance.d.ts +2 -0
  68. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  69. package/dist/react/utils/useFileInstance.js +38 -28
  70. package/dist/react/utils/useFileInstance.js.map +1 -1
  71. package/dist/react/utils/useForceUpdate.d.ts +5 -0
  72. package/dist/react/utils/useForceUpdate.d.ts.map +1 -0
  73. package/dist/react/utils/useForceUpdate.js +27 -0
  74. package/dist/react/utils/useForceUpdate.js.map +1 -0
  75. package/dist/react/utils/useNextRenderData.d.ts +9 -0
  76. package/dist/react/utils/useNextRenderData.d.ts.map +1 -0
  77. package/dist/react/utils/useNextRenderData.js +9 -0
  78. package/dist/react/utils/useNextRenderData.js.map +1 -0
  79. package/dist/react/utils/useUnresolvedFileInstance.d.ts +1 -0
  80. package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -1
  81. package/dist/react/utils/useUnresolvedFileInstance.js +26 -11
  82. package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
  83. package/dist/renderers/DiffHunksRenderer.d.ts +2 -1
  84. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  85. package/dist/renderers/DiffHunksRenderer.js +62 -32
  86. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  87. package/dist/renderers/FileRenderer.d.ts +4 -1
  88. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  89. package/dist/renderers/FileRenderer.js +55 -30
  90. package/dist/renderers/FileRenderer.js.map +1 -1
  91. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
  92. package/dist/renderers/UnresolvedFileHunksRenderer.js +1 -1
  93. package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
  94. package/dist/ssr/FileDiffReact.js +1 -1
  95. package/dist/types.d.ts +10 -0
  96. package/dist/types.d.ts.map +1 -1
  97. package/dist/utils/canUseWASM.d.ts +13 -0
  98. package/dist/utils/canUseWASM.d.ts.map +1 -0
  99. package/dist/utils/canUseWASM.js +59 -0
  100. package/dist/utils/canUseWASM.js.map +1 -0
  101. package/dist/utils/getCodeViewItemRenderData.d.ts +10 -0
  102. package/dist/utils/getCodeViewItemRenderData.d.ts.map +1 -0
  103. package/dist/utils/getCodeViewItemRenderData.js +19 -0
  104. package/dist/utils/getCodeViewItemRenderData.js.map +1 -0
  105. package/dist/utils/hastToHtml.d.ts +2 -2
  106. package/dist/utils/hastToHtml.js +2 -2
  107. package/dist/utils/hastToHtml.js.map +1 -1
  108. package/dist/utils/hydratePartialDiff.js +4 -0
  109. package/dist/utils/hydratePartialDiff.js.map +1 -1
  110. package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
  111. package/dist/utils/parseMergeConflictDiffFromFile.js +2 -0
  112. package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
  113. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  114. package/dist/utils/parsePatchFiles.js +24 -4
  115. package/dist/utils/parsePatchFiles.js.map +1 -1
  116. package/dist/utils/renderTokenLines.d.ts +6 -1
  117. package/dist/utils/renderTokenLines.d.ts.map +1 -1
  118. package/dist/utils/renderTokenLines.js +4 -0
  119. package/dist/utils/renderTokenLines.js.map +1 -1
  120. package/dist/utils/resolveRegion.js +20 -10
  121. package/dist/utils/resolveRegion.js.map +1 -1
  122. package/dist/utils/tokenStyle.d.ts +5 -1
  123. package/dist/utils/tokenStyle.d.ts.map +1 -1
  124. package/dist/utils/tokenStyle.js +5 -1
  125. package/dist/utils/tokenStyle.js.map +1 -1
  126. package/dist/utils/tokensToHtml.d.ts +5 -2
  127. package/dist/utils/tokensToHtml.d.ts.map +1 -1
  128. package/dist/utils/tokensToHtml.js +5 -2
  129. package/dist/utils/tokensToHtml.js.map +1 -1
  130. package/dist/utils/updateDiffHunks.d.ts +2 -2
  131. package/dist/utils/updateDiffHunks.d.ts.map +1 -1
  132. package/dist/utils/updateDiffHunks.js +7 -3
  133. package/dist/utils/updateDiffHunks.js.map +1 -1
  134. package/dist/worker/WorkerPoolManager.d.ts +12 -0
  135. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  136. package/dist/worker/WorkerPoolManager.js +99 -21
  137. package/dist/worker/WorkerPoolManager.js.map +1 -1
  138. package/dist/worker/{highlights-sAHlxqlf.js → highlights-CpZm9DAR.js} +2 -2
  139. package/dist/worker/{highlights-sAHlxqlf.js.map → highlights-CpZm9DAR.js.map} +1 -1
  140. package/dist/worker/{shiki-Bx2JpdqZ.js → shiki-Ci4cdHsM.js} +2 -2
  141. package/dist/worker/{shiki-Bx2JpdqZ.js.map → shiki-Ci4cdHsM.js.map} +1 -1
  142. package/dist/worker/{stream-tokenizer-YZ6M1qSx.js → stream-tokenizer-DK9xp5M5.js} +8 -5
  143. package/dist/worker/stream-tokenizer-DK9xp5M5.js.map +1 -0
  144. package/dist/worker/types.d.ts +11 -0
  145. package/dist/worker/types.d.ts.map +1 -1
  146. package/dist/worker/worker-portable.js +4 -4
  147. package/dist/worker/worker-portable.js.map +1 -1
  148. package/dist/worker/worker.js +12 -3
  149. package/dist/worker/worker.js.map +1 -1
  150. package/package.json +28 -30
  151. package/dist/worker/stream-tokenizer-YZ6M1qSx.js.map +0 -1
@@ -28,7 +28,6 @@ declare class FileRenderer<LAnnotation = undefined> {
28
28
  private onRenderUpdate?;
29
29
  private workerManager?;
30
30
  readonly __id: string;
31
- private highlighter;
32
31
  private file;
33
32
  private renderCache;
34
33
  private pendingHighlightResult;
@@ -37,6 +36,7 @@ declare class FileRenderer<LAnnotation = undefined> {
37
36
  private lineCache;
38
37
  private pendingStructuralRows;
39
38
  private textDocumentCache;
39
+ private ownedRows;
40
40
  private editSessionActive;
41
41
  get fileCache(): FileContents | undefined;
42
42
  constructor(options?: FileRendererOptions, annotationSlotName?: (annotation: LineAnnotation<LAnnotation>) => string, onRenderUpdate?: (() => unknown) | undefined, workerManager?: WorkerPoolManager | undefined);
@@ -65,6 +65,8 @@ declare class FileRenderer<LAnnotation = undefined> {
65
65
  recycle(): void;
66
66
  clearRenderCache(): void;
67
67
  hydrate(file: FileContents): void;
68
+ private getHighlightWorkerManager;
69
+ private cacheHighlightResult;
68
70
  private getLocalHighlightTheme;
69
71
  getEffectiveCodeOptions(): Pick<BaseCodeOptions, 'theme' | 'tokenizeMaxLineLength'>;
70
72
  private getRenderOptions;
@@ -79,6 +81,7 @@ declare class FileRenderer<LAnnotation = undefined> {
79
81
  getLineCount(file: FileContents): number;
80
82
  updateRenderCache(dirtyLines: Map<number, Array<HighlightedToken>>, themeType: 'dark' | 'light', lineCountChangeInFlight?: boolean): void;
81
83
  applyDocumentChange(textDocument: TextDocument<'file', LAnnotation>): void;
84
+ private ownRow;
82
85
  renderFile(file?: FileContents | undefined, renderRange?: RenderRange): FileRenderResult | undefined;
83
86
  asyncRender(file: FileContents, renderRange?: RenderRange): Promise<FileRenderResult>;
84
87
  private asyncHighlight;
@@ -1 +1 @@
1
- {"version":3,"file":"FileRenderer.d.ts","names":[],"sources":["../../src/renderers/FileRenderer.ts"],"mappings":";;;;;;;UAiFiB;EACf,MAAM;EACN,WAAW;EACX,YAAY;EACZ,QAAQ;EACR,WAAW;EACX;EACA;EACA;EACA;EACA;EACA;EACA;;UAkBe,4BAA4B;EAC3C,mBAAmB;;cAKR,aAAa;EAmCf,SAAS;UACR;UAGA;UACA;WAvCD;UAED;UAIA;UAEA;UAGA;UAEA;UACA;UACA;UACA;UACA;UAUA;MAEG,aAAa;EAIxB,YACS,UAAS,qBACR,sBACN,YAAY,eAAe,yBAErB,8CACA,gBAAgB;EASnB,WAAW,SAAS;EAIpB,aAAa,SAAS,QAAQ;EAI9B,mBACL,iBAAiB,eAAe;EAU3B;;;;;;;EAaA,iBACL,MAAM,cACN,eAAe;;;;;;;EA2EV,eAAe,cAAc;;;;EAwB7B;EAQA;EAmBA;EAMA,QAAQ,MAAM;UA4Cb;EAQD,2BAA2B,KAChC;UAeM;;;;;;EAuCD,qBAAqB,MAAM,eAAe;UAyBzC;EAqCD,qBAAqB,MAAM;EAgB3B,aAAa,MAAM;EAKnB,kBACL,YAAY,YAAY,MAAM,oBAC9B,6BACA;EAkFK,oBACL,cAAc,qBAAqB;EAmG9B,WACL,OAAM,0BACN,cAAa,cACZ;EA2IG,YACJ,MAAM,cACN,cAAa,cACZ,QAAQ;UASG;UAgCN;UAcA;UA+FA;EASD,eAAe,QAAQ;EAIvB,cACL,QAAQ,kBACR,WAAU,mBACT;EAWI,cAAc,QAAQ,mBAAmB;EAWzC,kBACL,UAAU,kBACV;EAcW,yBAAyB,QAAQ;EAavC,mBACL,MAAM,cACN,QAAQ,kBACR,SAAS,mBACT;UAQM;UAqCA;UAgBA;UAoBA;EAaD,iBAAiB;UAIhB;UAIA"}
1
+ {"version":3,"file":"FileRenderer.d.ts","names":[],"sources":["../../src/renderers/FileRenderer.ts"],"mappings":";;;;;;;UAiFiB;EACf,MAAM;EACN,WAAW;EACX,YAAY;EACZ,QAAQ;EACR,WAAW;EACX;EACA;EACA;EACA;EACA;EACA;EACA;;UAkBe,4BAA4B;EAC3C,mBAAmB;;cAKR,aAAa;EAsCf,SAAS;UACR;UAGA;UACA;WA1CD;UAKD;UAEA;UAGA;UAEA;UACA;UACA;UACA;UACA;UAOA;UAOA;MAEG,aAAa;EAIxB,YACS,UAAS,qBACR,sBACN,YAAY,eAAe,yBAErB,8CACA,gBAAgB;EAGnB,WAAW,SAAS;EAIpB,aAAa,SAAS,QAAQ;EAI9B,mBACL,iBAAiB,eAAe;EAU3B;;;;;;;EAaA,iBACL,MAAM,cACN,eAAe;;;;;;;EA2EV,eAAe,cAAc;;;;EAwB7B;EAQA;EAkBA;EAMA,QAAQ,MAAM;UA0Cb;UAWA;UAUA;EAQD,2BAA2B,KAChC;UAeM;;;;;;EAuCD,qBAAqB,MAAM,eAAe;UAyBzC;EA+BD,qBAAqB,MAAM;EAgB3B,aAAa,MAAM;EAKnB,kBACL,YAAY,YAAY,MAAM,oBAC9B,6BACA;EAmFK,oBACL,cAAc,qBAAqB;UA2G7B;EAKD,WACL,OAAM,0BACN,cAAa,cACZ;EA8IG,YACJ,MAAM,cACN,cAAa,cACZ,QAAQ;UASG;UAiCN;UAcA;UA+FA;EASD,eAAe,QAAQ;EAIvB,cACL,QAAQ,kBACR,WAAU,mBACT;EAWI,cAAc,QAAQ,mBAAmB;EAWzC,kBACL,UAAU,kBACV;EAcK,yBAAyB,QAAQ;EAYjC,mBACL,MAAM,cACN,QAAQ,kBACR,SAAS,mBACT;UAQM;UAqCA;UAgBA;UAoBA;EAaD,iBAAiB;UAIhB;UAIA"}
@@ -33,7 +33,6 @@ var FileRenderer = class {
33
33
  onRenderUpdate;
34
34
  workerManager;
35
35
  __id = `file-renderer:${++instanceId}`;
36
- highlighter;
37
36
  file;
38
37
  renderCache;
39
38
  pendingHighlightResult;
@@ -42,6 +41,7 @@ var FileRenderer = class {
42
41
  lineCache;
43
42
  pendingStructuralRows;
44
43
  textDocumentCache = /* @__PURE__ */ new WeakMap();
44
+ ownedRows = /* @__PURE__ */ new WeakSet();
45
45
  editSessionActive = false;
46
46
  get fileCache() {
47
47
  return this.renderCache?.file;
@@ -51,7 +51,6 @@ var FileRenderer = class {
51
51
  this.annotationSlotName = annotationSlotName;
52
52
  this.onRenderUpdate = onRenderUpdate;
53
53
  this.workerManager = workerManager;
54
- if (workerManager?.isWorkingPool() !== true) this.highlighter = getHighlighterIfLoaded({ theme: options.theme ?? DEFAULT_THEMES });
55
54
  }
56
55
  setOptions(options) {
57
56
  this.options = options;
@@ -158,7 +157,6 @@ var FileRenderer = class {
158
157
  this.lineCache = void 0;
159
158
  this.textDocumentCache = /* @__PURE__ */ new WeakMap();
160
159
  }
161
- this.highlighter = void 0;
162
160
  this.workerManager?.cleanUpTasks(this);
163
161
  this.file = void 0;
164
162
  }
@@ -169,7 +167,6 @@ var FileRenderer = class {
169
167
  }
170
168
  hydrate(file) {
171
169
  this.file = file;
172
- this.highlighter = getHighlighterIfLoaded({ theme: this.getLocalHighlightTheme() });
173
170
  const { options } = this.getRenderOptions(file);
174
171
  const massiveFile = isFileMassive(this.getOrCreateLineCache(file).length, this.getTokenizeMaxLength());
175
172
  let cache = this.workerManager?.getFileResultCache(file);
@@ -182,15 +179,24 @@ var FileRenderer = class {
182
179
  result: massiveFile ? void 0 : cache?.result,
183
180
  renderRange: void 0
184
181
  };
185
- if (!this.editSessionActive && this.workerManager?.isWorkingPool() === true) {
186
- if (this.renderCache.result == null && !massiveFile) this.workerManager.highlightFileAST(this, file);
187
- } else if (this.highlighter == null) {
182
+ const workerManager = this.getHighlightWorkerManager(file);
183
+ if (workerManager != null) {
184
+ if (this.renderCache.result == null && !massiveFile) workerManager.highlightFileAST(this, file);
185
+ } else if (getHighlighterIfLoaded({ theme: this.getLocalHighlightTheme() }) == null) {
188
186
  this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);
189
187
  this.initializeHighlighter().catch((error) => {
190
188
  if (!(error instanceof HighlighterDisposedError)) this.onHighlightError(error);
191
189
  });
192
190
  }
193
191
  }
192
+ getHighlightWorkerManager(file) {
193
+ const { editSessionActive, workerManager } = this;
194
+ return !editSessionActive && workerManager?.isWorkingPool() === true && !workerManager.shouldHighlightOnMainThread(file) ? workerManager : void 0;
195
+ }
196
+ cacheHighlightResult(file, renderResult) {
197
+ const { editSessionActive, workerManager } = this;
198
+ if (!editSessionActive && workerManager?.isWorkingPool() === true) workerManager.setFileResultCache(file.cacheKey, renderResult);
199
+ }
194
200
  getLocalHighlightTheme() {
195
201
  return this.workerManager?.getFileRenderOptions().theme ?? this.options.theme ?? DEFAULT_THEMES;
196
202
  }
@@ -250,10 +256,10 @@ var FileRenderer = class {
250
256
  canRenderFile(file, options, forcePlainText) {
251
257
  const { renderCache } = this;
252
258
  if (renderCache == null || areFileTargetsEqual(renderCache.file, file)) return true;
253
- if (forcePlainText) return renderCache.result == null && renderCache.hydrated !== true || this.workerManager?.isWorkingPool() === true || this.highlighter != null && areThemesAttached(options.theme, this.highlighter);
259
+ if (forcePlainText) return renderCache.result == null && renderCache.hydrated !== true || this.workerManager?.isWorkingPool() === true && !this.workerManager.shouldHighlightOnMainThread(file) || getHighlighterIfLoaded({ theme: options.theme }) != null;
254
260
  if (renderCache.result == null && renderCache.hydrated !== true) return true;
255
- if (!this.editSessionActive && this.workerManager?.isWorkingPool() === true) return !renderCache.highlighted;
256
- return this.highlighter != null && areThemesAttached(options.theme, this.highlighter);
261
+ if (this.getHighlightWorkerManager(file) != null) return !renderCache.highlighted;
262
+ return getHighlighterIfLoaded({ theme: options.theme }) != null;
257
263
  }
258
264
  getOrCreateLineCache(file) {
259
265
  let { lineCache } = this;
@@ -319,6 +325,7 @@ var FileRenderer = class {
319
325
  };
320
326
  })
321
327
  };
328
+ this.ownedRows.add(row);
322
329
  if (pendingStructuralRows != null) pendingStructuralRows.set(line, row);
323
330
  else result.code[line] = row;
324
331
  }
@@ -350,7 +357,7 @@ var FileRenderer = class {
350
357
  if (pendingStructuralRows !== void 0) {
351
358
  for (const [line, row] of pendingStructuralRows) if (line < nextLines.length) result.code[line] = row;
352
359
  }
353
- for (let i = prefix; i < nextLines.length - suffix; i++) result.code[i] ??= {
360
+ for (let i = prefix; i < nextLines.length - suffix; i++) result.code[i] ??= this.ownRow({
354
361
  type: "element",
355
362
  tagName: "div",
356
363
  properties: {
@@ -367,12 +374,17 @@ var FileRenderer = class {
367
374
  value: textDocument.getLineText(i)
368
375
  }]
369
376
  }]
370
- };
377
+ });
371
378
  for (let i = 0; i < result.code.length; i++) {
372
379
  const line = result.code[i];
373
- if (line?.type === "element") {
374
- line.properties["data-line"] = i + 1;
375
- line.properties["data-line-index"] = i;
380
+ if (line?.type === "element" && (line.properties["data-line"] !== i + 1 || line.properties["data-line-index"] !== i)) {
381
+ const row = this.ownedRows.has(line) ? line : this.ownRow({
382
+ ...line,
383
+ properties: { ...line.properties }
384
+ });
385
+ row.properties["data-line"] = i + 1;
386
+ row.properties["data-line-index"] = i;
387
+ result.code[i] = row;
376
388
  }
377
389
  }
378
390
  if (renderCache != null) renderCache.isDirty = true;
@@ -387,6 +399,10 @@ var FileRenderer = class {
387
399
  this.textDocumentCache.set(file, textDocument);
388
400
  file.contents = contents;
389
401
  }
402
+ ownRow(row) {
403
+ this.ownedRows.add(row);
404
+ return row;
405
+ }
390
406
  renderFile(file = this.file, renderRange = DEFAULT_RENDER_RANGE) {
391
407
  this.file = file;
392
408
  if (file == null) {
@@ -414,28 +430,29 @@ var FileRenderer = class {
414
430
  const lines = this.getOrCreateLineCache(file);
415
431
  const hasContent = file.contents.length > 0;
416
432
  const forcePlainText = !hasContent || isFilePlainText(file) || isFileMassive(lines.length, this.getTokenizeMaxLength());
417
- this.highlighter = getHighlighterIfLoaded();
418
433
  const canRenderFile = this.canRenderFile(file, options, forcePlainText);
419
434
  const newContent = !areFileTargetsEqual(file, this.renderCache.file);
420
435
  const newRenderRange = !areRenderRangesEqual(this.renderCache.renderRange, renderRange);
421
- if (!this.editSessionActive && this.workerManager?.isWorkingPool() === true) {
436
+ const workerManager = this.getHighlightWorkerManager(file);
437
+ if (workerManager != null) {
422
438
  const preserveHydratedContent = this.renderCache.result == null && this.renderCache.highlighted && !forcePlainText && !newContent && isDefaultRenderRange(renderRange);
423
439
  if (canRenderFile && !preserveHydratedContent && (forcePlainText || this.renderCache.result == null || !this.renderCache.highlighted && (newContent || newRenderRange))) {
424
440
  this.renderCache.file = file;
425
441
  this.renderCache.options = options;
426
442
  this.renderCache.highlighted = false;
427
- if (this.renderCache.result == null || newContent || newRenderRange || forceHighlight) this.renderCache.result = this.workerManager.getPlainFileAST(file, renderRange.startingLine, renderRange.totalLines, lines);
443
+ if (this.renderCache.result == null || newContent || newRenderRange || forceHighlight) this.renderCache.result = workerManager.getPlainFileAST(file, renderRange.startingLine, renderRange.totalLines, lines);
428
444
  this.renderCache.renderRange = renderRange;
429
445
  }
430
- if (!forcePlainText && hasContent && (!this.renderCache.highlighted || forceHighlight)) this.workerManager.highlightFileAST(this, file);
446
+ if (!forcePlainText && hasContent && (!this.renderCache.highlighted || forceHighlight)) workerManager.highlightFileAST(this, file);
431
447
  } else {
432
448
  this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);
433
- const hasThemes = this.highlighter != null && areThemesAttached(options.theme, this.highlighter);
434
- const hasLangs = this.highlighter != null && areLanguagesAttached(this.computedLang, this.highlighter);
449
+ const highlighter = getHighlighterIfLoaded();
450
+ const hasThemes = highlighter != null && areThemesAttached(options.theme, highlighter);
451
+ const hasLangs = highlighter != null && areLanguagesAttached(this.computedLang, highlighter);
435
452
  const canHighlight = !forcePlainText && hasLangs;
436
453
  const lazyLineAST = Number.isFinite(renderRange.totalLines);
437
- if (canRenderFile && this.highlighter != null && hasThemes && (forceHighlight || forcePlainText || !this.renderCache.highlighted && canHighlight || this.renderCache.result == null)) {
438
- const { result, options } = this.renderFileWithHighlighter(file, this.highlighter, forcePlainText || !hasLangs, lazyLineAST);
454
+ if (canRenderFile && highlighter != null && hasThemes && (forceHighlight || forcePlainText || !this.renderCache.highlighted && canHighlight || this.renderCache.result == null)) {
455
+ const { result, options } = this.renderFileWithHighlighter(file, highlighter, forcePlainText || !hasLangs, lazyLineAST);
439
456
  this.renderCache = {
440
457
  file,
441
458
  options,
@@ -443,8 +460,16 @@ var FileRenderer = class {
443
460
  result,
444
461
  renderRange: void 0
445
462
  };
463
+ if (canHighlight) this.cacheHighlightResult(file, {
464
+ result,
465
+ options
466
+ });
446
467
  }
447
468
  if (!hasThemes || !forcePlainText && !hasLangs) this.asyncHighlight(file, lazyLineAST).then(({ result, options }) => {
469
+ if (!forcePlainText) this.cacheHighlightResult(file, {
470
+ result,
471
+ options
472
+ });
448
473
  this.applyHighlightResult(file, result, options, !forcePlainText);
449
474
  }).catch((error) => {
450
475
  if (!(error instanceof HighlighterDisposedError)) this.onHighlightError(error);
@@ -460,10 +485,11 @@ var FileRenderer = class {
460
485
  async asyncHighlight(file, lazyLineAST = false) {
461
486
  const forcePlainText = isFileMassive(this.getOrCreateLineCache(file).length, this.getTokenizeMaxLength());
462
487
  this.computedLang = forcePlainText ? "text" : file.lang ?? getFiletypeFromFileName(file.name);
463
- const hasThemes = this.highlighter != null && areThemesAttached(this.getLocalHighlightTheme(), this.highlighter);
464
- const hasLangs = forcePlainText || this.highlighter != null && areLanguagesAttached(this.computedLang, this.highlighter);
465
- if (this.highlighter == null || !hasThemes || !hasLangs) this.highlighter = await this.initializeHighlighter();
466
- return this.renderFileWithHighlighter(file, this.highlighter, forcePlainText, lazyLineAST);
488
+ let highlighter = getHighlighterIfLoaded();
489
+ const hasThemes = highlighter != null && areThemesAttached(this.getLocalHighlightTheme(), highlighter);
490
+ const hasLangs = forcePlainText || highlighter != null && areLanguagesAttached(this.computedLang, highlighter);
491
+ if (highlighter == null || !hasThemes || !hasLangs) highlighter = await this.initializeHighlighter();
492
+ return this.renderFileWithHighlighter(file, highlighter, forcePlainText, lazyLineAST);
467
493
  }
468
494
  renderFileWithHighlighter(file, highlighter, forcePlainText = false, lazyLineAST = false) {
469
495
  const { options } = this.getRenderOptions(file);
@@ -572,12 +598,11 @@ var FileRenderer = class {
572
598
  properties: { "data-code": "" }
573
599
  }));
574
600
  }
575
- async initializeHighlighter() {
576
- this.highlighter = await getSharedHighlighter(getHighlighterOptions(this.computedLang, {
601
+ initializeHighlighter() {
602
+ return getSharedHighlighter(getHighlighterOptions(this.computedLang, {
577
603
  theme: this.getLocalHighlightTheme(),
578
604
  preferredHighlighter: resolvePreferredHighlighter(this.workerManager, this.options)
579
605
  }));
580
- return this.highlighter;
581
606
  }
582
607
  onHighlightSuccess(file, result, options, highlighted = true) {
583
608
  if (this.editSessionActive) return;
@@ -1 +1 @@
1
- {"version":3,"file":"FileRenderer.js","names":[],"sources":["../../src/renderers/FileRenderer.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement } from 'hast';\n\nimport {\n DEFAULT_RENDER_RANGE,\n DEFAULT_THEMES,\n DEFAULT_TOKENIZE_MAX_LENGTH,\n} from '../constants';\nimport type { TextDocument } from '../editor/textDocument';\nimport { areLanguagesAttached } from '../highlighter/languages/areLanguagesAttached';\nimport {\n getHighlighterIfLoaded,\n getSharedHighlighter,\n HighlighterDisposedError,\n} from '../highlighter/shared_highlighter';\nimport { areThemesAttached } from '../highlighter/themes/areThemesAttached';\nimport type {\n BaseCodeOptions,\n DiffsHighlighter,\n FileContents,\n FileHeaderRenderMode,\n HighlightedToken,\n LineAnnotation,\n RenderedFileASTCache,\n RenderFileOptions,\n RenderFileResult,\n RenderRange,\n SupportedLanguages,\n ThemedFileResult,\n} from '../types';\nimport { applyLineTextWithNewline } from '../utils/applyLineTextWithNewline';\nimport { areFileRenderOptionsEqual } from '../utils/areFileRenderOptionsEqual';\nimport { areFileTargetsEqual } from '../utils/areFileTargetsEqual';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { linesFromFileContents } from '../utils/computeFileOffsets';\nimport { createAnnotationElement } from '../utils/createAnnotationElement';\nimport { createContentColumn } from '../utils/createContentColumn';\nimport { createFileHeaderElement } from '../utils/createFileHeaderElement';\nimport { createPreElement } from '../utils/createPreElement';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport { getHighlighterOptions } from '../utils/getHighlighterOptions';\nimport { getLineAnnotationName } from '../utils/getLineAnnotationName';\nimport {\n createGutterGap,\n createGutterItem,\n createGutterWrapper,\n createHastElement,\n} from '../utils/hast_utils';\nimport { hastToHtml } from '../utils/hastToHtml';\nimport {\n FILE_ANNOTATION_HUNK_INDEX,\n FILE_ANNOTATION_LINE_INDEX,\n getFileAnnotations,\n shouldRenderFileAnnotations,\n} from '../utils/includesFileAnnotations';\nimport { isDefaultRenderRange } from '../utils/isDefaultRenderRange';\nimport { isFilePlainText } from '../utils/isFilePlainText';\nimport { renderFileWithHighlighter } from '../utils/renderFileWithHighlighter';\nimport { resolvePreferredHighlighter } from '../utils/resolvePreferredHighlighter';\nimport type { WorkerPoolManager } from '../worker';\n\ntype AnnotationLineMap<LAnnotation> = Record<\n number,\n LineAnnotation<LAnnotation>[] | undefined\n>;\n\ninterface GetRenderOptionsReturn {\n options: RenderFileOptions;\n forceHighlight: boolean;\n}\n\ninterface PendingHighlightResult extends RenderFileResult {\n file: FileContents;\n highlighted: boolean;\n}\n\ninterface FileRenderCache extends RenderedFileASTCache {\n // hydrate() describes DOM that already exists, even when no reusable AST\n // was available for that server-rendered content.\n hydrated?: boolean;\n}\n\nexport interface FileRenderResult {\n file: FileContents;\n gutterAST: ElementContent[];\n contentAST: ElementContent[];\n preAST: HASTElement;\n headerAST: HASTElement | undefined;\n css: string;\n totalLines: number;\n themeStyles: string;\n baseThemeType: 'light' | 'dark' | undefined;\n rowCount: number;\n bufferBefore: number;\n bufferAfter: number;\n}\n\ninterface LineCache {\n cacheKey: string | undefined;\n file: FileContents;\n sourceContents: string;\n lines: string[];\n}\n\n// Explicit keys may share cached lines across equivalent file objects. Unkeyed\n// files stay isolated by object identity while still supporting edit recycle.\nfunction isLineCacheForFile(lineCache: LineCache, file: FileContents): boolean {\n return file.cacheKey == null\n ? lineCache.file === file && lineCache.sourceContents === file.contents\n : lineCache.cacheKey === file.cacheKey;\n}\n\nexport interface FileRendererOptions extends BaseCodeOptions {\n headerRenderMode?: FileHeaderRenderMode;\n}\n\nlet instanceId = -1;\n\nexport class FileRenderer<LAnnotation = undefined> {\n readonly __id: string = `file-renderer:${++instanceId}`;\n\n private highlighter: DiffsHighlighter | undefined;\n // The latest file requested by the component. The render cache may\n // intentionally keep displaying an older highlighted file while this one\n // is highlighted in the background.\n private file: FileContents | undefined;\n\n private renderCache: FileRenderCache | undefined;\n // Completed background work waits here until the next render can update its\n // DOM and layout together.\n private pendingHighlightResult: PendingHighlightResult | undefined;\n\n private computedLang: SupportedLanguages = 'text';\n private lineAnnotations: AnnotationLineMap<LAnnotation> = {};\n private lineCache: LineCache | undefined;\n private pendingStructuralRows: Map<number, HASTElement> | undefined;\n private textDocumentCache = new WeakMap<\n FileContents,\n TextDocument<'file', LAnnotation>\n >();\n\n // Edit-session state: while active, this renderer stays on the main thread\n // with editor-compatible token markup — the editor's caret/selection\n // mapping needs the token transformer, and the pool's global options are\n // not guaranteed to produce it. The pool keeps serving every surface\n // without a session.\n private editSessionActive = false;\n\n public get fileCache(): FileContents | undefined {\n return this.renderCache?.file;\n }\n\n constructor(\n public options: FileRendererOptions = { theme: DEFAULT_THEMES },\n private annotationSlotName: (\n annotation: LineAnnotation<LAnnotation>\n ) => string = getLineAnnotationName,\n private onRenderUpdate?: () => unknown,\n private workerManager?: WorkerPoolManager | undefined\n ) {\n if (workerManager?.isWorkingPool() !== true) {\n this.highlighter = getHighlighterIfLoaded({\n theme: options.theme ?? DEFAULT_THEMES,\n });\n }\n }\n\n public setOptions(options: FileRendererOptions): void {\n this.options = options;\n }\n\n public mergeOptions(options: Partial<FileRendererOptions>): void {\n this.options = { ...this.options, ...options };\n }\n\n public setLineAnnotations(\n lineAnnotations: LineAnnotation<LAnnotation>[]\n ): void {\n this.lineAnnotations = {};\n for (const annotation of lineAnnotations) {\n const arr = this.lineAnnotations[annotation.lineNumber] ?? [];\n this.lineAnnotations[annotation.lineNumber] = arr;\n arr.push(annotation);\n }\n }\n\n public cleanUp(): void {\n this.endEditSession();\n this.recycle();\n this.workerManager = undefined;\n this.onRenderUpdate = undefined;\n }\n\n /**\n * Enter edit-session mode: rendering happens locally with the token\n * transformer forced on, and worker-pool requests/results are suspended\n * for this renderer. Called on initial editor association and whenever its\n * rendering resumes after recycle.\n */\n public beginEditSession(\n file: FileContents,\n externalFile?: FileContents\n ): void {\n const { editSessionActive: wasAlreadyActive, renderCache } = this;\n this.editSessionActive = true;\n if (!wasAlreadyActive) {\n this.pendingHighlightResult = undefined;\n }\n\n this.file = file;\n if (renderCache == null) {\n return;\n }\n // Edit updates call this again before each write. That cache is already\n // private and must retain plain-text session results.\n if (wasAlreadyActive && renderCache.file === file) {\n return;\n }\n if (wasAlreadyActive) {\n this.clearRenderCache();\n this.lineCache = undefined;\n this.textDocumentCache = new WeakMap();\n return;\n }\n const { options } = this.getRenderOptions(file);\n const cacheBelongsToSession = renderCache.file === file;\n const cacheBelongsToExternal =\n externalFile != null &&\n areFileTargetsEqual(renderCache.file, externalFile);\n const { result } = renderCache;\n if (\n !renderCache.highlighted ||\n result == null ||\n !areFileRenderOptionsEqual(renderCache.options, options) ||\n (!cacheBelongsToSession && !cacheBelongsToExternal)\n ) {\n this.clearRenderCache();\n this.lineCache = undefined;\n this.textDocumentCache = new WeakMap();\n return;\n }\n if (cacheBelongsToSession) {\n return;\n }\n\n this.renderCache = {\n ...renderCache,\n file,\n result: {\n ...result,\n code: [...result.code],\n },\n };\n const { lineCache } = this;\n if (\n lineCache != null &&\n externalFile != null &&\n isLineCacheForFile(lineCache, externalFile)\n ) {\n this.lineCache = {\n cacheKey: undefined,\n file,\n sourceContents: file.contents,\n lines: lineCache.lines,\n };\n } else {\n this.lineCache = undefined;\n }\n }\n\n /**\n * Leave edit-session mode. Rendering returns to the pool when one works.\n * When `settledFile` has the content the cache already shows, the cache\n * adopts it as its identity so the next render treats it as current\n * instead of a new file.\n */\n public endEditSession(settledFile?: FileContents): void {\n this.editSessionActive = false;\n this.pendingHighlightResult = undefined;\n if (this.file == null) {\n this.clearRenderCache();\n this.lineCache = undefined;\n this.textDocumentCache = new WeakMap();\n return;\n }\n const { renderCache } = this;\n if (\n settledFile == null ||\n renderCache == null ||\n renderCache.file === settledFile ||\n !areFileTargetsEqual(renderCache.file, settledFile)\n ) {\n return;\n }\n renderCache.file = settledFile;\n }\n\n /**\n * Ensures that the DOM is compatible with editor render updates\n */\n public editorRenderReady(): boolean {\n return (\n this.renderCache?.options.useTokenTransformer === true &&\n this.renderCache.highlighted &&\n this.renderCache.result != null\n );\n }\n\n public recycle(): void {\n if (this.editSessionActive) {\n // The editor and its document survive this recycle. Keep their patched\n // highlight, line map, and document count together for the next mount.\n if (this.renderCache != null) {\n this.renderCache.renderRange = undefined;\n }\n this.pendingHighlightResult = undefined;\n this.pendingStructuralRows = undefined;\n } else {\n this.clearRenderCache();\n this.lineCache = undefined;\n this.textDocumentCache = new WeakMap();\n }\n this.highlighter = undefined;\n this.workerManager?.cleanUpTasks(this);\n this.file = undefined;\n }\n\n public clearRenderCache(): void {\n this.pendingStructuralRows = undefined;\n this.renderCache = undefined;\n this.pendingHighlightResult = undefined;\n }\n\n public hydrate(file: FileContents): void {\n this.file = file;\n this.highlighter = getHighlighterIfLoaded({\n theme: this.getLocalHighlightTheme(),\n });\n const { options } = this.getRenderOptions(file);\n const lines = this.getOrCreateLineCache(file);\n const massiveFile = isFileMassive(\n lines.length,\n this.getTokenizeMaxLength()\n );\n let cache = this.workerManager?.getFileResultCache(file);\n if (cache != null && !areFileRenderOptionsEqual(options, cache.options)) {\n cache = undefined;\n }\n this.renderCache ??= {\n file,\n hydrated: true,\n options,\n highlighted: !massiveFile && !isFilePlainText(file),\n result: massiveFile ? undefined : cache?.result,\n // FIXME(amadeus): Add support for renderRanges\n renderRange: undefined,\n };\n if (\n !this.editSessionActive &&\n this.workerManager?.isWorkingPool() === true\n ) {\n if (this.renderCache.result == null && !massiveFile) {\n // We should only kick off a preload of the AST if we have a WorkerPool\n this.workerManager.highlightFileAST(this, file);\n }\n }\n // Lets attempt to get the highlighter/languages ready immediately\n else if (this.highlighter == null) {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n void this.initializeHighlighter().catch((error: unknown) => {\n if (!(error instanceof HighlighterDisposedError)) {\n this.onHighlightError(error);\n }\n });\n }\n }\n\n private getLocalHighlightTheme(): RenderFileOptions['theme'] {\n return (\n this.workerManager?.getFileRenderOptions().theme ??\n this.options.theme ??\n DEFAULT_THEMES\n );\n }\n\n public getEffectiveCodeOptions(): Pick<\n BaseCodeOptions,\n 'theme' | 'tokenizeMaxLineLength'\n > {\n const poolOptions =\n this.workerManager?.isWorkingPool() === true\n ? this.workerManager.getFileRenderOptions()\n : undefined;\n return {\n theme: this.getLocalHighlightTheme(),\n tokenizeMaxLineLength:\n poolOptions?.tokenizeMaxLineLength ??\n this.options.tokenizeMaxLineLength,\n };\n }\n\n private getRenderOptions(file: FileContents): GetRenderOptionsReturn {\n const options: RenderFileOptions = (() => {\n if (this.workerManager?.isWorkingPool() === true) {\n const poolOptions = this.workerManager.getFileRenderOptions();\n // Active edit sessions require `useTokenTransformer: true`\n if (\n this.editSessionActive &&\n poolOptions.useTokenTransformer !== true\n ) {\n return { ...poolOptions, useTokenTransformer: true };\n }\n return poolOptions;\n }\n const { tokenizeMaxLineLength = 1000 } = this.options;\n return {\n theme: this.getLocalHighlightTheme(),\n useTokenTransformer:\n this.editSessionActive || this.options.useTokenTransformer === true,\n tokenizeMaxLineLength,\n };\n })();\n const { renderCache } = this;\n if (renderCache?.result == null) {\n return { options, forceHighlight: true };\n }\n if (\n !areFileTargetsEqual(file, renderCache.file) ||\n !areFileRenderOptionsEqual(options, renderCache.options)\n ) {\n return { options, forceHighlight: true };\n }\n return { options, forceHighlight: false };\n }\n\n /**\n * Returns the file that the next synchronous render can commit without\n * changing the current render cache. Virtualized layouts use this to stay\n * aligned with the DOM while a replacement highlight is still pending.\n */\n public getFileForNextRender(file: FileContents): FileContents {\n const { options } = this.getRenderOptions(file);\n if (this.getReadyRenderResult(file, options) != null) {\n return file;\n }\n\n const { renderCache } = this;\n if (renderCache == null) {\n return file;\n }\n if (areFileTargetsEqual(renderCache.file, file)) {\n return renderCache.file;\n }\n\n const lines = linesFromFileContents(file.contents);\n const forcePlainText =\n file.contents.length === 0 ||\n isFilePlainText(file) ||\n isFileMassive(lines.length, this.getTokenizeMaxLength());\n\n return this.canRenderFile(file, options, forcePlainText)\n ? file\n : renderCache.file;\n }\n\n private canRenderFile(\n file: FileContents,\n options: RenderFileOptions,\n forcePlainText: boolean\n ): boolean {\n const { renderCache } = this;\n if (renderCache == null || areFileTargetsEqual(renderCache.file, file)) {\n return true;\n }\n if (forcePlainText) {\n return (\n (renderCache.result == null && renderCache.hydrated !== true) ||\n this.workerManager?.isWorkingPool() === true ||\n (this.highlighter != null &&\n areThemesAttached(options.theme, this.highlighter))\n );\n }\n // Hydration has highlighted DOM without a local AST. It is still active\n // rendered content and must remain visible while a non-plain replacement\n // is prepared.\n if (renderCache.result == null && renderCache.hydrated !== true) {\n return true;\n }\n\n if (\n !this.editSessionActive &&\n this.workerManager?.isWorkingPool() === true\n ) {\n return !renderCache.highlighted;\n }\n\n return (\n this.highlighter != null &&\n areThemesAttached(options.theme, this.highlighter)\n );\n }\n\n public getOrCreateLineCache(file: FileContents): string[] {\n let { lineCache } = this;\n if (lineCache == null || !isLineCacheForFile(lineCache, file)) {\n lineCache = {\n cacheKey: file.cacheKey,\n file,\n sourceContents: file.contents,\n lines: linesFromFileContents(file.contents),\n };\n }\n this.lineCache = lineCache;\n return lineCache.lines;\n }\n\n // when a emitLineCountChange is called,\n // calculate the line count using the cached text document\n public getLineCount(file: FileContents): number {\n const lines = this.getOrCreateLineCache(file);\n return this.textDocumentCache.get(file)?.lineCount ?? lines.length;\n }\n\n public updateRenderCache(\n dirtyLines: Map<number, Array<HighlightedToken>>,\n themeType: 'dark' | 'light',\n lineCountChangeInFlight = false\n ): void {\n this.pendingStructuralRows = undefined;\n const { renderCache } = this;\n if (renderCache == null) {\n return;\n }\n const { file, result } = renderCache;\n if (result == null) {\n return;\n }\n const pendingStructuralRows = lineCountChangeInFlight\n ? new Map<number, HASTElement>()\n : undefined;\n this.pendingStructuralRows = pendingStructuralRows;\n // Same-line edits can update the document cache immediately. Structural\n // rows use post-edit indexes, so hold them until applyDocumentChange has\n // shifted the old cache; writing now would overwrite rows that must move.\n const lineCache =\n this.lineCache != null && isLineCacheForFile(this.lineCache, file)\n ? this.lineCache\n : undefined;\n for (const [line, tokens] of dirtyLines) {\n if (\n pendingStructuralRows == null &&\n lineCache != null &&\n line < lineCache.lines.length\n ) {\n const lineText = tokens.map((token) => token[2]).join('');\n lineCache.lines[line] = applyLineTextWithNewline(\n lineCache.lines[line] ?? '',\n lineText\n );\n }\n const row: HASTElement = {\n type: 'element',\n tagName: 'div',\n properties: {\n 'data-line': line + 1,\n 'data-line-type': 'context',\n 'data-line-index': line,\n },\n children: tokens.map(([char, fg, text]) => {\n if (char === 0 && fg === '') {\n if (text === '') {\n return {\n type: 'element',\n tagName: 'br',\n properties: {},\n children: [],\n };\n }\n return { type: 'text', value: text };\n }\n return {\n type: 'element',\n tagName: 'span',\n properties: {\n 'data-char': char,\n style: `color:${fg};`,\n },\n children: [{ type: 'text', value: text }],\n };\n }),\n };\n if (pendingStructuralRows != null) {\n pendingStructuralRows.set(line, row);\n } else {\n result.code[line] = row;\n }\n }\n\n result.baseThemeType = themeType;\n renderCache.isDirty = true;\n if (pendingStructuralRows == null && lineCache != null) {\n file.contents = lineCache.lines.join('');\n lineCache.sourceContents = file.contents;\n }\n }\n\n // Reconcile the session source even when no highlighted result exists. A\n // suspended editor can still receive programmatic edits after cache clear.\n public applyDocumentChange(\n textDocument: TextDocument<'file', LAnnotation>\n ): void {\n const { pendingStructuralRows, renderCache } = this;\n this.pendingStructuralRows = undefined;\n const file = this.file ?? renderCache?.file;\n if (file == null) {\n return;\n }\n const result = renderCache?.result;\n // Structural edits renumber cached HAST rows. Keep the unchanged prefix\n // and suffix, and plain-fill only the window that still needs tokenizing.\n const previousLines =\n this.lineCache != null && isLineCacheForFile(this.lineCache, file)\n ? this.lineCache.lines\n : linesFromFileContents(file.contents);\n const nextLines = linesFromFileContents(textDocument.getText());\n if (result != null && previousLines.length !== nextLines.length) {\n const maxShared = Math.min(previousLines.length, nextLines.length);\n let prefix = 0;\n while (\n prefix < maxShared &&\n previousLines[prefix] === nextLines[prefix]\n ) {\n prefix++;\n }\n let suffix = 0;\n while (\n suffix < maxShared - prefix &&\n previousLines[previousLines.length - 1 - suffix] ===\n nextLines[nextLines.length - 1 - suffix]\n ) {\n suffix++;\n }\n\n const previousCode = result.code;\n result.code = new Array(nextLines.length);\n for (let i = 0; i < prefix; i++) {\n result.code[i] = previousCode[i];\n }\n for (let i = 0; i < suffix; i++) {\n result.code[nextLines.length - 1 - i] =\n previousCode[previousLines.length - 1 - i];\n }\n if (pendingStructuralRows !== undefined) {\n for (const [line, row] of pendingStructuralRows) {\n if (line < nextLines.length) {\n result.code[line] = row;\n }\n }\n }\n for (let i = prefix; i < nextLines.length - suffix; i++) {\n result.code[i] ??= {\n type: 'element',\n tagName: 'div',\n properties: {\n 'data-line': i + 1,\n 'data-line-type': 'context',\n 'data-line-index': i,\n },\n children: [\n {\n type: 'element',\n tagName: 'span',\n properties: {\n 'data-char': 0,\n },\n children: [\n {\n type: 'text',\n value: textDocument.getLineText(i),\n },\n ],\n },\n ],\n };\n }\n for (let i = 0; i < result.code.length; i++) {\n const line = result.code[i];\n if (line?.type === 'element') {\n line.properties['data-line'] = i + 1;\n line.properties['data-line-index'] = i;\n }\n }\n if (renderCache != null) {\n renderCache.isDirty = true;\n }\n }\n // Replace the old split-line cache with the authoritative edited document.\n const contents = textDocument.getText();\n this.lineCache = {\n cacheKey: file.cacheKey,\n file,\n sourceContents: contents,\n lines: nextLines,\n };\n this.textDocumentCache.set(file, textDocument);\n file.contents = contents;\n }\n\n public renderFile(\n file: FileContents | undefined = this.file,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): FileRenderResult | undefined {\n this.file = file;\n if (file == null) {\n this.pendingHighlightResult = undefined;\n return undefined;\n }\n let { options, forceHighlight } = this.getRenderOptions(file);\n const readyResult = this.getReadyRenderResult(file, options);\n this.pendingHighlightResult = undefined;\n if (readyResult != null) {\n this.renderCache = {\n ...readyResult,\n file,\n renderRange: undefined,\n };\n forceHighlight = false;\n }\n this.renderCache ??= {\n file,\n highlighted: false,\n options,\n result: undefined,\n renderRange: undefined,\n };\n const lines = this.getOrCreateLineCache(file);\n const hasContent = file.contents.length > 0;\n const forcePlainText =\n !hasContent ||\n isFilePlainText(file) ||\n isFileMassive(lines.length, this.getTokenizeMaxLength());\n this.highlighter = getHighlighterIfLoaded();\n const canRenderFile = this.canRenderFile(file, options, forcePlainText);\n const newContent = !areFileTargetsEqual(file, this.renderCache.file);\n const newRenderRange = !areRenderRangesEqual(\n this.renderCache.renderRange,\n renderRange\n );\n if (\n !this.editSessionActive &&\n this.workerManager?.isWorkingPool() === true\n ) {\n // Hydration has highlighted DOM but no local AST. Keep that DOM until\n // its corresponding worker result is ready.\n const preserveHydratedContent =\n this.renderCache.result == null &&\n this.renderCache.highlighted &&\n !forcePlainText &&\n !newContent &&\n isDefaultRenderRange(renderRange);\n if (\n canRenderFile &&\n !preserveHydratedContent &&\n (forcePlainText ||\n this.renderCache.result == null ||\n (!this.renderCache.highlighted && (newContent || newRenderRange)))\n ) {\n this.renderCache.file = file;\n this.renderCache.options = options;\n this.renderCache.highlighted = false;\n if (\n this.renderCache.result == null ||\n newContent ||\n newRenderRange ||\n forceHighlight\n ) {\n this.renderCache.result = this.workerManager.getPlainFileAST(\n file,\n renderRange.startingLine,\n renderRange.totalLines,\n lines\n );\n }\n this.renderCache.renderRange = renderRange;\n }\n\n if (\n !forcePlainText &&\n hasContent &&\n (!this.renderCache.highlighted || forceHighlight)\n ) {\n this.workerManager.highlightFileAST(this, file);\n }\n } else {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n const hasThemes =\n this.highlighter != null &&\n areThemesAttached(options.theme, this.highlighter);\n const hasLangs =\n this.highlighter != null &&\n areLanguagesAttached(this.computedLang, this.highlighter);\n const canHighlight = !forcePlainText && hasLangs;\n const lazyLineAST = Number.isFinite(renderRange.totalLines);\n\n if (\n canRenderFile &&\n this.highlighter != null &&\n hasThemes &&\n (forceHighlight ||\n forcePlainText ||\n (!this.renderCache.highlighted && canHighlight) ||\n this.renderCache.result == null)\n ) {\n const { result, options } = this.renderFileWithHighlighter(\n file,\n this.highlighter,\n forcePlainText || !hasLangs,\n lazyLineAST\n );\n this.renderCache = {\n file,\n options,\n highlighted: canHighlight,\n result,\n renderRange: undefined,\n };\n }\n\n if (!hasThemes || (!forcePlainText && !hasLangs)) {\n void this.asyncHighlight(file, lazyLineAST)\n .then(({ result, options }) => {\n this.applyHighlightResult(file, result, options, !forcePlainText);\n })\n .catch((error: unknown) => {\n if (!(error instanceof HighlighterDisposedError)) {\n this.onHighlightError(error);\n }\n });\n }\n }\n\n return this.renderCache.result != null\n ? this.processFileResult(\n this.renderCache.file,\n renderRange,\n this.renderCache.result\n )\n : undefined;\n }\n\n async asyncRender(\n file: FileContents,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): Promise<FileRenderResult> {\n this.file = file;\n const { result } = await this.asyncHighlight(\n file,\n Number.isFinite(renderRange.totalLines)\n );\n return this.processFileResult(file, renderRange, result);\n }\n\n private async asyncHighlight(\n file: FileContents,\n lazyLineAST = false\n ): Promise<RenderFileResult> {\n const lines = this.getOrCreateLineCache(file);\n const forcePlainText = isFileMassive(\n lines.length,\n this.getTokenizeMaxLength()\n );\n this.computedLang = forcePlainText\n ? 'text'\n : (file.lang ?? getFiletypeFromFileName(file.name));\n const hasThemes =\n this.highlighter != null &&\n areThemesAttached(this.getLocalHighlightTheme(), this.highlighter);\n const hasLangs =\n forcePlainText ||\n (this.highlighter != null &&\n areLanguagesAttached(this.computedLang, this.highlighter));\n // If we don't have the required langs or themes, then we need to\n // initialize the highlighter to load the appropriate languages and themes\n if (this.highlighter == null || !hasThemes || !hasLangs) {\n this.highlighter = await this.initializeHighlighter();\n }\n return this.renderFileWithHighlighter(\n file,\n this.highlighter,\n forcePlainText,\n lazyLineAST\n );\n }\n\n private renderFileWithHighlighter(\n file: FileContents,\n highlighter: DiffsHighlighter,\n forcePlainText = false,\n lazyLineAST = false\n ): RenderFileResult {\n const { options } = this.getRenderOptions(file);\n const result = renderFileWithHighlighter(file, highlighter, options, {\n forcePlainText,\n lazyLineAST,\n });\n return { result, options };\n }\n\n private processFileResult(\n file: FileContents,\n renderRange: RenderRange,\n { code, themeStyles, baseThemeType }: ThemedFileResult\n ): FileRenderResult {\n const totalLines = this.getLineCount(file);\n const { disableFileHeader = false } = this.options;\n const contentArray: ElementContent[] = [];\n const gutter = createGutterWrapper();\n const endLine = Math.min(\n renderRange.startingLine + renderRange.totalLines,\n totalLines\n );\n let rowCount = 0;\n\n const fileLevelAnnotations = shouldRenderFileAnnotations(renderRange)\n ? getFileAnnotations(this.lineAnnotations)\n : undefined;\n if (fileLevelAnnotations != null) {\n gutter.children.push(createGutterGap('context', 'annotation', 1));\n contentArray.push(\n createAnnotationElement({\n type: 'annotation',\n hunkIndex: FILE_ANNOTATION_HUNK_INDEX,\n lineIndex: FILE_ANNOTATION_LINE_INDEX,\n annotations: fileLevelAnnotations.map((annotation) =>\n this.annotationSlotName(annotation)\n ),\n })\n );\n rowCount++;\n }\n\n for (\n let lineIndex = renderRange.startingLine;\n lineIndex < endLine;\n lineIndex++\n ) {\n const lineNumber = lineIndex + 1;\n\n // Sparse array - directly indexed by lineIndex\n const line = code[lineIndex];\n if (line == null) {\n const message = 'FileRenderer.processFileResult: Line doesnt exist';\n console.error(message, {\n name: file.name,\n lineIndex,\n lineNumber,\n });\n throw new Error(message);\n }\n\n // Add gutter line number\n gutter.children.push(\n createGutterItem('context', lineNumber, `${lineIndex}`)\n );\n contentArray.push(line);\n rowCount++;\n\n // Check annotations using ACTUAL line number from file\n const annotations = this.lineAnnotations[lineNumber];\n if (annotations != null) {\n gutter.children.push(createGutterGap('context', 'annotation', 1));\n contentArray.push(\n createAnnotationElement({\n type: 'annotation',\n hunkIndex: 0,\n lineIndex: lineNumber,\n annotations: annotations.map((annotation) =>\n this.annotationSlotName(annotation)\n ),\n })\n );\n rowCount++;\n }\n }\n\n // Finalize: wrap gutter and content\n gutter.properties.style = `grid-row: span ${rowCount}`;\n return {\n file,\n gutterAST: gutter.children ?? [],\n contentAST: contentArray,\n preAST: this.createPreElement(totalLines),\n headerAST: !disableFileHeader ? this.renderHeader(file) : undefined,\n totalLines: totalLines,\n rowCount,\n themeStyles: themeStyles,\n baseThemeType,\n bufferBefore: renderRange.bufferBefore,\n bufferAfter: renderRange.bufferAfter,\n css: '',\n };\n }\n\n private renderHeader(file: FileContents) {\n const { headerRenderMode = 'default', stickyHeader = false } = this.options;\n return createFileHeaderElement({\n fileOrDiff: file,\n mode: headerRenderMode,\n stickyHeader,\n });\n }\n\n public renderFullHTML(result: FileRenderResult): string {\n return hastToHtml(this.renderFullAST(result));\n }\n\n public renderFullAST(\n result: FileRenderResult,\n children: ElementContent[] = []\n ): HASTElement {\n children.push(\n createHastElement({\n tagName: 'code',\n children: this.renderCodeAST(result),\n properties: { 'data-code': '' },\n })\n );\n return { ...result.preAST, children };\n }\n\n public renderCodeAST(result: FileRenderResult): ElementContent[] {\n const gutter = createGutterWrapper();\n gutter.children = result.gutterAST;\n gutter.properties.style = `grid-row: span ${result.rowCount}`;\n const contentColumn = createContentColumn(\n result.contentAST,\n result.rowCount\n );\n return [gutter, contentColumn];\n }\n\n public renderPartialHTML(\n children: ElementContent[],\n includeCodeNode: boolean = false\n ): string {\n if (!includeCodeNode) {\n return hastToHtml(children);\n }\n return hastToHtml(\n createHastElement({\n tagName: 'code',\n children,\n properties: { 'data-code': '' },\n })\n );\n }\n\n public async initializeHighlighter(): Promise<DiffsHighlighter> {\n this.highlighter = await getSharedHighlighter(\n getHighlighterOptions(this.computedLang, {\n theme: this.getLocalHighlightTheme(),\n preferredHighlighter: resolvePreferredHighlighter(\n this.workerManager,\n this.options\n ),\n })\n );\n return this.highlighter;\n }\n\n public onHighlightSuccess(\n file: FileContents,\n result: ThemedFileResult,\n options: RenderFileOptions,\n highlighted = true\n ): void {\n if (this.editSessionActive) {\n return;\n }\n this.applyHighlightResult(file, result, options, highlighted);\n }\n\n private applyHighlightResult(\n file: FileContents,\n result: ThemedFileResult,\n options: RenderFileOptions,\n highlighted = true\n ): void {\n const { file: currentFile, renderCache } = this;\n if (\n currentFile == null ||\n renderCache == null ||\n !areFileTargetsEqual(file, currentFile) ||\n !areFileRenderOptionsEqual(\n options,\n this.getRenderOptions(currentFile).options\n )\n ) {\n return;\n }\n\n const triggerRender =\n renderCache.result == null ||\n !renderCache.highlighted ||\n !areFileRenderOptionsEqual(renderCache.options, options) ||\n !areFileTargetsEqual(renderCache.file, currentFile);\n if (!triggerRender) {\n return;\n }\n\n this.pendingHighlightResult = {\n file: currentFile,\n options,\n highlighted,\n result,\n };\n this.onRenderUpdate?.();\n }\n\n private getMatchingWorkerResultCache(\n file: FileContents,\n options: RenderFileOptions\n ): RenderFileResult | undefined {\n if (this.editSessionActive) {\n return undefined;\n }\n const cache = this.workerManager?.getFileResultCache(file);\n if (cache == null || !areFileRenderOptionsEqual(options, cache.options)) {\n return undefined;\n }\n return cache;\n }\n\n // Returns completed background work that can replace the rendered AST on\n // the next render. Reading it does not promote or discard pending work.\n private getReadyRenderResult(\n file: FileContents,\n options: RenderFileOptions\n ): PendingHighlightResult | undefined {\n const { pendingHighlightResult } = this;\n if (\n pendingHighlightResult != null &&\n areFileTargetsEqual(pendingHighlightResult.file, file) &&\n areFileRenderOptionsEqual(pendingHighlightResult.options, options)\n ) {\n return pendingHighlightResult;\n }\n\n const workerCache = this.getMatchingWorkerResultCache(file, options);\n if (workerCache == null || this.hasHighlightedRenderCache(file, options)) {\n return undefined;\n }\n return { file, highlighted: true, ...workerCache };\n }\n\n private hasHighlightedRenderCache(\n file: FileContents,\n options: RenderFileOptions\n ): boolean {\n const { renderCache } = this;\n return (\n renderCache?.result != null &&\n renderCache.highlighted &&\n areFileTargetsEqual(file, renderCache.file) &&\n areFileRenderOptionsEqual(options, renderCache.options)\n );\n }\n\n public onHighlightError(error: unknown): void {\n console.error(error);\n }\n\n private getTokenizeMaxLength(): number {\n return this.options.tokenizeMaxLength ?? DEFAULT_TOKENIZE_MAX_LENGTH;\n }\n\n private createPreElement(totalLines: number): HASTElement {\n const { disableLineNumbers = false, overflow = 'scroll' } = this.options;\n return createPreElement({\n type: 'file',\n diffIndicators: 'none',\n disableBackground: true,\n disableLineNumbers,\n overflow,\n split: false,\n totalLines,\n });\n }\n}\n\nfunction isFileMassive(lineCount: number, tokenizeMaxLength: number): boolean {\n return lineCount > tokenizeMaxLength;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"FileRenderer.js","names":[],"sources":["../../src/renderers/FileRenderer.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement } from 'hast';\n\nimport {\n DEFAULT_RENDER_RANGE,\n DEFAULT_THEMES,\n DEFAULT_TOKENIZE_MAX_LENGTH,\n} from '../constants';\nimport type { TextDocument } from '../editor/textDocument';\nimport { areLanguagesAttached } from '../highlighter/languages/areLanguagesAttached';\nimport {\n getHighlighterIfLoaded,\n getSharedHighlighter,\n HighlighterDisposedError,\n} from '../highlighter/shared_highlighter';\nimport { areThemesAttached } from '../highlighter/themes/areThemesAttached';\nimport type {\n BaseCodeOptions,\n DiffsHighlighter,\n FileContents,\n FileHeaderRenderMode,\n HighlightedToken,\n LineAnnotation,\n RenderedFileASTCache,\n RenderFileOptions,\n RenderFileResult,\n RenderRange,\n SupportedLanguages,\n ThemedFileResult,\n} from '../types';\nimport { applyLineTextWithNewline } from '../utils/applyLineTextWithNewline';\nimport { areFileRenderOptionsEqual } from '../utils/areFileRenderOptionsEqual';\nimport { areFileTargetsEqual } from '../utils/areFileTargetsEqual';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { linesFromFileContents } from '../utils/computeFileOffsets';\nimport { createAnnotationElement } from '../utils/createAnnotationElement';\nimport { createContentColumn } from '../utils/createContentColumn';\nimport { createFileHeaderElement } from '../utils/createFileHeaderElement';\nimport { createPreElement } from '../utils/createPreElement';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport { getHighlighterOptions } from '../utils/getHighlighterOptions';\nimport { getLineAnnotationName } from '../utils/getLineAnnotationName';\nimport {\n createGutterGap,\n createGutterItem,\n createGutterWrapper,\n createHastElement,\n} from '../utils/hast_utils';\nimport { hastToHtml } from '../utils/hastToHtml';\nimport {\n FILE_ANNOTATION_HUNK_INDEX,\n FILE_ANNOTATION_LINE_INDEX,\n getFileAnnotations,\n shouldRenderFileAnnotations,\n} from '../utils/includesFileAnnotations';\nimport { isDefaultRenderRange } from '../utils/isDefaultRenderRange';\nimport { isFilePlainText } from '../utils/isFilePlainText';\nimport { renderFileWithHighlighter } from '../utils/renderFileWithHighlighter';\nimport { resolvePreferredHighlighter } from '../utils/resolvePreferredHighlighter';\nimport type { WorkerPoolManager } from '../worker';\n\ntype AnnotationLineMap<LAnnotation> = Record<\n number,\n LineAnnotation<LAnnotation>[] | undefined\n>;\n\ninterface GetRenderOptionsReturn {\n options: RenderFileOptions;\n forceHighlight: boolean;\n}\n\ninterface PendingHighlightResult extends RenderFileResult {\n file: FileContents;\n highlighted: boolean;\n}\n\ninterface FileRenderCache extends RenderedFileASTCache {\n // hydrate() describes DOM that already exists, even when no reusable AST\n // was available for that server-rendered content.\n hydrated?: boolean;\n}\n\nexport interface FileRenderResult {\n file: FileContents;\n gutterAST: ElementContent[];\n contentAST: ElementContent[];\n preAST: HASTElement;\n headerAST: HASTElement | undefined;\n css: string;\n totalLines: number;\n themeStyles: string;\n baseThemeType: 'light' | 'dark' | undefined;\n rowCount: number;\n bufferBefore: number;\n bufferAfter: number;\n}\n\ninterface LineCache {\n cacheKey: string | undefined;\n file: FileContents;\n sourceContents: string;\n lines: string[];\n}\n\n// Explicit keys may share cached lines across equivalent file objects. Unkeyed\n// files stay isolated by object identity while still supporting edit recycle.\nfunction isLineCacheForFile(lineCache: LineCache, file: FileContents): boolean {\n return file.cacheKey == null\n ? lineCache.file === file && lineCache.sourceContents === file.contents\n : lineCache.cacheKey === file.cacheKey;\n}\n\nexport interface FileRendererOptions extends BaseCodeOptions {\n headerRenderMode?: FileHeaderRenderMode;\n}\n\nlet instanceId = -1;\n\nexport class FileRenderer<LAnnotation = undefined> {\n readonly __id: string = `file-renderer:${++instanceId}`;\n\n // The latest file requested by the component. The render cache may\n // intentionally keep displaying an older highlighted file while this one\n // is highlighted in the background.\n private file: FileContents | undefined;\n\n private renderCache: FileRenderCache | undefined;\n // Completed background work waits here until the next render can update its\n // DOM and layout together.\n private pendingHighlightResult: PendingHighlightResult | undefined;\n\n private computedLang: SupportedLanguages = 'text';\n private lineAnnotations: AnnotationLineMap<LAnnotation> = {};\n private lineCache: LineCache | undefined;\n private pendingStructuralRows: Map<number, HASTElement> | undefined;\n private textDocumentCache = new WeakMap<\n FileContents,\n TextDocument<'file', LAnnotation>\n >();\n // Rows this renderer built itself, which edits renumber in place. Any other\n // row can be shared with the pool cache or other renderers, so an edit\n // copies it the first time it has to change.\n private ownedRows = new WeakSet<HASTElement>();\n\n // Edit-session state: while active, this renderer stays on the main thread\n // with editor-compatible token markup — the editor's caret/selection\n // mapping needs the token transformer, and the pool's global options are\n // not guaranteed to produce it. The pool keeps serving every surface\n // without a session.\n private editSessionActive = false;\n\n public get fileCache(): FileContents | undefined {\n return this.renderCache?.file;\n }\n\n constructor(\n public options: FileRendererOptions = { theme: DEFAULT_THEMES },\n private annotationSlotName: (\n annotation: LineAnnotation<LAnnotation>\n ) => string = getLineAnnotationName,\n private onRenderUpdate?: () => unknown,\n private workerManager?: WorkerPoolManager | undefined\n ) {}\n\n public setOptions(options: FileRendererOptions): void {\n this.options = options;\n }\n\n public mergeOptions(options: Partial<FileRendererOptions>): void {\n this.options = { ...this.options, ...options };\n }\n\n public setLineAnnotations(\n lineAnnotations: LineAnnotation<LAnnotation>[]\n ): void {\n this.lineAnnotations = {};\n for (const annotation of lineAnnotations) {\n const arr = this.lineAnnotations[annotation.lineNumber] ?? [];\n this.lineAnnotations[annotation.lineNumber] = arr;\n arr.push(annotation);\n }\n }\n\n public cleanUp(): void {\n this.endEditSession();\n this.recycle();\n this.workerManager = undefined;\n this.onRenderUpdate = undefined;\n }\n\n /**\n * Enter edit-session mode: rendering happens locally with the token\n * transformer forced on, and worker-pool requests/results are suspended\n * for this renderer. Called on initial editor association and whenever its\n * rendering resumes after recycle.\n */\n public beginEditSession(\n file: FileContents,\n externalFile?: FileContents\n ): void {\n const { editSessionActive: wasAlreadyActive, renderCache } = this;\n this.editSessionActive = true;\n if (!wasAlreadyActive) {\n this.pendingHighlightResult = undefined;\n }\n\n this.file = file;\n if (renderCache == null) {\n return;\n }\n // Edit updates call this again before each write. That cache is already\n // private and must retain plain-text session results.\n if (wasAlreadyActive && renderCache.file === file) {\n return;\n }\n if (wasAlreadyActive) {\n this.clearRenderCache();\n this.lineCache = undefined;\n this.textDocumentCache = new WeakMap();\n return;\n }\n const { options } = this.getRenderOptions(file);\n const cacheBelongsToSession = renderCache.file === file;\n const cacheBelongsToExternal =\n externalFile != null &&\n areFileTargetsEqual(renderCache.file, externalFile);\n const { result } = renderCache;\n if (\n !renderCache.highlighted ||\n result == null ||\n !areFileRenderOptionsEqual(renderCache.options, options) ||\n (!cacheBelongsToSession && !cacheBelongsToExternal)\n ) {\n this.clearRenderCache();\n this.lineCache = undefined;\n this.textDocumentCache = new WeakMap();\n return;\n }\n if (cacheBelongsToSession) {\n return;\n }\n\n this.renderCache = {\n ...renderCache,\n file,\n result: {\n ...result,\n code: [...result.code],\n },\n };\n const { lineCache } = this;\n if (\n lineCache != null &&\n externalFile != null &&\n isLineCacheForFile(lineCache, externalFile)\n ) {\n this.lineCache = {\n cacheKey: undefined,\n file,\n sourceContents: file.contents,\n lines: lineCache.lines,\n };\n } else {\n this.lineCache = undefined;\n }\n }\n\n /**\n * Leave edit-session mode. Rendering returns to the pool when one works.\n * When `settledFile` has the content the cache already shows, the cache\n * adopts it as its identity so the next render treats it as current\n * instead of a new file.\n */\n public endEditSession(settledFile?: FileContents): void {\n this.editSessionActive = false;\n this.pendingHighlightResult = undefined;\n if (this.file == null) {\n this.clearRenderCache();\n this.lineCache = undefined;\n this.textDocumentCache = new WeakMap();\n return;\n }\n const { renderCache } = this;\n if (\n settledFile == null ||\n renderCache == null ||\n renderCache.file === settledFile ||\n !areFileTargetsEqual(renderCache.file, settledFile)\n ) {\n return;\n }\n renderCache.file = settledFile;\n }\n\n /**\n * Ensures that the DOM is compatible with editor render updates\n */\n public editorRenderReady(): boolean {\n return (\n this.renderCache?.options.useTokenTransformer === true &&\n this.renderCache.highlighted &&\n this.renderCache.result != null\n );\n }\n\n public recycle(): void {\n if (this.editSessionActive) {\n // The editor and its document survive this recycle. Keep their patched\n // highlight, line map, and document count together for the next mount.\n if (this.renderCache != null) {\n this.renderCache.renderRange = undefined;\n }\n this.pendingHighlightResult = undefined;\n this.pendingStructuralRows = undefined;\n } else {\n this.clearRenderCache();\n this.lineCache = undefined;\n this.textDocumentCache = new WeakMap();\n }\n this.workerManager?.cleanUpTasks(this);\n this.file = undefined;\n }\n\n public clearRenderCache(): void {\n this.pendingStructuralRows = undefined;\n this.renderCache = undefined;\n this.pendingHighlightResult = undefined;\n }\n\n public hydrate(file: FileContents): void {\n this.file = file;\n const { options } = this.getRenderOptions(file);\n const lines = this.getOrCreateLineCache(file);\n const massiveFile = isFileMassive(\n lines.length,\n this.getTokenizeMaxLength()\n );\n let cache = this.workerManager?.getFileResultCache(file);\n if (cache != null && !areFileRenderOptionsEqual(options, cache.options)) {\n cache = undefined;\n }\n this.renderCache ??= {\n file,\n hydrated: true,\n options,\n highlighted: !massiveFile && !isFilePlainText(file),\n result: massiveFile ? undefined : cache?.result,\n // FIXME(amadeus): Add support for renderRanges\n renderRange: undefined,\n };\n const workerManager = this.getHighlightWorkerManager(file);\n if (workerManager != null) {\n if (this.renderCache.result == null && !massiveFile) {\n // We should only kick off a preload of the AST if we have a WorkerPool\n workerManager.highlightFileAST(this, file);\n }\n }\n // Lets attempt to get the highlighter/languages ready immediately\n else if (\n getHighlighterIfLoaded({ theme: this.getLocalHighlightTheme() }) == null\n ) {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n void this.initializeHighlighter().catch((error: unknown) => {\n if (!(error instanceof HighlighterDisposedError)) {\n this.onHighlightError(error);\n }\n });\n }\n }\n\n // Returns the pool when there's a valid worker AND we should use it\n private getHighlightWorkerManager(\n file: FileContents\n ): WorkerPoolManager | undefined {\n const { editSessionActive, workerManager } = this;\n return !editSessionActive &&\n workerManager?.isWorkingPool() === true &&\n !workerManager.shouldHighlightOnMainThread(file)\n ? workerManager\n : undefined;\n }\n\n private cacheHighlightResult(\n file: FileContents,\n renderResult: RenderFileResult\n ): void {\n const { editSessionActive, workerManager } = this;\n if (!editSessionActive && workerManager?.isWorkingPool() === true) {\n workerManager.setFileResultCache(file.cacheKey, renderResult);\n }\n }\n\n private getLocalHighlightTheme(): RenderFileOptions['theme'] {\n return (\n this.workerManager?.getFileRenderOptions().theme ??\n this.options.theme ??\n DEFAULT_THEMES\n );\n }\n\n public getEffectiveCodeOptions(): Pick<\n BaseCodeOptions,\n 'theme' | 'tokenizeMaxLineLength'\n > {\n const poolOptions =\n this.workerManager?.isWorkingPool() === true\n ? this.workerManager.getFileRenderOptions()\n : undefined;\n return {\n theme: this.getLocalHighlightTheme(),\n tokenizeMaxLineLength:\n poolOptions?.tokenizeMaxLineLength ??\n this.options.tokenizeMaxLineLength,\n };\n }\n\n private getRenderOptions(file: FileContents): GetRenderOptionsReturn {\n const options: RenderFileOptions = (() => {\n if (this.workerManager?.isWorkingPool() === true) {\n const poolOptions = this.workerManager.getFileRenderOptions();\n // Active edit sessions require `useTokenTransformer: true`\n if (\n this.editSessionActive &&\n poolOptions.useTokenTransformer !== true\n ) {\n return { ...poolOptions, useTokenTransformer: true };\n }\n return poolOptions;\n }\n const { tokenizeMaxLineLength = 1000 } = this.options;\n return {\n theme: this.getLocalHighlightTheme(),\n useTokenTransformer:\n this.editSessionActive || this.options.useTokenTransformer === true,\n tokenizeMaxLineLength,\n };\n })();\n const { renderCache } = this;\n if (renderCache?.result == null) {\n return { options, forceHighlight: true };\n }\n if (\n !areFileTargetsEqual(file, renderCache.file) ||\n !areFileRenderOptionsEqual(options, renderCache.options)\n ) {\n return { options, forceHighlight: true };\n }\n return { options, forceHighlight: false };\n }\n\n /**\n * Returns the file that the next synchronous render can commit without\n * changing the current render cache. Virtualized layouts use this to stay\n * aligned with the DOM while a replacement highlight is still pending.\n */\n public getFileForNextRender(file: FileContents): FileContents {\n const { options } = this.getRenderOptions(file);\n if (this.getReadyRenderResult(file, options) != null) {\n return file;\n }\n\n const { renderCache } = this;\n if (renderCache == null) {\n return file;\n }\n if (areFileTargetsEqual(renderCache.file, file)) {\n return renderCache.file;\n }\n\n const lines = linesFromFileContents(file.contents);\n const forcePlainText =\n file.contents.length === 0 ||\n isFilePlainText(file) ||\n isFileMassive(lines.length, this.getTokenizeMaxLength());\n\n return this.canRenderFile(file, options, forcePlainText)\n ? file\n : renderCache.file;\n }\n\n private canRenderFile(\n file: FileContents,\n options: RenderFileOptions,\n forcePlainText: boolean\n ): boolean {\n const { renderCache } = this;\n if (renderCache == null || areFileTargetsEqual(renderCache.file, file)) {\n return true;\n }\n if (forcePlainText) {\n return (\n (renderCache.result == null && renderCache.hydrated !== true) ||\n (this.workerManager?.isWorkingPool() === true &&\n !this.workerManager.shouldHighlightOnMainThread(file)) ||\n getHighlighterIfLoaded({ theme: options.theme }) != null\n );\n }\n // Hydration has highlighted DOM without a local AST. It is still active\n // rendered content and must remain visible while a non-plain replacement\n // is prepared.\n if (renderCache.result == null && renderCache.hydrated !== true) {\n return true;\n }\n\n if (this.getHighlightWorkerManager(file) != null) {\n return !renderCache.highlighted;\n }\n\n return getHighlighterIfLoaded({ theme: options.theme }) != null;\n }\n\n public getOrCreateLineCache(file: FileContents): string[] {\n let { lineCache } = this;\n if (lineCache == null || !isLineCacheForFile(lineCache, file)) {\n lineCache = {\n cacheKey: file.cacheKey,\n file,\n sourceContents: file.contents,\n lines: linesFromFileContents(file.contents),\n };\n }\n this.lineCache = lineCache;\n return lineCache.lines;\n }\n\n // when a emitLineCountChange is called,\n // calculate the line count using the cached text document\n public getLineCount(file: FileContents): number {\n const lines = this.getOrCreateLineCache(file);\n return this.textDocumentCache.get(file)?.lineCount ?? lines.length;\n }\n\n public updateRenderCache(\n dirtyLines: Map<number, Array<HighlightedToken>>,\n themeType: 'dark' | 'light',\n lineCountChangeInFlight = false\n ): void {\n this.pendingStructuralRows = undefined;\n const { renderCache } = this;\n if (renderCache == null) {\n return;\n }\n const { file, result } = renderCache;\n if (result == null) {\n return;\n }\n const pendingStructuralRows = lineCountChangeInFlight\n ? new Map<number, HASTElement>()\n : undefined;\n this.pendingStructuralRows = pendingStructuralRows;\n // Same-line edits can update the document cache immediately. Structural\n // rows use post-edit indexes, so hold them until applyDocumentChange has\n // shifted the old cache; writing now would overwrite rows that must move.\n const lineCache =\n this.lineCache != null && isLineCacheForFile(this.lineCache, file)\n ? this.lineCache\n : undefined;\n for (const [line, tokens] of dirtyLines) {\n if (\n pendingStructuralRows == null &&\n lineCache != null &&\n line < lineCache.lines.length\n ) {\n const lineText = tokens.map((token) => token[2]).join('');\n lineCache.lines[line] = applyLineTextWithNewline(\n lineCache.lines[line] ?? '',\n lineText\n );\n }\n const row: HASTElement = {\n type: 'element',\n tagName: 'div',\n properties: {\n 'data-line': line + 1,\n 'data-line-type': 'context',\n 'data-line-index': line,\n },\n children: tokens.map(([char, fg, text]) => {\n if (char === 0 && fg === '') {\n if (text === '') {\n return {\n type: 'element',\n tagName: 'br',\n properties: {},\n children: [],\n };\n }\n return { type: 'text', value: text };\n }\n return {\n type: 'element',\n tagName: 'span',\n properties: {\n 'data-char': char,\n style: `color:${fg};`,\n },\n children: [{ type: 'text', value: text }],\n };\n }),\n };\n this.ownedRows.add(row);\n if (pendingStructuralRows != null) {\n pendingStructuralRows.set(line, row);\n } else {\n result.code[line] = row;\n }\n }\n\n result.baseThemeType = themeType;\n renderCache.isDirty = true;\n if (pendingStructuralRows == null && lineCache != null) {\n file.contents = lineCache.lines.join('');\n lineCache.sourceContents = file.contents;\n }\n }\n\n // Reconcile the session source even when no highlighted result exists. A\n // suspended editor can still receive programmatic edits after cache clear.\n public applyDocumentChange(\n textDocument: TextDocument<'file', LAnnotation>\n ): void {\n const { pendingStructuralRows, renderCache } = this;\n this.pendingStructuralRows = undefined;\n const file = this.file ?? renderCache?.file;\n if (file == null) {\n return;\n }\n const result = renderCache?.result;\n // Structural edits renumber cached HAST rows. Keep the unchanged prefix\n // and suffix, and plain-fill only the window that still needs tokenizing.\n const previousLines =\n this.lineCache != null && isLineCacheForFile(this.lineCache, file)\n ? this.lineCache.lines\n : linesFromFileContents(file.contents);\n const nextLines = linesFromFileContents(textDocument.getText());\n if (result != null && previousLines.length !== nextLines.length) {\n const maxShared = Math.min(previousLines.length, nextLines.length);\n let prefix = 0;\n while (\n prefix < maxShared &&\n previousLines[prefix] === nextLines[prefix]\n ) {\n prefix++;\n }\n let suffix = 0;\n while (\n suffix < maxShared - prefix &&\n previousLines[previousLines.length - 1 - suffix] ===\n nextLines[nextLines.length - 1 - suffix]\n ) {\n suffix++;\n }\n\n const previousCode = result.code;\n result.code = new Array(nextLines.length);\n for (let i = 0; i < prefix; i++) {\n result.code[i] = previousCode[i];\n }\n for (let i = 0; i < suffix; i++) {\n result.code[nextLines.length - 1 - i] =\n previousCode[previousLines.length - 1 - i];\n }\n if (pendingStructuralRows !== undefined) {\n for (const [line, row] of pendingStructuralRows) {\n if (line < nextLines.length) {\n result.code[line] = row;\n }\n }\n }\n for (let i = prefix; i < nextLines.length - suffix; i++) {\n result.code[i] ??= this.ownRow({\n type: 'element',\n tagName: 'div',\n properties: {\n 'data-line': i + 1,\n 'data-line-type': 'context',\n 'data-line-index': i,\n },\n children: [\n {\n type: 'element',\n tagName: 'span',\n properties: {\n 'data-char': 0,\n },\n children: [\n {\n type: 'text',\n value: textDocument.getLineText(i),\n },\n ],\n },\n ],\n });\n }\n for (let i = 0; i < result.code.length; i++) {\n const line = result.code[i];\n if (\n line?.type === 'element' &&\n (line.properties['data-line'] !== i + 1 ||\n line.properties['data-line-index'] !== i)\n ) {\n const row = this.ownedRows.has(line)\n ? line\n : this.ownRow({ ...line, properties: { ...line.properties } });\n row.properties['data-line'] = i + 1;\n row.properties['data-line-index'] = i;\n result.code[i] = row;\n }\n }\n if (renderCache != null) {\n renderCache.isDirty = true;\n }\n }\n // Replace the old split-line cache with the authoritative edited document.\n const contents = textDocument.getText();\n this.lineCache = {\n cacheKey: file.cacheKey,\n file,\n sourceContents: contents,\n lines: nextLines,\n };\n this.textDocumentCache.set(file, textDocument);\n file.contents = contents;\n }\n\n private ownRow(row: HASTElement): HASTElement {\n this.ownedRows.add(row);\n return row;\n }\n\n public renderFile(\n file: FileContents | undefined = this.file,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): FileRenderResult | undefined {\n this.file = file;\n if (file == null) {\n this.pendingHighlightResult = undefined;\n return undefined;\n }\n let { options, forceHighlight } = this.getRenderOptions(file);\n const readyResult = this.getReadyRenderResult(file, options);\n this.pendingHighlightResult = undefined;\n if (readyResult != null) {\n this.renderCache = {\n ...readyResult,\n file,\n renderRange: undefined,\n };\n forceHighlight = false;\n }\n this.renderCache ??= {\n file,\n highlighted: false,\n options,\n result: undefined,\n renderRange: undefined,\n };\n const lines = this.getOrCreateLineCache(file);\n const hasContent = file.contents.length > 0;\n const forcePlainText =\n !hasContent ||\n isFilePlainText(file) ||\n isFileMassive(lines.length, this.getTokenizeMaxLength());\n const canRenderFile = this.canRenderFile(file, options, forcePlainText);\n const newContent = !areFileTargetsEqual(file, this.renderCache.file);\n const newRenderRange = !areRenderRangesEqual(\n this.renderCache.renderRange,\n renderRange\n );\n const workerManager = this.getHighlightWorkerManager(file);\n if (workerManager != null) {\n // Hydration has highlighted DOM but no local AST. Keep that DOM until\n // its corresponding worker result is ready.\n const preserveHydratedContent =\n this.renderCache.result == null &&\n this.renderCache.highlighted &&\n !forcePlainText &&\n !newContent &&\n isDefaultRenderRange(renderRange);\n if (\n canRenderFile &&\n !preserveHydratedContent &&\n (forcePlainText ||\n this.renderCache.result == null ||\n (!this.renderCache.highlighted && (newContent || newRenderRange)))\n ) {\n this.renderCache.file = file;\n this.renderCache.options = options;\n this.renderCache.highlighted = false;\n if (\n this.renderCache.result == null ||\n newContent ||\n newRenderRange ||\n forceHighlight\n ) {\n this.renderCache.result = workerManager.getPlainFileAST(\n file,\n renderRange.startingLine,\n renderRange.totalLines,\n lines\n );\n }\n this.renderCache.renderRange = renderRange;\n }\n\n if (\n !forcePlainText &&\n hasContent &&\n (!this.renderCache.highlighted || forceHighlight)\n ) {\n workerManager.highlightFileAST(this, file);\n }\n } else {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n const highlighter = getHighlighterIfLoaded();\n const hasThemes =\n highlighter != null && areThemesAttached(options.theme, highlighter);\n const hasLangs =\n highlighter != null &&\n areLanguagesAttached(this.computedLang, highlighter);\n const canHighlight = !forcePlainText && hasLangs;\n const lazyLineAST = Number.isFinite(renderRange.totalLines);\n\n if (\n canRenderFile &&\n highlighter != null &&\n hasThemes &&\n (forceHighlight ||\n forcePlainText ||\n (!this.renderCache.highlighted && canHighlight) ||\n this.renderCache.result == null)\n ) {\n const { result, options } = this.renderFileWithHighlighter(\n file,\n highlighter,\n forcePlainText || !hasLangs,\n lazyLineAST\n );\n this.renderCache = {\n file,\n options,\n highlighted: canHighlight,\n result,\n renderRange: undefined,\n };\n if (canHighlight) {\n this.cacheHighlightResult(file, { result, options });\n }\n }\n\n if (!hasThemes || (!forcePlainText && !hasLangs)) {\n void this.asyncHighlight(file, lazyLineAST)\n .then(({ result, options }) => {\n if (!forcePlainText) {\n this.cacheHighlightResult(file, { result, options });\n }\n this.applyHighlightResult(file, result, options, !forcePlainText);\n })\n .catch((error: unknown) => {\n if (!(error instanceof HighlighterDisposedError)) {\n this.onHighlightError(error);\n }\n });\n }\n }\n\n return this.renderCache.result != null\n ? this.processFileResult(\n this.renderCache.file,\n renderRange,\n this.renderCache.result\n )\n : undefined;\n }\n\n async asyncRender(\n file: FileContents,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): Promise<FileRenderResult> {\n this.file = file;\n const { result } = await this.asyncHighlight(\n file,\n Number.isFinite(renderRange.totalLines)\n );\n return this.processFileResult(file, renderRange, result);\n }\n\n private async asyncHighlight(\n file: FileContents,\n lazyLineAST = false\n ): Promise<RenderFileResult> {\n const lines = this.getOrCreateLineCache(file);\n const forcePlainText = isFileMassive(\n lines.length,\n this.getTokenizeMaxLength()\n );\n this.computedLang = forcePlainText\n ? 'text'\n : (file.lang ?? getFiletypeFromFileName(file.name));\n let highlighter = getHighlighterIfLoaded();\n const hasThemes =\n highlighter != null &&\n areThemesAttached(this.getLocalHighlightTheme(), highlighter);\n const hasLangs =\n forcePlainText ||\n (highlighter != null &&\n areLanguagesAttached(this.computedLang, highlighter));\n // If we don't have the required langs or themes, then we need to\n // initialize the highlighter to load the appropriate languages and themes\n if (highlighter == null || !hasThemes || !hasLangs) {\n highlighter = await this.initializeHighlighter();\n }\n return this.renderFileWithHighlighter(\n file,\n highlighter,\n forcePlainText,\n lazyLineAST\n );\n }\n\n private renderFileWithHighlighter(\n file: FileContents,\n highlighter: DiffsHighlighter,\n forcePlainText = false,\n lazyLineAST = false\n ): RenderFileResult {\n const { options } = this.getRenderOptions(file);\n const result = renderFileWithHighlighter(file, highlighter, options, {\n forcePlainText,\n lazyLineAST,\n });\n return { result, options };\n }\n\n private processFileResult(\n file: FileContents,\n renderRange: RenderRange,\n { code, themeStyles, baseThemeType }: ThemedFileResult\n ): FileRenderResult {\n const totalLines = this.getLineCount(file);\n const { disableFileHeader = false } = this.options;\n const contentArray: ElementContent[] = [];\n const gutter = createGutterWrapper();\n const endLine = Math.min(\n renderRange.startingLine + renderRange.totalLines,\n totalLines\n );\n let rowCount = 0;\n\n const fileLevelAnnotations = shouldRenderFileAnnotations(renderRange)\n ? getFileAnnotations(this.lineAnnotations)\n : undefined;\n if (fileLevelAnnotations != null) {\n gutter.children.push(createGutterGap('context', 'annotation', 1));\n contentArray.push(\n createAnnotationElement({\n type: 'annotation',\n hunkIndex: FILE_ANNOTATION_HUNK_INDEX,\n lineIndex: FILE_ANNOTATION_LINE_INDEX,\n annotations: fileLevelAnnotations.map((annotation) =>\n this.annotationSlotName(annotation)\n ),\n })\n );\n rowCount++;\n }\n\n for (\n let lineIndex = renderRange.startingLine;\n lineIndex < endLine;\n lineIndex++\n ) {\n const lineNumber = lineIndex + 1;\n\n // Sparse array - directly indexed by lineIndex\n const line = code[lineIndex];\n if (line == null) {\n const message = 'FileRenderer.processFileResult: Line doesnt exist';\n console.error(message, {\n name: file.name,\n lineIndex,\n lineNumber,\n });\n throw new Error(message);\n }\n\n // Add gutter line number\n gutter.children.push(\n createGutterItem('context', lineNumber, `${lineIndex}`)\n );\n contentArray.push(line);\n rowCount++;\n\n // Check annotations using ACTUAL line number from file\n const annotations = this.lineAnnotations[lineNumber];\n if (annotations != null) {\n gutter.children.push(createGutterGap('context', 'annotation', 1));\n contentArray.push(\n createAnnotationElement({\n type: 'annotation',\n hunkIndex: 0,\n lineIndex: lineNumber,\n annotations: annotations.map((annotation) =>\n this.annotationSlotName(annotation)\n ),\n })\n );\n rowCount++;\n }\n }\n\n // Finalize: wrap gutter and content\n gutter.properties.style = `grid-row: span ${rowCount}`;\n return {\n file,\n gutterAST: gutter.children ?? [],\n contentAST: contentArray,\n preAST: this.createPreElement(totalLines),\n headerAST: !disableFileHeader ? this.renderHeader(file) : undefined,\n totalLines: totalLines,\n rowCount,\n themeStyles: themeStyles,\n baseThemeType,\n bufferBefore: renderRange.bufferBefore,\n bufferAfter: renderRange.bufferAfter,\n css: '',\n };\n }\n\n private renderHeader(file: FileContents) {\n const { headerRenderMode = 'default', stickyHeader = false } = this.options;\n return createFileHeaderElement({\n fileOrDiff: file,\n mode: headerRenderMode,\n stickyHeader,\n });\n }\n\n public renderFullHTML(result: FileRenderResult): string {\n return hastToHtml(this.renderFullAST(result));\n }\n\n public renderFullAST(\n result: FileRenderResult,\n children: ElementContent[] = []\n ): HASTElement {\n children.push(\n createHastElement({\n tagName: 'code',\n children: this.renderCodeAST(result),\n properties: { 'data-code': '' },\n })\n );\n return { ...result.preAST, children };\n }\n\n public renderCodeAST(result: FileRenderResult): ElementContent[] {\n const gutter = createGutterWrapper();\n gutter.children = result.gutterAST;\n gutter.properties.style = `grid-row: span ${result.rowCount}`;\n const contentColumn = createContentColumn(\n result.contentAST,\n result.rowCount\n );\n return [gutter, contentColumn];\n }\n\n public renderPartialHTML(\n children: ElementContent[],\n includeCodeNode: boolean = false\n ): string {\n if (!includeCodeNode) {\n return hastToHtml(children);\n }\n return hastToHtml(\n createHastElement({\n tagName: 'code',\n children,\n properties: { 'data-code': '' },\n })\n );\n }\n\n public initializeHighlighter(): Promise<DiffsHighlighter> {\n return getSharedHighlighter(\n getHighlighterOptions(this.computedLang, {\n theme: this.getLocalHighlightTheme(),\n preferredHighlighter: resolvePreferredHighlighter(\n this.workerManager,\n this.options\n ),\n })\n );\n }\n\n public onHighlightSuccess(\n file: FileContents,\n result: ThemedFileResult,\n options: RenderFileOptions,\n highlighted = true\n ): void {\n if (this.editSessionActive) {\n return;\n }\n this.applyHighlightResult(file, result, options, highlighted);\n }\n\n private applyHighlightResult(\n file: FileContents,\n result: ThemedFileResult,\n options: RenderFileOptions,\n highlighted = true\n ): void {\n const { file: currentFile, renderCache } = this;\n if (\n currentFile == null ||\n renderCache == null ||\n !areFileTargetsEqual(file, currentFile) ||\n !areFileRenderOptionsEqual(\n options,\n this.getRenderOptions(currentFile).options\n )\n ) {\n return;\n }\n\n const triggerRender =\n renderCache.result == null ||\n !renderCache.highlighted ||\n !areFileRenderOptionsEqual(renderCache.options, options) ||\n !areFileTargetsEqual(renderCache.file, currentFile);\n if (!triggerRender) {\n return;\n }\n\n this.pendingHighlightResult = {\n file: currentFile,\n options,\n highlighted,\n result,\n };\n this.onRenderUpdate?.();\n }\n\n private getMatchingWorkerResultCache(\n file: FileContents,\n options: RenderFileOptions\n ): RenderFileResult | undefined {\n if (this.editSessionActive) {\n return undefined;\n }\n const cache = this.workerManager?.getFileResultCache(file);\n if (cache == null || !areFileRenderOptionsEqual(options, cache.options)) {\n return undefined;\n }\n return cache;\n }\n\n // Returns completed background work that can replace the rendered AST on\n // the next render. Reading it does not promote or discard pending work.\n private getReadyRenderResult(\n file: FileContents,\n options: RenderFileOptions\n ): PendingHighlightResult | undefined {\n const { pendingHighlightResult } = this;\n if (\n pendingHighlightResult != null &&\n areFileTargetsEqual(pendingHighlightResult.file, file) &&\n areFileRenderOptionsEqual(pendingHighlightResult.options, options)\n ) {\n return pendingHighlightResult;\n }\n\n const workerCache = this.getMatchingWorkerResultCache(file, options);\n if (workerCache == null || this.hasHighlightedRenderCache(file, options)) {\n return undefined;\n }\n return { file, highlighted: true, ...workerCache };\n }\n\n private hasHighlightedRenderCache(\n file: FileContents,\n options: RenderFileOptions\n ): boolean {\n const { renderCache } = this;\n return (\n renderCache?.result != null &&\n renderCache.highlighted &&\n areFileTargetsEqual(file, renderCache.file) &&\n areFileRenderOptionsEqual(options, renderCache.options)\n );\n }\n\n public onHighlightError(error: unknown): void {\n console.error(error);\n }\n\n private getTokenizeMaxLength(): number {\n return this.options.tokenizeMaxLength ?? DEFAULT_TOKENIZE_MAX_LENGTH;\n }\n\n private createPreElement(totalLines: number): HASTElement {\n const { disableLineNumbers = false, overflow = 'scroll' } = this.options;\n return createPreElement({\n type: 'file',\n diffIndicators: 'none',\n disableBackground: true,\n disableLineNumbers,\n overflow,\n split: false,\n totalLines,\n });\n }\n}\n\nfunction isFileMassive(lineCount: number, tokenizeMaxLength: number): boolean {\n return lineCount > tokenizeMaxLength;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"UnresolvedFileHunksRenderer.d.ts","names":[],"sources":["../../src/renderers/UnresolvedFileHunksRenderer.ts"],"mappings":";;;;;;;UA+DU,0CAA0C;EAClD,0BAA0B;;KAGvB;UAEY,2CAA2C;EAC1D,2BAA2B;;cAGhB,4BACX,iCACQ,kBAAkB;UAClB;UACA;UACA;EACQ,SAAS;EAEzB,YACE,UAAS,oCAGT,sBACE,YAAY,mBAAmB,yBAEjC,gCACA,gBAAgB;EAWX,iBACL,kBAAkB,wCAClB,YAAY,0BACZ,MAAM;UAOA;UA0BA;EAUQ,WACd,OAAO,8BACP,cAAa,cACZ;EAWmB,YACpB,MAAM,kBACN,cAAa,cACZ,QAAQ;YASQ,iBACjB,gBACA,qBACC;YAMgB,2BACjB,MACA,YACC,6BAA6B;YAiBb,yBACjB,MACA,QACC,2BAA2B;YAiBX,gCAA6B,KACzC,wBACJ;YAgCgB,0BAA0B"}
1
+ {"version":3,"file":"UnresolvedFileHunksRenderer.d.ts","names":[],"sources":["../../src/renderers/UnresolvedFileHunksRenderer.ts"],"mappings":";;;;;;;UA+DU,0CAA0C;EAClD,0BAA0B;;KAGvB;UAEY,2CAA2C;EAC1D,2BAA2B;;cAGhB,4BACX,iCACQ,kBAAkB;UAClB;UACA;UACA;EACQ,SAAS;EAEzB,YACE,UAAS,oCAGT,sBACE,YAAY,mBAAmB,yBAEjC,gCACA,gBAAgB;EAMX,iBACL,kBAAkB,wCAClB,YAAY,0BACZ,MAAM;UAOA;UA0BA;EAUQ,WACd,OAAO,8BACP,cAAa,cACZ;EAWmB,YACpB,MAAM,kBACN,cAAa,cACZ,QAAQ;YASQ,iBACjB,gBACA,qBACC;YAMgB,2BACjB,MACA,YACC,6BAA6B;YAiBb,yBACjB,MACA,QACC,2BAA2B;YAiBX,gCAA6B,KACzC,wBACJ;YAgCgB,0BAA0B"}
@@ -40,7 +40,7 @@ var UnresolvedFileHunksRenderer = class extends DiffHunksRenderer {
40
40
  else rows.push(row);
41
41
  }
42
42
  renderDiff(diff, renderRange = DEFAULT_RENDER_RANGE) {
43
- if (diff != null) this.syncInjectedRows(this.pendingConflictActions, this.pendingMarkerRows, diff);
43
+ if (diff != null) this.syncInjectedRows(this.pendingConflictActions, this.pendingMarkerRows, this.getDiffForNextRender(diff));
44
44
  return super.renderDiff(diff, renderRange);
45
45
  }
46
46
  async asyncRender(diff, renderRange = DEFAULT_RENDER_RANGE) {
@@ -1 +1 @@
1
- {"version":3,"file":"UnresolvedFileHunksRenderer.js","names":[],"sources":["../../src/renderers/UnresolvedFileHunksRenderer.ts"],"sourcesContent":["import type { Element as HASTElement, Properties } from 'hast';\n\nimport { DEFAULT_RENDER_RANGE, DEFAULT_THEMES } from '../constants';\nimport type {\n DiffLineAnnotation,\n FileDiffMetadata,\n MergeConflictMarkerRow,\n MergeConflictResolution,\n RenderRange,\n} from '../types';\nimport { getMergeConflictActionSlotName } from '../utils/getMergeConflictActionSlotName';\nimport {\n createGutterGap,\n createHastElement,\n createTextNodeElement,\n} from '../utils/hast_utils';\nimport {\n getMergeConflictActionAnchor,\n type MergeConflictDiffAction,\n} from '../utils/parseMergeConflictDiffFromFile';\nimport type { WorkerPoolManager } from '../worker';\nimport {\n DiffHunksRenderer,\n type DiffHunksRendererOptions,\n type DiffHunksRendererOptionsWithDefaults,\n type HunksRenderResult,\n type InjectedRow,\n type LineDecoration,\n type RenderedLineContext,\n type SplitLineDecorationProps,\n type UnifiedInjectedRowPlacement,\n type UnifiedLineDecorationProps,\n} from './DiffHunksRenderer';\n\ntype MergeConflictMarkerType =\n | 'marker-start'\n | 'marker-base'\n | 'marker-separator'\n | 'marker-end'\n | 'current'\n | 'incoming';\n\ninterface MergeConflictActionRowData {\n hunkIndex: number;\n lineIndex: number;\n conflictIndex: number;\n}\n\ninterface MergeConflictMarkerInjectedRow extends MergeConflictMarkerRow {\n type: Extract<\n MergeConflictMarkerRow['type'],\n 'marker-start' | 'marker-base' | 'marker-separator' | 'marker-end'\n >;\n lineText: string;\n lineIndex: number;\n}\n\n// NOTE(amadeus): Don't love this, should probably rework into an\n// interface/extender\ntype MergeConflictInjectedRowData =\n | ({ type: 'actions' } & MergeConflictActionRowData)\n | MergeConflictMarkerInjectedRow;\n\ninterface BaseUnresolvedOptionsWithDefaults extends DiffHunksRendererOptionsWithDefaults {\n mergeConflictActionsType: MergeConflictActionsType;\n}\n\ntype MergeConflictActionsType = 'none' | 'default' | 'custom';\n\nexport interface UnresolvedFileHunksRendererOptions extends DiffHunksRendererOptions {\n mergeConflictActionsType?: MergeConflictActionsType;\n}\n\nexport class UnresolvedFileHunksRenderer<\n LAnnotation = undefined,\n> extends DiffHunksRenderer<LAnnotation> {\n private pendingConflictActions: (MergeConflictDiffAction | undefined)[] = [];\n private pendingMarkerRows: MergeConflictMarkerRow[] = [];\n private injectedRows = new Map<string, MergeConflictInjectedRowData[]>();\n public override options: UnresolvedFileHunksRendererOptions;\n\n constructor(\n options: UnresolvedFileHunksRendererOptions = {\n theme: DEFAULT_THEMES,\n },\n annotationSlotName?: (\n annotation: DiffLineAnnotation<LAnnotation>\n ) => string,\n onRenderUpdate?: () => unknown,\n workerManager?: WorkerPoolManager | undefined\n ) {\n super(undefined, annotationSlotName, onRenderUpdate, workerManager);\n this.options = options;\n }\n\n // SELF_REVIEW: I don't love how this is hooked up with `renderDiff` right\n // now, so we definitely need to figure out what the fuck we are gonna do\n // about it...\n // I think at the very least we should keep it like annotations, and just\n // sorta assume there's a disconnect there\n public setConflictState(\n conflictActions: (MergeConflictDiffAction | undefined)[],\n markerRows: MergeConflictMarkerRow[],\n diff: FileDiffMetadata\n ): void {\n this.pendingConflictActions = conflictActions;\n this.pendingMarkerRows = markerRows;\n this.syncInjectedRows(conflictActions, markerRows, diff);\n }\n\n private syncInjectedRows(\n conflictActions: (MergeConflictDiffAction | undefined)[],\n markerRows: MergeConflictMarkerRow[],\n diff: FileDiffMetadata\n ): void {\n this.injectedRows.clear();\n for (const action of conflictActions) {\n const anchor =\n action != null ? getMergeConflictActionAnchor(action, diff) : undefined;\n if (action == null || anchor == null) {\n continue;\n }\n const row: MergeConflictInjectedRowData = {\n type: 'actions',\n hunkIndex: anchor.hunkIndex,\n lineIndex: anchor.lineIndex,\n conflictIndex: action.conflictIndex,\n };\n this.addInjectedRow(row);\n }\n\n for (const row of markerRows) {\n this.addInjectedRow(row);\n }\n }\n\n private addInjectedRow(row: MergeConflictInjectedRowData): void {\n const key = `${row.hunkIndex}:${row.lineIndex}`;\n const rows = this.injectedRows.get(key);\n if (rows == null) {\n this.injectedRows.set(key, [row]);\n } else {\n rows.push(row);\n }\n }\n\n public override renderDiff(\n diff?: FileDiffMetadata | undefined,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): HunksRenderResult | undefined {\n if (diff != null) {\n this.syncInjectedRows(\n this.pendingConflictActions,\n this.pendingMarkerRows,\n diff\n );\n }\n return super.renderDiff(diff, renderRange);\n }\n\n public override async asyncRender(\n diff: FileDiffMetadata,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): Promise<HunksRenderResult> {\n this.syncInjectedRows(\n this.pendingConflictActions,\n this.pendingMarkerRows,\n diff\n );\n return super.asyncRender(diff, renderRange);\n }\n\n protected override createPreElement(\n split: boolean,\n totalLines: number\n ): HASTElement {\n return super.createPreElement(split, totalLines, {\n 'data-has-merge-conflict': '',\n });\n }\n\n protected override getUnifiedLineDecoration({\n type,\n lineType,\n }: UnifiedLineDecorationProps): LineDecoration {\n const mergeConflictType =\n type === 'change'\n ? lineType === 'change-deletion'\n ? 'current'\n : 'incoming'\n : undefined;\n return {\n gutterLineType: type === 'change' ? 'context' : lineType,\n gutterProperties: getMergeConflictGutterProperties(mergeConflictType),\n contentProperties: getMergeConflictContentProperties(\n type,\n mergeConflictType\n ),\n };\n }\n\n protected override getSplitLineDecoration({\n side,\n type,\n }: SplitLineDecorationProps): LineDecoration {\n const mergeConflictType =\n type === 'change'\n ? side === 'deletions'\n ? 'current'\n : 'incoming'\n : undefined;\n return {\n gutterLineType: type === 'change' ? 'context' : type,\n gutterProperties: getMergeConflictGutterProperties(mergeConflictType),\n contentProperties: getMergeConflictContentProperties(\n type,\n mergeConflictType\n ),\n };\n }\n\n protected override getUnifiedInjectedRowsForLine = (\n ctx: RenderedLineContext\n ): UnifiedInjectedRowPlacement | undefined => {\n const rows = this.injectedRows.get(`${ctx.hunkIndex}:${ctx.lineIndex}`);\n if (rows == null || rows.length === 0) {\n return undefined;\n }\n const { mergeConflictActionsType } = this.getOptionsWithDefaults();\n const before: InjectedRow[] = [];\n const after: InjectedRow[] = [];\n for (const row of rows) {\n if (row.type === 'actions') {\n before.push({\n content: createMergeConflictActionsRowElement({\n row,\n includeDefaultActions: mergeConflictActionsType === 'default',\n includeSlot: true,\n }),\n gutter: createMergeConflictGutterGap('action'),\n });\n continue;\n }\n const target = row.type === 'marker-end' ? after : before;\n target.push({\n content: createMergeConflictMarkerRowElement(row),\n gutter: createMergeConflictGutterGap('marker', row.type),\n });\n }\n return {\n before: before.length > 0 ? before : undefined,\n after: after.length > 0 ? after : undefined,\n };\n };\n\n protected override getOptionsWithDefaults(): BaseUnresolvedOptionsWithDefaults {\n const options = super.getOptionsWithDefaults();\n options.diffStyle = 'unified';\n options.lineDiffType = 'none';\n // NOTE(amadeus): Aint nobody got time for a spread\n (options as BaseUnresolvedOptionsWithDefaults).mergeConflictActionsType =\n this.options.mergeConflictActionsType ?? 'default';\n return options as BaseUnresolvedOptionsWithDefaults;\n }\n}\n\nfunction getMergeConflictGutterProperties(\n mergeConflictType: MergeConflictMarkerType | undefined\n): Properties | undefined {\n return mergeConflictType != null\n ? { 'data-merge-conflict': mergeConflictType }\n : undefined;\n}\n\nfunction getMergeConflictContentProperties(\n type: 'change' | 'context' | 'context-expanded',\n mergeConflictType: MergeConflictMarkerType | undefined\n): Properties | undefined {\n if (mergeConflictType == null) {\n return undefined;\n }\n if (type === 'change') {\n if (mergeConflictType === 'current' || mergeConflictType === 'incoming') {\n return {\n 'data-line-type': 'context',\n 'data-merge-conflict': mergeConflictType,\n };\n }\n return undefined;\n }\n if (\n mergeConflictType === 'marker-start' ||\n mergeConflictType === 'marker-base' ||\n mergeConflictType === 'marker-separator' ||\n mergeConflictType === 'marker-end'\n ) {\n return { 'data-merge-conflict': mergeConflictType };\n }\n return undefined;\n}\n\nfunction createMergeConflictGutterGap(\n type: 'action' | 'marker',\n markerType?: MergeConflictMarkerInjectedRow['type']\n): HASTElement {\n const gap = createGutterGap(undefined, 'annotation', 1);\n gap.properties['data-gutter-buffer'] =\n type === 'action'\n ? 'merge-conflict-action'\n : `merge-conflict-${markerType ?? 'marker'}`;\n return gap;\n}\n\ninterface CreateMergeConflictActionsRowElementProps {\n row: MergeConflictActionRowData;\n includeDefaultActions: boolean;\n includeSlot: boolean;\n}\n\nfunction createMergeConflictActionsRowElement({\n row,\n includeDefaultActions,\n includeSlot,\n}: CreateMergeConflictActionsRowElementProps): HASTElement {\n const contentChildren: HASTElement[] = includeDefaultActions\n ? createMergeConflictActionsContent(row.conflictIndex)\n : [];\n if (includeSlot) {\n contentChildren.push(\n createHastElement({\n tagName: 'slot',\n properties: {\n name: getMergeConflictActionSlotName({\n hunkIndex: row.hunkIndex,\n lineIndex: row.lineIndex,\n conflictIndex: row.conflictIndex,\n }),\n 'data-merge-conflict-action-slot': '',\n },\n })\n );\n }\n return createHastElement({\n tagName: 'div',\n properties: {\n 'data-merge-conflict-actions': '',\n },\n children: [\n createHastElement({\n tagName: 'div',\n properties: { 'data-merge-conflict-actions-content': '' },\n children: contentChildren,\n }),\n ],\n });\n}\n\nfunction createMergeConflictMarkerRowElement(\n row: MergeConflictMarkerInjectedRow\n): HASTElement {\n return createHastElement({\n tagName: 'div',\n properties: {\n 'data-merge-conflict': row.type,\n 'data-merge-conflict-marker-row': '',\n },\n children: [\n createTextNodeElement(row.lineText.replace(/(?:\\r\\n|\\n|\\r)$/, '')),\n ],\n });\n}\n\nfunction createMergeConflictActionsContent(\n conflictIndex: number\n): HASTElement[] {\n return [\n createMergeConflictActionButton({\n resolution: 'current',\n label: 'Accept current change',\n conflictIndex,\n }),\n createMergeConflictActionSeparator(),\n createMergeConflictActionButton({\n resolution: 'incoming',\n label: 'Accept incoming change',\n conflictIndex,\n }),\n createMergeConflictActionSeparator(),\n createMergeConflictActionButton({\n resolution: 'both',\n label: 'Accept both',\n conflictIndex,\n }),\n ];\n}\n\ninterface CreateMergeConflictActionButtonProps {\n resolution: MergeConflictResolution;\n label: string;\n conflictIndex: number;\n}\n\nfunction createMergeConflictActionButton({\n resolution,\n label,\n conflictIndex,\n}: CreateMergeConflictActionButtonProps): HASTElement {\n return createHastElement({\n tagName: 'button',\n properties: {\n type: 'button',\n 'data-merge-conflict-action': resolution,\n 'data-merge-conflict-conflict-index': `${conflictIndex}`,\n },\n children: [createTextNodeElement(label)],\n });\n}\n\nfunction createMergeConflictActionSeparator(): HASTElement {\n return createHastElement({\n tagName: 'span',\n properties: { 'data-merge-conflict-action-separator': '' },\n children: [createTextNodeElement('|')],\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"UnresolvedFileHunksRenderer.js","names":[],"sources":["../../src/renderers/UnresolvedFileHunksRenderer.ts"],"sourcesContent":["import type { Element as HASTElement, Properties } from 'hast';\n\nimport { DEFAULT_RENDER_RANGE, DEFAULT_THEMES } from '../constants';\nimport type {\n DiffLineAnnotation,\n FileDiffMetadata,\n MergeConflictMarkerRow,\n MergeConflictResolution,\n RenderRange,\n} from '../types';\nimport { getMergeConflictActionSlotName } from '../utils/getMergeConflictActionSlotName';\nimport {\n createGutterGap,\n createHastElement,\n createTextNodeElement,\n} from '../utils/hast_utils';\nimport {\n getMergeConflictActionAnchor,\n type MergeConflictDiffAction,\n} from '../utils/parseMergeConflictDiffFromFile';\nimport type { WorkerPoolManager } from '../worker';\nimport {\n DiffHunksRenderer,\n type DiffHunksRendererOptions,\n type DiffHunksRendererOptionsWithDefaults,\n type HunksRenderResult,\n type InjectedRow,\n type LineDecoration,\n type RenderedLineContext,\n type SplitLineDecorationProps,\n type UnifiedInjectedRowPlacement,\n type UnifiedLineDecorationProps,\n} from './DiffHunksRenderer';\n\ntype MergeConflictMarkerType =\n | 'marker-start'\n | 'marker-base'\n | 'marker-separator'\n | 'marker-end'\n | 'current'\n | 'incoming';\n\ninterface MergeConflictActionRowData {\n hunkIndex: number;\n lineIndex: number;\n conflictIndex: number;\n}\n\ninterface MergeConflictMarkerInjectedRow extends MergeConflictMarkerRow {\n type: Extract<\n MergeConflictMarkerRow['type'],\n 'marker-start' | 'marker-base' | 'marker-separator' | 'marker-end'\n >;\n lineText: string;\n lineIndex: number;\n}\n\n// NOTE(amadeus): Don't love this, should probably rework into an\n// interface/extender\ntype MergeConflictInjectedRowData =\n | ({ type: 'actions' } & MergeConflictActionRowData)\n | MergeConflictMarkerInjectedRow;\n\ninterface BaseUnresolvedOptionsWithDefaults extends DiffHunksRendererOptionsWithDefaults {\n mergeConflictActionsType: MergeConflictActionsType;\n}\n\ntype MergeConflictActionsType = 'none' | 'default' | 'custom';\n\nexport interface UnresolvedFileHunksRendererOptions extends DiffHunksRendererOptions {\n mergeConflictActionsType?: MergeConflictActionsType;\n}\n\nexport class UnresolvedFileHunksRenderer<\n LAnnotation = undefined,\n> extends DiffHunksRenderer<LAnnotation> {\n private pendingConflictActions: (MergeConflictDiffAction | undefined)[] = [];\n private pendingMarkerRows: MergeConflictMarkerRow[] = [];\n private injectedRows = new Map<string, MergeConflictInjectedRowData[]>();\n public override options: UnresolvedFileHunksRendererOptions;\n\n constructor(\n options: UnresolvedFileHunksRendererOptions = {\n theme: DEFAULT_THEMES,\n },\n annotationSlotName?: (\n annotation: DiffLineAnnotation<LAnnotation>\n ) => string,\n onRenderUpdate?: () => unknown,\n workerManager?: WorkerPoolManager | undefined\n ) {\n super(undefined, annotationSlotName, onRenderUpdate, workerManager);\n this.options = options;\n }\n\n public setConflictState(\n conflictActions: (MergeConflictDiffAction | undefined)[],\n markerRows: MergeConflictMarkerRow[],\n diff: FileDiffMetadata\n ): void {\n this.pendingConflictActions = conflictActions;\n this.pendingMarkerRows = markerRows;\n this.syncInjectedRows(conflictActions, markerRows, diff);\n }\n\n private syncInjectedRows(\n conflictActions: (MergeConflictDiffAction | undefined)[],\n markerRows: MergeConflictMarkerRow[],\n diff: FileDiffMetadata\n ): void {\n this.injectedRows.clear();\n for (const action of conflictActions) {\n const anchor =\n action != null ? getMergeConflictActionAnchor(action, diff) : undefined;\n if (action == null || anchor == null) {\n continue;\n }\n const row: MergeConflictInjectedRowData = {\n type: 'actions',\n hunkIndex: anchor.hunkIndex,\n lineIndex: anchor.lineIndex,\n conflictIndex: action.conflictIndex,\n };\n this.addInjectedRow(row);\n }\n\n for (const row of markerRows) {\n this.addInjectedRow(row);\n }\n }\n\n private addInjectedRow(row: MergeConflictInjectedRowData): void {\n const key = `${row.hunkIndex}:${row.lineIndex}`;\n const rows = this.injectedRows.get(key);\n if (rows == null) {\n this.injectedRows.set(key, [row]);\n } else {\n rows.push(row);\n }\n }\n\n public override renderDiff(\n diff?: FileDiffMetadata | undefined,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): HunksRenderResult | undefined {\n if (diff != null) {\n this.syncInjectedRows(\n this.pendingConflictActions,\n this.pendingMarkerRows,\n this.getDiffForNextRender(diff)\n );\n }\n return super.renderDiff(diff, renderRange);\n }\n\n public override async asyncRender(\n diff: FileDiffMetadata,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): Promise<HunksRenderResult> {\n this.syncInjectedRows(\n this.pendingConflictActions,\n this.pendingMarkerRows,\n diff\n );\n return super.asyncRender(diff, renderRange);\n }\n\n protected override createPreElement(\n split: boolean,\n totalLines: number\n ): HASTElement {\n return super.createPreElement(split, totalLines, {\n 'data-has-merge-conflict': '',\n });\n }\n\n protected override getUnifiedLineDecoration({\n type,\n lineType,\n }: UnifiedLineDecorationProps): LineDecoration {\n const mergeConflictType =\n type === 'change'\n ? lineType === 'change-deletion'\n ? 'current'\n : 'incoming'\n : undefined;\n return {\n gutterLineType: type === 'change' ? 'context' : lineType,\n gutterProperties: getMergeConflictGutterProperties(mergeConflictType),\n contentProperties: getMergeConflictContentProperties(\n type,\n mergeConflictType\n ),\n };\n }\n\n protected override getSplitLineDecoration({\n side,\n type,\n }: SplitLineDecorationProps): LineDecoration {\n const mergeConflictType =\n type === 'change'\n ? side === 'deletions'\n ? 'current'\n : 'incoming'\n : undefined;\n return {\n gutterLineType: type === 'change' ? 'context' : type,\n gutterProperties: getMergeConflictGutterProperties(mergeConflictType),\n contentProperties: getMergeConflictContentProperties(\n type,\n mergeConflictType\n ),\n };\n }\n\n protected override getUnifiedInjectedRowsForLine = (\n ctx: RenderedLineContext\n ): UnifiedInjectedRowPlacement | undefined => {\n const rows = this.injectedRows.get(`${ctx.hunkIndex}:${ctx.lineIndex}`);\n if (rows == null || rows.length === 0) {\n return undefined;\n }\n const { mergeConflictActionsType } = this.getOptionsWithDefaults();\n const before: InjectedRow[] = [];\n const after: InjectedRow[] = [];\n for (const row of rows) {\n if (row.type === 'actions') {\n before.push({\n content: createMergeConflictActionsRowElement({\n row,\n includeDefaultActions: mergeConflictActionsType === 'default',\n includeSlot: true,\n }),\n gutter: createMergeConflictGutterGap('action'),\n });\n continue;\n }\n const target = row.type === 'marker-end' ? after : before;\n target.push({\n content: createMergeConflictMarkerRowElement(row),\n gutter: createMergeConflictGutterGap('marker', row.type),\n });\n }\n return {\n before: before.length > 0 ? before : undefined,\n after: after.length > 0 ? after : undefined,\n };\n };\n\n protected override getOptionsWithDefaults(): BaseUnresolvedOptionsWithDefaults {\n const options = super.getOptionsWithDefaults();\n options.diffStyle = 'unified';\n options.lineDiffType = 'none';\n // NOTE(amadeus): Aint nobody got time for a spread\n (options as BaseUnresolvedOptionsWithDefaults).mergeConflictActionsType =\n this.options.mergeConflictActionsType ?? 'default';\n return options as BaseUnresolvedOptionsWithDefaults;\n }\n}\n\nfunction getMergeConflictGutterProperties(\n mergeConflictType: MergeConflictMarkerType | undefined\n): Properties | undefined {\n return mergeConflictType != null\n ? { 'data-merge-conflict': mergeConflictType }\n : undefined;\n}\n\nfunction getMergeConflictContentProperties(\n type: 'change' | 'context' | 'context-expanded',\n mergeConflictType: MergeConflictMarkerType | undefined\n): Properties | undefined {\n if (mergeConflictType == null) {\n return undefined;\n }\n if (type === 'change') {\n if (mergeConflictType === 'current' || mergeConflictType === 'incoming') {\n return {\n 'data-line-type': 'context',\n 'data-merge-conflict': mergeConflictType,\n };\n }\n return undefined;\n }\n if (\n mergeConflictType === 'marker-start' ||\n mergeConflictType === 'marker-base' ||\n mergeConflictType === 'marker-separator' ||\n mergeConflictType === 'marker-end'\n ) {\n return { 'data-merge-conflict': mergeConflictType };\n }\n return undefined;\n}\n\nfunction createMergeConflictGutterGap(\n type: 'action' | 'marker',\n markerType?: MergeConflictMarkerInjectedRow['type']\n): HASTElement {\n const gap = createGutterGap(undefined, 'annotation', 1);\n gap.properties['data-gutter-buffer'] =\n type === 'action'\n ? 'merge-conflict-action'\n : `merge-conflict-${markerType ?? 'marker'}`;\n return gap;\n}\n\ninterface CreateMergeConflictActionsRowElementProps {\n row: MergeConflictActionRowData;\n includeDefaultActions: boolean;\n includeSlot: boolean;\n}\n\nfunction createMergeConflictActionsRowElement({\n row,\n includeDefaultActions,\n includeSlot,\n}: CreateMergeConflictActionsRowElementProps): HASTElement {\n const contentChildren: HASTElement[] = includeDefaultActions\n ? createMergeConflictActionsContent(row.conflictIndex)\n : [];\n if (includeSlot) {\n contentChildren.push(\n createHastElement({\n tagName: 'slot',\n properties: {\n name: getMergeConflictActionSlotName({\n hunkIndex: row.hunkIndex,\n lineIndex: row.lineIndex,\n conflictIndex: row.conflictIndex,\n }),\n 'data-merge-conflict-action-slot': '',\n },\n })\n );\n }\n return createHastElement({\n tagName: 'div',\n properties: {\n 'data-merge-conflict-actions': '',\n },\n children: [\n createHastElement({\n tagName: 'div',\n properties: { 'data-merge-conflict-actions-content': '' },\n children: contentChildren,\n }),\n ],\n });\n}\n\nfunction createMergeConflictMarkerRowElement(\n row: MergeConflictMarkerInjectedRow\n): HASTElement {\n return createHastElement({\n tagName: 'div',\n properties: {\n 'data-merge-conflict': row.type,\n 'data-merge-conflict-marker-row': '',\n },\n children: [\n createTextNodeElement(row.lineText.replace(/(?:\\r\\n|\\n|\\r)$/, '')),\n ],\n });\n}\n\nfunction createMergeConflictActionsContent(\n conflictIndex: number\n): HASTElement[] {\n return [\n createMergeConflictActionButton({\n resolution: 'current',\n label: 'Accept current change',\n conflictIndex,\n }),\n createMergeConflictActionSeparator(),\n createMergeConflictActionButton({\n resolution: 'incoming',\n label: 'Accept incoming change',\n conflictIndex,\n }),\n createMergeConflictActionSeparator(),\n createMergeConflictActionButton({\n resolution: 'both',\n label: 'Accept both',\n conflictIndex,\n }),\n ];\n}\n\ninterface CreateMergeConflictActionButtonProps {\n resolution: MergeConflictResolution;\n label: string;\n conflictIndex: number;\n}\n\nfunction createMergeConflictActionButton({\n resolution,\n label,\n conflictIndex,\n}: CreateMergeConflictActionButtonProps): HASTElement {\n return createHastElement({\n tagName: 'button',\n properties: {\n type: 'button',\n 'data-merge-conflict-action': resolution,\n 'data-merge-conflict-conflict-index': `${conflictIndex}`,\n },\n children: [createTextNodeElement(label)],\n });\n}\n\nfunction createMergeConflictActionSeparator(): HASTElement {\n return createHastElement({\n tagName: 'span',\n properties: { 'data-merge-conflict-action-separator': '' },\n children: [createTextNodeElement('|')],\n });\n}\n"],"mappings":"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"}