diff options
| author | Leonardo Bishop <me@leonardobishop.com> | 2024-03-12 23:18:23 +0000 |
|---|---|---|
| committer | Leonardo Bishop <me@leonardobishop.com> | 2024-03-12 23:18:23 +0000 |
| commit | a072c91cc0dc26e417c51f666e8547e08ef40942 (patch) | |
| tree | 1a7296d2acb9038b1928cc1f0f5a08aa6b92b222 /utils | |
| parent | a4052ffee8bc7c6c8a69eba5120b5c6c2d951b0f (diff) | |
Add import from file system
Diffstat (limited to 'utils')
| -rw-r--r-- | utils/loader.ts | 93 | ||||
| -rw-r--r-- | utils/util.ts | 29 | ||||
| -rw-r--r-- | utils/validators.ts | 13 |
3 files changed, 135 insertions, 0 deletions
diff --git a/utils/loader.ts b/utils/loader.ts new file mode 100644 index 0000000..56e29fa --- /dev/null +++ b/utils/loader.ts @@ -0,0 +1,93 @@ +import { parse } from "yaml"; +import { loadCategoriesFromJson, loadItemsFromJson, loadQuestsFromJson } from "~/lib/questsLoader"; + +export async function openFileSystem() { + try { + return await (window as any).showDirectoryPicker(); + } catch (e) { + return undefined; + } +} + +export async function enumerateQuestDirectory(dirHandle: any) { + let configFile: any = null; + let categoryFile: any = null; + let questsDirectory: any = null; + let itemsDirectory: any = null; + + for await (const [name, handle] of dirHandle) { + if (name === 'quests' && handle.kind === 'directory') { + questsDirectory = handle; + } else if (name === 'items' && handle.kind === 'directory') { + itemsDirectory = handle; + } else if (name === 'config.yml' && handle.kind === 'file') { + configFile = handle; + } else if (name === 'categories.yml' && handle.kind === 'file') { + categoryFile = handle; + } + } + + if (!configFile) { + throw Error('invalid quest directory'); + } + + const [questFiles, itemFiles] = await Promise.all([questsDirectory ? listAllFilesAndDirs(questsDirectory) : [], itemsDirectory ? listAllFilesAndDirs(itemsDirectory) : []]); + const [categories, quests, items] = await Promise.all([(async () => { + if (!categoryFile) { + return []; + } + + const file: any = await categoryFile.getFile(); + const text: string = await file.text(); + const parsedYaml: any = parse(text); + + return loadCategoriesFromJson(parsedYaml.categories); + })(), + (async () => { + if (!questFiles) { + return []; + } + + const allQuests = await Promise.all(questFiles.filter(({ name, handle, kind }) => name.endsWith('.yml')).map(async ({ name, handle, kind }) => { + const file: any = await handle.getFile(); + const text: string = await file.text(); + return [ + name.replace('.yml', ''), + parse(text) + ]; + })) + + return loadQuestsFromJson(Object.fromEntries(allQuests)); + })(), + (async () => { + if (!itemFiles) { + return []; + } + + const allItems = await Promise.all(itemFiles.filter(({ name, handle, kind }) => name.endsWith('.yml')).map(async ({ name, handle, kind }) => { + const file: any = await handle.getFile(); + const text: string = await file.text(); + return [ + name.replace('.yml', ''), + parse(text) + ]; + })) + + return loadItemsFromJson(Object.fromEntries(allItems)); + })()]); + + return { categories, quests, items }; +} + +async function listAllFilesAndDirs(dirHandle: any): Promise<any[]> { + const files = []; + for await (const [name, handle] of dirHandle) { + const { kind } = handle; + if (handle.kind === 'directory') { + files.push(...await listAllFilesAndDirs(handle)); + } else { + files.push({ name, handle, kind }); + } + } + return files; +}
\ No newline at end of file diff --git a/utils/util.ts b/utils/util.ts new file mode 100644 index 0000000..cc500e0 --- /dev/null +++ b/utils/util.ts @@ -0,0 +1,29 @@ +const COLOR_CODE_REGEX = /&([0-9a-fk-or]|#[0-9A-F]{6})/ig; + +export function stripColorCodes(str: string): string { + return str.replace(COLOR_CODE_REGEX, ''); +} + +export function navigateToEditorPane(type: 'quest' | 'category' | 'item' | null, id?: string) { + if (id) { + if (type === 'category') { + navigateTo({ path: '/category/' + id }) + } else if (type === 'quest') { + navigateTo({ path: '/quest/' + id }) + } else if (type === 'item') { + navigateTo({ path: '/item/' + id }) + } + } else if (!id && !type) { + navigateTo({ path: '/' }) + } +} + +export type BrowserCapabilities = { + canUseFsApi: boolean +} + +export function getBrowserCapabilities(): BrowserCapabilities { + return { + canUseFsApi: typeof (window as any)?.showDirectoryPicker === 'function' + } +}
\ No newline at end of file diff --git a/utils/validators.ts b/utils/validators.ts new file mode 100644 index 0000000..5bf259a --- /dev/null +++ b/utils/validators.ts @@ -0,0 +1,13 @@ +const VALID_ID_REGEX = /^[a-z0-9_]+$/i; + +export function validateQuestId(id: string): boolean { + return VALID_ID_REGEX.test(id); +} + +export function validateCategoryId(id: string): boolean { + return VALID_ID_REGEX.test(id); +} + +export function validateTaskId(id: string): boolean { + return VALID_ID_REGEX.test(id); +} |
