Use new playbill updates
This commit is contained in:
parent
c1f3c6cade
commit
f7f861a1cb
8 changed files with 81 additions and 210 deletions
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
type Ability,
|
type Ability,
|
||||||
|
type AnyPlaybillComponent,
|
||||||
type Blueprint,
|
type Blueprint,
|
||||||
type Item,
|
type Item,
|
||||||
type Method,
|
type Method,
|
||||||
|
@ -161,37 +162,7 @@ const parseComponentType = (val: unknown): ComponentType => {
|
||||||
return val as ComponentType;
|
return val as ComponentType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ParsedComponent =
|
function parseAbilityDefinition(obj: unknown): Ability {
|
||||||
| {
|
|
||||||
type: "ability";
|
|
||||||
component: Ability;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "blueprint";
|
|
||||||
component: Blueprint;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "item";
|
|
||||||
component: Item;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "method";
|
|
||||||
component: Method;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "resource";
|
|
||||||
component: Resource;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "rule";
|
|
||||||
component: Rule;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "species";
|
|
||||||
component: Species;
|
|
||||||
};
|
|
||||||
|
|
||||||
function parseAbilityDefinition(obj: unknown): ParsedComponent {
|
|
||||||
const parsed = AbilitySchema.parse(obj);
|
const parsed = AbilitySchema.parse(obj);
|
||||||
|
|
||||||
const ability = parseAbility({
|
const ability = parseAbility({
|
||||||
|
@ -214,13 +185,10 @@ function parseAbilityDefinition(obj: unknown): ParsedComponent {
|
||||||
roll: parsed.roll,
|
roll: parsed.roll,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return ability;
|
||||||
type: "ability",
|
|
||||||
component: ability,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseBlueprintDefinition(obj: unknown): ParsedComponent {
|
function parseBlueprintDefinition(obj: unknown): Blueprint {
|
||||||
const parsed = BlueprintSchema.parse(obj);
|
const parsed = BlueprintSchema.parse(obj);
|
||||||
|
|
||||||
const blueprint = parseBlueprint({
|
const blueprint = parseBlueprint({
|
||||||
|
@ -244,18 +212,13 @@ function parseBlueprintDefinition(obj: unknown): ParsedComponent {
|
||||||
spark: parsed.spark,
|
spark: parsed.spark,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return blueprint;
|
||||||
type: "blueprint",
|
|
||||||
component: blueprint,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseItemDefinition(obj: unknown): ParsedComponent {
|
function parseItemDefinition(obj: unknown): Item {
|
||||||
const parsed = ItemSchema.parse(obj);
|
const parsed = ItemSchema.parse(obj);
|
||||||
|
|
||||||
return {
|
return parseItem({
|
||||||
type: "item",
|
|
||||||
component: parseItem({
|
|
||||||
...parsed,
|
...parsed,
|
||||||
damage:
|
damage:
|
||||||
parsed.damage > 0
|
parsed.damage > 0
|
||||||
|
@ -267,11 +230,10 @@ function parseItemDefinition(obj: unknown): ParsedComponent {
|
||||||
abilities: parsed.abilities,
|
abilities: parsed.abilities,
|
||||||
tweak: "",
|
tweak: "",
|
||||||
temper: "",
|
temper: "",
|
||||||
}),
|
});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseMethodDefinition(obj: unknown): ParsedComponent {
|
function parseMethodDefinition(obj: unknown): Method {
|
||||||
const parsed = MethodSchema.parse(obj);
|
const parsed = MethodSchema.parse(obj);
|
||||||
|
|
||||||
// Prefer `abilities` if defined, otherwise
|
// Prefer `abilities` if defined, otherwise
|
||||||
|
@ -310,40 +272,29 @@ function parseMethodDefinition(obj: unknown): ParsedComponent {
|
||||||
abilities: abilities,
|
abilities: abilities,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return parseMethod(method);
|
||||||
type: "method",
|
|
||||||
component: parseMethod(method),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseResourceDefinition(obj: unknown): ParsedComponent {
|
function parseResourceDefinition(obj: unknown): Resource {
|
||||||
const parsed = ResourceSchema.parse(obj);
|
const parsed = ResourceSchema.parse(obj);
|
||||||
|
return parseResource(parsed);
|
||||||
return {
|
|
||||||
type: "resource",
|
|
||||||
component: parseResource(parsed),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseRuleDefinition(obj: unknown): ParsedComponent {
|
function parseRuleDefinition(obj: unknown): Rule {
|
||||||
const parsed = RuleSchema.parse(obj);
|
const parsed = RuleSchema.parse(obj);
|
||||||
|
|
||||||
return {
|
return parseRule(parsed);
|
||||||
type: "rule",
|
|
||||||
component: parseRule(parsed),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSpeciesDefinition(obj: unknown): ParsedComponent {
|
function parseSpeciesDefinition(obj: unknown): Species {
|
||||||
const parsed = SpeciesSchema.parse(obj);
|
const parsed = SpeciesSchema.parse(obj);
|
||||||
|
|
||||||
return {
|
return parseSpecies(parsed);
|
||||||
type: "species",
|
|
||||||
component: parseSpecies(parsed),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parsePlaybillComponent(obj: unknown): ParsedComponent | null {
|
export function parsePlaybillComponent(
|
||||||
|
obj: unknown,
|
||||||
|
): AnyPlaybillComponent | null {
|
||||||
const baseParse = Base.parse(obj);
|
const baseParse = Base.parse(obj);
|
||||||
|
|
||||||
if (baseParse.$hidden) {
|
if (baseParse.$hidden) {
|
||||||
|
|
18
src/index.ts
18
src/index.ts
|
@ -21,17 +21,17 @@ enum ExitCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processBinding({ inputFilePath, options }: CLIArguments) {
|
async function processBinding({ inputFilePath, options }: CLIArguments) {
|
||||||
// -- BINDING FILE -- //
|
// Load the binding
|
||||||
const bindingPath = await resolveBindingPath(inputFilePath);
|
const bindingPath = await resolveBindingPath(inputFilePath);
|
||||||
const binding = await loadFromBinding(bindingPath);
|
const binding = await loadFromBinding(bindingPath);
|
||||||
|
|
||||||
// -- EXIT EARLY IF JUST CHECKING VALIDATION --//
|
// If --check is specified, exit early
|
||||||
if (options.check) {
|
if (options.check) {
|
||||||
console.log(chalk.green("Playbill validated successfully"));
|
console.log(chalk.green("Playbill validated successfully"));
|
||||||
return ExitCode.Success;
|
return ExitCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- SERIALIZE USING RENDERER --//
|
// Serialize (default: JSON)
|
||||||
let serializedPlaybill = "";
|
let serializedPlaybill = "";
|
||||||
|
|
||||||
switch (options.renderer) {
|
switch (options.renderer) {
|
||||||
|
@ -48,12 +48,13 @@ async function processBinding({ inputFilePath, options }: CLIArguments) {
|
||||||
throw new CLIError(`Unknown renderer: ${options.renderer}`);
|
throw new CLIError(`Unknown renderer: ${options.renderer}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to disk if an outfile is specified
|
// Write to disk if --outfile is specified
|
||||||
if (options.outfile !== "") {
|
if (options.outfile !== "") {
|
||||||
await Bun.write(options.outfile, serializedPlaybill);
|
await Bun.write(options.outfile, serializedPlaybill);
|
||||||
return ExitCode.Success;
|
return ExitCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, write to stdout
|
||||||
console.log(serializedPlaybill);
|
console.log(serializedPlaybill);
|
||||||
return ExitCode.Success;
|
return ExitCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -62,26 +63,27 @@ async function main(): Promise<number> {
|
||||||
const cliArguments = parseCLIArguments(Bun.argv.slice(2));
|
const cliArguments = parseCLIArguments(Bun.argv.slice(2));
|
||||||
const { options } = cliArguments;
|
const { options } = cliArguments;
|
||||||
|
|
||||||
// -- HELP TEXT -- //
|
// If --help is specified, print usage and exit
|
||||||
if (options.help) {
|
if (options.help) {
|
||||||
console.log(USAGE);
|
console.log(USAGE);
|
||||||
return ExitCode.Success;
|
return ExitCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Processing ${cliArguments.inputFilePath}`);
|
|
||||||
let lastProcessResult = await processBinding(cliArguments);
|
let lastProcessResult = await processBinding(cliArguments);
|
||||||
|
|
||||||
if (options.watch) {
|
if (options.watch) {
|
||||||
const watchDir = getAbsoluteDirname(cliArguments.inputFilePath);
|
const watchDir = getAbsoluteDirname(cliArguments.inputFilePath);
|
||||||
|
|
||||||
console.log(`Watching ${watchDir} for changes`);
|
console.log(`Watching ${watchDir} for changes...`);
|
||||||
|
|
||||||
const watcher = watch(watchDir, {
|
const watcher = watch(watchDir, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
for await (const event of watcher) {
|
for await (const event of watcher) {
|
||||||
console.log(`Detected ${event.eventType} on ${event.filename}`);
|
console.log(
|
||||||
|
`Detected ${event.eventType} on ${event.filename}. Reprocessing...`,
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
lastProcessResult = await processBinding(cliArguments);
|
lastProcessResult = await processBinding(cliArguments);
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import {
|
import { type AnyPlaybillComponent, Playbill } from "@proscenium/playbill";
|
||||||
type Ability,
|
|
||||||
type Blueprint,
|
|
||||||
type Item,
|
|
||||||
type Method,
|
|
||||||
Playbill,
|
|
||||||
type Resource,
|
|
||||||
type Rule,
|
|
||||||
type Species,
|
|
||||||
} from "@proscenium/playbill";
|
|
||||||
import { Glob } from "bun";
|
import { Glob } from "bun";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
import { loadYAMLFileOrFail } from "#util";
|
import { loadYAMLFileOrFail } from "#util";
|
||||||
|
@ -33,11 +24,7 @@ const BindingSchema = z.object({
|
||||||
terms: z.record(z.string(), z.string()).default({}),
|
terms: z.record(z.string(), z.string()).default({}),
|
||||||
});
|
});
|
||||||
|
|
||||||
type Binding = z.infer<typeof BindingSchema>;
|
|
||||||
|
|
||||||
export interface BoundPlaybill {
|
export interface BoundPlaybill {
|
||||||
_raw: Binding;
|
|
||||||
|
|
||||||
// File information
|
// File information
|
||||||
bindingFilePath: string;
|
bindingFilePath: string;
|
||||||
bindingFileDirname: string;
|
bindingFileDirname: string;
|
||||||
|
@ -93,7 +80,12 @@ export async function loadFromBinding(
|
||||||
const fileGlobs = binding.files;
|
const fileGlobs = binding.files;
|
||||||
const bindingFileDirname = path.dirname(resolvedBindingPath);
|
const bindingFileDirname = path.dirname(resolvedBindingPath);
|
||||||
|
|
||||||
const playbill = new Playbill();
|
const playbill = new Playbill(
|
||||||
|
binding.name,
|
||||||
|
binding.author,
|
||||||
|
binding.description,
|
||||||
|
binding.version,
|
||||||
|
);
|
||||||
|
|
||||||
// If this is extending another binding, load that first
|
// If this is extending another binding, load that first
|
||||||
for (const includePath of binding.include) {
|
for (const includePath of binding.include) {
|
||||||
|
@ -151,86 +143,15 @@ export async function loadFromBinding(
|
||||||
|
|
||||||
await Promise.all(fileLoadPromises);
|
await Promise.all(fileLoadPromises);
|
||||||
|
|
||||||
// Decorate the playbill with the binding metadata
|
// Aggregate all loaded components
|
||||||
playbill.name = binding.name;
|
const loadedComponents: AnyPlaybillComponent[] = [];
|
||||||
playbill.author = binding.author ?? "Anonymous";
|
|
||||||
playbill.version = binding.version;
|
|
||||||
playbill.description = binding.description ?? "";
|
|
||||||
|
|
||||||
const abilities: Ability[] = [];
|
|
||||||
const bluprints: Blueprint[] = [];
|
|
||||||
const methods: Method[] = [];
|
|
||||||
const species: Species[] = [];
|
|
||||||
const items: Item[] = [];
|
|
||||||
const rules: Rule[] = [];
|
|
||||||
const resources: Resource[] = [];
|
|
||||||
|
|
||||||
// Aggregate all components before adding to playbill to allow for
|
|
||||||
// ensuring components are added in a valid order
|
|
||||||
for (const file of componentFiles) {
|
for (const file of componentFiles) {
|
||||||
// Load components from the file into the playbill
|
loadedComponents.push(...file.components);
|
||||||
for (const component of file.components) {
|
|
||||||
switch (component.type) {
|
|
||||||
case "ability":
|
|
||||||
abilities.push(component.component);
|
|
||||||
break;
|
|
||||||
case "blueprint":
|
|
||||||
bluprints.push(component.component);
|
|
||||||
break;
|
|
||||||
case "method":
|
|
||||||
methods.push(component.component);
|
|
||||||
break;
|
|
||||||
case "species":
|
|
||||||
species.push(component.component);
|
|
||||||
break;
|
|
||||||
case "item":
|
|
||||||
items.push(component.component);
|
|
||||||
break;
|
|
||||||
case "rule":
|
|
||||||
rules.push(component.component);
|
|
||||||
break;
|
|
||||||
case "resource":
|
|
||||||
resources.push(component.component);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error("Unknown component type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add resources first
|
// Add all components to the playbill
|
||||||
for (const resource of resources) {
|
// (This method ensures proper addition order maintain correctness)
|
||||||
playbill.addResource(resource);
|
playbill.addManyComponents(loadedComponents);
|
||||||
}
|
|
||||||
// Add abilities before methods, species, and blueprints
|
|
||||||
for (const ability of abilities) {
|
|
||||||
playbill.addAbility(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add species before blueprints
|
|
||||||
for (const specie of species) {
|
|
||||||
playbill.addSpecies(specie);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add methods after abilities
|
|
||||||
for (const method of methods) {
|
|
||||||
playbill.addMethod(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add items
|
|
||||||
for (const item of items) {
|
|
||||||
playbill.addItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add blueprints after methods, species, items, and abilities
|
|
||||||
for (const blueprint of bluprints) {
|
|
||||||
playbill.addBlueprint(blueprint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add rules
|
|
||||||
for (const rule of rules) {
|
|
||||||
playbill.addRule(rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all definitions
|
// Add all definitions
|
||||||
for (const [term, definition] of Object.entries(binding.terms)) {
|
for (const [term, definition] of Object.entries(binding.terms)) {
|
||||||
|
@ -238,7 +159,6 @@ export async function loadFromBinding(
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_raw: binding,
|
|
||||||
bindingFilePath: bindingPath,
|
bindingFilePath: bindingPath,
|
||||||
bindingFileDirname,
|
bindingFileDirname,
|
||||||
files: filePathsWithoutBindingFile,
|
files: filePathsWithoutBindingFile,
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { type ParsedComponent, parsePlaybillComponent } from "define";
|
import { parsePlaybillComponent } from "define";
|
||||||
import YAML, { YAMLParseError } from "yaml";
|
import YAML, { YAMLParseError } from "yaml";
|
||||||
import { ZodError } from "zod";
|
import { ZodError } from "zod";
|
||||||
import { loadFileOrFail } from "#util";
|
import { loadFileOrFail } from "#util";
|
||||||
import { MalformedResourceFileError } from "./errors";
|
import { MalformedResourceFileError } from "./errors";
|
||||||
import { toSlug } from "./slug";
|
import { toSlug } from "./slug";
|
||||||
|
import type { AnyPlaybillComponent } from "@proscenium/playbill";
|
||||||
|
|
||||||
type FileFormat = "yaml" | "markdown";
|
type FileFormat = "yaml" | "markdown";
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ function extractMarkdown(content: string): string {
|
||||||
function parseYAMLResourceFile(
|
function parseYAMLResourceFile(
|
||||||
filePath: string,
|
filePath: string,
|
||||||
text: string,
|
text: string,
|
||||||
): ParsedComponent[] {
|
): AnyPlaybillComponent[] {
|
||||||
const parsedDocs = YAML.parseAllDocuments(text);
|
const parsedDocs = YAML.parseAllDocuments(text);
|
||||||
|
|
||||||
if (parsedDocs.some((doc) => doc.toJS() === null)) {
|
if (parsedDocs.some((doc) => doc.toJS() === null)) {
|
||||||
|
@ -62,7 +63,7 @@ function parseYAMLResourceFile(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const collection: ParsedComponent[] = [];
|
const collection: AnyPlaybillComponent[] = [];
|
||||||
|
|
||||||
for (const doc of parsedDocs) {
|
for (const doc of parsedDocs) {
|
||||||
const raw = doc.toJS();
|
const raw = doc.toJS();
|
||||||
|
@ -78,7 +79,7 @@ function parseYAMLResourceFile(
|
||||||
function parseMarkdownResourceFile(
|
function parseMarkdownResourceFile(
|
||||||
filePath: string,
|
filePath: string,
|
||||||
text: string,
|
text: string,
|
||||||
): ParsedComponent[] {
|
): AnyPlaybillComponent[] {
|
||||||
try {
|
try {
|
||||||
const defaultName = path.basename(filePath, ".md");
|
const defaultName = path.basename(filePath, ".md");
|
||||||
const defaultId = toSlug(defaultName);
|
const defaultId = toSlug(defaultName);
|
||||||
|
@ -124,7 +125,7 @@ export class ComponentFile {
|
||||||
private _filePath: string;
|
private _filePath: string;
|
||||||
private _raw = "";
|
private _raw = "";
|
||||||
private _format: FileFormat;
|
private _format: FileFormat;
|
||||||
private _components: ParsedComponent[] = [];
|
private _components: AnyPlaybillComponent[] = [];
|
||||||
private _basename: string;
|
private _basename: string;
|
||||||
|
|
||||||
constructor(filePath: string) {
|
constructor(filePath: string) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { toSlug } from "./slug";
|
||||||
import rehypeRaw from "rehype-raw";
|
import rehypeRaw from "rehype-raw";
|
||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
import rehypeShiftHeading from "rehype-shift-heading";
|
import rehypeShiftHeading from "rehype-shift-heading";
|
||||||
import type { TaggedComponent } from "@proscenium/playbill";
|
import type { AnyPlaybillComponent } from "@proscenium/playbill";
|
||||||
|
|
||||||
export type MarkdownParserFunction = (input: string) => Promise<string>;
|
export type MarkdownParserFunction = (input: string) => Promise<string>;
|
||||||
|
|
||||||
|
@ -26,9 +26,7 @@ export function createMarkdownRenderer(
|
||||||
.use(remarkGfm)
|
.use(remarkGfm)
|
||||||
.use(remarkWikiLink, {
|
.use(remarkWikiLink, {
|
||||||
aliasDivider: "|",
|
aliasDivider: "|",
|
||||||
permalinks: binding.playbill
|
permalinks: binding.playbill.allComponents().map((c) => c.id),
|
||||||
.allComponents()
|
|
||||||
.map((c) => `${c.component.id}`),
|
|
||||||
pageResolver: (permalink: string) => {
|
pageResolver: (permalink: string) => {
|
||||||
return [toSlug(permalink)];
|
return [toSlug(permalink)];
|
||||||
},
|
},
|
||||||
|
@ -54,21 +52,19 @@ export async function compileMarkdownInPlaybill(
|
||||||
const playbill = boundPlaybill.playbill;
|
const playbill = boundPlaybill.playbill;
|
||||||
|
|
||||||
// Define a processor function to iterate over all components and process their markdown
|
// Define a processor function to iterate over all components and process their markdown
|
||||||
const processMarkdownInComponent = async (entry: TaggedComponent) => {
|
const processMarkdownInComponent = async (entry: AnyPlaybillComponent) => {
|
||||||
entry.component.description = await renderMarkdown(
|
entry.description = await renderMarkdown(entry.description);
|
||||||
entry.component.description,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (entry.type === "resource" && entry.component.type === "table") {
|
if (entry._component === "resource" && entry.type === "table") {
|
||||||
const newData: string[][] = [];
|
const newData: string[][] = [];
|
||||||
for (const row of entry.component.data) {
|
for (const row of entry.data) {
|
||||||
const newRow: string[] = [];
|
const newRow: string[] = [];
|
||||||
for (const cell of row) {
|
for (const cell of row) {
|
||||||
newRow.push(await renderMarkdown(cell));
|
newRow.push(await renderMarkdown(cell));
|
||||||
}
|
}
|
||||||
newData.push(newRow);
|
newData.push(newRow);
|
||||||
}
|
}
|
||||||
entry.component.data = newData;
|
entry.data = newData;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { Section } from "./base/section";
|
import { Section } from "./base/section";
|
||||||
|
|
||||||
interface GlossaryTableProps {
|
interface GlossaryTableProps {
|
||||||
glossary: Record<string, string[]>;
|
terms: [string, string[]][];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GlossaryTable({ glossary }: GlossaryTableProps) {
|
export function GlossaryTable({ terms }: GlossaryTableProps) {
|
||||||
return (
|
return (
|
||||||
<Section type="glossary" componentId="glossary" title="Glossary">
|
<Section type="glossary" componentId="glossary" title="Glossary">
|
||||||
<div className="glossary-content">
|
<div className="glossary-content">
|
||||||
<dl>
|
<dl>
|
||||||
{Object.entries(glossary).map(([term, defs]) => {
|
{terms.map(([term, defs]) => {
|
||||||
return (
|
return (
|
||||||
<div key={term}>
|
<div key={term}>
|
||||||
<dt>{term}</dt>
|
<dt>{term}</dt>
|
||||||
|
|
|
@ -17,7 +17,12 @@ export function MethodSection({ method, playbill }: MethodSectionProps) {
|
||||||
<h3>Rank {i + 1}</h3>
|
<h3>Rank {i + 1}</h3>
|
||||||
<div className="method-rank-content" style={{ gridTemplateColumns }}>
|
<div className="method-rank-content" style={{ gridTemplateColumns }}>
|
||||||
{rank.map((abilityId) => {
|
{rank.map((abilityId) => {
|
||||||
const ability = playbill.abilities[abilityId];
|
const ability = playbill.getAbility(abilityId);
|
||||||
|
|
||||||
|
if (ability === null) {
|
||||||
|
throw new Error(`Ability not found: ${abilityId}`);
|
||||||
|
}
|
||||||
|
|
||||||
return <AbilityCard ability={ability} key={abilityId} />;
|
return <AbilityCard ability={ability} key={abilityId} />;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Playbill } from "@proscenium/playbill";
|
import { Playbill } from "@proscenium/playbill";
|
||||||
import sortBy from "lodash-es/sortBy";
|
|
||||||
import { compileMarkdownInPlaybill, type BoundPlaybill } from "#lib";
|
import { compileMarkdownInPlaybill, type BoundPlaybill } from "#lib";
|
||||||
import { GlossaryTable } from "./component/glossary";
|
import { GlossaryTable } from "./component/glossary";
|
||||||
import { PageHeader } from "./component/header";
|
import { PageHeader } from "./component/header";
|
||||||
|
@ -19,9 +18,6 @@ export async function renderPlaybillToHTML(
|
||||||
const playbill = Playbill.fromSerialized(boundPlaybill.playbill.serialize());
|
const playbill = Playbill.fromSerialized(boundPlaybill.playbill.serialize());
|
||||||
await compileMarkdownInPlaybill(boundPlaybill);
|
await compileMarkdownInPlaybill(boundPlaybill);
|
||||||
|
|
||||||
// Soprt rules by their order prop
|
|
||||||
const rulesByOrder = sortBy(Object.values(playbill.rules), "order");
|
|
||||||
|
|
||||||
// Prepare stylesheet
|
// Prepare stylesheet
|
||||||
const cssParts: string[] = [];
|
const cssParts: string[] = [];
|
||||||
|
|
||||||
|
@ -38,7 +34,7 @@ export async function renderPlaybillToHTML(
|
||||||
const body = renderToString(
|
const body = renderToString(
|
||||||
<>
|
<>
|
||||||
<article id="species" className="view">
|
<article id="species" className="view">
|
||||||
{Object.values(playbill.species).map((species) => (
|
{playbill.allSpecies.map((species) => (
|
||||||
<SpeciesSection
|
<SpeciesSection
|
||||||
key={species.id}
|
key={species.id}
|
||||||
species={species}
|
species={species}
|
||||||
|
@ -48,29 +44,29 @@ export async function renderPlaybillToHTML(
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article id="methods" className="view" style={{ display: "none" }}>
|
<article id="methods" className="view" style={{ display: "none" }}>
|
||||||
{Object.values(playbill.methods).map((method) => (
|
{playbill.allMethods.map((method) => (
|
||||||
<MethodSection key={method.id} method={method} playbill={playbill} />
|
<MethodSection key={method.id} method={method} playbill={playbill} />
|
||||||
))}
|
))}
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article id="items" className="view" style={{ display: "none" }}>
|
<article id="items" className="view" style={{ display: "none" }}>
|
||||||
{Object.values(playbill.items).map((item) => (
|
{playbill.allItems.map((item) => (
|
||||||
<ItemCard key={item.id} item={item} />
|
<ItemCard key={item.id} item={item} />
|
||||||
))}
|
))}
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article id="rules" className="view" style={{ display: "none" }}>
|
<article id="rules" className="view" style={{ display: "none" }}>
|
||||||
{rulesByOrder.map((rule) => (
|
{playbill.allRules.map((rule) => (
|
||||||
<RuleSection key={rule.id} rule={rule} />
|
<RuleSection key={rule.id} rule={rule} />
|
||||||
))}
|
))}
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article id="glossary" className="view" style={{ display: "none" }}>
|
<article id="glossary" className="view" style={{ display: "none" }}>
|
||||||
{<GlossaryTable glossary={playbill.glossary} />}
|
{<GlossaryTable terms={playbill.allDefinitions} />}
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article id="resources" className="view" style={{ display: "none" }}>
|
<article id="resources" className="view" style={{ display: "none" }}>
|
||||||
{Object.values(playbill.resources).map((resource) => (
|
{playbill.allResources.map((resource) => (
|
||||||
<ResourceSection key={resource.id} resource={resource} />
|
<ResourceSection key={resource.id} resource={resource} />
|
||||||
))}
|
))}
|
||||||
</article>
|
</article>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue