ds-markdown
Version:
> π React Markdown ζεε¨η»η»δ»ΆοΌζδΎη°δ»£θ倩ηι’ζζ
122 lines β’ 5.91 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
/* eslint-disable @typescript-eslint/no-explicit-any */
import { forwardRef, useCallback, useImperativeHandle, useMemo, useRef } from 'react';
import gfmPlugin from 'remark-gfm';
import classNames from 'classnames';
import { __DEV__, katexId } from '../constant.js';
import { MarkdownTyperCMD } from 'react-markdown-typer';
import { DEFAULT_ANSWER_TYPE, DEFAULT_PLUGINS, DEFAULT_THEME, MarkdownThemeProvider, useMarkdownThemeContext } from '../context/MarkdownThemeProvider.js';
import { MarkdownProvider } from '../context/MarkdownProvider.js';
import { useConfig } from '../context/ConfigProvider/index.js';
import { replaceMathBracket } from '../utils/remarkMathBracket.js';
import CodeComponent from '../components/CodeComponent/index.js';
const MarkdownCMDInner = forwardRef(({ answerType = 'answer', timerType = 'requestAnimationFrame', ...rest }, ref) => {
var _a, _b;
const { state: themeState } = useMarkdownThemeContext();
const cmdRef = useRef(null);
// Get theme config from context
const currentTheme = themeState.theme;
useImperativeHandle(ref, () => ({
push: cmdRef.current.push,
clear: cmdRef.current.clear,
triggerWholeEnd: cmdRef.current.triggerWholeEnd,
stop: cmdRef.current.stop,
resume: cmdRef.current.resume,
start: cmdRef.current.start,
restart: cmdRef.current.restart,
}));
const { katexConfig } = useConfig();
// Get theme config from context
const currentMath = themeState.math;
const currentPlugins = themeState.plugins;
const mathSplitSymbol = (_a = currentMath === null || currentMath === void 0 ? void 0 : currentMath.splitSymbol) !== null && _a !== void 0 ? _a : 'dollar';
const finalReplaceMathBracket = (_b = currentMath === null || currentMath === void 0 ? void 0 : currentMath.replaceMathBracket) !== null && _b !== void 0 ? _b : replaceMathBracket;
const { remarkPlugins, rehypePlugins, hasKatexPlugin, components } = useMemo(() => {
let hasKatexPlugin = false;
const components = {};
const remarkPlugins = [gfmPlugin];
const rehypePlugins = [];
if (!currentPlugins) {
return {
remarkPlugins,
rehypePlugins,
};
}
currentPlugins.forEach((plugin) => {
if (plugin.id === katexId) {
hasKatexPlugin = true;
remarkPlugins.push(plugin.remarkPlugin);
rehypePlugins.push([plugin.rehypePlugin, katexConfig]);
}
else {
if (plugin.rehypePlugin) {
rehypePlugins.push(plugin.rehypePlugin);
}
if (plugin.remarkPlugin) {
remarkPlugins.push(plugin.remarkPlugin);
}
}
if (plugin.components) {
Object.assign(components, plugin.components);
}
});
return {
remarkPlugins,
rehypePlugins,
hasKatexPlugin,
components,
};
}, [currentPlugins, katexConfig]);
const customConvertMarkdownString = useCallback((markdownString) => {
/** If math plugin exists and math delimiter is bracket, replace with $ symbol */
if (hasKatexPlugin && mathSplitSymbol === 'bracket') {
return finalReplaceMathBracket(markdownString);
}
return markdownString;
}, [finalReplaceMathBracket, hasKatexPlugin, mathSplitSymbol]);
return (_jsx("div", { className: classNames({
'ds-markdown': true,
apple: true,
'ds-markdown-dark': currentTheme === 'dark',
}), children: _jsx("div", { className: `ds-markdown-${answerType}`, children: _jsx(MarkdownTyperCMD, { ref: cmdRef, timerType: timerType, customConvertMarkdownString: customConvertMarkdownString, ...rest, reactMarkdownProps: {
remarkPlugins,
rehypePlugins,
components: {
code: CodeComponent,
table: ({ children, ...props }) => {
return (_jsx("div", { className: "markdown-table-wrapper", children: _jsx("table", { className: "ds-markdown-table", children: children }) }));
},
...components,
},
} }) }) }));
});
if (__DEV__) {
MarkdownCMDInner.displayName = 'MarkdownCMD';
}
const MarkdownCMD = forwardRef((props, ref) => {
const { children = '', answerType = 'answer', isInnerRender, ...reset } = props;
if (__DEV__) {
if (!['thinking', 'answer'].includes(answerType)) {
throw new Error('The answerType of MarkdownCMD component must be thinking or answer');
}
if (typeof children !== 'string') {
throw new Error('The children of MarkdownCMD component must be a string');
}
}
const contextValue = useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
// Separate theme-related props
const themeProps = useMemo(() => ({
theme: props.theme || DEFAULT_THEME,
math: props.math,
codeBlock: props.codeBlock,
plugins: props.plugins || DEFAULT_PLUGINS,
answerType: props.answerType || DEFAULT_ANSWER_TYPE,
}), [props.theme, props.math, props.codeBlock, props.plugins, props.answerType]);
if (isInnerRender) {
// Inner render, outer layer has already passed props via context, no need to pass again here
return _jsx(MarkdownCMDInner, { ...props, ref: ref });
}
return (_jsx(MarkdownProvider, { value: contextValue, children: _jsx(MarkdownThemeProvider, { value: themeProps, children: _jsx(MarkdownCMDInner, { ...props, ref: ref }) }) }));
});
export default MarkdownCMD;
//# sourceMappingURL=index.js.map