@pierre/diffs 1.1.7 → 1.1.9

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 (65) hide show
  1. package/dist/components/AdvancedVirtualizedFileDiff.d.ts.map +1 -1
  2. package/dist/components/File.d.ts.map +1 -1
  3. package/dist/components/FileDiff.js +2 -2
  4. package/dist/components/FileDiff.js.map +1 -1
  5. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  6. package/dist/components/VirtualizedFileDiff.js +1 -1
  7. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  8. package/dist/index.d.ts +4 -3
  9. package/dist/index.js +2 -1
  10. package/dist/managers/InteractionManager.d.ts +15 -2
  11. package/dist/managers/InteractionManager.d.ts.map +1 -1
  12. package/dist/managers/InteractionManager.js +143 -40
  13. package/dist/managers/InteractionManager.js.map +1 -1
  14. package/dist/react/index.d.ts +2 -2
  15. package/dist/renderers/DiffHunksRenderer.js +11 -10
  16. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  17. package/dist/renderers/FileRenderer.js +3 -1
  18. package/dist/renderers/FileRenderer.js.map +1 -1
  19. package/dist/ssr/FileDiffReact.js +1 -1
  20. package/dist/ssr/index.d.ts +2 -2
  21. package/dist/ssr/preloadDiffs.js +1 -1
  22. package/dist/ssr/preloadDiffs.js.map +1 -1
  23. package/dist/style.js +1 -1
  24. package/dist/style.js.map +1 -1
  25. package/dist/types.d.ts +23 -2
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/utils/areDiffRenderOptionsEqual.d.ts +7 -0
  28. package/dist/utils/areDiffRenderOptionsEqual.d.ts.map +1 -0
  29. package/dist/utils/areDiffRenderOptionsEqual.js +10 -0
  30. package/dist/utils/areDiffRenderOptionsEqual.js.map +1 -0
  31. package/dist/utils/areOptionsEqual.d.ts +2 -1
  32. package/dist/utils/areOptionsEqual.d.ts.map +1 -1
  33. package/dist/utils/areOptionsEqual.js +8 -1
  34. package/dist/utils/areOptionsEqual.js.map +1 -1
  35. package/dist/utils/createTransformerWithState.d.ts +1 -1
  36. package/dist/utils/createTransformerWithState.d.ts.map +1 -1
  37. package/dist/utils/createTransformerWithState.js +27 -2
  38. package/dist/utils/createTransformerWithState.js.map +1 -1
  39. package/dist/utils/parseDiffFromFile.js +1 -0
  40. package/dist/utils/parseDiffFromFile.js.map +1 -1
  41. package/dist/utils/renderDiffWithHighlighter.js +6 -3
  42. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  43. package/dist/utils/renderFileWithHighlighter.d.ts +2 -1
  44. package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
  45. package/dist/utils/renderFileWithHighlighter.js +2 -2
  46. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  47. package/dist/utils/shouldUseTokenTransformer.d.ts +9 -0
  48. package/dist/utils/shouldUseTokenTransformer.d.ts.map +1 -0
  49. package/dist/utils/shouldUseTokenTransformer.js +8 -0
  50. package/dist/utils/shouldUseTokenTransformer.js.map +1 -0
  51. package/dist/utils/wrapTokenFragments.d.ts +10 -0
  52. package/dist/utils/wrapTokenFragments.d.ts.map +1 -0
  53. package/dist/utils/wrapTokenFragments.js +82 -0
  54. package/dist/utils/wrapTokenFragments.js.map +1 -0
  55. package/dist/worker/WorkerPoolManager.d.ts +4 -0
  56. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  57. package/dist/worker/WorkerPoolManager.js +11 -6
  58. package/dist/worker/WorkerPoolManager.js.map +1 -1
  59. package/dist/worker/types.d.ts +2 -0
  60. package/dist/worker/types.d.ts.map +1 -1
  61. package/dist/worker/worker-portable.js +142 -8
  62. package/dist/worker/worker-portable.js.map +1 -1
  63. package/dist/worker/worker.js +124 -8
  64. package/dist/worker/worker.js.map +1 -1
  65. package/package.json +1 -1
@@ -6,6 +6,7 @@ import { toHtml } from "hast-util-to-html";
6
6
  //#region src/managers/InteractionManager.ts
