@git-diff-view/react 0.0.5 → 0.0.6

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 (27) hide show
  1. package/dist/cjs/index.development.js +402 -220
  2. package/dist/cjs/index.development.js.map +1 -1
  3. package/dist/cjs/index.production.js +386 -223
  4. package/dist/cjs/index.production.js.map +1 -1
  5. package/dist/css/diff-view.css +1 -1
  6. package/dist/esm/index.mjs +407 -224
  7. package/dist/esm/index.mjs.map +1 -1
  8. package/dist/types/components/DiffContent.d.ts.map +1 -1
  9. package/dist/types/components/DiffSplitHunkLineNormal.d.ts +0 -4
  10. package/dist/types/components/DiffSplitHunkLineNormal.d.ts.map +1 -1
  11. package/dist/types/components/DiffSplitHunkLineWrap.d.ts +0 -3
  12. package/dist/types/components/DiffSplitHunkLineWrap.d.ts.map +1 -1
  13. package/dist/types/components/DiffSplitView.d.ts.map +1 -1
  14. package/dist/types/components/DiffSplitViewLineNormal.d.ts +9 -0
  15. package/dist/types/components/DiffSplitViewLineNormal.d.ts.map +1 -0
  16. package/dist/types/components/DiffSplitViewLineWrap.d.ts +7 -0
  17. package/dist/types/components/DiffSplitViewLineWrap.d.ts.map +1 -0
  18. package/dist/types/components/DiffSplitViewNormal.d.ts +1 -1
  19. package/dist/types/components/DiffSplitViewNormal.d.ts.map +1 -1
  20. package/dist/types/components/DiffSplitViewWrap.d.ts.map +1 -1
  21. package/dist/types/components/DiffUnifiedHunkLine.d.ts +0 -3
  22. package/dist/types/components/DiffUnifiedHunkLine.d.ts.map +1 -1
  23. package/dist/types/components/DiffUnifiedView.d.ts.map +1 -1
  24. package/dist/types/components/DiffView.d.ts +9 -3
  25. package/dist/types/components/DiffView.d.ts.map +1 -1
  26. package/package.json +3 -3
  27. package/readme.md +68 -1
@@ -1515,6 +1515,7 @@ lowlight.register("vue", function hljsDefineVue(hljs) {
1515
1515
  const highlighter = lowlight;
1516
1516
  let _autoDetectLang = true;
1517
1517
  let _maxLineToIgnoreSyntax = 2000;
1518
+ const _ignoreSyntaxHighlightList = [];
1518
1519
  Object.defineProperty(highlighter, "maxLineToIgnoreSyntax", {
1519
1520
  get: () => _maxLineToIgnoreSyntax,
1520
1521
  });
@@ -1531,11 +1532,21 @@ Object.defineProperty(highlighter, "setAutoDetectLang", {
1531
1532
  _autoDetectLang = v;
1532
1533
  },
1533
1534
  });
1535
+ Object.defineProperty(highlighter, "ignoreSyntaxHighlightList", {
1536
+ get: () => _ignoreSyntaxHighlightList,
1537
+ });
1538
+ Object.defineProperty(highlighter, "setIgnoreSyntaxHighlightList", {
1539
+ value: (v) => {
1540
+ _ignoreSyntaxHighlightList.length = 0;
1541
+ _ignoreSyntaxHighlightList.push(...v);
1542
+ },
1543
+ });
1534
1544
 
1535
1545
  const map = new LRUCache({ max: 30 });
1536
1546
  class File {
1537
1547
  raw;
1538
1548
  lang;
1549
+ fileName;
1539
1550
  ast;
1540
1551
  rawFile = {};
1541
1552
  hasDoRaw = false;
@@ -1544,9 +1555,10 @@ class File {
1544
1555
  hasDoSyntax = false;
1545
1556
  syntaxLength;
1546
1557
  maxLineNumber = 0;
1547
- constructor(raw, lang) {
1558
+ constructor(raw, lang, fileName) {
1548
1559
  this.raw = raw;
1549
1560
  this.lang = lang;
1561
+ this.fileName = fileName;
1550
1562
  Object.defineProperty(this, "__v_skip", { value: true });
1551
1563
  }
1552
1564
  doSyntax({ autoDetectLang, registerHighlighter, }) {
@@ -1569,6 +1581,11 @@ class File {
1569
1581
  console.warn(`ignore syntax for current file, because the rawLength is too long: ${this.rawLength}`);
1570
1582
  return;
1571
1583
  }
1584
+ if (this.fileName &&
1585
+ _highlighter.ignoreSyntaxHighlightList.some((item) => item instanceof RegExp ? item.test(this.fileName) : this.fileName === item)) {
1586
+ console.warn(`ignore syntax for current file, because the fileName is in the ignoreSyntaxHighlightList: ${this.fileName}`);
1587
+ return;
1588
+ }
1572
1589
  if (hasRegisteredLang) {
1573
1590
  this.ast = _highlighter.highlight(this.lang, this.raw);
1574
1591
  }
@@ -1588,10 +1605,18 @@ class File {
1588
1605
  const rawArray = rawString.split("\n");
1589
1606
  this.rawLength = rawArray.length;
1590
1607
  this.maxLineNumber = rawArray.length;
1591
- this.rawFile = rawArray.reduce((p, item, index) => ({
1592
- ...p,
1593
- [index + 1]: index < rawArray.length - 1 ? item + "\n" : item,
1594
- }), {});
1608
+ this.rawFile = {};
1609
+ for (let i = 0; i < rawArray.length; i++) {
1610
+ this.rawFile[i + 1] = i < rawArray.length - 1 ? rawArray[i] + "\n" : rawArray[i];
1611
+ }
1612
+ // reduce 对于大数组性能很差
1613
+ // this.rawFile = rawArray.reduce(
1614
+ // (p, item, index) => ({
1615
+ // ...p,
1616
+ // [index + 1]: index < rawArray.length - 1 ? item + "\n" : item,
1617
+ // }),
1618
+ // {}
1619
+ // );
1595
1620
  this.hasDoRaw = true;
1596
1621
  }
1597
1622
  #doAST() {
@@ -1682,11 +1707,11 @@ class File {
1682
1707
  }
1683
1708
  }
1684
1709
  }
1685
- const getFile = (raw, lang) => {
1686
- const key = raw + "--" + "0.0.5" + "--" + lang;
1710
+ const getFile = (raw, lang, fileName) => {
1711
+ const key = raw + "--" + "0.0.6" + "--" + lang;
1687
1712
  if (map.has(key))
1688
1713
  return map.get(key);
1689
- const file = new File(raw, lang);
1714
+ const file = new File(raw, lang, fileName);
1690
1715
  map.set(key, file);
1691
1716
  return file;
1692
1717
  };
@@ -1720,10 +1745,20 @@ function relativeChanges(stringA, stringB) {
1720
1745
  let aRange = { location: 0, length: stringA.length };
1721
1746
  const _stringA = stringA.trimEnd();
1722
1747
  const _stringB = stringB.trimEnd();
1723
- if (_stringA === _stringB) {
1748
+ const aEndStr = stringA.slice(-2);
1749
+ const bEndStr = stringB.slice(-2);
1750
+ if (_stringA === _stringB && aEndStr !== bEndStr && (aEndStr === "\r\n" || bEndStr === "\r\n")) {
1724
1751
  return {
1725
- stringARange: { location: _stringA.length, length: stringA.length - _stringA.length },
1726
- stringBRange: { location: _stringB.length, length: stringB.length - _stringB.length },
1752
+ stringARange: {
1753
+ location: _stringA.length,
1754
+ length: stringA.length - _stringA.length,
1755
+ isNewLineSymbolChanged: true,
1756
+ },
1757
+ stringBRange: {
1758
+ location: _stringB.length,
1759
+ length: stringB.length - _stringB.length,
1760
+ isNewLineSymbolChanged: true,
1761
+ },
1727
1762
  };
1728
1763
  }
1729
1764
  if (isInValidString(stringA) || isInValidString(stringB)) {
@@ -1745,6 +1780,16 @@ function relativeChanges(stringA, stringB) {
1745
1780
  aRange.length -= suffixLength;
1746
1781
  return { stringARange: aRange, stringBRange: bRange };
1747
1782
  }
1783
+ /** Check two string have a diff range */
1784
+ function hasRelativeChange(stringA, stringB) {
1785
+ const _stringA = stringA.trim();
1786
+ const _stringB = stringB.trim();
1787
+ const { stringARange, stringBRange } = relativeChanges(_stringA, _stringB);
1788
+ return (stringARange.location > 0 ||
1789
+ stringBRange.location > 0 ||
1790
+ stringARange.length < _stringA.length ||
1791
+ stringBRange.length < _stringB.length);
1792
+ }
1748
1793
 
1749
1794
  /** indicate what a line in the diff represents */
1750
1795
  var DiffLineType;
@@ -1963,11 +2008,14 @@ const getDiffRange = (additions, deletions) => {
1963
2008
  for (let i = 0; i < len; i++) {
1964
2009
  const addition = additions[i];
1965
2010
  const deletion = deletions[i];
1966
- const { stringARange, stringBRange } = relativeChanges(addition.text, deletion.text);
1967
- addition.needRematch = true;
1968
- addition.range = stringARange;
1969
- deletion.needRematch = true;
1970
- deletion.range = stringBRange;
2011
+ const hasDiffRange = hasRelativeChange(addition.text, deletion.text);
2012
+ if (hasDiffRange) {
2013
+ const { stringARange, stringBRange } = relativeChanges(addition.text, deletion.text);
2014
+ addition.needRematch = true;
2015
+ addition.range = stringARange;
2016
+ deletion.needRematch = true;
2017
+ deletion.range = stringBRange;
2018
+ }
1971
2019
  }
1972
2020
  }
1973
2021
  };
@@ -2342,10 +2390,8 @@ class DiffFile {
2342
2390
  #splitLeftLines = [];
2343
2391
  #splitRightLines = [];
2344
2392
  #splitHunksLines;
2345
- #splitLastStartIndex;
2346
2393
  #unifiedLines = [];
2347
2394
  #unifiedHunksLines;
2348
- #unifiedLastStartIndex;
2349
2395
  #listeners = [];
2350
2396
  #hasInitRaw = false;
2351
2397
  #hasInitSyntax = false;
@@ -2353,6 +2399,7 @@ class DiffFile {
2353
2399
  #hasBuildUnified = false;
2354
2400
  #updateCount = 0;
2355
2401
  #composeByDiff = false;
2402
+ _version_ = "0.0.6";
2356
2403
  _oldFileContent = "";
2357
2404
  _oldFileLang = "";
2358
2405
  _newFileContent = "";
@@ -2403,10 +2450,10 @@ class DiffFile {
2403
2450
  if (!this._oldFileContent && !this._newFileContent)
2404
2451
  return;
2405
2452
  if (this._oldFileContent) {
2406
- this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang);
2453
+ this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang, this._oldFileName);
2407
2454
  }
2408
2455
  if (this._newFileContent) {
2409
- this.#newFileResult = getFile(this._newFileContent, this._newFileLang);
2456
+ this.#newFileResult = getFile(this._newFileContent, this._newFileLang, this._newFileName);
2410
2457
  }
2411
2458
  }
2412
2459
  #composeRaw() {
@@ -2448,8 +2495,8 @@ class DiffFile {
2448
2495
  return;
2449
2496
  this._oldFileContent = oldFileContent;
2450
2497
  this._newFileContent = newFileContent;
2451
- this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang);
2452
- this.#newFileResult = getFile(this._newFileContent, this._newFileLang);
2498
+ this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang, this._oldFileName);
2499
+ this.#newFileResult = getFile(this._newFileContent, this._newFileLang, this._newFileName);
2453
2500
  // all of the file just compose by diff, so we can not do the expand action
2454
2501
  this.#composeByDiff = true;
2455
2502
  }
@@ -2470,7 +2517,7 @@ class DiffFile {
2470
2517
  if (newFileContent === this._oldFileContent)
2471
2518
  return;
2472
2519
  this._newFileContent = newFileContent;
2473
- this.#newFileResult = getFile(this._newFileContent, this._newFileLang);
2520
+ this.#newFileResult = getFile(this._newFileContent, this._newFileLang, this._newFileName);
2474
2521
  }
2475
2522
  else if (this.#newFileResult) {
2476
2523
  let oldLineNumber = 1;
@@ -2489,7 +2536,7 @@ class DiffFile {
2489
2536
  if (oldFileContent === this._newFileContent)
2490
2537
  return;
2491
2538
  this._oldFileContent = oldFileContent;
2492
- this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang);
2539
+ this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang, this._oldFileName);
2493
2540
  }
2494
2541
  this.#composeRaw();
2495
2542
  }
@@ -2517,9 +2564,14 @@ class DiffFile {
2517
2564
  getDiffRange(additions, deletions);
2518
2565
  });
2519
2566
  });
