UNPKG

@21epub/epub-thirdparty

Version:
1,018 lines 101 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var _a; import './media/diffEditor.css'; import * as nls from '../../../nls.js'; import * as dom from '../../../base/browser/dom.js'; import { createFastDomNode } from '../../../base/browser/fastDomNode.js'; import { Sash } from '../../../base/browser/ui/sash/sash.js'; import { RunOnceScheduler } from '../../../base/common/async.js'; import { Emitter } from '../../../base/common/event.js'; import { Disposable } from '../../../base/common/lifecycle.js'; import { Configuration } from '../config/configuration.js'; import { StableEditorScrollState } from '../core/editorState.js'; import { ICodeEditorService } from '../services/codeEditorService.js'; import { CodeEditorWidget } from './codeEditorWidget.js'; import { DiffReview } from './diffReview.js'; import { EditorOptions, EditorFontLigatures, stringSet as validateStringSetOption, boolean as validateBooleanOption, clampedInt } from '../../common/config/editorOptions.js'; import { Range } from '../../common/core/range.js'; import { createStringBuilder } from '../../common/core/stringBuilder.js'; import * as editorCommon from '../../common/editorCommon.js'; import { ModelDecorationOptions } from '../../common/model/textModel.js'; import { IEditorWorkerService } from '../../common/services/editorWorkerService.js'; import { OverviewRulerZone } from '../../common/view/overviewZoneManager.js'; import { LineDecoration } from '../../common/viewLayout/lineDecorations.js'; import { RenderLineInput, renderViewLine } from '../../common/viewLayout/viewLineRenderer.js'; import { InlineDecoration, ViewLineRenderingData } from '../../common/viewModel/viewModel.js'; import { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js'; import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js'; import { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js'; import { INotificationService } from '../../../platform/notification/common/notification.js'; import { defaultInsertColor, defaultRemoveColor, diffBorder, diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, scrollbarShadow, scrollbarSliderBackground, scrollbarSliderHoverBackground, scrollbarSliderActiveBackground, diffDiagonalFill } from '../../../platform/theme/common/colorRegistry.js'; import { IThemeService, getThemeTypeSelector, registerThemingParticipant, ThemeIcon } from '../../../platform/theme/common/themeService.js'; import { IContextMenuService } from '../../../platform/contextview/browser/contextView.js'; import { InlineDiffMargin } from './inlineDiffMargin.js'; import { IClipboardService } from '../../../platform/clipboard/common/clipboardService.js'; import { EditorExtensionsRegistry } from '../editorExtensions.js'; import { onUnexpectedError } from '../../../base/common/errors.js'; import { IEditorProgressService } from '../../../platform/progress/common/progress.js'; import { ElementSizeObserver } from '../config/elementSizeObserver.js'; import { Codicon } from '../../../base/common/codicons.js'; import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from '../../../base/browser/ui/mouseCursor/mouseCursor.js'; import { registerIcon } from '../../../platform/theme/common/iconRegistry.js'; class VisualEditorState { constructor(_contextMenuService, _clipboardService) { this._contextMenuService = _contextMenuService; this._clipboardService = _clipboardService; this._zones = []; this._inlineDiffMargins = []; this._zonesMap = {}; this._decorations = []; } getForeignViewZones(allViewZones) { return allViewZones.filter((z) => !this._zonesMap[String(z.id)]); } clean(editor) { // (1) View zones if (this._zones.length > 0) { editor.changeViewZones((viewChangeAccessor) => { for (const zoneId of this._zones) { viewChangeAccessor.removeZone(zoneId); } }); } this._zones = []; this._zonesMap = {}; // (2) Model decorations this._decorations = editor.deltaDecorations(this._decorations, []); } apply(editor, overviewRuler, newDecorations, restoreScrollState) { const scrollState = restoreScrollState ? StableEditorScrollState.capture(editor) : null; // view zones editor.changeViewZones((viewChangeAccessor) => { var _a; for (const zoneId of this._zones) { viewChangeAccessor.removeZone(zoneId); } for (const inlineDiffMargin of this._inlineDiffMargins) { inlineDiffMargin.dispose(); } this._zones = []; this._zonesMap = {}; this._inlineDiffMargins = []; for (let i = 0, length = newDecorations.zones.length; i < length; i++) { const viewZone = newDecorations.zones[i]; viewZone.suppressMouseDown = true; const zoneId = viewChangeAccessor.addZone(viewZone); this._zones.push(zoneId); this._zonesMap[String(zoneId)] = true; if (newDecorations.zones[i].diff && viewZone.marginDomNode) { viewZone.suppressMouseDown = false; if (((_a = newDecorations.zones[i].diff) === null || _a === void 0 ? void 0 : _a.originalModel.getValueLength()) !== 0) { // do not contribute diff margin actions for newly created files this._inlineDiffMargins.push(new InlineDiffMargin(zoneId, viewZone.marginDomNode, editor, newDecorations.zones[i].diff, this._contextMenuService, this._clipboardService)); } } } }); if (scrollState) { scrollState.restore(editor); } // decorations this._decorations = editor.deltaDecorations(this._decorations, newDecorations.decorations); // overview ruler if (overviewRuler) { overviewRuler.setZones(newDecorations.overviewZones); } } } let DIFF_EDITOR_ID = 0; const diffInsertIcon = registerIcon('diff-insert', Codicon.add, nls.localize('diffInsertIcon', 'Line decoration for inserts in the diff editor.')); const diffRemoveIcon = registerIcon('diff-remove', Codicon.remove, nls.localize('diffRemoveIcon', 'Line decoration for removals in the diff editor.')); const ttPolicy = (_a = window.trustedTypes) === null || _a === void 0 ? void 0 : _a.createPolicy('diffEditorWidget', { createHTML: value => value }); let DiffEditorWidget = class DiffEditorWidget extends Disposable { constructor(domElement, options, codeEditorWidgetOptions, clipboardService, editorWorkerService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService, contextMenuService, _editorProgressService) { super(); this._editorProgressService = _editorProgressService; this._onDidDispose = this._register(new Emitter()); this.onDidDispose = this._onDidDispose.event; this._onDidUpdateDiff = this._register(new Emitter()); this.onDidUpdateDiff = this._onDidUpdateDiff.event; this._onDidContentSizeChange = this._register(new Emitter()); this._lastOriginalWarning = null; this._lastModifiedWarning = null; this._editorWorkerService = editorWorkerService; this._codeEditorService = codeEditorService; this._contextKeyService = this._register(contextKeyService.createScoped(domElement)); this._instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this._contextKeyService])); this._contextKeyService.createKey('isInDiffEditor', true); this._themeService = themeService; this._notificationService = notificationService; this._id = (++DIFF_EDITOR_ID); this._state = 0 /* Idle */; this._updatingDiffProgress = null; this._domElement = domElement; options = options || {}; this._options = validateDiffEditorOptions(options, { enableSplitViewResizing: true, renderSideBySide: true, maxComputationTime: 5000, maxFileSize: 50, ignoreTrimWhitespace: true, renderIndicators: true, originalEditable: false, diffCodeLens: false, renderOverviewRuler: true, diffWordWrap: 'inherit' }); if (typeof options.isInEmbeddedEditor !== 'undefined') { this._contextKeyService.createKey('isInEmbeddedDiffEditor', options.isInEmbeddedEditor); } else { this._contextKeyService.createKey('isInEmbeddedDiffEditor', false); } this._updateDecorationsRunner = this._register(new RunOnceScheduler(() => this._updateDecorations(), 0)); this._containerDomElement = document.createElement('div'); this._containerDomElement.className = DiffEditorWidget._getClassName(this._themeService.getColorTheme(), this._options.renderSideBySide); this._containerDomElement.style.position = 'relative'; this._containerDomElement.style.height = '100%'; this._domElement.appendChild(this._containerDomElement); this._overviewViewportDomElement = createFastDomNode(document.createElement('div')); this._overviewViewportDomElement.setClassName('diffViewport'); this._overviewViewportDomElement.setPosition('absolute'); this._overviewDomElement = document.createElement('div'); this._overviewDomElement.className = 'diffOverview'; this._overviewDomElement.style.position = 'absolute'; this._overviewDomElement.appendChild(this._overviewViewportDomElement.domNode); this._register(dom.addStandardDisposableListener(this._overviewDomElement, 'mousedown', (e) => { this._modifiedEditor.delegateVerticalScrollbarMouseDown(e); })); if (this._options.renderOverviewRuler) { this._containerDomElement.appendChild(this._overviewDomElement); } // Create left side this._originalDomNode = document.createElement('div'); this._originalDomNode.className = 'editor original'; this._originalDomNode.style.position = 'absolute'; this._originalDomNode.style.height = '100%'; this._containerDomElement.appendChild(this._originalDomNode); // Create right side this._modifiedDomNode = document.createElement('div'); this._modifiedDomNode.className = 'editor modified'; this._modifiedDomNode.style.position = 'absolute'; this._modifiedDomNode.style.height = '100%'; this._containerDomElement.appendChild(this._modifiedDomNode); this._beginUpdateDecorationsTimeout = -1; this._currentlyChangingViewZones = false; this._diffComputationToken = 0; this._originalEditorState = new VisualEditorState(contextMenuService, clipboardService); this._modifiedEditorState = new VisualEditorState(contextMenuService, clipboardService); this._isVisible = true; this._isHandlingScrollEvent = false; this._elementSizeObserver = this._register(new ElementSizeObserver(this._containerDomElement, options.dimension, () => this._onDidContainerSizeChanged())); if (options.automaticLayout) { this._elementSizeObserver.startObserving(); } this._diffComputationResult = null; this._originalEditor = this._createLeftHandSideEditor(options, codeEditorWidgetOptions.originalEditor || {}); this._modifiedEditor = this._createRightHandSideEditor(options, codeEditorWidgetOptions.modifiedEditor || {}); this._originalOverviewRuler = null; this._modifiedOverviewRuler = null; this._reviewPane = instantiationService.createInstance(DiffReview, this); this._containerDomElement.appendChild(this._reviewPane.domNode.domNode); this._containerDomElement.appendChild(this._reviewPane.shadow.domNode); this._containerDomElement.appendChild(this._reviewPane.actionBarContainer.domNode); if (this._options.renderSideBySide) { this._setStrategy(new DiffEditorWidgetSideBySide(this._createDataSource(), this._options.enableSplitViewResizing)); } else { this._setStrategy(new DiffEditorWidgetInline(this._createDataSource(), this._options.enableSplitViewResizing)); } this._register(themeService.onDidColorThemeChange(t => { if (this._strategy && this._strategy.applyColors(t)) { this._updateDecorationsRunner.schedule(); } this._containerDomElement.className = DiffEditorWidget._getClassName(this._themeService.getColorTheme(), this._options.renderSideBySide); })); const contributions = EditorExtensionsRegistry.getDiffEditorContributions(); for (const desc of contributions) { try { this._register(instantiationService.createInstance(desc.ctor, this)); } catch (err) { onUnexpectedError(err); } } this._codeEditorService.addDiffEditor(this); } _setState(newState) { if (this._state === newState) { return; } this._state = newState; if (this._updatingDiffProgress) { this._updatingDiffProgress.done(); this._updatingDiffProgress = null; } if (this._state === 1 /* ComputingDiff */) { this._updatingDiffProgress = this._editorProgressService.show(true, 1000); } } diffReviewNext() { this._reviewPane.next(); } diffReviewPrev() { this._reviewPane.prev(); } static _getClassName(theme, renderSideBySide) { let result = 'monaco-diff-editor monaco-editor-background '; if (renderSideBySide) { result += 'side-by-side '; } result += getThemeTypeSelector(theme.type); return result; } _recreateOverviewRulers() { if (!this._options.renderOverviewRuler) { return; } if (this._originalOverviewRuler) { this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode()); this._originalOverviewRuler.dispose(); } if (this._originalEditor.hasModel()) { this._originalOverviewRuler = this._originalEditor.createOverviewRuler('original diffOverviewRuler'); this._overviewDomElement.appendChild(this._originalOverviewRuler.getDomNode()); } if (this._modifiedOverviewRuler) { this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode()); this._modifiedOverviewRuler.dispose(); } if (this._modifiedEditor.hasModel()) { this._modifiedOverviewRuler = this._modifiedEditor.createOverviewRuler('modified diffOverviewRuler'); this._overviewDomElement.appendChild(this._modifiedOverviewRuler.getDomNode()); } this._layoutOverviewRulers(); } _createLeftHandSideEditor(options, codeEditorWidgetOptions) { const editor = this._createInnerEditor(this._instantiationService, this._originalDomNode, this._adjustOptionsForLeftHandSide(options), codeEditorWidgetOptions); this._register(editor.onDidScrollChange((e) => { if (this._isHandlingScrollEvent) { return; } if (!e.scrollTopChanged && !e.scrollLeftChanged && !e.scrollHeightChanged) { return; } this._isHandlingScrollEvent = true; this._modifiedEditor.setScrollPosition({ scrollLeft: e.scrollLeft, scrollTop: e.scrollTop }); this._isHandlingScrollEvent = false; this._layoutOverviewViewport(); })); this._register(editor.onDidChangeViewZones(() => { this._onViewZonesChanged(); })); this._register(editor.onDidChangeConfiguration((e) => { if (!editor.getModel()) { return; } if (e.hasChanged(43 /* fontInfo */)) { this._updateDecorationsRunner.schedule(); } if (e.hasChanged(130 /* wrappingInfo */)) { this._updateDecorationsRunner.cancel(); this._updateDecorations(); } })); this._register(editor.onDidChangeHiddenAreas(() => { this._updateDecorationsRunner.cancel(); this._updateDecorations(); })); this._register(editor.onDidChangeModelContent(() => { if (this._isVisible) { this._beginUpdateDecorationsSoon(); } })); const isInDiffLeftEditorKey = this._contextKeyService.createKey('isInDiffLeftEditor', editor.hasWidgetFocus()); this._register(editor.onDidFocusEditorWidget(() => isInDiffLeftEditorKey.set(true))); this._register(editor.onDidBlurEditorWidget(() => isInDiffLeftEditorKey.set(false))); this._register(editor.onDidContentSizeChange(e => { const width = this._originalEditor.getContentWidth() + this._modifiedEditor.getContentWidth() + DiffEditorWidget.ONE_OVERVIEW_WIDTH; const height = Math.max(this._modifiedEditor.getContentHeight(), this._originalEditor.getContentHeight()); this._onDidContentSizeChange.fire({ contentHeight: height, contentWidth: width, contentHeightChanged: e.contentHeightChanged, contentWidthChanged: e.contentWidthChanged }); })); return editor; } _createRightHandSideEditor(options, codeEditorWidgetOptions) { const editor = this._createInnerEditor(this._instantiationService, this._modifiedDomNode, this._adjustOptionsForRightHandSide(options), codeEditorWidgetOptions); this._register(editor.onDidScrollChange((e) => { if (this._isHandlingScrollEvent) { return; } if (!e.scrollTopChanged && !e.scrollLeftChanged && !e.scrollHeightChanged) { return; } this._isHandlingScrollEvent = true; this._originalEditor.setScrollPosition({ scrollLeft: e.scrollLeft, scrollTop: e.scrollTop }); this._isHandlingScrollEvent = false; this._layoutOverviewViewport(); })); this._register(editor.onDidChangeViewZones(() => { this._onViewZonesChanged(); })); this._register(editor.onDidChangeConfiguration((e) => { if (!editor.getModel()) { return; } if (e.hasChanged(43 /* fontInfo */)) { this._updateDecorationsRunner.schedule(); } if (e.hasChanged(130 /* wrappingInfo */)) { this._updateDecorationsRunner.cancel(); this._updateDecorations(); } })); this._register(editor.onDidChangeHiddenAreas(() => { this._updateDecorationsRunner.cancel(); this._updateDecorations(); })); this._register(editor.onDidChangeModelContent(() => { if (this._isVisible) { this._beginUpdateDecorationsSoon(); } })); this._register(editor.onDidChangeModelOptions((e) => { if (e.tabSize) { this._updateDecorationsRunner.schedule(); } })); const isInDiffRightEditorKey = this._contextKeyService.createKey('isInDiffRightEditor', editor.hasWidgetFocus()); this._register(editor.onDidFocusEditorWidget(() => isInDiffRightEditorKey.set(true))); this._register(editor.onDidBlurEditorWidget(() => isInDiffRightEditorKey.set(false))); this._register(editor.onDidContentSizeChange(e => { const width = this._originalEditor.getContentWidth() + this._modifiedEditor.getContentWidth() + DiffEditorWidget.ONE_OVERVIEW_WIDTH; const height = Math.max(this._modifiedEditor.getContentHeight(), this._originalEditor.getContentHeight()); this._onDidContentSizeChange.fire({ contentHeight: height, contentWidth: width, contentHeightChanged: e.contentHeightChanged, contentWidthChanged: e.contentWidthChanged }); })); return editor; } _createInnerEditor(instantiationService, container, options, editorWidgetOptions) { return instantiationService.createInstance(CodeEditorWidget, container, options, editorWidgetOptions); } dispose() { this._codeEditorService.removeDiffEditor(this); if (this._beginUpdateDecorationsTimeout !== -1) { window.clearTimeout(this._beginUpdateDecorationsTimeout); this._beginUpdateDecorationsTimeout = -1; } this._cleanViewZonesAndDecorations(); if (this._originalOverviewRuler) { this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode()); this._originalOverviewRuler.dispose(); } if (this._modifiedOverviewRuler) { this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode()); this._modifiedOverviewRuler.dispose(); } this._overviewDomElement.removeChild(this._overviewViewportDomElement.domNode); if (this._options.renderOverviewRuler) { this._containerDomElement.removeChild(this._overviewDomElement); } this._containerDomElement.removeChild(this._originalDomNode); this._originalEditor.dispose(); this._containerDomElement.removeChild(this._modifiedDomNode); this._modifiedEditor.dispose(); this._strategy.dispose(); this._containerDomElement.removeChild(this._reviewPane.domNode.domNode); this._containerDomElement.removeChild(this._reviewPane.shadow.domNode); this._containerDomElement.removeChild(this._reviewPane.actionBarContainer.domNode); this._reviewPane.dispose(); this._domElement.removeChild(this._containerDomElement); this._onDidDispose.fire(); super.dispose(); } //------------ begin IDiffEditor methods getId() { return this.getEditorType() + ':' + this._id; } getEditorType() { return editorCommon.EditorType.IDiffEditor; } getLineChanges() { if (!this._diffComputationResult) { return null; } return this._diffComputationResult.changes; } getOriginalEditor() { return this._originalEditor; } getModifiedEditor() { return this._modifiedEditor; } updateOptions(_newOptions) { const newOptions = validateDiffEditorOptions(_newOptions, this._options); const changed = changedDiffEditorOptions(this._options, newOptions); this._options = newOptions; const beginUpdateDecorations = (changed.ignoreTrimWhitespace || changed.renderIndicators); const beginUpdateDecorationsSoon = (this._isVisible && (changed.maxComputationTime || changed.maxFileSize)); if (beginUpdateDecorations) { this._beginUpdateDecorations(); } else if (beginUpdateDecorationsSoon) { this._beginUpdateDecorationsSoon(); } this._modifiedEditor.updateOptions(this._adjustOptionsForRightHandSide(_newOptions)); this._originalEditor.updateOptions(this._adjustOptionsForLeftHandSide(_newOptions)); // enableSplitViewResizing this._strategy.setEnableSplitViewResizing(this._options.enableSplitViewResizing); // renderSideBySide if (changed.renderSideBySide) { if (this._options.renderSideBySide) { this._setStrategy(new DiffEditorWidgetSideBySide(this._createDataSource(), this._options.enableSplitViewResizing)); } else { this._setStrategy(new DiffEditorWidgetInline(this._createDataSource(), this._options.enableSplitViewResizing)); } // Update class name this._containerDomElement.className = DiffEditorWidget._getClassName(this._themeService.getColorTheme(), this._options.renderSideBySide); } // renderOverviewRuler if (changed.renderOverviewRuler) { if (this._options.renderOverviewRuler) { this._containerDomElement.appendChild(this._overviewDomElement); } else { this._containerDomElement.removeChild(this._overviewDomElement); } } } getModel() { return { original: this._originalEditor.getModel(), modified: this._modifiedEditor.getModel() }; } setModel(model) { // Guard us against partial null model if (model && (!model.original || !model.modified)) { throw new Error(!model.original ? 'DiffEditorWidget.setModel: Original model is null' : 'DiffEditorWidget.setModel: Modified model is null'); } // Remove all view zones & decorations this._cleanViewZonesAndDecorations(); // Update code editor models this._originalEditor.setModel(model ? model.original : null); this._modifiedEditor.setModel(model ? model.modified : null); this._updateDecorationsRunner.cancel(); // this.originalEditor.onDidChangeModelOptions if (model) { this._originalEditor.setScrollTop(0); this._modifiedEditor.setScrollTop(0); } // Disable any diff computations that will come in this._diffComputationResult = null; this._diffComputationToken++; this._setState(0 /* Idle */); if (model) { this._recreateOverviewRulers(); // Begin comparing this._beginUpdateDecorations(); } this._layoutOverviewViewport(); } getDomNode() { return this._domElement; } getVisibleColumnFromPosition(position) { return this._modifiedEditor.getVisibleColumnFromPosition(position); } getPosition() { return this._modifiedEditor.getPosition(); } setPosition(position) { this._modifiedEditor.setPosition(position); } revealLine(lineNumber, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealLine(lineNumber, scrollType); } revealLineInCenter(lineNumber, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealLineInCenter(lineNumber, scrollType); } revealLineInCenterIfOutsideViewport(lineNumber, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealLineInCenterIfOutsideViewport(lineNumber, scrollType); } revealLineNearTop(lineNumber, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealLineNearTop(lineNumber, scrollType); } revealPosition(position, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealPosition(position, scrollType); } revealPositionInCenter(position, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealPositionInCenter(position, scrollType); } revealPositionInCenterIfOutsideViewport(position, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealPositionInCenterIfOutsideViewport(position, scrollType); } revealPositionNearTop(position, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealPositionNearTop(position, scrollType); } getSelection() { return this._modifiedEditor.getSelection(); } getSelections() { return this._modifiedEditor.getSelections(); } setSelection(something) { this._modifiedEditor.setSelection(something); } setSelections(ranges) { this._modifiedEditor.setSelections(ranges); } revealLines(startLineNumber, endLineNumber, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealLines(startLineNumber, endLineNumber, scrollType); } revealLinesInCenter(startLineNumber, endLineNumber, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealLinesInCenter(startLineNumber, endLineNumber, scrollType); } revealLinesInCenterIfOutsideViewport(startLineNumber, endLineNumber, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealLinesInCenterIfOutsideViewport(startLineNumber, endLineNumber, scrollType); } revealLinesNearTop(startLineNumber, endLineNumber, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealLinesNearTop(startLineNumber, endLineNumber, scrollType); } revealRange(range, scrollType = 0 /* Smooth */, revealVerticalInCenter = false, revealHorizontal = true) { this._modifiedEditor.revealRange(range, scrollType, revealVerticalInCenter, revealHorizontal); } revealRangeInCenter(range, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealRangeInCenter(range, scrollType); } revealRangeInCenterIfOutsideViewport(range, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealRangeInCenterIfOutsideViewport(range, scrollType); } revealRangeNearTop(range, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealRangeNearTop(range, scrollType); } revealRangeNearTopIfOutsideViewport(range, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealRangeNearTopIfOutsideViewport(range, scrollType); } revealRangeAtTop(range, scrollType = 0 /* Smooth */) { this._modifiedEditor.revealRangeAtTop(range, scrollType); } getSupportedActions() { return this._modifiedEditor.getSupportedActions(); } saveViewState() { const originalViewState = this._originalEditor.saveViewState(); const modifiedViewState = this._modifiedEditor.saveViewState(); return { original: originalViewState, modified: modifiedViewState }; } restoreViewState(s) { if (s && s.original && s.modified) { const diffEditorState = s; this._originalEditor.restoreViewState(diffEditorState.original); this._modifiedEditor.restoreViewState(diffEditorState.modified); } } layout(dimension) { this._elementSizeObserver.observe(dimension); } focus() { this._modifiedEditor.focus(); } hasTextFocus() { return this._originalEditor.hasTextFocus() || this._modifiedEditor.hasTextFocus(); } trigger(source, handlerId, payload) { this._modifiedEditor.trigger(source, handlerId, payload); } changeDecorations(callback) { return this._modifiedEditor.changeDecorations(callback); } //------------ end IDiffEditor methods //------------ begin layouting methods _onDidContainerSizeChanged() { this._doLayout(); } _getReviewHeight() { return this._reviewPane.isVisible() ? this._elementSizeObserver.getHeight() : 0; } _layoutOverviewRulers() { if (!this._options.renderOverviewRuler) { return; } if (!this._originalOverviewRuler || !this._modifiedOverviewRuler) { return; } const height = this._elementSizeObserver.getHeight(); const reviewHeight = this._getReviewHeight(); const freeSpace = DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH - 2 * DiffEditorWidget.ONE_OVERVIEW_WIDTH; const layoutInfo = this._modifiedEditor.getLayoutInfo(); if (layoutInfo) { this._originalOverviewRuler.setLayout({ top: 0, width: DiffEditorWidget.ONE_OVERVIEW_WIDTH, right: freeSpace + DiffEditorWidget.ONE_OVERVIEW_WIDTH, height: (height - reviewHeight) }); this._modifiedOverviewRuler.setLayout({ top: 0, right: 0, width: DiffEditorWidget.ONE_OVERVIEW_WIDTH, height: (height - reviewHeight) }); } } //------------ end layouting methods _onViewZonesChanged() { if (this._currentlyChangingViewZones) { return; } this._updateDecorationsRunner.schedule(); } _beginUpdateDecorationsSoon() { // Clear previous timeout if necessary if (this._beginUpdateDecorationsTimeout !== -1) { window.clearTimeout(this._beginUpdateDecorationsTimeout); this._beginUpdateDecorationsTimeout = -1; } this._beginUpdateDecorationsTimeout = window.setTimeout(() => this._beginUpdateDecorations(), DiffEditorWidget.UPDATE_DIFF_DECORATIONS_DELAY); } static _equals(a, b) { if (!a && !b) { return true; } if (!a || !b) { return false; } return (a.toString() === b.toString()); } _beginUpdateDecorations() { this._beginUpdateDecorationsTimeout = -1; const currentOriginalModel = this._originalEditor.getModel(); const currentModifiedModel = this._modifiedEditor.getModel(); if (!currentOriginalModel || !currentModifiedModel) { return; } // Prevent old diff requests to come if a new request has been initiated // The best method would be to call cancel on the Promise, but this is not // yet supported, so using tokens for now. this._diffComputationToken++; const currentToken = this._diffComputationToken; const diffLimit = this._options.maxFileSize * 1024 * 1024; // MB const canSyncModelForDiff = (model) => { const bufferTextLength = model.getValueLength(); return (diffLimit === 0 || bufferTextLength <= diffLimit); }; if (!canSyncModelForDiff(currentOriginalModel) || !canSyncModelForDiff(currentModifiedModel)) { if (!DiffEditorWidget._equals(currentOriginalModel.uri, this._lastOriginalWarning) || !DiffEditorWidget._equals(currentModifiedModel.uri, this._lastModifiedWarning)) { this._lastOriginalWarning = currentOriginalModel.uri; this._lastModifiedWarning = currentModifiedModel.uri; this._notificationService.warn(nls.localize("diff.tooLarge", "Cannot compare files because one file is too large.")); } return; } this._setState(1 /* ComputingDiff */); this._editorWorkerService.computeDiff(currentOriginalModel.uri, currentModifiedModel.uri, this._options.ignoreTrimWhitespace, this._options.maxComputationTime).then((result) => { if (currentToken === this._diffComputationToken && currentOriginalModel === this._originalEditor.getModel() && currentModifiedModel === this._modifiedEditor.getModel()) { this._setState(2 /* DiffComputed */); this._diffComputationResult = result; this._updateDecorationsRunner.schedule(); this._onDidUpdateDiff.fire(); } }, (error) => { if (currentToken === this._diffComputationToken && currentOriginalModel === this._originalEditor.getModel() && currentModifiedModel === this._modifiedEditor.getModel()) { this._setState(2 /* DiffComputed */); this._diffComputationResult = null; this._updateDecorationsRunner.schedule(); } }); } _cleanViewZonesAndDecorations() { this._originalEditorState.clean(this._originalEditor); this._modifiedEditorState.clean(this._modifiedEditor); } _updateDecorations() { if (!this._originalEditor.getModel() || !this._modifiedEditor.getModel()) { return; } const lineChanges = (this._diffComputationResult ? this._diffComputationResult.changes : []); const foreignOriginal = this._originalEditorState.getForeignViewZones(this._originalEditor.getWhitespaces()); const foreignModified = this._modifiedEditorState.getForeignViewZones(this._modifiedEditor.getWhitespaces()); const diffDecorations = this._strategy.getEditorsDiffDecorations(lineChanges, this._options.ignoreTrimWhitespace, this._options.renderIndicators, foreignOriginal, foreignModified); try { this._currentlyChangingViewZones = true; this._originalEditorState.apply(this._originalEditor, this._originalOverviewRuler, diffDecorations.original, false); this._modifiedEditorState.apply(this._modifiedEditor, this._modifiedOverviewRuler, diffDecorations.modified, true); } finally { this._currentlyChangingViewZones = false; } } _adjustOptionsForSubEditor(options) { const clonedOptions = Object.assign({}, options); clonedOptions.inDiffEditor = true; clonedOptions.automaticLayout = false; // Clone scrollbar options before changing them clonedOptions.scrollbar = Object.assign({}, (clonedOptions.scrollbar || {})); clonedOptions.scrollbar.vertical = 'visible'; clonedOptions.folding = false; clonedOptions.codeLens = this._options.diffCodeLens; clonedOptions.fixedOverflowWidgets = true; // clonedOptions.lineDecorationsWidth = '2ch'; // Clone minimap options before changing them clonedOptions.minimap = Object.assign({}, (clonedOptions.minimap || {})); clonedOptions.minimap.enabled = false; return clonedOptions; } _adjustOptionsForLeftHandSide(options) { const result = this._adjustOptionsForSubEditor(options); if (!this._options.renderSideBySide) { // never wrap hidden editor result.wordWrapOverride1 = 'off'; } else { result.wordWrapOverride1 = this._options.diffWordWrap; } if (options.originalAriaLabel) { result.ariaLabel = options.originalAriaLabel; } result.readOnly = !this._options.originalEditable; result.extraEditorClassName = 'original-in-monaco-diff-editor'; return Object.assign(Object.assign({}, result), { dimension: { height: 0, width: 0 } }); } _adjustOptionsForRightHandSide(options) { const result = this._adjustOptionsForSubEditor(options); if (options.modifiedAriaLabel) { result.ariaLabel = options.modifiedAriaLabel; } result.wordWrapOverride1 = this._options.diffWordWrap; result.revealHorizontalRightPadding = EditorOptions.revealHorizontalRightPadding.defaultValue + DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH; result.scrollbar.verticalHasArrows = false; result.extraEditorClassName = 'modified-in-monaco-diff-editor'; return Object.assign(Object.assign({}, result), { dimension: { height: 0, width: 0 } }); } doLayout() { this._elementSizeObserver.observe(); this._doLayout(); } _doLayout() { const width = this._elementSizeObserver.getWidth(); const height = this._elementSizeObserver.getHeight(); const reviewHeight = this._getReviewHeight(); const splitPoint = this._strategy.layout(); this._originalDomNode.style.width = splitPoint + 'px'; this._originalDomNode.style.left = '0px'; this._modifiedDomNode.style.width = (width - splitPoint) + 'px'; this._modifiedDomNode.style.left = splitPoint + 'px'; this._overviewDomElement.style.top = '0px'; this._overviewDomElement.style.height = (height - reviewHeight) + 'px'; this._overviewDomElement.style.width = DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH + 'px'; this._overviewDomElement.style.left = (width - DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH) + 'px'; this._overviewViewportDomElement.setWidth(DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH); this._overviewViewportDomElement.setHeight(30); this._originalEditor.layout({ width: splitPoint, height: (height - reviewHeight) }); this._modifiedEditor.layout({ width: width - splitPoint - (this._options.renderOverviewRuler ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0), height: (height - reviewHeight) }); if (this._originalOverviewRuler || this._modifiedOverviewRuler) { this._layoutOverviewRulers(); } this._reviewPane.layout(height - reviewHeight, width, reviewHeight); this._layoutOverviewViewport(); } _layoutOverviewViewport() { const layout = this._computeOverviewViewport(); if (!layout) { this._overviewViewportDomElement.setTop(0); this._overviewViewportDomElement.setHeight(0); } else { this._overviewViewportDomElement.setTop(layout.top); this._overviewViewportDomElement.setHeight(layout.height); } } _computeOverviewViewport() { const layoutInfo = this._modifiedEditor.getLayoutInfo(); if (!layoutInfo) { return null; } const scrollTop = this._modifiedEditor.getScrollTop(); const scrollHeight = this._modifiedEditor.getScrollHeight(); const computedAvailableSize = Math.max(0, layoutInfo.height); const computedRepresentableSize = Math.max(0, computedAvailableSize - 2 * 0); const computedRatio = scrollHeight > 0 ? (computedRepresentableSize / scrollHeight) : 0; const computedSliderSize = Math.max(0, Math.floor(layoutInfo.height * computedRatio)); const computedSliderPosition = Math.floor(scrollTop * computedRatio); return { height: computedSliderSize, top: computedSliderPosition }; } _createDataSource() { return { getWidth: () => { return this._elementSizeObserver.getWidth(); }, getHeight: () => { return (this._elementSizeObserver.getHeight() - this._getReviewHeight()); }, getOptions: () => { return { renderOverviewRuler: this._options.renderOverviewRuler }; }, getContainerDomNode: () => { return this._containerDomElement; }, relayoutEditors: () => { this._doLayout(); }, getOriginalEditor: () => { return this._originalEditor; }, getModifiedEditor: () => { return this._modifiedEditor; } }; } _setStrategy(newStrategy) { if (this._strategy) { this._strategy.dispose(); } this._strategy = newStrategy; newStrategy.applyColors(this._themeService.getColorTheme()); if (this._diffComputationResult) { this._updateDecorations(); } // Just do a layout, the strategy might need it this._doLayout(); } _getLineChangeAtOrBeforeLineNumber(lineNumber, startLineNumberExtractor) { const lineChanges = (this._diffComputationResult ? this._diffComputationResult.changes : []); if (lineChanges.length === 0 || lineNumber < startLineNumberExtractor(lineChanges[0])) { // There are no changes or `lineNumber` is before the first change return null; } let min = 0; let max = lineChanges.length - 1; while (min < max) { const mid = Math.floor((min + max) / 2); const midStart = startLineNumberExtractor(lineChanges[mid]); const midEnd = (mid + 1 <= max ? startLineNumberExtractor(lineChanges[mid + 1]) : 1073741824 /* MAX_SAFE_SMALL_INTEGER */); if (lineNumber < midStart) { max = mid - 1; } else if (lineNumber >= midEnd) { min = mid + 1; } else { // HIT! min = mid; max = mid; } } return lineChanges[min]; } _getEquivalentLineForOriginalLineNumber(lineNumber) { const lineChange = this._getLineChangeAtOrBeforeLineNumber(lineNumber, (lineChange) => lineChange.originalStartLineNumber); if (!lineChange) { return lineNumber; } const originalEquivalentLineNumber = lineChange.originalStartLineNumber + (lineChange.originalEndLineNumber > 0 ? -1 : 0); const modifiedEquivalentLineNumber = lineChange.modifiedStartLineNumber + (lineChange.modifiedEndLineNumber > 0 ? -1 : 0); const lineChangeOriginalLength = (lineChange.originalEndLineNumber > 0 ? (lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1) : 0); const lineChangeModifiedLength = (lineChange.modifiedEndLineNumber > 0 ? (lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1) : 0); const delta = lineNumber - originalEquivalentLineNumber; if (delta <= lineChangeOriginalLength) { return modifiedEquivalentLineNumber + Math.min(delta, lineChangeModifiedLength); } return modifiedEquivalentLineNumber + lineChangeModifiedLength - lineChangeOriginalLength + delta; } _getEquivalentLineForModifiedLineNumber(lineNumber) { const lineChange = this._getLineChangeAtOrBeforeLineNumber(lineNumber, (lineChange) => lineChange.modifiedStartLineNumber); if (!lineChange) { return lineNumber; } const originalEquivalentLineNumber = lineChange.originalStartLineNumber + (lineChange.originalEndLineNumber > 0 ? -1 : 0); const modifiedEquivalentLineNumber = lineChange.modifiedStartLineNumber + (lineChange.modifiedEndLineNumber > 0 ? -1 : 0); const lineChangeOriginalLength = (lineChange.originalEndLineNumber > 0 ? (lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1) : 0); const lineChangeModifiedLength = (lineChange.modifiedEndLineNumber > 0 ? (lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1) : 0); const delta = lineNumber - modifiedEquivalentLineNumber; if (delta <= lineChangeModifiedLength) { return originalEquivalentLineNumber + Math.min(delta, lineChangeOriginalLength); } return originalEquivalentLineNumber + lineChangeOriginalLength - lineChangeModifiedLength + delta; } getDiffLineInformationForOriginal(lineNumber) { if (!this._diffComputationResult) { // Cannot answer that which I don't know return null; } return { equivalentLineNumber: this._getEquivalentLineForOriginalLineNumber(lineNumber) }; } getDiffLineInformationForModified(lineNumber) { if (!this._diffComputationResult) { // Cannot answer that which I don't know return null; } return { equivalentLineNumber: this._getEquivalentLineForModifiedLineNumber(lineNumber) }; } }; DiffEditorWidget.ONE_OVERVIEW_WIDTH = 15; DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH = 30; DiffEditorWidget.UPDATE_DIFF_DECORATIONS_DELAY = 200; // ms DiffEditorWidget = __decorate([ __param(3, IClipboardService), __param(4, IEditorWorkerService), __param(5, IContextKeyService), __param(6, IInstantiationService), __param(7, ICodeEditorService), __param(8, IThemeService), __param(9, INotificationService), __param(10, IContextMenuService), __param(11, IEditorProgressService) ], DiffEditorWidget); export { DiffEditorWidget }; class DiffEditorWidgetStyle extends Disposable { constructor(dataSource) { super(); this._dataSource = dataSource; this._insertColor = null; this._removeColor = null; } applyColors(theme) { const newInsertColor = (theme.getColor(diffInserted) || defaultInsertColor).transparent(2); const newRemoveColor = (theme.getColor(diffRemoved) || defaultRemoveColor).transparent(2); const hasChanges = !newInsertColor.equals(this._insertColor) || !newRemoveColor.equals(this._removeColor); this._insertColor = newInsertColor; this._removeColor = newRemoveColor; return hasChanges; } getEditorsDiffDecorations(lineChanges, ignoreTrimWhitespace, renderIndicators, originalWhitespaces, modifiedWhitespaces) { // Get view zones modifiedWhitespaces = modifiedWhitespaces.sort((a, b) => { return a.afterLineNumber - b.afterLineNumber; }); originalW