@pierre/diffs 1.1.14 → 1.1.16

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.
@@ -1 +1 @@
1
- {"version":3,"file":"VirtulizerDevelopment.d.ts","names":["AdvancedVirtualizer","Virtualizer","_0","sideEffect"],"sources":["../../src/components/VirtulizerDevelopment.d.ts"],"sourcesContent":["import type { AdvancedVirtualizer } from './AdvancedVirtualizer';\nimport type { Virtualizer } from './Virtualizer';\n\n// FIXME(amadeus): REMOVE ME AFTER RELEASING VIRTUALIZATION\ndeclare global {\n interface Window {\n // oxlint-disable-next-line typescript/no-explicit-any\n __INSTANCE?: AdvancedVirtualizer<any> | Virtualizer;\n __TOGGLE?: () => void;\n __LOG?: boolean;\n }\n}\n"],"mappings":";;;;;AACiD,QAAAE,MAAA,CAAA;EAAA,UAAA,MAAA,CAAA;;IAMMC,UAAAD,CAAA,EAAtCF,mBAAsC,CAAA,GAAA,CAAA,GAAXC,WAAW;IAAA,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA"}
1
+ {"version":3,"file":"VirtulizerDevelopment.d.ts","names":["AdvancedVirtualizer","Virtualizer","_1","sideEffect"],"sources":["../../src/components/VirtulizerDevelopment.d.ts"],"sourcesContent":["import type { AdvancedVirtualizer } from './AdvancedVirtualizer';\nimport type { Virtualizer } from './Virtualizer';\n\n// FIXME(amadeus): REMOVE ME AFTER RELEASING VIRTUALIZATION\ndeclare global {\n interface Window {\n // oxlint-disable-next-line typescript/no-explicit-any\n __INSTANCE?: AdvancedVirtualizer<any> | Virtualizer;\n __TOGGLE?: () => void;\n __LOG?: boolean;\n }\n}\n"],"mappings":";;;;;AACiD,QAAAE,MAAA,CAAA;EAAA,UAAA,MAAA,CAAA;;IAMMC,UAAAD,CAAA,EAAtCF,mBAAsC,CAAA,GAAA,CAAA,GAAXC,WAAW;IAAA,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA"}
@@ -2,7 +2,10 @@ import { AttachedLanguages } from "./constants.js";
2
2
 
3
3
  //#region src/highlighter/languages/areLanguagesAttached.ts
4
4
  function areLanguagesAttached(languages) {
5
- for (const language of Array.isArray(languages) ? languages : [languages]) if (!AttachedLanguages.has(language)) return false;
5
+ for (const language of Array.isArray(languages) ? languages : [languages]) {
6
+ if (language === "text" || language === "ansi") continue;
7
+ if (!AttachedLanguages.has(language)) return false;
8
+ }
6
9
  return true;
7
10
  }
8
11
 
