{"version":3,"file":"AdvancedVirtualizedFileDiff.js","names":["hunkOffsets: number[]","startingLine: number | undefined","hunkLineCount"],"sources":["../../src/components/AdvancedVirtualizedFileDiff.ts"],"sourcesContent":["import { DEFAULT_THEMES, EMPTY_RENDER_RANGE } from '../constants';\nimport type {\n  FileDiffMetadata,\n  RenderRange,\n  RenderWindow,\n  VirtualFileMetrics,\n} from '../types';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { resolveVirtualFileMetrics } from '../utils/resolveVirtualFileMetrics';\nimport type { WorkerPoolManager } from '../worker';\nimport { FileDiff, type FileDiffOptions } from './FileDiff';\n\nexport type { FileDiffOptions };\n\ninterface RenderProps {\n  fileContainer?: HTMLElement;\n  renderWindow: RenderWindow;\n}\n\ninterface PositionProps {\n  unifiedTop: number;\n  splitTop: number;\n  fileDiff: FileDiffMetadata;\n}\n\nlet instanceId = -1;\n\nexport class AdvancedVirtualizedFileDiff<\n  LAnnotation = undefined,\n> extends FileDiff<LAnnotation> {\n  override readonly __id: string = `virtualized-file-diff:${++instanceId}`;\n\n  public unifiedTop: number;\n  public splitTop: number;\n  public unifiedHeight: number = 0;\n  public splitHeight: number = 0;\n  private metrics: VirtualFileMetrics;\n\n  override fileDiff: FileDiffMetadata;\n  public renderedRange: RenderRange | undefined;\n\n  constructor(\n    { unifiedTop, splitTop, fileDiff }: PositionProps,\n    options: FileDiffOptions<LAnnotation> = { theme: DEFAULT_THEMES },\n    metrics?: Partial<VirtualFileMetrics>,\n    workerManager?: WorkerPoolManager | undefined\n  ) {\n    super(options, workerManager, true);\n    this.fileDiff = fileDiff;\n    this.unifiedTop = unifiedTop;\n    this.splitTop = splitTop;\n    const { hunkSeparators = 'line-info' } = this.options;\n    this.metrics = resolveVirtualFileMetrics(\n      typeof hunkSeparators === 'function' ? 'custom' : hunkSeparators,\n      metrics\n    );\n    this.computeSize();\n  }\n\n  override cleanUp(recycle = false): void {\n    super.cleanUp(recycle);\n    this.renderedRange = undefined;\n  }\n\n  private computeSize() {\n    const {\n      options: { disableFileHeader = false },\n      fileDiff,\n      metrics: { diffHeaderHeight, fileGap, hunkSeparatorHeight, lineHeight },\n    } = this;\n\n    // Add header height\n    if (!disableFileHeader) {\n      this.unifiedHeight += diffHeaderHeight;\n      this.splitHeight += diffHeaderHeight;\n    } else {\n      this.unifiedHeight += fileGap;\n      this.splitHeight += fileGap;\n    }\n\n    // NOTE(amadeus): I wonder if it's worth shortcutting this? It might help\n    // to measure these values though and see if it's at all an issue on the\n    // big bois\n    for (const hunk of fileDiff.hunks) {\n      this.unifiedHeight += hunk.unifiedLineCount * lineHeight;\n      this.splitHeight += hunk.splitLineCount * lineHeight;\n    }\n\n    // Add hunk separators height\n    const hunkCount = fileDiff.hunks.length;\n    const [firstHunk] = fileDiff.hunks;\n    if (firstHunk != null) {\n      let hunkSize = (hunkSeparatorHeight + fileGap * 2) * (hunkCount - 1);\n      if (firstHunk.additionStart > 1 || firstHunk.deletionStart > 1) {\n        hunkSize += hunkSeparatorHeight + fileGap;\n      }\n      this.unifiedHeight += hunkSize;\n      this.splitHeight += hunkSize;\n    }\n\n    // If there are hunks of code, then we gotta render some bottom padding\n    if (hunkCount > 0) {\n      this.unifiedHeight += fileGap;\n      this.splitHeight += fileGap;\n    }\n  }\n\n  virtualizedRender({ renderWindow, fileContainer }: RenderProps): void {\n    const { fileDiff } = this;\n    const renderRange = this.computeRenderRangeFromWindow(renderWindow);\n    if (\n      this.fileContainer != null &&\n      areRenderRangesEqual(renderRange, this.renderedRange)\n    ) {\n      return;\n    }\n    this.renderedRange = renderRange;\n    fileContainer = this.getOrCreateFileContainer(fileContainer);\n    this.render({ fileDiff, fileContainer, renderRange });\n  }\n\n  private computeRenderRangeFromWindow({\n    top,\n    bottom,\n  }: RenderWindow): RenderRange {\n    const { diffStyle = 'split', disableFileHeader = false } = this.options;\n    const {\n      diffHeaderHeight,\n      fileGap,\n      hunkLineCount,\n      hunkSeparatorHeight,\n      lineHeight,\n    } = this.metrics;\n    const { lineCount, fileTop, fileHeight } = getSpecs(this, diffStyle);\n\n    // We should never hit this theoretically, but if so, gtfo and yell loudly,\n    // so we can fix\n    if (fileTop < top - fileHeight || fileTop > bottom) {\n      console.error(\n        'VirtulizedFileDiff.computeRenderRangeFromWindow: invalid render',\n        this.fileDiff.name\n      );\n      return EMPTY_RENDER_RANGE;\n    }\n\n    // Whole file is under HUNK_LINE_COUNT, just render it all\n    if (lineCount <= hunkLineCount) {\n      return {\n        startingLine: 0,\n        totalLines: Infinity,\n        bufferBefore: 0,\n        bufferAfter: 0,\n      };\n    }\n\n    const headerRegion = disableFileHeader ? fileGap : diffHeaderHeight;\n    let absoluteLineTop = fileTop + headerRegion;\n    let currentLine = 0;\n    const hunkOffsets: number[] = [];\n    let startingLine: number | undefined;\n    let endingLine = 0;\n    for (const hunk of this.fileDiff.hunks) {\n      let hunkGap = 0;\n      if (hunk.additionStart > 1 || hunk.deletionStart > 1) {\n        hunkGap = hunkSeparatorHeight + fileGap;\n        if (hunk !== this.fileDiff.hunks[0]) {\n          hunkGap += fileGap;\n        }\n        absoluteLineTop += hunkGap;\n      }\n      const hunkLineCount =\n        diffStyle === 'split' ? hunk.splitLineCount : hunk.unifiedLineCount;\n      for (let l = 0; l < hunkLineCount; l++) {\n        if (currentLine % hunkLineCount === 0) {\n          hunkOffsets.push(\n            absoluteLineTop - (fileTop + headerRegion + (l === 0 ? hunkGap : 0))\n          );\n        }\n        if (\n          startingLine == null &&\n          absoluteLineTop > top - lineHeight &&\n          absoluteLineTop < bottom\n        ) {\n          startingLine = currentLine;\n          endingLine = startingLine + 1;\n        } else if (startingLine != null && absoluteLineTop < bottom) {\n          endingLine++;\n        }\n        currentLine++;\n        absoluteLineTop += lineHeight;\n      }\n    }\n\n    if (startingLine == null) {\n      return {\n        startingLine: 0,\n        totalLines: 0,\n        bufferBefore: fileHeight - headerRegion,\n        bufferAfter: 0,\n      };\n    }\n\n    startingLine = Math.floor(startingLine / hunkLineCount) * hunkLineCount;\n    const totalLines =\n      Math.ceil((endingLine - startingLine) / hunkLineCount) * hunkLineCount;\n\n    const finalHunkBufferOffset = (startingLine + totalLines) / hunkLineCount;\n    const bufferBefore = hunkOffsets[startingLine / hunkLineCount] ?? 0;\n    const bufferAfter =\n      finalHunkBufferOffset < hunkOffsets.length\n        ? fileHeight -\n          headerRegion -\n          hunkOffsets[finalHunkBufferOffset] -\n          fileGap // this is to account for bottom padding of the code container\n        : 0;\n    return { startingLine, totalLines, bufferBefore, bufferAfter };\n  }\n}\n\nfunction getSpecs<LAnnotation>(\n  instance: AdvancedVirtualizedFileDiff<LAnnotation>,\n  type: 'split' | 'unified' = 'split'\n) {\n  if (type === 'split') {\n    return {\n      lineCount: instance.fileDiff.splitLineCount,\n      fileTop: instance.splitTop,\n      fileHeight: instance.splitHeight,\n    };\n  }\n  return {\n    lineCount: instance.fileDiff.unifiedLineCount,\n    fileTop: instance.unifiedTop,\n    fileHeight: instance.unifiedHeight,\n  };\n}\n"],"mappings":"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"}