2520
- this.#diffLines = this.#diffListResults
2521
- .reduce((p, c) => p.concat(...c.hunks.reduce((_p, _c) => _p.concat(..._c.lines), [])), [])
2522
- .map((i, index) => {
2567
+ this.#diffLines = [];
2568
+ const tmp = [];
2569
+ this.#diffListResults.forEach((item) => {
2570
+ item.hunks.forEach((_item) => {
2571
+ tmp.push(..._item.lines);
2572
+ });
2573
+ });
2574
+ this.#diffLines = tmp.map((i, index) => {
2523
2575
  const typedI = i;
2524
2576
  typedI.index = index;
2525
2577
  if (typedI.type === DiffLineType.Hunk) {
@@ -2534,28 +2586,49 @@ class DiffFile {
2534
2586
  oldLength: Number(oldNumLength),
2535
2587
  newStartIndex: +Number(newNumStartIndex),
2536
2588
  newLength: Number(newNumLength),
2589
+ _oldStartIndex: -Number(oldNumStartIndex),
2590
+ _oldLength: Number(oldNumLength),
2591
+ _newStartIndex: +Number(newNumStartIndex),
2592
+ _newLength: Number(newNumLength),
2537
2593
  };
2538
2594
  }
2539
2595
  return typedI;
2540
2596
  });
2541
- this.#oldFileDiffLines = this.#diffLines.reduce((p, c) => {
2542
- if (c.oldLineNumber) {
2543
- this.diffLineLength = Math.max(this.diffLineLength, c.oldLineNumber);
2544
- return { ...p, [c.oldLineNumber]: c };
2597
+ // this.#diffLines = this.#diffListResults
2598
+ // .reduce<DiffLine[]>((p, c) => p.concat(...c.hunks.reduce<DiffLine[]>((_p, _c) => _p.concat(..._c.lines), [])), [])
2599
+ // .map<DiffLineItem>((i, index) => {
2600
+ // const typedI = i as DiffLineItem;
2601
+ // typedI.index = index;
2602
+ // if (typedI.type === DiffLineType.Hunk) {
2603
+ // const numInfo = typedI.text.split("@@")?.[1].split(" ").filter(Boolean);
2604
+ // const oldNumInfo = numInfo?.[0] || "";
2605
+ // const newNumInfo = numInfo?.[1] || "";
2606
+ // const [oldNumStartIndex, oldNumLength] = oldNumInfo.split(",");
2607
+ // const [newNumStartIndex, newNumLength] = newNumInfo.split(",");
2608
+ // const typedTypeI = typedI as DiffHunkItem;
2609
+ // typedTypeI.hunkInfo = {
2610
+ // oldStartIndex: -Number(oldNumStartIndex),
2611
+ // oldLength: Number(oldNumLength),
2612
+ // newStartIndex: +Number(newNumStartIndex),
2613
+ // newLength: Number(newNumLength),
2614
+ // };
2615
+ // }
2616
+ // return typedI;
2617
+ // });
2618
+ this.#oldFileDiffLines = {};
2619
+ this.#diffLines.forEach((item) => {
2620
+ if (item.oldLineNumber) {
2621
+ this.diffLineLength = Math.max(this.diffLineLength, item.oldLineNumber);
2622
+ this.#oldFileDiffLines[item.oldLineNumber] = item;
2545
2623
  }
2546
- else {
2547
- return p;
2548
- }
2549
- }, {});
2550
- this.#newFileDiffLines = this.#diffLines.reduce((p, c) => {
2551
- if (c.newLineNumber) {
2552
- this.diffLineLength = Math.max(this.diffLineLength, c.newLineNumber);
2553
- return { ...p, [c.newLineNumber]: c };
2554
- }
2555
- else {
2556
- return p;
2624
+ });
2625
+ this.#newFileDiffLines = {};
2626
+ this.#diffLines.forEach((item) => {
2627
+ if (item.newLineNumber) {
2628
+ this.diffLineLength = Math.max(this.diffLineLength, item.newLineNumber);
2629
+ this.#newFileDiffLines[item.newLineNumber] = item;
2557
2630
  }
2558
- }, {});
2631
+ });
2559
2632
  }
2560
2633
  #composeSyntax({ autoDetectLang, registerHighlighter, }) {
2561
2634
  this.#oldFileResult?.doSyntax({ autoDetectLang, registerHighlighter });
@@ -2623,14 +2696,27 @@ class DiffFile {
2623
2696
  const maxOldFileLineNumber = this.#oldFileResult?.maxLineNumber || 0;
2624
2697
  const maxNewFileLineNumber = this.#newFileResult?.maxLineNumber || 0;
2625
2698
  while (oldFileLineNumber <= maxOldFileLineNumber || newFileLineNumber <= maxNewFileLineNumber) {
2626
- const oldRawLine = this.#getOldRawLine(oldFileLineNumber);
2627
2699
  const oldDiffLine = this.#getOldDiffLine(oldFileLineNumber);
2628
- const newRawLine = this.#getNewRawLine(newFileLineNumber);
2629
2700
  const newDiffLine = this.#getNewDiffLine(newFileLineNumber);
2701
+ const oldRawLine = this.#getOldRawLine(oldFileLineNumber);
2702
+ const newRawLine = this.#getNewRawLine(newFileLineNumber);
2630
2703
  const oldLineHasChange = oldDiffLine?.isIncludeableLine();
2631
2704
  const newLineHasChange = newDiffLine?.isIncludeableLine();
2632
2705
  const len = this.#splitRightLines.length;
2633
2706
  const isHidden = !oldDiffLine && !newDiffLine;
2707
+ if ((oldDiffLine && !newDiffLine && oldDiffLine.newLineNumber && oldDiffLine.newLineNumber > newFileLineNumber) ||
2708
+ (!oldDiffLine && newDiffLine && newDiffLine.oldLineNumber && newDiffLine.oldLineNumber > oldFileLineNumber)) {
2709
+ if (this.#composeByDiff) {
2710
+ oldDiffLine && newFileLineNumber++;
2711
+ newDiffLine && oldFileLineNumber++;
2712
+ continue;
2713
+ }
2714
+ else {
2715
+ {
2716
+ console.error("some error happen for generate diff line!");
2717
+ }
2718
+ }
2719
+ }
2634
2720
  if (!oldDiffLine && !newRawLine && !oldDiffLine && !newDiffLine)
2635
2721
  break;
2636
2722
  if ((oldLineHasChange && newLineHasChange) || (!oldLineHasChange && !newLineHasChange)) {
@@ -2639,12 +2725,14 @@ class DiffFile {
2639
2725
  value: oldRawLine,
2640
2726
  diff: oldDiffLine,
2641
2727
  isHidden,
2728
+ _isHidden: isHidden,
2642
2729
  });
2643
2730
  this.#splitRightLines.push({
2644
2731
  lineNumber: newFileLineNumber++,
2645
2732
  value: newRawLine,
2646
2733
  diff: newDiffLine,
2647
2734
  isHidden,
2735
+ _isHidden: isHidden,
2648
2736
  });
