let dataIndex: Record | null = null; let isDevIndexLoaded = false; let isCliIndexLoaded = false; /** * 从索引获取数据 */ function getIndexedData(path: string): string | null { if (dataIndex && dataIndex[path]) { return dataIndex[path]; } return null; } /** * 在 dev 环境加载 glob 索引 */ async function loadDevIndex(): Promise { if (isDevIndexLoaded) return; isDevIndexLoaded = true; // @ts-ignore - import.meta.glob 在构建时会被处理 if (typeof import.meta !== "undefined" && import.meta.glob) { try { // @ts-ignore - 只加载 .csv 和 .md 文件 const modules = import.meta.glob("../../content/**/*.{csv,md}", { as: "raw", eager: true, }); const index: Record = {}; for (const [path, content] of Object.entries(modules)) { const normalizedPath = path.replace("/src/", "/"); index[normalizedPath] = content as string; } dataIndex = { ...dataIndex, ...index }; } catch (e) { // glob 不可用时忽略 } } } /** * 在 CLI 环境从 /__CONTENT_INDEX.json 加载索引 */ async function loadCliIndex(): Promise { if (isCliIndexLoaded) return; isCliIndexLoaded = true; try { const response = await fetch("/__CONTENT_INDEX.json"); if (!response.ok) { throw new Error("Failed to fetch content index"); } const index = await response.json(); dataIndex = { ...dataIndex, ...index }; } catch (e) { // CLI 索引不可用时忽略(可能不在 CLI 环境) } } /** * 异步加载数据 * @param path 数据路径 * @returns 数据内容 */ export async function fetchData(path: string): Promise { // CLI 环境:先从 /__CONTENT_INDEX.json 加载索引 await loadCliIndex(); // dev 环境:加载 glob 索引 await loadDevIndex(); // 首先尝试从索引获取 const indexedData = getIndexedData(path); if (indexedData) { return indexedData; } // 索引不存在时,使用 fetch 加载 if (dataIndex !== null) throw new Error(`no data in index: ${path}`); try { const response = await fetch(path); if (!response.ok) { throw new Error(`Failed to fetch: ${path}`); } return await response.text(); } catch (error) { console.error("fetchData error:", error); throw error; } }