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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +6 -6
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +6 -6
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +1 -0
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +26 -12
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +1 -0
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +12 -11
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.js +4 -2
  14. package/dist/components/FileStream.js.map +1 -1
  15. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  16. package/dist/components/VirtualizedFile.d.ts +5 -1
  17. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  18. package/dist/components/VirtualizedFile.js +82 -21
  19. package/dist/components/VirtualizedFile.js.map +1 -1
  20. package/dist/components/VirtualizedFileDiff.d.ts +6 -1
  21. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  22. package/dist/components/VirtualizedFileDiff.js +77 -15
  23. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  24. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  25. package/dist/editor/command.d.ts +1 -1
  26. package/dist/editor/command.d.ts.map +1 -1
  27. package/dist/editor/command.js +3 -3
  28. package/dist/editor/command.js.map +1 -1
  29. package/dist/editor/editor.d.ts +31 -5
  30. package/dist/editor/editor.d.ts.map +1 -1
  31. package/dist/editor/editor.js +240 -178
  32. package/dist/editor/editor.js.map +1 -1
  33. package/dist/editor/editor2.js +1 -1
  34. package/dist/editor/editor2.js.map +1 -1
  35. package/dist/editor/index.d.ts +2 -2
  36. package/dist/editor/marker.d.ts +2 -2
  37. package/dist/editor/marker.d.ts.map +1 -1
  38. package/dist/editor/marker.js +2 -2
  39. package/dist/editor/marker.js.map +1 -1
  40. package/dist/editor/pieceTable.d.ts +6 -1
  41. package/dist/editor/pieceTable.d.ts.map +1 -1
  42. package/dist/editor/pieceTable.js +32 -1
  43. package/dist/editor/pieceTable.js.map +1 -1
  44. package/dist/editor/searchPanel.d.ts +12 -3
  45. package/dist/editor/searchPanel.d.ts.map +1 -1
  46. package/dist/editor/searchPanel.js +168 -54
  47. package/dist/editor/searchPanel.js.map +1 -1
  48. package/dist/editor/selection.d.ts.map +1 -1
  49. package/dist/editor/sprite.d.ts +2 -2
  50. package/dist/editor/sprite.d.ts.map +1 -1
  51. package/dist/editor/sprite.js +10 -3
  52. package/dist/editor/sprite.js.map +1 -1
  53. package/dist/editor/textMeasure.d.ts +1 -0
  54. package/dist/editor/textMeasure.d.ts.map +1 -1
  55. package/dist/editor/textMeasure.js +6 -0
  56. package/dist/editor/textMeasure.js.map +1 -1
  57. package/dist/editor/tokenzier.js +9 -6
  58. package/dist/editor/tokenzier.js.map +1 -1
  59. package/dist/managers/InteractionManager.js +1 -1
  60. package/dist/managers/InteractionManager.js.map +1 -1
  61. package/dist/managers/ResizeManager.js +1 -1
  62. package/dist/managers/ResizeManager.js.map +1 -1
  63. package/dist/react/CodeView.js +1 -1
  64. package/dist/react/jsx.d.ts.map +1 -1
  65. package/dist/renderers/DiffHunksRenderer.d.ts +3 -2
  66. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  67. package/dist/renderers/DiffHunksRenderer.js +49 -2
  68. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  69. package/dist/renderers/FileRenderer.js +12 -0
  70. package/dist/renderers/FileRenderer.js.map +1 -1
  71. package/dist/ssr/FileDiffReact.js +1 -1
  72. package/dist/types.d.ts +17 -2
  73. package/dist/types.d.ts.map +1 -1
  74. package/dist/utils/includesFileAnnotations.d.ts +17 -0
  75. package/dist/utils/includesFileAnnotations.d.ts.map +1 -0
  76. package/dist/utils/includesFileAnnotations.js +19 -0
  77. package/dist/utils/includesFileAnnotations.js.map +1 -0
  78. package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
  79. package/dist/utils/renderDiffWithHighlighter.js +4 -2
  80. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  81. package/dist/utils/renderFileWithHighlighter.js +4 -2
  82. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  83. package/dist/worker/{wasm-BaDzIkIn.js → wasm-qE0LgnY3.js} +2 -2
  84. package/dist/worker/{wasm-BaDzIkIn.js.map → wasm-qE0LgnY3.js.map} +1 -1
  85. package/dist/worker/worker-portable.js +289 -253
  86. package/dist/worker/worker-portable.js.map +1 -1
  87. package/dist/worker/worker.js +8 -4
  88. package/dist/worker/worker.js.map +1 -1
  89. package/package.json +4 -10
