diff --git a/packages/preferences/src/browser/views/components/preference-markdown-renderer.ts b/packages/preferences/src/browser/views/components/preference-markdown-renderer.ts new file mode 100644 index 0000000000000..231524e99a504 --- /dev/null +++ b/packages/preferences/src/browser/views/components/preference-markdown-renderer.ts @@ -0,0 +1,68 @@ +// ***************************************************************************** +// Copyright (C) 2023 TypeFox and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { inject, injectable } from '@theia/core/shared/inversify'; +import { PreferenceTreeModel } from '../../preference-tree-model'; +import { PreferenceTreeLabelProvider } from '../../util/preference-tree-label-provider'; +import * as markdownit from '@theia/core/shared/markdown-it'; + +@injectable() +export class PreferenceMarkdownRenderer { + + @inject(PreferenceTreeModel) protected readonly model: PreferenceTreeModel; + @inject(PreferenceTreeLabelProvider) protected readonly labelProvider: PreferenceTreeLabelProvider; + + protected _renderer?: markdownit; + + render(text: string): string { + return this.getRenderer().render(text); + } + + renderInline(text: string): string { + return this.getRenderer().renderInline(text); + } + + protected getRenderer(): markdownit { + this._renderer ??= this.buildMarkdownRenderer(); + return this._renderer; + } + + protected buildMarkdownRenderer(): markdownit { + const engine = markdownit(); + const inlineCode = engine.renderer.rules.code_inline; + + engine.renderer.rules.code_inline = (tokens, idx, options, env, self) => { + const token = tokens[idx]; + const content = token.content; + if (content.startsWith('#') && content.endsWith('#')) { + const preferenceId = content.substring(1, content.length - 1); + const preferenceNode = this.model.getNodeFromPreferenceId(preferenceId); + if (preferenceNode) { + let name = this.labelProvider.getName(preferenceNode); + const prefix = this.labelProvider.getPrefix(preferenceNode, true); + if (prefix) { + name = prefix + name; + } + return `${name}`; + } else { + console.warn(`Linked preference "${preferenceId}" not found.`); + } + } + return inlineCode ? inlineCode(tokens, idx, options, env, self) : ''; + }; + return engine; + } +} diff --git a/packages/preferences/src/browser/views/components/preference-node-renderer.ts b/packages/preferences/src/browser/views/components/preference-node-renderer.ts index b034b8a477955..35fff31db55ef 100644 --- a/packages/preferences/src/browser/views/components/preference-node-renderer.ts +++ b/packages/preferences/src/browser/views/components/preference-node-renderer.ts @@ -27,9 +27,9 @@ import { JSONValue } from '@theia/core/shared/@phosphor/coreutils'; import debounce = require('@theia/core/shared/lodash.debounce'); import { PreferenceTreeModel } from '../../preference-tree-model'; import { PreferencesSearchbarWidget } from '../preference-searchbar-widget'; -import * as markdownit from '@theia/core/shared/markdown-it'; import * as DOMPurify from '@theia/core/shared/dompurify'; import URI from '@theia/core/lib/common/uri'; +import { PreferenceMarkdownRenderer } from './preference-markdown-renderer'; export const PreferenceNodeRendererFactory = Symbol('PreferenceNodeRendererFactory'); export type PreferenceNodeRendererFactory = (node: Preference.TreeNode) => PreferenceNodeRenderer; @@ -163,13 +163,13 @@ export abstract class PreferenceLeafNodeRenderer | undefined; protected isModifiedFromDefault = false; - protected markdownRenderer: markdownit; get schema(): PreferenceDataProperty { return this.preferenceNode.preference.data; @@ -179,7 +179,6 @@ export abstract class PreferenceLeafNodeRenderer(this.id, this.scopeTracker.currentScope.uri); } - protected buildMarkdownRenderer(): markdownit { - const engine = markdownit(); - const inlineCode = engine.renderer.rules.code_inline; - - engine.renderer.rules.code_inline = (tokens, idx, options, env, self) => { - const token = tokens[idx]; - const content = token.content; - if (content.startsWith('#') && content.endsWith('#')) { - const preferenceId = content.substring(1, content.length - 1); - const preferenceNode = this.model.getNodeFromPreferenceId(preferenceId); - if (preferenceNode) { - let name = this.labelProvider.getName(preferenceNode); - const prefix = this.labelProvider.getPrefix(preferenceNode, true); - if (prefix) { - name = prefix + name; - } - return `${name}`; - } else { - console.warn(`Linked preference "${preferenceId}" not found. Source: "${this.preferenceNode.preferenceId}"`); - } - } - return inlineCode ? inlineCode(tokens, idx, options, env, self) : ''; - }; - return engine; - } - protected openLink(event: MouseEvent): void { if (event.target instanceof HTMLAnchorElement) { event.preventDefault(); diff --git a/packages/preferences/src/browser/views/preference-widget-bindings.ts b/packages/preferences/src/browser/views/preference-widget-bindings.ts index a2369163124e4..926893f74ad96 100644 --- a/packages/preferences/src/browser/views/preference-widget-bindings.ts +++ b/packages/preferences/src/browser/views/preference-widget-bindings.ts @@ -30,6 +30,7 @@ import { import { PreferenceNumberInputRenderer, PreferenceNumberInputRendererContribution } from './components/preference-number-input'; import { PreferenceSelectInputRenderer, PreferenceSelectInputRendererContribution } from './components/preference-select-input'; import { PreferenceStringInputRenderer, PreferenceStringInputRendererContribution } from './components/preference-string-input'; +import { PreferenceMarkdownRenderer } from './components/preference-markdown-renderer'; import { PreferencesEditorWidget } from './preference-editor-widget'; import { PreferencesScopeTabBar } from './preference-scope-tabbar-widget'; import { PreferencesSearchbarWidget } from './preference-searchbar-widget'; @@ -95,5 +96,7 @@ export function createPreferencesWidgetContainer(parent: interfaces.Container): return creator.createRenderer(node, container); }); + child.bind(PreferenceMarkdownRenderer).toSelf().inSingletonScope(); + return child; }