genre-profile.ts 1.1 KB

123456789101112131415161718192021222324252627282930313233343536
  1. import { z } from "zod";
  2. import yaml from "js-yaml";
  3. export const GenreProfileSchema = z.object({
  4. name: z.string(),
  5. id: z.string(),
  6. language: z.enum(["zh", "en"]).default("zh"),
  7. chapterTypes: z.array(z.string()),
  8. fatigueWords: z.array(z.string()),
  9. numericalSystem: z.boolean().default(false),
  10. powerScaling: z.boolean().default(false),
  11. eraResearch: z.boolean().default(false),
  12. pacingRule: z.string().default(""),
  13. satisfactionTypes: z.array(z.string()).default([]),
  14. auditDimensions: z.array(z.number()).default([]),
  15. });
  16. export type GenreProfile = z.infer<typeof GenreProfileSchema>;
  17. export interface ParsedGenreProfile {
  18. readonly profile: GenreProfile;
  19. readonly body: string;
  20. }
  21. export function parseGenreProfile(raw: string): ParsedGenreProfile {
  22. const fmMatch = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
  23. if (!fmMatch) {
  24. throw new Error("Genre profile missing YAML frontmatter (--- ... ---)");
  25. }
  26. const frontmatter = yaml.load(fmMatch[1]) as Record<string, unknown>;
  27. const profile = GenreProfileSchema.parse(frontmatter);
  28. const body = fmMatch[2].trim();
  29. return { profile, body };
  30. }