@pierre/diffs 1.3.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CodeView.d.ts +113 -68
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +153 -58
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +75 -15
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +223 -62
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +97 -21
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +400 -100
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts +2 -2
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +2 -2
- package/dist/components/UnresolvedFile.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +16 -7
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +140 -51
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +14 -8
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +183 -93
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
- package/dist/edit/index.d.ts +7 -4
- package/dist/edit/index.js +5 -1
- package/dist/editor/EditStateManager.d.ts +56 -0
- package/dist/editor/EditStateManager.d.ts.map +1 -0
- package/dist/editor/EditStateManager.js +135 -0
- package/dist/editor/EditStateManager.js.map +1 -0
- package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts +7 -0
- package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts.map +1 -0
- package/dist/editor/cloneRetainedDiffSessionSnapshot.js +16 -0
- package/dist/editor/cloneRetainedDiffSessionSnapshot.js.map +1 -0
- package/dist/editor/editPrediction.d.ts +76 -0
- package/dist/editor/editPrediction.d.ts.map +1 -0
- package/dist/editor/editPrediction.js +365 -0
- package/dist/editor/editPrediction.js.map +1 -0
- package/dist/editor/editStack.d.ts +19 -40
- package/dist/editor/editStack.d.ts.map +1 -1
- package/dist/editor/editStack.js +67 -4
- package/dist/editor/editStack.js.map +1 -1
- package/dist/editor/editor.d.ts +118 -29
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +1103 -383
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/languages.d.ts +3 -3
- package/dist/editor/languages.d.ts.map +1 -1
- package/dist/editor/languages.js.map +1 -1
- package/dist/editor/lineAnnotations.d.ts +3 -3
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +16 -7
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +2 -2
- package/dist/editor/marker.d.ts.map +1 -1
- package/dist/editor/marker.js.map +1 -1
- package/dist/editor/matchBrackets.d.ts +2 -2
- package/dist/editor/matchBrackets.d.ts.map +1 -1
- package/dist/editor/matchBrackets.js.map +1 -1
- package/dist/editor/pieceTable.d.ts +1 -1
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/searchPanel.d.ts +2 -2
- package/dist/editor/searchPanel.js +1 -1
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +32 -23
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +3 -3
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/selectionAction.d.ts +3 -3
- package/dist/editor/selectionAction.d.ts.map +1 -1
- package/dist/editor/selectionAction.js.map +1 -1
- package/dist/editor/textDocument.d.ts +11 -8
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +28 -5
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textDocumentChangeTransaction.d.ts +15 -0
- package/dist/editor/textDocumentChangeTransaction.d.ts.map +1 -0
- package/dist/editor/textDocumentChangeTransaction.js +12 -0
- package/dist/editor/textDocumentChangeTransaction.js.map +1 -0
- package/dist/editor/textMeasure.d.ts +5 -0
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +10 -0
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/tokenizer.d.ts +1 -1
- package/dist/editor/tokenizer.js.map +1 -1
- package/dist/editor/types.d.ts +267 -0
- package/dist/editor/types.d.ts.map +1 -0
- package/dist/editor/types.js +0 -0
- package/dist/editor/utils.d.ts +2 -1
- package/dist/editor/utils.d.ts.map +1 -1
- package/dist/editor/utils.js +4 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +9 -8
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +7 -0
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/react/CodeView.d.ts +36 -25
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +15 -14
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/EditContext.d.ts +8 -11
- package/dist/react/EditContext.d.ts.map +1 -1
- package/dist/react/EditContext.js +2 -9
- package/dist/react/EditContext.js.map +1 -1
- package/dist/react/File.d.ts +10 -6
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +8 -4
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +10 -5
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +8 -4
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +8 -5
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +8 -12
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +7 -4
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +8 -4
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.d.ts +3 -3
- package/dist/react/UnresolvedFile.d.ts.map +1 -1
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/index.d.ts +8 -5
- package/dist/react/types.d.ts +46 -9
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.d.ts +14 -12
- package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.js +2 -2
- package/dist/react/utils/renderDiffChildren.js.map +1 -1
- package/dist/react/utils/renderFileChildren.d.ts +14 -12
- package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
- package/dist/react/utils/renderFileChildren.js +2 -2
- package/dist/react/utils/renderFileChildren.js.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +22 -10
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +112 -22
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +15 -9
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +84 -25
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +30 -15
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +172 -108
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +27 -11
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +138 -64
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +2 -2
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.js +2 -2
- package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
- package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
- package/dist/shiki-stream/tokenizer.js +2 -1
- package/dist/shiki-stream/tokenizer.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/preloadDiffs.d.ts +21 -21
- package/dist/ssr/preloadDiffs.d.ts.map +1 -1
- package/dist/ssr/preloadDiffs.js +1 -1
- package/dist/ssr/preloadDiffs.js.map +1 -1
- package/dist/ssr/preloadFile.d.ts +6 -6
- package/dist/ssr/preloadFile.d.ts.map +1 -1
- package/dist/ssr/preloadFile.js.map +1 -1
- package/dist/ssr/preloadPatchFile.d.ts +4 -4
- package/dist/ssr/preloadPatchFile.d.ts.map +1 -1
- package/dist/ssr/preloadPatchFile.js.map +1 -1
- package/dist/style.js +1 -1
- package/dist/types.d.ts +13 -263
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/appendItems.d.ts +5 -0
- package/dist/utils/appendItems.d.ts.map +1 -0
- package/dist/utils/appendItems.js +8 -0
- package/dist/utils/appendItems.js.map +1 -0
- package/dist/utils/areDiffTargetsEqual.js +1 -1
- package/dist/utils/areDiffTargetsEqual.js.map +1 -1
- package/dist/utils/areFileTargetsEqual.d.ts +7 -0
- package/dist/utils/areFileTargetsEqual.d.ts.map +1 -0
- package/dist/utils/areFileTargetsEqual.js +8 -0
- package/dist/utils/areFileTargetsEqual.js.map +1 -0
- package/dist/utils/areManagedSnapshotsEqual.d.ts +1 -1
- package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
- package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
- package/dist/utils/areOptionsEqual.d.ts +3 -3
- package/dist/utils/areOptionsEqual.d.ts.map +1 -1
- package/dist/utils/areOptionsEqual.js.map +1 -1
- package/dist/utils/cloneFileDiffMetadata.d.ts +3 -2
- package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -1
- package/dist/utils/cloneFileDiffMetadata.js +8 -5
- package/dist/utils/cloneFileDiffMetadata.js.map +1 -1
- package/dist/utils/composeCacheKey.d.ts +6 -0
- package/dist/utils/composeCacheKey.d.ts.map +1 -0
- package/dist/utils/composeCacheKey.js +10 -0
- package/dist/utils/composeCacheKey.js.map +1 -0
- package/dist/utils/editSessionAnnotations.d.ts +69 -0
- package/dist/utils/editSessionAnnotations.d.ts.map +1 -0
- package/dist/utils/editSessionAnnotations.js +64 -0
- package/dist/utils/editSessionAnnotations.js.map +1 -0
- package/dist/utils/editSessionHunks.d.ts +5 -3
- package/dist/utils/editSessionHunks.d.ts.map +1 -1
- package/dist/utils/editSessionHunks.js +7 -5
- package/dist/utils/editSessionHunks.js.map +1 -1
- package/dist/utils/getDiffHunksRendererOptions.d.ts +1 -1
- package/dist/utils/getDiffHunksRendererOptions.d.ts.map +1 -1
- package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
- package/dist/utils/getFileRendererOptions.d.ts +1 -1
- package/dist/utils/getFileRendererOptions.d.ts.map +1 -1
- package/dist/utils/getFileRendererOptions.js.map +1 -1
- package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
- package/dist/utils/hydratePartialDiff.js +2 -1
- package/dist/utils/hydratePartialDiff.js.map +1 -1
- package/dist/utils/lineAnnotationIdentity.d.ts +16 -0
- package/dist/utils/lineAnnotationIdentity.d.ts.map +1 -0
- package/dist/utils/lineAnnotationIdentity.js +17 -0
- package/dist/utils/lineAnnotationIdentity.js.map +1 -0
- package/dist/utils/parseDiffFromFile.d.ts +2 -2
- package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseDiffFromFile.js +6 -6
- package/dist/utils/parseDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts +6 -3
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +34 -9
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.js +6 -5
- package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
- package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderFileWithHighlighter.js +7 -4
- package/dist/utils/renderFileWithHighlighter.js.map +1 -1
- package/dist/utils/trimPatchContext.d.ts.map +1 -1
- package/dist/utils/trimPatchContext.js +3 -2
- package/dist/utils/trimPatchContext.js.map +1 -1
- package/dist/utils/updateDiffHunks.js +1 -1
- package/dist/utils/virtualDiffLayout.js +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +4 -3
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +33 -4
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/types.d.ts +5 -0
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker-portable.js +14 -6
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +14 -6
- package/dist/worker/worker.js.map +1 -1
- package/package.json +9 -1
- package/dist/editor/stateStorage.d.ts +0 -15
- package/dist/editor/stateStorage.d.ts.map +0 -1
- package/dist/editor/stateStorage.js +0 -65
- package/dist/editor/stateStorage.js.map +0 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { LineAnnotationPosition } from "./lineAnnotationIdentity.js";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/editSessionAnnotations.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Annotation state for an active edit session. Like the private
|
|
6
|
+
* `editSessionFile`/`editSessionDiff` render models, we avoid mutating the
|
|
7
|
+
* original annotations and instead create a duplicate set that we mutate as
|
|
8
|
+
* needed while the user is editing the file or diff. When editing is
|
|
9
|
+
* finished, we can either revert back to the old state, or inherit the new
|
|
10
|
+
* mutated annotations.
|
|
11
|
+
*
|
|
12
|
+
* `current` holds the annotations actually rendered; the editor replaces
|
|
13
|
+
* them as edits move annotations between lines. `provided` is the last
|
|
14
|
+
* annotations array the component rendered with. When a render is called with
|
|
15
|
+
* annotations, we check whether it's a new array or the existing annotations
|
|
16
|
+
* we've previously rendered. If new, we fully replace whatever the edit
|
|
17
|
+
* session derived since there's no way to really reasonably rectify existing
|
|
18
|
+
* state. If it's the same as `provided` or `current`, we continue assuming
|
|
19
|
+
* `current` is the latest source of truth.
|
|
20
|
+
*
|
|
21
|
+
* `slotNames` map is a hack to keep annotation content attached while lines
|
|
22
|
+
* move around. Normally slotNames are derived from the target line number (and
|
|
23
|
+
* possibly side of the diff). Doing this while editing would force every
|
|
24
|
+
* annotation that gets moved to remount which is not ideal. So by keeping a
|
|
25
|
+
* reference map of annotation to slot name, we can keep invalid slot names
|
|
26
|
+
* until editing is completed, and then either revert back to our original
|
|
27
|
+
* annotations or update them with their new slot names (which will currently
|
|
28
|
+
* trigger a remount). In a future update we'll add a better ID system for
|
|
29
|
+
* annotations so we don't need to depend on this flawed keying architecture.
|
|
30
|
+
*/
|
|
31
|
+
interface EditSessionAnnotations<TAnnotation> {
|
|
32
|
+
provided: TAnnotation[];
|
|
33
|
+
current: TAnnotation[];
|
|
34
|
+
slotNames: Map<object, string>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates session state when an editor attaches. The array is kept as-is for
|
|
38
|
+
* both `provided` and `current`, and we record each annotation's slot name
|
|
39
|
+
* before any edits can move it.
|
|
40
|
+
*
|
|
41
|
+
* `previousSession` covers a whole new file or diff arriving mid-edit. The
|
|
42
|
+
* annotations that come with it describe the new document, so we rebuild the
|
|
43
|
+
* session around them — but any annotation the outgoing session already
|
|
44
|
+
* named keeps that name, since the caller's content is already rendered into
|
|
45
|
+
* a slot with it. Names for annotations that didn't survive the swap are
|
|
46
|
+
* simply dropped.
|
|
47
|
+
*/
|
|
48
|
+
declare function adoptEditSessionAnnotations<TAnnotation extends LineAnnotationPosition>(annotations: TAnnotation[], getName: (annotation: TAnnotation) => string, previousSession?: EditSessionAnnotations<TAnnotation>): EditSessionAnnotations<TAnnotation>;
|
|
49
|
+
/**
|
|
50
|
+
* Handles the caller passing a brand new annotations array while editing is
|
|
51
|
+
* active. We take it exactly as given — line numbers are read against the
|
|
52
|
+
* document as currently edited, and there's no merging with what the session
|
|
53
|
+
* had — so it replaces both `provided` and `current`. Annotations we've seen
|
|
54
|
+
* before keep their recorded slot names; new ones record a name for wherever
|
|
55
|
+
* they landed.
|
|
56
|
+
*/
|
|
57
|
+
declare function writeEditSessionAnnotations<TAnnotation extends LineAnnotationPosition>(session: EditSessionAnnotations<TAnnotation>, annotations: TAnnotation[], getName: (annotation: TAnnotation) => string): void;
|
|
58
|
+
/**
|
|
59
|
+
* Every slot name an editable component renders resolves through here. With
|
|
60
|
+
* no active session this is just the normal position-derived name. During a
|
|
61
|
+
* session we return the recorded name instead, and an annotation we've never
|
|
62
|
+
* seen records its name the first time anyone asks. That way everything that
|
|
63
|
+
* writes slot names — the renderers, the editor, the light-DOM wrappers —
|
|
64
|
+
* lands on the same name for the same annotation.
|
|
65
|
+
*/
|
|
66
|
+
declare function resolveEditSessionSlotName<TAnnotation extends LineAnnotationPosition>(session: EditSessionAnnotations<TAnnotation> | undefined, annotation: TAnnotation, getName: (annotation: TAnnotation) => string): string;
|
|
67
|
+
//#endregion
|
|
68
|
+
export { EditSessionAnnotations, adoptEditSessionAnnotations, resolveEditSessionSlotName, writeEditSessionAnnotations };
|
|
69
|
+
//# sourceMappingURL=editSessionAnnotations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editSessionAnnotations.d.ts","names":[],"sources":["../../src/utils/editSessionAnnotations.ts"],"mappings":";;;;;AAiCA;;;;;;;;;;;;;;;;AAGgB;AAehB;;;;;;;;UAlBiB,sBAAA;EACf,QAAA,EAAU,WAAA;EACV,OAAA,EAAS,WAAA;EACT,SAAA,EAAW,GAAA;AAAA;;;;;;;;;;;;;iBAeG,2BAAA,qBACM,sBAAA,EAEpB,WAAA,EAAa,WAAA,IACb,OAAA,GAAU,UAAA,EAAY,WAAA,aACtB,eAAA,GAAkB,sBAAA,CAAuB,WAAA,IACxC,sBAAA,CAAuB,WAAA;AAoB1B;;;;;;;;AAAA,iBAAgB,2BAAA,qBACM,sBAAA,EAEpB,OAAA,EAAS,sBAAA,CAAuB,WAAA,GAChC,WAAA,EAAa,WAAA,IACb,OAAA,GAAU,UAAA,EAAY,WAAA;;;;;;;;;iBAoBR,0BAAA,qBACM,sBAAA,EAEpB,OAAA,EAAS,sBAAA,CAAuB,WAAA,eAChC,UAAA,EAAY,WAAA,EACZ,OAAA,GAAU,UAAA,EAAY,WAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getLineAnnotationSource } from "./lineAnnotationIdentity.js";
|
|
2
|
+
//#region src/utils/editSessionAnnotations.ts
|
|
3
|
+
/**
|
|
4
|
+
* Creates session state when an editor attaches. The array is kept as-is for
|
|
5
|
+
* both `provided` and `current`, and we record each annotation's slot name
|
|
6
|
+
* before any edits can move it.
|
|
7
|
+
*
|
|
8
|
+
* `previousSession` covers a whole new file or diff arriving mid-edit. The
|
|
9
|
+
* annotations that come with it describe the new document, so we rebuild the
|
|
10
|
+
* session around them — but any annotation the outgoing session already
|
|
11
|
+
* named keeps that name, since the caller's content is already rendered into
|
|
12
|
+
* a slot with it. Names for annotations that didn't survive the swap are
|
|
13
|
+
* simply dropped.
|
|
14
|
+
*/
|
|
15
|
+
function adoptEditSessionAnnotations(annotations, getName, previousSession) {
|
|
16
|
+
const slotNames = /* @__PURE__ */ new Map();
|
|
17
|
+
for (const annotation of annotations) {
|
|
18
|
+
const source = getLineAnnotationSource(annotation);
|
|
19
|
+
slotNames.set(source, previousSession?.slotNames.get(source) ?? getName(annotation));
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
provided: annotations,
|
|
23
|
+
current: annotations,
|
|
24
|
+
slotNames
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Handles the caller passing a brand new annotations array while editing is
|
|
29
|
+
* active. We take it exactly as given — line numbers are read against the
|
|
30
|
+
* document as currently edited, and there's no merging with what the session
|
|
31
|
+
* had — so it replaces both `provided` and `current`. Annotations we've seen
|
|
32
|
+
* before keep their recorded slot names; new ones record a name for wherever
|
|
33
|
+
* they landed.
|
|
34
|
+
*/
|
|
35
|
+
function writeEditSessionAnnotations(session, annotations, getName) {
|
|
36
|
+
for (const annotation of annotations) {
|
|
37
|
+
const source = getLineAnnotationSource(annotation);
|
|
38
|
+
if (!session.slotNames.has(source)) session.slotNames.set(source, getName(annotation));
|
|
39
|
+
}
|
|
40
|
+
session.provided = annotations;
|
|
41
|
+
session.current = annotations;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Every slot name an editable component renders resolves through here. With
|
|
45
|
+
* no active session this is just the normal position-derived name. During a
|
|
46
|
+
* session we return the recorded name instead, and an annotation we've never
|
|
47
|
+
* seen records its name the first time anyone asks. That way everything that
|
|
48
|
+
* writes slot names — the renderers, the editor, the light-DOM wrappers —
|
|
49
|
+
* lands on the same name for the same annotation.
|
|
50
|
+
*/
|
|
51
|
+
function resolveEditSessionSlotName(session, annotation, getName) {
|
|
52
|
+
if (session == null) return getName(annotation);
|
|
53
|
+
const source = getLineAnnotationSource(annotation);
|
|
54
|
+
let name = session.slotNames.get(source);
|
|
55
|
+
if (name == null) {
|
|
56
|
+
name = getName(annotation);
|
|
57
|
+
session.slotNames.set(source, name);
|
|
58
|
+
}
|
|
59
|
+
return name;
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { adoptEditSessionAnnotations, resolveEditSessionSlotName, writeEditSessionAnnotations };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=editSessionAnnotations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editSessionAnnotations.js","names":[],"sources":["../../src/utils/editSessionAnnotations.ts"],"sourcesContent":["import {\n getLineAnnotationSource,\n type LineAnnotationPosition,\n} from './lineAnnotationIdentity';\n\n/**\n * Annotation state for an active edit session. Like the private\n * `editSessionFile`/`editSessionDiff` render models, we avoid mutating the\n * original annotations and instead create a duplicate set that we mutate as\n * needed while the user is editing the file or diff. When editing is\n * finished, we can either revert back to the old state, or inherit the new\n * mutated annotations.\n *\n * `current` holds the annotations actually rendered; the editor replaces\n * them as edits move annotations between lines. `provided` is the last\n * annotations array the component rendered with. When a render is called with\n * annotations, we check whether it's a new array or the existing annotations\n * we've previously rendered. If new, we fully replace whatever the edit\n * session derived since there's no way to really reasonably rectify existing\n * state. If it's the same as `provided` or `current`, we continue assuming\n * `current` is the latest source of truth.\n *\n * `slotNames` map is a hack to keep annotation content attached while lines\n * move around. Normally slotNames are derived from the target line number (and\n * possibly side of the diff). Doing this while editing would force every\n * annotation that gets moved to remount which is not ideal. So by keeping a\n * reference map of annotation to slot name, we can keep invalid slot names\n * until editing is completed, and then either revert back to our original\n * annotations or update them with their new slot names (which will currently\n * trigger a remount). In a future update we'll add a better ID system for\n * annotations so we don't need to depend on this flawed keying architecture.\n */\n\nexport interface EditSessionAnnotations<TAnnotation> {\n provided: TAnnotation[];\n current: TAnnotation[];\n slotNames: Map<object, string>;\n}\n\n/**\n * Creates session state when an editor attaches. The array is kept as-is for\n * both `provided` and `current`, and we record each annotation's slot name\n * before any edits can move it.\n *\n * `previousSession` covers a whole new file or diff arriving mid-edit. The\n * annotations that come with it describe the new document, so we rebuild the\n * session around them — but any annotation the outgoing session already\n * named keeps that name, since the caller's content is already rendered into\n * a slot with it. Names for annotations that didn't survive the swap are\n * simply dropped.\n */\nexport function adoptEditSessionAnnotations<\n TAnnotation extends LineAnnotationPosition,\n>(\n annotations: TAnnotation[],\n getName: (annotation: TAnnotation) => string,\n previousSession?: EditSessionAnnotations<TAnnotation>\n): EditSessionAnnotations<TAnnotation> {\n const slotNames = new Map<object, string>();\n for (const annotation of annotations) {\n const source = getLineAnnotationSource(annotation);\n slotNames.set(\n source,\n previousSession?.slotNames.get(source) ?? getName(annotation)\n );\n }\n return { provided: annotations, current: annotations, slotNames };\n}\n\n/**\n * Handles the caller passing a brand new annotations array while editing is\n * active. We take it exactly as given — line numbers are read against the\n * document as currently edited, and there's no merging with what the session\n * had — so it replaces both `provided` and `current`. Annotations we've seen\n * before keep their recorded slot names; new ones record a name for wherever\n * they landed.\n */\nexport function writeEditSessionAnnotations<\n TAnnotation extends LineAnnotationPosition,\n>(\n session: EditSessionAnnotations<TAnnotation>,\n annotations: TAnnotation[],\n getName: (annotation: TAnnotation) => string\n): void {\n for (const annotation of annotations) {\n const source = getLineAnnotationSource(annotation);\n if (!session.slotNames.has(source)) {\n session.slotNames.set(source, getName(annotation));\n }\n }\n session.provided = annotations;\n session.current = annotations;\n}\n\n/**\n * Every slot name an editable component renders resolves through here. With\n * no active session this is just the normal position-derived name. During a\n * session we return the recorded name instead, and an annotation we've never\n * seen records its name the first time anyone asks. That way everything that\n * writes slot names — the renderers, the editor, the light-DOM wrappers —\n * lands on the same name for the same annotation.\n */\nexport function resolveEditSessionSlotName<\n TAnnotation extends LineAnnotationPosition,\n>(\n session: EditSessionAnnotations<TAnnotation> | undefined,\n annotation: TAnnotation,\n getName: (annotation: TAnnotation) => string\n): string {\n if (session == null) {\n return getName(annotation);\n }\n const source = getLineAnnotationSource(annotation);\n let name = session.slotNames.get(source);\n if (name == null) {\n name = getName(annotation);\n session.slotNames.set(source, name);\n }\n return name;\n}\n"],"mappings":";;;;;;;;;;;;;;AAmDA,SAAgB,4BAGd,aACA,SACA,iBACqC;CACrC,MAAM,4BAAY,IAAI,IAAoB;CAC1C,KAAK,MAAM,cAAc,aAAa;EACpC,MAAM,SAAS,wBAAwB,UAAU;EACjD,UAAU,IACR,QACA,iBAAiB,UAAU,IAAI,MAAM,KAAK,QAAQ,UAAU,CAC9D;CACF;CACA,OAAO;EAAE,UAAU;EAAa,SAAS;EAAa;CAAU;AAClE;;;;;;;;;AAUA,SAAgB,4BAGd,SACA,aACA,SACM;CACN,KAAK,MAAM,cAAc,aAAa;EACpC,MAAM,SAAS,wBAAwB,UAAU;EACjD,IAAI,CAAC,QAAQ,UAAU,IAAI,MAAM,GAC/B,QAAQ,UAAU,IAAI,QAAQ,QAAQ,UAAU,CAAC;CAErD;CACA,QAAQ,WAAW;CACnB,QAAQ,UAAU;AACpB;;;;;;;;;AAUA,SAAgB,2BAGd,SACA,YACA,SACQ;CACR,IAAI,WAAW,MACb,OAAO,QAAQ,UAAU;CAE3B,MAAM,SAAS,wBAAwB,UAAU;CACjD,IAAI,OAAO,QAAQ,UAAU,IAAI,MAAM;CACvC,IAAI,QAAQ,MAAM;EAChB,OAAO,QAAQ,UAAU;EACzB,QAAQ,UAAU,IAAI,QAAQ,IAAI;CACpC;CACA,OAAO;AACT"}
|
|
@@ -56,9 +56,11 @@ declare function captureExpansionAnchors(diff: FileDiffMetadata, expandedHunks:
|
|
|
56
56
|
*/
|
|
57
57
|
declare function rebuildExpansionFromAnchors(diff: FileDiffMetadata, anchors: ExpansionAnchorRange[]): Map<number, HunkExpansionRegion>;
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* the
|
|
59
|
+
* While editing, hunk updates keep a lightweight session-specific shape and
|
|
60
|
+
* mark the diff with `editSessionDirty`. Called at session end, this
|
|
61
|
+
* recomputes the hunks in full from the diff's current lines — the same
|
|
62
|
+
* hunks a non-session edit would have produced — and clears the flag.
|
|
63
|
+
* Returns true when a recompute ran.
|
|
62
64
|
*/
|
|
63
65
|
declare function finishEditSessionForDiff(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): boolean;
|
|
64
66
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editSessionHunks.d.ts","names":[],"sources":["../../src/utils/editSessionHunks.ts"],"mappings":";;;;UA8BiB,cAAA;EACf,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,UAGQ,kBAAA;EACR,UAAA;EACA,SAAS;AAAA;;UAIM,mBAAA;EACf,OAAA,EAAS,KAAK,CAAC,kBAAA;AAAA;;;AALN;AAIX;;iBA4BgB,oBAAA,CAAqB,KAAe;;;;;iBAWpC,kBAAA,CACd,aAAA,YACA,aAAA,aACC,cAAc;AAzCkB;AA2BnC;;;;AA3BmC,iBAoEnB,mBAAA,CACd,IAAA,EAAM,gBAAA,EACN,gBAAA,GAAmB,8BAAA,GAClB,mBAAA;AAjCH;;;;AAAA,iBAoEgB,wBAAA,CACd,IAAA,EAAM,gBAAA,EACN,0BAAA,EAA4B,QAAA,UAC5B,gBAAA,GAAmB,8BAAA,EACnB,qBAAA,GAAwB,WAAA,mBACvB,mBAAA;;iBAwHa,iCAAA,CACd,aAAA,EAAe,GAAA,SAAY,mBAAA,GAC3B,MAAA,EAAQ,mBAAA,GACP,GAAA,SAAY,mBAAA;;AAjME;AA2BjB;;;;KAmMY,oBAAA,IAAwB,KAAA,UAAe,GAAG;;iBAGtC,uBAAA,CACd,IAAA,EAAM,gBAAA,EACN,aAAA,EAAe,GAAA,SAAY,mBAAA,GAC3B,yBAAA,WACC,oBAAA;;;;;;;iBAoDa,2BAAA,CACd,IAAA,EAAM,gBAAA,EACN,OAAA,EAAS,oBAAA,KACR,GAAA,SAAY,mBAAA;AA9PO;AAmCtB
|
|
1
|
+
{"version":3,"file":"editSessionHunks.d.ts","names":[],"sources":["../../src/utils/editSessionHunks.ts"],"mappings":";;;;UA8BiB,cAAA;EACf,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,UAGQ,kBAAA;EACR,UAAA;EACA,SAAS;AAAA;;UAIM,mBAAA;EACf,OAAA,EAAS,KAAK,CAAC,kBAAA;AAAA;;;AALN;AAIX;;iBA4BgB,oBAAA,CAAqB,KAAe;;;;;iBAWpC,kBAAA,CACd,aAAA,YACA,aAAA,aACC,cAAc;AAzCkB;AA2BnC;;;;AA3BmC,iBAoEnB,mBAAA,CACd,IAAA,EAAM,gBAAA,EACN,gBAAA,GAAmB,8BAAA,GAClB,mBAAA;AAjCH;;;;AAAA,iBAoEgB,wBAAA,CACd,IAAA,EAAM,gBAAA,EACN,0BAAA,EAA4B,QAAA,UAC5B,gBAAA,GAAmB,8BAAA,EACnB,qBAAA,GAAwB,WAAA,mBACvB,mBAAA;;iBAwHa,iCAAA,CACd,aAAA,EAAe,GAAA,SAAY,mBAAA,GAC3B,MAAA,EAAQ,mBAAA,GACP,GAAA,SAAY,mBAAA;;AAjME;AA2BjB;;;;KAmMY,oBAAA,IAAwB,KAAA,UAAe,GAAG;;iBAGtC,uBAAA,CACd,IAAA,EAAM,gBAAA,EACN,aAAA,EAAe,GAAA,SAAY,mBAAA,GAC3B,yBAAA,WACC,oBAAA;;;;;;;iBAoDa,2BAAA,CACd,IAAA,EAAM,gBAAA,EACN,OAAA,EAAS,oBAAA,KACR,GAAA,SAAY,mBAAA;AA9PO;AAmCtB;;;;;;AAnCsB,iBA8SN,wBAAA,CACd,IAAA,EAAM,gBAAA,EACN,gBAAA,GAAmB,8BAA8B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getHunkSideStartBoundary } from "./getHunkSideBoundaries.js";
|
|
2
|
-
import { parseDiffFromFile } from "./parseDiffFromFile.js";
|
|
3
2
|
import { getExpandedRegion, getTrailingExpandedRegion } from "./virtualDiffLayout.js";
|
|
3
|
+
import { parseDiffFromFile } from "./parseDiffFromFile.js";
|
|
4
4
|
import { offsetHunkContent, preserveTrailingEditorBlankLine, recomputeDiffHunks, recomputeDiffHunksForEdit, recomputeDiffRenderLineCounts, recomputeHunkRenderLineCounts, syncHunkNoEOFCRFromFullFile } from "./updateDiffHunks.js";
|
|
5
5
|
//#region src/utils/editSessionHunks.ts
|
|
6
6
|
const deletionLineSetCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -198,13 +198,15 @@ function rebuildExpansionFromAnchors(diff, anchors) {
|
|
|
198
198
|
return rebuilt;
|
|
199
199
|
}
|
|
200
200
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* the
|
|
201
|
+
* While editing, hunk updates keep a lightweight session-specific shape and
|
|
202
|
+
* mark the diff with `editSessionDirty`. Called at session end, this
|
|
203
|
+
* recomputes the hunks in full from the diff's current lines — the same
|
|
204
|
+
* hunks a non-session edit would have produced — and clears the flag.
|
|
205
|
+
* Returns true when a recompute ran.
|
|
204
206
|
*/
|
|
205
207
|
function finishEditSessionForDiff(diff, parseDiffOptions) {
|
|
206
208
|
if (diff.editSessionDirty !== true) return false;
|
|
207
|
-
diff.editSessionDirty
|
|
209
|
+
delete diff.editSessionDirty;
|
|
208
210
|
Object.assign(diff, diff.additionLines.length <= 1 && diff.additionLines.join("") === "" ? recomputeDiffHunks(diff, parseDiffOptions) : recomputeDiffHunksForEdit(diff, parseDiffOptions));
|
|
209
211
|
return true;
|
|
210
212
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editSessionHunks.js","names":[],"sources":["../../src/utils/editSessionHunks.ts"],"sourcesContent":["import type { CreatePatchOptionsNonabortable } from 'diff';\n\nimport type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n HunkExpansionRegion,\n} from '../types';\nimport { getHunkSideStartBoundary } from './getHunkSideBoundaries';\nimport { parseDiffFromFile } from './parseDiffFromFile';\nimport {\n offsetHunkContent,\n preserveTrailingEditorBlankLine,\n recomputeDiffHunks,\n recomputeDiffHunksForEdit,\n recomputeDiffRenderLineCounts,\n recomputeHunkRenderLineCounts,\n syncHunkNoEOFCRFromFullFile,\n} from './updateDiffHunks';\nimport {\n getExpandedRegion,\n getTrailingExpandedRegion,\n} from './virtualDiffLayout';\n\n// While an editor is attached to a FileDiff, each hunk is a persistent region\n// identified by its old-side range. Structural passes rebuild those regions\n// from one canonical old/current diff; a reverted region remains as context so\n// its rows keep rendering until the genuine session-exit recompute.\n\nexport interface DivergenceCore {\n start: number;\n deletionEnd: number;\n additionEnd: number;\n}\n\ninterface PreviousRegionSpan {\n firstIndex: number;\n lastIndex: number;\n}\n\n/** Maps rebuilt regions back to the previous skeleton for expansion remapping. */\nexport interface SessionRegionChange {\n regions: Array<PreviousRegionSpan | undefined>;\n}\n\ninterface RegionBounds {\n additionStart: number;\n additionEnd: number;\n deletionStart: number;\n deletionEnd: number;\n}\n\ninterface RegionPlan {\n deletionStart: number;\n deletionEnd: number;\n blocks: ChangeContent[];\n previousSpan: PreviousRegionSpan | undefined;\n}\n\nconst deletionLineSetCache = new WeakMap<\n FileDiffMetadata,\n { lines: string[]; set: Set<string> }\n>();\n\n/**\n * Drops the editor document's phantom trailing empty line (a document ending\n * in a newline exposes one extra empty line the parsed diff never contains)\n * so session line arrays compare like parse-derived ones.\n */\nexport function normalizeEditorLines(lines: string[]): string[] {\n if (lines.length > 1 && lines[lines.length - 1] === '') {\n return lines.slice(0, -1);\n }\n return lines;\n}\n\n/**\n * Find the complete old/current divergence core. The old side is immutable\n * during an edit session, so this result needs no prior-pass snapshot.\n */\nexport function findDivergenceCore(\n deletionLines: string[],\n additionLines: string[]\n): DivergenceCore | undefined {\n const maxStart = Math.min(deletionLines.length, additionLines.length);\n let start = 0;\n while (start < maxStart && deletionLines[start] === additionLines[start]) {\n start++;\n }\n let deletionEnd = deletionLines.length;\n let additionEnd = additionLines.length;\n while (\n deletionEnd > start &&\n additionEnd > start &&\n deletionLines[deletionEnd - 1] === additionLines[additionEnd - 1]\n ) {\n deletionEnd--;\n additionEnd--;\n }\n if (start === deletionEnd && start === additionEnd) {\n return undefined;\n }\n return { start, deletionEnd, additionEnd };\n}\n\n/**\n * Rebuild the session skeleton as a pure function of the immutable old lines,\n * current new lines, and old-side ranges of the previous regions. One\n * canonical parse supplies the same change blocks that session exit will use.\n */\nexport function rebuildSessionHunks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): SessionRegionChange | undefined {\n const previousHunks = diff.hunks;\n const editorAdditionLines = diff.additionLines;\n const canonicalAdditionLines = normalizeEditorLines(editorAdditionLines);\n const canonicalDiff =\n canonicalAdditionLines === editorAdditionLines\n ? diff\n : { ...diff, additionLines: canonicalAdditionLines };\n const blocks = parseCanonicalChangeBlocks(canonicalDiff, parseDiffOptions);\n const plans = buildRegionPlans(\n previousHunks,\n blocks,\n diff.deletionLines.length\n );\n\n const nextHunks = buildRegionHunks(canonicalDiff, plans);\n diff.additionLines = canonicalAdditionLines;\n diff.hunks = nextHunks;\n diff.editSessionDirty = true;\n finalizeSessionHunks(diff);\n preserveTrailingEditorBlankLine(diff, editorAdditionLines);\n const layoutChanged = hasRegionOrSplitLayoutChanged(\n previousHunks,\n diff.hunks\n );\n if (!layoutChanged) {\n return undefined;\n }\n return { regions: plans.map((plan) => plan.previousSpan) };\n}\n\n/**\n * Keep a cheap content-only path when a same-line-count pass cannot alter the\n * canonical blocks. Gap, ambiguous, or multi-region edits rebuild statelessly.\n */\nexport function applySessionChangedLines(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>,\n parseDiffOptions?: CreatePatchOptionsNonabortable,\n previousAdditionLines?: ReadonlyMap<number, string>\n): SessionRegionChange | undefined {\n const lines = Array.from(new Set(changedAdditionLineIndexes))\n .filter((line) => line >= 0 && line < diff.additionLines.length)\n .sort((a, b) => a - b);\n if (lines.length === 0) {\n return undefined;\n }\n\n const { hunks } = diff;\n let regionIndex: number | undefined;\n let hunkIndex = 0;\n for (const line of lines) {\n while (hunkIndex < hunks.length) {\n const hunk = hunks[hunkIndex];\n const start = getHunkAdditionStart(hunk);\n if (line < start + hunk.additionCount) break;\n hunkIndex++;\n }\n const hunk = hunks[hunkIndex];\n const start = hunk == null ? undefined : getHunkAdditionStart(hunk);\n if (\n start == null ||\n line < start ||\n (regionIndex != null && regionIndex !== hunkIndex)\n ) {\n return rebuildSessionHunks(diff, parseDiffOptions);\n }\n regionIndex = hunkIndex;\n }\n\n if (regionIndex == null) {\n return undefined;\n }\n if (\n canRetainCanonicalBlocks(\n diff,\n lines,\n regionIndex,\n previousAdditionLines,\n parseDiffOptions\n )\n ) {\n diff.editSessionDirty = true;\n return undefined;\n }\n return rebuildSessionHunks(diff, parseDiffOptions);\n}\n\n// Existing balanced change blocks remain canonical when every edited line was\n// unmatched before and stays unmatched now: the old/new equality matrix is\n// unchanged, and similarity realignment never reorders a balanced block.\nfunction canRetainCanonicalBlocks(\n diff: FileDiffMetadata,\n changedLines: number[],\n regionIndex: number,\n previousAdditionLines: ReadonlyMap<number, string> | undefined,\n parseDiffOptions: CreatePatchOptionsNonabortable | undefined\n): boolean {\n if (\n previousAdditionLines == null ||\n parseDiffOptions?.ignoreWhitespace === true ||\n parseDiffOptions?.stripTrailingCr === true\n ) {\n return false;\n }\n const deletionLineSet = getDeletionLineSet(diff);\n const hunk = diff.hunks[regionIndex];\n if (hunk.hunkContent.some(isPureChange)) {\n return false;\n }\n for (const line of changedLines) {\n const previousLine = previousAdditionLines.get(line);\n const additionLine = diff.additionLines[line];\n if (\n previousLine == null ||\n additionLine == null ||\n deletionLineSet.has(previousLine) ||\n deletionLineSet.has(additionLine)\n ) {\n return false;\n }\n let insideBalancedChange = false;\n for (const content of hunk.hunkContent) {\n if (\n content.type === 'change' &&\n content.additions === content.deletions &&\n line >= content.additionLineIndex &&\n line < content.additionLineIndex + content.additions\n ) {\n insideBalancedChange = true;\n break;\n }\n }\n if (!insideBalancedChange) {\n return false;\n }\n }\n return true;\n}\n\nfunction getDeletionLineSet(diff: FileDiffMetadata): Set<string> {\n const cached = deletionLineSetCache.get(diff);\n if (cached?.lines === diff.deletionLines) {\n return cached.set;\n }\n const set = new Set(diff.deletionLines);\n deletionLineSetCache.set(diff, { lines: diff.deletionLines, set });\n return set;\n}\n\nfunction isPureChange(\n content: ContextContent | ChangeContent | undefined\n): boolean {\n return (\n content?.type === 'change' &&\n (content.additions === 0 || content.deletions === 0)\n );\n}\n\n/** Preserve expansion at the surviving outer edges of rebuilt old-side gaps. */\nexport function remapExpandedHunksForRegionChange(\n expandedHunks: Map<number, HunkExpansionRegion>,\n change: SessionRegionChange\n): Map<number, HunkExpansionRegion> {\n const remapped = new Map<number, HunkExpansionRegion>();\n const { regions } = change;\n for (let key = 0; key <= regions.length; key++) {\n const previous = regions[key - 1];\n const next = regions[key];\n const fromStartSource =\n key === 0\n ? expandedHunks.get(0)\n : previous == null\n ? undefined\n : expandedHunks.get(previous.lastIndex + 1);\n const fromEndSource =\n next == null ? undefined : expandedHunks.get(next.firstIndex);\n const fromStart = fromStartSource?.fromStart ?? 0;\n const fromEnd = fromEndSource?.fromEnd ?? 0;\n if (fromStart > 0 || fromEnd > 0) {\n remapped.set(key, { fromStart, fromEnd });\n }\n }\n return remapped;\n}\n\n/**\n * An expanded gap-edge slice in old-side (deletion-line) coordinates as a\n * `[start, end)` range. Old-side coordinates survive the exit recompute\n * unchanged — edits only touch the new side — so these anchor best-effort\n * expansion preservation across the recompute.\n */\nexport type ExpansionAnchorRange = [start: number, end: number];\n\n/** Snapshot the expanded gap-edge slices before the exit recompute. */\nexport function captureExpansionAnchors(\n diff: FileDiffMetadata,\n expandedHunks: Map<number, HunkExpansionRegion>,\n collapsedContextThreshold: number\n): ExpansionAnchorRange[] {\n const anchors: ExpansionAnchorRange[] = [];\n if (diff.isPartial) {\n return anchors;\n }\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const region = getExpandedRegion({\n isPartial: diff.isPartial,\n rangeSize: hunk.collapsedBefore,\n expandedHunks,\n hunkIndex,\n collapsedContextThreshold,\n });\n // Gaps at or below the threshold render on their own; only explicit\n // expansion state needs preserving.\n if (region.rangeSize <= collapsedContextThreshold) {\n continue;\n }\n const gapEnd = getHunkDeletionStart(hunk);\n const gapStart = gapEnd - region.rangeSize;\n if (region.fromStart > 0) {\n anchors.push([gapStart, gapStart + region.fromStart]);\n }\n if (region.fromEnd > 0) {\n anchors.push([gapEnd - region.fromEnd, gapEnd]);\n }\n }\n const trailingRegion = getTrailingExpandedRegion({\n fileDiff: diff,\n hunkIndex: diff.hunks.length - 1,\n expandedHunks,\n collapsedContextThreshold,\n errorPrefix: 'captureExpansionAnchors',\n });\n if (\n trailingRegion != null &&\n trailingRegion.fromStart > 0 &&\n trailingRegion.rangeSize > collapsedContextThreshold\n ) {\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n const gapStart = getHunkDeletionStart(lastHunk) + lastHunk.deletionCount;\n anchors.push([gapStart, gapStart + trailingRegion.fromStart]);\n }\n return anchors;\n}\n\n/**\n * Rebuild gap expansion state against the recomputed hunks: for each new\n * gap, an anchor touching the gap's start edge restores `fromStart`, one\n * touching its end edge restores `fromEnd`, and anchors for gaps that no\n * longer exist drop.\n */\nexport function rebuildExpansionFromAnchors(\n diff: FileDiffMetadata,\n anchors: ExpansionAnchorRange[]\n): Map<number, HunkExpansionRegion> {\n const rebuilt = new Map<number, HunkExpansionRegion>();\n if (anchors.length === 0) {\n return rebuilt;\n }\n const applyGap = (key: number, gapStart: number, gapEnd: number) => {\n if (gapEnd <= gapStart) {\n return;\n }\n let fromStart = 0;\n let fromEnd = 0;\n for (const [start, end] of anchors) {\n if (end <= gapStart || start >= gapEnd) {\n continue;\n }\n if (start <= gapStart) {\n fromStart = Math.max(fromStart, Math.min(end, gapEnd) - gapStart);\n }\n if (end >= gapEnd) {\n fromEnd = Math.max(fromEnd, gapEnd - Math.max(start, gapStart));\n }\n }\n if (fromStart > 0 || fromEnd > 0) {\n rebuilt.set(key, { fromStart, fromEnd });\n }\n };\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const gapEnd = getHunkDeletionStart(hunk);\n applyGap(hunkIndex, gapEnd - Math.max(hunk.collapsedBefore, 0), gapEnd);\n }\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n if (lastHunk != null && !diff.isPartial && diff.deletionLines.length > 0) {\n applyGap(\n diff.hunks.length,\n getHunkDeletionStart(lastHunk) + lastHunk.deletionCount,\n diff.deletionLines.length\n );\n }\n return rebuilt;\n}\n\n/**\n * Genuine session exit: when session passes reshaped the hunks, run the real\n * full recompute so exit state matches a non-session edit pipeline, and clear\n * the marker. Returns true when a recompute ran.\n */\nexport function finishEditSessionForDiff(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): boolean {\n if (diff.editSessionDirty !== true) {\n return false;\n }\n diff.editSessionDirty = undefined;\n // The empty editor row only hosts a caret; it is not file content after exit.\n Object.assign(\n diff,\n diff.additionLines.length <= 1 && diff.additionLines.join('') === ''\n ? recomputeDiffHunks(diff, parseDiffOptions)\n : recomputeDiffHunksForEdit(diff, parseDiffOptions)\n );\n return true;\n}\n\n// Parse the complete old/current files once with the same context policy as\n// session exit. Equal boundary lines affect Myers tie-breaking, while parsed\n// context is required for the blank-run alignment post-pass; only canonical\n// change blocks are retained. Running cursors normalize unified N,0 indexes.\nfunction parseCanonicalChangeBlocks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): ChangeContent[] {\n if (findDivergenceCore(diff.deletionLines, diff.additionLines) == null) {\n return [];\n }\n const parsed = 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\n const blocks: ChangeContent[] = [];\n let coveredAdditions = 0;\n let coveredDeletions = 0;\n for (const hunk of parsed.hunks) {\n const contextLines =\n hunk.additionCount > 0\n ? hunk.additionLineIndex - coveredAdditions\n : hunk.deletionLineIndex - coveredDeletions;\n coveredAdditions += contextLines;\n coveredDeletions += contextLines;\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n coveredAdditions += content.lines;\n coveredDeletions += content.lines;\n continue;\n }\n const block = offsetHunkContent(content, 0, 0) as ChangeContent;\n if (block.additions === 0) {\n block.additionLineIndex = coveredAdditions;\n }\n if (block.deletions === 0) {\n block.deletionLineIndex = coveredDeletions;\n }\n blocks.push(block);\n coveredAdditions += block.additions;\n coveredDeletions += block.deletions;\n }\n }\n return blocks;\n}\n\n// Co-walk canonical blocks and previous old-side regions. A block touching a\n// region grows it; touching several merges them; a block wholly in a gap gets\n// its own region. Pure insertions/deletions absorb one adjacent context line\n// when available so the region stays renderable on both sides and after undo.\nfunction buildRegionPlans(\n previousHunks: Hunk[],\n blocks: ChangeContent[],\n deletionLineCount: number\n): RegionPlan[] {\n const previousPlans = previousHunks.map((hunk, index): RegionPlan => {\n const deletionStart = getHunkDeletionStart(hunk);\n return {\n deletionStart,\n deletionEnd: deletionStart + hunk.deletionCount,\n blocks: [],\n previousSpan: { firstIndex: index, lastIndex: index },\n };\n });\n const plans: RegionPlan[] = [];\n let previousIndex = 0;\n\n for (const block of blocks) {\n const blockStart = block.deletionLineIndex;\n const blockEnd = blockStart + block.deletions;\n while (\n previousIndex < previousPlans.length &&\n previousPlans[previousIndex].deletionEnd < blockStart\n ) {\n plans.push(previousPlans[previousIndex]);\n previousIndex++;\n }\n\n let plan =\n plans.length > 0 &&\n blockTouchesRegion(blockStart, blockEnd, plans[plans.length - 1])\n ? plans.pop()\n : undefined;\n while (\n previousIndex < previousPlans.length &&\n previousPlans[previousIndex].deletionStart <= blockEnd\n ) {\n plan = mergeRegionPlans(plan, previousPlans[previousIndex]);\n previousIndex++;\n }\n\n if (plan == null) {\n let deletionStart = blockStart;\n let deletionEnd = blockEnd;\n if (\n (block.deletions === 0 || block.additions === 0) &&\n deletionLineCount > block.deletions\n ) {\n const previousEnd = plans[plans.length - 1]?.deletionEnd ?? 0;\n const nextStart =\n previousPlans[previousIndex]?.deletionStart ?? deletionLineCount;\n if (blockStart > previousEnd) {\n deletionStart--;\n } else if (blockEnd < nextStart) {\n deletionEnd++;\n }\n }\n plan = {\n deletionStart,\n deletionEnd,\n blocks: [],\n previousSpan: undefined,\n };\n }\n plan.deletionStart = Math.min(plan.deletionStart, blockStart);\n plan.deletionEnd = Math.max(plan.deletionEnd, blockEnd);\n plan.blocks.push(block);\n plans.push(plan);\n }\n\n while (previousIndex < previousPlans.length) {\n plans.push(previousPlans[previousIndex]);\n previousIndex++;\n }\n return plans;\n}\n\nfunction blockTouchesRegion(\n blockStart: number,\n blockEnd: number,\n region: RegionPlan\n): boolean {\n return blockStart <= region.deletionEnd && blockEnd >= region.deletionStart;\n}\n\nfunction mergeRegionPlans(\n target: RegionPlan | undefined,\n source: RegionPlan\n): RegionPlan {\n if (target == null) {\n return source;\n }\n target.deletionStart = Math.min(target.deletionStart, source.deletionStart);\n target.deletionEnd = Math.max(target.deletionEnd, source.deletionEnd);\n target.blocks.push(...source.blocks);\n if (source.previousSpan != null) {\n target.previousSpan ??= { ...source.previousSpan };\n target.previousSpan.firstIndex = Math.min(\n target.previousSpan.firstIndex,\n source.previousSpan.firstIndex\n );\n target.previousSpan.lastIndex = Math.max(\n target.previousSpan.lastIndex,\n source.previousSpan.lastIndex\n );\n }\n return target;\n}\n\n// One paired-context walk constructs every region's new-side range. There is\n// no downstream coordinate shifting: each boundary is derived from the\n// canonical blocks that precede it.\nfunction buildRegionHunks(diff: FileDiffMetadata, plans: RegionPlan[]): Hunk[] {\n const hunks: Hunk[] = [];\n let deletionCursor = 0;\n let additionCursor = 0;\n for (const plan of plans) {\n const contextBefore = plan.deletionStart - deletionCursor;\n if (contextBefore < 0) {\n throw new Error('buildRegionHunks: overlapping old-side regions');\n }\n deletionCursor += contextBefore;\n additionCursor += contextBefore;\n const additionStart = additionCursor;\n const hunkContent: Array<ContextContent | ChangeContent> = [];\n\n for (const canonicalBlock of plan.blocks) {\n const deletionContext = canonicalBlock.deletionLineIndex - deletionCursor;\n const additionContext = canonicalBlock.additionLineIndex - additionCursor;\n if (deletionContext < 0 || deletionContext !== additionContext) {\n throw new Error('buildRegionHunks: canonical block context mismatch');\n }\n pushContext(hunkContent, deletionContext, additionCursor, deletionCursor);\n deletionCursor += deletionContext;\n additionCursor += additionContext;\n hunkContent.push({ ...canonicalBlock });\n deletionCursor += canonicalBlock.deletions;\n additionCursor += canonicalBlock.additions;\n }\n\n const trailingContext = plan.deletionEnd - deletionCursor;\n if (trailingContext < 0) {\n throw new Error('buildRegionHunks: block exceeds its old-side region');\n }\n pushContext(hunkContent, trailingContext, additionCursor, deletionCursor);\n deletionCursor += trailingContext;\n additionCursor += trailingContext;\n hunks.push(\n createRegionHunk(\n diff,\n {\n additionStart,\n additionEnd: additionCursor,\n deletionStart: plan.deletionStart,\n deletionEnd: plan.deletionEnd,\n },\n hunkContent\n )\n );\n }\n\n if (\n diff.deletionLines.length - deletionCursor !==\n diff.additionLines.length - additionCursor\n ) {\n throw new Error('buildRegionHunks: trailing context mismatch');\n }\n return hunks;\n}\n\nfunction createRegionHunk(\n diff: FileDiffMetadata,\n bounds: RegionBounds,\n hunkContent: Array<ContextContent | ChangeContent>\n): Hunk {\n const additionCount = bounds.additionEnd - bounds.additionStart;\n const deletionCount = bounds.deletionEnd - bounds.deletionStart;\n let additionLines = 0;\n let deletionLines = 0;\n for (const content of hunkContent) {\n if (content.type === 'change') {\n additionLines += content.additions;\n deletionLines += content.deletions;\n }\n }\n const hunk: Hunk = {\n collapsedBefore: 0,\n additionStart: getUnifiedStart(bounds.additionStart, additionCount),\n additionCount,\n additionLines,\n additionLineIndex: getUnifiedLineIndex(bounds.additionStart, additionCount),\n deletionStart: getUnifiedStart(bounds.deletionStart, deletionCount),\n deletionCount,\n deletionLines,\n deletionLineIndex: getUnifiedLineIndex(bounds.deletionStart, deletionCount),\n hunkContent,\n hunkSpecs: `@@ -${getUnifiedStart(bounds.deletionStart, deletionCount)},${deletionCount} +${getUnifiedStart(bounds.additionStart, additionCount)},${additionCount} @@`,\n splitLineStart: 0,\n splitLineCount: 0,\n unifiedLineStart: 0,\n unifiedLineCount: 0,\n noEOFCRAdditions: false,\n noEOFCRDeletions: false,\n };\n recomputeHunkRenderLineCounts(hunk);\n return hunk;\n}\n\nfunction pushContext(\n hunkContent: Array<ContextContent | ChangeContent>,\n lines: number,\n additionLineIndex: number,\n deletionLineIndex: number\n): void {\n if (lines > 0) {\n hunkContent.push({\n type: 'context',\n lines,\n additionLineIndex,\n deletionLineIndex,\n });\n }\n}\n\nfunction hasRegionOrSplitLayoutChanged(\n previous: Hunk[],\n next: Hunk[]\n): boolean {\n if (previous.length !== next.length) {\n return true;\n }\n for (let index = 0; index < previous.length; index++) {\n const previousHunk = previous[index];\n const nextHunk = next[index];\n if (\n getHunkDeletionStart(previousHunk) !== getHunkDeletionStart(nextHunk) ||\n previousHunk.deletionCount !== nextHunk.deletionCount ||\n getHunkAdditionStart(previousHunk) !== getHunkAdditionStart(nextHunk) ||\n previousHunk.additionCount !== nextHunk.additionCount ||\n previousHunk.splitLineCount !== nextHunk.splitLineCount ||\n !haveSameSplitRowMapping(previousHunk, nextHunk)\n ) {\n return true;\n }\n }\n return false;\n}\n\nfunction haveSameSplitRowMapping(previous: Hunk, next: Hunk): boolean {\n const previousRows = iterateSplitRowMapping(previous);\n const nextRows = iterateSplitRowMapping(next);\n while (true) {\n const previousRow = previousRows.next();\n const nextRow = nextRows.next();\n if (previousRow.done === true || nextRow.done === true) {\n return previousRow.done === nextRow.done;\n }\n if (\n previousRow.value[0] !== nextRow.value[0] ||\n previousRow.value[1] !== nextRow.value[1]\n ) {\n return false;\n }\n }\n}\n\nfunction* iterateSplitRowMapping(\n hunk: Hunk\n): Generator<\n [deletionLine: number | undefined, additionLine: number | undefined]\n> {\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n for (let offset = 0; offset < content.lines; offset++) {\n yield [\n content.deletionLineIndex + offset,\n content.additionLineIndex + offset,\n ];\n }\n continue;\n }\n const rowCount = Math.max(content.deletions, content.additions);\n for (let offset = 0; offset < rowCount; offset++) {\n yield [\n offset < content.deletions\n ? content.deletionLineIndex + offset\n : undefined,\n offset < content.additions\n ? content.additionLineIndex + offset\n : undefined,\n ];\n }\n }\n}\n\nfunction getHunkAdditionStart(hunk: Hunk): number {\n return getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount);\n}\n\nfunction getHunkDeletionStart(hunk: Hunk): number {\n return getHunkSideStartBoundary(hunk.deletionStart, hunk.deletionCount);\n}\n\nfunction getUnifiedStart(lineIndex: number, count: number): number {\n return count === 0 ? lineIndex : lineIndex + 1;\n}\n\nfunction getUnifiedLineIndex(lineIndex: number, count: number): number {\n return count === 0 ? lineIndex - 1 : lineIndex;\n}\n\nfunction finalizeSessionHunks(diff: FileDiffMetadata): void {\n recomputeDiffRenderLineCounts(diff);\n for (let index = 0; index < diff.hunks.length; index++) {\n syncHunkNoEOFCRFromFullFile(diff, index);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"editSessionHunks.js","names":[],"sources":["../../src/utils/editSessionHunks.ts"],"sourcesContent":["import type { CreatePatchOptionsNonabortable } from 'diff';\n\nimport type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n HunkExpansionRegion,\n} from '../types';\nimport { getHunkSideStartBoundary } from './getHunkSideBoundaries';\nimport { parseDiffFromFile } from './parseDiffFromFile';\nimport {\n offsetHunkContent,\n preserveTrailingEditorBlankLine,\n recomputeDiffHunks,\n recomputeDiffHunksForEdit,\n recomputeDiffRenderLineCounts,\n recomputeHunkRenderLineCounts,\n syncHunkNoEOFCRFromFullFile,\n} from './updateDiffHunks';\nimport {\n getExpandedRegion,\n getTrailingExpandedRegion,\n} from './virtualDiffLayout';\n\n// While an editor is attached to a FileDiff, each hunk is a persistent region\n// identified by its old-side range. Structural passes rebuild those regions\n// from one canonical old/current diff; a reverted region remains as context so\n// its rows keep rendering until the session-exit recompute.\n\nexport interface DivergenceCore {\n start: number;\n deletionEnd: number;\n additionEnd: number;\n}\n\ninterface PreviousRegionSpan {\n firstIndex: number;\n lastIndex: number;\n}\n\n/** Maps rebuilt regions back to the previous skeleton for expansion remapping. */\nexport interface SessionRegionChange {\n regions: Array<PreviousRegionSpan | undefined>;\n}\n\ninterface RegionBounds {\n additionStart: number;\n additionEnd: number;\n deletionStart: number;\n deletionEnd: number;\n}\n\ninterface RegionPlan {\n deletionStart: number;\n deletionEnd: number;\n blocks: ChangeContent[];\n previousSpan: PreviousRegionSpan | undefined;\n}\n\nconst deletionLineSetCache = new WeakMap<\n FileDiffMetadata,\n { lines: string[]; set: Set<string> }\n>();\n\n/**\n * Drops the editor document's phantom trailing empty line (a document ending\n * in a newline exposes one extra empty line the parsed diff never contains)\n * so session line arrays compare like parse-derived ones.\n */\nexport function normalizeEditorLines(lines: string[]): string[] {\n if (lines.length > 1 && lines[lines.length - 1] === '') {\n return lines.slice(0, -1);\n }\n return lines;\n}\n\n/**\n * Find the complete old/current divergence core. The old side is immutable\n * during an edit session, so this result needs no prior-pass snapshot.\n */\nexport function findDivergenceCore(\n deletionLines: string[],\n additionLines: string[]\n): DivergenceCore | undefined {\n const maxStart = Math.min(deletionLines.length, additionLines.length);\n let start = 0;\n while (start < maxStart && deletionLines[start] === additionLines[start]) {\n start++;\n }\n let deletionEnd = deletionLines.length;\n let additionEnd = additionLines.length;\n while (\n deletionEnd > start &&\n additionEnd > start &&\n deletionLines[deletionEnd - 1] === additionLines[additionEnd - 1]\n ) {\n deletionEnd--;\n additionEnd--;\n }\n if (start === deletionEnd && start === additionEnd) {\n return undefined;\n }\n return { start, deletionEnd, additionEnd };\n}\n\n/**\n * Rebuild the session skeleton as a pure function of the immutable old lines,\n * current new lines, and old-side ranges of the previous regions. One\n * canonical parse supplies the same change blocks that session exit will use.\n */\nexport function rebuildSessionHunks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): SessionRegionChange | undefined {\n const previousHunks = diff.hunks;\n const editorAdditionLines = diff.additionLines;\n const canonicalAdditionLines = normalizeEditorLines(editorAdditionLines);\n const canonicalDiff =\n canonicalAdditionLines === editorAdditionLines\n ? diff\n : { ...diff, additionLines: canonicalAdditionLines };\n const blocks = parseCanonicalChangeBlocks(canonicalDiff, parseDiffOptions);\n const plans = buildRegionPlans(\n previousHunks,\n blocks,\n diff.deletionLines.length\n );\n\n const nextHunks = buildRegionHunks(canonicalDiff, plans);\n diff.additionLines = canonicalAdditionLines;\n diff.hunks = nextHunks;\n diff.editSessionDirty = true;\n finalizeSessionHunks(diff);\n preserveTrailingEditorBlankLine(diff, editorAdditionLines);\n const layoutChanged = hasRegionOrSplitLayoutChanged(\n previousHunks,\n diff.hunks\n );\n if (!layoutChanged) {\n return undefined;\n }\n return { regions: plans.map((plan) => plan.previousSpan) };\n}\n\n/**\n * Keep a cheap content-only path when a same-line-count pass cannot alter the\n * canonical blocks. Gap, ambiguous, or multi-region edits rebuild statelessly.\n */\nexport function applySessionChangedLines(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>,\n parseDiffOptions?: CreatePatchOptionsNonabortable,\n previousAdditionLines?: ReadonlyMap<number, string>\n): SessionRegionChange | undefined {\n const lines = Array.from(new Set(changedAdditionLineIndexes))\n .filter((line) => line >= 0 && line < diff.additionLines.length)\n .sort((a, b) => a - b);\n if (lines.length === 0) {\n return undefined;\n }\n\n const { hunks } = diff;\n let regionIndex: number | undefined;\n let hunkIndex = 0;\n for (const line of lines) {\n while (hunkIndex < hunks.length) {\n const hunk = hunks[hunkIndex];\n const start = getHunkAdditionStart(hunk);\n if (line < start + hunk.additionCount) break;\n hunkIndex++;\n }\n const hunk = hunks[hunkIndex];\n const start = hunk == null ? undefined : getHunkAdditionStart(hunk);\n if (\n start == null ||\n line < start ||\n (regionIndex != null && regionIndex !== hunkIndex)\n ) {\n return rebuildSessionHunks(diff, parseDiffOptions);\n }\n regionIndex = hunkIndex;\n }\n\n if (regionIndex == null) {\n return undefined;\n }\n if (\n canRetainCanonicalBlocks(\n diff,\n lines,\n regionIndex,\n previousAdditionLines,\n parseDiffOptions\n )\n ) {\n diff.editSessionDirty = true;\n return undefined;\n }\n return rebuildSessionHunks(diff, parseDiffOptions);\n}\n\n// Existing balanced change blocks remain canonical when every edited line was\n// unmatched before and stays unmatched now: the old/new equality matrix is\n// unchanged, and similarity realignment never reorders a balanced block.\nfunction canRetainCanonicalBlocks(\n diff: FileDiffMetadata,\n changedLines: number[],\n regionIndex: number,\n previousAdditionLines: ReadonlyMap<number, string> | undefined,\n parseDiffOptions: CreatePatchOptionsNonabortable | undefined\n): boolean {\n if (\n previousAdditionLines == null ||\n parseDiffOptions?.ignoreWhitespace === true ||\n parseDiffOptions?.stripTrailingCr === true\n ) {\n return false;\n }\n const deletionLineSet = getDeletionLineSet(diff);\n const hunk = diff.hunks[regionIndex];\n if (hunk.hunkContent.some(isPureChange)) {\n return false;\n }\n for (const line of changedLines) {\n const previousLine = previousAdditionLines.get(line);\n const additionLine = diff.additionLines[line];\n if (\n previousLine == null ||\n additionLine == null ||\n deletionLineSet.has(previousLine) ||\n deletionLineSet.has(additionLine)\n ) {\n return false;\n }\n let insideBalancedChange = false;\n for (const content of hunk.hunkContent) {\n if (\n content.type === 'change' &&\n content.additions === content.deletions &&\n line >= content.additionLineIndex &&\n line < content.additionLineIndex + content.additions\n ) {\n insideBalancedChange = true;\n break;\n }\n }\n if (!insideBalancedChange) {\n return false;\n }\n }\n return true;\n}\n\nfunction getDeletionLineSet(diff: FileDiffMetadata): Set<string> {\n const cached = deletionLineSetCache.get(diff);\n if (cached?.lines === diff.deletionLines) {\n return cached.set;\n }\n const set = new Set(diff.deletionLines);\n deletionLineSetCache.set(diff, { lines: diff.deletionLines, set });\n return set;\n}\n\nfunction isPureChange(\n content: ContextContent | ChangeContent | undefined\n): boolean {\n return (\n content?.type === 'change' &&\n (content.additions === 0 || content.deletions === 0)\n );\n}\n\n/** Preserve expansion at the surviving outer edges of rebuilt old-side gaps. */\nexport function remapExpandedHunksForRegionChange(\n expandedHunks: Map<number, HunkExpansionRegion>,\n change: SessionRegionChange\n): Map<number, HunkExpansionRegion> {\n const remapped = new Map<number, HunkExpansionRegion>();\n const { regions } = change;\n for (let key = 0; key <= regions.length; key++) {\n const previous = regions[key - 1];\n const next = regions[key];\n const fromStartSource =\n key === 0\n ? expandedHunks.get(0)\n : previous == null\n ? undefined\n : expandedHunks.get(previous.lastIndex + 1);\n const fromEndSource =\n next == null ? undefined : expandedHunks.get(next.firstIndex);\n const fromStart = fromStartSource?.fromStart ?? 0;\n const fromEnd = fromEndSource?.fromEnd ?? 0;\n if (fromStart > 0 || fromEnd > 0) {\n remapped.set(key, { fromStart, fromEnd });\n }\n }\n return remapped;\n}\n\n/**\n * An expanded gap-edge slice in old-side (deletion-line) coordinates as a\n * `[start, end)` range. Old-side coordinates survive the exit recompute\n * unchanged — edits only touch the new side — so these anchor best-effort\n * expansion preservation across the recompute.\n */\nexport type ExpansionAnchorRange = [start: number, end: number];\n\n/** Snapshot the expanded gap-edge slices before the exit recompute. */\nexport function captureExpansionAnchors(\n diff: FileDiffMetadata,\n expandedHunks: Map<number, HunkExpansionRegion>,\n collapsedContextThreshold: number\n): ExpansionAnchorRange[] {\n const anchors: ExpansionAnchorRange[] = [];\n if (diff.isPartial) {\n return anchors;\n }\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const region = getExpandedRegion({\n isPartial: diff.isPartial,\n rangeSize: hunk.collapsedBefore,\n expandedHunks,\n hunkIndex,\n collapsedContextThreshold,\n });\n // Gaps at or below the threshold render on their own; only explicit\n // expansion state needs preserving.\n if (region.rangeSize <= collapsedContextThreshold) {\n continue;\n }\n const gapEnd = getHunkDeletionStart(hunk);\n const gapStart = gapEnd - region.rangeSize;\n if (region.fromStart > 0) {\n anchors.push([gapStart, gapStart + region.fromStart]);\n }\n if (region.fromEnd > 0) {\n anchors.push([gapEnd - region.fromEnd, gapEnd]);\n }\n }\n const trailingRegion = getTrailingExpandedRegion({\n fileDiff: diff,\n hunkIndex: diff.hunks.length - 1,\n expandedHunks,\n collapsedContextThreshold,\n errorPrefix: 'captureExpansionAnchors',\n });\n if (\n trailingRegion != null &&\n trailingRegion.fromStart > 0 &&\n trailingRegion.rangeSize > collapsedContextThreshold\n ) {\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n const gapStart = getHunkDeletionStart(lastHunk) + lastHunk.deletionCount;\n anchors.push([gapStart, gapStart + trailingRegion.fromStart]);\n }\n return anchors;\n}\n\n/**\n * Rebuild gap expansion state against the recomputed hunks: for each new\n * gap, an anchor touching the gap's start edge restores `fromStart`, one\n * touching its end edge restores `fromEnd`, and anchors for gaps that no\n * longer exist drop.\n */\nexport function rebuildExpansionFromAnchors(\n diff: FileDiffMetadata,\n anchors: ExpansionAnchorRange[]\n): Map<number, HunkExpansionRegion> {\n const rebuilt = new Map<number, HunkExpansionRegion>();\n if (anchors.length === 0) {\n return rebuilt;\n }\n const applyGap = (key: number, gapStart: number, gapEnd: number) => {\n if (gapEnd <= gapStart) {\n return;\n }\n let fromStart = 0;\n let fromEnd = 0;\n for (const [start, end] of anchors) {\n if (end <= gapStart || start >= gapEnd) {\n continue;\n }\n if (start <= gapStart) {\n fromStart = Math.max(fromStart, Math.min(end, gapEnd) - gapStart);\n }\n if (end >= gapEnd) {\n fromEnd = Math.max(fromEnd, gapEnd - Math.max(start, gapStart));\n }\n }\n if (fromStart > 0 || fromEnd > 0) {\n rebuilt.set(key, { fromStart, fromEnd });\n }\n };\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const gapEnd = getHunkDeletionStart(hunk);\n applyGap(hunkIndex, gapEnd - Math.max(hunk.collapsedBefore, 0), gapEnd);\n }\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n if (lastHunk != null && !diff.isPartial && diff.deletionLines.length > 0) {\n applyGap(\n diff.hunks.length,\n getHunkDeletionStart(lastHunk) + lastHunk.deletionCount,\n diff.deletionLines.length\n );\n }\n return rebuilt;\n}\n\n/**\n * While editing, hunk updates keep a lightweight session-specific shape and\n * mark the diff with `editSessionDirty`. Called at session end, this\n * recomputes the hunks in full from the diff's current lines — the same\n * hunks a non-session edit would have produced — and clears the flag.\n * Returns true when a recompute ran.\n */\nexport function finishEditSessionForDiff(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): boolean {\n if (diff.editSessionDirty !== true) {\n return false;\n }\n delete diff.editSessionDirty;\n // The empty editor row only hosts a caret; it is not file content after exit.\n Object.assign(\n diff,\n diff.additionLines.length <= 1 && diff.additionLines.join('') === ''\n ? recomputeDiffHunks(diff, parseDiffOptions)\n : recomputeDiffHunksForEdit(diff, parseDiffOptions)\n );\n return true;\n}\n\n// Parse the complete old/current files once with the same context policy as\n// session exit. Equal boundary lines affect Myers tie-breaking, while parsed\n// context is required for the blank-run alignment post-pass; only canonical\n// change blocks are retained. Running cursors normalize unified N,0 indexes.\nfunction parseCanonicalChangeBlocks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): ChangeContent[] {\n if (findDivergenceCore(diff.deletionLines, diff.additionLines) == null) {\n return [];\n }\n const parsed = 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\n const blocks: ChangeContent[] = [];\n let coveredAdditions = 0;\n let coveredDeletions = 0;\n for (const hunk of parsed.hunks) {\n const contextLines =\n hunk.additionCount > 0\n ? hunk.additionLineIndex - coveredAdditions\n : hunk.deletionLineIndex - coveredDeletions;\n coveredAdditions += contextLines;\n coveredDeletions += contextLines;\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n coveredAdditions += content.lines;\n coveredDeletions += content.lines;\n continue;\n }\n const block = offsetHunkContent(content, 0, 0) as ChangeContent;\n if (block.additions === 0) {\n block.additionLineIndex = coveredAdditions;\n }\n if (block.deletions === 0) {\n block.deletionLineIndex = coveredDeletions;\n }\n blocks.push(block);\n coveredAdditions += block.additions;\n coveredDeletions += block.deletions;\n }\n }\n return blocks;\n}\n\n// Co-walk canonical blocks and previous old-side regions. A block touching a\n// region grows it; touching several merges them; a block wholly in a gap gets\n// its own region. Pure insertions/deletions absorb one adjacent context line\n// when available so the region stays renderable on both sides and after undo.\nfunction buildRegionPlans(\n previousHunks: Hunk[],\n blocks: ChangeContent[],\n deletionLineCount: number\n): RegionPlan[] {\n const previousPlans = previousHunks.map((hunk, index): RegionPlan => {\n const deletionStart = getHunkDeletionStart(hunk);\n return {\n deletionStart,\n deletionEnd: deletionStart + hunk.deletionCount,\n blocks: [],\n previousSpan: { firstIndex: index, lastIndex: index },\n };\n });\n const plans: RegionPlan[] = [];\n let previousIndex = 0;\n\n for (const block of blocks) {\n const blockStart = block.deletionLineIndex;\n const blockEnd = blockStart + block.deletions;\n while (\n previousIndex < previousPlans.length &&\n previousPlans[previousIndex].deletionEnd < blockStart\n ) {\n plans.push(previousPlans[previousIndex]);\n previousIndex++;\n }\n\n let plan =\n plans.length > 0 &&\n blockTouchesRegion(blockStart, blockEnd, plans[plans.length - 1])\n ? plans.pop()\n : undefined;\n while (\n previousIndex < previousPlans.length &&\n previousPlans[previousIndex].deletionStart <= blockEnd\n ) {\n plan = mergeRegionPlans(plan, previousPlans[previousIndex]);\n previousIndex++;\n }\n\n if (plan == null) {\n let deletionStart = blockStart;\n let deletionEnd = blockEnd;\n if (\n (block.deletions === 0 || block.additions === 0) &&\n deletionLineCount > block.deletions\n ) {\n const previousEnd = plans[plans.length - 1]?.deletionEnd ?? 0;\n const nextStart =\n previousPlans[previousIndex]?.deletionStart ?? deletionLineCount;\n if (blockStart > previousEnd) {\n deletionStart--;\n } else if (blockEnd < nextStart) {\n deletionEnd++;\n }\n }\n plan = {\n deletionStart,\n deletionEnd,\n blocks: [],\n previousSpan: undefined,\n };\n }\n plan.deletionStart = Math.min(plan.deletionStart, blockStart);\n plan.deletionEnd = Math.max(plan.deletionEnd, blockEnd);\n plan.blocks.push(block);\n plans.push(plan);\n }\n\n while (previousIndex < previousPlans.length) {\n plans.push(previousPlans[previousIndex]);\n previousIndex++;\n }\n return plans;\n}\n\nfunction blockTouchesRegion(\n blockStart: number,\n blockEnd: number,\n region: RegionPlan\n): boolean {\n return blockStart <= region.deletionEnd && blockEnd >= region.deletionStart;\n}\n\nfunction mergeRegionPlans(\n target: RegionPlan | undefined,\n source: RegionPlan\n): RegionPlan {\n if (target == null) {\n return source;\n }\n target.deletionStart = Math.min(target.deletionStart, source.deletionStart);\n target.deletionEnd = Math.max(target.deletionEnd, source.deletionEnd);\n target.blocks.push(...source.blocks);\n if (source.previousSpan != null) {\n target.previousSpan ??= { ...source.previousSpan };\n target.previousSpan.firstIndex = Math.min(\n target.previousSpan.firstIndex,\n source.previousSpan.firstIndex\n );\n target.previousSpan.lastIndex = Math.max(\n target.previousSpan.lastIndex,\n source.previousSpan.lastIndex\n );\n }\n return target;\n}\n\n// One paired-context walk constructs every region's new-side range. There is\n// no downstream coordinate shifting: each boundary is derived from the\n// canonical blocks that precede it.\nfunction buildRegionHunks(diff: FileDiffMetadata, plans: RegionPlan[]): Hunk[] {\n const hunks: Hunk[] = [];\n let deletionCursor = 0;\n let additionCursor = 0;\n for (const plan of plans) {\n const contextBefore = plan.deletionStart - deletionCursor;\n if (contextBefore < 0) {\n throw new Error('buildRegionHunks: overlapping old-side regions');\n }\n deletionCursor += contextBefore;\n additionCursor += contextBefore;\n const additionStart = additionCursor;\n const hunkContent: Array<ContextContent | ChangeContent> = [];\n\n for (const canonicalBlock of plan.blocks) {\n const deletionContext = canonicalBlock.deletionLineIndex - deletionCursor;\n const additionContext = canonicalBlock.additionLineIndex - additionCursor;\n if (deletionContext < 0 || deletionContext !== additionContext) {\n throw new Error('buildRegionHunks: canonical block context mismatch');\n }\n pushContext(hunkContent, deletionContext, additionCursor, deletionCursor);\n deletionCursor += deletionContext;\n additionCursor += additionContext;\n hunkContent.push({ ...canonicalBlock });\n deletionCursor += canonicalBlock.deletions;\n additionCursor += canonicalBlock.additions;\n }\n\n const trailingContext = plan.deletionEnd - deletionCursor;\n if (trailingContext < 0) {\n throw new Error('buildRegionHunks: block exceeds its old-side region');\n }\n pushContext(hunkContent, trailingContext, additionCursor, deletionCursor);\n deletionCursor += trailingContext;\n additionCursor += trailingContext;\n hunks.push(\n createRegionHunk(\n diff,\n {\n additionStart,\n additionEnd: additionCursor,\n deletionStart: plan.deletionStart,\n deletionEnd: plan.deletionEnd,\n },\n hunkContent\n )\n );\n }\n\n if (\n diff.deletionLines.length - deletionCursor !==\n diff.additionLines.length - additionCursor\n ) {\n throw new Error('buildRegionHunks: trailing context mismatch');\n }\n return hunks;\n}\n\nfunction createRegionHunk(\n diff: FileDiffMetadata,\n bounds: RegionBounds,\n hunkContent: Array<ContextContent | ChangeContent>\n): Hunk {\n const additionCount = bounds.additionEnd - bounds.additionStart;\n const deletionCount = bounds.deletionEnd - bounds.deletionStart;\n let additionLines = 0;\n let deletionLines = 0;\n for (const content of hunkContent) {\n if (content.type === 'change') {\n additionLines += content.additions;\n deletionLines += content.deletions;\n }\n }\n const hunk: Hunk = {\n collapsedBefore: 0,\n additionStart: getUnifiedStart(bounds.additionStart, additionCount),\n additionCount,\n additionLines,\n additionLineIndex: getUnifiedLineIndex(bounds.additionStart, additionCount),\n deletionStart: getUnifiedStart(bounds.deletionStart, deletionCount),\n deletionCount,\n deletionLines,\n deletionLineIndex: getUnifiedLineIndex(bounds.deletionStart, deletionCount),\n hunkContent,\n hunkSpecs: `@@ -${getUnifiedStart(bounds.deletionStart, deletionCount)},${deletionCount} +${getUnifiedStart(bounds.additionStart, additionCount)},${additionCount} @@`,\n splitLineStart: 0,\n splitLineCount: 0,\n unifiedLineStart: 0,\n unifiedLineCount: 0,\n noEOFCRAdditions: false,\n noEOFCRDeletions: false,\n };\n recomputeHunkRenderLineCounts(hunk);\n return hunk;\n}\n\nfunction pushContext(\n hunkContent: Array<ContextContent | ChangeContent>,\n lines: number,\n additionLineIndex: number,\n deletionLineIndex: number\n): void {\n if (lines > 0) {\n hunkContent.push({\n type: 'context',\n lines,\n additionLineIndex,\n deletionLineIndex,\n });\n }\n}\n\nfunction hasRegionOrSplitLayoutChanged(\n previous: Hunk[],\n next: Hunk[]\n): boolean {\n if (previous.length !== next.length) {\n return true;\n }\n for (let index = 0; index < previous.length; index++) {\n const previousHunk = previous[index];\n const nextHunk = next[index];\n if (\n getHunkDeletionStart(previousHunk) !== getHunkDeletionStart(nextHunk) ||\n previousHunk.deletionCount !== nextHunk.deletionCount ||\n getHunkAdditionStart(previousHunk) !== getHunkAdditionStart(nextHunk) ||\n previousHunk.additionCount !== nextHunk.additionCount ||\n previousHunk.splitLineCount !== nextHunk.splitLineCount ||\n !haveSameSplitRowMapping(previousHunk, nextHunk)\n ) {\n return true;\n }\n }\n return false;\n}\n\nfunction haveSameSplitRowMapping(previous: Hunk, next: Hunk): boolean {\n const previousRows = iterateSplitRowMapping(previous);\n const nextRows = iterateSplitRowMapping(next);\n while (true) {\n const previousRow = previousRows.next();\n const nextRow = nextRows.next();\n if (previousRow.done === true || nextRow.done === true) {\n return previousRow.done === nextRow.done;\n }\n if (\n previousRow.value[0] !== nextRow.value[0] ||\n previousRow.value[1] !== nextRow.value[1]\n ) {\n return false;\n }\n }\n}\n\nfunction* iterateSplitRowMapping(\n hunk: Hunk\n): Generator<\n [deletionLine: number | undefined, additionLine: number | undefined]\n> {\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n for (let offset = 0; offset < content.lines; offset++) {\n yield [\n content.deletionLineIndex + offset,\n content.additionLineIndex + offset,\n ];\n }\n continue;\n }\n const rowCount = Math.max(content.deletions, content.additions);\n for (let offset = 0; offset < rowCount; offset++) {\n yield [\n offset < content.deletions\n ? content.deletionLineIndex + offset\n : undefined,\n offset < content.additions\n ? content.additionLineIndex + offset\n : undefined,\n ];\n }\n }\n}\n\nfunction getHunkAdditionStart(hunk: Hunk): number {\n return getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount);\n}\n\nfunction getHunkDeletionStart(hunk: Hunk): number {\n return getHunkSideStartBoundary(hunk.deletionStart, hunk.deletionCount);\n}\n\nfunction getUnifiedStart(lineIndex: number, count: number): number {\n return count === 0 ? lineIndex : lineIndex + 1;\n}\n\nfunction getUnifiedLineIndex(lineIndex: number, count: number): number {\n return count === 0 ? lineIndex - 1 : lineIndex;\n}\n\nfunction finalizeSessionHunks(diff: FileDiffMetadata): void {\n recomputeDiffRenderLineCounts(diff);\n for (let index = 0; index < diff.hunks.length; index++) {\n syncHunkNoEOFCRFromFullFile(diff, index);\n }\n}\n"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { DiffHunksRendererOptions } from "../renderers/DiffHunksRenderer.js";
|
|
|
2
2
|
import { FileDiffOptions } from "../components/FileDiff.js";
|
|
3
3
|
|
|
4
4
|
//#region src/utils/getDiffHunksRendererOptions.d.ts
|
|
5
|
-
declare function getDiffHunksRendererOptions<LAnnotation>(options: FileDiffOptions<LAnnotation> | undefined): DiffHunksRendererOptions;
|
|
5
|
+
declare function getDiffHunksRendererOptions<LAnnotation, Caret>(options: FileDiffOptions<LAnnotation, Caret> | undefined): DiffHunksRendererOptions;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { getDiffHunksRendererOptions };
|
|
8
8
|
//# sourceMappingURL=getDiffHunksRendererOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getDiffHunksRendererOptions.d.ts","names":[],"sources":["../../src/utils/getDiffHunksRendererOptions.ts"],"mappings":";;;;iBAMgB,2BAAA,
|
|
1
|
+
{"version":3,"file":"getDiffHunksRendererOptions.d.ts","names":[],"sources":["../../src/utils/getDiffHunksRendererOptions.ts"],"mappings":";;;;iBAMgB,2BAAA,qBACd,OAAA,EAAS,eAAA,CAAgB,WAAA,EAAa,KAAA,gBACrC,wBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getDiffHunksRendererOptions.js","names":[],"sources":["../../src/utils/getDiffHunksRendererOptions.ts"],"sourcesContent":["import type { FileDiffOptions } from '../components/FileDiff';\nimport type { DiffHunksRendererOptions } from '../renderers/DiffHunksRenderer';\nimport { shouldUseTokenTransformer } from './shouldUseTokenTransformer';\n\n// Build the renderer option snapshot with direct property reads. CodeView item\n// options may inherit prototype getters, so object spread can miss values.\nexport function getDiffHunksRendererOptions<LAnnotation>(\n options: FileDiffOptions<LAnnotation> | undefined\n): DiffHunksRendererOptions {\n return {\n theme: options?.theme,\n disableLineNumbers: options?.disableLineNumbers,\n overflow: options?.overflow,\n collapsed: options?.collapsed,\n disableFileHeader: options?.disableFileHeader,\n disableVirtualizationBuffers: options?.disableVirtualizationBuffers,\n stickyHeader: options?.stickyHeader,\n preferredHighlighter: options?.preferredHighlighter,\n useCSSClasses: options?.useCSSClasses,\n useTokenTransformer: shouldUseTokenTransformer<'diff'>(options),\n tokenizeMaxLineLength: options?.tokenizeMaxLineLength,\n tokenizeMaxLength: options?.tokenizeMaxLength,\n diffStyle: options?.diffStyle,\n diffIndicators: options?.diffIndicators,\n disableBackground: options?.disableBackground,\n hunkSeparators:\n typeof options?.hunkSeparators === 'function'\n ? 'custom'\n : options?.hunkSeparators,\n expandUnchanged: options?.expandUnchanged,\n loadDiffFiles: options?.loadDiffFiles,\n collapsedContextThreshold: options?.collapsedContextThreshold,\n lineDiffType: options?.lineDiffType,\n maxLineDiffLength: options?.maxLineDiffLength,\n expansionLineCount: options?.expansionLineCount,\n headerRenderMode:\n options?.renderCustomHeader != null ? 'custom' : 'default',\n };\n}\n"],"mappings":";;AAMA,SAAgB,4BACd,SAC0B;CAC1B,OAAO;EACL,OAAO,SAAS;EAChB,oBAAoB,SAAS;EAC7B,UAAU,SAAS;EACnB,WAAW,SAAS;EACpB,mBAAmB,SAAS;EAC5B,8BAA8B,SAAS;EACvC,cAAc,SAAS;EACvB,sBAAsB,SAAS;EAC/B,eAAe,SAAS;EACxB,qBAAqB,0BAAkC,OAAO;EAC9D,uBAAuB,SAAS;EAChC,mBAAmB,SAAS;EAC5B,WAAW,SAAS;EACpB,gBAAgB,SAAS;EACzB,mBAAmB,SAAS;EAC5B,gBACE,OAAO,SAAS,mBAAmB,aAC/B,WACA,SAAS;EACf,iBAAiB,SAAS;EAC1B,eAAe,SAAS;EACxB,2BAA2B,SAAS;EACpC,cAAc,SAAS;EACvB,mBAAmB,SAAS;EAC5B,oBAAoB,SAAS;EAC7B,kBACE,SAAS,sBAAsB,OAAO,WAAW;CACrD;AACF"}
|
|
1
|
+
{"version":3,"file":"getDiffHunksRendererOptions.js","names":[],"sources":["../../src/utils/getDiffHunksRendererOptions.ts"],"sourcesContent":["import type { FileDiffOptions } from '../components/FileDiff';\nimport type { DiffHunksRendererOptions } from '../renderers/DiffHunksRenderer';\nimport { shouldUseTokenTransformer } from './shouldUseTokenTransformer';\n\n// Build the renderer option snapshot with direct property reads. CodeView item\n// options may inherit prototype getters, so object spread can miss values.\nexport function getDiffHunksRendererOptions<LAnnotation, Caret>(\n options: FileDiffOptions<LAnnotation, Caret> | undefined\n): DiffHunksRendererOptions {\n return {\n theme: options?.theme,\n disableLineNumbers: options?.disableLineNumbers,\n overflow: options?.overflow,\n collapsed: options?.collapsed,\n disableFileHeader: options?.disableFileHeader,\n disableVirtualizationBuffers: options?.disableVirtualizationBuffers,\n stickyHeader: options?.stickyHeader,\n preferredHighlighter: options?.preferredHighlighter,\n useCSSClasses: options?.useCSSClasses,\n useTokenTransformer: shouldUseTokenTransformer<'diff'>(options),\n tokenizeMaxLineLength: options?.tokenizeMaxLineLength,\n tokenizeMaxLength: options?.tokenizeMaxLength,\n diffStyle: options?.diffStyle,\n diffIndicators: options?.diffIndicators,\n disableBackground: options?.disableBackground,\n hunkSeparators:\n typeof options?.hunkSeparators === 'function'\n ? 'custom'\n : options?.hunkSeparators,\n expandUnchanged: options?.expandUnchanged,\n loadDiffFiles: options?.loadDiffFiles,\n collapsedContextThreshold: options?.collapsedContextThreshold,\n lineDiffType: options?.lineDiffType,\n maxLineDiffLength: options?.maxLineDiffLength,\n expansionLineCount: options?.expansionLineCount,\n headerRenderMode:\n options?.renderCustomHeader != null ? 'custom' : 'default',\n };\n}\n"],"mappings":";;AAMA,SAAgB,4BACd,SAC0B;CAC1B,OAAO;EACL,OAAO,SAAS;EAChB,oBAAoB,SAAS;EAC7B,UAAU,SAAS;EACnB,WAAW,SAAS;EACpB,mBAAmB,SAAS;EAC5B,8BAA8B,SAAS;EACvC,cAAc,SAAS;EACvB,sBAAsB,SAAS;EAC/B,eAAe,SAAS;EACxB,qBAAqB,0BAAkC,OAAO;EAC9D,uBAAuB,SAAS;EAChC,mBAAmB,SAAS;EAC5B,WAAW,SAAS;EACpB,gBAAgB,SAAS;EACzB,mBAAmB,SAAS;EAC5B,gBACE,OAAO,SAAS,mBAAmB,aAC/B,WACA,SAAS;EACf,iBAAiB,SAAS;EAC1B,eAAe,SAAS;EACxB,2BAA2B,SAAS;EACpC,cAAc,SAAS;EACvB,mBAAmB,SAAS;EAC5B,oBAAoB,SAAS;EAC7B,kBACE,SAAS,sBAAsB,OAAO,WAAW;CACrD;AACF"}
|
|
@@ -2,7 +2,7 @@ import { FileRendererOptions } from "../renderers/FileRenderer.js";
|
|
|
2
2
|
import { FileOptions } from "../components/File.js";
|
|
3
3
|
|
|
4
4
|
//#region src/utils/getFileRendererOptions.d.ts
|
|
5
|
-
declare function getFileRendererOptions<LAnnotation>(options: FileOptions<LAnnotation> | undefined): FileRendererOptions;
|
|
5
|
+
declare function getFileRendererOptions<LAnnotation, Caret>(options: FileOptions<LAnnotation, Caret> | undefined): FileRendererOptions;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { getFileRendererOptions };
|
|
8
8
|
//# sourceMappingURL=getFileRendererOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFileRendererOptions.d.ts","names":[],"sources":["../../src/utils/getFileRendererOptions.ts"],"mappings":";;;;iBAMgB,sBAAA,
|
|
1
|
+
{"version":3,"file":"getFileRendererOptions.d.ts","names":[],"sources":["../../src/utils/getFileRendererOptions.ts"],"mappings":";;;;iBAMgB,sBAAA,qBACd,OAAA,EAAS,WAAA,CAAY,WAAA,EAAa,KAAA,gBACjC,mBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFileRendererOptions.js","names":[],"sources":["../../src/utils/getFileRendererOptions.ts"],"sourcesContent":["import type { FileOptions } from '../components/File';\nimport type { FileRendererOptions } from '../renderers/FileRenderer';\nimport { shouldUseTokenTransformer } from './shouldUseTokenTransformer';\n\n// Build the renderer option snapshot with direct property reads. CodeView item\n// options may inherit prototype getters, so object spread can miss values.\nexport function getFileRendererOptions<LAnnotation>(\n options: FileOptions<LAnnotation> | undefined\n): FileRendererOptions {\n return {\n theme: options?.theme,\n disableLineNumbers: options?.disableLineNumbers,\n overflow: options?.overflow,\n themeType: options?.themeType,\n collapsed: options?.collapsed,\n disableFileHeader: options?.disableFileHeader,\n disableVirtualizationBuffers: options?.disableVirtualizationBuffers,\n stickyHeader: options?.stickyHeader,\n preferredHighlighter: options?.preferredHighlighter,\n useCSSClasses: options?.useCSSClasses,\n useTokenTransformer: shouldUseTokenTransformer(options),\n tokenizeMaxLineLength: options?.tokenizeMaxLineLength,\n tokenizeMaxLength: options?.tokenizeMaxLength,\n unsafeCSS: options?.unsafeCSS,\n headerRenderMode:\n options?.renderCustomHeader != null ? 'custom' : 'default',\n };\n}\n"],"mappings":";;AAMA,SAAgB,uBACd,SACqB;CACrB,OAAO;EACL,OAAO,SAAS;EAChB,oBAAoB,SAAS;EAC7B,UAAU,SAAS;EACnB,WAAW,SAAS;EACpB,WAAW,SAAS;EACpB,mBAAmB,SAAS;EAC5B,8BAA8B,SAAS;EACvC,cAAc,SAAS;EACvB,sBAAsB,SAAS;EAC/B,eAAe,SAAS;EACxB,qBAAqB,0BAA0B,OAAO;EACtD,uBAAuB,SAAS;EAChC,mBAAmB,SAAS;EAC5B,WAAW,SAAS;EACpB,kBACE,SAAS,sBAAsB,OAAO,WAAW;CACrD;AACF"}
|
|
1
|
+
{"version":3,"file":"getFileRendererOptions.js","names":[],"sources":["../../src/utils/getFileRendererOptions.ts"],"sourcesContent":["import type { FileOptions } from '../components/File';\nimport type { FileRendererOptions } from '../renderers/FileRenderer';\nimport { shouldUseTokenTransformer } from './shouldUseTokenTransformer';\n\n// Build the renderer option snapshot with direct property reads. CodeView item\n// options may inherit prototype getters, so object spread can miss values.\nexport function getFileRendererOptions<LAnnotation, Caret>(\n options: FileOptions<LAnnotation, Caret> | undefined\n): FileRendererOptions {\n return {\n theme: options?.theme,\n disableLineNumbers: options?.disableLineNumbers,\n overflow: options?.overflow,\n themeType: options?.themeType,\n collapsed: options?.collapsed,\n disableFileHeader: options?.disableFileHeader,\n disableVirtualizationBuffers: options?.disableVirtualizationBuffers,\n stickyHeader: options?.stickyHeader,\n preferredHighlighter: options?.preferredHighlighter,\n useCSSClasses: options?.useCSSClasses,\n useTokenTransformer: shouldUseTokenTransformer(options),\n tokenizeMaxLineLength: options?.tokenizeMaxLineLength,\n tokenizeMaxLength: options?.tokenizeMaxLength,\n unsafeCSS: options?.unsafeCSS,\n headerRenderMode:\n options?.renderCustomHeader != null ? 'custom' : 'default',\n };\n}\n"],"mappings":";;AAMA,SAAgB,uBACd,SACqB;CACrB,OAAO;EACL,OAAO,SAAS;EAChB,oBAAoB,SAAS;EAC7B,UAAU,SAAS;EACnB,WAAW,SAAS;EACpB,WAAW,SAAS;EACpB,mBAAmB,SAAS;EAC5B,8BAA8B,SAAS;EACvC,cAAc,SAAS;EACvB,sBAAsB,SAAS;EAC/B,eAAe,SAAS;EACxB,qBAAqB,0BAA0B,OAAO;EACtD,uBAAuB,SAAS;EAChC,mBAAmB,SAAS;EAC5B,WAAW,SAAS;EACpB,kBACE,SAAS,sBAAsB,OAAO,WAAW;CACrD;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hydratePartialDiff.d.ts","names":[],"sources":["../../src/utils/hydratePartialDiff.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"hydratePartialDiff.d.ts","names":[],"sources":["../../src/utils/hydratePartialDiff.ts"],"mappings":";;;;;AAuBA;iBAAgB,kBAAA,CACd,IAAA,qBACA,QAAA,EAAU,gBAAA,EACV,KAAA,EAAO,mBAAA,GACN,gBAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getHunkSideEndBoundary, getHunkSideStartBoundary } from "./getHunkSideBoundaries.js";
|
|
2
2
|
import { cloneFileDiffMetadata } from "./cloneFileDiffMetadata.js";
|
|
3
|
+
import { composeCacheKey } from "./composeCacheKey.js";
|
|
3
4
|
import { splitFileContents } from "./splitFileContents.js";
|
|
4
5
|
//#region src/utils/hydratePartialDiff.ts
|
|
5
6
|
/**
|
|
@@ -132,7 +133,7 @@ function setHydratedCacheKey(fileDiff, oldFile, newFile) {
|
|
|
132
133
|
fileDiff.cacheKey = cacheKey;
|
|
133
134
|
}
|
|
134
135
|
function getLoadedFileCacheKey(oldFile, newFile) {
|
|
135
|
-
if (oldFile != null && newFile != null) return oldFile.cacheKey != null && newFile.cacheKey != null ?
|
|
136
|
+
if (oldFile != null && newFile != null) return oldFile.cacheKey != null && newFile.cacheKey != null ? composeCacheKey("hydrated-files", oldFile.cacheKey, newFile.cacheKey) : void 0;
|
|
136
137
|
return oldFile?.cacheKey ?? newFile?.cacheKey;
|
|
137
138
|
}
|
|
138
139
|
//#endregion
|
|
@@ -1 +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 {\n getHunkSideEndBoundary,\n getHunkSideStartBoundary,\n} from './getHunkSideBoundaries';\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 getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount) -\n 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 = getHunkSideEndBoundary(\n hunk.additionStart,\n hunk.additionCount\n );\n }\n\n if (hydratedHunks.length > 0) {\n const lastHunk = hydratedHunks[hydratedHunks.length - 1];\n const lastHunkEnd = getHunkSideEndBoundary(\n lastHunk.additionStart,\n lastHunk.additionCount\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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"}
|
|
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 { composeCacheKey } from './composeCacheKey';\nimport {\n getHunkSideEndBoundary,\n getHunkSideStartBoundary,\n} from './getHunkSideBoundaries';\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 getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount) -\n 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 = getHunkSideEndBoundary(\n hunk.additionStart,\n hunk.additionCount\n );\n }\n\n if (hydratedHunks.length > 0) {\n const lastHunk = hydratedHunks[hydratedHunks.length - 1];\n const lastHunkEnd = getHunkSideEndBoundary(\n lastHunk.additionStart,\n lastHunk.additionCount\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 ? composeCacheKey('hydrated-files', oldFile.cacheKey, newFile.cacheKey)\n : undefined;\n }\n return oldFile?.cacheKey ?? newFile?.cacheKey;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AnnotationSide } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/lineAnnotationIdentity.d.ts
|
|
4
|
+
interface LineAnnotationPosition {
|
|
5
|
+
lineNumber: number;
|
|
6
|
+
side?: AnnotationSide;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a possibly-remapped annotation back to the original object it
|
|
10
|
+
* descends from. Annotations that were never cloned resolve to themselves.
|
|
11
|
+
*/
|
|
12
|
+
declare function getLineAnnotationSource<T extends LineAnnotationPosition>(annotation: T): T;
|
|
13
|
+
declare function recordLineAnnotationSource(moved: LineAnnotationPosition, annotation: LineAnnotationPosition): void;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { LineAnnotationPosition, getLineAnnotationSource, recordLineAnnotationSource };
|
|
16
|
+
//# sourceMappingURL=lineAnnotationIdentity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineAnnotationIdentity.d.ts","names":[],"sources":["../../src/utils/lineAnnotationIdentity.ts"],"mappings":";;;UAEiB,sBAAA;EACf,UAAA;EACA,IAAA,GAAO,cAAc;AAAA;;;;;iBAmBP,uBAAA,WAAkC,sBAAA,EAChD,UAAA,EAAY,CAAA,GACX,CAAA;AAAA,iBAKa,0BAAA,CACd,KAAA,EAAO,sBAAA,EACP,UAAA,EAAY,sBAAsB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/utils/lineAnnotationIdentity.ts
|
|
2
|
+
const lineAnnotationSources = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a possibly-remapped annotation back to the original object it
|
|
5
|
+
* descends from. Annotations that were never cloned resolve to themselves.
|
|
6
|
+
*/
|
|
7
|
+
function getLineAnnotationSource(annotation) {
|
|
8
|
+
const source = lineAnnotationSources.get(annotation);
|
|
9
|
+
return source == null ? annotation : source;
|
|
10
|
+
}
|
|
11
|
+
function recordLineAnnotationSource(moved, annotation) {
|
|
12
|
+
lineAnnotationSources.set(moved, annotation);
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { getLineAnnotationSource, recordLineAnnotationSource };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=lineAnnotationIdentity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineAnnotationIdentity.js","names":[],"sources":["../../src/utils/lineAnnotationIdentity.ts"],"sourcesContent":["import type { AnnotationSide } from '../types';\n\nexport interface LineAnnotationPosition {\n lineNumber: number;\n side?: AnnotationSide;\n}\n\n// When an edit moves an annotation to another line, the remap replaces it\n// with a shallow clone holding the new line number, and later edits clone\n// those clones again. This map links every clone back to the original\n// annotation the caller passed in, so session state keyed by that original —\n// most importantly recorded slot names — keeps working no matter how many\n// times an annotation has been cloned, or which clone generation an undo\n// brings back.\nconst lineAnnotationSources = new WeakMap<\n LineAnnotationPosition,\n LineAnnotationPosition\n>();\n\n/**\n * Resolve a possibly-remapped annotation back to the original object it\n * descends from. Annotations that were never cloned resolve to themselves.\n */\nexport function getLineAnnotationSource<T extends LineAnnotationPosition>(\n annotation: T\n): T {\n const source = lineAnnotationSources.get(annotation);\n return source == null ? annotation : (source as T);\n}\n\nexport function recordLineAnnotationSource(\n moved: LineAnnotationPosition,\n annotation: LineAnnotationPosition\n): void {\n lineAnnotationSources.set(moved, annotation);\n}\n"],"mappings":";AAcA,MAAM,wCAAwB,IAAI,QAGhC;;;;;AAMF,SAAgB,wBACd,YACG;CACH,MAAM,SAAS,sBAAsB,IAAI,UAAU;CACnD,OAAO,UAAU,OAAO,aAAc;AACxC;AAEA,SAAgB,2BACd,OACA,YACM;CACN,sBAAsB,IAAI,OAAO,UAAU;AAC7C"}
|
|
@@ -5,8 +5,8 @@ import { CreatePatchOptionsNonabortable } from "diff";
|
|
|
5
5
|
/**
|
|
6
6
|
* Parses a diff from two file contents objects.
|
|
7
7
|
*
|
|
8
|
-
* If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff
|
|
9
|
-
*
|
|
8
|
+
* If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff gets a
|
|
9
|
+
* collision-safe key derived from both values.
|
|
10
10
|
*/
|
|
11
11
|
declare function parseDiffFromFile(oldFile: FileContents | null, newFile: FileContents | null, options?: CreatePatchOptionsNonabortable, throwOnError?: boolean): FileDiffMetadata;
|
|
12
12
|
//#endregion
|
|
@@ -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":";;;;;;AAcA;;;;iBAAgB,iBAAA,CACd,OAAA,EAAS,YAAA,SACT,OAAA,EAAS,YAAA,SACT,OAAA,GAAU,8BAAA,EACV,YAAA,aACC,gBAAA"}
|