<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as path from 'path';

import * as nls from 'vscode-nls';
import { Logger } from '../logger';
import { MarkdownContentProvider, PreviewConfigManager, isMarkdownFile } from './previewContentProvider';
const localize = nls.loadMessageBundle();

class MarkdownPreview {

	public static previewScheme = 'vscode-markdown-preview';
	private static previewCount = 0;

	public isScrolling = false;
	public readonly uri: vscode.Uri;
	private readonly webview: vscode.Webview;
	private throttleTimer: any;
	private initialLine: number | undefined = undefined;
	private readonly disposables: vscode.Disposable[] = [];
	private firstUpdate = true;
	private currentVersion?: { resource: vscode.Uri, version: number };
	private _forceUpdate: boolean = false;

	constructor(
		private _resource: vscode.Uri,
		previewColumn: vscode.ViewColumn,
		public locked: boolean,
		private readonly contentProvider: MarkdownContentProvider,
		private readonly previewConfigurations: PreviewConfigManager,
		private readonly logger: Logger
	) {
		this.uri = vscode.Uri.parse(`${MarkdownPreview.previewScheme}:${MarkdownPreview.previewCount++}`);
		this.webview = vscode.window.createWebview(
			this.uri,
			this.getPreviewTitle(this._resource),
			previewColumn, {
				enableScripts: true,
				localResourceRoots: this.getLocalResourceRoots(_resource)
			});

		this.webview.onDidDispose(() => {
			this.dispose();
		}, null, this.disposables);

		this.webview.onDidChangeViewColumn(() => {
			this._onDidChangeViewColumnEmitter.fire();
		}, null, this.disposables);

		this.webview.onDidReceiveMessage(e => {
			vscode.commands.executeCommand(e.command, ...e.args);
		}, null, this.disposables);

		vscode.workspace.onDidChangeTextDocument(event => {
			if (isMarkdownFile(event.document) && this.isPreviewOf(event.document.uri)) {
				this.refresh();
			}
		}, null, this.disposables);

		vscode.window.onDidChangeTextEditorVisibleRanges(event => {
			if (isMarkdownFile(event.textEditor.document) && this.isPreviewOf(event.textEditor.document.uri)) {
				const resource = event.textEditor.document.uri;
				const line = getVisibleLine(event.textEditor);
				this.updateForView(resource, line);
			}
		}, null, this.disposables);

		vscode.window.onDidChangeTextEditorSelection(event => {
			if (isMarkdownFile(event.textEditor.document) && this.isPreviewOf(event.textEditor.document.uri)) {
				this.webview.postMessage({
					type: 'onDidChangeTextEditorSelection',
					line: event.selections[0].active.line,
					source: this.resource.toString()
				});
			}
		}, null, this.disposables);
	}

	private readonly _onDisposeEmitter = new vscode.EventEmitter<void>();
	public readonly onDispose = this._onDisposeEmitter.event;

	private readonly _onDidChangeViewColumnEmitter = new vscode.EventEmitter<vscode.ViewColumn>();
	public readonly onDidChangeViewColumn = this._onDidChangeViewColumnEmitter.event;

	public get resource(): vscode.Uri {
		return this._resource;
	}

	public dispose() {
		this._onDisposeEmitter.fire();

		this._onDisposeEmitter.dispose();
		this._onDidChangeViewColumnEmitter.dispose();
		this.webview.dispose();

		disposeAll(this.disposables);
	}

	public update(resource: vscode.Uri) {
		const editor = vscode.window.activeTextEditor;
		if (editor && editor.document.uri.fsPath === resource.fsPath) {
			this.initialLine = getVisibleLine(editor);
		} else {
			this.initialLine = undefined;
		}

		// Schedule update
		if (!this.throttleTimer) {
			this.throttleTimer = setTimeout(() => this.doUpdate(), resource.fsPath === this._resource.fsPath && !this.firstUpdate ? 300 : 0);
		}

		this.firstUpdate = false;
		this._resource = resource;
	}

	public refresh() {
		this._forceUpdate = true;
		this.update(this._resource);
	}

	public updateConfiguration() {
		if (this.previewConfigurations.shouldUpdateConfiguration(this._resource)) {
			this.refresh();
		}
	}

	public get viewColumn(): vscode.ViewColumn | undefined {
		return this.webview.viewColumn;
	}

