From cd7b5dabb73cbb6751bd081e550fd648b0fce9c1 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 14 Aug 2024 03:19:16 +0900 Subject: refactor(blog/nuldoc): use zod for runtime validation --- vhosts/blog/nuldoc-src/ndoc/parse.ts | 48 +++++++++++++++-------------------- vhosts/blog/nuldoc-src/slide/parse.ts | 36 ++++++++++++++------------ 2 files changed, 40 insertions(+), 44 deletions(-) diff --git a/vhosts/blog/nuldoc-src/ndoc/parse.ts b/vhosts/blog/nuldoc-src/ndoc/parse.ts index 136bc53e..857c086c 100644 --- a/vhosts/blog/nuldoc-src/ndoc/parse.ts +++ b/vhosts/blog/nuldoc-src/ndoc/parse.ts @@ -3,6 +3,23 @@ import { Config } from "../config.ts"; import { parseXmlString } from "../xml.ts"; import { createNewDocumentFromRootElement, Document } from "./document.ts"; import toHtml from "./to_html.ts"; +import { z } from "zod/mod.ts"; + +const PostMetadataSchema = z.object({ + article: z.object({ + uuid: z.string(), + title: z.string(), + description: z.string(), + tags: z.array(z.string()), + revisions: z.array(z.object({ + date: z.string(), + remark: z.string(), + isInternal: z.boolean().optional(), + })), + }), +}); + +type PostMetadata = z.infer; export async function parseNulDocFile( filePath: string, @@ -11,7 +28,7 @@ export async function parseNulDocFile( try { const fileContent = await Deno.readTextFile(filePath); const parts = fileContent.split(/^---$/m); - const meta = parseMetaInfo(parts[1]); + const meta = parseMetadata(parts[1]); const root = parseXmlString("" + parts[2]); const doc = createNewDocumentFromRootElement(root, meta, filePath, config); return toHtml(doc); @@ -21,31 +38,6 @@ export async function parseNulDocFile( } } -function parseMetaInfo(s: string): { - article: { - uuid: string; - title: string; - description: string; - tags: string[]; - revisions: { - date: string; - remark: string; - isInternal?: boolean; - }[]; - }; -} { - const root = parseToml(s) as { - article: { - uuid: string; - title: string; - description: string; - tags: string[]; - revisions: { - date: string; - remark: string; - isInternal?: boolean; - }[]; - }; - }; - return root; +function parseMetadata(s: string): PostMetadata { + return PostMetadataSchema.parse(parseToml(s)); } diff --git a/vhosts/blog/nuldoc-src/slide/parse.ts b/vhosts/blog/nuldoc-src/slide/parse.ts index 5daa6ed0..82510a95 100644 --- a/vhosts/blog/nuldoc-src/slide/parse.ts +++ b/vhosts/blog/nuldoc-src/slide/parse.ts @@ -1,28 +1,32 @@ import { parse as parseToml } from "std/toml/mod.ts"; import { Config } from "../config.ts"; import { createNewSlideFromTomlRootObject, Slide } from "./slide.ts"; +import { z } from "zod/mod.ts"; + +const SlideMetadataSchema = z.object({ + slide: z.object({ + uuid: z.string(), + title: z.string(), + event: z.string(), + talkType: z.string(), + link: z.string(), + tags: z.array(z.string()), + revisions: z.array(z.object({ + date: z.string(), + remark: z.string(), + isInternal: z.boolean().optional(), + })), + }), +}); export async function parseSlideFile( filePath: string, config: Config, ): Promise { try { - // TODO runtime assertion - const root = parseToml(await Deno.readTextFile(filePath)) as { - slide: { - uuid: string; - title: string; - event: string; - talkType: string; - link: string; - tags: string[]; - revisions: { - date: string; - remark: string; - isInternal?: boolean; - }[]; - }; - }; + const root = SlideMetadataSchema.parse( + parseToml(await Deno.readTextFile(filePath)), + ); return createNewSlideFromTomlRootObject(root, filePath, config); } catch (e) { e.message = `${e.message} in ${filePath}`; -- cgit v1.2.3-70-g09d2