react-intlayer
Version:
Easily internationalize i18n your React applications with type-safe multilingual content management.
198 lines (195 loc) • 5.26 kB
JavaScript
'use client';
import { compileMarkdown } from "./processor.mjs";
import { useMarkdownContext } from "./MarkdownProvider.mjs";
import { Fragment, jsx } from "react/jsx-runtime";
//#region src/markdown/MarkdownRenderer.tsx
/**
* Renders markdown content to JSX with the provided components and options.
*
* This function does not use context from MarkdownProvider. Use `useMarkdownRenderer`
* hook if you want to leverage provider context.
*
* @param content - The markdown string to render
* @param props - Configuration options for rendering
* @param props.components - Component overrides for HTML tags
* @param props.wrapper - Wrapper component for multiple children
* @returns JSX element representing the rendered markdown
*
* @example
* ```tsx
* import { renderMarkdown } from '@intlayer/react-intlayer/markdown';
*
* const markdown = '# Hello World\n\nThis is **bold** text.';
* const jsx = renderMarkdown(markdown, {
* components: {
* h1: ({ children }) => <h1 className="title">{children}</h1>,
* },
* forceBlock: true,
* });
* ```
*/
const renderMarkdown = (content, { components, wrapper, forceBlock, forceInline, preserveFrontmatter, tagfilter } = {}) => {
return compileMarkdown(content, {
components,
forceBlock,
forceInline,
wrapper,
forceWrapper: !!wrapper,
preserveFrontmatter,
tagfilter
});
};
/**
* Hook that returns a function to render markdown content.
*
* This hook considers the configuration from the `MarkdownProvider` context if available,
* falling back to the provided props or default behavior.
*
* @param props - Optional configuration that will override context values
* @param props.components - Component overrides for HTML tags (overrides context)
* @param props.wrapper - Wrapper component (overrides context)
* @returns A function that takes markdown content and returns JSX
*
* @example
* ```tsx
* import { useMarkdownRenderer } from '@intlayer/react-intlayer/markdown';
*
* function MyComponent() {
* const renderMarkdown = useMarkdownRenderer({
* components: {
* h1: ({ children }) => <h1 className="custom">{children}</h1>,
* },
* });
*
* return (
* <div>
* {renderMarkdown('# Hello\n\nThis is **markdown**')}
* </div>
* );
* }
* ```
*
* @example
* ```tsx
* // With MarkdownProvider context
* function App() {
* return (
* <MarkdownProvider
* components={{ h1: CustomHeading }}
* forceBlock={true}
* >
* <MyComponent />
* </MarkdownProvider>
* );
* }
* ```
*/
const useMarkdownRenderer = ({ components, wrapper, forceBlock, forceInline, preserveFrontmatter, tagfilter } = {}) => {
const context = useMarkdownContext();
return (content) => {
if (context) return context.renderMarkdown(content, {
forceBlock,
forceInline,
preserveFrontmatter,
tagfilter
}, components, wrapper);
return renderMarkdown(content, {
components,
wrapper,
forceBlock,
forceInline,
preserveFrontmatter,
tagfilter
});
};
};
/**
* React component that renders markdown content to JSX.
*
* This component uses the `renderMarkdown` function from the `MarkdownProvider` context
* if available. Otherwise, it falls back to the default compiler with provided components
* and options. You can also provide a custom `renderMarkdown` function prop to override
* all rendering behavior.
*
* @example
* ```tsx
* import { MarkdownRenderer } from '@intlayer/react-intlayer/markdown';
*
* function MyComponent() {
* return (
* <MarkdownRenderer>
* {`# Hello World
*
* This is a paragraph with **bold** and *italic* text.
*
* - List item 1
* - List item 2`}
* </MarkdownRenderer>
* );
* }
* ```
*
* @example
* ```tsx
* // With custom components
* <MarkdownRenderer
* components={{
* h1: ({ children }) => <h1 className="text-4xl font-bold">{children}</h1>,
* a: ({ href, children }) => (
* <a href={href} className="text-blue-500 hover:underline">
* {children}
* </a>
* ),
* }}
* forceBlock={true}
* >
* {markdownContent}
* </MarkdownRenderer>
* ```
*
* @example
* ```tsx
* // With MarkdownProvider context
* function App() {
* return (
* <MarkdownProvider
* components={{ h1: CustomHeading }}
* forceBlock={true}
* >
* <MarkdownRenderer>
* {markdownContent}
* </MarkdownRenderer>
* </MarkdownProvider>
* );
* }
* ```
*/
const MarkdownRenderer = ({ children = "", components, wrapper, forceBlock, forceInline, preserveFrontmatter, tagfilter, renderMarkdown }) => {
const context = useMarkdownContext();
if (renderMarkdown) return /* @__PURE__ */ jsx(Fragment, { children: renderMarkdown(children, {
components,
wrapper,
forceBlock,
forceInline,
preserveFrontmatter,
tagfilter
}) });
if (context) return /* @__PURE__ */ jsx(Fragment, { children: context.renderMarkdown(children, {
forceBlock,
forceInline,
preserveFrontmatter,
tagfilter
}, components, wrapper) });
return /* @__PURE__ */ jsx(Fragment, { children: compileMarkdown(children, {
components,
forceBlock,
forceInline,
wrapper,
forceWrapper: !!wrapper,
preserveFrontmatter,
tagfilter
}) });
};
//#endregion
export { MarkdownRenderer, renderMarkdown, useMarkdownRenderer };
//# sourceMappingURL=MarkdownRenderer.mjs.map