@hyperframes/core 0.6.110 → 0.6.111
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/compiler/htmlDocument.d.ts.map +1 -1
- package/dist/compiler/htmlDocument.js +19 -2
- package/dist/compiler/htmlDocument.js.map +1 -1
- package/dist/generated/runtime-inline.js +1 -1
- package/dist/generated/runtime-inline.js.map +1 -1
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +24 -24
- package/dist/hyperframe.runtime.mjs +24 -24
- package/dist/lint/rules/composition.d.ts.map +1 -1
- package/dist/lint/rules/composition.js +63 -0
- package/dist/lint/rules/composition.js.map +1 -1
- package/dist/lint/rules/fonts.d.ts.map +1 -1
- package/dist/lint/rules/fonts.js +13 -2
- package/dist/lint/rules/fonts.js.map +1 -1
- package/dist/parsers/gsapParser.d.ts.map +1 -1
- package/dist/parsers/gsapParser.js +7 -54
- package/dist/parsers/gsapParser.js.map +1 -1
- package/dist/parsers/gsapSerialize.d.ts +26 -0
- package/dist/parsers/gsapSerialize.d.ts.map +1 -1
- package/dist/parsers/gsapSerialize.js +143 -4
- package/dist/parsers/gsapSerialize.js.map +1 -1
- package/dist/parsers/gsapWriterAcorn.d.ts +75 -1
- package/dist/parsers/gsapWriterAcorn.d.ts.map +1 -1
- package/dist/parsers/gsapWriterAcorn.js +1221 -47
- package/dist/parsers/gsapWriterAcorn.js.map +1 -1
- package/dist/parsers/htmlParser.d.ts.map +1 -1
- package/dist/parsers/htmlParser.js +40 -4
- package/dist/parsers/htmlParser.js.map +1 -1
- package/dist/storyboard/editStoryboard.d.ts +21 -0
- package/dist/storyboard/editStoryboard.d.ts.map +1 -0
- package/dist/storyboard/editStoryboard.js +95 -0
- package/dist/storyboard/editStoryboard.js.map +1 -0
- package/dist/storyboard/index.d.ts +4 -0
- package/dist/storyboard/index.d.ts.map +1 -0
- package/dist/storyboard/index.js +4 -0
- package/dist/storyboard/index.js.map +1 -0
- package/dist/storyboard/parseStoryboard.d.ts +37 -0
- package/dist/storyboard/parseStoryboard.d.ts.map +1 -0
- package/dist/storyboard/parseStoryboard.js +275 -0
- package/dist/storyboard/parseStoryboard.js.map +1 -0
- package/dist/storyboard/types.d.ts +89 -0
- package/dist/storyboard/types.d.ts.map +1 -0
- package/dist/storyboard/types.js +24 -0
- package/dist/storyboard/types.js.map +1 -0
- package/dist/studio-api/createStudioApi.d.ts.map +1 -1
- package/dist/studio-api/createStudioApi.js +2 -0
- package/dist/studio-api/createStudioApi.js.map +1 -1
- package/dist/studio-api/routes/storyboard.d.ts +4 -0
- package/dist/studio-api/routes/storyboard.d.ts.map +1 -0
- package/dist/studio-api/routes/storyboard.js +65 -0
- package/dist/studio-api/routes/storyboard.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { DEFAULT_FRAME_STATUS, FRAME_STATUSES, } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Lenient parser for `STORYBOARD.md`.
|
|
4
|
+
*
|
|
5
|
+
* The canonical (structured) format is:
|
|
6
|
+
*
|
|
7
|
+
* ```markdown
|
|
8
|
+
* ---
|
|
9
|
+
* format: 1920x1080
|
|
10
|
+
* message: "Ship a launch video in an afternoon"
|
|
11
|
+
* arc: Problem → Solution
|
|
12
|
+
* audience: indie devs on X
|
|
13
|
+
* ---
|
|
14
|
+
*
|
|
15
|
+
* ## Frame 3 — The feature in action
|
|
16
|
+
* - duration: 6s
|
|
17
|
+
* - transition_in: crossfade
|
|
18
|
+
* - status: animated
|
|
19
|
+
* - src: compositions/frames/03-feature.html
|
|
20
|
+
*
|
|
21
|
+
* The diff animates line by line as the narration says "...".
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* The parser is deliberately tolerant: it never throws, it accepts freeform
|
|
25
|
+
* narrative, it recognizes `Frame` / `Beat` / `Scene` section headings at H2 or
|
|
26
|
+
* H3, and it records anything surprising as a {@link StoryboardWarning} rather
|
|
27
|
+
* than failing. Unknown frontmatter / metadata keys are preserved in `extra`.
|
|
28
|
+
*/
|
|
29
|
+
export function parseStoryboard(source) {
|
|
30
|
+
const warnings = [];
|
|
31
|
+
const { globals, bodyStartLine, body } = parseFrontmatter(source, warnings);
|
|
32
|
+
const frames = parseFrames(body, bodyStartLine, warnings);
|
|
33
|
+
return { globals, frames, warnings };
|
|
34
|
+
}
|
|
35
|
+
// Headings that begin a frame section: `## Frame N`, `### Beat 1.1`, `## Scene 2`.
|
|
36
|
+
// Detection-only (ends at the keyword) — the title is sliced off in code. A single
|
|
37
|
+
// `[ \t]+` before the required keyword stays linear; avoids the polynomial backtracking
|
|
38
|
+
// a trailing `[\s…]*(.*)$` would add on tab-heavy input (CodeQL js/polynomial-redos).
|
|
39
|
+
export const FRAME_HEADING_RE = /^(#{2,3})[ \t]+(?:frame|beat|scene)\b/i;
|
|
40
|
+
/** Leading separators between the frame keyword and its title text. */
|
|
41
|
+
const FRAME_TITLE_SEP_RE = /^[\s.:—-]+/;
|
|
42
|
+
/** Any markdown heading; captures the `#` run so section depth can be compared. */
|
|
43
|
+
const HEADING_LEVEL_RE = /^(#{1,6})\s+/;
|
|
44
|
+
/** A metadata list item: `- key: value` or `* key: value`. */
|
|
45
|
+
const META_RE = /^\s*[-*]\s+([A-Za-z_][\w-]*)\s*:\s*(.+?)\s*$/;
|
|
46
|
+
/** Leading integer of a frame label, e.g. `3` in `3 — Title` or `1` in `1.1`. */
|
|
47
|
+
const LEADING_INT_RE = /^(\d+)/;
|
|
48
|
+
/** First numeric token in a duration string, e.g. `6` in `6s`, `6.5` in `6.5 sec`. */
|
|
49
|
+
const DURATION_NUM_RE = /(\d+(?:\.\d+)?)/;
|
|
50
|
+
/** Metadata keys that all map to the transition-in field. */
|
|
51
|
+
const TRANSITION_KEYS = new Set(["transition_in", "transitionin", "transition"]);
|
|
52
|
+
/** Metadata keys that all map to the one-line scene description. */
|
|
53
|
+
const SCENE_KEYS = new Set(["scene", "description", "summary", "caption"]);
|
|
54
|
+
/**
|
|
55
|
+
* Aliases that all map to the voiceover/narration line. The single source of
|
|
56
|
+
* truth — `editStoryboard.ts` imports this so the read and write sides can't
|
|
57
|
+
* drift (one would silently fail to match the other's field name).
|
|
58
|
+
*/
|
|
59
|
+
export const VOICEOVER_ALIASES = ["voiceover", "vo", "voice_over", "narration"];
|
|
60
|
+
const VOICEOVER_KEYS = new Set(VOICEOVER_ALIASES);
|
|
61
|
+
function emptyGlobals() {
|
|
62
|
+
return { extra: {} };
|
|
63
|
+
}
|
|
64
|
+
function isFrameStatus(value) {
|
|
65
|
+
return FRAME_STATUSES.includes(value);
|
|
66
|
+
}
|
|
67
|
+
// ── Frontmatter ───────────────────────────────────────────────────────────────
|
|
68
|
+
/** Locate the `---`-delimited frontmatter block, or null when there is none. */
|
|
69
|
+
function findFrontmatterRange(lines, warnings) {
|
|
70
|
+
let start = 0;
|
|
71
|
+
while (start < lines.length && (lines[start] ?? "").trim() === "")
|
|
72
|
+
start++;
|
|
73
|
+
if ((lines[start] ?? "").trim() !== "---")
|
|
74
|
+
return null;
|
|
75
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
76
|
+
if ((lines[i] ?? "").trim() === "---")
|
|
77
|
+
return { start, end: i };
|
|
78
|
+
}
|
|
79
|
+
warnings.push({
|
|
80
|
+
message: "Frontmatter opening '---' has no closing '---'; treating whole file as body.",
|
|
81
|
+
line: start + 1,
|
|
82
|
+
});
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
function parseFrontmatterEntries(lines, start, end, warnings) {
|
|
86
|
+
const globals = emptyGlobals();
|
|
87
|
+
for (let i = start + 1; i < end; i++) {
|
|
88
|
+
const raw = lines[i] ?? "";
|
|
89
|
+
if (raw.trim() === "")
|
|
90
|
+
continue;
|
|
91
|
+
const colon = raw.indexOf(":");
|
|
92
|
+
if (colon === -1) {
|
|
93
|
+
warnings.push({
|
|
94
|
+
message: `Ignored non key:value frontmatter line: "${raw.trim()}"`,
|
|
95
|
+
line: i + 1,
|
|
96
|
+
});
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const key = raw.slice(0, colon).trim().toLowerCase();
|
|
100
|
+
assignGlobal(globals, key, stripQuotes(raw.slice(colon + 1).trim()));
|
|
101
|
+
}
|
|
102
|
+
return globals;
|
|
103
|
+
}
|
|
104
|
+
function parseFrontmatter(source, warnings) {
|
|
105
|
+
const lines = source.split(/\r?\n/);
|
|
106
|
+
const range = findFrontmatterRange(lines, warnings);
|
|
107
|
+
if (!range)
|
|
108
|
+
return { globals: emptyGlobals(), bodyStartLine: 1, body: source };
|
|
109
|
+
const globals = parseFrontmatterEntries(lines, range.start, range.end, warnings);
|
|
110
|
+
const body = lines.slice(range.end + 1).join("\n");
|
|
111
|
+
return { globals, bodyStartLine: range.end + 2, body };
|
|
112
|
+
}
|
|
113
|
+
function assignGlobal(globals, key, value) {
|
|
114
|
+
switch (key) {
|
|
115
|
+
case "format":
|
|
116
|
+
globals.format = value;
|
|
117
|
+
break;
|
|
118
|
+
case "message":
|
|
119
|
+
globals.message = value;
|
|
120
|
+
break;
|
|
121
|
+
case "arc":
|
|
122
|
+
globals.arc = value;
|
|
123
|
+
break;
|
|
124
|
+
case "audience":
|
|
125
|
+
globals.audience = value;
|
|
126
|
+
break;
|
|
127
|
+
default:
|
|
128
|
+
globals.extra[key] = value;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** Open a new frame section if `line` is a frame heading, else null. */
|
|
132
|
+
function openFrameSection(line, headingLine) {
|
|
133
|
+
const match = FRAME_HEADING_RE.exec(line);
|
|
134
|
+
if (!match)
|
|
135
|
+
return null;
|
|
136
|
+
const headingText = line.slice(match[0].length).replace(FRAME_TITLE_SEP_RE, "").trim();
|
|
137
|
+
return { headingText, headingLine, level: (match[1] ?? "##").length, lines: [] };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Whether `line` ends the current frame: a non-frame heading at the same or
|
|
141
|
+
* shallower depth (e.g. a sibling `## Fonts`). Deeper sub-headings (e.g.
|
|
142
|
+
* `#### Beats`) stay part of the frame's narrative.
|
|
143
|
+
*/
|
|
144
|
+
function endsFrameSection(line, current) {
|
|
145
|
+
if (!current)
|
|
146
|
+
return false;
|
|
147
|
+
const heading = HEADING_LEVEL_RE.exec(line);
|
|
148
|
+
return heading !== null && (heading[1] ?? "").length <= current.level;
|
|
149
|
+
}
|
|
150
|
+
function parseFrames(body, bodyStartLine, warnings) {
|
|
151
|
+
const lines = body.split(/\r?\n/);
|
|
152
|
+
const sections = [];
|
|
153
|
+
let current = null;
|
|
154
|
+
for (let i = 0; i < lines.length; i++) {
|
|
155
|
+
const line = lines[i] ?? "";
|
|
156
|
+
const opened = openFrameSection(line, bodyStartLine + i);
|
|
157
|
+
if (opened) {
|
|
158
|
+
sections.push(opened);
|
|
159
|
+
current = opened;
|
|
160
|
+
}
|
|
161
|
+
else if (endsFrameSection(line, current)) {
|
|
162
|
+
current = null;
|
|
163
|
+
}
|
|
164
|
+
else if (current) {
|
|
165
|
+
current.lines.push(line);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return sections.map((section, idx) => buildFrame(section, idx + 1, warnings));
|
|
169
|
+
}
|
|
170
|
+
function buildFrame(section, index, warnings) {
|
|
171
|
+
const frame = { index, status: DEFAULT_FRAME_STATUS, narrative: "", extra: {} };
|
|
172
|
+
const { number, title } = parseHeading(section.headingText);
|
|
173
|
+
if (number !== undefined)
|
|
174
|
+
frame.number = number;
|
|
175
|
+
if (title)
|
|
176
|
+
frame.title = title;
|
|
177
|
+
const narrativeLines = [];
|
|
178
|
+
for (const line of section.lines) {
|
|
179
|
+
const meta = META_RE.exec(line);
|
|
180
|
+
if (meta) {
|
|
181
|
+
applyMeta(frame, (meta[1] ?? "").toLowerCase(), (meta[2] ?? "").trim(), section.headingLine, warnings);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
narrativeLines.push(line);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
frame.narrative = narrativeLines.join("\n").trim();
|
|
188
|
+
return frame;
|
|
189
|
+
}
|
|
190
|
+
function parseHeading(text) {
|
|
191
|
+
if (!text)
|
|
192
|
+
return {};
|
|
193
|
+
const intMatch = LEADING_INT_RE.exec(text);
|
|
194
|
+
if (!intMatch)
|
|
195
|
+
return { title: text };
|
|
196
|
+
const number = Number.parseInt(intMatch[1] ?? "", 10);
|
|
197
|
+
const rest = text
|
|
198
|
+
.slice((intMatch[0] ?? "").length)
|
|
199
|
+
.replace(/^[\s.:—-]+/, "")
|
|
200
|
+
.trim();
|
|
201
|
+
return { number, title: rest || undefined };
|
|
202
|
+
}
|
|
203
|
+
/** Map of metadata key (and aliases) → setter. Keeps {@link applyMeta} a flat dispatch. */
|
|
204
|
+
const META_SETTERS = new Map([
|
|
205
|
+
["duration", applyDuration],
|
|
206
|
+
["status", applyStatus],
|
|
207
|
+
["poster", applyPoster],
|
|
208
|
+
[
|
|
209
|
+
"src",
|
|
210
|
+
(frame, value) => {
|
|
211
|
+
frame.src = value;
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
...keyedSetters(TRANSITION_KEYS, (frame, value) => {
|
|
215
|
+
frame.transitionIn = value;
|
|
216
|
+
}),
|
|
217
|
+
...keyedSetters(SCENE_KEYS, (frame, value) => {
|
|
218
|
+
frame.scene = value;
|
|
219
|
+
}),
|
|
220
|
+
...keyedSetters(VOICEOVER_KEYS, (frame, value) => {
|
|
221
|
+
frame.voiceover = stripQuotes(value);
|
|
222
|
+
}),
|
|
223
|
+
]);
|
|
224
|
+
function keyedSetters(keys, setter) {
|
|
225
|
+
return [...keys].map((key) => [key, setter]);
|
|
226
|
+
}
|
|
227
|
+
function applyMeta(frame, key, value, headingLine, warnings) {
|
|
228
|
+
const setter = META_SETTERS.get(key);
|
|
229
|
+
if (setter)
|
|
230
|
+
setter(frame, value, headingLine, warnings);
|
|
231
|
+
else
|
|
232
|
+
frame.extra[key] = value;
|
|
233
|
+
}
|
|
234
|
+
function applyPoster(frame, value) {
|
|
235
|
+
const num = DURATION_NUM_RE.exec(value);
|
|
236
|
+
if (num)
|
|
237
|
+
frame.poster = Number.parseFloat(num[1] ?? "");
|
|
238
|
+
}
|
|
239
|
+
function applyDuration(frame, value, headingLine, warnings) {
|
|
240
|
+
frame.duration = value;
|
|
241
|
+
const num = DURATION_NUM_RE.exec(value);
|
|
242
|
+
if (num) {
|
|
243
|
+
frame.durationSeconds = Number.parseFloat(num[1] ?? "");
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
warnings.push({
|
|
247
|
+
message: `Frame ${frame.index}: could not parse duration "${value}".`,
|
|
248
|
+
line: headingLine,
|
|
249
|
+
frameIndex: frame.index,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
function applyStatus(frame, value, headingLine, warnings) {
|
|
253
|
+
const normalized = value.toLowerCase();
|
|
254
|
+
if (isFrameStatus(normalized)) {
|
|
255
|
+
frame.status = normalized;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
frame.extra.status = value;
|
|
259
|
+
warnings.push({
|
|
260
|
+
message: `Frame ${frame.index}: unknown status "${value}"; defaulting to "${DEFAULT_FRAME_STATUS}".`,
|
|
261
|
+
line: headingLine,
|
|
262
|
+
frameIndex: frame.index,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
function stripQuotes(value) {
|
|
266
|
+
if (value.length >= 2) {
|
|
267
|
+
const first = value[0];
|
|
268
|
+
const last = value[value.length - 1];
|
|
269
|
+
if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
|
|
270
|
+
return value.slice(1, -1);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return value;
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=parseStoryboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseStoryboard.js","sourceRoot":"","sources":["../../src/storyboard/parseStoryboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storyboard data model.
|
|
3
|
+
*
|
|
4
|
+
* A storyboard is the plan for a video before any animation work happens: an
|
|
5
|
+
* ordered set of frames (key moments) plus their narrative/script. It is
|
|
6
|
+
* authored as a single canonical markdown file (`STORYBOARD.md`) and parsed
|
|
7
|
+
* into this normalized shape for the Studio's storyboard view and for agents.
|
|
8
|
+
*
|
|
9
|
+
* See PRD: "Storyboarding in HyperFrames". The markdown stays canonical; this
|
|
10
|
+
* is the derived structure the parser produces.
|
|
11
|
+
*/
|
|
12
|
+
/** Canonical filename for the storyboard manifest at a project root. */
|
|
13
|
+
export declare const STORYBOARD_FILENAME = "STORYBOARD.md";
|
|
14
|
+
/**
|
|
15
|
+
* Canonical filename for the companion narration script. Holds the full
|
|
16
|
+
* voiceover script (voice settings, per-line delivery + timing). Optional —
|
|
17
|
+
* frames can also carry an inline `voiceover` line in {@link STORYBOARD_FILENAME}.
|
|
18
|
+
*/
|
|
19
|
+
export declare const SCRIPT_FILENAME = "SCRIPT.md";
|
|
20
|
+
/**
|
|
21
|
+
* Lifecycle of a single frame. The agent advances each frame
|
|
22
|
+
* `outline → built → animated`; the Studio renders progress from this.
|
|
23
|
+
*/
|
|
24
|
+
export type FrameStatus = "outline" | "built" | "animated";
|
|
25
|
+
/** The set of recognized {@link FrameStatus} values. */
|
|
26
|
+
export declare const FRAME_STATUSES: readonly FrameStatus[];
|
|
27
|
+
/** Default status when a frame omits one (it is still just an outline). */
|
|
28
|
+
export declare const DEFAULT_FRAME_STATUS: FrameStatus;
|
|
29
|
+
/** Global direction for the whole video, parsed from the frontmatter. */
|
|
30
|
+
export interface StoryboardGlobals {
|
|
31
|
+
/** Canvas format as authored, e.g. `"1920x1080"`. */
|
|
32
|
+
format?: string;
|
|
33
|
+
/** One-line message / thesis of the video. */
|
|
34
|
+
message?: string;
|
|
35
|
+
/** Narrative arc, e.g. `"Problem → Solution"`. */
|
|
36
|
+
arc?: string;
|
|
37
|
+
/** Target audience, e.g. `"indie devs on X"`. */
|
|
38
|
+
audience?: string;
|
|
39
|
+
/** Any frontmatter keys outside the known set, preserved verbatim. */
|
|
40
|
+
extra: Record<string, string>;
|
|
41
|
+
}
|
|
42
|
+
/** A single frame: one key moment in the video. */
|
|
43
|
+
export interface StoryboardFrame {
|
|
44
|
+
/** 1-based order within the storyboard, assigned by document order. */
|
|
45
|
+
index: number;
|
|
46
|
+
/** Frame number as authored (the `N` in `Frame N`), when present. */
|
|
47
|
+
number?: number;
|
|
48
|
+
/** Frame title (the text after the number), when present. */
|
|
49
|
+
title?: string;
|
|
50
|
+
/** Lifecycle status; defaults to {@link DEFAULT_FRAME_STATUS}. */
|
|
51
|
+
status: FrameStatus;
|
|
52
|
+
/** Project-relative path to the frame's HTML sub-composition, when linked. */
|
|
53
|
+
src?: string;
|
|
54
|
+
/** Duration in seconds, parsed from e.g. `"6s"`. Undefined when unparseable. */
|
|
55
|
+
durationSeconds?: number;
|
|
56
|
+
/** Raw duration string as authored, e.g. `"6s"`. */
|
|
57
|
+
duration?: string;
|
|
58
|
+
/** Transition into this frame, e.g. `"crossfade"`. */
|
|
59
|
+
transitionIn?: string;
|
|
60
|
+
/** One-line description of the key moment (the contact-sheet caption). */
|
|
61
|
+
scene?: string;
|
|
62
|
+
/** Voiceover / narration line spoken over this frame. */
|
|
63
|
+
voiceover?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Representative time (seconds) to show this frame at in the contact sheet —
|
|
66
|
+
* a "poster" frame past the intro animation. Falls back to a heuristic.
|
|
67
|
+
*/
|
|
68
|
+
poster?: number;
|
|
69
|
+
/** Narrative / script markdown for this frame (everything below the metadata). */
|
|
70
|
+
narrative: string;
|
|
71
|
+
/** Metadata keys outside the known set, preserved verbatim. */
|
|
72
|
+
extra: Record<string, string>;
|
|
73
|
+
}
|
|
74
|
+
/** A non-fatal issue encountered while parsing. The parser never throws. */
|
|
75
|
+
export interface StoryboardWarning {
|
|
76
|
+
message: string;
|
|
77
|
+
/** 1-based source line number, when known. */
|
|
78
|
+
line?: number;
|
|
79
|
+
/** 1-based frame index the warning relates to, when applicable. */
|
|
80
|
+
frameIndex?: number;
|
|
81
|
+
}
|
|
82
|
+
/** Fully parsed storyboard manifest. */
|
|
83
|
+
export interface StoryboardManifest {
|
|
84
|
+
globals: StoryboardGlobals;
|
|
85
|
+
frames: StoryboardFrame[];
|
|
86
|
+
/** Non-fatal parse issues (unknown status, unparseable duration, etc.). */
|
|
87
|
+
warnings: StoryboardWarning[];
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/storyboard/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAE3D,wDAAwD;AACxD,eAAO,MAAM,cAAc,EAAE,SAAS,WAAW,EAAqC,CAAC;AAEvF,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,EAAE,WAAuB,CAAC;AAE3D,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,EAAE,WAAW,CAAC;IACpB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storyboard data model.
|
|
3
|
+
*
|
|
4
|
+
* A storyboard is the plan for a video before any animation work happens: an
|
|
5
|
+
* ordered set of frames (key moments) plus their narrative/script. It is
|
|
6
|
+
* authored as a single canonical markdown file (`STORYBOARD.md`) and parsed
|
|
7
|
+
* into this normalized shape for the Studio's storyboard view and for agents.
|
|
8
|
+
*
|
|
9
|
+
* See PRD: "Storyboarding in HyperFrames". The markdown stays canonical; this
|
|
10
|
+
* is the derived structure the parser produces.
|
|
11
|
+
*/
|
|
12
|
+
/** Canonical filename for the storyboard manifest at a project root. */
|
|
13
|
+
export const STORYBOARD_FILENAME = "STORYBOARD.md";
|
|
14
|
+
/**
|
|
15
|
+
* Canonical filename for the companion narration script. Holds the full
|
|
16
|
+
* voiceover script (voice settings, per-line delivery + timing). Optional —
|
|
17
|
+
* frames can also carry an inline `voiceover` line in {@link STORYBOARD_FILENAME}.
|
|
18
|
+
*/
|
|
19
|
+
export const SCRIPT_FILENAME = "SCRIPT.md";
|
|
20
|
+
/** The set of recognized {@link FrameStatus} values. */
|
|
21
|
+
export const FRAME_STATUSES = ["outline", "built", "animated"];
|
|
22
|
+
/** Default status when a frame omits one (it is still just an outline). */
|
|
23
|
+
export const DEFAULT_FRAME_STATUS = "outline";
|
|
24
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/storyboard/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wEAAwE;AACxE,MAAM,CAAC,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAEnD;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAQ3C,wDAAwD;AACxD,MAAM,CAAC,MAAM,cAAc,GAA2B,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AAEvF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,oBAAoB,GAAgB,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createStudioApi.d.ts","sourceRoot":"","sources":["../../src/studio-api/createStudioApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"createStudioApi.d.ts","sourceRoot":"","sources":["../../src/studio-api/createStudioApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAYnD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAe/D"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import { registerProjectRoutes } from "./routes/projects.js";
|
|
3
|
+
import { registerStoryboardRoutes } from "./routes/storyboard.js";
|
|
3
4
|
import { registerFileRoutes } from "./routes/files.js";
|
|
4
5
|
import { registerPreviewRoutes } from "./routes/preview.js";
|
|
5
6
|
import { registerLintRoutes } from "./routes/lint.js";
|
|
@@ -17,6 +18,7 @@ import { registerRegistryRoutes } from "./routes/registry.js";
|
|
|
17
18
|
export function createStudioApi(adapter) {
|
|
18
19
|
const api = new Hono();
|
|
19
20
|
registerProjectRoutes(api, adapter);
|
|
21
|
+
registerStoryboardRoutes(api, adapter);
|
|
20
22
|
registerFileRoutes(api, adapter);
|
|
21
23
|
registerPreviewRoutes(api, adapter);
|
|
22
24
|
registerLintRoutes(api, adapter);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createStudioApi.js","sourceRoot":"","sources":["../../src/studio-api/createStudioApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpC,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpC,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACnC,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACtC,sBAAsB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACrC,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACxB,sBAAsB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAErC,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
1
|
+
{"version":3,"file":"createStudioApi.js","sourceRoot":"","sources":["../../src/studio-api/createStudioApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpC,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACvC,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpC,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACnC,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACtC,sBAAsB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACrC,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACxB,sBAAsB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAErC,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyboard.d.ts","sourceRoot":"","sources":["../../../src/studio-api/routes/storyboard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAuCpD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAsCnF"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { resolveWithinProject } from "../helpers/safePath.js";
|
|
3
|
+
import { parseStoryboard, SCRIPT_FILENAME, STORYBOARD_FILENAME, } from "../../storyboard/index.js";
|
|
4
|
+
function resolveFrames(projectDir, frames) {
|
|
5
|
+
return frames.map((frame) => {
|
|
6
|
+
let srcExists = false;
|
|
7
|
+
if (frame.src) {
|
|
8
|
+
const abs = resolveWithinProject(projectDir, frame.src);
|
|
9
|
+
srcExists = abs ? existsSync(abs) : false;
|
|
10
|
+
}
|
|
11
|
+
return { ...frame, srcExists };
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/** Read the companion SCRIPT.md narration doc if it exists alongside the storyboard. */
|
|
15
|
+
function readScript(projectDir) {
|
|
16
|
+
const abs = resolveWithinProject(projectDir, SCRIPT_FILENAME);
|
|
17
|
+
if (abs && existsSync(abs)) {
|
|
18
|
+
try {
|
|
19
|
+
return { exists: true, path: SCRIPT_FILENAME, content: readFileSync(abs, "utf-8") };
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
/* fall through to absent */
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return { exists: false, path: SCRIPT_FILENAME, content: "" };
|
|
26
|
+
}
|
|
27
|
+
export function registerStoryboardRoutes(api, adapter) {
|
|
28
|
+
// Parsed storyboard manifest for a project. Markdown (STORYBOARD.md) stays
|
|
29
|
+
// canonical on disk; this returns the derived, normalized structure. When the
|
|
30
|
+
// file is absent we return `exists: false` with empty frames rather than 404,
|
|
31
|
+
// so the Studio can render an opt-in empty state.
|
|
32
|
+
api.get("/projects/:id/storyboard", async (c) => {
|
|
33
|
+
const project = await adapter.resolveProject(c.req.param("id"));
|
|
34
|
+
if (!project)
|
|
35
|
+
return c.json({ error: "not found" }, 404);
|
|
36
|
+
const abs = resolveWithinProject(project.dir, STORYBOARD_FILENAME);
|
|
37
|
+
if (!abs || !existsSync(abs)) {
|
|
38
|
+
return c.json({
|
|
39
|
+
exists: false,
|
|
40
|
+
path: STORYBOARD_FILENAME,
|
|
41
|
+
globals: { extra: {} },
|
|
42
|
+
frames: [],
|
|
43
|
+
warnings: [],
|
|
44
|
+
script: readScript(project.dir),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
let source;
|
|
48
|
+
try {
|
|
49
|
+
source = readFileSync(abs, "utf-8");
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return c.json({ error: "failed to read storyboard" }, 500);
|
|
53
|
+
}
|
|
54
|
+
const manifest = parseStoryboard(source);
|
|
55
|
+
return c.json({
|
|
56
|
+
exists: true,
|
|
57
|
+
path: STORYBOARD_FILENAME,
|
|
58
|
+
globals: manifest.globals,
|
|
59
|
+
frames: resolveFrames(project.dir, manifest.frames),
|
|
60
|
+
warnings: manifest.warnings,
|
|
61
|
+
script: readScript(project.dir),
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=storyboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyboard.js","sourceRoot":"","sources":["../../../src/studio-api/routes/storyboard.ts"],"names":[],"mappings":"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"}
|