@pierre/diffs 1.3.0-beta.3 → 1.3.0-beta.5

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 (161) hide show
  1. package/README.md +6 -6
  2. package/dist/components/CodeView.js +6 -6
  3. package/dist/components/CodeView.js.map +1 -1
  4. package/dist/components/File.d.ts +3 -2
  5. package/dist/components/File.d.ts.map +1 -1
  6. package/dist/components/File.js +35 -21
  7. package/dist/components/File.js.map +1 -1
  8. package/dist/components/FileDiff.d.ts +8 -4
  9. package/dist/components/FileDiff.d.ts.map +1 -1
  10. package/dist/components/FileDiff.js +66 -56
  11. package/dist/components/FileDiff.js.map +1 -1
  12. package/dist/components/FileStream.js +4 -2
  13. package/dist/components/FileStream.js.map +1 -1
  14. package/dist/components/UnresolvedFile.js +1 -1
  15. package/dist/components/VirtualizedFile.d.ts +6 -2
  16. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  17. package/dist/components/VirtualizedFile.js +89 -24
  18. package/dist/components/VirtualizedFile.js.map +1 -1
  19. package/dist/components/VirtualizedFileDiff.d.ts +8 -2
  20. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  21. package/dist/components/VirtualizedFileDiff.js +91 -15
  22. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  23. package/dist/editor/command.d.ts +1 -1
  24. package/dist/editor/command.d.ts.map +1 -1
  25. package/dist/editor/command.js +3 -3
  26. package/dist/editor/command.js.map +1 -1
  27. package/dist/editor/editStack.d.ts +1 -1
  28. package/dist/editor/editor.d.ts +37 -9
  29. package/dist/editor/editor.d.ts.map +1 -1
  30. package/dist/editor/editor.js +558 -449
  31. package/dist/editor/editor.js.map +1 -1
  32. package/dist/editor/editor2.js +1 -1
  33. package/dist/editor/editor2.js.map +1 -1
  34. package/dist/editor/index.d.ts +2 -2
  35. package/dist/editor/lineAnnotations.d.ts +2 -1
  36. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  37. package/dist/editor/lineAnnotations.js +111 -1
  38. package/dist/editor/lineAnnotations.js.map +1 -1
  39. package/dist/editor/marker.d.ts +33 -0
  40. package/dist/editor/marker.d.ts.map +1 -0
  41. package/dist/editor/marker.js +185 -0
  42. package/dist/editor/marker.js.map +1 -0
  43. package/dist/editor/pieceTable.d.ts +8 -3
  44. package/dist/editor/pieceTable.d.ts.map +1 -1
  45. package/dist/editor/pieceTable.js +74 -12
  46. package/dist/editor/pieceTable.js.map +1 -1
  47. package/dist/editor/searchPanel.d.ts +12 -3
  48. package/dist/editor/searchPanel.d.ts.map +1 -1
  49. package/dist/editor/searchPanel.js +168 -54
  50. package/dist/editor/searchPanel.js.map +1 -1
  51. package/dist/editor/selection.d.ts +19 -3
  52. package/dist/editor/selection.d.ts.map +1 -1
  53. package/dist/editor/selection.js +188 -37
  54. package/dist/editor/selection.js.map +1 -1
  55. package/dist/editor/{quickEdit.d.ts → selectionAction.d.ts} +8 -8
  56. package/dist/editor/selectionAction.d.ts.map +1 -0
  57. package/dist/editor/{quickEdit.js → selectionAction.js} +18 -18
  58. package/dist/editor/selectionAction.js.map +1 -0
  59. package/dist/editor/sprite.d.ts +4 -3
  60. package/dist/editor/sprite.d.ts.map +1 -1
  61. package/dist/editor/sprite.js +19 -5
  62. package/dist/editor/sprite.js.map +1 -1
  63. package/dist/editor/textDocument.d.ts +4 -4
  64. package/dist/editor/textDocument.d.ts.map +1 -1
  65. package/dist/editor/textDocument.js +7 -7
  66. package/dist/editor/textDocument.js.map +1 -1
  67. package/dist/editor/textMeasure.d.ts +1 -0
  68. package/dist/editor/textMeasure.d.ts.map +1 -1
  69. package/dist/editor/textMeasure.js +6 -0
  70. package/dist/editor/textMeasure.js.map +1 -1
  71. package/dist/editor/tokenzier.js +20 -9
  72. package/dist/editor/tokenzier.js.map +1 -1
  73. package/dist/editor/utils.d.ts +3 -1
  74. package/dist/editor/utils.d.ts.map +1 -1
  75. package/dist/editor/utils.js +16 -1
  76. package/dist/editor/utils.js.map +1 -1
  77. package/dist/highlighter/shared_highlighter.js +3 -29
  78. package/dist/highlighter/shared_highlighter.js.map +1 -1
  79. package/dist/highlighter/themes/attachResolvedThemes.js +4 -3
  80. package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
  81. package/dist/highlighter/themes/cleanUpResolvedThemes.js +3 -2
  82. package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
  83. package/dist/highlighter/themes/constants.d.ts +1 -7
  84. package/dist/highlighter/themes/constants.d.ts.map +1 -1
  85. package/dist/highlighter/themes/constants.js +1 -4
  86. package/dist/highlighter/themes/constants.js.map +1 -1
  87. package/dist/highlighter/themes/getResolvedOrResolveTheme.js +2 -2
  88. package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
  89. package/dist/highlighter/themes/getResolvedThemes.js +2 -8
  90. package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
  91. package/dist/highlighter/themes/hasResolvedThemes.js +2 -3
  92. package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
  93. package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +1 -1
  94. package/dist/highlighter/themes/registerCustomTheme.d.ts +5 -3
  95. package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
  96. package/dist/highlighter/themes/registerCustomTheme.js +15 -5
  97. package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
  98. package/dist/highlighter/themes/resolveTheme.js +6 -27
  99. package/dist/highlighter/themes/resolveTheme.js.map +1 -1
  100. package/dist/highlighter/themes/resolveThemes.js +5 -12
  101. package/dist/highlighter/themes/resolveThemes.js.map +1 -1
  102. package/dist/highlighter/themes/themeResolution.d.ts +8 -0
  103. package/dist/highlighter/themes/themeResolution.d.ts.map +1 -0
  104. package/dist/highlighter/themes/themeResolution.js +22 -0
  105. package/dist/highlighter/themes/themeResolution.js.map +1 -0
  106. package/dist/highlighter/themes/themeResolver.d.ts +8 -0
  107. package/dist/highlighter/themes/themeResolver.d.ts.map +1 -0
  108. package/dist/highlighter/themes/themeResolver.js +8 -0
  109. package/dist/highlighter/themes/themeResolver.js.map +1 -0
  110. package/dist/index.d.ts +4 -4
  111. package/dist/index.js +3 -3
  112. package/dist/managers/InteractionManager.js +1 -1
  113. package/dist/managers/InteractionManager.js.map +1 -1
  114. package/dist/managers/ResizeManager.js +1 -1
  115. package/dist/managers/ResizeManager.js.map +1 -1
  116. package/dist/react/CodeView.js +1 -1
  117. package/dist/react/index.d.ts +2 -2
  118. package/dist/react/utils/useFileDiffInstance.js +1 -0
  119. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  120. package/dist/renderers/DiffHunksRenderer.d.ts +6 -2
  121. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  122. package/dist/renderers/DiffHunksRenderer.js +183 -12
  123. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  124. package/dist/renderers/FileRenderer.d.ts +2 -2
  125. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  126. package/dist/renderers/FileRenderer.js +17 -5
  127. package/dist/renderers/FileRenderer.js.map +1 -1
  128. package/dist/ssr/FileDiffReact.js +1 -1
  129. package/dist/ssr/index.d.ts +2 -2
  130. package/dist/types.d.ts +25 -8
  131. package/dist/types.d.ts.map +1 -1
  132. package/dist/utils/getHighlighterThemeStyles.js +16 -12
  133. package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
  134. package/dist/utils/includesFileAnnotations.d.ts +17 -0
  135. package/dist/utils/includesFileAnnotations.d.ts.map +1 -0
  136. package/dist/utils/includesFileAnnotations.js +19 -0
  137. package/dist/utils/includesFileAnnotations.js.map +1 -0
  138. package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
  139. package/dist/utils/parsePatchFiles.js +93 -4
  140. package/dist/utils/parsePatchFiles.js.map +1 -1
  141. package/dist/utils/renderDiffWithHighlighter.js +4 -2
  142. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  143. package/dist/utils/renderFileWithHighlighter.js +4 -2
  144. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  145. package/dist/utils/updateDiffHunks.d.ts +13 -0
  146. package/dist/utils/updateDiffHunks.d.ts.map +1 -0
  147. package/dist/utils/updateDiffHunks.js +171 -0
  148. package/dist/utils/updateDiffHunks.js.map +1 -0
  149. package/dist/utils/virtualDiffLayout.d.ts +2 -1
  150. package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
  151. package/dist/utils/virtualDiffLayout.js +9 -1
  152. package/dist/utils/virtualDiffLayout.js.map +1 -1
  153. package/dist/worker/{wasm-BaDzIkIn.js → wasm-qE0LgnY3.js} +2 -2
  154. package/dist/worker/{wasm-BaDzIkIn.js.map → wasm-qE0LgnY3.js.map} +1 -1
  155. package/dist/worker/worker-portable.js +1016 -275
  156. package/dist/worker/worker-portable.js.map +1 -1
  157. package/dist/worker/worker.js +31 -19
  158. package/dist/worker/worker.js.map +1 -1
  159. package/package.json +5 -10
  160. package/dist/editor/quickEdit.d.ts.map +0 -1
  161. package/dist/editor/quickEdit.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualizedFile.js","names":["virtualizer: Virtualizer | CodeView<LAnnotation>","metrics: VirtualFileMetrics","result: FileLayoutCheckpoint | undefined","idealStartHunk","startingLine","clampedTotalLines","bufferBefore","hunkOffsets: number[]","firstVisibleHunk: number | undefined","centerHunk: number | undefined","overflowCounter: number | undefined","lineHeight"],"sources":["../../src/components/VirtualizedFile.ts"],"sourcesContent":["import { DEFAULT_VIRTUAL_FILE_METRICS } from '../constants';\nimport type {\n DiffsTextDocument,\n FileContents,\n LineAnnotation,\n NumericScrollLineAnchor,\n PendingCodeViewLayoutReset,\n RenderRange,\n RenderWindow,\n StickySpecs,\n ThemeTypes,\n VirtualFileMetrics,\n} from '../types';\nimport { areFilesEqual } from '../utils/areFilesEqual';\nimport { areObjectsEqual } from '../utils/areObjectsEqual';\nimport { areOptionsEqual } from '../utils/areOptionsEqual';\nimport {\n getVirtualFileHeaderRegion,\n getVirtualFilePaddingBottom,\n} from '../utils/computeVirtualFileMetrics';\nimport type { WorkerPoolManager } from '../worker';\nimport type { CodeView } from './CodeView';\nimport { File, type FileOptions, type FileRenderProps } from './File';\nimport type { Virtualizer } from './Virtualizer';\n\ninterface FileLayoutCheckpoint {\n lineIndex: number;\n top: number;\n}\n\ninterface FileLayoutCache {\n // Sparse map: line index -> measured height. Only stores lines that differ\n // from what is returned by `getLineHeight`.\n heights: Map<number, number>;\n // Sparse measured positions used to resume deep geometry scans near a target\n // line or scroll offset instead of replaying layout from the start.\n checkpoints: FileLayoutCheckpoint[];\n}\n\nconst LAYOUT_CHECKPOINT_INTERVAL = 5_000;\n\nlet instanceId = -1;\n\nfunction hasFileLayoutOptionChanged<LAnnotation>(\n previousOptions: FileOptions<LAnnotation>,\n nextOptions: FileOptions<LAnnotation>\n): boolean {\n return (\n (previousOptions.overflow ?? 'scroll') !==\n (nextOptions.overflow ?? 'scroll') ||\n (previousOptions.collapsed ?? false) !== (nextOptions.collapsed ?? false) ||\n (previousOptions.disableLineNumbers ?? false) !==\n (nextOptions.disableLineNumbers ?? false) ||\n (previousOptions.disableFileHeader ?? false) !==\n (nextOptions.disableFileHeader ?? false) ||\n previousOptions.unsafeCSS !== nextOptions.unsafeCSS\n );\n}\n\nexport class VirtualizedFile<\n LAnnotation = undefined,\n> extends File<LAnnotation> {\n override readonly __id: string = `virtualized-file:${++instanceId}`;\n\n public top: number | undefined;\n public height: number = 0;\n private cache: FileLayoutCache = { heights: new Map(), checkpoints: [] };\n private isVisible: boolean = false;\n private isSetup: boolean = false;\n private layoutDirty = true;\n private forceRenderOverride: true | undefined;\n private currentCollapsed: boolean | undefined;\n\n constructor(\n options: FileOptions<LAnnotation> | undefined,\n private virtualizer: Virtualizer | CodeView<LAnnotation>,\n private metrics: VirtualFileMetrics = DEFAULT_VIRTUAL_FILE_METRICS,\n workerManager?: WorkerPoolManager,\n isContainerManaged = false\n ) {\n super(options, workerManager, isContainerManaged);\n }\n\n public setMetrics(metrics: VirtualFileMetrics, force = false): void {\n if (!force && areObjectsEqual(this.metrics, metrics)) {\n return;\n }\n\n this.metrics = metrics;\n this.resetLayoutCache();\n }\n\n // Get the height for a line, using cached value if available.\n // If not cached and hasMetadataLine is true, adds lineHeight for the\n // metadata.\n public getLineHeight(lineIndex: number, hasMetadataLine = false): number {\n const cached = this.cache.heights.get(lineIndex);\n if (cached != null) {\n return cached;\n }\n const multiplier = hasMetadataLine ? 2 : 1;\n return this.metrics.lineHeight * multiplier;\n }\n\n override setOptions(options: FileOptions<LAnnotation> | undefined): void {\n if (this.isAdvancedMode()) {\n throw new Error(\n 'VirtualizedFile.setOptions cannot be used inside CodeView. Update CodeView options instead.'\n );\n }\n\n if (options == null) return;\n const { options: previousOptions } = this;\n const optionsChanged = !areOptionsEqual(previousOptions, options);\n const layoutChanged = hasFileLayoutOptionChanged(previousOptions, options);\n\n super.setOptions(options);\n\n if (layoutChanged) {\n this.resetLayoutCache(true);\n }\n // Any option can affect rendered DOM; only layout-affecting options clear\n // the measured height cache above.\n if (optionsChanged) {\n this.forceRenderOverride = true;\n }\n if (optionsChanged) {\n this.virtualizer.instanceChanged(this, layoutChanged);\n }\n }\n\n override setThemeType(themeType: ThemeTypes): void {\n if (this.isAdvancedMode()) {\n throw new Error(\n 'VirtualizedFile.setThemeType cannot be used inside CodeView. Update CodeView options instead.'\n );\n }\n\n super.setThemeType(themeType);\n }\n\n private resetLayoutCache(recompute = false): void {\n this.layoutDirty = true;\n if (this.cache.heights.size > 0) {\n this.cache.heights.clear();\n }\n if (this.cache.checkpoints.length > 0) {\n this.cache.checkpoints.length = 0;\n }\n if (this.renderRange != null) {\n this.renderRange = undefined;\n }\n // NOTE(amadeus): In CodeView we intentionally batch computes to all happen\n // at the same time, so we shouldn't trigger this there.\n if (recompute && this.isSimpleMode()) {\n this.computeApproximateSize();\n }\n }\n\n // Measure rendered lines and update height cache.\n // Called after render to reconcile estimated vs actual heights.\n public reconcileHeights(): boolean {\n let hasHeightChange = false;\n if (this.fileContainer == null || this.file == null) {\n if (this.height !== 0) {\n hasHeightChange = true;\n }\n this.height = 0;\n return hasHeightChange;\n }\n const { overflow = 'scroll' } = this.options;\n this.top = this.getVirtualizedTop();\n\n // If the file has no annotations and we are using the scroll variant, then\n // we can probably skip everything\n if (\n overflow === 'scroll' &&\n this.lineAnnotations.length === 0 &&\n !this.isResizeDebuggingEnabled()\n ) {\n return hasHeightChange;\n }\n\n // Single code element (no split mode)\n if (this.code == null) {\n return hasHeightChange;\n }\n const content = this.code.children[1]; // Content column (gutter is [0])\n if (!(content instanceof HTMLElement)) {\n return hasHeightChange;\n }\n\n for (const line of content.children) {\n if (!(line instanceof HTMLElement)) continue;\n\n const lineIndexAttr = line.dataset.lineIndex;\n if (lineIndexAttr == null) continue;\n\n const lineIndex = Number(lineIndexAttr);\n let measuredHeight = line.getBoundingClientRect().height;\n let hasMetadata = false;\n\n // Annotations or noNewline metadata increase the size of their attached line\n if (\n line.nextElementSibling instanceof HTMLElement &&\n ('lineAnnotation' in line.nextElementSibling.dataset ||\n 'noNewline' in line.nextElementSibling.dataset)\n ) {\n if ('noNewline' in line.nextElementSibling.dataset) {\n hasMetadata = true;\n }\n measuredHeight +=\n line.nextElementSibling.getBoundingClientRect().height;\n }\n\n const expectedHeight = this.getLineHeight(lineIndex, hasMetadata);\n\n if (measuredHeight === expectedHeight) {\n continue;\n }\n\n hasHeightChange = true;\n // Line is back to standard height (e.g., after window resize)\n // Remove from cache\n if (measuredHeight === this.metrics.lineHeight * (hasMetadata ? 2 : 1)) {\n this.cache.heights.delete(lineIndex);\n }\n // Non-standard height, cache it\n else {\n this.cache.heights.set(lineIndex, measuredHeight);\n }\n }\n\n if (hasHeightChange || this.isResizeDebuggingEnabled()) {\n this.computeApproximateSize(true);\n }\n return hasHeightChange;\n }\n\n public onRender = (dirty: boolean): boolean => {\n if (this.fileContainer == null || this.file == null) {\n return false;\n }\n if (dirty) {\n this.top = this.getVirtualizedTop();\n }\n return this.render({ file: this.file });\n };\n\n // Prepares this item for CodeView layout by binding the latest file, syncing\n // its virtualized top, and returning an approximate height. This method is\n // called while downstream items are being re-positioned, so later changes\n // should keep clean instances on a cached-height fast path.\n public prepareCodeViewItem(\n file: FileContents,\n top: number,\n reset?: PendingCodeViewLayoutReset\n ): number {\n let shouldResetLayoutCache = reset?.resetFileLayoutCache === true;\n if (reset?.metrics != null) {\n this.metrics = reset.metrics;\n shouldResetLayoutCache = true;\n }\n\n const { collapsed = false } = this.options;\n if (this.currentCollapsed !== collapsed) {\n this.currentCollapsed = collapsed;\n shouldResetLayoutCache = true;\n }\n\n if (shouldResetLayoutCache) {\n this.resetLayoutCache();\n }\n\n if (this.file !== file) {\n this.layoutDirty = true;\n }\n this.file = file;\n this.top = top;\n this.computeApproximateSize();\n return this.height;\n }\n\n public getLinePosition(\n lineNumber: number\n ): { top: number; height: number } | undefined {\n if (this.file == null) {\n return undefined;\n }\n\n const { disableFileHeader = false, collapsed = false } = this.options;\n const lastLineIndex = this.fileRenderer.getLineCount(this.file) - 1;\n let top = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);\n\n if (collapsed || lastLineIndex < 0) {\n return { top, height: 0 };\n }\n\n const clampedLineIndex = Math.min(\n Math.max(lineNumber - 1, 0),\n lastLineIndex\n );\n const { overflow = 'scroll' } = this.options;\n const { lineHeight } = this.metrics;\n\n if (overflow === 'scroll' && this.lineAnnotations.length === 0) {\n return {\n top: top + clampedLineIndex * lineHeight,\n height: lineHeight,\n };\n }\n\n const checkpoint =\n this.getLayoutCheckpointBeforeLineIndex(clampedLineIndex);\n top = checkpoint?.top ?? top;\n for (\n let lineIndex = checkpoint?.lineIndex ?? 0;\n lineIndex < clampedLineIndex;\n lineIndex++\n ) {\n top += this.getLineHeight(lineIndex, false);\n }\n\n return {\n top,\n height: this.getLineHeight(clampedLineIndex, false),\n };\n }\n\n public getNumericScrollAnchor(\n localViewportTop: number\n ): NumericScrollLineAnchor | undefined {\n if (this.file == null || this.renderRange == null) {\n return undefined;\n }\n\n const {\n disableFileHeader = false,\n collapsed = false,\n overflow = 'scroll',\n } = this.options;\n if (collapsed || this.renderRange.totalLines <= 0) {\n return undefined;\n }\n\n const lastLineIndex = this.fileRenderer.getLineCount(this.file) - 1;\n if (lastLineIndex < 0) {\n return undefined;\n }\n\n const headerRegion = getVirtualFileHeaderRegion(\n this.metrics,\n disableFileHeader\n );\n const firstRenderedLineIndex = Math.min(\n this.renderRange.startingLine,\n lastLineIndex\n );\n const lastRenderedLineIndex = Math.min(\n firstRenderedLineIndex + this.renderRange.totalLines - 1,\n lastLineIndex\n );\n if (lastRenderedLineIndex < firstRenderedLineIndex) {\n return undefined;\n }\n\n // If we don't allow line wrapping and have no annotations, we can just\n // multiply our way to the the correct value\n if (overflow === 'scroll' && this.lineAnnotations.length === 0) {\n const { lineHeight } = this.metrics;\n const firstRenderedLineTop = headerRegion + this.renderRange.bufferBefore;\n const deltaLineCount = Math.max(\n Math.ceil((localViewportTop - firstRenderedLineTop) / lineHeight),\n 0\n );\n const lineIndex = firstRenderedLineIndex + deltaLineCount;\n if (lineIndex > lastRenderedLineIndex) {\n return undefined;\n }\n\n return {\n lineNumber: lineIndex + 1,\n top: headerRegion + lineIndex * lineHeight,\n };\n }\n\n // Otherwise we gotta iterate through the range\n let top = headerRegion + this.renderRange.bufferBefore;\n for (\n let lineIndex = firstRenderedLineIndex;\n lineIndex <= lastRenderedLineIndex;\n lineIndex++\n ) {\n if (top >= localViewportTop) {\n return {\n lineNumber: lineIndex + 1,\n top,\n };\n }\n top += this.getLineHeight(lineIndex);\n }\n\n return undefined;\n }\n\n public getVirtualizedHeight(): number {\n return this.height;\n }\n\n public getAdvancedStickySpecs(\n windowSpecs?: RenderWindow\n ): StickySpecs | undefined {\n if (this.top == null || this.file == null) {\n return undefined;\n }\n if (this.options.collapsed === true) {\n return { topOffset: this.top, height: this.height };\n }\n const renderRange =\n windowSpecs != null\n ? this.computeRenderRangeFromWindow(this.file, this.top, windowSpecs)\n : this.renderRange;\n if (renderRange == null) {\n return undefined;\n }\n const { bufferBefore, bufferAfter, totalLines } = renderRange;\n // Rendered items flow contiguously in the sticky container with no buffer\n // spacers, so a header-only item (totalLines === 0, none of its rows fall\n // inside the window) must report where its header actually sits in that\n // flow, which depends on which side of the window its content is on:\n // - content ABOVE the window (item starts above window.top): the header\n // sits at the item's bottom so the following item connects, so offset by\n // bufferAfter.\n // - content BELOW the window (item starts at/after window.top, e.g. a\n // trailing header peeking in at the bottom): the header renders at the\n // item's top with nothing after it, so no offset. Always adding\n // bufferAfter here made getStickyBounds over-measure the sticky\n // container for that trailing case.\n let headerOnlyOffset = 0;\n if (totalLines === 0) {\n const activeWindow = windowSpecs ?? this.virtualizer.getWindowSpecs();\n if (this.top < activeWindow.top) {\n headerOnlyOffset = bufferAfter;\n }\n }\n return {\n topOffset: this.top + bufferBefore + headerOnlyOffset,\n height: this.height - (bufferBefore + bufferAfter),\n };\n }\n\n override cleanUp(recycle = false): void {\n if (this.fileContainer != null && this.isSimpleMode()) {\n this.getSimpleVirtualizer()?.disconnect(this.fileContainer);\n }\n if (!recycle) {\n this.layoutDirty = true;\n }\n this.isSetup = false;\n super.cleanUp(recycle);\n }\n\n // Compute the approximate size of the file using cached line heights.\n // Uses lineHeight for lines without cached measurements.\n private computeApproximateSize(force = false): void {\n const shouldValidateSize = this.isResizeDebuggingEnabled();\n if (!force && !this.layoutDirty && !shouldValidateSize) {\n return;\n }\n\n const isFirstCompute = this.height === 0;\n this.height = 0;\n this.cache.checkpoints = [];\n if (this.file == null) {\n this.layoutDirty = false;\n return;\n }\n\n const {\n disableFileHeader = false,\n collapsed = false,\n overflow = 'scroll',\n } = this.options;\n const { lineHeight } = this.metrics;\n const lineCount = this.fileRenderer.getLineCount(this.file);\n const headerRegion = getVirtualFileHeaderRegion(\n this.metrics,\n disableFileHeader\n );\n const paddingBottom = getVirtualFilePaddingBottom(this.metrics);\n\n this.height += headerRegion;\n if (collapsed) {\n this.layoutDirty = false;\n return;\n }\n\n if (overflow === 'scroll' && this.lineAnnotations.length === 0) {\n this.height += lineCount * lineHeight;\n } else {\n for (let lineIndex = 0; lineIndex < lineCount; lineIndex++) {\n this.addLayoutCheckpoint(lineIndex, this.height);\n this.height += this.getLineHeight(lineIndex, false);\n }\n }\n\n if (lineCount > 0) {\n this.height += paddingBottom;\n }\n\n if (this.fileContainer != null && shouldValidateSize && !isFirstCompute) {\n const rect = this.fileContainer.getBoundingClientRect();\n if (rect.height !== this.height) {\n console.log(\n 'VirtualizedFile.computeApproximateSize: computed height doesnt match',\n {\n name: this.file.name,\n elementHeight: rect.height,\n computedHeight: this.height,\n }\n );\n } else {\n console.log(\n 'VirtualizedFile.computeApproximateSize: computed height IS CORRECT'\n );\n }\n }\n this.layoutDirty = false;\n }\n\n public setVisibility(visible: boolean): void {\n if (this.isAdvancedMode() || this.fileContainer == null) {\n return;\n }\n if (visible && !this.isVisible) {\n this.top = this.getVirtualizedTop();\n this.isVisible = true;\n } else if (!visible && this.isVisible) {\n this.isVisible = false;\n this.rerender();\n }\n }\n\n override rerender(): void {\n if (!this.enabled || this.file == null) {\n return;\n }\n this.forceRenderOverride = true;\n this.virtualizer.instanceChanged(this, false);\n }\n\n override applyLayoutChange(\n textDocument: DiffsTextDocument,\n newLineAnnotations?: LineAnnotation<LAnnotation>[],\n shouldUpdateBuffer = false\n ): void {\n const previousRenderRange = this.renderRange;\n super.applyLayoutChange(textDocument, newLineAnnotations);\n this.getSimpleVirtualizer()?.markDOMDirty();\n this.resetLayoutCache(true);\n // Update the buffers caused by the line-count change to ensure the editor\n // scrolls to the correct position before re-rendering\n if (\n shouldUpdateBuffer &&\n previousRenderRange !== undefined &&\n this.file !== undefined\n ) {\n const windowSpecs = this.virtualizer.getWindowSpecs();\n const renderRange = this.computeRenderRangeFromWindow(\n this.file,\n this.top ?? 0,\n windowSpecs\n );\n if (renderRange.bufferAfter !== previousRenderRange.bufferAfter) {\n this.updateBuffers(renderRange);\n }\n }\n }\n\n override render({\n fileContainer,\n file,\n forceRender = false,\n ...props\n }: FileRenderProps<LAnnotation>): boolean {\n const didFileChange = this.file == null || !areFilesEqual(this.file, file);\n const { forceRenderOverride, isSetup } = this;\n this.forceRenderOverride = undefined;\n\n this.file = file;\n\n fileContainer = this.getOrCreateFileContainerNode(fileContainer);\n\n if (this.file == null) {\n console.error(\n 'VirtualizedFile.render: attempting to virtually render when we dont have file'\n );\n return false;\n }\n\n if (!isSetup) {\n this.computeApproximateSize();\n const virtualizer = this.getSimpleVirtualizer();\n this.top ??= this.getVirtualizedTop();\n if (this.isAdvancedMode()) {\n this.isVisible = true;\n } else {\n if (virtualizer == null) {\n throw new Error(\n 'VirtualizedFile.render: simple virtualizer is not available'\n );\n }\n virtualizer.connect(fileContainer, this);\n this.isVisible = virtualizer.isInstanceVisible(\n this.top ?? 0,\n this.height\n );\n }\n this.isSetup = true;\n } else {\n this.top ??= this.getVirtualizedTop();\n if (didFileChange && this.isSimpleMode()) {\n this.getSimpleVirtualizer()?.markDOMDirty();\n this.resetLayoutCache(true);\n }\n }\n\n if (!this.isVisible && this.isSimpleMode()) {\n return this.renderPlaceholder(this.height);\n }\n\n const windowSpecs = this.virtualizer.getWindowSpecs();\n const fileTop = this.top ?? 0;\n const renderRange = this.computeRenderRangeFromWindow(\n this.file,\n fileTop,\n windowSpecs\n );\n return super.render({\n file: this.file,\n fileContainer,\n renderRange,\n forceRender: forceRenderOverride ?? forceRender,\n ...props,\n });\n }\n\n public syncVirtualizedTop(): void {\n this.top = this.getVirtualizedTop();\n }\n\n protected override shouldDisableVirtualizationBuffers(): boolean {\n return this.isAdvancedMode() || super.shouldDisableVirtualizationBuffers();\n }\n\n private isSimpleMode(): boolean {\n return this.virtualizer.type === 'simple';\n }\n\n private isAdvancedMode(): boolean {\n return this.virtualizer.type === 'advanced';\n }\n\n private addLayoutCheckpoint(lineIndex: number, top: number): void {\n if (lineIndex % LAYOUT_CHECKPOINT_INTERVAL !== 0) {\n return;\n }\n this.cache.checkpoints.push({ lineIndex, top });\n }\n\n // Find the nearest sparse layout checkpoint at or before a raw file line.\n // Checkpoints store measured `top` offsets every few thousand lines, so a\n // binary search lets deep line-position lookups resume from that checkpoint\n // instead of replaying layout from the start of the file.\n private getLayoutCheckpointBeforeLineIndex(\n lineIndex: number\n ): FileLayoutCheckpoint | undefined {\n if (lineIndex <= 0 || this.cache.checkpoints.length === 0) {\n return undefined;\n }\n\n let low = 0;\n let high = this.cache.checkpoints.length - 1;\n let result: FileLayoutCheckpoint | undefined;\n\n while (low <= high) {\n const mid = (low + high) >> 1;\n const checkpoint = this.cache.checkpoints[mid];\n if (checkpoint == null) {\n throw new Error('VirtualizedFile: invalid checkpoint index');\n }\n if (checkpoint.lineIndex <= lineIndex) {\n result = checkpoint;\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n return result;\n }\n\n // Find the nearest sparse layout checkpoint at or before a scroll offset.\n // Render-range scans start from this checkpoint so variable-height files\n // only replay the nearby measured rows. When `hunkLineCount` is provided,\n // step backward to a hunk boundary so hooks that depend on grouped lines\n // still see a complete hunk.\n private getLayoutCheckpointBeforeTop(\n top: number,\n hunkLineCount?: number\n ): FileLayoutCheckpoint | undefined {\n let low = 0;\n let high = this.cache.checkpoints.length - 1;\n let resultIndex = -1;\n\n while (low <= high) {\n const mid = (low + high) >> 1;\n const checkpoint = this.cache.checkpoints[mid];\n if (checkpoint == null) {\n throw new Error('VirtualizedFile: invalid checkpoint index');\n }\n if (checkpoint.top <= top) {\n resultIndex = mid;\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n if (hunkLineCount == null) {\n return resultIndex >= 0 ? this.cache.checkpoints[resultIndex] : undefined;\n }\n\n for (let index = resultIndex; index >= 0; index--) {\n const checkpoint = this.cache.checkpoints[index];\n if (checkpoint == null) {\n throw new Error('VirtualizedFile: invalid checkpoint index');\n }\n if (checkpoint.lineIndex % hunkLineCount === 0) {\n return checkpoint;\n }\n }\n\n return undefined;\n }\n\n private getVirtualizedTop(): number {\n if (this.virtualizer.type === 'advanced') {\n return this.virtualizer.getLocalTopForInstance(this);\n }\n return this.fileContainer != null\n ? this.virtualizer.getOffsetInScrollContainer(this.fileContainer)\n : 0;\n }\n\n private getSimpleVirtualizer(): Virtualizer | undefined {\n return this.virtualizer.type === 'simple' ? this.virtualizer : undefined;\n }\n\n private isResizeDebuggingEnabled(): boolean {\n return this.getSimpleVirtualizer()?.config.resizeDebugging ?? false;\n }\n\n private computeRenderRangeFromWindow(\n file: FileContents,\n fileTop: number,\n { top, bottom }: RenderWindow\n ): RenderRange {\n const { disableFileHeader = false, overflow = 'scroll' } = this.options;\n const { hunkLineCount, lineHeight } = this.metrics;\n const lineCount = this.fileRenderer.getLineCount(file);\n const fileHeight = this.height;\n const headerRegion = getVirtualFileHeaderRegion(\n this.metrics,\n disableFileHeader\n );\n const paddingBottom =\n lineCount > 0 ? getVirtualFilePaddingBottom(this.metrics) : 0;\n\n // File is outside render window\n if (fileTop < top - fileHeight || fileTop > bottom) {\n return {\n startingLine: 0,\n totalLines: 0,\n bufferBefore: 0,\n bufferAfter: fileHeight - headerRegion - paddingBottom,\n };\n }\n\n // Small file, just render it all\n if (lineCount <= hunkLineCount) {\n return {\n startingLine: 0,\n totalLines: hunkLineCount,\n bufferBefore: 0,\n bufferAfter: 0,\n };\n }\n\n // Calculate totalLines based on viewport size\n const estimatedTargetLines = Math.ceil(\n Math.max(bottom - top, 0) / lineHeight\n );\n const totalLines =\n Math.ceil(estimatedTargetLines / hunkLineCount) * hunkLineCount +\n hunkLineCount * 2;\n const totalHunks = totalLines / hunkLineCount;\n const viewportCenter = (top + bottom) / 2;\n\n // Simple case: overflow scroll with no annotations - pure math!\n if (overflow === 'scroll' && this.lineAnnotations.length === 0) {\n // Find which line is at viewport center\n const centerLine = Math.floor(\n (viewportCenter - (fileTop + headerRegion)) / lineHeight\n );\n const centerHunk = Math.floor(centerLine / hunkLineCount);\n\n // Calculate ideal start centered around viewport\n const idealStartHunk = centerHunk - Math.floor(totalHunks / 2);\n const totalHunksInFile = Math.ceil(lineCount / hunkLineCount);\n const startingLine =\n Math.max(0, Math.min(idealStartHunk, totalHunksInFile)) * hunkLineCount;\n\n const clampedTotalLines =\n idealStartHunk < 0\n ? totalLines + idealStartHunk * hunkLineCount\n : totalLines;\n\n const bufferBefore = startingLine * lineHeight;\n const renderedLines = Math.min(\n clampedTotalLines,\n lineCount - startingLine\n );\n const bufferAfter = Math.max(\n 0,\n (lineCount - startingLine - renderedLines) * lineHeight\n );\n\n return {\n startingLine,\n totalLines: clampedTotalLines,\n bufferBefore,\n bufferAfter,\n };\n }\n\n // Complex case: need to account for line annotations or wrap overflow\n const overflowHunks = totalHunks;\n const hunkOffsets: number[] = [];\n // Start the scan before the viewport so we collect hunk offsets that may be\n // needed for bufferBefore. This only chooses the scan origin; the returned\n // render range is still computed from the visible window below.\n const checkpoint = this.getLayoutCheckpointBeforeTop(\n Math.max(0, top - fileTop - totalLines * lineHeight * 2),\n hunkLineCount\n );\n\n let absoluteLineTop = fileTop + (checkpoint?.top ?? headerRegion);\n let currentLine = checkpoint?.lineIndex ?? 0;\n let firstVisibleHunk: number | undefined;\n let centerHunk: number | undefined;\n let overflowCounter: number | undefined;\n\n const startingLineIndex = checkpoint?.lineIndex ?? 0;\n for (\n let lineIndex = startingLineIndex;\n lineIndex < lineCount;\n lineIndex++\n ) {\n const isAtHunkBoundary = currentLine % hunkLineCount === 0;\n const currentHunk = Math.floor(currentLine / hunkLineCount);\n\n if (isAtHunkBoundary) {\n hunkOffsets[currentHunk] = absoluteLineTop - (fileTop + headerRegion);\n\n if (overflowCounter != null) {\n if (overflowCounter <= 0) {\n break;\n }\n overflowCounter--;\n }\n }\n\n const lineHeight = this.getLineHeight(lineIndex, false);\n\n // Track visible region\n if (absoluteLineTop > top - lineHeight && absoluteLineTop < bottom) {\n firstVisibleHunk ??= currentHunk;\n }\n\n // Track which hunk contains the viewport center\n if (absoluteLineTop + lineHeight > viewportCenter) {\n centerHunk ??= currentHunk;\n }\n\n // Start overflow when we are out of the viewport at a hunk boundary\n if (\n overflowCounter == null &&\n absoluteLineTop >= bottom &&\n isAtHunkBoundary\n ) {\n overflowCounter = overflowHunks;\n }\n\n currentLine++;\n absoluteLineTop += lineHeight;\n }\n\n // No visible lines found\n if (firstVisibleHunk == null) {\n return {\n startingLine: 0,\n totalLines: 0,\n bufferBefore: 0,\n bufferAfter: fileHeight - headerRegion - paddingBottom,\n };\n }\n\n // Calculate balanced startingLine centered around the viewport center\n centerHunk ??= firstVisibleHunk;\n const idealStartHunk = Math.round(centerHunk - totalHunks / 2);\n\n // Clamp startHunk: at the beginning, reduce totalLines; at the end, shift\n // startHunk back\n const maxStartHunk = Math.max(\n 0,\n Math.ceil(lineCount / hunkLineCount) - totalHunks\n );\n const startHunk = Math.max(0, Math.min(idealStartHunk, maxStartHunk));\n const startingLine = startHunk * hunkLineCount;\n\n // If we wanted to start before 0, reduce totalLines by the clamped amount\n const clampedTotalLines =\n idealStartHunk < 0\n ? totalLines + idealStartHunk * hunkLineCount\n : totalLines;\n\n // Use hunkOffsets array for efficient buffer calculations\n const bufferBefore = hunkOffsets[startHunk] ?? 0;\n\n // Calculate bufferAfter\n const finalHunkIndex = startHunk + clampedTotalLines / hunkLineCount;\n const bufferAfter =\n finalHunkIndex < hunkOffsets.length\n ? fileHeight -\n headerRegion -\n hunkOffsets[finalHunkIndex] -\n paddingBottom\n : fileHeight - (absoluteLineTop - fileTop) - paddingBottom;\n\n return {\n startingLine,\n totalLines: clampedTotalLines,\n bufferBefore,\n bufferAfter,\n };\n }\n}\n"],"mappings":";;;;;;;;AAuCA,MAAM,6BAA6B;AAEnC,IAAI,aAAa;AAEjB,SAAS,2BACP,iBACA,aACS;AACT,SACG,gBAAgB,YAAY,eAC1B,YAAY,YAAY,cAC1B,gBAAgB,aAAa,YAAY,YAAY,aAAa,WAClE,gBAAgB,sBAAsB,YACpC,YAAY,sBAAsB,WACpC,gBAAgB,qBAAqB,YACnC,YAAY,qBAAqB,UACpC,gBAAgB,cAAc,YAAY;;AAI9C,IAAa,kBAAb,cAEU,KAAkB;CAC1B,AAAkB,OAAe,oBAAoB,EAAE;CAEvD,AAAO;CACP,AAAO,SAAiB;CACxB,AAAQ,QAAyB;EAAE,yBAAS,IAAI,KAAK;EAAE,aAAa,EAAE;EAAE;CACxE,AAAQ,YAAqB;CAC7B,AAAQ,UAAmB;CAC3B,AAAQ,cAAc;CACtB,AAAQ;CACR,AAAQ;CAER,YACE,SACA,AAAQA,aACR,AAAQC,UAA8B,8BACtC,eACA,qBAAqB,OACrB;AACA,QAAM,SAAS,eAAe,mBAAmB;EALzC;EACA;;CAOV,AAAO,WAAW,SAA6B,QAAQ,OAAa;AAClE,MAAI,CAAC,SAAS,gBAAgB,KAAK,SAAS,QAAQ,CAClD;AAGF,OAAK,UAAU;AACf,OAAK,kBAAkB;;CAMzB,AAAO,cAAc,WAAmB,kBAAkB,OAAe;EACvE,MAAM,SAAS,KAAK,MAAM,QAAQ,IAAI,UAAU;AAChD,MAAI,UAAU,KACZ,QAAO;EAET,MAAM,aAAa,kBAAkB,IAAI;AACzC,SAAO,KAAK,QAAQ,aAAa;;CAGnC,AAAS,WAAW,SAAqD;AACvE,MAAI,KAAK,gBAAgB,CACvB,OAAM,IAAI,MACR,8FACD;AAGH,MAAI,WAAW,KAAM;EACrB,MAAM,EAAE,SAAS,oBAAoB;EACrC,MAAM,iBAAiB,CAAC,gBAAgB,iBAAiB,QAAQ;EACjE,MAAM,gBAAgB,2BAA2B,iBAAiB,QAAQ;AAE1E,QAAM,WAAW,QAAQ;AAEzB,MAAI,cACF,MAAK,iBAAiB,KAAK;AAI7B,MAAI,eACF,MAAK,sBAAsB;AAE7B,MAAI,eACF,MAAK,YAAY,gBAAgB,MAAM,cAAc;;CAIzD,AAAS,aAAa,WAA6B;AACjD,MAAI,KAAK,gBAAgB,CACvB,OAAM,IAAI,MACR,gGACD;AAGH,QAAM,aAAa,UAAU;;CAG/B,AAAQ,iBAAiB,YAAY,OAAa;AAChD,OAAK,cAAc;AACnB,MAAI,KAAK,MAAM,QAAQ,OAAO,EAC5B,MAAK,MAAM,QAAQ,OAAO;AAE5B,MAAI,KAAK,MAAM,YAAY,SAAS,EAClC,MAAK,MAAM,YAAY,SAAS;AAElC,MAAI,KAAK,eAAe,KACtB,MAAK,cAAc;AAIrB,MAAI,aAAa,KAAK,cAAc,CAClC,MAAK,wBAAwB;;CAMjC,AAAO,mBAA4B;EACjC,IAAI,kBAAkB;AACtB,MAAI,KAAK,iBAAiB,QAAQ,KAAK,QAAQ,MAAM;AACnD,OAAI,KAAK,WAAW,EAClB,mBAAkB;AAEpB,QAAK,SAAS;AACd,UAAO;;EAET,MAAM,EAAE,WAAW,aAAa,KAAK;AACrC,OAAK,MAAM,KAAK,mBAAmB;AAInC,MACE,aAAa,YACb,KAAK,gBAAgB,WAAW,KAChC,CAAC,KAAK,0BAA0B,CAEhC,QAAO;AAIT,MAAI,KAAK,QAAQ,KACf,QAAO;EAET,MAAM,UAAU,KAAK,KAAK,SAAS;AACnC,MAAI,EAAE,mBAAmB,aACvB,QAAO;AAGT,OAAK,MAAM,QAAQ,QAAQ,UAAU;AACnC,OAAI,EAAE,gBAAgB,aAAc;GAEpC,MAAM,gBAAgB,KAAK,QAAQ;AACnC,OAAI,iBAAiB,KAAM;GAE3B,MAAM,YAAY,OAAO,cAAc;GACvC,IAAI,iBAAiB,KAAK,uBAAuB,CAAC;GAClD,IAAI,cAAc;AAGlB,OACE,KAAK,8BAA8B,gBAClC,oBAAoB,KAAK,mBAAmB,WAC3C,eAAe,KAAK,mBAAmB,UACzC;AACA,QAAI,eAAe,KAAK,mBAAmB,QACzC,eAAc;AAEhB,sBACE,KAAK,mBAAmB,uBAAuB,CAAC;;GAGpD,MAAM,iBAAiB,KAAK,cAAc,WAAW,YAAY;AAEjE,OAAI,mBAAmB,eACrB;AAGF,qBAAkB;AAGlB,OAAI,mBAAmB,KAAK,QAAQ,cAAc,cAAc,IAAI,GAClE,MAAK,MAAM,QAAQ,OAAO,UAAU;OAIpC,MAAK,MAAM,QAAQ,IAAI,WAAW,eAAe;;AAIrD,MAAI,mBAAmB,KAAK,0BAA0B,CACpD,MAAK,uBAAuB,KAAK;AAEnC,SAAO;;CAGT,AAAO,YAAY,UAA4B;AAC7C,MAAI,KAAK,iBAAiB,QAAQ,KAAK,QAAQ,KAC7C,QAAO;AAET,MAAI,MACF,MAAK,MAAM,KAAK,mBAAmB;AAErC,SAAO,KAAK,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;;CAOzC,AAAO,oBACL,MACA,KACA,OACQ;EACR,IAAI,yBAAyB,OAAO,yBAAyB;AAC7D,MAAI,OAAO,WAAW,MAAM;AAC1B,QAAK,UAAU,MAAM;AACrB,4BAAyB;;EAG3B,MAAM,EAAE,YAAY,UAAU,KAAK;AACnC,MAAI,KAAK,qBAAqB,WAAW;AACvC,QAAK,mBAAmB;AACxB,4BAAyB;;AAG3B,MAAI,uBACF,MAAK,kBAAkB;AAGzB,MAAI,KAAK,SAAS,KAChB,MAAK,cAAc;AAErB,OAAK,OAAO;AACZ,OAAK,MAAM;AACX,OAAK,wBAAwB;AAC7B,SAAO,KAAK;;CAGd,AAAO,gBACL,YAC6C;AAC7C,MAAI,KAAK,QAAQ,KACf;EAGF,MAAM,EAAE,oBAAoB,OAAO,YAAY,UAAU,KAAK;EAC9D,MAAM,gBAAgB,KAAK,aAAa,aAAa,KAAK,KAAK,GAAG;EAClE,IAAI,MAAM,2BAA2B,KAAK,SAAS,kBAAkB;AAErE,MAAI,aAAa,gBAAgB,EAC/B,QAAO;GAAE;GAAK,QAAQ;GAAG;EAG3B,MAAM,mBAAmB,KAAK,IAC5B,KAAK,IAAI,aAAa,GAAG,EAAE,EAC3B,cACD;EACD,MAAM,EAAE,WAAW,aAAa,KAAK;EACrC,MAAM,EAAE,eAAe,KAAK;AAE5B,MAAI,aAAa,YAAY,KAAK,gBAAgB,WAAW,EAC3D,QAAO;GACL,KAAK,MAAM,mBAAmB;GAC9B,QAAQ;GACT;EAGH,MAAM,aACJ,KAAK,mCAAmC,iBAAiB;AAC3D,QAAM,YAAY,OAAO;AACzB,OACE,IAAI,YAAY,YAAY,aAAa,GACzC,YAAY,kBACZ,YAEA,QAAO,KAAK,cAAc,WAAW,MAAM;AAG7C,SAAO;GACL;GACA,QAAQ,KAAK,cAAc,kBAAkB,MAAM;GACpD;;CAGH,AAAO,uBACL,kBACqC;AACrC,MAAI,KAAK,QAAQ,QAAQ,KAAK,eAAe,KAC3C;EAGF,MAAM,EACJ,oBAAoB,OACpB,YAAY,OACZ,WAAW,aACT,KAAK;AACT,MAAI,aAAa,KAAK,YAAY,cAAc,EAC9C;EAGF,MAAM,gBAAgB,KAAK,aAAa,aAAa,KAAK,KAAK,GAAG;AAClE,MAAI,gBAAgB,EAClB;EAGF,MAAM,eAAe,2BACnB,KAAK,SACL,kBACD;EACD,MAAM,yBAAyB,KAAK,IAClC,KAAK,YAAY,cACjB,cACD;EACD,MAAM,wBAAwB,KAAK,IACjC,yBAAyB,KAAK,YAAY,aAAa,GACvD,cACD;AACD,MAAI,wBAAwB,uBAC1B;AAKF,MAAI,aAAa,YAAY,KAAK,gBAAgB,WAAW,GAAG;GAC9D,MAAM,EAAE,eAAe,KAAK;GAC5B,MAAM,uBAAuB,eAAe,KAAK,YAAY;GAK7D,MAAM,YAAY,yBAJK,KAAK,IAC1B,KAAK,MAAM,mBAAmB,wBAAwB,WAAW,EACjE,EACD;AAED,OAAI,YAAY,sBACd;AAGF,UAAO;IACL,YAAY,YAAY;IACxB,KAAK,eAAe,YAAY;IACjC;;EAIH,IAAI,MAAM,eAAe,KAAK,YAAY;AAC1C,OACE,IAAI,YAAY,wBAChB,aAAa,uBACb,aACA;AACA,OAAI,OAAO,iBACT,QAAO;IACL,YAAY,YAAY;IACxB;IACD;AAEH,UAAO,KAAK,cAAc,UAAU;;;CAMxC,AAAO,uBAA+B;AACpC,SAAO,KAAK;;CAGd,AAAO,uBACL,aACyB;AACzB,MAAI,KAAK,OAAO,QAAQ,KAAK,QAAQ,KACnC;AAEF,MAAI,KAAK,QAAQ,cAAc,KAC7B,QAAO;GAAE,WAAW,KAAK;GAAK,QAAQ,KAAK;GAAQ;EAErD,MAAM,cACJ,eAAe,OACX,KAAK,6BAA6B,KAAK,MAAM,KAAK,KAAK,YAAY,GACnE,KAAK;AACX,MAAI,eAAe,KACjB;EAEF,MAAM,EAAE,cAAc,aAAa,eAAe;EAalD,IAAI,mBAAmB;AACvB,MAAI,eAAe,GAAG;GACpB,MAAM,eAAe,eAAe,KAAK,YAAY,gBAAgB;AACrE,OAAI,KAAK,MAAM,aAAa,IAC1B,oBAAmB;;AAGvB,SAAO;GACL,WAAW,KAAK,MAAM,eAAe;GACrC,QAAQ,KAAK,UAAU,eAAe;GACvC;;CAGH,AAAS,QAAQ,UAAU,OAAa;AACtC,MAAI,KAAK,iBAAiB,QAAQ,KAAK,cAAc,CACnD,MAAK,sBAAsB,EAAE,WAAW,KAAK,cAAc;AAE7D,MAAI,CAAC,QACH,MAAK,cAAc;AAErB,OAAK,UAAU;AACf,QAAM,QAAQ,QAAQ;;CAKxB,AAAQ,uBAAuB,QAAQ,OAAa;EAClD,MAAM,qBAAqB,KAAK,0BAA0B;AAC1D,MAAI,CAAC,SAAS,CAAC,KAAK,eAAe,CAAC,mBAClC;EAGF,MAAM,iBAAiB,KAAK,WAAW;AACvC,OAAK,SAAS;AACd,OAAK,MAAM,cAAc,EAAE;AAC3B,MAAI,KAAK,QAAQ,MAAM;AACrB,QAAK,cAAc;AACnB;;EAGF,MAAM,EACJ,oBAAoB,OACpB,YAAY,OACZ,WAAW,aACT,KAAK;EACT,MAAM,EAAE,eAAe,KAAK;EAC5B,MAAM,YAAY,KAAK,aAAa,aAAa,KAAK,KAAK;EAC3D,MAAM,eAAe,2BACnB,KAAK,SACL,kBACD;EACD,MAAM,gBAAgB,4BAA4B,KAAK,QAAQ;AAE/D,OAAK,UAAU;AACf,MAAI,WAAW;AACb,QAAK,cAAc;AACnB;;AAGF,MAAI,aAAa,YAAY,KAAK,gBAAgB,WAAW,EAC3D,MAAK,UAAU,YAAY;MAE3B,MAAK,IAAI,YAAY,GAAG,YAAY,WAAW,aAAa;AAC1D,QAAK,oBAAoB,WAAW,KAAK,OAAO;AAChD,QAAK,UAAU,KAAK,cAAc,WAAW,MAAM;;AAIvD,MAAI,YAAY,EACd,MAAK,UAAU;AAGjB,MAAI,KAAK,iBAAiB,QAAQ,sBAAsB,CAAC,gBAAgB;GACvE,MAAM,OAAO,KAAK,cAAc,uBAAuB;AACvD,OAAI,KAAK,WAAW,KAAK,OACvB,SAAQ,IACN,wEACA;IACE,MAAM,KAAK,KAAK;IAChB,eAAe,KAAK;IACpB,gBAAgB,KAAK;IACtB,CACF;OAED,SAAQ,IACN,qEACD;;AAGL,OAAK,cAAc;;CAGrB,AAAO,cAAc,SAAwB;AAC3C,MAAI,KAAK,gBAAgB,IAAI,KAAK,iBAAiB,KACjD;AAEF,MAAI,WAAW,CAAC,KAAK,WAAW;AAC9B,QAAK,MAAM,KAAK,mBAAmB;AACnC,QAAK,YAAY;aACR,CAAC,WAAW,KAAK,WAAW;AACrC,QAAK,YAAY;AACjB,QAAK,UAAU;;;CAInB,AAAS,WAAiB;AACxB,MAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,KAChC;AAEF,OAAK,sBAAsB;AAC3B,OAAK,YAAY,gBAAgB,MAAM,MAAM;;CAG/C,AAAS,kBACP,cACA,oBACA,qBAAqB,OACf;EACN,MAAM,sBAAsB,KAAK;AACjC,QAAM,kBAAkB,cAAc,mBAAmB;AACzD,OAAK,sBAAsB,EAAE,cAAc;AAC3C,OAAK,iBAAiB,KAAK;AAG3B,MACE,sBACA,wBAAwB,UACxB,KAAK,SAAS,QACd;GACA,MAAM,cAAc,KAAK,YAAY,gBAAgB;GACrD,MAAM,cAAc,KAAK,6BACvB,KAAK,MACL,KAAK,OAAO,GACZ,YACD;AACD,OAAI,YAAY,gBAAgB,oBAAoB,YAClD,MAAK,cAAc,YAAY;;;CAKrC,AAAS,OAAO,EACd,eACA,MACA,cAAc,MACd,GAAG,SACqC;EACxC,MAAM,gBAAgB,KAAK,QAAQ,QAAQ,CAAC,cAAc,KAAK,MAAM,KAAK;EAC1E,MAAM,EAAE,qBAAqB,YAAY;AACzC,OAAK,sBAAsB;AAE3B,OAAK,OAAO;AAEZ,kBAAgB,KAAK,6BAA6B,cAAc;AAEhE,MAAI,KAAK,QAAQ,MAAM;AACrB,WAAQ,MACN,gFACD;AACD,UAAO;;AAGT,MAAI,CAAC,SAAS;AACZ,QAAK,wBAAwB;GAC7B,MAAM,cAAc,KAAK,sBAAsB;AAC/C,QAAK,QAAQ,KAAK,mBAAmB;AACrC,OAAI,KAAK,gBAAgB,CACvB,MAAK,YAAY;QACZ;AACL,QAAI,eAAe,KACjB,OAAM,IAAI,MACR,8DACD;AAEH,gBAAY,QAAQ,eAAe,KAAK;AACxC,SAAK,YAAY,YAAY,kBAC3B,KAAK,OAAO,GACZ,KAAK,OACN;;AAEH,QAAK,UAAU;SACV;AACL,QAAK,QAAQ,KAAK,mBAAmB;AACrC,OAAI,iBAAiB,KAAK,cAAc,EAAE;AACxC,SAAK,sBAAsB,EAAE,cAAc;AAC3C,SAAK,iBAAiB,KAAK;;;AAI/B,MAAI,CAAC,KAAK,aAAa,KAAK,cAAc,CACxC,QAAO,KAAK,kBAAkB,KAAK,OAAO;EAG5C,MAAM,cAAc,KAAK,YAAY,gBAAgB;EACrD,MAAM,UAAU,KAAK,OAAO;EAC5B,MAAM,cAAc,KAAK,6BACvB,KAAK,MACL,SACA,YACD;AACD,SAAO,MAAM,OAAO;GAClB,MAAM,KAAK;GACX;GACA;GACA,aAAa,uBAAuB;GACpC,GAAG;GACJ,CAAC;;CAGJ,AAAO,qBAA2B;AAChC,OAAK,MAAM,KAAK,mBAAmB;;CAGrC,AAAmB,qCAA8C;AAC/D,SAAO,KAAK,gBAAgB,IAAI,MAAM,oCAAoC;;CAG5E,AAAQ,eAAwB;AAC9B,SAAO,KAAK,YAAY,SAAS;;CAGnC,AAAQ,iBAA0B;AAChC,SAAO,KAAK,YAAY,SAAS;;CAGnC,AAAQ,oBAAoB,WAAmB,KAAmB;AAChE,MAAI,YAAY,+BAA+B,EAC7C;AAEF,OAAK,MAAM,YAAY,KAAK;GAAE;GAAW;GAAK,CAAC;;CAOjD,AAAQ,mCACN,WACkC;AAClC,MAAI,aAAa,KAAK,KAAK,MAAM,YAAY,WAAW,EACtD;EAGF,IAAI,MAAM;EACV,IAAI,OAAO,KAAK,MAAM,YAAY,SAAS;EAC3C,IAAIC;AAEJ,SAAO,OAAO,MAAM;GAClB,MAAM,MAAO,MAAM,QAAS;GAC5B,MAAM,aAAa,KAAK,MAAM,YAAY;AAC1C,OAAI,cAAc,KAChB,OAAM,IAAI,MAAM,4CAA4C;AAE9D,OAAI,WAAW,aAAa,WAAW;AACrC,aAAS;AACT,UAAM,MAAM;SAEZ,QAAO,MAAM;;AAIjB,SAAO;;CAQT,AAAQ,6BACN,KACA,eACkC;EAClC,IAAI,MAAM;EACV,IAAI,OAAO,KAAK,MAAM,YAAY,SAAS;EAC3C,IAAI,cAAc;AAElB,SAAO,OAAO,MAAM;GAClB,MAAM,MAAO,MAAM,QAAS;GAC5B,MAAM,aAAa,KAAK,MAAM,YAAY;AAC1C,OAAI,cAAc,KAChB,OAAM,IAAI,MAAM,4CAA4C;AAE9D,OAAI,WAAW,OAAO,KAAK;AACzB,kBAAc;AACd,UAAM,MAAM;SAEZ,QAAO,MAAM;;AAIjB,MAAI,iBAAiB,KACnB,QAAO,eAAe,IAAI,KAAK,MAAM,YAAY,eAAe;AAGlE,OAAK,IAAI,QAAQ,aAAa,SAAS,GAAG,SAAS;GACjD,MAAM,aAAa,KAAK,MAAM,YAAY;AAC1C,OAAI,cAAc,KAChB,OAAM,IAAI,MAAM,4CAA4C;AAE9D,OAAI,WAAW,YAAY,kBAAkB,EAC3C,QAAO;;;CAOb,AAAQ,oBAA4B;AAClC,MAAI,KAAK,YAAY,SAAS,WAC5B,QAAO,KAAK,YAAY,uBAAuB,KAAK;AAEtD,SAAO,KAAK,iBAAiB,OACzB,KAAK,YAAY,2BAA2B,KAAK,cAAc,GAC/D;;CAGN,AAAQ,uBAAgD;AACtD,SAAO,KAAK,YAAY,SAAS,WAAW,KAAK,cAAc;;CAGjE,AAAQ,2BAAoC;AAC1C,SAAO,KAAK,sBAAsB,EAAE,OAAO,mBAAmB;;CAGhE,AAAQ,6BACN,MACA,SACA,EAAE,KAAK,UACM;EACb,MAAM,EAAE,oBAAoB,OAAO,WAAW,aAAa,KAAK;EAChE,MAAM,EAAE,eAAe,eAAe,KAAK;EAC3C,MAAM,YAAY,KAAK,aAAa,aAAa,KAAK;EACtD,MAAM,aAAa,KAAK;EACxB,MAAM,eAAe,2BACnB,KAAK,SACL,kBACD;EACD,MAAM,gBACJ,YAAY,IAAI,4BAA4B,KAAK,QAAQ,GAAG;AAG9D,MAAI,UAAU,MAAM,cAAc,UAAU,OAC1C,QAAO;GACL,cAAc;GACd,YAAY;GACZ,cAAc;GACd,aAAa,aAAa,eAAe;GAC1C;AAIH,MAAI,aAAa,cACf,QAAO;GACL,cAAc;GACd,YAAY;GACZ,cAAc;GACd,aAAa;GACd;EAIH,MAAM,uBAAuB,KAAK,KAChC,KAAK,IAAI,SAAS,KAAK,EAAE,GAAG,WAC7B;EACD,MAAM,aACJ,KAAK,KAAK,uBAAuB,cAAc,GAAG,gBAClD,gBAAgB;EAClB,MAAM,aAAa,aAAa;EAChC,MAAM,kBAAkB,MAAM,UAAU;AAGxC,MAAI,aAAa,YAAY,KAAK,gBAAgB,WAAW,GAAG;GAE9D,MAAM,aAAa,KAAK,OACrB,kBAAkB,UAAU,iBAAiB,WAC/C;GAID,MAAMC,mBAHa,KAAK,MAAM,aAAa,cAAc,GAGrB,KAAK,MAAM,aAAa,EAAE;GAC9D,MAAM,mBAAmB,KAAK,KAAK,YAAY,cAAc;GAC7D,MAAMC,iBACJ,KAAK,IAAI,GAAG,KAAK,IAAID,kBAAgB,iBAAiB,CAAC,GAAG;GAE5D,MAAME,sBACJF,mBAAiB,IACb,aAAaA,mBAAiB,gBAC9B;GAEN,MAAMG,iBAAeF,iBAAe;GACpC,MAAM,gBAAgB,KAAK,IACzBC,qBACA,YAAYD,eACb;AAMD,UAAO;IACL;IACA,YAAYC;IACZ;IACA,aATkB,KAAK,IACvB,IACC,YAAYD,iBAAe,iBAAiB,WAC9C;IAOA;;EAIH,MAAM,gBAAgB;EACtB,MAAMG,cAAwB,EAAE;EAIhC,MAAM,aAAa,KAAK,6BACtB,KAAK,IAAI,GAAG,MAAM,UAAU,aAAa,aAAa,EAAE,EACxD,cACD;EAED,IAAI,kBAAkB,WAAW,YAAY,OAAO;EACpD,IAAI,cAAc,YAAY,aAAa;EAC3C,IAAIC;EACJ,IAAIC;EACJ,IAAIC;EAEJ,MAAM,oBAAoB,YAAY,aAAa;AACnD,OACE,IAAI,YAAY,mBAChB,YAAY,WACZ,aACA;GACA,MAAM,mBAAmB,cAAc,kBAAkB;GACzD,MAAM,cAAc,KAAK,MAAM,cAAc,cAAc;AAE3D,OAAI,kBAAkB;AACpB,gBAAY,eAAe,mBAAmB,UAAU;AAExD,QAAI,mBAAmB,MAAM;AAC3B,SAAI,mBAAmB,EACrB;AAEF;;;GAIJ,MAAMC,eAAa,KAAK,cAAc,WAAW,MAAM;AAGvD,OAAI,kBAAkB,MAAMA,gBAAc,kBAAkB,OAC1D,sBAAqB;AAIvB,OAAI,kBAAkBA,eAAa,eACjC,gBAAe;AAIjB,OACE,mBAAmB,QACnB,mBAAmB,UACnB,iBAEA,mBAAkB;AAGpB;AACA,sBAAmBA;;AAIrB,MAAI,oBAAoB,KACtB,QAAO;GACL,cAAc;GACd,YAAY;GACZ,cAAc;GACd,aAAa,aAAa,eAAe;GAC1C;AAIH,iBAAe;EACf,MAAM,iBAAiB,KAAK,MAAM,aAAa,aAAa,EAAE;EAI9D,MAAM,eAAe,KAAK,IACxB,GACA,KAAK,KAAK,YAAY,cAAc,GAAG,WACxC;EACD,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,gBAAgB,aAAa,CAAC;EACrE,MAAM,eAAe,YAAY;EAGjC,MAAM,oBACJ,iBAAiB,IACb,aAAa,iBAAiB,gBAC9B;EAGN,MAAM,eAAe,YAAY,cAAc;EAG/C,MAAM,iBAAiB,YAAY,oBAAoB;AASvD,SAAO;GACL;GACA,YAAY;GACZ;GACA,aAXA,iBAAiB,YAAY,SACzB,aACA,eACA,YAAY,kBACZ,gBACA,cAAc,kBAAkB,WAAW;GAOhD"}
1
+ {"version":3,"file":"VirtualizedFile.js","names":["virtualizer: Virtualizer | CodeView<LAnnotation>","metrics: VirtualFileMetrics","result: FileLayoutCheckpoint | undefined","idealStartHunk","startingLine","clampedTotalLines","bufferBefore","hunkOffsets: number[]","firstVisibleHunk: number | undefined","centerHunk: number | undefined","overflowCounter: number | undefined","lineHeight","height: number | undefined"],"sources":["../../src/components/VirtualizedFile.ts"],"sourcesContent":["import { DEFAULT_VIRTUAL_FILE_METRICS } from '../constants';\nimport type {\n DiffsTextDocument,\n FileContents,\n LineAnnotation,\n NumericScrollLineAnchor,\n PendingCodeViewLayoutReset,\n RenderRange,\n RenderWindow,\n StickySpecs,\n ThemeTypes,\n VirtualFileMetrics,\n} from '../types';\nimport { areFilesEqual } from '../utils/areFilesEqual';\nimport { areObjectsEqual } from '../utils/areObjectsEqual';\nimport { areOptionsEqual } from '../utils/areOptionsEqual';\nimport {\n getVirtualFileHeaderRegion,\n getVirtualFilePaddingBottom,\n} from '../utils/computeVirtualFileMetrics';\nimport {\n FILE_ANNOTATION_DOM_KEY,\n FILE_ANNOTATION_LINE_NUMBER,\n includesFileAnnotations,\n shouldRenderFileAnnotations,\n} from '../utils/includesFileAnnotations';\nimport type { WorkerPoolManager } from '../worker';\nimport type { CodeView } from './CodeView';\nimport { File, type FileOptions, type FileRenderProps } from './File';\nimport type { Virtualizer } from './Virtualizer';\n\ninterface FileLayoutCheckpoint {\n lineIndex: number;\n top: number;\n}\n\ninterface FileLayoutCache {\n // Sparse map: line index -> measured height. Only stores lines that differ\n // from what is returned by `getLineHeight`.\n heights: Map<number, number>;\n // Sparse measured positions used to resume deep geometry scans near a target\n // line or scroll offset instead of replaying layout from the start.\n checkpoints: FileLayoutCheckpoint[];\n // Measured height for the file-level annotation row. Starts at 0 so\n // unmeasured annotations behave like all other unmeasured annotations.\n fileAnnotationHeight: number;\n}\n\nconst LAYOUT_CHECKPOINT_INTERVAL = 5_000;\n\nlet instanceId = -1;\n\nfunction hasFileLayoutOptionChanged<LAnnotation>(\n previousOptions: FileOptions<LAnnotation>,\n nextOptions: FileOptions<LAnnotation>\n): boolean {\n return (\n (previousOptions.overflow ?? 'scroll') !==\n (nextOptions.overflow ?? 'scroll') ||\n (previousOptions.collapsed ?? false) !== (nextOptions.collapsed ?? false) ||\n (previousOptions.disableLineNumbers ?? false) !==\n (nextOptions.disableLineNumbers ?? false) ||\n (previousOptions.disableFileHeader ?? false) !==\n (nextOptions.disableFileHeader ?? false) ||\n previousOptions.unsafeCSS !== nextOptions.unsafeCSS\n );\n}\n\nexport class VirtualizedFile<\n LAnnotation = undefined,\n> extends File<LAnnotation> {\n override readonly __id: string = `virtualized-file:${++instanceId}`;\n\n public top: number | undefined;\n public height: number = 0;\n private cache: FileLayoutCache = {\n heights: new Map(),\n checkpoints: [],\n fileAnnotationHeight: 0,\n };\n private isVisible: boolean = false;\n private isSetup: boolean = false;\n private layoutDirty = true;\n private forceRenderOverride: true | undefined;\n private currentCollapsed: boolean | undefined;\n\n constructor(\n options: FileOptions<LAnnotation> | undefined,\n private virtualizer: Virtualizer | CodeView<LAnnotation>,\n private metrics: VirtualFileMetrics = DEFAULT_VIRTUAL_FILE_METRICS,\n workerManager?: WorkerPoolManager,\n isContainerManaged = false\n ) {\n super(options, workerManager, isContainerManaged);\n }\n\n public setMetrics(metrics: VirtualFileMetrics, force = false): void {\n if (!force && areObjectsEqual(this.metrics, metrics)) {\n return;\n }\n\n this.metrics = metrics;\n this.resetLayoutCache();\n }\n\n override setLineAnnotations(\n lineAnnotations: LineAnnotation<LAnnotation>[]\n ): void {\n if (this.syncLineAnnotations(lineAnnotations)) {\n this.resetLayoutCache();\n }\n }\n\n private syncLineAnnotations(\n lineAnnotations: LineAnnotation<LAnnotation>[] | undefined\n ): boolean {\n if (lineAnnotations == null || lineAnnotations === this.lineAnnotations) {\n return false;\n }\n if (lineAnnotations.length === 0 && this.lineAnnotations.length === 0) {\n return false;\n }\n\n super.setLineAnnotations(lineAnnotations);\n return true;\n }\n\n private hasLineAnnotations(): boolean {\n return this.lineAnnotations.some(\n (annotation) => annotation.lineNumber > FILE_ANNOTATION_LINE_NUMBER\n );\n }\n\n // Get the height for a line, using cached value if available.\n // If not cached and hasMetadataLine is true, adds lineHeight for the\n // metadata.\n public getLineHeight(lineIndex: number, hasMetadataLine = false): number {\n const cached = this.cache.heights.get(lineIndex);\n if (cached != null) {\n return cached;\n }\n const multiplier = hasMetadataLine ? 2 : 1;\n return this.metrics.lineHeight * multiplier;\n }\n\n override setOptions(options: FileOptions<LAnnotation> | undefined): void {\n if (this.isAdvancedMode()) {\n throw new Error(\n 'VirtualizedFile.setOptions cannot be used inside CodeView. Update CodeView options instead.'\n );\n }\n\n if (options == null) return;\n const { options: previousOptions } = this;\n const optionsChanged = !areOptionsEqual(previousOptions, options);\n const layoutChanged = hasFileLayoutOptionChanged(previousOptions, options);\n\n super.setOptions(options);\n\n if (layoutChanged) {\n this.resetLayoutCache(true);\n }\n // Any option can affect rendered DOM; only layout-affecting options clear\n // the measured height cache above.\n if (optionsChanged) {\n this.forceRenderOverride = true;\n }\n if (optionsChanged) {\n this.virtualizer.instanceChanged(this, layoutChanged);\n }\n }\n\n override setThemeType(themeType: ThemeTypes): void {\n if (this.isAdvancedMode()) {\n throw new Error(\n 'VirtualizedFile.setThemeType cannot be used inside CodeView. Update CodeView options instead.'\n );\n }\n\n super.setThemeType(themeType);\n }\n\n private resetLayoutCache(recompute = false): void {\n this.layoutDirty = true;\n this.cache.fileAnnotationHeight = 0;\n if (this.cache.heights.size > 0) {\n this.cache.heights.clear();\n }\n if (this.cache.checkpoints.length > 0) {\n this.cache.checkpoints.length = 0;\n }\n if (this.renderRange != null) {\n this.renderRange = undefined;\n }\n // NOTE(amadeus): In CodeView we intentionally batch computes to all happen\n // at the same time, so we shouldn't trigger this there.\n if (recompute && this.isSimpleMode()) {\n this.computeApproximateSize();\n }\n }\n\n // Measure rendered lines and update height cache.\n // Called after render to reconcile estimated vs actual heights.\n public reconcileHeights(): boolean {\n let hasHeightChange = false;\n if (this.fileContainer == null || this.file == null) {\n if (this.height !== 0) {\n hasHeightChange = true;\n }\n this.height = 0;\n return hasHeightChange;\n }\n const { overflow = 'scroll' } = this.options;\n this.top = this.getVirtualizedTop();\n\n // If the file has no annotations and we are using the scroll variant, then\n // we can probably skip everything\n if (\n overflow === 'scroll' &&\n this.lineAnnotations.length === 0 &&\n !this.isResizeDebuggingEnabled()\n ) {\n return hasHeightChange;\n }\n\n // Single code element (no split mode)\n if (this.code == null) {\n return hasHeightChange;\n }\n const content = this.code.children[1]; // Content column (gutter is [0])\n if (!(content instanceof HTMLElement)) {\n return hasHeightChange;\n }\n\n const hasFileAnnotations = includesFileAnnotations(this.lineAnnotations);\n if (\n this.renderRange != null &&\n hasFileAnnotations &&\n shouldRenderFileAnnotations(this.renderRange)\n ) {\n const fileAnnotationHeight = measureFileAnnotationHeight(content);\n const nextFileAnnotationHeight = fileAnnotationHeight ?? 0;\n if (nextFileAnnotationHeight !== this.cache.fileAnnotationHeight) {\n this.cache.fileAnnotationHeight = nextFileAnnotationHeight;\n hasHeightChange = true;\n }\n } else if (!hasFileAnnotations && this.cache.fileAnnotationHeight !== 0) {\n this.cache.fileAnnotationHeight = 0;\n hasHeightChange = true;\n }\n\n for (const line of content.children) {\n if (!(line instanceof HTMLElement)) continue;\n\n const lineIndexAttr = line.dataset.lineIndex;\n if (lineIndexAttr == null) continue;\n\n const lineIndex = Number(lineIndexAttr);\n let measuredHeight = line.getBoundingClientRect().height;\n let hasMetadata = false;\n\n // Annotations or noNewline metadata increase the size of their attached line\n if (\n line.nextElementSibling instanceof HTMLElement &&\n ('lineAnnotation' in line.nextElementSibling.dataset ||\n 'noNewline' in line.nextElementSibling.dataset)\n ) {\n if ('noNewline' in line.nextElementSibling.dataset) {\n hasMetadata = true;\n }\n measuredHeight +=\n line.nextElementSibling.getBoundingClientRect().height;\n }\n\n const expectedHeight = this.getLineHeight(lineIndex, hasMetadata);\n\n if (measuredHeight === expectedHeight) {\n continue;\n }\n\n hasHeightChange = true;\n // Line is back to standard height (e.g., after window resize)\n // Remove from cache\n if (measuredHeight === this.metrics.lineHeight * (hasMetadata ? 2 : 1)) {\n this.cache.heights.delete(lineIndex);\n }\n // Non-standard height, cache it\n else {\n this.cache.heights.set(lineIndex, measuredHeight);\n }\n }\n\n if (hasHeightChange || this.isResizeDebuggingEnabled()) {\n this.computeApproximateSize(true);\n }\n return hasHeightChange;\n }\n\n public onRender = (dirty: boolean): boolean => {\n if (this.fileContainer == null || this.file == null) {\n return false;\n }\n if (dirty) {\n this.top = this.getVirtualizedTop();\n }\n return this.render({ file: this.file });\n };\n\n // Prepares this item for CodeView layout by binding the latest file, syncing\n // its virtualized top, and returning an approximate height. This method is\n // called while downstream items are being re-positioned, so later changes\n // should keep clean instances on a cached-height fast path.\n public prepareCodeViewItem(\n file: FileContents,\n top: number,\n reset?: PendingCodeViewLayoutReset,\n lineAnnotations?: LineAnnotation<LAnnotation>[]\n ): number {\n const annotationsChanged = this.syncLineAnnotations(lineAnnotations);\n let shouldResetLayoutCache =\n reset?.resetFileLayoutCache === true || annotationsChanged;\n if (reset?.metrics != null) {\n this.metrics = reset.metrics;\n shouldResetLayoutCache = true;\n }\n\n const { collapsed = false } = this.options;\n if (this.currentCollapsed !== collapsed) {\n this.currentCollapsed = collapsed;\n shouldResetLayoutCache = true;\n }\n\n if (shouldResetLayoutCache) {\n this.resetLayoutCache();\n }\n\n if (this.file !== file) {\n this.layoutDirty = true;\n }\n this.file = file;\n this.top = top;\n this.computeApproximateSize();\n return this.height;\n }\n\n public getLinePosition(\n lineNumber: number\n ): { top: number; height: number } | undefined {\n if (this.file == null || lineNumber < 1) {\n return undefined;\n }\n\n const { disableFileHeader = false, collapsed = false } = this.options;\n const lastLineIndex = this.fileRenderer.getLineCount(this.file) - 1;\n let top = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);\n\n if (collapsed || lastLineIndex < 0) {\n return { top, height: 0 };\n }\n\n const clampedLineIndex = Math.min(\n Math.max(lineNumber - 1, 0),\n lastLineIndex\n );\n const { overflow = 'scroll' } = this.options;\n const { lineHeight } = this.metrics;\n top += this.cache.fileAnnotationHeight;\n\n if (overflow === 'scroll' && !this.hasLineAnnotations()) {\n return {\n top: top + clampedLineIndex * lineHeight,\n height: lineHeight,\n };\n }\n\n const checkpoint =\n this.getLayoutCheckpointBeforeLineIndex(clampedLineIndex);\n top = checkpoint?.top ?? top;\n for (\n let lineIndex = checkpoint?.lineIndex ?? 0;\n lineIndex < clampedLineIndex;\n lineIndex++\n ) {\n top += this.getLineHeight(lineIndex, false);\n }\n\n return {\n top,\n height: this.getLineHeight(clampedLineIndex, false),\n };\n }\n\n public getNumericScrollAnchor(\n localViewportTop: number\n ): NumericScrollLineAnchor | undefined {\n if (this.file == null || this.renderRange == null) {\n return undefined;\n }\n\n const {\n disableFileHeader = false,\n collapsed = false,\n overflow = 'scroll',\n } = this.options;\n if (collapsed || this.renderRange.totalLines <= 0) {\n return undefined;\n }\n\n const lastLineIndex = this.fileRenderer.getLineCount(this.file) - 1;\n if (lastLineIndex < 0) {\n return undefined;\n }\n\n const headerRegion = getVirtualFileHeaderRegion(\n this.metrics,\n disableFileHeader\n );\n const firstRenderedLineIndex = Math.min(\n this.renderRange.startingLine,\n lastLineIndex\n );\n const lastRenderedLineIndex = Math.min(\n firstRenderedLineIndex + this.renderRange.totalLines - 1,\n lastLineIndex\n );\n if (lastRenderedLineIndex < firstRenderedLineIndex) {\n return undefined;\n }\n const { fileAnnotationHeight } = this.cache;\n\n // If we don't allow line wrapping and have no annotations, we can just\n // multiply our way to the the correct value\n if (overflow === 'scroll' && !this.hasLineAnnotations()) {\n const { lineHeight } = this.metrics;\n const firstRenderedLineTop =\n headerRegion +\n (firstRenderedLineIndex === 0\n ? fileAnnotationHeight\n : this.renderRange.bufferBefore);\n const deltaLineCount = Math.max(\n Math.ceil((localViewportTop - firstRenderedLineTop) / lineHeight),\n 0\n );\n const lineIndex = firstRenderedLineIndex + deltaLineCount;\n if (lineIndex > lastRenderedLineIndex) {\n return undefined;\n }\n\n return {\n lineNumber: lineIndex + 1,\n top: headerRegion + fileAnnotationHeight + lineIndex * lineHeight,\n };\n }\n\n // Otherwise we gotta iterate through the range\n let top =\n headerRegion +\n (firstRenderedLineIndex === 0\n ? fileAnnotationHeight\n : this.renderRange.bufferBefore);\n for (\n let lineIndex = firstRenderedLineIndex;\n lineIndex <= lastRenderedLineIndex;\n lineIndex++\n ) {\n if (top >= localViewportTop) {\n return {\n lineNumber: lineIndex + 1,\n top,\n };\n }\n top += this.getLineHeight(lineIndex);\n }\n\n return undefined;\n }\n\n public getVirtualizedHeight(): number {\n return this.height;\n }\n\n public getAdvancedStickySpecs(\n windowSpecs?: RenderWindow\n ): StickySpecs | undefined {\n if (this.top == null || this.file == null) {\n return undefined;\n }\n if (this.options.collapsed === true) {\n return { topOffset: this.top, height: this.height };\n }\n const renderRange =\n windowSpecs != null\n ? this.computeRenderRangeFromWindow(this.file, this.top, windowSpecs)\n : this.renderRange;\n if (renderRange == null) {\n return undefined;\n }\n const { bufferBefore, bufferAfter, totalLines } = renderRange;\n // Rendered items flow contiguously in the sticky container with no buffer\n // spacers, so a header-only item (totalLines === 0, none of its rows fall\n // inside the window) must report where its header actually sits in that\n // flow, which depends on which side of the window its content is on:\n // - content ABOVE the window (item starts above window.top): the header\n // sits at the item's bottom so the following item connects, so offset by\n // bufferAfter.\n // - content BELOW the window (item starts at/after window.top, e.g. a\n // trailing header peeking in at the bottom): the header renders at the\n // item's top with nothing after it, so no offset. Always adding\n // bufferAfter here made getStickyBounds over-measure the sticky\n // container for that trailing case.\n let headerOnlyOffset = 0;\n if (totalLines === 0) {\n const activeWindow = windowSpecs ?? this.virtualizer.getWindowSpecs();\n if (this.top < activeWindow.top) {\n headerOnlyOffset = bufferAfter;\n }\n }\n return {\n topOffset: this.top + bufferBefore + headerOnlyOffset,\n height: this.height - (bufferBefore + bufferAfter),\n };\n }\n\n override cleanUp(recycle = false): void {\n if (this.fileContainer != null && this.isSimpleMode()) {\n this.getSimpleVirtualizer()?.disconnect(this.fileContainer);\n }\n if (!recycle) {\n this.resetLayoutCache();\n }\n this.isSetup = false;\n super.cleanUp(recycle);\n }\n\n // Compute the approximate size of the file using cached line heights.\n // Uses lineHeight for lines without cached measurements.\n private computeApproximateSize(force = false): void {\n const shouldValidateSize = this.isResizeDebuggingEnabled();\n if (!force && !this.layoutDirty && !shouldValidateSize) {\n return;\n }\n\n const isFirstCompute = this.height === 0;\n this.height = 0;\n this.cache.checkpoints = [];\n if (this.file == null) {\n this.layoutDirty = false;\n return;\n }\n\n const {\n disableFileHeader = false,\n collapsed = false,\n overflow = 'scroll',\n } = this.options;\n const { lineHeight } = this.metrics;\n const lineCount = this.fileRenderer.getLineCount(this.file);\n const headerRegion = getVirtualFileHeaderRegion(\n this.metrics,\n disableFileHeader\n );\n const paddingBottom = getVirtualFilePaddingBottom(this.metrics);\n\n this.height += headerRegion;\n if (collapsed) {\n this.layoutDirty = false;\n return;\n }\n\n this.height += this.cache.fileAnnotationHeight;\n\n if (overflow === 'scroll' && !this.hasLineAnnotations()) {\n this.height += lineCount * lineHeight;\n } else {\n for (let lineIndex = 0; lineIndex < lineCount; lineIndex++) {\n this.addLayoutCheckpoint(lineIndex, this.height);\n this.height += this.getLineHeight(lineIndex, false);\n }\n }\n\n if (lineCount > 0) {\n this.height += paddingBottom;\n }\n\n if (this.fileContainer != null && shouldValidateSize && !isFirstCompute) {\n const rect = this.fileContainer.getBoundingClientRect();\n if (rect.height !== this.height) {\n console.log(\n 'VirtualizedFile.computeApproximateSize: computed height doesnt match',\n {\n name: this.file.name,\n elementHeight: rect.height,\n computedHeight: this.height,\n }\n );\n } else {\n console.log(\n 'VirtualizedFile.computeApproximateSize: computed height IS CORRECT'\n );\n }\n }\n this.layoutDirty = false;\n }\n\n public setVisibility(visible: boolean): void {\n if (this.isAdvancedMode() || this.fileContainer == null) {\n return;\n }\n if (visible && !this.isVisible) {\n this.top = this.getVirtualizedTop();\n this.isVisible = true;\n } else if (!visible && this.isVisible) {\n this.isVisible = false;\n this.rerender();\n }\n }\n\n override rerender(): void {\n if (!this.enabled || this.file == null) {\n return;\n }\n this.forceRenderOverride = true;\n this.virtualizer.instanceChanged(this, false);\n }\n\n // normally triggered by the editor when the document line count changes\n override applyDocumentChange(\n textDocument: DiffsTextDocument,\n newLineAnnotations?: LineAnnotation<LAnnotation>[],\n shouldUpdateBuffer = false\n ): void {\n const { heights, checkpoints } = this.cache;\n const previousRenderRange = this.renderRange;\n\n super.applyDocumentChange(textDocument, newLineAnnotations);\n\n // reset the layout cache\n this.getSimpleVirtualizer()?.markDOMDirty();\n this.layoutDirty = true;\n if (heights.size > 0) {\n heights.clear();\n }\n if (checkpoints.length > 0) {\n checkpoints.length = 0;\n }\n if (this.isSimpleMode()) {\n this.computeApproximateSize();\n }\n\n // Update the buffers caused by the line-count change to ensure the editor\n // scrolls to the correct position before re-rendering\n if (\n shouldUpdateBuffer &&\n previousRenderRange !== undefined &&\n this.file !== undefined\n ) {\n const windowSpecs = this.virtualizer.getWindowSpecs();\n const renderRange = this.computeRenderRangeFromWindow(\n this.file,\n this.top ?? 0,\n windowSpecs\n );\n if (renderRange.bufferAfter !== previousRenderRange.bufferAfter) {\n this.updateBuffers(renderRange);\n }\n }\n }\n\n override render({\n fileContainer,\n file,\n forceRender = false,\n lineAnnotations,\n ...props\n }: FileRenderProps<LAnnotation>): boolean {\n const didFileChange = this.file == null || !areFilesEqual(this.file, file);\n const { forceRenderOverride, isSetup } = this;\n this.forceRenderOverride = undefined;\n const annotationsChanged = this.syncLineAnnotations(lineAnnotations);\n if (annotationsChanged) {\n this.resetLayoutCache();\n }\n\n this.file = file;\n\n fileContainer = this.getOrCreateFileContainerNode(fileContainer);\n\n if (this.file == null) {\n console.error(\n 'VirtualizedFile.render: attempting to virtually render when we dont have file'\n );\n return false;\n }\n\n if (!isSetup) {\n this.computeApproximateSize();\n const virtualizer = this.getSimpleVirtualizer();\n this.top ??= this.getVirtualizedTop();\n if (this.isAdvancedMode()) {\n this.isVisible = true;\n } else {\n if (virtualizer == null) {\n throw new Error(\n 'VirtualizedFile.render: simple virtualizer is not available'\n );\n }\n virtualizer.connect(fileContainer, this);\n this.isVisible = virtualizer.isInstanceVisible(\n this.top ?? 0,\n this.height\n );\n }\n this.isSetup = true;\n } else {\n this.top ??= this.getVirtualizedTop();\n if (didFileChange && this.isSimpleMode()) {\n this.getSimpleVirtualizer()?.markDOMDirty();\n this.resetLayoutCache(true);\n }\n }\n\n if (!this.isVisible && this.isSimpleMode()) {\n return this.renderPlaceholder(this.height);\n }\n\n const windowSpecs = this.virtualizer.getWindowSpecs();\n const fileTop = this.top ?? 0;\n const renderRange = this.computeRenderRangeFromWindow(\n this.file,\n fileTop,\n windowSpecs\n );\n return super.render({\n file: this.file,\n fileContainer,\n renderRange,\n lineAnnotations,\n forceRender: (forceRenderOverride ?? forceRender) || annotationsChanged,\n ...props,\n });\n }\n\n public syncVirtualizedTop(): void {\n this.top = this.getVirtualizedTop();\n }\n\n protected override shouldDisableVirtualizationBuffers(): boolean {\n return this.isAdvancedMode() || super.shouldDisableVirtualizationBuffers();\n }\n\n private isSimpleMode(): boolean {\n return this.virtualizer.type === 'simple';\n }\n\n private isAdvancedMode(): boolean {\n return this.virtualizer.type === 'advanced';\n }\n\n private addLayoutCheckpoint(lineIndex: number, top: number): void {\n if (lineIndex % LAYOUT_CHECKPOINT_INTERVAL !== 0) {\n return;\n }\n this.cache.checkpoints.push({ lineIndex, top });\n }\n\n // Find the nearest sparse layout checkpoint at or before a raw file line.\n // Checkpoints store measured `top` offsets every few thousand lines, so a\n // binary search lets deep line-position lookups resume from that checkpoint\n // instead of replaying layout from the start of the file.\n private getLayoutCheckpointBeforeLineIndex(\n lineIndex: number\n ): FileLayoutCheckpoint | undefined {\n if (lineIndex <= 0 || this.cache.checkpoints.length === 0) {\n return undefined;\n }\n\n let low = 0;\n let high = this.cache.checkpoints.length - 1;\n let result: FileLayoutCheckpoint | undefined;\n\n while (low <= high) {\n const mid = (low + high) >> 1;\n const checkpoint = this.cache.checkpoints[mid];\n if (checkpoint == null) {\n throw new Error('VirtualizedFile: invalid checkpoint index');\n }\n if (checkpoint.lineIndex <= lineIndex) {\n result = checkpoint;\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n return result;\n }\n\n // Find the nearest sparse layout checkpoint at or before a scroll offset.\n // Render-range scans start from this checkpoint so variable-height files\n // only replay the nearby measured rows. When `hunkLineCount` is provided,\n // step backward to a hunk boundary so hooks that depend on grouped lines\n // still see a complete hunk.\n private getLayoutCheckpointBeforeTop(\n top: number,\n hunkLineCount?: number\n ): FileLayoutCheckpoint | undefined {\n let low = 0;\n let high = this.cache.checkpoints.length - 1;\n let resultIndex = -1;\n\n while (low <= high) {\n const mid = (low + high) >> 1;\n const checkpoint = this.cache.checkpoints[mid];\n if (checkpoint == null) {\n throw new Error('VirtualizedFile: invalid checkpoint index');\n }\n if (checkpoint.top <= top) {\n resultIndex = mid;\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n if (hunkLineCount == null) {\n return resultIndex >= 0 ? this.cache.checkpoints[resultIndex] : undefined;\n }\n\n for (let index = resultIndex; index >= 0; index--) {\n const checkpoint = this.cache.checkpoints[index];\n if (checkpoint == null) {\n throw new Error('VirtualizedFile: invalid checkpoint index');\n }\n if (checkpoint.lineIndex % hunkLineCount === 0) {\n return checkpoint;\n }\n }\n\n return undefined;\n }\n\n private getVirtualizedTop(): number {\n if (this.virtualizer.type === 'advanced') {\n return this.virtualizer.getLocalTopForInstance(this);\n }\n return this.fileContainer != null\n ? this.virtualizer.getOffsetInScrollContainer(this.fileContainer)\n : 0;\n }\n\n private getSimpleVirtualizer(): Virtualizer | undefined {\n return this.virtualizer.type === 'simple' ? this.virtualizer : undefined;\n }\n\n private isResizeDebuggingEnabled(): boolean {\n return this.getSimpleVirtualizer()?.config.resizeDebugging ?? false;\n }\n\n private computeRenderRangeFromWindow(\n file: FileContents,\n fileTop: number,\n { top, bottom }: RenderWindow\n ): RenderRange {\n const { disableFileHeader = false, overflow = 'scroll' } = this.options;\n const { hunkLineCount, lineHeight } = this.metrics;\n const lineCount = this.fileRenderer.getLineCount(file);\n const fileHeight = this.height;\n const headerRegion = getVirtualFileHeaderRegion(\n this.metrics,\n disableFileHeader\n );\n const paddingBottom =\n lineCount > 0 ? getVirtualFilePaddingBottom(this.metrics) : 0;\n const { fileAnnotationHeight } = this.cache;\n const codeRegionTop = headerRegion + fileAnnotationHeight;\n const codeRowsHeight = Math.max(\n 0,\n fileHeight - headerRegion - fileAnnotationHeight - paddingBottom\n );\n const hasFileAnnotations = includesFileAnnotations(this.lineAnnotations);\n const fileAnnotationTop = fileTop + headerRegion;\n const measuredFileAnnotationVisible =\n fileAnnotationHeight > 0 &&\n hasFileAnnotations &&\n fileAnnotationTop < bottom &&\n fileAnnotationTop + fileAnnotationHeight > top;\n\n // File is outside render window\n if (fileTop < top - fileHeight || fileTop > bottom) {\n return {\n startingLine: 0,\n totalLines: 0,\n bufferBefore: 0,\n bufferAfter: fileHeight - headerRegion - paddingBottom,\n };\n }\n\n // Small file, just render it all\n if (lineCount <= hunkLineCount) {\n return {\n startingLine: 0,\n totalLines: hunkLineCount,\n bufferBefore: 0,\n bufferAfter: 0,\n };\n }\n\n // Calculate totalLines based on viewport size\n const estimatedTargetLines = Math.ceil(\n Math.max(bottom - top, 0) / lineHeight\n );\n const totalLines =\n Math.ceil(estimatedTargetLines / hunkLineCount) * hunkLineCount +\n hunkLineCount * 2;\n const totalHunks = totalLines / hunkLineCount;\n const viewportCenter = (top + bottom) / 2;\n // Simple case: overflow scroll with no annotations - pure math!\n if (overflow === 'scroll' && !this.hasLineAnnotations()) {\n const sourceRowsTop = fileTop + codeRegionTop;\n const sourceRowsBottom = sourceRowsTop + codeRowsHeight;\n const sourceRowsVisible =\n sourceRowsTop < bottom && sourceRowsBottom > top;\n if (!measuredFileAnnotationVisible && !sourceRowsVisible) {\n return {\n startingLine: 0,\n totalLines: 0,\n bufferBefore: 0,\n bufferAfter: fileHeight - headerRegion - paddingBottom,\n };\n }\n\n // Find which line is at viewport center\n const centerLine = Math.floor(\n measuredFileAnnotationVisible &&\n viewportCenter < fileTop + codeRegionTop\n ? 0\n : (viewportCenter - (fileTop + codeRegionTop)) / lineHeight\n );\n const centerHunk = Math.floor(centerLine / hunkLineCount);\n\n // Calculate ideal start centered around viewport\n const idealStartHunk = centerHunk - Math.floor(totalHunks / 2);\n const totalHunksInFile = Math.ceil(lineCount / hunkLineCount);\n const startingLine =\n Math.max(0, Math.min(idealStartHunk, totalHunksInFile)) * hunkLineCount;\n\n const clampedTotalLines =\n idealStartHunk < 0\n ? totalLines + idealStartHunk * hunkLineCount\n : totalLines;\n\n const bufferBefore =\n startingLine === 0\n ? 0\n : fileAnnotationHeight + startingLine * lineHeight;\n const renderedLines = Math.min(\n clampedTotalLines,\n lineCount - startingLine\n );\n const bufferAfter = Math.max(\n 0,\n (lineCount - startingLine - renderedLines) * lineHeight\n );\n\n return {\n startingLine,\n totalLines: clampedTotalLines,\n bufferBefore,\n bufferAfter,\n };\n }\n\n // Complex case: need to account for line annotations or wrap overflow\n const overflowHunks = totalHunks;\n const hunkOffsets: number[] = [];\n // Start the scan before the viewport so we collect hunk offsets that may be\n // needed for bufferBefore. This only chooses the scan origin; the returned\n // render range is still computed from the visible window below.\n const checkpoint = this.getLayoutCheckpointBeforeTop(\n Math.max(0, top - fileTop - totalLines * lineHeight * 2),\n hunkLineCount\n );\n\n let absoluteLineTop = fileTop + (checkpoint?.top ?? codeRegionTop);\n let currentLine = checkpoint?.lineIndex ?? 0;\n let firstVisibleHunk: number | undefined;\n let centerHunk: number | undefined;\n let overflowCounter: number | undefined;\n\n const startingLineIndex = checkpoint?.lineIndex ?? 0;\n for (\n let lineIndex = startingLineIndex;\n lineIndex < lineCount;\n lineIndex++\n ) {\n const isAtHunkBoundary = currentLine % hunkLineCount === 0;\n const currentHunk = Math.floor(currentLine / hunkLineCount);\n\n if (isAtHunkBoundary) {\n hunkOffsets[currentHunk] = absoluteLineTop - (fileTop + codeRegionTop);\n\n if (overflowCounter != null) {\n if (overflowCounter <= 0) {\n break;\n }\n overflowCounter--;\n }\n }\n\n const lineHeight = this.getLineHeight(lineIndex, false);\n\n // Track visible region\n if (absoluteLineTop > top - lineHeight && absoluteLineTop < bottom) {\n firstVisibleHunk ??= currentHunk;\n }\n\n // Track which hunk contains the viewport center\n if (absoluteLineTop + lineHeight > viewportCenter) {\n centerHunk ??= currentHunk;\n }\n\n // Start overflow when we are out of the viewport at a hunk boundary\n if (\n overflowCounter == null &&\n absoluteLineTop >= bottom &&\n isAtHunkBoundary\n ) {\n overflowCounter = overflowHunks;\n }\n\n currentLine++;\n absoluteLineTop += lineHeight;\n }\n\n // No visible lines found\n if (firstVisibleHunk == null) {\n if (measuredFileAnnotationVisible) {\n firstVisibleHunk = 0;\n centerHunk = 0;\n } else {\n return {\n startingLine: 0,\n totalLines: 0,\n bufferBefore: 0,\n bufferAfter: fileHeight - headerRegion - paddingBottom,\n };\n }\n }\n\n // Calculate balanced startingLine centered around the viewport center\n centerHunk ??= firstVisibleHunk;\n const idealStartHunk = Math.round(centerHunk - totalHunks / 2);\n\n // Clamp startHunk: at the beginning, reduce totalLines; at the end, shift\n // startHunk back\n const maxStartHunk = Math.max(\n 0,\n Math.ceil(lineCount / hunkLineCount) - totalHunks\n );\n const startHunk = Math.max(0, Math.min(idealStartHunk, maxStartHunk));\n const startingLine = startHunk * hunkLineCount;\n\n // If we wanted to start before 0, reduce totalLines by the clamped amount\n const clampedTotalLines =\n idealStartHunk < 0\n ? totalLines + idealStartHunk * hunkLineCount\n : totalLines;\n\n // Use hunkOffsets array for efficient buffer calculations\n const codeBufferBefore = hunkOffsets[startHunk] ?? 0;\n const bufferBefore =\n startingLine === 0 ? 0 : fileAnnotationHeight + codeBufferBefore;\n\n // Calculate bufferAfter\n const finalHunkIndex = startHunk + clampedTotalLines / hunkLineCount;\n const bufferAfter =\n finalHunkIndex < hunkOffsets.length\n ? codeRowsHeight - hunkOffsets[finalHunkIndex]\n : codeRowsHeight - (absoluteLineTop - fileTop - codeRegionTop);\n\n return {\n startingLine,\n totalLines: clampedTotalLines,\n bufferBefore,\n bufferAfter: Math.max(0, bufferAfter),\n };\n }\n}\n\nfunction measureFileAnnotationHeight(content: HTMLElement): number | undefined {\n let height: number | undefined;\n for (const child of content.children) {\n if (!(child instanceof HTMLElement)) {\n continue;\n }\n if (child.dataset.lineAnnotation !== FILE_ANNOTATION_DOM_KEY) {\n continue;\n }\n height = Math.max(height ?? 0, child.getBoundingClientRect().height);\n }\n return height;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { ExpansionDirections, FileDiffMetadata, NumericScrollLineAnchor, PendingCodeViewLayoutReset, RenderWindow, SelectionSide, StickySpecs, ThemeTypes, VirtualFileMetrics } from "../types.js";
1
+ import { DiffLineAnnotation, DiffsTextDocument, ExpansionDirections, FileDiffMetadata, NumericScrollLineAnchor, PendingCodeViewLayoutReset, RenderWindow, SelectionSide, StickySpecs, ThemeTypes, VirtualFileMetrics } from "../types.js";
2
2
  import { WorkerPoolManager } from "../worker/WorkerPoolManager.js";
3
3
  import "../worker/index.js";
4
4
  import { Virtualizer } from "./Virtualizer.js";
@@ -20,6 +20,10 @@ declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnn
20
20
  private currentCollapsed;
21
21
  constructor(options: FileDiffOptions<LAnnotation> | undefined, virtualizer: Virtualizer | CodeView<LAnnotation>, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager, isContainerManaged?: boolean);
22
22
  setMetrics(metrics?: Partial<VirtualFileMetrics>, force?: boolean): void;
23
+ setLineAnnotations(lineAnnotations: DiffLineAnnotation<LAnnotation>[]): void;
24
+ private syncLineAnnotations;
25
+ private setFileAnnotationHeight;
26
+ private hasFileAnnotations;
23
27
  private getLineHeight;
24
28
  private getEstimatedLineHeight;
25
29
  setOptions(options: FileDiffOptions<LAnnotation> | undefined): void;
@@ -27,7 +31,7 @@ declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnn
27
31
  private resetLayoutCache;
28
32
  reconcileHeights(): boolean;
29
33
  onRender: (dirty: boolean) => boolean;
30
- prepareCodeViewItem(fileDiff: FileDiffMetadata, top: number, reset?: PendingCodeViewLayoutReset): number;
34
+ prepareCodeViewItem(fileDiff: FileDiffMetadata, top: number, reset?: PendingCodeViewLayoutReset, lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): number;
31
35
  getLinePosition(lineNumber: number, side?: SelectionSide): {
32
36
  top: number;
33
37
  height: number;
@@ -39,6 +43,7 @@ declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnn
39
43
  expandHunk: (hunkIndex: number, direction: ExpansionDirections, expansionLineCountOverride?: number | undefined) => void;
40
44
  setVisibility(visible: boolean): void;
41
45
  rerender(): void;
46
+ applyDocumentChange(textDocument: DiffsTextDocument, newLineAnnotations?: DiffLineAnnotation<LAnnotation>[], shouldUpdateBuffer?: boolean): void;
42
47
  private computeApproximateSize;
43
48
  private getActiveEstimatedHeight;
44
49
  private ensureEstimatedDiffHeights;
@@ -49,6 +54,7 @@ declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnn
49
54
  newFile,
50
55
  fileDiff,
51
56
  forceRender,
57
+ lineAnnotations,
52
58
  ...props
53
59
  }?: FileDiffRenderProps<LAnnotation>): boolean;
54
60
  syncVirtualizedTop(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualizedFileDiff.d.ts","names":["ExpansionDirections","FileDiffMetadata","NumericScrollLineAnchor","PendingCodeViewLayoutReset","RenderWindow","SelectionSide","StickySpecs","ThemeTypes","VirtualFileMetrics","WorkerPoolManager","CodeView","FileDiff","FileDiffOptions","FileDiffRenderProps","Virtualizer","VirtualizedFileDiff","LAnnotation","Partial","fileContainer","oldFile","newFile","fileDiff","forceRender"],"sources":["../../src/components/VirtualizedFileDiff.d.ts"],"sourcesContent":["import type { ExpansionDirections, FileDiffMetadata, NumericScrollLineAnchor, PendingCodeViewLayoutReset, RenderWindow, SelectionSide, StickySpecs, ThemeTypes, VirtualFileMetrics } from '../types';\nimport type { WorkerPoolManager } from '../worker';\nimport type { CodeView } from './CodeView';\nimport { FileDiff, type FileDiffOptions, type FileDiffRenderProps } from './FileDiff';\nimport type { Virtualizer } from './Virtualizer';\nexport declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnnotation> {\n readonly __id: string;\n top: number | undefined;\n height: number;\n private metrics;\n private cache;\n private isVisible;\n private isSetup;\n private virtualizer;\n private layoutDirty;\n private forceRenderOverride;\n private currentCollapsed;\n constructor(options: FileDiffOptions<LAnnotation> | undefined, virtualizer: Virtualizer | CodeView<LAnnotation>, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager, isContainerManaged?: boolean);\n setMetrics(metrics?: Partial<VirtualFileMetrics>, force?: boolean): void;\n private getLineHeight;\n private getEstimatedLineHeight;\n setOptions(options: FileDiffOptions<LAnnotation> | undefined): void;\n setThemeType(themeType: ThemeTypes): void;\n private resetLayoutCache;\n reconcileHeights(): boolean;\n onRender: (dirty: boolean) => boolean;\n prepareCodeViewItem(fileDiff: FileDiffMetadata, top: number, reset?: PendingCodeViewLayoutReset): number;\n getLinePosition(lineNumber: number, side?: SelectionSide): {\n top: number;\n height: number;\n } | undefined;\n getNumericScrollAnchor(localViewportTop: number): NumericScrollLineAnchor | undefined;\n getVirtualizedHeight(): number;\n getAdvancedStickySpecs(windowSpecs?: RenderWindow): StickySpecs | undefined;\n cleanUp(recycle?: boolean): void;\n expandHunk: (hunkIndex: number, direction: ExpansionDirections, expansionLineCountOverride?: number | undefined) => void;\n setVisibility(visible: boolean): void;\n rerender(): void;\n private computeApproximateSize;\n private getActiveEstimatedHeight;\n private ensureEstimatedDiffHeights;\n private validateComputedHeight;\n render({ fileContainer, oldFile, newFile, fileDiff, forceRender, ...props }?: FileDiffRenderProps<LAnnotation>): boolean;\n syncVirtualizedTop(): void;\n protected shouldDisableVirtualizationBuffers(): boolean;\n private isSimpleMode;\n private isAdvancedMode;\n private getVirtualizedTop;\n private getSimpleVirtualizer;\n private isResizeDebuggingEnabled;\n private getDiffStyle;\n private getHunkSeparatorType;\n private approximateLayoutCheckpoints;\n private getLayoutCheckpointBeforeLineIndex;\n private getLayoutCheckpointBeforeTop;\n private getExpandedLineCount;\n private computeRenderRangeFromWindow;\n}\n//# sourceMappingURL=VirtualizedFileDiff.d.ts.map"],"mappings":";;;;;;;;cAKqBe,qDAAqDJ,SAASK;;;EAA9DD,MAAAA,EAAAA,MAAAA;EAA8DC,QAAAA,OAAAA;EAY1CA,QAAAA,KAAAA;EAAhBJ,QAAAA,SAAAA;EAAuDE,QAAAA,OAAAA;EAAuBE,QAAAA,WAAAA;EAATN,QAAAA,WAAAA;EAAyCF,QAAAA,mBAAAA;EAARS,QAAAA,gBAAAA;EAA6CR,WAAAA,CAAAA,OAAAA,EAAnJG,eAAmJH,CAAnIO,WAAmIP,CAAAA,GAAAA,SAAAA,EAAAA,WAAAA,EAA5FK,WAA4FL,GAA9EC,QAA8ED,CAArEO,WAAqEP,CAAAA,EAAAA,OAAAA,CAAAA,EAA7CQ,OAA6CR,CAArCD,kBAAqCC,CAAAA,EAAAA,aAAAA,CAAAA,EAAAA,iBAAAA,EAAAA,kBAAAA,CAAAA,EAAAA,OAAAA;EAC3ID,UAAAA,CAAAA,OAAAA,CAAAA,EAARS,OAAQT,CAAAA,kBAAAA,CAAAA,EAAAA,KAAAA,CAAAA,EAAAA,OAAAA,CAAAA,EAAAA,IAAAA;EAARS,QAAAA,aAAAA;EAGeD,QAAAA,sBAAAA;EAAhBJ,UAAAA,CAAAA,OAAAA,EAAAA,eAAAA,CAAgBI,WAAhBJ,CAAAA,GAAAA,SAAAA,CAAAA,EAAAA,IAAAA;EACIL,YAAAA,CAAAA,SAAAA,EAAAA,UAAAA,CAAAA,EAAAA,IAAAA;EAIMN,QAAAA,gBAAAA;EAAuCE,gBAAAA,CAAAA,CAAAA,EAAAA,OAAAA;EAC1BE,QAAAA,EAAAA,CAAAA,KAAAA,EAAAA,OAAAA,EAAAA,GAAAA,OAAAA;EAIOH,mBAAAA,CAAAA,QAAAA,EALpBD,gBAKoBC,EAAAA,GAAAA,EAAAA,MAAAA,EAAAA,KAAAA,CAAAA,EALmBC,0BAKnBD,CAAAA,EAAAA,MAAAA;EAEbE,eAAAA,CAAAA,UAAAA,EAAAA,MAAAA,EAAAA,IAAAA,CAAAA,EANMC,aAMND,CAAAA,EAAAA;IAAeE,GAAAA,EAAAA,MAAAA;IAETN,MAAAA,EAAAA,MAAAA;EAOlCkB,CAAAA,GAAAA,SAAAA;EAAeC,sBAAAA,CAAAA,gBAAAA,EAAAA,MAAAA,CAAAA,EAX0BjB,uBAW1BiB,GAAAA,SAAAA;EAASC,oBAAAA,CAAAA,CAAAA,EAAAA,MAAAA;EAASC,sBAAAA,CAAAA,WAAAA,CAAAA,EATLjB,YASKiB,CAAAA,EATUf,WASVe,GAAAA,SAAAA;EAAUC,OAAAA,CAAAA,OAAAA,CAAAA,EAAAA,OAAAA,CAAAA,EAAAA,IAAAA;EAA8CN,UAAAA,EAAAA,CAAAA,SAAAA,EAAAA,MAAAA,EAAAA,SAAAA,EAPvDhB,mBAOuDgB,EAAAA,0BAAAA,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA,EAAAA,GAAAA,IAAAA;EAApBH,aAAAA,CAAAA,OAAAA,EAAAA,OAAAA,CAAAA,EAAAA,IAAAA;EArCRF,QAAAA,CAAAA,CAAAA,EAAAA,IAAAA;EAAQ,QAAA,sBAAA;;;;;;;;;;;MAqCAE,oBAAoBG"}
1
+ {"version":3,"file":"VirtualizedFileDiff.d.ts","names":["DiffLineAnnotation","DiffsTextDocument","ExpansionDirections","FileDiffMetadata","NumericScrollLineAnchor","PendingCodeViewLayoutReset","RenderWindow","SelectionSide","StickySpecs","ThemeTypes","VirtualFileMetrics","WorkerPoolManager","CodeView","FileDiff","FileDiffOptions","FileDiffRenderProps","Virtualizer","VirtualizedFileDiff","LAnnotation","Partial","fileContainer","oldFile","newFile","fileDiff","forceRender","lineAnnotations"],"sources":["../../src/components/VirtualizedFileDiff.d.ts"],"sourcesContent":["import type { DiffLineAnnotation, DiffsTextDocument, ExpansionDirections, FileDiffMetadata, NumericScrollLineAnchor, PendingCodeViewLayoutReset, RenderWindow, SelectionSide, StickySpecs, ThemeTypes, VirtualFileMetrics } from '../types';\nimport type { WorkerPoolManager } from '../worker';\nimport type { CodeView } from './CodeView';\nimport { FileDiff, type FileDiffOptions, type FileDiffRenderProps } from './FileDiff';\nimport type { Virtualizer } from './Virtualizer';\nexport declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnnotation> {\n readonly __id: string;\n top: number | undefined;\n height: number;\n private metrics;\n private cache;\n private isVisible;\n private isSetup;\n private virtualizer;\n private layoutDirty;\n private forceRenderOverride;\n private currentCollapsed;\n constructor(options: FileDiffOptions<LAnnotation> | undefined, virtualizer: Virtualizer | CodeView<LAnnotation>, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager, isContainerManaged?: boolean);\n setMetrics(metrics?: Partial<VirtualFileMetrics>, force?: boolean): void;\n setLineAnnotations(lineAnnotations: DiffLineAnnotation<LAnnotation>[]): void;\n private syncLineAnnotations;\n private setFileAnnotationHeight;\n private hasFileAnnotations;\n private getLineHeight;\n private getEstimatedLineHeight;\n setOptions(options: FileDiffOptions<LAnnotation> | undefined): void;\n setThemeType(themeType: ThemeTypes): void;\n private resetLayoutCache;\n reconcileHeights(): boolean;\n onRender: (dirty: boolean) => boolean;\n prepareCodeViewItem(fileDiff: FileDiffMetadata, top: number, reset?: PendingCodeViewLayoutReset, lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): number;\n getLinePosition(lineNumber: number, side?: SelectionSide): {\n top: number;\n height: number;\n } | undefined;\n getNumericScrollAnchor(localViewportTop: number): NumericScrollLineAnchor | undefined;\n getVirtualizedHeight(): number;\n getAdvancedStickySpecs(windowSpecs?: RenderWindow): StickySpecs | undefined;\n cleanUp(recycle?: boolean): void;\n expandHunk: (hunkIndex: number, direction: ExpansionDirections, expansionLineCountOverride?: number | undefined) => void;\n setVisibility(visible: boolean): void;\n rerender(): void;\n applyDocumentChange(textDocument: DiffsTextDocument, newLineAnnotations?: DiffLineAnnotation<LAnnotation>[], shouldUpdateBuffer?: boolean): void;\n private computeApproximateSize;\n private getActiveEstimatedHeight;\n private ensureEstimatedDiffHeights;\n private validateComputedHeight;\n render({ fileContainer, oldFile, newFile, fileDiff, forceRender, lineAnnotations, ...props }?: FileDiffRenderProps<LAnnotation>): boolean;\n syncVirtualizedTop(): void;\n protected shouldDisableVirtualizationBuffers(): boolean;\n private isSimpleMode;\n private isAdvancedMode;\n private getVirtualizedTop;\n private getSimpleVirtualizer;\n private isResizeDebuggingEnabled;\n private getDiffStyle;\n private getHunkSeparatorType;\n private approximateLayoutCheckpoints;\n private getLayoutCheckpointBeforeLineIndex;\n private getLayoutCheckpointBeforeTop;\n private getExpandedLineCount;\n private computeRenderRangeFromWindow;\n}\n//# sourceMappingURL=VirtualizedFileDiff.d.ts.map"],"mappings":"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"}
@@ -2,6 +2,7 @@ import { DEFAULT_COLLAPSED_CONTEXT_THRESHOLD } from "../constants.js";
2
2
  import { areObjectsEqual } from "../utils/areObjectsEqual.js";
3
3
  import { areOptionsEqual } from "../utils/areOptionsEqual.js";
4
4
  import { computeVirtualFileMetrics, getVirtualFileHeaderRegion, getVirtualFilePaddingBottom } from "../utils/computeVirtualFileMetrics.js";
5
+ import { FILE_ANNOTATION_DOM_KEY, FILE_ANNOTATION_LINE_NUMBER, includesFileAnnotations, shouldRenderFileAnnotations } from "../utils/includesFileAnnotations.js";
5
6
  import { areDiffTargetsEqual } from "../utils/areDiffTargetsEqual.js";
6
7
  import { getExpandedRegion, getLeadingHunkSeparatorLayout, getTrailingExpandedRegion, getTrailingHunkSeparatorLayout } from "../utils/virtualDiffLayout.js";
7
8
  import { computeEstimatedDiffHeights } from "../utils/computeEstimatedDiffHeights.js";
@@ -23,7 +24,8 @@ var VirtualizedFileDiff = class extends FileDiff {
23
24
  estimatedSplitHeight: void 0,
24
25
  estimatedUnifiedHeight: void 0,
25
26
  checkpoints: [],
26
- totalLines: 0
27
+ totalLines: 0,
28
+ fileAnnotationHeight: 0
27
29
  };
28
30
  isVisible = false;
29
31
  isSetup = false;
@@ -42,6 +44,30 @@ var VirtualizedFileDiff = class extends FileDiff {
42
44
  this.metrics = nextMetrics;
43
45
  this.resetLayoutCache({ includeEstimatedHeights: true });
44
46
  }
47
+ setLineAnnotations(lineAnnotations) {
48
+ if (this.syncLineAnnotations(lineAnnotations)) this.resetLayoutCache({ includeEstimatedHeights: false });
49
+ }
50
+ syncLineAnnotations(lineAnnotations) {
51
+ if (lineAnnotations == null || lineAnnotations === this.lineAnnotations || lineAnnotations.length === 0 && this.lineAnnotations.length === 0) return false;
52
+ super.setLineAnnotations(lineAnnotations);
53
+ return true;
54
+ }
55
+ setFileAnnotationHeight(nextHeight) {
56
+ const previousHeight = this.cache.fileAnnotationHeight;
57
+ if (nextHeight === previousHeight) return false;
58
+ this.cache.fileAnnotationHeight = nextHeight;
59
+ this.cache.measuredHeightDeltaTotal += nextHeight - previousHeight;
60
+ return true;
61
+ }
62
+ hasFileAnnotations(fileDiff = this.fileDiff) {
63
+ if (fileDiff == null || !includesFileAnnotations(this.lineAnnotations)) return false;
64
+ return this.lineAnnotations.some((annotation) => {
65
+ if (annotation.lineNumber !== FILE_ANNOTATION_LINE_NUMBER) return false;
66
+ if (fileDiff.type === "new") return annotation.side === "additions";
67
+ if (fileDiff.type === "deleted") return annotation.side === "deletions";
68
+ return true;
69
+ });
70
+ }
45
71
  getLineHeight(lineIndex, hasMetadataLine = false) {
46
72
  return this.getEstimatedLineHeight(hasMetadataLine) + (this.cache.heightDeltas.get(lineIndex) ?? 0);
47
73
  }
@@ -69,6 +95,7 @@ var VirtualizedFileDiff = class extends FileDiff {
69
95
  }
70
96
  resetLayoutCache({ forceSimpleRecompute = false, includeEstimatedHeights = false } = {}) {
71
97
  this.layoutDirty = true;
98
+ this.cache.fileAnnotationHeight = 0;
72
99
  if (this.cache.heightDeltas.size > 0) this.cache.heightDeltas.clear();
73
100
  if (this.cache.measuredHeightDeltaTotal !== 0) this.cache.measuredHeightDeltaTotal = 0;
74
101
  if (this.cache.checkpoints.length > 0) this.cache.checkpoints.length = 0;
@@ -92,6 +119,11 @@ var VirtualizedFileDiff = class extends FileDiff {
92
119
  if (overflow === "scroll" && this.lineAnnotations.length === 0 && !this.isResizeDebuggingEnabled()) return hasHeightChange;
93
120
  const diffStyle = this.getDiffStyle();
94
121
  const codeGroups = diffStyle === "split" ? [this.codeDeletions, this.codeAdditions] : [this.codeUnified];
122
+ const hasFileAnnotations = this.hasFileAnnotations(this.fileDiff);
123
+ if (this.renderRange != null && hasFileAnnotations && shouldRenderFileAnnotations(this.renderRange)) {
124
+ const nextFileAnnotationHeight = measureFileAnnotationHeight(codeGroups) ?? 0;
125
+ if (this.setFileAnnotationHeight(nextFileAnnotationHeight)) hasHeightChange = true;
126
+ } else if (!hasFileAnnotations && this.setFileAnnotationHeight(0)) hasHeightChange = true;
95
127
  for (const codeGroup of codeGroups) {
96
128
  if (codeGroup == null) continue;
97
129
  const content = codeGroup.children[1];
@@ -125,9 +157,10 @@ var VirtualizedFileDiff = class extends FileDiff {
125
157
  if (dirty) this.top = this.getVirtualizedTop();
126
158
  return this.render();
127
159
  };
128
- prepareCodeViewItem(fileDiff, top, reset) {
160
+ prepareCodeViewItem(fileDiff, top, reset, lineAnnotations) {
129
161
  const targetChanged = !areDiffTargetsEqual(this.fileDiff, fileDiff);
130
- let shouldResetLayoutCache = reset?.resetDiffLayoutCache === true || targetChanged;
162
+ const annotationsChanged = this.syncLineAnnotations(lineAnnotations);
163
+ let shouldResetLayoutCache = reset?.resetDiffLayoutCache === true || targetChanged || annotationsChanged;
131
164
  let includeEstimatedHeights = targetChanged || reset?.resetDiffLayoutCache === true && reset.includeEstimatedDiffHeights;
132
165
  if (reset?.metrics != null) {
133
166
  this.metrics = computeVirtualFileMetrics(reset.metrics);
@@ -146,7 +179,7 @@ var VirtualizedFileDiff = class extends FileDiff {
146
179
  return this.height;
147
180
  }
148
181
  getLinePosition(lineNumber, side = "additions") {
149
- if (this.fileDiff == null) return;
182
+ if (this.fileDiff == null || lineNumber < 1) return;
150
183
  const targetLineIndexes = this.getLineIndex(lineNumber, side);
151
184
  if (targetLineIndexes == null) return;
152
185
  const { disableFileHeader = false, expandUnchanged = false, collapsed = false, collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD } = this.options;
@@ -154,10 +187,11 @@ var VirtualizedFileDiff = class extends FileDiff {
154
187
  const hunkSeparators = this.getHunkSeparatorType();
155
188
  const targetLineIndex = diffStyle === "split" ? targetLineIndexes[1] : targetLineIndexes[0];
156
189
  this.approximateLayoutCheckpoints();
190
+ const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
157
191
  const checkpoint = this.getLayoutCheckpointBeforeLineIndex(targetLineIndex);
158
- let top = checkpoint?.top ?? getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
192
+ let top = checkpoint?.top ?? headerRegion + this.cache.fileAnnotationHeight;
159
193
  if (collapsed) return {
160
- top,
194
+ top: headerRegion,
161
195
  height: 0
162
196
  };
163
197
  let position;
@@ -227,7 +261,7 @@ var VirtualizedFileDiff = class extends FileDiff {
227
261
  const hunkSeparators = this.getHunkSeparatorType();
228
262
  this.approximateLayoutCheckpoints();
229
263
  const checkpoint = this.getLayoutCheckpointBeforeTop(localViewportTop);
230
- let top = checkpoint?.top ?? getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
264
+ let top = checkpoint?.top ?? getVirtualFileHeaderRegion(this.metrics, disableFileHeader) + this.cache.fileAnnotationHeight;
231
265
  let anchor;
232
266
  iterateOverDiff({
233
267
  diff: this.fileDiff,
@@ -325,6 +359,20 @@ var VirtualizedFileDiff = class extends FileDiff {
325
359
  this.forceRenderOverride = true;
326
360
  this.virtualizer.instanceChanged(this, false);
327
361
  }
362
+ applyDocumentChange(textDocument, newLineAnnotations, shouldUpdateBuffer = false) {
363
+ const previousRenderRange = this.renderRange;
364
+ super.applyDocumentChange(textDocument, newLineAnnotations);
365
+ this.getSimpleVirtualizer()?.markDOMDirty();
366
+ this.resetLayoutCache({
367
+ forceSimpleRecompute: this.isSimpleMode(),
368
+ includeEstimatedHeights: true
369
+ });
370
+ if (shouldUpdateBuffer && previousRenderRange !== void 0 && this.fileDiff !== void 0) {
371
+ const windowSpecs = this.virtualizer.getWindowSpecs();
372
+ const renderRange = this.computeRenderRangeFromWindow(this.fileDiff, this.top ?? 0, windowSpecs);
373
+ if (renderRange.bufferAfter !== previousRenderRange.bufferAfter) this.updateBuffers(renderRange);
374
+ }
375
+ }
328
376
  computeApproximateSize(force = false) {
329
377
  const shouldValidateSize = this.isResizeDebuggingEnabled();
330
378
  if (!force && !this.layoutDirty && !shouldValidateSize) return;
@@ -383,9 +431,11 @@ var VirtualizedFileDiff = class extends FileDiff {
383
431
  });
384
432
  else console.log("VirtualizedFileDiff.computeApproximateSize: computed height IS CORRECT");
385
433
  }
386
- render({ fileContainer, oldFile, newFile, fileDiff, forceRender = false,...props } = {}) {
434
+ render({ fileContainer, oldFile, newFile, fileDiff, forceRender = false, lineAnnotations,...props } = {}) {
387
435
  const { forceRenderOverride, isSetup } = this;
388
436
  this.forceRenderOverride = void 0;
437
+ const annotationsChanged = this.syncLineAnnotations(lineAnnotations);
438
+ if (annotationsChanged) this.resetLayoutCache({ includeEstimatedHeights: false });
389
439
  this.fileDiff ??= fileDiff ?? (oldFile != null && newFile != null ? parseDiffFromFile(oldFile, newFile, this.options.parseDiffOptions) : void 0);
390
440
  fileContainer = this.getOrCreateFileContainer(fileContainer);
391
441
  if (this.fileDiff == null) {
@@ -414,7 +464,8 @@ var VirtualizedFileDiff = class extends FileDiff {
414
464
  renderRange,
415
465
  oldFile,
416
466
  newFile,
417
- forceRender: forceRenderOverride ?? forceRender,
467
+ lineAnnotations,
468
+ forceRender: (forceRenderOverride ?? forceRender) || annotationsChanged,
418
469
  ...props
419
470
  });
420
471
  }
@@ -454,7 +505,7 @@ var VirtualizedFileDiff = class extends FileDiff {
454
505
  const hunkSeparators = this.getHunkSeparatorType();
455
506
  const expandedHunks = expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap();
456
507
  const heightDeltaPrefix = createHeightDeltaPrefix(this.cache.heightDeltas);
457
- let top = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
508
+ let top = getVirtualFileHeaderRegion(this.metrics, disableFileHeader) + this.cache.fileAnnotationHeight;
458
509
  let renderedLineIndex = 0;
459
510
  const processRows = ({ rowCount, startLineIndex, preSeparatorHeight = 0, postSeparatorHeight = 0, metadataOffsets = [] }) => {
460
511
  if (rowCount <= 0) return;
@@ -610,6 +661,12 @@ var VirtualizedFileDiff = class extends FileDiff {
610
661
  let lineCount = this.cache.totalLines > 0 ? this.cache.totalLines : this.getExpandedLineCount(fileDiff, diffStyle);
611
662
  const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
612
663
  const paddingBottom = fileDiff.hunks.length > 0 ? getVirtualFilePaddingBottom(this.metrics) : 0;
664
+ const { fileAnnotationHeight } = this.cache;
665
+ const codeRegionTop = headerRegion + fileAnnotationHeight;
666
+ const codeHeight = Math.max(0, fileHeight - headerRegion - fileAnnotationHeight - paddingBottom);
667
+ const hasFileAnnotations = this.hasFileAnnotations(fileDiff);
668
+ const fileAnnotationTop = fileTop + headerRegion;
669
+ const measuredFileAnnotationVisible = fileAnnotationHeight > 0 && hasFileAnnotations && fileAnnotationTop < bottom && fileAnnotationTop + fileAnnotationHeight > top;
613
670
  if (fileTop < top - fileHeight || fileTop > bottom) return {
614
671
  startingLine: 0,
615
672
  totalLines: 0,
@@ -631,7 +688,7 @@ var VirtualizedFileDiff = class extends FileDiff {
631
688
  const hunkOffsets = [];
632
689
  const viewportCenter = (top + bottom) / 2;
633
690
  const checkpoint = this.getLayoutCheckpointBeforeTop(Math.max(0, top - fileTop - totalLines * lineHeight * 2), hunkLineCount);
634
- let absoluteLineTop = fileTop + (checkpoint?.top ?? headerRegion);
691
+ let absoluteLineTop = fileTop + (checkpoint?.top ?? codeRegionTop);
635
692
  let currentLine = checkpoint?.renderedLineIndex ?? 0;
636
693
  let firstVisibleHunk;
637
694
  let centerHunk;
@@ -656,7 +713,7 @@ var VirtualizedFileDiff = class extends FileDiff {
656
713
  const isAtHunkBoundary = currentLine % hunkLineCount === 0;
657
714
  const currentHunk = Math.floor(currentLine / hunkLineCount);
658
715
  if (isAtHunkBoundary) {
659
- hunkOffsets[currentHunk] = absoluteLineTop - (fileTop + headerRegion + gapAdjustment);
716
+ hunkOffsets[currentHunk] = absoluteLineTop - (fileTop + codeRegionTop + gapAdjustment);
660
717
  if (overflowCounter != null) {
661
718
  if (overflowCounter <= 0) return true;
662
719
  overflowCounter--;
@@ -675,7 +732,10 @@ var VirtualizedFileDiff = class extends FileDiff {
675
732
  return false;
676
733
  }
677
734
  });
678
- if (firstVisibleHunk == null) return {
735
+ if (firstVisibleHunk == null) if (measuredFileAnnotationVisible) {
736
+ firstVisibleHunk = 0;
737
+ centerHunk = 0;
738
+ } else return {
679
739
  startingLine: 0,
680
740
  totalLines: 0,
681
741
  bufferBefore: 0,
@@ -687,16 +747,32 @@ var VirtualizedFileDiff = class extends FileDiff {
687
747
  const startHunk = Math.max(0, Math.min(idealStartHunk, maxStartHunk));
688
748
  const startingLine = startHunk * hunkLineCount;
689
749
  const clampedTotalLines = idealStartHunk < 0 ? totalLines + idealStartHunk * hunkLineCount : totalLines;
690
- const bufferBefore = hunkOffsets[startHunk] ?? 0;
750
+ const codeBufferBefore = hunkOffsets[startHunk] ?? 0;
751
+ const bufferBefore = startingLine === 0 ? 0 : fileAnnotationHeight + codeBufferBefore;
691
752
  const finalHunkIndex = startHunk + clampedTotalLines / hunkLineCount;
753
+ const bufferAfter = finalHunkIndex < hunkOffsets.length ? codeHeight - hunkOffsets[finalHunkIndex] : codeHeight - (absoluteLineTop - fileTop - codeRegionTop);
692
754
  return {
693
755
  startingLine,
694
756
  totalLines: clampedTotalLines,
695
757
  bufferBefore,
696
- bufferAfter: finalHunkIndex < hunkOffsets.length ? fileHeight - headerRegion - hunkOffsets[finalHunkIndex] - paddingBottom : fileHeight - (absoluteLineTop - fileTop) - paddingBottom
758
+ bufferAfter: Math.max(0, bufferAfter)
697
759
  };
698
760
  }
699
761
  };
762
+ function measureFileAnnotationHeight(codeGroups) {
763
+ let height;
764
+ for (const codeGroup of codeGroups) {
765
+ if (codeGroup == null) continue;
766
+ const content = codeGroup.children[1];
767
+ if (!(content instanceof HTMLElement)) continue;
768
+ for (const child of content.children) {
769
+ if (!(child instanceof HTMLElement)) continue;
770
+ if (child.dataset.lineAnnotation !== FILE_ANNOTATION_DOM_KEY) continue;
771
+ height = Math.max(height ?? 0, child.getBoundingClientRect().height);
772
+ }
773
+ }
774
+ return height;
775
+ }
700
776
  function createHeightDeltaPrefix(heightDeltas) {
701
777
  const entries = Array.from(heightDeltas).sort((a, b) => a[0] - b[0]);
702
778
  const lineIndexes = [];