@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
188 lines • 7.2 kB
JavaScript
;
// *****************************************************************************
// Copyright (C) 2025 EclipseSource 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
// *****************************************************************************
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalizedMarkdown = exports.useMarkdown = exports.Markdown = void 0;
const React = require("react");
const markdown_string_1 = require("../../common/markdown-rendering/markdown-string");
const nls_1 = require("../../common/nls");
/**
* A React component for rendering markdown content.
*
* @example Basic usage
* ```tsx
* const MyComponent = ({ markdownRenderer }: { markdownRenderer: MarkdownRenderer }) => {
* return (
* <Markdown
* markdown="Hello **World**!"
* markdownRenderer={markdownRenderer}
* className="my-content"
* markdownOptions={{ supportHtml: true }}
* />
* );
* };
* ```
*
* @example With localized content
* ```tsx
* const MyComponent = ({ markdownRenderer }: { markdownRenderer: MarkdownRenderer }) => {
* const content = nls.localize('my.key', 'Hello **{0}**!', 'World');
*
* return (
* <Markdown
* markdown={content}
* markdownRenderer={markdownRenderer}
* className="my-content"
* />
* );
* };
* ```
*
* @example With command links
* ```tsx
* const content = nls.localize(
* 'my.key',
* 'Open [settings]({0}) to configure.',
* `command:${CommonCommands.OPEN_PREFERENCES.id}`
* );
*
* return (
* <Markdown
* markdown={content}
* markdownRenderer={markdownRenderer}
* markdownOptions={{
* isTrusted: { enabledCommands: [CommonCommands.OPEN_PREFERENCES.id] }
* }}
* />
* );
* ```
*/
const MarkdownComponent = ({ markdown, markdownRenderer, className, markdownOptions, onRender }) => {
const ref = useMarkdown(markdown, markdownRenderer, markdownOptions, onRender);
return React.createElement("div", { className: className, ref: ref });
};
MarkdownComponent.displayName = 'Markdown';
exports.Markdown = React.memo(MarkdownComponent);
/**
* A React hook for rendering markdown content.
*
* This hook integrates MarkdownRenderer with React's lifecycle,
* ensuring that:
* - Markdown is rendered only when content or renderer changes
* - MarkdownRenderResult is properly disposed when component unmounts
* - DOM elements are correctly managed by React
* - Event listeners and other imperative DOM operations are preserved
*
* Returns a ref that should be attached to a DOM element.
*
* @example Basic usage
* ```tsx
* const MyComponent = ({ markdownRenderer }: { markdownRenderer: MarkdownRenderer }) => {
* const ref = useMarkdown('Hello **World**!', markdownRenderer, { supportHtml: true });
* return <div className="my-content" ref={ref} />;
* };
* ```
*
* @example With localized content
* ```tsx
* const MyComponent = ({ markdownRenderer }: { markdownRenderer: MarkdownRenderer }) => {
* const content = nls.localize('my.key', 'Hello **{0}**!', 'World');
* const ref = useMarkdown(content, markdownRenderer);
* return <div className="my-content" ref={ref} />;
* };
* ```
*/
function useMarkdown(markdown, markdownRenderer, markdownOptions, onRender) {
// eslint-disable-next-line no-null/no-null
const containerRef = React.useRef(null);
const renderResultRef = React.useRef();
const renderedElement = React.useMemo(() => {
var _a;
(_a = renderResultRef.current) === null || _a === void 0 ? void 0 : _a.dispose();
renderResultRef.current = undefined;
if (!markdown || (typeof markdown === 'string' && markdown.trim() === '')) {
return undefined;
}
const markdownString = typeof markdown === 'string'
? new markdown_string_1.MarkdownStringImpl(markdown, markdownOptions)
: markdown;
const rendered = markdownRenderer.render(markdownString);
renderResultRef.current = rendered;
return rendered.element;
}, [markdown, markdownRenderer, markdownOptions]);
React.useEffect(() => {
if (containerRef.current && renderedElement) {
containerRef.current.replaceChildren(renderedElement);
onRender === null || onRender === void 0 ? void 0 : onRender(renderedElement);
}
else if (containerRef.current && !renderedElement) {
containerRef.current.replaceChildren();
onRender === null || onRender === void 0 ? void 0 : onRender(undefined);
}
}, [renderedElement, onRender]);
React.useEffect(() => () => {
var _a;
(_a = renderResultRef.current) === null || _a === void 0 ? void 0 : _a.dispose();
}, []);
return containerRef;
}
exports.useMarkdown = useMarkdown;
/**
* A React component that combines localization with markdown rendering.
*
* This component automatically handles the localization of markdown content using `nls.localize`
* and then renders it using the Markdown component.
*
* @example Basic usage
* ```tsx
* <LocalizedMarkdown
* localizationKey="theia/mypackage/welcome"
* defaultMarkdown="Welcome to **Theia**!"
* markdownRenderer={this.markdownRenderer}
* className="welcome-message"
* />
* ```
*
* @example With parameters
* ```tsx
* <LocalizedMarkdown
* localizationKey="theia/mypackage/greeting"
* defaultMarkdown="Hello **{0}**! You have {1} new messages."
* args={['Alice', 5]}
* markdownRenderer={this.markdownRenderer}
* />
* ```
*
* @example With command links
* ```tsx
* <LocalizedMarkdown
* localizationKey="theia/mypackage/settings"
* defaultMarkdown="Open [settings]({0}) to configure."
* args={[`command:${CommonCommands.OPEN_PREFERENCES.id}`]}
* markdownRenderer={this.markdownRenderer}
* markdownOptions={{
* isTrusted: { enabledCommands: [CommonCommands.OPEN_PREFERENCES.id] }
* }}
* />
* ```
*/
const LocalizedMarkdown = ({ localizationKey, defaultMarkdown, args = [], markdownRenderer, className, markdownOptions, onRender }) => {
const localizedMarkdown = React.useMemo(() => nls_1.nls.localize(localizationKey, defaultMarkdown, ...args), [localizationKey, defaultMarkdown, ...args]);
return (React.createElement(exports.Markdown, { markdown: localizedMarkdown, markdownRenderer: markdownRenderer, className: className, markdownOptions: markdownOptions, onRender: onRender }));
};
exports.LocalizedMarkdown = LocalizedMarkdown;
exports.LocalizedMarkdown.displayName = 'LocalizedMarkdown';
//# sourceMappingURL=markdown.js.map