@elvishscout/mdstory 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import handlebars from "handlebars";
1
+ import Handlebars from "handlebars";
2
2
  import MarkdownIt from "markdown-it";
3
3
  import pluginAttrs from "markdown-it-attrs";
4
4
  const valueType = (value) => {
@@ -58,47 +58,56 @@ const createSubmitButtonHtml = ({ tagMap = {}, target, children, }) => {
58
58
  };
59
59
  return createElementHtml(tag, buttonAttrs, children);
60
60
  };
61
- const createInputMarkdown = ({ name, type }) => {
62
- if (type === "boolean") {
63
- return `[ ${name}? ]`;
64
- }
65
- return `[> ${name} <]`;
66
- };
67
- const useHelper = ({ inputs, sets, navs }, options) => {
61
+ const useHelper = ({ inputs, sets, navs }, assets, options) => {
68
62
  return {
69
63
  input(type, opt) {
70
64
  for (const name in opt.hash) {
65
+ let result;
71
66
  const value = opt.hash[name];
72
67
  inputs.push({ name, type, value });
73
68
  if (options.format === "html") {
74
- return createInputHtml({ name, type, value, ...options });
69
+ result = createInputHtml({ name, type, value, ...options });
75
70
  }
76
- return createInputMarkdown({ name, type });
71
+ else {
72
+ if (type === "boolean") {
73
+ result = `[? _${name}_]`;
74
+ }
75
+ else {
76
+ result = `[> _${name}_]`;
77
+ }
78
+ }
79
+ return new Handlebars.SafeString(result);
77
80
  }
78
81
  return "";
79
82
  },
80
83
  set(opt) {
81
- return Object.entries(opt.hash)
82
- .map(([name, value]) => {
84
+ for (const name in opt.hash) {
85
+ const value = opt.hash[name];
83
86
  const type = valueType(value);
84
87
  sets.push({ name, type, value });
85
- if (options.format === "html") {
86
- return createInputHtml({ name, type, value, readonly: true, ...options });
87
- }
88
- return "";
89
- })
90
- .join("");
88
+ }
89
+ return "";
91
90
  },
92
91
  nav(target, opt) {
93
- const text = opt.fn(target).trim();
92
+ let result;
93
+ const text = opt.fn(this).trim();
94
94
  navs.push({ text, target });
95
95
  if (options.format === "html") {
96
- return createSubmitButtonHtml({ target: target ?? "", children: text, ...options });
96
+ result = createSubmitButtonHtml({ target: target ?? "", children: text, ...options });
97
97
  }
98
- return "";
98
+ else {
99
+ result = `[@ __${text}__]`;
100
+ }
101
+ return new Handlebars.SafeString(result);
99
102
  },
100
- br(num) {
101
- return new Array(num ?? 1).fill("<br>").join();
103
+ asset(name) {
104
+ return new Handlebars.SafeString(assets[name]?.url ?? "");
105
+ },
106
+ mime(name) {
107
+ return new Handlebars.SafeString(assets[name]?.mime ?? "");
108
+ },
109
+ linebreak(n) {
110
+ return new Handlebars.SafeString("\n".repeat(n ?? 1));
102
111
  },
103
112
  };
104
113
  };
@@ -109,20 +118,23 @@ export class Chapter {
109
118
  this.template = template;
110
119
  this.hooks = hooks;
111
120
  }
112
- render(scope, options) {
121
+ render(scope, assets = {}, options) {
113
122
  const md = new MarkdownIt({ html: true }).use(pluginAttrs);
114
123
  const fields = {
115
124
  inputs: [],
116
125
  sets: [],
117
126
  navs: [],
118
127
  };
119
- const handle = handlebars.create();
120
- handle.registerHelper(useHelper(fields, options));
121
- let text = handle.compile(this.template)(scope);
128
+ const helpers = useHelper(fields, assets, options);
129
+ let text;
122
130
  if (options.format === "html") {
131
+ text = Handlebars.compile(this.template)(scope, { helpers });
123
132
  text = md.render(text);
124
133
  text = createElementHtml("input", { type: "submit", disabled: true, hidden: true }) + text;
125
134
  }
135
+ else {
136
+ text = Handlebars.compile(this.template, { noEscape: true })(scope, { helpers });
137
+ }
126
138
  return { text, ...fields };
127
139
  }
128
140
  }
@@ -1,9 +1,17 @@
1
1
  import { z } from "zod";
2
2
  export const ValueSchema = z.any().transform((v) => v);
3
3
  export const ScopeSchema = z.record(ValueSchema);
4
+ export const AssetSchema = z.union([
5
+ z.string().transform((url) => ({ url, mime: undefined })),
6
+ z.object({ url: z.string(), mime: z.string().optional() }),
7
+ ]);
8
+ export const AssetsSchema = z.record(AssetSchema);
4
9
  export const MetadataSchema = z.object({
5
- title: z.string().default(""),
6
- globals: ScopeSchema.default({}),
10
+ title: z.string().optional(),
11
+ author: z.string().optional(),
12
+ email: z.string().optional(),
13
+ globals: ScopeSchema.optional(),
14
+ assets: AssetsSchema.optional(),
7
15
  });
8
16
  const TargetSchema = z.string().or(z.null());
9
17
  export const StoryHooksSchema = z
@@ -1,4 +1,5 @@
1
1
  export * from "./definitions.js";
2
2
  export * from "./story.js";
3
+ export * from "./parser.js";
3
4
  export * from "./chapter.js";
4
5
  export * from "./error.js";
@@ -0,0 +1,86 @@
1
+ import yaml from "js-yaml";
2
+ import MarkdownIt from "markdown-it";
3
+ import pluginFrontMatter from "markdown-it-front-matter";
4
+ import pluginAttrs from "markdown-it-attrs";
5
+ import { MetadataSchema } from "./definitions.js";
6
+ import { DuplicateIdError, EmptyChapterIdError, InvalidMetadataError } from "./error.js";
7
+ export const parseStoryContent = (content) => {
8
+ const md = new MarkdownIt({ html: true }).use(pluginAttrs).use(pluginFrontMatter, () => { });
9
+ const tokens = md.parse(content, {});
10
+ let metadata = MetadataSchema.parse({});
11
+ let storyScript = "";
12
+ let stylesheet = "";
13
+ const ignoredRanges = [];
14
+ const divisions = [];
15
+ tokens.forEach((token, i) => {
16
+ if (token.type === "front_matter" && token.meta) {
17
+ try {
18
+ const frontMatter = MetadataSchema.parse(yaml.load(token.meta));
19
+ metadata = Object.assign(metadata, frontMatter);
20
+ }
21
+ catch {
22
+ throw new InvalidMetadataError(token.meta);
23
+ }
24
+ }
25
+ else if (token.type === "heading_open" && token.tag === "h1" && token.level === 0 && token.map) {
26
+ const lineno = token.map[0];
27
+ let id = token.attrs?.find(([key]) => key === "id")?.[1] ?? "";
28
+ let title = "";
29
+ const nextToken = tokens[i + 1];
30
+ if (nextToken && nextToken.type === "inline") {
31
+ const content = nextToken.content.trim();
32
+ id || (id = content);
33
+ title = content;
34
+ }
35
+ if (!id) {
36
+ throw new EmptyChapterIdError();
37
+ }
38
+ if (divisions.find(({ id: _id }) => id === _id)) {
39
+ throw new DuplicateIdError(id);
40
+ }
41
+ divisions.push({ id, title, lineno, script: "" });
42
+ }
43
+ else if (token.type === "html_block" && token.map) {
44
+ let regres;
45
+ if ((regres = /^[\s]*<script>(.*)<\/script>[\s]*$/s.exec(token.content))) {
46
+ const script = regres[1].trim();
47
+ if (script) {
48
+ if (divisions.length === 0) {
49
+ storyScript = script;
50
+ }
51
+ else {
52
+ divisions[divisions.length - 1].script = script;
53
+ }
54
+ ignoredRanges.push(token.map);
55
+ }
56
+ }
57
+ else if ((regres = /^[\s]*<style>(.*)<\/style>[\s]*$/s.exec(token.content))) {
58
+ const style = regres[1].trim();
59
+ stylesheet += style;
60
+ ignoredRanges.push(token.map);
61
+ }
62
+ }
63
+ });
64
+ const lines = content.split("\n").map((line, i) => {
65
+ if (ignoredRanges.find(([from, to]) => i >= from && i < to)) {
66
+ return null;
67
+ }
68
+ return line;
69
+ });
70
+ const chapterEntries = divisions.map(({ id, title, lineno, script }, i) => {
71
+ const template = lines
72
+ .slice(lineno, divisions[i + 1]?.lineno)
73
+ .filter((line) => line !== null)
74
+ .join("\n");
75
+ return [id, { title, template, script }];
76
+ });
77
+ const chapters = Object.fromEntries(chapterEntries);
78
+ const entry = chapterEntries[0]?.[0] || null;
79
+ return {
80
+ metadata,
81
+ chapters,
82
+ entry,
83
+ script: storyScript,
84
+ stylesheet,
85
+ };
86
+ };
@@ -1,10 +1,6 @@
1
- import yaml from "js-yaml";
2
- import MarkdownIt from "markdown-it";
3
- import pluginFrontMatter from "markdown-it-front-matter";
4
- import pluginAttrs from "markdown-it-attrs";
5
- import { MetadataSchema, StoryHooksSchema, ChapterHooksSchema, } from "./definitions.js";
1
+ import { ChapterHooksSchema, StoryHooksSchema, } from "./definitions.js";
6
2
  import { Chapter } from "./chapter.js";
7
- import { ChapterNotFoundError, DuplicateIdError, EmptyChapterIdError, InvalidInputError, InvalidMetadataError, } from "./error.js";
3
+ import { ChapterNotFoundError, InvalidInputError } from "./error.js";
8
4
  const parstInput = (type, text) => {
9
5
  if (type === "boolean") {
10
6
  return text === "on";
@@ -30,114 +26,36 @@ const parseFormData = (formData, { inputs, sets }) => {
30
26
  }));
31
27
  return { target, updates };
32
28
  };
33
- export const parseStoryContent = (content) => {
34
- const md = new MarkdownIt({ html: true }).use(pluginAttrs).use(pluginFrontMatter, () => { });
35
- const tokens = md.parse(content, {});
36
- let metadata = MetadataSchema.parse({});
37
- let storyScript = "";
38
- let stylesheet = "";
39
- const ignoredRanges = [];
40
- const divisions = [];
41
- tokens.forEach((token, i) => {
42
- if (token.type === "front_matter" && token.meta) {
43
- try {
44
- const frontMatter = MetadataSchema.parse(yaml.load(token.meta));
45
- metadata = { ...metadata, ...frontMatter };
46
- }
47
- catch {
48
- throw new InvalidMetadataError(token.meta);
49
- }
50
- }
51
- else if (token.type === "heading_open" && token.tag === "h1" && token.level === 0 && token.map) {
52
- const lineno = token.map[0];
53
- let id = token.attrs?.find(([key]) => key === "id")?.[1] ?? "";
54
- let title = "";
55
- const nextToken = tokens[i + 1];
56
- if (nextToken && nextToken.type === "inline") {
57
- const content = nextToken.content.trim();
58
- id || (id = content);
59
- title = content;
60
- }
61
- if (!id) {
62
- throw new EmptyChapterIdError();
63
- }
64
- if (divisions.find(({ id: _id }) => id === _id)) {
65
- throw new DuplicateIdError(id);
66
- }
67
- divisions.push({ id, title, lineno, script: "" });
68
- }
69
- else if (token.type === "html_block" && token.map) {
70
- let regres;
71
- if ((regres = /^[\s]*<script>(.*)<\/script>[\s]*$/s.exec(token.content))) {
72
- const script = regres[1].trim();
73
- if (script) {
74
- if (divisions.length === 0) {
75
- storyScript = script;
76
- }
77
- else {
78
- divisions[divisions.length - 1].script = script;
79
- }
80
- ignoredRanges.push(token.map);
81
- }
82
- }
83
- else if ((regres = /^[\s]*<style>(.*)<\/style>[\s]*$/s.exec(token.content))) {
84
- const style = regres[1].trim();
85
- stylesheet += style;
86
- ignoredRanges.push(token.map);
87
- }
88
- }
89
- });
90
- const lines = content.split("\n").map((line, i) => {
91
- if (ignoredRanges.find(([from, to]) => i >= from && i < to)) {
92
- return null;
93
- }
94
- return line;
95
- });
96
- const chapterEntries = divisions.map(({ id, title, lineno, script }, i) => {
97
- const template = lines
98
- .slice(lineno, divisions[i + 1]?.lineno)
99
- .filter((line) => line !== null)
100
- .join("\n");
101
- const hooks = script ? ChapterHooksSchema.parse(new Function(script)()) : {};
102
- return [id, { title, template, hooks }];
103
- });
104
- const chapters = Object.fromEntries(chapterEntries);
105
- const entry = chapterEntries[0]?.[0] || null;
106
- const hooks = storyScript ? StoryHooksSchema.parse(new Function(storyScript)()) : {};
107
- return {
108
- metadata,
109
- chapters,
110
- entry,
111
- hooks,
112
- stylesheet,
113
- };
114
- };
115
29
  export class StoryBase {
116
- constructor({ metadata, chapters, entry, hooks, stylesheet }) {
117
- const realChapters = Object.fromEntries(Object.entries(chapters).map(([id, options]) => {
118
- return [id, new Chapter({ id, ...options })];
30
+ constructor({ metadata, chapters, entry, script, stylesheet }) {
31
+ const realChapters = Object.fromEntries(Object.entries(chapters).map(([id, { title, template, script }]) => {
32
+ const hooks = (script && ChapterHooksSchema.parse(new Function(script)())) || {};
33
+ return [id, new Chapter({ id, title, template, hooks })];
119
34
  }));
120
35
  this.metadata = metadata;
121
- this.globals = metadata.globals;
36
+ this.globals = metadata.globals ?? {};
122
37
  this.chapters = realChapters;
123
38
  this.entry = (entry && realChapters[entry]) || null;
124
- this.hooks = hooks;
39
+ this.hooks = (script && StoryHooksSchema.parse(new Function(script)())) || {};
125
40
  this.stylesheet = stylesheet;
41
+ this.assets = metadata.assets ?? {};
126
42
  }
127
43
  async play(prompt, options) {
128
44
  if (this.hooks.onStart) {
129
45
  this.hooks.onStart(this.globals);
130
46
  }
47
+ const assetsUrl = Object.fromEntries(Object.entries(this.assets).map(([name, { url }]) => [name, url]));
131
48
  let chapter = this.entry;
132
49
  while (chapter) {
133
- let modifiedGlobals = this.globals;
50
+ let scope = this.globals;
51
+ scope = Object.assign(scope, assetsUrl);
134
52
  if (chapter.hooks.onEnter) {
135
53
  const modified = chapter.hooks.onEnter(this.globals);
136
54
  if (modified !== undefined) {
137
- modifiedGlobals = Object.assign(modifiedGlobals, modified);
55
+ scope = Object.assign(scope, modified);
138
56
  }
139
57
  }
140
- const renderResult = chapter.render(modifiedGlobals, options);
58
+ const renderResult = chapter.render(scope, this.assets, options);
141
59
  const promptResult = await prompt({ chapter, ...renderResult });
142
60
  const { target, updates } = promptResult instanceof FormData ? parseFormData(promptResult, renderResult) : promptResult;
143
61
  let modifiedTarget = target;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elvishscout/mdstory",
3
- "version": "0.1.0",
4
- "description": "An interactive story format based on Markdown and Handlebars with JavaScript support",
3
+ "version": "0.1.2",
4
+ "description": "An interactive story format based on Markdown and Handlebars with JavaScript support.",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",
7
7
  "files": [
@@ -10,7 +10,7 @@
10
10
  ],
11
11
  "scripts": {
12
12
  "build": "tsc",
13
- "test": "node ./test/index.test.js"
13
+ "test": "tsx ./test/index.test.ts"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/js-yaml": "^4.0.9",
@@ -19,6 +19,7 @@
19
19
  "@types/node": "^22.14.1",
20
20
  "inquirer": "^12.6.0",
21
21
  "markdown-it-terminal": "^0.4.0",
22
+ "tsx": "^4.19.3",
22
23
  "typescript": "~5.7.2"
23
24
  },
24
25
  "dependencies": {
@@ -36,4 +37,4 @@
36
37
  ],
37
38
  "author": "Jiakai Jiang",
38
39
  "license": "ISC"
39
- }
40
+ }
@@ -1,4 +1,4 @@
1
- import { ValueType, Value, ChapterHooks, Scope } from "./definitions.js";
1
+ import { ValueType, Value, ChapterHooks, Scope, Asset } from "./definitions.js";
2
2
  type MarkdownOptions = {};
3
3
  type HtmlOptions = {
4
4
  tagMap?: Record<string, string>;
@@ -39,6 +39,6 @@ export declare class Chapter {
39
39
  template: string;
40
40
  hooks: ChapterHooks;
41
41
  constructor({ id, title, template, hooks }: ChapterOptions);
42
- render(scope: Scope, options: RenderOptions): RenderResult;
42
+ render(scope: Scope, assets: Record<string, Asset> | undefined, options: RenderOptions): RenderResult;
43
43
  }
44
44
  export {};
@@ -7,15 +7,71 @@ type JsonObject = {
7
7
  type JsonValue = JsonPrimitive | JsonArray | JsonObject;
8
8
  export declare const ValueSchema: z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>;
9
9
  export declare const ScopeSchema: z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>;
10
+ export declare const AssetSchema: z.ZodUnion<[z.ZodEffects<z.ZodString, {
11
+ url: string;
12
+ mime: undefined;
13
+ }, string>, z.ZodObject<{
14
+ url: z.ZodString;
15
+ mime: z.ZodOptional<z.ZodString>;
16
+ }, "strip", z.ZodTypeAny, {
17
+ url: string;
18
+ mime?: string | undefined;
19
+ }, {
20
+ url: string;
21
+ mime?: string | undefined;
22
+ }>]>;
23
+ export declare const AssetsSchema: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodEffects<z.ZodString, {
24
+ url: string;
25
+ mime: undefined;
26
+ }, string>, z.ZodObject<{
27
+ url: z.ZodString;
28
+ mime: z.ZodOptional<z.ZodString>;
29
+ }, "strip", z.ZodTypeAny, {
30
+ url: string;
31
+ mime?: string | undefined;
32
+ }, {
33
+ url: string;
34
+ mime?: string | undefined;
35
+ }>]>>;
10
36
  export declare const MetadataSchema: z.ZodObject<{
11
- title: z.ZodDefault<z.ZodString>;
12
- globals: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>>;
37
+ title: z.ZodOptional<z.ZodString>;
38
+ author: z.ZodOptional<z.ZodString>;
39
+ email: z.ZodOptional<z.ZodString>;
40
+ globals: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>>;
41
+ assets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodEffects<z.ZodString, {
42
+ url: string;
43
+ mime: undefined;
44
+ }, string>, z.ZodObject<{
45
+ url: z.ZodString;
46
+ mime: z.ZodOptional<z.ZodString>;
47
+ }, "strip", z.ZodTypeAny, {
48
+ url: string;
49
+ mime?: string | undefined;
50
+ }, {
51
+ url: string;
52
+ mime?: string | undefined;
53
+ }>]>>>;
13
54
  }, "strip", z.ZodTypeAny, {
14
- title: string;
15
- globals: Record<string, string | number | boolean | JsonArray | JsonObject | null>;
55
+ title?: string | undefined;
56
+ author?: string | undefined;
57
+ email?: string | undefined;
58
+ globals?: Record<string, string | number | boolean | JsonArray | JsonObject | null> | undefined;
59
+ assets?: Record<string, {
60
+ url: string;
61
+ mime: undefined;
62
+ } | {
63
+ url: string;
64
+ mime?: string | undefined;
65
+ }> | undefined;
16
66
  }, {
17
67
  title?: string | undefined;
68
+ author?: string | undefined;
69
+ email?: string | undefined;
18
70
  globals?: Record<string, any> | undefined;
71
+ assets?: Record<string, string | {
72
+ url: string;
73
+ mime?: string | undefined;
74
+ }> | undefined;
19
75
  }>;
20
76
  export declare const StoryHooksSchema: z.ZodObject<{
21
77
  onStart: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>], z.ZodUnknown>, z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>, z.ZodVoid]>>>;
@@ -39,8 +95,22 @@ export declare const ChapterHooksSchema: z.ZodObject<{
39
95
  }>;
40
96
  export type Value = z.infer<typeof ValueSchema>;
41
97
  export type Scope = z.infer<typeof ScopeSchema>;
98
+ export type Asset = z.infer<typeof AssetSchema>;
42
99
  export type Metadata = z.infer<typeof MetadataSchema>;
43
100
  export type StoryHooks = z.infer<typeof StoryHooksSchema>;
44
101
  export type ChapterHooks = z.infer<typeof ChapterHooksSchema>;
45
102
  export type ValueType = "string" | "number" | "boolean" | "object";
103
+ export type ChapterBody = {
104
+ title: string;
105
+ template: string;
106
+ script: string;
107
+ };
108
+ export type StoryBody = {
109
+ metadata: Metadata;
110
+ chapters: Record<string, ChapterBody>;
111
+ entry: string | null;
112
+ script: string;
113
+ stylesheet: string;
114
+ };
115
+ export type StoryAssets = Record<string, string>;
46
116
  export {};
@@ -1,4 +1,5 @@
1
1
  export * from "./definitions.js";
2
2
  export * from "./story.js";
3
+ export * from "./parser.js";
3
4
  export * from "./chapter.js";
4
5
  export * from "./error.js";
@@ -0,0 +1,2 @@
1
+ import { StoryBody } from "./definitions.js";
2
+ export declare const parseStoryContent: (content: string) => StoryBody;
@@ -1,4 +1,4 @@
1
- import { StoryHooks, Scope, Metadata, ChapterHooks } from "./definitions.js";
1
+ import { StoryBody, StoryHooks, Scope, Metadata, Asset } from "./definitions.js";
2
2
  import { Chapter, RenderOptions, RenderResult } from "./chapter.js";
3
3
  export type StoryPrompt = (props: {
4
4
  chapter: Chapter;
@@ -6,19 +6,6 @@ export type StoryPrompt = (props: {
6
6
  target: string | null;
7
7
  updates: Scope;
8
8
  } | FormData>;
9
- type ChapterBody = {
10
- title: string;
11
- template: string;
12
- hooks: ChapterHooks;
13
- };
14
- type StoryBody = {
15
- metadata: Metadata;
16
- chapters: Record<string, ChapterBody>;
17
- entry: string | null;
18
- hooks: StoryHooks;
19
- stylesheet: string;
20
- };
21
- export declare const parseStoryContent: (content: string) => StoryBody;
22
9
  export declare class StoryBase {
23
10
  metadata: Metadata;
24
11
  globals: Scope;
@@ -26,7 +13,7 @@ export declare class StoryBase {
26
13
  entry: Chapter | null;
27
14
  hooks: StoryHooks;
28
15
  stylesheet: string;
29
- constructor({ metadata, chapters, entry, hooks, stylesheet }: StoryBody);
16
+ assets: Record<string, Asset>;
17
+ constructor({ metadata, chapters, entry, script, stylesheet }: StoryBody);
30
18
  play(prompt: StoryPrompt, options: RenderOptions): Promise<void>;
31
19
  }
32
- export {};
@@ -1,44 +0,0 @@
1
- import { ValueType, Value, ChapterHooks, Scope } from "./definitions.js";
2
- type MarkdownOptions = {};
3
- type HtmlOptions = {
4
- tagMap?: Record<string, string>;
5
- };
6
- export type RenderOptions = ({
7
- format: "markdown";
8
- } & MarkdownOptions) | ({
9
- format: "html";
10
- } & HtmlOptions);
11
- type Fields = {
12
- inputs: {
13
- name: string;
14
- type: ValueType;
15
- value: Value;
16
- }[];
17
- sets: {
18
- name: string;
19
- type: ValueType;
20
- value: Value;
21
- }[];
22
- navs: {
23
- text: string;
24
- target: string | null;
25
- }[];
26
- };
27
- export type RenderResult = {
28
- text: string;
29
- } & Fields;
30
- export type ChapterOptions = {
31
- id: string;
32
- title: string;
33
- template: string;
34
- hooks: ChapterHooks;
35
- };
36
- export declare class Chapter {
37
- id: string;
38
- title: string;
39
- template: string;
40
- hooks: ChapterHooks;
41
- constructor({ id, title, template, hooks }: ChapterOptions);
42
- render(scope: Scope, options: RenderOptions): RenderResult;
43
- }
44
- export {};
@@ -1,46 +0,0 @@
1
- import { z } from "zod";
2
- type JsonPrimitive = number | string | boolean | null;
3
- type JsonArray = JsonValue[];
4
- type JsonObject = {
5
- [key: string]: JsonValue;
6
- };
7
- type JsonValue = JsonPrimitive | JsonArray | JsonObject;
8
- export declare const ValueSchema: z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>;
9
- export declare const ScopeSchema: z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>;
10
- export declare const MetadataSchema: z.ZodObject<{
11
- title: z.ZodDefault<z.ZodString>;
12
- globals: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>>;
13
- }, "strip", z.ZodTypeAny, {
14
- title: string;
15
- globals: Record<string, string | number | boolean | JsonArray | JsonObject | null>;
16
- }, {
17
- title?: string | undefined;
18
- globals?: Record<string, any> | undefined;
19
- }>;
20
- export declare const StoryHooksSchema: z.ZodObject<{
21
- onStart: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>], z.ZodUnknown>, z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>, z.ZodVoid]>>>;
22
- }, "strip", z.ZodTypeAny, {
23
- onStart?: ((args_0: Record<string, any>, ...args: unknown[]) => void | Record<string, string | number | boolean | JsonArray | JsonObject | null>) | undefined;
24
- }, {
25
- onStart?: ((args_0: Record<string, string | number | boolean | JsonArray | JsonObject | null>, ...args: unknown[]) => void | Record<string, any>) | undefined;
26
- }>;
27
- export declare const ChapterHooksSchema: z.ZodObject<{
28
- onEnter: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>], z.ZodUnknown>, z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>, z.ZodVoid]>>>;
29
- onLeave: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>, z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>], z.ZodUnknown>, z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>, z.ZodVoid]>>>;
30
- onNavigate: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodUnion<[z.ZodString, z.ZodNull]>, z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>, z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodAny, string | number | boolean | JsonArray | JsonObject | null, any>>], z.ZodUnknown>, z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodNull]>, z.ZodVoid]>>>;
31
- }, "strip", z.ZodTypeAny, {
32
- onEnter?: ((args_0: Record<string, any>, ...args: unknown[]) => void | Record<string, string | number | boolean | JsonArray | JsonObject | null>) | undefined;
33
- onLeave?: ((args_0: Record<string, any>, args_1: Record<string, any>, ...args: unknown[]) => void | Record<string, string | number | boolean | JsonArray | JsonObject | null>) | undefined;
34
- onNavigate?: ((args_0: string | null, args_1: Record<string, any>, args_2: Record<string, any>, ...args: unknown[]) => string | void | null) | undefined;
35
- }, {
36
- onEnter?: ((args_0: Record<string, string | number | boolean | JsonArray | JsonObject | null>, ...args: unknown[]) => void | Record<string, any>) | undefined;
37
- onLeave?: ((args_0: Record<string, string | number | boolean | JsonArray | JsonObject | null>, args_1: Record<string, string | number | boolean | JsonArray | JsonObject | null>, ...args: unknown[]) => void | Record<string, any>) | undefined;
38
- onNavigate?: ((args_0: string | null, args_1: Record<string, string | number | boolean | JsonArray | JsonObject | null>, args_2: Record<string, string | number | boolean | JsonArray | JsonObject | null>, ...args: unknown[]) => string | void | null) | undefined;
39
- }>;
40
- export type Value = z.infer<typeof ValueSchema>;
41
- export type Scope = z.infer<typeof ScopeSchema>;
42
- export type Metadata = z.infer<typeof MetadataSchema>;
43
- export type StoryHooks = z.infer<typeof StoryHooksSchema>;
44
- export type ChapterHooks = z.infer<typeof ChapterHooksSchema>;
45
- export type ValueType = "string" | "number" | "boolean" | "object";
46
- export {};
@@ -1,20 +0,0 @@
1
- export declare class InvalidMetadataError extends Error {
2
- content: string;
3
- constructor(content: string, message?: string);
4
- }
5
- export declare class DuplicateIdError extends Error {
6
- id: string;
7
- constructor(id: string, message?: string);
8
- }
9
- export declare class EmptyChapterIdError extends Error {
10
- constructor(message?: string);
11
- }
12
- export declare class ChapterNotFoundError extends Error {
13
- target: string | null;
14
- constructor(target: string | null, message?: string);
15
- }
16
- export declare class InvalidInputError extends Error {
17
- name: string;
18
- input: string | null;
19
- constructor(name: string, input: string | null, message?: string);
20
- }
@@ -1,4 +0,0 @@
1
- export * from "./definitions.js";
2
- export * from "./story.js";
3
- export * from "./chapter.js";
4
- export * from "./error.js";
@@ -1,32 +0,0 @@
1
- import { StoryHooks, Scope, Metadata, ChapterHooks } from "./definitions.js";
2
- import { Chapter, RenderOptions, RenderResult } from "./chapter.js";
3
- export type StoryPrompt = (props: {
4
- chapter: Chapter;
5
- } & RenderResult) => Promise<{
6
- target: string | null;
7
- updates: Scope;
8
- } | FormData>;
9
- type ChapterBody = {
10
- title: string;
11
- template: string;
12
- hooks: ChapterHooks;
13
- };
14
- type StoryBody = {
15
- metadata: Metadata;
16
- chapters: Record<string, ChapterBody>;
17
- entry: string | null;
18
- hooks: StoryHooks;
19
- stylesheet: string;
20
- };
21
- export declare const parseStoryContent: (content: string) => StoryBody;
22
- export declare class StoryBase {
23
- metadata: Metadata;
24
- globals: Scope;
25
- chapters: Record<string, Chapter>;
26
- entry: Chapter | null;
27
- hooks: StoryHooks;
28
- stylesheet: string;
29
- constructor({ metadata, chapters, entry, hooks, stylesheet }: StoryBody);
30
- play(prompt: StoryPrompt, options: RenderOptions): Promise<void>;
31
- }
32
- export {};
@@ -1,5 +0,0 @@
1
- export * from "./base/index.js";
2
- import { StoryBase } from "./base/index.js";
3
- export declare class Story extends StoryBase {
4
- constructor(content: string);
5
- }