	public isPreviewOf(resource: vscode.Uri): boolean {
		return this._resource.fsPath === resource.fsPath;<commit_msg>Clean up preview update logic<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as path from 'path';

import * as nls from 'vscode-nls';
import { Logger } from '../logger';
import { MarkdownContentProvider, PreviewConfigManager, isMarkdownFile } from './previewContentProvider';
const localize = nls.loadMessageBundle();

class MarkdownPreview {

	public static previewScheme = 'vscode-markdown-preview';
	private static previewCount = 0;

	public isScrolling = false;
	public readonly uri: vscode.Uri;
	private readonly webview: vscode.Webview;
	private throttleTimer: any;
	private initialLine: number | undefined = undefined;
	private readonly disposables: vscode.Disposable[] = [];
	private firstUpdate = true;
	private currentVersion?: { resource: vscode.Uri, version: number };
	private _forceUpdate: boolean = false;

	constructor(
		private _resource: vscode.Uri,
		previewColumn: vscode.ViewColumn,
		public locked: boolean,
		private readonly contentProvider: MarkdownContentProvider,
		private readonly previewConfigurations: PreviewConfigManager,
		private readonly logger: Logger
	) {
		this.uri = vscode.Uri.parse(`${MarkdownPreview.previewScheme}:${MarkdownPreview.previewCount++}`);
		this.webview = vscode.window.createWebview(
			this.uri,
			this.getPreviewTitle(this._resource),
			previewColumn, {
				enableScripts: true,
				localResourceRoots: this.getLocalResourceRoots(_resource)
			});

		this.webview.onDidDispose(() => {
			this.dispose();
		}, null, this.disposables);

		this.webview.onDidChangeViewColumn(() => {
			this._onDidChangeViewColumnEmitter.fire();
		}, null, this.disposables);

		this.webview.onDidReceiveMessage(e => {
			vscode.commands.executeCommand(e.command, ...e.args);
		}, null, this.disposables);

		vscode.workspace.onDidChangeTextDocument(event => {
			if (isMarkdownFile(event.document) && this.isPreviewOf(event.document.uri)) {
				this.refresh();
			}
		}, null, this.disposables);

		vscode.window.onDidChangeTextEditorVisibleRanges(event => {
			if (isMarkdownFile(event.textEditor.document) && this.isPreviewOf(event.textEditor.document.uri)) {
				const resource = event.textEditor.document.uri;
				const line = getVisibleLine(event.textEditor);
				this.updateForView(resource, line);
			}
		}, null, this.disposables);

		vscode.window.onDidChangeTextEditorSelection(event => {
			if (isMarkdownFile(event.textEditor.document) && this.isPreviewOf(event.textEditor.document.uri)) {
				this.webview.postMessage({
					type: 'onDidChangeTextEditorSelection',
					line: event.selections[0].active.line,
					source: this.resource.toString()
				});
			}
		}, null, this.disposables);
	}

	private readonly _onDisposeEmitter = new vscode.EventEmitter<void>();
	public readonly onDispose = this._onDisposeEmitter.event;

	private readonly _onDidChangeViewColumnEmitter = new vscode.EventEmitter<vscode.ViewColumn>();
	public readonly onDidChangeViewColumn = this._onDidChangeViewColumnEmitter.event;

	public get resource(): vscode.Uri {
		return this._resource;
	}

	public dispose() {
		this._onDisposeEmitter.fire();

		this._onDisposeEmitter.dispose();
		this._onDidChangeViewColumnEmitter.dispose();
		this.webview.dispose();

		disposeAll(this.disposables);
	}

	public update(resource: vscode.Uri) {
		const editor = vscode.window.activeTextEditor;
		if (editor && editor.document.uri.fsPath === resource.fsPath) {
			this.initialLine = getVisibleLine(editor);
		} else {
			this.initialLine = undefined;
		}

		// If we have changed resources, cancel any pending updates
		const isResourceChange = resource.fsPath !== this._resource.fsPath;
		if (isResourceChange) {
			clearTimeout(this.throttleTimer);
			this.throttleTimer = undefined;
		}

		this._resource = resource;

		// Schedule update if none is pending
		if (!this.throttleTimer) {
			if (isResourceChange || this.firstUpdate) {
				this.doUpdate();
			} else {
				this.throttleTimer = setTimeout(() => this.doUpdate(), 300);
			}
		}

		this.firstUpdate = false;
	}

	public refresh() {
		this._forceUpdate = true;
		this.update(this._resource);
	}

	public updateConfiguration() {
		if (this.previewConfigurations.shouldUpdateConfiguration(this._resource)) {
			this.refresh();
		}
	}

	public get viewColumn(): vscode.ViewColumn | undefined {
		return this.webview.viewColumn;
	}

	public isPreviewOf(resource: vscode.Uri): boolean {
		return this._resource.fsPath === resource.fsPath;
{'fraction_non_alphanumeric': 0.15541415012942192, 'fraction_numerical': 0.001186367558239862, 'mean_word_length': 3.799689440993789, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6640801', 'n_tokens_mistral': 3022, 'n_tokens_neox': 2739, 'n_words': 548}