@pierre/diffs 1.1.19 → 1.2.0-beta.0

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 (147) hide show
  1. package/dist/components/CodeView.d.ts +324 -0
  2. package/dist/components/CodeView.d.ts.map +1 -0
  3. package/dist/components/CodeView.js +1245 -0
  4. package/dist/components/CodeView.js.map +1 -0
  5. package/dist/components/File.d.ts +13 -12
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +68 -28
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +9 -10
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +57 -30
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.js +9 -3
  14. package/dist/components/FileStream.js.map +1 -1
  15. package/dist/components/VirtualizedFile.d.ts +28 -5
  16. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  17. package/dist/components/VirtualizedFile.js +225 -45
  18. package/dist/components/VirtualizedFile.js.map +1 -1
  19. package/dist/components/VirtualizedFileDiff.d.ts +28 -5
  20. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  21. package/dist/components/VirtualizedFileDiff.js +285 -49
  22. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  23. package/dist/components/Virtualizer.d.ts +6 -3
  24. package/dist/components/Virtualizer.d.ts.map +1 -1
  25. package/dist/components/Virtualizer.js +4 -6
  26. package/dist/components/Virtualizer.js.map +1 -1
  27. package/dist/components/VirtulizerDevelopment.d.ts +2 -2
  28. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  29. package/dist/constants.d.ts +6 -2
  30. package/dist/constants.d.ts.map +1 -1
  31. package/dist/constants.js +17 -2
  32. package/dist/constants.js.map +1 -1
  33. package/dist/index.d.ts +6 -5
  34. package/dist/index.js +11 -10
  35. package/dist/managers/InteractionManager.d.ts +11 -7
  36. package/dist/managers/InteractionManager.d.ts.map +1 -1
  37. package/dist/managers/InteractionManager.js +38 -25
  38. package/dist/managers/InteractionManager.js.map +1 -1
  39. package/dist/managers/ResizeManager.d.ts +4 -4
  40. package/dist/managers/ResizeManager.d.ts.map +1 -1
  41. package/dist/managers/ResizeManager.js +89 -54
  42. package/dist/managers/ResizeManager.js.map +1 -1
  43. package/dist/managers/UniversalRenderingManager.d.ts +2 -1
  44. package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
  45. package/dist/managers/UniversalRenderingManager.js +13 -16
  46. package/dist/managers/UniversalRenderingManager.js.map +1 -1
  47. package/dist/react/CodeView.d.ts +45 -0
  48. package/dist/react/CodeView.d.ts.map +1 -0
  49. package/dist/react/CodeView.js +241 -0
  50. package/dist/react/CodeView.js.map +1 -0
  51. package/dist/react/File.d.ts +0 -1
  52. package/dist/react/File.d.ts.map +1 -1
  53. package/dist/react/File.js +2 -3
  54. package/dist/react/File.js.map +1 -1
  55. package/dist/react/FileDiff.d.ts +0 -1
  56. package/dist/react/FileDiff.d.ts.map +1 -1
  57. package/dist/react/FileDiff.js +3 -4
  58. package/dist/react/FileDiff.js.map +1 -1
  59. package/dist/react/MultiFileDiff.d.ts +0 -1
  60. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  61. package/dist/react/MultiFileDiff.js +3 -4
  62. package/dist/react/MultiFileDiff.js.map +1 -1
  63. package/dist/react/PatchDiff.d.ts +0 -1
  64. package/dist/react/PatchDiff.d.ts.map +1 -1
  65. package/dist/react/PatchDiff.js +3 -4
  66. package/dist/react/PatchDiff.js.map +1 -1
  67. package/dist/react/UnresolvedFile.d.ts +0 -1
  68. package/dist/react/UnresolvedFile.d.ts.map +1 -1
  69. package/dist/react/UnresolvedFile.js +3 -4
  70. package/dist/react/UnresolvedFile.js.map +1 -1
  71. package/dist/react/index.d.ts +3 -2
  72. package/dist/react/index.js +5 -4
  73. package/dist/react/jsx.d.ts.map +1 -1
  74. package/dist/react/types.d.ts +0 -8
  75. package/dist/react/types.d.ts.map +1 -1
  76. package/dist/react/utils/renderDiffChildren.d.ts +0 -2
  77. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  78. package/dist/react/utils/renderDiffChildren.js +3 -4
  79. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  80. package/dist/react/utils/renderFileChildren.d.ts +0 -2
  81. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  82. package/dist/react/utils/renderFileChildren.js +3 -4
  83. package/dist/react/utils/renderFileChildren.js.map +1 -1
  84. package/dist/react/utils/useFileDiffInstance.js +12 -7
  85. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  86. package/dist/react/utils/useFileInstance.js +12 -7
  87. package/dist/react/utils/useFileInstance.js.map +1 -1
  88. package/dist/react/utils/useUnresolvedFileInstance.js +6 -2
  89. package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
  90. package/dist/renderers/DiffHunksRenderer.d.ts +2 -1
  91. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  92. package/dist/renderers/DiffHunksRenderer.js +35 -20
  93. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  94. package/dist/renderers/FileRenderer.d.ts +2 -1
  95. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  96. package/dist/renderers/FileRenderer.js +34 -20
  97. package/dist/renderers/FileRenderer.js.map +1 -1
  98. package/dist/ssr/index.d.ts +2 -2
  99. package/dist/ssr/preloadDiffs.js +1 -1
  100. package/dist/style.js +1 -1
  101. package/dist/style.js.map +1 -1
  102. package/dist/types.d.ts +98 -3
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/utils/areManagedSnapshotsEqual.d.ts +7 -0
  105. package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -0
  106. package/dist/utils/areManagedSnapshotsEqual.js +15 -0
  107. package/dist/utils/areManagedSnapshotsEqual.js.map +1 -0
  108. package/dist/utils/areOptionsEqual.d.ts +2 -1
  109. package/dist/utils/areOptionsEqual.d.ts.map +1 -1
  110. package/dist/utils/areOptionsEqual.js +1 -1
  111. package/dist/utils/areOptionsEqual.js.map +1 -1
  112. package/dist/utils/createFileHeaderElement.d.ts +3 -1
  113. package/dist/utils/createFileHeaderElement.d.ts.map +1 -1
  114. package/dist/utils/createFileHeaderElement.js +3 -2
  115. package/dist/utils/createFileHeaderElement.js.map +1 -1
  116. package/dist/utils/createWindowFromScrollPosition.d.ts +3 -3
  117. package/dist/utils/createWindowFromScrollPosition.d.ts.map +1 -1
  118. package/dist/utils/createWindowFromScrollPosition.js +6 -6
  119. package/dist/utils/createWindowFromScrollPosition.js.map +1 -1
  120. package/dist/utils/iterateOverDiff.d.ts +2 -1
  121. package/dist/utils/iterateOverDiff.d.ts.map +1 -1
  122. package/dist/utils/iterateOverDiff.js +135 -7
  123. package/dist/utils/iterateOverDiff.js.map +1 -1
  124. package/dist/utils/parsePatchFiles.js +2 -2
  125. package/dist/utils/parsePatchFiles.js.map +1 -1
  126. package/dist/utils/renderFileWithHighlighter.js +1 -1
  127. package/dist/utils/resolveVirtualFileMetrics.d.ts +4 -1
  128. package/dist/utils/resolveVirtualFileMetrics.d.ts.map +1 -1
  129. package/dist/utils/resolveVirtualFileMetrics.js +11 -1
  130. package/dist/utils/resolveVirtualFileMetrics.js.map +1 -1
  131. package/dist/utils/roundToDevicePixel.d.ts +14 -0
  132. package/dist/utils/roundToDevicePixel.d.ts.map +1 -0
  133. package/dist/utils/roundToDevicePixel.js +18 -0
  134. package/dist/utils/roundToDevicePixel.js.map +1 -0
  135. package/dist/worker/worker-portable.js +195 -14
  136. package/dist/worker/worker-portable.js.map +1 -1
  137. package/dist/worker/worker.js +146 -7
  138. package/dist/worker/worker.js.map +1 -1
  139. package/package.json +10 -1
  140. package/dist/components/AdvancedVirtualizedFileDiff.d.ts +0 -40
  141. package/dist/components/AdvancedVirtualizedFileDiff.d.ts.map +0 -1
  142. package/dist/components/AdvancedVirtualizedFileDiff.js +0 -140
  143. package/dist/components/AdvancedVirtualizedFileDiff.js.map +0 -1
  144. package/dist/components/AdvancedVirtualizer.d.ts +0 -38
  145. package/dist/components/AdvancedVirtualizer.d.ts.map +0 -1
  146. package/dist/components/AdvancedVirtualizer.js +0 -201
  147. package/dist/components/AdvancedVirtualizer.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pierre/diffs",
