diff --git a/README.md b/README.md index 051c667..e6b84a3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Playbill Builder CLI -This is a CLI tool for compiling YAML files into a validated Playbill for [Proscenium](https://proscenium.game) +This is a CLI tool for compiling Markdown and YAML files into a validated Playbill for [Proscenium](https://proscenium.game) ## Usage @@ -9,22 +9,139 @@ Usage: muse [/path/to/binding.yaml] Options: - --check Only load and check the current binding and resources, - but do not compile - --write Write the output to a file. If not specified, outputs to stdout - --outfile Specify the output file path [default: playbill.json] - --verbose, -v Verbose output - --help, -h Show this help message + --check Only load and check the current binding and resources, but do not compile + --outfile, -o Specify the output file path. If not specified, output to stdout + --watch, -w Watch the directory for changes and recompile + --renderer, -r Specify the output renderer. Options: json, html + --help, -h Show this help message ``` ## Binding File ```yaml -$binding: playbill # Required -id: the-playbill-id # Required name: My Playbill # Required author: My Name # Required version: 0.0.1 # Required files: # Optional - "**/*.yaml" +styles: # Optional + - stylesheet.css +terms: # Optional + Some Term: Some Definition + Another Term: Another Definition +``` + +## Definition Shapes + +These YAML representations of definitions show the properties available for each Playbill component. + +Note that every Playbill component definition can define the following properties: + +```yaml +id: some-hypenated-id # default: slug-ified file name +name: The Name of the Component # default: Name of the containing file +description: A markdown-enabled description # default: Placeholder / empty +categories: # default: No categories + - list + - of + - categories +``` + +### Ability Definition + +```yaml +$define: ability +type: action | cue | trait +ap: 0 +hp: 0 +ep: 0 +xp: 0 +damage: 0 +damageType: phy | arc +roll: none | attack | fate | +``` + +### Blueprint Definition + +```yaml +$define: blueprint +species: some-hypenated-id +items: + - item-id + - item-id-two + - item-id-three +abilities: + - ability-id + - ability-id-two + - ability-id-three +ap: 0 +hp: 0 +ep: 0 +xp: 0 +muscle: novice | adept | master +focus: novice | adept | master +knowledge: novice | adept | master +charm: novice | adept | master +cunning: novice | adept | master +spark: novice | adept | master +``` + +### Item Definition + +```yaml +$define: item +type: wielded | worn | trinket +rarity: common | uncommon | rare | legendary +affinity: none | attack | fate | +damage: 0 +damageType: phy | arc +hands: 1 | 2 # Only for wielded items +slot: headgear | outfit | gloves | boots | adornment | unique # Only for worn items +``` + +### Method Definition + +```yaml +$define: method +curator: Someone +abilities: + - [rank-1-ability-id-one, rank-1-ability-id-two] + - [rank-2-ability-id-one] +``` + +### Resource Definition + +```yaml +$define: resource +type: text | image | table +url: https://example.com/image.jpeg # Only for image resources +data: # Only for table resources +``` + +### Rule Definition + +```yaml +$define: rule +overrule: another-rule-id # Optional +order: 0 # Optional +``` + +### Species Definition + +```yaml +$define: species +hands: 2 +abilities: + - some-ability-id + - another-ability-id +ap: 0 +hp: 0 +ep: 0 +xp: 0 +muscle: novice | adept | master +focus: novice | adept | master +knowledge: novice | adept | master +charm: novice | adept | master +cunning: novice | adept | master +spark: novice | adept | master ``` diff --git a/src/define/index.ts b/src/define/index.ts index 23cc8b7..c44c120 100644 --- a/src/define/index.ts +++ b/src/define/index.ts @@ -17,18 +17,14 @@ import { import { z } from "zod"; const Base = z.object({ - // Required -- defines the type of component $define: z.string(), -}); - -const Info = Base.extend({ id: z.string(), // TODO: Validate ID shapes name: z.string().default("Unnamed Component"), description: z.string().default("No description provided"), categories: z.array(z.string()).default([]), }); -const AbilitySchema = Info.extend({ +const AbilitySchema = Base.extend({ $define: z.literal("ability"), type: z.string().default("action"), ap: z.number().int().default(0), @@ -40,7 +36,7 @@ const AbilitySchema = Info.extend({ roll: z.string().default("none"), }); -const BlueprintSchema = Info.extend({ +const BlueprintSchema = Base.extend({ $define: z.literal("blueprint"), species: z.string(), items: z.array(z.string()).default([]), @@ -62,7 +58,7 @@ const GlossarySchema = Base.extend({ terms: z.record(z.string(), z.string()), }); -const BaseItem = Info.extend({ +const BaseItem = Base.extend({ $define: z.literal("item"), rarity: z.string().default("common"), affinity: z.string().default("none"), @@ -78,43 +74,43 @@ const ItemSchema = z.discriminatedUnion("type", [ }), BaseItem.extend({ type: z.literal("worn"), - hands: z.number().int().default(1), + slot: z.string().default("unique"), }), BaseItem.extend({ type: z.literal("trinket"), }), ]); -const MethodSchema = Info.extend({ +const MethodSchema = Base.extend({ $define: z.literal("method"), curator: z.string().default("Someone"), abilities: z.array(z.array(z.string())).default([]), }); const ResourceSchema = z.discriminatedUnion("type", [ - Info.extend({ + Base.extend({ $define: z.literal("resource"), type: z.literal("text"), }), - Info.extend({ + Base.extend({ $define: z.literal("resource"), type: z.literal("image"), url: z.string(), }), - Info.extend({ + Base.extend({ $define: z.literal("resource"), type: z.literal("table"), data: z.array(z.array(z.string())), }), ]); -const RuleSchema = Info.extend({ +const RuleSchema = Base.extend({ $define: z.literal("rule"), overrule: z.nullable(z.string()).default(null), order: z.number().int().default(Number.POSITIVE_INFINITY), }); -const SpeciesSchema = Info.extend({ +const SpeciesSchema = Base.extend({ $define: z.literal("species"), hands: z.number().int().default(2), abilities: z.array(z.string()).default([]),