UNPKG

@pierre/diffs

Version:

337 lines (336 loc) 17.2 kB
import { AppliedThemeStyleCache, BaseCodeOptions, BaseDiffOptions, CustomPreProperties, DiffLineAnnotation, ExpansionDirections, FileContents, FileDiffMetadata, HighlightedToken, HunkData, HunkSeparators, LineAnnotation, MaybeDiffFileInput, PostRenderPhase, PrePropertiesConfig, RenderHeaderFilenameSuffixCallback, RenderHeaderMetadataCallback, RenderHeaderPrefixCallback, RenderRange, SelectedLineRange, SelectionSide, ThemeTypes } from "../types.js"; import { CapturedDiffSessionState, EditCompletionDecision, EditorActiveLineOptions, EditorChangeEvent, FileDiffEditCompleteEvent } from "../editor/types.js"; import { TextDocument } from "../editor/textDocument.js"; import { GetHoveredLineResult, GetLineIndexUtility, InteractionManager, InteractionManagerBaseOptions, SelectionWriteOptions } from "../managers/InteractionManager.js"; import { ResizeManager } from "../managers/ResizeManager.js"; import { WorkerPoolManager } from "../worker/WorkerPoolManager.js"; import { ScrollSyncManager } from "../managers/ScrollSyncManager.js"; import { DiffHunksRenderer, DiffHunksRendererOptions, HunksRenderResult } from "../renderers/DiffHunksRenderer.js"; import { Editor } from "../editor/editor.js"; //#region src/components/FileDiff.d.ts type LoadedPartialDiffContents = Awaited<ReturnType<NonNullable<BaseDiffOptions['loadDiffFiles']>>>; type DeferredSelectedLinesWrite = [range: SelectedLineRange | null, options: SelectionWriteOptions | undefined]; type DeferredEditorActiveLineWrite = [lineNumber: number | null, options: EditorActiveLineOptions | undefined]; interface FileDiffRenderBaseProps<LAnnotation> { fileDiff?: FileDiffMetadata; deferManagers?: boolean; forceRender?: boolean; preventEmit?: boolean; fileContainer?: HTMLElement; containerWrapper?: HTMLElement; lineAnnotations?: DiffLineAnnotation<LAnnotation>[]; renderRange?: RenderRange; } type FileDiffRenderProps<LAnnotation> = FileDiffRenderBaseProps<LAnnotation> & MaybeDiffFileInput; type FileDiffHydrationProps<LAnnotation> = Omit<FileDiffRenderBaseProps<LAnnotation>, 'fileContainer'> & MaybeDiffFileInput & { fileContainer: HTMLElement; prerenderedHTML?: string; }; type FileDiffType = 'file-diff' | 'unresolved-file'; type FileDiffEditChangeHandler<LAnnotation, Caret> = (event: EditorChangeEvent<'file-diff', LAnnotation, Caret>) => void; /** * Decides a completed edit synchronously: return `'accept'` to install the * event's `fileDiff` and annotations, or `'reject'` to restore the original * values. The event is frozen, so re-key the accepted diff in place * (`event.fileDiff.cacheKey = '…'`) before accepting. The event's editor is * detached and returns its final state from `getViewState()`. A missing handler * rejects. */ type FileDiffEditCompleteHandler<LAnnotation, Caret> = (event: FileDiffEditCompleteEvent<LAnnotation, Caret>) => EditCompletionDecision; interface FileDiffOptions<LAnnotation, Caret> extends Omit<BaseDiffOptions, 'hunkSeparators'>, InteractionManagerBaseOptions<'diff'> { hunkSeparators?: Exclude<HunkSeparators, 'custom'> /** * @deprecated Custom hunk separator functions are deprecated and will be * removed in a future version. */ | ((hunk: HunkData, instance: FileDiff<LAnnotation, Caret>) => HTMLElement | DocumentFragment | null | undefined); disableFileHeader?: boolean; renderHeaderPrefix?: RenderHeaderPrefixCallback; renderHeaderFilenameSuffix?: RenderHeaderFilenameSuffixCallback; renderHeaderMetadata?: RenderHeaderMetadataCallback; renderCustomHeader?: RenderHeaderMetadataCallback; /** * When true, errors during rendering are rethrown instead of being caught * and displayed in the DOM. Useful for testing or when you want to handle * errors yourself. */ disableErrorHandling?: boolean; renderAnnotation?(annotation: DiffLineAnnotation<LAnnotation>): HTMLElement | undefined; renderGutterUtility?(getHoveredRow: () => GetHoveredLineResult<'diff'> | undefined): HTMLElement | null | undefined; onPostRender?(node: HTMLElement, instance: FileDiff<LAnnotation, Caret>, phase: PostRenderPhase): unknown; /** * Fired for every document change of an active edit session on this * component, with the same `EditorChangeEvent` the editor reports through * its own `onChange`. Do not feed the event's file back into the component * while the session is active. */ onEditChange?: FileDiffEditChangeHandler<LAnnotation, Caret>; /** * Fired when `edit` toggles false or a component unmounts, including when the * final contents are unchanged. If no callback is provided, the component * reverts to the last `fileDiff` or `oldFile`/`newFiles` and annotations * passed into it. The callback receives the detached editor with its final * pre-detach state. */ onEditComplete?: FileDiffEditCompleteHandler<LAnnotation, Caret>; } interface AnnotationElementCache<LAnnotation> { element: HTMLElement; annotation: DiffLineAnnotation<LAnnotation>; } interface CustomHunkElementCache { element: HTMLElement; hunkData: HunkData; } interface PendingFileLoad { fileDiff: FileDiffMetadata; promise: Promise<void>; } type HydrationSetup<LAnnotation> = { fileDiff: FileDiffMetadata | undefined; lineAnnotations: DiffLineAnnotation<LAnnotation>[] | undefined; } & MaybeDiffFileInput; interface HeaderCache { lastRenderedHTML: string | undefined; html: string | undefined; fileDiff: FileDiffMetadata | undefined; } declare class FileDiff<LAnnotation = undefined, Caret = undefined> { options: FileDiffOptions<LAnnotation, Caret>; protected workerManager?: WorkerPoolManager | undefined; protected isContainerManaged: boolean; static LoadedCustomComponent: boolean; readonly __id: string; readonly type: FileDiffType; protected fileContainer: HTMLElement | undefined; protected spriteSVG: SVGElement | undefined; protected pre: HTMLPreElement | undefined; protected codeUnified: HTMLElement | undefined; protected codeDeletions: HTMLElement | undefined; protected codeAdditions: HTMLElement | undefined; protected bufferBefore: HTMLElement | undefined; protected bufferAfter: HTMLElement | undefined; protected themeCSSStyle: HTMLStyleElement | undefined; protected appliedThemeCSS: AppliedThemeStyleCache | undefined; protected hasAdoptedThemeCSS: boolean; protected unsafeCSSStyle: HTMLStyleElement | undefined; protected appliedUnsafeCSS: string | undefined; protected gutterUtilityContent: HTMLElement | undefined; protected headerElement: HTMLElement | undefined; protected headerPrefix: HTMLElement | undefined; protected headerFilenameSuffix: HTMLElement | undefined; protected headerMetadata: HTMLElement | undefined; protected headerCustom: HTMLElement | undefined; protected separatorCache: Map<string, CustomHunkElementCache>; protected errorWrapper: HTMLElement | undefined; protected placeHolder: HTMLElement | undefined; protected hunksRenderer: DiffHunksRenderer<LAnnotation>; protected resizeManager: ResizeManager; protected scrollSyncManager: ScrollSyncManager; protected interactionManager: InteractionManager<'diff'>; protected annotationCache: Map<string, AnnotationElementCache<LAnnotation>>; protected lineAnnotations: DiffLineAnnotation<LAnnotation>[]; protected managersDirty: boolean; protected deletionFile?: FileContents | null; protected additionFile?: FileContents | null; fileDiff: FileDiffMetadata | undefined; private editSession; protected renderedDiff: FileDiffMetadata | undefined; protected renderRange: RenderRange | undefined; protected pendingFiles: PendingFileLoad | undefined; protected appliedPreAttributes: PrePropertiesConfig | undefined; protected headerCache: HeaderCache; protected lastRowCount: number | undefined; private mounted; protected enabled: boolean; protected editor: Editor<'file-diff', LAnnotation, Caret> | undefined; protected refreshViewTimeout: ReturnType<typeof setTimeout> | undefined; protected lineStateRefreshPending: boolean; protected deferredSelectedLines: DeferredSelectedLinesWrite | undefined; protected deferredEditorActiveLine: DeferredEditorActiveLineWrite | undefined; constructor(options?: FileDiffOptions<LAnnotation, Caret>, workerManager?: WorkerPoolManager | undefined, isContainerManaged?: boolean); protected handleHighlightRender: () => void; private getTheme; protected getHunksRendererOptions(options: FileDiffOptions<LAnnotation, Caret>): DiffHunksRendererOptions; protected createHunksRenderer(options: FileDiffOptions<LAnnotation, Caret>): DiffHunksRenderer<LAnnotation>; getLineIndex: GetLineIndexUtility; protected getDiffForLineIndex(): FileDiffMetadata | undefined; protected getLineIndexForDiff(fileDiff: FileDiffMetadata | undefined, lineNumber: number, side: SelectionSide): [number, number] | undefined; setOptions(options: FileDiffOptions<LAnnotation, Caret> | undefined): void; protected syncInteractionOptions(): void; private mergeOptions; setThemeType(themeType: ThemeTypes): void; private applyCachedThemeState; private hasThemeChanged; getHoveredLine: () => GetHoveredLineResult<'diff'> | undefined; getAnnotationSlotName: (annotation: LineAnnotation<LAnnotation> | DiffLineAnnotation<LAnnotation>) => string; protected getLatestAnnotations(): DiffLineAnnotation<LAnnotation>[]; protected isNewAnnotations(lineAnnotations: DiffLineAnnotation<LAnnotation>[]): boolean; setLineAnnotations(lineAnnotations: DiffLineAnnotation<LAnnotation>[]): void; protected syncEditSessionAnnotationsFromEditor(lineAnnotations: DiffLineAnnotation<LAnnotation>[]): boolean; private canPartiallyRender; setSelectedLines(range: SelectedLineRange | null, options?: SelectionWriteOptions): void; setEditorActiveLine(lineNumber: number | null, options?: EditorActiveLineOptions): void; protected flushDeferredLineState(): void; flushManagers(): void; protected shouldApplyColumnVariables(overflow: 'scroll' | 'wrap'): boolean; getCodeScrollLeft(): number; setCodeScrollLeft(position: number): void; __getEffectiveCodeOptions(): BaseCodeOptions; cleanUp(recycle?: boolean): void; virtualizedSetup(): void; hydrate({ fileContainer, prerenderedHTML, preventEmit, lineAnnotations, fileDiff, ...fileInputProps }: FileDiffHydrationProps<LAnnotation>): void; protected hydrateElements(fileContainer: HTMLElement, prerenderedHTML: string | undefined): void; protected hydrationSetup({ fileDiff, oldFile, newFile, lineAnnotations }: HydrationSetup<LAnnotation>): void; rerender(): void; onThemeChange(): void; handleExpandHunk: (hunkIndex: number, direction: ExpansionDirections, expansionLineCountOverride?: number) => void; expandHunk: (hunkIndex: number, direction: ExpansionDirections, expansionLineCountOverride?: number) => void; protected loadFilesIfNecessary(): void; private loadFilesForDiff; protected handleFilesLoaded(expectedDiff: FileDiffMetadata, files: LoadedPartialDiffContents): Promise<void>; protected startHydratedEditSession(expectedDiff: FileDiffMetadata): boolean; protected updateExternalDiff(incomingExternalDiff: FileDiffMetadata, lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): boolean; private installEditSession; protected setHydratedState(files: LoadedPartialDiffContents): void; render({ fileDiff, deferManagers, forceRender, preventEmit, lineAnnotations, fileContainer, containerWrapper, renderRange, ...fileInputProps }: FileDiffRenderProps<LAnnotation>): boolean; protected finalizeRender(): void; protected emitPostRender(unmount?: boolean): void; protected getLatestDiff(fileDiff?: FileDiffMetadata | undefined): FileDiffMetadata | undefined; protected getRenderedDiff(): FileDiffMetadata | undefined; private syncRenderViewToEditor; private computeEditorRenderRange; /** @internal The editor applied or edited past the pending external replacement. */ __acknowledgeDocumentUpdate(): void; /** @internal Settle annotations locally. */ __acceptEditorChange(event: EditorChangeEvent<'file-diff', LAnnotation, Caret>): void; emitEditChange(event: EditorChangeEvent<'file-diff', LAnnotation, Caret>): void; /** * @internal Capture the current diff session, or return `undefined` when no * complete compatible session exists. * * When `clone` is true, the returned lines and hunks are copied. */ __captureDocumentSessionState(clone?: boolean): CapturedDiffSessionState | undefined; /** @internal Associate this component with its editor for a render lifecycle. */ __attachEditor(editor: Editor<'file-diff', LAnnotation, Caret>): () => void; /** @internal Resume rendering for the editor already associated with this component. */ __resumeEditor(editor: Editor<'file-diff', LAnnotation, Caret>): void; private resumeEditorRendering; private finishEditSession; /** * @internal * * Ends the edit session and settles which diff this component renders. * Requires the editor to be detached first. Does nothing when no session * exists, so callers can invoke it again safely after it has settled. * * `onEditComplete` receives the completed diff, current external diff, * complete file pair, and both annotation collections even when the final * text is unchanged. In `install` mode, accepting installs the completed diff * and its annotations; rejecting or having no handler restores the external * values. `discard` mode always restores the external values. An accepted * diff cannot reuse the replaced diff's `cacheKey`. */ __completeEditSession(editor: Editor<'file-diff', LAnnotation, Caret>, mode: 'install' | 'discard'): void; private settleEditSession; /** * Run the session-end recompute: restore recompute-shaped hunks (a * context-only region collapses away, boundaries re-derive), preserve * expansion state best-effort via old-side anchors, and repaint through * the session render path — which also invalidates virtualized layout, * since nothing else does at exit now that editing does not flip * expandUnchanged. Marker-guarded and idempotent; CodeView also calls this * when ending a session whose detach closure was consumed by a recycle. * Safe on a cleaned-up instance: the recompute is pure metadata work and * the deferred rerender is enabled-guarded. Returns true when a recompute * ran. */ finalizeEditSessionHunks(): boolean; applyDocumentChange(textDocument: TextDocument<'file-diff', LAnnotation>, newLineAnnotations?: DiffLineAnnotation<LAnnotation>[]): void; updateRenderCache(dirtyLines: Map<number, Array<HighlightedToken>>, themeType: 'dark' | 'light', options?: { shouldRefreshDiffsView?: boolean; lineCountChangeInFlight?: boolean; }): void; private detachAdditionLines; isLineRenderable(lineNumber: number): boolean; getNearestRenderableLine(lineNumber: number, direction: 'up' | 'down'): number | undefined; revealLine(lineNumber: number): boolean; protected shouldSelfHealEditSession(): boolean; protected escalateEditSessionRender(): void; private handleEditSessionRender; private removeRenderedCode; private clearAuxiliaryNodes; renderPlaceholder(height: number): boolean; primeHighlightCache(fileDiff?: FileDiffMetadata | undefined): Promise<void>; private cleanChildNodes; private renderSeparators; protected renderAnnotations(): void; protected renderGutterUtility(): void; protected getOrCreateFileContainer(fileContainer?: HTMLElement, parentNode?: HTMLElement): HTMLElement; private adoptReusableShellElements; private ensureSpriteSVG; private getOrCreatePreNode; protected syncCodeNodesFromPre(pre: HTMLPreElement): void; private applyHeaderToDOM; protected clearReusableHeader(): void; private clearHeaderSlots; private upsertHeaderSlotElement; private replaceHeaderSlotContent; private createHeaderSlotElement; protected injectUnsafeCSS(): void; private applyThemeState; private hydrateMeasuredScrollbar; protected shouldGuardRebuildScroll(): boolean; private applyHunksToDOM; private applyCodeColumnsInPlace; private replaceCodeColumns; private applyPartialRender; private insertPartialHTML; private refreshSplitDiffView; private refreshUnifiedDiffView; private renderPartialColumn; private mergeBuffersIfNecessary; private applyRowSpan; private trimColumnRows; private trimColumns; private getBufferSize; private updateBufferSize; private getColumnPair; private getCodeColumns; protected updateBuffers(renderRange: RenderRange): void; private applyBuffers; protected shouldDisableVirtualizationBuffers(): boolean; protected applyPreNodeAttributes(pre: HTMLPreElement, { additionsContentAST, deletionsContentAST, totalLines }: HunksRenderResult, customProperties?: CustomPreProperties): void; private applyErrorToDOM; private cleanupErrorWrapper; } //#endregion export { FileDiff, FileDiffEditChangeHandler, type FileDiffEditCompleteEvent, FileDiffEditCompleteHandler, FileDiffHydrationProps, FileDiffOptions, FileDiffRenderBaseProps, FileDiffRenderProps, FileDiffType }; //# sourceMappingURL=FileDiff.d.ts.map