diff --git a/src/world/loader.test.ts b/src/world/loader.test.ts index e6114da..56b677d 100644 --- a/src/world/loader.test.ts +++ b/src/world/loader.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest' -import { parseRoom } from './loader' +import { parseRoom, parseItem } from './loader' const FOYER_MD = `--- id: foyer @@ -161,3 +161,56 @@ items: [] expect(() => parseRoom(md, 'rooms/r.md')).toThrow(/exitDRequires is set but exitDLockedText is missing/) }) }) + +// Add to the bottom of loader.test.ts + +const LAMP_MD = `--- +id: lamp +names: [lamp, oil lamp, torch] +short: an oil lamp +takeable: true +initialState: + lit: false +--- + +An iron oil lamp with a glass chimney. Currently unlit. +` + +describe('parseItem', () => { + it('parses an item with state', () => { + const item = parseItem(LAMP_MD, 'items/lamp.md') + expect(item).toEqual({ + id: 'lamp', + names: ['lamp', 'oil lamp', 'torch'], + short: 'an oil lamp', + long: 'An iron oil lamp with a glass chimney. Currently unlit.', + initialState: { lit: false }, + takeable: true, + }) + }) + + it('uses empty initialState when omitted', () => { + const md = `--- +id: x +names: [x] +short: x +takeable: false +--- + +The long description. +` + const item = parseItem(md, 'items/x.md') + expect(item.initialState).toEqual({}) + }) + + it('throws when body is empty', () => { + const md = `--- +id: x +names: [x] +short: x +takeable: false +--- +` + expect(() => parseItem(md, 'items/x.md')).toThrow(/empty long description/i) + }) +}) diff --git a/src/world/loader.ts b/src/world/loader.ts index 100469e..86ff6e6 100644 --- a/src/world/loader.ts +++ b/src/world/loader.ts @@ -1,7 +1,7 @@ import matter from 'gray-matter' -import type { Room, RoomDescriptions } from './types' +import type { Room, RoomDescriptions, Item } from './types' import type { Direction } from '../engine/types' -import { roomFrontmatterSchema } from './schema' +import { roomFrontmatterSchema, itemFrontmatterSchema } from './schema' const WIKILINK = /^\[\[([^\]|]+)(?:\|[^\]]*)?\]\]$/ @@ -97,3 +97,21 @@ export function parseRoom(raw: string, sourcePath: string): Room { if (fm.safe) room.safe = fm.safe return room } + +export function parseItem(raw: string, sourcePath: string): Item { + const parsed = matter(raw) + const frontmatter = stripWikilink(parsed.data) as Record + const fm = itemFrontmatterSchema.parse(frontmatter) + const long = parsed.content.trim() + if (long.length === 0) { + throw new Error(`${sourcePath}: empty long description`) + } + return { + id: fm.id, + names: fm.names, + short: fm.short, + long, + initialState: fm.initialState, + takeable: fm.takeable, + } +}