tutorial-forge 0.1.0 → 0.2.0
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/browser/instrument.js +8 -3
- package/dist/browser/instrument.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -1
- package/dist/i18n.d.ts +14 -0
- package/dist/i18n.js +48 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/record.d.ts +2 -0
- package/dist/pipeline/record.js +10 -8
- package/dist/pipeline/record.js.map +1 -1
- package/dist/pipeline/render.js +7 -1
- package/dist/pipeline/render.js.map +1 -1
- package/dist/types.d.ts +22 -6
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CURSOR_TRAVEL_MS } from './cursor.js';
|
|
2
|
+
import { CALLOUT_VISIBLE_MS } from './callout.js';
|
|
2
3
|
import { logger } from '../util/logger.js';
|
|
3
4
|
/** Locator methods that interact with an element (cursor should travel there first). */
|
|
4
5
|
const ACTION_METHODS = new Set([
|
|
@@ -43,12 +44,16 @@ async function presentAction(page, target, method, hooks) {
|
|
|
43
44
|
await page.waitForTimeout(CURSOR_TRAVEL_MS + 50);
|
|
44
45
|
}
|
|
45
46
|
if (CLICK_METHODS.has(method)) {
|
|
46
|
-
if (hooks.cursor) {
|
|
47
|
-
await page.evaluate(([x, y]) => window.__forgeCursor?.pulse(x, y), [cx, cy]);
|
|
48
|
-
}
|
|
49
47
|
if (hooks.callouts) {
|
|
50
48
|
await page.evaluate(([x, y, w, h]) => window.__forgeCallout?.(x, y, w, h), [box.x, box.y, box.width, box.height]);
|
|
51
49
|
hooks.onCallout({ atMs: hooks.nowMs(), x: box.x, y: box.y, w: box.width, h: box.height });
|
|
50
|
+
// Let the ring play out fully BEFORE the click: it sits above app
|
|
51
|
+
// content (high z-index), so if it lingered past the click it would
|
|
52
|
+
// float over whatever the click reveals — modal backdrops, new routes.
|
|
53
|
+
await page.waitForTimeout(CALLOUT_VISIBLE_MS + 250);
|
|
54
|
+
}
|
|
55
|
+
if (hooks.cursor) {
|
|
56
|
+
await page.evaluate(([x, y]) => window.__forgeCursor?.pulse(x, y), [cx, cy]);
|
|
52
57
|
}
|
|
53
58
|
}
|
|
54
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument.js","sourceRoot":"","sources":["../../src/browser/instrument.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAU3C,wFAAwF;AACxF,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY;IACtE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,OAAO;CACrE,CAAC,CAAC;AAEH,yDAAyD;AACzD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK;CAC7E,CAAC,CAAC;AAEH,8EAA8E;AAC9E,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB;IACrE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK;IACnE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU;CAClC,CAAC,CAAC;AAEH,wDAAwD;AACxD,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB;IACrE,aAAa,EAAE,YAAY,EAAE,cAAc;CAC5C,CAAC,CAAC;AAEH,iFAAiF;AACjF,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM;CACjG,CAAC,CAAC;AAEH;;;GAGG;AACH,KAAK,UAAU,aAAa,CAC1B,IAAU,EACV,MAAe,EACf,MAAc,EACd,KAAsB;IAEtB,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ;QAAE,OAAO;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;QACvC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;QACjC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QAClC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,QAAQ,CACjB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAE,MAAqE,CAAC,aAAa,EAAE,MAAM,CAAC,CAAE,EAAE,CAAE,CAAC,EAChH,CAAC,EAAE,EAAE,EAAE,CAAC,CACT,CAAC;YACF,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,IAAI,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"instrument.js","sourceRoot":"","sources":["../../src/browser/instrument.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAU3C,wFAAwF;AACxF,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY;IACtE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,OAAO;CACrE,CAAC,CAAC;AAEH,yDAAyD;AACzD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK;CAC7E,CAAC,CAAC;AAEH,8EAA8E;AAC9E,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB;IACrE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK;IACnE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU;CAClC,CAAC,CAAC;AAEH,wDAAwD;AACxD,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB;IACrE,aAAa,EAAE,YAAY,EAAE,cAAc;CAC5C,CAAC,CAAC;AAEH,iFAAiF;AACjF,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM;CACjG,CAAC,CAAC;AAEH;;;GAGG;AACH,KAAK,UAAU,aAAa,CAC1B,IAAU,EACV,MAAe,EACf,MAAc,EACd,KAAsB;IAEtB,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ;QAAE,OAAO;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;QACvC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;QACjC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QAClC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,QAAQ,CACjB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAE,MAAqE,CAAC,aAAa,EAAE,MAAM,CAAC,CAAE,EAAE,CAAE,CAAC,EAChH,CAAC,EAAE,EAAE,EAAE,CAAC,CACT,CAAC;YACF,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,IAAI,CAAC,QAAQ,CACjB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CACd,MAAoF,CAAC,cAAc,EAAE,CAAC,CAAE,EAAE,CAAE,EAAE,CAAE,EAAE,CAAE,CAAC,EACxH,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CACtC,CAAC;gBACF,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC1F,kEAAkE;gBAClE,oEAAoE;gBACpE,uEAAuE;gBACvE,MAAM,IAAI,CAAC,cAAc,CAAC,kBAAkB,GAAG,GAAG,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,MAAM,IAAI,CAAC,QAAQ,CACjB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAE,MAAoE,CAAC,aAAa,EAAE,KAAK,CAAC,CAAE,EAAE,CAAE,CAAC,EAC9G,CAAC,EAAE,EAAE,EAAE,CAAC,CACT,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,mCAAmC,MAAM,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACzG,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,OAAgB,EAAE,IAAU,EAAE,KAAsB;IACvE,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;QACxB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ;YACxB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAChD,IAAI,OAAO,KAAK,KAAK,UAAU,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC1E,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,OAAO,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;oBAClC,MAAM,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;oBAC/C,OAAQ,KAAsC,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACrE,CAAC,CAAC;YACJ,CAAC;YACD,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE;oBAC5B,MAAM,MAAM,GAAI,KAAsC,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;oBAC3E,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,MAAiB,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBACtF,CAAC,CAAC;YACJ,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAC/B,OAAO,CAAC,CAAC,CAAC,IAAI,OAAQ,CAAa,CAAC,KAAK,KAAK,UAAU,IAAI,OAAQ,CAAa,CAAC,WAAW,KAAK,UAAU,CAAC;AAC/G,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU,EAAE,KAAsB;IAC/D,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;QACrB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ;YACxB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAChD,IAAI,OAAO,KAAK,KAAK,UAAU,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC1E,IAAI,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE;oBAC5B,MAAM,MAAM,GAAI,KAAsC,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;oBAC3E,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,MAAiB,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBACxF,CAAC,CAAC;YACJ,CAAC;YACD,IAAI,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClC,OAAO,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;oBAClC,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;wBAChC,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;oBACpE,CAAC;oBACD,OAAQ,KAAsC,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACrE,CAAC,CAAC;YACJ,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -19,6 +19,12 @@ export interface ForgeConfig {
|
|
|
19
19
|
keepWorkDir?: boolean;
|
|
20
20
|
ttsCacheDir?: string;
|
|
21
21
|
ttsConcurrency?: number;
|
|
22
|
+
/** Languages rendered by default (overridable with --lang). Omit for source-language only. */
|
|
23
|
+
languages?: string[];
|
|
24
|
+
/** The language tutorial narration is written in. Default 'en'. */
|
|
25
|
+
defaultLang?: string;
|
|
26
|
+
/** Per-language TTS provider override (e.g. a different voice per language). Falls back to tts. */
|
|
27
|
+
ttsByLang?: Record<string, TTSProvider>;
|
|
22
28
|
}
|
|
23
29
|
export declare function defineConfig(config: ForgeConfig): ForgeConfig;
|
|
24
30
|
/** Validate a loaded config object (e.g. from forge.config.ts). Throws with a readable message. */
|
package/dist/config.js
CHANGED
|
@@ -20,6 +20,11 @@ const configSchema = z.object({
|
|
|
20
20
|
keepWorkDir: z.boolean().optional(),
|
|
21
21
|
ttsCacheDir: z.string().optional(),
|
|
22
22
|
ttsConcurrency: z.number().int().positive().optional(),
|
|
23
|
+
languages: z.array(z.string().min(2)).optional(),
|
|
24
|
+
defaultLang: z.string().min(2).optional(),
|
|
25
|
+
ttsByLang: z
|
|
26
|
+
.record(z.object({ cacheKey: z.string().min(1), synthesize: z.function() }))
|
|
27
|
+
.optional(),
|
|
23
28
|
});
|
|
24
29
|
export function defineConfig(config) {
|
|
25
30
|
return config;
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Tutorial } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Return a copy of the tutorial with narration swapped to the given language.
|
|
4
|
+
* Translation tables are keyed by step id — give steps explicit ids so tables
|
|
5
|
+
* stay stable when steps are reordered.
|
|
6
|
+
*
|
|
7
|
+
* - lang === defaultLang → the spec's own narration, unchanged.
|
|
8
|
+
* - Missing entries fall back to the source narration with a warning.
|
|
9
|
+
* - A language with no table at all throws: rendering a wholly untranslated
|
|
10
|
+
* tutorial under a language suffix would silently produce a mislabeled video.
|
|
11
|
+
*/
|
|
12
|
+
export declare function localizeTutorial(tutorial: Tutorial, lang: string, defaultLang?: string): Tutorial;
|
|
13
|
+
/** Languages a tutorial can render in: the default language plus every translation table. */
|
|
14
|
+
export declare function availableLanguages(tutorial: Tutorial, defaultLang?: string): string[];
|
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { stepId } from './spec.js';
|
|
2
|
+
import { logger } from './util/logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Return a copy of the tutorial with narration swapped to the given language.
|
|
5
|
+
* Translation tables are keyed by step id — give steps explicit ids so tables
|
|
6
|
+
* stay stable when steps are reordered.
|
|
7
|
+
*
|
|
8
|
+
* - lang === defaultLang → the spec's own narration, unchanged.
|
|
9
|
+
* - Missing entries fall back to the source narration with a warning.
|
|
10
|
+
* - A language with no table at all throws: rendering a wholly untranslated
|
|
11
|
+
* tutorial under a language suffix would silently produce a mislabeled video.
|
|
12
|
+
*/
|
|
13
|
+
export function localizeTutorial(tutorial, lang, defaultLang = 'en') {
|
|
14
|
+
if (lang === defaultLang)
|
|
15
|
+
return tutorial;
|
|
16
|
+
const table = tutorial.translations?.[lang];
|
|
17
|
+
if (!table) {
|
|
18
|
+
const available = Object.keys(tutorial.translations ?? {});
|
|
19
|
+
throw new Error(`Tutorial "${tutorial.id}" has no translations for "${lang}"` +
|
|
20
|
+
(available.length ? ` (available: ${available.join(', ')})` : '') +
|
|
21
|
+
` — add a <tutorial-file>.${lang}.json sidecar or a translations entry`);
|
|
22
|
+
}
|
|
23
|
+
const knownIds = new Set(tutorial.steps.map((s, i) => stepId(s, i)));
|
|
24
|
+
const unknown = Object.keys(table).filter((k) => !knownIds.has(k));
|
|
25
|
+
if (unknown.length) {
|
|
26
|
+
logger.warn(`Tutorial "${tutorial.id}" [${lang}]: translation keys match no step: ${unknown.join(', ')}`);
|
|
27
|
+
}
|
|
28
|
+
const missing = [];
|
|
29
|
+
const steps = tutorial.steps.map((step, i) => {
|
|
30
|
+
const id = stepId(step, i);
|
|
31
|
+
const translated = table[id];
|
|
32
|
+
if (translated === undefined) {
|
|
33
|
+
if (step.narration.trim())
|
|
34
|
+
missing.push(id);
|
|
35
|
+
return step;
|
|
36
|
+
}
|
|
37
|
+
return { ...step, narration: translated };
|
|
38
|
+
});
|
|
39
|
+
if (missing.length) {
|
|
40
|
+
logger.warn(`Tutorial "${tutorial.id}" [${lang}]: no translation for step(s) ${missing.join(', ')} — using source narration`);
|
|
41
|
+
}
|
|
42
|
+
return { ...tutorial, steps };
|
|
43
|
+
}
|
|
44
|
+
/** Languages a tutorial can render in: the default language plus every translation table. */
|
|
45
|
+
export function availableLanguages(tutorial, defaultLang = 'en') {
|
|
46
|
+
return [defaultLang, ...Object.keys(tutorial.translations ?? {}).filter((l) => l !== defaultLang)];
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=i18n.js.map
|
package/dist/i18n.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAkB,EAAE,IAAY,EAAE,WAAW,GAAG,IAAI;IACnF,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,QAAQ,CAAC;IAE1C,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,aAAa,QAAQ,CAAC,EAAE,8BAA8B,IAAI,GAAG;YAC3D,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,4BAA4B,IAAI,uCAAuC,CAC1E,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CACT,aAAa,QAAQ,CAAC,EAAE,MAAM,IAAI,sCAAsC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC7F,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QAC3C,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3B,MAAM,UAAU,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;gBAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CACT,aAAa,QAAQ,CAAC,EAAE,MAAM,IAAI,iCAAiC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,2BAA2B,CACjH,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,kBAAkB,CAAC,QAAkB,EAAE,WAAW,GAAG,IAAI;IACvE,OAAO,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC;AACrG,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export type { Tutorial, Step, TutorialAdapter, TTSProvider, RenderOptions, TimingManifest, ManifestStep, CalloutRecord, } from './types.js';
|
|
1
|
+
export type { Tutorial, Step, StepContext, TutorialAdapter, TTSProvider, RenderOptions, TimingManifest, ManifestStep, CalloutRecord, } from './types.js';
|
|
2
2
|
export { StepError } from './types.js';
|
|
3
3
|
export { tutorial, step, validateTutorial, stepId } from './spec.js';
|
|
4
|
+
export { localizeTutorial, availableLanguages } from './i18n.js';
|
|
4
5
|
export { defineConfig, validateConfig, type ForgeConfig } from './config.js';
|
|
5
6
|
export { render, type RenderResult } from './pipeline/render.js';
|
|
6
7
|
export { runTTSPhase, loadTTSResult } from './pipeline/tts.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Public API surface — re-exports only.
|
|
2
2
|
export { StepError } from './types.js';
|
|
3
3
|
export { tutorial, step, validateTutorial, stepId } from './spec.js';
|
|
4
|
+
export { localizeTutorial, availableLanguages } from './i18n.js';
|
|
4
5
|
export { defineConfig, validateConfig } from './config.js';
|
|
5
6
|
export { render } from './pipeline/render.js';
|
|
6
7
|
export { runTTSPhase, loadTTSResult } from './pipeline/tts.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAaxC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAoB,MAAM,aAAa,CAAC;AAE7E,OAAO,EAAE,MAAM,EAAqB,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAqB,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAA0B,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,aAAa,GAEd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -12,6 +12,8 @@ export interface RecordPhaseOptions {
|
|
|
12
12
|
cursor: boolean;
|
|
13
13
|
callouts: boolean;
|
|
14
14
|
leadInMs: number;
|
|
15
|
+
/** Language being rendered; exposed to adapter and step callbacks via ctx. */
|
|
16
|
+
lang?: string;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* Phase 2 — drive the browser through the tutorial while Playwright records
|
package/dist/pipeline/record.js
CHANGED
|
@@ -50,8 +50,9 @@ export async function runRecordPhase(tutorial, adapter, tts, opts) {
|
|
|
50
50
|
resolve();
|
|
51
51
|
}, ms));
|
|
52
52
|
}, FLASH_MS);
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
const ctx = { lang: opts.lang };
|
|
54
|
+
logger.info(`record: setup (${adapter.baseURL})${opts.lang ? ` [${opts.lang}]` : ''}`);
|
|
55
|
+
await adapter.setup(page, ctx);
|
|
55
56
|
const callouts = tutorial.steps.map(() => []);
|
|
56
57
|
let currentStep = 0;
|
|
57
58
|
const instrumented = instrumentPage(page, {
|
|
@@ -74,12 +75,12 @@ export async function runRecordPhase(tutorial, adapter, tts, opts) {
|
|
|
74
75
|
await page.waitForTimeout(opts.leadInMs);
|
|
75
76
|
const actionStartMs = clock.now();
|
|
76
77
|
try {
|
|
77
|
-
await step.run(instrumented);
|
|
78
|
-
await step.waitFor?.(instrumented);
|
|
78
|
+
await step.run(instrumented, ctx);
|
|
79
|
+
await step.waitFor?.(instrumented, ctx);
|
|
79
80
|
}
|
|
80
81
|
catch (cause) {
|
|
81
82
|
await captureFailure(page, opts.workDir, id);
|
|
82
|
-
await saveManifest(tutorial, clock, manifestSteps, opts.workDir);
|
|
83
|
+
await saveManifest(tutorial, clock, manifestSteps, opts.workDir, opts.lang);
|
|
83
84
|
await safeClose(context.close());
|
|
84
85
|
throw new StepError(tutorial.id, id, cause);
|
|
85
86
|
}
|
|
@@ -107,10 +108,10 @@ export async function runRecordPhase(tutorial, adapter, tts, opts) {
|
|
|
107
108
|
});
|
|
108
109
|
}
|
|
109
110
|
await page.waitForTimeout(FINAL_HOLD_MS);
|
|
110
|
-
const manifest = await saveManifest(tutorial, clock, manifestSteps, opts.workDir);
|
|
111
|
+
const manifest = await saveManifest(tutorial, clock, manifestSteps, opts.workDir, opts.lang);
|
|
111
112
|
if (adapter.teardown) {
|
|
112
113
|
try {
|
|
113
|
-
await adapter.teardown(page);
|
|
114
|
+
await adapter.teardown(page, ctx);
|
|
114
115
|
}
|
|
115
116
|
catch (err) {
|
|
116
117
|
logger.warn(`teardown failed (ignored): ${err instanceof Error ? err.message : err}`);
|
|
@@ -136,9 +137,10 @@ async function launchChromium(headless) {
|
|
|
136
137
|
return chromium.launch({ headless });
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
|
-
async function saveManifest(tutorial, clock, steps, workDir) {
|
|
140
|
+
async function saveManifest(tutorial, clock, steps, workDir, lang) {
|
|
140
141
|
const manifest = {
|
|
141
142
|
tutorialId: tutorial.id,
|
|
143
|
+
...(lang ? { lang } : {}),
|
|
142
144
|
fps: 25,
|
|
143
145
|
recordingStartEpochMs: clock.zeroEpoch,
|
|
144
146
|
steps,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/pipeline/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAA2B,MAAM,YAAY,CAAC;AAE/D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AACzC,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAC7C,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/pipeline/record.ts"],"names":[],"mappings":"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"}
|
package/dist/pipeline/render.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { resolve, join } from 'node:path';
|
|
2
2
|
import { validateTutorial } from '../spec.js';
|
|
3
|
+
import { localizeTutorial } from '../i18n.js';
|
|
3
4
|
import { runTTSPhase, loadTTSResult } from './tts.js';
|
|
4
5
|
import { runRecordPhase, loadManifest } from './record.js';
|
|
5
6
|
import { runPostPhase } from './post.js';
|
|
@@ -13,7 +14,11 @@ import { logger } from '../util/logger.js';
|
|
|
13
14
|
*/
|
|
14
15
|
export async function render(tutorial, adapter, options) {
|
|
15
16
|
validateTutorial(tutorial);
|
|
16
|
-
const
|
|
17
|
+
const lang = options.lang;
|
|
18
|
+
if (lang) {
|
|
19
|
+
tutorial = localizeTutorial(tutorial, lang, options.defaultLang ?? 'en');
|
|
20
|
+
}
|
|
21
|
+
const workDir = resolve(options.workDir ?? join('.forge', lang ? `${tutorial.id}.${lang}` : tutorial.id));
|
|
17
22
|
const output = resolve(options.output);
|
|
18
23
|
const viewport = options.viewport ?? { width: 1920, height: 1080 };
|
|
19
24
|
const leadInMs = options.leadInMs ?? 300;
|
|
@@ -39,6 +44,7 @@ export async function render(tutorial, adapter, options) {
|
|
|
39
44
|
cursor: options.cursor ?? true,
|
|
40
45
|
callouts: options.callouts ?? true,
|
|
41
46
|
leadInMs,
|
|
47
|
+
lang,
|
|
42
48
|
})
|
|
43
49
|
: await loadManifest(workDir);
|
|
44
50
|
if (phase === 'record') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/pipeline/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAwB,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAO3C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,QAAkB,EAClB,OAAwB,EACxB,OAAsB;IAEtB,gBAAgB,CAAC,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/pipeline/render.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import type { Page } from 'playwright';
|
|
2
|
+
/** Passed to adapter and step callbacks; lets app code react to the render language. */
|
|
3
|
+
export interface StepContext {
|
|
4
|
+
/** The language being rendered (from RenderOptions.lang / --lang), if any. */
|
|
5
|
+
lang?: string;
|
|
6
|
+
}
|
|
2
7
|
/** Gets the target app into a known, recordable state. The only app-specific code. */
|
|
3
8
|
export interface TutorialAdapter {
|
|
4
9
|
/** Base URL of the running app, e.g. http://localhost:3000 */
|
|
5
10
|
baseURL: string;
|
|
6
11
|
/** Auth, seeding, navigation to a starting screen. Runs after page creation, before step 1. Excluded from the final video by default. */
|
|
7
|
-
setup(page: Page): Promise<void>;
|
|
12
|
+
setup(page: Page, ctx: StepContext): Promise<void>;
|
|
8
13
|
/** Optional cleanup after recording (delete seeded data, logout). Never recorded. */
|
|
9
|
-
teardown?(page: Page): Promise<void>;
|
|
14
|
+
teardown?(page: Page, ctx: StepContext): Promise<void>;
|
|
10
15
|
}
|
|
11
16
|
export interface Step {
|
|
12
|
-
/** Stable id, auto-derived from index if omitted. Used in manifest, cache keys, logs. */
|
|
17
|
+
/** Stable id, auto-derived from index if omitted. Used in manifest, cache keys, logs, translation tables. */
|
|
13
18
|
id?: string;
|
|
14
|
-
/** The narration line spoken over this step. Plain text; may be ''. */
|
|
19
|
+
/** The narration line spoken over this step, in the source language. Plain text; may be ''. */
|
|
15
20
|
narration: string;
|
|
16
21
|
/** The action. Receives the raw Playwright Page. May be a no-op for pure-narration steps. */
|
|
17
|
-
run: (page: Page) => Promise<void>;
|
|
22
|
+
run: (page: Page, ctx: StepContext) => Promise<void>;
|
|
18
23
|
/** Optional readiness hook awaited after run(); use when auto-waiting isn't enough. */
|
|
19
|
-
waitFor?: (page: Page) => Promise<void>;
|
|
24
|
+
waitFor?: (page: Page, ctx: StepContext) => Promise<void>;
|
|
20
25
|
/** Extra hold time (ms) after both narration and action complete. Default 400. */
|
|
21
26
|
settleMs?: number;
|
|
22
27
|
}
|
|
@@ -26,6 +31,11 @@ export interface Tutorial {
|
|
|
26
31
|
title: string;
|
|
27
32
|
description?: string;
|
|
28
33
|
steps: Step[];
|
|
34
|
+
/**
|
|
35
|
+
* Per-language narration overrides: lang → (step id → translated line).
|
|
36
|
+
* Usually loaded from sidecar files (<tutorial-file>.<lang>.json) by the CLI.
|
|
37
|
+
*/
|
|
38
|
+
translations?: Record<string, Record<string, string>>;
|
|
29
39
|
}
|
|
30
40
|
export interface TTSProvider {
|
|
31
41
|
/** Unique key for cache partitioning, e.g. "elevenlabs:daniel:eleven_turbo_v2" */
|
|
@@ -62,6 +72,10 @@ export interface RenderOptions {
|
|
|
62
72
|
ttsConcurrency?: number;
|
|
63
73
|
/** Which phases to run. Default 'all'. */
|
|
64
74
|
phase?: 'tts' | 'record' | 'post' | 'all';
|
|
75
|
+
/** Render this language: narration comes from tutorial.translations[lang] and ctx.lang is set. */
|
|
76
|
+
lang?: string;
|
|
77
|
+
/** The language the spec's narration strings are written in. Default 'en'. */
|
|
78
|
+
defaultLang?: string;
|
|
65
79
|
}
|
|
66
80
|
export interface CalloutRecord {
|
|
67
81
|
atMs: number;
|
|
@@ -89,6 +103,8 @@ export interface ManifestStep {
|
|
|
89
103
|
/** Written to workDir as manifest.json; the contract between record and post phases. */
|
|
90
104
|
export interface TimingManifest {
|
|
91
105
|
tutorialId: string;
|
|
106
|
+
/** Language this render used, if localized. */
|
|
107
|
+
lang?: string;
|
|
92
108
|
fps: number;
|
|
93
109
|
recordingStartEpochMs: number;
|
|
94
110
|
/** Offset (ms) into the raw webm where the recording clock's zero falls, derived from the calibration flash. 0 if undetected. */
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAyHA,qEAAqE;AACrE,MAAM,OAAO,SAAU,SAAQ,KAAK;IAEhB;IACA;IACS;IAH3B,YACkB,UAAkB,EAClB,MAAc,EACL,KAAc;QAEvC,KAAK,CACH,SAAS,MAAM,kBAAkB,UAAU,aAAa,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACjH,CAAC;QANc,eAAU,GAAV,UAAU,CAAQ;QAClB,WAAM,GAAN,MAAM,CAAQ;QACL,UAAK,GAAL,KAAK,CAAS;QAKvC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tutorial-forge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Turn scripted Playwright walkthroughs into narrated tutorial videos (MP4). Tutorials are source code: re-render instead of re-recording when your UI changes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|