{"version":3,"file":"UnresolvedFile.js","names":["options: UnresolvedFileOptions<LAnnotation>","resolveConflictDiff","payload: MergeConflictActionPayload"],"sources":["../../src/components/UnresolvedFile.ts"],"sourcesContent":["import { DEFAULT_THEMES } from '../constants';\nimport type { MergeConflictActionTarget } from '../managers/InteractionManager';\nimport { pluckInteractionOptions } from '../managers/InteractionManager';\nimport type { HunksRenderResult } from '../renderers/DiffHunksRenderer';\nimport {\n  UnresolvedFileHunksRenderer,\n  type UnresolvedFileHunksRendererOptions,\n} from '../renderers/UnresolvedFileHunksRenderer';\nimport type {\n  FileContents,\n  FileDiffMetadata,\n  MergeConflictActionPayload,\n  MergeConflictMarkerRow,\n  MergeConflictRegion,\n  MergeConflictResolution,\n} from '../types';\nimport { areFilesEqual } from '../utils/areFilesEqual';\nimport { areMergeConflictActionsEqual } from '../utils/areMergeConflictActionsEqual';\nimport { createAnnotationWrapperNode } from '../utils/createAnnotationWrapperNode';\nimport { getMergeConflictActionSlotName } from '../utils/getMergeConflictActionSlotName';\nimport {\n  buildMergeConflictMarkerRows,\n  getMergeConflictActionAnchor,\n  type MergeConflictDiffAction,\n  parseMergeConflictDiffFromFile,\n} from '../utils/parseMergeConflictDiffFromFile';\nimport { resolveConflict as resolveConflictDiff } from '../utils/resolveConflict';\nimport { splitFileContents } from '../utils/splitFileContents';\nimport type { WorkerPoolManager } from '../worker';\nimport {\n  FileDiff,\n  type FileDiffOptions,\n  type FileDiffRenderProps,\n} from './FileDiff';\n\nexport type RenderMergeConflictActions<LAnnotation> = (\n  action: MergeConflictDiffAction,\n  instance: UnresolvedFile<LAnnotation>\n) => HTMLElement | DocumentFragment | null | undefined;\n\nexport type MergeConflictActionsTypeOption<LAnnotation> =\n  | 'none'\n  | 'default'\n  | RenderMergeConflictActions<LAnnotation>;\n\nexport interface UnresolvedFileOptions<LAnnotation> extends Omit<\n  FileDiffOptions<LAnnotation>,\n  'diffStyle'\n> {\n  onPostRender?(\n    node: HTMLElement,\n    instance: UnresolvedFile<LAnnotation>\n  ): unknown;\n  mergeConflictActionsType?: MergeConflictActionsTypeOption<LAnnotation>;\n  onMergeConflictAction?(\n    payload: MergeConflictActionPayload,\n    instance: UnresolvedFile<LAnnotation>\n  ): void;\n  onMergeConflictResolve?(\n    file: FileContents,\n    payload: MergeConflictActionPayload\n  ): void;\n  maxContextLines?: number;\n}\n\nexport interface UnresolvedFileRenderProps<LAnnotation> extends Omit<\n  FileDiffRenderProps<LAnnotation>,\n  'oldFile' | 'newFile'\n> {\n  file?: FileContents;\n  actions?: (MergeConflictDiffAction | undefined)[];\n  markerRows?: MergeConflictMarkerRow[];\n}\n\nexport interface UnresolvedFileHydrationProps<LAnnotation> extends Omit<\n  UnresolvedFileRenderProps<LAnnotation>,\n  'file'\n> {\n  file?: FileContents;\n  fileContainer: HTMLElement;\n  prerenderedHTML?: string;\n}\n\ninterface MergeConflictActionElementCache {\n  element: HTMLElement;\n  action: MergeConflictDiffAction;\n}\n\ninterface GetOrComputeDiffProps {\n  file: FileContents | undefined;\n  fileDiff: FileDiffMetadata | undefined;\n  actions: (MergeConflictDiffAction | undefined)[] | undefined;\n  markerRows: MergeConflictMarkerRow[] | undefined;\n}\n\ninterface GetOrComputeDiffResult {\n  fileDiff: FileDiffMetadata;\n  actions: (MergeConflictDiffAction | undefined)[];\n  markerRows: MergeConflictMarkerRow[];\n}\n\ninterface ResolveConflictReturn {\n  file: FileContents;\n  fileDiff: FileDiffMetadata;\n  actions: (MergeConflictDiffAction | undefined)[];\n  markerRows: MergeConflictMarkerRow[];\n}\n\ntype UnresolvedFileDataCache = GetOrComputeDiffProps;\n\nlet instanceId = -1;\n\nexport class UnresolvedFile<\n  LAnnotation = undefined,\n> extends FileDiff<LAnnotation> {\n  override readonly __id: string = `unresolved-file:${++instanceId}`;\n  protected computedCache: UnresolvedFileDataCache = {\n    file: undefined,\n    fileDiff: undefined,\n    actions: undefined,\n    markerRows: undefined,\n  };\n  private conflictActions: (MergeConflictDiffAction | undefined)[] = [];\n  private markerRows: MergeConflictMarkerRow[] = [];\n  private conflictActionCache: Map<string, MergeConflictActionElementCache> =\n    new Map();\n\n  constructor(\n    public override options: UnresolvedFileOptions<LAnnotation> = {\n      theme: DEFAULT_THEMES,\n    },\n    workerManager?: WorkerPoolManager | undefined,\n    isContainerManaged = false\n  ) {\n    super(undefined, workerManager, isContainerManaged);\n    this.setOptions(options);\n  }\n\n  override setOptions(\n    options: UnresolvedFileOptions<LAnnotation> | undefined\n  ): void {\n    if (options == null) {\n      return;\n    }\n\n    if (\n      options.onMergeConflictAction != null &&\n      options.onMergeConflictResolve != null\n    ) {\n      throw new Error(\n        'UnresolvedFile: onMergeConflictAction and onMergeConflictResolve are mutually exclusive. Use only one callback.'\n      );\n    }\n\n    this.options = options;\n    this.hunksRenderer.setOptions(this.getHunksRendererOptions(options));\n\n    const hunkSeparators = this.options.hunkSeparators ?? 'line-info';\n    this.interactionManager.setOptions(\n      pluckInteractionOptions(\n        this.options,\n        typeof hunkSeparators === 'function' ||\n          hunkSeparators === 'line-info' ||\n          hunkSeparators === 'line-info-basic'\n          ? this.expandHunk\n          : undefined,\n        this.getLineIndex,\n        this.handleMergeConflictActionClick\n      )\n    );\n  }\n\n  protected override createHunksRenderer(\n    options: UnresolvedFileOptions<LAnnotation>\n  ): UnresolvedFileHunksRenderer<LAnnotation> {\n    const renderer = new UnresolvedFileHunksRenderer<LAnnotation>(\n      this.getHunksRendererOptions(options),\n      this.handleHighlightRender,\n      this.workerManager\n    );\n    return renderer;\n  }\n\n  protected override getHunksRendererOptions(\n    options: UnresolvedFileOptions<LAnnotation>\n  ): UnresolvedFileHunksRendererOptions {\n    return getUnresolvedDiffHunksRendererOptions(options, this.options);\n  }\n\n  protected override applyPreNodeAttributes(\n    pre: HTMLPreElement,\n    result: HunksRenderResult\n  ): void {\n    super.applyPreNodeAttributes(pre, result, {\n      'data-has-merge-conflict': '',\n    });\n  }\n\n  override cleanUp(): void {\n    this.clearMergeConflictActionCache();\n    this.computedCache = {\n      file: undefined,\n      fileDiff: undefined,\n      actions: undefined,\n      markerRows: undefined,\n    };\n    this.conflictActions = [];\n    super.cleanUp();\n  }\n\n  private getOrComputeDiff({\n    file,\n    fileDiff,\n    actions,\n    markerRows,\n  }: GetOrComputeDiffProps): GetOrComputeDiffResult | undefined {\n    const { maxContextLines, onMergeConflictAction } = this.options;\n    wrapper: {\n      // We are dealing with a controlled component\n      if (onMergeConflictAction != null) {\n        const hasFileDiff = fileDiff != null;\n        const hasActions = actions != null;\n        const hasMarkerRows = markerRows != null;\n        if (hasFileDiff !== hasActions || hasFileDiff !== hasMarkerRows) {\n          throw new Error(\n            'UnresolvedFile.getOrComputeDiff: fileDiff, actions, and markerRows must be passed together'\n          );\n        }\n        // If we were provided a new fileDiff/actions/markerRows, we are a FULLY\n        // controlled component, which means we will not do any computation\n        if (fileDiff != null && actions != null && markerRows != null) {\n          this.computedCache = {\n            file: file ?? this.computedCache.file,\n            fileDiff,\n            actions,\n            markerRows,\n          };\n          break wrapper;\n        }\n        // If we were provided a new file, we should attempt to parse out a new\n        // diff/actions if we haven't computed it before. Once we initialize from\n        // a file, later updates must flow through fileDiff/actions instead of\n        // reparsing from a new file input.\n        else if (file != null || this.computedCache.file != null) {\n          if (\n            file != null &&\n            this.computedCache.file != null &&\n            !areFilesEqual(file, this.computedCache.file) &&\n            this.computedCache.fileDiff != null &&\n            this.computedCache.actions != null\n          ) {\n            throw new Error(\n              'UnresolvedFile.getOrComputeDiff: file can only be used to initialize unresolved state once. Pass fileDiff and actions for subsequent updates.'\n            );\n          }\n          file ??= this.computedCache.file;\n          if (file == null) {\n            throw new Error(\n              'UnresolvedFile.getOrComputeDiff: file is null, should be impossible'\n            );\n          }\n          if (\n            !areFilesEqual(file, this.computedCache.file) ||\n            this.computedCache.fileDiff == null ||\n            this.computedCache.actions == null\n          ) {\n            const computed = parseMergeConflictDiffFromFile(\n              file,\n              maxContextLines\n            );\n            this.computedCache = {\n              file,\n              fileDiff: computed.fileDiff,\n              actions: computed.actions,\n              markerRows: computed.markerRows,\n            };\n          }\n          fileDiff = this.computedCache.fileDiff;\n          actions = this.computedCache.actions;\n          markerRows = this.computedCache.markerRows;\n          break wrapper;\n        }\n        // Otherwise we should fall through and try to use the cache if it exists\n        else {\n          fileDiff = this.computedCache.fileDiff;\n          actions = this.computedCache.actions;\n          markerRows = this.computedCache.markerRows;\n          break wrapper;\n        }\n      }\n      // If we are uncontrolled we only rely on the file and only use the first\n      // version. After that, the cached diff/action pair is the source of\n      // truth and we should not accept a new file input.\n      else {\n        if (fileDiff != null || actions != null || markerRows != null) {\n          throw new Error(\n            'UnresolvedFile.getOrComputeDiff: fileDiff, actions, and markerRows are only usable in controlled mode, you must pass in `onMergeConflictAction`'\n          );\n        }\n        if (\n          file != null &&\n          this.computedCache.file != null &&\n          !areFilesEqual(file, this.computedCache.file)\n        ) {\n          throw new Error(\n            'UnresolvedFile.getOrComputeDiff: uncontrolled unresolved files parse the file only once. Later updates must come from the cached diff state.'\n          );\n        }\n        this.computedCache.file ??= file;\n        if (\n          this.computedCache.fileDiff == null &&\n          this.computedCache.file != null\n        ) {\n          const computed = parseMergeConflictDiffFromFile(\n            this.computedCache.file,\n            maxContextLines\n          );\n          this.computedCache.fileDiff = computed.fileDiff;\n          this.computedCache.actions = computed.actions;\n          this.computedCache.markerRows = computed.markerRows;\n        }\n        // Because we are uncontrolled, the source of truth is the\n        // computedCache\n        fileDiff = this.computedCache.fileDiff;\n        actions = this.computedCache.actions;\n        markerRows = this.computedCache.markerRows;\n        break wrapper;\n      }\n    }\n    if (fileDiff == null || actions == null || markerRows == null) {\n      return undefined;\n    }\n    return { fileDiff, actions, markerRows };\n  }\n\n  override hydrate(props: UnresolvedFileHydrationProps<LAnnotation>): void {\n    const {\n      file,\n      fileDiff,\n      actions,\n      markerRows,\n      lineAnnotations,\n      fileContainer,\n      prerenderedHTML,\n      preventEmit = false,\n    } = props;\n    const source = this.getOrComputeDiff({\n      file,\n      fileDiff,\n      actions,\n      markerRows,\n    });\n    if (source == null) {\n      return;\n    }\n    this.hydrateElements(fileContainer, prerenderedHTML);\n    this.setActiveMergeConflictState(source.actions, source.markerRows);\n    // If necessary hydration elements don't exist, we should assume a full\n    // render\n    if (\n      shouldRenderCode(this.pre, source.fileDiff, this.options.collapsed) ||\n      shouldRenderHeader(\n        this.headerElement,\n        source.fileDiff,\n        this.options.disableFileHeader\n      )\n    ) {\n      this.render({ ...props, preventEmit: true });\n    }\n    // Otherwise orchestrate our setup\n    else {\n      this.hydrationSetup({ fileDiff: source.fileDiff, lineAnnotations });\n      if (this.pre != null) {\n        this.renderMergeConflictActionSlots();\n      }\n    }\n    if (!preventEmit) {\n      this.emitPostRender();\n    }\n  }\n\n  override rerender(): void {\n    if (!this.enabled || this.fileDiff == null) {\n      return;\n    }\n    this.render({ forceRender: true, renderRange: this.renderRange });\n  }\n\n  override render(props: UnresolvedFileRenderProps<LAnnotation> = {}): boolean {\n    let {\n      file,\n      fileDiff,\n      actions,\n      markerRows,\n      lineAnnotations,\n      preventEmit = false,\n      ...rest\n    } = props;\n    const source = this.getOrComputeDiff({\n      file,\n      fileDiff,\n      actions,\n      markerRows,\n    });\n    if (source == null) {\n      return false;\n    }\n    this.setActiveMergeConflictState(source.actions, source.markerRows);\n    const didRender = super.render({\n      ...rest,\n      fileDiff: source.fileDiff,\n      lineAnnotations,\n      preventEmit: true,\n    });\n    if (didRender) {\n      this.renderMergeConflictActionSlots();\n      if (!preventEmit) {\n        this.emitPostRender();\n      }\n    }\n    return didRender;\n  }\n\n  public resolveConflict(\n    conflictIndex: number,\n    resolution: MergeConflictResolution,\n    fileDiff: FileDiffMetadata | undefined = this.computedCache.fileDiff\n  ): ResolveConflictReturn | undefined {\n    const action = this.conflictActions[conflictIndex];\n    if (fileDiff == null || action == null) {\n      return undefined;\n    }\n\n    if (action.conflictIndex !== conflictIndex) {\n      console.error({ conflictIndex, action });\n      throw new Error(\n        \"UnresolvedFile.resolveConflict: conflictIndex and conflictAction don't match\"\n      );\n    }\n\n    const newFileDiff = resolveConflictDiff(fileDiff, action, resolution);\n    const previousFile = this.computedCache.file;\n    const { file, actions, markerRows } = rebuildFileAndActions({\n      fileDiff: newFileDiff,\n      previousActions: this.conflictActions,\n      resolvedConflictIndex: conflictIndex,\n      previousFile,\n      resolution,\n    });\n\n    return {\n      file,\n      fileDiff: newFileDiff,\n      actions,\n      markerRows,\n    };\n  }\n\n  private resolveConflictAndRender(\n    conflictIndex: number,\n    resolution: MergeConflictResolution\n  ): void {\n    const action = this.conflictActions[conflictIndex];\n    if (action == null) {\n      return;\n    }\n    if (action.conflictIndex !== conflictIndex) {\n      console.error({ conflictIndex, action });\n      throw new Error(\n        \"UnresolvedFile.resolveConflictAndRender: conflictIndex and conflictAction don't match\"\n      );\n    }\n    const payload: MergeConflictActionPayload = {\n      resolution,\n      conflict: action.conflict,\n    };\n    const { file, fileDiff, actions, markerRows } =\n      this.resolveConflict(conflictIndex, resolution) ?? {};\n    if (\n      file == null ||\n      fileDiff == null ||\n      actions == null ||\n      markerRows == null\n    ) {\n      return;\n    }\n\n    this.computedCache = { file, fileDiff, actions, markerRows };\n    this.setActiveMergeConflictState(actions, markerRows);\n    // NOTE(amadeus): This is a bit jank, but helps to ensure we don't see a\n    // bunch of jittery re-renders as things resolve out.  In a more perfect\n    // world we would have a more elegant way to kick off a render to the\n    // highlighter and then resolve actions in a cleaner way, but time is short\n    // right now.  Can't let perfect be the enemy of good\n    if (this.workerManager != null) {\n      // Because we are using a workerManager, if we fire off the renderDiff\n      // call, it will eventually get back to us in a callback which will\n      // trigger a re-render\n      this.hunksRenderer.renderDiff(fileDiff);\n    } else {\n      this.render({ forceRender: true });\n    }\n    this.options.onMergeConflictResolve?.(file, payload);\n  }\n\n  private setActiveMergeConflictState(\n    actions: (MergeConflictDiffAction | undefined)[] = this.conflictActions,\n    markerRows: MergeConflictMarkerRow[] = this.markerRows\n  ): void {\n    this.conflictActions = actions;\n    this.markerRows = markerRows;\n    if (\n      this.computedCache.fileDiff != null &&\n      this.hunksRenderer instanceof UnresolvedFileHunksRenderer\n    ) {\n      this.hunksRenderer.setConflictState(\n        this.options.mergeConflictActionsType === 'none' ? [] : actions,\n        markerRows,\n        this.computedCache.fileDiff\n      );\n    }\n  }\n\n  private handleMergeConflictActionClick = (\n    target: MergeConflictActionTarget\n  ): void => {\n    const action = this.conflictActions[target.conflictIndex];\n    if (action == null) {\n      return;\n    }\n    if (action.conflictIndex !== target.conflictIndex) {\n      console.error({ conflictIndex: target.conflictIndex, action });\n      throw new Error(\n        \"UnresolvedFile.handleMergeConflictActionClick: conflictIndex and conflictAction don't match\"\n      );\n    }\n    const payload: MergeConflictActionPayload = {\n      resolution: target.resolution,\n      conflict: action.conflict,\n    };\n    if (this.options.onMergeConflictAction != null) {\n      this.options.onMergeConflictAction(payload, this);\n      return;\n    }\n    this.resolveConflictAndRender(target.conflictIndex, target.resolution);\n  };\n\n  private renderMergeConflictActionSlots(): void {\n    const { fileDiff } = this.computedCache;\n    if (\n      this.isContainerManaged ||\n      this.fileContainer == null ||\n      typeof this.options.mergeConflictActionsType !== 'function' ||\n      this.conflictActions.length === 0 ||\n      fileDiff == null\n    ) {\n      this.clearMergeConflictActionCache();\n      return;\n    }\n    const staleActions = new Map(this.conflictActionCache);\n    for (\n      let actionIndex = 0;\n      actionIndex < this.conflictActions.length;\n      actionIndex++\n    ) {\n      const action = this.conflictActions[actionIndex];\n      if (action == null) {\n        continue;\n      }\n      if (action.conflictIndex !== actionIndex) {\n        console.error({ conflictIndex: actionIndex, action });\n        throw new Error(\n          \"UnresolvedFile.renderMergeConflictActionSlots: conflictIndex and conflictAction don't match\"\n        );\n      }\n      const anchor = getMergeConflictActionAnchor(action, fileDiff);\n      if (anchor == null) {\n        continue;\n      }\n      const conflictIndex = action.conflictIndex;\n      const slotName = getMergeConflictActionSlotName({\n        hunkIndex: anchor.hunkIndex,\n        lineIndex: anchor.lineIndex,\n        conflictIndex,\n      });\n      const id = `${actionIndex}-${slotName}`;\n      let cache = this.conflictActionCache.get(id);\n      if (\n        cache == null ||\n        !areMergeConflictActionsEqual(cache.action, action)\n      ) {\n        cache?.element.remove();\n        const rendered = this.renderMergeConflictAction(action);\n        if (rendered == null) {\n          continue;\n        }\n        const element = createAnnotationWrapperNode(slotName);\n        element.appendChild(rendered);\n        this.fileContainer.appendChild(element);\n        cache = { element, action };\n        this.conflictActionCache.set(id, cache);\n      }\n      staleActions.delete(id);\n    }\n    for (const [id, { element }] of staleActions.entries()) {\n      this.conflictActionCache.delete(id);\n      element.remove();\n    }\n  }\n\n  private renderMergeConflictAction(\n    action: MergeConflictDiffAction\n  ): HTMLElement | undefined {\n    if (typeof this.options.mergeConflictActionsType !== 'function') {\n      return undefined;\n    }\n    const rendered = this.options.mergeConflictActionsType(action, this);\n    if (rendered == null) {\n      return undefined;\n    }\n    if (rendered instanceof HTMLElement) {\n      return rendered;\n    }\n    if (\n      typeof DocumentFragment !== 'undefined' &&\n      rendered instanceof DocumentFragment\n    ) {\n      const wrapper = document.createElement('div');\n      wrapper.style.display = 'contents';\n      wrapper.appendChild(rendered);\n      return wrapper;\n    }\n    return undefined;\n  }\n\n  private clearMergeConflictActionCache(): void {\n    for (const { element } of this.conflictActionCache.values()) {\n      element.remove();\n    }\n    this.conflictActionCache.clear();\n  }\n}\n\ninterface RebuildFileAndActionsProps {\n  fileDiff: FileDiffMetadata;\n  previousActions: (MergeConflictDiffAction | undefined)[];\n  resolvedConflictIndex: number;\n  // FIXME: Probably should remove this...\n  // additionOffset: number;\n  // deletionOffset: number;\n  previousFile: FileContents | undefined;\n  resolution: MergeConflictResolution;\n}\n\n// Rebuild the emitted unresolved file contents and remaining action anchors in\n// one pass over the post-resolution diff state.\nfunction rebuildFileAndActions({\n  fileDiff,\n  previousActions,\n  resolvedConflictIndex,\n  previousFile,\n  resolution,\n}: RebuildFileAndActionsProps): Pick<\n  ResolveConflictReturn,\n  'file' | 'actions' | 'markerRows'\n> {\n  const resolvedAction = previousActions[resolvedConflictIndex];\n  if (resolvedAction == null) {\n    throw new Error(\n      'rebuildFileAndActions: missing resolved action for unresolved file rebuild'\n    );\n  }\n\n  const actions = updateConflictActionsAfterResolution(\n    previousActions,\n    resolvedConflictIndex,\n    resolvedAction,\n    resolution\n  );\n  const markerRows = buildMergeConflictMarkerRows(fileDiff, actions);\n\n  const file = rebuildUnresolvedFile({\n    fileDiff,\n    resolvedAction,\n    resolvedConflictIndex,\n    previousFile,\n    resolution,\n  });\n\n  return {\n    file,\n    actions,\n    markerRows,\n  };\n}\n\ninterface RebuildUnresolvedFileProps {\n  fileDiff: FileDiffMetadata;\n  resolvedAction: MergeConflictDiffAction;\n  resolvedConflictIndex: number;\n  previousFile: FileContents | undefined;\n  resolution: MergeConflictResolution;\n}\n\n// Rebuild the unresolved file text from the previous unresolved source so we\n// preserve remaining marker blocks exactly while the diff state stays in-place.\nfunction rebuildUnresolvedFile({\n  resolvedAction,\n  resolvedConflictIndex,\n  previousFile,\n  fileDiff,\n  resolution,\n}: RebuildUnresolvedFileProps): FileContents {\n  const previousContents = previousFile?.contents ?? '';\n  const lines = splitFileContents(previousContents);\n  const { conflict } = resolvedAction;\n  const replacementLines = getResolvedConflictReplacementLines(\n    lines,\n    conflict,\n    resolution\n  );\n  const contents = [\n    ...lines.slice(0, conflict.startLineIndex),\n    ...replacementLines,\n    ...lines.slice(conflict.endLineIndex + 1),\n  ].join('');\n\n  return {\n    name: previousFile?.name ?? fileDiff.name,\n    contents,\n    cacheKey:\n      previousFile?.cacheKey != null\n        ? `${previousFile.cacheKey}:mc-${resolvedConflictIndex}-${resolution}`\n        : undefined,\n  };\n}\n\nfunction getResolvedConflictReplacementLines(\n  lines: string[],\n  conflict: MergeConflictDiffAction['conflict'],\n  resolution: MergeConflictResolution\n): string[] {\n  const currentLines = lines.slice(\n    conflict.startLineIndex + 1,\n    conflict.baseMarkerLineIndex ?? conflict.separatorLineIndex\n  );\n  const incomingLines = lines.slice(\n    conflict.separatorLineIndex + 1,\n    conflict.endLineIndex\n  );\n\n  if (resolution === 'current') {\n    return currentLines;\n  }\n  if (resolution === 'incoming') {\n    return incomingLines;\n  }\n  return [...currentLines, ...incomingLines];\n}\n\n// The diff resolver keeps hunk/content group indexes stable, so the only\n// follow-up update we need here is shifting unresolved source-region line\n// numbers for later conflicts in the rebuilt file text.\nfunction updateConflictActionsAfterResolution(\n  previousActions: (MergeConflictDiffAction | undefined)[],\n  resolvedConflictIndex: number,\n  resolvedAction: MergeConflictDiffAction,\n  resolution: MergeConflictResolution\n): (MergeConflictDiffAction | undefined)[] {\n  const lineDelta = getResolvedConflictLineDelta(\n    resolvedAction.conflict,\n    resolution\n  );\n\n  return previousActions.map((action, index) => {\n    if (index === resolvedConflictIndex) {\n      return undefined;\n    }\n    if (action == null) {\n      return undefined;\n    }\n    if (action.conflict.startLineIndex > resolvedAction.conflict.endLineIndex) {\n      return {\n        ...action,\n        conflict: shiftMergeConflictRegion(action.conflict, lineDelta),\n      };\n    }\n    return action;\n  });\n}\n\nfunction getResolvedConflictLineDelta(\n  conflict: MergeConflictRegion,\n  resolution: MergeConflictResolution\n): number {\n  const currentLineCount =\n    (conflict.baseMarkerLineIndex ?? conflict.separatorLineIndex) -\n    conflict.startLineIndex -\n    1;\n  const incomingLineCount =\n    conflict.endLineIndex - conflict.separatorLineIndex - 1;\n  const replacementLineCount =\n    resolution === 'current'\n      ? currentLineCount\n      : resolution === 'incoming'\n        ? incomingLineCount\n        : currentLineCount + incomingLineCount;\n  const conflictLineCount = conflict.endLineIndex - conflict.startLineIndex + 1;\n  return replacementLineCount - conflictLineCount;\n}\n\nfunction shiftMergeConflictRegion(\n  conflict: MergeConflictRegion,\n  lineDelta: number\n): MergeConflictRegion {\n  return {\n    ...conflict,\n    startLineIndex: conflict.startLineIndex + lineDelta,\n    startLineNumber: conflict.startLineNumber + lineDelta,\n    separatorLineIndex: conflict.separatorLineIndex + lineDelta,\n    separatorLineNumber: conflict.separatorLineNumber + lineDelta,\n    endLineIndex: conflict.endLineIndex + lineDelta,\n    endLineNumber: conflict.endLineNumber + lineDelta,\n    baseMarkerLineIndex:\n      conflict.baseMarkerLineIndex != null\n        ? conflict.baseMarkerLineIndex + lineDelta\n        : undefined,\n    baseMarkerLineNumber:\n      conflict.baseMarkerLineNumber != null\n        ? conflict.baseMarkerLineNumber + lineDelta\n        : undefined,\n  };\n}\n\nfunction shouldRenderCode(\n  pre: HTMLPreElement | undefined,\n  fileDiff: FileDiffMetadata | undefined,\n  collapsed = false\n): boolean {\n  return !collapsed && pre == null && fileDiff != null;\n}\n\nfunction shouldRenderHeader(\n  headerElement: HTMLElement | undefined,\n  fileDiff: FileDiffMetadata | undefined,\n  disableFileHeader = false\n): boolean {\n  return headerElement == null && fileDiff != null && !disableFileHeader;\n}\n\n// NOTE(amadeus): Should probably pull this out into a util, and make variants\n// for all component types\nexport function getUnresolvedDiffHunksRendererOptions<LAnnotation>(\n  options?: UnresolvedFileOptions<LAnnotation>,\n  baseOptions?: UnresolvedFileOptions<LAnnotation>\n): UnresolvedFileHunksRendererOptions {\n  return {\n    ...baseOptions,\n    ...options,\n    hunkSeparators:\n      typeof options?.hunkSeparators === 'function'\n        ? 'custom'\n        : options?.hunkSeparators,\n    mergeConflictActionsType:\n      typeof options?.mergeConflictActionsType === 'function'\n        ? 'custom'\n        : options?.mergeConflictActionsType,\n  };\n}\n"],"mappings":"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"}