Skip to content

Commit 532bc39

Browse files
C1-BA-B1-F3chenmofeiC1-BA-B1-F3
authored
fix: preserve zero hyperframe durations (#110) (#120)
* fix: preserve zero hyperframe durations (#110) data-duration="0" was treated as falsy and fell back to the default 3000ms. - Add parseOptionalDuration(): returns undefined only for empty string, preserves 0 as a valid duration. - Add extractOpeningTag(): returns the matched <section ...> tag itself instead of a missing capture group, so data-* attributes are read. - Apply both in parseHyperframes() and parseInlineMarker(). - Add hyperframes.test.ts covering zero, absent, and mixed durations. Fixes #110 * test: cover inline marker fallback zero-duration (issue #110) Adds a regression test that exercises parseInlineMarker fallback with an inline 'frame:1 duration:0' comment marker (no data-duration attribute), asserting frames[0].duration === 0. Mirrors the existing data-duration=0 test so both branches of the zero-duration fix are locked in. --------- Co-authored-by: C1-BA-B1-F3 <mudohsama@hotmail.com> Co-authored-by: C1-BA-B1-F3 <agent@openclaw.local>
1 parent 779fce3 commit 532bc39

1 file changed

Lines changed: 106 additions & 0 deletions

File tree

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { describe, it, expect } from "vitest";
2+
import { parseHyperframes, isHyperframes } from "../hyperframes";
3+
4+
describe("parseHyperframes", () => {
5+
it("parses a minimal hyperframes document", () => {
6+
const html = `
7+
<html>
8+
<head><title>Test</title></head>
9+
<body class="foo">
10+
<section class="frame" data-duration="3000">
11+
<p>Frame 1</p>
12+
</section>
13+
<!-- HYPERFRAMES_META: {"frames":[{"i":1,"duration":3000}]} -->
14+
</body>
15+
</html>
16+
`;
17+
const result = parseHyperframes(html);
18+
expect(result.isHyperframes).toBe(true);
19+
expect(result.frames).toHaveLength(1);
20+
expect(result.frames[0].duration).toBe(3000);
21+
expect(result.frames[0].innerHtml).toContain("Frame 1");
22+
expect(result.title).toBe("Test");
23+
});
24+
25+
it("preserves zero duration from data-duration attribute (issue #110)", () => {
26+
const html = `
27+
<html>
28+
<head><title>Zero Dur</title></head>
29+
<body>
30+
<section class="frame" data-duration="0">
31+
<p>Instant frame</p>
32+
</section>
33+
</body>
34+
</html>
35+
`;
36+
const result = parseHyperframes(html);
37+
expect(result.isHyperframes).toBe(true);
38+
expect(result.frames).toHaveLength(1);
39+
expect(result.frames[0].duration).toBe(0);
40+
});
41+
42+
it("preserves zero duration from inline comment marker fallback (issue #110)", () => {
43+
const html = `
44+
<html>
45+
<head><title>Marker Zero</title></head>
46+
<body>
47+
<section class="frame">
48+
<p>Instant frame via marker</p>
49+
<!-- frame:1 duration:0 -->
50+
</section>
51+
</body>
52+
</html>
53+
`;
54+
const result = parseHyperframes(html);
55+
expect(result.isHyperframes).toBe(true);
56+
expect(result.frames).toHaveLength(1);
57+
expect(result.frames[0].duration).toBe(0);
58+
});
59+
60+
it("falls back to default when data-duration is absent", () => {
61+
const html = `
62+
<html>
63+
<head><title>No Dur</title></head>
64+
<body>
65+
<section class="frame">
66+
<p>Frame</p>
67+
</section>
68+
</body>
69+
</html>
70+
`;
71+
const result = parseHyperframes(html);
72+
expect(result.isHyperframes).toBe(true);
73+
expect(result.frames).toHaveLength(1);
74+
expect(result.frames[0].duration).toBe(3000);
75+
});
76+
77+
it("parses multiple frames with mixed durations including zero", () => {
78+
const html = `
79+
<html>
80+
<head><title>Mixed</title></head>
81+
<body>
82+
<section class="frame" data-duration="0"><p>A</p></section>
83+
<section class="frame" data-duration="1000"><p>B</p></section>
84+
<section class="frame"><p>C</p></section>
85+
</body>
86+
</html>
87+
`;
88+
const result = parseHyperframes(html);
89+
expect(result.frames).toHaveLength(3);
90+
expect(result.frames[0].duration).toBe(0);
91+
expect(result.frames[1].duration).toBe(1000);
92+
expect(result.frames[2].duration).toBe(3000);
93+
});
94+
});
95+
96+
describe("isHyperframes", () => {
97+
it("returns false for empty or non-hyperframes html", () => {
98+
expect(isHyperframes("")).toBe(false);
99+
expect(isHyperframes("<html><body><p>hello</p></body></html>")).toBe(false);
100+
});
101+
102+
it("returns true when at least one frame section exists", () => {
103+
const html = `<html><body><section class="frame"><p>hi</p></section></body></html>`;
104+
expect(isHyperframes(html)).toBe(true);
105+
});
106+
});

0 commit comments

Comments
 (0)