2649
2737
  }
2650
2738
  else if (oldLineHasChange) {
@@ -2652,6 +2740,8 @@ class DiffFile {
2652
2740
  lineNumber: oldFileLineNumber++,
2653
2741
  value: oldRawLine,
2654
2742
  diff: oldDiffLine,
2743
+ isHidden,
2744
+ _isHidden: isHidden,
2655
2745
  });
2656
2746
  this.#splitRightLines.push({});
2657
2747
  }
@@ -2661,6 +2751,8 @@ class DiffFile {
2661
2751
  lineNumber: newFileLineNumber++,
2662
2752
  value: newRawLine,
2663
2753
  diff: newDiffLine,
2754
+ isHidden,
2755
+ _isHidden: isHidden,
2664
2756
  });
2665
2757
  }
2666
2758
  if (!prevIsHidden && isHidden) {
@@ -2678,18 +2770,48 @@ class DiffFile {
2678
2770
  startHiddenIndex: hideStart,
2679
2771
  endHiddenIndex: len,
2680
2772
  plainText: typedPrevious.text,
2773
+ _startHiddenIndex: hideStart,
2774
+ _endHiddenIndex: len,
2775
+ _plainText: typedPrevious.text,
2681
2776
  };
2682
2777
  hideStart = Infinity;
2683
2778
  }
2684
2779
  this.#splitHunksLines = {
2685
2780
  ...this.#splitHunksLines,
2686
- [len]: previous,
2781
+ [len]: typedPrevious,
2687
2782
  };
2688
2783
  }
2689
2784
  }
2690
2785
  }
2786
+ // have last hunk
2787
+ if (Number.isFinite(hideStart)) {
2788
+ const lastDiff = new DiffLine("", DiffLineType.Hunk, null, null, null);
2789
+ const lastHunk = lastDiff;
2790
+ lastHunk.isLast = true;
2791
+ lastHunk.splitInfo = {
2792
+ startHiddenIndex: hideStart,
2793
+ endHiddenIndex: this.#splitRightLines.length,
2794
+ _startHiddenIndex: hideStart,
2795
+ _endHiddenIndex: this.#splitRightLines.length,
2796
+ // just for placeholder
2797
+ plainText: "",
2798
+ oldStartIndex: 0,
2799
+ newStartIndex: 0,
2800
+ oldLength: 0,
2801
+ newLength: 0,
2802
+ _plainText: "",
2803
+ _oldStartIndex: 0,
2804
+ _newStartIndex: 0,
2805
+ _oldLength: 0,
2806
+ _newLength: 0,
2807
+ };
2808
+ this.#splitHunksLines = {
2809
+ ...this.#splitHunksLines,
2810
+ [this.#splitRightLines.length]: lastHunk,
2811
+ };
2812
+ hideStart = Infinity;
2813
+ }
2691
2814
  this.splitLineLength = this.#splitRightLines.length;
2692
- this.#splitLastStartIndex = hideStart;
2693
2815
  this.#hasBuildSplit = true;
2694
2816
  this.notifyAll();
2695
2817
  }
@@ -2711,6 +2833,19 @@ class DiffFile {
2711
2833
  const newLineHasChange = newDiffLine?.isIncludeableLine();
2712
2834
  const len = this.#unifiedLines.length;
2713
2835
  const isHidden = !oldDiffLine && !newDiffLine;
2836
+ if ((oldDiffLine && !newDiffLine && oldDiffLine.newLineNumber && oldDiffLine.newLineNumber > newFileLineNumber) ||
2837
+ (!oldDiffLine && newDiffLine && newDiffLine.oldLineNumber && newDiffLine.oldLineNumber > oldFileLineNumber)) {
2838
+ if (this.#composeByDiff) {
2839
+ oldDiffLine && newFileLineNumber++;
2840
+ newDiffLine && oldFileLineNumber++;
2841
+ continue;
2842
+ }
2843
+ else {
2844
+ {
2845
+ console.error("some error happen for generate diff line!");
2846
+ }
2847
+ }
2848
+ }
2714
2849
  if (!oldRawLine && !newRawLine && !newDiffLine && !oldDiffLine)
2715
2850
  break;
2716
2851
  if (!oldLineHasChange && !newLineHasChange) {
@@ -2720,6 +2855,7 @@ class DiffFile {
2720
2855
  value: newRawLine,
2721
2856
  diff: newDiffLine,
2722
2857
  isHidden,
2858
+ _isHidden: isHidden,
2723
2859
  });
2724
2860
  }
2725
2861
  else if (oldLineHasChange) {
@@ -2727,6 +2863,8 @@ class DiffFile {
2727
2863
  oldLineNumber: oldFileLineNumber++,
2728
2864
  value: oldRawLine,
2729
2865
  diff: oldDiffLine,
2866
+ isHidden,
2867
+ _isHidden: isHidden,
2730
2868
  });
2731
2869
  }
2732
2870
  else if (newLineHasChange) {
@@ -2734,6 +2872,8 @@ class DiffFile {
2734
2872
  newLineNumber: newFileLineNumber++,
2735
2873
  value: newRawLine,
2736
2874
  diff: newDiffLine,
2875
+ isHidden,
2876
+ _isHidden: isHidden,
2737
2877
  });
2738
2878
  }
2739
2879
  if (!prevIsHidden && isHidden) {
@@ -2751,18 +2891,48 @@ class DiffFile {
2751
2891
  startHiddenIndex: hideStart,
2752
2892
  endHiddenIndex: len,
2753
2893
  plainText: typedPrevious.text,
2894
+ _startHiddenIndex: hideStart,
2895
+ _endHiddenIndex: len,
2896
+ _plainText: typedPrevious.text,
2754
2897
  };
2755
2898
  hideStart = Infinity;
2756
2899
  }
2757
2900
  this.#unifiedHunksLines = {
2758
2901
  ...this.#unifiedHunksLines,
2759
- [len]: previous,
2902
+ [len]: typedPrevious,
2760
2903
  };
2761
2904
  }
2762
2905
  }
2763
2906
  }
2907
+ // have last hunk
2908
+ if (Number.isFinite(hideStart)) {
2909
+ const lastDiff = new DiffLine("", DiffLineType.Hunk, null, null, null);
2910
+ const lastHunk = lastDiff;
2911
+ lastHunk.isLast = true;
2912
+ lastHunk.unifiedInfo = {
2913
+ startHiddenIndex: hideStart,
2914
+ endHiddenIndex: this.#unifiedLines.length,
2915
+ _startHiddenIndex: hideStart,
2916
+ _endHiddenIndex: this.#unifiedLines.length,
2917
+ // just for placeholder
2918
+ plainText: "",
2919
+ oldStartIndex: 0,
2920
+ newStartIndex: 0,
2921
+ oldLength: 0,
2922
+ newLength: 0,
2923
+ _plainText: "",
2924
+ _oldStartIndex: 0,
2925
+ _newStartIndex: 0,
2926
+ _oldLength: 0,
2927
+ _newLength: 0,
2928
+ };
2929
+ this.#unifiedHunksLines = {
2930
+ ...this.#unifiedHunksLines,
2931
+ [this.#unifiedLines.length]: lastHunk,
2932
+ };
2933
+ hideStart = Infinity;
2934
+ }
2764
2935
  this.unifiedLineLength = this.#unifiedLines.length;
2765
- this.#unifiedLastStartIndex = hideStart;
2766
2936
  this.#hasBuildUnified = true;
2767
2937
  this.notifyAll();
2768
2938
  }
