yarn-spinner-runner-ts 0.1.4-a → 0.1.4-c
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.
- package/dist/markup/parser.js +15 -2
- package/dist/markup/parser.js.map +1 -1
- package/dist/react/DialogueExample.js +4 -4
- package/dist/react/DialogueExample.js.map +1 -1
- package/dist/react/DialogueView.d.ts +2 -1
- package/dist/react/DialogueView.js +29 -17
- package/dist/react/DialogueView.js.map +1 -1
- package/dist/react/MarkupRenderer.js +1 -1
- package/dist/react/MarkupRenderer.js.map +1 -1
- package/dist/react/useYarnRunner.js +60 -16
- package/dist/react/useYarnRunner.js.map +1 -1
- package/dist/tests/dialogue_view.test.d.ts +1 -0
- package/dist/tests/dialogue_view.test.js +18 -0
- package/dist/tests/dialogue_view.test.js.map +1 -0
- package/dist/tests/markup.test.js +7 -0
- package/dist/tests/markup.test.js.map +1 -1
- package/docs/markup.md +33 -33
- package/eslint.config.cjs +39 -39
- package/package.json +1 -1
- package/src/markup/parser.ts +56 -43
- package/src/react/DialogueExample.tsx +10 -9
- package/src/react/DialogueView.tsx +312 -297
- package/src/react/MarkupRenderer.tsx +1 -2
- package/src/react/useYarnRunner.tsx +101 -46
- package/src/tests/dialogue_view.test.tsx +26 -0
- package/src/tests/markup.test.ts +17 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yarn-spinner-runner-ts",
|
|
3
|
-
"version": "0.1.4-
|
|
3
|
+
"version": "0.1.4-c",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "TypeScript parser, compiler, and runtime for Yarn Spinner 3.x with React adapter [NPM package](https://www.npmjs.com/package/yarn-spinner-runner-ts)",
|
|
6
6
|
"license": "MIT",
|
package/src/markup/parser.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { MarkupParseResult, MarkupSegment, MarkupValue, MarkupWrapper } from "./types.js";
|
|
2
|
-
|
|
3
|
-
const DEFAULT_HTML_TAGS = new Set(["b", "em", "small", "strong", "sub", "sup", "ins", "del", "mark"]);
|
|
1
|
+
import type { MarkupParseResult, MarkupSegment, MarkupValue, MarkupWrapper } from "./types.js";
|
|
2
|
+
|
|
3
|
+
const DEFAULT_HTML_TAGS = new Set(["b", "em", "small", "strong", "sub", "sup", "ins", "del", "mark", "br"]);
|
|
4
|
+
const SELF_CLOSING_TAGS = new Set(["br"]);
|
|
4
5
|
|
|
5
6
|
interface StackEntry {
|
|
6
7
|
name: string;
|
|
@@ -125,8 +126,9 @@ export function parseMarkup(input: string): MarkupParseResult {
|
|
|
125
126
|
rest = rest.slice(attrMatch[0].length).trim();
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
const finalKind: ParsedTag["kind"] = kind === "self" || SELF_CLOSING_TAGS.has(name) ? "self" : kind;
|
|
130
|
+
return { kind: finalKind, name, properties };
|
|
131
|
+
};
|
|
130
132
|
|
|
131
133
|
const parseAttributeValue = (raw: string): MarkupValue => {
|
|
132
134
|
const trimmed = raw.trim();
|
|
@@ -142,20 +144,23 @@ export function parseMarkup(input: string): MarkupParseResult {
|
|
|
142
144
|
return trimmed;
|
|
143
145
|
};
|
|
144
146
|
|
|
145
|
-
const handleSelfClosing = (tag: ParsedTag) => {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
147
|
+
const handleSelfClosing = (tag: ParsedTag) => {
|
|
148
|
+
if (tag.name === "br") {
|
|
149
|
+
appendChar("\n");
|
|
150
|
+
}
|
|
151
|
+
const wrapper: MarkupWrapper = {
|
|
152
|
+
name: tag.name,
|
|
153
|
+
type: DEFAULT_HTML_TAGS.has(tag.name) ? "default" : "custom",
|
|
154
|
+
properties: tag.properties,
|
|
155
|
+
};
|
|
156
|
+
const position = chars.length;
|
|
157
|
+
pushSegment({
|
|
158
|
+
start: position,
|
|
159
|
+
end: position,
|
|
160
|
+
wrappers: [wrapper],
|
|
161
|
+
selfClosing: true,
|
|
162
|
+
});
|
|
163
|
+
};
|
|
159
164
|
|
|
160
165
|
let i = 0;
|
|
161
166
|
while (i < input.length) {
|
|
@@ -215,30 +220,38 @@ export function parseMarkup(input: string): MarkupParseResult {
|
|
|
215
220
|
continue;
|
|
216
221
|
}
|
|
217
222
|
|
|
218
|
-
if (parsed.kind === "self") {
|
|
219
|
-
handleSelfClosing(parsed);
|
|
220
|
-
i = closeIndex + 1;
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// closing tag
|
|
225
|
-
if (stack.length === 0) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
223
|
+
if (parsed.kind === "self") {
|
|
224
|
+
handleSelfClosing(parsed);
|
|
225
|
+
i = closeIndex + 1;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// closing tag
|
|
230
|
+
if (stack.length === 0) {
|
|
231
|
+
if (SELF_CLOSING_TAGS.has(parsed.name)) {
|
|
232
|
+
i = closeIndex + 1;
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
appendLiteral(originalText);
|
|
236
|
+
i = closeIndex + 1;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const top = stack[stack.length - 1];
|
|
240
|
+
if (top.name === parsed.name) {
|
|
241
|
+
flushCurrentSegment();
|
|
242
|
+
stack.pop();
|
|
243
|
+
i = closeIndex + 1;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (SELF_CLOSING_TAGS.has(parsed.name)) {
|
|
247
|
+
i = closeIndex + 1;
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
// mismatched closing; treat as literal
|
|
251
|
+
appendLiteral(originalText);
|
|
252
|
+
i = closeIndex + 1;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
242
255
|
|
|
243
256
|
appendChar(char);
|
|
244
257
|
i += 1;
|
|
@@ -8,8 +8,8 @@ import type { SceneCollection } from "../scene/types.js";
|
|
|
8
8
|
const DEFAULT_YARN = `title: Start
|
|
9
9
|
scene: scene1
|
|
10
10
|
---
|
|
11
|
-
Narrator: {
|
|
12
|
-
Narrator:
|
|
11
|
+
Narrator: Welcome to [b]yarn-spinner-ts[/b], {$playerName}!
|
|
12
|
+
Narrator: Current street cred: {$reputation}
|
|
13
13
|
npc: This is a dialogue system powered by Yarn Spinner.
|
|
14
14
|
Narrator: Click anywhere to continue, or choose an option below.
|
|
15
15
|
-> Start the adventure &css{backgroundColor: #4a9eff; color: white;}
|
|
@@ -46,7 +46,7 @@ actors:
|
|
|
46
46
|
export function DialogueExample() {
|
|
47
47
|
const [yarnText] = useState(DEFAULT_YARN);
|
|
48
48
|
const [error, setError] = useState<string | null>(null);
|
|
49
|
-
const enableTypingAnimation =
|
|
49
|
+
const enableTypingAnimation = false;
|
|
50
50
|
|
|
51
51
|
const scenes: SceneCollection = useMemo(() => {
|
|
52
52
|
try {
|
|
@@ -101,12 +101,13 @@ export function DialogueExample() {
|
|
|
101
101
|
</div>
|
|
102
102
|
)}
|
|
103
103
|
|
|
104
|
-
<DialogueView
|
|
105
|
-
program={program || { nodes: {}, enums: {} }}
|
|
106
|
-
startNode="Start"
|
|
107
|
-
scenes={scenes}
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
<DialogueView
|
|
105
|
+
program={program || { nodes: {}, enums: {} }}
|
|
106
|
+
startNode="Start"
|
|
107
|
+
scenes={scenes}
|
|
108
|
+
variables={{ playerName: "V", reputation: 3 }}
|
|
109
|
+
enableTypingAnimation={enableTypingAnimation}
|
|
110
|
+
showTypingCursor={true}
|
|
110
111
|
typingSpeed={20}
|
|
111
112
|
cursorCharacter="$"
|
|
112
113
|
autoAdvanceAfterTyping={true}
|