@pierre/diffs 1.3.0-beta.6 → 1.3.0-beta.8
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.
- package/dist/components/CodeView.d.ts +90 -5
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +291 -38
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +1 -0
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +20 -6
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +38 -23
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +144 -61
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts +3 -2
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +4 -2
- package/dist/components/UnresolvedFile.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +6 -8
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +13 -5
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +192 -55
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/Virtualizer.d.ts +2 -0
- package/dist/components/Virtualizer.d.ts.map +1 -1
- package/dist/components/Virtualizer.js +16 -3
- package/dist/components/Virtualizer.js.map +1 -1
- package/dist/constants.d.ts +3 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/editor/command.d.ts +1 -1
- package/dist/editor/command.d.ts.map +1 -1
- package/dist/editor/command.js +8 -0
- package/dist/editor/command.js.map +1 -1
- package/dist/editor/editor.d.ts +10 -3
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +325 -135
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +84 -12
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +5 -3
- package/dist/editor/marker.d.ts.map +1 -1
- package/dist/editor/marker.js +35 -12
- package/dist/editor/marker.js.map +1 -1
- package/dist/editor/matchBrackets.d.ts +8 -0
- package/dist/editor/matchBrackets.d.ts.map +1 -0
- package/dist/editor/matchBrackets.js +146 -0
- package/dist/editor/matchBrackets.js.map +1 -0
- package/dist/editor/popover.d.ts +45 -0
- package/dist/editor/popover.d.ts.map +1 -0
- package/dist/editor/popover.js +145 -0
- package/dist/editor/popover.js.map +1 -0
- package/dist/editor/selection.d.ts +14 -2
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +142 -41
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/selectionAction.d.ts +20 -3
- package/dist/editor/selectionAction.d.ts.map +1 -1
- package/dist/editor/selectionAction.js +41 -10
- package/dist/editor/selectionAction.js.map +1 -1
- package/dist/editor/textDocument.d.ts +2 -0
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +22 -6
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +25 -7
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/tokenzier.d.ts +6 -7
- package/dist/editor/tokenzier.d.ts.map +1 -1
- package/dist/editor/tokenzier.js +83 -34
- package/dist/editor/tokenzier.js.map +1 -1
- package/dist/editor/utils.d.ts +3 -1
- package/dist/editor/utils.d.ts.map +1 -1
- package/dist/editor/utils.js +14 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/index.d.ts +9 -7
- package/dist/index.js +6 -4
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +0 -1
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/managers/ResizeManager.d.ts +10 -2
- package/dist/managers/ResizeManager.d.ts.map +1 -1
- package/dist/managers/ResizeManager.js +33 -13
- package/dist/managers/ResizeManager.js.map +1 -1
- package/dist/react/CodeView.d.ts +25 -1
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +76 -17
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/EditorContext.d.ts +2 -2
- package/dist/react/EditorContext.d.ts.map +1 -1
- package/dist/react/EditorContext.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +3 -4
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/utils/useFileDiffInstance.js +14 -15
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +2 -2
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +45 -23
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +2 -1
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +58 -38
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/preloadDiffs.d.ts +11 -10
- package/dist/ssr/preloadDiffs.d.ts.map +1 -1
- package/dist/ssr/preloadDiffs.js +14 -6
- package/dist/ssr/preloadDiffs.js.map +1 -1
- package/dist/types.d.ts +100 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/applyLineTextWithNewline.d.ts +5 -0
- package/dist/utils/applyLineTextWithNewline.d.ts.map +1 -0
- package/dist/utils/applyLineTextWithNewline.js +11 -0
- package/dist/utils/applyLineTextWithNewline.js.map +1 -0
- package/dist/utils/areHunkDataEqual.js +1 -1
- package/dist/utils/areHunkDataEqual.js.map +1 -1
- package/dist/utils/areManagedSnapshotsEqual.d.ts +2 -2
- package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
- package/dist/utils/areManagedSnapshotsEqual.js +5 -0
- package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
- package/dist/utils/awaitWithTimeout.d.ts +5 -0
- package/dist/utils/awaitWithTimeout.d.ts.map +1 -0
- package/dist/utils/awaitWithTimeout.js +15 -0
- package/dist/utils/awaitWithTimeout.js.map +1 -0
- package/dist/utils/cloneFileDiffMetadata.d.ts +7 -0
- package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -0
- package/dist/utils/cloneFileDiffMetadata.js +16 -0
- package/dist/utils/cloneFileDiffMetadata.js.map +1 -0
- package/dist/utils/computeEstimatedDiffHeights.d.ts +3 -1
- package/dist/utils/computeEstimatedDiffHeights.d.ts.map +1 -1
- package/dist/utils/computeEstimatedDiffHeights.js +8 -1
- package/dist/utils/computeEstimatedDiffHeights.js.map +1 -1
- package/dist/utils/createCodeViewHeaderFooterHostElement.d.ts +5 -0
- package/dist/utils/createCodeViewHeaderFooterHostElement.d.ts.map +1 -0
- package/dist/utils/createCodeViewHeaderFooterHostElement.js +19 -0
- package/dist/utils/createCodeViewHeaderFooterHostElement.js.map +1 -0
- package/dist/utils/createPreElement.js +0 -1
- package/dist/utils/createPreElement.js.map +1 -1
- package/dist/utils/getDiffFileInput.d.ts +14 -0
- package/dist/utils/getDiffFileInput.d.ts.map +1 -0
- package/dist/utils/getDiffFileInput.js +24 -0
- package/dist/utils/getDiffFileInput.js.map +1 -0
- package/dist/utils/getDiffHunksRendererOptions.js +1 -0
- package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
- package/dist/utils/getFiletypeFromFileName.d.ts.map +1 -1
- package/dist/utils/getFiletypeFromFileName.js +2 -0
- package/dist/utils/getFiletypeFromFileName.js.map +1 -1
- package/dist/utils/hydratePartialDiff.d.ts +10 -0
- package/dist/utils/hydratePartialDiff.d.ts.map +1 -0
- package/dist/utils/hydratePartialDiff.js +140 -0
- package/dist/utils/hydratePartialDiff.js.map +1 -0
- package/dist/utils/iterateOverDiff.js +3 -3
- package/dist/utils/iterateOverDiff.js.map +1 -1
- package/dist/utils/parseDiffFromFile.d.ts +1 -1
- package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseDiffFromFile.js +26 -5
- package/dist/utils/parseDiffFromFile.js.map +1 -1
- package/dist/utils/setWrapperNodeProps.js +0 -1
- package/dist/utils/setWrapperNodeProps.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +5 -1
- package/dist/utils/updateDiffHunks.d.ts.map +1 -1
- package/dist/utils/updateDiffHunks.js +48 -4
- package/dist/utils/updateDiffHunks.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +7 -2
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +78 -15
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/index.d.ts +2 -2
- package/dist/worker/types.d.ts +7 -1
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker-portable.js +5 -3
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +5 -3
- package/dist/worker/worker.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydratePartialDiff.js","names":[],"sources":["../../src/utils/hydratePartialDiff.ts"],"sourcesContent":["import type {\n FileContents,\n FileDiffLoadedFiles,\n FileDiffMetadata,\n Hunk,\n} from '../types';\nimport { cloneFileDiffMetadata } from './cloneFileDiffMetadata';\nimport { splitFileContents } from './splitFileContents';\n\ninterface HydratedHunksResult {\n hunks: Hunk[];\n splitLineCount: number;\n unifiedLineCount: number;\n}\n\n/**\n * Hydrates a partial diff in place with full file line arrays.\n */\nexport function hydratePartialDiff(\n type: 'clone' | 'merge',\n fileDiff: FileDiffMetadata,\n files: FileDiffLoadedFiles\n): FileDiffMetadata {\n const targetFileDiff =\n type === 'clone' ? cloneFileDiffMetadata(fileDiff) : fileDiff;\n\n if (!targetFileDiff.isPartial) {\n throw new Error('hydratePartialDiff: fileDiff must be partial');\n }\n\n switch (targetFileDiff.type) {\n case 'change':\n case 'rename-changed': {\n const oldFile = requireOldFile(targetFileDiff, files);\n const newFile = requireNewFile(targetFileDiff, files);\n return hydrateTwoSidedFileDiff(targetFileDiff, oldFile, newFile);\n }\n case 'rename-pure': {\n const newFile = requireNewFile(targetFileDiff, files);\n requireMissingOldFile(targetFileDiff, files);\n const lines = splitFileContents(newFile.contents);\n targetFileDiff.isPartial = false;\n targetFileDiff.deletionLines = lines;\n targetFileDiff.additionLines = lines;\n setHydratedCacheKey(targetFileDiff, null, newFile);\n return targetFileDiff;\n }\n }\n throw new Error(\n `hydratePartialDiff: ${targetFileDiff.type} diffs cannot be hydrated from loaded files`\n );\n}\n\nfunction hydrateTwoSidedFileDiff(\n fileDiff: FileDiffMetadata,\n oldFile: FileContents,\n newFile: FileContents\n): FileDiffMetadata {\n const deletionLines = splitFileContents(oldFile.contents);\n const additionLines = splitFileContents(newFile.contents);\n const { hunks, splitLineCount, unifiedLineCount } = hydrateHunks(\n fileDiff.hunks,\n additionLines.length\n );\n\n fileDiff.hunks = hunks;\n fileDiff.splitLineCount = splitLineCount;\n fileDiff.unifiedLineCount = unifiedLineCount;\n fileDiff.isPartial = false;\n fileDiff.deletionLines = deletionLines;\n fileDiff.additionLines = additionLines;\n setHydratedCacheKey(fileDiff, oldFile, newFile);\n return fileDiff;\n}\n\nfunction hydrateHunks(\n hunks: Hunk[],\n totalAdditionLines: number\n): HydratedHunksResult {\n let splitLineCount = 0;\n let unifiedLineCount = 0;\n let lastHunkAdditionEnd = 0;\n\n const hydratedHunks: Hunk[] = [];\n\n for (const hunk of hunks) {\n const additionLineIndex = Math.max(hunk.additionStart - 1, 0);\n const deletionLineIndex = Math.max(hunk.deletionStart - 1, 0);\n let contentAdditionLineIndex = additionLineIndex;\n let contentDeletionLineIndex = deletionLineIndex;\n let hunkAdditionLines = 0;\n let hunkDeletionLines = 0;\n let hunkSplitLineCount = 0;\n let hunkUnifiedLineCount = 0;\n const hunkContent: Hunk['hunkContent'] = [];\n\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n hunkContent.push({\n ...content,\n additionLineIndex: contentAdditionLineIndex,\n deletionLineIndex: contentDeletionLineIndex,\n });\n contentAdditionLineIndex += content.lines;\n contentDeletionLineIndex += content.lines;\n hunkSplitLineCount += content.lines;\n hunkUnifiedLineCount += content.lines;\n continue;\n }\n\n hunkContent.push({\n ...content,\n additionLineIndex: contentAdditionLineIndex,\n deletionLineIndex: contentDeletionLineIndex,\n });\n contentAdditionLineIndex += content.additions;\n contentDeletionLineIndex += content.deletions;\n hunkAdditionLines += content.additions;\n hunkDeletionLines += content.deletions;\n hunkSplitLineCount += Math.max(content.additions, content.deletions);\n hunkUnifiedLineCount += content.additions + content.deletions;\n }\n\n const collapsedBefore = Math.max(\n hunk.additionStart - 1 - lastHunkAdditionEnd,\n 0\n );\n hydratedHunks.push({\n ...hunk,\n collapsedBefore,\n additionLineIndex,\n deletionLineIndex,\n additionLines: hunkAdditionLines,\n deletionLines: hunkDeletionLines,\n hunkContent,\n splitLineStart: splitLineCount + collapsedBefore,\n unifiedLineStart: unifiedLineCount + collapsedBefore,\n splitLineCount: hunkSplitLineCount,\n unifiedLineCount: hunkUnifiedLineCount,\n });\n\n splitLineCount += collapsedBefore + hunkSplitLineCount;\n unifiedLineCount += collapsedBefore + hunkUnifiedLineCount;\n lastHunkAdditionEnd = hunk.additionStart + hunk.additionCount - 1;\n }\n\n if (hydratedHunks.length > 0) {\n const lastHunk = hydratedHunks[hydratedHunks.length - 1];\n const lastHunkEnd = Math.max(\n lastHunk.additionStart + lastHunk.additionCount - 1,\n 0\n );\n const collapsedAfter = Math.max(totalAdditionLines - lastHunkEnd, 0);\n splitLineCount += collapsedAfter;\n unifiedLineCount += collapsedAfter;\n }\n\n return { hunks: hydratedHunks, splitLineCount, unifiedLineCount };\n}\n\nfunction requireOldFile(\n fileDiff: FileDiffMetadata,\n files: FileDiffLoadedFiles\n): FileContents {\n if (files.oldFile == null) {\n throw new Error(\n `hydratePartialDiff: ${fileDiff.type} diff for ${fileDiff.name} requires oldFile`\n );\n }\n return files.oldFile;\n}\n\nfunction requireNewFile(\n fileDiff: FileDiffMetadata,\n files: FileDiffLoadedFiles\n): FileContents {\n if (files.newFile == null) {\n throw new Error(\n `hydratePartialDiff: ${fileDiff.type} diff for ${fileDiff.name} requires newFile`\n );\n }\n return files.newFile;\n}\n\nfunction requireMissingOldFile(\n fileDiff: FileDiffMetadata,\n files: FileDiffLoadedFiles\n): void {\n if (files.oldFile !== null) {\n throw new Error(\n `hydratePartialDiff: ${fileDiff.type} diff for ${fileDiff.name} requires oldFile to be null`\n );\n }\n}\n\nfunction getHydratedCacheKey(\n fileDiff: FileDiffMetadata,\n oldFile: FileContents | null,\n newFile: FileContents | null\n): string | undefined {\n if (fileDiff.cacheKey != null) {\n return `${fileDiff.cacheKey}:hydrated`;\n }\n return getLoadedFileCacheKey(oldFile, newFile);\n}\n\nfunction setHydratedCacheKey(\n fileDiff: FileDiffMetadata,\n oldFile: FileContents | null,\n newFile: FileContents | null\n): void {\n const cacheKey = getHydratedCacheKey(fileDiff, oldFile, newFile);\n if (cacheKey == null) {\n delete fileDiff.cacheKey;\n return;\n }\n fileDiff.cacheKey = cacheKey;\n}\n\nfunction getLoadedFileCacheKey(\n oldFile: FileContents | null,\n newFile: FileContents | null\n): string | undefined {\n if (oldFile != null && newFile != null) {\n return oldFile.cacheKey != null && newFile.cacheKey != null\n ? `${oldFile.cacheKey}:${newFile.cacheKey}`\n : undefined;\n }\n return oldFile?.cacheKey ?? newFile?.cacheKey;\n}\n"],"mappings":"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"}
|
|
@@ -24,10 +24,10 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
|
|
|
24
24
|
else if (diffStyle === "split") return breakSplit;
|
|
25
25
|
else return breakUnified && breakSplit;
|
|
26
26
|
},
|
|
27
|
-
shouldSkip(
|
|
27
|
+
shouldSkip(unifiedCount, splitCount) {
|
|
28
28
|
if (!state.isWindowedHighlight) return false;
|
|
29
|
-
const skipUnified = state.unifiedCount +
|
|
30
|
-
const skipSplit = state.splitCount +
|
|
29
|
+
const skipUnified = unifiedCount > 0 && state.unifiedCount + unifiedCount <= startingLine;
|
|
30
|
+
const skipSplit = splitCount > 0 && state.splitCount + splitCount <= startingLine;
|
|
31
31
|
if (diffStyle === "unified") return skipUnified;
|
|
32
32
|
else if (diffStyle === "split") return skipSplit;
|
|
33
33
|
else return skipUnified && skipSplit;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterateOverDiff.js","names":[],"sources":["../../src/utils/iterateOverDiff.ts"],"sourcesContent":["import { DEFAULT_COLLAPSED_CONTEXT_THRESHOLD } from '../constants';\nimport type {\n ChangeContent,\n FileDiffMetadata,\n Hunk,\n HunkExpansionRegion,\n} from '../types';\nimport {\n getExpandedRegion,\n getTrailingExpandedRegion,\n} from './virtualDiffLayout';\n\nexport interface DiffLineMetadata {\n unifiedLineIndex: number;\n splitLineIndex: number;\n lineIndex: number;\n lineNumber: number;\n noEOFCR: boolean;\n}\n\nexport interface DiffLineCallbackBase {\n hunkIndex: number;\n hunk: Hunk | undefined; // undefined for trailing expansion region\n collapsedBefore: number; // > 0 means separator before this line, value = hidden lines\n collapsedAfter: number; // > 0 only on final line if trailing collapsed content\n}\n\ninterface DiffLineCallbackContextChange extends DiffLineCallbackBase {\n type: 'change' | 'context' | 'context-expanded';\n deletionLine: DiffLineMetadata;\n additionLine: DiffLineMetadata;\n}\n\ninterface DiffLineCallbackChangeDeletion extends DiffLineCallbackBase {\n type: 'change';\n deletionLine: DiffLineMetadata;\n additionLine?: undefined;\n}\n\ninterface DiffLineCallbackChangeAddition extends DiffLineCallbackBase {\n type: 'change';\n deletionLine?: undefined;\n additionLine: DiffLineMetadata;\n}\n\nexport type DiffLineCallbackProps =\n | DiffLineCallbackContextChange\n | DiffLineCallbackChangeDeletion\n | DiffLineCallbackChangeAddition;\n\ntype DiffStyle = 'unified' | 'split' | 'both';\n\ntype LineIterationBounds = [startIndex: number, endIndex: number];\n\ntype ChangeContentSide = 'deletions' | 'additions';\n\ntype ContextLineCallback = (index: number) => boolean | void;\n\ninterface IterationState {\n isWindowedHighlight: boolean;\n viewportStart: number;\n viewportEnd: number;\n splitCount: number;\n unifiedCount: number;\n finalHunkIndex: number;\n shouldBreak(): boolean;\n shouldSkip(unifiedHeight: number, splitHeight: number): boolean;\n incrementCounts(unifiedValue: number, splitValue: number): void;\n isInWindow(unifiedHeight: number, splitHeight: number): boolean;\n isInUnifiedWindow(height: number): boolean;\n isInSplitWindow(height: number): boolean;\n emit(props: DiffLineCallbackProps, silent?: boolean): boolean;\n}\n\ninterface IterationStartState {\n hunkIndex: number;\n splitCount: number;\n unifiedCount: number;\n}\n\ninterface HunkPrefixCounts {\n splitCount: number;\n unifiedCount: number;\n}\n\ninterface IterationStartStateProps extends Omit<\n IterateOverDiffProps,\n 'callback' | 'totalLines'\n> {\n startingLine: number;\n collapsedContextThreshold: number;\n}\n\ninterface HunkPrefixCountsProps extends Pick<\n IterationStartStateProps,\n 'diff' | 'expandedHunks' | 'collapsedContextThreshold'\n> {}\n\nexport type DiffLineCallback = (props: DiffLineCallbackProps) => boolean | void;\n\nexport interface IterateOverDiffProps {\n diff: FileDiffMetadata;\n diffStyle: DiffStyle;\n startingLine?: number;\n totalLines?: number;\n expandedHunks?: Map<number, HunkExpansionRegion> | true;\n collapsedContextThreshold?: number;\n callback: DiffLineCallback;\n}\n\nexport function iterateOverDiff({\n diff,\n diffStyle,\n startingLine = 0,\n totalLines = Infinity,\n expandedHunks,\n collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD,\n callback,\n}: IterateOverDiffProps): void {\n const iterationStart = getIterationStartState({\n diff,\n diffStyle,\n startingLine,\n expandedHunks,\n collapsedContextThreshold,\n });\n const state: IterationState = {\n viewportStart: startingLine,\n viewportEnd: startingLine + totalLines,\n isWindowedHighlight: startingLine > 0 || totalLines < Infinity,\n splitCount: iterationStart.splitCount,\n unifiedCount: iterationStart.unifiedCount,\n finalHunkIndex: diff.hunks.length - 1,\n shouldBreak() {\n if (!state.isWindowedHighlight) {\n return false;\n }\n\n const breakUnified = state.unifiedCount >= startingLine + totalLines;\n const breakSplit = state.splitCount >= startingLine + totalLines;\n\n if (diffStyle === 'unified') {\n return breakUnified;\n } else if (diffStyle === 'split') {\n return breakSplit;\n } else {\n return breakUnified && breakSplit;\n }\n },\n shouldSkip(unifiedHeight: number, splitHeight: number) {\n if (!state.isWindowedHighlight) {\n return false;\n }\n\n const skipUnified = state.unifiedCount + unifiedHeight < startingLine;\n const skipSplit = state.splitCount + splitHeight < startingLine;\n\n if (diffStyle === 'unified') {\n return skipUnified;\n } else if (diffStyle === 'split') {\n return skipSplit;\n } else {\n return skipUnified && skipSplit;\n }\n },\n incrementCounts(unifiedValue: number, splitValue: number) {\n if (diffStyle === 'unified' || diffStyle === 'both') {\n state.unifiedCount += unifiedValue;\n }\n if (diffStyle === 'split' || diffStyle === 'both') {\n state.splitCount += splitValue;\n }\n },\n isInWindow(unifiedHeight: number, splitHeight: number) {\n if (!state.isWindowedHighlight) {\n return true;\n }\n\n const unifiedInWindow = state.isInUnifiedWindow(unifiedHeight);\n const splitInWindow = state.isInSplitWindow(splitHeight);\n\n if (diffStyle === 'unified') {\n return unifiedInWindow;\n } else if (diffStyle === 'split') {\n return splitInWindow;\n } else {\n return unifiedInWindow || splitInWindow;\n }\n },\n isInUnifiedWindow(unifiedHeight: number) {\n return (\n !state.isWindowedHighlight ||\n (state.unifiedCount >= startingLine - unifiedHeight &&\n state.unifiedCount < startingLine + totalLines)\n );\n },\n isInSplitWindow(splitHeight: number) {\n return (\n !state.isWindowedHighlight ||\n (state.splitCount >= startingLine - splitHeight &&\n state.splitCount < startingLine + totalLines)\n );\n },\n emit(props: DiffLineCallbackProps, silent = false): boolean {\n if (!silent) {\n if (diffStyle === 'unified') {\n state.incrementCounts(1, 0);\n } else if (diffStyle === 'split') {\n state.incrementCounts(0, 1);\n } else {\n state.incrementCounts(1, 1);\n }\n }\n return callback(props) ?? false;\n },\n };\n\n hunkIterator: for (\n let hunkIndex = iterationStart.hunkIndex;\n hunkIndex < diff.hunks.length;\n hunkIndex++\n ) {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n throw new Error('iterateOverDiff: invalid hunk index');\n }\n if (state.shouldBreak()) {\n break;\n }\n\n const leadingRegion = getExpandedRegion({\n isPartial: diff.isPartial,\n rangeSize: hunk.collapsedBefore,\n expandedHunks,\n hunkIndex,\n collapsedContextThreshold,\n });\n const trailingRegion =\n hunkIndex === state.finalHunkIndex\n ? getTrailingExpandedRegion({\n fileDiff: diff,\n hunkIndex,\n expandedHunks,\n collapsedContextThreshold,\n errorPrefix: 'iterateOverDiff',\n })\n : undefined;\n const expandedLineCount = leadingRegion.fromStart + leadingRegion.fromEnd;\n\n function getTrailingCollapsedAfter(\n unifiedLineIndex: number,\n splitLineIndex: number\n ) {\n if (\n trailingRegion == null ||\n trailingRegion.collapsedLines <= 0 ||\n trailingRegion.fromStart + trailingRegion.fromEnd > 0\n ) {\n return 0;\n }\n if (diffStyle === 'unified') {\n return unifiedLineIndex ===\n hunk.unifiedLineStart + hunk.unifiedLineCount - 1\n ? trailingRegion.collapsedLines\n : 0;\n }\n return splitLineIndex === hunk.splitLineStart + hunk.splitLineCount - 1\n ? trailingRegion.collapsedLines\n : 0;\n }\n\n let consumedCollapsed = leadingRegion.collapsedLines === 0;\n function consumePendingCollapsed() {\n if (consumedCollapsed) {\n return 0;\n }\n consumedCollapsed = true;\n return leadingRegion.collapsedLines;\n }\n\n // Emit for expanded lines\n if (!state.shouldSkip(expandedLineCount, expandedLineCount)) {\n let unifiedLineIndex = hunk.unifiedLineStart - leadingRegion.rangeSize;\n let splitLineIndex = hunk.splitLineStart - leadingRegion.rangeSize;\n\n let deletionLineIndex = hunk.deletionLineIndex - leadingRegion.rangeSize;\n let additionLineIndex = hunk.additionLineIndex - leadingRegion.rangeSize;\n let deletionLineNumber = hunk.deletionStart - leadingRegion.rangeSize;\n let additionLineNumber = hunk.additionStart - leadingRegion.rangeSize;\n\n if (\n walkContextLines(state, leadingRegion.fromStart, diffStyle, (index) => {\n return state.emit({\n hunkIndex,\n hunk: hunk,\n collapsedBefore: 0,\n collapsedAfter: 0,\n type: 'context-expanded',\n deletionLine: {\n lineNumber: deletionLineNumber + index,\n lineIndex: deletionLineIndex + index,\n noEOFCR: false,\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n },\n additionLine: {\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n lineIndex: additionLineIndex + index,\n lineNumber: additionLineNumber + index,\n noEOFCR: false,\n },\n });\n })\n ) {\n break hunkIterator;\n }\n\n unifiedLineIndex = hunk.unifiedLineStart - leadingRegion.fromEnd;\n splitLineIndex = hunk.splitLineStart - leadingRegion.fromEnd;\n\n deletionLineIndex = hunk.deletionLineIndex - leadingRegion.fromEnd;\n additionLineIndex = hunk.additionLineIndex - leadingRegion.fromEnd;\n deletionLineNumber = hunk.deletionStart - leadingRegion.fromEnd;\n additionLineNumber = hunk.additionStart - leadingRegion.fromEnd;\n if (\n walkContextLines(\n state,\n leadingRegion.fromEnd,\n diffStyle,\n (index) => {\n return state.emit({\n hunkIndex,\n hunk,\n collapsedBefore: consumePendingCollapsed(),\n collapsedAfter: 0,\n type: 'context-expanded',\n deletionLine: {\n lineNumber: deletionLineNumber + index,\n lineIndex: deletionLineIndex + index,\n noEOFCR: false,\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n },\n additionLine: {\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n lineIndex: additionLineIndex + index,\n lineNumber: additionLineNumber + index,\n noEOFCR: false,\n },\n });\n },\n () => {\n // The collapsed separator belongs before this fromEnd slice. If the\n // render window starts inside the slice, consume it with the skipped\n // rows so it is not attached to the first emitted row.\n consumePendingCollapsed();\n }\n )\n ) {\n break hunkIterator;\n }\n } else {\n state.incrementCounts(expandedLineCount, expandedLineCount);\n consumePendingCollapsed();\n }\n\n let unifiedLineIndex = hunk.unifiedLineStart;\n let splitLineIndex = hunk.splitLineStart;\n\n let deletionLineIndex = hunk.deletionLineIndex;\n let additionLineIndex = hunk.additionLineIndex;\n let deletionLineNumber = hunk.deletionStart;\n let additionLineNumber = hunk.additionStart;\n const lastContent = hunk.hunkContent.at(-1);\n\n for (const content of hunk.hunkContent) {\n if (state.shouldBreak()) {\n break hunkIterator;\n }\n\n const isLastContent = content === lastContent;\n\n // Hunk Context Content\n if (content.type === 'context') {\n if (!state.shouldSkip(content.lines, content.lines)) {\n if (\n walkContextLines(\n state,\n content.lines,\n diffStyle,\n (index) => {\n const isLastLine = isLastContent && index === content.lines - 1;\n const unifiedRowIndex = unifiedLineIndex + index;\n const splitRowIndex = splitLineIndex + index;\n return state.emit({\n hunkIndex,\n hunk,\n collapsedBefore: consumePendingCollapsed(),\n collapsedAfter: getTrailingCollapsedAfter(\n unifiedRowIndex,\n splitRowIndex\n ),\n type: 'context',\n deletionLine: {\n lineNumber: deletionLineNumber + index,\n lineIndex: deletionLineIndex + index,\n noEOFCR: isLastLine && hunk.noEOFCRDeletions,\n unifiedLineIndex: unifiedRowIndex,\n splitLineIndex: splitRowIndex,\n },\n additionLine: {\n unifiedLineIndex: unifiedRowIndex,\n splitLineIndex: splitRowIndex,\n lineIndex: additionLineIndex + index,\n lineNumber: additionLineNumber + index,\n noEOFCR: isLastLine && hunk.noEOFCRAdditions,\n },\n });\n },\n () => {\n // When windowing starts inside context content, the leading\n // separator was above the visible range and should not be\n // emitted on the first rendered context line.\n consumePendingCollapsed();\n }\n )\n ) {\n break hunkIterator;\n }\n } else {\n state.incrementCounts(content.lines, content.lines);\n consumePendingCollapsed();\n }\n unifiedLineIndex += content.lines;\n splitLineIndex += content.lines;\n\n deletionLineIndex += content.lines;\n additionLineIndex += content.lines;\n deletionLineNumber += content.lines;\n additionLineNumber += content.lines;\n }\n // Hunk Change Content\n else {\n const splitCount = Math.max(content.deletions, content.additions);\n const unifiedCount = content.deletions + content.additions;\n const shouldSkipChange = state.shouldSkip(unifiedCount, splitCount);\n if (!shouldSkipChange) {\n const iterationRanges = getChangeIterationRanges(\n state,\n content,\n diffStyle\n );\n const firstRangeStart = iterationRanges[0]?.[0] ?? 0;\n if (firstRangeStart > 0) {\n // Change rows can be windowed from the middle of the block too. In\n // that case the leading separator belongs to skipped rows, not to\n // the first visible deletion/addition row.\n consumePendingCollapsed();\n }\n // Change ranges are already clipped to the active window. Counts move\n // once for the whole change block after the selected rows emit.\n for (const [rangeStart, rangeEnd] of iterationRanges) {\n for (let index = rangeStart; index < rangeEnd; index++) {\n const unifiedRowIndex = unifiedLineIndex + index;\n const splitRowIndex =\n diffStyle === 'unified'\n ? splitLineIndex +\n (index < content.deletions\n ? index\n : index - content.deletions)\n : splitLineIndex + index;\n const collapsedAfter = getTrailingCollapsedAfter(\n unifiedRowIndex,\n splitRowIndex\n );\n if (\n state.emit(\n getChangeLineData({\n hunkIndex,\n hunk,\n collapsedBefore: consumePendingCollapsed(),\n collapsedAfter,\n diffStyle,\n index,\n unifiedLineIndex,\n splitLineIndex,\n additionLineIndex,\n deletionLineIndex,\n additionLineNumber,\n deletionLineNumber,\n content,\n isLastContent,\n unifiedCount,\n splitCount,\n }),\n true\n )\n ) {\n break hunkIterator;\n }\n }\n }\n }\n\n consumePendingCollapsed();\n state.incrementCounts(unifiedCount, splitCount);\n unifiedLineIndex += unifiedCount;\n splitLineIndex += splitCount;\n deletionLineIndex += content.deletions;\n additionLineIndex += content.additions;\n deletionLineNumber += content.deletions;\n additionLineNumber += content.additions;\n }\n }\n\n if (trailingRegion != null) {\n const { collapsedLines, fromStart, fromEnd } = trailingRegion;\n const len = fromStart + fromEnd;\n if (\n walkContextLines(\n state,\n len,\n diffStyle,\n (index) => {\n const isLastLine = index === len - 1;\n return state.emit({\n hunkIndex: diff.hunks.length,\n hunk: undefined,\n collapsedBefore: 0,\n collapsedAfter: isLastLine ? collapsedLines : 0,\n type: 'context-expanded',\n deletionLine: {\n lineNumber: deletionLineNumber + index,\n lineIndex: deletionLineIndex + index,\n noEOFCR: false,\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n },\n additionLine: {\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n lineIndex: additionLineIndex + index,\n lineNumber: additionLineNumber + index,\n noEOFCR: false,\n },\n });\n },\n undefined,\n () => state.shouldBreak()\n )\n ) {\n break hunkIterator;\n }\n }\n }\n}\n\n// Seek the iterator to the hunk that contains `startingLine` without changing\n// the public meaning of `startingLine`: it is a dense rendered-row index, not\n// a raw split/unified line index. We first build prefix counts for each hunk\n// under the current expansion/collapse settings, binary-search those counts to\n// find the first hunk whose rendered rows cross `startingLine`, then seed the\n// running split/unified counters as if every prior hunk had already been\n// walked.\nfunction getIterationStartState({\n diff,\n diffStyle,\n startingLine,\n expandedHunks,\n collapsedContextThreshold,\n}: IterationStartStateProps): IterationStartState {\n if (startingLine <= 0 || diffStyle === 'both') {\n return { hunkIndex: 0, splitCount: 0, unifiedCount: 0 };\n }\n\n const prefixCounts = getHunkPrefixCounts({\n diff,\n expandedHunks,\n collapsedContextThreshold,\n });\n\n let low = 0;\n let high = diff.hunks.length - 1;\n let result = diff.hunks.length;\n\n while (low <= high) {\n const mid = (low + high) >> 1;\n const counts = prefixCounts[mid + 1];\n if (counts == null) {\n throw new Error('iterateOverDiff: invalid hunk prefix index');\n }\n const selectedCount =\n diffStyle === 'unified' ? counts.unifiedCount : counts.splitCount;\n\n if (selectedCount > startingLine) {\n result = mid;\n high = mid - 1;\n } else {\n low = mid + 1;\n }\n }\n\n if (result >= diff.hunks.length) {\n const counts = prefixCounts[diff.hunks.length];\n if (counts == null) {\n throw new Error('iterateOverDiff: invalid terminal hunk prefix index');\n }\n return {\n hunkIndex: diff.hunks.length,\n splitCount: counts.splitCount,\n unifiedCount: counts.unifiedCount,\n };\n }\n\n const counts = prefixCounts[result];\n if (counts == null) {\n throw new Error('iterateOverDiff: invalid selected hunk prefix index');\n }\n return {\n hunkIndex: result,\n splitCount: counts.splitCount,\n unifiedCount: counts.unifiedCount,\n };\n}\n\n// Build cumulative rendered-row counts at every hunk boundary for the current\n// expansion state. Entry 0 is always zero rows before the first hunk; entry N\n// is the split/unified row count after hunks [0, N). These counts let\n// getIterationStartState binary-search by dense rendered row without replaying\n// every prior hunk.\nfunction getHunkPrefixCounts({\n diff,\n expandedHunks,\n collapsedContextThreshold,\n}: HunkPrefixCountsProps): HunkPrefixCounts[] {\n let splitCount = 0;\n let unifiedCount = 0;\n const finalHunkIndex = diff.hunks.length - 1;\n const prefixCounts: HunkPrefixCounts[] = [\n {\n splitCount: 0,\n unifiedCount: 0,\n },\n ];\n\n for (let index = 0; index < diff.hunks.length; index++) {\n const hunk = diff.hunks[index];\n if (hunk == null) {\n throw new Error('iterateOverDiff: invalid hunk summary index');\n }\n\n const leadingRegion = getExpandedRegion({\n isPartial: diff.isPartial,\n rangeSize: hunk.collapsedBefore,\n expandedHunks,\n hunkIndex: index,\n collapsedContextThreshold,\n });\n const leadingCount = leadingRegion.fromStart + leadingRegion.fromEnd;\n splitCount += leadingCount + hunk.splitLineCount;\n unifiedCount += leadingCount + hunk.unifiedLineCount;\n\n const trailingRegion =\n index === finalHunkIndex\n ? getTrailingExpandedRegion({\n fileDiff: diff,\n hunkIndex: index,\n expandedHunks,\n collapsedContextThreshold,\n errorPrefix: 'iterateOverDiff',\n })\n : undefined;\n if (trailingRegion != null) {\n const trailingCount = trailingRegion.fromStart + trailingRegion.fromEnd;\n splitCount += trailingCount;\n unifiedCount += trailingCount;\n }\n\n prefixCounts.push({ splitCount, unifiedCount });\n }\n\n return prefixCounts;\n}\n\n// Clip a run of context rows to a single bounded hull around the active rendered\n// window. `diffStyle: both` can make split and unified rows visible in disjoint\n// ranges, so these bounds may include interior gaps that still need per-row\n// filtering before emitting.\nfunction getContextLineIterationBounds(\n state: IterationState,\n count: number,\n diffStyle: DiffStyle\n): LineIterationBounds {\n if (!state.isWindowedHighlight || count <= 0) {\n return [0, count];\n }\n\n const ranges: LineIterationBounds[] = [];\n function pushRange(currentCount: number): void {\n const start = Math.max(0, state.viewportStart - currentCount);\n const end = Math.min(count, state.viewportEnd - currentCount);\n if (end > start) {\n ranges.push([start, end]);\n }\n }\n\n if (diffStyle !== 'split') {\n pushRange(state.unifiedCount);\n }\n if (diffStyle !== 'unified') {\n pushRange(state.splitCount);\n }\n\n if (ranges.length === 0) {\n return [0, 0];\n }\n\n let start = ranges[0][0];\n let end = ranges[0][1];\n for (let index = 1; index < ranges.length; index++) {\n const range = ranges[index];\n start = Math.min(start, range[0]);\n end = Math.max(end, range[1]);\n }\n return [start, end];\n}\n\n// Walk context rows through the active window while keeping split and\n// unified counters aligned. The callback only runs after the final per-row\n// window check, which keeps `diffStyle: both` gap rows from being emitted.\nfunction walkContextLines(\n state: IterationState,\n count: number,\n diffStyle: DiffStyle,\n callback: ContextLineCallback,\n onSkippedStart?: () => void,\n shouldBreak?: () => boolean\n): boolean {\n const [startIndex, endIndex] = getContextLineIterationBounds(\n state,\n count,\n diffStyle\n );\n if (startIndex > 0) {\n state.incrementCounts(startIndex, startIndex);\n onSkippedStart?.();\n }\n\n let index = startIndex;\n while (index < count) {\n if (shouldBreak?.() === true) {\n return true;\n }\n if (index >= endIndex) {\n state.incrementCounts(count - index, count - index);\n break;\n }\n if (state.isInWindow(0, 0)) {\n if (callback(index) === true) {\n return true;\n }\n } else {\n state.incrementCounts(1, 1);\n }\n index++;\n }\n\n return false;\n}\n\n// Clip a change block to the rows that can be visible in the active coordinate\n// space. `diffStyle: both` iterates in split row space, but includes the unified\n// ranges too so either view can render the visible change rows it needs.\nfunction getChangeIterationRanges(\n state: IterationState,\n content: ChangeContent,\n diffStyle: DiffStyle\n): LineIterationBounds[] {\n // If not a window highlight, then we should just render the entire range\n if (!state.isWindowedHighlight) {\n return [\n [\n 0,\n diffStyle === 'unified'\n ? content.deletions + content.additions\n : Math.max(content.deletions, content.additions),\n ],\n ];\n }\n const useUnified = diffStyle !== 'split';\n const useSplit = diffStyle !== 'unified';\n const iterationSpace = diffStyle === 'unified' ? 'unified' : 'split';\n const iterationRanges: LineIterationBounds[] = [];\n function getVisibleRange(\n start: number,\n count: number\n ): LineIterationBounds | undefined {\n const end = start + count;\n if (end <= state.viewportStart || start >= state.viewportEnd) {\n return undefined;\n }\n const visibleStart = Math.max(0, state.viewportStart - start);\n const visibleEnd = Math.min(count, state.viewportEnd - start);\n return visibleEnd > visibleStart ? [visibleStart, visibleEnd] : undefined;\n }\n function mapRangeToIteration(\n range: LineIterationBounds,\n kind: ChangeContentSide\n ): LineIterationBounds {\n if (iterationSpace === 'split') {\n // For split iteration, additions/deletions are already in split row space.\n return range;\n }\n return kind === 'additions'\n ? [range[0] + content.deletions, range[1] + content.deletions]\n : range;\n }\n function pushRange(\n range: LineIterationBounds | undefined,\n kind: ChangeContentSide\n ) {\n if (range == null) {\n return;\n }\n const [start, end] = mapRangeToIteration(range, kind);\n if (end > start) {\n iterationRanges.push([start, end]);\n }\n }\n\n if (useUnified) {\n pushRange(\n getVisibleRange(state.unifiedCount, content.deletions),\n 'deletions'\n );\n pushRange(\n getVisibleRange(\n state.unifiedCount + content.deletions,\n content.additions\n ),\n 'additions'\n );\n }\n\n if (useSplit) {\n pushRange(\n getVisibleRange(state.splitCount, content.deletions),\n 'deletions'\n );\n pushRange(\n getVisibleRange(state.splitCount, content.additions),\n 'additions'\n );\n }\n\n if (iterationRanges.length === 0) {\n return iterationRanges;\n }\n\n iterationRanges.sort((a, b) => a[0] - b[0]);\n const merged: LineIterationBounds[] = [iterationRanges[0]];\n for (const [start, end] of iterationRanges.slice(1)) {\n const last = merged[merged.length - 1];\n if (start <= last[1]) {\n last[1] = Math.max(last[1], end);\n } else {\n merged.push([start, end]);\n }\n }\n\n return merged;\n}\n\ninterface GetChangeLineDataProps {\n hunkIndex: number;\n hunk: Hunk;\n collapsedBefore: number;\n collapsedAfter: number;\n diffStyle: DiffStyle;\n index: number;\n unifiedLineIndex: number;\n splitLineIndex: number;\n additionLineIndex: number;\n additionLineNumber: number;\n deletionLineNumber: number;\n deletionLineIndex: number;\n content: ChangeContent;\n isLastContent: boolean;\n unifiedCount: number;\n splitCount: number;\n}\n\n// Build the callback payload for one change row, mapping the selected row index\n// into split/unified coordinates and addition/deletion line metadata.\nfunction getChangeLineData({\n hunkIndex,\n hunk,\n collapsedAfter,\n collapsedBefore,\n diffStyle,\n index,\n unifiedLineIndex,\n splitLineIndex,\n additionLineIndex,\n deletionLineIndex,\n additionLineNumber,\n deletionLineNumber,\n content,\n isLastContent,\n unifiedCount,\n splitCount,\n}: GetChangeLineDataProps): DiffLineCallbackProps {\n const unifiedDeletionLineIndex =\n index < content.deletions ? unifiedLineIndex + index : undefined;\n const unifiedAdditionLineIndex =\n diffStyle === 'unified'\n ? index >= content.deletions\n ? unifiedLineIndex + index\n : undefined\n : index < content.additions\n ? unifiedLineIndex + content.deletions + index\n : undefined;\n\n const resolvedSplitLineIndex =\n diffStyle === 'unified'\n ? splitLineIndex +\n (index < content.deletions ? index : index - content.deletions)\n : splitLineIndex + index;\n\n const deletionLineIndexValue =\n index < content.deletions ? deletionLineIndex + index : undefined;\n const deletionLineNumberValue =\n index < content.deletions ? deletionLineNumber + index : undefined;\n const additionLineIndexValue =\n diffStyle === 'unified'\n ? index >= content.deletions\n ? additionLineIndex + (index - content.deletions)\n : undefined\n : index < content.additions\n ? additionLineIndex + index\n : undefined;\n const additionLineNumberValue =\n diffStyle === 'unified'\n ? index >= content.deletions\n ? additionLineNumber + (index - content.deletions)\n : undefined\n : index < content.additions\n ? additionLineNumber + index\n : undefined;\n\n const noEOFCRDeletion =\n diffStyle === 'unified'\n ? isLastContent &&\n index === content.deletions - 1 &&\n hunk.noEOFCRDeletions\n : isLastContent && index === splitCount - 1 && hunk.noEOFCRDeletions;\n const noEOFCRAddition =\n diffStyle === 'unified'\n ? isLastContent && index === unifiedCount - 1 && hunk.noEOFCRAdditions\n : isLastContent && index === splitCount - 1 && hunk.noEOFCRAdditions;\n\n const deletionLine: DiffLineMetadata | undefined =\n deletionLineIndexValue != null &&\n deletionLineNumberValue != null &&\n unifiedDeletionLineIndex != null\n ? {\n lineNumber: deletionLineNumberValue,\n lineIndex: deletionLineIndexValue,\n noEOFCR: noEOFCRDeletion,\n unifiedLineIndex: unifiedDeletionLineIndex,\n splitLineIndex: resolvedSplitLineIndex,\n }\n : undefined;\n const additionLine: DiffLineMetadata | undefined =\n additionLineIndexValue != null &&\n additionLineNumberValue != null &&\n unifiedAdditionLineIndex != null\n ? {\n unifiedLineIndex: unifiedAdditionLineIndex,\n splitLineIndex: resolvedSplitLineIndex,\n lineIndex: additionLineIndexValue,\n lineNumber: additionLineNumberValue,\n noEOFCR: noEOFCRAddition,\n }\n : undefined;\n\n if (deletionLine == null && additionLine != null) {\n return {\n type: 'change',\n hunkIndex,\n hunk,\n collapsedAfter,\n collapsedBefore,\n deletionLine: undefined,\n additionLine,\n };\n } else if (deletionLine != null && additionLine == null) {\n return {\n type: 'change',\n hunkIndex,\n hunk,\n collapsedAfter,\n collapsedBefore,\n deletionLine,\n additionLine: undefined,\n };\n }\n\n if (deletionLine == null || additionLine == null) {\n throw new Error('iterateOverDiff: missing change line data');\n }\n\n return {\n type: 'change',\n hunkIndex,\n hunk,\n collapsedAfter,\n collapsedBefore,\n deletionLine,\n additionLine,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"iterateOverDiff.js","names":[],"sources":["../../src/utils/iterateOverDiff.ts"],"sourcesContent":["import { DEFAULT_COLLAPSED_CONTEXT_THRESHOLD } from '../constants';\nimport type {\n ChangeContent,\n FileDiffMetadata,\n Hunk,\n HunkExpansionRegion,\n} from '../types';\nimport {\n getExpandedRegion,\n getTrailingExpandedRegion,\n} from './virtualDiffLayout';\n\nexport interface DiffLineMetadata {\n unifiedLineIndex: number;\n splitLineIndex: number;\n lineIndex: number;\n lineNumber: number;\n noEOFCR: boolean;\n}\n\nexport interface DiffLineCallbackBase {\n hunkIndex: number;\n hunk: Hunk | undefined; // undefined for trailing expansion region\n collapsedBefore: number; // > 0 means separator before this line, value = hidden lines\n collapsedAfter: number; // > 0 only on final line if trailing collapsed content\n}\n\ninterface DiffLineCallbackContextChange extends DiffLineCallbackBase {\n type: 'change' | 'context' | 'context-expanded';\n deletionLine: DiffLineMetadata;\n additionLine: DiffLineMetadata;\n}\n\ninterface DiffLineCallbackChangeDeletion extends DiffLineCallbackBase {\n type: 'change';\n deletionLine: DiffLineMetadata;\n additionLine?: undefined;\n}\n\ninterface DiffLineCallbackChangeAddition extends DiffLineCallbackBase {\n type: 'change';\n deletionLine?: undefined;\n additionLine: DiffLineMetadata;\n}\n\nexport type DiffLineCallbackProps =\n | DiffLineCallbackContextChange\n | DiffLineCallbackChangeDeletion\n | DiffLineCallbackChangeAddition;\n\ntype DiffStyle = 'unified' | 'split' | 'both';\n\ntype LineIterationBounds = [startIndex: number, endIndex: number];\n\ntype ChangeContentSide = 'deletions' | 'additions';\n\ntype ContextLineCallback = (index: number) => boolean | void;\n\ninterface IterationState {\n isWindowedHighlight: boolean;\n viewportStart: number;\n viewportEnd: number;\n splitCount: number;\n unifiedCount: number;\n finalHunkIndex: number;\n shouldBreak(): boolean;\n shouldSkip(unifiedHeight: number, splitHeight: number): boolean;\n incrementCounts(unifiedValue: number, splitValue: number): void;\n isInWindow(unifiedHeight: number, splitHeight: number): boolean;\n isInUnifiedWindow(height: number): boolean;\n isInSplitWindow(height: number): boolean;\n emit(props: DiffLineCallbackProps, silent?: boolean): boolean;\n}\n\ninterface IterationStartState {\n hunkIndex: number;\n splitCount: number;\n unifiedCount: number;\n}\n\ninterface HunkPrefixCounts {\n splitCount: number;\n unifiedCount: number;\n}\n\ninterface IterationStartStateProps extends Omit<\n IterateOverDiffProps,\n 'callback' | 'totalLines'\n> {\n startingLine: number;\n collapsedContextThreshold: number;\n}\n\ninterface HunkPrefixCountsProps extends Pick<\n IterationStartStateProps,\n 'diff' | 'expandedHunks' | 'collapsedContextThreshold'\n> {}\n\nexport type DiffLineCallback = (props: DiffLineCallbackProps) => boolean | void;\n\nexport interface IterateOverDiffProps {\n diff: FileDiffMetadata;\n diffStyle: DiffStyle;\n startingLine?: number;\n totalLines?: number;\n expandedHunks?: Map<number, HunkExpansionRegion> | true;\n collapsedContextThreshold?: number;\n callback: DiffLineCallback;\n}\n\nexport function iterateOverDiff({\n diff,\n diffStyle,\n startingLine = 0,\n totalLines = Infinity,\n expandedHunks,\n collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD,\n callback,\n}: IterateOverDiffProps): void {\n const iterationStart = getIterationStartState({\n diff,\n diffStyle,\n startingLine,\n expandedHunks,\n collapsedContextThreshold,\n });\n const state: IterationState = {\n viewportStart: startingLine,\n viewportEnd: startingLine + totalLines,\n isWindowedHighlight: startingLine > 0 || totalLines < Infinity,\n splitCount: iterationStart.splitCount,\n unifiedCount: iterationStart.unifiedCount,\n finalHunkIndex: diff.hunks.length - 1,\n shouldBreak() {\n if (!state.isWindowedHighlight) {\n return false;\n }\n\n const breakUnified = state.unifiedCount >= startingLine + totalLines;\n const breakSplit = state.splitCount >= startingLine + totalLines;\n\n if (diffStyle === 'unified') {\n return breakUnified;\n } else if (diffStyle === 'split') {\n return breakSplit;\n } else {\n return breakUnified && breakSplit;\n }\n },\n shouldSkip(unifiedCount: number, splitCount: number) {\n if (!state.isWindowedHighlight) {\n return false;\n }\n\n const skipUnified =\n unifiedCount > 0 && state.unifiedCount + unifiedCount <= startingLine;\n const skipSplit =\n splitCount > 0 && state.splitCount + splitCount <= startingLine;\n\n if (diffStyle === 'unified') {\n return skipUnified;\n } else if (diffStyle === 'split') {\n return skipSplit;\n } else {\n return skipUnified && skipSplit;\n }\n },\n incrementCounts(unifiedValue: number, splitValue: number) {\n if (diffStyle === 'unified' || diffStyle === 'both') {\n state.unifiedCount += unifiedValue;\n }\n if (diffStyle === 'split' || diffStyle === 'both') {\n state.splitCount += splitValue;\n }\n },\n isInWindow(unifiedHeight: number, splitHeight: number) {\n if (!state.isWindowedHighlight) {\n return true;\n }\n\n const unifiedInWindow = state.isInUnifiedWindow(unifiedHeight);\n const splitInWindow = state.isInSplitWindow(splitHeight);\n\n if (diffStyle === 'unified') {\n return unifiedInWindow;\n } else if (diffStyle === 'split') {\n return splitInWindow;\n } else {\n return unifiedInWindow || splitInWindow;\n }\n },\n isInUnifiedWindow(unifiedHeight: number) {\n return (\n !state.isWindowedHighlight ||\n (state.unifiedCount >= startingLine - unifiedHeight &&\n state.unifiedCount < startingLine + totalLines)\n );\n },\n isInSplitWindow(splitHeight: number) {\n return (\n !state.isWindowedHighlight ||\n (state.splitCount >= startingLine - splitHeight &&\n state.splitCount < startingLine + totalLines)\n );\n },\n emit(props: DiffLineCallbackProps, silent = false): boolean {\n if (!silent) {\n if (diffStyle === 'unified') {\n state.incrementCounts(1, 0);\n } else if (diffStyle === 'split') {\n state.incrementCounts(0, 1);\n } else {\n state.incrementCounts(1, 1);\n }\n }\n return callback(props) ?? false;\n },\n };\n\n hunkIterator: for (\n let hunkIndex = iterationStart.hunkIndex;\n hunkIndex < diff.hunks.length;\n hunkIndex++\n ) {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n throw new Error('iterateOverDiff: invalid hunk index');\n }\n if (state.shouldBreak()) {\n break;\n }\n\n const leadingRegion = getExpandedRegion({\n isPartial: diff.isPartial,\n rangeSize: hunk.collapsedBefore,\n expandedHunks,\n hunkIndex,\n collapsedContextThreshold,\n });\n const trailingRegion =\n hunkIndex === state.finalHunkIndex\n ? getTrailingExpandedRegion({\n fileDiff: diff,\n hunkIndex,\n expandedHunks,\n collapsedContextThreshold,\n errorPrefix: 'iterateOverDiff',\n })\n : undefined;\n const expandedLineCount = leadingRegion.fromStart + leadingRegion.fromEnd;\n\n function getTrailingCollapsedAfter(\n unifiedLineIndex: number,\n splitLineIndex: number\n ) {\n if (\n trailingRegion == null ||\n trailingRegion.collapsedLines <= 0 ||\n trailingRegion.fromStart + trailingRegion.fromEnd > 0\n ) {\n return 0;\n }\n if (diffStyle === 'unified') {\n return unifiedLineIndex ===\n hunk.unifiedLineStart + hunk.unifiedLineCount - 1\n ? trailingRegion.collapsedLines\n : 0;\n }\n return splitLineIndex === hunk.splitLineStart + hunk.splitLineCount - 1\n ? trailingRegion.collapsedLines\n : 0;\n }\n\n let consumedCollapsed = leadingRegion.collapsedLines === 0;\n function consumePendingCollapsed() {\n if (consumedCollapsed) {\n return 0;\n }\n consumedCollapsed = true;\n return leadingRegion.collapsedLines;\n }\n\n // Emit for expanded lines\n if (!state.shouldSkip(expandedLineCount, expandedLineCount)) {\n let unifiedLineIndex = hunk.unifiedLineStart - leadingRegion.rangeSize;\n let splitLineIndex = hunk.splitLineStart - leadingRegion.rangeSize;\n\n let deletionLineIndex = hunk.deletionLineIndex - leadingRegion.rangeSize;\n let additionLineIndex = hunk.additionLineIndex - leadingRegion.rangeSize;\n let deletionLineNumber = hunk.deletionStart - leadingRegion.rangeSize;\n let additionLineNumber = hunk.additionStart - leadingRegion.rangeSize;\n\n if (\n walkContextLines(state, leadingRegion.fromStart, diffStyle, (index) => {\n return state.emit({\n hunkIndex,\n hunk: hunk,\n collapsedBefore: 0,\n collapsedAfter: 0,\n type: 'context-expanded',\n deletionLine: {\n lineNumber: deletionLineNumber + index,\n lineIndex: deletionLineIndex + index,\n noEOFCR: false,\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n },\n additionLine: {\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n lineIndex: additionLineIndex + index,\n lineNumber: additionLineNumber + index,\n noEOFCR: false,\n },\n });\n })\n ) {\n break hunkIterator;\n }\n\n unifiedLineIndex = hunk.unifiedLineStart - leadingRegion.fromEnd;\n splitLineIndex = hunk.splitLineStart - leadingRegion.fromEnd;\n\n deletionLineIndex = hunk.deletionLineIndex - leadingRegion.fromEnd;\n additionLineIndex = hunk.additionLineIndex - leadingRegion.fromEnd;\n deletionLineNumber = hunk.deletionStart - leadingRegion.fromEnd;\n additionLineNumber = hunk.additionStart - leadingRegion.fromEnd;\n if (\n walkContextLines(\n state,\n leadingRegion.fromEnd,\n diffStyle,\n (index) => {\n return state.emit({\n hunkIndex,\n hunk,\n collapsedBefore: consumePendingCollapsed(),\n collapsedAfter: 0,\n type: 'context-expanded',\n deletionLine: {\n lineNumber: deletionLineNumber + index,\n lineIndex: deletionLineIndex + index,\n noEOFCR: false,\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n },\n additionLine: {\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n lineIndex: additionLineIndex + index,\n lineNumber: additionLineNumber + index,\n noEOFCR: false,\n },\n });\n },\n () => {\n // The collapsed separator belongs before this fromEnd slice. If the\n // render window starts inside the slice, consume it with the skipped\n // rows so it is not attached to the first emitted row.\n consumePendingCollapsed();\n }\n )\n ) {\n break hunkIterator;\n }\n } else {\n state.incrementCounts(expandedLineCount, expandedLineCount);\n consumePendingCollapsed();\n }\n\n let unifiedLineIndex = hunk.unifiedLineStart;\n let splitLineIndex = hunk.splitLineStart;\n\n let deletionLineIndex = hunk.deletionLineIndex;\n let additionLineIndex = hunk.additionLineIndex;\n let deletionLineNumber = hunk.deletionStart;\n let additionLineNumber = hunk.additionStart;\n const lastContent = hunk.hunkContent.at(-1);\n\n for (const content of hunk.hunkContent) {\n if (state.shouldBreak()) {\n break hunkIterator;\n }\n\n const isLastContent = content === lastContent;\n\n // Hunk Context Content\n if (content.type === 'context') {\n if (!state.shouldSkip(content.lines, content.lines)) {\n if (\n walkContextLines(\n state,\n content.lines,\n diffStyle,\n (index) => {\n const isLastLine = isLastContent && index === content.lines - 1;\n const unifiedRowIndex = unifiedLineIndex + index;\n const splitRowIndex = splitLineIndex + index;\n return state.emit({\n hunkIndex,\n hunk,\n collapsedBefore: consumePendingCollapsed(),\n collapsedAfter: getTrailingCollapsedAfter(\n unifiedRowIndex,\n splitRowIndex\n ),\n type: 'context',\n deletionLine: {\n lineNumber: deletionLineNumber + index,\n lineIndex: deletionLineIndex + index,\n noEOFCR: isLastLine && hunk.noEOFCRDeletions,\n unifiedLineIndex: unifiedRowIndex,\n splitLineIndex: splitRowIndex,\n },\n additionLine: {\n unifiedLineIndex: unifiedRowIndex,\n splitLineIndex: splitRowIndex,\n lineIndex: additionLineIndex + index,\n lineNumber: additionLineNumber + index,\n noEOFCR: isLastLine && hunk.noEOFCRAdditions,\n },\n });\n },\n () => {\n // When windowing starts inside context content, the leading\n // separator was above the visible range and should not be\n // emitted on the first rendered context line.\n consumePendingCollapsed();\n }\n )\n ) {\n break hunkIterator;\n }\n } else {\n state.incrementCounts(content.lines, content.lines);\n consumePendingCollapsed();\n }\n unifiedLineIndex += content.lines;\n splitLineIndex += content.lines;\n\n deletionLineIndex += content.lines;\n additionLineIndex += content.lines;\n deletionLineNumber += content.lines;\n additionLineNumber += content.lines;\n }\n // Hunk Change Content\n else {\n const splitCount = Math.max(content.deletions, content.additions);\n const unifiedCount = content.deletions + content.additions;\n const shouldSkipChange = state.shouldSkip(unifiedCount, splitCount);\n if (!shouldSkipChange) {\n const iterationRanges = getChangeIterationRanges(\n state,\n content,\n diffStyle\n );\n const firstRangeStart = iterationRanges[0]?.[0] ?? 0;\n if (firstRangeStart > 0) {\n // Change rows can be windowed from the middle of the block too. In\n // that case the leading separator belongs to skipped rows, not to\n // the first visible deletion/addition row.\n consumePendingCollapsed();\n }\n // Change ranges are already clipped to the active window. Counts move\n // once for the whole change block after the selected rows emit.\n for (const [rangeStart, rangeEnd] of iterationRanges) {\n for (let index = rangeStart; index < rangeEnd; index++) {\n const unifiedRowIndex = unifiedLineIndex + index;\n const splitRowIndex =\n diffStyle === 'unified'\n ? splitLineIndex +\n (index < content.deletions\n ? index\n : index - content.deletions)\n : splitLineIndex + index;\n const collapsedAfter = getTrailingCollapsedAfter(\n unifiedRowIndex,\n splitRowIndex\n );\n if (\n state.emit(\n getChangeLineData({\n hunkIndex,\n hunk,\n collapsedBefore: consumePendingCollapsed(),\n collapsedAfter,\n diffStyle,\n index,\n unifiedLineIndex,\n splitLineIndex,\n additionLineIndex,\n deletionLineIndex,\n additionLineNumber,\n deletionLineNumber,\n content,\n isLastContent,\n unifiedCount,\n splitCount,\n }),\n true\n )\n ) {\n break hunkIterator;\n }\n }\n }\n }\n\n consumePendingCollapsed();\n state.incrementCounts(unifiedCount, splitCount);\n unifiedLineIndex += unifiedCount;\n splitLineIndex += splitCount;\n deletionLineIndex += content.deletions;\n additionLineIndex += content.additions;\n deletionLineNumber += content.deletions;\n additionLineNumber += content.additions;\n }\n }\n\n if (trailingRegion != null) {\n const { collapsedLines, fromStart, fromEnd } = trailingRegion;\n const len = fromStart + fromEnd;\n if (\n walkContextLines(\n state,\n len,\n diffStyle,\n (index) => {\n const isLastLine = index === len - 1;\n return state.emit({\n hunkIndex: diff.hunks.length,\n hunk: undefined,\n collapsedBefore: 0,\n collapsedAfter: isLastLine ? collapsedLines : 0,\n type: 'context-expanded',\n deletionLine: {\n lineNumber: deletionLineNumber + index,\n lineIndex: deletionLineIndex + index,\n noEOFCR: false,\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n },\n additionLine: {\n unifiedLineIndex: unifiedLineIndex + index,\n splitLineIndex: splitLineIndex + index,\n lineIndex: additionLineIndex + index,\n lineNumber: additionLineNumber + index,\n noEOFCR: false,\n },\n });\n },\n undefined,\n () => state.shouldBreak()\n )\n ) {\n break hunkIterator;\n }\n }\n }\n}\n\n// Seek the iterator to the hunk that contains `startingLine` without changing\n// the public meaning of `startingLine`: it is a dense rendered-row index, not\n// a raw split/unified line index. We first build prefix counts for each hunk\n// under the current expansion/collapse settings, binary-search those counts to\n// find the first hunk whose rendered rows cross `startingLine`, then seed the\n// running split/unified counters as if every prior hunk had already been\n// walked.\nfunction getIterationStartState({\n diff,\n diffStyle,\n startingLine,\n expandedHunks,\n collapsedContextThreshold,\n}: IterationStartStateProps): IterationStartState {\n if (startingLine <= 0 || diffStyle === 'both') {\n return { hunkIndex: 0, splitCount: 0, unifiedCount: 0 };\n }\n\n const prefixCounts = getHunkPrefixCounts({\n diff,\n expandedHunks,\n collapsedContextThreshold,\n });\n\n let low = 0;\n let high = diff.hunks.length - 1;\n let result = diff.hunks.length;\n\n while (low <= high) {\n const mid = (low + high) >> 1;\n const counts = prefixCounts[mid + 1];\n if (counts == null) {\n throw new Error('iterateOverDiff: invalid hunk prefix index');\n }\n const selectedCount =\n diffStyle === 'unified' ? counts.unifiedCount : counts.splitCount;\n\n if (selectedCount > startingLine) {\n result = mid;\n high = mid - 1;\n } else {\n low = mid + 1;\n }\n }\n\n if (result >= diff.hunks.length) {\n const counts = prefixCounts[diff.hunks.length];\n if (counts == null) {\n throw new Error('iterateOverDiff: invalid terminal hunk prefix index');\n }\n return {\n hunkIndex: diff.hunks.length,\n splitCount: counts.splitCount,\n unifiedCount: counts.unifiedCount,\n };\n }\n\n const counts = prefixCounts[result];\n if (counts == null) {\n throw new Error('iterateOverDiff: invalid selected hunk prefix index');\n }\n return {\n hunkIndex: result,\n splitCount: counts.splitCount,\n unifiedCount: counts.unifiedCount,\n };\n}\n\n// Build cumulative rendered-row counts at every hunk boundary for the current\n// expansion state. Entry 0 is always zero rows before the first hunk; entry N\n// is the split/unified row count after hunks [0, N). These counts let\n// getIterationStartState binary-search by dense rendered row without replaying\n// every prior hunk.\nfunction getHunkPrefixCounts({\n diff,\n expandedHunks,\n collapsedContextThreshold,\n}: HunkPrefixCountsProps): HunkPrefixCounts[] {\n let splitCount = 0;\n let unifiedCount = 0;\n const finalHunkIndex = diff.hunks.length - 1;\n const prefixCounts: HunkPrefixCounts[] = [\n {\n splitCount: 0,\n unifiedCount: 0,\n },\n ];\n\n for (let index = 0; index < diff.hunks.length; index++) {\n const hunk = diff.hunks[index];\n if (hunk == null) {\n throw new Error('iterateOverDiff: invalid hunk summary index');\n }\n\n const leadingRegion = getExpandedRegion({\n isPartial: diff.isPartial,\n rangeSize: hunk.collapsedBefore,\n expandedHunks,\n hunkIndex: index,\n collapsedContextThreshold,\n });\n const leadingCount = leadingRegion.fromStart + leadingRegion.fromEnd;\n splitCount += leadingCount + hunk.splitLineCount;\n unifiedCount += leadingCount + hunk.unifiedLineCount;\n\n const trailingRegion =\n index === finalHunkIndex\n ? getTrailingExpandedRegion({\n fileDiff: diff,\n hunkIndex: index,\n expandedHunks,\n collapsedContextThreshold,\n errorPrefix: 'iterateOverDiff',\n })\n : undefined;\n if (trailingRegion != null) {\n const trailingCount = trailingRegion.fromStart + trailingRegion.fromEnd;\n splitCount += trailingCount;\n unifiedCount += trailingCount;\n }\n\n prefixCounts.push({ splitCount, unifiedCount });\n }\n\n return prefixCounts;\n}\n\n// Clip a run of context rows to a single bounded hull around the active rendered\n// window. `diffStyle: both` can make split and unified rows visible in disjoint\n// ranges, so these bounds may include interior gaps that still need per-row\n// filtering before emitting.\nfunction getContextLineIterationBounds(\n state: IterationState,\n count: number,\n diffStyle: DiffStyle\n): LineIterationBounds {\n if (!state.isWindowedHighlight || count <= 0) {\n return [0, count];\n }\n\n const ranges: LineIterationBounds[] = [];\n function pushRange(currentCount: number): void {\n const start = Math.max(0, state.viewportStart - currentCount);\n const end = Math.min(count, state.viewportEnd - currentCount);\n if (end > start) {\n ranges.push([start, end]);\n }\n }\n\n if (diffStyle !== 'split') {\n pushRange(state.unifiedCount);\n }\n if (diffStyle !== 'unified') {\n pushRange(state.splitCount);\n }\n\n if (ranges.length === 0) {\n return [0, 0];\n }\n\n let start = ranges[0][0];\n let end = ranges[0][1];\n for (let index = 1; index < ranges.length; index++) {\n const range = ranges[index];\n start = Math.min(start, range[0]);\n end = Math.max(end, range[1]);\n }\n return [start, end];\n}\n\n// Walk context rows through the active window while keeping split and\n// unified counters aligned. The callback only runs after the final per-row\n// window check, which keeps `diffStyle: both` gap rows from being emitted.\nfunction walkContextLines(\n state: IterationState,\n count: number,\n diffStyle: DiffStyle,\n callback: ContextLineCallback,\n onSkippedStart?: () => void,\n shouldBreak?: () => boolean\n): boolean {\n const [startIndex, endIndex] = getContextLineIterationBounds(\n state,\n count,\n diffStyle\n );\n if (startIndex > 0) {\n state.incrementCounts(startIndex, startIndex);\n onSkippedStart?.();\n }\n\n let index = startIndex;\n while (index < count) {\n if (shouldBreak?.() === true) {\n return true;\n }\n if (index >= endIndex) {\n state.incrementCounts(count - index, count - index);\n break;\n }\n if (state.isInWindow(0, 0)) {\n if (callback(index) === true) {\n return true;\n }\n } else {\n state.incrementCounts(1, 1);\n }\n index++;\n }\n\n return false;\n}\n\n// Clip a change block to the rows that can be visible in the active coordinate\n// space. `diffStyle: both` iterates in split row space, but includes the unified\n// ranges too so either view can render the visible change rows it needs.\nfunction getChangeIterationRanges(\n state: IterationState,\n content: ChangeContent,\n diffStyle: DiffStyle\n): LineIterationBounds[] {\n // If not a window highlight, then we should just render the entire range\n if (!state.isWindowedHighlight) {\n return [\n [\n 0,\n diffStyle === 'unified'\n ? content.deletions + content.additions\n : Math.max(content.deletions, content.additions),\n ],\n ];\n }\n const useUnified = diffStyle !== 'split';\n const useSplit = diffStyle !== 'unified';\n const iterationSpace = diffStyle === 'unified' ? 'unified' : 'split';\n const iterationRanges: LineIterationBounds[] = [];\n function getVisibleRange(\n start: number,\n count: number\n ): LineIterationBounds | undefined {\n const end = start + count;\n if (end <= state.viewportStart || start >= state.viewportEnd) {\n return undefined;\n }\n const visibleStart = Math.max(0, state.viewportStart - start);\n const visibleEnd = Math.min(count, state.viewportEnd - start);\n return visibleEnd > visibleStart ? [visibleStart, visibleEnd] : undefined;\n }\n function mapRangeToIteration(\n range: LineIterationBounds,\n kind: ChangeContentSide\n ): LineIterationBounds {\n if (iterationSpace === 'split') {\n // For split iteration, additions/deletions are already in split row space.\n return range;\n }\n return kind === 'additions'\n ? [range[0] + content.deletions, range[1] + content.deletions]\n : range;\n }\n function pushRange(\n range: LineIterationBounds | undefined,\n kind: ChangeContentSide\n ) {\n if (range == null) {\n return;\n }\n const [start, end] = mapRangeToIteration(range, kind);\n if (end > start) {\n iterationRanges.push([start, end]);\n }\n }\n\n if (useUnified) {\n pushRange(\n getVisibleRange(state.unifiedCount, content.deletions),\n 'deletions'\n );\n pushRange(\n getVisibleRange(\n state.unifiedCount + content.deletions,\n content.additions\n ),\n 'additions'\n );\n }\n\n if (useSplit) {\n pushRange(\n getVisibleRange(state.splitCount, content.deletions),\n 'deletions'\n );\n pushRange(\n getVisibleRange(state.splitCount, content.additions),\n 'additions'\n );\n }\n\n if (iterationRanges.length === 0) {\n return iterationRanges;\n }\n\n iterationRanges.sort((a, b) => a[0] - b[0]);\n const merged: LineIterationBounds[] = [iterationRanges[0]];\n for (const [start, end] of iterationRanges.slice(1)) {\n const last = merged[merged.length - 1];\n if (start <= last[1]) {\n last[1] = Math.max(last[1], end);\n } else {\n merged.push([start, end]);\n }\n }\n\n return merged;\n}\n\ninterface GetChangeLineDataProps {\n hunkIndex: number;\n hunk: Hunk;\n collapsedBefore: number;\n collapsedAfter: number;\n diffStyle: DiffStyle;\n index: number;\n unifiedLineIndex: number;\n splitLineIndex: number;\n additionLineIndex: number;\n additionLineNumber: number;\n deletionLineNumber: number;\n deletionLineIndex: number;\n content: ChangeContent;\n isLastContent: boolean;\n unifiedCount: number;\n splitCount: number;\n}\n\n// Build the callback payload for one change row, mapping the selected row index\n// into split/unified coordinates and addition/deletion line metadata.\nfunction getChangeLineData({\n hunkIndex,\n hunk,\n collapsedAfter,\n collapsedBefore,\n diffStyle,\n index,\n unifiedLineIndex,\n splitLineIndex,\n additionLineIndex,\n deletionLineIndex,\n additionLineNumber,\n deletionLineNumber,\n content,\n isLastContent,\n unifiedCount,\n splitCount,\n}: GetChangeLineDataProps): DiffLineCallbackProps {\n const unifiedDeletionLineIndex =\n index < content.deletions ? unifiedLineIndex + index : undefined;\n const unifiedAdditionLineIndex =\n diffStyle === 'unified'\n ? index >= content.deletions\n ? unifiedLineIndex + index\n : undefined\n : index < content.additions\n ? unifiedLineIndex + content.deletions + index\n : undefined;\n\n const resolvedSplitLineIndex =\n diffStyle === 'unified'\n ? splitLineIndex +\n (index < content.deletions ? index : index - content.deletions)\n : splitLineIndex + index;\n\n const deletionLineIndexValue =\n index < content.deletions ? deletionLineIndex + index : undefined;\n const deletionLineNumberValue =\n index < content.deletions ? deletionLineNumber + index : undefined;\n const additionLineIndexValue =\n diffStyle === 'unified'\n ? index >= content.deletions\n ? additionLineIndex + (index - content.deletions)\n : undefined\n : index < content.additions\n ? additionLineIndex + index\n : undefined;\n const additionLineNumberValue =\n diffStyle === 'unified'\n ? index >= content.deletions\n ? additionLineNumber + (index - content.deletions)\n : undefined\n : index < content.additions\n ? additionLineNumber + index\n : undefined;\n\n const noEOFCRDeletion =\n diffStyle === 'unified'\n ? isLastContent &&\n index === content.deletions - 1 &&\n hunk.noEOFCRDeletions\n : isLastContent && index === splitCount - 1 && hunk.noEOFCRDeletions;\n const noEOFCRAddition =\n diffStyle === 'unified'\n ? isLastContent && index === unifiedCount - 1 && hunk.noEOFCRAdditions\n : isLastContent && index === splitCount - 1 && hunk.noEOFCRAdditions;\n\n const deletionLine: DiffLineMetadata | undefined =\n deletionLineIndexValue != null &&\n deletionLineNumberValue != null &&\n unifiedDeletionLineIndex != null\n ? {\n lineNumber: deletionLineNumberValue,\n lineIndex: deletionLineIndexValue,\n noEOFCR: noEOFCRDeletion,\n unifiedLineIndex: unifiedDeletionLineIndex,\n splitLineIndex: resolvedSplitLineIndex,\n }\n : undefined;\n const additionLine: DiffLineMetadata | undefined =\n additionLineIndexValue != null &&\n additionLineNumberValue != null &&\n unifiedAdditionLineIndex != null\n ? {\n unifiedLineIndex: unifiedAdditionLineIndex,\n splitLineIndex: resolvedSplitLineIndex,\n lineIndex: additionLineIndexValue,\n lineNumber: additionLineNumberValue,\n noEOFCR: noEOFCRAddition,\n }\n : undefined;\n\n if (deletionLine == null && additionLine != null) {\n return {\n type: 'change',\n hunkIndex,\n hunk,\n collapsedAfter,\n collapsedBefore,\n deletionLine: undefined,\n additionLine,\n };\n } else if (deletionLine != null && additionLine == null) {\n return {\n type: 'change',\n hunkIndex,\n hunk,\n collapsedAfter,\n collapsedBefore,\n deletionLine,\n additionLine: undefined,\n };\n }\n\n if (deletionLine == null || additionLine == null) {\n throw new Error('iterateOverDiff: missing change line data');\n }\n\n return {\n type: 'change',\n hunkIndex,\n hunk,\n collapsedAfter,\n collapsedBefore,\n deletionLine,\n additionLine,\n };\n}\n"],"mappings":";;;AA8GA,SAAgB,gBAAgB,EAC9B,MACA,WACA,eAAe,GACf,aAAa,UACb,eACA,4BAAA,GACA,YAC6B;CAC7B,MAAM,iBAAiB,uBAAuB;EAC5C;EACA;EACA;EACA;EACA;CACF,CAAC;CACD,MAAM,QAAwB;EAC5B,eAAe;EACf,aAAa,eAAe;EAC5B,qBAAqB,eAAe,KAAK,aAAa;EACtD,YAAY,eAAe;EAC3B,cAAc,eAAe;EAC7B,gBAAgB,KAAK,MAAM,SAAS;EACpC,cAAc;GACZ,IAAI,CAAC,MAAM,qBACT,OAAO;GAGT,MAAM,eAAe,MAAM,gBAAgB,eAAe;GAC1D,MAAM,aAAa,MAAM,cAAc,eAAe;GAEtD,IAAI,cAAc,WAChB,OAAO;QACF,IAAI,cAAc,SACvB,OAAO;QAEP,OAAO,gBAAgB;EAE3B;EACA,WAAW,cAAsB,YAAoB;GACnD,IAAI,CAAC,MAAM,qBACT,OAAO;GAGT,MAAM,cACJ,eAAe,KAAK,MAAM,eAAe,gBAAgB;GAC3D,MAAM,YACJ,aAAa,KAAK,MAAM,aAAa,cAAc;GAErD,IAAI,cAAc,WAChB,OAAO;QACF,IAAI,cAAc,SACvB,OAAO;QAEP,OAAO,eAAe;EAE1B;EACA,gBAAgB,cAAsB,YAAoB;GACxD,IAAI,cAAc,aAAa,cAAc,QAC3C,MAAM,gBAAgB;GAExB,IAAI,cAAc,WAAW,cAAc,QACzC,MAAM,cAAc;EAExB;EACA,WAAW,eAAuB,aAAqB;GACrD,IAAI,CAAC,MAAM,qBACT,OAAO;GAGT,MAAM,kBAAkB,MAAM,kBAAkB,aAAa;GAC7D,MAAM,gBAAgB,MAAM,gBAAgB,WAAW;GAEvD,IAAI,cAAc,WAChB,OAAO;QACF,IAAI,cAAc,SACvB,OAAO;QAEP,OAAO,mBAAmB;EAE9B;EACA,kBAAkB,eAAuB;GACvC,OACE,CAAC,MAAM,uBACN,MAAM,gBAAgB,eAAe,iBACpC,MAAM,eAAe,eAAe;EAE1C;EACA,gBAAgB,aAAqB;GACnC,OACE,CAAC,MAAM,uBACN,MAAM,cAAc,eAAe,eAClC,MAAM,aAAa,eAAe;EAExC;EACA,KAAK,OAA8B,SAAS,OAAgB;GAC1D,IAAI,CAAC,QACH,IAAI,cAAc,WAChB,MAAM,gBAAgB,GAAG,CAAC;QACrB,IAAI,cAAc,SACvB,MAAM,gBAAgB,GAAG,CAAC;QAE1B,MAAM,gBAAgB,GAAG,CAAC;GAG9B,OAAO,SAAS,KAAK,KAAK;EAC5B;CACF;CAEA,cAAc,KACZ,IAAI,YAAY,eAAe,WAC/B,YAAY,KAAK,MAAM,QACvB,aACA;EACA,MAAM,OAAO,KAAK,MAAM;EACxB,IAAI,QAAQ,MACV,MAAM,IAAI,MAAM,qCAAqC;EAEvD,IAAI,MAAM,YAAY,GACpB;EAGF,MAAM,gBAAgB,kBAAkB;GACtC,WAAW,KAAK;GAChB,WAAW,KAAK;GAChB;GACA;GACA;EACF,CAAC;EACD,MAAM,iBACJ,cAAc,MAAM,iBAChB,0BAA0B;GACxB,UAAU;GACV;GACA;GACA;GACA,aAAa;EACf,CAAC,IACD,KAAA;EACN,MAAM,oBAAoB,cAAc,YAAY,cAAc;EAElE,SAAS,0BACP,kBACA,gBACA;GACA,IACE,kBAAkB,QAClB,eAAe,kBAAkB,KACjC,eAAe,YAAY,eAAe,UAAU,GAEpD,OAAO;GAET,IAAI,cAAc,WAChB,OAAO,qBACL,KAAK,mBAAmB,KAAK,mBAAmB,IAC9C,eAAe,iBACf;GAEN,OAAO,mBAAmB,KAAK,iBAAiB,KAAK,iBAAiB,IAClE,eAAe,iBACf;EACN;EAEA,IAAI,oBAAoB,cAAc,mBAAmB;EACzD,SAAS,0BAA0B;GACjC,IAAI,mBACF,OAAO;GAET,oBAAoB;GACpB,OAAO,cAAc;EACvB;EAGA,IAAI,CAAC,MAAM,WAAW,mBAAmB,iBAAiB,GAAG;GAC3D,IAAI,mBAAmB,KAAK,mBAAmB,cAAc;GAC7D,IAAI,iBAAiB,KAAK,iBAAiB,cAAc;GAEzD,IAAI,oBAAoB,KAAK,oBAAoB,cAAc;GAC/D,IAAI,oBAAoB,KAAK,oBAAoB,cAAc;GAC/D,IAAI,qBAAqB,KAAK,gBAAgB,cAAc;GAC5D,IAAI,qBAAqB,KAAK,gBAAgB,cAAc;GAE5D,IACE,iBAAiB,OAAO,cAAc,WAAW,YAAY,UAAU;IACrE,OAAO,MAAM,KAAK;KAChB;KACM;KACN,iBAAiB;KACjB,gBAAgB;KAChB,MAAM;KACN,cAAc;MACZ,YAAY,qBAAqB;MACjC,WAAW,oBAAoB;MAC/B,SAAS;MACT,kBAAkB,mBAAmB;MACrC,gBAAgB,iBAAiB;KACnC;KACA,cAAc;MACZ,kBAAkB,mBAAmB;MACrC,gBAAgB,iBAAiB;MACjC,WAAW,oBAAoB;MAC/B,YAAY,qBAAqB;MACjC,SAAS;KACX;IACF,CAAC;GACH,CAAC,GAED,MAAM;GAGR,mBAAmB,KAAK,mBAAmB,cAAc;GACzD,iBAAiB,KAAK,iBAAiB,cAAc;GAErD,oBAAoB,KAAK,oBAAoB,cAAc;GAC3D,oBAAoB,KAAK,oBAAoB,cAAc;GAC3D,qBAAqB,KAAK,gBAAgB,cAAc;GACxD,qBAAqB,KAAK,gBAAgB,cAAc;GACxD,IACE,iBACE,OACA,cAAc,SACd,YACC,UAAU;IACT,OAAO,MAAM,KAAK;KAChB;KACA;KACA,iBAAiB,wBAAwB;KACzC,gBAAgB;KAChB,MAAM;KACN,cAAc;MACZ,YAAY,qBAAqB;MACjC,WAAW,oBAAoB;MAC/B,SAAS;MACT,kBAAkB,mBAAmB;MACrC,gBAAgB,iBAAiB;KACnC;KACA,cAAc;MACZ,kBAAkB,mBAAmB;MACrC,gBAAgB,iBAAiB;MACjC,WAAW,oBAAoB;MAC/B,YAAY,qBAAqB;MACjC,SAAS;KACX;IACF,CAAC;GACH,SACM;IAIJ,wBAAwB;GAC1B,CACF,GAEA,MAAM;EAEV,OAAO;GACL,MAAM,gBAAgB,mBAAmB,iBAAiB;GAC1D,wBAAwB;EAC1B;EAEA,IAAI,mBAAmB,KAAK;EAC5B,IAAI,iBAAiB,KAAK;EAE1B,IAAI,oBAAoB,KAAK;EAC7B,IAAI,oBAAoB,KAAK;EAC7B,IAAI,qBAAqB,KAAK;EAC9B,IAAI,qBAAqB,KAAK;EAC9B,MAAM,cAAc,KAAK,YAAY,GAAG,EAAE;EAE1C,KAAK,MAAM,WAAW,KAAK,aAAa;GACtC,IAAI,MAAM,YAAY,GACpB,MAAM;GAGR,MAAM,gBAAgB,YAAY;GAGlC,IAAI,QAAQ,SAAS,WAAW;IAC9B,IAAI,CAAC,MAAM,WAAW,QAAQ,OAAO,QAAQ,KAAK;SAE9C,iBACE,OACA,QAAQ,OACR,YACC,UAAU;MACT,MAAM,aAAa,iBAAiB,UAAU,QAAQ,QAAQ;MAC9D,MAAM,kBAAkB,mBAAmB;MAC3C,MAAM,gBAAgB,iBAAiB;MACvC,OAAO,MAAM,KAAK;OAChB;OACA;OACA,iBAAiB,wBAAwB;OACzC,gBAAgB,0BACd,iBACA,aACF;OACA,MAAM;OACN,cAAc;QACZ,YAAY,qBAAqB;QACjC,WAAW,oBAAoB;QAC/B,SAAS,cAAc,KAAK;QAC5B,kBAAkB;QAClB,gBAAgB;OAClB;OACA,cAAc;QACZ,kBAAkB;QAClB,gBAAgB;QAChB,WAAW,oBAAoB;QAC/B,YAAY,qBAAqB;QACjC,SAAS,cAAc,KAAK;OAC9B;MACF,CAAC;KACH,SACM;MAIJ,wBAAwB;KAC1B,CACF,GAEA,MAAM;IAAA,OAEH;KACL,MAAM,gBAAgB,QAAQ,OAAO,QAAQ,KAAK;KAClD,wBAAwB;IAC1B;IACA,oBAAoB,QAAQ;IAC5B,kBAAkB,QAAQ;IAE1B,qBAAqB,QAAQ;IAC7B,qBAAqB,QAAQ;IAC7B,sBAAsB,QAAQ;IAC9B,sBAAsB,QAAQ;GAChC,OAEK;IACH,MAAM,aAAa,KAAK,IAAI,QAAQ,WAAW,QAAQ,SAAS;IAChE,MAAM,eAAe,QAAQ,YAAY,QAAQ;IAEjD,IAAI,CADqB,MAAM,WAAW,cAAc,UACpC,GAAG;KACrB,MAAM,kBAAkB,yBACtB,OACA,SACA,SACF;KAEA,KADwB,gBAAgB,EAAE,GAAG,MAAM,KAC7B,GAIpB,wBAAwB;KAI1B,KAAK,MAAM,CAAC,YAAY,aAAa,iBACnC,KAAK,IAAI,QAAQ,YAAY,QAAQ,UAAU,SAAS;MAStD,MAAM,iBAAiB,0BARC,mBAAmB,OAEzC,cAAc,YACV,kBACC,QAAQ,QAAQ,YACb,QACA,QAAQ,QAAQ,aACpB,iBAAiB,KAIvB;MACA,IACE,MAAM,KACJ,kBAAkB;OAChB;OACA;OACA,iBAAiB,wBAAwB;OACzC;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;MACF,CAAC,GACD,IACF,GAEA,MAAM;KAEV;IAEJ;IAEA,wBAAwB;IACxB,MAAM,gBAAgB,cAAc,UAAU;IAC9C,oBAAoB;IACpB,kBAAkB;IAClB,qBAAqB,QAAQ;IAC7B,qBAAqB,QAAQ;IAC7B,sBAAsB,QAAQ;IAC9B,sBAAsB,QAAQ;GAChC;EACF;EAEA,IAAI,kBAAkB,MAAM;GAC1B,MAAM,EAAE,gBAAgB,WAAW,YAAY;GAC/C,MAAM,MAAM,YAAY;GACxB,IACE,iBACE,OACA,KACA,YACC,UAAU;IACT,MAAM,aAAa,UAAU,MAAM;IACnC,OAAO,MAAM,KAAK;KAChB,WAAW,KAAK,MAAM;KACtB,MAAM,KAAA;KACN,iBAAiB;KACjB,gBAAgB,aAAa,iBAAiB;KAC9C,MAAM;KACN,cAAc;MACZ,YAAY,qBAAqB;MACjC,WAAW,oBAAoB;MAC/B,SAAS;MACT,kBAAkB,mBAAmB;MACrC,gBAAgB,iBAAiB;KACnC;KACA,cAAc;MACZ,kBAAkB,mBAAmB;MACrC,gBAAgB,iBAAiB;MACjC,WAAW,oBAAoB;MAC/B,YAAY,qBAAqB;MACjC,SAAS;KACX;IACF,CAAC;GACH,GACA,KAAA,SACM,MAAM,YAAY,CAC1B,GAEA,MAAM;EAEV;CACF;AACF;AASA,SAAS,uBAAuB,EAC9B,MACA,WACA,cACA,eACA,6BACgD;CAChD,IAAI,gBAAgB,KAAK,cAAc,QACrC,OAAO;EAAE,WAAW;EAAG,YAAY;EAAG,cAAc;CAAE;CAGxD,MAAM,eAAe,oBAAoB;EACvC;EACA;EACA;CACF,CAAC;CAED,IAAI,MAAM;CACV,IAAI,OAAO,KAAK,MAAM,SAAS;CAC/B,IAAI,SAAS,KAAK,MAAM;CAExB,OAAO,OAAO,MAAM;EAClB,MAAM,MAAO,MAAM,QAAS;EAC5B,MAAM,SAAS,aAAa,MAAM;EAClC,IAAI,UAAU,MACZ,MAAM,IAAI,MAAM,4CAA4C;EAK9D,KAFE,cAAc,YAAY,OAAO,eAAe,OAAO,cAErC,cAAc;GAChC,SAAS;GACT,OAAO,MAAM;EACf,OACE,MAAM,MAAM;CAEhB;CAEA,IAAI,UAAU,KAAK,MAAM,QAAQ;EAC/B,MAAM,SAAS,aAAa,KAAK,MAAM;EACvC,IAAI,UAAU,MACZ,MAAM,IAAI,MAAM,qDAAqD;EAEvE,OAAO;GACL,WAAW,KAAK,MAAM;GACtB,YAAY,OAAO;GACnB,cAAc,OAAO;EACvB;CACF;CAEA,MAAM,SAAS,aAAa;CAC5B,IAAI,UAAU,MACZ,MAAM,IAAI,MAAM,qDAAqD;CAEvE,OAAO;EACL,WAAW;EACX,YAAY,OAAO;EACnB,cAAc,OAAO;CACvB;AACF;AAOA,SAAS,oBAAoB,EAC3B,MACA,eACA,6BAC4C;CAC5C,IAAI,aAAa;CACjB,IAAI,eAAe;CACnB,MAAM,iBAAiB,KAAK,MAAM,SAAS;CAC3C,MAAM,eAAmC,CACvC;EACE,YAAY;EACZ,cAAc;CAChB,CACF;CAEA,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,MAAM,QAAQ,SAAS;EACtD,MAAM,OAAO,KAAK,MAAM;EACxB,IAAI,QAAQ,MACV,MAAM,IAAI,MAAM,6CAA6C;EAG/D,MAAM,gBAAgB,kBAAkB;GACtC,WAAW,KAAK;GAChB,WAAW,KAAK;GAChB;GACA,WAAW;GACX;EACF,CAAC;EACD,MAAM,eAAe,cAAc,YAAY,cAAc;EAC7D,cAAc,eAAe,KAAK;EAClC,gBAAgB,eAAe,KAAK;EAEpC,MAAM,iBACJ,UAAU,iBACN,0BAA0B;GACxB,UAAU;GACV,WAAW;GACX;GACA;GACA,aAAa;EACf,CAAC,IACD,KAAA;EACN,IAAI,kBAAkB,MAAM;GAC1B,MAAM,gBAAgB,eAAe,YAAY,eAAe;GAChE,cAAc;GACd,gBAAgB;EAClB;EAEA,aAAa,KAAK;GAAE;GAAY;EAAa,CAAC;CAChD;CAEA,OAAO;AACT;AAMA,SAAS,8BACP,OACA,OACA,WACqB;CACrB,IAAI,CAAC,MAAM,uBAAuB,SAAS,GACzC,OAAO,CAAC,GAAG,KAAK;CAGlB,MAAM,SAAgC,CAAC;CACvC,SAAS,UAAU,cAA4B;EAC7C,MAAM,QAAQ,KAAK,IAAI,GAAG,MAAM,gBAAgB,YAAY;EAC5D,MAAM,MAAM,KAAK,IAAI,OAAO,MAAM,cAAc,YAAY;EAC5D,IAAI,MAAM,OACR,OAAO,KAAK,CAAC,OAAO,GAAG,CAAC;CAE5B;CAEA,IAAI,cAAc,SAChB,UAAU,MAAM,YAAY;CAE9B,IAAI,cAAc,WAChB,UAAU,MAAM,UAAU;CAG5B,IAAI,OAAO,WAAW,GACpB,OAAO,CAAC,GAAG,CAAC;CAGd,IAAI,QAAQ,OAAO,EAAE,CAAC;CACtB,IAAI,MAAM,OAAO,EAAE,CAAC;CACpB,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS;EAClD,MAAM,QAAQ,OAAO;EACrB,QAAQ,KAAK,IAAI,OAAO,MAAM,EAAE;EAChC,MAAM,KAAK,IAAI,KAAK,MAAM,EAAE;CAC9B;CACA,OAAO,CAAC,OAAO,GAAG;AACpB;AAKA,SAAS,iBACP,OACA,OACA,WACA,UACA,gBACA,aACS;CACT,MAAM,CAAC,YAAY,YAAY,8BAC7B,OACA,OACA,SACF;CACA,IAAI,aAAa,GAAG;EAClB,MAAM,gBAAgB,YAAY,UAAU;EAC5C,iBAAiB;CACnB;CAEA,IAAI,QAAQ;CACZ,OAAO,QAAQ,OAAO;EACpB,IAAI,cAAc,MAAM,MACtB,OAAO;EAET,IAAI,SAAS,UAAU;GACrB,MAAM,gBAAgB,QAAQ,OAAO,QAAQ,KAAK;GAClD;EACF;EACA,IAAI,MAAM,WAAW,GAAG,CAAC;OACnB,SAAS,KAAK,MAAM,MACtB,OAAO;EAAA,OAGT,MAAM,gBAAgB,GAAG,CAAC;EAE5B;CACF;CAEA,OAAO;AACT;AAKA,SAAS,yBACP,OACA,SACA,WACuB;CAEvB,IAAI,CAAC,MAAM,qBACT,OAAO,CACL,CACE,GACA,cAAc,YACV,QAAQ,YAAY,QAAQ,YAC5B,KAAK,IAAI,QAAQ,WAAW,QAAQ,SAAS,CACnD,CACF;CAEF,MAAM,aAAa,cAAc;CACjC,MAAM,WAAW,cAAc;CAC/B,MAAM,iBAAiB,cAAc,YAAY,YAAY;CAC7D,MAAM,kBAAyC,CAAC;CAChD,SAAS,gBACP,OACA,OACiC;EAEjC,IADY,QAAQ,SACT,MAAM,iBAAiB,SAAS,MAAM,aAC/C;EAEF,MAAM,eAAe,KAAK,IAAI,GAAG,MAAM,gBAAgB,KAAK;EAC5D,MAAM,aAAa,KAAK,IAAI,OAAO,MAAM,cAAc,KAAK;EAC5D,OAAO,aAAa,eAAe,CAAC,cAAc,UAAU,IAAI,KAAA;CAClE;CACA,SAAS,oBACP,OACA,MACqB;EACrB,IAAI,mBAAmB,SAErB,OAAO;EAET,OAAO,SAAS,cACZ,CAAC,MAAM,KAAK,QAAQ,WAAW,MAAM,KAAK,QAAQ,SAAS,IAC3D;CACN;CACA,SAAS,UACP,OACA,MACA;EACA,IAAI,SAAS,MACX;EAEF,MAAM,CAAC,OAAO,OAAO,oBAAoB,OAAO,IAAI;EACpD,IAAI,MAAM,OACR,gBAAgB,KAAK,CAAC,OAAO,GAAG,CAAC;CAErC;CAEA,IAAI,YAAY;EACd,UACE,gBAAgB,MAAM,cAAc,QAAQ,SAAS,GACrD,WACF;EACA,UACE,gBACE,MAAM,eAAe,QAAQ,WAC7B,QAAQ,SACV,GACA,WACF;CACF;CAEA,IAAI,UAAU;EACZ,UACE,gBAAgB,MAAM,YAAY,QAAQ,SAAS,GACnD,WACF;EACA,UACE,gBAAgB,MAAM,YAAY,QAAQ,SAAS,GACnD,WACF;CACF;CAEA,IAAI,gBAAgB,WAAW,GAC7B,OAAO;CAGT,gBAAgB,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE;CAC1C,MAAM,SAAgC,CAAC,gBAAgB,EAAE;CACzD,KAAK,MAAM,CAAC,OAAO,QAAQ,gBAAgB,MAAM,CAAC,GAAG;EACnD,MAAM,OAAO,OAAO,OAAO,SAAS;EACpC,IAAI,SAAS,KAAK,IAChB,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,GAAG;OAE/B,OAAO,KAAK,CAAC,OAAO,GAAG,CAAC;CAE5B;CAEA,OAAO;AACT;AAuBA,SAAS,kBAAkB,EACzB,WACA,MACA,gBACA,iBACA,WACA,OACA,kBACA,gBACA,mBACA,mBACA,oBACA,oBACA,SACA,eACA,cACA,cACgD;CAChD,MAAM,2BACJ,QAAQ,QAAQ,YAAY,mBAAmB,QAAQ,KAAA;CACzD,MAAM,2BACJ,cAAc,YACV,SAAS,QAAQ,YACf,mBAAmB,QACnB,KAAA,IACF,QAAQ,QAAQ,YACd,mBAAmB,QAAQ,YAAY,QACvC,KAAA;CAER,MAAM,yBACJ,cAAc,YACV,kBACC,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,QAAQ,aACrD,iBAAiB;CAEvB,MAAM,yBACJ,QAAQ,QAAQ,YAAY,oBAAoB,QAAQ,KAAA;CAC1D,MAAM,0BACJ,QAAQ,QAAQ,YAAY,qBAAqB,QAAQ,KAAA;CAC3D,MAAM,yBACJ,cAAc,YACV,SAAS,QAAQ,YACf,qBAAqB,QAAQ,QAAQ,aACrC,KAAA,IACF,QAAQ,QAAQ,YACd,oBAAoB,QACpB,KAAA;CACR,MAAM,0BACJ,cAAc,YACV,SAAS,QAAQ,YACf,sBAAsB,QAAQ,QAAQ,aACtC,KAAA,IACF,QAAQ,QAAQ,YACd,qBAAqB,QACrB,KAAA;CAER,MAAM,kBACJ,cAAc,YACV,iBACA,UAAU,QAAQ,YAAY,KAC9B,KAAK,mBACL,iBAAiB,UAAU,aAAa,KAAK,KAAK;CACxD,MAAM,kBACJ,cAAc,YACV,iBAAiB,UAAU,eAAe,KAAK,KAAK,mBACpD,iBAAiB,UAAU,aAAa,KAAK,KAAK;CAExD,MAAM,eACJ,0BAA0B,QAC1B,2BAA2B,QAC3B,4BAA4B,OACxB;EACE,YAAY;EACZ,WAAW;EACX,SAAS;EACT,kBAAkB;EAClB,gBAAgB;CAClB,IACA,KAAA;CACN,MAAM,eACJ,0BAA0B,QAC1B,2BAA2B,QAC3B,4BAA4B,OACxB;EACE,kBAAkB;EAClB,gBAAgB;EAChB,WAAW;EACX,YAAY;EACZ,SAAS;CACX,IACA,KAAA;CAEN,IAAI,gBAAgB,QAAQ,gBAAgB,MAC1C,OAAO;EACL,MAAM;EACN;EACA;EACA;EACA;EACA,cAAc,KAAA;EACd;CACF;MACK,IAAI,gBAAgB,QAAQ,gBAAgB,MACjD,OAAO;EACL,MAAM;EACN;EACA;EACA;EACA;EACA;EACA,cAAc,KAAA;CAChB;CAGF,IAAI,gBAAgB,QAAQ,gBAAgB,MAC1C,MAAM,IAAI,MAAM,2CAA2C;CAG7D,OAAO;EACL,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -8,7 +8,7 @@ import { CreatePatchOptionsNonabortable } from "diff";
|
|
|
8
8
|
* If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff will
|
|
9
9
|
* automatically get a combined cache key in the format `oldKey:newKey`.
|
|
10
10
|
*/
|
|
11
|
-
declare function parseDiffFromFile(oldFile: FileContents, newFile: FileContents, options?: CreatePatchOptionsNonabortable, throwOnError?: boolean): FileDiffMetadata;
|
|
11
|
+
declare function parseDiffFromFile(oldFile: FileContents | null, newFile: FileContents | null, options?: CreatePatchOptionsNonabortable, throwOnError?: boolean): FileDiffMetadata;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { parseDiffFromFile };
|
|
14
14
|
//# sourceMappingURL=parseDiffFromFile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseDiffFromFile.d.ts","names":[],"sources":["../../src/utils/parseDiffFromFile.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"parseDiffFromFile.d.ts","names":[],"sources":["../../src/utils/parseDiffFromFile.ts"],"mappings":";;;;;;AAaA;;;;iBAAgB,iBAAA,CACd,OAAA,EAAS,YAAA,SACT,OAAA,EAAS,YAAA,SACT,OAAA,GAAU,8BAAA,EACV,YAAA,aACC,gBAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { processFile } from "./parsePatchFiles.js";
|
|
2
2
|
import { createTwoFilesPatch } from "diff";
|
|
3
3
|
//#region src/utils/parseDiffFromFile.ts
|
|
4
|
+
const MISSING_FILE_NAME = "/dev/null";
|
|
4
5
|
/**
|
|
5
6
|
* Parses a diff from two file contents objects.
|
|
6
7
|
*
|
|
@@ -8,18 +9,38 @@ import { createTwoFilesPatch } from "diff";
|
|
|
8
9
|
* automatically get a combined cache key in the format `oldKey:newKey`.
|
|
9
10
|
*/
|
|
10
11
|
function parseDiffFromFile(oldFile, newFile, options, throwOnError = false) {
|
|
11
|
-
|
|
12
|
+
if (oldFile === null && newFile === null) throw new Error("parseDiffFromFile: You must pass oldFile, newFile, or both");
|
|
13
|
+
const resolvedOldFile = oldFile ?? createMissingFile();
|
|
14
|
+
const resolvedNewFile = newFile ?? createMissingFile();
|
|
15
|
+
const fileData = processFile(createTwoFilesPatch(resolvedOldFile.name, resolvedNewFile.name, resolvedOldFile.contents, resolvedNewFile.contents, resolvedOldFile.header, resolvedNewFile.header, options), {
|
|
12
16
|
cacheKey: (() => {
|
|
13
|
-
|
|
17
|
+
const oldCacheKey = oldFile?.cacheKey ?? oldFile?.name;
|
|
18
|
+
const newCacheKey = newFile?.cacheKey ?? newFile?.name;
|
|
19
|
+
if (oldCacheKey != null && newCacheKey != null) return oldCacheKey + ":" + newCacheKey;
|
|
20
|
+
return oldCacheKey ?? newCacheKey;
|
|
14
21
|
})(),
|
|
15
|
-
oldFile,
|
|
16
|
-
newFile,
|
|
22
|
+
oldFile: resolvedOldFile,
|
|
23
|
+
newFile: resolvedNewFile,
|
|
17
24
|
throwOnError
|
|
18
25
|
});
|
|
19
26
|
if (fileData == null) throw new Error("parseDiffFrom: FileInvalid diff -- probably need to fix something -- if the files are the same maybe?");
|
|
20
|
-
if (
|
|
27
|
+
if (oldFile === null) {
|
|
28
|
+
fileData.type = "new";
|
|
29
|
+
fileData.prevName = void 0;
|
|
30
|
+
} else if (newFile === null) {
|
|
31
|
+
fileData.type = "deleted";
|
|
32
|
+
fileData.prevName = void 0;
|
|
33
|
+
}
|
|
34
|
+
const language = newFile?.lang ?? (newFile === null ? oldFile?.lang : void 0);
|
|
35
|
+
if (language != null) fileData.lang = language;
|
|
21
36
|
return fileData;
|
|
22
37
|
}
|
|
38
|
+
function createMissingFile() {
|
|
39
|
+
return {
|
|
40
|
+
name: MISSING_FILE_NAME,
|
|
41
|
+
contents: ""
|
|
42
|
+
};
|
|
43
|
+
}
|
|
23
44
|
//#endregion
|
|
24
45
|
export { parseDiffFromFile };
|
|
25
46
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseDiffFromFile.js","names":[],"sources":["../../src/utils/parseDiffFromFile.ts"],"sourcesContent":["import { type CreatePatchOptionsNonabortable, createTwoFilesPatch } from 'diff';\n\nimport type { FileContents, FileDiffMetadata } from '../types';\nimport { processFile } from './parsePatchFiles';\n\n/**\n * Parses a diff from two file contents objects.\n *\n * If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff will\n * automatically get a combined cache key in the format `oldKey:newKey`.\n */\nexport function parseDiffFromFile(\n
|
|
1
|
+
{"version":3,"file":"parseDiffFromFile.js","names":[],"sources":["../../src/utils/parseDiffFromFile.ts"],"sourcesContent":["import { type CreatePatchOptionsNonabortable, createTwoFilesPatch } from 'diff';\n\nimport type { FileContents, FileDiffMetadata } from '../types';\nimport { processFile } from './parsePatchFiles';\n\nconst MISSING_FILE_NAME = '/dev/null';\n\n/**\n * Parses a diff from two file contents objects.\n *\n * If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff will\n * automatically get a combined cache key in the format `oldKey:newKey`.\n */\nexport function parseDiffFromFile(\n oldFile: FileContents | null,\n newFile: FileContents | null,\n options?: CreatePatchOptionsNonabortable,\n throwOnError = false\n): FileDiffMetadata {\n if (oldFile === null && newFile === null) {\n throw new Error(\n 'parseDiffFromFile: You must pass oldFile, newFile, or both'\n );\n }\n\n const resolvedOldFile = oldFile ?? createMissingFile();\n const resolvedNewFile = newFile ?? createMissingFile();\n const patch = createTwoFilesPatch(\n resolvedOldFile.name,\n resolvedNewFile.name,\n resolvedOldFile.contents,\n resolvedNewFile.contents,\n resolvedOldFile.header,\n resolvedNewFile.header,\n options\n );\n\n const fileData = processFile(patch, {\n cacheKey: (() => {\n const oldCacheKey = oldFile?.cacheKey ?? oldFile?.name;\n const newCacheKey = newFile?.cacheKey ?? newFile?.name;\n if (oldCacheKey != null && newCacheKey != null) {\n return oldCacheKey + ':' + newCacheKey;\n }\n return oldCacheKey ?? newCacheKey;\n })(),\n oldFile: resolvedOldFile,\n newFile: resolvedNewFile,\n throwOnError,\n });\n if (fileData == null) {\n throw new Error(\n 'parseDiffFrom: FileInvalid diff -- probably need to fix something -- if the files are the same maybe?'\n );\n }\n if (oldFile === null) {\n fileData.type = 'new';\n fileData.prevName = undefined;\n } else if (newFile === null) {\n fileData.type = 'deleted';\n fileData.prevName = undefined;\n }\n // If we've been provided an override for language in the newFile, let’s pass\n // it through to FileDiffMetadata.\n const language =\n newFile?.lang ?? (newFile === null ? oldFile?.lang : undefined);\n if (language != null) {\n fileData.lang = language;\n }\n return fileData;\n}\n\nfunction createMissingFile(): FileContents {\n return { name: MISSING_FILE_NAME, contents: '' };\n}\n"],"mappings":";;;AAKA,MAAM,oBAAoB;;;;;;;AAQ1B,SAAgB,kBACd,SACA,SACA,SACA,eAAe,OACG;CAClB,IAAI,YAAY,QAAQ,YAAY,MAClC,MAAM,IAAI,MACR,4DACF;CAGF,MAAM,kBAAkB,WAAW,kBAAkB;CACrD,MAAM,kBAAkB,WAAW,kBAAkB;CAWrD,MAAM,WAAW,YAVH,oBACZ,gBAAgB,MAChB,gBAAgB,MAChB,gBAAgB,UAChB,gBAAgB,UAChB,gBAAgB,QAChB,gBAAgB,QAChB,OAG+B,GAAG;EAClC,iBAAiB;GACf,MAAM,cAAc,SAAS,YAAY,SAAS;GAClD,MAAM,cAAc,SAAS,YAAY,SAAS;GAClD,IAAI,eAAe,QAAQ,eAAe,MACxC,OAAO,cAAc,MAAM;GAE7B,OAAO,eAAe;EACxB,EAAA,CAAG;EACH,SAAS;EACT,SAAS;EACT;CACF,CAAC;CACD,IAAI,YAAY,MACd,MAAM,IAAI,MACR,uGACF;CAEF,IAAI,YAAY,MAAM;EACpB,SAAS,OAAO;EAChB,SAAS,WAAW,KAAA;CACtB,OAAO,IAAI,YAAY,MAAM;EAC3B,SAAS,OAAO;EAChB,SAAS,WAAW,KAAA;CACtB;CAGA,MAAM,WACJ,SAAS,SAAS,YAAY,OAAO,SAAS,OAAO,KAAA;CACvD,IAAI,YAAY,MACd,SAAS,OAAO;CAElB,OAAO;AACT;AAEA,SAAS,oBAAkC;CACzC,OAAO;EAAE,MAAM;EAAmB,UAAU;CAAG;AACjD"}
|
|
@@ -27,7 +27,6 @@ function setPreNodeProperties(pre, { type, diffIndicators, disableBackground, di
|
|
|
27
27
|
if (type === "diff") pre.setAttribute("data-diff-type", split ? "split" : "single");
|
|
28
28
|
else pre.removeAttribute("data-diff-type");
|
|
29
29
|
pre.setAttribute("data-overflow", overflow);
|
|
30
|
-
pre.tabIndex = 0;
|
|
31
30
|
pre.style.setProperty("--diffs-min-number-column-width-default", `${`${totalLines}`.length}ch`);
|
|
32
31
|
return pre;
|
|
33
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setWrapperNodeProps.js","names":[],"sources":["../../src/utils/setWrapperNodeProps.ts"],"sourcesContent":["import type { PrePropertiesConfig } from '../types';\n\nexport function setPreNodeProperties(\n pre: HTMLPreElement,\n {\n type,\n diffIndicators,\n disableBackground,\n disableLineNumbers,\n overflow,\n split,\n totalLines,\n customProperties,\n }: PrePropertiesConfig\n): HTMLPreElement {\n // NOTE: We always apply custom properties first so the important properties\n // cannot be overridden.\n if (customProperties != null) {\n for (const key in customProperties) {\n const value = customProperties[key];\n if (value != null) {\n pre.setAttribute(key, `${value}`);\n }\n }\n }\n if (type === 'diff') {\n pre.setAttribute('data-diff', '');\n pre.removeAttribute('data-file');\n } else {\n pre.setAttribute('data-file', '');\n pre.removeAttribute('data-diff');\n }\n switch (diffIndicators) {\n case 'bars':\n case 'classic':\n pre.setAttribute('data-indicators', diffIndicators);\n break;\n case 'none':\n pre.removeAttribute('data-indicators');\n break;\n }\n if (disableLineNumbers) {\n pre.setAttribute('data-disable-line-numbers', '');\n } else {\n pre.removeAttribute('data-disable-line-numbers');\n }\n if (disableBackground) {\n pre.removeAttribute('data-background');\n } else {\n pre.setAttribute('data-background', '');\n }\n if (type === 'diff') {\n pre.setAttribute('data-diff-type', split ? 'split' : 'single');\n } else {\n pre.removeAttribute('data-diff-type');\n }\n pre.setAttribute('data-overflow', overflow);\n
|
|
1
|
+
{"version":3,"file":"setWrapperNodeProps.js","names":[],"sources":["../../src/utils/setWrapperNodeProps.ts"],"sourcesContent":["import type { PrePropertiesConfig } from '../types';\n\nexport function setPreNodeProperties(\n pre: HTMLPreElement,\n {\n type,\n diffIndicators,\n disableBackground,\n disableLineNumbers,\n overflow,\n split,\n totalLines,\n customProperties,\n }: PrePropertiesConfig\n): HTMLPreElement {\n // NOTE: We always apply custom properties first so the important properties\n // cannot be overridden.\n if (customProperties != null) {\n for (const key in customProperties) {\n const value = customProperties[key];\n if (value != null) {\n pre.setAttribute(key, `${value}`);\n }\n }\n }\n if (type === 'diff') {\n pre.setAttribute('data-diff', '');\n pre.removeAttribute('data-file');\n } else {\n pre.setAttribute('data-file', '');\n pre.removeAttribute('data-diff');\n }\n switch (diffIndicators) {\n case 'bars':\n case 'classic':\n pre.setAttribute('data-indicators', diffIndicators);\n break;\n case 'none':\n pre.removeAttribute('data-indicators');\n break;\n }\n if (disableLineNumbers) {\n pre.setAttribute('data-disable-line-numbers', '');\n } else {\n pre.removeAttribute('data-disable-line-numbers');\n }\n if (disableBackground) {\n pre.removeAttribute('data-background');\n } else {\n pre.setAttribute('data-background', '');\n }\n if (type === 'diff') {\n pre.setAttribute('data-diff-type', split ? 'split' : 'single');\n } else {\n pre.removeAttribute('data-diff-type');\n }\n pre.setAttribute('data-overflow', overflow);\n // Set CSS custom property for line number column width\n pre.style.setProperty(\n '--diffs-min-number-column-width-default',\n `${`${totalLines}`.length}ch`\n );\n return pre;\n}\n"],"mappings":";AAEA,SAAgB,qBACd,KACA,EACE,MACA,gBACA,mBACA,oBACA,UACA,OACA,YACA,oBAEc;CAGhB,IAAI,oBAAoB,MACtB,KAAK,MAAM,OAAO,kBAAkB;EAClC,MAAM,QAAQ,iBAAiB;EAC/B,IAAI,SAAS,MACX,IAAI,aAAa,KAAK,GAAG,OAAO;CAEpC;CAEF,IAAI,SAAS,QAAQ;EACnB,IAAI,aAAa,aAAa,EAAE;EAChC,IAAI,gBAAgB,WAAW;CACjC,OAAO;EACL,IAAI,aAAa,aAAa,EAAE;EAChC,IAAI,gBAAgB,WAAW;CACjC;CACA,QAAQ,gBAAR;EACE,KAAK;EACL,KAAK;GACH,IAAI,aAAa,mBAAmB,cAAc;GAClD;EACF,KAAK;GACH,IAAI,gBAAgB,iBAAiB;GACrC;CACJ;CACA,IAAI,oBACF,IAAI,aAAa,6BAA6B,EAAE;MAEhD,IAAI,gBAAgB,2BAA2B;CAEjD,IAAI,mBACF,IAAI,gBAAgB,iBAAiB;MAErC,IAAI,aAAa,mBAAmB,EAAE;CAExC,IAAI,SAAS,QACX,IAAI,aAAa,kBAAkB,QAAQ,UAAU,QAAQ;MAE7D,IAAI,gBAAgB,gBAAgB;CAEtC,IAAI,aAAa,iBAAiB,QAAQ;CAE1C,IAAI,MAAM,YACR,2CACA,GAAG,GAAG,aAAa,OAAO,GAC5B;CACA,OAAO;AACT"}
|
|
@@ -6,9 +6,13 @@ type HunkMetadataUpdate = Pick<FileDiffMetadata, 'hunks' | 'splitLineCount' | 'u
|
|
|
6
6
|
type FullDiffHunkUpdate = HunkMetadataUpdate & Pick<FileDiffMetadata, 'additionLines' | 'deletionLines'>;
|
|
7
7
|
/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */
|
|
8
8
|
declare function recomputeDiffHunks(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
|
|
9
|
+
declare function shouldTopAlignAdditionRecompute(diff: FileDiffMetadata, additionLines: string[]): boolean;
|
|
10
|
+
declare function recomputeTopAlignedAdditionDiff(diff: FileDiffMetadata, additionLines: string[], parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
|
|
9
11
|
declare function recomputeEmptyDocumentDiff(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
|
|
12
|
+
/** Rebuilds diff hunks after an edit, top-aligning sparse addition sides when needed. */
|
|
13
|
+
declare function recomputeDiffHunksForEdit(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
|
|
10
14
|
/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */
|
|
11
15
|
declare function updateDiffHunks(diff: FileDiffMetadata, changedAdditionLineIndexes: Iterable<number>, parseDiffOptions?: CreatePatchOptionsNonabortable): HunkMetadataUpdate;
|
|
12
16
|
//#endregion
|
|
13
|
-
export { recomputeDiffHunks, recomputeEmptyDocumentDiff, updateDiffHunks };
|
|
17
|
+
export { recomputeDiffHunks, recomputeDiffHunksForEdit, recomputeEmptyDocumentDiff, recomputeTopAlignedAdditionDiff, shouldTopAlignAdditionRecompute, updateDiffHunks };
|
|
14
18
|
//# sourceMappingURL=updateDiffHunks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateDiffHunks.d.ts","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"mappings":";;;;KAcK,kBAAA,GAAqB,IAAI,CAC5B,gBAAA;AAAA,KAIG,kBAAA,GAAqB,kBAAA,GACxB,IAAA,CAAK,gBAAA;AAbW;AAAA,iBAgBF,kBAAA,CACd,IAAA,EAAM,gBAAA,EACN,gBAAA,GAAmB,8BAAA,GAClB,kBAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"updateDiffHunks.d.ts","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"mappings":";;;;KAcK,kBAAA,GAAqB,IAAI,CAC5B,gBAAA;AAAA,KAIG,kBAAA,GAAqB,kBAAA,GACxB,IAAA,CAAK,gBAAA;AAbW;AAAA,iBAgBF,kBAAA,CACd,IAAA,EAAM,gBAAA,EACN,gBAAA,GAAmB,8BAAA,GAClB,kBAAA;AAAA,iBAwDa,+BAAA,CACd,IAAA,EAAM,gBAAgB,EACtB,aAAA;AAAA,iBAYc,+BAAA,CACd,IAAA,EAAM,gBAAA,EACN,aAAA,YACA,gBAAA,GAAmB,8BAAA,GAClB,kBAAA;AAAA,iBAkCa,0BAAA,CACd,IAAA,EAAM,gBAAA,EACN,gBAAA,GAAmB,8BAAA,GAClB,kBAAA;AA1He;AAAA,iBA+HF,yBAAA,CACd,IAAA,EAAM,gBAAA,EACN,gBAAA,GAAmB,8BAAA,GAClB,kBAAA;;iBAgEa,eAAA,CACd,IAAA,EAAM,gBAAA,EACN,0BAAA,EAA4B,QAAA,UAC5B,gBAAA,GAAmB,8BAAA,GAClB,kBAAA"}
|
|
@@ -21,9 +21,22 @@ function recomputeDiffHunks(diff, parseDiffOptions) {
|
|
|
21
21
|
type: recomputed.type
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
function
|
|
24
|
+
function buildTopAlignedAdditionSentinel(lineCount, deletionContents) {
|
|
25
|
+
const count = Math.max(lineCount, 1);
|
|
26
|
+
let sentinel = Array.from({ length: count }, (_, index) => `${" ".repeat(index + 1)}\n`).join("");
|
|
27
|
+
if (sentinel === deletionContents) sentinel = Array.from({ length: count }, (_, index) => `\u0000${" ".repeat(index)}\n`).join("");
|
|
28
|
+
return sentinel;
|
|
29
|
+
}
|
|
30
|
+
function hasOnlyBlankAdditionContents(additionLines) {
|
|
31
|
+
for (const line of additionLines) if (line.trim().length > 0) return false;
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
function shouldTopAlignAdditionRecompute(diff, additionLines) {
|
|
35
|
+
return additionLines.length > 0 && additionLines.length < diff.deletionLines.length && hasOnlyBlankAdditionContents(additionLines);
|
|
36
|
+
}
|
|
37
|
+
function recomputeTopAlignedAdditionDiff(diff, additionLines, parseDiffOptions) {
|
|
25
38
|
const deletionContents = diff.deletionLines.join("");
|
|
26
|
-
const additionSentinel = deletionContents
|
|
39
|
+
const additionSentinel = buildTopAlignedAdditionSentinel(additionLines.length, deletionContents);
|
|
27
40
|
const recomputed = parseDiffFromFile({
|
|
28
41
|
name: diff.prevName ?? diff.name,
|
|
29
42
|
contents: deletionContents
|
|
@@ -36,11 +49,42 @@ function recomputeEmptyDocumentDiff(diff, parseDiffOptions) {
|
|
|
36
49
|
hunks: recomputed.hunks,
|
|
37
50
|
splitLineCount: recomputed.splitLineCount,
|
|
38
51
|
unifiedLineCount: recomputed.unifiedLineCount,
|
|
39
|
-
additionLines
|
|
52
|
+
additionLines,
|
|
40
53
|
deletionLines: recomputed.deletionLines,
|
|
41
54
|
type: recomputed.type
|
|
42
55
|
};
|
|
43
56
|
}
|
|
57
|
+
function recomputeEmptyDocumentDiff(diff, parseDiffOptions) {
|
|
58
|
+
return recomputeTopAlignedAdditionDiff(diff, [""], parseDiffOptions);
|
|
59
|
+
}
|
|
60
|
+
/** Rebuilds diff hunks after an edit, top-aligning sparse addition sides when needed. */
|
|
61
|
+
function recomputeDiffHunksForEdit(diff, parseDiffOptions) {
|
|
62
|
+
if (diff.additionLines.length === 0) return recomputeEmptyDocumentDiff(diff, parseDiffOptions);
|
|
63
|
+
if (shouldTopAlignAdditionRecompute(diff, diff.additionLines)) return recomputeTopAlignedAdditionDiff(diff, diff.additionLines, parseDiffOptions);
|
|
64
|
+
const additionLines = diff.additionLines;
|
|
65
|
+
const recomputed = recomputeDiffHunks(diff, parseDiffOptions);
|
|
66
|
+
if (additionLines.length > recomputed.additionLines.length && hasTrailingEditorBlankLine(additionLines)) preserveTrailingEditorBlankLine(recomputed, additionLines);
|
|
67
|
+
return recomputed;
|
|
68
|
+
}
|
|
69
|
+
function hasTrailingEditorBlankLine(additionLines) {
|
|
70
|
+
return additionLines.length > 1 && additionLines.at(-1) === "";
|
|
71
|
+
}
|
|
72
|
+
function preserveTrailingEditorBlankLine(recomputed, additionLines) {
|
|
73
|
+
const extraLineCount = additionLines.length - recomputed.additionLines.length;
|
|
74
|
+
if (extraLineCount <= 0) return;
|
|
75
|
+
const extraAdditionLineIndex = recomputed.additionLines.length;
|
|
76
|
+
const lastHunk = recomputed.hunks.at(-1);
|
|
77
|
+
if (lastHunk == null) return;
|
|
78
|
+
if (lastHunk.additionLineIndex + lastHunk.additionCount !== extraAdditionLineIndex) return;
|
|
79
|
+
for (const content of lastHunk.hunkContent) if (content.type === "change" && content.additions < content.deletions && content.additionLineIndex + content.additions === extraAdditionLineIndex) {
|
|
80
|
+
recomputed.additionLines = additionLines;
|
|
81
|
+
content.additions += extraLineCount;
|
|
82
|
+
lastHunk.additionCount += extraLineCount;
|
|
83
|
+
lastHunk.additionLines += extraLineCount;
|
|
84
|
+
recomputeDiffRenderLineCounts(recomputed);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
44
88
|
/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */
|
|
45
89
|
function updateDiffHunks(diff, changedAdditionLineIndexes, parseDiffOptions) {
|
|
46
90
|
if (diff.isPartial) return applyHunkUpdateResult(diff, recomputeDiffHunks(diff, parseDiffOptions));
|
|
@@ -185,6 +229,6 @@ function recomputeDiffRenderLineCounts(diff) {
|
|
|
185
229
|
diff.unifiedLineCount = unifiedTotal;
|
|
186
230
|
}
|
|
187
231
|
//#endregion
|
|
188
|
-
export { recomputeDiffHunks, recomputeEmptyDocumentDiff, updateDiffHunks };
|
|
232
|
+
export { recomputeDiffHunks, recomputeDiffHunksForEdit, recomputeEmptyDocumentDiff, recomputeTopAlignedAdditionDiff, shouldTopAlignAdditionRecompute, updateDiffHunks };
|
|
189
233
|
|
|
190
234
|
//# sourceMappingURL=updateDiffHunks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateDiffHunks.js","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"sourcesContent":["import type { CreatePatchOptionsNonabortable } from 'diff';\n\nimport type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { parseDiffFromFile } from './parseDiffFromFile';\nimport { hasTrailingContextMismatch } from './virtualDiffLayout';\n\ntype HunkContent = ContextContent | ChangeContent;\n\ntype HunkMetadataUpdate = Pick<\n FileDiffMetadata,\n 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'type'\n>;\n\ntype FullDiffHunkUpdate = HunkMetadataUpdate &\n Pick<FileDiffMetadata, 'additionLines' | 'deletionLines'>;\n\n/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */\nexport function recomputeDiffHunks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: diff.deletionLines.join(''),\n },\n {\n name: diff.name,\n contents: diff.additionLines.join(''),\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines: recomputed.additionLines,\n deletionLines: recomputed.deletionLines,\n type: recomputed.type,\n };\n}\n\n// Rebuilds hunk metadata when the editable side has been emptied of all text.\n//\n// The editor always keeps one (empty) line for an empty document, but an empty\n// string splits into zero addition lines, so a normal recompute produces a diff\n// with no addition rows at all. Rendering that leaves the attached editor with\n// no line element to host its caret. To keep one editable row, diff the\n// unchanged deletions against a single line (which yields a hunk that places\n// exactly one addition row), then store the addition as `['']` so it still\n// joins back to the editor's empty document.\n//\n// The sentinel only has to differ from the deletion side so a hunk is produced;\n// its text is discarded by the `['']` override below. When the old side is\n// itself a single blank line the empty sentinel would be identical and yield no\n// hunk (and so no editable row), so fall back to a non-blank line there.\nexport function recomputeEmptyDocumentDiff(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const deletionContents = diff.deletionLines.join('');\n const additionSentinel = deletionContents === '\\n' ? ' \\n' : '\\n';\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionContents,\n },\n {\n name: diff.name,\n contents: additionSentinel,\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines: [''],\n deletionLines: recomputed.deletionLines,\n type: recomputed.type,\n };\n}\n\n/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */\nexport function updateDiffHunks(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): HunkMetadataUpdate {\n if (diff.isPartial) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n if (diff.deletionLines.length !== diff.additionLines.length) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n const changedLines = Array.from(changedAdditionLineIndexes);\n if (changedLines.length === 0) {\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n }\n for (const line of changedLines) {\n const additionLine = diff.additionLines[line];\n const deletionLine = diff.deletionLines[line];\n if (additionLine == null || deletionLine == null) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n // Restoring a line to the old side can merge/split hunks across context windows.\n if (cleanLastNewline(additionLine) === cleanLastNewline(deletionLine)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n const affectedHunkIndexes = getAffectedHunkIndexes(diff, changedLines);\n if (affectedHunkIndexes.size === 0) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n for (const hunkIndex of affectedHunkIndexes) {\n const updated = reparseHunkRegion(diff, hunkIndex, parseDiffOptions);\n if (!updated) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n recomputeDiffRenderLineCounts(diff);\n\n if (hasTrailingContextMismatch(diff)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n}\n\nfunction applyHunkUpdateResult<T extends HunkMetadataUpdate>(\n diff: FileDiffMetadata,\n result: T\n): T {\n Object.assign(diff, result);\n return result;\n}\n\nfunction getAffectedHunkIndexes(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>\n): Set<number> {\n const indexes = new Set<number>();\n for (const line of changedAdditionLineIndexes) {\n const hunkIndex = findHunkIndexForAdditionLine(diff, line);\n if (hunkIndex == null) {\n return new Set();\n }\n indexes.add(hunkIndex);\n }\n return indexes;\n}\n\nfunction findHunkIndexForAdditionLine(\n diff: FileDiffMetadata,\n line: number\n): number | undefined {\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const end = hunk.additionLineIndex + hunk.additionCount;\n if (line >= hunk.additionLineIndex && line < end) {\n return hunkIndex;\n }\n }\n return undefined;\n}\n\nfunction reparseHunkRegion(\n diff: FileDiffMetadata,\n hunkIndex: number,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): boolean {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return false;\n }\n\n const deletionSlice = diff.deletionLines.slice(\n hunk.deletionLineIndex,\n hunk.deletionLineIndex + hunk.deletionCount\n );\n const additionSlice = diff.additionLines.slice(\n hunk.additionLineIndex,\n hunk.additionLineIndex + hunk.additionCount\n );\n\n const reparsed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionSlice.join(''),\n },\n {\n name: diff.name,\n contents: additionSlice.join(''),\n lang: diff.lang,\n },\n { ...parseDiffOptions, context: 0 }\n );\n\n const reparsedHunk = reparsed.hunks[0];\n if (reparsedHunk == null || reparsed.hunks.length !== 1) {\n return false;\n }\n\n applyReparsedHunk(hunk, reparsedHunk);\n syncHunkNoEOFCRFromFullFile(diff, hunkIndex);\n return true;\n}\n\nfunction syncHunkNoEOFCRFromFullFile(\n diff: FileDiffMetadata,\n hunkIndex: number\n): void {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return;\n }\n\n const isLastHunk = hunkIndex === diff.hunks.length - 1;\n if (!isLastHunk) {\n hunk.noEOFCRAdditions = false;\n hunk.noEOFCRDeletions = false;\n return;\n }\n\n const lastAdditionLine = diff.additionLines.at(-1);\n const lastDeletionLine = diff.deletionLines.at(-1);\n hunk.noEOFCRAdditions =\n lastAdditionLine != null &&\n lastAdditionLine !== '' &&\n !lastAdditionLine.endsWith('\\n');\n hunk.noEOFCRDeletions =\n lastDeletionLine != null &&\n lastDeletionLine !== '' &&\n !lastDeletionLine.endsWith('\\n');\n}\n\nfunction applyReparsedHunk(target: Hunk, parsed: Hunk): void {\n const additionOffset = target.additionLineIndex;\n const deletionOffset = target.deletionLineIndex;\n\n target.hunkContent = parsed.hunkContent.map((content) =>\n offsetHunkContent(content, additionOffset, deletionOffset)\n );\n target.additionLineIndex = additionOffset + parsed.additionLineIndex;\n target.additionStart = target.additionStart + parsed.additionLineIndex;\n target.additionCount = parsed.additionCount;\n target.additionLines = parsed.additionLines;\n if (parsed.deletionLineIndex >= 0) {\n target.deletionLineIndex = deletionOffset + parsed.deletionLineIndex;\n target.deletionStart = target.deletionStart + parsed.deletionLineIndex;\n }\n target.deletionCount = parsed.deletionCount;\n target.deletionLines = parsed.deletionLines;\n target.noEOFCRAdditions = parsed.noEOFCRAdditions;\n target.noEOFCRDeletions = parsed.noEOFCRDeletions;\n\n recomputeHunkRenderLineCounts(target);\n}\n\nfunction offsetHunkContent(\n content: HunkContent,\n additionOffset: number,\n deletionOffset: number\n): HunkContent {\n return {\n ...content,\n additionLineIndex: content.additionLineIndex + additionOffset,\n deletionLineIndex: content.deletionLineIndex + deletionOffset,\n };\n}\n\nfunction recomputeHunkRenderLineCounts(hunk: Hunk): void {\n let splitLineCount = 0;\n let unifiedLineCount = 0;\n\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n splitLineCount += content.lines;\n unifiedLineCount += content.lines;\n } else {\n splitLineCount += Math.max(content.additions, content.deletions);\n unifiedLineCount += content.additions + content.deletions;\n }\n }\n\n hunk.splitLineCount = splitLineCount;\n hunk.unifiedLineCount = unifiedLineCount;\n}\n\nfunction recomputeDiffRenderLineCounts(diff: FileDiffMetadata): void {\n let splitTotal = 0;\n let unifiedTotal = 0;\n let lastHunkAdditionEnd = 0;\n\n for (const hunk of diff.hunks) {\n hunk.collapsedBefore = Math.max(\n hunk.additionStart - 1 - lastHunkAdditionEnd,\n 0\n );\n hunk.splitLineStart = splitTotal + hunk.collapsedBefore;\n hunk.unifiedLineStart = unifiedTotal + hunk.collapsedBefore;\n\n recomputeHunkRenderLineCounts(hunk);\n\n splitTotal += hunk.collapsedBefore + hunk.splitLineCount;\n unifiedTotal += hunk.collapsedBefore + hunk.unifiedLineCount;\n lastHunkAdditionEnd = hunk.additionStart + hunk.additionCount - 1;\n }\n\n if (diff.hunks.length > 0) {\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n const collapsedAfter = Math.max(\n diff.additionLines.length -\n (lastHunk.additionLineIndex + lastHunk.additionCount),\n 0\n );\n splitTotal += collapsedAfter;\n unifiedTotal += collapsedAfter;\n }\n\n diff.splitLineCount = splitTotal;\n diff.unifiedLineCount = unifiedTotal;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"updateDiffHunks.js","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"sourcesContent":["import type { CreatePatchOptionsNonabortable } from 'diff';\n\nimport type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { parseDiffFromFile } from './parseDiffFromFile';\nimport { hasTrailingContextMismatch } from './virtualDiffLayout';\n\ntype HunkContent = ContextContent | ChangeContent;\n\ntype HunkMetadataUpdate = Pick<\n FileDiffMetadata,\n 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'type'\n>;\n\ntype FullDiffHunkUpdate = HunkMetadataUpdate &\n Pick<FileDiffMetadata, 'additionLines' | 'deletionLines'>;\n\n/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */\nexport function recomputeDiffHunks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: diff.deletionLines.join(''),\n },\n {\n name: diff.name,\n contents: diff.additionLines.join(''),\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines: recomputed.additionLines,\n deletionLines: recomputed.deletionLines,\n type: recomputed.type,\n };\n}\n\n// Builds placeholder addition contents that diff as one top-aligned change row per\n// line. Bare `\\\\n` sentinels align as context against the first deletion lines,\n// which pushes the real addition rows down in split view.\nfunction buildTopAlignedAdditionSentinel(\n lineCount: number,\n deletionContents: string\n): string {\n const count = Math.max(lineCount, 1);\n let sentinel = Array.from(\n { length: count },\n (_, index) => `${' '.repeat(index + 1)}\\n`\n ).join('');\n if (sentinel === deletionContents) {\n sentinel = Array.from(\n { length: count },\n (_, index) => `\\u0000${' '.repeat(index)}\\n`\n ).join('');\n }\n return sentinel;\n}\n\nfunction hasOnlyBlankAdditionContents(additionLines: string[]): boolean {\n for (const line of additionLines) {\n if (line.trim().length > 0) {\n return false;\n }\n }\n return true;\n}\n\n// After delete-all the editable side is blank and much shorter than the deletion\n// side. A normal recompute can still treat newline-only additions as context and\n// render the first editable row deep in split view instead of at the top.\nexport function shouldTopAlignAdditionRecompute(\n diff: FileDiffMetadata,\n additionLines: string[]\n): boolean {\n return (\n additionLines.length > 0 &&\n additionLines.length < diff.deletionLines.length &&\n hasOnlyBlankAdditionContents(additionLines)\n );\n}\n\n// Rebuilds hunk metadata while keeping the editable addition rows top-aligned in\n// split view. The sentinel only shapes hunks; the caller's addition lines are\n// preserved so the editor document stays the source of truth.\nexport function recomputeTopAlignedAdditionDiff(\n diff: FileDiffMetadata,\n additionLines: string[],\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const deletionContents = diff.deletionLines.join('');\n const additionSentinel = buildTopAlignedAdditionSentinel(\n additionLines.length,\n deletionContents\n );\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionContents,\n },\n {\n name: diff.name,\n contents: additionSentinel,\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines,\n deletionLines: recomputed.deletionLines,\n type: recomputed.type,\n };\n}\n\n// Rebuilds hunk metadata when the editable side has been emptied of all text.\n//\n// The editor always keeps one (empty) line for an empty document, but an empty\n// string splits into zero addition lines, so a normal recompute produces a diff\n// with no addition rows at all. Rendering that leaves the attached editor with\n// no line element to host its caret.\nexport function recomputeEmptyDocumentDiff(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n return recomputeTopAlignedAdditionDiff(diff, [''], parseDiffOptions);\n}\n\n/** Rebuilds diff hunks after an edit, top-aligning sparse addition sides when needed. */\nexport function recomputeDiffHunksForEdit(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n if (diff.additionLines.length === 0) {\n return recomputeEmptyDocumentDiff(diff, parseDiffOptions);\n }\n if (shouldTopAlignAdditionRecompute(diff, diff.additionLines)) {\n return recomputeTopAlignedAdditionDiff(\n diff,\n diff.additionLines,\n parseDiffOptions\n );\n }\n const additionLines = diff.additionLines;\n const recomputed = recomputeDiffHunks(diff, parseDiffOptions);\n if (\n additionLines.length > recomputed.additionLines.length &&\n hasTrailingEditorBlankLine(additionLines)\n ) {\n preserveTrailingEditorBlankLine(recomputed, additionLines);\n }\n return recomputed;\n}\n\nfunction hasTrailingEditorBlankLine(additionLines: string[]): boolean {\n return additionLines.length > 1 && additionLines.at(-1) === '';\n}\n\nfunction preserveTrailingEditorBlankLine(\n recomputed: FullDiffHunkUpdate,\n additionLines: string[]\n): void {\n const extraLineCount = additionLines.length - recomputed.additionLines.length;\n if (extraLineCount <= 0) {\n return;\n }\n const extraAdditionLineIndex = recomputed.additionLines.length;\n\n const lastHunk = recomputed.hunks.at(-1);\n if (lastHunk == null) {\n return;\n }\n\n const lastHunkAdditionEnd =\n lastHunk.additionLineIndex + lastHunk.additionCount;\n if (lastHunkAdditionEnd !== extraAdditionLineIndex) {\n return;\n }\n\n for (const content of lastHunk.hunkContent) {\n if (\n content.type === 'change' &&\n content.additions < content.deletions &&\n content.additionLineIndex + content.additions === extraAdditionLineIndex\n ) {\n recomputed.additionLines = additionLines;\n content.additions += extraLineCount;\n lastHunk.additionCount += extraLineCount;\n lastHunk.additionLines += extraLineCount;\n recomputeDiffRenderLineCounts(recomputed);\n return;\n }\n }\n}\n\n/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */\nexport function updateDiffHunks(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): HunkMetadataUpdate {\n if (diff.isPartial) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n if (diff.deletionLines.length !== diff.additionLines.length) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n const changedLines = Array.from(changedAdditionLineIndexes);\n if (changedLines.length === 0) {\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n }\n for (const line of changedLines) {\n const additionLine = diff.additionLines[line];\n const deletionLine = diff.deletionLines[line];\n if (additionLine == null || deletionLine == null) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n // Restoring a line to the old side can merge/split hunks across context windows.\n if (cleanLastNewline(additionLine) === cleanLastNewline(deletionLine)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n const affectedHunkIndexes = getAffectedHunkIndexes(diff, changedLines);\n if (affectedHunkIndexes.size === 0) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n for (const hunkIndex of affectedHunkIndexes) {\n const updated = reparseHunkRegion(diff, hunkIndex, parseDiffOptions);\n if (!updated) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n recomputeDiffRenderLineCounts(diff);\n\n if (hasTrailingContextMismatch(diff)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n}\n\nfunction applyHunkUpdateResult<T extends HunkMetadataUpdate>(\n diff: FileDiffMetadata,\n result: T\n): T {\n Object.assign(diff, result);\n return result;\n}\n\nfunction getAffectedHunkIndexes(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>\n): Set<number> {\n const indexes = new Set<number>();\n for (const line of changedAdditionLineIndexes) {\n const hunkIndex = findHunkIndexForAdditionLine(diff, line);\n if (hunkIndex == null) {\n return new Set();\n }\n indexes.add(hunkIndex);\n }\n return indexes;\n}\n\nfunction findHunkIndexForAdditionLine(\n diff: FileDiffMetadata,\n line: number\n): number | undefined {\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const end = hunk.additionLineIndex + hunk.additionCount;\n if (line >= hunk.additionLineIndex && line < end) {\n return hunkIndex;\n }\n }\n return undefined;\n}\n\nfunction reparseHunkRegion(\n diff: FileDiffMetadata,\n hunkIndex: number,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): boolean {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return false;\n }\n\n const deletionSlice = diff.deletionLines.slice(\n hunk.deletionLineIndex,\n hunk.deletionLineIndex + hunk.deletionCount\n );\n const additionSlice = diff.additionLines.slice(\n hunk.additionLineIndex,\n hunk.additionLineIndex + hunk.additionCount\n );\n\n const reparsed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionSlice.join(''),\n },\n {\n name: diff.name,\n contents: additionSlice.join(''),\n lang: diff.lang,\n },\n { ...parseDiffOptions, context: 0 }\n );\n\n const reparsedHunk = reparsed.hunks[0];\n if (reparsedHunk == null || reparsed.hunks.length !== 1) {\n return false;\n }\n\n applyReparsedHunk(hunk, reparsedHunk);\n syncHunkNoEOFCRFromFullFile(diff, hunkIndex);\n return true;\n}\n\nfunction syncHunkNoEOFCRFromFullFile(\n diff: FileDiffMetadata,\n hunkIndex: number\n): void {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return;\n }\n\n const isLastHunk = hunkIndex === diff.hunks.length - 1;\n if (!isLastHunk) {\n hunk.noEOFCRAdditions = false;\n hunk.noEOFCRDeletions = false;\n return;\n }\n\n const lastAdditionLine = diff.additionLines.at(-1);\n const lastDeletionLine = diff.deletionLines.at(-1);\n hunk.noEOFCRAdditions =\n lastAdditionLine != null &&\n lastAdditionLine !== '' &&\n !lastAdditionLine.endsWith('\\n');\n hunk.noEOFCRDeletions =\n lastDeletionLine != null &&\n lastDeletionLine !== '' &&\n !lastDeletionLine.endsWith('\\n');\n}\n\nfunction applyReparsedHunk(target: Hunk, parsed: Hunk): void {\n const additionOffset = target.additionLineIndex;\n const deletionOffset = target.deletionLineIndex;\n\n target.hunkContent = parsed.hunkContent.map((content) =>\n offsetHunkContent(content, additionOffset, deletionOffset)\n );\n target.additionLineIndex = additionOffset + parsed.additionLineIndex;\n target.additionStart = target.additionStart + parsed.additionLineIndex;\n target.additionCount = parsed.additionCount;\n target.additionLines = parsed.additionLines;\n if (parsed.deletionLineIndex >= 0) {\n target.deletionLineIndex = deletionOffset + parsed.deletionLineIndex;\n target.deletionStart = target.deletionStart + parsed.deletionLineIndex;\n }\n target.deletionCount = parsed.deletionCount;\n target.deletionLines = parsed.deletionLines;\n target.noEOFCRAdditions = parsed.noEOFCRAdditions;\n target.noEOFCRDeletions = parsed.noEOFCRDeletions;\n\n recomputeHunkRenderLineCounts(target);\n}\n\nfunction offsetHunkContent(\n content: HunkContent,\n additionOffset: number,\n deletionOffset: number\n): HunkContent {\n return {\n ...content,\n additionLineIndex: content.additionLineIndex + additionOffset,\n deletionLineIndex: content.deletionLineIndex + deletionOffset,\n };\n}\n\nfunction recomputeHunkRenderLineCounts(hunk: Hunk): void {\n let splitLineCount = 0;\n let unifiedLineCount = 0;\n\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n splitLineCount += content.lines;\n unifiedLineCount += content.lines;\n } else {\n splitLineCount += Math.max(content.additions, content.deletions);\n unifiedLineCount += content.additions + content.deletions;\n }\n }\n\n hunk.splitLineCount = splitLineCount;\n hunk.unifiedLineCount = unifiedLineCount;\n}\n\nfunction recomputeDiffRenderLineCounts(\n diff: HunkMetadataUpdate & Pick<FileDiffMetadata, 'additionLines'>\n): void {\n let splitTotal = 0;\n let unifiedTotal = 0;\n let lastHunkAdditionEnd = 0;\n\n for (const hunk of diff.hunks) {\n hunk.collapsedBefore = Math.max(\n hunk.additionStart - 1 - lastHunkAdditionEnd,\n 0\n );\n hunk.splitLineStart = splitTotal + hunk.collapsedBefore;\n hunk.unifiedLineStart = unifiedTotal + hunk.collapsedBefore;\n\n recomputeHunkRenderLineCounts(hunk);\n\n splitTotal += hunk.collapsedBefore + hunk.splitLineCount;\n unifiedTotal += hunk.collapsedBefore + hunk.unifiedLineCount;\n lastHunkAdditionEnd = hunk.additionStart + hunk.additionCount - 1;\n }\n\n if (diff.hunks.length > 0) {\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n const collapsedAfter = Math.max(\n diff.additionLines.length -\n (lastHunk.additionLineIndex + lastHunk.additionCount),\n 0\n );\n splitTotal += collapsedAfter;\n unifiedTotal += collapsedAfter;\n }\n\n diff.splitLineCount = splitTotal;\n diff.unifiedLineCount = unifiedTotal;\n}\n"],"mappings":"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"}
|
|
@@ -69,10 +69,12 @@ declare class WorkerPoolManager {
|
|
|
69
69
|
private initializeWorkers;
|
|
70
70
|
private drainQueue;
|
|
71
71
|
highlightFileAST(instance: FileRendererInstance, file: FileContents): void;
|
|
72
|
-
primeFileHighlightCache(file: FileContents): void
|
|
72
|
+
primeFileHighlightCache(file: FileContents): Promise<void>;
|
|
73
|
+
private getOrCreateFileHighlightCacheTask;
|
|
73
74
|
getPlainFileAST(file: FileContents, startingLine: number, totalLines: number, lines?: string[]): ThemedFileResult | undefined;
|
|
74
75
|
highlightDiffAST(instance: DiffRendererInstance, diff: FileDiffMetadata): void;
|
|
75
|
-
primeDiffHighlightCache(diff: FileDiffMetadata): void
|
|
76
|
+
primeDiffHighlightCache(diff: FileDiffMetadata): Promise<void>;
|
|
77
|
+
private getOrCreateDiffHighlightCacheTask;
|
|
76
78
|
getPlainDiffAST(diff: FileDiffMetadata, startingLine: number, totalLines: number, expandedHunks?: Map<number, HunkExpansionRegion> | true, collapsedContextThreshold?: number): ThemedDiffResult | undefined;
|
|
77
79
|
terminate(): void;
|
|
78
80
|
private isCurrentLifecycle;
|
|
@@ -102,6 +104,9 @@ declare class WorkerPoolManager {
|
|
|
102
104
|
private detachInstanceFromRenderTask;
|
|
103
105
|
private removeQueuedTask;
|
|
104
106
|
private removeActiveTask;
|
|
107
|
+
private createRenderTaskCallbacks;
|
|
108
|
+
private resolveRenderTaskCallbacks;
|
|
109
|
+
private rejectRenderTaskCallbacks;
|
|
105
110
|
private invalidateRenderTasks;
|
|
106
111
|
private clearQueuedInstanceRequests;
|
|
107
112
|
private clearHighlightKey;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerPoolManager.d.ts","names":[],"sources":["../../src/worker/WorkerPoolManager.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"WorkerPoolManager.d.ts","names":[],"sources":["../../src/worker/WorkerPoolManager.ts"],"mappings":"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"}
|