@@ -2775,9 +2945,9 @@ class DiffFile {
2775
2945
  getSplitHunkLine = (index) => {
2776
2946
  return this.#splitHunksLines?.[index];
2777
2947
  };
2778
- onSplitHunkExpand = (dir, index) => {
2948
+ onSplitHunkExpand = (dir, index, needTrigger = true) => {
2779
2949
  const current = this.#splitHunksLines?.[index];
2780
- if (!current)
2950
+ if (!current || !current.splitInfo)
2781
2951
  return;
2782
2952
  if (dir === "all") {
2783
2953
  for (let i = current.splitInfo.startHiddenIndex; i < current.splitInfo.endHiddenIndex; i++) {
@@ -2788,7 +2958,6 @@ class DiffFile {
2788
2958
  if (rightLine?.isHidden)
2789
2959
  rightLine.isHidden = false;
2790
2960
  }
2791
- current.splitInfo.plainText = current.text;
2792
2961
  current.splitInfo = {
2793
2962
  ...current.splitInfo,
2794
2963
  ...current.hunkInfo,
@@ -2805,13 +2974,25 @@ class DiffFile {
2805
2974
  if (rightLine?.isHidden)
2806
2975
  rightLine.isHidden = false;
2807
2976
  }
2808
- current.splitInfo = {
2809
- ...current.splitInfo,
2810
- startHiddenIndex: current.splitInfo.startHiddenIndex + composeLen,
2811
- plainText: `@@ -${current.splitInfo.oldStartIndex},${current.splitInfo.oldLength} +${current.splitInfo.newStartIndex},${current.splitInfo.newLength}`,
2812
- };
2977
+ if (current.isLast) {
2978
+ current.splitInfo = {
2979
+ ...current.splitInfo,
2980
+ startHiddenIndex: current.splitInfo.startHiddenIndex + composeLen,
2981
+ };
2982
+ }
2983
+ else {
2984
+ current.splitInfo = {
2985
+ ...current.splitInfo,
2986
+ startHiddenIndex: current.splitInfo.startHiddenIndex + composeLen,
2987
+ plainText: `@@ -${current.splitInfo.oldStartIndex},${current.splitInfo.oldLength} +${current.splitInfo.newStartIndex},${current.splitInfo.newLength}`,
2988
+ };
2989
+ }
2813
2990
  }
2814
2991
  else {
2992
+ if (current.isLast) {
2993
+ console.error("the last hunk can not expand up!");
2994
+ return;
2995
+ }
2815
2996
  for (let i = current.splitInfo.endHiddenIndex - composeLen; i < current.splitInfo.endHiddenIndex; i++) {
2816
2997
  const leftLine = this.#splitLeftLines[i];
2817
2998
  const rightLine = this.#splitRightLines[i];
@@ -2836,25 +3017,7 @@ class DiffFile {
2836
3017
  delete this.#splitHunksLines?.[index];
2837
3018
  this.#splitHunksLines[current.splitInfo.endHiddenIndex] = current;
2838
3019
  }
2839
- this.notifyAll();
2840
- };
2841
- onSplitLastExpand = (expandAll) => {
2842
- if (!this.#splitLastStartIndex || !Number.isFinite(this.#splitLastStartIndex))
2843
- return;
2844
- const start = this.#splitLastStartIndex;
2845
- const end = expandAll ? this.splitLineLength : this.#splitLastStartIndex + composeLen;
2846
- for (let i = start; i < end; i++) {
2847
- const leftLine = this.#splitLeftLines[i];
2848
- const rightLine = this.#splitRightLines[i];
2849
- if (leftLine?.isHidden)
2850
- leftLine.isHidden = false;
2851
- if (rightLine?.isHidden)
2852
- rightLine.isHidden = false;
2853
- }
2854
- this.#splitLastStartIndex = end;
2855
- this.#splitLastStartIndex =
2856
- this.#splitLastStartIndex >= this.splitLineLength ? Infinity : this.#splitLastStartIndex;
2857
- this.notifyAll();
3020
+ needTrigger && this.notifyAll();
2858
3021
  };
2859
3022
  getUnifiedLine = (index) => {
2860
3023
  return this.#unifiedLines[index];
@@ -2862,9 +3025,9 @@ class DiffFile {
2862
3025
  getUnifiedHunkLine = (index) => {
2863
3026
  return this.#unifiedHunksLines?.[index];
2864
3027
  };
2865
- onUnifiedHunkExpand = (dir, index) => {
3028
+ onUnifiedHunkExpand = (dir, index, needTrigger = true) => {
2866
3029
  const current = this.#unifiedHunksLines?.[index];
2867
- if (!current)
3030
+ if (!current || !current.unifiedInfo)
2868
3031
  return;
2869
3032
  if (dir === "all") {
2870
3033
  for (let i = current.unifiedInfo.startHiddenIndex; i < current.unifiedInfo.endHiddenIndex; i++) {
@@ -2873,7 +3036,6 @@ class DiffFile {
2873
3036
  unifiedLine.isHidden = false;
2874
3037
  }
2875
3038
  }
2876
- current.unifiedInfo.plainText = current.text;
2877
3039
  current.unifiedInfo = {
2878
3040
  ...current.unifiedInfo,
2879
3041
  ...current.hunkInfo,
@@ -2887,13 +3049,25 @@ class DiffFile {
2887
3049
  if (unifiedLine?.isHidden)
2888
3050
  unifiedLine.isHidden = false;
2889
3051
  }
2890
- current.unifiedInfo = {
2891
- ...current.unifiedInfo,
2892
- startHiddenIndex: current.unifiedInfo.startHiddenIndex + composeLen,
2893
- plainText: `@@ -${current.unifiedInfo.oldStartIndex},${current.unifiedInfo.oldLength} +${current.unifiedInfo.newStartIndex},${current.unifiedInfo.newLength}`,
2894
- };
3052
+ if (current.isLast) {
3053
+ current.unifiedInfo = {
3054
+ ...current.unifiedInfo,
3055
+ startHiddenIndex: current.unifiedInfo.startHiddenIndex + composeLen,
3056
+ };
3057
+ }
3058
+ else {
3059
+ current.unifiedInfo = {
3060
+ ...current.unifiedInfo,
3061
+ startHiddenIndex: current.unifiedInfo.startHiddenIndex + composeLen,
3062
+ plainText: `@@ -${current.unifiedInfo.oldStartIndex},${current.unifiedInfo.oldLength} +${current.unifiedInfo.newStartIndex},${current.unifiedInfo.newLength}`,
3063
+ };
3064
+ }
2895
3065
  }
2896
3066
  else {
3067
+ if (current.isLast) {
3068
+ console.error("the last hunk can not expand up!");
3069
+ return;
3070
+ }
2897
3071
  for (let i = current.unifiedInfo.endHiddenIndex - composeLen; i < current.unifiedInfo.endHiddenIndex; i++) {
2898
3072
  const unifiedLine = this.#unifiedLines[i];
2899
3073
  if (unifiedLine?.isHidden)
@@ -2915,21 +3089,87 @@ class DiffFile {
2915
3089
  delete this.#unifiedHunksLines?.[index];
2916
3090
  this.#unifiedHunksLines[current.unifiedInfo.endHiddenIndex] = current;
2917
3091
  }
3092
+ needTrigger && this.notifyAll();
3093
+ };
3094
+ onAllExpand = (mode) => {
3095
+ if (mode === "split") {
3096
+ Object.keys(this.#splitHunksLines || {}).forEach((key) => {
3097
+ this.onSplitHunkExpand("all", +key, false);
3098
+ });
3099
+ }
3100
+ else {
3101
+ Object.keys(this.#unifiedHunksLines || {}).forEach((key) => {
3102
+ this.onUnifiedHunkExpand("all", +key, false);
3103
+ });
3104
+ }
2918
3105
  this.notifyAll();
2919
3106
  };
2920
- onUnifiedLastExpand = (expandAll) => {
2921
- if (!this.#unifiedLastStartIndex || !Number.isFinite(this.#unifiedLastStartIndex))
2922
- return;
2923
- const start = this.#unifiedLastStartIndex;
2924
- const end = expandAll ? this.unifiedLineLength : this.#unifiedLastStartIndex + composeLen;
2925
- for (let i = start; i < end; i++) {
2926
- const unifiedLine = this.#unifiedLines[i];
2927
- if (unifiedLine?.isHidden)
2928
- unifiedLine.isHidden = false;
2929
- }
2930
- this.#unifiedLastStartIndex = end;
2931
- this.#unifiedLastStartIndex =
2932
- this.#unifiedLastStartIndex >= this.unifiedLineLength ? Infinity : this.#unifiedLastStartIndex;
3107
+ onAllCollapse = (mode) => {
3108
+ if (mode === "split") {
3109
+ Object.values(this.#splitLeftLines || {}).forEach((item) => {
3110
+ if (!item.isHidden && item._isHidden) {
3111
+ item.isHidden = item._isHidden;
3112
+ }
3113
+ });
3114
+ Object.values(this.#splitRightLines || {}).forEach((item) => {
3115
+ if (!item.isHidden && item._isHidden) {
3116
+ item.isHidden = item._isHidden;
3117
+ }
3118
+ });
3119
+ Object.values(this.#splitHunksLines || {}).forEach((item) => {
3120
+ if (!item.splitInfo)
3121
+ return;
3122
+ item.splitInfo = {
3123
+ ...item.splitInfo,
3124
+ oldStartIndex: item.splitInfo._oldStartIndex,
3125
+ oldLength: item.splitInfo._oldLength,
3126
+ newStartIndex: item.splitInfo._newStartIndex,
3127
+ newLength: item.splitInfo._newLength,
3128
+ startHiddenIndex: item.splitInfo._startHiddenIndex,
3129
+ endHiddenIndex: item.splitInfo._endHiddenIndex,
3130
+ plainText: item.splitInfo._plainText,
3131
+ };
3132
+ });
3133
+ Object.keys(this.#splitHunksLines || {}).forEach((key) => {
3134
+ const item = this.#splitHunksLines[key];
3135
+ if (!item.splitInfo)
3136
+ return;
3137
+ if (item.splitInfo.endHiddenIndex !== +key) {
3138
+ delete this.#splitHunksLines[key];
3139
+ this.#splitHunksLines[item.splitInfo.endHiddenIndex] = item;
3140
+ }
3141
+ });
3142
+ }
3143
+ else {
3144
+ Object.values(this.#unifiedLines || {}).forEach((item) => {
3145
+ if (!item.isHidden && item._isHidden) {
3146
+ item.isHidden = item._isHidden;
3147
+ }
3148
+ });
3149
+ Object.values(this.#unifiedHunksLines || {}).forEach((item) => {
3150
+ if (!item.unifiedInfo)
3151
+ return;
3152
+ item.unifiedInfo = {
3153
+ ...item.unifiedInfo,
3154
+ oldStartIndex: item.unifiedInfo._oldStartIndex,
3155
+ oldLength: item.unifiedInfo._oldLength,
3156
+ newStartIndex: item.unifiedInfo._newStartIndex,
3157
+ newLength: item.unifiedInfo._newLength,
3158
+ startHiddenIndex: item.unifiedInfo._startHiddenIndex,
3159
+ endHiddenIndex: item.unifiedInfo._endHiddenIndex,
3160
+ plainText: item.unifiedInfo._plainText,
3161
+ };
3162
+ });
3163
+ Object.keys(this.#unifiedHunksLines || {}).forEach((key) => {
3164
+ const item = this.#unifiedHunksLines[key];
3165
+ if (!item.unifiedInfo)
3166
+ return;
3167
+ if (item.unifiedInfo.endHiddenIndex !== +key) {
3168
+ delete this.#unifiedHunksLines[key];
3169
+ this.#unifiedHunksLines[item.unifiedInfo.endHiddenIndex] = item;
3170
+ }
3171
+ });
3172
+ }
2933
3173
  this.notifyAll();
2934
3174
  };
2935
3175
  getOldSyntaxLine = (lineNumber) => {
@@ -2954,19 +3194,6 @@ class DiffFile {
2954
3194
  });
2955
3195
  };
2956
3196
  getUpdateCount = () => this.#updateCount;
2957
- getNeedShowExpandAll = (mode) => {
2958
- if (mode === "split") {
2959
- return (this.#splitLastStartIndex &&
2960
- Number.isFinite(this.#splitLastStartIndex) &&
2961
- (this.getSplitLeftLine(this.splitLineLength - 1)?.isHidden ||
2962
- this.getSplitRightLine(this.splitLineLength - 1)?.isHidden));
2963
- }
2964
- else {
2965
- return (this.#unifiedLastStartIndex &&
2966
- Number.isFinite(this.#unifiedLastStartIndex) &&
2967
- this.getUnifiedLine(this.unifiedLineLength - 1)?.isHidden);
2968
- }
2969
- };
2970
3197
  getExpandEnabled = () => !this.#composeByDiff;
2971
3198
  getBundle = () => {
2972
3199
  // common
@@ -2987,11 +3214,10 @@ class DiffFile {
2987
3214
  const splitLeftLines = this.#splitLeftLines;
2988
3215
  const splitRightLines = this.#splitRightLines;
2989
3216
  const splitHunkLines = this.#splitHunksLines;
2990
- const splitLastStartIndex = this.#splitLastStartIndex;
2991
3217
  // unified
2992
3218
  const unifiedLines = this.#unifiedLines;
2993
3219
  const unifiedHunkLines = this.#unifiedHunksLines;
2994
- const unifiedLastStartIndex = this.#unifiedLastStartIndex;
3220
+ const version = this._version_;
2995
3221
  return {
2996
3222
  hasInitRaw,
2997
3223
  hasInitSyntax,
@@ -3008,11 +3234,10 @@ class DiffFile {
3008
3234
  splitLeftLines,
3009
3235
  splitRightLines,
3010
3236
  splitHunkLines,
3011
- splitLastStartIndex,
3012
3237
  unifiedLines,
3013
3238
  unifiedHunkLines,
3014
- unifiedLastStartIndex,
3015
3239
  composeByDiff,
3240
+ version
3016
3241
  };
3017
3242
  };
3018
3243
  mergeBundle = (data) => {
@@ -3032,10 +3257,11 @@ class DiffFile {
3032
3257
  this.#splitLeftLines = data.splitLeftLines;
3033
3258
  this.#splitRightLines = data.splitRightLines;
3034
3259
  this.#splitHunksLines = data.splitHunkLines;
3035
- this.#splitLastStartIndex = data.splitLastStartIndex;
3036
3260
  this.#unifiedLines = data.unifiedLines;
3037
3261
  this.#unifiedHunksLines = data.unifiedHunkLines;
3038
- this.#unifiedLastStartIndex = data.unifiedLastStartIndex;
3262
+ if (this._version_ !== data.version) {
3263
+ console.error('the version of the `diffInstance` is not match, some error may happen!');
3264
+ }
3039
3265
  this.notifyAll();
3040
3266
  };
3041
3267
  _addClonedInstance = (instance) => {
@@ -3111,7 +3337,6 @@ var DiffFileLineType;
3111
3337
  DiffFileLineType[DiffFileLineType["content"] = 2] = "content";
3112
3338
  DiffFileLineType[DiffFileLineType["widget"] = 3] = "widget";
3113
3339
  DiffFileLineType[DiffFileLineType["extend"] = 4] = "extend";
3114
- DiffFileLineType[DiffFileLineType["lastHunk"] = 5] = "lastHunk";
3115
3340
  })(DiffFileLineType || (DiffFileLineType = {}));
3116
3341
  const getSplitLines = (diffFile, options) => {
3117
3342
  const splitLineLength = diffFile.splitLineLength;
@@ -3139,15 +3364,6 @@ const getSplitLines = (diffFile, options) => {
3139
3364
  extendLine &&
3140
3365
  splitLines.push({ type: DiffFileLineType.extend, index, lineNumber: index + 1, extendLine: extendLine });
3141
3366
  });
3142
- const lastHunkLine = diffFile.getNeedShowExpandAll("split");
3143
- const expandEnabled = diffFile.getExpandEnabled();
3144
- if (lastHunkLine && expandEnabled) {
3145
- splitLines.push({
3146
- type: DiffFileLineType.lastHunk,
3147
- index: splitLineLength,
3148
- lineNumber: splitLineLength + 1,
3149
- });
3150
- }
3151
3367
  return splitLines;
3152
3368
  };
3153
3369
  const getSplitContentLines = (diffFile) => {
@@ -3173,15 +3389,6 @@ const getUnifiedLines = (diffFile, options) => {
3173
3389
  extendLine &&
3174
3390
  unifiedLines.push({ type: DiffFileLineType.extend, index, lineNumber: index + 1, extendLine: extendLine });
3175
3391
  });
3176
- const lastHunkLine = diffFile.getNeedShowExpandAll("unified");
3177
- const expandEnabled = diffFile.getExpandEnabled();
3178
- if (lastHunkLine && expandEnabled) {
3179
- unifiedLines.push({
3180
- type: DiffFileLineType.lastHunk,
3181
- index: unifiedLineLength,
3182
- lineNumber: unifiedLineLength + 1,
3183
- });
3184
- }
3185
3392
  return unifiedLines;
3186
3393
  };
3187
3394
  const getUnifiedContentLine = (diffFile) => {
@@ -3434,22 +3641,26 @@ const _DiffSplitHunkLine = ({ index, diffFile, side, lineNumber, }) => {
3434
3641
  currentHunk.splitInfo &&
3435
3642
  currentHunk.splitInfo.endHiddenIndex - currentHunk.splitInfo.startHiddenIndex < composeLen;
3436
3643
  const isFirstLine = currentHunk && currentHunk.index === 0;
3644
+ const isLastLine = currentHunk && currentHunk.isLast;
3437
3645
  return (React__namespace.createElement("tr", { "data-line": `${lineNumber}-hunk`, "data-state": "hunk", "data-side": exports.SplitSide[side], className: "diff-line diff-line-hunk" }, enableHunkAction ? (React__namespace.createElement(React__namespace.Fragment, null,
3438
3646
  React__namespace.createElement("td", { className: "diff-line-hunk-action sticky left-0 p-[1px] w-[1%] min-w-[40px] select-none", style: {
3439
3647
  backgroundColor: `var(${hunkLineNumberBGName})`,
3440
3648
  color: `var(${plainLineNumberColorName})`,
3441
3649
  } }, expandEnabled ? (isFirstLine ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand Up", "data-title": "Expand Up", onClick: () => diffFile.onSplitHunkExpand("up", index) },
3442
- React__namespace.createElement(ExpandUp, { className: "fill-current" }))) : isExpandAll ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand All", "data-title": "Expand All", onClick: () => diffFile.onSplitHunkExpand("all", index) },
3650
+ React__namespace.createElement(ExpandUp, { className: "fill-current" }))) : isLastLine ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px] relative", title: "Expand Down", "data-title": "Expand Down", onClick: () => {
3651
+ diffFile.onSplitHunkExpand("down", index);
3652
+ } },
3653
+ React__namespace.createElement(ExpandDown, { className: "fill-current" }))) : isExpandAll ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand All", "data-title": "Expand All", onClick: () => diffFile.onSplitHunkExpand("all", index) },
3443
3654
  React__namespace.createElement(ExpandAll, { className: "fill-current" }))) : (React__namespace.createElement(React__namespace.Fragment, null,
3444
3655
  React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[2px] cursor-pointer rounded-[2px]", title: "Expand Down", "data-title": "Expand Down", onClick: () => diffFile.onSplitHunkExpand("down", index) },
3445
3656
  React__namespace.createElement(ExpandDown, { className: "fill-current" })),
3446
3657
  React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[2px] cursor-pointer rounded-[2px]", title: "Expand Up", "data-title": "Expand Up", onClick: () => diffFile.onSplitHunkExpand("up", index) },
3447
- React__namespace.createElement(ExpandUp, { className: "fill-current" }))))) : (React__namespace.createElement("span", null, "\u2002"))),
3658
+ React__namespace.createElement(ExpandUp, { className: "fill-current" }))))) : (React__namespace.createElement("div", { className: "min-h-[28px]" }, "\u2002"))),
3448
3659
  React__namespace.createElement("td", { className: "diff-line-hunk-content pr-[10px] align-middle", style: { backgroundColor: `var(${hunkContentBGName})` } },
3449
3660
  React__namespace.createElement("div", { className: "pl-[1.5em]", style: {
3450
3661
  color: `var(${hunkContentColorName})`,
3451
3662
  } }, currentHunk.splitInfo.plainText)))) : (React__namespace.createElement("td", { className: "diff-line-hunk-placeholder select-none", colSpan: 2, style: { backgroundColor: `var(${hunkContentBGName})` } },
3452
- React__namespace.createElement("span", null, "\u2002")))));
3663
+ React__namespace.createElement("div", { className: "min-h-[28px]" }, "\u2002")))));
3453
3664
  };
