@pierre/diffs 1.0.2 → 1.0.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.
@@ -67,13 +67,13 @@ var LineSelectionManager = class {
67
67
  attachEventListeners() {
68
68
  if (this.pre == null) return;
69
69
  this.removeEventListeners();
70
- this.pre.addEventListener("mousedown", this.handleMouseDown);
70
+ this.pre.addEventListener("pointerdown", this.handleMouseDown);
71
71
  }
72
72
  removeEventListeners() {
73
73
  if (this.pre == null) return;
74
- this.pre.removeEventListener("mousedown", this.handleMouseDown);
75
- document.removeEventListener("mousemove", this.handleMouseMove);
76
- document.removeEventListener("mouseup", this.handleMouseUp);
74
+ this.pre.removeEventListener("pointerdown", this.handleMouseDown);
75
+ document.removeEventListener("pointermove", this.handleMouseMove);
76
+ document.removeEventListener("pointerup", this.handleMouseUp);
77
77
  }
78
78
  handleMouseDown = (event) => {
79
79
  const mouseEventData = event.button === 0 ? this.getMouseEventDataForPath(event.composedPath(), "click") : void 0;
@@ -105,8 +105,8 @@ var LineSelectionManager = class {
105
105
  this.updateSelection(lineNumber, eventSide);
106
106
  this.notifySelectionStart(this.selectedRange);
107
107
  }
108
- document.addEventListener("mousemove", this.handleMouseMove);
109
- document.addEventListener("mouseup", this.handleMouseUp);
108
+ document.addEventListener("pointermove", this.handleMouseMove);
109
+ document.addEventListener("pointerup", this.handleMouseUp);
110
110
  };
111
111
  handleMouseMove = (event) => {
112
112
  const mouseEventData = this.getMouseEventDataForPath(event.composedPath(), "move");
@@ -116,8 +116,8 @@ var LineSelectionManager = class {
116
116
  };
117
117
  handleMouseUp = () => {
118
118
  this.anchor = void 0;
119
- document.removeEventListener("mousemove", this.handleMouseMove);
120
- document.removeEventListener("mouseup", this.handleMouseUp);
119
+ document.removeEventListener("pointermove", this.handleMouseMove);
120
+ document.removeEventListener("pointerup", this.handleMouseUp);
121
121
  this.notifySelectionEnd(this.selectedRange);
122
122
  this.notifySelectionChange();
123
123
  };
@@ -1 +1 @@
1
- {"version":3,"file":"LineSelectionManager.js","names":["options: LineSelectionOptions","lineNumber: number | undefined","lineIndex: number | undefined","eventSide: AnnotationSide | undefined"],"sources":["../../src/managers/LineSelectionManager.ts"],"sourcesContent":["import type { AnnotationSide } from '../types';\nimport { areSelectionsEqual } from '../utils/areSelectionsEqual';\n\nexport type SelectionSide = AnnotationSide;\n\nexport interface SelectedLineRange {\n start: number;\n side?: SelectionSide;\n end: number;\n endSide?: SelectionSide;\n}\n\nexport interface LineSelectionOptions {\n enableLineSelection?: boolean;\n onLineSelected?: (range: SelectedLineRange | null) => void;\n onLineSelectionStart?: (range: SelectedLineRange | null) => void;\n onLineSelectionEnd?: (range: SelectedLineRange | null) => void;\n}\n\ninterface MouseInfo {\n lineNumber: number;\n eventSide: AnnotationSide;\n lineIndex: number;\n}\n\n/**\n * Manages line selection state and interactions for code/diff viewers.\n * Handles:\n * - Click and drag selection\n * - Shift-click to extend selection\n * - DOM attribute updates (data-selected-line)\n */\nexport class LineSelectionManager {\n private pre: HTMLPreElement | undefined;\n private selectedRange: SelectedLineRange | null = null;\n private renderedSelectionRange: SelectedLineRange | null | undefined;\n private anchor: { line: number; side: SelectionSide } | undefined;\n private _queuedRender: number | undefined;\n\n constructor(private options: LineSelectionOptions = {}) {}\n\n setOptions(options: LineSelectionOptions): void {\n this.options = { ...this.options, ...options };\n this.removeEventListeners();\n if (this.options.enableLineSelection === true) {\n this.attachEventListeners();\n }\n }\n\n cleanUp(): void {\n this.removeEventListeners();\n if (this._queuedRender != null) {\n cancelAnimationFrame(this._queuedRender);\n this._queuedRender = undefined;\n }\n if (this.pre != null) {\n delete this.pre.dataset.interactiveLineNumbers;\n }\n this.pre = undefined;\n }\n\n setup(pre: HTMLPreElement): void {\n // Assume we are always dirty after a setup...\n this.setDirty();\n if (this.pre !== pre) {\n this.cleanUp();\n }\n this.pre = pre;\n const { enableLineSelection = false } = this.options;\n if (enableLineSelection) {\n this.pre.dataset.interactiveLineNumbers = '';\n this.attachEventListeners();\n } else {\n this.removeEventListeners();\n delete this.pre.dataset.interactiveLineNumbers;\n }\n\n this.setSelection(this.selectedRange);\n }\n\n setDirty(): void {\n this.renderedSelectionRange = undefined;\n }\n\n isDirty(): boolean {\n return this.renderedSelectionRange === undefined;\n }\n\n setSelection(range: SelectedLineRange | null): void {\n const isRangeChange = !(\n range === this.selectedRange ||\n areSelectionsEqual(range ?? undefined, this.selectedRange ?? undefined)\n );\n if (!this.isDirty() && !isRangeChange) return;\n this.selectedRange = range;\n this.renderSelection();\n if (isRangeChange) {\n this.notifySelectionChange();\n }\n }\n\n getSelection(): SelectedLineRange | null {\n return this.selectedRange;\n }\n\n private attachEventListeners(): void {\n if (this.pre == null) return;\n // Lets run a cleanup, just in case\n this.removeEventListeners();\n this.pre.addEventListener('mousedown', this.handleMouseDown);\n }\n\n private removeEventListeners(): void {\n if (this.pre == null) return;\n this.pre.removeEventListener('mousedown', this.handleMouseDown);\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n }\n\n private handleMouseDown = (event: MouseEvent): void => {\n // Only handle left mouse button\n const mouseEventData =\n event.button === 0\n ? this.getMouseEventDataForPath(event.composedPath(), 'click')\n : undefined;\n if (mouseEventData == null) {\n return;\n }\n event.preventDefault();\n const { lineNumber, eventSide, lineIndex } = mouseEventData;\n if (event.shiftKey && this.selectedRange != null) {\n const range = this.deriveRowRangeFromDOM(\n this.selectedRange,\n this.pre?.dataset.type === 'split'\n );\n if (range == null) return;\n const useStart =\n range.start <= range.end\n ? lineIndex >= range.start\n : lineIndex <= range.end;\n this.anchor = {\n line: useStart ? this.selectedRange.start : this.selectedRange.end,\n side:\n (useStart\n ? this.selectedRange.side\n : (this.selectedRange.endSide ?? this.selectedRange.side)) ??\n 'additions',\n };\n this.updateSelection(lineNumber, eventSide);\n this.notifySelectionStart(this.selectedRange);\n } else {\n // Check if clicking on already selected single line to unselect\n if (\n this.selectedRange?.start === lineNumber &&\n this.selectedRange?.end === lineNumber\n ) {\n this.updateSelection(null);\n this.notifySelectionEnd(null);\n this.notifySelectionChange();\n return;\n }\n this.selectedRange = null;\n this.anchor = { line: lineNumber, side: eventSide };\n this.updateSelection(lineNumber, eventSide);\n this.notifySelectionStart(this.selectedRange);\n }\n\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n };\n\n private handleMouseMove = (event: MouseEvent): void => {\n const mouseEventData = this.getMouseEventDataForPath(\n event.composedPath(),\n 'move'\n );\n if (mouseEventData == null || this.anchor == null) return;\n const { lineNumber, eventSide } = mouseEventData;\n this.updateSelection(lineNumber, eventSide);\n };\n\n private handleMouseUp = (): void => {\n this.anchor = undefined;\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n this.notifySelectionEnd(this.selectedRange);\n this.notifySelectionChange();\n };\n\n private updateSelection(currentLine: null): void;\n private updateSelection(currentLine: number, side: AnnotationSide): void;\n private updateSelection(\n currentLine: number | null,\n side?: AnnotationSide\n ): void {\n if (currentLine == null) {\n this.selectedRange = null;\n } else {\n const anchorSide = this.anchor?.side ?? side;\n const anchorLine = this.anchor?.line ?? currentLine;\n this.selectedRange = {\n start: anchorLine,\n end: currentLine,\n side: anchorSide,\n endSide: anchorSide !== side ? side : undefined,\n };\n }\n this._queuedRender ??= requestAnimationFrame(this.renderSelection);\n }\n\n private renderSelection = (): void => {\n if (this._queuedRender != null) {\n cancelAnimationFrame(this._queuedRender);\n this._queuedRender = undefined;\n }\n if (\n this.pre == null ||\n this.renderedSelectionRange === this.selectedRange\n ) {\n return;\n }\n\n // First clear existing selections, maybe we\n // can cache this to better avoid this query?\n const allSelected = this.pre.querySelectorAll('[data-selected-line]');\n for (const element of allSelected) {\n element.removeAttribute('data-selected-line');\n }\n\n this.renderedSelectionRange = this.selectedRange;\n if (this.selectedRange == null) {\n return;\n }\n\n const codeElements = this.pre.querySelectorAll('[data-code]');\n if (codeElements.length === 0) return;\n if (codeElements.length > 2) {\n console.error(codeElements);\n throw new Error(\n 'LineSelectionManager.applySelectionToDOM: Somehow there are more than 2 code elements...'\n );\n }\n const split = this.pre.dataset.type === 'split';\n const rowRange = this.deriveRowRangeFromDOM(this.selectedRange, split);\n if (rowRange == null) {\n console.error({ rowRange, selectedRange: this.selectedRange });\n throw new Error(\n 'LineSelectionManager.renderSelection: No valid rowRange'\n );\n }\n const isSingle = rowRange.start === rowRange.end;\n const first = Math.min(rowRange.start, rowRange.end);\n const last = Math.max(rowRange.start, rowRange.end);\n for (const code of codeElements) {\n for (const element of code.children) {\n if (!(element instanceof HTMLElement)) continue;\n const lineIndex = this.getLineIndex(element, split);\n if ((lineIndex ?? 0) > last) break;\n if (lineIndex == null || lineIndex < first) continue;\n let attributeValue = isSingle\n ? 'single'\n : lineIndex === first\n ? 'first'\n : lineIndex === last\n ? 'last'\n : '';\n element.setAttribute('data-selected-line', attributeValue);\n // If we have a line annotation following our selected line, we should\n // mark it as selected as well\n if (\n element.nextSibling instanceof HTMLElement &&\n element.nextSibling.hasAttribute('data-line-annotation')\n ) {\n // Depending on the line's attribute value, lets go ahead and correct\n // it when adding in the annotation row\n if (isSingle) {\n // Single technically becomes 2 selected lines\n attributeValue = 'last';\n element.setAttribute('data-selected-line', 'first');\n } else if (lineIndex === first) {\n // We don't want apply 'first' to the line annotation\n attributeValue = '';\n } else if (lineIndex === last) {\n // the annotation will become the last selected line and therefore\n // our existing line should no longer be last\n element.setAttribute('data-selected-line', '');\n }\n element.nextSibling.setAttribute(\n 'data-selected-line',\n attributeValue\n );\n }\n }\n }\n };\n\n private deriveRowRangeFromDOM(\n range: SelectedLineRange,\n split: boolean\n ): { start: number; end: number } | undefined {\n if (range == null) return undefined;\n const start = this.findRowIndexForLineNumber(\n range.start,\n range.side,\n split\n );\n const end =\n range.end === range.start &&\n (range.endSide == null || range.endSide === range.side)\n ? start\n : this.findRowIndexForLineNumber(\n range.end,\n range.endSide ?? range.side,\n split\n );\n return start != null && end != null ? { start, end } : undefined;\n }\n\n private findRowIndexForLineNumber(\n lineNumber: number,\n targetSide: SelectionSide = 'additions',\n split: boolean\n ): number | undefined {\n if (this.pre == null) return undefined;\n const elements = Array.from(\n this.pre.querySelectorAll(`[data-line=\"${lineNumber}\"]`)\n );\n // Given how unified diffs can order things, we need to always process\n // `[data-line]` elements before `[data-alt-line]`\n elements.push(\n ...Array.from(\n this.pre.querySelectorAll(`[data-alt-line=\"${lineNumber}\"]`)\n )\n );\n if (elements.length === 0) return undefined;\n\n for (const element of elements) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n const side = this.getLineSideFromElement(element);\n if (side === targetSide) {\n return this.getLineIndex(element, split);\n } else if (parseInt(element.dataset.altLine ?? '') === lineNumber) {\n return this.getLineIndex(element, split);\n }\n }\n console.error(\n 'LineSelectionManager.findRowIndexForLineNumber: Invalid selection',\n lineNumber,\n targetSide\n );\n return undefined;\n }\n\n private notifySelectionChange(): void {\n const { onLineSelected } = this.options;\n if (onLineSelected == null) return;\n\n onLineSelected(this.selectedRange ?? null);\n }\n\n private notifySelectionStart(range: SelectedLineRange | null): void {\n const { onLineSelectionStart } = this.options;\n if (onLineSelectionStart == null) return;\n onLineSelectionStart(range);\n }\n\n private notifySelectionEnd(range: SelectedLineRange | null): void {\n const { onLineSelectionEnd } = this.options;\n if (onLineSelectionEnd == null) return;\n onLineSelectionEnd(range);\n }\n\n private getMouseEventDataForPath(\n path: (EventTarget | undefined)[],\n eventType: 'click' | 'move'\n ): MouseInfo | undefined {\n let lineNumber: number | undefined;\n let lineIndex: number | undefined;\n let isNumberColumn = false;\n let eventSide: AnnotationSide | undefined;\n for (const element of path) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n if (element.hasAttribute('data-column-number')) {\n isNumberColumn = true;\n continue;\n }\n if (element.hasAttribute('data-line')) {\n lineNumber = this.getLineNumber(element);\n lineIndex = this.getLineIndex(\n element,\n this.pre?.dataset.type === 'split'\n );\n if (element.dataset.lineType === 'change-deletion') {\n eventSide = 'deletions';\n } else if (element.dataset.lineType === 'change-additions') {\n eventSide = 'additions';\n }\n // if we can't pull out an index or line number, we can't do anything.\n if (lineIndex == null || lineNumber == null) {\n lineIndex = undefined;\n lineNumber = undefined;\n break;\n }\n // If we already have an eventSide, we done computin\n if (eventSide != null) {\n break;\n } else {\n // context type lines will need to be discovered higher up\n // at the data-code level\n }\n continue;\n }\n if (element.hasAttribute('data-code')) {\n eventSide ??= element.hasAttribute('data-deletions')\n ? 'deletions'\n : // context in unified style are assumed to be additions based on\n // their line numbers\n 'additions';\n // If we got to the code element, we def done, son\n break;\n }\n }\n if (\n (eventType === 'click' && !isNumberColumn) ||\n lineIndex == null ||\n lineNumber == null\n ) {\n return undefined;\n }\n return {\n lineIndex,\n lineNumber,\n // Normally this shouldn't hit unless we broke early for whatever reason,\n // but for types lets ensure it's additions if undefined\n eventSide: eventSide ?? 'additions',\n };\n }\n\n private getLineNumber(element: HTMLElement): number | undefined {\n const lineNumber = parseInt(element.dataset.line ?? '', 10);\n return !Number.isNaN(lineNumber) ? lineNumber : undefined;\n }\n\n private getLineIndex(\n element: HTMLElement,\n split: boolean\n ): number | undefined {\n const lineIndexes = (element.dataset.lineIndex ?? '')\n .split(',')\n .map((value) => parseInt(value))\n .filter((value) => !Number.isNaN(value));\n\n if (split && lineIndexes.length === 2) {\n return lineIndexes[1];\n } else if (!split) {\n return lineIndexes[0];\n }\n return undefined;\n }\n\n private getLineSideFromElement(element: HTMLElement): SelectionSide {\n if (element.dataset.lineType === 'change-deletion') {\n return 'deletions';\n }\n if (element.dataset.lineType === 'change-addition') {\n return 'additions';\n }\n const parent = element.closest('[data-code]');\n if (!(parent instanceof HTMLElement)) {\n return 'additions';\n }\n return parent.hasAttribute('data-deletions') ? 'deletions' : 'additions';\n }\n}\n\nexport function pluckLineSelectionOptions({\n enableLineSelection,\n onLineSelected,\n onLineSelectionStart,\n onLineSelectionEnd,\n}: LineSelectionOptions): LineSelectionOptions {\n return {\n enableLineSelection,\n onLineSelected,\n onLineSelectionStart,\n onLineSelectionEnd,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LineSelectionManager.js","names":["options: LineSelectionOptions","lineNumber: number | undefined","lineIndex: number | undefined","eventSide: AnnotationSide | undefined"],"sources":["../../src/managers/LineSelectionManager.ts"],"sourcesContent":["import type { AnnotationSide } from '../types';\nimport { areSelectionsEqual } from '../utils/areSelectionsEqual';\n\nexport type SelectionSide = AnnotationSide;\n\nexport interface SelectedLineRange {\n start: number;\n side?: SelectionSide;\n end: number;\n endSide?: SelectionSide;\n}\n\nexport interface LineSelectionOptions {\n enableLineSelection?: boolean;\n onLineSelected?: (range: SelectedLineRange | null) => void;\n onLineSelectionStart?: (range: SelectedLineRange | null) => void;\n onLineSelectionEnd?: (range: SelectedLineRange | null) => void;\n}\n\ninterface MouseInfo {\n lineNumber: number;\n eventSide: AnnotationSide;\n lineIndex: number;\n}\n\n/**\n * Manages line selection state and interactions for code/diff viewers.\n * Handles:\n * - Click and drag selection\n * - Shift-click to extend selection\n * - DOM attribute updates (data-selected-line)\n */\nexport class LineSelectionManager {\n private pre: HTMLPreElement | undefined;\n private selectedRange: SelectedLineRange | null = null;\n private renderedSelectionRange: SelectedLineRange | null | undefined;\n private anchor: { line: number; side: SelectionSide } | undefined;\n private _queuedRender: number | undefined;\n\n constructor(private options: LineSelectionOptions = {}) {}\n\n setOptions(options: LineSelectionOptions): void {\n this.options = { ...this.options, ...options };\n this.removeEventListeners();\n if (this.options.enableLineSelection === true) {\n this.attachEventListeners();\n }\n }\n\n cleanUp(): void {\n this.removeEventListeners();\n if (this._queuedRender != null) {\n cancelAnimationFrame(this._queuedRender);\n this._queuedRender = undefined;\n }\n if (this.pre != null) {\n delete this.pre.dataset.interactiveLineNumbers;\n }\n this.pre = undefined;\n }\n\n setup(pre: HTMLPreElement): void {\n // Assume we are always dirty after a setup...\n this.setDirty();\n if (this.pre !== pre) {\n this.cleanUp();\n }\n this.pre = pre;\n const { enableLineSelection = false } = this.options;\n if (enableLineSelection) {\n this.pre.dataset.interactiveLineNumbers = '';\n this.attachEventListeners();\n } else {\n this.removeEventListeners();\n delete this.pre.dataset.interactiveLineNumbers;\n }\n\n this.setSelection(this.selectedRange);\n }\n\n setDirty(): void {\n this.renderedSelectionRange = undefined;\n }\n\n isDirty(): boolean {\n return this.renderedSelectionRange === undefined;\n }\n\n setSelection(range: SelectedLineRange | null): void {\n const isRangeChange = !(\n range === this.selectedRange ||\n areSelectionsEqual(range ?? undefined, this.selectedRange ?? undefined)\n );\n if (!this.isDirty() && !isRangeChange) return;\n this.selectedRange = range;\n this.renderSelection();\n if (isRangeChange) {\n this.notifySelectionChange();\n }\n }\n\n getSelection(): SelectedLineRange | null {\n return this.selectedRange;\n }\n\n private attachEventListeners(): void {\n if (this.pre == null) return;\n // Lets run a cleanup, just in case\n this.removeEventListeners();\n this.pre.addEventListener('pointerdown', this.handleMouseDown);\n }\n\n private removeEventListeners(): void {\n if (this.pre == null) return;\n this.pre.removeEventListener('pointerdown', this.handleMouseDown);\n document.removeEventListener('pointermove', this.handleMouseMove);\n document.removeEventListener('pointerup', this.handleMouseUp);\n }\n\n private handleMouseDown = (event: PointerEvent): void => {\n // Only handle left mouse button\n const mouseEventData =\n event.button === 0\n ? this.getMouseEventDataForPath(event.composedPath(), 'click')\n : undefined;\n if (mouseEventData == null) {\n return;\n }\n event.preventDefault();\n const { lineNumber, eventSide, lineIndex } = mouseEventData;\n if (event.shiftKey && this.selectedRange != null) {\n const range = this.deriveRowRangeFromDOM(\n this.selectedRange,\n this.pre?.dataset.type === 'split'\n );\n if (range == null) return;\n const useStart =\n range.start <= range.end\n ? lineIndex >= range.start\n : lineIndex <= range.end;\n this.anchor = {\n line: useStart ? this.selectedRange.start : this.selectedRange.end,\n side:\n (useStart\n ? this.selectedRange.side\n : (this.selectedRange.endSide ?? this.selectedRange.side)) ??\n 'additions',\n };\n this.updateSelection(lineNumber, eventSide);\n this.notifySelectionStart(this.selectedRange);\n } else {\n // Check if clicking on already selected single line to unselect\n if (\n this.selectedRange?.start === lineNumber &&\n this.selectedRange?.end === lineNumber\n ) {\n this.updateSelection(null);\n this.notifySelectionEnd(null);\n this.notifySelectionChange();\n return;\n }\n this.selectedRange = null;\n this.anchor = { line: lineNumber, side: eventSide };\n this.updateSelection(lineNumber, eventSide);\n this.notifySelectionStart(this.selectedRange);\n }\n\n document.addEventListener('pointermove', this.handleMouseMove);\n document.addEventListener('pointerup', this.handleMouseUp);\n };\n\n private handleMouseMove = (event: PointerEvent): void => {\n const mouseEventData = this.getMouseEventDataForPath(\n event.composedPath(),\n 'move'\n );\n if (mouseEventData == null || this.anchor == null) return;\n const { lineNumber, eventSide } = mouseEventData;\n this.updateSelection(lineNumber, eventSide);\n };\n\n private handleMouseUp = (): void => {\n this.anchor = undefined;\n document.removeEventListener('pointermove', this.handleMouseMove);\n document.removeEventListener('pointerup', this.handleMouseUp);\n this.notifySelectionEnd(this.selectedRange);\n this.notifySelectionChange();\n };\n\n private updateSelection(currentLine: null): void;\n private updateSelection(currentLine: number, side: AnnotationSide): void;\n private updateSelection(\n currentLine: number | null,\n side?: AnnotationSide\n ): void {\n if (currentLine == null) {\n this.selectedRange = null;\n } else {\n const anchorSide = this.anchor?.side ?? side;\n const anchorLine = this.anchor?.line ?? currentLine;\n this.selectedRange = {\n start: anchorLine,\n end: currentLine,\n side: anchorSide,\n endSide: anchorSide !== side ? side : undefined,\n };\n }\n this._queuedRender ??= requestAnimationFrame(this.renderSelection);\n }\n\n private renderSelection = (): void => {\n if (this._queuedRender != null) {\n cancelAnimationFrame(this._queuedRender);\n this._queuedRender = undefined;\n }\n if (\n this.pre == null ||\n this.renderedSelectionRange === this.selectedRange\n ) {\n return;\n }\n\n // First clear existing selections, maybe we\n // can cache this to better avoid this query?\n const allSelected = this.pre.querySelectorAll('[data-selected-line]');\n for (const element of allSelected) {\n element.removeAttribute('data-selected-line');\n }\n\n this.renderedSelectionRange = this.selectedRange;\n if (this.selectedRange == null) {\n return;\n }\n\n const codeElements = this.pre.querySelectorAll('[data-code]');\n if (codeElements.length === 0) return;\n if (codeElements.length > 2) {\n console.error(codeElements);\n throw new Error(\n 'LineSelectionManager.applySelectionToDOM: Somehow there are more than 2 code elements...'\n );\n }\n const split = this.pre.dataset.type === 'split';\n const rowRange = this.deriveRowRangeFromDOM(this.selectedRange, split);\n if (rowRange == null) {\n console.error({ rowRange, selectedRange: this.selectedRange });\n throw new Error(\n 'LineSelectionManager.renderSelection: No valid rowRange'\n );\n }\n const isSingle = rowRange.start === rowRange.end;\n const first = Math.min(rowRange.start, rowRange.end);\n const last = Math.max(rowRange.start, rowRange.end);\n for (const code of codeElements) {\n for (const element of code.children) {\n if (!(element instanceof HTMLElement)) continue;\n const lineIndex = this.getLineIndex(element, split);\n if ((lineIndex ?? 0) > last) break;\n if (lineIndex == null || lineIndex < first) continue;\n let attributeValue = isSingle\n ? 'single'\n : lineIndex === first\n ? 'first'\n : lineIndex === last\n ? 'last'\n : '';\n element.setAttribute('data-selected-line', attributeValue);\n // If we have a line annotation following our selected line, we should\n // mark it as selected as well\n if (\n element.nextSibling instanceof HTMLElement &&\n element.nextSibling.hasAttribute('data-line-annotation')\n ) {\n // Depending on the line's attribute value, lets go ahead and correct\n // it when adding in the annotation row\n if (isSingle) {\n // Single technically becomes 2 selected lines\n attributeValue = 'last';\n element.setAttribute('data-selected-line', 'first');\n } else if (lineIndex === first) {\n // We don't want apply 'first' to the line annotation\n attributeValue = '';\n } else if (lineIndex === last) {\n // the annotation will become the last selected line and therefore\n // our existing line should no longer be last\n element.setAttribute('data-selected-line', '');\n }\n element.nextSibling.setAttribute(\n 'data-selected-line',\n attributeValue\n );\n }\n }\n }\n };\n\n private deriveRowRangeFromDOM(\n range: SelectedLineRange,\n split: boolean\n ): { start: number; end: number } | undefined {\n if (range == null) return undefined;\n const start = this.findRowIndexForLineNumber(\n range.start,\n range.side,\n split\n );\n const end =\n range.end === range.start &&\n (range.endSide == null || range.endSide === range.side)\n ? start\n : this.findRowIndexForLineNumber(\n range.end,\n range.endSide ?? range.side,\n split\n );\n return start != null && end != null ? { start, end } : undefined;\n }\n\n private findRowIndexForLineNumber(\n lineNumber: number,\n targetSide: SelectionSide = 'additions',\n split: boolean\n ): number | undefined {\n if (this.pre == null) return undefined;\n const elements = Array.from(\n this.pre.querySelectorAll(`[data-line=\"${lineNumber}\"]`)\n );\n // Given how unified diffs can order things, we need to always process\n // `[data-line]` elements before `[data-alt-line]`\n elements.push(\n ...Array.from(\n this.pre.querySelectorAll(`[data-alt-line=\"${lineNumber}\"]`)\n )\n );\n if (elements.length === 0) return undefined;\n\n for (const element of elements) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n const side = this.getLineSideFromElement(element);\n if (side === targetSide) {\n return this.getLineIndex(element, split);\n } else if (parseInt(element.dataset.altLine ?? '') === lineNumber) {\n return this.getLineIndex(element, split);\n }\n }\n console.error(\n 'LineSelectionManager.findRowIndexForLineNumber: Invalid selection',\n lineNumber,\n targetSide\n );\n return undefined;\n }\n\n private notifySelectionChange(): void {\n const { onLineSelected } = this.options;\n if (onLineSelected == null) return;\n\n onLineSelected(this.selectedRange ?? null);\n }\n\n private notifySelectionStart(range: SelectedLineRange | null): void {\n const { onLineSelectionStart } = this.options;\n if (onLineSelectionStart == null) return;\n onLineSelectionStart(range);\n }\n\n private notifySelectionEnd(range: SelectedLineRange | null): void {\n const { onLineSelectionEnd } = this.options;\n if (onLineSelectionEnd == null) return;\n onLineSelectionEnd(range);\n }\n\n private getMouseEventDataForPath(\n path: (EventTarget | undefined)[],\n eventType: 'click' | 'move'\n ): MouseInfo | undefined {\n let lineNumber: number | undefined;\n let lineIndex: number | undefined;\n let isNumberColumn = false;\n let eventSide: AnnotationSide | undefined;\n for (const element of path) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n if (element.hasAttribute('data-column-number')) {\n isNumberColumn = true;\n continue;\n }\n if (element.hasAttribute('data-line')) {\n lineNumber = this.getLineNumber(element);\n lineIndex = this.getLineIndex(\n element,\n this.pre?.dataset.type === 'split'\n );\n if (element.dataset.lineType === 'change-deletion') {\n eventSide = 'deletions';\n } else if (element.dataset.lineType === 'change-additions') {\n eventSide = 'additions';\n }\n // if we can't pull out an index or line number, we can't do anything.\n if (lineIndex == null || lineNumber == null) {\n lineIndex = undefined;\n lineNumber = undefined;\n break;\n }\n // If we already have an eventSide, we done computin\n if (eventSide != null) {\n break;\n } else {\n // context type lines will need to be discovered higher up\n // at the data-code level\n }\n continue;\n }\n if (element.hasAttribute('data-code')) {\n eventSide ??= element.hasAttribute('data-deletions')\n ? 'deletions'\n : // context in unified style are assumed to be additions based on\n // their line numbers\n 'additions';\n // If we got to the code element, we def done, son\n break;\n }\n }\n if (\n (eventType === 'click' && !isNumberColumn) ||\n lineIndex == null ||\n lineNumber == null\n ) {\n return undefined;\n }\n return {\n lineIndex,\n lineNumber,\n // Normally this shouldn't hit unless we broke early for whatever reason,\n // but for types lets ensure it's additions if undefined\n eventSide: eventSide ?? 'additions',\n };\n }\n\n private getLineNumber(element: HTMLElement): number | undefined {\n const lineNumber = parseInt(element.dataset.line ?? '', 10);\n return !Number.isNaN(lineNumber) ? lineNumber : undefined;\n }\n\n private getLineIndex(\n element: HTMLElement,\n split: boolean\n ): number | undefined {\n const lineIndexes = (element.dataset.lineIndex ?? '')\n .split(',')\n .map((value) => parseInt(value))\n .filter((value) => !Number.isNaN(value));\n\n if (split && lineIndexes.length === 2) {\n return lineIndexes[1];\n } else if (!split) {\n return lineIndexes[0];\n }\n return undefined;\n }\n\n private getLineSideFromElement(element: HTMLElement): SelectionSide {\n if (element.dataset.lineType === 'change-deletion') {\n return 'deletions';\n }\n if (element.dataset.lineType === 'change-addition') {\n return 'additions';\n }\n const parent = element.closest('[data-code]');\n if (!(parent instanceof HTMLElement)) {\n return 'additions';\n }\n return parent.hasAttribute('data-deletions') ? 'deletions' : 'additions';\n }\n}\n\nexport function pluckLineSelectionOptions({\n enableLineSelection,\n onLineSelected,\n onLineSelectionStart,\n onLineSelectionEnd,\n}: LineSelectionOptions): LineSelectionOptions {\n return {\n enableLineSelection,\n onLineSelected,\n onLineSelectionStart,\n onLineSelectionEnd,\n };\n}\n"],"mappings":"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"}
@@ -7,13 +7,13 @@ interface OnLineClickProps extends LineEventBaseProps {
7
7
  event: PointerEvent;
8
8
  }
9
9
  interface OnLineEnterLeaveProps extends LineEventBaseProps {
10
- event: MouseEvent;
10
+ event: PointerEvent;
11
11
  }
12
12
  interface OnDiffLineClickProps extends DiffLineEventBaseProps {
13
13
  event: PointerEvent;
14
14
  }
15
15
  interface OnDiffLineEnterLeaveProps extends DiffLineEventBaseProps {
16
- event: MouseEvent;
16
+ event: PointerEvent;
17
17
  }
18
18
  type EventClickProps<TMode extends MouseEventManagerMode> = TMode extends "file" ? OnLineClickProps : OnDiffLineClickProps;
19
19
  type MouseEventEnterLeaveProps<TMode extends MouseEventManagerMode> = TMode extends "file" ? OnLineEnterLeaveProps : OnDiffLineEnterLeaveProps;
@@ -45,9 +45,9 @@ declare class MouseEventManager<TMode extends MouseEventManagerMode> {
45
45
  cleanUp(): void;
46
46
  setup(pre: HTMLPreElement): void;
47
47
  getHoveredLine: () => GetHoveredLineResult<TMode> | undefined;
48
- handleMouseClick: (event: MouseEvent) => void;
49
- handleMouseMove: (event: MouseEvent) => void;
50
- handleMouseLeave: (event: MouseEvent) => void;
48
+ handleMouseClick: (event: PointerEvent) => void;
49
+ handleMouseMove: (event: PointerEvent) => void;
50
+ handleMouseLeave: (event: PointerEvent) => void;
51
51
  private handleMouseEvent;
52
52
  private getLineData;
53
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MouseEventManager.d.ts","names":["mode: TMode","options: MouseEventManagerOptions<TMode>"],"sources":["../../src/managers/MouseEventManager.ts"],"sourcesContent":[],"mappings":";;;KAOY,QAAA;KAEA,qBAAA;AAFA,UAIK,gBAAA,SAAyB,kBAJ9B,CAAA;EAEZ,KAAY,EAGH,YAHG;AAEZ;AAIiB,UAAA,qBAAA,SAA8B,kBAAA,CAAA;EAI/C,KAAiB,EAHR,UAGQ;AAIjB;AAQK,UAZY,oBAAA,SAA6B,sBAYzC,CAAA;EAA8B,KAAA,EAX1B,YAW0B;;AAC/B,UATa,yBAAA,SAAkC,sBAS/C,CAAA;EACA,KAAA,EATK,UASL;;AAAA,KAFC,eAIA,CAAA,cAJ8B,qBAI9B,CAAA,GAJuD,KAIvD,SAAA,MAAA,GAHD,gBAGC,GAFD,oBAEC;KAAA,yBAAwC,CAAA,cAAA,qBAAA,CAAA,GAC3C,KAD2C,SAAA,MAAA,GACpB,qBADoB,GACI,yBADJ;AAC3C,KAYU,oBAZV,CAAA,cAY6C,qBAZ7C,CAAA,GAaA,KAbA,SAAA,MAAA,GAAA;EAAuB,UAAA,EAAA,MAAA;CAAwB,GAAA;EAAA,UAAA,EAAA,MAAA;EAYjD,IAAY,EAGsB,cAHtB;CAAmC;AAC7C,UAmCe,4BAnCf,CAAA,cAoCc,qBApCd,CAAA,CAAA;EAEgC,kBAAA,CAAA,EAAA,OAAA;EAAA,WAAA,EAAA,KAAA,EAqCZ,eArCY,CAqCI,KArCJ,CAAA,CAAA,EAAA,OAAA;EAiClC,iBAAiB,EAAA,KAAA,EAKW,eALX,CAK2B,KAL3B,CAAA,CAAA,EAAA,OAAA;EACD,WAAA,EAAA,KAAA,EAKM,yBALN,CAKgC,KALhC,CAAA,CAAA,EAAA,OAAA;EAGsB,WAAA,EAAA,KAAA,EAGhB,yBAHgB,CAGU,KAHV,CAAA,CAAA,EAAA,OAAA;EAAhB,kBAAA,CAAA,EAIC,QAJD;;AACM,UAMX,wBANW,CAAA,cAM4B,qBAN5B,CAAA,SAOlB,4BAPkB,CAOW,KAPX,CAAA,CAAA;EACoB,YAAA,EAAA,SAAA,EAAA,MAAA,EAAA,SAAA,EAOF,mBAPE,CAAA,EAAA,OAAA;;AACA,cASnC,iBATmC,CAAA,cASH,qBATG,CAAA,CAAA;EAA1B,QAAA,IAAA;EACC,QAAA,OAAA;EAAA,QAAA,WAAA;EAGvB,QAAiB,GAAA;EAAuC,QAAA,SAAA;EACjB,WAAA,CAAA,IAAA,EAUrB,KAVqB,EAAA,OAAA,EAWlB,wBAXkB,CAWO,KAXP,CAAA;EACO,UAAA,CAAA,OAAA,EAaxB,wBAbwB,CAaC,KAbD,CAAA,CAAA,EAAA,IAAA;EADpC,OAAA,CAAA,CAAA,EAAA,IAAA;EAAA,KAAA,CAAA,GAAA,EA2BG,cA3BH,CAAA,EAAA,IAAA;EAIV,cAAa,EAAA,GAAA,GAgGU,oBAhGV,CAgG+B,KAhG/B,CAAA,GAAA,SAAA;EAAgC,gBAAA,EAAA,CAAA,KAAA,EAiHhB,UAjHgB,EAAA,GAAA,IAAA;EAM3B,eAAA,EAAA,CAAA,KAAA,EAqHU,UArHV,EAAA,GAAA,IAAA;EAC4B,gBAAA,EAAA,CAAA,KAAA,EA8HjB,UA9HiB,EAAA,GAAA,IAAA;EAAzB,QAAA,gBAAA;EAG0B,QAAA,WAAA;;AAalC,iBAsWG,sBAtWH,CAAA,cAsWwC,qBAtWxC,CAAA,CAAA;EAAA,WAAA;EAAA,iBAAA;EAAA,WAAA;EAAA,WAAA;EAAA,kBAAA;EAAA;AAAA,CAAA,EA8WR,4BA9WQ,CA8WqB,KA9WrB,CAAA,EAAA,YAAA,CAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,SAAA,EA+WmC,mBA/WnC,EAAA,GAAA,OAAA,CAAA,EAgXV,wBAhXU,CAgXe,KAhXf,CAAA"}
1
+ {"version":3,"file":"MouseEventManager.d.ts","names":["mode: TMode","options: MouseEventManagerOptions<TMode>"],"sources":["../../src/managers/MouseEventManager.ts"],"sourcesContent":[],"mappings":";;;KAOY,QAAA;KAEA,qBAAA;AAFA,UAIK,gBAAA,SAAyB,kBAJ9B,CAAA;EAEZ,KAAY,EAGH,YAHG;AAEZ;AAIiB,UAAA,qBAAA,SAA8B,kBAAA,CAAA;EAI/C,KAAiB,EAHR,YAGQ;AAIjB;AAQK,UAZY,oBAAA,SAA6B,sBAYzC,CAAA;EAA8B,KAAA,EAX1B,YAW0B;;AAC/B,UATa,yBAAA,SAAkC,sBAS/C,CAAA;EACA,KAAA,EATK,YASL;;AAAA,KAFC,eAIA,CAAA,cAJ8B,qBAI9B,CAAA,GAJuD,KAIvD,SAAA,MAAA,GAHD,gBAGC,GAFD,oBAEC;KAAA,yBAAwC,CAAA,cAAA,qBAAA,CAAA,GAC3C,KAD2C,SAAA,MAAA,GACpB,qBADoB,GACI,yBADJ;AAC3C,KAYU,oBAZV,CAAA,cAY6C,qBAZ7C,CAAA,GAaA,KAbA,SAAA,MAAA,GAAA;EAAuB,UAAA,EAAA,MAAA;CAAwB,GAAA;EAAA,UAAA,EAAA,MAAA;EAYjD,IAAY,EAGsB,cAHtB;CAAmC;AAC7C,UAmCe,4BAnCf,CAAA,cAoCc,qBApCd,CAAA,CAAA;EAEgC,kBAAA,CAAA,EAAA,OAAA;EAAA,WAAA,EAAA,KAAA,EAqCZ,eArCY,CAqCI,KArCJ,CAAA,CAAA,EAAA,OAAA;EAiClC,iBAAiB,EAAA,KAAA,EAKW,eALX,CAK2B,KAL3B,CAAA,CAAA,EAAA,OAAA;EACD,WAAA,EAAA,KAAA,EAKM,yBALN,CAKgC,KALhC,CAAA,CAAA,EAAA,OAAA;EAGsB,WAAA,EAAA,KAAA,EAGhB,yBAHgB,CAGU,KAHV,CAAA,CAAA,EAAA,OAAA;EAAhB,kBAAA,CAAA,EAIC,QAJD;;AACM,UAMX,wBANW,CAAA,cAM4B,qBAN5B,CAAA,SAOlB,4BAPkB,CAOW,KAPX,CAAA,CAAA;EACoB,YAAA,EAAA,SAAA,EAAA,MAAA,EAAA,SAAA,EAOF,mBAPE,CAAA,EAAA,OAAA;;AACA,cASnC,iBATmC,CAAA,cASH,qBATG,CAAA,CAAA;EAA1B,QAAA,IAAA;EACC,QAAA,OAAA;EAAA,QAAA,WAAA;EAGvB,QAAiB,GAAA;EAAuC,QAAA,SAAA;EACjB,WAAA,CAAA,IAAA,EAUrB,KAVqB,EAAA,OAAA,EAWlB,wBAXkB,CAWO,KAXP,CAAA;EACO,UAAA,CAAA,OAAA,EAaxB,wBAbwB,CAaC,KAbD,CAAA,CAAA,EAAA,IAAA;EADpC,OAAA,CAAA,CAAA,EAAA,IAAA;EAAA,KAAA,CAAA,GAAA,EA2BG,cA3BH,CAAA,EAAA,IAAA;EAIV,cAAa,EAAA,GAAA,GAgGU,oBAhGV,CAgG+B,KAhG/B,CAAA,GAAA,SAAA;EAAgC,gBAAA,EAAA,CAAA,KAAA,EAiHhB,YAjHgB,EAAA,GAAA,IAAA;EAM3B,eAAA,EAAA,CAAA,KAAA,EAqHU,YArHV,EAAA,GAAA,IAAA;EAC4B,gBAAA,EAAA,CAAA,KAAA,EA8HjB,YA9HiB,EAAA,GAAA,IAAA;EAAzB,QAAA,gBAAA;EAG0B,QAAA,WAAA;;AAalC,iBAsWG,sBAtWH,CAAA,cAsWwC,qBAtWxC,CAAA,CAAA;EAAA,WAAA;EAAA,iBAAA;EAAA,WAAA;EAAA,WAAA;EAAA,kBAAA;EAAA;AAAA,CAAA,EA8WR,4BA9WQ,CA8WqB,KA9WrB,CAAA,EAAA,YAAA,CAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,SAAA,EA+WmC,mBA/WnC,EAAA,GAAA,OAAA,CAAA,EAgXV,wBAhXU,CAgXe,KAhXf,CAAA"}
@@ -20,8 +20,8 @@ var MouseEventManager = class {
20
20
  }
21
21
  cleanUp() {
22
22
  this.pre?.removeEventListener("click", this.handleMouseClick);
23
- this.pre?.removeEventListener("mousemove", this.handleMouseMove);
24
- this.pre?.removeEventListener("mouseout", this.handleMouseLeave);
23
+ this.pre?.removeEventListener("pointermove", this.handleMouseMove);
24
+ this.pre?.removeEventListener("pointerout", this.handleMouseLeave);
25
25
  delete this.pre?.dataset.interactiveLines;
26
26
  delete this.pre?.dataset.interactiveLineNumbers;
27
27
  this.pre = void 0;
@@ -55,10 +55,10 @@ var MouseEventManager = class {
55
55
  })());
56
56
  }
57
57
  if (onLineEnter != null || onLineLeave != null || enableHoverUtility) {
58
- pre.addEventListener("mousemove", this.handleMouseMove);
59
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.attachEventListeners: Attaching mouse move event");
60
- pre.addEventListener("mouseleave", this.handleMouseLeave);
61
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.attachEventListeners: Attaching mouse leave event");
58
+ pre.addEventListener("pointermove", this.handleMouseMove);
59
+ debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.attachEventListeners: Attaching pointer move event");
60
+ pre.addEventListener("pointerleave", this.handleMouseLeave);
61
+ debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event");
62
62
  }
63
63
  }
64
64
  getHoveredLine = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"MouseEventManager.js","names":["mode: TMode","options: MouseEventManagerOptions<TMode>","reasons: string[]","direction: ExpansionDirections | undefined","numberElement"],"sources":["../../src/managers/MouseEventManager.ts"],"sourcesContent":["import type {\n AnnotationSide,\n DiffLineEventBaseProps,\n ExpansionDirections,\n LineEventBaseProps,\n} from '../types';\n\nexport type LogTypes = 'click' | 'move' | 'both' | 'none';\n\nexport type MouseEventManagerMode = 'file' | 'diff';\n\nexport interface OnLineClickProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnLineEnterLeaveProps extends LineEventBaseProps {\n event: MouseEvent;\n}\n\nexport interface OnDiffLineClickProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineEnterLeaveProps extends DiffLineEventBaseProps {\n event: MouseEvent;\n}\n\ntype HandleMouseEventProps =\n | { eventType: 'click'; event: MouseEvent }\n | { eventType: 'move'; event: MouseEvent };\n\ntype EventClickProps<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? OnLineClickProps\n : OnDiffLineClickProps;\n\ntype MouseEventEnterLeaveProps<TMode extends MouseEventManagerMode> =\n TMode extends 'file' ? OnLineEnterLeaveProps : OnDiffLineEnterLeaveProps;\n\ntype EventBaseProps<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? LineEventBaseProps\n : DiffLineEventBaseProps;\n\ninterface ExpandoEventProps {\n type: 'line-info';\n hunkIndex: number;\n direction: ExpansionDirections;\n}\n\nexport type GetHoveredLineResult<TMode extends MouseEventManagerMode> =\n TMode extends 'file'\n ? { lineNumber: number }\n : { lineNumber: number; side: AnnotationSide };\n\ntype GetLineDataResult<TMode extends MouseEventManagerMode> =\n TMode extends 'file'\n ? LineEventBaseProps | ExpandoEventProps | undefined\n : DiffLineEventBaseProps | ExpandoEventProps | undefined;\n\ntype LineEventData<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? LineEventBaseProps\n : DiffLineEventBaseProps;\n\nfunction isLineEventData<TMode extends MouseEventManagerMode>(\n data: GetLineDataResult<TMode>,\n mode: TMode\n): data is LineEventData<TMode> {\n if (data == null) return false;\n if (mode === 'file') {\n return data.type === 'line';\n } else {\n return data.type === 'diff-line';\n }\n}\n\nfunction isExpandoEventData(\n data:\n | LineEventBaseProps\n | DiffLineEventBaseProps\n | ExpandoEventProps\n | undefined\n): data is ExpandoEventProps {\n return data?.type === 'line-info';\n}\n\nexport interface MouseEventManagerBaseOptions<\n TMode extends MouseEventManagerMode,\n> {\n enableHoverUtility?: boolean;\n onLineClick?(props: EventClickProps<TMode>): unknown;\n onLineNumberClick?(props: EventClickProps<TMode>): unknown;\n onLineEnter?(props: MouseEventEnterLeaveProps<TMode>): unknown;\n onLineLeave?(props: MouseEventEnterLeaveProps<TMode>): unknown;\n __debugMouseEvents?: LogTypes;\n}\n\nexport interface MouseEventManagerOptions<TMode extends MouseEventManagerMode>\n extends MouseEventManagerBaseOptions<TMode> {\n onHunkExpand?(hunkIndex: number, direction: ExpansionDirections): unknown;\n}\n\nexport class MouseEventManager<TMode extends MouseEventManagerMode> {\n private hoveredLine: EventBaseProps<TMode> | undefined;\n private pre: HTMLPreElement | undefined;\n private hoverSlot: HTMLDivElement | undefined;\n\n constructor(\n private mode: TMode,\n private options: MouseEventManagerOptions<TMode>\n ) {}\n\n setOptions(options: MouseEventManagerOptions<TMode>): void {\n this.options = options;\n }\n\n cleanUp(): void {\n this.pre?.removeEventListener('click', this.handleMouseClick);\n this.pre?.removeEventListener('mousemove', this.handleMouseMove);\n this.pre?.removeEventListener('mouseout', this.handleMouseLeave);\n delete this.pre?.dataset.interactiveLines;\n delete this.pre?.dataset.interactiveLineNumbers;\n this.pre = undefined;\n }\n\n setup(pre: HTMLPreElement): void {\n const {\n __debugMouseEvents,\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onHunkExpand,\n enableHoverUtility = false,\n } = this.options;\n\n this.cleanUp();\n this.pre = pre;\n\n if (enableHoverUtility && this.hoverSlot == null) {\n this.hoverSlot = document.createElement('div');\n this.hoverSlot.dataset.hoverSlot = '';\n const slotElement = document.createElement('slot');\n slotElement.name = 'hover-slot';\n this.hoverSlot.appendChild(slotElement);\n } else if (!enableHoverUtility && this.hoverSlot != null) {\n this.hoverSlot.parentNode?.removeChild(this.hoverSlot);\n this.hoverSlot = undefined;\n }\n\n if (\n onLineClick != null ||\n onLineNumberClick != null ||\n onHunkExpand != null\n ) {\n pre.addEventListener('click', this.handleMouseClick);\n if (onLineClick != null) {\n pre.dataset.interactiveLines = '';\n } else if (onLineNumberClick != null) {\n pre.dataset.interactiveLineNumbers = '';\n }\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n 'FileDiff.DEBUG.attachEventListeners: Attaching click events for:',\n (() => {\n const reasons: string[] = [];\n if (__debugMouseEvents === 'both' || __debugMouseEvents === 'click') {\n if (onLineClick != null) {\n reasons.push('onLineClick');\n }\n if (onLineNumberClick != null) {\n reasons.push('onLineNumberClick');\n }\n if (onHunkExpand != null) {\n reasons.push('expandable hunk separators');\n }\n }\n return reasons;\n })()\n );\n }\n if (onLineEnter != null || onLineLeave != null || enableHoverUtility) {\n pre.addEventListener('mousemove', this.handleMouseMove);\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching mouse move event'\n );\n pre.addEventListener('mouseleave', this.handleMouseLeave);\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching mouse leave event'\n );\n }\n }\n\n getHoveredLine = (): GetHoveredLineResult<TMode> | undefined => {\n if (this.hoveredLine != null) {\n if (this.mode === 'diff' && this.hoveredLine.type === 'diff-line') {\n return {\n lineNumber: this.hoveredLine.lineNumber,\n side: this.hoveredLine.annotationSide,\n } as GetHoveredLineResult<TMode>;\n }\n if (this.mode === 'file' && this.hoveredLine.type === 'line') {\n return {\n lineNumber: this.hoveredLine.lineNumber,\n } as GetHoveredLineResult<TMode>;\n }\n }\n return undefined;\n };\n\n handleMouseClick = (event: MouseEvent): void => {\n debugLogIfEnabled(\n this.options.__debugMouseEvents,\n 'click',\n 'FileDiff.DEBUG.handleMouseClick:',\n event\n );\n this.handleMouseEvent({ eventType: 'click', event });\n };\n\n handleMouseMove = (event: MouseEvent): void => {\n debugLogIfEnabled(\n this.options.__debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseMove:',\n event\n );\n this.handleMouseEvent({ eventType: 'move', event });\n };\n\n handleMouseLeave = (event: MouseEvent): void => {\n const { __debugMouseEvents } = this.options;\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseLeave: no event'\n );\n if (this.hoveredLine == null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseLeave: returned early, no .hoveredLine'\n );\n return;\n }\n this.hoverSlot?.parentElement?.removeChild(this.hoverSlot);\n this.options.onLineLeave?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n this.hoveredLine = undefined;\n };\n\n private handleMouseEvent({ eventType, event }: HandleMouseEventProps) {\n const { __debugMouseEvents } = this.options;\n const composedPath = event.composedPath();\n debugLogIfEnabled(\n __debugMouseEvents,\n eventType,\n 'FileDiff.DEBUG.handleMouseEvent:',\n { eventType, composedPath }\n );\n const data = this.getLineData(composedPath);\n debugLogIfEnabled(\n __debugMouseEvents,\n eventType,\n 'FileDiff.DEBUG.handleMouseEvent: getLineData result:',\n data\n );\n const {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onHunkExpand,\n } = this.options;\n switch (eventType) {\n case 'move': {\n if (\n isLineEventData(data, this.mode) &&\n this.hoveredLine?.lineElement === data.lineElement\n ) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', returned early because same line\"\n );\n break;\n }\n if (this.hoveredLine != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', clearing an existing hovered line and firing onLineLeave\"\n );\n this.hoverSlot?.parentElement?.removeChild(this.hoverSlot);\n onLineLeave?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n this.hoveredLine = undefined;\n }\n if (isLineEventData(data, this.mode)) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', setting up a new hoveredLine and firing onLineEnter\"\n );\n this.hoveredLine = data;\n if (this.hoverSlot != null) {\n data.numberElement?.appendChild(this.hoverSlot);\n }\n onLineEnter?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n }\n break;\n }\n case 'click':\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', with data:\",\n data\n );\n if (data == null) break;\n if (isExpandoEventData(data) && onHunkExpand != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', expanding a hunk\"\n );\n onHunkExpand(data.hunkIndex, data.direction);\n break;\n }\n if (isLineEventData(data, this.mode)) {\n if (onLineNumberClick != null && data.numberColumn) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', firing 'onLineNumberClick'\"\n );\n onLineNumberClick({ ...data, event } as EventClickProps<TMode>);\n } else if (onLineClick != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', firing 'onLineClick'\"\n );\n onLineClick({ ...data, event } as EventClickProps<TMode>);\n } else {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', fell through, no event to fire\"\n );\n }\n }\n break;\n }\n }\n\n private getLineData(\n path: (EventTarget | undefined)[]\n ): GetLineDataResult<TMode> {\n let numberColumn = false;\n const lineElement = path.find((element) => {\n if (!(element instanceof HTMLElement)) {\n return false;\n }\n numberColumn = numberColumn || 'columnNumber' in element.dataset;\n return 'line' in element.dataset || 'expandIndex' in element.dataset;\n });\n if (!(lineElement instanceof HTMLElement)) return undefined;\n if (lineElement.dataset.expandIndex != null) {\n const hunkIndex = parseInt(lineElement.dataset.expandIndex);\n if (isNaN(hunkIndex)) {\n return undefined;\n }\n let direction: ExpansionDirections | undefined;\n for (const element of path) {\n if (element === lineElement) break;\n if (element instanceof HTMLElement) {\n direction =\n direction ??\n ('expandUp' in element.dataset ? 'up' : undefined) ??\n ('expandDown' in element.dataset ? 'down' : undefined) ??\n ('expandBoth' in element.dataset ? 'both' : undefined);\n if (direction != null) {\n break;\n }\n }\n }\n return direction != null\n ? { type: 'line-info', hunkIndex, direction }\n : undefined;\n }\n const lineNumber = parseInt(lineElement.dataset.line ?? '');\n if (isNaN(lineNumber)) return;\n const lineType = lineElement.dataset.lineType;\n if (\n lineType !== 'context' &&\n lineType !== 'context-expanded' &&\n lineType !== 'change-deletion' &&\n lineType !== 'change-addition'\n ) {\n return undefined;\n }\n\n const numberElement = (() => {\n const numberElement = lineElement.children[0];\n return numberElement instanceof HTMLElement &&\n numberElement.dataset.columnNumber != null\n ? numberElement\n : undefined;\n })();\n\n if (this.mode === 'file') {\n return {\n type: 'line',\n lineElement,\n lineNumber,\n numberElement,\n numberColumn,\n } as GetLineDataResult<TMode>;\n }\n\n const annotationSide: AnnotationSide = (() => {\n if (lineType === 'change-deletion') {\n return 'deletions';\n }\n if (lineType === 'change-addition') {\n return 'additions';\n }\n const parent = lineElement.closest('[data-code]');\n if (!(parent instanceof HTMLElement)) {\n return 'additions';\n }\n return 'deletions' in parent.dataset ? 'deletions' : 'additions';\n })();\n\n return {\n type: 'diff-line',\n annotationSide,\n lineType,\n lineElement,\n numberElement,\n lineNumber,\n numberColumn,\n } as GetLineDataResult<TMode>;\n }\n}\n\nfunction debugLogIfEnabled(\n debugLogType: LogTypes | undefined = 'none',\n logIfType: 'move' | 'click',\n ...args: unknown[]\n) {\n switch (debugLogType) {\n case 'none':\n return;\n case 'both':\n break;\n case 'click':\n if (logIfType !== 'click') {\n return;\n }\n break;\n case 'move':\n if (logIfType !== 'move') {\n return;\n }\n break;\n }\n console.log(...args);\n}\n\nexport function pluckMouseEventOptions<TMode extends MouseEventManagerMode>(\n {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n enableHoverUtility,\n __debugMouseEvents,\n }: MouseEventManagerBaseOptions<TMode>,\n onHunkExpand?: (hunkIndex: number, direction: ExpansionDirections) => unknown\n): MouseEventManagerOptions<TMode> {\n return {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n enableHoverUtility,\n __debugMouseEvents,\n onHunkExpand,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MouseEventManager.js","names":["mode: TMode","options: MouseEventManagerOptions<TMode>","reasons: string[]","direction: ExpansionDirections | undefined","numberElement"],"sources":["../../src/managers/MouseEventManager.ts"],"sourcesContent":["import type {\n AnnotationSide,\n DiffLineEventBaseProps,\n ExpansionDirections,\n LineEventBaseProps,\n} from '../types';\n\nexport type LogTypes = 'click' | 'move' | 'both' | 'none';\n\nexport type MouseEventManagerMode = 'file' | 'diff';\n\nexport interface OnLineClickProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnLineEnterLeaveProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineClickProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineEnterLeaveProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\ntype HandleMouseEventProps =\n | { eventType: 'click'; event: PointerEvent }\n | { eventType: 'move'; event: PointerEvent };\n\ntype EventClickProps<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? OnLineClickProps\n : OnDiffLineClickProps;\n\ntype MouseEventEnterLeaveProps<TMode extends MouseEventManagerMode> =\n TMode extends 'file' ? OnLineEnterLeaveProps : OnDiffLineEnterLeaveProps;\n\ntype EventBaseProps<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? LineEventBaseProps\n : DiffLineEventBaseProps;\n\ninterface ExpandoEventProps {\n type: 'line-info';\n hunkIndex: number;\n direction: ExpansionDirections;\n}\n\nexport type GetHoveredLineResult<TMode extends MouseEventManagerMode> =\n TMode extends 'file'\n ? { lineNumber: number }\n : { lineNumber: number; side: AnnotationSide };\n\ntype GetLineDataResult<TMode extends MouseEventManagerMode> =\n TMode extends 'file'\n ? LineEventBaseProps | ExpandoEventProps | undefined\n : DiffLineEventBaseProps | ExpandoEventProps | undefined;\n\ntype LineEventData<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? LineEventBaseProps\n : DiffLineEventBaseProps;\n\nfunction isLineEventData<TMode extends MouseEventManagerMode>(\n data: GetLineDataResult<TMode>,\n mode: TMode\n): data is LineEventData<TMode> {\n if (data == null) return false;\n if (mode === 'file') {\n return data.type === 'line';\n } else {\n return data.type === 'diff-line';\n }\n}\n\nfunction isExpandoEventData(\n data:\n | LineEventBaseProps\n | DiffLineEventBaseProps\n | ExpandoEventProps\n | undefined\n): data is ExpandoEventProps {\n return data?.type === 'line-info';\n}\n\nexport interface MouseEventManagerBaseOptions<\n TMode extends MouseEventManagerMode,\n> {\n enableHoverUtility?: boolean;\n onLineClick?(props: EventClickProps<TMode>): unknown;\n onLineNumberClick?(props: EventClickProps<TMode>): unknown;\n onLineEnter?(props: MouseEventEnterLeaveProps<TMode>): unknown;\n onLineLeave?(props: MouseEventEnterLeaveProps<TMode>): unknown;\n __debugMouseEvents?: LogTypes;\n}\n\nexport interface MouseEventManagerOptions<TMode extends MouseEventManagerMode>\n extends MouseEventManagerBaseOptions<TMode> {\n onHunkExpand?(hunkIndex: number, direction: ExpansionDirections): unknown;\n}\n\nexport class MouseEventManager<TMode extends MouseEventManagerMode> {\n private hoveredLine: EventBaseProps<TMode> | undefined;\n private pre: HTMLPreElement | undefined;\n private hoverSlot: HTMLDivElement | undefined;\n\n constructor(\n private mode: TMode,\n private options: MouseEventManagerOptions<TMode>\n ) {}\n\n setOptions(options: MouseEventManagerOptions<TMode>): void {\n this.options = options;\n }\n\n cleanUp(): void {\n this.pre?.removeEventListener('click', this.handleMouseClick);\n this.pre?.removeEventListener('pointermove', this.handleMouseMove);\n this.pre?.removeEventListener('pointerout', this.handleMouseLeave);\n delete this.pre?.dataset.interactiveLines;\n delete this.pre?.dataset.interactiveLineNumbers;\n this.pre = undefined;\n }\n\n setup(pre: HTMLPreElement): void {\n const {\n __debugMouseEvents,\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onHunkExpand,\n enableHoverUtility = false,\n } = this.options;\n\n this.cleanUp();\n this.pre = pre;\n\n if (enableHoverUtility && this.hoverSlot == null) {\n this.hoverSlot = document.createElement('div');\n this.hoverSlot.dataset.hoverSlot = '';\n const slotElement = document.createElement('slot');\n slotElement.name = 'hover-slot';\n this.hoverSlot.appendChild(slotElement);\n } else if (!enableHoverUtility && this.hoverSlot != null) {\n this.hoverSlot.parentNode?.removeChild(this.hoverSlot);\n this.hoverSlot = undefined;\n }\n\n if (\n onLineClick != null ||\n onLineNumberClick != null ||\n onHunkExpand != null\n ) {\n pre.addEventListener('click', this.handleMouseClick);\n if (onLineClick != null) {\n pre.dataset.interactiveLines = '';\n } else if (onLineNumberClick != null) {\n pre.dataset.interactiveLineNumbers = '';\n }\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n 'FileDiff.DEBUG.attachEventListeners: Attaching click events for:',\n (() => {\n const reasons: string[] = [];\n if (__debugMouseEvents === 'both' || __debugMouseEvents === 'click') {\n if (onLineClick != null) {\n reasons.push('onLineClick');\n }\n if (onLineNumberClick != null) {\n reasons.push('onLineNumberClick');\n }\n if (onHunkExpand != null) {\n reasons.push('expandable hunk separators');\n }\n }\n return reasons;\n })()\n );\n }\n if (onLineEnter != null || onLineLeave != null || enableHoverUtility) {\n pre.addEventListener('pointermove', this.handleMouseMove);\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching pointer move event'\n );\n pre.addEventListener('pointerleave', this.handleMouseLeave);\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event'\n );\n }\n }\n\n getHoveredLine = (): GetHoveredLineResult<TMode> | undefined => {\n if (this.hoveredLine != null) {\n if (this.mode === 'diff' && this.hoveredLine.type === 'diff-line') {\n return {\n lineNumber: this.hoveredLine.lineNumber,\n side: this.hoveredLine.annotationSide,\n } as GetHoveredLineResult<TMode>;\n }\n if (this.mode === 'file' && this.hoveredLine.type === 'line') {\n return {\n lineNumber: this.hoveredLine.lineNumber,\n } as GetHoveredLineResult<TMode>;\n }\n }\n return undefined;\n };\n\n handleMouseClick = (event: PointerEvent): void => {\n debugLogIfEnabled(\n this.options.__debugMouseEvents,\n 'click',\n 'FileDiff.DEBUG.handleMouseClick:',\n event\n );\n this.handleMouseEvent({ eventType: 'click', event });\n };\n\n handleMouseMove = (event: PointerEvent): void => {\n debugLogIfEnabled(\n this.options.__debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseMove:',\n event\n );\n this.handleMouseEvent({ eventType: 'move', event });\n };\n\n handleMouseLeave = (event: PointerEvent): void => {\n const { __debugMouseEvents } = this.options;\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseLeave: no event'\n );\n if (this.hoveredLine == null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseLeave: returned early, no .hoveredLine'\n );\n return;\n }\n this.hoverSlot?.parentElement?.removeChild(this.hoverSlot);\n this.options.onLineLeave?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n this.hoveredLine = undefined;\n };\n\n private handleMouseEvent({ eventType, event }: HandleMouseEventProps) {\n const { __debugMouseEvents } = this.options;\n const composedPath = event.composedPath();\n debugLogIfEnabled(\n __debugMouseEvents,\n eventType,\n 'FileDiff.DEBUG.handleMouseEvent:',\n { eventType, composedPath }\n );\n const data = this.getLineData(composedPath);\n debugLogIfEnabled(\n __debugMouseEvents,\n eventType,\n 'FileDiff.DEBUG.handleMouseEvent: getLineData result:',\n data\n );\n const {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onHunkExpand,\n } = this.options;\n switch (eventType) {\n case 'move': {\n if (\n isLineEventData(data, this.mode) &&\n this.hoveredLine?.lineElement === data.lineElement\n ) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', returned early because same line\"\n );\n break;\n }\n if (this.hoveredLine != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', clearing an existing hovered line and firing onLineLeave\"\n );\n this.hoverSlot?.parentElement?.removeChild(this.hoverSlot);\n onLineLeave?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n this.hoveredLine = undefined;\n }\n if (isLineEventData(data, this.mode)) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', setting up a new hoveredLine and firing onLineEnter\"\n );\n this.hoveredLine = data;\n if (this.hoverSlot != null) {\n data.numberElement?.appendChild(this.hoverSlot);\n }\n onLineEnter?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n }\n break;\n }\n case 'click':\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', with data:\",\n data\n );\n if (data == null) break;\n if (isExpandoEventData(data) && onHunkExpand != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', expanding a hunk\"\n );\n onHunkExpand(data.hunkIndex, data.direction);\n break;\n }\n if (isLineEventData(data, this.mode)) {\n if (onLineNumberClick != null && data.numberColumn) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', firing 'onLineNumberClick'\"\n );\n onLineNumberClick({ ...data, event } as EventClickProps<TMode>);\n } else if (onLineClick != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', firing 'onLineClick'\"\n );\n onLineClick({ ...data, event } as EventClickProps<TMode>);\n } else {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', fell through, no event to fire\"\n );\n }\n }\n break;\n }\n }\n\n private getLineData(\n path: (EventTarget | undefined)[]\n ): GetLineDataResult<TMode> {\n let numberColumn = false;\n const lineElement = path.find((element) => {\n if (!(element instanceof HTMLElement)) {\n return false;\n }\n numberColumn = numberColumn || 'columnNumber' in element.dataset;\n return 'line' in element.dataset || 'expandIndex' in element.dataset;\n });\n if (!(lineElement instanceof HTMLElement)) return undefined;\n if (lineElement.dataset.expandIndex != null) {\n const hunkIndex = parseInt(lineElement.dataset.expandIndex);\n if (isNaN(hunkIndex)) {\n return undefined;\n }\n let direction: ExpansionDirections | undefined;\n for (const element of path) {\n if (element === lineElement) break;\n if (element instanceof HTMLElement) {\n direction =\n direction ??\n ('expandUp' in element.dataset ? 'up' : undefined) ??\n ('expandDown' in element.dataset ? 'down' : undefined) ??\n ('expandBoth' in element.dataset ? 'both' : undefined);\n if (direction != null) {\n break;\n }\n }\n }\n return direction != null\n ? { type: 'line-info', hunkIndex, direction }\n : undefined;\n }\n const lineNumber = parseInt(lineElement.dataset.line ?? '');\n if (isNaN(lineNumber)) return;\n const lineType = lineElement.dataset.lineType;\n if (\n lineType !== 'context' &&\n lineType !== 'context-expanded' &&\n lineType !== 'change-deletion' &&\n lineType !== 'change-addition'\n ) {\n return undefined;\n }\n\n const numberElement = (() => {\n const numberElement = lineElement.children[0];\n return numberElement instanceof HTMLElement &&\n numberElement.dataset.columnNumber != null\n ? numberElement\n : undefined;\n })();\n\n if (this.mode === 'file') {\n return {\n type: 'line',\n lineElement,\n lineNumber,\n numberElement,\n numberColumn,\n } as GetLineDataResult<TMode>;\n }\n\n const annotationSide: AnnotationSide = (() => {\n if (lineType === 'change-deletion') {\n return 'deletions';\n }\n if (lineType === 'change-addition') {\n return 'additions';\n }\n const parent = lineElement.closest('[data-code]');\n if (!(parent instanceof HTMLElement)) {\n return 'additions';\n }\n return 'deletions' in parent.dataset ? 'deletions' : 'additions';\n })();\n\n return {\n type: 'diff-line',\n annotationSide,\n lineType,\n lineElement,\n numberElement,\n lineNumber,\n numberColumn,\n } as GetLineDataResult<TMode>;\n }\n}\n\nfunction debugLogIfEnabled(\n debugLogType: LogTypes | undefined = 'none',\n logIfType: 'move' | 'click',\n ...args: unknown[]\n) {\n switch (debugLogType) {\n case 'none':\n return;\n case 'both':\n break;\n case 'click':\n if (logIfType !== 'click') {\n return;\n }\n break;\n case 'move':\n if (logIfType !== 'move') {\n return;\n }\n break;\n }\n console.log(...args);\n}\n\nexport function pluckMouseEventOptions<TMode extends MouseEventManagerMode>(\n {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n enableHoverUtility,\n __debugMouseEvents,\n }: MouseEventManagerBaseOptions<TMode>,\n onHunkExpand?: (hunkIndex: number, direction: ExpansionDirections) => unknown\n): MouseEventManagerOptions<TMode> {\n return {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n enableHoverUtility,\n __debugMouseEvents,\n onHunkExpand,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;UAaiB,YAAA;;EAAjB,IAAiB,EAAA,MAAA;EAoBjB,QAAY,EAAA,MAAA;EAMZ,IAAY,CAAA,EAtBH,kBAsBG;EAEZ,MAAY,CAAA,EAAA,MAAA;;AAAmB,KARnB,eAAA,GACR,YAO2B,GAAA,aAAA,GAAA,cAAA,GAAA,CAAA,MAAA,GAAA,CAAA,CAAA,CAAA;AAAA,KAFnB,UAAA,GAAa,MAEM,CAAA,MAAA,GAAA,OAAA,EAFmB,eAEnB,CAAA;AAKnB,KALA,gBAAA,GAAmB,kBAKnB,CAJV,kBAIU,EAHV,eAGU,CAAA;AAOK,KAPL,WAAA,GAOK,QAER,GAAA,aAAA,GAAA,gBAAA,GAAA,KAAA,GAAA,SAAA;AAGQ,UALA,WAAA,CAKA;EAMjB,aAAiB,CAAA,EAAA,MAAA;EAQjB,KAAiB,EAjBR,gBA6BO,EAAA;AAKhB;AAGS,UAlCQ,cAAA,CAkCR;EACD,IAAA,EAAA,SAAA;EACC,KAAA,EAAA,MAAA,EAAA;EAAA,OAAA,EAAA,OAAA;AAUT;AAGY,UA3CK,aAAA,CA2CL;EAOZ,IAAY,EAAA,QAAA;EAEZ,SAAY,EAAA,MAAA,EAAA;EAEZ,SAAY,EAAA,MAAA,EAAA;EAEZ,gBAAiB,EAAA,OAAA;EACP,gBAAA,EAAA,OAAA;;AAGI,UApDG,IAAA,CAoDH;EAAA,eAAA,EAAA,MAAA;EAWd,cAAiB,EAAA,MAAA;EAIE,cAAA,EAAA,MAAA;EAIF,gBAAA,EAAA,MAAA;EARwB,gBAAA,EAAA,MAAA;EAAA,aAAA,EAAA,MAAA;EAkBzC,aAAiB,EAAA,MAAA;EAGX,aAAA,EAAA,MAAA;EADF,aAAA,EAAA,MAAA;EADM,aAAA,EAAA,MAAA;EAAA,aAAA,EAAA,MAAA;EAeV,WAAiB,EAAA,CArFD,cAqFC,GArFgB,aAqFhB,CAAA,EAAA;EACL,WAAA,EAAA,MAAA,GAAA,SAAA;EACA,SAAA,EAAA,MAAA,GAAA,SAAA;;AACC,UAnFI,gBAAA,CAmFJ;EAGb,IAAY,EAAA,MAAA;EAIZ,QAAY,EAAA,MAAA,GAAA,SAAA;EAIZ,IAAY,CAAA,EA3FH,kBA2FG;EAEZ,IAAY,EA5FJ,WA4FI;EAA+B,KAEtC,EA7FI,IA6FJ,EAAA;EAIL,cAAY,EAAA,MAAA;EAIZ,gBAAY,EAAA,MAAA;EACJ,OAAA,CAAA,EAAA,MAAA;EAEa,IAAA,CAAA,EAAA,MAAA;EAAjB,QAAA,CAAA,EAAA,MAAA,EAAA;EAAA,QAAA,CAAA,EAAA,MAAA,EAAA;EAEJ,QAAiB,CAAA,EAAA,MAAA;AAKjB;AAKY,KA1GA,kBAAA,GAAqB,eA0GrB,GAAA,MAAA;AAMK,KA7GL,YAAA,GA6GK,SACT,GAAA,UAAA,GAAA,UAAA,GAAA,UAAA,GAAA,UAAA;AAMS,KA7GL,UAAA,GA6GK,QAAA,GAAA,OAAA,GAAA,MAAA;AAEI,KA7GT,cAAA,GA6GS,QAAA,GAAA,UAAA,GAAA,WAAA,GAAA,QAAA;AAAf,KA3GM,aAAA,GA2GN,UAAA,GAAA,MAAA,GAAA,MAAA,GAAA,MAAA;AAC8B,UA1GnB,eAAA,CA0GmB;EAAA,KAAA,CAAA,EAzG1B,eAyG0B,GAzGR,UAyGQ;EAGpC,kBAAiB,CAAA,EAAA,OAAA;EAOjB,QAAiB,CAAA,EAAA,QAAA,GAAA,MAAA;EAQjB,SAAiB,CAAA,EAxHH,UAwHG;EACF,iBAAA,CAAA,EAAA,OAAA;EAEG,aAAA,CAAA,EAAA,OAAA;EACN,qBAAA,CAAA,EAAA,MAAA;EAHF,SAAA,CAAA,EAAA,MAAA;;AAMO,UApHA,eAAA,SAAwB,eAoHxB,CAAA;EAGF,SAAA,CAAA,EAAA,SAAA,GAAA,OAAA;EACJ,cAAA,CAAA,EAAA,SAAA,GAAA,MAAA,GAAA,MAAA;EAII,iBAAA,CAAA,EAAA,OAAA;EACJ,cAAA,CAAA,EAzHQ,cAyHR;EAAA,eAAA,CAAA,EAAA,OAAA;EAMX,YAAiB,CAAA,EA3HA,aA2HA;EAQjB,iBAAiB,CAAA,EAAA,MAAA;EAYjB,kBAAiB,CAAA,EAAA,MAAA;AAQjB;AAEqB,UA/IJ,mBAAA,SACP,QA8IW,CA7IjB,IA6IiB,CA5If,eA4Ie,EAAA,gBAAA,GAAA,mBAAA,GAAA,oBAAA,GAAA,UAAA,GAAA,WAAA,CAAA,CAAA,CAAA;EAAnB,KAAA,EAAA,OAAA;EAF2C,WAAA,EAAA,MAAA;EAAA,UAAA,EAAA,MAAA;AAK7C;AAEiB,UApIA,yBAAA,CAqIL;EAKZ,OAAiB,CAAA,EAzIL,YAyIK;EAMjB,OAAiB,CAAA,EA9IL,YA8IK;EAMjB,QAAiB,CAAA,EAnJJ,gBAmJI;AAMjB;AACS,KAvJG,4BAAA,GAuJH,CAAA,KAAA,EAtJA,yBAsJA,EAAA,GArJJ,OAqJI,GAAA,IAAA,GAAA,SAAA,GAAA,MAAA,GAAA,MAAA;AAA2C,KAnJxC,kBAAA,GAmJwC,CAAA,IAAA,EAlJ5C,YAkJ4C,EAAA,GAjJ/C,OAiJ+C,GAAA,IAAA,GAAA,SAAA,GAAA,MAAA,GAAA,MAAA;AAAzB,KA/If,kBAAA,GAAqB,MA+IN,CAAA,MAAA,EA/IqB,kBA+IrB,GAAA,SAAA,CAAA;AAAA,KA7If,cAAA,GA6Ie,WAAA,GAAA,WAAA;AAI3B,KA/IK,gBA+IY,CAAA,CAAA,CAAA,GA/IU,CA+IV,SAAA,SAAA,GAAA;EACR,QAAA,CAAA,EAAA,SAAA;CAA2C,GAAA;EAAzB,QAAA,EA9IX,CA8IW;CAEX;AAAA,KA9IJ,cA8II,CAAA,IAAA,SAAA,CAAA,GAAA;EAGhB,UAAiB,EAAA,MAAA;AAKjB,CAAA,GApJI,gBAoJa,CApJI,CAoJJ,CAAA;AAKA,KAvJL,kBAuJK,CAAA,IAAA,SAAA,CAAA,GAAA;EACT,IAAA,EAvJA,cAuJA;EAEG,UAAA,EAAA,MAAA;CACD,GAxJN,gBAwJM,CAxJW,CAwJX,CAAA;AAAA,UAtJO,OAAA,CAsJP;EAGV,IAAiB,EAAA,KAAA;EACT,IAAA,EAAA,MAAA;;AAGE,KAxJE,SAAA,GAAY,OAwJd,GAxJwB,cAwJxB;AAAA,KAnJE,SAAA,GAmJF,iBAAA,GAAA,iBAAA,GAAA,SAAA,GAAA,kBAAA;UA7IO,QAAA;QACT;;;;;UAMS,iBAAA;YAEX,eAAe,sDACe;;UAGnB,cAAA;;;;;;UAOA,kBAAA;;;eAGF;iBACE;;;UAIA,sBAAA,SACP,KAAK;;kBAEG;YACN;;UAGK,uBAAA;;;eAGF;WACJ;;;;eAII;WACJ;;;;;UAMM,iBAAA;;eAEF;iBACE;;;;UAKA,QAAA;;;;;;;;;;;UAYA,UAAA;;;;;;;KAQL,iCAAiC,eAE3C,mBAAmB;KAGT,mBAAA;UAEK,qBAAA;YACL;YACA;;;UAIK,qBAAA;SACR;;;;UAKQ,gBAAA;QACT;;;;UAKS,gBAAA;QACT,wBAAwB;;;;UAKf,iBAAA;SACR,kBAAkB,yBAAyB;;;UAInC,iBAAA;SACR,kBAAkB,yBAAyB;;gBAEpC;;UAGC,gBAAA;UACP;WACC;;UAGM,gBAAA;UACP;WACC;;UAGM,oBAAA;QACT;;WAEG;UACD;;UAGO,oBAAA;QACT;;WAEG;UACD"}
@@ -1,4 +1,5 @@
1
1
  import { FileContents, FileDiffMetadata } from "../types.js";
2
+ import { CreatePatchOptionsNonabortable } from "diff";
2
3
 
3
4
  //#region src/utils/parseDiffFromFile.d.ts
4
5
 
@@ -8,7 +9,7 @@ import { FileContents, FileDiffMetadata } from "../types.js";
8
9
  * If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff will
9
10
  * automatically get a combined cache key in the format `oldKey:newKey`.
10
11
  */
11
- declare function parseDiffFromFile(oldFile: FileContents, newFile: FileContents): FileDiffMetadata;
12
+ declare function parseDiffFromFile(oldFile: FileContents, newFile: FileContents, options?: CreatePatchOptionsNonabortable): FileDiffMetadata;
12
13
  //#endregion
13
14
  export { parseDiffFromFile };
14
15
  //# sourceMappingURL=parseDiffFromFile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseDiffFromFile.d.ts","names":[],"sources":["../../src/utils/parseDiffFromFile.ts"],"sourcesContent":[],"mappings":";;;;;;AAYA;;;;AAGG,iBAHa,iBAAA,CAGb,OAAA,EAFQ,YAER,EAAA,OAAA,EADQ,YACR,CAAA,EAAA,gBAAA"}
1
+ {"version":3,"file":"parseDiffFromFile.d.ts","names":[],"sources":["../../src/utils/parseDiffFromFile.ts"],"sourcesContent":[],"mappings":";;;;;;;AAYA;;;;AAIG,iBAJa,iBAAA,CAIb,OAAA,EAHQ,YAGR,EAAA,OAAA,EAFQ,YAER,EAAA,OAAA,CAAA,EADS,8BACT,CAAA,EAAA,gBAAA"}
@@ -9,8 +9,8 @@ import { createTwoFilesPatch } from "diff";
9
9
  * If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff will
10
10
  * automatically get a combined cache key in the format `oldKey:newKey`.
11
11
  */
12
- function parseDiffFromFile(oldFile, newFile) {
13
- const fileData = parsePatchFiles(createTwoFilesPatch(oldFile.name, newFile.name, oldFile.contents, newFile.contents, oldFile.header, newFile.header))[0]?.files[0];
12
+ function parseDiffFromFile(oldFile, newFile, options) {
13
+ const fileData = parsePatchFiles(createTwoFilesPatch(oldFile.name, newFile.name, oldFile.contents, newFile.contents, oldFile.header, newFile.header, options))[0]?.files[0];
14
14
  if (fileData == null) throw new Error("parseDiffFrom: FileInvalid diff -- probably need to fix something -- if the files are the same maybe?");
15
15
  fileData.oldLines = oldFile.contents.split(SPLIT_WITH_NEWLINES);
16
16
  fileData.newLines = newFile.contents.split(SPLIT_WITH_NEWLINES);
@@ -1 +1 @@
1
- {"version":3,"file":"parseDiffFromFile.js","names":[],"sources":["../../src/utils/parseDiffFromFile.ts"],"sourcesContent":["import { createTwoFilesPatch } from 'diff';\n\nimport { SPLIT_WITH_NEWLINES } from '../constants';\nimport type { FileContents, FileDiffMetadata } from '../types';\nimport { parsePatchFiles } from './parsePatchFiles';\n\n/**\n * Parses a diff from two file contents objects.\n *\n * If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff will\n * automatically get a combined cache key in the format `oldKey:newKey`.\n */\nexport function parseDiffFromFile(\n oldFile: FileContents,\n newFile: FileContents\n): FileDiffMetadata {\n const patch = createTwoFilesPatch(\n oldFile.name,\n newFile.name,\n oldFile.contents,\n newFile.contents,\n oldFile.header,\n newFile.header\n );\n const fileData = parsePatchFiles(patch)[0]?.files[0];\n if (fileData == null) {\n throw new Error(\n 'parseDiffFrom: FileInvalid diff -- probably need to fix something -- if the files are the same maybe?'\n );\n }\n fileData.oldLines = oldFile.contents.split(SPLIT_WITH_NEWLINES);\n fileData.newLines = newFile.contents.split(SPLIT_WITH_NEWLINES);\n if (oldFile.cacheKey != null && newFile.cacheKey != null) {\n fileData.cacheKey = `${oldFile.cacheKey}:${newFile.cacheKey}`;\n }\n return fileData;\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,kBACd,SACA,SACkB;CASlB,MAAM,WAAW,gBARH,oBACZ,QAAQ,MACR,QAAQ,MACR,QAAQ,UACR,QAAQ,UACR,QAAQ,QACR,QAAQ,OACT,CACsC,CAAC,IAAI,MAAM;AAClD,KAAI,YAAY,KACd,OAAM,IAAI,MACR,wGACD;AAEH,UAAS,WAAW,QAAQ,SAAS,MAAM,oBAAoB;AAC/D,UAAS,WAAW,QAAQ,SAAS,MAAM,oBAAoB;AAC/D,KAAI,QAAQ,YAAY,QAAQ,QAAQ,YAAY,KAClD,UAAS,WAAW,GAAG,QAAQ,SAAS,GAAG,QAAQ;AAErD,QAAO"}
1
+ {"version":3,"file":"parseDiffFromFile.js","names":[],"sources":["../../src/utils/parseDiffFromFile.ts"],"sourcesContent":["import { type CreatePatchOptionsNonabortable, createTwoFilesPatch } from 'diff';\n\nimport { SPLIT_WITH_NEWLINES } from '../constants';\nimport type { FileContents, FileDiffMetadata } from '../types';\nimport { parsePatchFiles } from './parsePatchFiles';\n\n/**\n * Parses a diff from two file contents objects.\n *\n * If both `oldFile` and `newFile` have a `cacheKey`, the resulting diff will\n * automatically get a combined cache key in the format `oldKey:newKey`.\n */\nexport function parseDiffFromFile(\n oldFile: FileContents,\n newFile: FileContents,\n options?: CreatePatchOptionsNonabortable\n): FileDiffMetadata {\n const patch = createTwoFilesPatch(\n oldFile.name,\n newFile.name,\n oldFile.contents,\n newFile.contents,\n oldFile.header,\n newFile.header,\n options\n );\n const fileData = parsePatchFiles(patch)[0]?.files[0];\n if (fileData == null) {\n throw new Error(\n 'parseDiffFrom: FileInvalid diff -- probably need to fix something -- if the files are the same maybe?'\n );\n }\n fileData.oldLines = oldFile.contents.split(SPLIT_WITH_NEWLINES);\n fileData.newLines = newFile.contents.split(SPLIT_WITH_NEWLINES);\n if (oldFile.cacheKey != null && newFile.cacheKey != null) {\n fileData.cacheKey = `${oldFile.cacheKey}:${newFile.cacheKey}`;\n }\n return fileData;\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,kBACd,SACA,SACA,SACkB;CAUlB,MAAM,WAAW,gBATH,oBACZ,QAAQ,MACR,QAAQ,MACR,QAAQ,UACR,QAAQ,UACR,QAAQ,QACR,QAAQ,QACR,QACD,CACsC,CAAC,IAAI,MAAM;AAClD,KAAI,YAAY,KACd,OAAM,IAAI,MACR,wGACD;AAEH,UAAS,WAAW,QAAQ,SAAS,MAAM,oBAAoB;AAC/D,UAAS,WAAW,QAAQ,SAAS,MAAM,oBAAoB;AAC/D,KAAI,QAAQ,YAAY,QAAQ,QAAQ,YAAY,KAClD,UAAS,WAAW,GAAG,QAAQ,SAAS,GAAG,QAAQ;AAErD,QAAO"}
@@ -283,8 +283,8 @@ function processLines({ hunks, oldLines, newLines, splitLineIndex = 0, unifiedLi
283
283
  }
284
284
  }
285
285
  return {
286
- oldContent: cleanLastNewline(oldContent),
287
- newContent: cleanLastNewline(newContent),
286
+ oldContent,
287
+ newContent,
288
288
  oldInfo,
289
289
  newInfo,
290
290
  oldDecorations,
@@ -322,14 +322,14 @@ function renderTwoFiles({ oldFile, newFile, oldInfo, newInfo, highlighter, oldDe
322
322
  hastConfig.lang = oldLang;
323
323
  state.lineInfo = oldInfo;
324
324
  hastConfig.decorations = oldDecorations;
325
- return getLineNodes(highlighter.codeToHast(oldFile.contents, hastConfig));
325
+ return getLineNodes(highlighter.codeToHast(cleanLastNewline(oldFile.contents), hastConfig));
326
326
  })(),
327
327
  newLines: (() => {
328
328
  if (newFile.contents === "") return [];
329
329
  hastConfig.lang = newLang;
330
330
  hastConfig.decorations = newDecorations;
331
331
  state.lineInfo = newInfo;
332
- return getLineNodes(highlighter.codeToHast(newFile.contents, hastConfig));
332
+ return getLineNodes(highlighter.codeToHast(cleanLastNewline(newFile.contents), hastConfig));
333
333
  })()
334
334
  };
335
335
  }
@@ -1 +1 @@
1
- {"version":3,"file":"renderDiffWithHighlighter.js","names":["hunks: RenderDiffFilesResult[]","deletionSpans: [0 | 1, string][]","additionSpans: [0 | 1, string][]","oldInfo: Record<number, LineInfo | undefined>","newInfo: Record<number, LineInfo | undefined>","oldDecorations: DecorationItem[]","newDecorations: DecorationItem[]","hastConfig: CodeToHastOptions<DiffsThemeNames>"],"sources":["../../src/utils/renderDiffWithHighlighter.ts"],"sourcesContent":["import { diffChars, diffWordsWithSpace } from 'diff';\n\nimport { DEFAULT_THEMES } from '../constants';\nimport type {\n CodeToHastOptions,\n DecorationItem,\n DiffsHighlighter,\n DiffsThemeNames,\n FileContents,\n FileDiffMetadata,\n Hunk,\n LineDiffTypes,\n LineInfo,\n RenderDiffFilesResult,\n RenderDiffOptions,\n SupportedLanguages,\n ThemedDiffResult,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { createTransformerWithState } from './createTransformerWithState';\nimport { formatCSSVariablePrefix } from './formatCSSVariablePrefix';\nimport { getFiletypeFromFileName } from './getFiletypeFromFileName';\nimport { getHighlighterThemeStyles } from './getHighlighterThemeStyles';\nimport { getLineNodes } from './getLineNodes';\nimport {\n createDiffSpanDecoration,\n pushOrJoinSpan,\n} from './parseDiffDecorations';\n\nexport function renderDiffWithHighlighter(\n diff: FileDiffMetadata,\n highlighter: DiffsHighlighter,\n options: RenderDiffOptions,\n forcePlainText = false\n): ThemedDiffResult {\n const baseThemeType = (() => {\n const theme = options.theme ?? DEFAULT_THEMES;\n if (typeof theme === 'string') {\n return highlighter.getTheme(theme).type;\n }\n return undefined;\n })();\n const themeStyles = getHighlighterThemeStyles({\n theme: options.theme,\n highlighter,\n });\n // If we've received a diff with both files\n if (diff.newLines != null && diff.oldLines != null) {\n const {\n oldContent,\n newContent,\n oldInfo,\n newInfo,\n oldDecorations,\n newDecorations,\n } = processLines({\n hunks: diff.hunks,\n oldLines: diff.oldLines,\n newLines: diff.newLines,\n lineDiffType: options.lineDiffType,\n });\n const oldFile = {\n name: diff.prevName ?? diff.name,\n contents: oldContent,\n };\n const newFile = {\n name: diff.name,\n contents: newContent,\n };\n const code = renderTwoFiles({\n oldFile,\n oldInfo,\n oldDecorations,\n\n newFile,\n newInfo,\n newDecorations,\n\n highlighter,\n options,\n languageOverride: forcePlainText ? 'text' : diff.lang,\n });\n return { code, themeStyles, baseThemeType };\n }\n const hunks: RenderDiffFilesResult[] = [];\n let splitLineIndex = 0;\n let unifiedLineIndex = 0;\n for (const hunk of diff.hunks) {\n const {\n oldContent,\n newContent,\n oldInfo,\n newInfo,\n oldDecorations,\n newDecorations,\n splitLineIndex: newSplitLineIndex,\n unifiedLineIndex: newUnifiedLineIndex,\n } = processLines({\n hunks: [hunk],\n splitLineIndex,\n unifiedLineIndex,\n lineDiffType: options.lineDiffType,\n });\n const oldFile = {\n name: diff.prevName ?? diff.name,\n contents: oldContent,\n };\n const newFile = {\n name: diff.name,\n contents: newContent,\n };\n hunks.push(\n renderTwoFiles({\n oldFile,\n oldInfo,\n oldDecorations,\n\n newFile,\n newInfo,\n newDecorations,\n\n highlighter,\n options,\n languageOverride: forcePlainText ? 'text' : diff.lang,\n })\n );\n splitLineIndex = newSplitLineIndex;\n unifiedLineIndex = newUnifiedLineIndex;\n }\n\n const code = (() => {\n if (hunks.length <= 1) {\n const hunk = hunks[0] ?? { oldLines: [], newLines: [] };\n if (hunk.newLines.length === 0 || hunk.oldLines.length === 0) {\n return hunk;\n }\n }\n return { hunks };\n })();\n\n return { code, themeStyles, baseThemeType };\n}\n\ninterface ProcessLineDiffProps {\n oldLine: string | undefined;\n newLine: string | undefined;\n oldLineIndex: number;\n newLineIndex: number;\n oldDecorations: DecorationItem[];\n newDecorations: DecorationItem[];\n lineDiffType: LineDiffTypes;\n}\n\nfunction computeLineDiffDecorations({\n oldLine,\n newLine,\n oldLineIndex,\n newLineIndex,\n oldDecorations,\n newDecorations,\n lineDiffType,\n}: ProcessLineDiffProps) {\n if (oldLine == null || newLine == null || lineDiffType === 'none') {\n return;\n }\n oldLine = cleanLastNewline(oldLine);\n newLine = cleanLastNewline(newLine);\n // NOTE(amadeus): Because we visually trim trailing newlines when rendering,\n // we also gotta make sure the diff parsing doesn't include the newline\n // character that could be there...\n const lineDiff =\n lineDiffType === 'char'\n ? diffChars(oldLine, newLine)\n : diffWordsWithSpace(oldLine, newLine);\n const deletionSpans: [0 | 1, string][] = [];\n const additionSpans: [0 | 1, string][] = [];\n const enableJoin = lineDiffType === 'word-alt';\n for (const item of lineDiff) {\n const isLastItem = item === lineDiff[lineDiff.length - 1];\n if (!item.added && !item.removed) {\n pushOrJoinSpan({\n item,\n arr: deletionSpans,\n enableJoin,\n isNeutral: true,\n isLastItem,\n });\n pushOrJoinSpan({\n item,\n arr: additionSpans,\n enableJoin,\n isNeutral: true,\n isLastItem,\n });\n } else if (item.removed) {\n pushOrJoinSpan({ item, arr: deletionSpans, enableJoin, isLastItem });\n } else {\n pushOrJoinSpan({ item, arr: additionSpans, enableJoin, isLastItem });\n }\n }\n let spanIndex = 0;\n for (const span of deletionSpans) {\n if (span[0] === 1) {\n oldDecorations.push(\n createDiffSpanDecoration({\n // Decoration indexes start at 0\n line: oldLineIndex - 1,\n spanStart: spanIndex,\n spanLength: span[1].length,\n })\n );\n }\n spanIndex += span[1].length;\n }\n spanIndex = 0;\n for (const span of additionSpans) {\n if (span[0] === 1) {\n newDecorations.push(\n createDiffSpanDecoration({\n // Decoration indexes start at 0\n line: newLineIndex - 1,\n spanStart: spanIndex,\n spanLength: span[1].length,\n })\n );\n }\n spanIndex += span[1].length;\n }\n}\n\ninterface ProcessLinesProps {\n hunks: Hunk[];\n oldLines?: string[];\n newLines?: string[];\n splitLineIndex?: number;\n unifiedLineIndex?: number;\n newLineIndex?: number;\n oldLineIndex?: number;\n lineDiffType: LineDiffTypes;\n}\n\nfunction processLines({\n hunks,\n oldLines,\n newLines,\n splitLineIndex = 0,\n unifiedLineIndex = 0,\n lineDiffType,\n}: ProcessLinesProps) {\n const oldInfo: Record<number, LineInfo | undefined> = {};\n const newInfo: Record<number, LineInfo | undefined> = {};\n const oldDecorations: DecorationItem[] = [];\n const newDecorations: DecorationItem[] = [];\n let newLineIndex = 1;\n let oldLineIndex = 1;\n let newLineNumber = 1;\n let oldLineNumber = 1;\n let oldContent = '';\n let newContent = '';\n for (const hunk of hunks) {\n // If there's content prior to the hunk, lets fill it up\n while (\n oldLines != null &&\n newLines != null &&\n newLineIndex < hunk.additionStart &&\n oldLineIndex < hunk.deletionStart\n ) {\n oldInfo[oldLineIndex] = {\n type: 'context-expanded',\n lineNumber: oldLineNumber,\n altLineNumber: newLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n newInfo[newLineIndex] = {\n type: 'context-expanded',\n lineNumber: newLineNumber,\n altLineNumber: oldLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n oldContent += oldLines[oldLineIndex - 1];\n newContent += newLines[newLineIndex - 1];\n oldLineIndex++;\n newLineIndex++;\n oldLineNumber++;\n newLineNumber++;\n splitLineIndex++;\n unifiedLineIndex++;\n }\n oldLineNumber = hunk.deletionStart;\n newLineNumber = hunk.additionStart;\n\n // Lets process the actual hunk content\n for (const hunkContent of hunk.hunkContent) {\n if (hunkContent.type === 'context') {\n for (const line of hunkContent.lines) {\n oldInfo[oldLineIndex] = {\n type: 'context',\n lineNumber: oldLineNumber,\n altLineNumber: newLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n newInfo[newLineIndex] = {\n type: 'context',\n lineNumber: newLineNumber,\n altLineNumber: oldLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n oldContent += line;\n newContent += line;\n oldLineIndex++;\n newLineIndex++;\n newLineNumber++;\n oldLineNumber++;\n splitLineIndex++;\n unifiedLineIndex++;\n }\n } else {\n const len = Math.max(\n hunkContent.additions.length,\n hunkContent.deletions.length\n );\n let i = 0;\n // NOTE(amadeus): Since we iterate through deletions and additions\n // simultaneously, we have to create a secondary iterator for\n // unifiedLineIndex, and then when we're done, add the combined lengths\n // of additions/deletions to the main variable\n let _unifiedLineIndex = unifiedLineIndex;\n while (i < len) {\n const oldLine = hunkContent.deletions[i];\n const newLine = hunkContent.additions[i];\n computeLineDiffDecorations({\n newLine,\n oldLine,\n oldLineIndex,\n newLineIndex,\n oldDecorations,\n newDecorations,\n lineDiffType,\n });\n if (oldLine != null) {\n oldInfo[oldLineIndex] = {\n type: 'change-deletion',\n lineNumber: oldLineNumber,\n lineIndex: `${_unifiedLineIndex},${splitLineIndex}`,\n };\n oldContent += oldLine;\n oldLineIndex++;\n oldLineNumber++;\n }\n if (newLine != null) {\n newInfo[newLineIndex] = {\n type: 'change-addition',\n lineNumber: newLineNumber,\n lineIndex: `${_unifiedLineIndex + hunkContent.deletions.length},${splitLineIndex}`,\n };\n newContent += newLine;\n newLineIndex++;\n newLineNumber++;\n }\n splitLineIndex++;\n _unifiedLineIndex++;\n i++;\n }\n unifiedLineIndex +=\n hunkContent.additions.length + hunkContent.deletions.length;\n }\n }\n\n if (\n oldLines == null ||\n newLines == null ||\n hunk !== hunks[hunks.length - 1]\n )\n continue;\n // If we are on the last hunk, we should fully iterate through the rest\n // of the lines\n while (oldLineIndex <= oldLines.length || newLineIndex <= oldLines.length) {\n const oldLine = oldLines[oldLineIndex - 1];\n const newLine = newLines[newLineIndex - 1];\n if (oldLine == null && newLine == null) {\n break;\n }\n if (oldLine != null) {\n oldInfo[oldLineIndex] = {\n type: 'context-expanded',\n lineNumber: oldLineNumber,\n altLineNumber: newLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n oldContent += oldLine;\n oldLineIndex++;\n oldLineNumber++;\n }\n if (newLine != null) {\n newInfo[newLineIndex] = {\n type: 'context-expanded',\n lineNumber: newLineNumber,\n altLineNumber: oldLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n newContent += newLine;\n newLineIndex++;\n newLineNumber++;\n }\n splitLineIndex++;\n unifiedLineIndex++;\n }\n }\n return {\n oldContent: cleanLastNewline(oldContent),\n newContent: cleanLastNewline(newContent),\n oldInfo,\n newInfo,\n oldDecorations,\n newDecorations,\n splitLineIndex,\n unifiedLineIndex,\n };\n}\n\ninterface RenderTwoFilesProps {\n oldFile: FileContents;\n newFile: FileContents;\n oldInfo: Record<number, LineInfo | undefined>;\n newInfo: Record<number, LineInfo | undefined>;\n oldDecorations: DecorationItem[];\n newDecorations: DecorationItem[];\n options: RenderDiffOptions;\n highlighter: DiffsHighlighter;\n languageOverride: SupportedLanguages | undefined;\n}\n\nfunction renderTwoFiles({\n oldFile,\n newFile,\n oldInfo,\n newInfo,\n highlighter,\n oldDecorations,\n newDecorations,\n languageOverride,\n options: { theme: themeOrThemes = DEFAULT_THEMES, ...options },\n}: RenderTwoFilesProps) {\n const oldLang = languageOverride ?? getFiletypeFromFileName(oldFile.name);\n const newLang = languageOverride ?? getFiletypeFromFileName(newFile.name);\n const { state, transformers } = createTransformerWithState();\n const hastConfig: CodeToHastOptions<DiffsThemeNames> = (() => {\n return typeof themeOrThemes === 'string'\n ? {\n ...options,\n // language will be overwritten for each highlight\n lang: 'text',\n theme: themeOrThemes,\n transformers,\n decorations: undefined,\n defaultColor: false,\n cssVariablePrefix: formatCSSVariablePrefix(),\n }\n : {\n ...options,\n // language will be overwritten for each highlight\n lang: 'text',\n themes: themeOrThemes,\n transformers,\n decorations: undefined,\n defaultColor: false,\n cssVariablePrefix: formatCSSVariablePrefix(),\n };\n })();\n\n const oldLines = (() => {\n if (oldFile.contents === '') {\n return [];\n }\n hastConfig.lang = oldLang;\n state.lineInfo = oldInfo;\n hastConfig.decorations = oldDecorations;\n return getLineNodes(highlighter.codeToHast(oldFile.contents, hastConfig));\n })();\n const newLines = (() => {\n if (newFile.contents === '') {\n return [];\n }\n hastConfig.lang = newLang;\n hastConfig.decorations = newDecorations;\n state.lineInfo = newInfo;\n return getLineNodes(highlighter.codeToHast(newFile.contents, hastConfig));\n })();\n\n return { oldLines, newLines };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"renderDiffWithHighlighter.js","names":["hunks: RenderDiffFilesResult[]","deletionSpans: [0 | 1, string][]","additionSpans: [0 | 1, string][]","oldInfo: Record<number, LineInfo | undefined>","newInfo: Record<number, LineInfo | undefined>","oldDecorations: DecorationItem[]","newDecorations: DecorationItem[]","hastConfig: CodeToHastOptions<DiffsThemeNames>"],"sources":["../../src/utils/renderDiffWithHighlighter.ts"],"sourcesContent":["import { diffChars, diffWordsWithSpace } from 'diff';\n\nimport { DEFAULT_THEMES } from '../constants';\nimport type {\n CodeToHastOptions,\n DecorationItem,\n DiffsHighlighter,\n DiffsThemeNames,\n FileContents,\n FileDiffMetadata,\n Hunk,\n LineDiffTypes,\n LineInfo,\n RenderDiffFilesResult,\n RenderDiffOptions,\n SupportedLanguages,\n ThemedDiffResult,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { createTransformerWithState } from './createTransformerWithState';\nimport { formatCSSVariablePrefix } from './formatCSSVariablePrefix';\nimport { getFiletypeFromFileName } from './getFiletypeFromFileName';\nimport { getHighlighterThemeStyles } from './getHighlighterThemeStyles';\nimport { getLineNodes } from './getLineNodes';\nimport {\n createDiffSpanDecoration,\n pushOrJoinSpan,\n} from './parseDiffDecorations';\n\nexport function renderDiffWithHighlighter(\n diff: FileDiffMetadata,\n highlighter: DiffsHighlighter,\n options: RenderDiffOptions,\n forcePlainText = false\n): ThemedDiffResult {\n const baseThemeType = (() => {\n const theme = options.theme ?? DEFAULT_THEMES;\n if (typeof theme === 'string') {\n return highlighter.getTheme(theme).type;\n }\n return undefined;\n })();\n const themeStyles = getHighlighterThemeStyles({\n theme: options.theme,\n highlighter,\n });\n // If we've received a diff with both files\n if (diff.newLines != null && diff.oldLines != null) {\n const {\n oldContent,\n newContent,\n oldInfo,\n newInfo,\n oldDecorations,\n newDecorations,\n } = processLines({\n hunks: diff.hunks,\n oldLines: diff.oldLines,\n newLines: diff.newLines,\n lineDiffType: options.lineDiffType,\n });\n const oldFile = {\n name: diff.prevName ?? diff.name,\n contents: oldContent,\n };\n const newFile = {\n name: diff.name,\n contents: newContent,\n };\n const code = renderTwoFiles({\n oldFile,\n oldInfo,\n oldDecorations,\n\n newFile,\n newInfo,\n newDecorations,\n\n highlighter,\n options,\n languageOverride: forcePlainText ? 'text' : diff.lang,\n });\n return { code, themeStyles, baseThemeType };\n }\n const hunks: RenderDiffFilesResult[] = [];\n let splitLineIndex = 0;\n let unifiedLineIndex = 0;\n for (const hunk of diff.hunks) {\n const {\n oldContent,\n newContent,\n oldInfo,\n newInfo,\n oldDecorations,\n newDecorations,\n splitLineIndex: newSplitLineIndex,\n unifiedLineIndex: newUnifiedLineIndex,\n } = processLines({\n hunks: [hunk],\n splitLineIndex,\n unifiedLineIndex,\n lineDiffType: options.lineDiffType,\n });\n const oldFile = {\n name: diff.prevName ?? diff.name,\n contents: oldContent,\n };\n const newFile = {\n name: diff.name,\n contents: newContent,\n };\n hunks.push(\n renderTwoFiles({\n oldFile,\n oldInfo,\n oldDecorations,\n\n newFile,\n newInfo,\n newDecorations,\n\n highlighter,\n options,\n languageOverride: forcePlainText ? 'text' : diff.lang,\n })\n );\n splitLineIndex = newSplitLineIndex;\n unifiedLineIndex = newUnifiedLineIndex;\n }\n\n const code = (() => {\n if (hunks.length <= 1) {\n const hunk = hunks[0] ?? { oldLines: [], newLines: [] };\n if (hunk.newLines.length === 0 || hunk.oldLines.length === 0) {\n return hunk;\n }\n }\n return { hunks };\n })();\n\n return { code, themeStyles, baseThemeType };\n}\n\ninterface ProcessLineDiffProps {\n oldLine: string | undefined;\n newLine: string | undefined;\n oldLineIndex: number;\n newLineIndex: number;\n oldDecorations: DecorationItem[];\n newDecorations: DecorationItem[];\n lineDiffType: LineDiffTypes;\n}\n\nfunction computeLineDiffDecorations({\n oldLine,\n newLine,\n oldLineIndex,\n newLineIndex,\n oldDecorations,\n newDecorations,\n lineDiffType,\n}: ProcessLineDiffProps) {\n if (oldLine == null || newLine == null || lineDiffType === 'none') {\n return;\n }\n oldLine = cleanLastNewline(oldLine);\n newLine = cleanLastNewline(newLine);\n // NOTE(amadeus): Because we visually trim trailing newlines when rendering,\n // we also gotta make sure the diff parsing doesn't include the newline\n // character that could be there...\n const lineDiff =\n lineDiffType === 'char'\n ? diffChars(oldLine, newLine)\n : diffWordsWithSpace(oldLine, newLine);\n const deletionSpans: [0 | 1, string][] = [];\n const additionSpans: [0 | 1, string][] = [];\n const enableJoin = lineDiffType === 'word-alt';\n for (const item of lineDiff) {\n const isLastItem = item === lineDiff[lineDiff.length - 1];\n if (!item.added && !item.removed) {\n pushOrJoinSpan({\n item,\n arr: deletionSpans,\n enableJoin,\n isNeutral: true,\n isLastItem,\n });\n pushOrJoinSpan({\n item,\n arr: additionSpans,\n enableJoin,\n isNeutral: true,\n isLastItem,\n });\n } else if (item.removed) {\n pushOrJoinSpan({ item, arr: deletionSpans, enableJoin, isLastItem });\n } else {\n pushOrJoinSpan({ item, arr: additionSpans, enableJoin, isLastItem });\n }\n }\n let spanIndex = 0;\n for (const span of deletionSpans) {\n if (span[0] === 1) {\n oldDecorations.push(\n createDiffSpanDecoration({\n // Decoration indexes start at 0\n line: oldLineIndex - 1,\n spanStart: spanIndex,\n spanLength: span[1].length,\n })\n );\n }\n spanIndex += span[1].length;\n }\n spanIndex = 0;\n for (const span of additionSpans) {\n if (span[0] === 1) {\n newDecorations.push(\n createDiffSpanDecoration({\n // Decoration indexes start at 0\n line: newLineIndex - 1,\n spanStart: spanIndex,\n spanLength: span[1].length,\n })\n );\n }\n spanIndex += span[1].length;\n }\n}\n\ninterface ProcessLinesProps {\n hunks: Hunk[];\n oldLines?: string[];\n newLines?: string[];\n splitLineIndex?: number;\n unifiedLineIndex?: number;\n newLineIndex?: number;\n oldLineIndex?: number;\n lineDiffType: LineDiffTypes;\n}\n\nfunction processLines({\n hunks,\n oldLines,\n newLines,\n splitLineIndex = 0,\n unifiedLineIndex = 0,\n lineDiffType,\n}: ProcessLinesProps) {\n const oldInfo: Record<number, LineInfo | undefined> = {};\n const newInfo: Record<number, LineInfo | undefined> = {};\n const oldDecorations: DecorationItem[] = [];\n const newDecorations: DecorationItem[] = [];\n let newLineIndex = 1;\n let oldLineIndex = 1;\n let newLineNumber = 1;\n let oldLineNumber = 1;\n let oldContent = '';\n let newContent = '';\n for (const hunk of hunks) {\n // If there's content prior to the hunk, lets fill it up\n while (\n oldLines != null &&\n newLines != null &&\n newLineIndex < hunk.additionStart &&\n oldLineIndex < hunk.deletionStart\n ) {\n oldInfo[oldLineIndex] = {\n type: 'context-expanded',\n lineNumber: oldLineNumber,\n altLineNumber: newLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n newInfo[newLineIndex] = {\n type: 'context-expanded',\n lineNumber: newLineNumber,\n altLineNumber: oldLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n oldContent += oldLines[oldLineIndex - 1];\n newContent += newLines[newLineIndex - 1];\n oldLineIndex++;\n newLineIndex++;\n oldLineNumber++;\n newLineNumber++;\n splitLineIndex++;\n unifiedLineIndex++;\n }\n oldLineNumber = hunk.deletionStart;\n newLineNumber = hunk.additionStart;\n\n // Lets process the actual hunk content\n for (const hunkContent of hunk.hunkContent) {\n if (hunkContent.type === 'context') {\n for (const line of hunkContent.lines) {\n oldInfo[oldLineIndex] = {\n type: 'context',\n lineNumber: oldLineNumber,\n altLineNumber: newLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n newInfo[newLineIndex] = {\n type: 'context',\n lineNumber: newLineNumber,\n altLineNumber: oldLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n oldContent += line;\n newContent += line;\n oldLineIndex++;\n newLineIndex++;\n newLineNumber++;\n oldLineNumber++;\n splitLineIndex++;\n unifiedLineIndex++;\n }\n } else {\n const len = Math.max(\n hunkContent.additions.length,\n hunkContent.deletions.length\n );\n let i = 0;\n // NOTE(amadeus): Since we iterate through deletions and additions\n // simultaneously, we have to create a secondary iterator for\n // unifiedLineIndex, and then when we're done, add the combined lengths\n // of additions/deletions to the main variable\n let _unifiedLineIndex = unifiedLineIndex;\n while (i < len) {\n const oldLine = hunkContent.deletions[i];\n const newLine = hunkContent.additions[i];\n computeLineDiffDecorations({\n newLine,\n oldLine,\n oldLineIndex,\n newLineIndex,\n oldDecorations,\n newDecorations,\n lineDiffType,\n });\n if (oldLine != null) {\n oldInfo[oldLineIndex] = {\n type: 'change-deletion',\n lineNumber: oldLineNumber,\n lineIndex: `${_unifiedLineIndex},${splitLineIndex}`,\n };\n oldContent += oldLine;\n oldLineIndex++;\n oldLineNumber++;\n }\n if (newLine != null) {\n newInfo[newLineIndex] = {\n type: 'change-addition',\n lineNumber: newLineNumber,\n lineIndex: `${_unifiedLineIndex + hunkContent.deletions.length},${splitLineIndex}`,\n };\n newContent += newLine;\n newLineIndex++;\n newLineNumber++;\n }\n splitLineIndex++;\n _unifiedLineIndex++;\n i++;\n }\n unifiedLineIndex +=\n hunkContent.additions.length + hunkContent.deletions.length;\n }\n }\n\n if (\n oldLines == null ||\n newLines == null ||\n hunk !== hunks[hunks.length - 1]\n )\n continue;\n // If we are on the last hunk, we should fully iterate through the rest\n // of the lines\n while (oldLineIndex <= oldLines.length || newLineIndex <= oldLines.length) {\n const oldLine = oldLines[oldLineIndex - 1];\n const newLine = newLines[newLineIndex - 1];\n if (oldLine == null && newLine == null) {\n break;\n }\n if (oldLine != null) {\n oldInfo[oldLineIndex] = {\n type: 'context-expanded',\n lineNumber: oldLineNumber,\n altLineNumber: newLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n oldContent += oldLine;\n oldLineIndex++;\n oldLineNumber++;\n }\n if (newLine != null) {\n newInfo[newLineIndex] = {\n type: 'context-expanded',\n lineNumber: newLineNumber,\n altLineNumber: oldLineNumber,\n lineIndex: `${unifiedLineIndex},${splitLineIndex}`,\n };\n newContent += newLine;\n newLineIndex++;\n newLineNumber++;\n }\n splitLineIndex++;\n unifiedLineIndex++;\n }\n }\n return {\n oldContent,\n newContent,\n oldInfo,\n newInfo,\n oldDecorations,\n newDecorations,\n splitLineIndex,\n unifiedLineIndex,\n };\n}\n\ninterface RenderTwoFilesProps {\n oldFile: FileContents;\n newFile: FileContents;\n oldInfo: Record<number, LineInfo | undefined>;\n newInfo: Record<number, LineInfo | undefined>;\n oldDecorations: DecorationItem[];\n newDecorations: DecorationItem[];\n options: RenderDiffOptions;\n highlighter: DiffsHighlighter;\n languageOverride: SupportedLanguages | undefined;\n}\n\nfunction renderTwoFiles({\n oldFile,\n newFile,\n oldInfo,\n newInfo,\n highlighter,\n oldDecorations,\n newDecorations,\n languageOverride,\n options: { theme: themeOrThemes = DEFAULT_THEMES, ...options },\n}: RenderTwoFilesProps) {\n const oldLang = languageOverride ?? getFiletypeFromFileName(oldFile.name);\n const newLang = languageOverride ?? getFiletypeFromFileName(newFile.name);\n const { state, transformers } = createTransformerWithState();\n const hastConfig: CodeToHastOptions<DiffsThemeNames> = (() => {\n return typeof themeOrThemes === 'string'\n ? {\n ...options,\n // language will be overwritten for each highlight\n lang: 'text',\n theme: themeOrThemes,\n transformers,\n decorations: undefined,\n defaultColor: false,\n cssVariablePrefix: formatCSSVariablePrefix(),\n }\n : {\n ...options,\n // language will be overwritten for each highlight\n lang: 'text',\n themes: themeOrThemes,\n transformers,\n decorations: undefined,\n defaultColor: false,\n cssVariablePrefix: formatCSSVariablePrefix(),\n };\n })();\n\n const oldLines = (() => {\n if (oldFile.contents === '') {\n return [];\n }\n hastConfig.lang = oldLang;\n state.lineInfo = oldInfo;\n hastConfig.decorations = oldDecorations;\n return getLineNodes(\n highlighter.codeToHast(cleanLastNewline(oldFile.contents), hastConfig)\n );\n })();\n const newLines = (() => {\n if (newFile.contents === '') {\n return [];\n }\n hastConfig.lang = newLang;\n hastConfig.decorations = newDecorations;\n state.lineInfo = newInfo;\n return getLineNodes(\n highlighter.codeToHast(cleanLastNewline(newFile.contents), hastConfig)\n );\n })();\n\n return { oldLines, newLines };\n}\n"],"mappings":"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"}