@@ -1 +1 @@
1
- {"version":3,"file":"editor.js","names":["#fileInstance","#renderRange","#textDocument","#getLineElement","#options","#initialize","#detach","codeElement: HTMLElement | undefined","gutterEl: HTMLElement | undefined","contentEl: HTMLElement | undefined","el","#fileContainer","#globalStyleElement","#editorStyleElement","#themeStyleElement","#spriteElement","#fileContents","#tokenizer","#onDeferTokenize","#shouldIgnoreSelectionChange","#overlayElements","#selections","#scrollingToLine","#reservedSelections","#searchPanel","#selectionAction","#contentElement","#codePaddingTop","#gutterWidthCache","#contentWidthCache","#gutterElement","#overlayElement","#metrics","#listenContentElement","#lineYCache","#wrapLineOffsetsCache","#lastAccessedLineElement","#lastAccessedCharX","#wrap","#lineAnnotations","#initSelections","#scrollToPrimaryCaret","#matches","#markerManager","#updateSelections","#scrollToLine","#scrollingToLineChar","#scrollingToLineNoFocus","#retainSearchPanelFocus","#isLineVisible","#getCharX","#getLineY","#isContentMouseDown","#isGutterMouseDown","#focus","#globalEventDisposes","#editorEventDisposes","#selectEventDisposes","#primaryCaretElement","#resizeObserver","#selectionStart","editorCSS","#rangeBelongsToEditor","#shiftKeyPressed","#setWindowSelection","#runCommand","#getSelectionText","#replaceSelectionText","#handleInput","selection: EditorSelection","textDocument","lineIndex","e","selection","#handleLayoutResize","#renderSearchPanel","expanded: EditorSelection[]","edits: TextEdit[]","nextSelections: EditorSelection[]","#applyChange","#getGutterWidth","#getContentWidth","#deleteSelectionText","#deleteSoftLineBackward","#deleteHardLineForward","#deleteWordBackward","#insertTranspose","#getScrollMargin","#renderSelection","#renderCaret","#renderSelectionActionIcon","range: Range","#renderWrappedSelection","#renderSelectionBlock","#wrapLineText","segmentLeft: number","segmentWidth: number","line","wrapLine","css","left","cacheKey","initialMatch: [number, number] | undefined","nextMatch: MatchRange | undefined","#applyChangeToLineAnnotations","edit: ResolvedTextEdit","#applyResolvedTextEdit","shouldUpdateBuffer: boolean | undefined","#rerender","lineElement: HTMLElement | null","starts: number[]"],"sources":["../../src/editor/editor.ts"],"sourcesContent":["import type {\n DiffLineAnnotation,\n DiffsEditableComponent,\n DiffsEditor,\n DiffsEditorSelection,\n DiffsHighlighter,\n FileContents,\n HighlightedToken,\n LineAnnotation,\n RenderRange,\n} from '../types';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport {\n type EditorCommand,\n resolveEditorCommandFromKeyboardEvent,\n} from './command';\nimport editorCSS from './editor.css';\nimport {\n applyDocumentChangeToLineAnnotations,\n renderLineAnnotations,\n} from './lineAnnotations';\nimport { type Marker, MarkerManager, markerSeverityDatasetKey } from './marker';\nimport { isMoveCursorShortcut, isPrimaryModifier, isSafari } from './platform';\nimport { type MatchRange, SearchPanelWidget } from './searchPanel';\nimport type { EditorSelection } from './selection';\nimport {\n applyDeleteHardLineForwardToSelections,\n applyDeleteSoftLineBackwardToSelections,\n applyDeleteWordBackwardToSelections,\n applyTextChangeToSelections,\n applyTextReplaceToSelections,\n applyTransposeToSelections,\n comparePosition,\n convertSelection,\n createSelectionFrom,\n createSelectionFromAnchorAndFocusOffsets,\n DirectionBackward,\n DirectionForward,\n DirectionNone,\n expandCollapsedSelectionToWord,\n extendSelection,\n extendSelections,\n findNexMatch,\n getCaretPosition,\n getDocumentBoundarySelection,\n getDocumentFullSelection,\n getSelectionAnchor,\n getSelectionText,\n isCollapsedSelection,\n isLineEditable,\n mapCursorMove,\n mapSelectionShift,\n mergeOverlappingSelections,\n resolveIndentEdits,\n selectionIntersects,\n} from './selection';\nimport {\n type SelectionActionContext,\n SelectionActionWidget,\n} from './selectionAction';\nimport { createSpriteElement } from './sprite';\nimport {\n type Position,\n type Range,\n type ResolvedTextEdit,\n TextDocument,\n type TextDocumentChange,\n type TextEdit,\n} from './textDocument';\nimport {\n getExpandedAsciiTextColumns,\n getUnicodeMeasurementOffsets,\n Metrics,\n snapTextOffsetToUnicodeBoundary,\n} from './textMeasure';\nimport { EditorTokenizer, renderLineTokens } from './tokenzier';\nimport {\n addEventListener,\n clampDomOffset,\n extend,\n getLineNumberAttr,\n h,\n round,\n} from './utils';\n\nexport interface EditorOptions<LAnnotation> {\n /** Render rounded corners for selection ranges, default is true. */\n roundedSelection?: boolean;\n /** Show the clickable selection action icon, default is disabled. */\n enabledSelectionAction?: boolean;\n /** Render the selection action widget element. */\n renderSelectionAction?: (\n context: SelectionActionContext<LAnnotation>\n ) => HTMLElement;\n /** Callback when the editor document changes. */\n onChange?: (\n file: FileContents,\n lineAnnotations?: DiffLineAnnotation<LAnnotation>[] | LineAnnotation<any>[]\n ) => void;\n __debug?: boolean;\n}\n\nexport class Editor<LAnnotation> implements DiffsEditor<LAnnotation> {\n #options: EditorOptions<LAnnotation>;\n #wrap = false;\n #metrics = new Metrics();\n #tokenizer?: EditorTokenizer;\n #markerManager?: MarkerManager;\n\n // event disposes\n #editorEventDisposes?: (() => void)[];\n #globalEventDisposes?: (() => void)[];\n #selectEventDisposes?: (() => void)[];\n #detach?: () => void;\n\n // file\n #fileInstance?: DiffsEditableComponent<LAnnotation>;\n #fileContents?: FileContents;\n #lineAnnotations?: DiffLineAnnotation<LAnnotation>[];\n #textDocument?: TextDocument<LAnnotation>;\n #renderRange?: RenderRange;\n\n // cache\n #codePaddingTop = 0;\n #gutterWidthCache?: number;\n #contentWidthCache?: number;\n #lineYCache = new Map<number, number>();\n #wrapLineOffsetsCache = new Map<number, Uint32Array>();\n #lastAccessedLineElement?: [number, HTMLElement];\n #lastAccessedCharX?: [\n line: number,\n character: number,\n x: number,\n wrapLine: number,\n ];\n\n // dom\n #globalStyleElement?: HTMLStyleElement;\n #editorStyleElement?: HTMLStyleElement;\n #themeStyleElement?: HTMLStyleElement;\n #spriteElement?: SVGSVGElement;\n #fileContainer?: HTMLElement;\n #gutterElement?: HTMLElement;\n #contentElement?: HTMLElement;\n #overlayElement?: HTMLElement;\n #primaryCaretElement?: HTMLElement;\n #overlayElements?: Map<string, HTMLElement>;\n #selectionAction?: SelectionActionWidget;\n #searchPanel?: SearchPanelWidget;\n #resizeObserver?: ResizeObserver;\n\n // state\n #shouldIgnoreSelectionChange = false;\n #isGutterMouseDown = false;\n #isContentMouseDown = false;\n #shiftKeyPressed = false;\n #selectionStart: EditorSelection | undefined;\n #reservedSelections?: EditorSelection[];\n #selections?: EditorSelection[];\n #initSelections?: DiffsEditorSelection[];\n #matches?: MatchRange[];\n #scrollingToLine?: number;\n #scrollingToLineChar?: number;\n #scrollingToLineNoFocus = false;\n #retainSearchPanelFocus = false;\n\n #onDeferTokenize = (\n lines: Map<number, Array<HighlightedToken>>,\n themeType: 'light' | 'dark'\n ) => {\n this.#fileInstance?.updateRenderCache(lines, themeType);\n // update the view if the render range is updated by scrolling\n // and the deferred tokenized lines inside the render range\n if (\n this.#renderRange !== undefined &&\n this.#renderRange.totalLines !== Infinity\n ) {\n const { startingLine, totalLines } = this.#renderRange;\n const endLine = Math.min(\n startingLine + totalLines,\n this.#textDocument?.lineCount ?? 0\n );\n for (const [line, tokens] of lines) {\n if (line >= startingLine && line < endLine) {\n const lineElement = this.#getLineElement(line);\n if (lineElement !== undefined) {\n lineElement.replaceChildren(...renderLineTokens(tokens, themeType));\n }\n }\n }\n }\n };\n\n constructor(options: EditorOptions<LAnnotation> = {}) {\n this.#options = options;\n }\n\n edit(component: DiffsEditableComponent<LAnnotation>): () => void {\n const {\n useTokenTransformer,\n enableGutterUtility,\n enableLineSelection,\n expandUnchanged,\n diffStyle,\n lineHoverHighlight,\n ...rest\n } = component.options;\n const isDiff = Object.hasOwn(component, 'fileDiff');\n if (\n useTokenTransformer !== true ||\n enableGutterUtility === true ||\n enableLineSelection === true ||\n (expandUnchanged !== true && isDiff) ||\n diffStyle === 'unified' ||\n lineHoverHighlight !== 'disabled'\n ) {\n component.setOptions({\n ...rest,\n useTokenTransformer: true,\n enableGutterUtility: false,\n enableLineSelection: false,\n expandUnchanged: true,\n diffStyle: 'split',\n lineHoverHighlight: 'disabled',\n });\n component.rerender();\n }\n this.#fileInstance = component;\n this.#initialize();\n this.#detach = component.attachEditor(this);\n return () => this.cleanUp();\n }\n\n syncToRenderedView(\n highlighter: DiffsHighlighter,\n fileContainer: HTMLElement,\n fileContents: FileContents,\n didFileChange: boolean,\n lineAnnotations: DiffLineAnnotation<LAnnotation>[] | undefined,\n renderRange: RenderRange | undefined\n ): void {\n const shadowRoot = fileContainer.shadowRoot;\n if (shadowRoot == null) {\n console.error('[editor] Could not find the shadow root.');\n return;\n }\n\n let codeElement: HTMLElement | undefined;\n let gutterEl: HTMLElement | undefined;\n let contentEl: HTMLElement | undefined;\n for (const el of shadowRoot.querySelectorAll<HTMLElement>('[data-code]')) {\n if (el.dataset.deletions === undefined) {\n codeElement = el;\n for (const child of el.children) {\n const el = child as HTMLElement;\n const { gutter, content } = el.dataset;\n if (gutter !== undefined) {\n gutterEl = el;\n } else if (content !== undefined) {\n contentEl = el;\n }\n }\n break;\n }\n }\n if (codeElement === undefined || contentEl === undefined) {\n return;\n }\n\n // inject editor&theme style to the file container\n if (this.#fileContainer !== fileContainer) {\n this.#fileContainer = fileContainer;\n if (this.#globalStyleElement !== undefined) {\n fileContainer.appendChild(this.#globalStyleElement);\n }\n if (this.#editorStyleElement !== undefined) {\n shadowRoot.appendChild(this.#editorStyleElement);\n }\n if (this.#themeStyleElement !== undefined) {\n shadowRoot.appendChild(this.#themeStyleElement);\n }\n if (this.#spriteElement !== undefined) {\n shadowRoot.prepend(this.#spriteElement);\n }\n }\n\n if (\n this.#textDocument === undefined ||\n this.#fileContents === undefined ||\n didFileChange\n ) {\n const textDocument = new TextDocument<LAnnotation>(\n fileContents.name,\n fileContents.contents,\n fileContents.lang ?? getFiletypeFromFileName(fileContents.name)\n );\n this.#fileContents = fileContents;\n this.#textDocument = textDocument;\n this.#tokenizer?.cleanUp();\n this.#tokenizer = new EditorTokenizer({\n highlighter,\n textDocument,\n codeOptions: this.#fileInstance?.options ?? {},\n onDeferTokenize: this.#onDeferTokenize,\n setStyle: (css) => {\n this.#themeStyleElement!.textContent = css;\n },\n __debug: this.#options.__debug,\n });\n this.#fileInstance?.setSelectedLines(null);\n this.#shouldIgnoreSelectionChange = false;\n this.#overlayElements?.forEach((el) => el.remove());\n this.#overlayElements?.clear();\n this.#overlayElements = undefined;\n this.#selections = undefined;\n this.#scrollingToLine = undefined;\n this.#reservedSelections = undefined;\n this.#searchPanel?.cleanup();\n this.#searchPanel = undefined;\n this.#selectionAction?.cleanup();\n this.#selectionAction = undefined;\n }\n\n if (this.#contentElement !== contentEl) {\n if (\n this.#contentElement !== undefined &&\n this.#options.__debug === true\n ) {\n console.log('[diffs/editor] full re-render triggered !!!');\n }\n const codePaddingTop = parseInt(\n getComputedStyle(codeElement).paddingTop.slice(0, -2),\n 10\n );\n this.#codePaddingTop = Number.isNaN(codePaddingTop) ? 0 : codePaddingTop;\n this.#gutterWidthCache = undefined;\n this.#contentWidthCache = undefined;\n this.#gutterElement = gutterEl;\n this.#contentElement = extend(contentEl, {\n contentEditable: 'true',\n role: 'textbox',\n ariaMultiLine: 'true',\n autocapitalize: 'off',\n writingSuggestions: 'off',\n autocorrect: false,\n spellcheck: false,\n translate: false,\n });\n if (this.#overlayElement !== undefined) {\n contentEl.after(this.#overlayElement);\n }\n this.#metrics.init(contentEl);\n this.#listenContentElement(contentEl, gutterEl);\n }\n\n this.#lineYCache.clear();\n this.#wrapLineOffsetsCache.clear();\n this.#lastAccessedLineElement = undefined;\n this.#lastAccessedCharX = undefined;\n\n this.#wrap = this.#fileInstance?.options.overflow === 'wrap';\n this.#lineAnnotations = lineAnnotations;\n this.#renderRange = renderRange;\n this.#tokenizer?.prebuildStateStack(renderRange);\n\n if (this.#initSelections !== undefined) {\n this.setSelections(this.#initSelections);\n this.#scrollToPrimaryCaret();\n this.#initSelections = undefined;\n } else if (\n this.#selections !== undefined ||\n this.#matches !== undefined ||\n this.#markerManager !== undefined\n ) {\n // when re-rendering triggered by virtual viewport scroll,\n // re-render the existing selections, matches, and markers\n this.#updateSelections(this.#selections ?? []);\n }\n\n if (this.#options.__debug === true && renderRange !== undefined) {\n const { startingLine, totalLines } = renderRange;\n console.log(\n '[diffs/editor] render file:',\n fileContents.name,\n 'RenderRange:',\n startingLine + '-' + (startingLine + totalLines),\n 'of',\n this.#textDocument.lineCount,\n 'lines'\n );\n }\n\n if (this.#scrollingToLine !== undefined) {\n this.#scrollToLine(\n this.#scrollingToLine,\n this.#scrollingToLineChar,\n this.#scrollingToLineNoFocus\n );\n } else if (\n this.#selections !== undefined &&\n this.#selections.length > 0 &&\n !this.#retainSearchPanelFocus\n ) {\n this.focus({ preventScroll: true });\n }\n\n if (this.#retainSearchPanelFocus) {\n this.#searchPanel?.focus();\n }\n\n if (\n this.#selectionAction !== undefined &&\n this.#isLineVisible(this.#selectionAction.line) &&\n this.#contentElement !== undefined\n ) {\n this.#selectionAction.render(this.#contentElement);\n }\n }\n\n postponeBackgroundTokenizeToNextFrame(): void {\n const tokenizer = this.#tokenizer;\n if (tokenizer !== undefined) {\n tokenizer.pauseBackgroundTokenize();\n requestAnimationFrame(() => {\n tokenizer.resumeBackgroundTokenize();\n });\n }\n }\n\n setSelections(selections: DiffsEditorSelection[]): void {\n const textDocument = this.#textDocument;\n if (textDocument !== undefined) {\n const resolvedSelections = selections.map<EditorSelection>(\n (selection) => {\n const start = textDocument.normalizePosition(selection.start);\n const end = textDocument.normalizePosition(selection.end);\n const direction =\n selection.direction === 'none'\n ? DirectionNone\n : selection.direction === 'backward'\n ? DirectionBackward\n : DirectionForward;\n return { direction, start, end };\n }\n );\n this.#updateSelections(resolvedSelections);\n this.#scrollToPrimaryCaret();\n } else {\n this.#initSelections = selections;\n }\n }\n\n setMarkers(markers: Marker[]): void {\n const textDocument = this.#textDocument;\n if (textDocument === undefined) {\n throw new Error('Text document is not initialized');\n }\n\n if (markers.length === 0) {\n this.#markerManager?.cleanup();\n this.#markerManager = undefined;\n this.#updateSelections(this.#selections ?? []);\n return;\n }\n\n this.#markerManager ??= new MarkerManager({\n getLineHeight: () => this.#metrics.lineHeight,\n getFileContainer: () => this.#fileContainer,\n getCharX: (line, character) => this.#getCharX(line, character),\n getLineY: (line) => this.#getLineY(line),\n isMouseDown: () => this.#isContentMouseDown || this.#isGutterMouseDown,\n });\n this.#markerManager.setMarkers(markers, textDocument);\n if (this.#contentElement !== undefined) {\n this.#markerManager.listenHover(this.#contentElement);\n }\n this.#updateSelections(this.#selections ?? []);\n }\n\n focus(options?: FocusOptions): void {\n const preventScroll = options?.preventScroll ?? false;\n const primarySelection = this.#selections?.at(-1);\n if (primarySelection !== undefined) {\n const pos =\n primarySelection.direction === DirectionBackward\n ? primarySelection.end\n : primarySelection.start;\n this.#focus(pos, preventScroll);\n } else {\n this.#focus(undefined, preventScroll);\n }\n }\n\n cleanUp(): void {\n this.#tokenizer?.cleanUp();\n this.#tokenizer = undefined;\n\n this.#globalEventDisposes?.forEach((dispose) => dispose());\n this.#globalEventDisposes = undefined;\n this.#editorEventDisposes?.forEach((dispose) => dispose());\n this.#editorEventDisposes = undefined;\n this.#selectEventDisposes?.forEach((dispose) => dispose());\n this.#selectEventDisposes = undefined;\n this.#markerManager?.cleanup();\n this.#markerManager = undefined;\n\n this.#detach?.();\n this.#detach = undefined;\n this.#fileInstance?.setSelectedLines(null);\n this.#fileInstance = undefined;\n this.#fileContents = undefined;\n this.#lineAnnotations = undefined;\n this.#textDocument = undefined;\n this.#renderRange = undefined;\n\n this.#gutterWidthCache = undefined;\n this.#contentWidthCache = undefined;\n this.#lineYCache.clear();\n this.#wrapLineOffsetsCache.clear();\n this.#lastAccessedLineElement = undefined;\n this.#lastAccessedCharX = undefined;\n\n this.#globalStyleElement?.remove();\n this.#globalStyleElement = undefined;\n this.#editorStyleElement?.remove();\n this.#editorStyleElement = undefined;\n this.#themeStyleElement?.remove();\n this.#themeStyleElement = undefined;\n this.#spriteElement?.remove();\n this.#spriteElement = undefined;\n this.#fileContainer = undefined;\n this.#gutterElement = undefined;\n this.#contentElement?.removeAttribute('contentEditable');\n this.#contentElement = undefined;\n this.#overlayElement?.remove();\n this.#overlayElement = undefined;\n this.#overlayElements?.forEach((el) => el.remove());\n this.#overlayElements = undefined;\n this.#primaryCaretElement = undefined;\n this.#searchPanel?.cleanup();\n this.#searchPanel = undefined;\n this.#selectionAction?.cleanup();\n this.#selectionAction = undefined;\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = undefined;\n\n this.#shouldIgnoreSelectionChange = false;\n this.#selectionStart = undefined;\n this.#selections = undefined;\n this.#reservedSelections = undefined;\n }\n\n #initialize(): void {\n // Safari doesn't support `::selection` for slot elements in ShadowDOM,\n // Add a global style to disable selection for slot elements\n this.#globalStyleElement = h('style', {\n dataset: 'editorGlobalCss',\n textContent: `\n [data-annotation-slot] {\n user-select: none;\n -webkit-user-select: none;\n }\n `,\n });\n\n this.#editorStyleElement = h('style', {\n dataset: 'editorCss',\n textContent: editorCSS,\n });\n\n this.#themeStyleElement = h('style', {\n dataset: 'editorThemeCss',\n });\n\n this.#spriteElement = createSpriteElement();\n\n this.#overlayElement = h('div', {\n dataset: 'editorOverlay',\n });\n\n this.#globalEventDisposes = [\n addEventListener(\n document,\n 'selectionchange',\n () => {\n const shadowRoot = this.#fileContainer?.shadowRoot;\n if (this.#shouldIgnoreSelectionChange || shadowRoot == null) {\n return;\n }\n\n // Native selection only tracks one range. focus() and DOM updates while\n // typing mirror the primary caret there, so selectionchange must not\n // overwrite multi-cursor editor state outside an active pointer gesture.\n if (\n this.#selections !== undefined &&\n this.#selections.length > 1 &&\n !this.#isContentMouseDown\n ) {\n return;\n }\n\n const selectionRaw = document.getSelection();\n const composedRange = selectionRaw?.getComposedRanges({\n shadowRoots: [shadowRoot],\n })?.[0];\n if (\n composedRange === undefined ||\n !this.#rangeBelongsToEditor(composedRange)\n ) {\n return;\n }\n\n let selection = convertSelection(composedRange, DirectionNone);\n if (selection === undefined) {\n return;\n }\n\n // extend selection by shift + click\n if (\n this.#isContentMouseDown &&\n this.#shiftKeyPressed &&\n this.#selections !== undefined &&\n this.#selections.length > 0\n ) {\n const primarySelection = this.#selections.at(-1)!;\n this.#updateSelections([\n extendSelection(primarySelection, selection),\n ]);\n return;\n }\n\n if (this.#isContentMouseDown) {\n if (this.#selectionStart !== undefined) {\n selection = createSelectionFrom(this.#selectionStart, selection);\n } else {\n this.#selectionStart = selection;\n }\n } else if (this.#selectionStart !== undefined) {\n selection.direction = createSelectionFrom(\n this.#selectionStart,\n selection\n ).direction;\n }\n\n if (this.#reservedSelections !== undefined) {\n this.#updateSelections([\n ...this.#reservedSelections.filter(\n (reservedSelection) =>\n !selectionIntersects(reservedSelection, selection)\n ),\n selection,\n ]);\n } else {\n this.#updateSelections([selection]);\n }\n },\n { passive: true }\n ),\n\n addEventListener(\n document,\n 'pointerup',\n (e) => {\n if (e.pointerType !== 'mouse') {\n return;\n }\n\n this.#selectEventDisposes?.forEach((dispose) => dispose());\n this.#selectEventDisposes = undefined;\n\n if (this.#isGutterMouseDown) {\n this.#isGutterMouseDown = false;\n this.#focus();\n }\n this.#shouldIgnoreSelectionChange = false;\n this.#isContentMouseDown = false;\n this.#shiftKeyPressed = false;\n this.#selectionStart = undefined;\n this.#reservedSelections = undefined;\n this.#overlayElements?.forEach((el, key) => {\n if (key.startsWith('selectionActionIcon-')) {\n el.dataset.visible = 'true';\n }\n });\n },\n { passive: true }\n ),\n\n addEventListener(\n document,\n 'keydown',\n (e) => {\n if (e.key === 'Shift') {\n this.#selectionStart = this.#selections?.at(-1);\n }\n },\n { passive: true }\n ),\n\n addEventListener(\n document,\n 'keyup',\n (e) => {\n if (e.key === 'Shift') {\n this.#selectionStart = undefined;\n }\n },\n { passive: true }\n ),\n ];\n }\n\n #listenContentElement(contentEl: HTMLElement, gutterEl?: HTMLElement): void {\n const targetIsContentElement = (e: Event) => {\n const target = e.composedPath()[0] as HTMLElement | undefined;\n return (\n target !== undefined &&\n (target === contentEl || contentEl.contains(target))\n );\n };\n\n this.#editorEventDisposes?.forEach((dispose) => dispose());\n this.#editorEventDisposes = [\n addEventListener(\n contentEl,\n 'pointerdown',\n (e) => {\n if (e.pointerType !== 'mouse') {\n return;\n }\n\n this.#markerManager?.removePopup();\n\n // this is a workaround for the selection rendering glitch\n // happens when selecting content in shadow DOM on Safari\n if (\n isSafari() &&\n this.#lineAnnotations !== undefined &&\n this.#lineAnnotations.length > 0\n ) {\n this.#selectEventDisposes = [\n ...contentEl.querySelectorAll<HTMLElement>(\n '[data-line-annotation]'\n ),\n ]\n .map((el) => [\n addEventListener(el, 'mouseenter', () => {\n this.#shouldIgnoreSelectionChange = true;\n }),\n addEventListener(el, 'mouseleave', () => {\n this.#shouldIgnoreSelectionChange = false;\n }),\n ])\n .flat();\n }\n\n this.#isContentMouseDown = true;\n this.#selectionStart = undefined;\n if (e.button === 0 && isPrimaryModifier(e)) {\n this.#reservedSelections = this.#selections?.map((selection) => ({\n ...selection,\n }));\n }\n if (e.shiftKey) {\n const primarySelection = this.#selections?.at(-1);\n if (primarySelection !== undefined) {\n const pos =\n primarySelection.direction === DirectionBackward\n ? primarySelection.end\n : primarySelection.start;\n // fix the window selection for shift mode\n this.#setWindowSelection({\n start: pos,\n end: pos,\n direction: DirectionNone,\n });\n }\n this.#shiftKeyPressed = true;\n }\n },\n { passive: true }\n ),\n\n addEventListener(contentEl, 'keydown', (e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n this.#searchPanel?.cleanup();\n this.#searchPanel = undefined;\n this.#retainSearchPanelFocus = false;\n this.#selectionAction?.cleanup();\n this.#selectionAction = undefined;\n if (this.#selections !== undefined && this.#selections.length > 0) {\n const primarySelection = this.#selections.at(-1)!;\n if (\n !isCollapsedSelection(primarySelection) ||\n this.#selections.length > 1\n ) {\n const pos = getCaretPosition(primarySelection);\n this.#updateSelections([\n {\n start: pos,\n end: pos,\n direction: DirectionNone,\n },\n ]);\n this.#focus(pos);\n }\n }\n return;\n }\n if (!targetIsContentElement(e)) {\n return;\n }\n\n // handle the cursor move events manually for multiple selections and virtual viewport\n const mvShortcut = isMoveCursorShortcut(e);\n const textDocument = this.#textDocument;\n if (\n this.#selections !== undefined &&\n this.#selections.length > 0 &&\n mvShortcut !== undefined &&\n textDocument !== undefined\n ) {\n if (e.shiftKey) {\n this.#updateSelections(\n mapSelectionShift(textDocument, this.#selections, mvShortcut)\n );\n } else {\n this.#updateSelections(\n mapCursorMove(textDocument, this.#selections, mvShortcut)\n );\n }\n this.#scrollToPrimaryCaret();\n e.preventDefault();\n return;\n }\n\n const command = resolveEditorCommandFromKeyboardEvent(e);\n if (command !== undefined) {\n e.preventDefault();\n this.#runCommand(command);\n }\n }),\n\n addEventListener(contentEl, 'copy', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n e.clipboardData?.setData('text', this.#getSelectionText());\n }),\n\n addEventListener(contentEl, 'cut', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n e.clipboardData?.setData('text', this.#getSelectionText());\n this.#replaceSelectionText('');\n }),\n\n addEventListener(contentEl, 'paste', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n const text = e.clipboardData?.getData('text');\n if (text !== undefined) {\n // TODO(@ije): Add support of multiple selections copy&paste\n // TODO(@ije): normalize the pasted text with textDocument.EOF\n this.#replaceSelectionText(text);\n }\n }),\n\n addEventListener(contentEl, 'beforeinput', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n this.#handleInput(e.inputType, e.data);\n }),\n\n addEventListener(contentEl, 'drop', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n // TODO(@ije): Add support of drag move selection\n }),\n\n addEventListener(\n contentEl,\n 'compositionstart',\n (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n this.#shouldIgnoreSelectionChange = true;\n },\n { passive: true }\n ),\n\n addEventListener(\n contentEl,\n 'compositionend',\n (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n this.#shouldIgnoreSelectionChange = false;\n this.#handleInput('insertText', e.data);\n },\n { passive: true }\n ),\n ];\n if (gutterEl !== undefined) {\n const resolveGutterTarget = (\n eventTarget: HTMLElement | undefined,\n includeContentLine = false\n ) => {\n let target = eventTarget;\n if (target?.dataset.lineNumberContent !== undefined) {\n target = target.parentElement ?? undefined;\n } else if (includeContentLine && target?.tagName === 'SPAN') {\n target = target.closest('[data-line]') as HTMLElement | undefined;\n }\n return target;\n };\n\n const resolveEditableLine = (target: HTMLElement | undefined) => {\n if (target === undefined) {\n return;\n }\n const lineType = target.dataset.lineType;\n const lineNumber =\n getLineNumberAttr(target) ??\n getLineNumberAttr(target, 'columnNumber');\n if (\n lineNumber === undefined ||\n lineType === undefined ||\n !isLineEditable(lineType)\n ) {\n return;\n }\n return lineNumber - 1;\n };\n\n this.#editorEventDisposes.push(\n addEventListener(\n gutterEl,\n 'pointerdown',\n (e) => {\n const textDocument = this.#textDocument;\n const lineIndex = resolveEditableLine(\n resolveGutterTarget(\n e.composedPath()[0] as HTMLElement | undefined\n )\n );\n if (lineIndex === undefined || textDocument === undefined) {\n return;\n }\n\n this.#markerManager?.removePopup();\n const selection: EditorSelection = {\n start: { line: lineIndex, character: 0 },\n end: {\n line: lineIndex,\n character: textDocument.getLineText(lineIndex).length,\n },\n direction: DirectionForward,\n };\n this.#isGutterMouseDown = true;\n this.#selectionStart = selection;\n this.#updateSelections([selection]);\n this.#focus(selection.end);\n this.#selectEventDisposes = [\n addEventListener(\n document,\n 'mousemove',\n (e) => {\n if (!this.#isGutterMouseDown) {\n return;\n }\n const textDocument = this.#textDocument;\n const lineIndex = resolveEditableLine(\n resolveGutterTarget(\n e.composedPath()[0] as HTMLElement | undefined,\n true\n )\n );\n if (lineIndex === undefined || textDocument === undefined) {\n return;\n }\n\n let selection: EditorSelection = {\n start: { line: lineIndex, character: 0 },\n end: {\n line: lineIndex,\n character: textDocument.getLineText(lineIndex).length,\n },\n direction: DirectionForward,\n };\n if (this.#selectionStart !== undefined) {\n selection = createSelectionFrom(\n this.#selectionStart,\n selection\n );\n } else {\n this.#selectionStart = selection;\n }\n this.#updateSelections([selection]);\n this.#focus(selection.end);\n },\n { passive: true }\n ),\n ];\n },\n { passive: true }\n )\n );\n }\n\n this.#markerManager?.listenHover(contentEl);\n\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = new ResizeObserver(() => {\n this.#handleLayoutResize();\n });\n this.#resizeObserver.observe(contentEl);\n this.#resizeObserver.observe(contentEl.parentElement!);\n }\n\n // TODO(@ije): add command registry\n #runCommand(command: EditorCommand) {\n const textDocument = this.#textDocument;\n if (textDocument === undefined) {\n return;\n }\n\n switch (command) {\n case 'openSearchPanel':\n this.#renderSearchPanel();\n break;\n\n case 'findNextMatch': {\n const selections = this.#selections;\n if (selections === undefined) {\n break;\n }\n const hasCollapsed = selections.some(isCollapsedSelection);\n if (hasCollapsed) {\n const expanded: EditorSelection[] = selections.map((sel) => {\n if (isCollapsedSelection(sel)) {\n return expandCollapsedSelectionToWord(textDocument, sel);\n }\n return sel;\n });\n this.#updateSelections(expanded);\n this.focus();\n } else {\n const nextMatch = findNexMatch(textDocument, selections);\n if (nextMatch !== undefined) {\n this.#updateSelections(nextMatch);\n this.#scrollToPrimaryCaret();\n }\n }\n break;\n }\n\n case 'indent':\n case 'outdent':\n if (this.#selections !== undefined) {\n const edits: TextEdit[] = [];\n const nextSelections: EditorSelection[] = [];\n for (const selection of this.#selections) {\n const startLine = selection.start.line;\n const outdent = command === 'outdent';\n if (startLine !== selection.end.line || outdent) {\n const ret = resolveIndentEdits(\n textDocument,\n selection,\n this.#metrics.tabSize,\n outdent\n );\n edits.push(...ret[0]);\n nextSelections.push(ret[1]);\n } else {\n const lineChar0 = textDocument.charAt({\n line: startLine,\n character: 0,\n });\n this.#replaceSelectionText(\n lineChar0 === '\\t' ? '\\t' : ' '.repeat(this.#metrics.tabSize)\n );\n }\n }\n const change = textDocument.applyEdits(\n edits,\n true,\n this.#selections,\n nextSelections\n );\n if (change !== undefined) {\n this.#applyChange(change, nextSelections);\n }\n }\n break;\n\n case 'selectAll':\n this.#updateSelections([getDocumentFullSelection(textDocument)]);\n this.focus();\n break;\n\n case 'moveCursorToDocStart':\n case 'moveCursorToDocEnd':\n {\n const atEnd = command === 'moveCursorToDocEnd';\n this.#updateSelections([\n getDocumentBoundarySelection(textDocument, atEnd),\n ]);\n this.#scrollToPrimaryCaret();\n }\n break;\n\n case 'expandSelectionDocStart':\n case 'expandSelectionDocEnd':\n {\n const atEnd = command === 'expandSelectionDocEnd';\n const selections = this.#selections;\n if (selections !== undefined) {\n this.#updateSelections(\n extendSelections(\n selections,\n getDocumentBoundarySelection(textDocument, atEnd)\n )\n );\n this.#scrollToPrimaryCaret();\n }\n }\n break;\n\n case 'undo':\n if (this.#textDocument?.canUndo === true) {\n const undoResult = this.#textDocument.undo();\n if (undoResult !== undefined) {\n this.#applyChange(...undoResult);\n }\n }\n break;\n\n case 'redo':\n if (this.#textDocument?.canRedo === true) {\n const redoResult = this.#textDocument.redo();\n if (redoResult !== undefined) {\n this.#applyChange(...redoResult);\n }\n }\n break;\n }\n }\n\n #handleLayoutResize() {\n const lineAnnotations = this.#lineAnnotations?.length ?? 0;\n const prevGutterWidth = this.#gutterWidthCache;\n const prevContentWidth = this.#contentWidthCache;\n this.#gutterWidthCache = undefined;\n this.#contentWidthCache = undefined;\n const gutterWidthChanged = this.#getGutterWidth() !== prevGutterWidth;\n const contentWidthChanged = this.#getContentWidth() !== prevContentWidth;\n if (!gutterWidthChanged && !contentWidthChanged) {\n return;\n }\n\n this.#lastAccessedLineElement = undefined;\n this.#lastAccessedCharX = undefined;\n if (contentWidthChanged && (this.#wrap || lineAnnotations > 0)) {\n this.#lineYCache.clear();\n this.#wrapLineOffsetsCache.clear();\n }\n if (\n this.#selections !== undefined ||\n this.#matches !== undefined ||\n this.#markerManager !== undefined\n ) {\n this.#updateSelections(this.#selections ?? []);\n if (this.#selections !== undefined) {\n this.focus();\n }\n }\n this.#markerManager?.removePopup();\n }\n\n #rerender(\n change: TextDocumentChange,\n newLineAnnotations?: DiffLineAnnotation<LAnnotation>[],\n renderRange = this.#renderRange,\n shouldUpdateBuffer?: boolean\n ) {\n const tokenizer = this.#tokenizer;\n const fileInstance = this.#fileInstance;\n const fileContents = this.#fileContents;\n const textDocument = this.#textDocument;\n const gutterEl = this.#gutterElement;\n const contentEl = this.#contentElement;\n if (\n tokenizer === undefined ||\n fileInstance === undefined ||\n fileContents === undefined ||\n textDocument === undefined ||\n contentEl === undefined\n ) {\n return;\n }\n\n // cancel existing background tokenzier task\n tokenizer.stopBackgroundTokenize();\n\n const t = performance.now();\n const dirtyLines = tokenizer.tokenize(change, renderRange);\n const t2 = performance.now();\n\n if (dirtyLines.size > 0) {\n const children = contentEl.children;\n const dirtyLineIndexes = new Set<number>(dirtyLines.keys());\n\n // update line elements that have been changed in the document\n const startingLine = renderRange?.startingLine ?? 0;\n for (let i = change.startLine - startingLine; i < children.length; i++) {\n const child = children[i] as HTMLElement | undefined;\n if (child !== undefined) {\n const lineNumber = getLineNumberAttr(child);\n if (lineNumber !== undefined) {\n const lineIndex = lineNumber - 1;\n if (dirtyLines.has(lineIndex)) {\n const tokens = dirtyLines.get(lineIndex)!;\n child.replaceChildren(\n ...renderLineTokens(tokens, tokenizer.themeType)\n );\n dirtyLineIndexes.delete(lineIndex);\n if (dirtyLineIndexes.size === 0) {\n break;\n }\n }\n }\n }\n }\n\n // create new line elements for the new lines\n if (dirtyLineIndexes.size > 0) {\n for (const lineIndex of dirtyLineIndexes) {\n const tokens = dirtyLines.get(lineIndex)!;\n const lineNumber = String(lineIndex + 1);\n h(\n 'div',\n {\n dataset: {\n line: lineNumber,\n lineType: 'context',\n lineIndex: lineIndex.toString(),\n },\n // oxlint-disable-next-line react/no-children-prop\n children: renderLineTokens(tokens, tokenizer.themeType),\n },\n contentEl\n );\n if (gutterEl !== undefined) {\n h(\n 'div',\n {\n dataset: {\n lineType: 'context',\n columnNumber: lineNumber,\n lineIndex: lineIndex.toString(),\n },\n // oxlint-disable-next-line react/no-children-prop\n children: [\n h('span', {\n dataset: {\n lineNumberContent: '',\n },\n textContent: lineNumber,\n }),\n ],\n },\n gutterEl\n );\n }\n }\n }\n }\n\n // remove line elements that have been deleted in the document\n if (change.lineDelta < 0) {\n for (const children of [contentEl.children, gutterEl?.children ?? []]) {\n for (let i = children.length - 1; i >= 0; i--) {\n const child = children[i] as HTMLElement;\n const lineNumber =\n getLineNumberAttr(child) ??\n getLineNumberAttr(child, 'columnNumber');\n if (lineNumber === undefined) {\n continue;\n }\n if (lineNumber - 1 < change.lineCount) {\n break;\n }\n child.remove();\n }\n }\n }\n\n const isDiff = Object.hasOwn(fileInstance, 'fileDiff');\n const didLineCountChange = change.lineDelta !== 0;\n\n // fix grid layout\n if (didLineCountChange) {\n let gridRow = contentEl.children.length;\n for (const child of contentEl.children) {\n const { bufferSize } = (child as HTMLElement).dataset;\n if (bufferSize !== undefined) {\n gridRow += parseInt(bufferSize) - 1;\n }\n }\n contentEl.style.gridRow = 'span ' + gridRow;\n if (gutterEl !== undefined) {\n gutterEl.style.gridRow = 'span ' + gridRow;\n }\n }\n\n fileInstance.updateRenderCache(\n dirtyLines,\n tokenizer.themeType,\n isDiff ? !didLineCountChange : undefined\n );\n if (didLineCountChange) {\n fileInstance.applyDocumentChange(\n textDocument,\n newLineAnnotations,\n shouldUpdateBuffer\n );\n }\n\n if (newLineAnnotations !== undefined) {\n this.#lineAnnotations = newLineAnnotations;\n renderLineAnnotations(newLineAnnotations, contentEl, gutterEl);\n }\n\n if (this.#options.__debug === true) {\n console.log(\n `[diffs/editor] re-render in: ${round(performance.now() - t2)}ms,`,\n `tokenize in: ${round(t2 - t)}ms (${dirtyLines.size} dirty lines)`\n );\n }\n }\n\n // input type doc: https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/inputType\n #handleInput(inputType: string, data: string | null) {\n switch (inputType) {\n case 'insertText':\n this.#replaceSelectionText(data ?? '');\n break;\n case 'insertParagraph':\n // TODO(@ije): use document.EOF instead of '\\n'\n this.#replaceSelectionText('\\n');\n break;\n case 'deleteContentBackward':\n this.#deleteSelectionText();\n break;\n case 'deleteContentForward':\n this.#deleteSelectionText(true);\n break;\n case 'deleteSoftLineBackward':\n this.#deleteSoftLineBackward();\n break;\n case 'deleteHardLineForward':\n // TODO(@ije): Safari and Firefox does not support this input type\n // use command instead\n this.#deleteHardLineForward();\n break;\n case 'deleteWordBackward':\n this.#deleteWordBackward();\n break;\n case 'insertTranspose':\n this.#insertTranspose();\n break;\n default:\n console.warn(`[diffs] Unknown input type: ${inputType}`, data);\n break;\n }\n }\n\n #focus(position?: Position, preventScroll = true) {\n if (position !== undefined) {\n this.#shouldIgnoreSelectionChange = true;\n this.#setWindowSelection({\n start: position,\n end: position,\n direction: DirectionNone,\n });\n // call focus in a request animation frame to prevent conflict with\n // the `setBaseAndExtent` method\n requestAnimationFrame(() => {\n this.#contentElement?.focus({ preventScroll });\n // another request animation frame since the `focus` call\n // may trigger a selectionchange event, which we want to ignore\n requestAnimationFrame(() => {\n this.#shouldIgnoreSelectionChange = false;\n });\n });\n } else {\n this.#contentElement?.focus({ preventScroll });\n }\n }\n\n // set window native selection to match the selection\n #setWindowSelection(selection: EditorSelection) {\n const winSelection = window.getSelection();\n if (winSelection === null) {\n return;\n }\n let { start, end, direction } = selection;\n if (comparePosition(start, end) > 0) {\n [start, end] = [end, start];\n }\n const startLineElement = this.#getLineElement(start.line);\n const endLineElement = this.#getLineElement(end.line);\n if (startLineElement === undefined || endLineElement === undefined) {\n return;\n }\n let [anchorNode, anchorOffset] = getSelectionAnchor(\n startLineElement,\n start.character\n );\n let [focusNode, focusOffset] = getSelectionAnchor(\n endLineElement,\n end.character\n );\n if (direction === DirectionBackward) {\n [anchorNode, anchorOffset, focusNode, focusOffset] = [\n focusNode,\n focusOffset,\n anchorNode,\n anchorOffset,\n ];\n }\n try {\n winSelection.setBaseAndExtent(\n anchorNode,\n clampDomOffset(anchorNode, anchorOffset),\n focusNode,\n clampDomOffset(focusNode, focusOffset)\n );\n } catch (err) {\n console.error('[diffs/editor] failed to update window selection:', err);\n }\n }\n\n #scrollToPrimaryCaret(noFocus = false) {\n const primaryCaretElement = this.#primaryCaretElement;\n const primarySelection = this.#selections?.at(-1);\n if (primarySelection === undefined) {\n return;\n }\n if (primaryCaretElement !== undefined) {\n primaryCaretElement.scrollIntoView({\n block: 'nearest',\n inline: 'nearest',\n });\n if (!noFocus) {\n this.#focus(\n primarySelection.direction === DirectionBackward\n ? primarySelection.end\n : primarySelection.start\n );\n }\n } else {\n const pos = getCaretPosition(primarySelection);\n this.#scrollToLine(pos.line, pos.character, noFocus);\n }\n }\n\n // add scroll margin to the primary caret element to prevent\n // the caret from being hidden by the gutter\n #getScrollMargin() {\n const componentTop = this.#fileInstance?.top ?? 0;\n const top = this.#searchPanel !== undefined ? 48 : 0;\n const start = this.#getGutterWidth() + this.#metrics.ch;\n const end = this.#metrics.ch;\n return `${componentTop + top}px ${end}px 0 ${start}px`;\n }\n\n #scrollToLine(line: number, char = 0, noFocus = false) {\n this.postponeBackgroundTokenizeToNextFrame();\n\n const virtualCaret = h('div', {\n style: {\n position: 'absolute',\n left: '0',\n width: '2px',\n height: this.#metrics.lineHeight + 'px',\n scrollMargin: this.#getScrollMargin(),\n },\n });\n if (this.#getLineElement(line) !== undefined) {\n const [left, wrapLine] = this.#getCharX(line, char);\n const lineY = this.#getLineY(line) + wrapLine * this.#metrics.lineHeight;\n virtualCaret.style.top = lineY + 'px';\n virtualCaret.style.left = left + 'px';\n this.#overlayElement?.appendChild(virtualCaret);\n virtualCaret.scrollIntoView({ block: 'center', inline: 'nearest' });\n if (!noFocus) {\n this.#focus({ line, character: char });\n }\n this.#scrollingToLine = undefined;\n this.#scrollingToLineChar = undefined;\n this.#scrollingToLineNoFocus = false;\n }\n // if the line is not rendered yet(virtualized), scroll to the approximate\n // line position to trigger the line to be rendered, then recall this function\n // to ensure the line is scrolled into view\n else {\n let yFix = 0;\n if (\n this.#scrollingToLine === line &&\n this.#contentElement !== undefined\n ) {\n for (let i = this.#contentElement.childElementCount - 1; i >= 0; i--) {\n const child = this.#contentElement.children[i] as HTMLElement;\n const lineType = child.dataset.lineType;\n const lineNumber = getLineNumberAttr(child);\n if (\n lineType !== undefined &&\n isLineEditable(lineType) &&\n lineNumber !== undefined\n ) {\n yFix = (line - lineNumber) * this.#metrics.lineHeight;\n break;\n }\n }\n }\n const lineAnnotations = (this.#lineAnnotations ?? []).filter(\n (annotation) => annotation.lineNumber < line\n ).length;\n const approximateLineY =\n (lineAnnotations + line) * this.#metrics.lineHeight + yFix;\n virtualCaret.style.top = approximateLineY + 'px';\n this.#fileContainer?.shadowRoot?.appendChild(virtualCaret);\n virtualCaret.scrollIntoView({ block: 'center', inline: 'nearest' });\n if (this.#scrollingToLine === line && yFix === 0) {\n this.#scrollingToLine = undefined;\n this.#scrollingToLineChar = undefined;\n this.#scrollingToLineNoFocus = false;\n } else {\n this.#scrollingToLine = line;\n this.#scrollingToLineChar = char;\n this.#scrollingToLineNoFocus = noFocus;\n }\n }\n virtualCaret.remove();\n }\n\n #updateSelections(selections: EditorSelection[]) {\n this.postponeBackgroundTokenizeToNextFrame();\n\n this.#primaryCaretElement = undefined;\n this.#fileInstance?.setSelectedLines(null);\n this.#gutterElement\n ?.querySelectorAll('[data-active]')\n .forEach((el) => el.removeAttribute('data-active'));\n\n if (\n selections.length === 0 &&\n this.#matches === undefined &&\n this.#markerManager === undefined\n ) {\n this.#selections = undefined;\n this.#overlayElements?.forEach((el) => el.remove());\n this.#overlayElements?.clear();\n return;\n }\n\n const fragment = document.createDocumentFragment();\n const renderCtx = {\n fragment,\n elements: new Map<string, HTMLElement>(),\n };\n\n if (selections.length > 0) {\n const normalizedSelections = mergeOverlappingSelections(selections);\n const primarySelection = normalizedSelections.at(-1)!;\n this.#selections = normalizedSelections;\n if (isCollapsedSelection(primarySelection)) {\n const line = primarySelection.start.line + 1;\n this.#fileInstance?.setSelectedLines({\n start: line,\n end: line,\n });\n } else {\n if (this.#gutterElement !== undefined) {\n const pos = getCaretPosition(primarySelection);\n this.#gutterElement\n .querySelector(`[data-column-number=\"${pos.line + 1}\"]`)\n ?.setAttribute('data-active', '');\n }\n }\n\n for (const selection of normalizedSelections) {\n if (!isCollapsedSelection(selection)) {\n this.#renderSelection(renderCtx, 'selection', selection);\n }\n this.#renderCaret(renderCtx, selection, selection === primarySelection);\n }\n if (\n this.#options.enabledSelectionAction === true &&\n !isCollapsedSelection(primarySelection)\n ) {\n this.#renderSelectionActionIcon(renderCtx, primarySelection);\n }\n }\n\n const textDocument = this.#textDocument;\n if (this.#matches !== undefined && textDocument !== undefined) {\n const primarySelection = this.#selections?.at(-1);\n const primaryStartOffset =\n primarySelection !== undefined\n ? textDocument.offsetAt(primarySelection.start)\n : -1;\n const primaryEndOffset =\n primarySelection !== undefined\n ? textDocument.offsetAt(primarySelection.end)\n : -1;\n for (const [startOffset, endOffset] of this.#matches) {\n const range: Range = {\n start: textDocument.positionAt(startOffset),\n end: textDocument.positionAt(endOffset),\n };\n const isFocused =\n primaryStartOffset === startOffset && primaryEndOffset === endOffset;\n this.#renderSelection(\n renderCtx,\n 'match',\n range,\n isFocused ? 'focus' : undefined\n );\n }\n }\n\n if (this.#markerManager !== undefined && textDocument !== undefined) {\n for (const marker of this.#markerManager.markers) {\n this.#renderSelection(\n renderCtx,\n 'marker',\n marker,\n markerSeverityDatasetKey(marker.severity)\n );\n }\n }\n\n this.#overlayElement?.appendChild(fragment);\n this.#overlayElements?.forEach((el) => el.remove());\n this.#overlayElements?.clear();\n this.#overlayElements = renderCtx.elements;\n }\n\n #renderSelection(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n },\n type: 'selection' | 'match' | 'marker',\n range: Range,\n extraDataset?: string\n ) {\n if (this.#textDocument === undefined) {\n return;\n }\n\n const { start, end } = range;\n for (let line = start.line; line <= end.line; line++) {\n if (!this.#isLineVisible(line)) {\n continue;\n }\n\n const isLastLine = line === end.line;\n const lineText = this.#textDocument.getLineText(line);\n const startChar = line === start.line ? start.character : 0;\n const endChar = isLastLine ? end.character : lineText.length;\n\n if (this.#wrap) {\n const contentWidth = this.#getContentWidth();\n const textWidth =\n 2 * this.#metrics.ch + this.#metrics.measureTextWidth(lineText);\n if (textWidth > contentWidth) {\n this.#renderWrappedSelection(\n renderCtx,\n line,\n lineText,\n startChar,\n endChar,\n isLastLine,\n type,\n extraDataset\n );\n continue;\n }\n }\n\n let left = 0;\n let width = 0;\n let paddingEnd = 0;\n if (startChar === 0) {\n left = this.#getGutterWidth() + this.#metrics.ch; // gutter width + inline padding (1ch)\n } else {\n left = this.#getCharX(line, startChar)[0];\n }\n if (!isLastLine && type === 'selection') {\n paddingEnd = this.#metrics.ch;\n }\n if (startChar === endChar) {\n width = paddingEnd;\n } else {\n width = this.#getCharX(line, endChar)[0] - left + paddingEnd;\n }\n this.#renderSelectionBlock(\n renderCtx,\n type,\n line,\n 0,\n left,\n width,\n extraDataset\n );\n }\n }\n\n // Render the selection on a wrapped logical line by splitting it into one\n // selection-range div per visual sub-line. For each wrap segment, we compute\n // the intersection with the line's selection range and render the slice in\n // segment-local coordinates so left/width line up with the visually wrapped\n // text. Zero-width slices that fall on intermediate segment boundaries are\n // skipped to avoid duplicate markers across consecutive visual lines.\n #renderWrappedSelection(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n },\n line: number,\n lineText: string,\n startChar: number,\n endChar: number,\n isLastLine: boolean,\n type: 'selection' | 'match' | 'marker',\n extraDataset?: string\n ) {\n const wrapOffsets = this.#wrapLineText(line);\n const segmentCount = wrapOffsets.length - 1;\n const offsetLeft = this.#getGutterWidth() + this.#metrics.ch;\n\n for (let wrapLine = 0; wrapLine < segmentCount; wrapLine++) {\n const segmentStart = wrapOffsets[wrapLine];\n const segmentEnd = wrapOffsets[wrapLine + 1];\n const wrapStartChar = Math.max(startChar, segmentStart);\n const wrapEndChar = Math.min(endChar, segmentEnd);\n\n // Selection range doesn't reach this visual segment.\n if (wrapStartChar > wrapEndChar) {\n continue;\n }\n\n let segmentLeft: number;\n let segmentWidth: number;\n let paddingEnd = 0;\n if (wrapStartChar === 0) {\n segmentLeft = offsetLeft;\n } else {\n const prefixInSegment = lineText.slice(segmentStart, wrapStartChar);\n const prefixAsciiColumns = getExpandedAsciiTextColumns(\n prefixInSegment,\n this.#metrics.tabSize\n );\n segmentLeft =\n offsetLeft +\n (prefixAsciiColumns !== -1\n ? prefixAsciiColumns * this.#metrics.ch\n : this.#metrics.measureTextWidth(prefixInSegment));\n }\n if (\n !isLastLine &&\n wrapLine === segmentCount - 1 &&\n type === 'selection'\n ) {\n paddingEnd = this.#metrics.ch;\n }\n if (wrapStartChar === wrapEndChar) {\n segmentWidth = paddingEnd;\n } else {\n const selectionInSegment = lineText.slice(wrapStartChar, wrapEndChar);\n const selectionAsciiWidth = getExpandedAsciiTextColumns(\n selectionInSegment,\n this.#metrics.tabSize\n );\n segmentWidth =\n selectionAsciiWidth !== -1\n ? selectionAsciiWidth * this.#metrics.ch\n : this.#metrics.measureTextWidth(selectionInSegment);\n segmentWidth += paddingEnd;\n }\n\n this.#renderSelectionBlock(\n renderCtx,\n type,\n line,\n wrapLine,\n segmentLeft,\n segmentWidth,\n extraDataset\n );\n }\n }\n\n // Render one selection block for a single visual line.\n #renderSelectionBlock(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n previousSelectionRange?: {\n element: HTMLElement;\n line: number;\n wrapLine: number;\n left: number;\n width: number;\n };\n },\n type: 'selection' | 'match' | 'marker',\n line: number,\n wrapLine: number,\n left: number,\n width: number,\n extraDataset?: string\n ) {\n if (width === 0) {\n return;\n }\n\n const { ch, lineHeight } = this.#metrics;\n const y = this.#getLineY(line) + wrapLine * lineHeight;\n const css = `width:${width}px;transform:translateX(${left}px) translateY(${y}px);`;\n const cacheKey = `${type}-${left}-${y}-${width}${extraDataset ?? ''}`;\n const overlayEls = this.#overlayElements;\n\n const rounded =\n (this.#options.roundedSelection ?? true) && type === 'selection';\n const addRoundedCorner = (\n line: number,\n wrapLine: number,\n left: number,\n radius: 'rtl' | 'rbl' | 'rbr'\n ) => {\n const top = this.#getLineY(line) + wrapLine * lineHeight;\n const css = `width:${ch}px;transform:translateX(${left}px) translateY(${top}px);`;\n const dataset = {\n selectionCorner: '',\n [radius]: '',\n };\n const cacheKeyPrefix = `${type}-block-${left}-${top}-1ch`;\n let cacheKey = cacheKeyPrefix + '-' + radius;\n if (radius === 'rbl') {\n const prevCornerKey = cacheKeyPrefix + '-rtl';\n const prevCorner = renderCtx.elements.get(prevCornerKey);\n if (prevCorner !== undefined) {\n prevCorner.remove();\n renderCtx.elements.delete(prevCornerKey);\n cacheKey += '-rtl';\n dataset.rtl = '';\n }\n }\n let cornerEl = renderCtx.elements.get(cacheKey);\n if (cornerEl !== undefined) {\n return;\n }\n if (overlayEls?.has(cacheKey) === true) {\n cornerEl = overlayEls.get(cacheKey)!;\n overlayEls.delete(cacheKey);\n } else {\n cornerEl = h(\n 'div',\n {\n dataset: 'selectionRange',\n style: { cssText: css },\n children: [\n h('div', {\n dataset: dataset,\n }),\n ],\n },\n renderCtx.fragment\n );\n }\n renderCtx.elements.set(cacheKey, cornerEl);\n };\n const addRadiusStyle = (element: HTMLElement) => {\n const end = left + width;\n const dataset = element.dataset;\n const previousSelectionRange = renderCtx.previousSelectionRange;\n if (\n previousSelectionRange === undefined ||\n previousSelectionRange.line !== line ||\n previousSelectionRange.wrapLine !== wrapLine\n ) {\n renderCtx.previousSelectionRange = {\n element,\n line,\n wrapLine,\n left,\n width,\n };\n }\n if (\n previousSelectionRange === undefined ||\n end <= previousSelectionRange.left\n ) {\n ['rtl', 'rtr', 'rbl', 'rbr'].forEach((key) => {\n dataset[key] = '';\n });\n } else {\n const prevLine = previousSelectionRange.line;\n const prevWrapLine = previousSelectionRange.wrapLine;\n const prevLeft = previousSelectionRange.left;\n const prevDataset = previousSelectionRange.element.dataset;\n const prevEnd = prevLeft + previousSelectionRange.width;\n if (prevLeft > left) {\n addRoundedCorner(prevLine, prevWrapLine, prevLeft - ch, 'rbr');\n }\n delete prevDataset.rbl;\n delete dataset.rtl;\n delete dataset.rtr;\n if (end >= prevEnd) {\n delete prevDataset.rbr;\n }\n if (end > prevEnd) {\n addRoundedCorner(prevLine, prevWrapLine, prevEnd, 'rbl');\n dataset.rtr = '';\n }\n if (end < prevEnd) {\n addRoundedCorner(line, wrapLine, end, 'rtl');\n }\n if (left < prevLeft) {\n dataset.rtl = '';\n }\n dataset.rbl = '';\n dataset.rbr = '';\n }\n };\n\n let rangeEl = renderCtx.elements.get(cacheKey);\n if (rangeEl !== undefined) {\n if (rounded) {\n addRadiusStyle(rangeEl);\n }\n return;\n }\n\n if (overlayEls?.has(cacheKey) === true) {\n rangeEl = overlayEls.get(cacheKey)!;\n overlayEls.delete(cacheKey);\n } else {\n rangeEl = h(\n 'div',\n {\n dataset: extraDataset\n ? [type + 'Range', extraDataset]\n : type + 'Range',\n style: { cssText: css },\n },\n renderCtx.fragment\n );\n }\n\n if (rounded) {\n addRadiusStyle(rangeEl);\n }\n renderCtx.elements.set(cacheKey, rangeEl);\n }\n\n #renderCaret(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n },\n selection: EditorSelection,\n isPrimary: boolean\n ) {\n const { line, character } = getCaretPosition(selection);\n if (!this.#isLineVisible(line)) {\n return;\n }\n const [left, wrapLine] = this.#getCharX(line, character);\n const cacheKey = 'caret-' + line + '/' + wrapLine + ':' + character;\n if (renderCtx.elements.has(cacheKey)) {\n return;\n }\n const x = left - 1;\n const y = this.#getLineY(line) + wrapLine * this.#metrics.lineHeight;\n const caretEl = h(\n 'div',\n {\n dataset: 'caret',\n style: {\n transform: `translateX(${x}px) translateY(${y}px)`,\n },\n },\n renderCtx.fragment\n );\n renderCtx.elements.set(cacheKey, caretEl);\n if (isPrimary) {\n caretEl.style.scrollMargin = this.#getScrollMargin();\n this.#primaryCaretElement = caretEl;\n }\n }\n\n #renderSelectionActionIcon(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n },\n selection: EditorSelection\n ) {\n const line = getCaretPosition(selection).line;\n if (!this.#isLineVisible(line)) {\n return;\n }\n\n const [left, wrapLine] = this.#getCharX(line, 0);\n const cacheKey = 'selectionActionIcon-' + line + '(' + wrapLine + ')';\n if (renderCtx.elements.has(cacheKey)) {\n return;\n }\n\n const selectionActionIcon = SelectionActionWidget.renderIcon(\n left,\n this.#getLineY(line) + wrapLine * this.#metrics.lineHeight,\n renderCtx.fragment,\n () => {\n const cleanUpSelectionAction = () => {\n this.#selectionAction?.cleanup();\n this.#selectionAction = undefined;\n };\n\n const handleWidgetDomResize = () => {\n // the line y cache is invalidated by the DOM change,\n // clear the line y cache and re-render the selection\n this.#lineYCache.clear();\n if (this.#selections !== undefined) {\n this.#updateSelections(this.#selections);\n }\n };\n\n // remove the existing selection action element\n cleanUpSelectionAction();\n\n const textDocument = this.#textDocument;\n const renderSelectionAction = this.#options.renderSelectionAction;\n const fileContainer = this.#fileContainer;\n if (\n textDocument === undefined ||\n renderSelectionAction === undefined ||\n fileContainer == null\n ) {\n return;\n }\n\n const line = selection.end.line;\n const lineText = textDocument.getLineText(line);\n const selectionActionElement = renderSelectionAction({\n textDocument,\n selection,\n applyEdits: (edits: TextEdit[]) => {\n const change = textDocument.applyEdits(\n edits,\n true,\n this.#selections\n );\n if (change !== undefined) {\n this.#applyChange(change);\n }\n },\n getSelectionText: () => {\n return this.#textDocument?.getText(selection) ?? '';\n },\n replaceSelectionText: (text: string) => {\n this.#replaceSelectionText(text);\n },\n close: () => {\n cleanUpSelectionAction();\n handleWidgetDomResize();\n this.#scrollToPrimaryCaret();\n },\n });\n let leadingWhitespaces = 0;\n for (let i = 0; i < lineText.length; i++) {\n const charCode = lineText.charCodeAt(i);\n if (charCode === /* space */ 32) {\n leadingWhitespaces++;\n } else if (charCode === /* tab */ 9) {\n leadingWhitespaces += this.#metrics.tabSize;\n } else {\n break;\n }\n }\n this.#selectionAction = new SelectionActionWidget(\n line,\n selectionActionElement,\n fileContainer,\n leadingWhitespaces,\n handleWidgetDomResize\n );\n this.#updateSelections([selection]);\n if (this.#isLineVisible(line) && this.#contentElement !== undefined) {\n this.#selectionAction.render(this.#contentElement);\n }\n }\n );\n renderCtx.elements.set(cacheKey, selectionActionIcon);\n }\n\n // TODO(@ije): render search highlight\n #renderSearchPanel() {\n // cleanup the existing search panel\n this.#searchPanel?.cleanup();\n\n const textDocument = this.#textDocument;\n const preElement =\n this.#fileContainer?.shadowRoot?.querySelector<HTMLElement>('pre');\n const selections = this.#selections;\n if (textDocument === undefined || preElement == null) {\n return;\n }\n\n let defaultQuery = '';\n let initialMatch: [number, number] | undefined = undefined;\n\n if (selections !== undefined && selections.length > 0) {\n let primarySelection = selections.at(-1)!;\n if (isCollapsedSelection(primarySelection)) {\n primarySelection = expandCollapsedSelectionToWord(\n textDocument,\n primarySelection\n );\n this.#updateSelections([...selections.slice(0, -1), primarySelection]);\n const selectionText = textDocument.getText(primarySelection);\n if (selectionText !== '' && !selectionText.includes('\\n')) {\n defaultQuery = selectionText;\n initialMatch = [\n textDocument.offsetAt(primarySelection.start),\n textDocument.offsetAt(primarySelection.end),\n ];\n }\n }\n }\n\n const scrollToMatch = (\n [startOffset, endOffset]: MatchRange,\n retainFocus: boolean\n ) => {\n const nextSelection = createSelectionFromAnchorAndFocusOffsets(\n textDocument,\n startOffset,\n endOffset\n );\n this.#updateSelections([nextSelection]);\n this.#scrollToPrimaryCaret(true); // scroll to the primary caret and don't focus\n this.#retainSearchPanelFocus = retainFocus;\n };\n\n const searchPanel = new SearchPanelWidget({\n textDocument,\n containerElement: preElement,\n defaultQuery,\n initialMatch,\n scrollToMatch,\n onUpdate: (allMatches: MatchRange[]): MatchRange | undefined => {\n if (allMatches.length === 0) {\n this.#matches = undefined;\n this.#updateSelections(this.#selections ?? []);\n return;\n }\n\n this.#matches = allMatches;\n const primarySelection = this.#selections?.at(-1);\n let searchOffset = 0;\n let nextMatch: MatchRange | undefined;\n if (primarySelection !== undefined) {\n searchOffset = textDocument.offsetAt(primarySelection.start);\n }\n for (const m of allMatches) {\n if (m[0] >= searchOffset) {\n nextMatch = m;\n break;\n }\n }\n if (nextMatch !== undefined) {\n scrollToMatch(nextMatch, true);\n } else {\n this.#updateSelections(this.#selections ?? []);\n }\n return nextMatch;\n },\n onClose: () => {\n this.#searchPanel = undefined;\n this.#retainSearchPanelFocus = false;\n this.#matches = undefined;\n this.#updateSelections(this.#selections ?? []);\n },\n });\n\n this.#searchPanel = searchPanel;\n this.#retainSearchPanelFocus = false;\n }\n\n #getSelectionText() {\n const textDocument = this.#textDocument;\n const selections = this.#selections;\n if (textDocument === undefined || selections === undefined) {\n return '';\n }\n return getSelectionText(textDocument, selections);\n }\n\n // replace the selection text\n #replaceSelectionText(text: string | string[]) {\n const selections = this.#selections;\n if (selections === undefined) {\n return;\n }\n const textDocument = this.#textDocument;\n const primarySelection = selections.at(-1);\n if (textDocument === undefined || primarySelection === undefined) {\n return;\n }\n const { nextSelections, change } =\n Array.isArray(text) && text.length === selections.length\n ? applyTextReplaceToSelections<LAnnotation>(\n textDocument,\n selections,\n text,\n this.#lineAnnotations\n )\n : applyTextChangeToSelections<LAnnotation>(\n textDocument,\n selections,\n {\n start: textDocument.offsetAt(primarySelection.start),\n end: textDocument.offsetAt(primarySelection.end),\n text: Array.isArray(text) ? text.join('\\n') : text,\n },\n this.#lineAnnotations\n );\n\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #deleteSelectionText(forward: boolean = false) {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n\n const primarySelection = selections.at(-1);\n if (primarySelection === undefined) {\n return;\n }\n\n let edit: ResolvedTextEdit;\n if (isCollapsedSelection(primarySelection)) {\n const offset = textDocument.offsetAt(primarySelection.start);\n const nextOffset = forward\n ? Math.min(textDocument.getText().length, offset + 1)\n : Math.max(0, offset - 1);\n edit = {\n start: Math.min(offset, nextOffset),\n end: Math.max(offset, nextOffset),\n text: '',\n };\n } else {\n edit = {\n start: textDocument.offsetAt(primarySelection.start),\n end: textDocument.offsetAt(primarySelection.end),\n text: '',\n };\n }\n\n this.#applyResolvedTextEdit(edit);\n }\n\n #deleteSoftLineBackward() {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n const getSoftLineStart = this.#wrap\n ? (line: number, character: number) => {\n const wrapOffsets = this.#wrapLineText(line);\n for (let w = 0; w + 1 < wrapOffsets.length; w++) {\n const segmentStart = wrapOffsets[w];\n const segmentEnd = wrapOffsets[w + 1];\n if (character >= segmentStart && character <= segmentEnd) {\n return segmentStart;\n }\n }\n return 0;\n }\n : undefined;\n const { nextSelections, change } =\n applyDeleteSoftLineBackwardToSelections<LAnnotation>(\n textDocument,\n selections,\n getSoftLineStart,\n this.#lineAnnotations\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #deleteWordBackward() {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n const { nextSelections, change } =\n applyDeleteWordBackwardToSelections<LAnnotation>(\n textDocument,\n selections,\n this.#lineAnnotations\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #deleteHardLineForward() {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n const { nextSelections, change } =\n applyDeleteHardLineForwardToSelections<LAnnotation>(\n textDocument,\n selections,\n this.#lineAnnotations\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #insertTranspose() {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n const { nextSelections, change } = applyTransposeToSelections<LAnnotation>(\n textDocument,\n selections,\n this.#lineAnnotations\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #applyResolvedTextEdit(edit: ResolvedTextEdit) {\n if (this.#selections === undefined || this.#textDocument === undefined) {\n return;\n }\n const { nextSelections, change } = applyTextChangeToSelections<LAnnotation>(\n this.#textDocument,\n this.#selections,\n edit,\n this.#lineAnnotations,\n this.#metrics.tabSize\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #applyChange(\n change: TextDocumentChange,\n selections?: EditorSelection[],\n newLineAnnotations?: DiffLineAnnotation<LAnnotation>[]\n ) {\n const fileContents = this.#fileContents;\n const textDocument = this.#textDocument;\n const onChange = this.#options.onChange;\n if (\n fileContents !== undefined &&\n textDocument !== undefined &&\n onChange !== undefined\n ) {\n const { contents: _, ...file } = fileContents;\n Object.defineProperty(file, 'contents', {\n enumerable: true,\n get: () => textDocument.getText(),\n });\n onChange(\n file as FileContents,\n newLineAnnotations ?? this.#lineAnnotations\n );\n }\n\n // Invalidate layout caches touched by the edit.\n // - line inserts/deletes shift line numbers, so clear from startLine onward\n // - wrapped edits can change visual height, which shifts downstream line Y\n if (change.lineDelta !== 0) {\n for (const line of this.#lineYCache.keys()) {\n if (line >= change.startLine) {\n this.#lineYCache.delete(line);\n }\n }\n }\n if (this.#wrap) {\n for (const line of this.#wrapLineOffsetsCache.keys()) {\n if (line >= change.startLine) {\n this.#wrapLineOffsetsCache.delete(line);\n }\n }\n }\n this.#lastAccessedCharX = undefined;\n\n let renderRange = this.#renderRange;\n let shouldUpdateBuffer: boolean | undefined;\n if (\n renderRange !== undefined &&\n selections !== undefined &&\n selections.length > 0\n ) {\n const primarySelection = selections.at(-1)!;\n const renderRangeEndLine =\n renderRange.startingLine + renderRange.totalLines;\n // when typing new line at the end of the file,\n // extend the render range +1 to trigger the re-render of the new line\n if (primarySelection.end.line === renderRangeEndLine) {\n renderRange = {\n ...renderRange,\n totalLines: renderRange.totalLines + 1,\n };\n } else if (primarySelection.end.line > renderRangeEndLine) {\n shouldUpdateBuffer = true;\n }\n }\n this.#rerender(change, newLineAnnotations, renderRange, shouldUpdateBuffer);\n\n if (selections !== undefined) {\n // re-render selection range and caret, focus to the editor to update the window selection,\n // and scroll to the crate to mock the 'contenteditable' behavior\n this.#updateSelections(selections);\n if (this.#primaryCaretElement !== undefined) {\n this.#primaryCaretElement.scrollIntoView({\n block: 'nearest',\n inline: 'nearest',\n });\n } else if (selections.length > 0) {\n const pos = getCaretPosition(selections.at(-1)!);\n this.#scrollToLine(pos.line, pos.character);\n }\n this.focus({ preventScroll: true });\n }\n }\n\n #applyChangeToLineAnnotations(\n change: TextDocumentChange\n ): DiffLineAnnotation<LAnnotation>[] | undefined {\n if (this.#lineAnnotations !== undefined) {\n const nextLineAnnotations =\n applyDocumentChangeToLineAnnotations<LAnnotation>(\n change,\n this.#lineAnnotations\n );\n if (nextLineAnnotations !== undefined) {\n this.#textDocument?.setLastUndoLineAnnotations(\n this.#lineAnnotations,\n nextLineAnnotations\n );\n return nextLineAnnotations;\n }\n }\n return undefined;\n }\n\n #getLineElement(line: number): HTMLElement | undefined {\n const lastAccessed = this.#lastAccessedLineElement;\n if (lastAccessed !== undefined && lastAccessed[0] === line) {\n return lastAccessed[1];\n }\n\n const contentElement = this.#contentElement;\n if (contentElement === undefined) {\n return undefined;\n }\n\n let lineElement: HTMLElement | null = null;\n\n // check if the line is within the render range (fast)\n if (this.#renderRange !== undefined) {\n const { startingLine } = this.#renderRange;\n const { children } = contentElement;\n for (let i = line - startingLine; i <= children.length; i++) {\n const child = children[i] as HTMLElement | undefined;\n if (child === undefined) {\n break;\n }\n const lineNumber = getLineNumberAttr(child);\n const lineType = child.dataset.lineType;\n if (\n lineNumber !== undefined &&\n lineNumber === line + 1 &&\n lineType !== undefined &&\n isLineEditable(lineType)\n ) {\n lineElement = child;\n break;\n }\n }\n }\n\n // fallback to query selector\n lineElement ??= contentElement.querySelector<HTMLElement>(\n `[data-line=\"${line + 1}\"]`\n );\n\n if (lineElement !== null) {\n if (lastAccessed !== undefined) {\n lastAccessed[0] = line;\n lastAccessed[1] = lineElement;\n } else {\n this.#lastAccessedLineElement = [line, lineElement];\n }\n return lineElement;\n }\n return undefined;\n }\n\n #getGutterWidth(): number {\n if (this.#gutterElement === undefined) {\n return 0;\n }\n\n if (this.#gutterWidthCache === undefined) {\n const diffsColumnNumberWidth =\n this.#contentElement?.parentElement?.style.getPropertyValue(\n '--diffs-column-number-width'\n );\n if (\n diffsColumnNumberWidth !== undefined &&\n diffsColumnNumberWidth.length > 2 &&\n diffsColumnNumberWidth.endsWith('px')\n ) {\n this.#gutterWidthCache = parseInt(\n diffsColumnNumberWidth.slice(0, -2),\n 10\n );\n } else {\n this.#gutterWidthCache = this.#gutterElement.offsetWidth;\n }\n }\n\n return this.#gutterWidthCache;\n }\n\n #getContentWidth(): number {\n if (this.#contentElement === undefined) {\n return 0;\n }\n\n if (this.#contentWidthCache === undefined) {\n const diffsColumnContentWidth =\n this.#contentElement.parentElement?.style.getPropertyValue(\n '--diffs-column-content-width'\n );\n if (\n diffsColumnContentWidth !== undefined &&\n diffsColumnContentWidth.length > 2 &&\n diffsColumnContentWidth.endsWith('px')\n ) {\n this.#contentWidthCache = parseFloat(\n diffsColumnContentWidth.slice(0, -2)\n );\n } else {\n this.#contentWidthCache = this.#contentElement.offsetWidth;\n }\n }\n return this.#contentWidthCache;\n }\n\n // get line top(y-coordinate) position\n #getLineY(line: number) {\n const cachedY = this.#lineYCache.get(line);\n if (cachedY !== undefined) {\n return cachedY;\n }\n\n const lineElement = this.#getLineElement(line);\n if (lineElement === undefined) {\n return -1;\n }\n\n // cold(slow) path: measure line top position from DOM (will cause reflow)\n const y = lineElement.offsetTop + this.#codePaddingTop;\n this.#lineYCache.set(line, y);\n return y;\n }\n\n // Return the visual position for a character. Wrapped lines include the\n // visual line index so carets can be placed on the correct row.\n #getCharX(line: number, char: number): [x: number, wrapLine: number] {\n if (\n this.#lastAccessedCharX !== undefined &&\n this.#lastAccessedCharX[0] === line &&\n this.#lastAccessedCharX[1] === char\n ) {\n return [this.#lastAccessedCharX[2], this.#lastAccessedCharX[3]];\n }\n\n const lineText = this.#textDocument?.getLineText(line);\n const offsetLeft = this.#getGutterWidth() + this.#metrics.ch; // gutter width + inline padding (1ch)\n if (lineText === undefined || lineText.length === 0 || char <= 0) {\n return [offsetLeft, 0];\n }\n\n const boundedCharacter = snapTextOffsetToUnicodeBoundary(\n lineText,\n Math.min(char, lineText.length)\n );\n const textBeforeCharacter = lineText.slice(0, boundedCharacter);\n const asciiColumns = getExpandedAsciiTextColumns(\n textBeforeCharacter,\n this.#metrics.tabSize\n );\n\n let left = 0;\n let wrapLine = 0;\n if (asciiColumns !== -1) {\n left = offsetLeft + asciiColumns * this.#metrics.ch;\n } else {\n left = offsetLeft + this.#metrics.measureTextWidth(textBeforeCharacter);\n }\n\n if (this.#wrap) {\n const contentWidth = this.#getContentWidth();\n const textWidth =\n 2 * this.#metrics.ch + this.#metrics.measureTextWidth(lineText);\n if (textWidth > contentWidth) {\n const wrapOffsets = this.#wrapLineText(line);\n for (let w = 0; w + 1 < wrapOffsets.length; w++) {\n const segmentStart = wrapOffsets[w];\n const segmentEnd = wrapOffsets[w + 1];\n if (boundedCharacter <= segmentEnd) {\n wrapLine = w;\n const prefixInSegment = lineText.slice(\n segmentStart,\n boundedCharacter\n );\n const segmentAsciiColumns = getExpandedAsciiTextColumns(\n prefixInSegment,\n this.#metrics.tabSize\n );\n if (segmentAsciiColumns !== -1) {\n left = offsetLeft + segmentAsciiColumns * this.#metrics.ch;\n } else {\n left =\n offsetLeft + this.#metrics.measureTextWidth(prefixInSegment);\n }\n break;\n }\n }\n }\n }\n\n if (this.#lastAccessedCharX !== undefined) {\n this.#lastAccessedCharX[0] = line;\n this.#lastAccessedCharX[1] = char;\n this.#lastAccessedCharX[2] = left;\n this.#lastAccessedCharX[3] = wrapLine;\n } else {\n this.#lastAccessedCharX = [line, char, left, wrapLine];\n }\n\n return [left, wrapLine];\n }\n\n // Compute how a logical line of text is broken into visual lines when line\n // wrapping is enabled.\n #wrapLineText(line: number): Uint32Array {\n const cachedOffsets = this.#wrapLineOffsetsCache.get(line);\n if (cachedOffsets !== undefined) {\n return cachedOffsets;\n }\n\n const lineText = this.#textDocument?.getLineText(line);\n if (lineText === undefined || lineText.length === 0) {\n const offsets = new Uint32Array([0]);\n this.#wrapLineOffsetsCache.set(line, offsets);\n return offsets;\n }\n\n const div = h(\n 'div',\n {\n style: {\n position: 'absolute',\n top: '0',\n left: '0',\n width: '100%',\n boxSizing: 'border-box',\n visibility: 'hidden',\n pointerEvents: 'none',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n font: 'inherit',\n paddingInline: '1ch',\n tabSize: this.#metrics.tabSize.toString(),\n },\n textContent: lineText,\n },\n this.#contentElement\n );\n const textNode = div.firstChild as Text;\n const range = document.createRange();\n const starts: number[] = [];\n\n try {\n const unicodeOffsets = getUnicodeMeasurementOffsets(lineText);\n const wrapLineStartLeft =\n div.getBoundingClientRect().left + this.#metrics.ch;\n\n let previousOffset = 0;\n let lastTop = Number.NEGATIVE_INFINITY;\n\n for (let i = 0, offsetIndex = 0; i < lineText.length; ) {\n const nextOffset =\n unicodeOffsets === undefined\n ? i + 1\n : unicodeOffsets[offsetIndex + 1];\n range.setStart(textNode, i);\n range.setEnd(textNode, nextOffset);\n\n // A new visual line starts whenever the character's top edge moves\n // below the previous character's top edge.\n const { left, top } = range.getBoundingClientRect();\n if (top > lastTop) {\n // Safari can report the first range on a wrapped visual line as\n // starting one character past the visual line start. Use the previous\n // offset so segment-local caret math begins at the actual wrap point.\n const startsPastLineStart =\n isSafari() &&\n starts.length > 0 &&\n left - wrapLineStartLeft > this.#metrics.ch / 2;\n starts.push(startsPastLineStart ? previousOffset : i);\n lastTop = top;\n }\n previousOffset = i;\n i = nextOffset;\n offsetIndex++;\n }\n\n const offsets = new Uint32Array(starts.length + 1);\n for (let i = 0; i < starts.length; i++) {\n offsets[i] = starts[i]!;\n }\n offsets[starts.length] = lineText.length;\n this.#wrapLineOffsetsCache.set(line, offsets);\n return offsets;\n } finally {\n div.remove();\n }\n }\n\n // check if the web selection belongs to editor\n #rangeBelongsToEditor({ startContainer, endContainer }: StaticRange) {\n const contentEl = this.#contentElement;\n if (contentEl === undefined) {\n return false;\n }\n return (\n contentEl.contains(startContainer) && contentEl.contains(endContainer)\n );\n }\n\n // Check whether a line is visible in the currently rendered line window.\n #isLineVisible(line: number): boolean {\n const lineCount = this.#textDocument?.lineCount ?? 0;\n if (line < 0 || line >= lineCount) {\n return false;\n }\n if (this.#renderRange === undefined) {\n return true;\n }\n const { startingLine, totalLines } = this.#renderRange;\n if (line < startingLine) {\n return false;\n }\n if (totalLines === Infinity) {\n return true;\n }\n return line < startingLine + totalLines;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"editor.js","names":["#fileInstance","#renderRange","#textDocument","#getLineElement","#options","#initialize","#detach","#selections","#applyChange","#applyChangeToLineAnnotations","#getFileRef","#lineAnnotations","#resetCache","#resetState","#initSelections","#updateSelections","#scrollToPrimaryCaret","#markerRenderer","#metrics","#fileContainer","#getCharX","#getLineY","#isContentMouseDown","#isGutterMouseDown","#contentElement","#focus","#tokenizer","#globalEventDisposes","#editorEventDisposes","#selectEventDisposes","#gutterWidthCache","#contentWidthCache","#lineYCache","#wrapLineOffsetsCache","#lastAccessedLineElement","#lastAccessedCharX","#globalStyleElement","#editorStyleElement","#themeStyleElement","#spriteElement","#gutterElement","#overlayElement","#resizeObserver","codeElement: HTMLElement | undefined","gutterEl: HTMLElement | undefined","contentEl: HTMLElement | undefined","el","#fileContents","#onDeferTokenize","#listenContentElement","#wrap","#matches","#primaryCaretElement","#scrollingToLine","#scrollToLine","#scrollingToLineChar","#scrollingToLineNoFocus","#retainSearchPanelFocus","#searchPanel","#selectionAction","#isLineVisible","#shouldIgnoreSelectionChange","#overlayElements","#reservedSelections","editorCSS","#rangeBelongsToEditor","#shiftKeyPressed","#selectionStart","#setWindowSelection","#runCommand","#getSelectionText","#replaceSelectionText","#handleInput","selection: EditorSelection","textDocument","lineIndex","e","selection","#handleLayoutResize","#openSearchPanel","expanded: EditorSelection[]","edits: TextEdit[]","nextSelections: EditorSelection[]","#getGutterWidth","#getContentWidth","#deleteSelectionText","#deleteSoftLineBackward","#deleteHardLineForward","#deleteWordBackward","#insertTranspose","#getScrollMargin","#renderSelection","#renderCaret","#renderSelectionActionIcon","range: Range","#renderWrappedSelection","#renderSelectionBlock","#wrapLineText","segmentLeft: number","segmentWidth: number","line","wrapLine","css","left","cacheKey","#renderSearchPanel","initialMatch: [number, number] | undefined","primarySelection","nextMatch: MatchRange | undefined","edit: ResolvedTextEdit","#applyResolvedTextEdit","shouldUpdateBuffer: boolean | undefined","#rerender","lineElement: HTMLElement | null","starts: number[]"],"sources":["../../src/editor/editor.ts"],"sourcesContent":["import type {\n DiffLineAnnotation,\n DiffsEditableComponent,\n DiffsEditor,\n DiffsEditorSelection,\n DiffsHighlighter,\n FileContents,\n HighlightedToken,\n RenderRange,\n} from '../types';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport {\n type EditorCommand,\n resolveEditorCommandFromKeyboardEvent,\n} from './command';\nimport editorCSS from './editor.css';\nimport { EditStack } from './editStack';\nimport {\n applyDocumentChangeToLineAnnotations,\n renderLineAnnotations,\n} from './lineAnnotations';\nimport {\n type Marker,\n MarkerRenderer,\n markerSeverityDatasetKey,\n} from './marker';\nimport { isMoveCursorShortcut, isPrimaryModifier, isSafari } from './platform';\nimport {\n type MatchRange,\n type SearchPanelMode,\n SearchPanelWidget,\n} from './searchPanel';\nimport type { EditorSelection } from './selection';\nimport {\n applyDeleteHardLineForwardToSelections,\n applyDeleteSoftLineBackwardToSelections,\n applyDeleteWordBackwardToSelections,\n applyTextChangeToSelections,\n applyTextReplaceToSelections,\n applyTransposeToSelections,\n comparePosition,\n convertSelection,\n createSelectionFrom,\n createSelectionFromAnchorAndFocusOffsets,\n DirectionBackward,\n DirectionForward,\n DirectionNone,\n expandCollapsedSelectionToWord,\n extendSelection,\n extendSelections,\n findNexMatch,\n getCaretPosition,\n getDocumentBoundarySelection,\n getDocumentFullSelection,\n getSelectionAnchor,\n getSelectionText,\n isCollapsedSelection,\n isLineEditable,\n mapCursorMove,\n mapSelectionShift,\n mergeOverlappingSelections,\n resolveIndentEdits,\n selectionIntersects,\n} from './selection';\nimport {\n type SelectionActionContext,\n SelectionActionWidget,\n} from './selectionAction';\nimport { createSpriteElement } from './sprite';\nimport {\n type Position,\n type Range,\n type ResolvedTextEdit,\n TextDocument,\n type TextDocumentChange,\n type TextEdit,\n} from './textDocument';\nimport {\n getExpandedAsciiTextColumns,\n getUnicodeMeasurementOffsets,\n Metrics,\n snapTextOffsetToUnicodeBoundary,\n} from './textMeasure';\nimport { EditorTokenizer, renderLineTokens } from './tokenzier';\nimport {\n addEventListener,\n clampDomOffset,\n extend,\n getLineNumberAttr,\n h,\n round,\n} from './utils';\n\nexport interface EditorOptions<LAnnotation> {\n /** The maximum number of entries to keep in the undo stack. */\n historyMaxEntries?: number;\n /** Render rounded corners for selection ranges, default is true. */\n roundedSelection?: boolean;\n /** Show the clickable selection action icon, default is disabled. */\n enabledSelectionAction?: boolean;\n /** Render the selection action widget element. */\n renderSelectionAction?: (\n context: SelectionActionContext<LAnnotation>\n ) => HTMLElement;\n /** Callback when the editor is attached to a file. */\n onAttach?: (\n editor: Editor<LAnnotation>,\n fileInstance: DiffsEditableComponent<LAnnotation>\n ) => void;\n /** Callback when the editor document changes. */\n onChange?: (\n file: FileContents,\n lineAnnotations?: DiffLineAnnotation<LAnnotation>[]\n ) => void;\n __debug?: boolean;\n}\n\nexport interface EditorState<LAnnotation> {\n file: FileContents;\n lineAnnotations?: DiffLineAnnotation<LAnnotation>[];\n selections?: EditorSelection[];\n renderRange?: RenderRange;\n}\n\nexport class Editor<LAnnotation> implements DiffsEditor<LAnnotation> {\n #options: EditorOptions<LAnnotation>;\n #wrap = false;\n #metrics = new Metrics();\n #tokenizer?: EditorTokenizer;\n\n // event disposes\n #editorEventDisposes?: (() => void)[];\n #globalEventDisposes?: (() => void)[];\n #selectEventDisposes?: (() => void)[];\n #detach?: () => void;\n\n // cache\n #gutterWidthCache?: number;\n #contentWidthCache?: number;\n #lineYCache = new Map<number, number>();\n #wrapLineOffsetsCache = new Map<number, Uint32Array>();\n #lastAccessedLineElement?: [number, HTMLElement];\n #lastAccessedCharX?: [\n line: number,\n character: number,\n x: number,\n wrapLine: number,\n ];\n\n // dom\n #globalStyleElement?: HTMLStyleElement;\n #editorStyleElement?: HTMLStyleElement;\n #themeStyleElement?: HTMLStyleElement;\n #spriteElement?: SVGSVGElement;\n #fileContainer?: HTMLElement;\n #gutterElement?: HTMLElement;\n #contentElement?: HTMLElement;\n #overlayElement?: HTMLElement;\n #overlayElements?: Map<string, HTMLElement>;\n #primaryCaretElement?: HTMLElement;\n #resizeObserver?: ResizeObserver;\n\n // state\n #fileInstance?: DiffsEditableComponent<LAnnotation>;\n #fileContents?: FileContents;\n #lineAnnotations?: DiffLineAnnotation<LAnnotation>[];\n #textDocument?: TextDocument<LAnnotation>;\n #renderRange?: RenderRange;\n #markerRenderer?: MarkerRenderer;\n #searchPanel?: SearchPanelWidget;\n #selectionAction?: SelectionActionWidget;\n #shouldIgnoreSelectionChange = false;\n #isGutterMouseDown = false;\n #isContentMouseDown = false;\n #shiftKeyPressed = false;\n #selectionStart: EditorSelection | undefined;\n #reservedSelections?: EditorSelection[];\n #initSelections?: EditorSelection[];\n #selections?: EditorSelection[];\n #matches?: MatchRange[];\n #scrollingToLine?: number;\n #scrollingToLineChar?: number;\n #scrollingToLineNoFocus = false;\n #retainSearchPanelFocus = false;\n\n #onDeferTokenize = (\n lines: Map<number, Array<HighlightedToken>>,\n themeType: 'light' | 'dark'\n ) => {\n this.#fileInstance?.updateRenderCache(lines, themeType);\n // update the view if the render range is updated by scrolling\n // and the deferred tokenized lines inside the render range\n if (\n this.#renderRange !== undefined &&\n this.#renderRange.totalLines !== Infinity\n ) {\n const { startingLine, totalLines } = this.#renderRange;\n const endLine = Math.min(\n startingLine + totalLines,\n this.#textDocument?.lineCount ?? 0\n );\n for (const [line, tokens] of lines) {\n if (line >= startingLine && line < endLine) {\n const lineElement = this.#getLineElement(line);\n if (lineElement !== undefined) {\n lineElement.replaceChildren(...renderLineTokens(tokens, themeType));\n }\n }\n }\n }\n };\n\n constructor(options: EditorOptions<LAnnotation> = {}) {\n this.#options = options;\n }\n\n edit(component: DiffsEditableComponent<LAnnotation>): () => void {\n const {\n useTokenTransformer,\n enableGutterUtility,\n enableLineSelection,\n expandUnchanged,\n diffStyle,\n lineHoverHighlight,\n ...rest\n } = component.options;\n const isDiff = component.type === 'file-diff';\n if (\n useTokenTransformer !== true ||\n enableGutterUtility === true ||\n enableLineSelection === true ||\n lineHoverHighlight !== 'disabled' ||\n (expandUnchanged !== true && isDiff) ||\n (diffStyle === 'unified' && isDiff)\n ) {\n component.setOptions({\n ...rest,\n useTokenTransformer: true,\n enableGutterUtility: false,\n enableLineSelection: false,\n lineHoverHighlight: 'disabled',\n expandUnchanged: true,\n diffStyle: 'split',\n });\n component.rerender();\n }\n this.#fileInstance = component;\n this.#initialize();\n this.#detach = component.attachEditor(this);\n return () => this.cleanUp();\n }\n\n /**\n * Apply edits to current attached file.\n */\n applyEdits(edits: TextEdit[], updateHistory = false): void {\n const textDocument = this.#textDocument;\n if (textDocument == null) {\n throw new Error('Editor is not attached');\n }\n const change = textDocument.applyEdits(\n edits,\n updateHistory,\n this.#selections\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n undefined,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n getState(): EditorState<LAnnotation> {\n const fileRef = this.#getFileRef();\n if (fileRef === undefined) {\n throw new Error('Editor is not attached');\n }\n return {\n file: { ...fileRef, cacheKey: 'edited-at-' + Date.now() },\n selections: this.#selections,\n lineAnnotations: this.#lineAnnotations,\n renderRange: this.#renderRange,\n };\n }\n\n setState({\n file,\n lineAnnotations,\n renderRange,\n selections,\n }: EditorState<LAnnotation>): void {\n this.#resetCache();\n this.#resetState();\n this.#initSelections = selections;\n this.#fileInstance?.render({\n file: { ...file, cacheKey: 'edited-at-' + Date.now() },\n lineAnnotations,\n renderRange,\n });\n }\n\n setSelections(selections: DiffsEditorSelection[]): void {\n const textDocument = this.#textDocument;\n if (textDocument === undefined) {\n throw new Error('Text document is not initialized');\n }\n const resolvedSelections = selections.map<EditorSelection>((selection) => {\n const start = textDocument.normalizePosition(selection.start);\n const end = textDocument.normalizePosition(selection.end);\n const direction =\n selection.direction === 'none'\n ? DirectionNone\n : selection.direction === 'backward'\n ? DirectionBackward\n : DirectionForward;\n return { direction, start, end };\n });\n this.#updateSelections(resolvedSelections);\n this.#scrollToPrimaryCaret(false, 'center');\n }\n\n setMarkers(markers: Marker[]): void {\n const textDocument = this.#textDocument;\n if (textDocument === undefined) {\n throw new Error('Text document is not initialized');\n }\n\n if (markers.length === 0) {\n this.#markerRenderer?.cleanup();\n this.#markerRenderer = undefined;\n this.#updateSelections(this.#selections ?? []);\n return;\n }\n\n this.#markerRenderer ??= new MarkerRenderer({\n getLineHeight: () => this.#metrics.lineHeight,\n getFileContainer: () => this.#fileContainer,\n getCharX: (line, character) => this.#getCharX(line, character),\n getLineY: (line) => this.#getLineY(line),\n isMouseDown: () => this.#isContentMouseDown || this.#isGutterMouseDown,\n });\n this.#markerRenderer.setMarkers(markers, textDocument);\n if (this.#contentElement !== undefined) {\n this.#markerRenderer.listenHover(this.#contentElement);\n }\n this.#updateSelections(this.#selections ?? []);\n }\n\n focus(options?: FocusOptions): void {\n const preventScroll = options?.preventScroll ?? false;\n const primarySelection = this.#selections?.at(-1);\n if (primarySelection !== undefined) {\n const pos =\n primarySelection.direction === DirectionBackward\n ? primarySelection.end\n : primarySelection.start;\n this.#focus(pos, preventScroll);\n } else {\n this.#focus(undefined, preventScroll);\n }\n }\n\n blur(): void {\n this.#contentElement?.blur();\n }\n\n cleanUp(): void {\n this.#tokenizer?.cleanUp();\n this.#tokenizer = undefined;\n\n // dispse event listeners\n this.#globalEventDisposes?.forEach((dispose) => dispose());\n this.#globalEventDisposes = undefined;\n this.#editorEventDisposes?.forEach((dispose) => dispose());\n this.#editorEventDisposes = undefined;\n this.#selectEventDisposes?.forEach((dispose) => dispose());\n this.#selectEventDisposes = undefined;\n this.#detach?.();\n this.#detach = undefined;\n\n // cache\n this.#gutterWidthCache = undefined;\n this.#contentWidthCache = undefined;\n this.#lineYCache.clear();\n this.#wrapLineOffsetsCache.clear();\n this.#lastAccessedLineElement = undefined;\n this.#lastAccessedCharX = undefined;\n\n // clean up dom elements\n this.#globalStyleElement?.remove();\n this.#globalStyleElement = undefined;\n this.#editorStyleElement?.remove();\n this.#editorStyleElement = undefined;\n this.#themeStyleElement?.remove();\n this.#themeStyleElement = undefined;\n this.#spriteElement?.remove();\n this.#spriteElement = undefined;\n this.#fileContainer = undefined;\n this.#gutterElement = undefined;\n this.#contentElement?.removeAttribute('contentEditable');\n this.#contentElement = undefined;\n this.#overlayElement?.remove();\n this.#overlayElement = undefined;\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = undefined;\n\n this.#resetState();\n }\n\n /** @internal */\n __postponeBackgroundTokenizeToNextFrame(): void {\n const tokenizer = this.#tokenizer;\n if (tokenizer !== undefined) {\n tokenizer.pauseBackgroundTokenize();\n requestAnimationFrame(() => {\n tokenizer.resumeBackgroundTokenize();\n });\n }\n }\n\n /** @internal */\n __syncRenderView: DiffsEditor<LAnnotation>['__syncRenderView'] = (\n highlighter: DiffsHighlighter,\n fileContainer: HTMLElement,\n fileContents: FileContents,\n lineAnnotations: DiffLineAnnotation<LAnnotation>[] | undefined,\n renderRange: RenderRange | undefined\n ) => {\n const shadowRoot = fileContainer.shadowRoot;\n if (shadowRoot == null) {\n console.error('[editor] Could not find the shadow root.');\n return;\n }\n\n let codeElement: HTMLElement | undefined;\n let gutterEl: HTMLElement | undefined;\n let contentEl: HTMLElement | undefined;\n for (const el of shadowRoot.querySelectorAll<HTMLElement>('[data-code]')) {\n if (el.dataset.deletions === undefined) {\n codeElement = el;\n for (const child of el.children) {\n const el = child as HTMLElement;\n const { gutter, content } = el.dataset;\n if (gutter !== undefined) {\n gutterEl = el;\n } else if (content !== undefined) {\n contentEl = el;\n }\n }\n break;\n }\n }\n if (codeElement === undefined || contentEl === undefined) {\n return;\n }\n\n // inject editor&theme style to the file container\n if (this.#fileContainer !== fileContainer) {\n this.#fileContainer = fileContainer;\n if (this.#globalStyleElement !== undefined) {\n fileContainer.appendChild(this.#globalStyleElement);\n }\n if (this.#editorStyleElement !== undefined) {\n shadowRoot.appendChild(this.#editorStyleElement);\n }\n if (this.#themeStyleElement !== undefined) {\n shadowRoot.appendChild(this.#themeStyleElement);\n }\n if (this.#spriteElement !== undefined) {\n shadowRoot.prepend(this.#spriteElement);\n }\n }\n\n if (\n this.#textDocument === undefined ||\n this.#fileContents === undefined ||\n this.#fileContents.name !== fileContents.name ||\n this.#fileContents.contents !== fileContents.contents ||\n this.#fileContents.lang !== fileContents.lang ||\n this.#fileContents.cacheKey !== fileContents.cacheKey\n ) {\n const editStack = new EditStack<LAnnotation>({\n maxEntries: this.#options.historyMaxEntries,\n });\n const textDocument = new TextDocument<LAnnotation>(\n fileContents.name,\n fileContents.contents,\n fileContents.lang ?? getFiletypeFromFileName(fileContents.name),\n 0,\n editStack\n );\n this.#fileContents = fileContents;\n this.#textDocument = textDocument;\n this.#tokenizer?.cleanUp();\n this.#tokenizer = new EditorTokenizer({\n highlighter,\n textDocument,\n codeOptions: this.#fileInstance?.options ?? {},\n onDeferTokenize: this.#onDeferTokenize,\n setStyle: (css) => {\n this.#themeStyleElement!.textContent = css;\n },\n __debug: this.#options.__debug,\n });\n this.#resetState();\n this.#selections = this.#initSelections;\n this.#options.onAttach?.(this, this.#fileInstance!);\n if (this.#textDocument !== undefined && this.#options.__debug === true) {\n console.log('[diffs/editor] text document changed !!!');\n }\n }\n\n if (this.#contentElement !== contentEl) {\n this.#gutterElement = gutterEl;\n this.#contentElement = extend(contentEl, {\n contentEditable: 'true',\n role: 'textbox',\n ariaMultiLine: 'true',\n autocapitalize: 'off',\n writingSuggestions: 'off',\n autocorrect: false,\n spellcheck: false,\n translate: false,\n });\n if (this.#overlayElement !== undefined) {\n contentEl.after(this.#overlayElement);\n }\n this.#metrics.init(contentEl);\n this.#listenContentElement(contentEl, gutterEl);\n if (\n this.#contentElement !== undefined &&\n this.#options.__debug === true\n ) {\n console.log('[diffs/editor] full re-render triggered !!!');\n }\n }\n\n this.#resetCache();\n\n this.#wrap = this.#fileInstance?.options.overflow === 'wrap';\n this.#lineAnnotations = lineAnnotations;\n this.#renderRange = renderRange;\n this.#tokenizer?.prebuildStateStack(renderRange);\n\n // re-render the existing selections, matches, and markers\n if (\n this.#selections !== undefined ||\n this.#matches !== undefined ||\n this.#markerRenderer !== undefined\n ) {\n this.#updateSelections(this.#selections ?? []);\n }\n\n if (\n this.#initSelections !== undefined &&\n this.#primaryCaretElement !== undefined\n ) {\n this.#initSelections = undefined;\n this.#scrollToPrimaryCaret(false, 'center');\n } else if (this.#scrollingToLine !== undefined) {\n this.#scrollToLine(\n this.#scrollingToLine,\n this.#scrollingToLineChar,\n this.#scrollingToLineNoFocus\n );\n } else if (\n this.#selections !== undefined &&\n this.#selections.length > 0 &&\n !this.#retainSearchPanelFocus\n ) {\n this.focus({ preventScroll: true });\n }\n\n if (this.#retainSearchPanelFocus) {\n this.#searchPanel?.focus();\n }\n\n if (\n this.#selectionAction !== undefined &&\n this.#isLineVisible(this.#selectionAction.line) &&\n this.#contentElement !== undefined\n ) {\n this.#selectionAction.render(this.#contentElement);\n }\n\n if (this.#options.__debug === true && renderRange !== undefined) {\n const { startingLine, totalLines } = renderRange;\n console.log(\n '[diffs/editor] render file:',\n fileContents.name,\n 'RenderRange:',\n startingLine + '-' + (startingLine + totalLines),\n 'of',\n this.#textDocument.lineCount,\n 'lines'\n );\n }\n };\n\n #resetCache(): void {\n this.#lineYCache.clear();\n this.#wrapLineOffsetsCache.clear();\n this.#lastAccessedLineElement = undefined;\n this.#lastAccessedCharX = undefined;\n }\n\n #resetState(): void {\n this.#gutterWidthCache = undefined;\n this.#contentWidthCache = undefined;\n this.#fileInstance?.setSelectedLines(null);\n this.#shouldIgnoreSelectionChange = false;\n this.#overlayElements?.forEach((el) => el.remove());\n this.#overlayElements = undefined;\n this.#selections = undefined;\n this.#reservedSelections = undefined;\n this.#scrollingToLine = undefined;\n this.#markerRenderer?.cleanup();\n this.#markerRenderer = undefined;\n this.#searchPanel?.cleanup();\n this.#searchPanel = undefined;\n this.#selectionAction?.cleanup();\n this.#selectionAction = undefined;\n }\n\n #initialize(): void {\n // Safari doesn't support `::selection` for slot elements in ShadowDOM,\n // Add a global style to disable selection for slot elements\n this.#globalStyleElement = h('style', {\n dataset: 'editorGlobalCss',\n textContent: `\n [data-annotation-slot] {\n user-select: none;\n -webkit-user-select: none;\n }\n `,\n });\n\n this.#editorStyleElement = h('style', {\n dataset: 'editorCss',\n textContent: editorCSS,\n });\n\n this.#themeStyleElement = h('style', {\n dataset: 'editorThemeCss',\n });\n\n this.#spriteElement = createSpriteElement();\n\n this.#overlayElement = h('div', {\n dataset: 'editorOverlay',\n });\n\n this.#globalEventDisposes = [\n addEventListener(\n document,\n 'selectionchange',\n () => {\n const shadowRoot = this.#fileContainer?.shadowRoot;\n if (this.#shouldIgnoreSelectionChange || shadowRoot == null) {\n return;\n }\n\n // Native selection only tracks one range. focus() and DOM updates while\n // typing mirror the primary caret there, so selectionchange must not\n // overwrite multi-cursor editor state outside an active pointer gesture.\n if (\n this.#selections !== undefined &&\n this.#selections.length > 1 &&\n !this.#isContentMouseDown\n ) {\n return;\n }\n\n const selectionRaw = document.getSelection();\n const composedRange = selectionRaw?.getComposedRanges({\n shadowRoots: [shadowRoot],\n })?.[0];\n if (\n composedRange === undefined ||\n !this.#rangeBelongsToEditor(composedRange)\n ) {\n return;\n }\n\n let selection = convertSelection(composedRange, DirectionNone);\n if (selection === undefined) {\n return;\n }\n\n // extend selection by shift + click\n if (\n this.#isContentMouseDown &&\n this.#shiftKeyPressed &&\n this.#selections !== undefined &&\n this.#selections.length > 0\n ) {\n const primarySelection = this.#selections.at(-1)!;\n this.#updateSelections([\n extendSelection(primarySelection, selection),\n ]);\n return;\n }\n\n if (this.#isContentMouseDown) {\n if (this.#selectionStart !== undefined) {\n selection = createSelectionFrom(this.#selectionStart, selection);\n } else {\n this.#selectionStart = selection;\n }\n } else if (this.#selectionStart !== undefined) {\n selection.direction = createSelectionFrom(\n this.#selectionStart,\n selection\n ).direction;\n }\n\n if (this.#reservedSelections !== undefined) {\n this.#updateSelections([\n ...this.#reservedSelections.filter(\n (reservedSelection) =>\n !selectionIntersects(reservedSelection, selection)\n ),\n selection,\n ]);\n } else {\n this.#updateSelections([selection]);\n }\n },\n { passive: true }\n ),\n\n addEventListener(\n document,\n 'pointerup',\n (e) => {\n if (e.pointerType !== 'mouse') {\n return;\n }\n\n this.#selectEventDisposes?.forEach((dispose) => dispose());\n this.#selectEventDisposes = undefined;\n\n if (this.#isGutterMouseDown) {\n this.#isGutterMouseDown = false;\n this.#focus();\n }\n this.#shouldIgnoreSelectionChange = false;\n this.#isContentMouseDown = false;\n this.#shiftKeyPressed = false;\n this.#selectionStart = undefined;\n this.#reservedSelections = undefined;\n this.#overlayElements?.forEach((el, key) => {\n if (key.startsWith('selectionActionIcon-')) {\n el.dataset.visible = 'true';\n }\n });\n },\n { passive: true }\n ),\n\n addEventListener(\n document,\n 'keydown',\n (e) => {\n if (e.key === 'Shift') {\n this.#selectionStart = this.#selections?.at(-1);\n }\n },\n { passive: true }\n ),\n\n addEventListener(\n document,\n 'keyup',\n (e) => {\n if (e.key === 'Shift') {\n this.#selectionStart = undefined;\n }\n },\n { passive: true }\n ),\n ];\n }\n\n #listenContentElement(contentEl: HTMLElement, gutterEl?: HTMLElement): void {\n const targetIsContentElement = (e: Event) => {\n const target = e.composedPath()[0] as HTMLElement | undefined;\n return (\n target !== undefined &&\n (target === contentEl || contentEl.contains(target))\n );\n };\n\n this.#editorEventDisposes?.forEach((dispose) => dispose());\n this.#editorEventDisposes = [\n addEventListener(\n contentEl,\n 'pointerdown',\n (e) => {\n if (e.pointerType !== 'mouse') {\n return;\n }\n\n this.#markerRenderer?.removePopup();\n\n // this is a workaround for the selection rendering glitch\n // happens when selecting content in shadow DOM on Safari\n if (\n isSafari() &&\n this.#lineAnnotations !== undefined &&\n this.#lineAnnotations.length > 0\n ) {\n this.#selectEventDisposes = [\n ...contentEl.querySelectorAll<HTMLElement>(\n '[data-line-annotation]'\n ),\n ]\n .map((el) => [\n addEventListener(el, 'mouseenter', () => {\n this.#shouldIgnoreSelectionChange = true;\n }),\n addEventListener(el, 'mouseleave', () => {\n this.#shouldIgnoreSelectionChange = false;\n }),\n ])\n .flat();\n }\n\n this.#isContentMouseDown = true;\n this.#selectionStart = undefined;\n if (e.button === 0 && isPrimaryModifier(e)) {\n this.#reservedSelections = this.#selections?.map((selection) => ({\n ...selection,\n }));\n }\n if (e.shiftKey) {\n const primarySelection = this.#selections?.at(-1);\n if (primarySelection !== undefined) {\n const pos =\n primarySelection.direction === DirectionBackward\n ? primarySelection.end\n : primarySelection.start;\n // fix the window selection for shift mode\n this.#setWindowSelection({\n start: pos,\n end: pos,\n direction: DirectionNone,\n });\n }\n this.#shiftKeyPressed = true;\n }\n },\n { passive: true }\n ),\n\n addEventListener(contentEl, 'keydown', (e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n this.#searchPanel?.cleanup();\n this.#searchPanel = undefined;\n this.#retainSearchPanelFocus = false;\n this.#selectionAction?.cleanup();\n this.#selectionAction = undefined;\n if (this.#selections !== undefined && this.#selections.length > 0) {\n const primarySelection = this.#selections.at(-1)!;\n if (\n !isCollapsedSelection(primarySelection) ||\n this.#selections.length > 1\n ) {\n const pos = getCaretPosition(primarySelection);\n this.#updateSelections([\n {\n start: pos,\n end: pos,\n direction: DirectionNone,\n },\n ]);\n this.#focus(pos);\n }\n }\n return;\n }\n if (!targetIsContentElement(e)) {\n return;\n }\n\n // handle the cursor move events manually for multiple selections and virtual viewport\n const mvShortcut = isMoveCursorShortcut(e);\n const textDocument = this.#textDocument;\n if (\n this.#selections !== undefined &&\n this.#selections.length > 0 &&\n mvShortcut !== undefined &&\n textDocument !== undefined\n ) {\n if (e.shiftKey) {\n this.#updateSelections(\n mapSelectionShift(textDocument, this.#selections, mvShortcut)\n );\n } else {\n this.#updateSelections(\n mapCursorMove(textDocument, this.#selections, mvShortcut)\n );\n }\n this.#scrollToPrimaryCaret();\n e.preventDefault();\n return;\n }\n\n const command = resolveEditorCommandFromKeyboardEvent(e);\n if (command !== undefined) {\n e.preventDefault();\n this.#runCommand(command);\n }\n }),\n\n addEventListener(contentEl, 'copy', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n e.clipboardData?.setData('text', this.#getSelectionText());\n }),\n\n addEventListener(contentEl, 'cut', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n e.clipboardData?.setData('text', this.#getSelectionText());\n this.#replaceSelectionText('');\n }),\n\n addEventListener(contentEl, 'paste', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n const text = e.clipboardData?.getData('text');\n if (text !== undefined) {\n // TODO(@ije): Add support of multiple selections copy&paste\n // TODO(@ije): normalize the pasted text with textDocument.EOF\n this.#replaceSelectionText(text);\n }\n }),\n\n addEventListener(contentEl, 'beforeinput', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n this.#handleInput(e.inputType, e.data);\n }),\n\n addEventListener(contentEl, 'drop', (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n e.preventDefault();\n // TODO(@ije): Add support of drag move selection\n }),\n\n addEventListener(\n contentEl,\n 'compositionstart',\n (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n this.#shouldIgnoreSelectionChange = true;\n },\n { passive: true }\n ),\n\n addEventListener(\n contentEl,\n 'compositionend',\n (e) => {\n if (!targetIsContentElement(e)) {\n return;\n }\n this.#shouldIgnoreSelectionChange = false;\n this.#handleInput('insertText', e.data);\n },\n { passive: true }\n ),\n ];\n if (gutterEl !== undefined) {\n const resolveGutterTarget = (\n eventTarget: HTMLElement | undefined,\n includeContentLine = false\n ) => {\n let target = eventTarget;\n if (target?.dataset.lineNumberContent !== undefined) {\n target = target.parentElement ?? undefined;\n } else if (includeContentLine && target?.tagName === 'SPAN') {\n target = target.closest('[data-line]') as HTMLElement | undefined;\n }\n return target;\n };\n\n const resolveEditableLine = (target: HTMLElement | undefined) => {\n if (target === undefined) {\n return;\n }\n const lineType = target.dataset.lineType;\n const lineNumber =\n getLineNumberAttr(target) ??\n getLineNumberAttr(target, 'columnNumber');\n if (\n lineNumber === undefined ||\n lineType === undefined ||\n !isLineEditable(lineType)\n ) {\n return;\n }\n return lineNumber - 1;\n };\n\n this.#editorEventDisposes.push(\n addEventListener(\n gutterEl,\n 'pointerdown',\n (e) => {\n const textDocument = this.#textDocument;\n const lineIndex = resolveEditableLine(\n resolveGutterTarget(\n e.composedPath()[0] as HTMLElement | undefined\n )\n );\n if (lineIndex === undefined || textDocument === undefined) {\n return;\n }\n\n this.#markerRenderer?.removePopup();\n const selection: EditorSelection = {\n start: { line: lineIndex, character: 0 },\n end: {\n line: lineIndex,\n character: textDocument.getLineText(lineIndex).length,\n },\n direction: DirectionForward,\n };\n this.#isGutterMouseDown = true;\n this.#selectionStart = selection;\n this.#updateSelections([selection]);\n this.#focus(selection.end);\n this.#selectEventDisposes = [\n addEventListener(\n document,\n 'mousemove',\n (e) => {\n if (!this.#isGutterMouseDown) {\n return;\n }\n const textDocument = this.#textDocument;\n const lineIndex = resolveEditableLine(\n resolveGutterTarget(\n e.composedPath()[0] as HTMLElement | undefined,\n true\n )\n );\n if (lineIndex === undefined || textDocument === undefined) {\n return;\n }\n\n let selection: EditorSelection = {\n start: { line: lineIndex, character: 0 },\n end: {\n line: lineIndex,\n character: textDocument.getLineText(lineIndex).length,\n },\n direction: DirectionForward,\n };\n if (this.#selectionStart !== undefined) {\n selection = createSelectionFrom(\n this.#selectionStart,\n selection\n );\n } else {\n this.#selectionStart = selection;\n }\n this.#updateSelections([selection]);\n this.#focus(selection.end);\n },\n { passive: true }\n ),\n ];\n },\n { passive: true }\n )\n );\n }\n\n this.#markerRenderer?.listenHover(contentEl);\n\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = new ResizeObserver(() => {\n this.#handleLayoutResize();\n });\n this.#resizeObserver.observe(contentEl);\n this.#resizeObserver.observe(contentEl.parentElement!);\n }\n\n // TODO(@ije): add command registry\n #runCommand(command: EditorCommand) {\n const textDocument = this.#textDocument;\n if (textDocument === undefined) {\n return;\n }\n\n switch (command) {\n case 'openSearchPanel':\n this.#openSearchPanel('find');\n break;\n\n case 'openSearchReplacePanel':\n this.#openSearchPanel('replace');\n break;\n\n case 'findNextMatch': {\n const selections = this.#selections;\n if (selections === undefined) {\n break;\n }\n const hasCollapsed = selections.some(isCollapsedSelection);\n if (hasCollapsed) {\n const expanded: EditorSelection[] = selections.map((sel) => {\n if (isCollapsedSelection(sel)) {\n return expandCollapsedSelectionToWord(textDocument, sel);\n }\n return sel;\n });\n this.#updateSelections(expanded);\n this.focus();\n } else {\n const nextMatch = findNexMatch(textDocument, selections);\n if (nextMatch !== undefined) {\n this.#updateSelections(nextMatch);\n this.#scrollToPrimaryCaret();\n }\n }\n break;\n }\n\n case 'indent':\n case 'outdent':\n if (this.#selections !== undefined) {\n const edits: TextEdit[] = [];\n const nextSelections: EditorSelection[] = [];\n for (const selection of this.#selections) {\n const startLine = selection.start.line;\n const outdent = command === 'outdent';\n if (startLine !== selection.end.line || outdent) {\n const ret = resolveIndentEdits(\n textDocument,\n selection,\n this.#metrics.tabSize,\n outdent\n );\n edits.push(...ret[0]);\n nextSelections.push(ret[1]);\n } else {\n const lineChar0 = textDocument.charAt({\n line: startLine,\n character: 0,\n });\n this.#replaceSelectionText(\n lineChar0 === '\\t' ? '\\t' : ' '.repeat(this.#metrics.tabSize)\n );\n }\n }\n const change = textDocument.applyEdits(\n edits,\n true,\n this.#selections,\n nextSelections\n );\n if (change !== undefined) {\n this.#applyChange(change, nextSelections);\n }\n }\n break;\n\n case 'selectAll':\n this.#updateSelections([getDocumentFullSelection(textDocument)]);\n this.focus();\n break;\n\n case 'moveCursorToDocStart':\n case 'moveCursorToDocEnd':\n {\n const atEnd = command === 'moveCursorToDocEnd';\n this.#updateSelections([\n getDocumentBoundarySelection(textDocument, atEnd),\n ]);\n this.#scrollToPrimaryCaret();\n }\n break;\n\n case 'expandSelectionDocStart':\n case 'expandSelectionDocEnd':\n {\n const atEnd = command === 'expandSelectionDocEnd';\n const selections = this.#selections;\n if (selections !== undefined) {\n this.#updateSelections(\n extendSelections(\n selections,\n getDocumentBoundarySelection(textDocument, atEnd)\n )\n );\n this.#scrollToPrimaryCaret();\n }\n }\n break;\n\n case 'undo':\n if (this.#textDocument?.canUndo === true) {\n const undoResult = this.#textDocument.undo();\n if (undoResult !== undefined) {\n this.#applyChange(...undoResult);\n }\n }\n break;\n\n case 'redo':\n if (this.#textDocument?.canRedo === true) {\n const redoResult = this.#textDocument.redo();\n if (redoResult !== undefined) {\n this.#applyChange(...redoResult);\n }\n }\n break;\n }\n }\n\n #handleLayoutResize() {\n const lineAnnotations = this.#lineAnnotations?.length ?? 0;\n const prevGutterWidth = this.#gutterWidthCache;\n const prevContentWidth = this.#contentWidthCache;\n this.#gutterWidthCache = undefined;\n this.#contentWidthCache = undefined;\n const gutterWidthChanged = this.#getGutterWidth() !== prevGutterWidth;\n const contentWidthChanged = this.#getContentWidth() !== prevContentWidth;\n if (!gutterWidthChanged && !contentWidthChanged) {\n return;\n }\n\n this.#lastAccessedLineElement = undefined;\n this.#lastAccessedCharX = undefined;\n if (contentWidthChanged && (this.#wrap || lineAnnotations > 0)) {\n this.#lineYCache.clear();\n this.#wrapLineOffsetsCache.clear();\n }\n if (\n this.#selections !== undefined ||\n this.#matches !== undefined ||\n this.#markerRenderer !== undefined\n ) {\n this.#updateSelections(this.#selections ?? []);\n if (this.#selections !== undefined) {\n this.focus();\n }\n }\n this.#markerRenderer?.removePopup();\n }\n\n #rerender(\n change: TextDocumentChange,\n newLineAnnotations?: DiffLineAnnotation<LAnnotation>[],\n renderRange = this.#renderRange,\n shouldUpdateBuffer?: boolean\n ) {\n const tokenizer = this.#tokenizer;\n const fileInstance = this.#fileInstance;\n const fileContents = this.#fileContents;\n const textDocument = this.#textDocument;\n const gutterEl = this.#gutterElement;\n const contentEl = this.#contentElement;\n if (\n tokenizer === undefined ||\n fileInstance === undefined ||\n fileContents === undefined ||\n textDocument === undefined ||\n contentEl === undefined\n ) {\n return;\n }\n\n // cancel existing background tokenzier task\n tokenizer.stopBackgroundTokenize();\n\n const t = performance.now();\n const dirtyLines = tokenizer.tokenize(change, renderRange);\n const t2 = performance.now();\n\n if (dirtyLines.size > 0) {\n const children = contentEl.children;\n const dirtyLineIndexes = new Set<number>(dirtyLines.keys());\n\n // update line elements that have been changed in the document\n const startingLine = renderRange?.startingLine ?? 0;\n for (let i = change.startLine - startingLine; i < children.length; i++) {\n const child = children[i] as HTMLElement | undefined;\n if (child !== undefined) {\n const lineNumber = getLineNumberAttr(child);\n if (lineNumber !== undefined) {\n const lineIndex = lineNumber - 1;\n if (dirtyLines.has(lineIndex)) {\n const tokens = dirtyLines.get(lineIndex)!;\n child.replaceChildren(\n ...renderLineTokens(tokens, tokenizer.themeType)\n );\n dirtyLineIndexes.delete(lineIndex);\n if (dirtyLineIndexes.size === 0) {\n break;\n }\n }\n }\n }\n }\n\n // create new line elements for the new lines\n if (dirtyLineIndexes.size > 0) {\n for (const lineIndex of dirtyLineIndexes) {\n const tokens = dirtyLines.get(lineIndex)!;\n const lineNumber = String(lineIndex + 1);\n h(\n 'div',\n {\n dataset: {\n line: lineNumber,\n lineType: 'context',\n lineIndex: lineIndex.toString(),\n },\n // oxlint-disable-next-line react/no-children-prop\n children: renderLineTokens(tokens, tokenizer.themeType),\n },\n contentEl\n );\n if (gutterEl !== undefined) {\n h(\n 'div',\n {\n dataset: {\n lineType: 'context',\n columnNumber: lineNumber,\n lineIndex: lineIndex.toString(),\n },\n // oxlint-disable-next-line react/no-children-prop\n children: [\n h('span', {\n dataset: {\n lineNumberContent: '',\n },\n textContent: lineNumber,\n }),\n ],\n },\n gutterEl\n );\n }\n }\n }\n }\n\n // remove line elements that have been deleted in the document\n if (change.lineDelta < 0) {\n for (const children of [contentEl.children, gutterEl?.children ?? []]) {\n for (let i = children.length - 1; i >= 0; i--) {\n const child = children[i] as HTMLElement;\n const lineNumber =\n getLineNumberAttr(child) ??\n getLineNumberAttr(child, 'columnNumber');\n if (lineNumber === undefined) {\n continue;\n }\n if (lineNumber - 1 < change.lineCount) {\n break;\n }\n child.remove();\n }\n }\n }\n\n const isDiff = Object.hasOwn(fileInstance, 'fileDiff');\n const didLineCountChange = change.lineDelta !== 0;\n\n // fix grid layout\n if (didLineCountChange) {\n let gridRow = contentEl.children.length;\n for (const child of contentEl.children) {\n const { bufferSize } = (child as HTMLElement).dataset;\n if (bufferSize !== undefined) {\n gridRow += parseInt(bufferSize) - 1;\n }\n }\n contentEl.style.gridRow = 'span ' + gridRow;\n if (gutterEl !== undefined) {\n gutterEl.style.gridRow = 'span ' + gridRow;\n }\n }\n\n fileInstance.updateRenderCache(\n dirtyLines,\n tokenizer.themeType,\n isDiff ? !didLineCountChange : undefined\n );\n if (didLineCountChange) {\n fileInstance.applyDocumentChange(\n textDocument,\n newLineAnnotations,\n shouldUpdateBuffer\n );\n }\n\n if (newLineAnnotations !== undefined) {\n this.#lineAnnotations = newLineAnnotations;\n renderLineAnnotations(newLineAnnotations, contentEl, gutterEl);\n }\n\n if (this.#options.__debug === true) {\n console.log(\n `[diffs/editor] re-render in: ${round(performance.now() - t2)}ms,`,\n `tokenize in: ${round(t2 - t)}ms (${dirtyLines.size} dirty lines)`\n );\n }\n }\n\n // input type doc: https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/inputType\n #handleInput(inputType: string, data: string | null) {\n switch (inputType) {\n case 'insertText':\n this.#replaceSelectionText(data ?? '');\n break;\n case 'insertParagraph':\n // TODO(@ije): use document.EOF instead of '\\n'\n this.#replaceSelectionText('\\n');\n break;\n case 'deleteContentBackward':\n this.#deleteSelectionText();\n break;\n case 'deleteContentForward':\n this.#deleteSelectionText(true);\n break;\n case 'deleteSoftLineBackward':\n this.#deleteSoftLineBackward();\n break;\n case 'deleteHardLineForward':\n // TODO(@ije): Safari and Firefox does not support this input type\n // use command instead\n this.#deleteHardLineForward();\n break;\n case 'deleteWordBackward':\n this.#deleteWordBackward();\n break;\n case 'insertTranspose':\n this.#insertTranspose();\n break;\n default:\n console.warn(`[diffs] Unknown input type: ${inputType}`, data);\n break;\n }\n }\n\n #focus(position?: Position, preventScroll = true) {\n if (position !== undefined) {\n this.#shouldIgnoreSelectionChange = true;\n this.#setWindowSelection({\n start: position,\n end: position,\n direction: DirectionNone,\n });\n // call focus in a request animation frame to prevent conflict with\n // the `setBaseAndExtent` method\n requestAnimationFrame(() => {\n this.#contentElement?.focus({ preventScroll });\n // another request animation frame since the `focus` call\n // may trigger a selectionchange event, which we want to ignore\n requestAnimationFrame(() => {\n this.#shouldIgnoreSelectionChange = false;\n });\n });\n } else {\n this.#contentElement?.focus({ preventScroll });\n }\n }\n\n // set window native selection to match the selection\n #setWindowSelection(selection: EditorSelection) {\n const winSelection = window.getSelection();\n if (winSelection === null) {\n return;\n }\n let { start, end, direction } = selection;\n if (comparePosition(start, end) > 0) {\n [start, end] = [end, start];\n }\n const startLineElement = this.#getLineElement(start.line);\n const endLineElement = this.#getLineElement(end.line);\n if (startLineElement === undefined || endLineElement === undefined) {\n return;\n }\n let [anchorNode, anchorOffset] = getSelectionAnchor(\n startLineElement,\n start.character\n );\n let [focusNode, focusOffset] = getSelectionAnchor(\n endLineElement,\n end.character\n );\n if (direction === DirectionBackward) {\n [anchorNode, anchorOffset, focusNode, focusOffset] = [\n focusNode,\n focusOffset,\n anchorNode,\n anchorOffset,\n ];\n }\n try {\n winSelection.setBaseAndExtent(\n anchorNode,\n clampDomOffset(anchorNode, anchorOffset),\n focusNode,\n clampDomOffset(focusNode, focusOffset)\n );\n } catch (err) {\n console.error('[diffs/editor] failed to update window selection:', err);\n }\n }\n\n #scrollToPrimaryCaret(\n noFocus = false,\n scrollPosition: ScrollLogicalPosition = 'nearest'\n ) {\n const primarySelection = this.#selections?.at(-1);\n if (primarySelection === undefined) {\n return;\n }\n const primaryCaretElement = this.#primaryCaretElement;\n if (primaryCaretElement !== undefined) {\n primaryCaretElement.scrollIntoView({\n block: scrollPosition,\n inline: 'nearest',\n });\n if (!noFocus) {\n this.#focus(\n primarySelection.direction === DirectionBackward\n ? primarySelection.end\n : primarySelection.start\n );\n }\n } else {\n const pos = getCaretPosition(primarySelection);\n this.#scrollToLine(pos.line, pos.character, noFocus);\n }\n }\n\n // add scroll margin to the primary caret element to prevent\n // the caret from being hidden by the gutter\n #getScrollMargin() {\n const componentTop = this.#fileInstance?.top ?? 0;\n const top = this.#searchPanel !== undefined ? 48 : 0;\n const start = this.#getGutterWidth() + this.#metrics.ch;\n const end = this.#metrics.ch;\n return `${componentTop + top}px ${end}px 0 ${start}px`;\n }\n\n #scrollToLine(line: number, char = 0, noFocus = false) {\n this.__postponeBackgroundTokenizeToNextFrame();\n\n const virtualCaret = h('div', {\n style: {\n position: 'absolute',\n left: '0',\n width: '2px',\n height: this.#metrics.lineHeight + 'px',\n scrollMargin: this.#getScrollMargin(),\n },\n });\n if (this.#getLineElement(line) !== undefined) {\n const [left, wrapLine] = this.#getCharX(line, char);\n const lineY = this.#getLineY(line) + wrapLine * this.#metrics.lineHeight;\n virtualCaret.style.top = lineY + 'px';\n virtualCaret.style.left = left + 'px';\n this.#overlayElement?.appendChild(virtualCaret);\n virtualCaret.scrollIntoView({ block: 'center', inline: 'nearest' });\n if (!noFocus) {\n this.#focus({ line, character: char });\n }\n this.#scrollingToLine = undefined;\n this.#scrollingToLineChar = undefined;\n this.#scrollingToLineNoFocus = false;\n }\n // if the line is not rendered yet(virtualized), scroll to the approximate\n // line position to trigger the line to be rendered, then recall this function\n // to ensure the line is scrolled into view\n else {\n let yFix = 0;\n if (\n this.#scrollingToLine === line &&\n this.#contentElement !== undefined\n ) {\n for (let i = this.#contentElement.childElementCount - 1; i >= 0; i--) {\n const child = this.#contentElement.children[i] as HTMLElement;\n const lineType = child.dataset.lineType;\n const lineNumber = getLineNumberAttr(child);\n if (\n lineType !== undefined &&\n isLineEditable(lineType) &&\n lineNumber !== undefined\n ) {\n yFix = (line - lineNumber) * this.#metrics.lineHeight;\n break;\n }\n }\n }\n const lineAnnotations = (this.#lineAnnotations ?? []).filter(\n (annotation) => annotation.lineNumber < line\n ).length;\n const approximateLineY =\n (lineAnnotations + line) * this.#metrics.lineHeight + yFix;\n virtualCaret.style.top = approximateLineY + 'px';\n this.#fileContainer?.shadowRoot?.appendChild(virtualCaret);\n virtualCaret.scrollIntoView({ block: 'center', inline: 'nearest' });\n if (this.#scrollingToLine === line && yFix === 0) {\n this.#scrollingToLine = undefined;\n this.#scrollingToLineChar = undefined;\n this.#scrollingToLineNoFocus = false;\n } else {\n this.#scrollingToLine = line;\n this.#scrollingToLineChar = char;\n this.#scrollingToLineNoFocus = noFocus;\n }\n }\n virtualCaret.remove();\n }\n\n #updateSelections(selections: EditorSelection[]) {\n this.__postponeBackgroundTokenizeToNextFrame();\n\n this.#primaryCaretElement = undefined;\n this.#fileInstance?.setSelectedLines(null);\n this.#gutterElement\n ?.querySelectorAll('[data-active]')\n .forEach((el) => el.removeAttribute('data-active'));\n\n if (\n selections.length === 0 &&\n this.#matches === undefined &&\n this.#markerRenderer === undefined\n ) {\n this.#selections = undefined;\n this.#overlayElements?.forEach((el) => el.remove());\n this.#overlayElements?.clear();\n return;\n }\n\n const fragment = document.createDocumentFragment();\n const renderCtx = {\n fragment,\n elements: new Map<string, HTMLElement>(),\n };\n\n if (selections.length > 0) {\n const normalizedSelections = mergeOverlappingSelections(selections);\n const primarySelection = normalizedSelections.at(-1)!;\n this.#selections = normalizedSelections;\n if (isCollapsedSelection(primarySelection)) {\n const line = primarySelection.start.line + 1;\n this.#fileInstance?.setSelectedLines({\n start: line,\n end: line,\n });\n } else {\n if (this.#gutterElement !== undefined) {\n const pos = getCaretPosition(primarySelection);\n this.#gutterElement\n .querySelector(`[data-column-number=\"${pos.line + 1}\"]`)\n ?.setAttribute('data-active', '');\n }\n }\n\n for (const selection of normalizedSelections) {\n if (!isCollapsedSelection(selection)) {\n this.#renderSelection(renderCtx, 'selection', selection);\n }\n this.#renderCaret(renderCtx, selection, selection === primarySelection);\n }\n if (\n this.#options.enabledSelectionAction === true &&\n !isCollapsedSelection(primarySelection)\n ) {\n this.#renderSelectionActionIcon(renderCtx, primarySelection);\n }\n }\n\n const textDocument = this.#textDocument;\n if (this.#matches !== undefined && textDocument !== undefined) {\n const primarySelection = this.#selections?.at(-1);\n const primaryStartOffset =\n primarySelection !== undefined\n ? textDocument.offsetAt(primarySelection.start)\n : -1;\n const primaryEndOffset =\n primarySelection !== undefined\n ? textDocument.offsetAt(primarySelection.end)\n : -1;\n for (const [startOffset, endOffset] of this.#matches) {\n const range: Range = {\n start: textDocument.positionAt(startOffset),\n end: textDocument.positionAt(endOffset),\n };\n const isFocused =\n primaryStartOffset === startOffset && primaryEndOffset === endOffset;\n this.#renderSelection(\n renderCtx,\n 'match',\n range,\n isFocused ? 'focus' : undefined\n );\n }\n }\n\n if (this.#markerRenderer !== undefined && textDocument !== undefined) {\n for (const marker of this.#markerRenderer.markers) {\n this.#renderSelection(\n renderCtx,\n 'marker',\n marker,\n markerSeverityDatasetKey(marker.severity)\n );\n }\n }\n\n this.#overlayElement?.appendChild(fragment);\n this.#overlayElements?.forEach((el) => el.remove());\n this.#overlayElements?.clear();\n this.#overlayElements = renderCtx.elements;\n }\n\n #renderSelection(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n },\n type: 'selection' | 'match' | 'marker',\n range: Range,\n extraDataset?: string\n ) {\n if (this.#textDocument === undefined) {\n return;\n }\n\n const { start, end } = range;\n for (let line = start.line; line <= end.line; line++) {\n if (!this.#isLineVisible(line)) {\n continue;\n }\n\n const isLastLine = line === end.line;\n const lineText = this.#textDocument.getLineText(line);\n const startChar = line === start.line ? start.character : 0;\n const endChar = isLastLine ? end.character : lineText.length;\n\n if (this.#wrap) {\n const contentWidth = this.#getContentWidth();\n const textWidth =\n 2 * this.#metrics.ch + this.#metrics.measureTextWidth(lineText);\n if (textWidth > contentWidth) {\n this.#renderWrappedSelection(\n renderCtx,\n line,\n lineText,\n startChar,\n endChar,\n isLastLine,\n type,\n extraDataset\n );\n continue;\n }\n }\n\n let left = 0;\n let width = 0;\n let paddingEnd = 0;\n if (startChar === 0) {\n left = this.#getGutterWidth() + this.#metrics.ch; // gutter width + inline padding (1ch)\n } else {\n left = this.#getCharX(line, startChar)[0];\n }\n if (!isLastLine && type === 'selection') {\n paddingEnd = this.#metrics.ch;\n }\n if (startChar === endChar) {\n width = paddingEnd;\n } else {\n width = this.#getCharX(line, endChar)[0] - left + paddingEnd;\n }\n this.#renderSelectionBlock(\n renderCtx,\n type,\n line,\n 0,\n left,\n width,\n extraDataset\n );\n }\n }\n\n // Render the selection on a wrapped logical line by splitting it into one\n // selection-range div per visual sub-line. For each wrap segment, we compute\n // the intersection with the line's selection range and render the slice in\n // segment-local coordinates so left/width line up with the visually wrapped\n // text. Zero-width slices that fall on intermediate segment boundaries are\n // skipped to avoid duplicate markers across consecutive visual lines.\n #renderWrappedSelection(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n },\n line: number,\n lineText: string,\n startChar: number,\n endChar: number,\n isLastLine: boolean,\n type: 'selection' | 'match' | 'marker',\n extraDataset?: string\n ) {\n const wrapOffsets = this.#wrapLineText(line);\n const segmentCount = wrapOffsets.length - 1;\n const offsetLeft = this.#getGutterWidth() + this.#metrics.ch;\n\n for (let wrapLine = 0; wrapLine < segmentCount; wrapLine++) {\n const segmentStart = wrapOffsets[wrapLine];\n const segmentEnd = wrapOffsets[wrapLine + 1];\n const wrapStartChar = Math.max(startChar, segmentStart);\n const wrapEndChar = Math.min(endChar, segmentEnd);\n\n // Selection range doesn't reach this visual segment.\n if (wrapStartChar > wrapEndChar) {\n continue;\n }\n\n let segmentLeft: number;\n let segmentWidth: number;\n let paddingEnd = 0;\n if (wrapStartChar === 0) {\n segmentLeft = offsetLeft;\n } else {\n const prefixInSegment = lineText.slice(segmentStart, wrapStartChar);\n const prefixAsciiColumns = getExpandedAsciiTextColumns(\n prefixInSegment,\n this.#metrics.tabSize\n );\n segmentLeft =\n offsetLeft +\n (prefixAsciiColumns !== -1\n ? prefixAsciiColumns * this.#metrics.ch\n : this.#metrics.measureTextWidth(prefixInSegment));\n }\n if (\n !isLastLine &&\n wrapLine === segmentCount - 1 &&\n type === 'selection'\n ) {\n paddingEnd = this.#metrics.ch;\n }\n if (wrapStartChar === wrapEndChar) {\n segmentWidth = paddingEnd;\n } else {\n const selectionInSegment = lineText.slice(wrapStartChar, wrapEndChar);\n const selectionAsciiWidth = getExpandedAsciiTextColumns(\n selectionInSegment,\n this.#metrics.tabSize\n );\n segmentWidth =\n selectionAsciiWidth !== -1\n ? selectionAsciiWidth * this.#metrics.ch\n : this.#metrics.measureTextWidth(selectionInSegment);\n segmentWidth += paddingEnd;\n }\n\n this.#renderSelectionBlock(\n renderCtx,\n type,\n line,\n wrapLine,\n segmentLeft,\n segmentWidth,\n extraDataset\n );\n }\n }\n\n // Render one selection block for a single visual line.\n #renderSelectionBlock(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n previousSelectionRange?: {\n element: HTMLElement;\n line: number;\n wrapLine: number;\n left: number;\n width: number;\n };\n },\n type: 'selection' | 'match' | 'marker',\n line: number,\n wrapLine: number,\n left: number,\n width: number,\n extraDataset?: string\n ) {\n if (width === 0) {\n return;\n }\n\n const { ch, lineHeight } = this.#metrics;\n const y = this.#getLineY(line) + wrapLine * lineHeight;\n const css = `width:${width}px;transform:translateX(${left}px) translateY(${y}px);`;\n const cacheKey = `${type}-${left}-${y}-${width}${extraDataset ?? ''}`;\n const overlayEls = this.#overlayElements;\n\n const rounded =\n (this.#options.roundedSelection ?? true) && type === 'selection';\n const addRoundedCorner = (\n line: number,\n wrapLine: number,\n left: number,\n radius: 'rtl' | 'rbl' | 'rbr'\n ) => {\n const top = this.#getLineY(line) + wrapLine * lineHeight;\n const css = `width:${ch}px;transform:translateX(${left}px) translateY(${top}px);`;\n const dataset = {\n selectionCorner: '',\n [radius]: '',\n };\n const cacheKeyPrefix = `${type}-block-${left}-${top}-1ch`;\n let cacheKey = cacheKeyPrefix + '-' + radius;\n if (radius === 'rbl') {\n const prevCornerKey = cacheKeyPrefix + '-rtl';\n const prevCorner = renderCtx.elements.get(prevCornerKey);\n if (prevCorner !== undefined) {\n prevCorner.remove();\n renderCtx.elements.delete(prevCornerKey);\n cacheKey += '-rtl';\n dataset.rtl = '';\n }\n }\n let cornerEl = renderCtx.elements.get(cacheKey);\n if (cornerEl !== undefined) {\n return;\n }\n if (overlayEls?.has(cacheKey) === true) {\n cornerEl = overlayEls.get(cacheKey)!;\n overlayEls.delete(cacheKey);\n } else {\n cornerEl = h(\n 'div',\n {\n dataset: 'selectionRange',\n style: { cssText: css },\n children: [\n h('div', {\n dataset: dataset,\n }),\n ],\n },\n renderCtx.fragment\n );\n }\n renderCtx.elements.set(cacheKey, cornerEl);\n };\n const addRadiusStyle = (element: HTMLElement) => {\n const end = left + width;\n const dataset = element.dataset;\n const previousSelectionRange = renderCtx.previousSelectionRange;\n if (\n previousSelectionRange === undefined ||\n previousSelectionRange.line !== line ||\n previousSelectionRange.wrapLine !== wrapLine\n ) {\n renderCtx.previousSelectionRange = {\n element,\n line,\n wrapLine,\n left,\n width,\n };\n }\n if (\n previousSelectionRange === undefined ||\n end <= previousSelectionRange.left\n ) {\n ['rtl', 'rtr', 'rbl', 'rbr'].forEach((key) => {\n dataset[key] = '';\n });\n } else {\n const prevLine = previousSelectionRange.line;\n const prevWrapLine = previousSelectionRange.wrapLine;\n const prevLeft = previousSelectionRange.left;\n const prevDataset = previousSelectionRange.element.dataset;\n const prevEnd = prevLeft + previousSelectionRange.width;\n if (prevLeft > left) {\n addRoundedCorner(prevLine, prevWrapLine, prevLeft - ch, 'rbr');\n }\n delete prevDataset.rbl;\n delete dataset.rtl;\n delete dataset.rtr;\n if (end >= prevEnd) {\n delete prevDataset.rbr;\n }\n if (end > prevEnd) {\n addRoundedCorner(prevLine, prevWrapLine, prevEnd, 'rbl');\n dataset.rtr = '';\n }\n if (end < prevEnd) {\n addRoundedCorner(line, wrapLine, end, 'rtl');\n }\n if (left < prevLeft) {\n dataset.rtl = '';\n }\n dataset.rbl = '';\n dataset.rbr = '';\n }\n };\n\n let rangeEl = renderCtx.elements.get(cacheKey);\n if (rangeEl !== undefined) {\n if (rounded) {\n addRadiusStyle(rangeEl);\n }\n return;\n }\n\n if (overlayEls?.has(cacheKey) === true) {\n rangeEl = overlayEls.get(cacheKey)!;\n overlayEls.delete(cacheKey);\n } else {\n rangeEl = h(\n 'div',\n {\n dataset: extraDataset\n ? [type + 'Range', extraDataset]\n : type + 'Range',\n style: { cssText: css },\n },\n renderCtx.fragment\n );\n }\n\n if (rounded) {\n addRadiusStyle(rangeEl);\n }\n renderCtx.elements.set(cacheKey, rangeEl);\n }\n\n #renderCaret(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n },\n selection: EditorSelection,\n isPrimary: boolean\n ) {\n const { line, character } = getCaretPosition(selection);\n if (!this.#isLineVisible(line)) {\n return;\n }\n const [left, wrapLine] = this.#getCharX(line, character);\n const cacheKey = 'caret-' + line + '/' + wrapLine + ':' + character;\n if (renderCtx.elements.has(cacheKey)) {\n return;\n }\n const x = left - 1;\n const y = this.#getLineY(line) + wrapLine * this.#metrics.lineHeight;\n const caretEl = h(\n 'div',\n {\n dataset: 'caret',\n style: {\n transform: `translateX(${x}px) translateY(${y}px)`,\n },\n },\n renderCtx.fragment\n );\n renderCtx.elements.set(cacheKey, caretEl);\n if (isPrimary) {\n caretEl.style.scrollMargin = this.#getScrollMargin();\n this.#primaryCaretElement = caretEl;\n }\n }\n\n #renderSelectionActionIcon(\n renderCtx: {\n fragment: DocumentFragment;\n elements: Map<string, HTMLElement>;\n },\n selection: EditorSelection\n ) {\n const line = getCaretPosition(selection).line;\n if (!this.#isLineVisible(line)) {\n return;\n }\n\n const [left, wrapLine] = this.#getCharX(line, 0);\n const cacheKey = 'selectionActionIcon-' + line + '(' + wrapLine + ')';\n if (renderCtx.elements.has(cacheKey)) {\n return;\n }\n\n const selectionActionIcon = SelectionActionWidget.renderIcon(\n left,\n this.#getLineY(line) + wrapLine * this.#metrics.lineHeight,\n renderCtx.fragment,\n () => {\n const cleanUp = () => {\n this.#selectionAction?.cleanup();\n this.#selectionAction = undefined;\n };\n\n const handleWidgetDomResize = () => {\n // the line y cache is invalidated by the DOM change,\n // clear the line y cache and re-render the selection\n this.#lineYCache.clear();\n if (this.#selections !== undefined) {\n this.#updateSelections(this.#selections);\n }\n };\n\n // remove the existing selection action element\n cleanUp();\n\n const textDocument = this.#textDocument;\n const renderSelectionAction = this.#options.renderSelectionAction;\n const fileContainer = this.#fileContainer;\n if (\n textDocument === undefined ||\n renderSelectionAction === undefined ||\n fileContainer == null\n ) {\n return;\n }\n\n const line = selection.end.line;\n const lineText = textDocument.getLineText(line);\n const selectionActionElement = renderSelectionAction({\n textDocument,\n selection,\n applyEdits: (edits: TextEdit[]) => this.applyEdits(edits, true),\n getSelectionText: () => {\n return this.#textDocument?.getText(selection) ?? '';\n },\n replaceSelectionText: (text: string) => {\n this.#replaceSelectionText(text, [selection]);\n },\n close: () => {\n cleanUp();\n handleWidgetDomResize();\n this.#scrollToPrimaryCaret();\n },\n });\n let leadingWhitespaces = 0;\n for (let i = 0; i < lineText.length; i++) {\n const charCode = lineText.charCodeAt(i);\n if (charCode === /* space */ 32) {\n leadingWhitespaces++;\n } else if (charCode === /* tab */ 9) {\n leadingWhitespaces += this.#metrics.tabSize;\n } else {\n break;\n }\n }\n this.#selectionAction = new SelectionActionWidget(\n line,\n selectionActionElement,\n fileContainer,\n leadingWhitespaces,\n handleWidgetDomResize\n );\n this.#updateSelections([selection]);\n if (this.#isLineVisible(line) && this.#contentElement !== undefined) {\n this.#selectionAction.render(this.#contentElement);\n }\n }\n );\n renderCtx.elements.set(cacheKey, selectionActionIcon);\n }\n\n // Opens the search panel in the requested mode. If a panel is already open,\n // it switches that panel's mode in place (preserving the current query)\n // rather than recreating it.\n #openSearchPanel(mode: SearchPanelMode) {\n if (this.#searchPanel !== undefined) {\n this.#searchPanel.setMode(mode);\n return;\n }\n this.#renderSearchPanel(mode);\n }\n\n // TODO(@ije): render search highlight\n #renderSearchPanel(mode: SearchPanelMode) {\n // cleanup the existing search panel\n this.#searchPanel?.cleanup();\n\n const textDocument = this.#textDocument;\n const preElement =\n this.#fileContainer?.shadowRoot?.querySelector<HTMLElement>('pre');\n const selections = this.#selections;\n if (textDocument === undefined || preElement == null) {\n return;\n }\n\n let defaultQuery = '';\n let initialMatch: [number, number] | undefined = undefined;\n\n if (selections !== undefined && selections.length > 0) {\n let primarySelection = selections.at(-1)!;\n if (isCollapsedSelection(primarySelection)) {\n primarySelection = expandCollapsedSelectionToWord(\n textDocument,\n primarySelection\n );\n this.#updateSelections([...selections.slice(0, -1), primarySelection]);\n const selectionText = textDocument.getText(primarySelection);\n if (selectionText !== '' && !selectionText.includes('\\n')) {\n defaultQuery = selectionText;\n initialMatch = [\n textDocument.offsetAt(primarySelection.start),\n textDocument.offsetAt(primarySelection.end),\n ];\n }\n }\n }\n\n const scrollToMatch = (\n [startOffset, endOffset]: MatchRange,\n retainFocus: boolean\n ) => {\n const nextSelection = createSelectionFromAnchorAndFocusOffsets(\n textDocument,\n startOffset,\n endOffset\n );\n this.#updateSelections([nextSelection]);\n this.#scrollToPrimaryCaret(true); // scroll to the primary caret and don't focus\n this.#retainSearchPanelFocus = retainFocus;\n };\n\n const searchPanel = new SearchPanelWidget({\n textDocument,\n containerElement: preElement,\n defaultQuery,\n mode,\n initialMatch,\n scrollToMatch,\n applyReplace: (edits: ResolvedTextEdit[]) => {\n if (edits.length === 0) {\n return;\n }\n const change = textDocument.applyEdits(\n edits.map((edit) => ({\n range: {\n start: textDocument.positionAt(edit.start),\n end: textDocument.positionAt(edit.end),\n },\n newText: edit.text,\n })),\n true,\n this.#selections\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n undefined,\n this.#applyChangeToLineAnnotations(change),\n { skipSearchRefresh: true }\n );\n }\n },\n onUpdate: (\n allMatches: MatchRange[],\n options?: { syncSelection?: boolean }\n ): MatchRange | undefined => {\n if (allMatches.length === 0) {\n this.#matches = undefined;\n this.#updateSelections(this.#selections ?? []);\n return;\n }\n\n this.#matches = allMatches;\n if (options?.syncSelection === false) {\n this.#updateSelections(this.#selections ?? []);\n const primarySelection = this.#selections?.at(-1);\n if (primarySelection !== undefined) {\n const startOffset = textDocument.offsetAt(primarySelection.start);\n const endOffset = textDocument.offsetAt(primarySelection.end);\n for (const match of allMatches) {\n if (match[0] === startOffset && match[1] === endOffset) {\n return match;\n }\n }\n }\n return undefined;\n }\n\n const primarySelection = this.#selections?.at(-1);\n let searchOffset = 0;\n let nextMatch: MatchRange | undefined;\n if (primarySelection !== undefined) {\n searchOffset = textDocument.offsetAt(primarySelection.start);\n }\n for (const m of allMatches) {\n if (m[0] >= searchOffset) {\n nextMatch = m;\n break;\n }\n }\n if (nextMatch !== undefined) {\n scrollToMatch(nextMatch, true);\n } else {\n this.#updateSelections(this.#selections ?? []);\n }\n return nextMatch;\n },\n onClose: () => {\n this.#searchPanel = undefined;\n this.#retainSearchPanelFocus = false;\n this.#matches = undefined;\n this.#updateSelections(this.#selections ?? []);\n },\n });\n\n this.#searchPanel = searchPanel;\n this.#retainSearchPanelFocus = false;\n }\n\n #getSelectionText() {\n const textDocument = this.#textDocument;\n const selections = this.#selections;\n if (textDocument === undefined || selections === undefined) {\n return '';\n }\n return getSelectionText(textDocument, selections);\n }\n\n // replace the selection text\n #replaceSelectionText(\n text: string | string[],\n selections = this.#selections\n ) {\n if (selections === undefined) {\n return;\n }\n const textDocument = this.#textDocument;\n const primarySelection = selections.at(-1);\n if (textDocument === undefined || primarySelection === undefined) {\n return;\n }\n const { nextSelections, change } =\n Array.isArray(text) && text.length === selections.length\n ? applyTextReplaceToSelections<LAnnotation>(\n textDocument,\n selections,\n text,\n this.#lineAnnotations\n )\n : applyTextChangeToSelections<LAnnotation>(\n textDocument,\n selections,\n {\n start: textDocument.offsetAt(primarySelection.start),\n end: textDocument.offsetAt(primarySelection.end),\n text: Array.isArray(text) ? text.join('\\n') : text,\n },\n this.#lineAnnotations\n );\n\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #deleteSelectionText(forward: boolean = false) {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n\n const primarySelection = selections.at(-1);\n if (primarySelection === undefined) {\n return;\n }\n\n let edit: ResolvedTextEdit;\n if (isCollapsedSelection(primarySelection)) {\n const offset = textDocument.offsetAt(primarySelection.start);\n const nextOffset = forward\n ? Math.min(textDocument.getText().length, offset + 1)\n : Math.max(0, offset - 1);\n edit = {\n start: Math.min(offset, nextOffset),\n end: Math.max(offset, nextOffset),\n text: '',\n };\n } else {\n edit = {\n start: textDocument.offsetAt(primarySelection.start),\n end: textDocument.offsetAt(primarySelection.end),\n text: '',\n };\n }\n\n this.#applyResolvedTextEdit(edit);\n }\n\n #deleteSoftLineBackward() {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n const getSoftLineStart = this.#wrap\n ? (line: number, character: number) => {\n const wrapOffsets = this.#wrapLineText(line);\n for (let w = 0; w + 1 < wrapOffsets.length; w++) {\n const segmentStart = wrapOffsets[w];\n const segmentEnd = wrapOffsets[w + 1];\n if (character >= segmentStart && character <= segmentEnd) {\n return segmentStart;\n }\n }\n return 0;\n }\n : undefined;\n const { nextSelections, change } =\n applyDeleteSoftLineBackwardToSelections<LAnnotation>(\n textDocument,\n selections,\n getSoftLineStart,\n this.#lineAnnotations\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #deleteWordBackward() {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n const { nextSelections, change } =\n applyDeleteWordBackwardToSelections<LAnnotation>(\n textDocument,\n selections,\n this.#lineAnnotations\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #deleteHardLineForward() {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n const { nextSelections, change } =\n applyDeleteHardLineForwardToSelections<LAnnotation>(\n textDocument,\n selections,\n this.#lineAnnotations\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #insertTranspose() {\n const selections = this.#selections;\n const textDocument = this.#textDocument;\n if (selections === undefined || textDocument === undefined) {\n return;\n }\n const { nextSelections, change } = applyTransposeToSelections<LAnnotation>(\n textDocument,\n selections,\n this.#lineAnnotations\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #applyResolvedTextEdit(edit: ResolvedTextEdit) {\n if (this.#selections === undefined || this.#textDocument === undefined) {\n return;\n }\n const { nextSelections, change } = applyTextChangeToSelections<LAnnotation>(\n this.#textDocument,\n this.#selections,\n edit,\n this.#lineAnnotations,\n this.#metrics.tabSize\n );\n if (change !== undefined) {\n this.#applyChange(\n change,\n nextSelections,\n this.#applyChangeToLineAnnotations(change)\n );\n }\n }\n\n #getFileRef(): FileContents | undefined {\n const fileContents = this.#fileContents;\n const textDocument = this.#textDocument;\n if (fileContents === undefined || textDocument === undefined) {\n return undefined;\n }\n const { contents: _, ...file } = fileContents;\n Object.defineProperty(file, 'contents', {\n enumerable: true,\n get: () => textDocument.getText(),\n });\n return file as FileContents;\n }\n\n #applyChange(\n change: TextDocumentChange,\n selections?: EditorSelection[],\n newLineAnnotations?: DiffLineAnnotation<LAnnotation>[],\n options?: { skipSearchRefresh?: boolean }\n ) {\n const fileRef = this.#getFileRef();\n const onChange = this.#options.onChange;\n if (fileRef !== undefined && onChange !== undefined) {\n onChange(fileRef, newLineAnnotations ?? this.#lineAnnotations);\n }\n\n // Invalidate layout caches touched by the edit.\n // - line inserts/deletes shift line numbers, so clear from startLine onward\n // - wrapped edits can change visual height, which shifts downstream line Y\n if (change.lineDelta !== 0) {\n for (const line of this.#lineYCache.keys()) {\n if (line >= change.startLine) {\n this.#lineYCache.delete(line);\n }\n }\n }\n if (this.#wrap) {\n for (const line of this.#wrapLineOffsetsCache.keys()) {\n if (line >= change.startLine) {\n this.#wrapLineOffsetsCache.delete(line);\n }\n }\n }\n this.#lastAccessedCharX = undefined;\n\n let renderRange = this.#renderRange;\n let shouldUpdateBuffer: boolean | undefined;\n if (\n renderRange !== undefined &&\n selections !== undefined &&\n selections.length > 0\n ) {\n const primarySelection = selections.at(-1)!;\n const renderRangeEndLine =\n renderRange.startingLine + renderRange.totalLines;\n // when typing new line at the end of the file,\n // extend the render range +1 to trigger the re-render of the new line\n if (primarySelection.end.line === renderRangeEndLine) {\n renderRange = {\n ...renderRange,\n totalLines: renderRange.totalLines + 1,\n };\n } else if (primarySelection.end.line > renderRangeEndLine) {\n shouldUpdateBuffer = true;\n }\n }\n this.#rerender(change, newLineAnnotations, renderRange, shouldUpdateBuffer);\n\n if (\n options?.skipSearchRefresh !== true &&\n this.#searchPanel !== undefined &&\n this.#matches !== undefined\n ) {\n this.#searchPanel.updateMatches({ syncSelection: false });\n }\n\n if (selections !== undefined) {\n // re-render selection range and caret, focus to the editor to update the window selection,\n // and scroll to the crate to mock the 'contenteditable' behavior\n this.#updateSelections(selections);\n if (this.#primaryCaretElement !== undefined) {\n this.#primaryCaretElement.scrollIntoView({\n block: 'nearest',\n inline: 'nearest',\n });\n } else if (selections.length > 0) {\n const pos = getCaretPosition(selections.at(-1)!);\n this.#scrollToLine(pos.line, pos.character);\n }\n this.focus({ preventScroll: true });\n }\n }\n\n #applyChangeToLineAnnotations(\n change: TextDocumentChange\n ): DiffLineAnnotation<LAnnotation>[] | undefined {\n if (this.#lineAnnotations !== undefined) {\n const nextLineAnnotations =\n applyDocumentChangeToLineAnnotations<LAnnotation>(\n change,\n this.#lineAnnotations\n );\n if (nextLineAnnotations !== undefined) {\n this.#textDocument?.setLastUndoLineAnnotations(\n this.#lineAnnotations,\n nextLineAnnotations\n );\n return nextLineAnnotations;\n }\n }\n return undefined;\n }\n\n #getLineElement(line: number): HTMLElement | undefined {\n const lastAccessed = this.#lastAccessedLineElement;\n if (lastAccessed !== undefined && lastAccessed[0] === line) {\n return lastAccessed[1];\n }\n\n const contentElement = this.#contentElement;\n if (contentElement === undefined) {\n return undefined;\n }\n\n let lineElement: HTMLElement | null = null;\n\n // check if the line is within the render range (fast)\n if (this.#renderRange !== undefined) {\n const { startingLine } = this.#renderRange;\n const { children } = contentElement;\n for (let i = line - startingLine; i <= children.length; i++) {\n const child = children[i] as HTMLElement | undefined;\n if (child === undefined) {\n break;\n }\n const lineNumber = getLineNumberAttr(child);\n const lineType = child.dataset.lineType;\n if (\n lineNumber !== undefined &&\n lineNumber === line + 1 &&\n lineType !== undefined &&\n isLineEditable(lineType)\n ) {\n lineElement = child;\n break;\n }\n }\n }\n\n // fallback to query selector\n lineElement ??= contentElement.querySelector<HTMLElement>(\n `[data-line=\"${line + 1}\"]`\n );\n\n if (lineElement !== null) {\n if (lastAccessed !== undefined) {\n lastAccessed[0] = line;\n lastAccessed[1] = lineElement;\n } else {\n this.#lastAccessedLineElement = [line, lineElement];\n }\n return lineElement;\n }\n return undefined;\n }\n\n #getGutterWidth(): number {\n if (this.#gutterElement === undefined) {\n return 0;\n }\n\n if (this.#gutterWidthCache === undefined) {\n const diffsColumnNumberWidth =\n this.#contentElement?.parentElement?.style.getPropertyValue(\n '--diffs-column-number-width'\n );\n if (\n diffsColumnNumberWidth !== undefined &&\n diffsColumnNumberWidth.length > 2 &&\n diffsColumnNumberWidth.endsWith('px')\n ) {\n this.#gutterWidthCache = parseInt(\n diffsColumnNumberWidth.slice(0, -2),\n 10\n );\n } else {\n this.#gutterWidthCache = this.#gutterElement.offsetWidth;\n }\n }\n\n return this.#gutterWidthCache;\n }\n\n #getContentWidth(): number {\n if (this.#contentElement === undefined) {\n return 0;\n }\n\n if (this.#contentWidthCache === undefined) {\n const diffsColumnContentWidth =\n this.#contentElement.parentElement?.style.getPropertyValue(\n '--diffs-column-content-width'\n );\n if (\n diffsColumnContentWidth !== undefined &&\n diffsColumnContentWidth.length > 2 &&\n diffsColumnContentWidth.endsWith('px')\n ) {\n this.#contentWidthCache = parseFloat(\n diffsColumnContentWidth.slice(0, -2)\n );\n } else {\n this.#contentWidthCache = this.#contentElement.offsetWidth;\n }\n }\n return this.#contentWidthCache;\n }\n\n // get line top(y-coordinate) position\n #getLineY(line: number) {\n const cachedY = this.#lineYCache.get(line);\n if (cachedY !== undefined) {\n return cachedY;\n }\n\n const lineElement = this.#getLineElement(line);\n if (lineElement === undefined) {\n return -1;\n }\n\n // cold(slow) path: measure line top position from DOM (will cause reflow)\n const y = lineElement.offsetTop + this.#metrics.paddingTop;\n this.#lineYCache.set(line, y);\n return y;\n }\n\n // Return the visual position for a character. Wrapped lines include the\n // visual line index so carets can be placed on the correct row.\n #getCharX(line: number, char: number): [x: number, wrapLine: number] {\n if (\n this.#lastAccessedCharX !== undefined &&\n this.#lastAccessedCharX[0] === line &&\n this.#lastAccessedCharX[1] === char\n ) {\n return [this.#lastAccessedCharX[2], this.#lastAccessedCharX[3]];\n }\n\n const lineText = this.#textDocument?.getLineText(line);\n const offsetLeft = this.#getGutterWidth() + this.#metrics.ch; // gutter width + inline padding (1ch)\n if (lineText === undefined || lineText.length === 0 || char <= 0) {\n return [offsetLeft, 0];\n }\n\n const boundedCharacter = snapTextOffsetToUnicodeBoundary(\n lineText,\n Math.min(char, lineText.length)\n );\n const textBeforeCharacter = lineText.slice(0, boundedCharacter);\n const asciiColumns = getExpandedAsciiTextColumns(\n textBeforeCharacter,\n this.#metrics.tabSize\n );\n\n let left = 0;\n let wrapLine = 0;\n if (asciiColumns !== -1) {\n left = offsetLeft + asciiColumns * this.#metrics.ch;\n } else {\n left = offsetLeft + this.#metrics.measureTextWidth(textBeforeCharacter);\n }\n\n if (this.#wrap) {\n const contentWidth = this.#getContentWidth();\n const textWidth =\n 2 * this.#metrics.ch + this.#metrics.measureTextWidth(lineText);\n if (textWidth > contentWidth) {\n const wrapOffsets = this.#wrapLineText(line);\n for (let w = 0; w + 1 < wrapOffsets.length; w++) {\n const segmentStart = wrapOffsets[w];\n const segmentEnd = wrapOffsets[w + 1];\n if (boundedCharacter <= segmentEnd) {\n wrapLine = w;\n const prefixInSegment = lineText.slice(\n segmentStart,\n boundedCharacter\n );\n const segmentAsciiColumns = getExpandedAsciiTextColumns(\n prefixInSegment,\n this.#metrics.tabSize\n );\n if (segmentAsciiColumns !== -1) {\n left = offsetLeft + segmentAsciiColumns * this.#metrics.ch;\n } else {\n left =\n offsetLeft + this.#metrics.measureTextWidth(prefixInSegment);\n }\n break;\n }\n }\n }\n }\n\n if (this.#lastAccessedCharX !== undefined) {\n this.#lastAccessedCharX[0] = line;\n this.#lastAccessedCharX[1] = char;\n this.#lastAccessedCharX[2] = left;\n this.#lastAccessedCharX[3] = wrapLine;\n } else {\n this.#lastAccessedCharX = [line, char, left, wrapLine];\n }\n\n return [left, wrapLine];\n }\n\n // Compute how a logical line of text is broken into visual lines when line\n // wrapping is enabled.\n #wrapLineText(line: number): Uint32Array {\n const cachedOffsets = this.#wrapLineOffsetsCache.get(line);\n if (cachedOffsets !== undefined) {\n return cachedOffsets;\n }\n\n const lineText = this.#textDocument?.getLineText(line);\n if (lineText === undefined || lineText.length === 0) {\n const offsets = new Uint32Array([0]);\n this.#wrapLineOffsetsCache.set(line, offsets);\n return offsets;\n }\n\n const div = h(\n 'div',\n {\n style: {\n position: 'absolute',\n top: '0',\n left: '0',\n width: '100%',\n boxSizing: 'border-box',\n visibility: 'hidden',\n pointerEvents: 'none',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n font: 'inherit',\n paddingInline: '1ch',\n tabSize: this.#metrics.tabSize.toString(),\n },\n textContent: lineText,\n },\n this.#contentElement\n );\n const textNode = div.firstChild as Text;\n const range = document.createRange();\n const starts: number[] = [];\n\n try {\n const unicodeOffsets = getUnicodeMeasurementOffsets(lineText);\n const wrapLineStartLeft =\n div.getBoundingClientRect().left + this.#metrics.ch;\n\n let previousOffset = 0;\n let lastTop = Number.NEGATIVE_INFINITY;\n\n for (let i = 0, offsetIndex = 0; i < lineText.length; ) {\n const nextOffset =\n unicodeOffsets === undefined\n ? i + 1\n : unicodeOffsets[offsetIndex + 1];\n range.setStart(textNode, i);\n range.setEnd(textNode, nextOffset);\n\n // A new visual line starts whenever the character's top edge moves\n // below the previous character's top edge.\n const { left, top } = range.getBoundingClientRect();\n if (top > lastTop) {\n // Safari can report the first range on a wrapped visual line as\n // starting one character past the visual line start. Use the previous\n // offset so segment-local caret math begins at the actual wrap point.\n const startsPastLineStart =\n isSafari() &&\n starts.length > 0 &&\n left - wrapLineStartLeft > this.#metrics.ch / 2;\n starts.push(startsPastLineStart ? previousOffset : i);\n lastTop = top;\n }\n previousOffset = i;\n i = nextOffset;\n offsetIndex++;\n }\n\n const offsets = new Uint32Array(starts.length + 1);\n for (let i = 0; i < starts.length; i++) {\n offsets[i] = starts[i]!;\n }\n offsets[starts.length] = lineText.length;\n this.#wrapLineOffsetsCache.set(line, offsets);\n return offsets;\n } finally {\n div.remove();\n }\n }\n\n // check if the web selection belongs to editor\n #rangeBelongsToEditor({ startContainer, endContainer }: StaticRange) {\n const contentEl = this.#contentElement;\n if (contentEl === undefined) {\n return false;\n }\n return (\n contentEl.contains(startContainer) && contentEl.contains(endContainer)\n );\n }\n\n // Check whether a line is visible in the currently rendered line window.\n #isLineVisible(line: number): boolean {\n const lineCount = this.#textDocument?.lineCount ?? 0;\n if (line < 0 || line >= lineCount) {\n return false;\n }\n if (this.#renderRange === undefined) {\n return true;\n }\n const { startingLine, totalLines } = this.#renderRange;\n if (line < startingLine) {\n return false;\n }\n if (totalLines === Infinity) {\n return true;\n }\n return line < startingLine + totalLines;\n }\n}\n"],"mappings":"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"}