@@ -1 +1 @@
1
- {"version":3,"file":"areLanguagesAttached.js","names":[],"sources":["../../../src/highlighter/languages/areLanguagesAttached.ts"],"sourcesContent":["import type { SupportedLanguages } from '../../types';\nimport { AttachedLanguages } from './constants';\n\nexport function areLanguagesAttached(\n languages: SupportedLanguages | SupportedLanguages[]\n): boolean {\n for (const language of Array.isArray(languages) ? languages : [languages]) {\n if (!AttachedLanguages.has(language)) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":";;;AAGA,SAAgB,qBACd,WACS;AACT,MAAK,MAAM,YAAY,MAAM,QAAQ,UAAU,GAAG,YAAY,CAAC,UAAU,CACvE,KAAI,CAAC,kBAAkB,IAAI,SAAS,CAClC,QAAO;AAGX,QAAO"}
1
+ {"version":3,"file":"areLanguagesAttached.js","names":[],"sources":["../../../src/highlighter/languages/areLanguagesAttached.ts"],"sourcesContent":["import type { SupportedLanguages } from '../../types';\nimport { AttachedLanguages } from './constants';\n\nexport function areLanguagesAttached(\n languages: SupportedLanguages | SupportedLanguages[]\n): boolean {\n for (const language of Array.isArray(languages) ? languages : [languages]) {\n if (language === 'text' || language === 'ansi') {\n continue;\n }\n if (!AttachedLanguages.has(language)) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":";;;AAGA,SAAgB,qBACd,WACS;AACT,MAAK,MAAM,YAAY,MAAM,QAAQ,UAAU,GAAG,YAAY,CAAC,UAAU,EAAE;AACzE,MAAI,aAAa,UAAU,aAAa,OACtC;AAEF,MAAI,CAAC,kBAAkB,IAAI,SAAS,CAClC,QAAO;;AAGX,QAAO"}
@@ -121,7 +121,7 @@ var ResizeManager = class {
121
121
  }
122
122
  handleResizeObserver = (entries) => {
123
123
  for (const entry of entries) {
124
- const { target, borderBoxSize } = entry;
124
+ const { target, borderBoxSize, contentBoxSize } = entry;
125
125
  if (!(target instanceof HTMLElement)) {
126
126
  console.error("FileDiff.handleResizeObserver: Invalid element for ResizeObserver", entry);
127
127
  continue;
@@ -131,7 +131,6 @@ var ResizeManager = class {
131
131
  console.error("FileDiff.handleResizeObserver: Not a valid observed node", entry);
132
132
  continue;
133
133
  }
134
- const specs = borderBoxSize[0];
135
134
  if (item.type === "annotations") {
136
135
  const column = (() => {
137
136
  if (target === item.column1.child) return item.column1;
@@ -144,11 +143,11 @@ var ResizeManager = class {
144
143
  });
145
144
  continue;
146
145
  }
147
- column.childHeight = specs.blockSize;
146
+ column.childHeight = borderBoxSize[0].blockSize;
148
147
  const newHeight = Math.max(item.column1.childHeight, item.column2.childHeight);
149
148
  this.applyNewHeight(item, newHeight);
150
149
  } else if (item.type === "code") {
151
- const update = [target, specs.inlineSize];
150
+ const update = [target, contentBoxSize[0].inlineSize];
152
151
  const updates = this.queuedUpdates.get(item) ?? [];
153
152
  updates.push(update);
154
153
  this.queuedUpdates.set(item, updates);
@@ -1 +1 @@
1
- {"version":3,"file":"ResizeManager.js","names":["item: ObservedGridNodes | ObservedAnnotationNodes | undefined","update: CodeColumnUpdate"],"sources":["../../src/managers/ResizeManager.ts"],"sourcesContent":["import type { ObservedAnnotationNodes, ObservedGridNodes } from '../types';\n\ntype CodeColumnUpdate = [HTMLElement, number];\n\nexport class ResizeManager {\n private observedNodes = new Map<\n HTMLElement,\n ObservedAnnotationNodes | ObservedGridNodes\n >();\n private queuedUpdates: Map<ObservedGridNodes, CodeColumnUpdate[]> = new Map();\n\n cleanUp(): void {\n // Disconnect any existing observer\n this.resizeObserver?.disconnect();\n this.observedNodes.clear();\n this.queuedUpdates.clear();\n }\n\n private resizeObserver: ResizeObserver | undefined;\n\n setup(pre: HTMLPreElement, disableAnnotations: boolean): void {\n this.resizeObserver ??= new ResizeObserver(this.handleResizeObserver);\n const codeElements = pre.querySelectorAll('code');\n\n const observedNodes = new Map(this.observedNodes);\n this.observedNodes.clear();\n for (const codeElement of codeElements) {\n let item: ObservedGridNodes | ObservedAnnotationNodes | undefined =\n observedNodes.get(codeElement);\n if (item != null && item.type !== 'code') {\n throw new Error(\n 'ResizeManager.setup: somehow a code node is being used for an annotation, should be impossible'\n );\n }\n\n let numberElement = codeElement.firstElementChild;\n if (!(numberElement instanceof HTMLElement)) {\n numberElement = null;\n }\n\n if (item != null) {\n this.observedNodes.set(codeElement, item);\n observedNodes.delete(codeElement);\n if (item.numberElement !== numberElement) {\n if (item.numberElement != null) {\n this.resizeObserver.unobserve(item.numberElement);\n }\n if (numberElement != null) {\n this.resizeObserver.observe(numberElement);\n observedNodes.delete(numberElement);\n this.observedNodes.set(numberElement, item);\n }\n item.numberElement = numberElement;\n } else if (item.numberElement != null) {\n observedNodes.delete(item.numberElement);\n this.observedNodes.set(item.numberElement, item);\n }\n } else {\n item = {\n type: 'code',\n codeElement,\n numberElement,\n codeWidth: 'auto',\n numberWidth: 0,\n };\n this.observedNodes.set(codeElement, item);\n this.resizeObserver.observe(codeElement);\n if (numberElement != null) {\n this.observedNodes.set(numberElement, item);\n this.resizeObserver.observe(numberElement);\n }\n }\n }\n\n if (codeElements.length > 1 && !disableAnnotations) {\n const annotationElements = pre.querySelectorAll(\n '[data-line-annotation*=\",\"]'\n );\n\n const elementMap = new Map<string, HTMLElement[]>();\n for (const element of annotationElements) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n const { lineAnnotation = '' } = element.dataset;\n if (!/^\\d+,\\d+$/.test(lineAnnotation)) {\n console.error(\n 'DiffFileRenderer.setupResizeObserver: Invalid element or annotation',\n { lineAnnotation, element }\n );\n continue;\n }\n let pairs = elementMap.get(lineAnnotation);\n if (pairs == null) {\n pairs = [];\n elementMap.set(lineAnnotation, pairs);\n }\n pairs.push(element);\n }\n\n for (const [key, pair] of elementMap) {\n if (pair.length !== 2) {\n console.error(\n 'DiffFileRenderer.setupResizeObserver: Bad Pair',\n key,\n pair\n );\n continue;\n }\n const [container1, container2] = pair;\n const child1 = container1.firstElementChild;\n const child2 = container2.firstElementChild;\n if (\n !(container1 instanceof HTMLElement) ||\n !(container2 instanceof HTMLElement) ||\n !(child1 instanceof HTMLElement) ||\n !(child2 instanceof HTMLElement)\n ) {\n continue;\n }\n\n let item = observedNodes.get(child1);\n\n if (item != null) {\n this.observedNodes.set(child1, item);\n this.observedNodes.set(child2, item);\n observedNodes.delete(child1);\n observedNodes.delete(child2);\n continue;\n }\n\n item = {\n type: 'annotations',\n column1: {\n container: container1,\n child: child1,\n childHeight: child1.getBoundingClientRect().height,\n },\n column2: {\n container: container2,\n child: child2,\n childHeight: child2.getBoundingClientRect().height,\n },\n currentHeight: 'auto',\n };\n\n const newHeight = Math.max(\n item.column1.childHeight,\n item.column2.childHeight\n );\n this.applyNewHeight(item, newHeight);\n\n this.observedNodes.set(child1, item);\n this.observedNodes.set(child2, item);\n this.resizeObserver.observe(child1);\n this.resizeObserver.observe(child2);\n }\n }\n\n for (const element of observedNodes.keys()) {\n if (element.isConnected) {\n element.style.removeProperty('--diffs-column-content-width');\n element.style.removeProperty('--diffs-column-number-width');\n element.style.removeProperty('--diffs-column-width');\n if (element.parentElement instanceof HTMLElement) {\n element.parentElement.style.removeProperty(\n '--diffs-annotation-min-height'\n );\n }\n }\n this.resizeObserver.unobserve(element);\n }\n observedNodes.clear();\n }\n\n private handleResizeObserver = (entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n const { target, borderBoxSize } = entry;\n if (!(target instanceof HTMLElement)) {\n console.error(\n 'FileDiff.handleResizeObserver: Invalid element for ResizeObserver',\n entry\n );\n continue;\n }\n const item = this.observedNodes.get(target);\n if (item == null) {\n console.error(\n 'FileDiff.handleResizeObserver: Not a valid observed node',\n entry\n );\n continue;\n }\n const specs = borderBoxSize[0];\n if (item.type === 'annotations') {\n const column = (() => {\n if (target === item.column1.child) {\n return item.column1;\n }\n if (target === item.column2.child) {\n return item.column2;\n }\n return undefined;\n })();\n\n if (column == null) {\n console.error(\n `FileDiff.handleResizeObserver: Couldn't find a column for`,\n { item, target }\n );\n continue;\n }\n\n column.childHeight = specs.blockSize;\n const newHeight = Math.max(\n item.column1.childHeight,\n item.column2.childHeight\n );\n this.applyNewHeight(item, newHeight);\n } else if (item.type === 'code') {\n const update: CodeColumnUpdate = [target, specs.inlineSize];\n const updates = this.queuedUpdates.get(item) ?? [];\n updates.push(update);\n this.queuedUpdates.set(item, updates);\n }\n }\n this.handleColumnChange();\n };\n\n private handleColumnChange = () => {\n for (const [item, updates] of this.queuedUpdates) {\n for (const [target, targetInlineSize] of updates) {\n // FIXME(amadeus): This needs to be re-worked with display: contents,\n // not sure setting to auto is a good assumption most of the time...\n if (target === item.codeElement) {\n const inlineSize = Math.max(Math.floor(targetInlineSize), 0);\n if (inlineSize !== item.codeWidth) {\n const targetWidth = Math.max(inlineSize - item.numberWidth, 0);\n item.codeWidth = inlineSize === 0 ? 'auto' : inlineSize;\n item.codeElement.style.setProperty(\n '--diffs-column-content-width',\n `${targetWidth > 0 ? `${targetWidth}px` : 'auto'}`\n );\n item.codeElement.style.setProperty(\n '--diffs-column-width',\n `${typeof item.codeWidth === 'number' ? `${item.codeWidth}px` : 'auto'}`\n );\n }\n if (\n item.numberElement != null &&\n typeof item.codeWidth === 'number' &&\n item.numberWidth === 0\n ) {\n updates.push([\n item.numberElement,\n item.numberElement.getBoundingClientRect().width,\n ]);\n }\n } else if (target === item.numberElement) {\n const inlineSize = Math.max(Math.ceil(targetInlineSize), 0);\n if (inlineSize !== item.numberWidth) {\n item.numberWidth = inlineSize;\n item.codeElement.style.setProperty(\n '--diffs-column-number-width',\n `${item.numberWidth === 0 ? 'auto' : `${item.numberWidth}px`}`\n );\n // We probably need to update code width variable if\n // `numberWidth` changed\n if (item.codeWidth !== 'auto') {\n const targetWidth = Math.max(\n item.codeWidth - item.numberWidth,\n 0\n );\n item.codeElement.style.setProperty(\n '--diffs-column-content-width',\n `${targetWidth === 0 ? 'auto' : `${targetWidth}px`}`\n );\n }\n }\n }\n }\n }\n this.queuedUpdates.clear();\n };\n\n private applyNewHeight(item: ObservedAnnotationNodes, newHeight: number) {\n if (newHeight !== item.currentHeight) {\n item.currentHeight = Math.max(newHeight, 0);\n item.column1.container.style.setProperty(\n '--diffs-annotation-min-height',\n `${item.currentHeight}px`\n );\n item.column2.container.style.setProperty(\n '--diffs-annotation-min-height',\n `${item.currentHeight}px`\n );\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ResizeManager.js","names":["item: ObservedGridNodes | ObservedAnnotationNodes | undefined","update: CodeColumnUpdate"],"sources":["../../src/managers/ResizeManager.ts"],"sourcesContent":["import type { ObservedAnnotationNodes, ObservedGridNodes } from '../types';\n\ntype CodeColumnUpdate = [HTMLElement, number];\n\nexport class ResizeManager {\n private observedNodes = new Map<\n HTMLElement,\n ObservedAnnotationNodes | ObservedGridNodes\n >();\n private queuedUpdates: Map<ObservedGridNodes, CodeColumnUpdate[]> = new Map();\n\n cleanUp(): void {\n // Disconnect any existing observer\n this.resizeObserver?.disconnect();\n this.observedNodes.clear();\n this.queuedUpdates.clear();\n }\n\n private resizeObserver: ResizeObserver | undefined;\n\n setup(pre: HTMLPreElement, disableAnnotations: boolean): void {\n this.resizeObserver ??= new ResizeObserver(this.handleResizeObserver);\n const codeElements = pre.querySelectorAll('code');\n\n const observedNodes = new Map(this.observedNodes);\n this.observedNodes.clear();\n for (const codeElement of codeElements) {\n let item: ObservedGridNodes | ObservedAnnotationNodes | undefined =\n observedNodes.get(codeElement);\n if (item != null && item.type !== 'code') {\n throw new Error(\n 'ResizeManager.setup: somehow a code node is being used for an annotation, should be impossible'\n );\n }\n\n let numberElement = codeElement.firstElementChild;\n if (!(numberElement instanceof HTMLElement)) {\n numberElement = null;\n }\n\n if (item != null) {\n this.observedNodes.set(codeElement, item);\n observedNodes.delete(codeElement);\n if (item.numberElement !== numberElement) {\n if (item.numberElement != null) {\n this.resizeObserver.unobserve(item.numberElement);\n }\n if (numberElement != null) {\n this.resizeObserver.observe(numberElement);\n observedNodes.delete(numberElement);\n this.observedNodes.set(numberElement, item);\n }\n item.numberElement = numberElement;\n } else if (item.numberElement != null) {\n observedNodes.delete(item.numberElement);\n this.observedNodes.set(item.numberElement, item);\n }\n } else {\n item = {\n type: 'code',\n codeElement,\n numberElement,\n codeWidth: 'auto',\n numberWidth: 0,\n };\n this.observedNodes.set(codeElement, item);\n this.resizeObserver.observe(codeElement);\n if (numberElement != null) {\n this.observedNodes.set(numberElement, item);\n this.resizeObserver.observe(numberElement);\n }\n }\n }\n\n if (codeElements.length > 1 && !disableAnnotations) {\n const annotationElements = pre.querySelectorAll(\n '[data-line-annotation*=\",\"]'\n );\n\n const elementMap = new Map<string, HTMLElement[]>();\n for (const element of annotationElements) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n const { lineAnnotation = '' } = element.dataset;\n if (!/^\\d+,\\d+$/.test(lineAnnotation)) {\n console.error(\n 'DiffFileRenderer.setupResizeObserver: Invalid element or annotation',\n { lineAnnotation, element }\n );\n continue;\n }\n let pairs = elementMap.get(lineAnnotation);\n if (pairs == null) {\n pairs = [];\n elementMap.set(lineAnnotation, pairs);\n }\n pairs.push(element);\n }\n\n for (const [key, pair] of elementMap) {\n if (pair.length !== 2) {\n console.error(\n 'DiffFileRenderer.setupResizeObserver: Bad Pair',\n key,\n pair\n );\n continue;\n }\n const [container1, container2] = pair;\n const child1 = container1.firstElementChild;\n const child2 = container2.firstElementChild;\n if (\n !(container1 instanceof HTMLElement) ||\n !(container2 instanceof HTMLElement) ||\n !(child1 instanceof HTMLElement) ||\n !(child2 instanceof HTMLElement)\n ) {\n continue;\n }\n\n let item = observedNodes.get(child1);\n\n if (item != null) {\n this.observedNodes.set(child1, item);\n this.observedNodes.set(child2, item);\n observedNodes.delete(child1);\n observedNodes.delete(child2);\n continue;\n }\n\n item = {\n type: 'annotations',\n column1: {\n container: container1,\n child: child1,\n childHeight: child1.getBoundingClientRect().height,\n },\n column2: {\n container: container2,\n child: child2,\n childHeight: child2.getBoundingClientRect().height,\n },\n currentHeight: 'auto',\n };\n\n const newHeight = Math.max(\n item.column1.childHeight,\n item.column2.childHeight\n );\n this.applyNewHeight(item, newHeight);\n\n this.observedNodes.set(child1, item);\n this.observedNodes.set(child2, item);\n this.resizeObserver.observe(child1);\n this.resizeObserver.observe(child2);\n }\n }\n\n for (const element of observedNodes.keys()) {\n if (element.isConnected) {\n element.style.removeProperty('--diffs-column-content-width');\n element.style.removeProperty('--diffs-column-number-width');\n element.style.removeProperty('--diffs-column-width');\n if (element.parentElement instanceof HTMLElement) {\n element.parentElement.style.removeProperty(\n '--diffs-annotation-min-height'\n );\n }\n }\n this.resizeObserver.unobserve(element);\n }\n observedNodes.clear();\n }\n\n private handleResizeObserver = (entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n const { target, borderBoxSize, contentBoxSize } = entry;\n if (!(target instanceof HTMLElement)) {\n console.error(\n 'FileDiff.handleResizeObserver: Invalid element for ResizeObserver',\n entry\n );\n continue;\n }\n const item = this.observedNodes.get(target);\n if (item == null) {\n console.error(\n 'FileDiff.handleResizeObserver: Not a valid observed node',\n entry\n );\n continue;\n }\n if (item.type === 'annotations') {\n const column = (() => {\n if (target === item.column1.child) {\n return item.column1;\n }\n if (target === item.column2.child) {\n return item.column2;\n }\n return undefined;\n })();\n\n if (column == null) {\n console.error(\n `FileDiff.handleResizeObserver: Couldn't find a column for`,\n { item, target }\n );\n continue;\n }\n\n column.childHeight = borderBoxSize[0].blockSize;\n const newHeight = Math.max(\n item.column1.childHeight,\n item.column2.childHeight\n );\n this.applyNewHeight(item, newHeight);\n } else if (item.type === 'code') {\n const update: CodeColumnUpdate = [target, contentBoxSize[0].inlineSize];\n const updates = this.queuedUpdates.get(item) ?? [];\n updates.push(update);\n this.queuedUpdates.set(item, updates);\n }\n }\n this.handleColumnChange();\n };\n\n private handleColumnChange = () => {\n for (const [item, updates] of this.queuedUpdates) {\n for (const [target, targetInlineSize] of updates) {\n // FIXME(amadeus): This needs to be re-worked with display: contents,\n // not sure setting to auto is a good assumption most of the time...\n if (target === item.codeElement) {\n const inlineSize = Math.max(Math.floor(targetInlineSize), 0);\n if (inlineSize !== item.codeWidth) {\n const targetWidth = Math.max(inlineSize - item.numberWidth, 0);\n item.codeWidth = inlineSize === 0 ? 'auto' : inlineSize;\n item.codeElement.style.setProperty(\n '--diffs-column-content-width',\n `${targetWidth > 0 ? `${targetWidth}px` : 'auto'}`\n );\n item.codeElement.style.setProperty(\n '--diffs-column-width',\n `${typeof item.codeWidth === 'number' ? `${item.codeWidth}px` : 'auto'}`\n );\n }\n if (\n item.numberElement != null &&\n typeof item.codeWidth === 'number' &&\n item.numberWidth === 0\n ) {\n updates.push([\n item.numberElement,\n item.numberElement.getBoundingClientRect().width,\n ]);\n }\n } else if (target === item.numberElement) {\n const inlineSize = Math.max(Math.ceil(targetInlineSize), 0);\n if (inlineSize !== item.numberWidth) {\n item.numberWidth = inlineSize;\n item.codeElement.style.setProperty(\n '--diffs-column-number-width',\n `${item.numberWidth === 0 ? 'auto' : `${item.numberWidth}px`}`\n );\n // We probably need to update code width variable if\n // `numberWidth` changed\n if (item.codeWidth !== 'auto') {\n const targetWidth = Math.max(\n item.codeWidth - item.numberWidth,\n 0\n );\n item.codeElement.style.setProperty(\n '--diffs-column-content-width',\n `${targetWidth === 0 ? 'auto' : `${targetWidth}px`}`\n );\n }\n }\n }\n }\n }\n this.queuedUpdates.clear();\n };\n\n private applyNewHeight(item: ObservedAnnotationNodes, newHeight: number) {\n if (newHeight !== item.currentHeight) {\n item.currentHeight = Math.max(newHeight, 0);\n item.column1.container.style.setProperty(\n '--diffs-annotation-min-height',\n `${item.currentHeight}px`\n );\n item.column2.container.style.setProperty(\n '--diffs-annotation-min-height',\n `${item.currentHeight}px`\n );\n }\n }\n}\n"],"mappings":"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"}
@@ -146,7 +146,12 @@ var DiffHunksRenderer = class {
146
146
  result: cache?.result,
147
147
  renderRange: void 0
148
148
  };
149
- if (this.workerManager?.isWorkingPool() === true && this.renderCache.result == null) this.workerManager.highlightDiffAST(this, this.diff);
149
+ if (this.workerManager?.isWorkingPool() === true) {
150
+ if (this.renderCache.result == null) this.workerManager.highlightDiffAST(this, this.diff);
151
+ } else if (this.highlighter == null) {
152
+ this.computedLang = diff.lang ?? getFiletypeFromFileName(diff.name);
153
+ this.initializeHighlighter();
154
+ }
150
155
  }
151
156
  getRenderOptions(diff) {
152
157
  const options = (() => {
@@ -215,6 +220,7 @@ var DiffHunksRenderer = class {
215
220
  };
216
221
  }
217
222
  if (!hasThemes || !hasLangs) this.asyncHighlight(diff).then(({ result, options: options$1 }) => {
223
+ if (this.renderCache != null) this.renderCache.highlighted = false;
218
224
  this.onHighlightSuccess(diff, result, options$1);
219
225
  });
220
226
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DiffHunksRenderer.js","names":["options: DiffHunksRendererOptions","onRenderUpdate?: () => unknown","workerManager?: WorkerPoolManager | undefined","createDefaultAnnotationElement","options: RenderDiffOptions","options","additionsContentAST: ElementContent[] | undefined","deletionsContentAST: ElementContent[] | undefined","unifiedContentAST: ElementContent[] | undefined","hunkData: HunkData[]","context: ProcessContext","pendingSplitContext: PendingSplitContext","renderedLineContext: RenderedLineContext","deletionSpan: AnnotationSpan","additionSpan: AnnotationSpan","createAnnotationElement"],"sources":["../../src/renderers/DiffHunksRenderer.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement, Properties } from 'hast';\nimport { toHtml } from 'hast-util-to-html';\n\nimport {\n DEFAULT_COLLAPSED_CONTEXT_THRESHOLD,\n DEFAULT_EXPANDED_REGION,\n DEFAULT_RENDER_RANGE,\n DEFAULT_THEMES,\n} from '../constants';\nimport { areLanguagesAttached } from '../highlighter/languages/areLanguagesAttached';\nimport {\n getHighlighterIfLoaded,\n getSharedHighlighter,\n} from '../highlighter/shared_highlighter';\nimport { areThemesAttached } from '../highlighter/themes/areThemesAttached';\nimport type {\n AnnotationLineMap,\n AnnotationSpan,\n BaseDiffOptions,\n BaseDiffOptionsWithDefaults,\n CodeColumnType,\n CustomPreProperties,\n DiffLineAnnotation,\n DiffsHighlighter,\n ExpansionDirections,\n FileDiffMetadata,\n FileHeaderRenderMode,\n HunkData,\n HunkExpansionRegion,\n HunkSeparators,\n LineTypes,\n RenderDiffOptions,\n RenderDiffResult,\n RenderedDiffASTCache,\n RenderRange,\n SupportedLanguages,\n ThemedDiffResult,\n} from '../types';\nimport { areDiffRenderOptionsEqual } from '../utils/areDiffRenderOptionsEqual';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { createAnnotationElement as createDefaultAnnotationElement } from '../utils/createAnnotationElement';\nimport { createContentColumn } from '../utils/createContentColumn';\nimport { createEmptyRowBuffer } from '../utils/createEmptyRowBuffer';\nimport { createFileHeaderElement } from '../utils/createFileHeaderElement';\nimport { createNoNewlineElement } from '../utils/createNoNewlineElement';\nimport { createPreElement } from '../utils/createPreElement';\nimport { createSeparator } from '../utils/createSeparator';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport { getHighlighterOptions } from '../utils/getHighlighterOptions';\nimport { getHunkSeparatorSlotName } from '../utils/getHunkSeparatorSlotName';\nimport { getLineAnnotationName } from '../utils/getLineAnnotationName';\nimport { getTotalLineCountFromHunks } from '../utils/getTotalLineCountFromHunks';\nimport {\n createGutterGap,\n createGutterItem,\n createGutterWrapper,\n createHastElement,\n} from '../utils/hast_utils';\nimport { isDefaultRenderRange } from '../utils/isDefaultRenderRange';\nimport { isDiffPlainText } from '../utils/isDiffPlainText';\nimport type { DiffLineMetadata } from '../utils/iterateOverDiff';\nimport { iterateOverDiff } from '../utils/iterateOverDiff';\nimport { renderDiffWithHighlighter } from '../utils/renderDiffWithHighlighter';\nimport { shouldUseTokenTransformer } from '../utils/shouldUseTokenTransformer';\nimport type { WorkerPoolManager } from '../worker';\n\ninterface PushLineWithAnnotation {\n diffStyle: 'unified' | 'split';\n type: 'context' | 'context-expanded' | 'change';\n\n deletionLine?: ElementContent;\n additionLine?: ElementContent;\n\n unifiedSpan?: AnnotationSpan;\n deletionSpan?: AnnotationSpan;\n additionSpan?: AnnotationSpan;\n\n createAnnotationElement(span: AnnotationSpan): HASTElement;\n context: ProcessContext;\n}\n\ninterface GetRenderOptionsReturn {\n options: RenderDiffOptions;\n forceRender: boolean;\n}\n\ninterface PushSeparatorProps {\n hunkIndex: number;\n collapsedLines: number;\n rangeSize: number;\n hunkSpecs: string | undefined;\n isFirstHunk: boolean;\n isLastHunk: boolean;\n isExpandable: boolean;\n}\n\ninterface ProcessContext {\n rowCount: number;\n expansionLineCount: number;\n hunkSeparators: HunkSeparators;\n unifiedContentAST: ElementContent[];\n deletionsContentAST: ElementContent[];\n additionsContentAST: ElementContent[];\n unifiedGutterAST: HASTElement;\n deletionsGutterAST: HASTElement;\n additionsGutterAST: HASTElement;\n hunkData: HunkData[];\n pushToGutter(type: CodeColumnType, element: HASTElement): void;\n incrementRowCount(count?: number): void;\n}\n\nexport interface DiffHunksRendererOptions extends BaseDiffOptions {\n headerRenderMode?: FileHeaderRenderMode;\n}\n\nexport interface DiffHunksRendererOptionsWithDefaults extends Omit<\n BaseDiffOptionsWithDefaults,\n 'themeType'\n> {\n headerRenderMode: FileHeaderRenderMode;\n}\n\nexport interface UnifiedLineDecorationProps {\n type: 'context' | 'context-expanded' | 'change';\n lineType: LineTypes;\n additionLineIndex: number | undefined;\n deletionLineIndex: number | undefined;\n}\n\nexport interface SplitLineDecorationProps {\n side: 'deletions' | 'additions';\n type: 'context' | 'context-expanded' | 'change';\n lineIndex: number | undefined;\n}\n\nexport interface LineDecoration {\n gutterLineType: LineTypes;\n gutterProperties?: Properties;\n contentProperties?: Properties;\n}\n\ninterface PendingSplitContext {\n size: number;\n side: 'additions' | 'deletions' | undefined;\n increment(): void;\n flush(): void;\n}\n\nexport interface RenderedLineContext {\n type: 'context' | 'context-expanded' | 'change';\n hunkIndex: number;\n lineIndex: number;\n unifiedLineIndex: number;\n splitLineIndex: number;\n deletionLine?: DiffLineMetadata;\n additionLine?: DiffLineMetadata;\n}\n\nexport interface InjectedRow {\n content: HASTElement;\n gutter: HASTElement;\n}\n\nexport interface SplitInjectedRow {\n deletion: InjectedRow | undefined;\n addition: InjectedRow | undefined;\n}\n\nexport interface UnifiedInjectedRowPlacement {\n before?: InjectedRow[];\n after?: InjectedRow[];\n}\n\nexport interface SplitInjectedRowPlacement {\n before?: SplitInjectedRow[];\n after?: SplitInjectedRow[];\n}\n\nexport interface HunksRenderResult {\n unifiedGutterAST: ElementContent[] | undefined;\n unifiedContentAST: ElementContent[] | undefined;\n deletionsGutterAST: ElementContent[] | undefined;\n deletionsContentAST: ElementContent[] | undefined;\n additionsGutterAST: ElementContent[] | undefined;\n additionsContentAST: ElementContent[] | undefined;\n hunkData: HunkData[];\n css: string;\n preNode: HASTElement;\n headerElement: HASTElement | undefined;\n totalLines: number;\n themeStyles: string;\n baseThemeType: 'light' | 'dark' | undefined;\n rowCount: number;\n bufferBefore: number;\n bufferAfter: number;\n}\n\nlet instanceId = -1;\n\nexport class DiffHunksRenderer<LAnnotation = undefined> {\n readonly __id: string = `diff-hunks-renderer:${++instanceId}`;\n\n private highlighter: DiffsHighlighter | undefined;\n private diff: FileDiffMetadata | undefined;\n\n private expandedHunks = new Map<number, HunkExpansionRegion>();\n\n private deletionAnnotations: AnnotationLineMap<LAnnotation> = {};\n private additionAnnotations: AnnotationLineMap<LAnnotation> = {};\n\n private computedLang: SupportedLanguages = 'text';\n private renderCache: RenderedDiffASTCache | undefined;\n\n constructor(\n public options: DiffHunksRendererOptions = { theme: DEFAULT_THEMES },\n private onRenderUpdate?: () => unknown,\n private workerManager?: WorkerPoolManager | undefined\n ) {\n if (workerManager?.isWorkingPool() !== true) {\n this.highlighter = areThemesAttached(options.theme ?? DEFAULT_THEMES)\n ? getHighlighterIfLoaded()\n : undefined;\n }\n }\n\n public cleanUp(): void {\n this.highlighter = undefined;\n this.diff = undefined;\n this.renderCache = undefined;\n this.workerManager?.cleanUpPendingTasks(this);\n this.workerManager = undefined;\n this.onRenderUpdate = undefined;\n }\n\n public recycle(): void {\n this.highlighter = undefined;\n this.diff = undefined;\n this.renderCache = undefined;\n this.workerManager?.cleanUpPendingTasks(this);\n }\n\n public setOptions(options: DiffHunksRendererOptions): void {\n this.options = options;\n }\n\n public mergeOptions(options: Partial<DiffHunksRendererOptions>): void {\n this.options = { ...this.options, ...options };\n }\n\n public expandHunk(\n index: number,\n direction: ExpansionDirections,\n expansionLineCount: number = this.getOptionsWithDefaults()\n .expansionLineCount\n ): void {\n const region = {\n ...(this.expandedHunks.get(index) ?? {\n fromStart: 0,\n fromEnd: 0,\n }),\n };\n if (direction === 'up' || direction === 'both') {\n region.fromStart += expansionLineCount;\n }\n if (direction === 'down' || direction === 'both') {\n region.fromEnd += expansionLineCount;\n }\n // NOTE(amadeus): If our render cache is not highlighted, we need to clear\n // it, otherwise we won't have the correct AST lines\n if (this.renderCache?.highlighted !== true) {\n this.renderCache = undefined;\n }\n this.expandedHunks.set(index, region);\n }\n\n public getExpandedHunk(hunkIndex: number): HunkExpansionRegion {\n return this.expandedHunks.get(hunkIndex) ?? DEFAULT_EXPANDED_REGION;\n }\n\n public getExpandedHunksMap(): Map<number, HunkExpansionRegion> {\n return this.expandedHunks;\n }\n\n public setLineAnnotations(\n lineAnnotations: DiffLineAnnotation<LAnnotation>[]\n ): void {\n this.additionAnnotations = {};\n this.deletionAnnotations = {};\n for (const annotation of lineAnnotations) {\n const map = ((): AnnotationLineMap<LAnnotation> => {\n switch (annotation.side) {\n case 'deletions':\n return this.deletionAnnotations;\n case 'additions':\n return this.additionAnnotations;\n }\n })();\n const arr = map[annotation.lineNumber] ?? [];\n map[annotation.lineNumber] = arr;\n arr.push(annotation);\n }\n }\n\n protected getUnifiedLineDecoration({\n lineType,\n }: UnifiedLineDecorationProps): LineDecoration {\n return { gutterLineType: lineType };\n }\n\n protected getSplitLineDecoration({\n side,\n type,\n }: SplitLineDecorationProps): LineDecoration {\n if (type !== 'change') {\n return { gutterLineType: type };\n }\n return {\n gutterLineType:\n side === 'deletions' ? 'change-deletion' : 'change-addition',\n };\n }\n\n protected createAnnotationElement(span: AnnotationSpan): HASTElement {\n return createDefaultAnnotationElement(span);\n }\n\n // Unified hook returns extra rows that render before/after the current line.\n declare protected getUnifiedInjectedRowsForLine?: (\n ctx: RenderedLineContext\n ) => UnifiedInjectedRowPlacement | undefined;\n\n // Split hook returns extra rows per side before/after the current line.\n declare protected getSplitInjectedRowsForLine?: (\n ctx: RenderedLineContext\n ) => SplitInjectedRowPlacement | undefined;\n\n protected getOptionsWithDefaults(): DiffHunksRendererOptionsWithDefaults {\n const {\n diffIndicators = 'bars',\n diffStyle = 'split',\n disableBackground = false,\n disableFileHeader = false,\n disableLineNumbers = false,\n disableVirtualizationBuffers = false,\n collapsed = false,\n expandUnchanged = false,\n collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD,\n expansionLineCount = 100,\n hunkSeparators = 'line-info',\n lineDiffType = 'word-alt',\n maxLineDiffLength = 1000,\n overflow = 'scroll',\n theme = DEFAULT_THEMES,\n headerRenderMode = 'default',\n tokenizeMaxLineLength = 1000,\n useTokenTransformer = false,\n useCSSClasses = false,\n } = this.options;\n return {\n diffIndicators,\n diffStyle,\n disableBackground,\n disableFileHeader,\n disableLineNumbers,\n disableVirtualizationBuffers,\n collapsed,\n expandUnchanged,\n collapsedContextThreshold,\n expansionLineCount,\n hunkSeparators,\n lineDiffType,\n maxLineDiffLength,\n overflow,\n theme: this.workerManager?.getDiffRenderOptions().theme ?? theme,\n headerRenderMode,\n tokenizeMaxLineLength,\n useTokenTransformer,\n useCSSClasses,\n };\n }\n\n private async initializeHighlighter(): Promise<DiffsHighlighter> {\n this.highlighter = await getSharedHighlighter(\n getHighlighterOptions(this.computedLang, this.options)\n );\n return this.highlighter;\n }\n\n public hydrate(diff: FileDiffMetadata | undefined): void {\n if (diff == null) {\n return;\n }\n this.diff = diff;\n const { options } = this.getRenderOptions(diff);\n let cache = this.workerManager?.getDiffResultCache(diff);\n if (cache != null && !areDiffRenderOptionsEqual(options, cache.options)) {\n cache = undefined;\n }\n this.renderCache ??= {\n diff,\n highlighted: !isDiffPlainText(diff),\n options,\n result: cache?.result,\n renderRange: undefined,\n };\n if (\n this.workerManager?.isWorkingPool() === true &&\n this.renderCache.result == null\n ) {\n // We should only kick off a preload of the AST if we have a WorkerPool\n this.workerManager.highlightDiffAST(this, this.diff);\n }\n }\n\n private getRenderOptions(diff: FileDiffMetadata): GetRenderOptionsReturn {\n const options: RenderDiffOptions = (() => {\n if (this.workerManager?.isWorkingPool() === true) {\n return this.workerManager.getDiffRenderOptions();\n }\n const { theme, tokenizeMaxLineLength, lineDiffType, maxLineDiffLength } =\n this.getOptionsWithDefaults();\n return {\n theme,\n useTokenTransformer: shouldUseTokenTransformer(this.options),\n tokenizeMaxLineLength,\n lineDiffType,\n maxLineDiffLength,\n };\n })();\n this.getOptionsWithDefaults();\n const { renderCache } = this;\n if (renderCache?.result == null) {\n return { options, forceRender: true };\n }\n if (\n diff !== renderCache.diff ||\n !areDiffRenderOptionsEqual(options, renderCache.options)\n ) {\n return { options, forceRender: true };\n }\n return { options, forceRender: false };\n }\n\n public renderDiff(\n diff: FileDiffMetadata | undefined = this.renderCache?.diff,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): HunksRenderResult | undefined {\n if (diff == null) {\n return undefined;\n }\n const { expandUnchanged = false, collapsedContextThreshold } =\n this.getOptionsWithDefaults();\n const cache = this.workerManager?.getDiffResultCache(diff);\n if (cache != null && this.renderCache == null) {\n this.renderCache = {\n diff,\n highlighted: true,\n renderRange: undefined,\n ...cache,\n };\n }\n const { options, forceRender } = this.getRenderOptions(diff);\n this.renderCache ??= {\n diff,\n highlighted: false,\n options,\n result: undefined,\n renderRange: undefined,\n };\n if (this.workerManager?.isWorkingPool() === true) {\n if (\n this.renderCache.result == null ||\n (!this.renderCache.highlighted &&\n (diff !== this.renderCache.diff ||\n !areRenderRangesEqual(this.renderCache.renderRange, renderRange)))\n ) {\n this.renderCache.diff = diff;\n this.renderCache.result = this.workerManager.getPlainDiffAST(\n diff,\n renderRange.startingLine,\n renderRange.totalLines,\n // If we aren't using a windowed render, then we need to render\n // everything\n isDefaultRenderRange(renderRange)\n ? true\n : expandUnchanged\n ? true\n : this.expandedHunks,\n collapsedContextThreshold\n );\n this.renderCache.renderRange = renderRange;\n }\n if (\n // We should only attempt to kick off the worker highlighter if there\n // are lines to render\n renderRange.totalLines > 0 &&\n (!this.renderCache.highlighted || forceRender)\n ) {\n this.workerManager.highlightDiffAST(this, diff);\n }\n } else {\n this.computedLang = diff.lang ?? getFiletypeFromFileName(diff.name);\n const hasThemes =\n this.highlighter != null && areThemesAttached(options.theme);\n const hasLangs =\n this.highlighter != null && areLanguagesAttached(this.computedLang);\n\n // If we have any semblance of a highlighter with the correct theme(s)\n // attached, we can kick off some form of rendering. If we don't have\n // the correct language, then we can render plain text and after kick off\n // an async job to get the highlighted AST\n if (\n this.highlighter != null &&\n hasThemes &&\n (forceRender ||\n (!this.renderCache.highlighted && hasLangs) ||\n this.renderCache.result == null)\n ) {\n const { result, options } = this.renderDiffWithHighlighter(\n diff,\n this.highlighter,\n !hasLangs\n );\n this.renderCache = {\n diff,\n options,\n highlighted: hasLangs,\n result,\n renderRange: undefined,\n };\n }\n\n // If we get in here it means we'll have to kick off an async highlight\n // process which will involve initializing the highlighter with new themes\n // and languages\n if (!hasThemes || !hasLangs) {\n void this.asyncHighlight(diff).then(({ result, options }) => {\n this.onHighlightSuccess(diff, result, options);\n });\n }\n }\n return this.renderCache.result != null\n ? this.processDiffResult(\n this.renderCache.diff,\n renderRange,\n this.renderCache.result\n )\n : undefined;\n }\n\n public async asyncRender(\n diff: FileDiffMetadata,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): Promise<HunksRenderResult> {\n const { result } = await this.asyncHighlight(diff);\n return this.processDiffResult(diff, renderRange, result);\n }\n\n protected createPreElement(\n split: boolean,\n totalLines: number,\n customProperties?: CustomPreProperties\n ): HASTElement {\n const { diffIndicators, disableBackground, disableLineNumbers, overflow } =\n this.getOptionsWithDefaults();\n return createPreElement({\n type: 'diff',\n diffIndicators,\n disableBackground,\n disableLineNumbers,\n overflow,\n split,\n totalLines,\n customProperties,\n });\n }\n\n private async asyncHighlight(\n diff: FileDiffMetadata\n ): Promise<RenderDiffResult> {\n this.computedLang = diff.lang ?? getFiletypeFromFileName(diff.name);\n const hasThemes =\n this.highlighter != null &&\n areThemesAttached(this.options.theme ?? DEFAULT_THEMES);\n const hasLangs =\n this.highlighter != null && areLanguagesAttached(this.computedLang);\n // If we don't have the required langs or themes, then we need to\n // initialize the highlighter to load the appropriate languages and themes\n if (this.highlighter == null || !hasThemes || !hasLangs) {\n this.highlighter = await this.initializeHighlighter();\n }\n return this.renderDiffWithHighlighter(diff, this.highlighter);\n }\n\n private renderDiffWithHighlighter(\n diff: FileDiffMetadata,\n highlighter: DiffsHighlighter,\n forcePlainText = false\n ): RenderDiffResult {\n const { options } = this.getRenderOptions(diff);\n const { collapsedContextThreshold } = this.getOptionsWithDefaults();\n const result = renderDiffWithHighlighter(diff, highlighter, options, {\n forcePlainText,\n expandedHunks: forcePlainText ? true : undefined,\n collapsedContextThreshold,\n });\n return { result, options };\n }\n\n public onHighlightSuccess(\n diff: FileDiffMetadata,\n result: ThemedDiffResult,\n options: RenderDiffOptions\n ): void {\n // NOTE(amadeus): This is a bad assumption, and I should figure out\n // something better...\n // If renderCache was blown away, we can assume we've run cleanUp()\n if (this.renderCache == null) {\n return;\n }\n\n const triggerRenderUpdate =\n !this.renderCache.highlighted ||\n !areDiffRenderOptionsEqual(this.renderCache.options, options) ||\n this.renderCache.diff !== diff;\n\n this.renderCache = {\n diff,\n options,\n highlighted: true,\n result,\n renderRange: undefined,\n };\n if (triggerRenderUpdate) {\n this.onRenderUpdate?.();\n }\n }\n\n public onHighlightError(error: unknown): void {\n console.error(error);\n }\n\n private processDiffResult(\n fileDiff: FileDiffMetadata,\n renderRange: RenderRange,\n { code, themeStyles, baseThemeType }: ThemedDiffResult\n ): HunksRenderResult {\n const {\n diffStyle,\n disableFileHeader,\n expandUnchanged,\n expansionLineCount,\n collapsedContextThreshold,\n hunkSeparators,\n } = this.getOptionsWithDefaults();\n\n this.diff = fileDiff;\n const unified = diffStyle === 'unified';\n\n let additionsContentAST: ElementContent[] | undefined = [];\n let deletionsContentAST: ElementContent[] | undefined = [];\n let unifiedContentAST: ElementContent[] | undefined = [];\n\n const hunkData: HunkData[] = [];\n const { additionLines, deletionLines } = code;\n const context: ProcessContext = {\n rowCount: 0,\n hunkSeparators,\n additionsContentAST,\n deletionsContentAST,\n unifiedContentAST,\n unifiedGutterAST: createGutterWrapper(),\n deletionsGutterAST: createGutterWrapper(),\n additionsGutterAST: createGutterWrapper(),\n expansionLineCount,\n hunkData,\n incrementRowCount(count = 1) {\n context.rowCount += count;\n },\n pushToGutter(type: CodeColumnType, element: HASTElement) {\n switch (type) {\n case 'unified': {\n context.unifiedGutterAST.children.push(element);\n break;\n }\n case 'deletions': {\n context.deletionsGutterAST.children.push(element);\n break;\n }\n case 'additions': {\n context.additionsGutterAST.children.push(element);\n break;\n }\n }\n },\n };\n const trailingRangeSize = calculateTrailingRangeSize(fileDiff);\n const pendingSplitContext: PendingSplitContext = {\n size: 0,\n side: undefined,\n increment() {\n this.size += 1;\n },\n flush() {\n if (diffStyle === 'unified') {\n return;\n }\n if (this.size <= 0 || this.side == null) {\n this.side = undefined;\n this.size = 0;\n return;\n }\n if (this.side === 'additions') {\n context.pushToGutter(\n 'additions',\n createGutterGap(undefined, 'buffer', this.size)\n );\n additionsContentAST?.push(createEmptyRowBuffer(this.size));\n } else {\n context.pushToGutter(\n 'deletions',\n createGutterGap(undefined, 'buffer', this.size)\n );\n deletionsContentAST?.push(createEmptyRowBuffer(this.size));\n }\n this.size = 0;\n this.side = undefined;\n },\n };\n\n const pushGutterLineNumber = (\n type: CodeColumnType,\n lineType: LineTypes | 'buffer' | 'separator' | 'annotation',\n lineNumber: number,\n lineIndex: string,\n gutterProperties: Properties | undefined\n ) => {\n context.pushToGutter(\n type,\n createGutterItem(lineType, lineNumber, lineIndex, gutterProperties)\n );\n };\n\n function pushSeparators(props: PushSeparatorProps) {\n pendingSplitContext.flush();\n if (diffStyle === 'unified') {\n pushSeparator('unified', props, context);\n } else {\n pushSeparator('deletions', props, context);\n pushSeparator('additions', props, context);\n }\n }\n\n iterateOverDiff({\n diff: fileDiff,\n diffStyle,\n startingLine: renderRange.startingLine,\n totalLines: renderRange.totalLines,\n expandedHunks: expandUnchanged ? true : this.expandedHunks,\n collapsedContextThreshold,\n callback: ({\n hunkIndex,\n hunk,\n collapsedBefore,\n collapsedAfter,\n additionLine,\n deletionLine,\n type,\n }) => {\n const splitLineIndex =\n deletionLine != null\n ? deletionLine.splitLineIndex\n : additionLine.splitLineIndex;\n const unifiedLineIndex =\n additionLine != null\n ? additionLine.unifiedLineIndex\n : deletionLine.unifiedLineIndex;\n\n if (diffStyle === 'split' && type !== 'change') {\n pendingSplitContext.flush();\n }\n\n if (collapsedBefore > 0) {\n pushSeparators({\n hunkIndex,\n collapsedLines: collapsedBefore,\n rangeSize: Math.max(hunk?.collapsedBefore ?? 0, 0),\n hunkSpecs: hunk?.hunkSpecs,\n isFirstHunk: hunkIndex === 0,\n isLastHunk: false,\n isExpandable: !fileDiff.isPartial,\n });\n }\n\n const lineIndex =\n diffStyle === 'unified' ? unifiedLineIndex : splitLineIndex;\n const renderedLineContext: RenderedLineContext = {\n type,\n hunkIndex,\n lineIndex,\n unifiedLineIndex,\n splitLineIndex,\n deletionLine,\n additionLine,\n };\n\n if (diffStyle === 'unified') {\n const injectedRows =\n this.getUnifiedInjectedRowsForLine?.(renderedLineContext);\n if (injectedRows?.before != null) {\n pushUnifiedInjectedRows(injectedRows.before, context);\n }\n let deletionLineContent =\n deletionLine != null\n ? deletionLines[deletionLine.lineIndex]\n : undefined;\n let additionLineContent =\n additionLine != null\n ? additionLines[additionLine.lineIndex]\n : undefined;\n if (deletionLineContent == null && additionLineContent == null) {\n const errorMessage =\n 'DiffHunksRenderer.processDiffResult: deletionLine and additionLine are null, something is wrong';\n console.error(errorMessage, { file: fileDiff.name });\n throw new Error(errorMessage);\n }\n const lineType =\n type === 'change'\n ? additionLine != null\n ? 'change-addition'\n : 'change-deletion'\n : type;\n const lineDecoration = this.getUnifiedLineDecoration({\n // NOTE: This function gets extended so don't remove\n // these extra props\n type,\n lineType,\n additionLineIndex: additionLine?.lineIndex,\n deletionLineIndex: deletionLine?.lineIndex,\n });\n pushGutterLineNumber(\n 'unified',\n lineDecoration.gutterLineType,\n additionLine != null\n ? additionLine.lineNumber\n : deletionLine.lineNumber,\n `${unifiedLineIndex},${splitLineIndex}`,\n lineDecoration.gutterProperties\n );\n if (additionLineContent != null) {\n additionLineContent = withContentProperties(\n additionLineContent,\n lineDecoration.contentProperties\n );\n } else if (deletionLineContent != null) {\n deletionLineContent = withContentProperties(\n deletionLineContent,\n lineDecoration.contentProperties\n );\n }\n pushLineWithAnnotation({\n diffStyle: 'unified',\n type: type,\n deletionLine: deletionLineContent,\n additionLine: additionLineContent,\n unifiedSpan: this.getAnnotations(\n 'unified',\n deletionLine?.lineNumber,\n additionLine?.lineNumber,\n hunkIndex,\n lineIndex\n ),\n createAnnotationElement: (span) =>\n this.createAnnotationElement(span),\n context,\n });\n if (injectedRows?.after != null) {\n pushUnifiedInjectedRows(injectedRows.after, context);\n }\n } else {\n const injectedRows =\n this.getSplitInjectedRowsForLine?.(renderedLineContext);\n if (injectedRows?.before != null) {\n pushSplitInjectedRows(\n injectedRows.before,\n context,\n pendingSplitContext\n );\n }\n\n let deletionLineContent =\n deletionLine != null\n ? deletionLines[deletionLine.lineIndex]\n : undefined;\n let additionLineContent =\n additionLine != null\n ? additionLines[additionLine.lineIndex]\n : undefined;\n const deletionLineDecoration = this.getSplitLineDecoration({\n side: 'deletions',\n type,\n lineIndex: deletionLine?.lineIndex,\n });\n const additionLineDecoration = this.getSplitLineDecoration({\n side: 'additions',\n type,\n lineIndex: additionLine?.lineIndex,\n });\n\n if (deletionLineContent == null && additionLineContent == null) {\n const errorMessage =\n 'DiffHunksRenderer.processDiffResult: deletionLine and additionLine are null, something is wrong';\n console.error(errorMessage, { file: fileDiff.name });\n throw new Error(errorMessage);\n }\n\n const missingSide = (() => {\n if (type === 'change') {\n if (additionLineContent == null) {\n return 'additions';\n } else if (deletionLineContent == null) {\n return 'deletions';\n }\n }\n return undefined;\n })();\n if (missingSide != null) {\n if (\n pendingSplitContext.side != null &&\n pendingSplitContext.side !== missingSide\n ) {\n // NOTE(amadeus): If we see this error, we might need to bring back: flushSplitSpan();\n throw new Error(\n 'DiffHunksRenderer.processDiffResult: iterateOverDiff, invalid pending splits'\n );\n }\n pendingSplitContext.side = missingSide;\n pendingSplitContext.increment();\n }\n\n const annotationSpans = this.getAnnotations(\n 'split',\n deletionLine?.lineNumber,\n additionLine?.lineNumber,\n hunkIndex,\n lineIndex\n );\n if (annotationSpans != null && pendingSplitContext.size > 0) {\n pendingSplitContext.flush();\n }\n\n if (deletionLine != null) {\n const deletionLineDecorated = withContentProperties(\n deletionLineContent,\n deletionLineDecoration.contentProperties\n );\n pushGutterLineNumber(\n 'deletions',\n deletionLineDecoration.gutterLineType,\n deletionLine.lineNumber,\n `${deletionLine.unifiedLineIndex},${splitLineIndex}`,\n deletionLineDecoration.gutterProperties\n );\n if (deletionLineDecorated != null) {\n deletionLineContent = deletionLineDecorated;\n }\n }\n if (additionLine != null) {\n const additionLineDecorated = withContentProperties(\n additionLineContent,\n additionLineDecoration.contentProperties\n );\n pushGutterLineNumber(\n 'additions',\n additionLineDecoration.gutterLineType,\n additionLine.lineNumber,\n `${additionLine.unifiedLineIndex},${splitLineIndex}`,\n additionLineDecoration.gutterProperties\n );\n if (additionLineDecorated != null) {\n additionLineContent = additionLineDecorated;\n }\n }\n pushLineWithAnnotation({\n diffStyle: 'split',\n type: type,\n additionLine: additionLineContent,\n deletionLine: deletionLineContent,\n ...annotationSpans,\n createAnnotationElement: (span) =>\n this.createAnnotationElement(span),\n context,\n });\n if (injectedRows?.after != null) {\n pushSplitInjectedRows(\n injectedRows.after,\n context,\n pendingSplitContext\n );\n }\n }\n\n const noEOFCRDeletion = deletionLine?.noEOFCR ?? false;\n const noEOFCRAddition = additionLine?.noEOFCR ?? false;\n if (noEOFCRAddition || noEOFCRDeletion) {\n if (noEOFCRDeletion) {\n const noEOFType =\n type === 'context' || type === 'context-expanded'\n ? type\n : 'change-deletion';\n if (diffStyle === 'unified') {\n context.unifiedContentAST.push(createNoNewlineElement(noEOFType));\n context.pushToGutter(\n 'unified',\n createGutterGap(noEOFType, 'metadata', 1)\n );\n } else {\n context.deletionsContentAST.push(\n createNoNewlineElement(noEOFType)\n );\n context.pushToGutter(\n 'deletions',\n createGutterGap(noEOFType, 'metadata', 1)\n );\n if (!noEOFCRAddition) {\n context.pushToGutter(\n 'additions',\n createGutterGap(undefined, 'buffer', 1)\n );\n context.additionsContentAST.push(createEmptyRowBuffer(1));\n }\n }\n }\n if (noEOFCRAddition) {\n const noEOFType =\n type === 'context' || type === 'context-expanded'\n ? type\n : 'change-addition';\n if (diffStyle === 'unified') {\n context.unifiedContentAST.push(createNoNewlineElement(noEOFType));\n context.pushToGutter(\n 'unified',\n createGutterGap(noEOFType, 'metadata', 1)\n );\n } else {\n context.additionsContentAST.push(\n createNoNewlineElement(noEOFType)\n );\n context.pushToGutter(\n 'additions',\n createGutterGap(noEOFType, 'metadata', 1)\n );\n if (!noEOFCRDeletion) {\n context.pushToGutter(\n 'deletions',\n createGutterGap(undefined, 'buffer', 1)\n );\n context.deletionsContentAST.push(createEmptyRowBuffer(1));\n }\n }\n }\n context.incrementRowCount(1);\n }\n\n if (collapsedAfter > 0 && hunkSeparators !== 'simple') {\n pushSeparators({\n hunkIndex: type === 'context-expanded' ? hunkIndex : hunkIndex + 1,\n collapsedLines: collapsedAfter,\n rangeSize: trailingRangeSize,\n hunkSpecs: undefined,\n isFirstHunk: false,\n isLastHunk: true,\n isExpandable: !fileDiff.isPartial,\n });\n }\n context.incrementRowCount(1);\n },\n });\n\n if (diffStyle === 'split') {\n pendingSplitContext.flush();\n }\n\n const totalLines = Math.max(\n getTotalLineCountFromHunks(fileDiff.hunks),\n fileDiff.additionLines.length ?? 0,\n fileDiff.deletionLines.length ?? 0\n );\n\n const hasBuffer =\n renderRange.bufferBefore > 0 || renderRange.bufferAfter > 0;\n // Determine which ASTs to include based on diff style and file type\n const shouldIncludeAdditions = !unified && fileDiff.type !== 'deleted';\n const shouldIncludeDeletions = !unified && fileDiff.type !== 'new';\n const hasContent = context.rowCount > 0 || hasBuffer;\n\n additionsContentAST =\n shouldIncludeAdditions && hasContent ? additionsContentAST : undefined;\n deletionsContentAST =\n shouldIncludeDeletions && hasContent ? deletionsContentAST : undefined;\n unifiedContentAST = unified && hasContent ? unifiedContentAST : undefined;\n\n const preNode = this.createPreElement(\n deletionsContentAST != null && additionsContentAST != null,\n totalLines\n );\n\n return {\n unifiedGutterAST:\n unified && hasContent ? context.unifiedGutterAST.children : undefined,\n unifiedContentAST,\n deletionsGutterAST:\n shouldIncludeDeletions && hasContent\n ? context.deletionsGutterAST.children\n : undefined,\n deletionsContentAST,\n additionsGutterAST:\n shouldIncludeAdditions && hasContent\n ? context.additionsGutterAST.children\n : undefined,\n additionsContentAST,\n hunkData,\n preNode,\n themeStyles,\n baseThemeType,\n headerElement: !disableFileHeader\n ? this.renderHeader(this.diff)\n : undefined,\n totalLines,\n rowCount: context.rowCount,\n bufferBefore: renderRange.bufferBefore,\n bufferAfter: renderRange.bufferAfter,\n // FIXME\n css: '',\n };\n }\n\n public renderCodeAST(\n type: 'unified' | 'deletions' | 'additions',\n result: HunksRenderResult\n ): ElementContent[] | undefined {\n const gutterAST =\n type === 'unified'\n ? result.unifiedGutterAST\n : type === 'deletions'\n ? result.deletionsGutterAST\n : result.additionsGutterAST;\n\n const contentAST =\n type === 'unified'\n ? result.unifiedContentAST\n : type === 'deletions'\n ? result.deletionsContentAST\n : result.additionsContentAST;\n\n if (gutterAST == null || contentAST == null) {\n return undefined;\n }\n\n const gutter = createGutterWrapper(gutterAST);\n gutter.properties.style = `grid-row: span ${result.rowCount}`;\n const contentColumn = createContentColumn(contentAST, result.rowCount);\n return [gutter, contentColumn];\n }\n\n public renderFullAST(\n result: HunksRenderResult,\n children: ElementContent[] = []\n ): HASTElement {\n const containerSize =\n this.getOptionsWithDefaults().hunkSeparators === 'line-info';\n const unifiedAST = this.renderCodeAST('unified', result);\n if (unifiedAST != null) {\n children.push(\n createHastElement({\n tagName: 'code',\n children: unifiedAST,\n properties: {\n 'data-code': '',\n 'data-container-size': containerSize ? '' : undefined,\n 'data-unified': '',\n },\n })\n );\n return { ...result.preNode, children };\n }\n\n const deletionsAST = this.renderCodeAST('deletions', result);\n if (deletionsAST != null) {\n children.push(\n createHastElement({\n tagName: 'code',\n children: deletionsAST,\n properties: {\n 'data-code': '',\n 'data-container-size': containerSize ? '' : undefined,\n 'data-deletions': '',\n },\n })\n );\n }\n const additionsAST = this.renderCodeAST('additions', result);\n if (additionsAST != null) {\n children.push(\n createHastElement({\n tagName: 'code',\n children: additionsAST,\n properties: {\n 'data-code': '',\n 'data-container-size': containerSize ? '' : undefined,\n 'data-additions': '',\n },\n })\n );\n }\n return { ...result.preNode, children };\n }\n\n public renderFullHTML(\n result: HunksRenderResult,\n tempChildren: ElementContent[] = []\n ): string {\n return toHtml(this.renderFullAST(result, tempChildren));\n }\n\n public renderPartialHTML(\n children: ElementContent[],\n columnType?: 'unified' | 'deletions' | 'additions'\n ): string {\n if (columnType == null) {\n return toHtml(children);\n }\n return toHtml(\n createHastElement({\n tagName: 'code',\n children,\n properties: {\n 'data-code': '',\n 'data-container-size':\n this.getOptionsWithDefaults().hunkSeparators === 'line-info'\n ? ''\n : undefined,\n [`data-${columnType}`]: '',\n },\n })\n );\n }\n\n private getAnnotations(\n type: 'unified',\n deletionLineNumber: number | undefined,\n additionLineNumber: number | undefined,\n hunkIndex: number,\n lineIndex: number\n ): AnnotationSpan | undefined;\n private getAnnotations(\n type: 'split',\n deletionLineNumber: number | undefined,\n additionLineNumber: number | undefined,\n hunkIndex: number,\n lineIndex: number\n ): { deletionSpan: AnnotationSpan; additionSpan: AnnotationSpan } | undefined;\n private getAnnotations(\n type: 'unified' | 'split',\n deletionLineNumber: number | undefined,\n additionLineNumber: number | undefined,\n hunkIndex: number,\n lineIndex: number\n ):\n | AnnotationSpan\n | { deletionSpan: AnnotationSpan; additionSpan: AnnotationSpan }\n | undefined {\n const deletionSpan: AnnotationSpan = {\n type: 'annotation',\n hunkIndex,\n lineIndex,\n annotations: [],\n };\n if (deletionLineNumber != null) {\n for (const anno of this.deletionAnnotations[deletionLineNumber] ?? []) {\n deletionSpan.annotations.push(getLineAnnotationName(anno));\n }\n }\n const additionSpan: AnnotationSpan = {\n type: 'annotation',\n hunkIndex,\n lineIndex,\n annotations: [],\n };\n if (additionLineNumber != null) {\n for (const anno of this.additionAnnotations[additionLineNumber] ?? []) {\n (type === 'unified' ? deletionSpan : additionSpan).annotations.push(\n getLineAnnotationName(anno)\n );\n }\n }\n if (type === 'unified') {\n if (deletionSpan.annotations.length > 0) {\n return deletionSpan;\n }\n return undefined;\n }\n if (\n additionSpan.annotations.length === 0 &&\n deletionSpan.annotations.length === 0\n ) {\n return undefined;\n }\n return { deletionSpan, additionSpan };\n }\n\n private renderHeader(diff: FileDiffMetadata): HASTElement {\n const { headerRenderMode } = this.getOptionsWithDefaults();\n return createFileHeaderElement({\n fileOrDiff: diff,\n mode: headerRenderMode,\n });\n }\n}\n\nfunction getModifiedLinesString(lines: number) {\n return `${lines} unmodified line${lines > 1 ? 's' : ''}`;\n}\n\nfunction pushUnifiedInjectedRows(\n rows: InjectedRow[],\n context: ProcessContext\n): void {\n for (const row of rows) {\n context.unifiedContentAST.push(row.content);\n context.pushToGutter('unified', row.gutter);\n context.incrementRowCount(1);\n }\n}\n\nfunction pushSplitInjectedRows(\n rows: SplitInjectedRow[],\n context: ProcessContext,\n pendingSplitContext: PendingSplitContext\n): void {\n for (const { deletion, addition } of rows) {\n if (deletion == null && addition == null) {\n continue;\n }\n const missingSide =\n deletion != null && addition != null\n ? undefined\n : deletion == null\n ? 'deletions'\n : 'additions';\n\n if (missingSide == null || pendingSplitContext.side !== missingSide) {\n pendingSplitContext.flush();\n }\n\n if (deletion != null) {\n context.deletionsContentAST.push(deletion.content);\n context.pushToGutter('deletions', deletion.gutter);\n }\n\n if (addition != null) {\n context.additionsContentAST.push(addition.content);\n context.pushToGutter('additions', addition.gutter);\n }\n\n if (missingSide != null) {\n pendingSplitContext.side = missingSide;\n pendingSplitContext.increment();\n }\n\n context.incrementRowCount(1);\n }\n}\n\nfunction pushLineWithAnnotation({\n diffStyle,\n type,\n deletionLine,\n additionLine,\n unifiedSpan,\n deletionSpan,\n additionSpan,\n createAnnotationElement,\n context,\n}: PushLineWithAnnotation) {\n let hasAnnotationRow = false;\n if (diffStyle === 'unified') {\n if (additionLine != null) {\n context.unifiedContentAST.push(additionLine);\n } else if (deletionLine != null) {\n context.unifiedContentAST.push(deletionLine);\n }\n if (unifiedSpan != null) {\n const lineType =\n type === 'change'\n ? deletionLine != null\n ? 'change-deletion'\n : 'change-addition'\n : type;\n context.unifiedContentAST.push(createAnnotationElement(unifiedSpan));\n context.pushToGutter(\n 'unified',\n createGutterGap(lineType, 'annotation', 1)\n );\n hasAnnotationRow = true;\n }\n } else if (diffStyle === 'split') {\n if (deletionLine != null) {\n context.deletionsContentAST.push(deletionLine);\n }\n if (additionLine != null) {\n context.additionsContentAST.push(additionLine);\n }\n if (deletionSpan != null) {\n const lineType =\n type === 'change'\n ? deletionLine != null\n ? 'change-deletion'\n : 'context'\n : type;\n context.deletionsContentAST.push(createAnnotationElement(deletionSpan));\n context.pushToGutter(\n 'deletions',\n createGutterGap(lineType, 'annotation', 1)\n );\n hasAnnotationRow = true;\n }\n if (additionSpan != null) {\n const lineType =\n type === 'change'\n ? additionLine != null\n ? 'change-addition'\n : 'context'\n : type;\n context.additionsContentAST.push(createAnnotationElement(additionSpan));\n context.pushToGutter(\n 'additions',\n createGutterGap(lineType, 'annotation', 1)\n );\n hasAnnotationRow = true;\n }\n }\n if (hasAnnotationRow) {\n context.incrementRowCount(1);\n }\n}\n\nfunction pushSeparator(\n type: 'additions' | 'deletions' | 'unified',\n {\n hunkIndex,\n collapsedLines,\n rangeSize,\n hunkSpecs,\n isFirstHunk,\n isLastHunk,\n isExpandable,\n }: PushSeparatorProps,\n context: ProcessContext\n) {\n if (collapsedLines <= 0) {\n return;\n }\n const linesAST =\n type === 'unified'\n ? context.unifiedContentAST\n : type === 'deletions'\n ? context.deletionsContentAST\n : context.additionsContentAST;\n\n if (context.hunkSeparators === 'metadata') {\n if (hunkSpecs != null) {\n context.pushToGutter(\n type,\n createSeparator({\n type: 'metadata',\n content: hunkSpecs,\n isFirstHunk,\n isLastHunk,\n })\n );\n linesAST.push(\n createSeparator({\n type: 'metadata',\n content: hunkSpecs,\n isFirstHunk,\n isLastHunk,\n })\n );\n if (type !== 'additions') {\n context.incrementRowCount(1);\n }\n }\n return;\n }\n if (context.hunkSeparators === 'simple') {\n if (hunkIndex > 0) {\n context.pushToGutter(\n type,\n createSeparator({ type: 'simple', isFirstHunk, isLastHunk: false })\n );\n linesAST.push(\n createSeparator({ type: 'simple', isFirstHunk, isLastHunk: false })\n );\n if (type !== 'additions') {\n context.incrementRowCount(1);\n }\n }\n return;\n }\n const slotName = getHunkSeparatorSlotName(type, hunkIndex);\n const chunked = rangeSize > context.expansionLineCount;\n const expandIndex = isExpandable ? hunkIndex : undefined;\n context.pushToGutter(\n type,\n createSeparator({\n type: context.hunkSeparators,\n content: getModifiedLinesString(collapsedLines),\n expandIndex,\n chunked,\n slotName,\n isFirstHunk,\n isLastHunk,\n })\n );\n linesAST.push(\n createSeparator({\n type: context.hunkSeparators,\n content: getModifiedLinesString(collapsedLines),\n expandIndex,\n chunked,\n slotName,\n isFirstHunk,\n isLastHunk,\n })\n );\n if (type !== 'additions') {\n context.incrementRowCount(1);\n }\n context.hunkData.push({\n slotName,\n hunkIndex,\n lines: collapsedLines,\n type,\n expandable: isExpandable\n ? { up: !isFirstHunk, down: !isLastHunk, chunked }\n : undefined,\n });\n}\n\nfunction withContentProperties(\n lineNode: ElementContent | undefined,\n contentProperties: Properties | undefined\n): ElementContent | undefined {\n if (\n lineNode == null ||\n lineNode.type !== 'element' ||\n contentProperties == null\n ) {\n return lineNode;\n }\n return {\n ...lineNode,\n properties: {\n ...lineNode.properties,\n ...contentProperties,\n },\n };\n}\n\nfunction calculateTrailingRangeSize(fileDiff: FileDiffMetadata): number {\n const lastHunk = fileDiff.hunks.at(-1);\n if (\n lastHunk == null ||\n fileDiff.isPartial ||\n fileDiff.additionLines.length === 0 ||\n fileDiff.deletionLines.length === 0\n ) {\n return 0;\n }\n const additionRemaining =\n fileDiff.additionLines.length -\n (lastHunk.additionLineIndex + lastHunk.additionCount);\n const deletionRemaining =\n fileDiff.deletionLines.length -\n (lastHunk.deletionLineIndex + lastHunk.deletionCount);\n if (additionRemaining !== deletionRemaining) {\n throw new Error(\n `DiffHunksRenderer.processDiffResult: trailing context mismatch (additions=${additionRemaining}, deletions=${deletionRemaining}) for ${fileDiff.name}`\n );\n }\n return Math.min(additionRemaining, deletionRemaining);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAqMA,IAAI,aAAa;AAEjB,IAAa,oBAAb,MAAwD;CACtD,AAAS,OAAe,uBAAuB,EAAE;CAEjD,AAAQ;CACR,AAAQ;CAER,AAAQ,gCAAgB,IAAI,KAAkC;CAE9D,AAAQ,sBAAsD,EAAE;CAChE,AAAQ,sBAAsD,EAAE;CAEhE,AAAQ,eAAmC;CAC3C,AAAQ;CAER,YACE,AAAOA,UAAoC,EAAE,OAAO,gBAAgB,EACpE,AAAQC,gBACR,AAAQC,eACR;EAHO;EACC;EACA;AAER,MAAI,eAAe,eAAe,KAAK,KACrC,MAAK,cAAc,kBAAkB,QAAQ,SAAS,eAAe,GACjE,wBAAwB,GACxB;;CAIR,AAAO,UAAgB;AACrB,OAAK,cAAc;AACnB,OAAK,OAAO;AACZ,OAAK,cAAc;AACnB,OAAK,eAAe,oBAAoB,KAAK;AAC7C,OAAK,gBAAgB;AACrB,OAAK,iBAAiB;;CAGxB,AAAO,UAAgB;AACrB,OAAK,cAAc;AACnB,OAAK,OAAO;AACZ,OAAK,cAAc;AACnB,OAAK,eAAe,oBAAoB,KAAK;;CAG/C,AAAO,WAAW,SAAyC;AACzD,OAAK,UAAU;;CAGjB,AAAO,aAAa,SAAkD;AACpE,OAAK,UAAU;GAAE,GAAG,KAAK;GAAS,GAAG;GAAS;;CAGhD,AAAO,WACL,OACA,WACA,qBAA6B,KAAK,wBAAwB,CACvD,oBACG;EACN,MAAM,SAAS,EACb,GAAI,KAAK,cAAc,IAAI,MAAM,IAAI;GACnC,WAAW;GACX,SAAS;GACV,EACF;AACD,MAAI,cAAc,QAAQ,cAAc,OACtC,QAAO,aAAa;AAEtB,MAAI,cAAc,UAAU,cAAc,OACxC,QAAO,WAAW;AAIpB,MAAI,KAAK,aAAa,gBAAgB,KACpC,MAAK,cAAc;AAErB,OAAK,cAAc,IAAI,OAAO,OAAO;;CAGvC,AAAO,gBAAgB,WAAwC;AAC7D,SAAO,KAAK,cAAc,IAAI,UAAU,IAAI;;CAG9C,AAAO,sBAAwD;AAC7D,SAAO,KAAK;;CAGd,AAAO,mBACL,iBACM;AACN,OAAK,sBAAsB,EAAE;AAC7B,OAAK,sBAAsB,EAAE;AAC7B,OAAK,MAAM,cAAc,iBAAiB;GACxC,MAAM,aAA6C;AACjD,YAAQ,WAAW,MAAnB;KACE,KAAK,YACH,QAAO,KAAK;KACd,KAAK,YACH,QAAO,KAAK;;OAEd;GACJ,MAAM,MAAM,IAAI,WAAW,eAAe,EAAE;AAC5C,OAAI,WAAW,cAAc;AAC7B,OAAI,KAAK,WAAW;;;CAIxB,AAAU,yBAAyB,EACjC,YAC6C;AAC7C,SAAO,EAAE,gBAAgB,UAAU;;CAGrC,AAAU,uBAAuB,EAC/B,MACA,QAC2C;AAC3C,MAAI,SAAS,SACX,QAAO,EAAE,gBAAgB,MAAM;AAEjC,SAAO,EACL,gBACE,SAAS,cAAc,oBAAoB,mBAC9C;;CAGH,AAAU,wBAAwB,MAAmC;AACnE,SAAOC,wBAA+B,KAAK;;CAa7C,AAAU,yBAA+D;EACvE,MAAM,EACJ,iBAAiB,QACjB,YAAY,SACZ,oBAAoB,OACpB,oBAAoB,OACpB,qBAAqB,OACrB,+BAA+B,OAC/B,YAAY,OACZ,kBAAkB,OAClB,4BAA4B,qCAC5B,qBAAqB,KACrB,iBAAiB,aACjB,eAAe,YACf,oBAAoB,KACpB,WAAW,UACX,QAAQ,gBACR,mBAAmB,WACnB,wBAAwB,KACxB,sBAAsB,OACtB,gBAAgB,UACd,KAAK;AACT,SAAO;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,OAAO,KAAK,eAAe,sBAAsB,CAAC,SAAS;GAC3D;GACA;GACA;GACA;GACD;;CAGH,MAAc,wBAAmD;AAC/D,OAAK,cAAc,MAAM,qBACvB,sBAAsB,KAAK,cAAc,KAAK,QAAQ,CACvD;AACD,SAAO,KAAK;;CAGd,AAAO,QAAQ,MAA0C;AACvD,MAAI,QAAQ,KACV;AAEF,OAAK,OAAO;EACZ,MAAM,EAAE,YAAY,KAAK,iBAAiB,KAAK;EAC/C,IAAI,QAAQ,KAAK,eAAe,mBAAmB,KAAK;AACxD,MAAI,SAAS,QAAQ,CAAC,0BAA0B,SAAS,MAAM,QAAQ,CACrE,SAAQ;AAEV,OAAK,gBAAgB;GACnB;GACA,aAAa,CAAC,gBAAgB,KAAK;GACnC;GACA,QAAQ,OAAO;GACf,aAAa;GACd;AACD,MACE,KAAK,eAAe,eAAe,KAAK,QACxC,KAAK,YAAY,UAAU,KAG3B,MAAK,cAAc,iBAAiB,MAAM,KAAK,KAAK;;CAIxD,AAAQ,iBAAiB,MAAgD;EACvE,MAAMC,iBAAoC;AACxC,OAAI,KAAK,eAAe,eAAe,KAAK,KAC1C,QAAO,KAAK,cAAc,sBAAsB;GAElD,MAAM,EAAE,OAAO,uBAAuB,cAAc,sBAClD,KAAK,wBAAwB;AAC/B,UAAO;IACL;IACA,qBAAqB,0BAA0B,KAAK,QAAQ;IAC5D;IACA;IACA;IACD;MACC;AACJ,OAAK,wBAAwB;EAC7B,MAAM,EAAE,gBAAgB;AACxB,MAAI,aAAa,UAAU,KACzB,QAAO;GAAE;GAAS,aAAa;GAAM;AAEvC,MACE,SAAS,YAAY,QACrB,CAAC,0BAA0B,SAAS,YAAY,QAAQ,CAExD,QAAO;GAAE;GAAS,aAAa;GAAM;AAEvC,SAAO;GAAE;GAAS,aAAa;GAAO;;CAGxC,AAAO,WACL,OAAqC,KAAK,aAAa,MACvD,cAA2B,sBACI;AAC/B,MAAI,QAAQ,KACV;EAEF,MAAM,EAAE,kBAAkB,OAAO,8BAC/B,KAAK,wBAAwB;EAC/B,MAAM,QAAQ,KAAK,eAAe,mBAAmB,KAAK;AAC1D,MAAI,SAAS,QAAQ,KAAK,eAAe,KACvC,MAAK,cAAc;GACjB;GACA,aAAa;GACb,aAAa;GACb,GAAG;GACJ;EAEH,MAAM,EAAE,SAAS,gBAAgB,KAAK,iBAAiB,KAAK;AAC5D,OAAK,gBAAgB;GACnB;GACA,aAAa;GACb;GACA,QAAQ;GACR,aAAa;GACd;AACD,MAAI,KAAK,eAAe,eAAe,KAAK,MAAM;AAChD,OACE,KAAK,YAAY,UAAU,QAC1B,CAAC,KAAK,YAAY,gBAChB,SAAS,KAAK,YAAY,QACzB,CAAC,qBAAqB,KAAK,YAAY,aAAa,YAAY,GACpE;AACA,SAAK,YAAY,OAAO;AACxB,SAAK,YAAY,SAAS,KAAK,cAAc,gBAC3C,MACA,YAAY,cACZ,YAAY,YAGZ,qBAAqB,YAAY,GAC7B,OACA,kBACE,OACA,KAAK,eACX,0BACD;AACD,SAAK,YAAY,cAAc;;AAEjC,OAGE,YAAY,aAAa,MACxB,CAAC,KAAK,YAAY,eAAe,aAElC,MAAK,cAAc,iBAAiB,MAAM,KAAK;SAE5C;AACL,QAAK,eAAe,KAAK,QAAQ,wBAAwB,KAAK,KAAK;GACnE,MAAM,YACJ,KAAK,eAAe,QAAQ,kBAAkB,QAAQ,MAAM;GAC9D,MAAM,WACJ,KAAK,eAAe,QAAQ,qBAAqB,KAAK,aAAa;AAMrE,OACE,KAAK,eAAe,QACpB,cACC,eACE,CAAC,KAAK,YAAY,eAAe,YAClC,KAAK,YAAY,UAAU,OAC7B;IACA,MAAM,EAAE,QAAQ,uBAAY,KAAK,0BAC/B,MACA,KAAK,aACL,CAAC,SACF;AACD,SAAK,cAAc;KACjB;KACA;KACA,aAAa;KACb;KACA,aAAa;KACd;;AAMH,OAAI,CAAC,aAAa,CAAC,SACjB,CAAK,KAAK,eAAe,KAAK,CAAC,MAAM,EAAE,QAAQ,yBAAc;AAC3D,SAAK,mBAAmB,MAAM,QAAQC,UAAQ;KAC9C;;AAGN,SAAO,KAAK,YAAY,UAAU,OAC9B,KAAK,kBACH,KAAK,YAAY,MACjB,aACA,KAAK,YAAY,OAClB,GACD;;CAGN,MAAa,YACX,MACA,cAA2B,sBACC;EAC5B,MAAM,EAAE,WAAW,MAAM,KAAK,eAAe,KAAK;AAClD,SAAO,KAAK,kBAAkB,MAAM,aAAa,OAAO;;CAG1D,AAAU,iBACR,OACA,YACA,kBACa;EACb,MAAM,EAAE,gBAAgB,mBAAmB,oBAAoB,aAC7D,KAAK,wBAAwB;AAC/B,SAAO,iBAAiB;GACtB,MAAM;GACN;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;;CAGJ,MAAc,eACZ,MAC2B;AAC3B,OAAK,eAAe,KAAK,QAAQ,wBAAwB,KAAK,KAAK;EACnE,MAAM,YACJ,KAAK,eAAe,QACpB,kBAAkB,KAAK,QAAQ,SAAS,eAAe;EACzD,MAAM,WACJ,KAAK,eAAe,QAAQ,qBAAqB,KAAK,aAAa;AAGrE,MAAI,KAAK,eAAe,QAAQ,CAAC,aAAa,CAAC,SAC7C,MAAK,cAAc,MAAM,KAAK,uBAAuB;AAEvD,SAAO,KAAK,0BAA0B,MAAM,KAAK,YAAY;;CAG/D,AAAQ,0BACN,MACA,aACA,iBAAiB,OACC;EAClB,MAAM,EAAE,YAAY,KAAK,iBAAiB,KAAK;EAC/C,MAAM,EAAE,8BAA8B,KAAK,wBAAwB;AAMnE,SAAO;GAAE,QALM,0BAA0B,MAAM,aAAa,SAAS;IACnE;IACA,eAAe,iBAAiB,OAAO;IACvC;IACD,CAAC;GACe;GAAS;;CAG5B,AAAO,mBACL,MACA,QACA,SACM;AAIN,MAAI,KAAK,eAAe,KACtB;EAGF,MAAM,sBACJ,CAAC,KAAK,YAAY,eAClB,CAAC,0BAA0B,KAAK,YAAY,SAAS,QAAQ,IAC7D,KAAK,YAAY,SAAS;AAE5B,OAAK,cAAc;GACjB;GACA;GACA,aAAa;GACb;GACA,aAAa;GACd;AACD,MAAI,oBACF,MAAK,kBAAkB;;CAI3B,AAAO,iBAAiB,OAAsB;AAC5C,UAAQ,MAAM,MAAM;;CAGtB,AAAQ,kBACN,UACA,aACA,EAAE,MAAM,aAAa,iBACF;EACnB,MAAM,EACJ,WACA,mBACA,iBACA,oBACA,2BACA,mBACE,KAAK,wBAAwB;AAEjC,OAAK,OAAO;EACZ,MAAM,UAAU,cAAc;EAE9B,IAAIC,sBAAoD,EAAE;EAC1D,IAAIC,sBAAoD,EAAE;EAC1D,IAAIC,oBAAkD,EAAE;EAExD,MAAMC,WAAuB,EAAE;EAC/B,MAAM,EAAE,eAAe,kBAAkB;EACzC,MAAMC,UAA0B;GAC9B,UAAU;GACV;GACA;GACA;GACA;GACA,kBAAkB,qBAAqB;GACvC,oBAAoB,qBAAqB;GACzC,oBAAoB,qBAAqB;GACzC;GACA;GACA,kBAAkB,QAAQ,GAAG;AAC3B,YAAQ,YAAY;;GAEtB,aAAa,MAAsB,SAAsB;AACvD,YAAQ,MAAR;KACE,KAAK;AACH,cAAQ,iBAAiB,SAAS,KAAK,QAAQ;AAC/C;KAEF,KAAK;AACH,cAAQ,mBAAmB,SAAS,KAAK,QAAQ;AACjD;KAEF,KAAK;AACH,cAAQ,mBAAmB,SAAS,KAAK,QAAQ;AACjD;;;GAIP;EACD,MAAM,oBAAoB,2BAA2B,SAAS;EAC9D,MAAMC,sBAA2C;GAC/C,MAAM;GACN,MAAM;GACN,YAAY;AACV,SAAK,QAAQ;;GAEf,QAAQ;AACN,QAAI,cAAc,UAChB;AAEF,QAAI,KAAK,QAAQ,KAAK,KAAK,QAAQ,MAAM;AACvC,UAAK,OAAO;AACZ,UAAK,OAAO;AACZ;;AAEF,QAAI,KAAK,SAAS,aAAa;AAC7B,aAAQ,aACN,aACA,gBAAgB,QAAW,UAAU,KAAK,KAAK,CAChD;AACD,0BAAqB,KAAK,qBAAqB,KAAK,KAAK,CAAC;WACrD;AACL,aAAQ,aACN,aACA,gBAAgB,QAAW,UAAU,KAAK,KAAK,CAChD;AACD,0BAAqB,KAAK,qBAAqB,KAAK,KAAK,CAAC;;AAE5D,SAAK,OAAO;AACZ,SAAK,OAAO;;GAEf;EAED,MAAM,wBACJ,MACA,UACA,YACA,WACA,qBACG;AACH,WAAQ,aACN,MACA,iBAAiB,UAAU,YAAY,WAAW,iBAAiB,CACpE;;EAGH,SAAS,eAAe,OAA2B;AACjD,uBAAoB,OAAO;AAC3B,OAAI,cAAc,UAChB,eAAc,WAAW,OAAO,QAAQ;QACnC;AACL,kBAAc,aAAa,OAAO,QAAQ;AAC1C,kBAAc,aAAa,OAAO,QAAQ;;;AAI9C,kBAAgB;GACd,MAAM;GACN;GACA,cAAc,YAAY;GAC1B,YAAY,YAAY;GACxB,eAAe,kBAAkB,OAAO,KAAK;GAC7C;GACA,WAAW,EACT,WACA,MACA,iBACA,gBACA,cACA,cACA,WACI;IACJ,MAAM,iBACJ,gBAAgB,OACZ,aAAa,iBACb,aAAa;IACnB,MAAM,mBACJ,gBAAgB,OACZ,aAAa,mBACb,aAAa;AAEnB,QAAI,cAAc,WAAW,SAAS,SACpC,qBAAoB,OAAO;AAG7B,QAAI,kBAAkB,EACpB,gBAAe;KACb;KACA,gBAAgB;KAChB,WAAW,KAAK,IAAI,MAAM,mBAAmB,GAAG,EAAE;KAClD,WAAW,MAAM;KACjB,aAAa,cAAc;KAC3B,YAAY;KACZ,cAAc,CAAC,SAAS;KACzB,CAAC;IAGJ,MAAM,YACJ,cAAc,YAAY,mBAAmB;IAC/C,MAAMC,sBAA2C;KAC/C;KACA;KACA;KACA;KACA;KACA;KACA;KACD;AAED,QAAI,cAAc,WAAW;KAC3B,MAAM,eACJ,KAAK,gCAAgC,oBAAoB;AAC3D,SAAI,cAAc,UAAU,KAC1B,yBAAwB,aAAa,QAAQ,QAAQ;KAEvD,IAAI,sBACF,gBAAgB,OACZ,cAAc,aAAa,aAC3B;KACN,IAAI,sBACF,gBAAgB,OACZ,cAAc,aAAa,aAC3B;AACN,SAAI,uBAAuB,QAAQ,uBAAuB,MAAM;MAC9D,MAAM,eACJ;AACF,cAAQ,MAAM,cAAc,EAAE,MAAM,SAAS,MAAM,CAAC;AACpD,YAAM,IAAI,MAAM,aAAa;;KAE/B,MAAM,WACJ,SAAS,WACL,gBAAgB,OACd,oBACA,oBACF;KACN,MAAM,iBAAiB,KAAK,yBAAyB;MAGnD;MACA;MACA,mBAAmB,cAAc;MACjC,mBAAmB,cAAc;MAClC,CAAC;AACF,0BACE,WACA,eAAe,gBACf,gBAAgB,OACZ,aAAa,aACb,aAAa,YACjB,GAAG,iBAAiB,GAAG,kBACvB,eAAe,iBAChB;AACD,SAAI,uBAAuB,KACzB,uBAAsB,sBACpB,qBACA,eAAe,kBAChB;cACQ,uBAAuB,KAChC,uBAAsB,sBACpB,qBACA,eAAe,kBAChB;AAEH,4BAAuB;MACrB,WAAW;MACL;MACN,cAAc;MACd,cAAc;MACd,aAAa,KAAK,eAChB,WACA,cAAc,YACd,cAAc,YACd,WACA,UACD;MACD,0BAA0B,SACxB,KAAK,wBAAwB,KAAK;MACpC;MACD,CAAC;AACF,SAAI,cAAc,SAAS,KACzB,yBAAwB,aAAa,OAAO,QAAQ;WAEjD;KACL,MAAM,eACJ,KAAK,8BAA8B,oBAAoB;AACzD,SAAI,cAAc,UAAU,KAC1B,uBACE,aAAa,QACb,SACA,oBACD;KAGH,IAAI,sBACF,gBAAgB,OACZ,cAAc,aAAa,aAC3B;KACN,IAAI,sBACF,gBAAgB,OACZ,cAAc,aAAa,aAC3B;KACN,MAAM,yBAAyB,KAAK,uBAAuB;MACzD,MAAM;MACN;MACA,WAAW,cAAc;MAC1B,CAAC;KACF,MAAM,yBAAyB,KAAK,uBAAuB;MACzD,MAAM;MACN;MACA,WAAW,cAAc;MAC1B,CAAC;AAEF,SAAI,uBAAuB,QAAQ,uBAAuB,MAAM;MAC9D,MAAM,eACJ;AACF,cAAQ,MAAM,cAAc,EAAE,MAAM,SAAS,MAAM,CAAC;AACpD,YAAM,IAAI,MAAM,aAAa;;KAG/B,MAAM,qBAAqB;AACzB,UAAI,SAAS,UACX;WAAI,uBAAuB,KACzB,QAAO;gBACE,uBAAuB,KAChC,QAAO;;SAIT;AACJ,SAAI,eAAe,MAAM;AACvB,UACE,oBAAoB,QAAQ,QAC5B,oBAAoB,SAAS,YAG7B,OAAM,IAAI,MACR,+EACD;AAEH,0BAAoB,OAAO;AAC3B,0BAAoB,WAAW;;KAGjC,MAAM,kBAAkB,KAAK,eAC3B,SACA,cAAc,YACd,cAAc,YACd,WACA,UACD;AACD,SAAI,mBAAmB,QAAQ,oBAAoB,OAAO,EACxD,qBAAoB,OAAO;AAG7B,SAAI,gBAAgB,MAAM;MACxB,MAAM,wBAAwB,sBAC5B,qBACA,uBAAuB,kBACxB;AACD,2BACE,aACA,uBAAuB,gBACvB,aAAa,YACb,GAAG,aAAa,iBAAiB,GAAG,kBACpC,uBAAuB,iBACxB;AACD,UAAI,yBAAyB,KAC3B,uBAAsB;;AAG1B,SAAI,gBAAgB,MAAM;MACxB,MAAM,wBAAwB,sBAC5B,qBACA,uBAAuB,kBACxB;AACD,2BACE,aACA,uBAAuB,gBACvB,aAAa,YACb,GAAG,aAAa,iBAAiB,GAAG,kBACpC,uBAAuB,iBACxB;AACD,UAAI,yBAAyB,KAC3B,uBAAsB;;AAG1B,4BAAuB;MACrB,WAAW;MACL;MACN,cAAc;MACd,cAAc;MACd,GAAG;MACH,0BAA0B,SACxB,KAAK,wBAAwB,KAAK;MACpC;MACD,CAAC;AACF,SAAI,cAAc,SAAS,KACzB,uBACE,aAAa,OACb,SACA,oBACD;;IAIL,MAAM,kBAAkB,cAAc,WAAW;IACjD,MAAM,kBAAkB,cAAc,WAAW;AACjD,QAAI,mBAAmB,iBAAiB;AACtC,SAAI,iBAAiB;MACnB,MAAM,YACJ,SAAS,aAAa,SAAS,qBAC3B,OACA;AACN,UAAI,cAAc,WAAW;AAC3B,eAAQ,kBAAkB,KAAK,uBAAuB,UAAU,CAAC;AACjE,eAAQ,aACN,WACA,gBAAgB,WAAW,YAAY,EAAE,CAC1C;aACI;AACL,eAAQ,oBAAoB,KAC1B,uBAAuB,UAAU,CAClC;AACD,eAAQ,aACN,aACA,gBAAgB,WAAW,YAAY,EAAE,CAC1C;AACD,WAAI,CAAC,iBAAiB;AACpB,gBAAQ,aACN,aACA,gBAAgB,QAAW,UAAU,EAAE,CACxC;AACD,gBAAQ,oBAAoB,KAAK,qBAAqB,EAAE,CAAC;;;;AAI/D,SAAI,iBAAiB;MACnB,MAAM,YACJ,SAAS,aAAa,SAAS,qBAC3B,OACA;AACN,UAAI,cAAc,WAAW;AAC3B,eAAQ,kBAAkB,KAAK,uBAAuB,UAAU,CAAC;AACjE,eAAQ,aACN,WACA,gBAAgB,WAAW,YAAY,EAAE,CAC1C;aACI;AACL,eAAQ,oBAAoB,KAC1B,uBAAuB,UAAU,CAClC;AACD,eAAQ,aACN,aACA,gBAAgB,WAAW,YAAY,EAAE,CAC1C;AACD,WAAI,CAAC,iBAAiB;AACpB,gBAAQ,aACN,aACA,gBAAgB,QAAW,UAAU,EAAE,CACxC;AACD,gBAAQ,oBAAoB,KAAK,qBAAqB,EAAE,CAAC;;;;AAI/D,aAAQ,kBAAkB,EAAE;;AAG9B,QAAI,iBAAiB,KAAK,mBAAmB,SAC3C,gBAAe;KACb,WAAW,SAAS,qBAAqB,YAAY,YAAY;KACjE,gBAAgB;KAChB,WAAW;KACX,WAAW;KACX,aAAa;KACb,YAAY;KACZ,cAAc,CAAC,SAAS;KACzB,CAAC;AAEJ,YAAQ,kBAAkB,EAAE;;GAE/B,CAAC;AAEF,MAAI,cAAc,QAChB,qBAAoB,OAAO;EAG7B,MAAM,aAAa,KAAK,IACtB,2BAA2B,SAAS,MAAM,EAC1C,SAAS,cAAc,UAAU,GACjC,SAAS,cAAc,UAAU,EAClC;EAED,MAAM,YACJ,YAAY,eAAe,KAAK,YAAY,cAAc;EAE5D,MAAM,yBAAyB,CAAC,WAAW,SAAS,SAAS;EAC7D,MAAM,yBAAyB,CAAC,WAAW,SAAS,SAAS;EAC7D,MAAM,aAAa,QAAQ,WAAW,KAAK;AAE3C,wBACE,0BAA0B,aAAa,sBAAsB;AAC/D,wBACE,0BAA0B,aAAa,sBAAsB;AAC/D,sBAAoB,WAAW,aAAa,oBAAoB;EAEhE,MAAM,UAAU,KAAK,iBACnB,uBAAuB,QAAQ,uBAAuB,MACtD,WACD;AAED,SAAO;GACL,kBACE,WAAW,aAAa,QAAQ,iBAAiB,WAAW;GAC9D;GACA,oBACE,0BAA0B,aACtB,QAAQ,mBAAmB,WAC3B;GACN;GACA,oBACE,0BAA0B,aACtB,QAAQ,mBAAmB,WAC3B;GACN;GACA;GACA;GACA;GACA;GACA,eAAe,CAAC,oBACZ,KAAK,aAAa,KAAK,KAAK,GAC5B;GACJ;GACA,UAAU,QAAQ;GAClB,cAAc,YAAY;GAC1B,aAAa,YAAY;GAEzB,KAAK;GACN;;CAGH,AAAO,cACL,MACA,QAC8B;EAC9B,MAAM,YACJ,SAAS,YACL,OAAO,mBACP,SAAS,cACP,OAAO,qBACP,OAAO;EAEf,MAAM,aACJ,SAAS,YACL,OAAO,oBACP,SAAS,cACP,OAAO,sBACP,OAAO;AAEf,MAAI,aAAa,QAAQ,cAAc,KACrC;EAGF,MAAM,SAAS,oBAAoB,UAAU;AAC7C,SAAO,WAAW,QAAQ,kBAAkB,OAAO;AAEnD,SAAO,CAAC,QADc,oBAAoB,YAAY,OAAO,SAAS,CACxC;;CAGhC,AAAO,cACL,QACA,WAA6B,EAAE,EAClB;EACb,MAAM,gBACJ,KAAK,wBAAwB,CAAC,mBAAmB;EACnD,MAAM,aAAa,KAAK,cAAc,WAAW,OAAO;AACxD,MAAI,cAAc,MAAM;AACtB,YAAS,KACP,kBAAkB;IAChB,SAAS;IACT,UAAU;IACV,YAAY;KACV,aAAa;KACb,uBAAuB,gBAAgB,KAAK;KAC5C,gBAAgB;KACjB;IACF,CAAC,CACH;AACD,UAAO;IAAE,GAAG,OAAO;IAAS;IAAU;;EAGxC,MAAM,eAAe,KAAK,cAAc,aAAa,OAAO;AAC5D,MAAI,gBAAgB,KAClB,UAAS,KACP,kBAAkB;GAChB,SAAS;GACT,UAAU;GACV,YAAY;IACV,aAAa;IACb,uBAAuB,gBAAgB,KAAK;IAC5C,kBAAkB;IACnB;GACF,CAAC,CACH;EAEH,MAAM,eAAe,KAAK,cAAc,aAAa,OAAO;AAC5D,MAAI,gBAAgB,KAClB,UAAS,KACP,kBAAkB;GAChB,SAAS;GACT,UAAU;GACV,YAAY;IACV,aAAa;IACb,uBAAuB,gBAAgB,KAAK;IAC5C,kBAAkB;IACnB;GACF,CAAC,CACH;AAEH,SAAO;GAAE,GAAG,OAAO;GAAS;GAAU;;CAGxC,AAAO,eACL,QACA,eAAiC,EAAE,EAC3B;AACR,SAAO,OAAO,KAAK,cAAc,QAAQ,aAAa,CAAC;;CAGzD,AAAO,kBACL,UACA,YACQ;AACR,MAAI,cAAc,KAChB,QAAO,OAAO,SAAS;AAEzB,SAAO,OACL,kBAAkB;GAChB,SAAS;GACT;GACA,YAAY;IACV,aAAa;IACb,uBACE,KAAK,wBAAwB,CAAC,mBAAmB,cAC7C,KACA;KACL,QAAQ,eAAe;IACzB;GACF,CAAC,CACH;;CAiBH,AAAQ,eACN,MACA,oBACA,oBACA,WACA,WAIY;EACZ,MAAMC,eAA+B;GACnC,MAAM;GACN;GACA;GACA,aAAa,EAAE;GAChB;AACD,MAAI,sBAAsB,KACxB,MAAK,MAAM,QAAQ,KAAK,oBAAoB,uBAAuB,EAAE,CACnE,cAAa,YAAY,KAAK,sBAAsB,KAAK,CAAC;EAG9D,MAAMC,eAA+B;GACnC,MAAM;GACN;GACA;GACA,aAAa,EAAE;GAChB;AACD,MAAI,sBAAsB,KACxB,MAAK,MAAM,QAAQ,KAAK,oBAAoB,uBAAuB,EAAE,CACnE,EAAC,SAAS,YAAY,eAAe,cAAc,YAAY,KAC7D,sBAAsB,KAAK,CAC5B;AAGL,MAAI,SAAS,WAAW;AACtB,OAAI,aAAa,YAAY,SAAS,EACpC,QAAO;AAET;;AAEF,MACE,aAAa,YAAY,WAAW,KACpC,aAAa,YAAY,WAAW,EAEpC;AAEF,SAAO;GAAE;GAAc;GAAc;;CAGvC,AAAQ,aAAa,MAAqC;EACxD,MAAM,EAAE,qBAAqB,KAAK,wBAAwB;AAC1D,SAAO,wBAAwB;GAC7B,YAAY;GACZ,MAAM;GACP,CAAC;;;AAIN,SAAS,uBAAuB,OAAe;AAC7C,QAAO,GAAG,MAAM,kBAAkB,QAAQ,IAAI,MAAM;;AAGtD,SAAS,wBACP,MACA,SACM;AACN,MAAK,MAAM,OAAO,MAAM;AACtB,UAAQ,kBAAkB,KAAK,IAAI,QAAQ;AAC3C,UAAQ,aAAa,WAAW,IAAI,OAAO;AAC3C,UAAQ,kBAAkB,EAAE;;;AAIhC,SAAS,sBACP,MACA,SACA,qBACM;AACN,MAAK,MAAM,EAAE,UAAU,cAAc,MAAM;AACzC,MAAI,YAAY,QAAQ,YAAY,KAClC;EAEF,MAAM,cACJ,YAAY,QAAQ,YAAY,OAC5B,SACA,YAAY,OACV,cACA;AAER,MAAI,eAAe,QAAQ,oBAAoB,SAAS,YACtD,qBAAoB,OAAO;AAG7B,MAAI,YAAY,MAAM;AACpB,WAAQ,oBAAoB,KAAK,SAAS,QAAQ;AAClD,WAAQ,aAAa,aAAa,SAAS,OAAO;;AAGpD,MAAI,YAAY,MAAM;AACpB,WAAQ,oBAAoB,KAAK,SAAS,QAAQ;AAClD,WAAQ,aAAa,aAAa,SAAS,OAAO;;AAGpD,MAAI,eAAe,MAAM;AACvB,uBAAoB,OAAO;AAC3B,uBAAoB,WAAW;;AAGjC,UAAQ,kBAAkB,EAAE;;;AAIhC,SAAS,uBAAuB,EAC9B,WACA,MACA,cACA,cACA,aACA,cACA,cACA,oDACA,WACyB;CACzB,IAAI,mBAAmB;AACvB,KAAI,cAAc,WAAW;AAC3B,MAAI,gBAAgB,KAClB,SAAQ,kBAAkB,KAAK,aAAa;WACnC,gBAAgB,KACzB,SAAQ,kBAAkB,KAAK,aAAa;AAE9C,MAAI,eAAe,MAAM;GACvB,MAAM,WACJ,SAAS,WACL,gBAAgB,OACd,oBACA,oBACF;AACN,WAAQ,kBAAkB,KAAKC,0BAAwB,YAAY,CAAC;AACpE,WAAQ,aACN,WACA,gBAAgB,UAAU,cAAc,EAAE,CAC3C;AACD,sBAAmB;;YAEZ,cAAc,SAAS;AAChC,MAAI,gBAAgB,KAClB,SAAQ,oBAAoB,KAAK,aAAa;AAEhD,MAAI,gBAAgB,KAClB,SAAQ,oBAAoB,KAAK,aAAa;AAEhD,MAAI,gBAAgB,MAAM;GACxB,MAAM,WACJ,SAAS,WACL,gBAAgB,OACd,oBACA,YACF;AACN,WAAQ,oBAAoB,KAAKA,0BAAwB,aAAa,CAAC;AACvE,WAAQ,aACN,aACA,gBAAgB,UAAU,cAAc,EAAE,CAC3C;AACD,sBAAmB;;AAErB,MAAI,gBAAgB,MAAM;GACxB,MAAM,WACJ,SAAS,WACL,gBAAgB,OACd,oBACA,YACF;AACN,WAAQ,oBAAoB,KAAKA,0BAAwB,aAAa,CAAC;AACvE,WAAQ,aACN,aACA,gBAAgB,UAAU,cAAc,EAAE,CAC3C;AACD,sBAAmB;;;AAGvB,KAAI,iBACF,SAAQ,kBAAkB,EAAE;;AAIhC,SAAS,cACP,MACA,EACE,WACA,gBACA,WACA,WACA,aACA,YACA,gBAEF,SACA;AACA,KAAI,kBAAkB,EACpB;CAEF,MAAM,WACJ,SAAS,YACL,QAAQ,oBACR,SAAS,cACP,QAAQ,sBACR,QAAQ;AAEhB,KAAI,QAAQ,mBAAmB,YAAY;AACzC,MAAI,aAAa,MAAM;AACrB,WAAQ,aACN,MACA,gBAAgB;IACd,MAAM;IACN,SAAS;IACT;IACA;IACD,CAAC,CACH;AACD,YAAS,KACP,gBAAgB;IACd,MAAM;IACN,SAAS;IACT;IACA;IACD,CAAC,CACH;AACD,OAAI,SAAS,YACX,SAAQ,kBAAkB,EAAE;;AAGhC;;AAEF,KAAI,QAAQ,mBAAmB,UAAU;AACvC,MAAI,YAAY,GAAG;AACjB,WAAQ,aACN,MACA,gBAAgB;IAAE,MAAM;IAAU;IAAa,YAAY;IAAO,CAAC,CACpE;AACD,YAAS,KACP,gBAAgB;IAAE,MAAM;IAAU;IAAa,YAAY;IAAO,CAAC,CACpE;AACD,OAAI,SAAS,YACX,SAAQ,kBAAkB,EAAE;;AAGhC;;CAEF,MAAM,WAAW,yBAAyB,MAAM,UAAU;CAC1D,MAAM,UAAU,YAAY,QAAQ;CACpC,MAAM,cAAc,eAAe,YAAY;AAC/C,SAAQ,aACN,MACA,gBAAgB;EACd,MAAM,QAAQ;EACd,SAAS,uBAAuB,eAAe;EAC/C;EACA;EACA;EACA;EACA;EACD,CAAC,CACH;AACD,UAAS,KACP,gBAAgB;EACd,MAAM,QAAQ;EACd,SAAS,uBAAuB,eAAe;EAC/C;EACA;EACA;EACA;EACA;EACD,CAAC,CACH;AACD,KAAI,SAAS,YACX,SAAQ,kBAAkB,EAAE;AAE9B,SAAQ,SAAS,KAAK;EACpB;EACA;EACA,OAAO;EACP;EACA,YAAY,eACR;GAAE,IAAI,CAAC;GAAa,MAAM,CAAC;GAAY;GAAS,GAChD;EACL,CAAC;;AAGJ,SAAS,sBACP,UACA,mBAC4B;AAC5B,KACE,YAAY,QACZ,SAAS,SAAS,aAClB,qBAAqB,KAErB,QAAO;AAET,QAAO;EACL,GAAG;EACH,YAAY;GACV,GAAG,SAAS;GACZ,GAAG;GACJ;EACF;;AAGH,SAAS,2BAA2B,UAAoC;CACtE,MAAM,WAAW,SAAS,MAAM,GAAG,GAAG;AACtC,KACE,YAAY,QACZ,SAAS,aACT,SAAS,cAAc,WAAW,KAClC,SAAS,cAAc,WAAW,EAElC,QAAO;CAET,MAAM,oBACJ,SAAS,cAAc,UACtB,SAAS,oBAAoB,SAAS;CACzC,MAAM,oBACJ,SAAS,cAAc,UACtB,SAAS,oBAAoB,SAAS;AACzC,KAAI,sBAAsB,kBACxB,OAAM,IAAI,MACR,6EAA6E,kBAAkB,cAAc,kBAAkB,QAAQ,SAAS,OACjJ;AAEH,QAAO,KAAK,IAAI,mBAAmB,kBAAkB"}
1
+ {"version":3,"file":"DiffHunksRenderer.js","names":["options: DiffHunksRendererOptions","onRenderUpdate?: () => unknown","workerManager?: WorkerPoolManager | undefined","createDefaultAnnotationElement","options: RenderDiffOptions","options","additionsContentAST: ElementContent[] | undefined","deletionsContentAST: ElementContent[] | undefined","unifiedContentAST: ElementContent[] | undefined","hunkData: HunkData[]","context: ProcessContext","pendingSplitContext: PendingSplitContext","renderedLineContext: RenderedLineContext","deletionSpan: AnnotationSpan","additionSpan: AnnotationSpan","createAnnotationElement"],"sources":["../../src/renderers/DiffHunksRenderer.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement, Properties } from 'hast';\nimport { toHtml } from 'hast-util-to-html';\n\nimport {\n DEFAULT_COLLAPSED_CONTEXT_THRESHOLD,\n DEFAULT_EXPANDED_REGION,\n DEFAULT_RENDER_RANGE,\n DEFAULT_THEMES,\n} from '../constants';\nimport { areLanguagesAttached } from '../highlighter/languages/areLanguagesAttached';\nimport {\n getHighlighterIfLoaded,\n getSharedHighlighter,\n} from '../highlighter/shared_highlighter';\nimport { areThemesAttached } from '../highlighter/themes/areThemesAttached';\nimport type {\n AnnotationLineMap,\n AnnotationSpan,\n BaseDiffOptions,\n BaseDiffOptionsWithDefaults,\n CodeColumnType,\n CustomPreProperties,\n DiffLineAnnotation,\n DiffsHighlighter,\n ExpansionDirections,\n FileDiffMetadata,\n FileHeaderRenderMode,\n HunkData,\n HunkExpansionRegion,\n HunkSeparators,\n LineTypes,\n RenderDiffOptions,\n RenderDiffResult,\n RenderedDiffASTCache,\n RenderRange,\n SupportedLanguages,\n ThemedDiffResult,\n} from '../types';\nimport { areDiffRenderOptionsEqual } from '../utils/areDiffRenderOptionsEqual';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { createAnnotationElement as createDefaultAnnotationElement } from '../utils/createAnnotationElement';\nimport { createContentColumn } from '../utils/createContentColumn';\nimport { createEmptyRowBuffer } from '../utils/createEmptyRowBuffer';\nimport { createFileHeaderElement } from '../utils/createFileHeaderElement';\nimport { createNoNewlineElement } from '../utils/createNoNewlineElement';\nimport { createPreElement } from '../utils/createPreElement';\nimport { createSeparator } from '../utils/createSeparator';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport { getHighlighterOptions } from '../utils/getHighlighterOptions';\nimport { getHunkSeparatorSlotName } from '../utils/getHunkSeparatorSlotName';\nimport { getLineAnnotationName } from '../utils/getLineAnnotationName';\nimport { getTotalLineCountFromHunks } from '../utils/getTotalLineCountFromHunks';\nimport {\n createGutterGap,\n createGutterItem,\n createGutterWrapper,\n createHastElement,\n} from '../utils/hast_utils';\nimport { isDefaultRenderRange } from '../utils/isDefaultRenderRange';\nimport { isDiffPlainText } from '../utils/isDiffPlainText';\nimport type { DiffLineMetadata } from '../utils/iterateOverDiff';\nimport { iterateOverDiff } from '../utils/iterateOverDiff';\nimport { renderDiffWithHighlighter } from '../utils/renderDiffWithHighlighter';\nimport { shouldUseTokenTransformer } from '../utils/shouldUseTokenTransformer';\nimport type { WorkerPoolManager } from '../worker';\n\ninterface PushLineWithAnnotation {\n diffStyle: 'unified' | 'split';\n type: 'context' | 'context-expanded' | 'change';\n\n deletionLine?: ElementContent;\n additionLine?: ElementContent;\n\n unifiedSpan?: AnnotationSpan;\n deletionSpan?: AnnotationSpan;\n additionSpan?: AnnotationSpan;\n\n createAnnotationElement(span: AnnotationSpan): HASTElement;\n context: ProcessContext;\n}\n\ninterface GetRenderOptionsReturn {\n options: RenderDiffOptions;\n forceRender: boolean;\n}\n\ninterface PushSeparatorProps {\n hunkIndex: number;\n collapsedLines: number;\n rangeSize: number;\n hunkSpecs: string | undefined;\n isFirstHunk: boolean;\n isLastHunk: boolean;\n isExpandable: boolean;\n}\n\ninterface ProcessContext {\n rowCount: number;\n expansionLineCount: number;\n hunkSeparators: HunkSeparators;\n unifiedContentAST: ElementContent[];\n deletionsContentAST: ElementContent[];\n additionsContentAST: ElementContent[];\n unifiedGutterAST: HASTElement;\n deletionsGutterAST: HASTElement;\n additionsGutterAST: HASTElement;\n hunkData: HunkData[];\n pushToGutter(type: CodeColumnType, element: HASTElement): void;\n incrementRowCount(count?: number): void;\n}\n\nexport interface DiffHunksRendererOptions extends BaseDiffOptions {\n headerRenderMode?: FileHeaderRenderMode;\n}\n\nexport interface DiffHunksRendererOptionsWithDefaults extends Omit<\n BaseDiffOptionsWithDefaults,\n 'themeType'\n> {\n headerRenderMode: FileHeaderRenderMode;\n}\n\nexport interface UnifiedLineDecorationProps {\n type: 'context' | 'context-expanded' | 'change';\n lineType: LineTypes;\n additionLineIndex: number | undefined;\n deletionLineIndex: number | undefined;\n}\n\nexport interface SplitLineDecorationProps {\n side: 'deletions' | 'additions';\n type: 'context' | 'context-expanded' | 'change';\n lineIndex: number | undefined;\n}\n\nexport interface LineDecoration {\n gutterLineType: LineTypes;\n gutterProperties?: Properties;\n contentProperties?: Properties;\n}\n\ninterface PendingSplitContext {\n size: number;\n side: 'additions' | 'deletions' | undefined;\n increment(): void;\n flush(): void;\n}\n\nexport interface RenderedLineContext {\n type: 'context' | 'context-expanded' | 'change';\n hunkIndex: number;\n lineIndex: number;\n unifiedLineIndex: number;\n splitLineIndex: number;\n deletionLine?: DiffLineMetadata;\n additionLine?: DiffLineMetadata;\n}\n\nexport interface InjectedRow {\n content: HASTElement;\n gutter: HASTElement;\n}\n\nexport interface SplitInjectedRow {\n deletion: InjectedRow | undefined;\n addition: InjectedRow | undefined;\n}\n\nexport interface UnifiedInjectedRowPlacement {\n before?: InjectedRow[];\n after?: InjectedRow[];\n}\n\nexport interface SplitInjectedRowPlacement {\n before?: SplitInjectedRow[];\n after?: SplitInjectedRow[];\n}\n\nexport interface HunksRenderResult {\n unifiedGutterAST: ElementContent[] | undefined;\n unifiedContentAST: ElementContent[] | undefined;\n deletionsGutterAST: ElementContent[] | undefined;\n deletionsContentAST: ElementContent[] | undefined;\n additionsGutterAST: ElementContent[] | undefined;\n additionsContentAST: ElementContent[] | undefined;\n hunkData: HunkData[];\n css: string;\n preNode: HASTElement;\n headerElement: HASTElement | undefined;\n totalLines: number;\n themeStyles: string;\n baseThemeType: 'light' | 'dark' | undefined;\n rowCount: number;\n bufferBefore: number;\n bufferAfter: number;\n}\n\nlet instanceId = -1;\n\nexport class DiffHunksRenderer<LAnnotation = undefined> {\n readonly __id: string = `diff-hunks-renderer:${++instanceId}`;\n\n private highlighter: DiffsHighlighter | undefined;\n private diff: FileDiffMetadata | undefined;\n\n private expandedHunks = new Map<number, HunkExpansionRegion>();\n\n private deletionAnnotations: AnnotationLineMap<LAnnotation> = {};\n private additionAnnotations: AnnotationLineMap<LAnnotation> = {};\n\n private computedLang: SupportedLanguages = 'text';\n private renderCache: RenderedDiffASTCache | undefined;\n\n constructor(\n public options: DiffHunksRendererOptions = { theme: DEFAULT_THEMES },\n private onRenderUpdate?: () => unknown,\n private workerManager?: WorkerPoolManager | undefined\n ) {\n if (workerManager?.isWorkingPool() !== true) {\n this.highlighter = areThemesAttached(options.theme ?? DEFAULT_THEMES)\n ? getHighlighterIfLoaded()\n : undefined;\n }\n }\n\n public cleanUp(): void {\n this.highlighter = undefined;\n this.diff = undefined;\n this.renderCache = undefined;\n this.workerManager?.cleanUpPendingTasks(this);\n this.workerManager = undefined;\n this.onRenderUpdate = undefined;\n }\n\n public recycle(): void {\n this.highlighter = undefined;\n this.diff = undefined;\n this.renderCache = undefined;\n this.workerManager?.cleanUpPendingTasks(this);\n }\n\n public setOptions(options: DiffHunksRendererOptions): void {\n this.options = options;\n }\n\n public mergeOptions(options: Partial<DiffHunksRendererOptions>): void {\n this.options = { ...this.options, ...options };\n }\n\n public expandHunk(\n index: number,\n direction: ExpansionDirections,\n expansionLineCount: number = this.getOptionsWithDefaults()\n .expansionLineCount\n ): void {\n const region = {\n ...(this.expandedHunks.get(index) ?? {\n fromStart: 0,\n fromEnd: 0,\n }),\n };\n if (direction === 'up' || direction === 'both') {\n region.fromStart += expansionLineCount;\n }\n if (direction === 'down' || direction === 'both') {\n region.fromEnd += expansionLineCount;\n }\n // NOTE(amadeus): If our render cache is not highlighted, we need to clear\n // it, otherwise we won't have the correct AST lines\n if (this.renderCache?.highlighted !== true) {\n this.renderCache = undefined;\n }\n this.expandedHunks.set(index, region);\n }\n\n public getExpandedHunk(hunkIndex: number): HunkExpansionRegion {\n return this.expandedHunks.get(hunkIndex) ?? DEFAULT_EXPANDED_REGION;\n }\n\n public getExpandedHunksMap(): Map<number, HunkExpansionRegion> {\n return this.expandedHunks;\n }\n\n public setLineAnnotations(\n lineAnnotations: DiffLineAnnotation<LAnnotation>[]\n ): void {\n this.additionAnnotations = {};\n this.deletionAnnotations = {};\n for (const annotation of lineAnnotations) {\n const map = ((): AnnotationLineMap<LAnnotation> => {\n switch (annotation.side) {\n case 'deletions':\n return this.deletionAnnotations;\n case 'additions':\n return this.additionAnnotations;\n }\n })();\n const arr = map[annotation.lineNumber] ?? [];\n map[annotation.lineNumber] = arr;\n arr.push(annotation);\n }\n }\n\n protected getUnifiedLineDecoration({\n lineType,\n }: UnifiedLineDecorationProps): LineDecoration {\n return { gutterLineType: lineType };\n }\n\n protected getSplitLineDecoration({\n side,\n type,\n }: SplitLineDecorationProps): LineDecoration {\n if (type !== 'change') {\n return { gutterLineType: type };\n }\n return {\n gutterLineType:\n side === 'deletions' ? 'change-deletion' : 'change-addition',\n };\n }\n\n protected createAnnotationElement(span: AnnotationSpan): HASTElement {\n return createDefaultAnnotationElement(span);\n }\n\n // Unified hook returns extra rows that render before/after the current line.\n declare protected getUnifiedInjectedRowsForLine?: (\n ctx: RenderedLineContext\n ) => UnifiedInjectedRowPlacement | undefined;\n\n // Split hook returns extra rows per side before/after the current line.\n declare protected getSplitInjectedRowsForLine?: (\n ctx: RenderedLineContext\n ) => SplitInjectedRowPlacement | undefined;\n\n protected getOptionsWithDefaults(): DiffHunksRendererOptionsWithDefaults {\n const {\n diffIndicators = 'bars',\n diffStyle = 'split',\n disableBackground = false,\n disableFileHeader = false,\n disableLineNumbers = false,\n disableVirtualizationBuffers = false,\n collapsed = false,\n expandUnchanged = false,\n collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD,\n expansionLineCount = 100,\n hunkSeparators = 'line-info',\n lineDiffType = 'word-alt',\n maxLineDiffLength = 1000,\n overflow = 'scroll',\n theme = DEFAULT_THEMES,\n headerRenderMode = 'default',\n tokenizeMaxLineLength = 1000,\n useTokenTransformer = false,\n useCSSClasses = false,\n } = this.options;\n return {\n diffIndicators,\n diffStyle,\n disableBackground,\n disableFileHeader,\n disableLineNumbers,\n disableVirtualizationBuffers,\n collapsed,\n expandUnchanged,\n collapsedContextThreshold,\n expansionLineCount,\n hunkSeparators,\n lineDiffType,\n maxLineDiffLength,\n overflow,\n theme: this.workerManager?.getDiffRenderOptions().theme ?? theme,\n headerRenderMode,\n tokenizeMaxLineLength,\n useTokenTransformer,\n useCSSClasses,\n };\n }\n\n private async initializeHighlighter(): Promise<DiffsHighlighter> {\n this.highlighter = await getSharedHighlighter(\n getHighlighterOptions(this.computedLang, this.options)\n );\n return this.highlighter;\n }\n\n public hydrate(diff: FileDiffMetadata | undefined): void {\n if (diff == null) {\n return;\n }\n this.diff = diff;\n const { options } = this.getRenderOptions(diff);\n let cache = this.workerManager?.getDiffResultCache(diff);\n if (cache != null && !areDiffRenderOptionsEqual(options, cache.options)) {\n cache = undefined;\n }\n this.renderCache ??= {\n diff,\n highlighted: !isDiffPlainText(diff),\n options,\n result: cache?.result,\n renderRange: undefined,\n };\n if (this.workerManager?.isWorkingPool() === true) {\n if (this.renderCache.result == null) {\n // We should only kick off a preload of the AST if we have a WorkerPool\n this.workerManager.highlightDiffAST(this, this.diff);\n }\n }\n // Lets attempt to get the highlighter/languages ready immediately\n else if (this.highlighter == null) {\n this.computedLang = diff.lang ?? getFiletypeFromFileName(diff.name);\n void this.initializeHighlighter();\n }\n }\n\n private getRenderOptions(diff: FileDiffMetadata): GetRenderOptionsReturn {\n const options: RenderDiffOptions = (() => {\n if (this.workerManager?.isWorkingPool() === true) {\n return this.workerManager.getDiffRenderOptions();\n }\n const { theme, tokenizeMaxLineLength, lineDiffType, maxLineDiffLength } =\n this.getOptionsWithDefaults();\n return {\n theme,\n useTokenTransformer: shouldUseTokenTransformer(this.options),\n tokenizeMaxLineLength,\n lineDiffType,\n maxLineDiffLength,\n };\n })();\n this.getOptionsWithDefaults();\n const { renderCache } = this;\n if (renderCache?.result == null) {\n return { options, forceRender: true };\n }\n if (\n diff !== renderCache.diff ||\n !areDiffRenderOptionsEqual(options, renderCache.options)\n ) {\n return { options, forceRender: true };\n }\n return { options, forceRender: false };\n }\n\n public renderDiff(\n diff: FileDiffMetadata | undefined = this.renderCache?.diff,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): HunksRenderResult | undefined {\n if (diff == null) {\n return undefined;\n }\n const { expandUnchanged = false, collapsedContextThreshold } =\n this.getOptionsWithDefaults();\n const cache = this.workerManager?.getDiffResultCache(diff);\n if (cache != null && this.renderCache == null) {\n this.renderCache = {\n diff,\n highlighted: true,\n renderRange: undefined,\n ...cache,\n };\n }\n const { options, forceRender } = this.getRenderOptions(diff);\n this.renderCache ??= {\n diff,\n highlighted: false,\n options,\n result: undefined,\n renderRange: undefined,\n };\n if (this.workerManager?.isWorkingPool() === true) {\n if (\n this.renderCache.result == null ||\n (!this.renderCache.highlighted &&\n (diff !== this.renderCache.diff ||\n !areRenderRangesEqual(this.renderCache.renderRange, renderRange)))\n ) {\n this.renderCache.diff = diff;\n this.renderCache.result = this.workerManager.getPlainDiffAST(\n diff,\n renderRange.startingLine,\n renderRange.totalLines,\n // If we aren't using a windowed render, then we need to render\n // everything\n isDefaultRenderRange(renderRange)\n ? true\n : expandUnchanged\n ? true\n : this.expandedHunks,\n collapsedContextThreshold\n );\n this.renderCache.renderRange = renderRange;\n }\n if (\n // We should only attempt to kick off the worker highlighter if there\n // are lines to render\n renderRange.totalLines > 0 &&\n (!this.renderCache.highlighted || forceRender)\n ) {\n this.workerManager.highlightDiffAST(this, diff);\n }\n } else {\n this.computedLang = diff.lang ?? getFiletypeFromFileName(diff.name);\n const hasThemes =\n this.highlighter != null && areThemesAttached(options.theme);\n const hasLangs =\n this.highlighter != null && areLanguagesAttached(this.computedLang);\n\n // If we have any semblance of a highlighter with the correct theme(s)\n // attached, we can kick off some form of rendering. If we don't have\n // the correct language, then we can render plain text and after kick off\n // an async job to get the highlighted AST\n if (\n this.highlighter != null &&\n hasThemes &&\n (forceRender ||\n (!this.renderCache.highlighted && hasLangs) ||\n this.renderCache.result == null)\n ) {\n const { result, options } = this.renderDiffWithHighlighter(\n diff,\n this.highlighter,\n !hasLangs\n );\n this.renderCache = {\n diff,\n options,\n highlighted: hasLangs,\n result,\n renderRange: undefined,\n };\n }\n\n // If we get in here it means we'll have to kick off an async highlight\n // process which will involve initializing the highlighter with new themes\n // and languages\n if (!hasThemes || !hasLangs) {\n void this.asyncHighlight(diff).then(({ result, options }) => {\n // In this case we need to force a re-render, so we can do that by\n // reaching into renderCache\n if (this.renderCache != null) {\n this.renderCache.highlighted = false;\n }\n this.onHighlightSuccess(diff, result, options);\n });\n }\n }\n return this.renderCache.result != null\n ? this.processDiffResult(\n this.renderCache.diff,\n renderRange,\n this.renderCache.result\n )\n : undefined;\n }\n\n public async asyncRender(\n diff: FileDiffMetadata,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): Promise<HunksRenderResult> {\n const { result } = await this.asyncHighlight(diff);\n return this.processDiffResult(diff, renderRange, result);\n }\n\n protected createPreElement(\n split: boolean,\n totalLines: number,\n customProperties?: CustomPreProperties\n ): HASTElement {\n const { diffIndicators, disableBackground, disableLineNumbers, overflow } =\n this.getOptionsWithDefaults();\n return createPreElement({\n type: 'diff',\n diffIndicators,\n disableBackground,\n disableLineNumbers,\n overflow,\n split,\n totalLines,\n customProperties,\n });\n }\n\n private async asyncHighlight(\n diff: FileDiffMetadata\n ): Promise<RenderDiffResult> {\n this.computedLang = diff.lang ?? getFiletypeFromFileName(diff.name);\n const hasThemes =\n this.highlighter != null &&\n areThemesAttached(this.options.theme ?? DEFAULT_THEMES);\n const hasLangs =\n this.highlighter != null && areLanguagesAttached(this.computedLang);\n // If we don't have the required langs or themes, then we need to\n // initialize the highlighter to load the appropriate languages and themes\n if (this.highlighter == null || !hasThemes || !hasLangs) {\n this.highlighter = await this.initializeHighlighter();\n }\n return this.renderDiffWithHighlighter(diff, this.highlighter);\n }\n\n private renderDiffWithHighlighter(\n diff: FileDiffMetadata,\n highlighter: DiffsHighlighter,\n forcePlainText = false\n ): RenderDiffResult {\n const { options } = this.getRenderOptions(diff);\n const { collapsedContextThreshold } = this.getOptionsWithDefaults();\n const result = renderDiffWithHighlighter(diff, highlighter, options, {\n forcePlainText,\n expandedHunks: forcePlainText ? true : undefined,\n collapsedContextThreshold,\n });\n return { result, options };\n }\n\n public onHighlightSuccess(\n diff: FileDiffMetadata,\n result: ThemedDiffResult,\n options: RenderDiffOptions\n ): void {\n // NOTE(amadeus): This is a bad assumption, and I should figure out\n // something better...\n // If renderCache was blown away, we can assume we've run cleanUp()\n if (this.renderCache == null) {\n return;\n }\n\n const triggerRenderUpdate =\n !this.renderCache.highlighted ||\n !areDiffRenderOptionsEqual(this.renderCache.options, options) ||\n this.renderCache.diff !== diff;\n\n this.renderCache = {\n diff,\n options,\n highlighted: true,\n result,\n renderRange: undefined,\n };\n if (triggerRenderUpdate) {\n this.onRenderUpdate?.();\n }\n }\n\n public onHighlightError(error: unknown): void {\n console.error(error);\n }\n\n private processDiffResult(\n fileDiff: FileDiffMetadata,\n renderRange: RenderRange,\n { code, themeStyles, baseThemeType }: ThemedDiffResult\n ): HunksRenderResult {\n const {\n diffStyle,\n disableFileHeader,\n expandUnchanged,\n expansionLineCount,\n collapsedContextThreshold,\n hunkSeparators,\n } = this.getOptionsWithDefaults();\n\n this.diff = fileDiff;\n const unified = diffStyle === 'unified';\n\n let additionsContentAST: ElementContent[] | undefined = [];\n let deletionsContentAST: ElementContent[] | undefined = [];\n let unifiedContentAST: ElementContent[] | undefined = [];\n\n const hunkData: HunkData[] = [];\n const { additionLines, deletionLines } = code;\n const context: ProcessContext = {\n rowCount: 0,\n hunkSeparators,\n additionsContentAST,\n deletionsContentAST,\n unifiedContentAST,\n unifiedGutterAST: createGutterWrapper(),\n deletionsGutterAST: createGutterWrapper(),\n additionsGutterAST: createGutterWrapper(),\n expansionLineCount,\n hunkData,\n incrementRowCount(count = 1) {\n context.rowCount += count;\n },\n pushToGutter(type: CodeColumnType, element: HASTElement) {\n switch (type) {\n case 'unified': {\n context.unifiedGutterAST.children.push(element);\n break;\n }\n case 'deletions': {\n context.deletionsGutterAST.children.push(element);\n break;\n }\n case 'additions': {\n context.additionsGutterAST.children.push(element);\n break;\n }\n }\n },\n };\n const trailingRangeSize = calculateTrailingRangeSize(fileDiff);\n const pendingSplitContext: PendingSplitContext = {\n size: 0,\n side: undefined,\n increment() {\n this.size += 1;\n },\n flush() {\n if (diffStyle === 'unified') {\n return;\n }\n if (this.size <= 0 || this.side == null) {\n this.side = undefined;\n this.size = 0;\n return;\n }\n if (this.side === 'additions') {\n context.pushToGutter(\n 'additions',\n createGutterGap(undefined, 'buffer', this.size)\n );\n additionsContentAST?.push(createEmptyRowBuffer(this.size));\n } else {\n context.pushToGutter(\n 'deletions',\n createGutterGap(undefined, 'buffer', this.size)\n );\n deletionsContentAST?.push(createEmptyRowBuffer(this.size));\n }\n this.size = 0;\n this.side = undefined;\n },\n };\n\n const pushGutterLineNumber = (\n type: CodeColumnType,\n lineType: LineTypes | 'buffer' | 'separator' | 'annotation',\n lineNumber: number,\n lineIndex: string,\n gutterProperties: Properties | undefined\n ) => {\n context.pushToGutter(\n type,\n createGutterItem(lineType, lineNumber, lineIndex, gutterProperties)\n );\n };\n\n function pushSeparators(props: PushSeparatorProps) {\n pendingSplitContext.flush();\n if (diffStyle === 'unified') {\n pushSeparator('unified', props, context);\n } else {\n pushSeparator('deletions', props, context);\n pushSeparator('additions', props, context);\n }\n }\n\n iterateOverDiff({\n diff: fileDiff,\n diffStyle,\n startingLine: renderRange.startingLine,\n totalLines: renderRange.totalLines,\n expandedHunks: expandUnchanged ? true : this.expandedHunks,\n collapsedContextThreshold,\n callback: ({\n hunkIndex,\n hunk,\n collapsedBefore,\n collapsedAfter,\n additionLine,\n deletionLine,\n type,\n }) => {\n const splitLineIndex =\n deletionLine != null\n ? deletionLine.splitLineIndex\n : additionLine.splitLineIndex;\n const unifiedLineIndex =\n additionLine != null\n ? additionLine.unifiedLineIndex\n : deletionLine.unifiedLineIndex;\n\n if (diffStyle === 'split' && type !== 'change') {\n pendingSplitContext.flush();\n }\n\n if (collapsedBefore > 0) {\n pushSeparators({\n hunkIndex,\n collapsedLines: collapsedBefore,\n rangeSize: Math.max(hunk?.collapsedBefore ?? 0, 0),\n hunkSpecs: hunk?.hunkSpecs,\n isFirstHunk: hunkIndex === 0,\n isLastHunk: false,\n isExpandable: !fileDiff.isPartial,\n });\n }\n\n const lineIndex =\n diffStyle === 'unified' ? unifiedLineIndex : splitLineIndex;\n const renderedLineContext: RenderedLineContext = {\n type,\n hunkIndex,\n lineIndex,\n unifiedLineIndex,\n splitLineIndex,\n deletionLine,\n additionLine,\n };\n\n if (diffStyle === 'unified') {\n const injectedRows =\n this.getUnifiedInjectedRowsForLine?.(renderedLineContext);\n if (injectedRows?.before != null) {\n pushUnifiedInjectedRows(injectedRows.before, context);\n }\n let deletionLineContent =\n deletionLine != null\n ? deletionLines[deletionLine.lineIndex]\n : undefined;\n let additionLineContent =\n additionLine != null\n ? additionLines[additionLine.lineIndex]\n : undefined;\n if (deletionLineContent == null && additionLineContent == null) {\n const errorMessage =\n 'DiffHunksRenderer.processDiffResult: deletionLine and additionLine are null, something is wrong';\n console.error(errorMessage, { file: fileDiff.name });\n throw new Error(errorMessage);\n }\n const lineType =\n type === 'change'\n ? additionLine != null\n ? 'change-addition'\n : 'change-deletion'\n : type;\n const lineDecoration = this.getUnifiedLineDecoration({\n // NOTE: This function gets extended so don't remove\n // these extra props\n type,\n lineType,\n additionLineIndex: additionLine?.lineIndex,\n deletionLineIndex: deletionLine?.lineIndex,\n });\n pushGutterLineNumber(\n 'unified',\n lineDecoration.gutterLineType,\n additionLine != null\n ? additionLine.lineNumber\n : deletionLine.lineNumber,\n `${unifiedLineIndex},${splitLineIndex}`,\n lineDecoration.gutterProperties\n );\n if (additionLineContent != null) {\n additionLineContent = withContentProperties(\n additionLineContent,\n lineDecoration.contentProperties\n );\n } else if (deletionLineContent != null) {\n deletionLineContent = withContentProperties(\n deletionLineContent,\n lineDecoration.contentProperties\n );\n }\n pushLineWithAnnotation({\n diffStyle: 'unified',\n type: type,\n deletionLine: deletionLineContent,\n additionLine: additionLineContent,\n unifiedSpan: this.getAnnotations(\n 'unified',\n deletionLine?.lineNumber,\n additionLine?.lineNumber,\n hunkIndex,\n lineIndex\n ),\n createAnnotationElement: (span) =>\n this.createAnnotationElement(span),\n context,\n });\n if (injectedRows?.after != null) {\n pushUnifiedInjectedRows(injectedRows.after, context);\n }\n } else {\n const injectedRows =\n this.getSplitInjectedRowsForLine?.(renderedLineContext);\n if (injectedRows?.before != null) {\n pushSplitInjectedRows(\n injectedRows.before,\n context,\n pendingSplitContext\n );\n }\n\n let deletionLineContent =\n deletionLine != null\n ? deletionLines[deletionLine.lineIndex]\n : undefined;\n let additionLineContent =\n additionLine != null\n ? additionLines[additionLine.lineIndex]\n : undefined;\n const deletionLineDecoration = this.getSplitLineDecoration({\n side: 'deletions',\n type,\n lineIndex: deletionLine?.lineIndex,\n });\n const additionLineDecoration = this.getSplitLineDecoration({\n side: 'additions',\n type,\n lineIndex: additionLine?.lineIndex,\n });\n\n if (deletionLineContent == null && additionLineContent == null) {\n const errorMessage =\n 'DiffHunksRenderer.processDiffResult: deletionLine and additionLine are null, something is wrong';\n console.error(errorMessage, { file: fileDiff.name });\n throw new Error(errorMessage);\n }\n\n const missingSide = (() => {\n if (type === 'change') {\n if (additionLineContent == null) {\n return 'additions';\n } else if (deletionLineContent == null) {\n return 'deletions';\n }\n }\n return undefined;\n })();\n if (missingSide != null) {\n if (\n pendingSplitContext.side != null &&\n pendingSplitContext.side !== missingSide\n ) {\n // NOTE(amadeus): If we see this error, we might need to bring back: flushSplitSpan();\n throw new Error(\n 'DiffHunksRenderer.processDiffResult: iterateOverDiff, invalid pending splits'\n );\n }\n pendingSplitContext.side = missingSide;\n pendingSplitContext.increment();\n }\n\n const annotationSpans = this.getAnnotations(\n 'split',\n deletionLine?.lineNumber,\n additionLine?.lineNumber,\n hunkIndex,\n lineIndex\n );\n if (annotationSpans != null && pendingSplitContext.size > 0) {\n pendingSplitContext.flush();\n }\n\n if (deletionLine != null) {\n const deletionLineDecorated = withContentProperties(\n deletionLineContent,\n deletionLineDecoration.contentProperties\n );\n pushGutterLineNumber(\n 'deletions',\n deletionLineDecoration.gutterLineType,\n deletionLine.lineNumber,\n `${deletionLine.unifiedLineIndex},${splitLineIndex}`,\n deletionLineDecoration.gutterProperties\n );\n if (deletionLineDecorated != null) {\n deletionLineContent = deletionLineDecorated;\n }\n }\n if (additionLine != null) {\n const additionLineDecorated = withContentProperties(\n additionLineContent,\n additionLineDecoration.contentProperties\n );\n pushGutterLineNumber(\n 'additions',\n additionLineDecoration.gutterLineType,\n additionLine.lineNumber,\n `${additionLine.unifiedLineIndex},${splitLineIndex}`,\n additionLineDecoration.gutterProperties\n );\n if (additionLineDecorated != null) {\n additionLineContent = additionLineDecorated;\n }\n }\n pushLineWithAnnotation({\n diffStyle: 'split',\n type: type,\n additionLine: additionLineContent,\n deletionLine: deletionLineContent,\n ...annotationSpans,\n createAnnotationElement: (span) =>\n this.createAnnotationElement(span),\n context,\n });\n if (injectedRows?.after != null) {\n pushSplitInjectedRows(\n injectedRows.after,\n context,\n pendingSplitContext\n );\n }\n }\n\n const noEOFCRDeletion = deletionLine?.noEOFCR ?? false;\n const noEOFCRAddition = additionLine?.noEOFCR ?? false;\n if (noEOFCRAddition || noEOFCRDeletion) {\n if (noEOFCRDeletion) {\n const noEOFType =\n type === 'context' || type === 'context-expanded'\n ? type\n : 'change-deletion';\n if (diffStyle === 'unified') {\n context.unifiedContentAST.push(createNoNewlineElement(noEOFType));\n context.pushToGutter(\n 'unified',\n createGutterGap(noEOFType, 'metadata', 1)\n );\n } else {\n context.deletionsContentAST.push(\n createNoNewlineElement(noEOFType)\n );\n context.pushToGutter(\n 'deletions',\n createGutterGap(noEOFType, 'metadata', 1)\n );\n if (!noEOFCRAddition) {\n context.pushToGutter(\n 'additions',\n createGutterGap(undefined, 'buffer', 1)\n );\n context.additionsContentAST.push(createEmptyRowBuffer(1));\n }\n }\n }\n if (noEOFCRAddition) {\n const noEOFType =\n type === 'context' || type === 'context-expanded'\n ? type\n : 'change-addition';\n if (diffStyle === 'unified') {\n context.unifiedContentAST.push(createNoNewlineElement(noEOFType));\n context.pushToGutter(\n 'unified',\n createGutterGap(noEOFType, 'metadata', 1)\n );\n } else {\n context.additionsContentAST.push(\n createNoNewlineElement(noEOFType)\n );\n context.pushToGutter(\n 'additions',\n createGutterGap(noEOFType, 'metadata', 1)\n );\n if (!noEOFCRDeletion) {\n context.pushToGutter(\n 'deletions',\n createGutterGap(undefined, 'buffer', 1)\n );\n context.deletionsContentAST.push(createEmptyRowBuffer(1));\n }\n }\n }\n context.incrementRowCount(1);\n }\n\n if (collapsedAfter > 0 && hunkSeparators !== 'simple') {\n pushSeparators({\n hunkIndex: type === 'context-expanded' ? hunkIndex : hunkIndex + 1,\n collapsedLines: collapsedAfter,\n rangeSize: trailingRangeSize,\n hunkSpecs: undefined,\n isFirstHunk: false,\n isLastHunk: true,\n isExpandable: !fileDiff.isPartial,\n });\n }\n context.incrementRowCount(1);\n },\n });\n\n if (diffStyle === 'split') {\n pendingSplitContext.flush();\n }\n\n const totalLines = Math.max(\n getTotalLineCountFromHunks(fileDiff.hunks),\n fileDiff.additionLines.length ?? 0,\n fileDiff.deletionLines.length ?? 0\n );\n\n const hasBuffer =\n renderRange.bufferBefore > 0 || renderRange.bufferAfter > 0;\n // Determine which ASTs to include based on diff style and file type\n const shouldIncludeAdditions = !unified && fileDiff.type !== 'deleted';\n const shouldIncludeDeletions = !unified && fileDiff.type !== 'new';\n const hasContent = context.rowCount > 0 || hasBuffer;\n\n additionsContentAST =\n shouldIncludeAdditions && hasContent ? additionsContentAST : undefined;\n deletionsContentAST =\n shouldIncludeDeletions && hasContent ? deletionsContentAST : undefined;\n unifiedContentAST = unified && hasContent ? unifiedContentAST : undefined;\n\n const preNode = this.createPreElement(\n deletionsContentAST != null && additionsContentAST != null,\n totalLines\n );\n\n return {\n unifiedGutterAST:\n unified && hasContent ? context.unifiedGutterAST.children : undefined,\n unifiedContentAST,\n deletionsGutterAST:\n shouldIncludeDeletions && hasContent\n ? context.deletionsGutterAST.children\n : undefined,\n deletionsContentAST,\n additionsGutterAST:\n shouldIncludeAdditions && hasContent\n ? context.additionsGutterAST.children\n : undefined,\n additionsContentAST,\n hunkData,\n preNode,\n themeStyles,\n baseThemeType,\n headerElement: !disableFileHeader\n ? this.renderHeader(this.diff)\n : undefined,\n totalLines,\n rowCount: context.rowCount,\n bufferBefore: renderRange.bufferBefore,\n bufferAfter: renderRange.bufferAfter,\n // FIXME\n css: '',\n };\n }\n\n public renderCodeAST(\n type: 'unified' | 'deletions' | 'additions',\n result: HunksRenderResult\n ): ElementContent[] | undefined {\n const gutterAST =\n type === 'unified'\n ? result.unifiedGutterAST\n : type === 'deletions'\n ? result.deletionsGutterAST\n : result.additionsGutterAST;\n\n const contentAST =\n type === 'unified'\n ? result.unifiedContentAST\n : type === 'deletions'\n ? result.deletionsContentAST\n : result.additionsContentAST;\n\n if (gutterAST == null || contentAST == null) {\n return undefined;\n }\n\n const gutter = createGutterWrapper(gutterAST);\n gutter.properties.style = `grid-row: span ${result.rowCount}`;\n const contentColumn = createContentColumn(contentAST, result.rowCount);\n return [gutter, contentColumn];\n }\n\n public renderFullAST(\n result: HunksRenderResult,\n children: ElementContent[] = []\n ): HASTElement {\n const containerSize =\n this.getOptionsWithDefaults().hunkSeparators === 'line-info';\n const unifiedAST = this.renderCodeAST('unified', result);\n if (unifiedAST != null) {\n children.push(\n createHastElement({\n tagName: 'code',\n children: unifiedAST,\n properties: {\n 'data-code': '',\n 'data-container-size': containerSize ? '' : undefined,\n 'data-unified': '',\n },\n })\n );\n return { ...result.preNode, children };\n }\n\n const deletionsAST = this.renderCodeAST('deletions', result);\n if (deletionsAST != null) {\n children.push(\n createHastElement({\n tagName: 'code',\n children: deletionsAST,\n properties: {\n 'data-code': '',\n 'data-container-size': containerSize ? '' : undefined,\n 'data-deletions': '',\n },\n })\n );\n }\n const additionsAST = this.renderCodeAST('additions', result);\n if (additionsAST != null) {\n children.push(\n createHastElement({\n tagName: 'code',\n children: additionsAST,\n properties: {\n 'data-code': '',\n 'data-container-size': containerSize ? '' : undefined,\n 'data-additions': '',\n },\n })\n );\n }\n return { ...result.preNode, children };\n }\n\n public renderFullHTML(\n result: HunksRenderResult,\n tempChildren: ElementContent[] = []\n ): string {\n return toHtml(this.renderFullAST(result, tempChildren));\n }\n\n public renderPartialHTML(\n children: ElementContent[],\n columnType?: 'unified' | 'deletions' | 'additions'\n ): string {\n if (columnType == null) {\n return toHtml(children);\n }\n return toHtml(\n createHastElement({\n tagName: 'code',\n children,\n properties: {\n 'data-code': '',\n 'data-container-size':\n this.getOptionsWithDefaults().hunkSeparators === 'line-info'\n ? ''\n : undefined,\n [`data-${columnType}`]: '',\n },\n })\n );\n }\n\n private getAnnotations(\n type: 'unified',\n deletionLineNumber: number | undefined,\n additionLineNumber: number | undefined,\n hunkIndex: number,\n lineIndex: number\n ): AnnotationSpan | undefined;\n private getAnnotations(\n type: 'split',\n deletionLineNumber: number | undefined,\n additionLineNumber: number | undefined,\n hunkIndex: number,\n lineIndex: number\n ): { deletionSpan: AnnotationSpan; additionSpan: AnnotationSpan } | undefined;\n private getAnnotations(\n type: 'unified' | 'split',\n deletionLineNumber: number | undefined,\n additionLineNumber: number | undefined,\n hunkIndex: number,\n lineIndex: number\n ):\n | AnnotationSpan\n | { deletionSpan: AnnotationSpan; additionSpan: AnnotationSpan }\n | undefined {\n const deletionSpan: AnnotationSpan = {\n type: 'annotation',\n hunkIndex,\n lineIndex,\n annotations: [],\n };\n if (deletionLineNumber != null) {\n for (const anno of this.deletionAnnotations[deletionLineNumber] ?? []) {\n deletionSpan.annotations.push(getLineAnnotationName(anno));\n }\n }\n const additionSpan: AnnotationSpan = {\n type: 'annotation',\n hunkIndex,\n lineIndex,\n annotations: [],\n };\n if (additionLineNumber != null) {\n for (const anno of this.additionAnnotations[additionLineNumber] ?? []) {\n (type === 'unified' ? deletionSpan : additionSpan).annotations.push(\n getLineAnnotationName(anno)\n );\n }\n }\n if (type === 'unified') {\n if (deletionSpan.annotations.length > 0) {\n return deletionSpan;\n }\n return undefined;\n }\n if (\n additionSpan.annotations.length === 0 &&\n deletionSpan.annotations.length === 0\n ) {\n return undefined;\n }\n return { deletionSpan, additionSpan };\n }\n\n private renderHeader(diff: FileDiffMetadata): HASTElement {\n const { headerRenderMode } = this.getOptionsWithDefaults();\n return createFileHeaderElement({\n fileOrDiff: diff,\n mode: headerRenderMode,\n });\n }\n}\n\nfunction getModifiedLinesString(lines: number) {\n return `${lines} unmodified line${lines > 1 ? 's' : ''}`;\n}\n\nfunction pushUnifiedInjectedRows(\n rows: InjectedRow[],\n context: ProcessContext\n): void {\n for (const row of rows) {\n context.unifiedContentAST.push(row.content);\n context.pushToGutter('unified', row.gutter);\n context.incrementRowCount(1);\n }\n}\n\nfunction pushSplitInjectedRows(\n rows: SplitInjectedRow[],\n context: ProcessContext,\n pendingSplitContext: PendingSplitContext\n): void {\n for (const { deletion, addition } of rows) {\n if (deletion == null && addition == null) {\n continue;\n }\n const missingSide =\n deletion != null && addition != null\n ? undefined\n : deletion == null\n ? 'deletions'\n : 'additions';\n\n if (missingSide == null || pendingSplitContext.side !== missingSide) {\n pendingSplitContext.flush();\n }\n\n if (deletion != null) {\n context.deletionsContentAST.push(deletion.content);\n context.pushToGutter('deletions', deletion.gutter);\n }\n\n if (addition != null) {\n context.additionsContentAST.push(addition.content);\n context.pushToGutter('additions', addition.gutter);\n }\n\n if (missingSide != null) {\n pendingSplitContext.side = missingSide;\n pendingSplitContext.increment();\n }\n\n context.incrementRowCount(1);\n }\n}\n\nfunction pushLineWithAnnotation({\n diffStyle,\n type,\n deletionLine,\n additionLine,\n unifiedSpan,\n deletionSpan,\n additionSpan,\n createAnnotationElement,\n context,\n}: PushLineWithAnnotation) {\n let hasAnnotationRow = false;\n if (diffStyle === 'unified') {\n if (additionLine != null) {\n context.unifiedContentAST.push(additionLine);\n } else if (deletionLine != null) {\n context.unifiedContentAST.push(deletionLine);\n }\n if (unifiedSpan != null) {\n const lineType =\n type === 'change'\n ? deletionLine != null\n ? 'change-deletion'\n : 'change-addition'\n : type;\n context.unifiedContentAST.push(createAnnotationElement(unifiedSpan));\n context.pushToGutter(\n 'unified',\n createGutterGap(lineType, 'annotation', 1)\n );\n hasAnnotationRow = true;\n }\n } else if (diffStyle === 'split') {\n if (deletionLine != null) {\n context.deletionsContentAST.push(deletionLine);\n }\n if (additionLine != null) {\n context.additionsContentAST.push(additionLine);\n }\n if (deletionSpan != null) {\n const lineType =\n type === 'change'\n ? deletionLine != null\n ? 'change-deletion'\n : 'context'\n : type;\n context.deletionsContentAST.push(createAnnotationElement(deletionSpan));\n context.pushToGutter(\n 'deletions',\n createGutterGap(lineType, 'annotation', 1)\n );\n hasAnnotationRow = true;\n }\n if (additionSpan != null) {\n const lineType =\n type === 'change'\n ? additionLine != null\n ? 'change-addition'\n : 'context'\n : type;\n context.additionsContentAST.push(createAnnotationElement(additionSpan));\n context.pushToGutter(\n 'additions',\n createGutterGap(lineType, 'annotation', 1)\n );\n hasAnnotationRow = true;\n }\n }\n if (hasAnnotationRow) {\n context.incrementRowCount(1);\n }\n}\n\nfunction pushSeparator(\n type: 'additions' | 'deletions' | 'unified',\n {\n hunkIndex,\n collapsedLines,\n rangeSize,\n hunkSpecs,\n isFirstHunk,\n isLastHunk,\n isExpandable,\n }: PushSeparatorProps,\n context: ProcessContext\n) {\n if (collapsedLines <= 0) {\n return;\n }\n const linesAST =\n type === 'unified'\n ? context.unifiedContentAST\n : type === 'deletions'\n ? context.deletionsContentAST\n : context.additionsContentAST;\n\n if (context.hunkSeparators === 'metadata') {\n if (hunkSpecs != null) {\n context.pushToGutter(\n type,\n createSeparator({\n type: 'metadata',\n content: hunkSpecs,\n isFirstHunk,\n isLastHunk,\n })\n );\n linesAST.push(\n createSeparator({\n type: 'metadata',\n content: hunkSpecs,\n isFirstHunk,\n isLastHunk,\n })\n );\n if (type !== 'additions') {\n context.incrementRowCount(1);\n }\n }\n return;\n }\n if (context.hunkSeparators === 'simple') {\n if (hunkIndex > 0) {\n context.pushToGutter(\n type,\n createSeparator({ type: 'simple', isFirstHunk, isLastHunk: false })\n );\n linesAST.push(\n createSeparator({ type: 'simple', isFirstHunk, isLastHunk: false })\n );\n if (type !== 'additions') {\n context.incrementRowCount(1);\n }\n }\n return;\n }\n const slotName = getHunkSeparatorSlotName(type, hunkIndex);\n const chunked = rangeSize > context.expansionLineCount;\n const expandIndex = isExpandable ? hunkIndex : undefined;\n context.pushToGutter(\n type,\n createSeparator({\n type: context.hunkSeparators,\n content: getModifiedLinesString(collapsedLines),\n expandIndex,\n chunked,\n slotName,\n isFirstHunk,\n isLastHunk,\n })\n );\n linesAST.push(\n createSeparator({\n type: context.hunkSeparators,\n content: getModifiedLinesString(collapsedLines),\n expandIndex,\n chunked,\n slotName,\n isFirstHunk,\n isLastHunk,\n })\n );\n if (type !== 'additions') {\n context.incrementRowCount(1);\n }\n context.hunkData.push({\n slotName,\n hunkIndex,\n lines: collapsedLines,\n type,\n expandable: isExpandable\n ? { up: !isFirstHunk, down: !isLastHunk, chunked }\n : undefined,\n });\n}\n\nfunction withContentProperties(\n lineNode: ElementContent | undefined,\n contentProperties: Properties | undefined\n): ElementContent | undefined {\n if (\n lineNode == null ||\n lineNode.type !== 'element' ||\n contentProperties == null\n ) {\n return lineNode;\n }\n return {\n ...lineNode,\n properties: {\n ...lineNode.properties,\n ...contentProperties,\n },\n };\n}\n\nfunction calculateTrailingRangeSize(fileDiff: FileDiffMetadata): number {\n const lastHunk = fileDiff.hunks.at(-1);\n if (\n lastHunk == null ||\n fileDiff.isPartial ||\n fileDiff.additionLines.length === 0 ||\n fileDiff.deletionLines.length === 0\n ) {\n return 0;\n }\n const additionRemaining =\n fileDiff.additionLines.length -\n (lastHunk.additionLineIndex + lastHunk.additionCount);\n const deletionRemaining =\n fileDiff.deletionLines.length -\n (lastHunk.deletionLineIndex + lastHunk.deletionCount);\n if (additionRemaining !== deletionRemaining) {\n throw new Error(\n `DiffHunksRenderer.processDiffResult: trailing context mismatch (additions=${additionRemaining}, deletions=${deletionRemaining}) for ${fileDiff.name}`\n );\n }\n return Math.min(additionRemaining, deletionRemaining);\n}\n"],"mappings":"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"}
@@ -71,7 +71,12 @@ var FileRenderer = class {
71
71
  result: cache?.result,
72
72
  renderRange: void 0
73
73
  };
74
- if (this.workerManager?.isWorkingPool() === true && this.renderCache.result == null) this.workerManager.highlightFileAST(this, file);
74
+ if (this.workerManager?.isWorkingPool() === true) {
75
+ if (this.renderCache.result == null) this.workerManager.highlightFileAST(this, file);
76
+ } else if (this.highlighter == null) {
77
+ this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);
78
+ this.initializeHighlighter();
79
+ }
75
80
  }
76
81
  getRenderOptions(file) {
77
82
  const options = (() => {
@@ -149,6 +154,7 @@ var FileRenderer = class {
149
154
  };
150
155
  }
151
156
  if (!hasThemes || !hasLangs) this.asyncHighlight(file).then(({ result, options: options$1 }) => {
157
+ if (this.renderCache != null) this.renderCache.highlighted = false;
152
158
  this.onHighlightSuccess(file, result, options$1);
153
159
  });
154
160
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FileRenderer.js","names":["options: FileRendererOptions","onRenderUpdate?: () => unknown","workerManager?: WorkerPoolManager | undefined","options: RenderFileOptions","options","contentArray: ElementContent[]"],"sources":["../../src/renderers/FileRenderer.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement } from 'hast';\nimport { toHtml } from 'hast-util-to-html';\n\nimport { DEFAULT_RENDER_RANGE, DEFAULT_THEMES } from '../constants';\nimport { areLanguagesAttached } from '../highlighter/languages/areLanguagesAttached';\nimport {\n getHighlighterIfLoaded,\n getSharedHighlighter,\n} from '../highlighter/shared_highlighter';\nimport { areThemesAttached } from '../highlighter/themes/areThemesAttached';\nimport { hasResolvedThemes } from '../highlighter/themes/hasResolvedThemes';\nimport type {\n BaseCodeOptions,\n DiffsHighlighter,\n FileContents,\n FileHeaderRenderMode,\n LineAnnotation,\n RenderedFileASTCache,\n RenderFileOptions,\n RenderFileResult,\n RenderRange,\n SupportedLanguages,\n ThemedFileResult,\n} from '../types';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { areThemesEqual } from '../utils/areThemesEqual';\nimport { createAnnotationElement } from '../utils/createAnnotationElement';\nimport { createContentColumn } from '../utils/createContentColumn';\nimport { createFileHeaderElement } from '../utils/createFileHeaderElement';\nimport { createPreElement } from '../utils/createPreElement';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport { getHighlighterOptions } from '../utils/getHighlighterOptions';\nimport { getLineAnnotationName } from '../utils/getLineAnnotationName';\nimport { getThemes } from '../utils/getThemes';\nimport {\n createGutterGap,\n createGutterItem,\n createGutterWrapper,\n createHastElement,\n} from '../utils/hast_utils';\nimport { isFilePlainText } from '../utils/isFilePlainText';\nimport { iterateOverFile } from '../utils/iterateOverFile';\nimport { renderFileWithHighlighter } from '../utils/renderFileWithHighlighter';\nimport { shouldUseTokenTransformer } from '../utils/shouldUseTokenTransformer';\nimport { splitFileContents } from '../utils/splitFileContents';\nimport type { WorkerPoolManager } from '../worker';\n\ntype AnnotationLineMap<LAnnotation> = Record<\n number,\n LineAnnotation<LAnnotation>[] | undefined\n>;\n\ninterface GetRenderOptionsReturn {\n options: RenderFileOptions;\n forceRender: boolean;\n}\n\nexport interface FileRenderResult {\n gutterAST: ElementContent[];\n contentAST: ElementContent[];\n preAST: HASTElement;\n headerAST: HASTElement | undefined;\n css: string;\n totalLines: number;\n themeStyles: string;\n baseThemeType: 'light' | 'dark' | undefined;\n rowCount: number;\n bufferBefore: number;\n bufferAfter: number;\n}\n\ninterface LineCache {\n cacheKey: string | undefined;\n lines: string[];\n}\n\nexport interface FileRendererOptions extends BaseCodeOptions {\n headerRenderMode?: FileHeaderRenderMode;\n}\n\nlet instanceId = -1;\n\nexport class FileRenderer<LAnnotation = undefined> {\n readonly __id: string = `file-renderer:${++instanceId}`;\n\n private highlighter: DiffsHighlighter | undefined;\n private renderCache: RenderedFileASTCache | undefined;\n private computedLang: SupportedLanguages = 'text';\n private lineAnnotations: AnnotationLineMap<LAnnotation> = {};\n private lineCache: LineCache | undefined;\n\n constructor(\n public options: FileRendererOptions = { theme: DEFAULT_THEMES },\n private onRenderUpdate?: () => unknown,\n private workerManager?: WorkerPoolManager | undefined\n ) {\n if (workerManager?.isWorkingPool() !== true) {\n this.highlighter = areThemesAttached(options.theme ?? DEFAULT_THEMES)\n ? getHighlighterIfLoaded()\n : undefined;\n }\n }\n\n public setOptions(options: FileRendererOptions): void {\n this.options = options;\n }\n\n public mergeOptions(options: Partial<FileRendererOptions>): void {\n this.options = { ...this.options, ...options };\n }\n\n public setLineAnnotations(\n lineAnnotations: LineAnnotation<LAnnotation>[]\n ): void {\n this.lineAnnotations = {};\n for (const annotation of lineAnnotations) {\n const arr = this.lineAnnotations[annotation.lineNumber] ?? [];\n this.lineAnnotations[annotation.lineNumber] = arr;\n arr.push(annotation);\n }\n }\n\n public cleanUp(): void {\n this.renderCache = undefined;\n this.highlighter = undefined;\n this.workerManager = undefined;\n this.onRenderUpdate = undefined;\n this.lineCache = undefined;\n }\n\n public hydrate(file: FileContents): void {\n const { options } = this.getRenderOptions(file);\n let cache = this.workerManager?.getFileResultCache(file);\n if (cache != null && !areRenderOptionsEqual(options, cache.options)) {\n cache = undefined;\n }\n this.renderCache ??= {\n file,\n options,\n highlighted: !isFilePlainText(file),\n result: cache?.result,\n // FIXME(amadeus): Add support for renderRanges\n renderRange: undefined,\n };\n if (\n this.workerManager?.isWorkingPool() === true &&\n this.renderCache.result == null\n ) {\n // We should only kick off a preload of the AST if we have a WorkerPool\n this.workerManager.highlightFileAST(this, file);\n }\n }\n\n private getRenderOptions(file: FileContents): GetRenderOptionsReturn {\n const options: RenderFileOptions = (() => {\n if (this.workerManager?.isWorkingPool() === true) {\n return this.workerManager.getFileRenderOptions();\n }\n const { theme = DEFAULT_THEMES, tokenizeMaxLineLength = 1000 } =\n this.options;\n return {\n theme,\n useTokenTransformer: shouldUseTokenTransformer(this.options),\n tokenizeMaxLineLength,\n };\n })();\n const { renderCache } = this;\n if (renderCache?.result == null) {\n return { options, forceRender: true };\n }\n if (\n file !== renderCache.file ||\n !areRenderOptionsEqual(options, renderCache.options)\n ) {\n return { options, forceRender: true };\n }\n return { options, forceRender: false };\n }\n\n public getOrCreateLineCache(file: FileContents): string[] {\n // Uncached files will get split every time, not the greatest experience\n // tbh... but something people should try to optimize away\n if (file.cacheKey == null) {\n this.lineCache = undefined;\n return splitFileContents(file.contents);\n }\n\n let { lineCache } = this;\n if (lineCache == null || lineCache.cacheKey !== file.cacheKey) {\n lineCache = {\n cacheKey: file.cacheKey,\n lines: splitFileContents(file.contents),\n };\n }\n this.lineCache = lineCache;\n return lineCache.lines;\n }\n\n public renderFile(\n file: FileContents | undefined = this.renderCache?.file,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): FileRenderResult | undefined {\n if (file == null) {\n return undefined;\n }\n const cache = this.workerManager?.getFileResultCache(file);\n if (cache != null && this.renderCache == null) {\n this.renderCache = {\n file,\n highlighted: true,\n renderRange: undefined,\n ...cache,\n };\n }\n const { options, forceRender } = this.getRenderOptions(file);\n this.renderCache ??= {\n file,\n highlighted: false,\n options,\n result: undefined,\n renderRange: undefined,\n };\n if (this.workerManager?.isWorkingPool() === true) {\n // Cache invalidation based on renderRange comparison\n if (\n this.renderCache.result == null ||\n (!this.renderCache.highlighted &&\n (file !== this.renderCache.file ||\n !areRenderRangesEqual(this.renderCache.renderRange, renderRange)))\n ) {\n this.renderCache.file = file;\n this.renderCache.result = this.workerManager.getPlainFileAST(\n file,\n renderRange.startingLine,\n renderRange.totalLines,\n this.getOrCreateLineCache(file)\n );\n this.renderCache.renderRange = renderRange;\n }\n\n if (\n // We should only attempt to kick off the worker highlighter if there\n // are lines to render\n renderRange.totalLines > 0 &&\n (!this.renderCache.highlighted || forceRender)\n ) {\n this.workerManager.highlightFileAST(this, file);\n }\n } else {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n const hasThemes =\n this.highlighter != null && areThemesAttached(options.theme);\n const hasLangs =\n this.highlighter != null && areLanguagesAttached(this.computedLang);\n\n // If we have any semblance of a highlighter with the correct theme(s)\n // attached, we can kick off some form of rendering. If we don't have\n // the correct language, then we can render plain text and after kick off\n // an async job to get the highlighted AST\n if (\n this.highlighter != null &&\n hasThemes &&\n (forceRender ||\n (!this.renderCache.highlighted && hasLangs) ||\n this.renderCache.result == null)\n ) {\n const { result, options } = this.renderFileWithHighlighter(\n file,\n this.highlighter,\n !hasLangs\n );\n this.renderCache = {\n file,\n options,\n highlighted: hasLangs,\n result,\n renderRange: undefined,\n };\n }\n\n // If we get in here it means we'll have to kick off an async highlight\n // process which will involve initializing the highlighter with new themes\n // and languages\n if (!hasThemes || !hasLangs) {\n void this.asyncHighlight(file).then(({ result, options }) => {\n this.onHighlightSuccess(file, result, options);\n });\n }\n }\n\n return this.renderCache.result != null\n ? this.processFileResult(\n this.renderCache.file,\n renderRange,\n this.renderCache.result\n )\n : undefined;\n }\n\n async asyncRender(\n file: FileContents,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): Promise<FileRenderResult> {\n const { result } = await this.asyncHighlight(file);\n return this.processFileResult(file, renderRange, result);\n }\n\n private async asyncHighlight(file: FileContents): Promise<RenderFileResult> {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n const hasThemes =\n this.highlighter != null &&\n hasResolvedThemes(getThemes(this.options.theme));\n const hasLangs =\n this.highlighter != null && areLanguagesAttached(this.computedLang);\n // If we don't have the required langs or themes, then we need to\n // initialize the highlighter to load the appropriate languages and themes\n if (this.highlighter == null || !hasThemes || !hasLangs) {\n this.highlighter = await this.initializeHighlighter();\n }\n return this.renderFileWithHighlighter(file, this.highlighter);\n }\n\n private renderFileWithHighlighter(\n file: FileContents,\n highlighter: DiffsHighlighter,\n forcePlainText = false\n ): RenderFileResult {\n const { options } = this.getRenderOptions(file);\n const result = renderFileWithHighlighter(file, highlighter, options, {\n forcePlainText,\n });\n return { result, options };\n }\n\n private processFileResult(\n file: FileContents,\n renderRange: RenderRange,\n { code, themeStyles, baseThemeType }: ThemedFileResult\n ): FileRenderResult {\n const { disableFileHeader = false } = this.options;\n const contentArray: ElementContent[] = [];\n const gutter = createGutterWrapper();\n const lines = this.getOrCreateLineCache(file);\n let rowCount = 0;\n\n iterateOverFile({\n lines,\n startingLine: renderRange.startingLine,\n totalLines: renderRange.totalLines,\n callback: ({ lineIndex, lineNumber }) => {\n // Sparse array - directly indexed by lineIndex\n const line = code[lineIndex];\n if (line == null) {\n const message = 'FileRenderer.processFileResult: Line doesnt exist';\n console.error(message, {\n name: file.name,\n lineIndex,\n lineNumber,\n lines,\n });\n throw new Error(message);\n }\n\n if (line != null) {\n // Add gutter line number\n gutter.children.push(\n createGutterItem('context', lineNumber, `${lineIndex}`)\n );\n contentArray.push(line);\n rowCount++;\n\n // Check annotations using ACTUAL line number from file\n const annotations = this.lineAnnotations[lineNumber];\n if (annotations != null) {\n gutter.children.push(createGutterGap('context', 'annotation', 1));\n contentArray.push(\n createAnnotationElement({\n type: 'annotation',\n hunkIndex: 0,\n lineIndex: lineNumber,\n annotations: annotations.map((annotation) =>\n getLineAnnotationName(annotation)\n ),\n })\n );\n rowCount++;\n }\n }\n },\n });\n\n // Finalize: wrap gutter and content\n gutter.properties.style = `grid-row: span ${rowCount}`;\n return {\n gutterAST: gutter.children ?? [],\n contentAST: contentArray,\n preAST: this.createPreElement(lines.length),\n headerAST: !disableFileHeader ? this.renderHeader(file) : undefined,\n totalLines: lines.length,\n rowCount,\n themeStyles: themeStyles,\n baseThemeType,\n bufferBefore: renderRange.bufferBefore,\n bufferAfter: renderRange.bufferAfter,\n css: '',\n };\n }\n\n private renderHeader(file: FileContents) {\n const { headerRenderMode = 'default' } = this.options;\n return createFileHeaderElement({\n fileOrDiff: file,\n mode: headerRenderMode,\n });\n }\n\n public renderFullHTML(result: FileRenderResult): string {\n return toHtml(this.renderFullAST(result));\n }\n\n public renderFullAST(\n result: FileRenderResult,\n children: ElementContent[] = []\n ): HASTElement {\n children.push(\n createHastElement({\n tagName: 'code',\n children: this.renderCodeAST(result),\n properties: { 'data-code': '' },\n })\n );\n return { ...result.preAST, children };\n }\n\n public renderCodeAST(result: FileRenderResult): ElementContent[] {\n const gutter = createGutterWrapper();\n gutter.children = result.gutterAST;\n gutter.properties.style = `grid-row: span ${result.rowCount}`;\n const contentColumn = createContentColumn(\n result.contentAST,\n result.rowCount\n );\n return [gutter, contentColumn];\n }\n\n public renderPartialHTML(\n children: ElementContent[],\n includeCodeNode: boolean = false\n ): string {\n if (!includeCodeNode) {\n return toHtml(children);\n }\n return toHtml(\n createHastElement({\n tagName: 'code',\n children,\n properties: { 'data-code': '' },\n })\n );\n }\n\n public async initializeHighlighter(): Promise<DiffsHighlighter> {\n this.highlighter = await getSharedHighlighter(\n getHighlighterOptions(this.computedLang, this.options)\n );\n return this.highlighter;\n }\n\n public onHighlightSuccess(\n file: FileContents,\n result: ThemedFileResult,\n options: RenderFileOptions\n ): void {\n if (this.renderCache == null) {\n return;\n }\n const triggerRenderUpdate =\n this.renderCache.file !== file ||\n !this.renderCache.highlighted ||\n !areRenderOptionsEqual(options, this.renderCache.options);\n\n this.renderCache = {\n file,\n options,\n highlighted: true,\n result,\n renderRange: undefined,\n };\n\n if (triggerRenderUpdate) {\n this.onRenderUpdate?.();\n }\n }\n\n public onHighlightError(error: unknown): void {\n console.error(error);\n }\n\n private createPreElement(totalLines: number): HASTElement {\n const { disableLineNumbers = false, overflow = 'scroll' } = this.options;\n return createPreElement({\n type: 'file',\n diffIndicators: 'none',\n disableBackground: true,\n disableLineNumbers,\n overflow,\n split: false,\n totalLines,\n });\n }\n}\n\nfunction areRenderOptionsEqual(\n optionsA: RenderFileOptions,\n optionsB: RenderFileOptions\n): boolean {\n return (\n areThemesEqual(optionsA.theme, optionsB.theme) &&\n optionsA.useTokenTransformer === optionsB.useTokenTransformer &&\n optionsA.tokenizeMaxLineLength === optionsB.tokenizeMaxLineLength\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"FileRenderer.js","names":["options: FileRendererOptions","onRenderUpdate?: () => unknown","workerManager?: WorkerPoolManager | undefined","options: RenderFileOptions","options","contentArray: ElementContent[]"],"sources":["../../src/renderers/FileRenderer.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement } from 'hast';\nimport { toHtml } from 'hast-util-to-html';\n\nimport { DEFAULT_RENDER_RANGE, DEFAULT_THEMES } from '../constants';\nimport { areLanguagesAttached } from '../highlighter/languages/areLanguagesAttached';\nimport {\n getHighlighterIfLoaded,\n getSharedHighlighter,\n} from '../highlighter/shared_highlighter';\nimport { areThemesAttached } from '../highlighter/themes/areThemesAttached';\nimport { hasResolvedThemes } from '../highlighter/themes/hasResolvedThemes';\nimport type {\n BaseCodeOptions,\n DiffsHighlighter,\n FileContents,\n FileHeaderRenderMode,\n LineAnnotation,\n RenderedFileASTCache,\n RenderFileOptions,\n RenderFileResult,\n RenderRange,\n SupportedLanguages,\n ThemedFileResult,\n} from '../types';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { areThemesEqual } from '../utils/areThemesEqual';\nimport { createAnnotationElement } from '../utils/createAnnotationElement';\nimport { createContentColumn } from '../utils/createContentColumn';\nimport { createFileHeaderElement } from '../utils/createFileHeaderElement';\nimport { createPreElement } from '../utils/createPreElement';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport { getHighlighterOptions } from '../utils/getHighlighterOptions';\nimport { getLineAnnotationName } from '../utils/getLineAnnotationName';\nimport { getThemes } from '../utils/getThemes';\nimport {\n createGutterGap,\n createGutterItem,\n createGutterWrapper,\n createHastElement,\n} from '../utils/hast_utils';\nimport { isFilePlainText } from '../utils/isFilePlainText';\nimport { iterateOverFile } from '../utils/iterateOverFile';\nimport { renderFileWithHighlighter } from '../utils/renderFileWithHighlighter';\nimport { shouldUseTokenTransformer } from '../utils/shouldUseTokenTransformer';\nimport { splitFileContents } from '../utils/splitFileContents';\nimport type { WorkerPoolManager } from '../worker';\n\ntype AnnotationLineMap<LAnnotation> = Record<\n number,\n LineAnnotation<LAnnotation>[] | undefined\n>;\n\ninterface GetRenderOptionsReturn {\n options: RenderFileOptions;\n forceRender: boolean;\n}\n\nexport interface FileRenderResult {\n gutterAST: ElementContent[];\n contentAST: ElementContent[];\n preAST: HASTElement;\n headerAST: HASTElement | undefined;\n css: string;\n totalLines: number;\n themeStyles: string;\n baseThemeType: 'light' | 'dark' | undefined;\n rowCount: number;\n bufferBefore: number;\n bufferAfter: number;\n}\n\ninterface LineCache {\n cacheKey: string | undefined;\n lines: string[];\n}\n\nexport interface FileRendererOptions extends BaseCodeOptions {\n headerRenderMode?: FileHeaderRenderMode;\n}\n\nlet instanceId = -1;\n\nexport class FileRenderer<LAnnotation = undefined> {\n readonly __id: string = `file-renderer:${++instanceId}`;\n\n private highlighter: DiffsHighlighter | undefined;\n private renderCache: RenderedFileASTCache | undefined;\n private computedLang: SupportedLanguages = 'text';\n private lineAnnotations: AnnotationLineMap<LAnnotation> = {};\n private lineCache: LineCache | undefined;\n\n constructor(\n public options: FileRendererOptions = { theme: DEFAULT_THEMES },\n private onRenderUpdate?: () => unknown,\n private workerManager?: WorkerPoolManager | undefined\n ) {\n if (workerManager?.isWorkingPool() !== true) {\n this.highlighter = areThemesAttached(options.theme ?? DEFAULT_THEMES)\n ? getHighlighterIfLoaded()\n : undefined;\n }\n }\n\n public setOptions(options: FileRendererOptions): void {\n this.options = options;\n }\n\n public mergeOptions(options: Partial<FileRendererOptions>): void {\n this.options = { ...this.options, ...options };\n }\n\n public setLineAnnotations(\n lineAnnotations: LineAnnotation<LAnnotation>[]\n ): void {\n this.lineAnnotations = {};\n for (const annotation of lineAnnotations) {\n const arr = this.lineAnnotations[annotation.lineNumber] ?? [];\n this.lineAnnotations[annotation.lineNumber] = arr;\n arr.push(annotation);\n }\n }\n\n public cleanUp(): void {\n this.renderCache = undefined;\n this.highlighter = undefined;\n this.workerManager = undefined;\n this.onRenderUpdate = undefined;\n this.lineCache = undefined;\n }\n\n public hydrate(file: FileContents): void {\n const { options } = this.getRenderOptions(file);\n let cache = this.workerManager?.getFileResultCache(file);\n if (cache != null && !areRenderOptionsEqual(options, cache.options)) {\n cache = undefined;\n }\n this.renderCache ??= {\n file,\n options,\n highlighted: !isFilePlainText(file),\n result: cache?.result,\n // FIXME(amadeus): Add support for renderRanges\n renderRange: undefined,\n };\n if (this.workerManager?.isWorkingPool() === true) {\n if (this.renderCache.result == null) {\n // We should only kick off a preload of the AST if we have a WorkerPool\n this.workerManager.highlightFileAST(this, file);\n }\n }\n // Lets attempt to get the highlighter/languages ready immediately\n else if (this.highlighter == null) {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n void this.initializeHighlighter();\n }\n }\n\n private getRenderOptions(file: FileContents): GetRenderOptionsReturn {\n const options: RenderFileOptions = (() => {\n if (this.workerManager?.isWorkingPool() === true) {\n return this.workerManager.getFileRenderOptions();\n }\n const { theme = DEFAULT_THEMES, tokenizeMaxLineLength = 1000 } =\n this.options;\n return {\n theme,\n useTokenTransformer: shouldUseTokenTransformer(this.options),\n tokenizeMaxLineLength,\n };\n })();\n const { renderCache } = this;\n if (renderCache?.result == null) {\n return { options, forceRender: true };\n }\n if (\n file !== renderCache.file ||\n !areRenderOptionsEqual(options, renderCache.options)\n ) {\n return { options, forceRender: true };\n }\n return { options, forceRender: false };\n }\n\n public getOrCreateLineCache(file: FileContents): string[] {\n // Uncached files will get split every time, not the greatest experience\n // tbh... but something people should try to optimize away\n if (file.cacheKey == null) {\n this.lineCache = undefined;\n return splitFileContents(file.contents);\n }\n\n let { lineCache } = this;\n if (lineCache == null || lineCache.cacheKey !== file.cacheKey) {\n lineCache = {\n cacheKey: file.cacheKey,\n lines: splitFileContents(file.contents),\n };\n }\n this.lineCache = lineCache;\n return lineCache.lines;\n }\n\n public renderFile(\n file: FileContents | undefined = this.renderCache?.file,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): FileRenderResult | undefined {\n if (file == null) {\n return undefined;\n }\n const cache = this.workerManager?.getFileResultCache(file);\n if (cache != null && this.renderCache == null) {\n this.renderCache = {\n file,\n highlighted: true,\n renderRange: undefined,\n ...cache,\n };\n }\n const { options, forceRender } = this.getRenderOptions(file);\n this.renderCache ??= {\n file,\n highlighted: false,\n options,\n result: undefined,\n renderRange: undefined,\n };\n if (this.workerManager?.isWorkingPool() === true) {\n // Cache invalidation based on renderRange comparison\n if (\n this.renderCache.result == null ||\n (!this.renderCache.highlighted &&\n (file !== this.renderCache.file ||\n !areRenderRangesEqual(this.renderCache.renderRange, renderRange)))\n ) {\n this.renderCache.file = file;\n this.renderCache.result = this.workerManager.getPlainFileAST(\n file,\n renderRange.startingLine,\n renderRange.totalLines,\n this.getOrCreateLineCache(file)\n );\n this.renderCache.renderRange = renderRange;\n }\n\n if (\n // We should only attempt to kick off the worker highlighter if there\n // are lines to render\n renderRange.totalLines > 0 &&\n (!this.renderCache.highlighted || forceRender)\n ) {\n this.workerManager.highlightFileAST(this, file);\n }\n } else {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n const hasThemes =\n this.highlighter != null && areThemesAttached(options.theme);\n const hasLangs =\n this.highlighter != null && areLanguagesAttached(this.computedLang);\n\n // If we have any semblance of a highlighter with the correct theme(s)\n // attached, we can kick off some form of rendering. If we don't have\n // the correct language, then we can render plain text and after kick off\n // an async job to get the highlighted AST\n if (\n this.highlighter != null &&\n hasThemes &&\n (forceRender ||\n (!this.renderCache.highlighted && hasLangs) ||\n this.renderCache.result == null)\n ) {\n const { result, options } = this.renderFileWithHighlighter(\n file,\n this.highlighter,\n !hasLangs\n );\n this.renderCache = {\n file,\n options,\n highlighted: hasLangs,\n result,\n renderRange: undefined,\n };\n }\n\n // If we get in here it means we'll have to kick off an async highlight\n // process which will involve initializing the highlighter with new themes\n // and languages\n if (!hasThemes || !hasLangs) {\n void this.asyncHighlight(file).then(({ result, options }) => {\n // In this case we need to force a re-render, so we can do that by\n // reaching into renderCache\n if (this.renderCache != null) {\n this.renderCache.highlighted = false;\n }\n this.onHighlightSuccess(file, result, options);\n });\n }\n }\n\n return this.renderCache.result != null\n ? this.processFileResult(\n this.renderCache.file,\n renderRange,\n this.renderCache.result\n )\n : undefined;\n }\n\n async asyncRender(\n file: FileContents,\n renderRange: RenderRange = DEFAULT_RENDER_RANGE\n ): Promise<FileRenderResult> {\n const { result } = await this.asyncHighlight(file);\n return this.processFileResult(file, renderRange, result);\n }\n\n private async asyncHighlight(file: FileContents): Promise<RenderFileResult> {\n this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n const hasThemes =\n this.highlighter != null &&\n hasResolvedThemes(getThemes(this.options.theme));\n const hasLangs =\n this.highlighter != null && areLanguagesAttached(this.computedLang);\n // If we don't have the required langs or themes, then we need to\n // initialize the highlighter to load the appropriate languages and themes\n if (this.highlighter == null || !hasThemes || !hasLangs) {\n this.highlighter = await this.initializeHighlighter();\n }\n return this.renderFileWithHighlighter(file, this.highlighter);\n }\n\n private renderFileWithHighlighter(\n file: FileContents,\n highlighter: DiffsHighlighter,\n forcePlainText = false\n ): RenderFileResult {\n const { options } = this.getRenderOptions(file);\n const result = renderFileWithHighlighter(file, highlighter, options, {\n forcePlainText,\n });\n return { result, options };\n }\n\n private processFileResult(\n file: FileContents,\n renderRange: RenderRange,\n { code, themeStyles, baseThemeType }: ThemedFileResult\n ): FileRenderResult {\n const { disableFileHeader = false } = this.options;\n const contentArray: ElementContent[] = [];\n const gutter = createGutterWrapper();\n const lines = this.getOrCreateLineCache(file);\n let rowCount = 0;\n\n iterateOverFile({\n lines,\n startingLine: renderRange.startingLine,\n totalLines: renderRange.totalLines,\n callback: ({ lineIndex, lineNumber }) => {\n // Sparse array - directly indexed by lineIndex\n const line = code[lineIndex];\n if (line == null) {\n const message = 'FileRenderer.processFileResult: Line doesnt exist';\n console.error(message, {\n name: file.name,\n lineIndex,\n lineNumber,\n lines,\n });\n throw new Error(message);\n }\n\n if (line != null) {\n // Add gutter line number\n gutter.children.push(\n createGutterItem('context', lineNumber, `${lineIndex}`)\n );\n contentArray.push(line);\n rowCount++;\n\n // Check annotations using ACTUAL line number from file\n const annotations = this.lineAnnotations[lineNumber];\n if (annotations != null) {\n gutter.children.push(createGutterGap('context', 'annotation', 1));\n contentArray.push(\n createAnnotationElement({\n type: 'annotation',\n hunkIndex: 0,\n lineIndex: lineNumber,\n annotations: annotations.map((annotation) =>\n getLineAnnotationName(annotation)\n ),\n })\n );\n rowCount++;\n }\n }\n },\n });\n\n // Finalize: wrap gutter and content\n gutter.properties.style = `grid-row: span ${rowCount}`;\n return {\n gutterAST: gutter.children ?? [],\n contentAST: contentArray,\n preAST: this.createPreElement(lines.length),\n headerAST: !disableFileHeader ? this.renderHeader(file) : undefined,\n totalLines: lines.length,\n rowCount,\n themeStyles: themeStyles,\n baseThemeType,\n bufferBefore: renderRange.bufferBefore,\n bufferAfter: renderRange.bufferAfter,\n css: '',\n };\n }\n\n private renderHeader(file: FileContents) {\n const { headerRenderMode = 'default' } = this.options;\n return createFileHeaderElement({\n fileOrDiff: file,\n mode: headerRenderMode,\n });\n }\n\n public renderFullHTML(result: FileRenderResult): string {\n return toHtml(this.renderFullAST(result));\n }\n\n public renderFullAST(\n result: FileRenderResult,\n children: ElementContent[] = []\n ): HASTElement {\n children.push(\n createHastElement({\n tagName: 'code',\n children: this.renderCodeAST(result),\n properties: { 'data-code': '' },\n })\n );\n return { ...result.preAST, children };\n }\n\n public renderCodeAST(result: FileRenderResult): ElementContent[] {\n const gutter = createGutterWrapper();\n gutter.children = result.gutterAST;\n gutter.properties.style = `grid-row: span ${result.rowCount}`;\n const contentColumn = createContentColumn(\n result.contentAST,\n result.rowCount\n );\n return [gutter, contentColumn];\n }\n\n public renderPartialHTML(\n children: ElementContent[],\n includeCodeNode: boolean = false\n ): string {\n if (!includeCodeNode) {\n return toHtml(children);\n }\n return toHtml(\n createHastElement({\n tagName: 'code',\n children,\n properties: { 'data-code': '' },\n })\n );\n }\n\n public async initializeHighlighter(): Promise<DiffsHighlighter> {\n this.highlighter = await getSharedHighlighter(\n getHighlighterOptions(this.computedLang, this.options)\n );\n return this.highlighter;\n }\n\n public onHighlightSuccess(\n file: FileContents,\n result: ThemedFileResult,\n options: RenderFileOptions\n ): void {\n if (this.renderCache == null) {\n return;\n }\n const triggerRenderUpdate =\n this.renderCache.file !== file ||\n !this.renderCache.highlighted ||\n !areRenderOptionsEqual(options, this.renderCache.options);\n\n this.renderCache = {\n file,\n options,\n highlighted: true,\n result,\n renderRange: undefined,\n };\n\n if (triggerRenderUpdate) {\n this.onRenderUpdate?.();\n }\n }\n\n public onHighlightError(error: unknown): void {\n console.error(error);\n }\n\n private createPreElement(totalLines: number): HASTElement {\n const { disableLineNumbers = false, overflow = 'scroll' } = this.options;\n return createPreElement({\n type: 'file',\n diffIndicators: 'none',\n disableBackground: true,\n disableLineNumbers,\n overflow,\n split: false,\n totalLines,\n });\n }\n}\n\nfunction areRenderOptionsEqual(\n optionsA: RenderFileOptions,\n optionsB: RenderFileOptions\n): boolean {\n return (\n areThemesEqual(optionsA.theme, optionsB.theme) &&\n optionsA.useTokenTransformer === optionsB.useTokenTransformer &&\n optionsA.tokenizeMaxLineLength === optionsB.tokenizeMaxLineLength\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAgFA,IAAI,aAAa;AAEjB,IAAa,eAAb,MAAmD;CACjD,AAAS,OAAe,iBAAiB,EAAE;CAE3C,AAAQ;CACR,AAAQ;CACR,AAAQ,eAAmC;CAC3C,AAAQ,kBAAkD,EAAE;CAC5D,AAAQ;CAER,YACE,AAAOA,UAA+B,EAAE,OAAO,gBAAgB,EAC/D,AAAQC,gBACR,AAAQC,eACR;EAHO;EACC;EACA;AAER,MAAI,eAAe,eAAe,KAAK,KACrC,MAAK,cAAc,kBAAkB,QAAQ,SAAS,eAAe,GACjE,wBAAwB,GACxB;;CAIR,AAAO,WAAW,SAAoC;AACpD,OAAK,UAAU;;CAGjB,AAAO,aAAa,SAA6C;AAC/D,OAAK,UAAU;GAAE,GAAG,KAAK;GAAS,GAAG;GAAS;;CAGhD,AAAO,mBACL,iBACM;AACN,OAAK,kBAAkB,EAAE;AACzB,OAAK,MAAM,cAAc,iBAAiB;GACxC,MAAM,MAAM,KAAK,gBAAgB,WAAW,eAAe,EAAE;AAC7D,QAAK,gBAAgB,WAAW,cAAc;AAC9C,OAAI,KAAK,WAAW;;;CAIxB,AAAO,UAAgB;AACrB,OAAK,cAAc;AACnB,OAAK,cAAc;AACnB,OAAK,gBAAgB;AACrB,OAAK,iBAAiB;AACtB,OAAK,YAAY;;CAGnB,AAAO,QAAQ,MAA0B;EACvC,MAAM,EAAE,YAAY,KAAK,iBAAiB,KAAK;EAC/C,IAAI,QAAQ,KAAK,eAAe,mBAAmB,KAAK;AACxD,MAAI,SAAS,QAAQ,CAAC,sBAAsB,SAAS,MAAM,QAAQ,CACjE,SAAQ;AAEV,OAAK,gBAAgB;GACnB;GACA;GACA,aAAa,CAAC,gBAAgB,KAAK;GACnC,QAAQ,OAAO;GAEf,aAAa;GACd;AACD,MAAI,KAAK,eAAe,eAAe,KAAK,MAC1C;OAAI,KAAK,YAAY,UAAU,KAE7B,MAAK,cAAc,iBAAiB,MAAM,KAAK;aAI1C,KAAK,eAAe,MAAM;AACjC,QAAK,eAAe,KAAK,QAAQ,wBAAwB,KAAK,KAAK;AACnE,GAAK,KAAK,uBAAuB;;;CAIrC,AAAQ,iBAAiB,MAA4C;EACnE,MAAMC,iBAAoC;AACxC,OAAI,KAAK,eAAe,eAAe,KAAK,KAC1C,QAAO,KAAK,cAAc,sBAAsB;GAElD,MAAM,EAAE,QAAQ,gBAAgB,wBAAwB,QACtD,KAAK;AACP,UAAO;IACL;IACA,qBAAqB,0BAA0B,KAAK,QAAQ;IAC5D;IACD;MACC;EACJ,MAAM,EAAE,gBAAgB;AACxB,MAAI,aAAa,UAAU,KACzB,QAAO;GAAE;GAAS,aAAa;GAAM;AAEvC,MACE,SAAS,YAAY,QACrB,CAAC,sBAAsB,SAAS,YAAY,QAAQ,CAEpD,QAAO;GAAE;GAAS,aAAa;GAAM;AAEvC,SAAO;GAAE;GAAS,aAAa;GAAO;;CAGxC,AAAO,qBAAqB,MAA8B;AAGxD,MAAI,KAAK,YAAY,MAAM;AACzB,QAAK,YAAY;AACjB,UAAO,kBAAkB,KAAK,SAAS;;EAGzC,IAAI,EAAE,cAAc;AACpB,MAAI,aAAa,QAAQ,UAAU,aAAa,KAAK,SACnD,aAAY;GACV,UAAU,KAAK;GACf,OAAO,kBAAkB,KAAK,SAAS;GACxC;AAEH,OAAK,YAAY;AACjB,SAAO,UAAU;;CAGnB,AAAO,WACL,OAAiC,KAAK,aAAa,MACnD,cAA2B,sBACG;AAC9B,MAAI,QAAQ,KACV;EAEF,MAAM,QAAQ,KAAK,eAAe,mBAAmB,KAAK;AAC1D,MAAI,SAAS,QAAQ,KAAK,eAAe,KACvC,MAAK,cAAc;GACjB;GACA,aAAa;GACb,aAAa;GACb,GAAG;GACJ;EAEH,MAAM,EAAE,SAAS,gBAAgB,KAAK,iBAAiB,KAAK;AAC5D,OAAK,gBAAgB;GACnB;GACA,aAAa;GACb;GACA,QAAQ;GACR,aAAa;GACd;AACD,MAAI,KAAK,eAAe,eAAe,KAAK,MAAM;AAEhD,OACE,KAAK,YAAY,UAAU,QAC1B,CAAC,KAAK,YAAY,gBAChB,SAAS,KAAK,YAAY,QACzB,CAAC,qBAAqB,KAAK,YAAY,aAAa,YAAY,GACpE;AACA,SAAK,YAAY,OAAO;AACxB,SAAK,YAAY,SAAS,KAAK,cAAc,gBAC3C,MACA,YAAY,cACZ,YAAY,YACZ,KAAK,qBAAqB,KAAK,CAChC;AACD,SAAK,YAAY,cAAc;;AAGjC,OAGE,YAAY,aAAa,MACxB,CAAC,KAAK,YAAY,eAAe,aAElC,MAAK,cAAc,iBAAiB,MAAM,KAAK;SAE5C;AACL,QAAK,eAAe,KAAK,QAAQ,wBAAwB,KAAK,KAAK;GACnE,MAAM,YACJ,KAAK,eAAe,QAAQ,kBAAkB,QAAQ,MAAM;GAC9D,MAAM,WACJ,KAAK,eAAe,QAAQ,qBAAqB,KAAK,aAAa;AAMrE,OACE,KAAK,eAAe,QACpB,cACC,eACE,CAAC,KAAK,YAAY,eAAe,YAClC,KAAK,YAAY,UAAU,OAC7B;IACA,MAAM,EAAE,QAAQ,uBAAY,KAAK,0BAC/B,MACA,KAAK,aACL,CAAC,SACF;AACD,SAAK,cAAc;KACjB;KACA;KACA,aAAa;KACb;KACA,aAAa;KACd;;AAMH,OAAI,CAAC,aAAa,CAAC,SACjB,CAAK,KAAK,eAAe,KAAK,CAAC,MAAM,EAAE,QAAQ,yBAAc;AAG3D,QAAI,KAAK,eAAe,KACtB,MAAK,YAAY,cAAc;AAEjC,SAAK,mBAAmB,MAAM,QAAQC,UAAQ;KAC9C;;AAIN,SAAO,KAAK,YAAY,UAAU,OAC9B,KAAK,kBACH,KAAK,YAAY,MACjB,aACA,KAAK,YAAY,OAClB,GACD;;CAGN,MAAM,YACJ,MACA,cAA2B,sBACA;EAC3B,MAAM,EAAE,WAAW,MAAM,KAAK,eAAe,KAAK;AAClD,SAAO,KAAK,kBAAkB,MAAM,aAAa,OAAO;;CAG1D,MAAc,eAAe,MAA+C;AAC1E,OAAK,eAAe,KAAK,QAAQ,wBAAwB,KAAK,KAAK;EACnE,MAAM,YACJ,KAAK,eAAe,QACpB,kBAAkB,UAAU,KAAK,QAAQ,MAAM,CAAC;EAClD,MAAM,WACJ,KAAK,eAAe,QAAQ,qBAAqB,KAAK,aAAa;AAGrE,MAAI,KAAK,eAAe,QAAQ,CAAC,aAAa,CAAC,SAC7C,MAAK,cAAc,MAAM,KAAK,uBAAuB;AAEvD,SAAO,KAAK,0BAA0B,MAAM,KAAK,YAAY;;CAG/D,AAAQ,0BACN,MACA,aACA,iBAAiB,OACC;EAClB,MAAM,EAAE,YAAY,KAAK,iBAAiB,KAAK;AAI/C,SAAO;GAAE,QAHM,0BAA0B,MAAM,aAAa,SAAS,EACnE,gBACD,CAAC;GACe;GAAS;;CAG5B,AAAQ,kBACN,MACA,aACA,EAAE,MAAM,aAAa,iBACH;EAClB,MAAM,EAAE,oBAAoB,UAAU,KAAK;EAC3C,MAAMC,eAAiC,EAAE;EACzC,MAAM,SAAS,qBAAqB;EACpC,MAAM,QAAQ,KAAK,qBAAqB,KAAK;EAC7C,IAAI,WAAW;AAEf,kBAAgB;GACd;GACA,cAAc,YAAY;GAC1B,YAAY,YAAY;GACxB,WAAW,EAAE,WAAW,iBAAiB;IAEvC,MAAM,OAAO,KAAK;AAClB,QAAI,QAAQ,MAAM;KAChB,MAAM,UAAU;AAChB,aAAQ,MAAM,SAAS;MACrB,MAAM,KAAK;MACX;MACA;MACA;MACD,CAAC;AACF,WAAM,IAAI,MAAM,QAAQ;;AAG1B,QAAI,QAAQ,MAAM;AAEhB,YAAO,SAAS,KACd,iBAAiB,WAAW,YAAY,GAAG,YAAY,CACxD;AACD,kBAAa,KAAK,KAAK;AACvB;KAGA,MAAM,cAAc,KAAK,gBAAgB;AACzC,SAAI,eAAe,MAAM;AACvB,aAAO,SAAS,KAAK,gBAAgB,WAAW,cAAc,EAAE,CAAC;AACjE,mBAAa,KACX,wBAAwB;OACtB,MAAM;OACN,WAAW;OACX,WAAW;OACX,aAAa,YAAY,KAAK,eAC5B,sBAAsB,WAAW,CAClC;OACF,CAAC,CACH;AACD;;;;GAIP,CAAC;AAGF,SAAO,WAAW,QAAQ,kBAAkB;AAC5C,SAAO;GACL,WAAW,OAAO,YAAY,EAAE;GAChC,YAAY;GACZ,QAAQ,KAAK,iBAAiB,MAAM,OAAO;GAC3C,WAAW,CAAC,oBAAoB,KAAK,aAAa,KAAK,GAAG;GAC1D,YAAY,MAAM;GAClB;GACa;GACb;GACA,cAAc,YAAY;GAC1B,aAAa,YAAY;GACzB,KAAK;GACN;;CAGH,AAAQ,aAAa,MAAoB;EACvC,MAAM,EAAE,mBAAmB,cAAc,KAAK;AAC9C,SAAO,wBAAwB;GAC7B,YAAY;GACZ,MAAM;GACP,CAAC;;CAGJ,AAAO,eAAe,QAAkC;AACtD,SAAO,OAAO,KAAK,cAAc,OAAO,CAAC;;CAG3C,AAAO,cACL,QACA,WAA6B,EAAE,EAClB;AACb,WAAS,KACP,kBAAkB;GAChB,SAAS;GACT,UAAU,KAAK,cAAc,OAAO;GACpC,YAAY,EAAE,aAAa,IAAI;GAChC,CAAC,CACH;AACD,SAAO;GAAE,GAAG,OAAO;GAAQ;GAAU;;CAGvC,AAAO,cAAc,QAA4C;EAC/D,MAAM,SAAS,qBAAqB;AACpC,SAAO,WAAW,OAAO;AACzB,SAAO,WAAW,QAAQ,kBAAkB,OAAO;AAKnD,SAAO,CAAC,QAJc,oBACpB,OAAO,YACP,OAAO,SACR,CAC6B;;CAGhC,AAAO,kBACL,UACA,kBAA2B,OACnB;AACR,MAAI,CAAC,gBACH,QAAO,OAAO,SAAS;AAEzB,SAAO,OACL,kBAAkB;GAChB,SAAS;GACT;GACA,YAAY,EAAE,aAAa,IAAI;GAChC,CAAC,CACH;;CAGH,MAAa,wBAAmD;AAC9D,OAAK,cAAc,MAAM,qBACvB,sBAAsB,KAAK,cAAc,KAAK,QAAQ,CACvD;AACD,SAAO,KAAK;;CAGd,AAAO,mBACL,MACA,QACA,SACM;AACN,MAAI,KAAK,eAAe,KACtB;EAEF,MAAM,sBACJ,KAAK,YAAY,SAAS,QAC1B,CAAC,KAAK,YAAY,eAClB,CAAC,sBAAsB,SAAS,KAAK,YAAY,QAAQ;AAE3D,OAAK,cAAc;GACjB;GACA;GACA,aAAa;GACb;GACA,aAAa;GACd;AAED,MAAI,oBACF,MAAK,kBAAkB;;CAI3B,AAAO,iBAAiB,OAAsB;AAC5C,UAAQ,MAAM,MAAM;;CAGtB,AAAQ,iBAAiB,YAAiC;EACxD,MAAM,EAAE,qBAAqB,OAAO,WAAW,aAAa,KAAK;AACjE,SAAO,iBAAiB;GACtB,MAAM;GACN,gBAAgB;GAChB,mBAAmB;GACnB;GACA;GACA,OAAO;GACP;GACD,CAAC;;;AAIN,SAAS,sBACP,UACA,UACS;AACT,QACE,eAAe,SAAS,OAAO,SAAS,MAAM,IAC9C,SAAS,wBAAwB,SAAS,uBAC1C,SAAS,0BAA0B,SAAS"}
@@ -9,6 +9,7 @@ function createExpandButton(type) {
9
9
  properties: { "data-icon": "" }
10
10
  })],
11
11
  properties: {
12
+ role: "button",
12
13
  "data-expand-button": "",
13
14
  "data-expand-both": type === "both" ? "" : void 0,
14
15
  "data-expand-up": type === "up" ? "" : void 0,
@@ -49,9 +50,10 @@ function createSeparator({ type, content, expandIndex, chunked = false, slotName
49
50
  properties: { "data-separator-content": "" }
50
51
  }));
51
52
  if (chunked && expandIndex != null) contentChildren.push(createHastElement({
52
- tagName: "span",
53
- children: [createTextNodeElement("Expand All")],
53
+ tagName: "div",
54
+ children: [createTextNodeElement("Expand all")],
54
55
  properties: {
56
+ role: "button",
55
57
  "data-expand-button": "",
56
58
  "data-expand-all-button": ""
57
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createSeparator.js","names":["contentChildren: ElementContent[]"],"sources":["../../src/utils/createSeparator.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement } from 'hast';\n\nimport type { ExpansionDirections, HunkSeparators } from '../types';\nimport {\n createHastElement,\n createIconElement,\n createTextNodeElement,\n} from './hast_utils';\n\ninterface CreateSeparatorProps {\n type: HunkSeparators;\n content?: string;\n expandIndex?: number;\n chunked?: boolean;\n slotName?: string;\n isFirstHunk: boolean;\n isLastHunk: boolean;\n}\n\nfunction createExpandButton(type: ExpansionDirections) {\n return createHastElement({\n tagName: 'div',\n children: [\n createIconElement({\n name: type === 'both' ? 'diffs-icon-expand-all' : 'diffs-icon-expand',\n properties: { 'data-icon': '' },\n }),\n ],\n properties: {\n 'data-expand-button': '',\n 'data-expand-both': type === 'both' ? '' : undefined,\n 'data-expand-up': type === 'up' ? '' : undefined,\n 'data-expand-down': type === 'down' ? '' : undefined,\n },\n });\n}\n\nexport function createSeparator({\n type,\n content,\n expandIndex,\n chunked = false,\n slotName,\n isFirstHunk,\n isLastHunk,\n}: CreateSeparatorProps): HASTElement {\n let buttonCount = 0;\n const children = [];\n if (type === 'metadata' && content != null) {\n children.push(\n createHastElement({\n tagName: 'div',\n children: [createTextNodeElement(content)],\n properties: { 'data-separator-wrapper': '' },\n })\n );\n }\n if ((type === 'line-info' || type === 'line-info-basic') && content != null) {\n const contentChildren: ElementContent[] = [];\n if (expandIndex != null) {\n if (!chunked) {\n contentChildren.push(\n createExpandButton(\n !isFirstHunk && !isLastHunk ? 'both' : isFirstHunk ? 'down' : 'up'\n )\n );\n buttonCount++;\n } else {\n if (!isFirstHunk) {\n contentChildren.push(createExpandButton('up'));\n buttonCount++;\n }\n if (!isLastHunk) {\n contentChildren.push(createExpandButton('down'));\n buttonCount++;\n }\n }\n }\n contentChildren.push(\n createHastElement({\n tagName: 'div',\n children: [\n createHastElement({\n tagName: 'span',\n children: [createTextNodeElement(content)],\n properties: { 'data-unmodified-lines': '' },\n }),\n ],\n properties: { 'data-separator-content': '' },\n })\n );\n if (chunked && expandIndex != null) {\n contentChildren.push(\n createHastElement({\n tagName: 'span',\n children: [createTextNodeElement('Expand All')],\n properties: {\n 'data-expand-button': '',\n 'data-expand-all-button': '',\n },\n })\n );\n }\n children.push(\n createHastElement({\n tagName: 'div',\n children: contentChildren,\n properties: {\n 'data-separator-wrapper': '',\n 'data-separator-multi-button': buttonCount > 1 ? '' : undefined,\n },\n })\n );\n }\n if (type === 'custom' && slotName != null) {\n children.push(\n createHastElement({\n tagName: 'slot',\n properties: { name: slotName },\n })\n );\n }\n return createHastElement({\n tagName: 'div',\n children,\n properties: {\n 'data-separator': children.length === 0 ? 'simple' : type,\n 'data-expand-index': expandIndex,\n 'data-separator-first': isFirstHunk ? '' : undefined,\n 'data-separator-last': isLastHunk ? '' : undefined,\n },\n });\n}\n"],"mappings":";;;AAmBA,SAAS,mBAAmB,MAA2B;AACrD,QAAO,kBAAkB;EACvB,SAAS;EACT,UAAU,CACR,kBAAkB;GAChB,MAAM,SAAS,SAAS,0BAA0B;GAClD,YAAY,EAAE,aAAa,IAAI;GAChC,CAAC,CACH;EACD,YAAY;GACV,sBAAsB;GACtB,oBAAoB,SAAS,SAAS,KAAK;GAC3C,kBAAkB,SAAS,OAAO,KAAK;GACvC,oBAAoB,SAAS,SAAS,KAAK;GAC5C;EACF,CAAC;;AAGJ,SAAgB,gBAAgB,EAC9B,MACA,SACA,aACA,UAAU,OACV,UACA,aACA,cACoC;CACpC,IAAI,cAAc;CAClB,MAAM,WAAW,EAAE;AACnB,KAAI,SAAS,cAAc,WAAW,KACpC,UAAS,KACP,kBAAkB;EAChB,SAAS;EACT,UAAU,CAAC,sBAAsB,QAAQ,CAAC;EAC1C,YAAY,EAAE,0BAA0B,IAAI;EAC7C,CAAC,CACH;AAEH,MAAK,SAAS,eAAe,SAAS,sBAAsB,WAAW,MAAM;EAC3E,MAAMA,kBAAoC,EAAE;AAC5C,MAAI,eAAe,KACjB,KAAI,CAAC,SAAS;AACZ,mBAAgB,KACd,mBACE,CAAC,eAAe,CAAC,aAAa,SAAS,cAAc,SAAS,KAC/D,CACF;AACD;SACK;AACL,OAAI,CAAC,aAAa;AAChB,oBAAgB,KAAK,mBAAmB,KAAK,CAAC;AAC9C;;AAEF,OAAI,CAAC,YAAY;AACf,oBAAgB,KAAK,mBAAmB,OAAO,CAAC;AAChD;;;AAIN,kBAAgB,KACd,kBAAkB;GAChB,SAAS;GACT,UAAU,CACR,kBAAkB;IAChB,SAAS;IACT,UAAU,CAAC,sBAAsB,QAAQ,CAAC;IAC1C,YAAY,EAAE,yBAAyB,IAAI;IAC5C,CAAC,CACH;GACD,YAAY,EAAE,0BAA0B,IAAI;GAC7C,CAAC,CACH;AACD,MAAI,WAAW,eAAe,KAC5B,iBAAgB,KACd,kBAAkB;GAChB,SAAS;GACT,UAAU,CAAC,sBAAsB,aAAa,CAAC;GAC/C,YAAY;IACV,sBAAsB;IACtB,0BAA0B;IAC3B;GACF,CAAC,CACH;AAEH,WAAS,KACP,kBAAkB;GAChB,SAAS;GACT,UAAU;GACV,YAAY;IACV,0BAA0B;IAC1B,+BAA+B,cAAc,IAAI,KAAK;IACvD;GACF,CAAC,CACH;;AAEH,KAAI,SAAS,YAAY,YAAY,KACnC,UAAS,KACP,kBAAkB;EAChB,SAAS;EACT,YAAY,EAAE,MAAM,UAAU;EAC/B,CAAC,CACH;AAEH,QAAO,kBAAkB;EACvB,SAAS;EACT;EACA,YAAY;GACV,kBAAkB,SAAS,WAAW,IAAI,WAAW;GACrD,qBAAqB;GACrB,wBAAwB,cAAc,KAAK;GAC3C,uBAAuB,aAAa,KAAK;GAC1C;EACF,CAAC"}
1
+ {"version":3,"file":"createSeparator.js","names":["contentChildren: ElementContent[]"],"sources":["../../src/utils/createSeparator.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement } from 'hast';\n\nimport type { ExpansionDirections, HunkSeparators } from '../types';\nimport {\n createHastElement,\n createIconElement,\n createTextNodeElement,\n} from './hast_utils';\n\ninterface CreateSeparatorProps {\n type: HunkSeparators;\n content?: string;\n expandIndex?: number;\n chunked?: boolean;\n slotName?: string;\n isFirstHunk: boolean;\n isLastHunk: boolean;\n}\n\nfunction createExpandButton(type: ExpansionDirections) {\n return createHastElement({\n tagName: 'div',\n children: [\n createIconElement({\n name: type === 'both' ? 'diffs-icon-expand-all' : 'diffs-icon-expand',\n properties: { 'data-icon': '' },\n }),\n ],\n properties: {\n role: 'button',\n 'data-expand-button': '',\n 'data-expand-both': type === 'both' ? '' : undefined,\n 'data-expand-up': type === 'up' ? '' : undefined,\n 'data-expand-down': type === 'down' ? '' : undefined,\n },\n });\n}\n\nexport function createSeparator({\n type,\n content,\n expandIndex,\n chunked = false,\n slotName,\n isFirstHunk,\n isLastHunk,\n}: CreateSeparatorProps): HASTElement {\n let buttonCount = 0;\n const children = [];\n if (type === 'metadata' && content != null) {\n children.push(\n createHastElement({\n tagName: 'div',\n children: [createTextNodeElement(content)],\n properties: { 'data-separator-wrapper': '' },\n })\n );\n }\n if ((type === 'line-info' || type === 'line-info-basic') && content != null) {\n const contentChildren: ElementContent[] = [];\n if (expandIndex != null) {\n if (!chunked) {\n contentChildren.push(\n createExpandButton(\n !isFirstHunk && !isLastHunk ? 'both' : isFirstHunk ? 'down' : 'up'\n )\n );\n buttonCount++;\n } else {\n if (!isFirstHunk) {\n contentChildren.push(createExpandButton('up'));\n buttonCount++;\n }\n if (!isLastHunk) {\n contentChildren.push(createExpandButton('down'));\n buttonCount++;\n }\n }\n }\n contentChildren.push(\n createHastElement({\n tagName: 'div',\n children: [\n createHastElement({\n tagName: 'span',\n children: [createTextNodeElement(content)],\n properties: { 'data-unmodified-lines': '' },\n }),\n ],\n properties: { 'data-separator-content': '' },\n })\n );\n if (chunked && expandIndex != null) {\n contentChildren.push(\n createHastElement({\n tagName: 'div',\n children: [createTextNodeElement('Expand all')],\n properties: {\n role: 'button',\n 'data-expand-button': '',\n 'data-expand-all-button': '',\n },\n })\n );\n }\n children.push(\n createHastElement({\n tagName: 'div',\n children: contentChildren,\n properties: {\n 'data-separator-wrapper': '',\n 'data-separator-multi-button': buttonCount > 1 ? '' : undefined,\n },\n })\n );\n }\n if (type === 'custom' && slotName != null) {\n children.push(\n createHastElement({\n tagName: 'slot',\n properties: { name: slotName },\n })\n );\n }\n return createHastElement({\n tagName: 'div',\n children,\n properties: {\n 'data-separator': children.length === 0 ? 'simple' : type,\n 'data-expand-index': expandIndex,\n 'data-separator-first': isFirstHunk ? '' : undefined,\n 'data-separator-last': isLastHunk ? '' : undefined,\n },\n });\n}\n"],"mappings":";;;AAmBA,SAAS,mBAAmB,MAA2B;AACrD,QAAO,kBAAkB;EACvB,SAAS;EACT,UAAU,CACR,kBAAkB;GAChB,MAAM,SAAS,SAAS,0BAA0B;GAClD,YAAY,EAAE,aAAa,IAAI;GAChC,CAAC,CACH;EACD,YAAY;GACV,MAAM;GACN,sBAAsB;GACtB,oBAAoB,SAAS,SAAS,KAAK;GAC3C,kBAAkB,SAAS,OAAO,KAAK;GACvC,oBAAoB,SAAS,SAAS,KAAK;GAC5C;EACF,CAAC;;AAGJ,SAAgB,gBAAgB,EAC9B,MACA,SACA,aACA,UAAU,OACV,UACA,aACA,cACoC;CACpC,IAAI,cAAc;CAClB,MAAM,WAAW,EAAE;AACnB,KAAI,SAAS,cAAc,WAAW,KACpC,UAAS,KACP,kBAAkB;EAChB,SAAS;EACT,UAAU,CAAC,sBAAsB,QAAQ,CAAC;EAC1C,YAAY,EAAE,0BAA0B,IAAI;EAC7C,CAAC,CACH;AAEH,MAAK,SAAS,eAAe,SAAS,sBAAsB,WAAW,MAAM;EAC3E,MAAMA,kBAAoC,EAAE;AAC5C,MAAI,eAAe,KACjB,KAAI,CAAC,SAAS;AACZ,mBAAgB,KACd,mBACE,CAAC,eAAe,CAAC,aAAa,SAAS,cAAc,SAAS,KAC/D,CACF;AACD;SACK;AACL,OAAI,CAAC,aAAa;AAChB,oBAAgB,KAAK,mBAAmB,KAAK,CAAC;AAC9C;;AAEF,OAAI,CAAC,YAAY;AACf,oBAAgB,KAAK,mBAAmB,OAAO,CAAC;AAChD;;;AAIN,kBAAgB,KACd,kBAAkB;GAChB,SAAS;GACT,UAAU,CACR,kBAAkB;IAChB,SAAS;IACT,UAAU,CAAC,sBAAsB,QAAQ,CAAC;IAC1C,YAAY,EAAE,yBAAyB,IAAI;IAC5C,CAAC,CACH;GACD,YAAY,EAAE,0BAA0B,IAAI;GAC7C,CAAC,CACH;AACD,MAAI,WAAW,eAAe,KAC5B,iBAAgB,KACd,kBAAkB;GAChB,SAAS;GACT,UAAU,CAAC,sBAAsB,aAAa,CAAC;GAC/C,YAAY;IACV,MAAM;IACN,sBAAsB;IACtB,0BAA0B;IAC3B;GACF,CAAC,CACH;AAEH,WAAS,KACP,kBAAkB;GAChB,SAAS;GACT,UAAU;GACV,YAAY;IACV,0BAA0B;IAC1B,+BAA+B,cAAc,IAAI,KAAK;IACvD;GACF,CAAC,CACH;;AAEH,KAAI,SAAS,YAAY,YAAY,KACnC,UAAS,KACP,kBAAkB;EAChB,SAAS;EACT,YAAY,EAAE,MAAM,UAAU;EAC/B,CAAC,CACH;AAEH,QAAO,kBAAkB;EACvB,SAAS;EACT;EACA,YAAY;GACV,kBAAkB,SAAS,WAAW,IAAI,WAAW;GACrD,qBAAqB;GACrB,wBAAwB,cAAc,KAAK;GAC3C,uBAAuB,aAAa,KAAK;GAC1C;EACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pierre/diffs",
3
- "version": "1.1.14",
3
+ "version": "1.1.16",
4
4
  "license": "apache-2.0",
5
5
  "files": [
6
6
  "dist",