From 5860f2a247af18fdcad49a2e469b73a8da88063d Mon Sep 17 00:00:00 2001 From: hypercross Date: Wed, 15 Apr 2026 10:19:03 +0800 Subject: [PATCH] feat: upgrade yarn-spinner-loader to 0.2.0 and add encounters.yarnproject test --- package-lock.json | 8 +-- package.json | 2 +- src/global.d.ts | 5 ++ .../encounters/encounters.yarnproject | 17 ++++++ .../dialogue/encounters/story.yarn | 42 +++++++++++++++ .../slay-the-spire-like/dialogue/index.ts | 1 + .../dialogue/encounters.test.ts | 53 +++++++++++++++++++ 7 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 src/global.d.ts create mode 100644 src/samples/slay-the-spire-like/dialogue/encounters/encounters.yarnproject create mode 100644 src/samples/slay-the-spire-like/dialogue/encounters/story.yarn create mode 100644 src/samples/slay-the-spire-like/dialogue/index.ts create mode 100644 tests/samples/slay-the-spire-like/dialogue/encounters.test.ts diff --git a/package-lock.json b/package-lock.json index b82311d..7020f0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "tsup": "^8.0.2", "typescript": "^5.3.3", "vitest": "^1.3.1", - "yarn-spinner-loader": "^0.1.1" + "yarn-spinner-loader": "^0.2.0" }, "peerDependencies": { "@preact/signals-core": "^1.5.1", @@ -3096,9 +3096,9 @@ } }, "node_modules/yarn-spinner-loader": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/yarn-spinner-loader/-/yarn-spinner-loader-0.1.1.tgz", - "integrity": "sha512-q1xC8QQghpZ1mJDgbnNVzVv3xtb6nOO7fC2YmFANHjz31tNfuf7jOZ1n+V80/5CUxK6ct5425XWYJpSRW/fWrw==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/yarn-spinner-loader/-/yarn-spinner-loader-0.2.0.tgz", + "integrity": "sha512-tWq+n7qziugn7pj+0Zf/XXWXqVxXZez1JkqQgk7JJD4yikHbY1OihYwqSvsUiNeav52j5VCrpU8vWlerwCawPw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 565087c..8e7b84b 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "tsup": "^8.0.2", "typescript": "^5.3.3", "vitest": "^1.3.1", - "yarn-spinner-loader": "^0.1.1" + "yarn-spinner-loader": "^0.2.0" }, "keywords": [ "boardgame", diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000..9ad777c --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,5 @@ +declare module '*.yarnproject' { + import type { LoadResult } from 'yarn-spinner-loader'; + const result: LoadResult; + export default result; +} diff --git a/src/samples/slay-the-spire-like/dialogue/encounters/encounters.yarnproject b/src/samples/slay-the-spire-like/dialogue/encounters/encounters.yarnproject new file mode 100644 index 0000000..9faa9d7 --- /dev/null +++ b/src/samples/slay-the-spire-like/dialogue/encounters/encounters.yarnproject @@ -0,0 +1,17 @@ +{ + "projectFileVersion": 4, + "sourceFiles": [ + "**/*.yarn" + ], + "excludeFiles": [], + "baseLanguage": "en", + "projectName": "encounters", + "authorName": [ + "hyper" + ], + "editorOptions": { + "yarnScriptEditor": { + "presenter": "try" + } + } +} \ No newline at end of file diff --git a/src/samples/slay-the-spire-like/dialogue/encounters/story.yarn b/src/samples/slay-the-spire-like/dialogue/encounters/story.yarn new file mode 100644 index 0000000..4ee78da --- /dev/null +++ b/src/samples/slay-the-spire-like/dialogue/encounters/story.yarn @@ -0,0 +1,42 @@ +title: Start +--- +// A linear story progresses from one scene to the next. +// Great for cutscenes, tutorials, or scripted sequences. + +<> +=== +title: Scene1 +--- +The sun rose over the quiet village. + +Birds sang their morning chorus as the first rays of light crept through the window. + +-> Continue + <> +=== +title: Scene2 +--- +In the kitchen, a kettle began to whistle. + +The smell of fresh bread filled the air. + +-> Continue + <> +=== +title: Scene3 +--- +A knock at the door broke the peaceful morning. + +Who could be visiting so early? + +-> Open the door + <> +=== +title: Scene4 +--- +A messenger stood at the threshold, parchment in hand. + +"News from the capital," they said breathlessly. "You must read this at once." + +// Your story continues from here! +=== diff --git a/src/samples/slay-the-spire-like/dialogue/index.ts b/src/samples/slay-the-spire-like/dialogue/index.ts new file mode 100644 index 0000000..cec38e0 --- /dev/null +++ b/src/samples/slay-the-spire-like/dialogue/index.ts @@ -0,0 +1 @@ +export {default as encounters} from './encounters/encounters.yarnproject'; \ No newline at end of file diff --git a/tests/samples/slay-the-spire-like/dialogue/encounters.test.ts b/tests/samples/slay-the-spire-like/dialogue/encounters.test.ts new file mode 100644 index 0000000..4dc075f --- /dev/null +++ b/tests/samples/slay-the-spire-like/dialogue/encounters.test.ts @@ -0,0 +1,53 @@ +import { describe, it, expect } from 'vitest'; +import encounters from '@/samples/slay-the-spire-like/dialogue/encounters/encounters.yarnproject'; + +describe('encounters.yarnproject import', () => { + it('should load the yarnproject with expected project metadata', () => { + expect(encounters.project.projectName).toBe('encounters'); + expect(encounters.project.baseLanguage).toBe('en'); + expect(encounters.project.authorName).toContain('hyper'); + expect(encounters.project.projectFileVersion).toBe(4); + }); + + it('should have sourceFiles configured', () => { + expect(encounters.project.sourceFiles).toContain('**/*.yarn'); + }); + + it('should have a valid baseDir', () => { + expect(typeof encounters.baseDir).toBe('string'); + expect(encounters.baseDir.length).toBeGreaterThan(0); + }); + + it('should compile nodes from .yarn files', () => { + const nodeTitles = Object.keys(encounters.program.nodes); + expect(nodeTitles.length).toBeGreaterThan(0); + }); + + it('should contain expected nodes from story.yarn', () => { + const nodeTitles = Object.keys(encounters.program.nodes); + expect(nodeTitles).toContain('Start'); + expect(nodeTitles).toContain('Scene1'); + expect(nodeTitles).toContain('Scene2'); + expect(nodeTitles).toContain('Scene3'); + expect(nodeTitles).toContain('Scene4'); + }); + + it('should have instructions in each node', () => { + for (const [title, node] of Object.entries(encounters.program.nodes)) { + if ('instructions' in node && Array.isArray((node as any).instructions)) { + expect((node as any).instructions.length).toBeGreaterThan(0); + } + } + }); + + it('should have Start node with jump instruction to Scene1', () => { + const startNode = encounters.program.nodes['Start']; + if ('instructions' in startNode) { + const jumpInstruction = startNode.instructions.find( + (instr) => instr.op === 'jump', + ); + expect(jumpInstruction).toBeDefined(); + expect(jumpInstruction!.target).toBe('Scene1'); + } + }); +});