feat: add md-emfont component and format code
- Add `md-emfont` custom element for dynamic font loading - Register `md-emfont` in component index - Reformat `Article.tsx` and `index.ts` using double quotes and consistent spacing - Fix indentation in `index.html`
This commit is contained in:
+33
-20
@@ -1,22 +1,32 @@
|
||||
import { Component, createEffect, onCleanup, Show, createResource, createMemo } from 'solid-js';
|
||||
import { parseMarkdown } from '../markdown';
|
||||
import { extractSection } from '../data-loader';
|
||||
import mermaid from 'mermaid';
|
||||
import {getIndexedData} from "../data-loader/file-index";
|
||||
import { resolvePath } from './utils/path';
|
||||
import { useLocation } from '@solidjs/router';
|
||||
import {
|
||||
Component,
|
||||
createEffect,
|
||||
onCleanup,
|
||||
Show,
|
||||
createResource,
|
||||
createMemo,
|
||||
} from "solid-js";
|
||||
import { parseMarkdown } from "../markdown";
|
||||
import { extractSection } from "../data-loader";
|
||||
import mermaid from "mermaid";
|
||||
import { getIndexedData } from "../data-loader/file-index";
|
||||
import { resolvePath } from "./utils/path";
|
||||
import { useLocation } from "@solidjs/router";
|
||||
|
||||
export interface ArticleProps {
|
||||
src: string;
|
||||
section?: string; // 指定要显示的标题(不含 #)
|
||||
iconPath?: string; // 图标路径前缀,默认为 "./assets",空字符串表示禁用
|
||||
section?: string; // 指定要显示的标题(不含 #)
|
||||
iconPath?: string; // 图标路径前缀,默认为 "./assets",空字符串表示禁用
|
||||
onLoaded?: () => void;
|
||||
onError?: (error: Error) => void;
|
||||
class?: string; // 额外的 class 用于样式控制
|
||||
class?: string; // 额外的 class 用于样式控制
|
||||
scrollToHash?: boolean; // 是否自动滚动到 hash
|
||||
}
|
||||
|
||||
async function fetchArticleContent(params: { src: string; section?: string }): Promise<string> {
|
||||
async function fetchArticleContent(params: {
|
||||
src: string;
|
||||
section?: string;
|
||||
}): Promise<string> {
|
||||
const text = await getIndexedData(params.src);
|
||||
// 如果指定了 section,提取对应内容
|
||||
return params.section ? extractSection(text, params.section) : text;
|
||||
@@ -28,17 +38,17 @@ async function fetchArticleContent(params: { src: string; section?: string }): P
|
||||
function scrollToHash(hash: string) {
|
||||
if (!hash) return;
|
||||
// 移除 # 前缀
|
||||
const id = hash.startsWith('#') ? hash.slice(1) : hash;
|
||||
const id = hash.startsWith("#") ? hash.slice(1) : hash;
|
||||
if (!id) return;
|
||||
|
||||
|
||||
// 使用 decodeURIComponent 解码 ID(处理中文等特殊字符)
|
||||
const decodedId = decodeURIComponent(id);
|
||||
|
||||
|
||||
// 尝试查找元素
|
||||
const element = document.getElementById(decodedId);
|
||||
if (element) {
|
||||
// 使用 scrollIntoView 滚动到元素
|
||||
element.scrollIntoView({ behavior: 'instant', block: 'start' });
|
||||
element.scrollIntoView({ behavior: "instant", block: "start" });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -52,12 +62,12 @@ export const Article: Component<ArticleProps> = (props) => {
|
||||
const location = useLocation();
|
||||
const [content, { refetch }] = createResource(
|
||||
() => ({ src: props.src, section: props.section }),
|
||||
fetchArticleContent
|
||||
fetchArticleContent,
|
||||
);
|
||||
|
||||
// 解析 iconPath,默认为 "./assets",空字符串表示禁用
|
||||
const iconPrefix = createMemo(() => {
|
||||
if (props.iconPath === '') return undefined; // 空字符串禁用图标前缀
|
||||
if (props.iconPath === "") return undefined; // 空字符串禁用图标前缀
|
||||
return resolvePath(props.src, props.iconPath ?? "./assets");
|
||||
});
|
||||
|
||||
@@ -67,7 +77,7 @@ export const Article: Component<ArticleProps> = (props) => {
|
||||
props.onLoaded?.();
|
||||
// 内容加载完成后,渲染 mermaid 图表
|
||||
void mermaid.run();
|
||||
|
||||
|
||||
// 内容渲染后检查 hash 并滚动
|
||||
scrollToHash(location.hash);
|
||||
}
|
||||
@@ -78,7 +88,7 @@ export const Article: Component<ArticleProps> = (props) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<article class={`prose ${props.class || ''}`} data-src={props.src}>
|
||||
<article class={`prose ${props.class || ""}`} data-src={props.src}>
|
||||
<Show when={content.loading}>
|
||||
<div class="text-gray-500">加载中...</div>
|
||||
</Show>
|
||||
@@ -86,7 +96,10 @@ export const Article: Component<ArticleProps> = (props) => {
|
||||
<div class="text-red-500">加载失败:{content.error?.message}</div>
|
||||
</Show>
|
||||
<Show when={!content.loading && !content.error && content()}>
|
||||
<div class="relative" innerHTML={parseMarkdown(content()!, iconPrefix())} />
|
||||
<div
|
||||
class="relative"
|
||||
innerHTML={parseMarkdown(content()!, iconPrefix())}
|
||||
/>
|
||||
</Show>
|
||||
</article>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user