yarn-spinner-runner-ts 0.1.0 → 0.1.1-b

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.
Files changed (45) hide show
  1. package/.github/workflows/npm-publish-github-packages.yml +39 -0
  2. package/README.md +205 -20
  3. package/dist/compile/compiler.js +5 -3
  4. package/dist/compile/compiler.js.map +1 -1
  5. package/dist/compile/ir.d.ts +1 -0
  6. package/dist/index.d.ts +6 -0
  7. package/dist/index.js +6 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/parse/parser.js +5 -2
  10. package/dist/parse/parser.js.map +1 -1
  11. package/dist/react/DialogueExample.d.ts +1 -0
  12. package/dist/react/DialogueExample.js +105 -0
  13. package/dist/react/DialogueExample.js.map +1 -0
  14. package/dist/react/DialogueScene.d.ts +11 -0
  15. package/dist/react/DialogueScene.js +70 -0
  16. package/dist/react/DialogueScene.js.map +1 -0
  17. package/dist/react/DialogueView.d.ts +9 -0
  18. package/dist/react/DialogueView.js +94 -0
  19. package/dist/react/DialogueView.js.map +1 -0
  20. package/dist/react/useYarnRunner.d.ts +8 -0
  21. package/dist/react/useYarnRunner.js +18 -0
  22. package/dist/react/useYarnRunner.js.map +1 -0
  23. package/dist/runtime/commands.js +1 -1
  24. package/dist/runtime/commands.js.map +1 -1
  25. package/dist/runtime/evaluator.js +0 -1
  26. package/dist/runtime/evaluator.js.map +1 -1
  27. package/dist/runtime/results.d.ts +4 -0
  28. package/dist/runtime/runner.js +3 -3
  29. package/dist/runtime/runner.js.map +1 -1
  30. package/dist/scene/parser.d.ts +9 -0
  31. package/dist/scene/parser.js +78 -0
  32. package/dist/scene/parser.js.map +1 -0
  33. package/dist/scene/types.d.ts +13 -0
  34. package/dist/scene/types.js +5 -0
  35. package/dist/scene/types.js.map +1 -0
  36. package/eslint.config.cjs +3 -0
  37. package/examples/browser/main.tsx +2 -0
  38. package/package.json +3 -2
  39. package/scripts/run-tests.js +57 -0
  40. package/src/react/DialogueScene.tsx +2 -1
  41. package/src/react/DialogueView.tsx +2 -1
  42. package/src/react/css.d.ts +9 -0
  43. package/src/react/useYarnRunner.tsx +3 -1
  44. package/src/runtime/commands.ts +1 -4
  45. package/src/runtime/evaluator.ts +0 -1
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Scene configuration parser using js-yaml
3
+ * Supports YAML string or plain object
4
+ */
5
+ import yaml from "js-yaml";
6
+ /**
7
+ * Parse scene configuration from YAML string or object
8
+ */
9
+ export function parseScenes(input) {
10
+ // If already an object, use it directly
11
+ if (typeof input === "object" && input !== null) {
12
+ return parseScenesFromObject(input);
13
+ }
14
+ // Parse YAML string
15
+ try {
16
+ const parsed = yaml.load(input);
17
+ return parseScenesFromObject(parsed || {});
18
+ }
19
+ catch (error) {
20
+ console.error("Failed to parse YAML scene config:", error);
21
+ throw new Error(`Invalid YAML scene configuration: ${error instanceof Error ? error.message : String(error)}`);
22
+ }
23
+ }
24
+ function parseScenesFromObject(obj) {
25
+ const scenes = {};
26
+ // Extract global actors if defined separately
27
+ const globalActors = {};
28
+ if (typeof obj.actors === "object" && obj.actors !== null) {
29
+ for (const [actorName, actorData] of Object.entries(obj.actors)) {
30
+ if (typeof actorData === "object" && actorData !== null) {
31
+ // Nested format: actorName: { image: "..." }
32
+ globalActors[actorName] = {
33
+ image: typeof actorData.image === "string" ? actorData.image : undefined,
34
+ };
35
+ }
36
+ else if (typeof actorData === "string") {
37
+ // Shorthand: actorName: "/path/to/image.png"
38
+ globalActors[actorName] = { image: actorData };
39
+ }
40
+ }
41
+ }
42
+ // Parse scenes
43
+ if (typeof obj.scenes === "object" && obj.scenes !== null) {
44
+ const scenesObj = obj.scenes;
45
+ for (const [sceneName, sceneData] of Object.entries(scenesObj)) {
46
+ if (typeof sceneData === "object" && sceneData !== null) {
47
+ const data = sceneData;
48
+ const sceneActors = { ...globalActors }; // Start with global actors
49
+ // Override with scene-specific actors if defined
50
+ if (typeof data.actors === "object" && data.actors !== null) {
51
+ for (const [actorName, actorData] of Object.entries(data.actors)) {
52
+ if (typeof actorData === "object" && actorData !== null) {
53
+ sceneActors[actorName] = {
54
+ image: typeof actorData.image === "string" ? actorData.image : undefined,
55
+ };
56
+ }
57
+ else if (typeof actorData === "string") {
58
+ sceneActors[actorName] = { image: actorData };
59
+ }
60
+ }
61
+ }
62
+ scenes[sceneName] = {
63
+ background: typeof data.background === "string" ? data.background : "",
64
+ actors: sceneActors,
65
+ };
66
+ }
67
+ else if (typeof sceneData === "string") {
68
+ // Shorthand: scene1: "/path/to/background.png" (uses global actors)
69
+ scenes[sceneName] = {
70
+ background: sceneData,
71
+ actors: { ...globalActors },
72
+ };
73
+ }
74
+ }
75
+ }
76
+ return { scenes };
77
+ }
78
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/scene/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Scene configuration types
3
+ */
4
+ export interface ActorConfig {
5
+ image?: string;
6
+ }
7
+ export interface SceneConfig {
8
+ background: string;
9
+ actors: Record<string, ActorConfig>;
10
+ }
11
+ export interface SceneCollection {
12
+ scenes: Record<string, SceneConfig>;
13
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Scene configuration types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/scene/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/eslint.config.cjs CHANGED
@@ -15,6 +15,9 @@ module.exports = [
15
15
  sourceType: "module",
16
16
  globals: {
17
17
  console: "readonly",
18
+ window: "readonly",
19
+ setTimeout: "readonly",
20
+ clearTimeout: "readonly",
18
21
  },
19
22
  },
20
23
  plugins: {
@@ -1,6 +1,8 @@
1
1
  import React from "react";
2
2
  import { createRoot } from "react-dom/client";
3
3
  import { DialogueExample } from "../../src/react/DialogueExample.js";
4
+ // Import CSS for dialogue system
5
+ import "../../src/react/dialogue.css";
4
6
 
5
7
  const rootEl = document.getElementById("root");
6
8
  if (!rootEl) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yarn-spinner-runner-ts",
3
- "version": "0.1.0",
3
+ "version": "0.1.1b",
4
4
  "private": false,
5
5
  "description": "TypeScript parser, compiler, and runtime for Yarn Spinner 3.x with React adapter",
6
6
  "license": "MIT",
@@ -13,8 +13,9 @@
13
13
  "clean": "rimraf dist",
14
14
  "dev": "tsc -w -p tsconfig.json",
15
15
  "lint": "eslint \"src/**/*.ts\" \"src/**/*.tsx\"",
16
+ "ts-check": "tsc -p tsconfig.json",
16
17
  "pretest": "npm run build",
17
- "test": "node --test --enable-source-maps \"dist/tests/**/*.test.js\" \"dist/tests/index.test.js\"",
18
+ "test": "node scripts/run-tests.js",
18
19
  "demo": "vite --config examples/browser/vite.config.ts --host 0.0.0.0",
19
20
  "demo:build": "vite build --config examples/browser/vite.config.ts"
20
21
  },
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Test runner script that discovers and runs all test files
5
+ * This ensures cross-platform compatibility (Windows, Linux, macOS)
6
+ */
7
+
8
+ import { readdir } from "fs/promises";
9
+ import { join, dirname } from "path";
10
+ import { fileURLToPath } from "url";
11
+ import { spawn } from "child_process";
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+ const projectRoot = join(__dirname, "..");
16
+ const testsDir = join(projectRoot, "dist", "tests");
17
+
18
+ async function findTestFiles() {
19
+ try {
20
+ const files = await readdir(testsDir);
21
+ return files
22
+ .filter((file) => file.endsWith(".test.js"))
23
+ .map((file) => join(testsDir, file));
24
+ } catch (error) {
25
+ console.error(`Error reading tests directory: ${error.message}`);
26
+ process.exit(1);
27
+ }
28
+ }
29
+
30
+ async function runTests() {
31
+ const testFiles = await findTestFiles();
32
+
33
+ if (testFiles.length === 0) {
34
+ console.error("No test files found!");
35
+ process.exit(1);
36
+ }
37
+
38
+ console.log(`Found ${testFiles.length} test file(s):`);
39
+ testFiles.forEach((file) => console.log(` - ${file}`));
40
+
41
+ const args = ["--test", "--enable-source-maps", ...testFiles];
42
+
43
+ const proc = spawn("node", args, {
44
+ stdio: "inherit",
45
+ cwd: projectRoot,
46
+ });
47
+
48
+ proc.on("exit", (code) => {
49
+ process.exit(code || 0);
50
+ });
51
+ }
52
+
53
+ runTests().catch((error) => {
54
+ console.error(`Error running tests: ${error.message}`);
55
+ process.exit(1);
56
+ });
57
+
@@ -1,6 +1,7 @@
1
1
  import React, { useState, useEffect } from "react";
2
2
  import type { SceneCollection, SceneConfig } from "../scene/types.js";
3
- import "./dialogue.css";
3
+ // Note: CSS is imported in the browser demo entry point (examples/browser/main.tsx)
4
+ // This prevents Node.js from trying to resolve CSS imports during tests
4
5
 
5
6
  export interface DialogueSceneProps {
6
7
  sceneName?: string;
@@ -2,7 +2,8 @@ import React from "react";
2
2
  import type { RuntimeResult } from "../runtime/results.js";
3
3
  import { DialogueScene } from "./DialogueScene.js";
4
4
  import type { SceneCollection } from "../scene/types.js";
5
- import "./dialogue.css";
5
+ // Note: CSS is imported in the browser demo entry point (examples/browser/main.tsx)
6
+ // This prevents Node.js from trying to resolve CSS imports during tests
6
7
 
7
8
  export interface DialogueViewProps {
8
9
  result: RuntimeResult | null;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Type declarations for CSS module imports
3
+ * This allows TypeScript to recognize CSS imports without errors
4
+ */
5
+ declare module "*.css" {
6
+ const content: string;
7
+ export default content;
8
+ }
9
+
@@ -1,5 +1,7 @@
1
1
  import { useState, useCallback, useRef } from "react";
2
- import { YarnRunner, type IRProgram, type RunnerOptions, type RuntimeResult } from "../runtime/runner.js";
2
+ import { YarnRunner, type RunnerOptions } from "../runtime/runner.js";
3
+ import type { IRProgram } from "../compile/ir.js";
4
+ import type { RuntimeResult } from "../runtime/results.js";
3
5
 
4
6
  export function useYarnRunner(
5
7
  program: IRProgram,
@@ -162,7 +162,7 @@ export class CommandHandler {
162
162
  } else if (value.startsWith(".")) {
163
163
  // Shorthand - we can't infer enum type from declaration alone
164
164
  // Store as-is, will be resolved on first use if variable has enum type
165
- value = value;
165
+ // Value is already set correctly above
166
166
  }
167
167
  }
168
168
 
@@ -178,6 +178,3 @@ export class CommandHandler {
178
178
  }
179
179
  }
180
180
 
181
- // Forward reference type (avoid circular import)
182
- type ExpressionEvaluator = import("./evaluator").ExpressionEvaluator;
183
-
@@ -202,7 +202,6 @@ export class ExpressionEvaluator {
202
202
 
203
203
  // Try shorthand enum: .CaseName (requires context from variables)
204
204
  if (expr.startsWith(".") && expr.length > 1) {
205
- const caseName = expr.slice(1);
206
205
  // Try to infer enum from variable types - for now, return as-is and let validation handle it
207
206
  return expr;
208
207
  }