ttrpg-tools/src/components/Article.tsx

58 lines
1.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Component, createSignal, onMount, onCleanup, Show } from 'solid-js';
import { parseMarkdown } from '../markdown';
import { fetchData } from '../data-loader';
export interface ArticleProps {
src: string;
onLoaded?: () => void;
onError?: (error: Error) => void;
}
/**
* Article 组件
* 用于将特定 src 位置的 md 文件显示为 markdown 文章
*/
export const Article: Component<ArticleProps> = (props) => {
const [content, setContent] = createSignal('');
const [loading, setLoading] = createSignal(true);
const [error, setError] = createSignal<Error | null>(null);
let articleRef: HTMLArticleElement | undefined;
onMount(async () => {
setLoading(true);
try {
const text = await fetchData(props.src);
setContent(text);
setLoading(false);
props.onLoaded?.();
} catch (err) {
const errorObj = err instanceof Error ? err : new Error(String(err));
setError(errorObj);
setLoading(false);
props.onError?.(errorObj);
}
});
onCleanup(() => {
// 清理时清空内容,触发内部组件的销毁
setContent('');
});
return (
<article ref={articleRef} class="prose" data-src={props.src}>
<Show when={loading()}>
<div class="text-gray-500">...</div>
</Show>
<Show when={error()}>
<div class="text-red-500">{error()?.message}</div>
</Show>
<Show when={!loading() && !error()}>
<div innerHTML={parseMarkdown(content())} />
</Show>
</article>
);
};
export default Article;