/** * This file is part of the NocoBase (R) project. * Copyright (c) 2020-2024 NocoBase Co., Ltd. * Authors: NocoBase Team. * * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ import { Spin } from 'antd'; import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { useRequest } from '../api-client'; import { useStyles as useMarkdownStyles } from '../schema-component/antd/markdown/style'; import { useParseMarkdown } from '../schema-component/antd/markdown/util'; import { useStyles } from './style'; import { useGlobalTheme } from '../global-theme'; const PLUGIN_STATICS_PATH = '/static/plugins/'; interface PluginDocumentProps { url: string; packageName?: string; } export const PluginDocument: React.FC = memo((props) => { const { isDarkTheme } = useGlobalTheme(); const { componentCls, hashId } = useMarkdownStyles({ isDarkTheme }); const { styles } = useStyles(); const { url, packageName } = props; const [docUrl, setDocUrl] = useState(url); const { data, loading, error } = useRequest( { url: docUrl, baseURL: '/' }, { refreshDeps: [docUrl], }, ); const { html, loading: parseLoading } = useParseMarkdown(data); const htmlWithOutRelativeDirect = useMemo(() => { if (html) { let res = html; const pattern = / match + `onclick="return false;"`); // prevent the default event of // replace img src res = res.replace(/src="(.*?)"/g, (match, src: string) => { if (src.startsWith('http') || src.startsWith('//:')) return match; return `src="${PLUGIN_STATICS_PATH}${packageName}/${src}"`; }); return res; } return ''; }, [html, packageName]); const handleSwitchDocLang = useCallback((e: MouseEvent) => { const url = (e.target as HTMLDivElement).getAttribute('href'); if (!url) return; const parsedUrl = new URL(docUrl, window.location.origin); const combinedUrl = new URL(url, parsedUrl); setDocUrl(combinedUrl.pathname); }, []); useEffect(() => { const md = document.getElementById('pm-md-preview'); md.addEventListener('click', handleSwitchDocLang); return () => { removeEventListener('click', handleSwitchDocLang); }; }, [handleSwitchDocLang]); return (
{loading || parseLoading ? ( ) : (
)}
); }); PluginDocument.displayName = 'PluginDocument';