yarn-spinner-runner-ts
Version:
TypeScript parser, compiler, and runtime for Yarn Spinner 3.x with React adapter [NPM package](https://www.npmjs.com/package/yarn-spinner-runner-ts)
79 lines (67 loc) • 2.81 kB
text/typescript
import { test } from "node:test";
import { strictEqual, ok } from "node:assert";
import { parseMarkup } from "../markup/parser.js";
import type { MarkupParseResult } from "../markup/types.js";
test("parseMarkup handles default HTML tags", () => {
const result = parseMarkup("This is [b]bold[/b] and [em]emphasized[/em].");
strictEqual(result.text, "This is bold and emphasized.");
const bold = findSegment(result, "bold");
ok(bold, "Expected bold segment");
strictEqual(bold.wrappers.length, 1);
strictEqual(bold.wrappers[0].name, "b");
strictEqual(bold.wrappers[0].type, "default");
const em = findSegment(result, "emphasized");
ok(em, "Expected em segment");
strictEqual(em.wrappers[0].name, "em");
strictEqual(em.wrappers[0].type, "default");
});
test("parseMarkup exposes custom tags with properties", () => {
const result = parseMarkup("Say [wave speed=2 tone=\"high\"]hello[/wave]!");
strictEqual(result.text, "Say hello!");
const segment = findSegment(result, "hello");
ok(segment, "Expected wave segment");
const wrapper = segment.wrappers.find((w) => w.name === "wave");
ok(wrapper, "Expected wave wrapper");
strictEqual(wrapper.type, "custom");
strictEqual(wrapper.properties.speed, 2);
strictEqual(wrapper.properties.tone, "high");
});
test("parseMarkup handles self-closing tags", () => {
const result = parseMarkup("[pause length=500/] Ready.");
strictEqual(result.text, " Ready.");
ok(
result.segments.some(
(seg) => seg.selfClosing && seg.wrappers.some((wrapper) => wrapper.name === "pause")
),
"Expected self closing pause marker"
);
});
test("parseMarkup handles br line breaks", () => {
const result = parseMarkup("Line one[br]Line two[/br][br/]Line three");
strictEqual(result.text, "Line oneLine twoLine three");
const brSegments = result.segments.filter(
(segment) => segment.selfClosing && segment.wrappers.some((wrapper) => wrapper.name === "br")
);
strictEqual(brSegments.length, 2);
ok(
brSegments.every((segment) =>
segment.wrappers.some((wrapper) => wrapper.name === "br" && wrapper.type === "default")
),
"Expected br wrappers to use default HTML type"
);
});
test("parseMarkup respects nomarkup blocks and escaping", () => {
const result = parseMarkup(`[nomarkup][b] raw [/b][/nomarkup] and \\[escaped\\]`);
strictEqual(result.text, "[b] raw [/b] and [escaped]");
ok(
result.segments.every((segment) => segment.wrappers.length === 0),
"Expected no wrappers when using nomarkup and escaping"
);
});
function findSegment(result: MarkupParseResult, target: string) {
return result.segments.find((segment) => {
if (segment.selfClosing) return false;
const text = result.text.slice(segment.start, segment.end);
return text === target;
});
}