3
- "version": "1.1.19",
3
+ "version": "1.2.0-beta.0",
4
4
  "license": "apache-2.0",
5
5
  "files": [
6
6
  "dist",
@@ -53,6 +53,10 @@
53
53
  "import": "./dist/worker/worker-portable.js"
54
54
  }
55
55
  },
56
+ "publishConfig": {
57
+ "access": "public",
58
+ "tag": "beta"
59
+ },
56
60
  "scripts": {
57
61
  "build": "tsdown --clean",
58
62
  "dev": "echo 'Watching for changes…' && tsdown --watch --log-level error",
@@ -72,10 +76,15 @@
72
76
  "devDependencies": {
73
77
  "@arethetypeswrong/core": "0.18.2",
74
78
  "@types/hast": "3.0.4",
79
+ "@types/jsdom": "28.0.1",
75
80
  "@types/react": "19.2.7",
76
81
  "@types/react-dom": "19.2.3",
77
82
  "autoprefixer": "10.4.22",
83
+ "jsdom": "26.1.0",
84
+ "lightningcss": "1.32.0",
78
85
  "postcss": "8.5.6",
86
+ "postcss-calc": "10.1.1",
87
+ "postcss-nesting": "14.0.0",
79
88
  "react": "19.2.3",
80
89
  "react-dom": "19.2.3",
81
90
  "tsdown": "0.15.11",
@@ -1,40 +0,0 @@
1
- import { FileDiffMetadata, RenderRange, RenderWindow, VirtualFileMetrics } from "../types.js";
2
- import { WorkerPoolManager } from "../worker/WorkerPoolManager.js";
3
- import "../worker/index.js";
4
- import { FileDiff, FileDiffOptions } from "./FileDiff.js";
5
-
6
- //#region src/components/AdvancedVirtualizedFileDiff.d.ts
7
- interface RenderProps {
8
- fileContainer?: HTMLElement;
9
- renderWindow: RenderWindow;
10
- }
11
- interface PositionProps {
12
- unifiedTop: number;
13
- splitTop: number;
14
- fileDiff: FileDiffMetadata;
15
- }
16
- declare class AdvancedVirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnnotation> {
17
- readonly __id: string;
18
- unifiedTop: number;
19
- splitTop: number;
20
- unifiedHeight: number;
21
- splitHeight: number;
22
- private metrics;
23
- fileDiff: FileDiffMetadata;
24
- renderedRange: RenderRange | undefined;
25
- constructor({
26
- unifiedTop,
27
- splitTop,
28
- fileDiff
29
- }: PositionProps, options?: FileDiffOptions<LAnnotation>, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager | undefined);
30
- cleanUp(recycle?: boolean): void;
31
- private computeSize;
32
- virtualizedRender({
33
- renderWindow,
34
- fileContainer
35
- }: RenderProps): void;
36
- private computeRenderRangeFromWindow;
37
- }
38
- //#endregion
39
- export { AdvancedVirtualizedFileDiff, type FileDiffOptions };
40
- //# sourceMappingURL=AdvancedVirtualizedFileDiff.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdvancedVirtualizedFileDiff.d.ts","names":["FileDiffMetadata","RenderRange","RenderWindow","VirtualFileMetrics","WorkerPoolManager","FileDiff","FileDiffOptions","RenderProps","HTMLElement","PositionProps","AdvancedVirtualizedFileDiff","LAnnotation","unifiedTop","splitTop","fileDiff","Partial","renderWindow","fileContainer"],"sources":["../../src/components/AdvancedVirtualizedFileDiff.d.ts"],"sourcesContent":["import type { FileDiffMetadata, RenderRange, RenderWindow, VirtualFileMetrics } from '../types';\nimport type { WorkerPoolManager } from '../worker';\nimport { FileDiff, type FileDiffOptions } from './FileDiff';\nexport type { FileDiffOptions };\ninterface RenderProps {\n fileContainer?: HTMLElement;\n renderWindow: RenderWindow;\n}\ninterface PositionProps {\n unifiedTop: number;\n splitTop: number;\n fileDiff: FileDiffMetadata;\n}\nexport declare class AdvancedVirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnnotation> {\n readonly __id: string;\n unifiedTop: number;\n splitTop: number;\n unifiedHeight: number;\n splitHeight: number;\n private metrics;\n fileDiff: FileDiffMetadata;\n renderedRange: RenderRange | undefined;\n constructor({ unifiedTop, splitTop, fileDiff }: PositionProps, options?: FileDiffOptions<LAnnotation>, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager | undefined);\n cleanUp(recycle?: boolean): void;\n private computeSize;\n virtualizedRender({ renderWindow, fileContainer }: RenderProps): void;\n private computeRenderRangeFromWindow;\n}\n//# sourceMappingURL=AdvancedVirtualizedFileDiff.d.ts.map"],"mappings":";;;;;;UAIUO,WAAAA;kBACUC;EADVD,YAAAA,EAEQL,YADEM;AACU;AAO9B,UALUC,aAAAA,CAKWC;EAAsEC,UAAAA,EAAAA,MAAAA;EAO7EX,QAAAA,EAAAA,MAAAA;EACKC,QAAAA,EAVLD,gBAUKC;;AACWY,cATTH,2BASSG,CAAAA,cAAAA,SAAAA,CAAAA,SAToDR,QASpDQ,CAT6DF,WAS7DE,CAAAA,CAAAA;EAAUC,SAAAA,IAAAA,EAAAA,MAAAA;EAAYL,UAAAA,EAAAA,MAAAA;EAAyCE,QAAAA,EAAAA,MAAAA;EAAhBL,aAAAA,EAAAA,MAAAA;EAAgDH,WAAAA,EAAAA,MAAAA;EAARY,QAAAA,OAAAA;EAA6CX,QAAAA,EAFpJJ,gBAEoJI;EAG1IY,aAAAA,EAJLf,WAIKe,GAAAA,SAAAA;EAAcC,WAAAA,CAAAA;IAAAA,UAAAA;IAAAA,QAAAA;IAAAA;EAAAA,CAAAA,EAHcR,aAGdQ,EAAAA,OAAAA,CAAAA,EAHuCX,eAGvCW,CAHuDN,WAGvDM,CAAAA,EAAAA,OAAAA,CAAAA,EAH+EF,OAG/EE,CAHuFd,kBAGvFc,CAAAA,EAAAA,aAAAA,CAAAA,EAH4Hb,iBAG5Ha,GAAAA,SAAAA;EAAiBV,OAAAA,CAAAA,OAAAA,CAAAA,EAAAA,OAAAA,CAAAA,EAAAA,IAAAA;EAZ2BF,QAAAA,WAAAA;EAAQ,iBAAA,CAAA;IAAA,YAAA;IAAA;EAAA,CAAA,EAYnCE,WAZmC,CAAA,EAAA,IAAA"}
@@ -1,140 +0,0 @@
1
- import { DEFAULT_THEMES, EMPTY_RENDER_RANGE } from "../constants.js";
2
- import { areRenderRangesEqual } from "../utils/areRenderRangesEqual.js";
3
- import { FileDiff } from "./FileDiff.js";
4
- import { resolveVirtualFileMetrics } from "../utils/resolveVirtualFileMetrics.js";
5
-
6
- //#region src/components/AdvancedVirtualizedFileDiff.ts
7
- let instanceId = -1;
8
- var AdvancedVirtualizedFileDiff = class extends FileDiff {
9
- __id = `virtualized-file-diff:${++instanceId}`;
10
- unifiedTop;
11
- splitTop;
12
- unifiedHeight = 0;
13
- splitHeight = 0;
14
- metrics;
15
- fileDiff;
16
- renderedRange;
17
- constructor({ unifiedTop, splitTop, fileDiff }, options = { theme: DEFAULT_THEMES }, metrics, workerManager) {
18
- super(options, workerManager, true);
19
- this.fileDiff = fileDiff;
20
- this.unifiedTop = unifiedTop;
21
- this.splitTop = splitTop;
22
- const { hunkSeparators = "line-info" } = this.options;
23
- this.metrics = resolveVirtualFileMetrics(typeof hunkSeparators === "function" ? "custom" : hunkSeparators, metrics);
24
- this.computeSize();
25
- }
26
- cleanUp(recycle = false) {
27
- super.cleanUp(recycle);
28
- this.renderedRange = void 0;
29
- }
30
- computeSize() {
31
- const { options: { disableFileHeader = false }, fileDiff, metrics: { diffHeaderHeight, fileGap, hunkSeparatorHeight, lineHeight } } = this;
32
- if (!disableFileHeader) {
33
- this.unifiedHeight += diffHeaderHeight;
34
- this.splitHeight += diffHeaderHeight;
35
- } else {
36
- this.unifiedHeight += fileGap;
37
- this.splitHeight += fileGap;
38
- }
39
- for (const hunk of fileDiff.hunks) {
40
- this.unifiedHeight += hunk.unifiedLineCount * lineHeight;
41
- this.splitHeight += hunk.splitLineCount * lineHeight;
42
- }
43
- const hunkCount = fileDiff.hunks.length;
44
- const [firstHunk] = fileDiff.hunks;
45
- if (firstHunk != null) {
46
- let hunkSize = (hunkSeparatorHeight + fileGap * 2) * (hunkCount - 1);
47
- if (firstHunk.additionStart > 1 || firstHunk.deletionStart > 1) hunkSize += hunkSeparatorHeight + fileGap;
48
- this.unifiedHeight += hunkSize;
49
- this.splitHeight += hunkSize;
50
- }
51
- if (hunkCount > 0) {
52
- this.unifiedHeight += fileGap;
53
- this.splitHeight += fileGap;
54
- }
55
- }
56
- virtualizedRender({ renderWindow, fileContainer }) {
57
- const { fileDiff } = this;
58
- const renderRange = this.computeRenderRangeFromWindow(renderWindow);
59
- if (this.fileContainer != null && areRenderRangesEqual(renderRange, this.renderedRange)) return;
60
- this.renderedRange = renderRange;
61
- fileContainer = this.getOrCreateFileContainer(fileContainer);
62
- this.render({
63
- fileDiff,
64
- fileContainer,
65
- renderRange
66
- });
67
- }
68
- computeRenderRangeFromWindow({ top, bottom }) {
69
- const { diffStyle = "split", disableFileHeader = false } = this.options;
70
- const { diffHeaderHeight, fileGap, hunkLineCount, hunkSeparatorHeight, lineHeight } = this.metrics;
71
- const { lineCount, fileTop, fileHeight } = getSpecs(this, diffStyle);
72
- if (fileTop < top - fileHeight || fileTop > bottom) {
73
- console.error("VirtulizedFileDiff.computeRenderRangeFromWindow: invalid render", this.fileDiff.name);
74
- return EMPTY_RENDER_RANGE;
75
- }
76
- if (lineCount <= hunkLineCount) return {
77
- startingLine: 0,
78
- totalLines: Infinity,
79
- bufferBefore: 0,
80
- bufferAfter: 0
81
- };
82
- const headerRegion = disableFileHeader ? fileGap : diffHeaderHeight;
83
- let absoluteLineTop = fileTop + headerRegion;
84
- let currentLine = 0;
85
- const hunkOffsets = [];
86
- let startingLine;
87
- let endingLine = 0;
88
- for (const hunk of this.fileDiff.hunks) {
89
- let hunkGap = 0;
90
- if (hunk.additionStart > 1 || hunk.deletionStart > 1) {
91
- hunkGap = hunkSeparatorHeight + fileGap;
92
- if (hunk !== this.fileDiff.hunks[0]) hunkGap += fileGap;
93
- absoluteLineTop += hunkGap;
94
- }
95
- const hunkLineCount$1 = diffStyle === "split" ? hunk.splitLineCount : hunk.unifiedLineCount;
96
- for (let l = 0; l < hunkLineCount$1; l++) {
97
- if (currentLine % hunkLineCount$1 === 0) hunkOffsets.push(absoluteLineTop - (fileTop + headerRegion + (l === 0 ? hunkGap : 0)));
98
- if (startingLine == null && absoluteLineTop > top - lineHeight && absoluteLineTop < bottom) {
99
- startingLine = currentLine;
100
- endingLine = startingLine + 1;
101
- } else if (startingLine != null && absoluteLineTop < bottom) endingLine++;
102
- currentLine++;
103
- absoluteLineTop += lineHeight;
104
- }
105
- }
106
- if (startingLine == null) return {
107
- startingLine: 0,
108
- totalLines: 0,
109
- bufferBefore: fileHeight - headerRegion,
110
- bufferAfter: 0
111
- };
112
- startingLine = Math.floor(startingLine / hunkLineCount) * hunkLineCount;
113
- const totalLines = Math.ceil((endingLine - startingLine) / hunkLineCount) * hunkLineCount;
114
- const finalHunkBufferOffset = (startingLine + totalLines) / hunkLineCount;
115
- const bufferBefore = hunkOffsets[startingLine / hunkLineCount] ?? 0;
116
- const bufferAfter = finalHunkBufferOffset < hunkOffsets.length ? fileHeight - headerRegion - hunkOffsets[finalHunkBufferOffset] - fileGap : 0;
117
- return {
118
- startingLine,
119
- totalLines,
120
- bufferBefore,
121
- bufferAfter
122
- };
123
- }
124
- };
125
- function getSpecs(instance, type = "split") {
126
- if (type === "split") return {
127
- lineCount: instance.fileDiff.splitLineCount,
128
- fileTop: instance.splitTop,
129
- fileHeight: instance.splitHeight
130
- };
131
- return {
132
- lineCount: instance.fileDiff.unifiedLineCount,
133
- fileTop: instance.unifiedTop,
134
- fileHeight: instance.unifiedHeight
135
- };
136
- }
137
-
138
- //#endregion
139
- export { AdvancedVirtualizedFileDiff };
140
- //# sourceMappingURL=AdvancedVirtualizedFileDiff.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdvancedVirtualizedFileDiff.js","names":["hunkOffsets: number[]","startingLine: number | undefined","hunkLineCount"],"sources":["../../src/components/AdvancedVirtualizedFileDiff.ts"],"sourcesContent":["import { DEFAULT_THEMES, EMPTY_RENDER_RANGE } from '../constants';\nimport type {\n FileDiffMetadata,\n RenderRange,\n RenderWindow,\n VirtualFileMetrics,\n} from '../types';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { resolveVirtualFileMetrics } from '../utils/resolveVirtualFileMetrics';\nimport type { WorkerPoolManager } from '../worker';\nimport { FileDiff, type FileDiffOptions } from './FileDiff';\n\nexport type { FileDiffOptions };\n\ninterface RenderProps {\n fileContainer?: HTMLElement;\n renderWindow: RenderWindow;\n}\n\ninterface PositionProps {\n unifiedTop: number;\n splitTop: number;\n fileDiff: FileDiffMetadata;\n}\n\nlet instanceId = -1;\n\nexport class AdvancedVirtualizedFileDiff<\n LAnnotation = undefined,\n> extends FileDiff<LAnnotation> {\n override readonly __id: string = `virtualized-file-diff:${++instanceId}`;\n\n public unifiedTop: number;\n public splitTop: number;\n public unifiedHeight: number = 0;\n public splitHeight: number = 0;\n private metrics: VirtualFileMetrics;\n\n override fileDiff: FileDiffMetadata;\n public renderedRange: RenderRange | undefined;\n\n constructor(\n { unifiedTop, splitTop, fileDiff }: PositionProps,\n options: FileDiffOptions<LAnnotation> = { theme: DEFAULT_THEMES },\n metrics?: Partial<VirtualFileMetrics>,\n workerManager?: WorkerPoolManager | undefined\n ) {\n super(options, workerManager, true);\n this.fileDiff = fileDiff;\n this.unifiedTop = unifiedTop;\n this.splitTop = splitTop;\n const { hunkSeparators = 'line-info' } = this.options;\n this.metrics = resolveVirtualFileMetrics(\n typeof hunkSeparators === 'function' ? 'custom' : hunkSeparators,\n metrics\n );\n this.computeSize();\n }\n\n override cleanUp(recycle = false): void {\n super.cleanUp(recycle);\n this.renderedRange = undefined;\n }\n\n private computeSize() {\n const {\n options: { disableFileHeader = false },\n fileDiff,\n metrics: { diffHeaderHeight, fileGap, hunkSeparatorHeight, lineHeight },\n } = this;\n\n // Add header height\n if (!disableFileHeader) {\n this.unifiedHeight += diffHeaderHeight;\n this.splitHeight += diffHeaderHeight;\n } else {\n this.unifiedHeight += fileGap;\n this.splitHeight += fileGap;\n }\n\n // NOTE(amadeus): I wonder if it's worth shortcutting this? It might help\n // to measure these values though and see if it's at all an issue on the\n // big bois\n for (const hunk of fileDiff.hunks) {\n this.unifiedHeight += hunk.unifiedLineCount * lineHeight;\n this.splitHeight += hunk.splitLineCount * lineHeight;\n }\n\n // Add hunk separators height\n const hunkCount = fileDiff.hunks.length;\n const [firstHunk] = fileDiff.hunks;\n if (firstHunk != null) {\n let hunkSize = (hunkSeparatorHeight + fileGap * 2) * (hunkCount - 1);\n if (firstHunk.additionStart > 1 || firstHunk.deletionStart > 1) {\n hunkSize += hunkSeparatorHeight + fileGap;\n }\n this.unifiedHeight += hunkSize;\n this.splitHeight += hunkSize;\n }\n\n // If there are hunks of code, then we gotta render some bottom padding\n if (hunkCount > 0) {\n this.unifiedHeight += fileGap;\n this.splitHeight += fileGap;\n }\n }\n\n virtualizedRender({ renderWindow, fileContainer }: RenderProps): void {\n const { fileDiff } = this;\n const renderRange = this.computeRenderRangeFromWindow(renderWindow);\n if (\n this.fileContainer != null &&\n areRenderRangesEqual(renderRange, this.renderedRange)\n ) {\n return;\n }\n this.renderedRange = renderRange;\n fileContainer = this.getOrCreateFileContainer(fileContainer);\n this.render({ fileDiff, fileContainer, renderRange });\n }\n\n private computeRenderRangeFromWindow({\n top,\n bottom,\n }: RenderWindow): RenderRange {\n const { diffStyle = 'split', disableFileHeader = false } = this.options;\n const {\n diffHeaderHeight,\n fileGap,\n hunkLineCount,\n hunkSeparatorHeight,\n lineHeight,\n } = this.metrics;\n const { lineCount, fileTop, fileHeight } = getSpecs(this, diffStyle);\n\n // We should never hit this theoretically, but if so, gtfo and yell loudly,\n // so we can fix\n if (fileTop < top - fileHeight || fileTop > bottom) {\n console.error(\n 'VirtulizedFileDiff.computeRenderRangeFromWindow: invalid render',\n this.fileDiff.name\n );\n return EMPTY_RENDER_RANGE;\n }\n\n // Whole file is under HUNK_LINE_COUNT, just render it all\n if (lineCount <= hunkLineCount) {\n return {\n startingLine: 0,\n totalLines: Infinity,\n bufferBefore: 0,\n bufferAfter: 0,\n };\n }\n\n const headerRegion = disableFileHeader ? fileGap : diffHeaderHeight;\n let absoluteLineTop = fileTop + headerRegion;\n let currentLine = 0;\n const hunkOffsets: number[] = [];\n let startingLine: number | undefined;\n let endingLine = 0;\n for (const hunk of this.fileDiff.hunks) {\n let hunkGap = 0;\n if (hunk.additionStart > 1 || hunk.deletionStart > 1) {\n hunkGap = hunkSeparatorHeight + fileGap;\n if (hunk !== this.fileDiff.hunks[0]) {\n hunkGap += fileGap;\n }\n absoluteLineTop += hunkGap;\n }\n const hunkLineCount =\n diffStyle === 'split' ? hunk.splitLineCount : hunk.unifiedLineCount;\n for (let l = 0; l < hunkLineCount; l++) {\n if (currentLine % hunkLineCount === 0) {\n hunkOffsets.push(\n absoluteLineTop - (fileTop + headerRegion + (l === 0 ? hunkGap : 0))\n );\n }\n if (\n startingLine == null &&\n absoluteLineTop > top - lineHeight &&\n absoluteLineTop < bottom\n ) {\n startingLine = currentLine;\n endingLine = startingLine + 1;\n } else if (startingLine != null && absoluteLineTop < bottom) {\n endingLine++;\n }\n currentLine++;\n absoluteLineTop += lineHeight;\n }\n }\n\n if (startingLine == null) {\n return {\n startingLine: 0,\n totalLines: 0,\n bufferBefore: fileHeight - headerRegion,\n bufferAfter: 0,\n };\n }\n\n startingLine = Math.floor(startingLine / hunkLineCount) * hunkLineCount;\n const totalLines =\n Math.ceil((endingLine - startingLine) / hunkLineCount) * hunkLineCount;\n\n const finalHunkBufferOffset = (startingLine + totalLines) / hunkLineCount;\n const bufferBefore = hunkOffsets[startingLine / hunkLineCount] ?? 0;\n const bufferAfter =\n finalHunkBufferOffset < hunkOffsets.length\n ? fileHeight -\n headerRegion -\n hunkOffsets[finalHunkBufferOffset] -\n fileGap // this is to account for bottom padding of the code container\n : 0;\n return { startingLine, totalLines, bufferBefore, bufferAfter };\n }\n}\n\nfunction getSpecs<LAnnotation>(\n instance: AdvancedVirtualizedFileDiff<LAnnotation>,\n type: 'split' | 'unified' = 'split'\n) {\n if (type === 'split') {\n return {\n lineCount: instance.fileDiff.splitLineCount,\n fileTop: instance.splitTop,\n fileHeight: instance.splitHeight,\n };\n }\n return {\n lineCount: instance.fileDiff.unifiedLineCount,\n fileTop: instance.unifiedTop,\n fileHeight: instance.unifiedHeight,\n };\n}\n"],"mappings":"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"}
@@ -1,38 +0,0 @@
1
- import { ParsedPatch, VirtualFileMetrics } from "../types.js";
2
- import { WorkerPoolManager } from "../worker/WorkerPoolManager.js";
3
- import "../worker/index.js";
4
- import { FileDiffOptions } from "./FileDiff.js";
5
-
6
- //#region src/components/AdvancedVirtualizer.d.ts
7
- declare class AdvancedVirtualizer<LAnnotations = undefined> {
8
- private container;
9
- private fileOptions;
10
- private metrics;
11
- private workerManager?;
12
- static __STOP: boolean;
13
- static __lastScrollPosition: number;
14
- type: string;
15
- private files;
16
- private totalHeightUnified;
17
- private totalHeightSplit;
18
- private rendered;
19
- private containerOffset;
20
- private scrollTop;
21
- private lastRenderedScrollY;
22
- private height;
23
- private scrollHeight;
24
- private initialized;
25
- private stickyContainer;
26
- private stickyOffset;
27
- constructor(container: HTMLElement, fileOptions?: FileDiffOptions<LAnnotations>, metrics?: VirtualFileMetrics, workerManager?: WorkerPoolManager | undefined);
28
- reset(): void;
29
- addFiles(parsedPatches: ParsedPatch[]): void;
30
- render(): void;
31
- _render: () => void;
32
- private setupContainer;
33
- handleScroll: () => void;
34
- handleResize: () => void;
35
- }
36
- //#endregion
37
- export { AdvancedVirtualizer };
38
- //# sourceMappingURL=AdvancedVirtualizer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdvancedVirtualizer.d.ts","names":["VirtualFileMetrics","ParsedPatch","WorkerPoolManager","FileDiffOptions","AdvancedVirtualizer","LAnnotations","HTMLElement"],"sources":["../../src/components/AdvancedVirtualizer.d.ts"],"sourcesContent":["import type { VirtualFileMetrics } from '../types';\nimport type { ParsedPatch } from '../types';\nimport type { WorkerPoolManager } from '../worker';\nimport type { FileDiffOptions } from './FileDiff';\nexport declare class AdvancedVirtualizer<LAnnotations = undefined> {\n private container;\n private fileOptions;\n private metrics;\n private workerManager?;\n static __STOP: boolean;\n static __lastScrollPosition: number;\n type: string;\n private files;\n private totalHeightUnified;\n private totalHeightSplit;\n private rendered;\n private containerOffset;\n private scrollTop;\n private lastRenderedScrollY;\n private height;\n private scrollHeight;\n private initialized;\n private stickyContainer;\n private stickyOffset;\n constructor(container: HTMLElement, fileOptions?: FileDiffOptions<LAnnotations>, metrics?: VirtualFileMetrics, workerManager?: WorkerPoolManager | undefined);\n reset(): void;\n addFiles(parsedPatches: ParsedPatch[]): void;\n render(): void;\n _render: () => void;\n private setupContainer;\n handleScroll: () => void;\n handleResize: () => void;\n}\n//# sourceMappingURL=AdvancedVirtualizer.d.ts.map"],"mappings":";;;;;;cAIqBI;;EAAAA,QAAAA,WAAAA;EAoBME,QAAAA,OAAAA;EAA2CD,QAAAA,aAAAA;EAAhBF,OAAAA,MAAAA,EAAAA,OAAAA;EAAyCH,OAAAA,oBAAAA,EAAAA,MAAAA;EAAoCE,IAAAA,EAAAA,MAAAA;EAEvGD,QAAAA,KAAAA;EAAW,QAAA,kBAAA;;;;;;;;;;;yBAFZK,2BAA2BH,gBAAgBE,yBAAyBL,oCAAoCE;;0BAEvGD"}
@@ -1,201 +0,0 @@
1
- import { DEFAULT_THEMES, DEFAULT_VIRTUAL_FILE_METRICS, DIFFS_TAG_NAME } from "../constants.js";
2
- import { queueRender } from "../managers/UniversalRenderingManager.js";
3
- import { createWindowFromScrollPosition } from "../utils/createWindowFromScrollPosition.js";
4
- import { AdvancedVirtualizedFileDiff } from "./AdvancedVirtualizedFileDiff.js";
5
-
6
- //#region src/components/AdvancedVirtualizer.ts
7
- const OVERSCROLL_SIZE = 500;
8
- var AdvancedVirtualizer = class AdvancedVirtualizer {
9
- static __STOP = false;
10
- static __lastScrollPosition = 0;
11
- type = "advanced";
12
- files = [];
13
- totalHeightUnified = 0;
14
- totalHeightSplit = 0;
15
- rendered = /* @__PURE__ */ new Map();
16
- containerOffset = 0;
17
- scrollTop = 0;
18
- lastRenderedScrollY = -1;
19
- height = 0;
20
- scrollHeight = 0;
21
- initialized = false;
22
- stickyContainer;
23
- stickyOffset;
24
- constructor(container, fileOptions = {
25
- theme: DEFAULT_THEMES,
26
- enableLineSelection: true,
27
- disableVirtualizationBuffers: true,
28
- diffStyle: "split"
29
- }, metrics = DEFAULT_VIRTUAL_FILE_METRICS, workerManager) {
30
- this.container = container;
31
- this.fileOptions = fileOptions;
32
- this.metrics = metrics;
33
- this.workerManager = workerManager;
34
- this.stickyOffset = document.createElement("div");
35
- this.stickyOffset.style.contain = "layout size";
36
- this.stickyContainer = document.createElement("div");
37
- this.stickyContainer.style.contain = "strict";
38
- this.stickyContainer.style.position = "sticky";
39
- this.stickyContainer.style.width = "100%";
40
- this.stickyContainer.style.contain = "strict";
41
- this.stickyContainer.style.isolation = "isolate";
42
- this.container.appendChild(this.stickyOffset);
43
- this.container.appendChild(this.stickyContainer);
44
- this.handleScroll();
45
- this.handleResize();
46
- this.containerOffset = this.container.getBoundingClientRect().top + this.scrollTop;
47
- window.__INSTANCE = this;
48
- window.__TOGGLE = () => {
49
- if (AdvancedVirtualizer.__STOP) {
50
- AdvancedVirtualizer.__STOP = false;
51
- window.scrollTo({ top: AdvancedVirtualizer.__lastScrollPosition });
52
- queueRender(this._render);
53
- } else {
54
- AdvancedVirtualizer.__lastScrollPosition = window.scrollY;
55
- AdvancedVirtualizer.__STOP = true;
56
- }
57
- };
58
- }
59
- reset() {
60
- this.files.length = 0;
61
- this.totalHeightSplit = 0;
62
- this.totalHeightUnified = 0;
63
- for (const [, item] of Array.from(this.rendered)) cleanupRenderedItem(item);
64
- this.rendered.clear();
65
- this.stickyContainer.innerHTML = "";
66
- this.stickyOffset.style.height = "";
67
- this.initialized = false;
68
- this.container.style.height = "";
69
- this.scrollHeight = 0;
70
- window.removeEventListener("scroll", this.handleScroll);
71
- window.removeEventListener("resize", this.handleResize);
72
- }
73
- addFiles(parsedPatches) {
74
- for (const patch of parsedPatches) for (const fileDiff of patch.files) {
75
- const vFileDiff = new AdvancedVirtualizedFileDiff({
76
- unifiedTop: this.totalHeightUnified,
77
- splitTop: this.totalHeightSplit,
78
- fileDiff
79
- }, this.fileOptions, this.metrics, this.workerManager);
80
- vFileDiff.cleanUp(true);
81
- this.files.push(vFileDiff);
82
- this.totalHeightUnified += vFileDiff.unifiedHeight + this.metrics.fileGap;
83
- this.totalHeightSplit += vFileDiff.splitHeight + this.metrics.fileGap;
84
- }
85
- }
86
- render() {
87
- this.setupContainer();
88
- queueRender(this._render);
89
- }
90
- _render = () => {
91
- if (this.files.length === 0 || AdvancedVirtualizer.__STOP) return;
92
- const { diffStyle = "split" } = this.fileOptions;
93
- const { scrollTop, height, scrollHeight, containerOffset } = this;
94
- const fitPerfectly = this.lastRenderedScrollY === -1 || Math.abs(scrollTop - this.lastRenderedScrollY) > height + OVERSCROLL_SIZE * 2;
95
- const { top, bottom } = createWindowFromScrollPosition({
96
- scrollTop,
97
- height,
98
- scrollHeight,
99
- containerOffset,
100
- fitPerfectly,
101
- overscrollSize: OVERSCROLL_SIZE
102
- });
103
- this.lastRenderedScrollY = scrollTop;
104
- for (const [renderedInstance, item] of Array.from(this.rendered)) if (!(getInstanceSpecs(renderedInstance, diffStyle).top > top - getInstanceSpecs(renderedInstance, diffStyle).height && getInstanceSpecs(renderedInstance, diffStyle).top <= bottom)) {
105
- cleanupRenderedItem(item);
106
- this.rendered.delete(renderedInstance);
107
- }
108
- let prevElement;
109
- let firstInstance;
110
- let lastInstance;
111
- for (const instance of this.files) {
112
- if (getInstanceSpecs(instance, diffStyle).top > bottom) break;
113
- if (getInstanceSpecs(instance, diffStyle).top < top - getInstanceSpecs(instance, diffStyle).height) continue;
114
- const rendered = this.rendered.get(instance);
115
- if (rendered == null) {
116
- const fileContainer = document.createElement(DIFFS_TAG_NAME);
117
- if (prevElement == null) this.stickyContainer.prepend(fileContainer);
118
- else if (prevElement.nextSibling !== fileContainer) prevElement.after(fileContainer);
119
- instance.virtualizedSetup();
120
- this.rendered.set(instance, {
121
- element: fileContainer,
122
- instance
123
- });
124
- instance.virtualizedRender({
125
- fileContainer,
126
- renderWindow: {
127
- top,
128
- bottom
129
- }
130
- });
131
- prevElement = fileContainer;
132
- } else {
133
- prevElement = rendered.element;
134
- rendered.instance.virtualizedRender({ renderWindow: {
135
- top,
136
- bottom
137
- } });
138
- }
139
- firstInstance ??= instance;
140
- lastInstance = instance;
141
- }
142
- if (firstInstance?.renderedRange != null && lastInstance?.renderedRange != null) {
143
- const firstSpecs = getInstanceSpecs(firstInstance, diffStyle);
144
- const lastSpecs = getInstanceSpecs(lastInstance, diffStyle);
145
- const stickyTop = Math.max(Math.min(firstSpecs.top + firstInstance.renderedRange.bufferBefore), 0);
146
- const lastBuffer = lastInstance.renderedRange.totalLines === 0 ? lastInstance.renderedRange.bufferBefore : lastInstance.renderedRange.bufferAfter;
147
- const totalHeight = Math.max(0, lastSpecs.top + lastSpecs.height - lastBuffer) - stickyTop;
148
- this.stickyOffset.style.height = `${stickyTop}px`;
149
- this.stickyContainer.style.top = `${-totalHeight + height + this.metrics.fileGap}px`;
150
- this.stickyContainer.style.bottom = `${-totalHeight + height}px`;
151
- this.stickyContainer.style.height = `${totalHeight}px`;
152
- }
153
- if (fitPerfectly) queueRender(this._render);
154
- };
155
- setupContainer() {
156
- const { diffStyle = "split" } = this.fileOptions;
157
- this.container.style.height = `${diffStyle === "split" ? this.totalHeightSplit : this.totalHeightUnified}px`;
158
- this.scrollHeight = document.documentElement.scrollHeight;
159
- if (!this.initialized) {
160
- window.addEventListener("scroll", this.handleScroll, { passive: true });
161
- window.addEventListener("resize", this.handleResize);
162
- this.initialized = true;
163
- }
164
- }
165
- handleScroll = () => {
166
- let { scrollY: scrollTop } = window;
167
- scrollTop = Math.max(scrollTop, 0);
168
- if (this.scrollTop === scrollTop) return;
169
- this.scrollTop = scrollTop;
170
- if (this.files.length === 0) return;
171
- queueRender(this._render);
172
- };
173
- handleResize = () => {
174
- const { innerHeight: height } = window;
175
- const { scrollHeight } = document.documentElement;
176
- if (this.height === height && this.scrollHeight === scrollHeight) return;
177
- this.height = height;
178
- this.scrollHeight = scrollHeight;
179
- if (this.files.length > 0) queueRender(this._render);
180
- };
181
- };
182
- function cleanupRenderedItem(item) {
183
- item.instance.cleanUp(true);
184
- item.element.remove();
185
- item.element.innerHTML = "";
186
- if (item.element.shadowRoot != null) item.element.shadowRoot.innerHTML = "";
187
- }
188
- function getInstanceSpecs(instance, diffStyle = "split") {
189
- if (diffStyle === "split") return {
190
- top: instance.splitTop,
191
- height: instance.splitHeight
192
- };
193
- return {
194
- top: instance.unifiedTop,
195
- height: instance.unifiedHeight
196
- };
197
- }
198
-
199
- //#endregion
200
- export { AdvancedVirtualizer };
201
- //# sourceMappingURL=AdvancedVirtualizer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdvancedVirtualizer.js","names":["container: HTMLElement","fileOptions: FileDiffOptions<LAnnotations>","metrics: VirtualFileMetrics","workerManager?: WorkerPoolManager | undefined","prevElement: HTMLElement | undefined","firstInstance: AdvancedVirtualizedFileDiff<LAnnotations> | undefined","lastInstance: AdvancedVirtualizedFileDiff<LAnnotations> | undefined"],"sources":["../../src/components/AdvancedVirtualizer.ts"],"sourcesContent":["import {\n DEFAULT_THEMES,\n DEFAULT_VIRTUAL_FILE_METRICS,\n DIFFS_TAG_NAME,\n} from '../constants';\nimport { queueRender } from '../managers/UniversalRenderingManager';\nimport type { VirtualFileMetrics } from '../types';\nimport type { ParsedPatch } from '../types';\nimport { createWindowFromScrollPosition } from '../utils/createWindowFromScrollPosition';\nimport type { WorkerPoolManager } from '../worker';\nimport { AdvancedVirtualizedFileDiff } from './AdvancedVirtualizedFileDiff';\nimport type { FileDiffOptions } from './FileDiff';\n\nconst ENABLE_RENDERING = true;\nconst OVERSCROLL_SIZE = 500;\n\ninterface RenderedItems<LAnnotations> {\n instance: AdvancedVirtualizedFileDiff<LAnnotations>;\n element: HTMLElement;\n}\n\nexport class AdvancedVirtualizer<LAnnotations = undefined> {\n static __STOP = false;\n static __lastScrollPosition = 0;\n\n public type = 'advanced';\n private files: AdvancedVirtualizedFileDiff<LAnnotations>[] = [];\n private totalHeightUnified = 0;\n private totalHeightSplit = 0;\n private rendered: Map<\n AdvancedVirtualizedFileDiff<LAnnotations>,\n RenderedItems<LAnnotations>\n > = new Map();\n\n private containerOffset = 0;\n private scrollTop: number = 0;\n private lastRenderedScrollY = -1;\n private height: number = 0;\n private scrollHeight: number = 0;\n private initialized = false;\n\n private stickyContainer: HTMLElement;\n private stickyOffset: HTMLElement;\n\n constructor(\n private container: HTMLElement,\n private fileOptions: FileDiffOptions<LAnnotations> = {\n theme: DEFAULT_THEMES,\n // FIXME(amadeus): Fix selected lines crashing when scroll out of the window\n enableLineSelection: true,\n disableVirtualizationBuffers: true,\n diffStyle: 'split',\n },\n private metrics: VirtualFileMetrics = DEFAULT_VIRTUAL_FILE_METRICS,\n private workerManager?: WorkerPoolManager | undefined\n ) {\n this.stickyOffset = document.createElement('div');\n this.stickyOffset.style.contain = 'layout size';\n this.stickyContainer = document.createElement('div');\n this.stickyContainer.style.contain = 'strict';\n this.stickyContainer.style.position = 'sticky';\n this.stickyContainer.style.width = '100%';\n this.stickyContainer.style.contain = 'strict';\n this.stickyContainer.style.isolation = 'isolate';\n this.container.appendChild(this.stickyOffset);\n this.container.appendChild(this.stickyContainer);\n this.handleScroll();\n this.handleResize();\n this.containerOffset =\n this.container.getBoundingClientRect().top + this.scrollTop;\n\n // FIXME(amadeus): Remove me before release\n window.__INSTANCE = this;\n window.__TOGGLE = () => {\n if (AdvancedVirtualizer.__STOP) {\n AdvancedVirtualizer.__STOP = false;\n window.scrollTo({ top: AdvancedVirtualizer.__lastScrollPosition });\n queueRender(this._render);\n } else {\n AdvancedVirtualizer.__lastScrollPosition = window.scrollY;\n AdvancedVirtualizer.__STOP = true;\n }\n };\n }\n\n reset(): void {\n this.files.length = 0;\n this.totalHeightSplit = 0;\n this.totalHeightUnified = 0;\n for (const [, item] of Array.from(this.rendered)) {\n cleanupRenderedItem(item);\n }\n this.rendered.clear();\n this.stickyContainer.innerHTML = '';\n this.stickyOffset.style.height = '';\n this.initialized = false;\n this.container.style.height = '';\n this.scrollHeight = 0;\n window.removeEventListener('scroll', this.handleScroll);\n window.removeEventListener('resize', this.handleResize);\n }\n\n addFiles(parsedPatches: ParsedPatch[]): void {\n for (const patch of parsedPatches) {\n for (const fileDiff of patch.files) {\n const vFileDiff = new AdvancedVirtualizedFileDiff<LAnnotations>(\n {\n unifiedTop: this.totalHeightUnified,\n splitTop: this.totalHeightSplit,\n fileDiff,\n },\n this.fileOptions,\n this.metrics,\n this.workerManager\n );\n\n // NOTE(amadeus): I hate this, lol... probably should figure out a way\n // to not immediately subscribe\n vFileDiff.cleanUp(true);\n this.files.push(vFileDiff);\n this.totalHeightUnified +=\n vFileDiff.unifiedHeight + this.metrics.fileGap;\n this.totalHeightSplit += vFileDiff.splitHeight + this.metrics.fileGap;\n }\n }\n }\n\n render(): void {\n this.setupContainer();\n if (!ENABLE_RENDERING) return;\n queueRender(this._render);\n }\n\n _render = (): void => {\n if (this.files.length === 0 || AdvancedVirtualizer.__STOP) {\n return;\n }\n const { diffStyle = 'split' } = this.fileOptions;\n const { scrollTop, height, scrollHeight, containerOffset } = this;\n const fitPerfectly =\n this.lastRenderedScrollY === -1 ||\n Math.abs(scrollTop - this.lastRenderedScrollY) >\n height + OVERSCROLL_SIZE * 2;\n const { top, bottom } = createWindowFromScrollPosition({\n scrollTop,\n height,\n scrollHeight,\n containerOffset,\n fitPerfectly,\n overscrollSize: OVERSCROLL_SIZE,\n });\n this.lastRenderedScrollY = scrollTop;\n for (const [renderedInstance, item] of Array.from(this.rendered)) {\n // If not visible, we should unmount it\n if (\n !(\n getInstanceSpecs(renderedInstance, diffStyle).top >\n top - getInstanceSpecs(renderedInstance, diffStyle).height &&\n getInstanceSpecs(renderedInstance, diffStyle).top <= bottom\n )\n ) {\n cleanupRenderedItem(item);\n this.rendered.delete(renderedInstance);\n }\n }\n let prevElement: HTMLElement | undefined;\n let firstInstance: AdvancedVirtualizedFileDiff<LAnnotations> | undefined;\n let lastInstance: AdvancedVirtualizedFileDiff<LAnnotations> | undefined;\n for (const instance of this.files) {\n // We can stop iterating when we get to elements after the window\n if (getInstanceSpecs(instance, diffStyle).top > bottom) {\n break;\n }\n if (\n getInstanceSpecs(instance, diffStyle).top <\n top - getInstanceSpecs(instance, diffStyle).height\n ) {\n continue;\n }\n const rendered = this.rendered.get(instance);\n if (rendered == null) {\n const fileContainer = document.createElement(DIFFS_TAG_NAME);\n // NOTE(amadeus): We gotta append first to ensure file ordering is\n // correct... but i guess maybe doesn't matter because we are positioning shit\n if (prevElement == null) {\n this.stickyContainer.prepend(fileContainer);\n } else if (prevElement.nextSibling !== fileContainer) {\n prevElement.after(fileContainer);\n }\n instance.virtualizedSetup();\n\n this.rendered.set(instance, {\n element: fileContainer,\n instance: instance,\n });\n instance.virtualizedRender({\n fileContainer,\n renderWindow: { top, bottom },\n });\n prevElement = fileContainer;\n } else {\n prevElement = rendered.element;\n rendered.instance.virtualizedRender({\n renderWindow: { top, bottom },\n });\n }\n firstInstance ??= instance;\n lastInstance = instance;\n }\n\n if (\n firstInstance?.renderedRange != null &&\n lastInstance?.renderedRange != null\n ) {\n const firstSpecs = getInstanceSpecs(firstInstance, diffStyle);\n const lastSpecs = getInstanceSpecs(lastInstance, diffStyle);\n const stickyTop = Math.max(\n Math.min(firstSpecs.top + firstInstance.renderedRange.bufferBefore),\n 0\n );\n const lastBuffer =\n lastInstance.renderedRange.totalLines === 0\n ? lastInstance.renderedRange.bufferBefore\n : lastInstance.renderedRange.bufferAfter;\n const stickyBottom = Math.max(\n 0,\n lastSpecs.top + lastSpecs.height - lastBuffer\n );\n const totalHeight = stickyBottom - stickyTop;\n this.stickyOffset.style.height = `${stickyTop}px`;\n this.stickyContainer.style.top = `${-totalHeight + height + this.metrics.fileGap}px`;\n this.stickyContainer.style.bottom = `${-totalHeight + height}px`;\n this.stickyContainer.style.height = `${totalHeight}px`;\n }\n\n if (fitPerfectly) {\n queueRender(this._render);\n }\n };\n\n private setupContainer() {\n const { diffStyle = 'split' } = this.fileOptions;\n this.container.style.height = `${diffStyle === 'split' ? this.totalHeightSplit : this.totalHeightUnified}px`;\n this.scrollHeight = document.documentElement.scrollHeight;\n if (!this.initialized) {\n window.addEventListener('scroll', this.handleScroll, { passive: true });\n window.addEventListener('resize', this.handleResize);\n this.initialized = true;\n }\n }\n\n handleScroll = (): void => {\n let { scrollY: scrollTop } = window;\n scrollTop = Math.max(scrollTop, 0);\n if (this.scrollTop === scrollTop) return;\n this.scrollTop = scrollTop;\n if (this.files.length === 0) return;\n queueRender(this._render);\n };\n\n handleResize = (): void => {\n const { innerHeight: height } = window;\n const { scrollHeight } = document.documentElement;\n if (this.height === height && this.scrollHeight === scrollHeight) {\n return;\n }\n this.height = height;\n this.scrollHeight = scrollHeight;\n if (this.files.length > 0) {\n queueRender(this._render);\n }\n };\n}\n\nfunction cleanupRenderedItem<LAnnotations>(item: RenderedItems<LAnnotations>) {\n item.instance.cleanUp(true);\n item.element.remove();\n item.element.innerHTML = '';\n if (item.element.shadowRoot != null) {\n item.element.shadowRoot.innerHTML = '';\n }\n}\n\nfunction getInstanceSpecs<LAnnotations>(\n instance: AdvancedVirtualizedFileDiff<LAnnotations>,\n diffStyle: 'split' | 'unified' = 'split'\n) {\n if (diffStyle === 'split') {\n return {\n top: instance.splitTop,\n height: instance.splitHeight,\n };\n }\n return {\n top: instance.unifiedTop,\n height: instance.unifiedHeight,\n };\n}\n"],"mappings":"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"}