7
7
  var InteractionManager = class {
8
8
  hoveredLine;
9
+ hoveredToken;
9
10
  pre;
10
11
  gutterUtilityContainer;
11
12
  gutterUtilityButton;
@@ -39,6 +40,7 @@ var InteractionManager = class {
39
40
  this.gutterUtilityButton = void 0;
40
41
  this.gutterUtilitySlot = void 0;
41
42
  this.clearHoveredLine();
43
+ this.clearHoveredToken();
42
44
  this.detachDocumentPointerListeners();
43
45
  this.clearPointerSession();
44
46
  if (this.queuedSelectionRender != null) {
@@ -97,8 +99,8 @@ var InteractionManager = class {
97
99
  }
98
100
  };
99
101
  handlePointerClick = (event) => {
100
- const { onHunkExpand, onLineClick, onLineNumberClick, onMergeConflictActionClick } = this.options;
101
- if (onHunkExpand == null && onLineClick == null && onLineNumberClick == null && onMergeConflictActionClick == null) return;
102
+ const { onHunkExpand, onLineClick, onLineNumberClick, onTokenClick, onMergeConflictActionClick } = this.options;
103
+ if (onHunkExpand == null && onLineClick == null && onLineNumberClick == null && onMergeConflictActionClick == null && onTokenClick == null) return;
102
104
  if (this.options.onGutterUtilityClick != null && isGutterUtilityPointerPath(event.composedPath())) return;
103
105
  debugLogIfEnabled(this.options.__debugPointerEvents, "click", "FileDiff.DEBUG.handlePointerClick:", event);
104
106
  this.handlePointerEvent({
@@ -107,8 +109,8 @@ var InteractionManager = class {
107
109
  });
108
110
  };
109
111
  handlePointerMove = (event) => {
110
- const { lineHoverHighlight = "disabled", onLineEnter, onLineLeave, enableGutterUtility = false } = this.options;
111
- if (lineHoverHighlight === "disabled" && !enableGutterUtility && onLineEnter == null && onLineLeave == null) return;
112
+ const { lineHoverHighlight = "disabled", onLineEnter, onLineLeave, onTokenEnter, onTokenLeave, enableGutterUtility = false } = this.options;
113
+ if (lineHoverHighlight === "disabled" && !enableGutterUtility && onLineEnter == null && onLineLeave == null && onTokenEnter == null && onTokenLeave == null) return;
112
114
  debugLogIfEnabled(this.options.__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerMove:", event);
113
115
  this.handlePointerEvent({
114
116
  eventType: "move",
@@ -118,16 +120,22 @@ var InteractionManager = class {
118
120
  handlePointerLeave = (event) => {
119
121
  const { __debugPointerEvents } = this.options;
120
122
  debugLogIfEnabled(__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerLeave: no event");
121
- if (this.hoveredLine == null) {
122
- debugLogIfEnabled(__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerLeave: returned early, no .hoveredLine");
123
+ if (this.hoveredLine == null && this.hoveredToken == null) {
124
+ debugLogIfEnabled(__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerLeave: returned early, no hovered line or token");
123
125
  return;
124
126
  }
125
127
  this.gutterUtilityContainer?.remove();
126
- this.options.onLineLeave?.({
127
- ...this.hoveredLine,
128
- event
129
- });
130
- this.clearHoveredLine();
128
+ if (this.hoveredToken != null) {
129
+ this.options.onTokenLeave?.(this.hoveredToken, event);
130
+ this.clearHoveredToken();
131
+ }
132
+ if (this.hoveredLine != null) {
133
+ this.options.onLineLeave?.({
134
+ ...this.hoveredLine,
135
+ event
136
+ });
137
+ this.clearHoveredLine();
138
+ }
131
139
  };
132
140
  handlePointerEvent({ eventType, event }) {
133
141
  const { __debugPointerEvents } = this.options;
@@ -138,27 +146,40 @@ var InteractionManager = class {
138
146
  });
139
147
  const target = this.resolvePointerTarget(composedPath);
140
148
  debugLogIfEnabled(__debugPointerEvents, eventType, "FileDiff.DEBUG.handlePointerEvent: resolvePointerTarget result:", target);
141
- const { onLineClick, onLineNumberClick, onLineEnter, onLineLeave, onHunkExpand, onMergeConflictActionClick } = this.options;
149
+ const { onLineClick, onLineNumberClick, onLineEnter, onLineLeave, onTokenClick, onTokenEnter, onTokenLeave, onHunkExpand, onMergeConflictActionClick } = this.options;
142
150
  switch (eventType) {
143
- case "move":
144
- if (isLinePointerTarget(target) && this.hoveredLine?.lineElement === target.lineElement) break;
145
- if (this.hoveredLine != null) {
146
- this.gutterUtilityContainer?.remove();
147
- onLineLeave?.({
148
- ...this.hoveredLine,
149
- event
150
- });
151
- this.clearHoveredLine();
151
+ case "move": {
152
+ const sameLine = isHoverableLinePointerTarget(target) && this.hoveredLine?.lineElement === target.lineElement;
153
+ if (!(isTokenPointerTarget(target) && this.hoveredToken?.tokenElement === target.tokenElement)) {
154
+ if (this.hoveredToken != null) {
155
+ onTokenLeave?.(this.hoveredToken, event);
156
+ this.clearHoveredToken();
157
+ }
158
+ if (isTokenPointerTarget(target)) {
159
+ this.setHoveredToken(this.toTokenEventBaseProps(target));
160
+ onTokenEnter?.(this.hoveredToken, event);
161
+ }
152
162
  }
153
- if (isLinePointerTarget(target)) {
154
- this.setHoveredLine(this.toEventBaseProps(target));
155
- if (this.gutterUtilityContainer != null) target.numberElement.appendChild(this.gutterUtilityContainer);
156
- onLineEnter?.({
157
- ...this.hoveredLine,
158
- event
159
- });
163
+ if (!sameLine) {
164
+ if (this.hoveredLine != null) {
165
+ this.gutterUtilityContainer?.remove();
166
+ onLineLeave?.({
167
+ ...this.hoveredLine,
168
+ event
169
+ });
170
+ this.clearHoveredLine();
171
+ }
172
+ if (isHoverableLinePointerTarget(target)) {
173
+ this.setHoveredLine(this.toEventBaseProps(target));
174
+ if (this.gutterUtilityContainer != null) target.numberElement.appendChild(this.gutterUtilityContainer);
175
+ onLineEnter?.({
176
+ ...this.hoveredLine,
177
+ event
178
+ });
179
+ }
160
180
  }
161
181
  break;
182
+ }
162
183
  case "click": {
163
184
  if (target == null) break;
164
185
  if (isMergeConflictActionPointerTarget(target) && onMergeConflictActionClick != null) {
@@ -169,7 +190,8 @@ var InteractionManager = class {
169
190
  onHunkExpand(target.hunkIndex, event.shiftKey ? "both" : target.direction, event.shiftKey ? Number.POSITIVE_INFINITY : void 0);
170
191
  break;
171
192
  }
172
- if (!isLinePointerTarget(target)) break;
193
+ if (!isHoverableLinePointerTarget(target)) break;
194
+ if (isTokenPointerTarget(target) && onTokenClick != null) onTokenClick(this.toTokenEventBaseProps(target), event);
173
195
  const eventBase = this.toEventBaseProps(target);
174
196
  if (onLineNumberClick != null && target.numberColumn) onLineNumberClick({
175
197
  ...eventBase,
@@ -184,9 +206,9 @@ var InteractionManager = class {
184
206
  }
185
207
  }
186
208
  syncPointerListeners(pre) {
187
- const { __debugPointerEvents, lineHoverHighlight = "disabled", onLineClick, onLineNumberClick, onLineEnter, onLineLeave, onHunkExpand, onMergeConflictActionClick, enableGutterUtility = false, enableLineSelection = false, onGutterUtilityClick } = this.options;
209
+ const { __debugPointerEvents, lineHoverHighlight = "disabled", onLineClick, onLineNumberClick, onLineEnter, onLineLeave, onTokenClick, onTokenEnter, onTokenLeave, onHunkExpand, onMergeConflictActionClick, enableGutterUtility = false, enableLineSelection = false, onGutterUtilityClick } = this.options;
188
210
  const enableGutterSelection = onGutterUtilityClick != null;
189
- const shouldAttachPointerListeners = lineHoverHighlight !== "disabled" || onLineClick != null || onLineNumberClick != null || onHunkExpand != null || onMergeConflictActionClick != null || onLineEnter != null || onLineLeave != null || enableGutterUtility || enableLineSelection || enableGutterSelection;
211
+ const shouldAttachPointerListeners = lineHoverHighlight !== "disabled" || onLineClick != null || onLineNumberClick != null || onLineEnter != null || onLineLeave != null || onTokenClick != null || onTokenEnter != null || onTokenLeave != null || onHunkExpand != null || onMergeConflictActionClick != null || enableGutterUtility || enableLineSelection || enableGutterSelection;
190
212
  if (shouldAttachPointerListeners && !this.hasPointerListeners) {
191
213
  pre.addEventListener("click", this.handlePointerClick);
192
214
  pre.addEventListener("pointerdown", this.handlePointerDown);
@@ -432,6 +454,14 @@ var InteractionManager = class {
432
454
  if (lineHoverHighlight === "both" || lineHoverHighlight === "number") this.hoveredLine.numberElement.setAttribute("data-hovered", "");
433
455
  }
434
456
  }
457
+ clearHoveredToken() {
458
+ if (this.hoveredToken == null) return;
459
+ this.hoveredToken = void 0;
460
+ }
461
+ setHoveredToken(hoveredToken) {
462
+ if (this.hoveredToken != null) this.clearHoveredToken();
463
+ this.hoveredToken = hoveredToken;
464
+ }
435
465
  ensureGutterUtilityNode(useCustomGutterUtility) {
436
466
  if (this.gutterUtilityContainer == null) {
437
467
  this.gutterUtilityContainer = document.createElement("div");
@@ -611,6 +641,25 @@ var InteractionManager = class {
611
641
  numberColumn: target.numberColumn
612
642
  };
613
643
  }
644
+ toTokenEventBaseProps({ lineCharEnd, lineCharStart, lineNumber, side, tokenElement, tokenText }) {
645
+ if (this.mode === "file") return {
646
+ type: "token",
647
+ lineCharEnd,
648
+ lineCharStart,
649
+ lineNumber,
650
+ tokenElement,
651
+ tokenText
652
+ };
653
+ return {
654
+ type: "token",
655
+ lineCharEnd,
656
+ lineCharStart,
657
+ lineNumber,
658
+ side,
659
+ tokenElement,
660
+ tokenText
661
+ };
662
+ }
614
663
  buildSelectedLineRange(anchor, current) {
615
664
  return this.buildSelectionRange(anchor.lineNumber, current.lineNumber, anchor.side, current.side);
616
665
  }
@@ -629,6 +678,8 @@ var InteractionManager = class {
629
678
  let lineElement;
630
679
  let lineIndexValue;
631
680
  let numberElement;
681
+ let tokenElement;
682
+ let tokenInfo;
632
683
  let expandInfo;
633
684
  let lineNumber;
634
685
  let mergeConflictActionTarget;
@@ -644,6 +695,24 @@ var InteractionManager = class {
644
695
  conflictIndex
645
696
  };
646
697
  }
698
+ if (tokenElement == null && element.hasAttribute("data-char")) {
699
+ tokenElement = element;
700
+ const startAttr = element.getAttribute("data-char");
701
+ if (startAttr != null) {
702
+ const lineCharStart = Number.parseInt(startAttr, 10);
703
+ if (!Number.isNaN(lineCharStart)) {
704
+ const tokenText = element.textContent ?? "";
705
+ const lineCharEnd = lineCharStart + tokenText.length;
706
+ if (tokenText.trim() !== "" || this.options.enableTokenInteractionsOnWhitespace === true) tokenInfo = {
707
+ tokenElement,
708
+ lineCharStart,
709
+ lineCharEnd,
710
+ tokenText
711
+ };
712
+ continue;
713
+ }
714
+ }
715
+ }
647
716
  const columnNumber = numberElement == null ? element.getAttribute("data-column-number") ?? void 0 : void 0;
648
717
  if (columnNumber != null) {
649
718
  numberElement = element;
@@ -693,6 +762,30 @@ var InteractionManager = class {
693
762
  numberElement ??= lineIndexValue != null ? queryHTMLElement(codeElement, `[data-column-number][data-line-index="${lineIndexValue}"]`) : void 0;
694
763
  if (codeElement == null || lineElement == null || numberElement == null || lineType == null || lineNumber == null || Number.isNaN(lineNumber)) return;
695
764
  const splitLineIndex = this.parseLineIndex(lineElement, this.isSplitDiff());
765
+ if (tokenInfo != null) {
766
+ if (this.mode === "file") return {
767
+ kind: "token",
768
+ lineType,
769
+ lineElement,
770
+ lineNumber,
771
+ numberColumn,
772
+ numberElement,
773
+ side: void 0,
774
+ splitLineIndex,
775
+ ...tokenInfo
776
+ };
777
+ return {
778
+ kind: "token",
779
+ lineType,
780
+ lineElement,
781
+ lineNumber,
782
+ numberColumn,
783
+ numberElement,
784
+ side: getAnnotationSide(lineType, codeElement),
785
+ splitLineIndex,
786
+ ...tokenInfo
787
+ };
788
+ }
696
789
  if (this.mode === "file") return {
697
790
  kind: "line",
698
791
  lineType,
@@ -703,13 +796,6 @@ var InteractionManager = class {
703
796
  side: void 0,
704
797
  splitLineIndex
705
798
  };
706
- const annotationSide = (() => {
707
- switch (lineType) {
708
- case "change-deletion": return "deletions";
709
- case "change-addition": return "additions";
710
- default: return codeElement.hasAttribute("data-deletions") ? "deletions" : "additions";
711
- }
712
- })();
713
799
  return {
714
800
  kind: "line",
715
801
  lineType,
@@ -717,7 +803,7 @@ var InteractionManager = class {
717
803
  lineNumber,
718
804
  numberColumn,
719
805
  numberElement,
720
- side: annotationSide,
806
+ side: getAnnotationSide(lineType, codeElement),
721
807
  splitLineIndex
722
808
  };
723
809
  }
@@ -730,8 +816,9 @@ var InteractionManager = class {
730
816
  if (!split) return lineIndexes[0];
731
817
  }
732
818
  };
733
- function pluckInteractionOptions({ enableGutterUtility, enableHoverUtility, lineHoverHighlight, onGutterUtilityClick, onLineClick, onLineEnter, onLineLeave, onLineNumberClick, renderGutterUtility, renderHoverUtility, __debugPointerEvents, enableLineSelection, onLineSelected, onLineSelectionStart, onLineSelectionChange, onLineSelectionEnd }, onHunkExpand, getLineIndex, onMergeConflictActionClick) {
819
+ function pluckInteractionOptions({ enableTokenInteractionsOnWhitespace, enableGutterUtility, enableHoverUtility, lineHoverHighlight, onGutterUtilityClick, onLineClick, onLineEnter, onLineLeave, onLineNumberClick, onTokenClick, onTokenEnter, onTokenLeave, renderGutterUtility, renderHoverUtility, __debugPointerEvents, enableLineSelection, onLineSelected, onLineSelectionStart, onLineSelectionChange, onLineSelectionEnd }, onHunkExpand, getLineIndex, onMergeConflictActionClick) {
734
820
  return {
821
+ enableTokenInteractionsOnWhitespace,
735
822
  enableGutterUtility: resolveEnableGutterUtilityOption({
736
823
  enableGutterUtility,
737
824
  enableHoverUtility,
@@ -748,6 +835,9 @@ function pluckInteractionOptions({ enableGutterUtility, enableHoverUtility, line
748
835
  onLineEnter,
749
836
  onLineLeave,
750
837
  onLineNumberClick,
838
+ onTokenClick,
839
+ onTokenEnter,
840
+ onTokenLeave,
751
841
  __debugPointerEvents,
752
842
  enableLineSelection,
753
843
  onLineSelected,
@@ -766,6 +856,12 @@ function resolveEnableGutterUtilityOption({ enableGutterUtility, enableHoverUtil
766
856
  function isLinePointerTarget(target) {
767
857
  return target != null && "kind" in target && target.kind === "line";
768
858
  }
859
+ function isTokenPointerTarget(target) {
860
+ return target != null && "kind" in target && target.kind === "token";
861
+ }
862
+ function isHoverableLinePointerTarget(target) {
863
+ return isLinePointerTarget(target) || isTokenPointerTarget(target);
864
+ }
769
865
  function isExpandoPointerTarget(target) {
770
866
  return "type" in target && target.type === "line-info";
771
867
  }
@@ -779,6 +875,13 @@ function queryHTMLElement(parent, query) {
779
875
  const element = parent?.querySelector(query);
780
876
  return element instanceof HTMLElement ? element : void 0;
781
877
  }
878
+ function getAnnotationSide(lineType, codeElement) {
879
+ switch (lineType) {
880
+ case "change-deletion": return "deletions";
881
+ case "change-addition": return "additions";
882
+ default: return codeElement.hasAttribute("data-deletions") ? "deletions" : "additions";
883
+ }
884
+ }
782
885
  function getLineTypeFromElement(element) {
783
886
  const lineType = element.getAttribute("data-line-type");
784
887
  if (lineType == null) return;