@pierre/diffs 1.3.0-beta.2 → 1.3.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/components/CodeView.d.ts +4 -0
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +38 -0
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +2 -2
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +13 -13
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +7 -4
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +57 -47
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  14. package/dist/components/UnresolvedFile.js +1 -1
  15. package/dist/components/VirtualizedFile.d.ts +1 -1
  16. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  17. package/dist/components/VirtualizedFile.js +13 -4
  18. package/dist/components/VirtualizedFile.js.map +1 -1
  19. package/dist/components/VirtualizedFileDiff.d.ts +2 -1
  20. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  21. package/dist/components/VirtualizedFileDiff.js +36 -42
  22. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  23. package/dist/components/Virtualizer.js +5 -3
  24. package/dist/components/Virtualizer.js.map +1 -1
  25. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  26. package/dist/editor/editStack.d.ts +1 -1
  27. package/dist/editor/editor.d.ts +14 -6
  28. package/dist/editor/editor.d.ts.map +1 -1
  29. package/dist/editor/editor.js +745 -553
  30. package/dist/editor/editor.js.map +1 -1
  31. package/dist/editor/editor2.js +6 -0
  32. package/dist/editor/editor2.js.map +1 -0
  33. package/dist/editor/lineAnnotations.d.ts +2 -1
  34. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  35. package/dist/editor/lineAnnotations.js +111 -1
  36. package/dist/editor/lineAnnotations.js.map +1 -1
  37. package/dist/editor/marker.d.ts +33 -0
  38. package/dist/editor/marker.d.ts.map +1 -0
  39. package/dist/editor/marker.js +185 -0
  40. package/dist/editor/marker.js.map +1 -0
  41. package/dist/editor/pieceTable.d.ts +3 -3
  42. package/dist/editor/pieceTable.d.ts.map +1 -1
  43. package/dist/editor/pieceTable.js +44 -33
  44. package/dist/editor/pieceTable.js.map +1 -1
  45. package/dist/editor/searchPanel.d.ts +6 -7
  46. package/dist/editor/searchPanel.d.ts.map +1 -1
  47. package/dist/editor/searchPanel.js +103 -138
  48. package/dist/editor/searchPanel.js.map +1 -1
  49. package/dist/editor/selection.d.ts +19 -3
  50. package/dist/editor/selection.d.ts.map +1 -1
  51. package/dist/editor/selection.js +196 -39
  52. package/dist/editor/selection.js.map +1 -1
  53. package/dist/editor/{quickEdit.d.ts → selectionAction.d.ts} +8 -8
  54. package/dist/editor/selectionAction.d.ts.map +1 -0
  55. package/dist/editor/{quickEdit.js → selectionAction.js} +19 -21
  56. package/dist/editor/selectionAction.js.map +1 -0
  57. package/dist/editor/sprite.d.ts +8 -0
  58. package/dist/editor/sprite.d.ts.map +1 -0
  59. package/dist/editor/sprite.js +45 -0
  60. package/dist/editor/sprite.js.map +1 -0
  61. package/dist/editor/textDocument.d.ts +5 -5
  62. package/dist/editor/textDocument.d.ts.map +1 -1
  63. package/dist/editor/textDocument.js +9 -9
  64. package/dist/editor/textDocument.js.map +1 -1
  65. package/dist/editor/textMeasure.js +3 -3
  66. package/dist/editor/textMeasure.js.map +1 -1
  67. package/dist/editor/tokenzier.d.ts +6 -2
  68. package/dist/editor/tokenzier.d.ts.map +1 -1
  69. package/dist/editor/tokenzier.js +135 -85
  70. package/dist/editor/tokenzier.js.map +1 -1
  71. package/dist/editor/utils.d.ts +3 -1
  72. package/dist/editor/utils.d.ts.map +1 -1
  73. package/dist/editor/utils.js +16 -1
  74. package/dist/editor/utils.js.map +1 -1
  75. package/dist/highlighter/shared_highlighter.js +3 -29
  76. package/dist/highlighter/shared_highlighter.js.map +1 -1
  77. package/dist/highlighter/themes/attachResolvedThemes.js +4 -3
  78. package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
  79. package/dist/highlighter/themes/cleanUpResolvedThemes.js +3 -2
  80. package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
  81. package/dist/highlighter/themes/constants.d.ts +1 -7
  82. package/dist/highlighter/themes/constants.d.ts.map +1 -1
  83. package/dist/highlighter/themes/constants.js +1 -4
  84. package/dist/highlighter/themes/constants.js.map +1 -1
  85. package/dist/highlighter/themes/getResolvedOrResolveTheme.js +2 -2
  86. package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
  87. package/dist/highlighter/themes/getResolvedThemes.js +2 -8
  88. package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
  89. package/dist/highlighter/themes/hasResolvedThemes.js +2 -3
  90. package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
  91. package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +1 -1
  92. package/dist/highlighter/themes/registerCustomTheme.d.ts +5 -3
  93. package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
  94. package/dist/highlighter/themes/registerCustomTheme.js +15 -5
  95. package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
  96. package/dist/highlighter/themes/resolveTheme.js +6 -27
  97. package/dist/highlighter/themes/resolveTheme.js.map +1 -1
  98. package/dist/highlighter/themes/resolveThemes.js +5 -12
  99. package/dist/highlighter/themes/resolveThemes.js.map +1 -1
  100. package/dist/highlighter/themes/themeResolution.d.ts +8 -0
  101. package/dist/highlighter/themes/themeResolution.d.ts.map +1 -0
  102. package/dist/highlighter/themes/themeResolution.js +22 -0
  103. package/dist/highlighter/themes/themeResolution.js.map +1 -0
  104. package/dist/highlighter/themes/themeResolver.d.ts +8 -0
  105. package/dist/highlighter/themes/themeResolver.d.ts.map +1 -0
  106. package/dist/highlighter/themes/themeResolver.js +8 -0
  107. package/dist/highlighter/themes/themeResolver.js.map +1 -0
  108. package/dist/index.d.ts +4 -4
  109. package/dist/index.js +3 -3
  110. package/dist/react/index.d.ts +2 -2
  111. package/dist/react/jsx.d.ts.map +1 -1
  112. package/dist/react/utils/useFileDiffInstance.js +1 -0
  113. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  114. package/dist/renderers/DiffHunksRenderer.d.ts +4 -1
  115. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  116. package/dist/renderers/DiffHunksRenderer.js +139 -19
  117. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  118. package/dist/renderers/FileRenderer.d.ts +2 -2
  119. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  120. package/dist/renderers/FileRenderer.js +5 -5
  121. package/dist/renderers/FileRenderer.js.map +1 -1
  122. package/dist/ssr/index.d.ts +2 -2
  123. package/dist/style.js +1 -1
  124. package/dist/style.js.map +1 -1
  125. package/dist/types.d.ts +19 -16
  126. package/dist/types.d.ts.map +1 -1
  127. package/dist/utils/computeEstimatedDiffHeights.js +9 -20
  128. package/dist/utils/computeEstimatedDiffHeights.js.map +1 -1
  129. package/dist/utils/getHighlighterThemeStyles.js +16 -12
  130. package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
  131. package/dist/utils/iterateOverDiff.js +147 -182
  132. package/dist/utils/iterateOverDiff.js.map +1 -1
  133. package/dist/utils/parsePatchFiles.js +93 -4
  134. package/dist/utils/parsePatchFiles.js.map +1 -1
  135. package/dist/utils/updateDiffHunks.d.ts +13 -0
  136. package/dist/utils/updateDiffHunks.d.ts.map +1 -0
  137. package/dist/utils/updateDiffHunks.js +171 -0
  138. package/dist/utils/updateDiffHunks.js.map +1 -0
  139. package/dist/utils/virtualDiffLayout.d.ts +24 -2
  140. package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
  141. package/dist/utils/virtualDiffLayout.js +49 -1
  142. package/dist/utils/virtualDiffLayout.js.map +1 -1
  143. package/dist/worker/WorkerPoolManager.js +1 -1
  144. package/dist/worker/WorkerPoolManager.js.map +1 -1
  145. package/dist/worker/{wasm-D4DU5jgR.js → wasm-BaDzIkIn.js} +2 -2
  146. package/dist/worker/wasm-BaDzIkIn.js.map +1 -0
  147. package/dist/worker/worker-portable.js +1021 -314
  148. package/dist/worker/worker-portable.js.map +1 -1
  149. package/dist/worker/worker.js +202 -196
  150. package/dist/worker/worker.js.map +1 -1
  151. package/package.json +4 -2
  152. package/dist/editor/css.d.ts +0 -6
  153. package/dist/editor/css.d.ts.map +0 -1
  154. package/dist/editor/css.js +0 -218
  155. package/dist/editor/css.js.map +0 -1
  156. package/dist/editor/quickEdit.d.ts.map +0 -1
  157. package/dist/editor/quickEdit.js.map +0 -1
  158. package/dist/worker/wasm-D4DU5jgR.js.map +0 -1