3454
3665
  const DiffSplitHunkLine$1 = ({ index, diffFile, side, lineNumber, }) => {
3455
3666
  const currentHunk = diffFile.getSplitHunkLine(index);
@@ -3460,33 +3671,6 @@ const DiffSplitHunkLine$1 = ({ index, diffFile, side, lineNumber, }) => {
3460
3671
  return null;
3461
3672
  return React__namespace.createElement(_DiffSplitHunkLine, { index: index, diffFile: diffFile, side: side, lineNumber: lineNumber });
3462
3673
  };
3463
- const _DiffSplitLastHunkLine = ({ diffFile, side }) => {
3464
- const enableHunkAction = side === exports.SplitSide.old;
3465
- useSyncHeight({
3466
- selector: `tr[data-line="last-hunk"]`,
3467
- side: exports.SplitSide[exports.SplitSide.old],
3468
- enable: side === exports.SplitSide.new,
3469
- });
3470
- return (React__namespace.createElement("tr", { "data-line": "last-hunk", "data-state": "hunk", "data-side": exports.SplitSide[side], className: "diff-line diff-line-hunk" }, enableHunkAction ? (React__namespace.createElement(React__namespace.Fragment, null,
3471
- React__namespace.createElement("td", { className: "diff-line-hunk-action sticky left-0 p-[1px] w-[1%] min-w-[40px] select-none", style: {
3472
- backgroundColor: `var(${hunkLineNumberBGName})`,
3473
- color: `var(${plainLineNumberColorName})`,
3474
- } },
3475
- React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px] relative", title: "Expand Down", "data-title": "Expand Down", onClick: () => {
3476
- diffFile.onSplitLastExpand();
3477
- } },
3478
- React__namespace.createElement(ExpandDown, { className: "fill-current" }))),
3479
- React__namespace.createElement("td", { className: "diff-line-hunk-content pr-[10px] align-middle select-none", style: { backgroundColor: `var(${hunkContentBGName})` } },
3480
- React__namespace.createElement("span", null, "\u2002")))) : (React__namespace.createElement("td", { className: "diff-line-hunk-placeholder select-none", colSpan: 2, style: { backgroundColor: `var(${hunkContentBGName})` } },
3481
- React__namespace.createElement("span", null, "\u2002")))));
3482
- };
3483
- const DiffSplitLastHunkLine$1 = ({ diffFile, side }) => {
3484
- const currentIsShow = diffFile.getNeedShowExpandAll("split");
3485
- const expandEnabled = diffFile.getExpandEnabled();
3486
- if (!currentIsShow || !expandEnabled)
3487
- return null;
3488
- return React__namespace.createElement(_DiffSplitLastHunkLine, { diffFile: diffFile, side: side });
3489
- };
3490
3674
 
