ttrpg-tools/src/components/Article.tsx

56 lines
1.7 KiB
TypeScript
Raw Normal View History

2026-02-26 14:51:26 +08:00
import { Component, createSignal, createEffect, onCleanup, Show, createResource } from 'solid-js';
2026-02-26 09:24:26 +08:00
import { parseMarkdown } from '../markdown';
2026-02-26 14:24:48 +08:00
import { fetchData, extractSection } from '../data-loader';
2026-02-26 09:24:26 +08:00
export interface ArticleProps {
src: string;
2026-02-26 09:53:30 +08:00
section?: string; // 指定要显示的标题(不含 #
2026-02-26 09:24:26 +08:00
onLoaded?: () => void;
onError?: (error: Error) => void;
2026-02-26 17:44:58 +08:00
class?: string; // 额外的 class 用于样式控制
2026-02-26 09:24:26 +08:00
}
2026-02-26 14:51:26 +08:00
async function fetchArticleContent(params: { src: string; section?: string }): Promise<string> {
const text = await fetchData(params.src);
// 如果指定了 section提取对应内容
return params.section ? extractSection(text, params.section) : text;
}
2026-02-26 09:24:26 +08:00
/**
* Article
* src md markdown
*/
export const Article: Component<ArticleProps> = (props) => {
2026-02-26 14:51:26 +08:00
const [content, { refetch }] = createResource(
() => ({ src: props.src, section: props.section }),
fetchArticleContent
);
2026-02-26 09:24:26 +08:00
2026-02-26 14:51:26 +08:00
createEffect(() => {
const data = content();
if (data) {
2026-02-26 09:24:26 +08:00
props.onLoaded?.();
}
});
onCleanup(() => {
// 清理时清空内容,触发内部组件的销毁
});
return (
2026-02-27 12:34:55 +08:00
<article class={`prose ${props.class || ''}`} data-src={props.src}>
2026-02-26 14:51:26 +08:00
<Show when={content.loading}>
2026-02-26 09:24:26 +08:00
<div class="text-gray-500">...</div>
</Show>
2026-02-26 14:51:26 +08:00
<Show when={content.error}>
<div class="text-red-500">{content.error?.message}</div>
2026-02-26 09:24:26 +08:00
</Show>
2026-02-26 14:51:26 +08:00
<Show when={!content.loading && !content.error && content()}>
2026-02-26 18:11:33 +08:00
<div class="relative" innerHTML={parseMarkdown(content()!)} />
2026-02-26 09:24:26 +08:00
</Show>
</article>
);
};
export default Article;