aboutsummaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorLeonardo Bishop <me@leonardobishop.com>2024-03-12 23:18:23 +0000
committerLeonardo Bishop <me@leonardobishop.com>2024-03-12 23:18:23 +0000
commita072c91cc0dc26e417c51f666e8547e08ef40942 (patch)
tree1a7296d2acb9038b1928cc1f0f5a08aa6b92b222 /utils
parenta4052ffee8bc7c6c8a69eba5120b5c6c2d951b0f (diff)
Add import from file system
Diffstat (limited to 'utils')
-rw-r--r--utils/loader.ts93
-rw-r--r--utils/util.ts29
-rw-r--r--utils/validators.ts13
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);
+}