3491
3675
  const DiffSplitAddWidget = ({ side, className, lineNumber, onWidgetClick, onOpenAddWidget, }) => {
3492
3676
  return (React__namespace.createElement("div", { className: "diff-add-widget-wrapper" + (className ? " " + className : ""), style: {
@@ -3521,16 +3705,25 @@ const DiffUnifiedAddWidget = ({ lineNumber, side, onWidgetClick, onOpenAddWidget
3521
3705
 
3522
3706
  const DiffString = ({ rawLine, diffLine, operator, }) => {
3523
3707
  const range = diffLine?.range;
3524
- if (range && range.length > 0 && range.length < rawLine.length) {
3708
+ if (range) {
3525
3709
  const str1 = rawLine.slice(0, range.location);
3526
3710
  const str2 = rawLine.slice(range.location, range.location + range.length);
3527
3711
  const str3 = rawLine.slice(range.location + range.length);
3712
+ const isNewLineSymbolChanged = range.isNewLineSymbolChanged;
3528
3713
  return (React__namespace.createElement("span", { className: "diff-line-content-raw" },
3529
3714
  React__namespace.createElement("span", { "data-range-start": range.location, "data-range-end": range.location + range.length },
3530
3715
  str1,
3531
3716
  React__namespace.createElement("span", { "data-diff-highlight": true, className: "rounded-[0.2em]", style: {
3532
3717
  backgroundColor: operator === "add" ? `var(${addContentHighlightBGName})` : `var(${delContentHighlightBGName})`,
3533
- } }, str2 === "\r" ? "␍" : str2 === "\n" ? "␊" : str2 === "\r\n" ? "␍␊" : str2),
3718
+ } }, isNewLineSymbolChanged
3719
+ ? str2 === "\r"
3720
+ ? "␍"
3721
+ : str2 === "\n"
3722
+ ? "␊"
3723
+ : str2 === "\r\n"
3724
+ ? "␍␊"
3725
+ : str2
3726
+ : str2),
3534
3727
  str3)));
3535
3728
  }
3536
3729
  return React__namespace.createElement("span", { className: "diff-line-content-raw" }, rawLine);
@@ -3540,7 +3733,7 @@ const DiffSyntax = ({ rawLine, diffLine, operator, syntaxLine, }) => {
3540
3733
  return React__namespace.createElement(DiffString, { rawLine: rawLine, diffLine: diffLine, operator: operator });
3541
3734
  }
3542
3735
  const range = diffLine?.range;
3543
- if (range && range.length > 0 && range.length < syntaxLine.valueLength) {
3736
+ if (range) {
3544
3737
  return (React__namespace.createElement("span", { className: "diff-line-syntax-raw" },
3545
3738
  React__namespace.createElement("span", { "data-range-start": range.location, "data-range-end": range.location + range.length }, syntaxLine.nodeList?.map(({ node, wrapper }, index) => {
3546
3739
  if (node.endIndex < range.location || range.location + range.length < node.startIndex) {
@@ -3554,6 +3747,7 @@ const DiffSyntax = ({ rawLine, diffLine, operator, syntaxLine, }) => {
3554
3747
  const str3 = node.value.slice(index1 + range.length);
3555
3748
  const isStart = str1.length || range.location === node.startIndex;
3556
3749
  const isEnd = str3.length || node.endIndex === range.location + range.length - 1;
3750
+ const isNewLineSymbolChanged = range.isNewLineSymbolChanged;
3557
3751
  return (React__namespace.createElement("span", { key: index, "data-start": node.startIndex, "data-end": node.endIndex, className: wrapper?.properties?.className?.join(" ") },
3558
3752
  str1,
3559
3753
  React__namespace.createElement("span", { "data-diff-highlight": true, style: {
@@ -3562,7 +3756,15 @@ const DiffSyntax = ({ rawLine, diffLine, operator, syntaxLine, }) => {
3562
3756
  borderBottomLeftRadius: isStart ? "0.2em" : undefined,
3563
3757
  borderTopRightRadius: isEnd ? "0.2em" : undefined,
3564
3758
  borderBottomRightRadius: isEnd ? "0.2em" : undefined,
3565
- } }, str2 === "\r" ? "␍" : str2 === "\n" ? "␊" : str2 === "\r\n" ? "␍␊" : str2),
3759
+ } }, isNewLineSymbolChanged
3760
+ ? str2 === "\r"
3761
+ ? "␍"
3762
+ : str2 === "\n"
3763
+ ? "␊"
3764
+ : str2 === "\r\n"
3765
+ ? "␍␊"
3766
+ : str2
3767
+ : str2),
3566
3768
  str3));
3567
3769
  }
3568
3770
  }))));
@@ -3725,7 +3927,7 @@ const DiffSplitViewTable = ({ side, diffFile, width }) => {
3725
3927
  React__namespace.createElement(DiffSplitLine$1, { index: line.index, side: side, lineNumber: line.lineNumber, diffFile: diffFile }),
3726
3928
  React__namespace.createElement(DiffSplitWidgetLine$1, { index: line.index, side: side, lineNumber: line.lineNumber, diffFile: diffFile }),
3727
3929
  React__namespace.createElement(DiffSplitExtendLine$1, { index: line.index, side: side, lineNumber: line.lineNumber, diffFile: diffFile })))),
3728
- React__namespace.createElement(DiffSplitLastHunkLine$1, { side: side, diffFile: diffFile }))));
3930
+ React__namespace.createElement(DiffSplitHunkLine$1, { side: side, index: diffFile.splitLineLength, lineNumber: diffFile.splitLineLength, diffFile: diffFile }))));
3729
3931
  };