@@ -1,8 +1,10 @@
1
1
  import { createHighlighterCore } from "shiki/core";
2
2
  import { createJavaScriptRegexEngine } from "shiki/engine/javascript";
3
3
  import { createOnigurumaEngine } from "shiki/engine/oniguruma";
4
+ import { createThemeResolver } from "@pierre/theming";
4
5
  import { diffChars, diffWordsWithSpace } from "diff";
5
6
  import { transformerStyleToClass } from "@shikijs/transformers";
7
+ import { normalizeThemeColors } from "@pierre/theming/color";
6
8
 
7
9
  //#region src/constants.ts
8
10
  const DIFFS_DEVELOPMENT_BUILD = (() => {
@@ -55,9 +57,12 @@ function attachResolvedLanguages(resolvedLanguages, highlighter$1) {
55
57
 
56
58
  //#endregion
57
59
  //#region src/highlighter/themes/constants.ts
58
- const ResolvedThemes = /* @__PURE__ */ new Map();
59
60
  const AttachedThemes = /* @__PURE__ */ new Set();
60
61
 
62
+ //#endregion
63
+ //#region src/highlighter/themes/themeResolver.ts
64
+ const themeResolver = createThemeResolver();
65
+
61
66
  //#endregion
62
67
  //#region src/highlighter/themes/attachResolvedThemes.ts
63
68
  function attachResolvedThemes(themes, highlighter$1) {
@@ -65,12 +70,12 @@ function attachResolvedThemes(themes, highlighter$1) {
65
70
  for (let themeRef of themes) {
66
71
  let resolvedTheme;
67
72
  if (typeof themeRef === "string") {
68
- resolvedTheme = ResolvedThemes.get(themeRef);
73
+ resolvedTheme = themeResolver.getResolvedTheme(themeRef);
69
74
  if (resolvedTheme == null) throw new Error(`loadResolvedThemes: ${themeRef} is not resolved, you must resolve it before calling loadResolvedThemes`);
70
75
  } else {
71
76
  resolvedTheme = themeRef;
72
77
  themeRef = themeRef.name;
73
- if (!ResolvedThemes.has(themeRef)) ResolvedThemes.set(themeRef, resolvedTheme);
78
+ if (themeResolver.getResolvedTheme(themeRef) == null) themeResolver.seedResolvedTheme(themeRef, resolvedTheme);
74
79
  }
75
80
  if (AttachedThemes.has(themeRef)) continue;
76
81
  AttachedThemes.add(themeRef);
@@ -681,24 +686,27 @@ function getHighlighterThemeStyles({ theme = DEFAULT_THEMES, highlighter: highli
681
686
  let styles = "";
682
687
  if (typeof theme === "string") {
683
688
  const themeData = highlighter$1.getTheme(theme);
684
- styles += `color:${themeData.fg};`;
685
- styles += `background-color:${themeData.bg};`;
686
- styles += `${formatCSSVariablePrefix("global")}fg:${themeData.fg};`;
687
- styles += `${formatCSSVariablePrefix("global")}bg:${themeData.bg};`;
688
- styles += getThemeVariables(themeData, prefix);
689
+ const normalized = normalizeThemeColors(themeData);
690
+ styles += `color:${normalized.fg};`;
691
+ styles += `background-color:${normalized.bg};`;
692
+ styles += `${formatCSSVariablePrefix("global")}fg:${normalized.fg};`;
693
+ styles += `${formatCSSVariablePrefix("global")}bg:${normalized.bg};`;
694
+ styles += getGitVariables(themeData, prefix);
689
695
  } else {
690
696
  let themeData = highlighter$1.getTheme(theme.dark);
691
- styles += `${formatCSSVariablePrefix("global")}dark:${themeData.fg};`;
692
- styles += `${formatCSSVariablePrefix("global")}dark-bg:${themeData.bg};`;
693
- styles += getThemeVariables(themeData, "dark");
697
+ let normalized = normalizeThemeColors(themeData);
698
+ styles += `${formatCSSVariablePrefix("global")}dark:${normalized.fg};`;
699
+ styles += `${formatCSSVariablePrefix("global")}dark-bg:${normalized.bg};`;
700
+ styles += getGitVariables(themeData, "dark");
694
701
  themeData = highlighter$1.getTheme(theme.light);
695
- styles += `${formatCSSVariablePrefix("global")}light:${themeData.fg};`;
696
- styles += `${formatCSSVariablePrefix("global")}light-bg:${themeData.bg};`;
697
- styles += getThemeVariables(themeData, "light");
702
+ normalized = normalizeThemeColors(themeData);
703
+ styles += `${formatCSSVariablePrefix("global")}light:${normalized.fg};`;
704
+ styles += `${formatCSSVariablePrefix("global")}light-bg:${normalized.bg};`;
705
+ styles += getGitVariables(themeData, "light");
698
706
  }
699
707
  return styles;
700
708
  }
701
- function getThemeVariables(themeData, modePrefix) {
709
+ function getGitVariables(themeData, modePrefix) {
702
710
  modePrefix = modePrefix != null ? `${modePrefix}-` : "";
703
711
  let styles = "";
704
712
  const additionGreen = themeData.colors?.["gitDecoration.addedResourceForeground"] ?? themeData.colors?.["terminal.ansiGreen"];
@@ -754,6 +762,39 @@ function getExpandedRegion({ isPartial, rangeSize, expandedHunks, hunkIndex, col
754
762
  renderAll
755
763
  };
756
764
  }
765
+ function getTrailingContextRangeSize({ fileDiff, errorPrefix }) {
766
+ const lastHunk = fileDiff.hunks[fileDiff.hunks.length - 1];
767
+ if (lastHunk == null || fileDiff.isPartial || fileDiff.additionLines.length === 0 || fileDiff.deletionLines.length === 0) return 0;
768
+ const additionRemaining = fileDiff.additionLines.length - (lastHunk.additionLineIndex + lastHunk.additionCount);
769
+ const deletionRemaining = fileDiff.deletionLines.length - (lastHunk.deletionLineIndex + lastHunk.deletionCount);
770
+ if (additionRemaining <= 0 && deletionRemaining <= 0) return 0;
771
+ if (additionRemaining !== deletionRemaining) throw new Error(`${errorPrefix}: trailing context mismatch (additions=${additionRemaining}, deletions=${deletionRemaining}) for ${fileDiff.name}`);
772
+ return Math.min(additionRemaining, deletionRemaining);
773
+ }
774
+ function getTrailingExpandedRegion({ fileDiff, hunkIndex, expandedHunks, collapsedContextThreshold, errorPrefix }) {
775
+ if (hunkIndex !== fileDiff.hunks.length - 1) return;
776
+ const trailingRangeSize = getTrailingContextRangeSize({
777
+ fileDiff,
778
+ errorPrefix
779
+ });
780
+ if (trailingRangeSize <= 0) return;
781
+ if (expandedHunks === true || trailingRangeSize <= collapsedContextThreshold) return {
782
+ fromStart: trailingRangeSize,
783
+ fromEnd: 0,
784
+ rangeSize: trailingRangeSize,
785
+ collapsedLines: 0,
786
+ renderAll: true
787
+ };
788
+ const region = expandedHunks?.get(fileDiff.hunks.length);
789
+ const fromStart = Math.min(Math.max(region?.fromStart ?? 0, 0), trailingRangeSize);
790
+ return {
791
+ fromStart,
792
+ fromEnd: 0,
793
+ rangeSize: trailingRangeSize,
794
+ collapsedLines: trailingRangeSize - fromStart,
795
+ renderAll: fromStart >= trailingRangeSize
796
+ };
797
+ }
757
798
 
758
799
  //#endregion
759
800
  //#region src/utils/iterateOverDiff.ts
@@ -766,12 +807,12 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
766
807
  collapsedContextThreshold
767
808
  });
768
809
  const state = {
769
- finalHunk: diff.hunks.at(-1),
770
810
  viewportStart: startingLine,
771
811
  viewportEnd: startingLine + totalLines,
772
812
  isWindowedHighlight: startingLine > 0 || totalLines < Infinity,
773
813
  splitCount: iterationStart.splitCount,
774
814
  unifiedCount: iterationStart.unifiedCount,
815
+ finalHunkIndex: diff.hunks.length - 1,
775
816
  shouldBreak() {
776
817
  if (!state.isWindowedHighlight) return false;
777
818
  const breakUnified = state.unifiedCount >= startingLine + totalLines;
@@ -824,31 +865,24 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
824
865
  hunkIndex,
825
866
  collapsedContextThreshold
826
867
  });
827
- const trailingRegion = (() => {
828
- if (hunk !== state.finalHunk || !hasFinalCollapsedHunk(diff)) return;
829
- const additionRemaining = diff.additionLines.length - (hunk.additionLineIndex + hunk.additionCount);
830
- const deletionRemaining = diff.deletionLines.length - (hunk.deletionLineIndex + hunk.deletionCount);
831
- if (additionRemaining !== deletionRemaining) throw new Error(`iterateOverDiff: trailing context mismatch (additions=${additionRemaining}, deletions=${deletionRemaining}) for ${diff.name}`);
832
- const trailingRangeSize = Math.min(additionRemaining, deletionRemaining);
833
- return getExpandedRegion({
834
- isPartial: diff.isPartial,
835
- rangeSize: trailingRangeSize,
836
- expandedHunks,
837
- hunkIndex: diff.hunks.length,
838
- collapsedContextThreshold
839
- });
840
- })();
868
+ const trailingRegion = hunkIndex === state.finalHunkIndex ? getTrailingExpandedRegion({
869
+ fileDiff: diff,
870
+ hunkIndex,
871
+ expandedHunks,
872
+ collapsedContextThreshold,
873
+ errorPrefix: "iterateOverDiff"
874
+ }) : void 0;
841
875
  const expandedLineCount = leadingRegion.fromStart + leadingRegion.fromEnd;
842
876
  function getTrailingCollapsedAfter(unifiedLineIndex$1, splitLineIndex$1) {
843
877
  if (trailingRegion == null || trailingRegion.collapsedLines <= 0 || trailingRegion.fromStart + trailingRegion.fromEnd > 0) return 0;
844
878
  if (diffStyle === "unified") return unifiedLineIndex$1 === hunk.unifiedLineStart + hunk.unifiedLineCount - 1 ? trailingRegion.collapsedLines : 0;
845
879
  return splitLineIndex$1 === hunk.splitLineStart + hunk.splitLineCount - 1 ? trailingRegion.collapsedLines : 0;
846
880
  }
847
- function getPendingCollapsed() {
848
- if (leadingRegion.collapsedLines === 0) return 0;
849
- const value = leadingRegion.collapsedLines;
850
- leadingRegion.collapsedLines = 0;
851
- return value;
881
+ let consumedCollapsed = leadingRegion.collapsedLines === 0;
882
+ function consumePendingCollapsed() {
883
+ if (consumedCollapsed) return 0;
884
+ consumedCollapsed = true;
885
+ return leadingRegion.collapsedLines;
852
886
  }
853
887
  if (!state.shouldSkip(expandedLineCount, expandedLineCount)) {
854
888
  let unifiedLineIndex$1 = hunk.unifiedLineStart - leadingRegion.rangeSize;
@@ -857,81 +891,63 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
857
891
  let additionLineIndex$1 = hunk.additionLineIndex - leadingRegion.rangeSize;
858
892
  let deletionLineNumber$1 = hunk.deletionStart - leadingRegion.rangeSize;
859
893
  let additionLineNumber$1 = hunk.additionStart - leadingRegion.rangeSize;
860
- const [startIndex, endIndex] = getEqualLineIterationRange(state, leadingRegion.fromStart, diffStyle);
861
- if (startIndex > 0) state.incrementCounts(startIndex, startIndex);
862
- let index = startIndex;
863
- while (index < leadingRegion.fromStart) {
864
- if (index >= endIndex) {
865
- state.incrementCounts(leadingRegion.fromStart - index, leadingRegion.fromStart - index);
866
- break;
867
- }
868
- if (state.isInWindow(0, 0)) {
869
- if (state.emit({
870
- hunkIndex,
871
- hunk,
872
- collapsedBefore: 0,
873
- collapsedAfter: 0,
874
- type: "context-expanded",
875
- deletionLine: {
876
- lineNumber: deletionLineNumber$1 + index,
877
- lineIndex: deletionLineIndex$1 + index,
878
- noEOFCR: false,
879
- unifiedLineIndex: unifiedLineIndex$1 + index,
880
- splitLineIndex: splitLineIndex$1 + index
881
- },
882
- additionLine: {
883
- unifiedLineIndex: unifiedLineIndex$1 + index,
884
- splitLineIndex: splitLineIndex$1 + index,
885
- lineIndex: additionLineIndex$1 + index,
886
- lineNumber: additionLineNumber$1 + index,
887
- noEOFCR: false
888
- }
889
- })) break hunkIterator;
890
- } else state.incrementCounts(1, 1);
891
- index++;
892
- }
894
+ if (walkContextLines(state, leadingRegion.fromStart, diffStyle, (index) => {
895
+ return state.emit({
896
+ hunkIndex,
897
+ hunk,
898
+ collapsedBefore: 0,
899
+ collapsedAfter: 0,
900
+ type: "context-expanded",
901
+ deletionLine: {
902
+ lineNumber: deletionLineNumber$1 + index,
903
+ lineIndex: deletionLineIndex$1 + index,
904
+ noEOFCR: false,
905
+ unifiedLineIndex: unifiedLineIndex$1 + index,
906
+ splitLineIndex: splitLineIndex$1 + index
907
+ },
908
+ additionLine: {
909
+ unifiedLineIndex: unifiedLineIndex$1 + index,
910
+ splitLineIndex: splitLineIndex$1 + index,
911
+ lineIndex: additionLineIndex$1 + index,
912
+ lineNumber: additionLineNumber$1 + index,
913
+ noEOFCR: false
914
+ }
915
+ });
916
+ })) break hunkIterator;
893
917
  unifiedLineIndex$1 = hunk.unifiedLineStart - leadingRegion.fromEnd;
894
918
  splitLineIndex$1 = hunk.splitLineStart - leadingRegion.fromEnd;
895
919
  deletionLineIndex$1 = hunk.deletionLineIndex - leadingRegion.fromEnd;
896
920
  additionLineIndex$1 = hunk.additionLineIndex - leadingRegion.fromEnd;
897
921
  deletionLineNumber$1 = hunk.deletionStart - leadingRegion.fromEnd;
898
922
  additionLineNumber$1 = hunk.additionStart - leadingRegion.fromEnd;
899
- const [fromEndStartIndex, fromEndEndIndex] = getEqualLineIterationRange(state, leadingRegion.fromEnd, diffStyle);
900
- if (fromEndStartIndex > 0) state.incrementCounts(fromEndStartIndex, fromEndStartIndex);
901
- index = fromEndStartIndex;
902
- while (index < leadingRegion.fromEnd) {
903
- if (index >= fromEndEndIndex) {
904
- state.incrementCounts(leadingRegion.fromEnd - index, leadingRegion.fromEnd - index);
905
- break;
906
- }
907
- if (state.isInWindow(0, 0)) {
908
- if (state.emit({
909
- hunkIndex,
910
- hunk,
911
- collapsedBefore: getPendingCollapsed(),
912
- collapsedAfter: 0,
913
- type: "context-expanded",
914
- deletionLine: {
915
- lineNumber: deletionLineNumber$1 + index,
916
- lineIndex: deletionLineIndex$1 + index,
917
- noEOFCR: false,
918
- unifiedLineIndex: unifiedLineIndex$1 + index,
919
- splitLineIndex: splitLineIndex$1 + index
920
- },
921
- additionLine: {
922
- unifiedLineIndex: unifiedLineIndex$1 + index,
923
- splitLineIndex: splitLineIndex$1 + index,
924
- lineIndex: additionLineIndex$1 + index,
925
- lineNumber: additionLineNumber$1 + index,
926
- noEOFCR: false
927
- }
928
- })) break hunkIterator;
929
- } else state.incrementCounts(1, 1);
930
- index++;
931
- }
923
+ if (walkContextLines(state, leadingRegion.fromEnd, diffStyle, (index) => {
924
+ return state.emit({
925
+ hunkIndex,
926
+ hunk,
927
+ collapsedBefore: consumePendingCollapsed(),
928
+ collapsedAfter: 0,
929
+ type: "context-expanded",
930
+ deletionLine: {
931
+ lineNumber: deletionLineNumber$1 + index,
932
+ lineIndex: deletionLineIndex$1 + index,
933
+ noEOFCR: false,
934
+ unifiedLineIndex: unifiedLineIndex$1 + index,
935
+ splitLineIndex: splitLineIndex$1 + index
936
+ },
937
+ additionLine: {
938
+ unifiedLineIndex: unifiedLineIndex$1 + index,
939
+ splitLineIndex: splitLineIndex$1 + index,
940
+ lineIndex: additionLineIndex$1 + index,
941
+ lineNumber: additionLineNumber$1 + index,
942
+ noEOFCR: false
943
+ }
944
+ });
945
+ }, () => {
946
+ consumePendingCollapsed();
947
+ })) break hunkIterator;
932
948
  } else {
933
949
  state.incrementCounts(expandedLineCount, expandedLineCount);
934
- getPendingCollapsed();
950
+ consumePendingCollapsed();
935
951
  }
936
952
  let unifiedLineIndex = hunk.unifiedLineStart;
937
953
  let splitLineIndex = hunk.splitLineStart;
@@ -945,45 +961,37 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
945
961
  const isLastContent = content === lastContent;
946
962
  if (content.type === "context") {
947
963
  if (!state.shouldSkip(content.lines, content.lines)) {
948
- const [startIndex, endIndex] = getEqualLineIterationRange(state, content.lines, diffStyle);
949
- if (startIndex > 0) state.incrementCounts(startIndex, startIndex);
950
- let index = startIndex;
951
- while (index < content.lines) {
952
- if (index >= endIndex) {
953
- state.incrementCounts(content.lines - index, content.lines - index);
954
- break;
955
- }
956
- if (state.isInWindow(0, 0)) {
957
- const isLastLine = isLastContent && index === content.lines - 1;
958
- const unifiedRowIndex = unifiedLineIndex + index;
959
- const splitRowIndex = splitLineIndex + index;
960
- if (state.emit({
961
- hunkIndex,
962
- hunk,
963
- collapsedBefore: getPendingCollapsed(),
964
- collapsedAfter: getTrailingCollapsedAfter(unifiedRowIndex, splitRowIndex),
965
- type: "context",
966
- deletionLine: {
967
- lineNumber: deletionLineNumber + index,
968
- lineIndex: deletionLineIndex + index,
969
- noEOFCR: isLastLine && hunk.noEOFCRDeletions,
970
- unifiedLineIndex: unifiedRowIndex,
971
- splitLineIndex: splitRowIndex
972
- },
973
- additionLine: {
974
- unifiedLineIndex: unifiedRowIndex,
975
- splitLineIndex: splitRowIndex,
976
- lineIndex: additionLineIndex + index,
977
- lineNumber: additionLineNumber + index,
978
- noEOFCR: isLastLine && hunk.noEOFCRAdditions
979
- }
980
- })) break hunkIterator;
981
- } else state.incrementCounts(1, 1);
982
- index++;
983
- }
964
+ if (walkContextLines(state, content.lines, diffStyle, (index) => {
965
+ const isLastLine = isLastContent && index === content.lines - 1;
966
+ const unifiedRowIndex = unifiedLineIndex + index;
967
+ const splitRowIndex = splitLineIndex + index;
968
+ return state.emit({
969
+ hunkIndex,
970
+ hunk,
971
+ collapsedBefore: consumePendingCollapsed(),
972
+ collapsedAfter: getTrailingCollapsedAfter(unifiedRowIndex, splitRowIndex),
973
+ type: "context",
974
+ deletionLine: {
975
+ lineNumber: deletionLineNumber + index,
976
+ lineIndex: deletionLineIndex + index,
977
+ noEOFCR: isLastLine && hunk.noEOFCRDeletions,
978
+ unifiedLineIndex: unifiedRowIndex,
979
+ splitLineIndex: splitRowIndex
980
+ },
981
+ additionLine: {
982
+ unifiedLineIndex: unifiedRowIndex,
983
+ splitLineIndex: splitRowIndex,
984
+ lineIndex: additionLineIndex + index,
985
+ lineNumber: additionLineNumber + index,
986
+ noEOFCR: isLastLine && hunk.noEOFCRAdditions
987
+ }
988
+ });
989
+ }, () => {
990
+ consumePendingCollapsed();
991
+ })) break hunkIterator;
984
992
  } else {
985
993
  state.incrementCounts(content.lines, content.lines);
986
- getPendingCollapsed();
994
+ consumePendingCollapsed();
987
995
  }
988
996
  unifiedLineIndex += content.lines;
989
997
  splitLineIndex += content.lines;
@@ -996,12 +1004,13 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
996
1004
  const unifiedCount = content.deletions + content.additions;
997
1005
  if (!state.shouldSkip(unifiedCount, splitCount)) {
998
1006
  const iterationRanges = getChangeIterationRanges(state, content, diffStyle);
1007
+ if ((iterationRanges[0]?.[0] ?? 0) > 0) consumePendingCollapsed();
999
1008
  for (const [rangeStart, rangeEnd] of iterationRanges) for (let index = rangeStart; index < rangeEnd; index++) {
1000
1009
  const collapsedAfter = getTrailingCollapsedAfter(unifiedLineIndex + index, diffStyle === "unified" ? splitLineIndex + (index < content.deletions ? index : index - content.deletions) : splitLineIndex + index);
1001
1010
  if (state.emit(getChangeLineData({
1002
1011
  hunkIndex,
1003
1012
  hunk,
1004
- collapsedBefore: getPendingCollapsed(),
1013
+ collapsedBefore: consumePendingCollapsed(),
1005
1014
  collapsedAfter,
1006
1015
  diffStyle,
1007
1016
  index,
@@ -1018,7 +1027,7 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
1018
1027
  }), true)) break hunkIterator;
1019
1028
  }
1020
1029
  }
1021
- getPendingCollapsed();
1030
+ consumePendingCollapsed();
1022
1031
  state.incrementCounts(unifiedCount, splitCount);
1023
1032
  unifiedLineIndex += unifiedCount;
1024
1033
  splitLineIndex += splitCount;
@@ -1031,41 +1040,30 @@ function iterateOverDiff({ diff, diffStyle, startingLine = 0, totalLines = Infin
1031
1040
  if (trailingRegion != null) {
1032
1041
  const { collapsedLines, fromStart, fromEnd } = trailingRegion;
1033
1042
  const len = fromStart + fromEnd;
1034
- const [startIndex, endIndex] = getEqualLineIterationRange(state, len, diffStyle);
1035
- if (startIndex > 0) state.incrementCounts(startIndex, startIndex);
1036
- let index = startIndex;
1037
- while (index < len) {
1038
- if (state.shouldBreak()) break hunkIterator;
1039
- if (index >= endIndex) {
1040
- state.incrementCounts(len - index, len - index);
1041
- break;
1042
- }
1043
- if (state.isInWindow(0, 0)) {
1044
- const isLastLine = index === len - 1;
1045
- if (state.emit({
1046
- hunkIndex: diff.hunks.length,
1047
- hunk: void 0,
1048
- collapsedBefore: 0,
1049
- collapsedAfter: isLastLine ? collapsedLines : 0,
1050
- type: "context-expanded",
1051
- deletionLine: {
1052
- lineNumber: deletionLineNumber + index,
1053
- lineIndex: deletionLineIndex + index,
1054
- noEOFCR: false,
1055
- unifiedLineIndex: unifiedLineIndex + index,
1056
- splitLineIndex: splitLineIndex + index
1057
- },
1058
- additionLine: {
1059
- unifiedLineIndex: unifiedLineIndex + index,
1060
- splitLineIndex: splitLineIndex + index,
1061
- lineIndex: additionLineIndex + index,
1062
- lineNumber: additionLineNumber + index,
1063
- noEOFCR: false
1064
- }
1065
- })) break hunkIterator;
1066
- } else state.incrementCounts(1, 1);
1067
- index++;
1068
- }
1043
+ if (walkContextLines(state, len, diffStyle, (index) => {
1044
+ const isLastLine = index === len - 1;
1045
+ return state.emit({
1046
+ hunkIndex: diff.hunks.length,
1047
+ hunk: void 0,
1048
+ collapsedBefore: 0,
1049
+ collapsedAfter: isLastLine ? collapsedLines : 0,
1050
+ type: "context-expanded",
1051
+ deletionLine: {
1052
+ lineNumber: deletionLineNumber + index,
1053
+ lineIndex: deletionLineIndex + index,
1054
+ noEOFCR: false,
1055
+ unifiedLineIndex: unifiedLineIndex + index,
1056
+ splitLineIndex: splitLineIndex + index
1057
+ },
1058
+ additionLine: {
1059
+ unifiedLineIndex: unifiedLineIndex + index,
1060
+ splitLineIndex: splitLineIndex + index,
1061
+ lineIndex: additionLineIndex + index,
1062
+ lineNumber: additionLineNumber + index,
1063
+ noEOFCR: false
1064
+ }
1065
+ });
1066
+ }, void 0, () => state.shouldBreak())) break hunkIterator;
1069
1067
  }
1070
1068
  }
1071
1069
  }
@@ -1130,15 +1128,14 @@ function getHunkPrefixCounts({ diff, expandedHunks, collapsedContextThreshold })
1130
1128
  const leadingCount = leadingRegion.fromStart + leadingRegion.fromEnd;
1131
1129
  splitCount += leadingCount + hunk.splitLineCount;
1132
1130
  unifiedCount += leadingCount + hunk.unifiedLineCount;
1133
- if (index === finalHunkIndex && hasFinalCollapsedHunk(diff)) {
1134
- const trailingRangeSize = getTrailingRangeSize(diff, hunk);
1135
- const trailingRegion = getExpandedRegion({
1136
- isPartial: diff.isPartial,
1137
- rangeSize: trailingRangeSize,
1138
- expandedHunks,
1139
- hunkIndex: diff.hunks.length,
1140
- collapsedContextThreshold
1141
- });
1131
+ const trailingRegion = index === finalHunkIndex ? getTrailingExpandedRegion({
1132
+ fileDiff: diff,
1133
+ hunkIndex: index,
1134
+ expandedHunks,
1135
+ collapsedContextThreshold,
1136
+ errorPrefix: "iterateOverDiff"
1137
+ }) : void 0;
1138
+ if (trailingRegion != null) {
1142
1139
  const trailingCount = trailingRegion.fromStart + trailingRegion.fromEnd;
1143
1140
  splitCount += trailingCount;
1144
1141
  unifiedCount += trailingCount;
@@ -1150,7 +1147,7 @@ function getHunkPrefixCounts({ diff, expandedHunks, collapsedContextThreshold })
1150
1147
  }
1151
1148
  return prefixCounts;
1152
1149
  }
1153
- function getEqualLineIterationRange(state, count, diffStyle) {
1150
+ function getContextLineIterationBounds(state, count, diffStyle) {
1154
1151
  if (!state.isWindowedHighlight || count <= 0) return [0, count];
1155
1152
  const ranges = [];
1156
1153
  function pushRange(currentCount) {
@@ -1170,16 +1167,25 @@ function getEqualLineIterationRange(state, count, diffStyle) {
1170
1167
  }
1171
1168
  return [start, end];
1172
1169
  }
1173
- function getTrailingRangeSize(diff, hunk) {
1174
- const additionRemaining = diff.additionLines.length - (hunk.additionLineIndex + hunk.additionCount);
1175
- const deletionRemaining = diff.deletionLines.length - (hunk.deletionLineIndex + hunk.deletionCount);
1176
- if (additionRemaining !== deletionRemaining) throw new Error(`iterateOverDiff: trailing context mismatch (additions=${additionRemaining}, deletions=${deletionRemaining}) for ${diff.name}`);
1177
- return Math.min(additionRemaining, deletionRemaining);
1178
- }
1179
- function hasFinalCollapsedHunk(diff) {
1180
- const lastHunk = diff.hunks.at(-1);
1181
- if (lastHunk == null || diff.isPartial || diff.additionLines.length === 0 || diff.deletionLines.length === 0) return false;
1182
- return lastHunk.additionLineIndex + lastHunk.additionCount < diff.additionLines.length || lastHunk.deletionLineIndex + lastHunk.deletionCount < diff.deletionLines.length;
1170
+ function walkContextLines(state, count, diffStyle, callback, onSkippedStart, shouldBreak) {
1171
+ const [startIndex, endIndex] = getContextLineIterationBounds(state, count, diffStyle);
1172
+ if (startIndex > 0) {
1173
+ state.incrementCounts(startIndex, startIndex);
1174
+ onSkippedStart?.();
1175
+ }
1176
+ let index = startIndex;
1177
+ while (index < count) {
1178
+ if (shouldBreak?.() === true) return true;
1179
+ if (index >= endIndex) {
1180
+ state.incrementCounts(count - index, count - index);
1181
+ break;
1182
+ }
1183
+ if (state.isInWindow(0, 0)) {
1184
+ if (callback(index) === true) return true;
1185
+ } else state.incrementCounts(1, 1);
1186
+ index++;
1187
+ }
1188
+ return false;
1183
1189
  }
1184
1190
  function getChangeIterationRanges(state, content, diffStyle) {
1185
1191
  if (!state.isWindowedHighlight) return [[0, diffStyle === "unified" ? content.deletions + content.additions : Math.max(content.deletions, content.additions)]];