ttrpg-tools/src/data-loader/file-index.ts

89 lines
2.5 KiB
TypeScript
Raw Normal View History

/**
*
*
*/
type FileIndex = Record<string, string>;
let fileIndex: FileIndex | null = null;
let indexLoadPromise: Promise<void> | null = null;
/**
*
* CLI JSON Dev 使 webpackContext .md
*/
function ensureIndexLoaded(): Promise<void> {
if (indexLoadPromise) return indexLoadPromise;
indexLoadPromise = (async () => {
2026-03-18 11:31:13 +08:00
// 尝试 CLI 环境:从 /__CONTENT_INDEX.json 加载
try {
2026-03-18 11:31:13 +08:00
const response = await fetch("/__CONTENT_INDEX.json");
if (response.ok) {
const index = await response.json();
fileIndex = { ...fileIndex, ...index };
return;
}
} catch (e) {
// CLI 索引不可用时尝试 dev 环境
}
// Dev 环境:使用 import.meta.webpackContext + raw loader 加载 .md, .csv, .yarn 文件
try {
const context = import.meta.webpackContext("../../content", {
recursive: true,
regExp: /\.md|\.yarn|\.csv$/i,
});
const keys = context.keys();
const index: FileIndex = {};
for (const key of keys) {
// context 返回的是模块,需要访问其 default 导出raw-loader 处理后的内容)
const module = context(key) as { default?: string } | string;
const content = typeof module === "string" ? module : module.default ?? "";
const normalizedPath = "/content" + key.slice(1);
index[normalizedPath] = content;
}
fileIndex = { ...fileIndex, ...index };
} catch (e) {
// webpackContext 不可用时忽略
}
})();
return indexLoadPromise;
}
/**
*
*/
export async function getIndexedData(path: string): Promise<string> {
await ensureIndexLoaded();
if (fileIndex && fileIndex[path]) {
return fileIndex[path];
}
const res = await fetch(path);
const content = await res.text();
fileIndex = fileIndex || {};
fileIndex[path] = content;
return content;
}
/**
*
*/
export async function getPathsByExtension(ext: string): Promise<string[]> {
await ensureIndexLoaded();
if (!fileIndex) return [];
const normalizedExt = ext.startsWith(".") ? ext : `.${ext}`;
return Object.keys(fileIndex).filter(path =>
path.toLowerCase().endsWith(normalizedExt.toLowerCase())
);
}
/**
*
*/
export function clearIndex(): void {
fileIndex = null;
indexLoadPromise = null;
}