3730
3932
  const DiffSplitViewNormal = React.memo(({ diffFile }) => {
3731
3933
  const ref1 = React.useRef(null);
@@ -3815,42 +4017,26 @@ const DiffSplitHunkLine = ({ index, diffFile, lineNumber, }) => {
3815
4017
  currentHunk.splitInfo &&
3816
4018
  currentHunk.splitInfo.startHiddenIndex < currentHunk.splitInfo.endHiddenIndex;
3817
4019
  const isFirstLine = currentHunk && currentHunk.index === 0;
4020
+ const isLastLine = currentHunk && currentHunk.isLast;
3818
4021
  if (!currentIsShow)
3819
4022
  return null;
3820
4023
  return (React__namespace.createElement("tr", { "data-line": `${lineNumber}-hunk`, "data-state": "hunk", className: "diff-line diff-line-hunk" },
3821
4024
  React__namespace.createElement("td", { className: "diff-line-hunk-action p-[1px] w-[1%] min-w-[40px] select-none", style: {
3822
4025
  backgroundColor: `var(${hunkLineNumberBGName})`,
3823
4026
  color: `var(${plainLineNumberColorName})`,
3824
- } }, expandEnabled &&
3825
- (isFirstLine ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand Up", "data-title": "Expand Up", onClick: () => diffFile.onSplitHunkExpand("up", index) },
3826
- React__namespace.createElement(ExpandUp, { className: "fill-current" }))) : isExpandAll ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand All", "data-title": "Expand All", onClick: () => diffFile.onSplitHunkExpand("all", index) },
3827
- React__namespace.createElement(ExpandAll, { className: "fill-current" }))) : (React__namespace.createElement(React__namespace.Fragment, null,
3828
- React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[2px] cursor-pointer rounded-[2px]", title: "Expand Down", "data-title": "Expand Down", onClick: () => diffFile.onSplitHunkExpand("down", index) },
3829
- React__namespace.createElement(ExpandDown, { className: "fill-current" })),
3830
- React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[2px] cursor-pointer rounded-[2px]", title: "Expand Up", "data-title": "Expand Up", onClick: () => diffFile.onSplitHunkExpand("up", index) },
3831
- React__namespace.createElement(ExpandUp, { className: "fill-current" })))))),
4027
+ } }, expandEnabled ? (isFirstLine ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand Up", "data-title": "Expand Up", onClick: () => diffFile.onSplitHunkExpand("up", index) },
4028
+ React__namespace.createElement(ExpandUp, { className: "fill-current" }))) : isLastLine ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand Down", "data-title": "Expand Down", onClick: () => diffFile.onSplitHunkExpand("down", index) },
4029
+ React__namespace.createElement(ExpandDown, { className: "fill-current" }))) : isExpandAll ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand All", "data-title": "Expand All", onClick: () => diffFile.onSplitHunkExpand("all", index) },
4030
+ React__namespace.createElement(ExpandAll, { className: "fill-current" }))) : (React__namespace.createElement(React__namespace.Fragment, null,
4031
+ React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[2px] cursor-pointer rounded-[2px]", title: "Expand Down", "data-title": "Expand Down", onClick: () => diffFile.onSplitHunkExpand("down", index) },
4032
+ React__namespace.createElement(ExpandDown, { className: "fill-current" })),
4033
+ React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[2px] cursor-pointer rounded-[2px]", title: "Expand Up", "data-title": "Expand Up", onClick: () => diffFile.onSplitHunkExpand("up", index) },
4034
+ React__namespace.createElement(ExpandUp, { className: "fill-current" }))))) : (React__namespace.createElement("div", { className: "min-h-[28px]" }, "\u2002"))),
3832
4035
  React__namespace.createElement("td", { className: "diff-line-hunk-content pr-[10px] align-middle", style: { backgroundColor: `var(${hunkContentBGName})` }, colSpan: 3 },
3833
4036
  React__namespace.createElement("div", { className: "pl-[1.5em]", style: {
3834
4037
  color: `var(${hunkContentColorName})`,
3835
4038
  } }, currentHunk.splitInfo.plainText))));
3836
4039
  };
3837
- const DiffSplitLastHunkLine = ({ diffFile }) => {
3838
- const currentIsShow = diffFile.getNeedShowExpandAll("split");
3839
- const expandEnabled = diffFile.getExpandEnabled();
3840
- if (!currentIsShow || !expandEnabled)
3841
- return null;
3842
- return (React__namespace.createElement("tr", { "data-line": "last-hunk", "data-state": "hunk", className: "diff-line diff-line-hunk" },
3843
- React__namespace.createElement("td", { className: "diff-line-hunk-action p-[1px] w-[1%] min-w-[40px] select-none", style: {
3844
- backgroundColor: `var(${hunkLineNumberBGName})`,
3845
- color: `var(${plainLineNumberColorName})`,
3846
- } },
3847
- React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand Down", "data-title": "Expand Down", onClick: () => {
3848
- diffFile.onSplitLastExpand();
3849
- } },
3850
- React__namespace.createElement(ExpandDown, { className: "fill-current" }))),
3851
- React__namespace.createElement("td", { className: "diff-line-hunk-content pr-[10px] align-middle select-none", colSpan: 3, style: { backgroundColor: `var(${hunkContentBGName})` } },
3852
- React__namespace.createElement("span", null, "\u2002"))));
3853
- };
3854
4040
 
3855
4041
  const _DiffSplitLine = ({ index, diffFile, lineNumber }) => {
3856
4042
  const oldLine = diffFile.getSplitLeftLine(index);
@@ -3943,7 +4129,6 @@ const DiffSplitWidgetLine = ({ index, diffFile, lineNumber, }) => {
3943
4129
  return React__namespace.createElement(_DiffSplitWidgetLine, { index: index, diffFile: diffFile, lineNumber: lineNumber });
3944
4130
  };
3945
4131
 
3946
- /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
3947
4132
  const Style = ({ useSelector, id, }) => {
3948
4133
  const splitRef = useSelector((s) => s.splitRef);
3949
4134
  return (React__namespace.createElement("style", null, splitRef === exports.SplitSide.old
@@ -4014,7 +4199,7 @@ const DiffSplitViewWrap = React.memo(({ diffFile }) => {
4014
4199
  React__namespace.createElement(DiffSplitLine, { index: line.index, lineNumber: line.lineNumber, diffFile: diffFile }),
4015
4200
  React__namespace.createElement(DiffSplitWidgetLine, { index: line.index, lineNumber: line.lineNumber, diffFile: diffFile }),
4016
4201
  React__namespace.createElement(DiffSplitExtendLine, { index: line.index, lineNumber: line.lineNumber, diffFile: diffFile })))),
4017
- React__namespace.createElement(DiffSplitLastHunkLine, { diffFile: diffFile }))))));
4202
+ React__namespace.createElement(DiffSplitHunkLine, { index: diffFile.splitLineLength, lineNumber: diffFile.splitLineLength, diffFile: diffFile }))))));
4018
4203
  });
4019
4204
  DiffSplitViewWrap.displayName = "DiffSplitViewWrap";
4020
4205
 
@@ -4026,11 +4211,14 @@ const DiffSplitView = React.memo(({ diffFile }) => {
4026
4211
  const widgetSide = reactivityStore.ref(undefined);
4027
4212
  const widgetLineNumber = reactivityStore.ref(undefined);
4028
4213
  const setWidget = ({ side, lineNumber }) => {
4214
+ const { renderWidgetLine } = useDiffContext.getReadonlyState();
4215
+ if (typeof renderWidgetLine !== "function")
4216
+ return;
4029
4217
  widgetSide.value = side;
4030
4218
  widgetLineNumber.value = lineNumber;
4031
4219
  };
4032
4220
  return { widgetSide, widgetLineNumber, setWidget };
4033
- }), []);
4221
+ }), [useDiffContext]);
4034
4222
  const contextValue = React.useMemo(() => ({ useWidget }), [useWidget]);
4035
4223
  shim.useSyncExternalStore(diffFile.subscribe, diffFile.getUpdateCount);
