generated from template/apps-template
71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import { cn } from '@/lib/utils';
|
|
import { useEffect, useState } from 'react';
|
|
import { Marked } from 'marked';
|
|
import hljs from 'highlight.js';
|
|
import { markedHighlight } from 'marked-highlight';
|
|
|
|
const markedAndHighlight = new Marked(
|
|
markedHighlight({
|
|
emptyLangClass: 'hljs',
|
|
langPrefix: 'hljs language-',
|
|
highlight(code, lang, info) {
|
|
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
|
|
return hljs.highlight(code, { language }).value;
|
|
},
|
|
}),
|
|
);
|
|
|
|
export const md2html = async (md: string) => {
|
|
const html = markedAndHighlight.parse(md);
|
|
return html;
|
|
};
|
|
|
|
export const clearMeta = (markdown?: string) => {
|
|
if (!markdown) return '';
|
|
// Remove YAML front matter if present
|
|
const yamlRegex = /^---\n[\s\S]*?\n---\n/;
|
|
return markdown.replace(yamlRegex, '');
|
|
};
|
|
type Props = {
|
|
children?: React.ReactNode;
|
|
className?: string;
|
|
style?: React.CSSProperties;
|
|
content?: string; // Optional content prop for markdown text
|
|
[key: string]: any; // Allow any additional props
|
|
};
|
|
export const MarkdownPreview = (props: Props) => {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'markdown-body scrollbar h-full overflow-auto w-full px-6 py-2 max-w-[800px] border my-4 flex flex-col justify-self-center rounded-md shadow-md',
|
|
props.className,
|
|
)}
|
|
style={props.style}>
|
|
{props.children ? <WrapperText>{props.children}</WrapperText> : <MarkdownPreviewWrapper content={clearMeta(props.content)} />}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const WrapperText = (props: { children?: React.ReactNode; html?: string }) => {
|
|
if (props.html) {
|
|
return <div className='w-full' dangerouslySetInnerHTML={{ __html: props.html }} />;
|
|
}
|
|
return <div className='w-full h-full'>{props.children}</div>;
|
|
};
|
|
|
|
export const MarkdownPreviewWrapper = (props: Props) => {
|
|
const [html, setHtml] = useState<string>('');
|
|
useEffect(() => {
|
|
init();
|
|
}, [props.content]);
|
|
const init = async () => {
|
|
if (props.content) {
|
|
const htmlContent = await md2html(props.content);
|
|
setHtml(htmlContent);
|
|
} else {
|
|
setHtml('');
|
|
}
|
|
};
|
|
return <WrapperText html={html} />;
|
|
};
|