diff --git a/eslint.config.js b/eslint.config.js index e7bc3f37aaa..73f062af66a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -2271,21 +2271,13 @@ export default tseslint.config( '@typescript-eslint': tseslint.plugin, }, rules: { - '@typescript-eslint/naming-convention': [ + 'no-restricted-syntax': [ 'warn', { - 'selector': 'default', - 'modifiers': ['private'], - 'format': null, - 'leadingUnderscore': 'require' + selector: ':matches(PropertyDefinition, TSParameterProperty, MethodDefinition[key.name!="constructor"])[accessibility="private"]', + message: 'Use #private instead', }, - { - 'selector': 'default', - 'modifiers': ['public'], - 'format': null, - 'leadingUnderscore': 'forbid' - } - ] + ], } }, // Additional extension strictness rules @@ -2351,5 +2343,4 @@ export default tseslint.config( }, ], } - }, -); + }); diff --git a/extensions/markdown-language-features/preview-src/activeLineMarker.ts b/extensions/markdown-language-features/preview-src/activeLineMarker.ts index 75c1ed7cbc9..33082275f6c 100644 --- a/extensions/markdown-language-features/preview-src/activeLineMarker.ts +++ b/extensions/markdown-language-features/preview-src/activeLineMarker.ts @@ -5,27 +5,27 @@ import { getElementsForSourceLine } from './scroll-sync'; export class ActiveLineMarker { - private _current: any; + #current: any; onDidChangeTextEditorSelection(line: number, documentVersion: number) { const { previous } = getElementsForSourceLine(line, documentVersion); - this._update(previous && (previous.codeElement || previous.element)); + this.#update(previous && (previous.codeElement || previous.element)); } - private _update(before: HTMLElement | undefined) { - this._unmarkActiveElement(this._current); - this._markActiveElement(before); - this._current = before; + #update(before: HTMLElement | undefined) { + this.#unmarkActiveElement(this.#current); + this.#markActiveElement(before); + this.#current = before; } - private _unmarkActiveElement(element: HTMLElement | undefined) { + #unmarkActiveElement(element: HTMLElement | undefined) { if (!element) { return; } element.classList.toggle('code-active-line', false); } - private _markActiveElement(element: HTMLElement | undefined) { + #markActiveElement(element: HTMLElement | undefined) { if (!element) { return; } diff --git a/extensions/markdown-language-features/preview-src/csp.ts b/extensions/markdown-language-features/preview-src/csp.ts index fcc38352da8..4db9d7b116f 100644 --- a/extensions/markdown-language-features/preview-src/csp.ts +++ b/extensions/markdown-language-features/preview-src/csp.ts @@ -11,45 +11,49 @@ import { getStrings } from './strings'; * Shows an alert when there is a content security policy violation. */ export class CspAlerter { - private _didShow = false; - private _didHaveCspWarning = false; + #didShow = false; + #didHaveCspWarning = false; - private _messaging?: MessagePoster; + #messaging?: MessagePoster; + + readonly #settingsManager: SettingsManager; constructor( - private readonly _settingsManager: SettingsManager, + settingsManager: SettingsManager, ) { + this.#settingsManager = settingsManager; + document.addEventListener('securitypolicyviolation', () => { - this._onCspWarning(); + this.#onCspWarning(); }); window.addEventListener('message', (event) => { if (event?.data && event.data.name === 'vscode-did-block-svg') { - this._onCspWarning(); + this.#onCspWarning(); } }); } public setPoster(poster: MessagePoster) { - this._messaging = poster; - if (this._didHaveCspWarning) { - this._showCspWarning(); + this.#messaging = poster; + if (this.#didHaveCspWarning) { + this.#showCspWarning(); } } - private _onCspWarning() { - this._didHaveCspWarning = true; - this._showCspWarning(); + #onCspWarning() { + this.#didHaveCspWarning = true; + this.#showCspWarning(); } - private _showCspWarning() { + #showCspWarning() { const strings = getStrings(); - const settings = this._settingsManager.settings; + const settings = this.#settingsManager.settings; - if (this._didShow || settings.disableSecurityWarnings || !this._messaging) { + if (this.#didShow || settings.disableSecurityWarnings || !this.#messaging) { return; } - this._didShow = true; + this.#didShow = true; const notification = document.createElement('a'); notification.innerText = strings.cspAlertMessageText; @@ -59,7 +63,7 @@ export class CspAlerter { notification.setAttribute('role', 'button'); notification.setAttribute('aria-label', strings.cspAlertMessageLabel); notification.onclick = () => { - this._messaging!.postMessage('showPreviewSecuritySelector', { source: settings.source }); + this.#messaging!.postMessage('showPreviewSecuritySelector', { source: settings.source }); }; document.body.appendChild(notification); } diff --git a/extensions/markdown-language-features/preview-src/loading.ts b/extensions/markdown-language-features/preview-src/loading.ts index c6e6d27acd9..ac5beaa0f8b 100644 --- a/extensions/markdown-language-features/preview-src/loading.ts +++ b/extensions/markdown-language-features/preview-src/loading.ts @@ -5,15 +5,15 @@ import { MessagePoster } from './messaging'; export class StyleLoadingMonitor { - private readonly _unloadedStyles: string[] = []; - private _finishedLoading: boolean = false; + readonly #unloadedStyles: string[] = []; + #finishedLoading: boolean = false; - private _poster?: MessagePoster; + #poster?: MessagePoster; constructor() { const onStyleLoadError = (event: any) => { const source = event.target.dataset.source; - this._unloadedStyles.push(source); + this.#unloadedStyles.push(source); }; window.addEventListener('DOMContentLoaded', () => { @@ -25,18 +25,18 @@ export class StyleLoadingMonitor { }); window.addEventListener('load', () => { - if (!this._unloadedStyles.length) { + if (!this.#unloadedStyles.length) { return; } - this._finishedLoading = true; - this._poster?.postMessage('previewStyleLoadError', { unloadedStyles: this._unloadedStyles }); + this.#finishedLoading = true; + this.#poster?.postMessage('previewStyleLoadError', { unloadedStyles: this.#unloadedStyles }); }); } public setPoster(poster: MessagePoster): void { - this._poster = poster; - if (this._finishedLoading) { - poster.postMessage('previewStyleLoadError', { unloadedStyles: this._unloadedStyles }); + this.#poster = poster; + if (this.#finishedLoading) { + poster.postMessage('previewStyleLoadError', { unloadedStyles: this.#unloadedStyles }); } } } diff --git a/extensions/markdown-language-features/preview-src/scroll-sync.ts b/extensions/markdown-language-features/preview-src/scroll-sync.ts index 33d81094cb5..14aa18d5490 100644 --- a/extensions/markdown-language-features/preview-src/scroll-sync.ts +++ b/extensions/markdown-language-features/preview-src/scroll-sync.ts @@ -9,18 +9,18 @@ const codeLineClass = 'code-line'; export class CodeLineElement { - private readonly _detailParentElements: readonly HTMLDetailsElement[]; + readonly #detailParentElements: readonly HTMLDetailsElement[]; constructor( readonly element: HTMLElement, readonly line: number, readonly codeElement?: HTMLElement, ) { - this._detailParentElements = Array.from(getParentsWithTagName(element, 'DETAILS')); + this.#detailParentElements = Array.from(getParentsWithTagName(element, 'DETAILS')); } get isVisible(): boolean { - if (this._detailParentElements.some(x => !x.open)) { + if (this.#detailParentElements.some(x => !x.open)) { return false; } diff --git a/extensions/markdown-language-features/preview-src/settings.ts b/extensions/markdown-language-features/preview-src/settings.ts index 0fb5d0c2686..6d642b58c64 100644 --- a/extensions/markdown-language-features/preview-src/settings.ts +++ b/extensions/markdown-language-features/preview-src/settings.ts @@ -33,13 +33,13 @@ export function getData(key: string): T { } export class SettingsManager { - private _settings: PreviewSettings = getData('data-settings'); + #settings: PreviewSettings = getData('data-settings'); public get settings(): PreviewSettings { - return this._settings; + return this.#settings; } public updateSettings(newSettings: PreviewSettings) { - this._settings = newSettings; + this.#settings = newSettings; } } diff --git a/extensions/markdown-language-features/src/client/client.ts b/extensions/markdown-language-features/src/client/client.ts index bf7be3f3206..dc279f02d84 100644 --- a/extensions/markdown-language-features/src/client/client.ts +++ b/extensions/markdown-language-features/src/client/client.ts @@ -17,37 +17,43 @@ export type LanguageClientConstructor = (name: string, description: string, clie export class MdLanguageClient implements IDisposable { + readonly #client: BaseLanguageClient; + readonly #workspace: VsCodeMdWorkspace; + constructor( - private readonly _client: BaseLanguageClient, - private readonly _workspace: VsCodeMdWorkspace, - ) { } + client: BaseLanguageClient, + workspace: VsCodeMdWorkspace, + ) { + this.#client = client; + this.#workspace = workspace; + } dispose(): void { - this._client.stop(); - this._workspace.dispose(); + this.#client.stop(); + this.#workspace.dispose(); } resolveLinkTarget(linkText: string, uri: vscode.Uri): Promise { - return this._client.sendRequest(proto.resolveLinkTarget, { linkText, uri: uri.toString() }); + return this.#client.sendRequest(proto.resolveLinkTarget, { linkText, uri: uri.toString() }); } getEditForFileRenames(files: ReadonlyArray<{ oldUri: string; newUri: string }>, token: vscode.CancellationToken) { - return this._client.sendRequest(proto.getEditForFileRenames, files, token); + return this.#client.sendRequest(proto.getEditForFileRenames, files, token); } getReferencesToFileInWorkspace(resource: vscode.Uri, token: vscode.CancellationToken) { - return this._client.sendRequest(proto.getReferencesToFileInWorkspace, { uri: resource.toString() }, token); + return this.#client.sendRequest(proto.getReferencesToFileInWorkspace, { uri: resource.toString() }, token); } prepareUpdatePastedLinks(doc: vscode.Uri, ranges: readonly vscode.Range[], token: vscode.CancellationToken) { - return this._client.sendRequest(proto.prepareUpdatePastedLinks, { + return this.#client.sendRequest(proto.prepareUpdatePastedLinks, { uri: doc.toString(), ranges: ranges.map(range => Range.create(range.start.line, range.start.character, range.end.line, range.end.character)), }, token); } getUpdatePastedLinksEdit(pastingIntoDoc: vscode.Uri, edits: readonly vscode.TextEdit[], metadata: string, token: vscode.CancellationToken) { - return this._client.sendRequest(proto.getUpdatePastedLinksEdit, { + return this.#client.sendRequest(proto.getUpdatePastedLinksEdit, { metadata, pasteIntoDoc: pastingIntoDoc.toString(), edits: edits.map(edit => TextEdit.replace(edit.range, edit.newText)), diff --git a/extensions/markdown-language-features/src/client/fileWatchingManager.ts b/extensions/markdown-language-features/src/client/fileWatchingManager.ts index e2010edda8a..c617a73634d 100644 --- a/extensions/markdown-language-features/src/client/fileWatchingManager.ts +++ b/extensions/markdown-language-features/src/client/fileWatchingManager.ts @@ -17,12 +17,12 @@ type DirWatcherEntry = { export class FileWatcherManager { - private readonly _fileWatchers = new Map(); - private readonly _dirWatchers = new ResourceMap<{ + readonly #dirWatchers = new ResourceMap<{ readonly watcher: vscode.FileSystemWatcher; refCount: number; }>(); @@ -35,7 +35,7 @@ export class FileWatcherManager { const watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(uri, '*'), !listeners.create, !listeners.change, !listeners.delete); const parentDirWatchers: DirWatcherEntry[] = []; - this._fileWatchers.set(id, { watcher, dirWatchers: parentDirWatchers }); + this.#fileWatchers.set(id, { watcher, dirWatchers: parentDirWatchers }); if (listeners.create) { watcher.onDidCreate(listeners.create); } if (listeners.change) { watcher.onDidChange(listeners.change); } @@ -46,12 +46,12 @@ export class FileWatcherManager { for (let dirUri = Utils.dirname(uri); dirUri.path.length > 1; dirUri = Utils.dirname(dirUri)) { const disposables: IDisposable[] = []; - let parentDirWatcher = this._dirWatchers.get(dirUri); + let parentDirWatcher = this.#dirWatchers.get(dirUri); if (!parentDirWatcher) { const glob = new vscode.RelativePattern(Utils.dirname(dirUri), Utils.basename(dirUri)); const parentWatcher = vscode.workspace.createFileSystemWatcher(glob, !listeners.create, true, !listeners.delete); parentDirWatcher = { refCount: 0, watcher: parentWatcher }; - this._dirWatchers.set(dirUri, parentDirWatcher); + this.#dirWatchers.set(dirUri, parentDirWatcher); } parentDirWatcher.refCount++; @@ -81,16 +81,16 @@ export class FileWatcherManager { } delete(id: number): void { - const entry = this._fileWatchers.get(id); + const entry = this.#fileWatchers.get(id); if (entry) { for (const dirWatcher of entry.dirWatchers) { disposeAll(dirWatcher.disposables); - const dirWatcherEntry = this._dirWatchers.get(dirWatcher.uri); + const dirWatcherEntry = this.#dirWatchers.get(dirWatcher.uri); if (dirWatcherEntry) { if (--dirWatcherEntry.refCount <= 0) { dirWatcherEntry.watcher.dispose(); - this._dirWatchers.delete(dirWatcher.uri); + this.#dirWatchers.delete(dirWatcher.uri); } } } @@ -98,6 +98,6 @@ export class FileWatcherManager { entry.watcher.dispose(); } - this._fileWatchers.delete(id); + this.#fileWatchers.delete(id); } } diff --git a/extensions/markdown-language-features/src/client/inMemoryDocument.ts b/extensions/markdown-language-features/src/client/inMemoryDocument.ts index 953f0da7c89..2726adb6de1 100644 --- a/extensions/markdown-language-features/src/client/inMemoryDocument.ts +++ b/extensions/markdown-language-features/src/client/inMemoryDocument.ts @@ -9,7 +9,7 @@ import { ITextDocument } from '../types/textDocument'; export class InMemoryDocument implements ITextDocument { - private readonly _doc: TextDocument; + readonly #doc: TextDocument; public readonly uri: vscode.Uri; public readonly version: number; @@ -21,15 +21,15 @@ export class InMemoryDocument implements ITextDocument { ) { this.uri = uri; this.version = version; - this._doc = TextDocument.create(this.uri.toString(), 'markdown', 0, contents); + this.#doc = TextDocument.create(this.uri.toString(), 'markdown', 0, contents); } getText(range?: vscode.Range): string { - return this._doc.getText(range); + return this.#doc.getText(range); } positionAt(offset: number): vscode.Position { - const pos = this._doc.positionAt(offset); + const pos = this.#doc.positionAt(offset); return new vscode.Position(pos.line, pos.character); } } diff --git a/extensions/markdown-language-features/src/client/workspace.ts b/extensions/markdown-language-features/src/client/workspace.ts index 9ea3173c9cc..b07a93ade78 100644 --- a/extensions/markdown-language-features/src/client/workspace.ts +++ b/extensions/markdown-language-features/src/client/workspace.ts @@ -17,47 +17,47 @@ import { ResourceMap } from '../util/resourceMap'; */ export class VsCodeMdWorkspace extends Disposable { - private readonly _watcher: vscode.FileSystemWatcher | undefined; + readonly #watcher: vscode.FileSystemWatcher | undefined; - private readonly _documentCache = new ResourceMap(); + readonly #documentCache = new ResourceMap(); - private readonly _utf8Decoder = new TextDecoder('utf-8'); + readonly #utf8Decoder = new TextDecoder('utf-8'); constructor() { super(); - this._watcher = this._register(vscode.workspace.createFileSystemWatcher('**/*.md')); + this.#watcher = this._register(vscode.workspace.createFileSystemWatcher('**/*.md')); - this._register(this._watcher.onDidChange(async resource => { - this._documentCache.delete(resource); + this._register(this.#watcher.onDidChange(async resource => { + this.#documentCache.delete(resource); })); - this._register(this._watcher.onDidDelete(resource => { - this._documentCache.delete(resource); + this._register(this.#watcher.onDidDelete(resource => { + this.#documentCache.delete(resource); })); this._register(vscode.workspace.onDidOpenTextDocument(e => { - this._documentCache.delete(e.uri); + this.#documentCache.delete(e.uri); })); this._register(vscode.workspace.onDidCloseTextDocument(e => { - this._documentCache.delete(e.uri); + this.#documentCache.delete(e.uri); })); } - private _isRelevantMarkdownDocument(doc: vscode.TextDocument) { + #isRelevantMarkdownDocument(doc: vscode.TextDocument) { return isMarkdownFile(doc) && doc.uri.scheme !== 'vscode-bulkeditpreview'; } public async getOrLoadMarkdownDocument(resource: vscode.Uri): Promise { - const existing = this._documentCache.get(resource); + const existing = this.#documentCache.get(resource); if (existing) { return existing; } - const matchingDocument = vscode.workspace.textDocuments.find((doc) => this._isRelevantMarkdownDocument(doc) && doc.uri.toString() === resource.toString()); + const matchingDocument = vscode.workspace.textDocuments.find((doc) => this.#isRelevantMarkdownDocument(doc) && doc.uri.toString() === resource.toString()); if (matchingDocument) { - this._documentCache.set(resource, matchingDocument); + this.#documentCache.set(resource, matchingDocument); return matchingDocument; } @@ -69,9 +69,9 @@ export class VsCodeMdWorkspace extends Disposable { const bytes = await vscode.workspace.fs.readFile(resource); // We assume that markdown is in UTF-8 - const text = this._utf8Decoder.decode(bytes); + const text = this.#utf8Decoder.decode(bytes); const doc = new InMemoryDocument(resource, text, 0); - this._documentCache.set(resource, doc); + this.#documentCache.set(resource, doc); return doc; } catch { return undefined; diff --git a/extensions/markdown-language-features/src/commandManager.ts b/extensions/markdown-language-features/src/commandManager.ts index ae2c4985066..0563db020c7 100644 --- a/extensions/markdown-language-features/src/commandManager.ts +++ b/extensions/markdown-language-features/src/commandManager.ts @@ -12,27 +12,27 @@ export interface Command { } export class CommandManager { - private readonly _commands = new Map(); + readonly #commands = new Map(); public dispose() { - for (const registration of this._commands.values()) { + for (const registration of this.#commands.values()) { registration.dispose(); } - this._commands.clear(); + this.#commands.clear(); } public register(command: T): vscode.Disposable { - this._registerCommand(command.id, command.execute, command); + this.#registerCommand(command.id, command.execute, command); return new vscode.Disposable(() => { - this._commands.delete(command.id); + this.#commands.delete(command.id); }); } - private _registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any) { - if (this._commands.has(id)) { + #registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any) { + if (this.#commands.has(id)) { return; } - this._commands.set(id, vscode.commands.registerCommand(id, impl, thisArg)); + this.#commands.set(id, vscode.commands.registerCommand(id, impl, thisArg)); } } diff --git a/extensions/markdown-language-features/src/commands/copyImage.ts b/extensions/markdown-language-features/src/commands/copyImage.ts index 86fd349c730..09a683ecfb2 100644 --- a/extensions/markdown-language-features/src/commands/copyImage.ts +++ b/extensions/markdown-language-features/src/commands/copyImage.ts @@ -10,12 +10,16 @@ import { MarkdownPreviewManager } from '../preview/previewManager'; export class CopyImageCommand implements Command { public readonly id = '_markdown.copyImage'; + readonly #webviewManager: MarkdownPreviewManager; + public constructor( - private readonly _webviewManager: MarkdownPreviewManager, - ) { } + webviewManager: MarkdownPreviewManager, + ) { + this.#webviewManager = webviewManager; + } public execute(args: { id: string; resource: string }) { const source = vscode.Uri.parse(args.resource); - this._webviewManager.findPreview(source)?.copyImage(args.id); + this.#webviewManager.findPreview(source)?.copyImage(args.id); } } diff --git a/extensions/markdown-language-features/src/commands/openImage.ts b/extensions/markdown-language-features/src/commands/openImage.ts index 64b1831df0d..4a121fd6989 100644 --- a/extensions/markdown-language-features/src/commands/openImage.ts +++ b/extensions/markdown-language-features/src/commands/openImage.ts @@ -10,12 +10,16 @@ import { MarkdownPreviewManager } from '../preview/previewManager'; export class OpenImageCommand implements Command { public readonly id = '_markdown.openImage'; + readonly #webviewManager: MarkdownPreviewManager; + public constructor( - private readonly _webviewManager: MarkdownPreviewManager, - ) { } + webviewManager: MarkdownPreviewManager, + ) { + this.#webviewManager = webviewManager; + } public execute(args: { resource: string; imageSource: string }) { const source = vscode.Uri.parse(args.resource); - this._webviewManager.openDocumentLink(args.imageSource, source); + this.#webviewManager.openDocumentLink(args.imageSource, source); } } diff --git a/extensions/markdown-language-features/src/commands/refreshPreview.ts b/extensions/markdown-language-features/src/commands/refreshPreview.ts index a94fa797462..52f320098b7 100644 --- a/extensions/markdown-language-features/src/commands/refreshPreview.ts +++ b/extensions/markdown-language-features/src/commands/refreshPreview.ts @@ -10,13 +10,19 @@ import { MarkdownPreviewManager } from '../preview/previewManager'; export class RefreshPreviewCommand implements Command { public readonly id = 'markdown.preview.refresh'; + readonly #webviewManager: MarkdownPreviewManager; + readonly #engine: MarkdownItEngine; + public constructor( - private readonly _webviewManager: MarkdownPreviewManager, - private readonly _engine: MarkdownItEngine - ) { } + webviewManager: MarkdownPreviewManager, + engine: MarkdownItEngine + ) { + this.#webviewManager = webviewManager; + this.#engine = engine; + } public execute() { - this._engine.cleanCache(); - this._webviewManager.refresh(); + this.#engine.cleanCache(); + this.#webviewManager.refresh(); } } diff --git a/extensions/markdown-language-features/src/commands/reloadPlugins.ts b/extensions/markdown-language-features/src/commands/reloadPlugins.ts index 16be408bbef..5d410780a2b 100644 --- a/extensions/markdown-language-features/src/commands/reloadPlugins.ts +++ b/extensions/markdown-language-features/src/commands/reloadPlugins.ts @@ -10,14 +10,20 @@ import { MarkdownPreviewManager } from '../preview/previewManager'; export class ReloadPlugins implements Command { public readonly id = 'markdown.api.reloadPlugins'; + readonly #webviewManager: MarkdownPreviewManager; + readonly #engine: MarkdownItEngine; + public constructor( - private readonly _webviewManager: MarkdownPreviewManager, - private readonly _engine: MarkdownItEngine, - ) { } + webviewManager: MarkdownPreviewManager, + engine: MarkdownItEngine, + ) { + this.#webviewManager = webviewManager; + this.#engine = engine; + } public execute(): void { - this._engine.reloadPlugins(); - this._engine.cleanCache(); - this._webviewManager.refresh(); + this.#engine.reloadPlugins(); + this.#engine.cleanCache(); + this.#webviewManager.refresh(); } } diff --git a/extensions/markdown-language-features/src/commands/renderDocument.ts b/extensions/markdown-language-features/src/commands/renderDocument.ts index ccefddedbd2..ffcbab6d41a 100644 --- a/extensions/markdown-language-features/src/commands/renderDocument.ts +++ b/extensions/markdown-language-features/src/commands/renderDocument.ts @@ -10,11 +10,15 @@ import { ITextDocument } from '../types/textDocument'; export class RenderDocument implements Command { public readonly id = 'markdown.api.render'; + readonly #engine: MarkdownItEngine; + public constructor( - private readonly _engine: MarkdownItEngine - ) { } + engine: MarkdownItEngine + ) { + this.#engine = engine; + } public async execute(document: ITextDocument | string): Promise { - return (await (this._engine.render(document))).html; + return (await (this.#engine.render(document))).html; } } diff --git a/extensions/markdown-language-features/src/commands/showPreview.ts b/extensions/markdown-language-features/src/commands/showPreview.ts index d5d430ade0e..4d59062c1a1 100644 --- a/extensions/markdown-language-features/src/commands/showPreview.ts +++ b/extensions/markdown-language-features/src/commands/showPreview.ts @@ -53,14 +53,20 @@ async function showPreview( export class ShowPreviewCommand implements Command { public readonly id = 'markdown.showPreview'; + readonly #webviewManager: MarkdownPreviewManager; + readonly #telemetryReporter: TelemetryReporter; + public constructor( - private readonly _webviewManager: MarkdownPreviewManager, - private readonly _telemetryReporter: TelemetryReporter - ) { } + webviewManager: MarkdownPreviewManager, + telemetryReporter: TelemetryReporter + ) { + this.#webviewManager = webviewManager; + this.#telemetryReporter = telemetryReporter; + } public execute(mainUri?: vscode.Uri, allUris?: vscode.Uri[], previewSettings?: DynamicPreviewSettings) { for (const uri of Array.isArray(allUris) ? allUris : [mainUri]) { - showPreview(this._webviewManager, this._telemetryReporter, uri, { + showPreview(this.#webviewManager, this.#telemetryReporter, uri, { sideBySide: false, locked: previewSettings?.locked }); @@ -71,13 +77,19 @@ export class ShowPreviewCommand implements Command { export class ShowPreviewToSideCommand implements Command { public readonly id = 'markdown.showPreviewToSide'; + readonly #webviewManager: MarkdownPreviewManager; + readonly #telemetryReporter: TelemetryReporter; + public constructor( - private readonly _webviewManager: MarkdownPreviewManager, - private readonly _telemetryReporter: TelemetryReporter - ) { } + webviewManager: MarkdownPreviewManager, + telemetryReporter: TelemetryReporter + ) { + this.#webviewManager = webviewManager; + this.#telemetryReporter = telemetryReporter; + } public execute(uri?: vscode.Uri, previewSettings?: DynamicPreviewSettings) { - showPreview(this._webviewManager, this._telemetryReporter, uri, { + showPreview(this.#webviewManager, this.#telemetryReporter, uri, { sideBySide: true, locked: previewSettings?.locked }); @@ -88,13 +100,19 @@ export class ShowPreviewToSideCommand implements Command { export class ShowLockedPreviewToSideCommand implements Command { public readonly id = 'markdown.showLockedPreviewToSide'; + readonly #webviewManager: MarkdownPreviewManager; + readonly #telemetryReporter: TelemetryReporter; + public constructor( - private readonly _webviewManager: MarkdownPreviewManager, - private readonly _telemetryReporter: TelemetryReporter - ) { } + webviewManager: MarkdownPreviewManager, + telemetryReporter: TelemetryReporter + ) { + this.#webviewManager = webviewManager; + this.#telemetryReporter = telemetryReporter; + } public execute(uri?: vscode.Uri) { - showPreview(this._webviewManager, this._telemetryReporter, uri, { + showPreview(this.#webviewManager, this.#telemetryReporter, uri, { sideBySide: true, locked: true }); diff --git a/extensions/markdown-language-features/src/commands/showPreviewSecuritySelector.ts b/extensions/markdown-language-features/src/commands/showPreviewSecuritySelector.ts index 7ea5a4079ed..fb6cd9ce9e7 100644 --- a/extensions/markdown-language-features/src/commands/showPreviewSecuritySelector.ts +++ b/extensions/markdown-language-features/src/commands/showPreviewSecuritySelector.ts @@ -12,19 +12,25 @@ import { isMarkdownFile } from '../util/file'; export class ShowPreviewSecuritySelectorCommand implements Command { public readonly id = 'markdown.showPreviewSecuritySelector'; + readonly #previewSecuritySelector: PreviewSecuritySelector; + readonly #previewManager: MarkdownPreviewManager; + public constructor( - private readonly _previewSecuritySelector: PreviewSecuritySelector, - private readonly _previewManager: MarkdownPreviewManager - ) { } + previewSecuritySelector: PreviewSecuritySelector, + previewManager: MarkdownPreviewManager + ) { + this.#previewSecuritySelector = previewSecuritySelector; + this.#previewManager = previewManager; + } public execute(resource: string | undefined) { - if (this._previewManager.activePreviewResource) { - this._previewSecuritySelector.showSecuritySelectorForResource(this._previewManager.activePreviewResource); + if (this.#previewManager.activePreviewResource) { + this.#previewSecuritySelector.showSecuritySelectorForResource(this.#previewManager.activePreviewResource); } else if (resource) { const source = vscode.Uri.parse(resource); - this._previewSecuritySelector.showSecuritySelectorForResource(source.query ? vscode.Uri.parse(source.query) : source); + this.#previewSecuritySelector.showSecuritySelectorForResource(source.query ? vscode.Uri.parse(source.query) : source); } else if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document)) { - this._previewSecuritySelector.showSecuritySelectorForResource(vscode.window.activeTextEditor.document.uri); + this.#previewSecuritySelector.showSecuritySelectorForResource(vscode.window.activeTextEditor.document.uri); } } } diff --git a/extensions/markdown-language-features/src/commands/showSource.ts b/extensions/markdown-language-features/src/commands/showSource.ts index 87d6b21ec68..3a6bb3e0e20 100644 --- a/extensions/markdown-language-features/src/commands/showSource.ts +++ b/extensions/markdown-language-features/src/commands/showSource.ts @@ -10,12 +10,16 @@ import { MarkdownPreviewManager } from '../preview/previewManager'; export class ShowSourceCommand implements Command { public readonly id = 'markdown.showSource'; + readonly #previewManager: MarkdownPreviewManager; + public constructor( - private readonly _previewManager: MarkdownPreviewManager - ) { } + previewManager: MarkdownPreviewManager + ) { + this.#previewManager = previewManager; + } public execute() { - const { activePreviewResource, activePreviewResourceColumn } = this._previewManager; + const { activePreviewResource, activePreviewResourceColumn } = this.#previewManager; if (activePreviewResource && activePreviewResourceColumn) { return vscode.workspace.openTextDocument(activePreviewResource).then(document => { return vscode.window.showTextDocument(document, activePreviewResourceColumn); diff --git a/extensions/markdown-language-features/src/commands/toggleLock.ts b/extensions/markdown-language-features/src/commands/toggleLock.ts index 9975d4872bb..0bc4656d08f 100644 --- a/extensions/markdown-language-features/src/commands/toggleLock.ts +++ b/extensions/markdown-language-features/src/commands/toggleLock.ts @@ -9,11 +9,15 @@ import { MarkdownPreviewManager } from '../preview/previewManager'; export class ToggleLockCommand implements Command { public readonly id = 'markdown.preview.toggleLock'; + readonly #previewManager: MarkdownPreviewManager; + public constructor( - private readonly _previewManager: MarkdownPreviewManager - ) { } + previewManager: MarkdownPreviewManager + ) { + this.#previewManager = previewManager; + } public execute() { - this._previewManager.toggleLock(); + this.#previewManager.toggleLock(); } } diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/dropOrPasteResource.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/dropOrPasteResource.ts index 7791d6b19e4..e59a207487d 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/dropOrPasteResource.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/dropOrPasteResource.ts @@ -36,14 +36,18 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v ...Object.values(rootMediaMimesTypes).map(type => `${type}/*`), ]; - private readonly _yieldTo = [ + readonly #yieldTo = [ vscode.DocumentDropOrPasteEditKind.Text, vscode.DocumentDropOrPasteEditKind.Empty.append('markdown', 'link', 'image', 'attachment'), // Prefer notebook attachments ]; + readonly #parser: IMdParser; + constructor( - private readonly _parser: IMdParser, - ) { } + parser: IMdParser, + ) { + this.#parser = parser; + } public async provideDocumentDropEdits( document: vscode.TextDocument, @@ -51,8 +55,8 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken, ): Promise { - const edit = await this._createEdit(document, [new vscode.Range(position, position)], dataTransfer, { - insert: this._getEnabled(document, 'editor.drop.enabled'), + const edit = await this.#createEdit(document, [new vscode.Range(position, position)], dataTransfer, { + insert: this.#getEnabled(document, 'editor.drop.enabled'), copyIntoWorkspace: vscode.workspace.getConfiguration('markdown', document).get('editor.drop.copyIntoWorkspace', CopyFilesSettings.MediaFiles) }, undefined, token); @@ -64,7 +68,7 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v dropEdit.title = edit.label; dropEdit.kind = edit.kind; dropEdit.additionalEdit = edit.additionalEdits; - dropEdit.yieldTo = [...this._yieldTo, ...edit.yieldTo]; + dropEdit.yieldTo = [...this.#yieldTo, ...edit.yieldTo]; return dropEdit; } @@ -75,8 +79,8 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v context: vscode.DocumentPasteEditContext, token: vscode.CancellationToken, ): Promise { - const edit = await this._createEdit(document, ranges, dataTransfer, { - insert: this._getEnabled(document, 'editor.paste.enabled'), + const edit = await this.#createEdit(document, ranges, dataTransfer, { + insert: this.#getEnabled(document, 'editor.paste.enabled'), copyIntoWorkspace: vscode.workspace.getConfiguration('markdown', document).get('editor.paste.copyIntoWorkspace', CopyFilesSettings.MediaFiles) }, context, token); @@ -86,11 +90,11 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v const pasteEdit = new vscode.DocumentPasteEdit(edit.snippet, edit.label, edit.kind); pasteEdit.additionalEdit = edit.additionalEdits; - pasteEdit.yieldTo = [...this._yieldTo, ...edit.yieldTo]; + pasteEdit.yieldTo = [...this.#yieldTo, ...edit.yieldTo]; return [pasteEdit]; } - private _getEnabled(document: vscode.TextDocument, settingName: string): InsertMarkdownLink { + #getEnabled(document: vscode.TextDocument, settingName: string): InsertMarkdownLink { const setting = vscode.workspace.getConfiguration('markdown', document).get(settingName, true); // Convert old boolean values to new enum setting if (setting === false) { @@ -102,7 +106,7 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v } } - private async _createEdit( + async #createEdit( document: vscode.TextDocument, ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, @@ -117,27 +121,27 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v return; } - let edit = await this._createEditForMediaFiles(document, dataTransfer, settings.copyIntoWorkspace, token); + let edit = await this.#createEditForMediaFiles(document, dataTransfer, settings.copyIntoWorkspace, token); if (token.isCancellationRequested) { return; } if (!edit) { - edit = await this._createEditFromUriListData(document, ranges, dataTransfer, context, token); + edit = await this.#createEditFromUriListData(document, ranges, dataTransfer, context, token); } if (!edit || token.isCancellationRequested) { return; } - if (!(await shouldInsertMarkdownLinkByDefault(this._parser, document, settings.insert, ranges, token))) { + if (!(await shouldInsertMarkdownLinkByDefault(this.#parser, document, settings.insert, ranges, token))) { edit.yieldTo.push(vscode.DocumentDropOrPasteEditKind.Empty.append('uri')); } return edit; } - private async _createEditFromUriListData( + async #createEditFromUriListData( document: vscode.TextDocument, ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, @@ -194,7 +198,7 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v * * This tries copying files outside of the workspace into the workspace. */ - private async _createEditForMediaFiles( + async #createEditForMediaFiles( document: vscode.TextDocument, dataTransfer: vscode.DataTransfer, copyIntoWorkspace: CopyFilesSettings, diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/newFilePathGenerator.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/newFilePathGenerator.ts index 1625977a72c..fe9030704c1 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/newFilePathGenerator.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/newFilePathGenerator.ts @@ -12,7 +12,7 @@ import { CopyFileConfiguration, getCopyFileConfiguration, parseGlob, resolveCopy export class NewFilePathGenerator { - private readonly _usedPaths = new Set(); + readonly #usedPaths = new Set(); async getNewFilePath( document: vscode.TextDocument, @@ -33,13 +33,13 @@ export class NewFilePathGenerator { const name = i === 0 ? baseName : `${baseName}-${i}`; const uri = vscode.Uri.joinPath(root, name + ext); - if (this._wasPathAlreadyUsed(uri)) { + if (this.#wasPathAlreadyUsed(uri)) { continue; } // Try overwriting if it already exists if (config.overwriteBehavior === 'overwrite') { - this._usedPaths.add(uri.toString()); + this.#usedPaths.add(uri.toString()); return { uri, overwrite: true }; } @@ -47,17 +47,17 @@ export class NewFilePathGenerator { try { await vscode.workspace.fs.stat(uri); } catch { - if (!this._wasPathAlreadyUsed(uri)) { + if (!this.#wasPathAlreadyUsed(uri)) { // Does not exist - this._usedPaths.add(uri.toString()); + this.#usedPaths.add(uri.toString()); return { uri, overwrite: false }; } } } } - private _wasPathAlreadyUsed(uri: vscode.Uri) { - return this._usedPaths.has(uri.toString()); + #wasPathAlreadyUsed(uri: vscode.Uri) { + return this.#usedPaths.has(uri.toString()); } } diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts index a947216fe32..faad54e10c3 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts @@ -21,9 +21,13 @@ class PasteUrlEditProvider implements vscode.DocumentPasteEditProvider { public static readonly pasteMimeTypes = [Mime.textPlain]; + readonly #parser: IMdParser; + constructor( - private readonly _parser: IMdParser, - ) { } + parser: IMdParser, + ) { + this.#parser = parser; + } async provideDocumentPasteEdits( document: vscode.TextDocument, @@ -64,7 +68,7 @@ class PasteUrlEditProvider implements vscode.DocumentPasteEditProvider { workspaceEdit.set(document.uri, edit.edits); pasteEdit.additionalEdit = workspaceEdit; - if (!(await shouldInsertMarkdownLinkByDefault(this._parser, document, pasteUrlSetting, ranges, token))) { + if (!(await shouldInsertMarkdownLinkByDefault(this.#parser, document, pasteUrlSetting, ranges, token))) { pasteEdit.yieldTo = [ vscode.DocumentDropOrPasteEditKind.Text, vscode.DocumentDropOrPasteEditKind.Empty.append('uri') diff --git a/extensions/markdown-language-features/src/languageFeatures/diagnostics.ts b/extensions/markdown-language-features/src/languageFeatures/diagnostics.ts index 8df16f4dcc6..871333cf4a4 100644 --- a/extensions/markdown-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/markdown-language-features/src/languageFeatures/diagnostics.ts @@ -19,18 +19,18 @@ export enum DiagnosticCode { class AddToIgnoreLinksQuickFixProvider implements vscode.CodeActionProvider { - private static readonly _addToIgnoreLinksCommandId = '_markdown.addToIgnoreLinks'; + static readonly #addToIgnoreLinksCommandId = '_markdown.addToIgnoreLinks'; - private static readonly _metadata: vscode.CodeActionProviderMetadata = { + static readonly #metadata: vscode.CodeActionProviderMetadata = { providedCodeActionKinds: [ vscode.CodeActionKind.QuickFix ], }; public static register(selector: vscode.DocumentSelector, commandManager: CommandManager): vscode.Disposable { - const reg = vscode.languages.registerCodeActionsProvider(selector, new AddToIgnoreLinksQuickFixProvider(), AddToIgnoreLinksQuickFixProvider._metadata); + const reg = vscode.languages.registerCodeActionsProvider(selector, new AddToIgnoreLinksQuickFixProvider(), AddToIgnoreLinksQuickFixProvider.#metadata); const commandReg = commandManager.register({ - id: AddToIgnoreLinksQuickFixProvider._addToIgnoreLinksCommandId, + id: AddToIgnoreLinksQuickFixProvider.#addToIgnoreLinksCommandId, execute(resource: vscode.Uri, path: string) { const settingId = 'validate.ignoredLinks'; const config = vscode.workspace.getConfiguration('markdown', resource); @@ -58,7 +58,7 @@ class AddToIgnoreLinksQuickFixProvider implements vscode.CodeActionProvider { vscode.CodeActionKind.QuickFix); fix.command = { - command: AddToIgnoreLinksQuickFixProvider._addToIgnoreLinksCommandId, + command: AddToIgnoreLinksQuickFixProvider.#addToIgnoreLinksCommandId, title: '', arguments: [document.uri, hrefText], }; diff --git a/extensions/markdown-language-features/src/languageFeatures/fileReferences.ts b/extensions/markdown-language-features/src/languageFeatures/fileReferences.ts index bda8b721e8b..23a2ed9e770 100644 --- a/extensions/markdown-language-features/src/languageFeatures/fileReferences.ts +++ b/extensions/markdown-language-features/src/languageFeatures/fileReferences.ts @@ -13,9 +13,13 @@ export class FindFileReferencesCommand implements Command { public readonly id = 'markdown.findAllFileReferences'; + readonly #client: MdLanguageClient; + constructor( - private readonly _client: MdLanguageClient, - ) { } + client: MdLanguageClient, + ) { + this.#client = client; + } public async execute(resource?: vscode.Uri) { resource ??= vscode.window.activeTextEditor?.document.uri; @@ -28,7 +32,7 @@ export class FindFileReferencesCommand implements Command { location: vscode.ProgressLocation.Window, title: vscode.l10n.t("Finding file references") }, async (_progress, token) => { - const locations = (await this._client.getReferencesToFileInWorkspace(resource, token)).map(loc => { + const locations = (await this.#client.getReferencesToFileInWorkspace(resource, token)).map(loc => { return new vscode.Location(vscode.Uri.parse(loc.uri), convertRange(loc.range)); }); diff --git a/extensions/markdown-language-features/src/languageFeatures/linkUpdater.ts b/extensions/markdown-language-features/src/languageFeatures/linkUpdater.ts index 5d42a033842..d912caa9060 100644 --- a/extensions/markdown-language-features/src/languageFeatures/linkUpdater.ts +++ b/extensions/markdown-language-features/src/languageFeatures/linkUpdater.ts @@ -33,46 +33,48 @@ interface RenameAction { class UpdateLinksOnFileRenameHandler extends Disposable { - private readonly _delayer = new Delayer(50); - private readonly _pendingRenames = new Set(); + readonly #delayer = new Delayer(50); + readonly #pendingRenames = new Set(); + readonly #client: MdLanguageClient; public constructor( - private readonly _client: MdLanguageClient, + client: MdLanguageClient, ) { super(); + this.#client = client; this._register(vscode.workspace.onDidRenameFiles(async (e) => { await Promise.all(e.files.map(async (rename) => { - if (await this._shouldParticipateInLinkUpdate(rename.newUri)) { - this._pendingRenames.add(rename); + if (await this.#shouldParticipateInLinkUpdate(rename.newUri)) { + this.#pendingRenames.add(rename); } })); - if (this._pendingRenames.size) { - this._delayer.trigger(() => { + if (this.#pendingRenames.size) { + this.#delayer.trigger(() => { vscode.window.withProgress({ location: vscode.ProgressLocation.Window, title: vscode.l10n.t("Checking for Markdown links to update") - }, () => this._flushRenames()); + }, () => this.#flushRenames()); }); } })); } - private async _flushRenames(): Promise { - const renames = Array.from(this._pendingRenames); - this._pendingRenames.clear(); + async #flushRenames(): Promise { + const renames = Array.from(this.#pendingRenames); + this.#pendingRenames.clear(); - const result = await this._getEditsForFileRename(renames, noopToken); + const result = await this.#getEditsForFileRename(renames, noopToken); if (result?.edit.size) { - if (await this._confirmActionWithUser(result.resourcesBeingRenamed)) { + if (await this.#confirmActionWithUser(result.resourcesBeingRenamed)) { await vscode.workspace.applyEdit(result.edit); } } } - private async _confirmActionWithUser(newResources: readonly vscode.Uri[]): Promise { + async #confirmActionWithUser(newResources: readonly vscode.Uri[]): Promise { if (!newResources.length) { return false; } @@ -81,7 +83,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable { const setting = config.get(settingNames.enabled); switch (setting) { case UpdateLinksOnFileMoveSetting.Prompt: - return this._promptUser(newResources); + return this.#promptUser(newResources); case UpdateLinksOnFileMoveSetting.Always: return true; case UpdateLinksOnFileMoveSetting.Never: @@ -89,7 +91,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable { return false; } } - private async _shouldParticipateInLinkUpdate(newUri: vscode.Uri): Promise { + async #shouldParticipateInLinkUpdate(newUri: vscode.Uri): Promise { const config = vscode.workspace.getConfiguration('markdown', newUri); const setting = config.get(settingNames.enabled); if (setting === UpdateLinksOnFileMoveSetting.Never) { @@ -113,7 +115,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable { return false; } - private async _promptUser(newResources: readonly vscode.Uri[]): Promise { + async #promptUser(newResources: readonly vscode.Uri[]): Promise { if (!newResources.length) { return false; } @@ -138,7 +140,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable { const choice = await vscode.window.showInformationMessage( newResources.length === 1 ? vscode.l10n.t("Update Markdown links for '{0}'?", Utils.basename(newResources[0])) - : this._getConfirmMessage(vscode.l10n.t("Update Markdown links for the following {0} files?", newResources.length), newResources), { + : this.#getConfirmMessage(vscode.l10n.t("Update Markdown links for the following {0} files?", newResources.length), newResources), { modal: true, }, rejectItem, acceptItem, alwaysItem, neverItem); @@ -154,7 +156,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable { config.update( settingNames.enabled, UpdateLinksOnFileMoveSetting.Always, - this._getConfigTargetScope(config, settingNames.enabled)); + this.#getConfigTargetScope(config, settingNames.enabled)); return true; } case neverItem: { @@ -162,7 +164,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable { config.update( settingNames.enabled, UpdateLinksOnFileMoveSetting.Never, - this._getConfigTargetScope(config, settingNames.enabled)); + this.#getConfigTargetScope(config, settingNames.enabled)); return false; } default: { @@ -171,8 +173,8 @@ class UpdateLinksOnFileRenameHandler extends Disposable { } } - private async _getEditsForFileRename(renames: readonly RenameAction[], token: vscode.CancellationToken): Promise<{ edit: vscode.WorkspaceEdit; resourcesBeingRenamed: vscode.Uri[] } | undefined> { - const result = await this._client.getEditForFileRenames(renames.map(rename => ({ oldUri: rename.oldUri.toString(), newUri: rename.newUri.toString() })), token); + async #getEditsForFileRename(renames: readonly RenameAction[], token: vscode.CancellationToken): Promise<{ edit: vscode.WorkspaceEdit; resourcesBeingRenamed: vscode.Uri[] } | undefined> { + const result = await this.#client.getEditForFileRenames(renames.map(rename => ({ oldUri: rename.oldUri.toString(), newUri: rename.newUri.toString() })), token); if (!result?.edit.documentChanges?.length) { return undefined; } @@ -192,7 +194,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable { }; } - private _getConfirmMessage(start: string, resourcesToConfirm: readonly vscode.Uri[]): string { + #getConfirmMessage(start: string, resourcesToConfirm: readonly vscode.Uri[]): string { const MAX_CONFIRM_FILES = 10; const paths = [start]; @@ -211,7 +213,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable { return paths.join('\n'); } - private _getConfigTargetScope(config: vscode.WorkspaceConfiguration, settingsName: string): vscode.ConfigurationTarget { + #getConfigTargetScope(config: vscode.WorkspaceConfiguration, settingsName: string): vscode.ConfigurationTarget { const inspected = config.inspect(settingsName); if (inspected?.workspaceFolderValue) { return vscode.ConfigurationTarget.WorkspaceFolder; diff --git a/extensions/markdown-language-features/src/languageFeatures/updateLinksOnPaste.ts b/extensions/markdown-language-features/src/languageFeatures/updateLinksOnPaste.ts index f8a7128eb05..b27a869db0e 100644 --- a/extensions/markdown-language-features/src/languageFeatures/updateLinksOnPaste.ts +++ b/extensions/markdown-language-features/src/languageFeatures/updateLinksOnPaste.ts @@ -13,16 +13,20 @@ class UpdatePastedLinksEditProvider implements vscode.DocumentPasteEditProvider public static readonly metadataMime = 'application/vnd.vscode.markdown.updatelinks.metadata'; + readonly #client: MdLanguageClient; + constructor( - private readonly _client: MdLanguageClient, - ) { } + client: MdLanguageClient, + ) { + this.#client = client; + } async prepareDocumentPaste(document: vscode.TextDocument, ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise { - if (!this._isEnabled(document)) { + if (!this.#isEnabled(document)) { return; } - const metadata = await this._client.prepareUpdatePastedLinks(document.uri, ranges, token); + const metadata = await this.#client.prepareUpdatePastedLinks(document.uri, ranges, token); if (token.isCancellationRequested) { return; } @@ -37,7 +41,7 @@ class UpdatePastedLinksEditProvider implements vscode.DocumentPasteEditProvider context: vscode.DocumentPasteEditContext, token: vscode.CancellationToken, ): Promise { - if (!this._isEnabled(document)) { + if (!this.#isEnabled(document)) { return; } @@ -56,7 +60,7 @@ class UpdatePastedLinksEditProvider implements vscode.DocumentPasteEditProvider // - copy empty line // - Copy with multiple cursors and paste into multiple locations // - ... - const edits = await this._client.getUpdatePastedLinksEdit(document.uri, ranges.map(x => new vscode.TextEdit(x, text)), metadata, token); + const edits = await this.#client.getUpdatePastedLinksEdit(document.uri, ranges.map(x => new vscode.TextEdit(x, text)), metadata, token); if (!edits?.length || token.isCancellationRequested) { return; } @@ -73,7 +77,7 @@ class UpdatePastedLinksEditProvider implements vscode.DocumentPasteEditProvider return [pasteEdit]; } - private _isEnabled(document: vscode.TextDocument): boolean { + #isEnabled(document: vscode.TextDocument): boolean { return vscode.workspace.getConfiguration('markdown', document.uri).get('editor.updateLinksOnPaste.enabled', true); } } diff --git a/extensions/markdown-language-features/src/logging.ts b/extensions/markdown-language-features/src/logging.ts index b5ea76f3608..30839d8c756 100644 --- a/extensions/markdown-language-features/src/logging.ts +++ b/extensions/markdown-language-features/src/logging.ts @@ -12,11 +12,11 @@ export interface ILogger { } export class VsCodeOutputLogger extends Disposable implements ILogger { - private _outputChannelValue?: vscode.LogOutputChannel; + #outputChannelValue?: vscode.LogOutputChannel; - private get _outputChannel() { - this._outputChannelValue ??= this._register(vscode.window.createOutputChannel('Markdown', { log: true })); - return this._outputChannelValue; + get #outputChannel() { + this.#outputChannelValue ??= this._register(vscode.window.createOutputChannel('Markdown', { log: true })); + return this.#outputChannelValue; } constructor() { @@ -24,6 +24,6 @@ export class VsCodeOutputLogger extends Disposable implements ILogger { } public trace(title: string, message: string, data?: any): void { - this._outputChannel.trace(`${title}: ${message}`, ...(data ? [JSON.stringify(data, null, 4)] : [])); + this.#outputChannel.trace(`${title}: ${message}`, ...(data ? [JSON.stringify(data, null, 4)] : [])); } } diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index 0f4c7eb6717..4ed3186c380 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -44,37 +44,37 @@ const pluginSourceMap: MarkdownIt.PluginSimple = (md): void => { type MarkdownItConfig = Readonly>>; class TokenCache { - private _cachedDocument?: { + #cachedDocument?: { readonly uri: vscode.Uri; readonly version: number; readonly config: MarkdownItConfig; }; - private _tokens?: MarkdownIt.Token[]; + #tokens?: MarkdownIt.Token[]; public tryGetCached(document: ITextDocument, config: MarkdownItConfig): MarkdownIt.Token[] | undefined { - if (this._cachedDocument - && this._cachedDocument.uri.toString() === document.uri.toString() - && document.version >= 0 && this._cachedDocument.version === document.version - && this._cachedDocument.config.breaks === config.breaks - && this._cachedDocument.config.linkify === config.linkify + if (this.#cachedDocument + && this.#cachedDocument.uri.toString() === document.uri.toString() + && document.version >= 0 && this.#cachedDocument.version === document.version + && this.#cachedDocument.config.breaks === config.breaks + && this.#cachedDocument.config.linkify === config.linkify ) { - return this._tokens; + return this.#tokens; } return undefined; } public update(document: ITextDocument, config: MarkdownItConfig, tokens: MarkdownIt.Token[]) { - this._cachedDocument = { + this.#cachedDocument = { uri: document.uri, version: document.version, config, }; - this._tokens = tokens; + this.#tokens = tokens; } public clean(): void { - this._cachedDocument = undefined; - this._tokens = undefined; + this.#cachedDocument = undefined; + this.#tokens = undefined; } } @@ -98,40 +98,45 @@ export interface IMdParser { export class MarkdownItEngine implements IMdParser { - private _md?: Promise; + #md?: Promise; - private readonly _tokenCache = new TokenCache(); + readonly #tokenCache = new TokenCache(); public readonly slugifier: ISlugifier; - public constructor( - private readonly _contributionProvider: MarkdownContributionProvider, - slugifier: ISlugifier, - private readonly _logger: ILogger, - ) { - this.slugifier = slugifier; + readonly #contributionProvider: MarkdownContributionProvider; + readonly #logger: ILogger; - _contributionProvider.onContributionsChanged(() => { + public constructor( + contributionProvider: MarkdownContributionProvider, + slugifier: ISlugifier, + logger: ILogger, + ) { + this.#contributionProvider = contributionProvider; + this.slugifier = slugifier; + this.#logger = logger; + + contributionProvider.onContributionsChanged(() => { // Markdown plugin contributions may have changed - this._md = undefined; - this._tokenCache.clean(); + this.#md = undefined; + this.#tokenCache.clean(); }); } public async getEngine(resource: vscode.Uri | undefined): Promise { - const config = this._getConfig(resource); - return this._getEngine(config); + const config = this.#getConfig(resource); + return this.#getEngine(config); } - private async _getEngine(config: MarkdownItConfig): Promise { - if (!this._md) { - this._md = (async () => { + async #getEngine(config: MarkdownItConfig): Promise { + if (!this.#md) { + this.#md = (async () => { const markdownIt = await import('markdown-it'); let md: MarkdownIt = markdownIt.default(await getMarkdownOptions(() => md)); md.linkify.set({ fuzzyLink: false }); - for (const plugin of this._contributionProvider.contributions.markdownItPlugins.values()) { + for (const plugin of this.#contributionProvider.contributions.markdownItPlugins.values()) { try { md = (await plugin)(md); } catch (e) { @@ -154,43 +159,43 @@ export class MarkdownItEngine implements IMdParser { alt: ['paragraph', 'reference', 'blockquote', 'list'] }); - this._addImageRenderer(md); - this._addFencedRenderer(md); - this._addLinkNormalizer(md); - this._addLinkValidator(md); - this._addNamedHeaders(md); - this._addLinkRenderer(md); + this.#addImageRenderer(md); + this.#addFencedRenderer(md); + this.#addLinkNormalizer(md); + this.#addLinkValidator(md); + this.#addNamedHeaders(md); + this.#addLinkRenderer(md); md.use(pluginSourceMap); return md; })(); } - const md = await this._md!; + const md = await this.#md!; md.set(config); return md; } public reloadPlugins() { - this._md = undefined; + this.#md = undefined; } - private _tokenizeDocument( + #tokenizeDocument( document: ITextDocument, config: MarkdownItConfig, engine: MarkdownIt ): MarkdownIt.Token[] { - const cached = this._tokenCache.tryGetCached(document, config); + const cached = this.#tokenCache.tryGetCached(document, config); if (cached) { return cached; } - this._logger.trace('MarkdownItEngine', `tokenizeDocument - ${document.uri}`); - const tokens = this._tokenizeString(document.getText(), engine); - this._tokenCache.update(document, config, tokens); + this.#logger.trace('MarkdownItEngine', `tokenizeDocument - ${document.uri}`); + const tokens = this.#tokenizeString(document.getText(), engine); + this.#tokenCache.update(document, config, tokens); return tokens; } - private _tokenizeString(text: string, engine: MarkdownIt) { + #tokenizeString(text: string, engine: MarkdownIt) { const env: RenderEnv = { currentDocument: undefined, containingImages: new Set(), @@ -201,12 +206,12 @@ export class MarkdownItEngine implements IMdParser { } public async render(input: ITextDocument | string, resourceProvider?: WebviewResourceProvider): Promise { - const config = this._getConfig(typeof input === 'string' ? undefined : input.uri); - const engine = await this._getEngine(config); + const config = this.#getConfig(typeof input === 'string' ? undefined : input.uri); + const engine = await this.#getEngine(config); const tokens = typeof input === 'string' - ? this._tokenizeString(input, engine) - : this._tokenizeDocument(input, config, engine); + ? this.#tokenizeString(input, engine) + : this.#tokenizeDocument(input, config, engine); const env: RenderEnv = { containingImages: new Set(), @@ -227,16 +232,16 @@ export class MarkdownItEngine implements IMdParser { } public async tokenize(document: ITextDocument): Promise { - const config = this._getConfig(document.uri); - const engine = await this._getEngine(config); - return this._tokenizeDocument(document, config, engine); + const config = this.#getConfig(document.uri); + const engine = await this.#getEngine(config); + return this.#tokenizeDocument(document, config, engine); } public cleanCache(): void { - this._tokenCache.clean(); + this.#tokenCache.clean(); } - private _getConfig(resource?: vscode.Uri): MarkdownItConfig { + #getConfig(resource?: vscode.Uri): MarkdownItConfig { const config = MarkdownPreviewConfiguration.getForResource(resource ?? null); return { breaks: config.previewLineBreaks, @@ -245,7 +250,7 @@ export class MarkdownItEngine implements IMdParser { }; } - private _addImageRenderer(md: MarkdownIt): void { + #addImageRenderer(md: MarkdownIt): void { const original = md.renderer.rules.image; md.renderer.rules.image = (tokens: MarkdownIt.Token[], idx: number, options, env: RenderEnv, self) => { const token = tokens[idx]; @@ -254,7 +259,7 @@ export class MarkdownItEngine implements IMdParser { env.containingImages?.add(src); if (!token.attrGet('data-src')) { - token.attrSet('src', this._toResourceUri(src, env.currentDocument, env.resourceProvider)); + token.attrSet('src', this.#toResourceUri(src, env.currentDocument, env.resourceProvider)); token.attrSet('data-src', src); } } @@ -267,7 +272,7 @@ export class MarkdownItEngine implements IMdParser { }; } - private _addFencedRenderer(md: MarkdownIt): void { + #addFencedRenderer(md: MarkdownIt): void { const original = md.renderer.rules['fenced']; md.renderer.rules['fenced'] = (tokens: MarkdownIt.Token[], idx: number, options, env, self) => { const token = tokens[idx]; @@ -283,7 +288,7 @@ export class MarkdownItEngine implements IMdParser { }; } - private _addLinkNormalizer(md: MarkdownIt): void { + #addLinkNormalizer(md: MarkdownIt): void { const normalizeLink = md.normalizeLink; md.normalizeLink = (link: string) => { try { @@ -299,7 +304,7 @@ export class MarkdownItEngine implements IMdParser { }; } - private _addLinkValidator(md: MarkdownIt): void { + #addLinkValidator(md: MarkdownIt): void { const validateLink = md.validateLink; md.validateLink = (link: string) => { return validateLink(link) @@ -309,10 +314,10 @@ export class MarkdownItEngine implements IMdParser { }; } - private _addNamedHeaders(md: MarkdownIt): void { + #addNamedHeaders(md: MarkdownIt): void { const original = md.renderer.rules.heading_open; md.renderer.rules.heading_open = (tokens: MarkdownIt.Token[], idx: number, options, env: unknown, self) => { - const title = this._tokenToPlainText(tokens[idx + 1]); + const title = this.#tokenToPlainText(tokens[idx + 1]); const slug = (env as RenderEnv).slugifier ? (env as RenderEnv).slugifier.add(title) : this.slugifier.fromHeading(title); tokens[idx].attrSet('id', slug.value); @@ -324,9 +329,9 @@ export class MarkdownItEngine implements IMdParser { }; } - private _tokenToPlainText(token: MarkdownIt.Token): string { + #tokenToPlainText(token: MarkdownIt.Token): string { if (token.children) { - return token.children.map(x => this._tokenToPlainText(x)).join(''); + return token.children.map(x => this.#tokenToPlainText(x)).join(''); } switch (token.type) { @@ -339,7 +344,7 @@ export class MarkdownItEngine implements IMdParser { } } - private _addLinkRenderer(md: MarkdownIt): void { + #addLinkRenderer(md: MarkdownIt): void { const original = md.renderer.rules.link_open; md.renderer.rules.link_open = (tokens: MarkdownIt.Token[], idx: number, options, env, self) => { @@ -357,7 +362,7 @@ export class MarkdownItEngine implements IMdParser { }; } - private _toResourceUri(href: string, currentDocument: vscode.Uri | undefined, resourceProvider: WebviewResourceProvider | undefined): string { + #toResourceUri(href: string, currentDocument: vscode.Uri | undefined, resourceProvider: WebviewResourceProvider | undefined): string { try { // Support file:// links if (isOfScheme(Schemes.file, href)) { diff --git a/extensions/markdown-language-features/src/markdownExtensions.ts b/extensions/markdown-language-features/src/markdownExtensions.ts index 1357b03d1de..568a0f0b638 100644 --- a/extensions/markdown-language-features/src/markdownExtensions.ts +++ b/extensions/markdown-language-features/src/markdownExtensions.ts @@ -119,36 +119,38 @@ export interface MarkdownContributionProvider { class VSCodeExtensionMarkdownContributionProvider extends Disposable implements MarkdownContributionProvider { - private _contributions?: MarkdownContributions; + #contributions?: MarkdownContributions; + readonly #extensionContext: vscode.ExtensionContext; public constructor( - private readonly _extensionContext: vscode.ExtensionContext, + extensionContext: vscode.ExtensionContext, ) { super(); + this.#extensionContext = extensionContext; this._register(vscode.extensions.onDidChange(() => { - const currentContributions = this._getCurrentContributions(); - const existingContributions = this._contributions || MarkdownContributions.Empty; + const currentContributions = this.#getCurrentContributions(); + const existingContributions = this.#contributions || MarkdownContributions.Empty; if (!MarkdownContributions.equal(existingContributions, currentContributions)) { - this._contributions = currentContributions; - this._onContributionsChanged.fire(this); + this.#contributions = currentContributions; + this.#onContributionsChanged.fire(this); } })); } public get extensionUri() { - return this._extensionContext.extensionUri; + return this.#extensionContext.extensionUri; } - private readonly _onContributionsChanged = this._register(new vscode.EventEmitter()); - public readonly onContributionsChanged = this._onContributionsChanged.event; + readonly #onContributionsChanged = this._register(new vscode.EventEmitter()); + public readonly onContributionsChanged = this.#onContributionsChanged.event; public get contributions(): MarkdownContributions { - this._contributions ??= this._getCurrentContributions(); - return this._contributions; + this.#contributions ??= this.#getCurrentContributions(); + return this.#contributions; } - private _getCurrentContributions(): MarkdownContributions { + #getCurrentContributions(): MarkdownContributions { return vscode.extensions.all .map(MarkdownContributions.fromExtension) .reduce(MarkdownContributions.merge, MarkdownContributions.Empty); diff --git a/extensions/markdown-language-features/src/preview/documentRenderer.ts b/extensions/markdown-language-features/src/preview/documentRenderer.ts index 61182a24436..f96fce9b745 100644 --- a/extensions/markdown-language-features/src/preview/documentRenderer.ts +++ b/extensions/markdown-language-features/src/preview/documentRenderer.ts @@ -41,16 +41,28 @@ export interface ImageInfo { } export class MdDocumentRenderer { + + readonly #engine: MarkdownItEngine; + readonly #context: vscode.ExtensionContext; + readonly #cspArbiter: ContentSecurityPolicyArbiter; + readonly #contributionProvider: MarkdownContributionProvider; + readonly #logger: ILogger; + constructor( - private readonly _engine: MarkdownItEngine, - private readonly _context: vscode.ExtensionContext, - private readonly _cspArbiter: ContentSecurityPolicyArbiter, - private readonly _contributionProvider: MarkdownContributionProvider, - private readonly _logger: ILogger + engine: MarkdownItEngine, + context: vscode.ExtensionContext, + cspArbiter: ContentSecurityPolicyArbiter, + contributionProvider: MarkdownContributionProvider, + logger: ILogger ) { + this.#engine = engine; + this.#context = context; + this.#cspArbiter = cspArbiter; + this.#contributionProvider = contributionProvider; + this.#logger = logger; this.iconPath = { - dark: vscode.Uri.joinPath(this._context.extensionUri, 'media', 'preview-dark.svg'), - light: vscode.Uri.joinPath(this._context.extensionUri, 'media', 'preview-light.svg'), + dark: vscode.Uri.joinPath(this.#context.extensionUri, 'media', 'preview-dark.svg'), + light: vscode.Uri.joinPath(this.#context.extensionUri, 'media', 'preview-light.svg'), }; } @@ -76,15 +88,15 @@ export class MdDocumentRenderer { scrollPreviewWithEditor: config.scrollPreviewWithEditor, scrollEditorWithPreview: config.scrollEditorWithPreview, doubleClickToSwitchToEditor: config.doubleClickToSwitchToEditor, - disableSecurityWarnings: this._cspArbiter.shouldDisableSecurityWarnings(), + disableSecurityWarnings: this.#cspArbiter.shouldDisableSecurityWarnings(), webviewResourceRoot: resourceProvider.asWebviewUri(markdownDocument.uri).toString(), }; - this._logger.trace('DocumentRenderer', `provideTextDocumentContent - ${markdownDocument.uri}`, initialData); + this.#logger.trace('DocumentRenderer', `provideTextDocumentContent - ${markdownDocument.uri}`, initialData); // Content Security Policy const nonce = generateUuid(); - const csp = this._getCsp(resourceProvider, sourceUri, nonce); + const csp = this.#getCsp(resourceProvider, sourceUri, nonce); const body = await this.renderBody(markdownDocument, resourceProvider); if (token.isCancellationRequested) { @@ -92,7 +104,7 @@ export class MdDocumentRenderer { } const html = ` - + @@ -101,12 +113,12 @@ export class MdDocumentRenderer { data-strings="${escapeAttribute(JSON.stringify(previewStrings))}" data-state="${escapeAttribute(JSON.stringify(state || {}))}" data-initial-md-content="${escapeAttribute(body.html)}"> - - ${this._getStyles(resourceProvider, sourceUri, config, imageInfo)} + + ${this.#getStyles(resourceProvider, sourceUri, config, imageInfo)} - ${this._getScripts(resourceProvider, nonce)} + ${this.#getScripts(resourceProvider, nonce)} `; return { @@ -119,7 +131,7 @@ export class MdDocumentRenderer { markdownDocument: vscode.TextDocument, resourceProvider: WebviewResourceProvider, ): Promise { - const rendered = await this._engine.render(markdownDocument, resourceProvider); + const rendered = await this.#engine.render(markdownDocument, resourceProvider); const html = `
${rendered.html}
`; return { html, @@ -138,13 +150,13 @@ export class MdDocumentRenderer { `; } - private _extensionResourcePath(resourceProvider: WebviewResourceProvider, mediaFile: string): string { + #extensionResourcePath(resourceProvider: WebviewResourceProvider, mediaFile: string): string { const webviewResource = resourceProvider.asWebviewUri( - vscode.Uri.joinPath(this._context.extensionUri, 'media', mediaFile)); + vscode.Uri.joinPath(this.#context.extensionUri, 'media', mediaFile)); return webviewResource.toString(); } - private _fixHref(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, href: string): string { + #fixHref(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, href: string): string { if (!href) { return href; } @@ -168,18 +180,18 @@ export class MdDocumentRenderer { return resourceProvider.asWebviewUri(vscode.Uri.joinPath(uri.Utils.dirname(resource), href)).toString(); } - private _computeCustomStyleSheetIncludes(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, config: MarkdownPreviewConfiguration): string { + #computeCustomStyleSheetIncludes(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, config: MarkdownPreviewConfiguration): string { if (!Array.isArray(config.styles)) { return ''; } const out: string[] = []; for (const style of config.styles) { - out.push(``); + out.push(``); } return out.join('\n'); } - private _getSettingsOverrideStyles(config: MarkdownPreviewConfiguration): string { + #getSettingsOverrideStyles(config: MarkdownPreviewConfiguration): string { return [ config.fontFamily ? `--markdown-font-family: ${config.fontFamily};` : '', isNaN(config.fontSize) ? '' : `--markdown-font-size: ${config.fontSize}px;`, @@ -187,7 +199,7 @@ export class MdDocumentRenderer { ].join(' '); } - private _getImageStabilizerStyles(imageInfo: readonly ImageInfo[]): string { + #getImageStabilizerStyles(imageInfo: readonly ImageInfo[]): string { if (!imageInfo.length) { return ''; } @@ -204,20 +216,20 @@ export class MdDocumentRenderer { return ret; } - private _getStyles(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, config: MarkdownPreviewConfiguration, imageInfo: readonly ImageInfo[]): string { + #getStyles(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, config: MarkdownPreviewConfiguration, imageInfo: readonly ImageInfo[]): string { const baseStyles: string[] = []; - for (const resource of this._contributionProvider.contributions.previewStyles) { + for (const resource of this.#contributionProvider.contributions.previewStyles) { baseStyles.push(``); } return `${baseStyles.join('\n')} - ${this._computeCustomStyleSheetIncludes(resourceProvider, resource, config)} - ${this._getImageStabilizerStyles(imageInfo)}`; + ${this.#computeCustomStyleSheetIncludes(resourceProvider, resource, config)} + ${this.#getImageStabilizerStyles(imageInfo)}`; } - private _getScripts(resourceProvider: WebviewResourceProvider, nonce: string): string { + #getScripts(resourceProvider: WebviewResourceProvider, nonce: string): string { const out: string[] = []; - for (const resource of this._contributionProvider.contributions.previewScripts) { + for (const resource of this.#contributionProvider.contributions.previewScripts) { out.push(`