4036
4224
  React.useEffect(() => {
@@ -4093,17 +4281,19 @@ const _DiffUnifiedHunkLine = ({ index, diffFile, lineNumber, }) => {
4093
4281
  currentHunk.unifiedInfo &&
4094
4282
  currentHunk.unifiedInfo.endHiddenIndex - currentHunk.unifiedInfo.startHiddenIndex < composeLen;
4095
4283
  const isFirstLine = currentHunk && currentHunk.index === 0;
4284
+ const isLastLine = currentHunk && currentHunk.isLast;
4096
4285
  return (React__namespace.createElement("tr", { "data-line": `${lineNumber}-hunk`, "data-state": "hunk", className: "diff-line diff-line-hunk" },
4097
4286
  React__namespace.createElement("td", { className: "diff-line-hunk-action sticky left-0 p-[1px] w-[1%] min-w-[100px] select-none", style: {
4098
4287
  backgroundColor: `var(${hunkLineNumberBGName})`,
4099
4288
  color: `var(${plainLineNumberColorName})`,
4100
4289
  } }, expandEnabled ? (isFirstLine ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand Up", "data-title": "Expand Up", onClick: () => diffFile.onUnifiedHunkExpand("up", index) },
4101
- React__namespace.createElement(ExpandUp, { className: "fill-current" }))) : isExpandAll ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand All", "data-title": "Expand All", onClick: () => diffFile.onUnifiedHunkExpand("all", index) },
4290
+ React__namespace.createElement(ExpandUp, { className: "fill-current" }))) : isLastLine ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand Down", "data-title": "Expand Down", onClick: () => diffFile.onUnifiedHunkExpand("down", index) },
4291
+ React__namespace.createElement(ExpandDown, { className: "fill-current" }))) : isExpandAll ? (React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand All", "data-title": "Expand All", onClick: () => diffFile.onUnifiedHunkExpand("all", index) },
4102
4292
  React__namespace.createElement(ExpandAll, { className: "fill-current" }))) : (React__namespace.createElement(React__namespace.Fragment, null,
4103
4293
  React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[2px] cursor-pointer rounded-[2px]", title: "Expand Down", "data-title": "Expand Down", onClick: () => diffFile.onUnifiedHunkExpand("down", index) },
4104
4294
  React__namespace.createElement(ExpandDown, { className: "fill-current" })),
4105
4295
  React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[2px] cursor-pointer rounded-[2px]", title: "Expand Up", "data-title": "Expand Up", onClick: () => diffFile.onUnifiedHunkExpand("up", index) },
4106
- React__namespace.createElement(ExpandUp, { className: "fill-current" }))))) : null),
4296
+ React__namespace.createElement(ExpandUp, { className: "fill-current" }))))) : (React__namespace.createElement("div", { className: "min-h-[28px]" }, "\u2002"))),
4107
4297
  React__namespace.createElement("td", { className: "diff-line-hunk-content pr-[10px] align-middle", style: { backgroundColor: `var(${hunkContentBGName})` } },
4108
4298
  React__namespace.createElement("div", { className: "pl-[1.5em]", style: {
4109
4299
  whiteSpace: enableWrap ? "pre-wrap" : "pre",
@@ -4120,21 +4310,6 @@ const DiffUnifiedHunkLine = ({ index, diffFile, lineNumber, }) => {
4120
4310
  return null;
4121
4311
  return React__namespace.createElement(_DiffUnifiedHunkLine, { index: index, diffFile: diffFile, lineNumber: lineNumber });
4122
4312
  };
4123
- const DiffUnifiedLastHunkLine = ({ diffFile }) => {
4124
- const currentIsShow = diffFile.getNeedShowExpandAll("unified");
4125
- const expandEnabled = diffFile.getExpandEnabled();
4126
- if (!currentIsShow || !expandEnabled)
4127
- return null;
4128
- return (React__namespace.createElement("tr", { "data-line": "last-hunk", "data-state": "hunk", className: "diff-line diff-line-hunk" },
4129
- React__namespace.createElement("td", { className: "diff-line-hunk-action sticky left-0 w-[1%] min-w-[100px] select-none", style: {
4130
- backgroundColor: `var(${hunkLineNumberBGName})`,
4131
- color: `var(${plainLineNumberColorName})`,
4132
- } },
4133
- React__namespace.createElement("button", { className: "w-full diff-widget-tooltip hover:bg-blue-300 flex justify-center items-center py-[6px] cursor-pointer rounded-[2px]", title: "Expand Down", "data-title": "Expand Down", onClick: () => diffFile.onUnifiedLastExpand() },
4134
- React__namespace.createElement(ExpandDown, { className: "fill-current" }))),
4135
- React__namespace.createElement("td", { className: "diff-line-hunk-content pr-[10px] align-middle", style: { backgroundColor: `var(${hunkContentBGName})` } },
4136
- React__namespace.createElement("span", null, "\u2002"))));
4137
- };
4138
4313
 
4139
4314
  const DiffUnifiedOldLine = ({ index, diffLine, rawLine, syntaxLine, lineNumber, diffFile, setWidget, enableWrap, enableAddWidget, enableHighlight, onAddWidgetClick, }) => {
4140
4315
  return (React__namespace.createElement("tr", { "data-line": index, "data-state": "diff", className: "diff-line group" },
@@ -4262,16 +4437,20 @@ const onMouseDown = (e) => {
4262
4437
  }
4263
4438
  };
4264
4439
  const DiffUnifiedView = React.memo(({ diffFile }) => {
4440
+ const { useDiffContext } = useDiffViewContext();
4265
4441
  // performance optimization
4266
4442
  const useWidget = React.useMemo(() => reactivityStore.createStore(() => {
4267
4443
  const widgetSide = reactivityStore.ref(undefined);
4268
4444
  const widgetLineNumber = reactivityStore.ref(undefined);
4269
4445
  const setWidget = ({ side, lineNumber }) => {
4446
+ const { renderWidgetLine } = useDiffContext.getReadonlyState();
4447
+ if (typeof renderWidgetLine !== "function")
4448
+ return;
4270
4449
  widgetSide.value = side;
4271
4450
  widgetLineNumber.value = lineNumber;
4272
4451
  };
4273
4452
  return { widgetSide, widgetLineNumber, setWidget };
4274
- }), []);
4453
+ }), [useDiffContext]);
4275
4454
  const contextValue = React.useMemo(() => ({ useWidget }), [useWidget]);
4276
4455
  shim.useSyncExternalStore(diffFile.subscribe, diffFile.getUpdateCount);
4277
4456
  React.useEffect(() => {
@@ -4296,7 +4475,7 @@ const DiffUnifiedView = React.memo(({ diffFile }) => {
4296
4475
  React__namespace.createElement(DiffUnifiedLine, { index: item.index, lineNumber: item.lineNumber, diffFile: diffFile }),
4297
4476
  React__namespace.createElement(DiffUnifiedWidgetLine, { index: item.index, lineNumber: item.lineNumber, diffFile: diffFile }),
4298
4477
  React__namespace.createElement(DiffUnifiedExtendLine, { index: item.index, lineNumber: item.lineNumber, diffFile: diffFile })))),
4299
- React__namespace.createElement(DiffUnifiedLastHunkLine, { diffFile: diffFile })))))));
4478
+ React__namespace.createElement(DiffUnifiedHunkLine, { index: diffFile.unifiedLineLength, lineNumber: diffFile.unifiedLineLength, diffFile: diffFile })))))));
4300
4479
  });
4301
4480
  DiffUnifiedView.displayName = "DiffUnifiedView";
4302
4481
 
@@ -4409,7 +4588,7 @@ const _InternalDiffView = (props) => {
4409
4588
  ]);
4410
4589
  const value = React.useMemo(() => ({ useDiffContext }), [useDiffContext]);
4411
4590
  return (React__namespace.createElement(DiffViewContext.Provider, { value: value },
4412
- React__namespace.createElement("div", { className: "diff-tailwindcss-wrapper" },
4591
+ React__namespace.createElement("div", { className: "diff-tailwindcss-wrapper", "data-component": "git-diff-view", "data-version": `${"0.0.6"}` },
4413
4592
  React__namespace.createElement("div", { className: "diff-style-root", style: {
4414
4593
  // @ts-ignore
4415
4594
  [diffFontSizeName]: diffViewFontSize + "px",
@@ -4417,7 +4596,7 @@ const _InternalDiffView = (props) => {
4417
4596
  React__namespace.createElement("div", { id: `diff-root${diffFileId}`, className: "diff-view-wrapper" + (className ? ` ${className}` : ""), style: style }, diffViewMode === exports.DiffModeEnum.Split ? (React__namespace.createElement(DiffSplitView, { diffFile: diffFile })) : (React__namespace.createElement(DiffUnifiedView, { diffFile: diffFile })))))));
4418
4597
  };
4419
4598
  const InternalDiffView = React.memo(_InternalDiffView);
4420
- const DiffView = (props) => {
4599
+ const DiffViewWithRef = (props, ref) => {
4421
4600
  const { registerHighlighter, autoDetectLang, data, diffFile: _diffFile, ...restProps } = props;
4422
4601
  const diffFile = React.useMemo(() => {
4423
4602
  if (_diffFile) {
@@ -4454,11 +4633,14 @@ const DiffView = (props) => {
4454
4633
  }
4455
4634
  }, [diffFile, _diffFile]);
4456
4635
  useUnmount(() => diffFile._destroy(), [diffFile]);
4636
+ React.useImperativeHandle(ref, () => ({ getDiffFileInstance: () => diffFile }), [diffFile]);
4457
4637
  if (!diffFile)
4458
4638
  return null;
4459
4639
  return (React__namespace.createElement(InternalDiffView, { key: diffFile.getId(), ...restProps, diffFile: diffFile, diffViewFontSize: restProps.diffViewFontSize || 14 }));
4460
4640
  };
4461
- const version = "0.0.5";
4641
+ const DiffView = React.forwardRef(DiffViewWithRef);
4642
+ DiffView.displayName = "DiffView";
4643
+ const version = "0.0.6";
4462
4644
 
4463
4645
  exports.DiffView = DiffView;
4464
4646
  exports.DiffViewContext = DiffViewContext;