@pinepaper.studio/mcp-server 1.6.12 → 1.6.14
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/README.de.md +1 -1
- package/README.es.md +1 -1
- package/README.fr.md +1 -1
- package/README.hi.md +1 -1
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +341 -4
- package/README.pt-BR.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/agent/export-manager.d.ts.map +1 -1
- package/dist/agent/export-manager.js +9 -7
- package/dist/agent/export-manager.js.map +1 -1
- package/dist/assets/repositories/iconify.d.ts +0 -5
- package/dist/assets/repositories/iconify.d.ts.map +1 -1
- package/dist/assets/repositories/iconify.js +17 -5
- package/dist/assets/repositories/iconify.js.map +1 -1
- package/dist/browser/puppeteer-controller.d.ts +16 -0
- package/dist/browser/puppeteer-controller.d.ts.map +1 -1
- package/dist/browser/puppeteer-controller.js +32 -2
- package/dist/browser/puppeteer-controller.js.map +1 -1
- package/dist/build-info.json +5 -0
- package/dist/design/design-systems.d.ts +27 -2
- package/dist/design/design-systems.d.ts.map +1 -1
- package/dist/design/design-systems.js +20 -0
- package/dist/design/design-systems.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/ontology/upstream-vocabulary.d.ts +23 -0
- package/dist/ontology/upstream-vocabulary.d.ts.map +1 -0
- package/dist/ontology/upstream-vocabulary.js +1172 -0
- package/dist/ontology/upstream-vocabulary.js.map +1 -0
- package/dist/ontology/vocabulary.d.ts.map +1 -1
- package/dist/ontology/vocabulary.js +19 -0
- package/dist/ontology/vocabulary.js.map +1 -1
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +299 -75
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/engine-methods.d.ts.map +1 -1
- package/dist/tools/engine-methods.js +28 -2
- package/dist/tools/engine-methods.js.map +1 -1
- package/dist/tools/engine-surface.d.ts +1 -1
- package/dist/tools/engine-surface.d.ts.map +1 -1
- package/dist/tools/engine-surface.js +18 -12
- package/dist/tools/engine-surface.js.map +1 -1
- package/dist/tools/handlers/camera.d.ts.map +1 -1
- package/dist/tools/handlers/camera.js +17 -2
- package/dist/tools/handlers/camera.js.map +1 -1
- package/dist/tools/handlers/font.d.ts.map +1 -1
- package/dist/tools/handlers/font.js +48 -3
- package/dist/tools/handlers/font.js.map +1 -1
- package/dist/tools/handlers/maps.d.ts.map +1 -1
- package/dist/tools/handlers/maps.js +16 -0
- package/dist/tools/handlers/maps.js.map +1 -1
- package/dist/tools/handlers.d.ts +24 -3
- package/dist/tools/handlers.d.ts.map +1 -1
- package/dist/tools/handlers.js +645 -27
- package/dist/tools/handlers.js.map +1 -1
- package/dist/tools/minimal-descriptions.d.ts.map +1 -1
- package/dist/tools/minimal-descriptions.js +2 -0
- package/dist/tools/minimal-descriptions.js.map +1 -1
- package/dist/tools/shape-params.d.ts +13 -2
- package/dist/tools/shape-params.d.ts.map +1 -1
- package/dist/tools/shape-params.js +80 -2
- package/dist/tools/shape-params.js.map +1 -1
- package/dist/tools/stick-vocabulary.d.ts +1 -1
- package/dist/tools/stick-vocabulary.js +1 -1
- package/dist/tools/toolkits.d.ts.map +1 -1
- package/dist/tools/toolkits.js +12 -1
- package/dist/tools/toolkits.js.map +1 -1
- package/dist/types/code-generator.d.ts +27 -1
- package/dist/types/code-generator.d.ts.map +1 -1
- package/dist/types/code-generator.js +2871 -316
- package/dist/types/code-generator.js.map +1 -1
- package/dist/types/schemas.d.ts +1595 -271
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/types/schemas.js +269 -31
- package/dist/types/schemas.js.map +1 -1
- package/dist/utils/a11y.d.ts +67 -0
- package/dist/utils/a11y.d.ts.map +1 -0
- package/dist/utils/a11y.js +117 -0
- package/dist/utils/a11y.js.map +1 -0
- package/dist/utils/ad-package.d.ts +44 -0
- package/dist/utils/ad-package.d.ts.map +1 -0
- package/dist/utils/ad-package.js +121 -0
- package/dist/utils/ad-package.js.map +1 -0
- package/dist/utils/scc.d.ts +41 -0
- package/dist/utils/scc.d.ts.map +1 -0
- package/dist/utils/scc.js +185 -0
- package/dist/utils/scc.js.map +1 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/dist/utils/zip.js +82 -0
- package/dist/utils/zip.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +31 -1
- package/dist/version.js.map +1 -1
- package/manifest.json +9 -1
- package/package.json +6 -4
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accessibility checks on a scene: text contrast (WCAG 2.x 1.4.3) and flashing
|
|
3
|
+
* (WCAG 2.3.1, general flash threshold). The studio measures; this decides.
|
|
4
|
+
*
|
|
5
|
+
* Both are HEURISTICS and say so in their results. Contrast compares a text's
|
|
6
|
+
* fill with the solid colour found behind it, not the rendered pixels, so a
|
|
7
|
+
* photo or gradient behind text is not judged. Flash detection samples
|
|
8
|
+
* luminance on a 3 x 3 grid — each cell about 11% of the frame, close to the
|
|
9
|
+
* WCAG area of 341 x 256 px on a 1024 x 768 screen — and counts opposing
|
|
10
|
+
* luminance changes; the red-flash threshold is not checked.
|
|
11
|
+
*/
|
|
12
|
+
export interface Rgba {
|
|
13
|
+
r: number;
|
|
14
|
+
g: number;
|
|
15
|
+
b: number;
|
|
16
|
+
a?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function relativeLuminance(c: Rgba): number;
|
|
19
|
+
export declare function contrastRatio(a: Rgba, b: Rgba): number;
|
|
20
|
+
/** A colour with alpha over an opaque one. */
|
|
21
|
+
export declare function over(fg: Rgba, bg: Rgba): Rgba;
|
|
22
|
+
/** 'rgb(1, 2, 3)', 'rgba(…)', '#abc', '#aabbcc' → Rgba, or null. */
|
|
23
|
+
export declare function parseCssColor(s: string | null | undefined): Rgba | null;
|
|
24
|
+
export interface TextSample {
|
|
25
|
+
id: string;
|
|
26
|
+
content: string;
|
|
27
|
+
fill: Rgba | null;
|
|
28
|
+
fontSize: number;
|
|
29
|
+
bold: boolean;
|
|
30
|
+
behind: Rgba | null;
|
|
31
|
+
behindId?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ContrastFinding {
|
|
34
|
+
id: string;
|
|
35
|
+
content: string;
|
|
36
|
+
ratio: number;
|
|
37
|
+
required: number;
|
|
38
|
+
large: boolean;
|
|
39
|
+
against: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* WCAG AA: 4.5:1, or 3:1 for large text (>= 18 pt = 24 px, or >= 14 pt = 18.66 px bold).
|
|
43
|
+
*/
|
|
44
|
+
export declare function checkContrast(texts: TextSample[], page: Rgba | null): {
|
|
45
|
+
failing: ContrastFinding[];
|
|
46
|
+
checked: number;
|
|
47
|
+
skipped: Array<{
|
|
48
|
+
id: string;
|
|
49
|
+
reason: string;
|
|
50
|
+
}>;
|
|
51
|
+
pageAssumed: boolean;
|
|
52
|
+
};
|
|
53
|
+
export interface FlashFinding {
|
|
54
|
+
region: number;
|
|
55
|
+
flashesPerSecond: number;
|
|
56
|
+
atSeconds: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* `series[f][cell]` = mean relative luminance of that grid cell at frame f.
|
|
60
|
+
* A flash is a pair of opposing changes of >= 0.1 where the darker state is
|
|
61
|
+
* below 0.8; more than three in any one-second window fails 2.3.1.
|
|
62
|
+
*/
|
|
63
|
+
export declare function checkFlashes(series: number[][], fps: number): {
|
|
64
|
+
maxFlashesPerSecond: number;
|
|
65
|
+
failing: FlashFinding[];
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=a11y.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../../src/utils/a11y.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,IAAI;IAAG,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE;AAQrE,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAGtD;AAED,8CAA8C;AAC9C,wBAAgB,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,GAAG,IAAI,CAG7C;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAWvE;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAElI;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG;IAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAiB3L;AAED,MAAM,WAAW,YAAY;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAE7F;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,mBAAmB,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE,CAkCtH"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accessibility checks on a scene: text contrast (WCAG 2.x 1.4.3) and flashing
|
|
3
|
+
* (WCAG 2.3.1, general flash threshold). The studio measures; this decides.
|
|
4
|
+
*
|
|
5
|
+
* Both are HEURISTICS and say so in their results. Contrast compares a text's
|
|
6
|
+
* fill with the solid colour found behind it, not the rendered pixels, so a
|
|
7
|
+
* photo or gradient behind text is not judged. Flash detection samples
|
|
8
|
+
* luminance on a 3 x 3 grid — each cell about 11% of the frame, close to the
|
|
9
|
+
* WCAG area of 341 x 256 px on a 1024 x 768 screen — and counts opposing
|
|
10
|
+
* luminance changes; the red-flash threshold is not checked.
|
|
11
|
+
*/
|
|
12
|
+
/** sRGB channel 0-255 → linear 0-1 (WCAG 2.x formula). */
|
|
13
|
+
function linear(c) {
|
|
14
|
+
const v = c / 255;
|
|
15
|
+
return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
|
|
16
|
+
}
|
|
17
|
+
export function relativeLuminance(c) {
|
|
18
|
+
return 0.2126 * linear(c.r) + 0.7152 * linear(c.g) + 0.0722 * linear(c.b);
|
|
19
|
+
}
|
|
20
|
+
export function contrastRatio(a, b) {
|
|
21
|
+
const la = relativeLuminance(a), lb = relativeLuminance(b);
|
|
22
|
+
return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
|
|
23
|
+
}
|
|
24
|
+
/** A colour with alpha over an opaque one. */
|
|
25
|
+
export function over(fg, bg) {
|
|
26
|
+
const a = fg.a ?? 1;
|
|
27
|
+
return { r: fg.r * a + bg.r * (1 - a), g: fg.g * a + bg.g * (1 - a), b: fg.b * a + bg.b * (1 - a), a: 1 };
|
|
28
|
+
}
|
|
29
|
+
/** 'rgb(1, 2, 3)', 'rgba(…)', '#abc', '#aabbcc' → Rgba, or null. */
|
|
30
|
+
export function parseCssColor(s) {
|
|
31
|
+
if (!s)
|
|
32
|
+
return null;
|
|
33
|
+
const t = s.trim().toLowerCase();
|
|
34
|
+
const m = /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)$/.exec(t);
|
|
35
|
+
if (m)
|
|
36
|
+
return { r: +m[1], g: +m[2], b: +m[3], a: m[4] !== undefined ? +m[4] : 1 };
|
|
37
|
+
const h = /^#([0-9a-f]{3}|[0-9a-f]{6})$/.exec(t);
|
|
38
|
+
if (h) {
|
|
39
|
+
const x = h[1].length === 3 ? h[1].split('').map((c) => c + c).join('') : h[1];
|
|
40
|
+
return { r: parseInt(x.slice(0, 2), 16), g: parseInt(x.slice(2, 4), 16), b: parseInt(x.slice(4, 6), 16), a: 1 };
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* WCAG AA: 4.5:1, or 3:1 for large text (>= 18 pt = 24 px, or >= 14 pt = 18.66 px bold).
|
|
46
|
+
*/
|
|
47
|
+
export function checkContrast(texts, page) {
|
|
48
|
+
const failing = [];
|
|
49
|
+
const skipped = [];
|
|
50
|
+
const base = page && (page.a ?? 1) > 0 ? { ...page, a: 1 } : { r: 255, g: 255, b: 255, a: 1 };
|
|
51
|
+
let checked = 0;
|
|
52
|
+
for (const t of texts) {
|
|
53
|
+
if (!t.fill) {
|
|
54
|
+
skipped.push({ id: t.id, reason: 'gradient or no fill' });
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const bg = t.behind ? over(t.behind, base) : base;
|
|
58
|
+
const ratio = contrastRatio(over(t.fill, bg), bg);
|
|
59
|
+
const large = t.fontSize >= 24 || (t.bold && t.fontSize >= 18.66);
|
|
60
|
+
const required = large ? 3 : 4.5;
|
|
61
|
+
checked++;
|
|
62
|
+
if (ratio < required) {
|
|
63
|
+
failing.push({ id: t.id, content: t.content.slice(0, 40), ratio: Math.round(ratio * 100) / 100, required, large, against: t.behindId ? `item ${t.behindId}` : 'the page background' });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { failing, checked, skipped, pageAssumed: !page || (page.a ?? 1) === 0 };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* `series[f][cell]` = mean relative luminance of that grid cell at frame f.
|
|
70
|
+
* A flash is a pair of opposing changes of >= 0.1 where the darker state is
|
|
71
|
+
* below 0.8; more than three in any one-second window fails 2.3.1.
|
|
72
|
+
*/
|
|
73
|
+
export function checkFlashes(series, fps) {
|
|
74
|
+
if (series.length < 3)
|
|
75
|
+
return { maxFlashesPerSecond: 0, failing: [] };
|
|
76
|
+
const cells = series[0].length;
|
|
77
|
+
const failing = [];
|
|
78
|
+
let worst = 0;
|
|
79
|
+
const win = Math.max(1, Math.round(fps));
|
|
80
|
+
for (let c = 0; c < cells; c++) {
|
|
81
|
+
// Turning points of this cell's luminance, then the qualifying changes between them.
|
|
82
|
+
// Runs of equal samples collapse to one point first: a flash held for
|
|
83
|
+
// several samples is a plateau, and comparing neighbours alone found no
|
|
84
|
+
// turn at a plateau's edge — a 10 Hz strobe sampled at 30 fps counted 0.
|
|
85
|
+
const all = series.map((f, i) => ({ i, v: f[c] }));
|
|
86
|
+
const pts = all.filter((p, k) => k === 0 || Math.abs(p.v - all[k - 1].v) > 1e-9);
|
|
87
|
+
const turns = [pts[0]];
|
|
88
|
+
for (let k = 1; k < pts.length - 1; k++) {
|
|
89
|
+
if ((pts[k].v - pts[k - 1].v) * (pts[k + 1].v - pts[k].v) < 0)
|
|
90
|
+
turns.push(pts[k]);
|
|
91
|
+
}
|
|
92
|
+
if (pts.length > 1)
|
|
93
|
+
turns.push(pts[pts.length - 1]);
|
|
94
|
+
const changes = []; // frame index at which each qualifying change ends
|
|
95
|
+
for (let k = 1; k < turns.length; k++) {
|
|
96
|
+
const a = turns[k - 1].v, b = turns[k].v;
|
|
97
|
+
if (Math.abs(a - b) >= 0.1 && Math.min(a, b) < 0.8)
|
|
98
|
+
changes.push(turns[k].i);
|
|
99
|
+
}
|
|
100
|
+
let cellWorst = 0, at = 0;
|
|
101
|
+
for (let s = 0; s < changes.length; s++) {
|
|
102
|
+
let e = s;
|
|
103
|
+
while (e + 1 < changes.length && changes[e + 1] - changes[s] < win)
|
|
104
|
+
e++;
|
|
105
|
+
const flashes = Math.floor((e - s + 1) / 2);
|
|
106
|
+
if (flashes > cellWorst) {
|
|
107
|
+
cellWorst = flashes;
|
|
108
|
+
at = changes[s] / fps;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
worst = Math.max(worst, cellWorst);
|
|
112
|
+
if (cellWorst > 3)
|
|
113
|
+
failing.push({ region: c, flashesPerSecond: cellWorst, atSeconds: Math.round(at * 100) / 100 });
|
|
114
|
+
}
|
|
115
|
+
return { maxFlashesPerSecond: worst, failing };
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=a11y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a11y.js","sourceRoot":"","sources":["../../src/utils/a11y.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrap the studio's standalone widget page as an ad.
|
|
3
|
+
*
|
|
4
|
+
* The page itself is the engine's (exportWidgetHTML: tree-shaken, no runtime
|
|
5
|
+
* dependencies). What an ad network adds on top is small and fixed, so it is
|
|
6
|
+
* done here, on the server, as plain string work that can be tested:
|
|
7
|
+
*
|
|
8
|
+
* - html5-ad (display networks: Google Ads, DV360 / CM360 and most DSPs): the
|
|
9
|
+
* `ad.size` meta, a `clickTag` variable, and a click target that opens it —
|
|
10
|
+
* the whole ad, or just a CTA's box. Uploaded as a zip.
|
|
11
|
+
* - playable (MRAID 2.0/3.0 networks): `mraid.js`, a start that waits for
|
|
12
|
+
* MRAID to be ready, and a CTA that goes through `mraid.open`. A single HTML
|
|
13
|
+
* file, which is what playable networks take. A playable is interactive, so
|
|
14
|
+
* only the CTA is a click-through — a full-area link would swallow the play.
|
|
15
|
+
*/
|
|
16
|
+
export interface CtaBox {
|
|
17
|
+
left: number;
|
|
18
|
+
top: number;
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
}
|
|
22
|
+
export interface AdOptions {
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
clickUrl?: string;
|
|
26
|
+
cta?: CtaBox | null;
|
|
27
|
+
/** The scene's background colour, pinned over the page's own (which can be stale). */
|
|
28
|
+
background?: string | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The widget renderer FILLS its canvas with SCENE.background, over any page
|
|
32
|
+
* CSS — so the CSS pin alone left a stale white on the canvas. The resolved
|
|
33
|
+
* colour is set on SCENE just before the renderer loads it. `applied` says
|
|
34
|
+
* whether the page had the load call to hook.
|
|
35
|
+
*/
|
|
36
|
+
export declare function pinSceneBackground(html: string, bg: string | null | undefined): {
|
|
37
|
+
html: string;
|
|
38
|
+
applied: boolean;
|
|
39
|
+
};
|
|
40
|
+
export declare function buildHtml5Ad(html: string, o: AdOptions): string;
|
|
41
|
+
export declare function buildPlayable(html: string, o: AdOptions): string;
|
|
42
|
+
/** Every absolute URL the page would fetch: src / href attributes and CSS url() / @import. */
|
|
43
|
+
export declare function externalRequests(html: string): string[];
|
|
44
|
+
//# sourceMappingURL=ad-package.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ad-package.d.ts","sourceRoot":"","sources":["../../src/utils/ad-package.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,MAAM;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAEpF,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAKD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAMlH;AA2CD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAW/D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAsBhE;AAED,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CASvD"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrap the studio's standalone widget page as an ad.
|
|
3
|
+
*
|
|
4
|
+
* The page itself is the engine's (exportWidgetHTML: tree-shaken, no runtime
|
|
5
|
+
* dependencies). What an ad network adds on top is small and fixed, so it is
|
|
6
|
+
* done here, on the server, as plain string work that can be tested:
|
|
7
|
+
*
|
|
8
|
+
* - html5-ad (display networks: Google Ads, DV360 / CM360 and most DSPs): the
|
|
9
|
+
* `ad.size` meta, a `clickTag` variable, and a click target that opens it —
|
|
10
|
+
* the whole ad, or just a CTA's box. Uploaded as a zip.
|
|
11
|
+
* - playable (MRAID 2.0/3.0 networks): `mraid.js`, a start that waits for
|
|
12
|
+
* MRAID to be ready, and a CTA that goes through `mraid.open`. A single HTML
|
|
13
|
+
* file, which is what playable networks take. A playable is interactive, so
|
|
14
|
+
* only the CTA is a click-through — a full-area link would swallow the play.
|
|
15
|
+
*/
|
|
16
|
+
/** A CSS colour we will write into a stylesheet: rgb()/rgba()/hex/a plain name only. */
|
|
17
|
+
const SAFE_COLOR = /^(#[0-9a-f]{3,8}|rgba?\([\d.,\s%]+\)|[a-z]+)$/i;
|
|
18
|
+
/**
|
|
19
|
+
* The widget renderer FILLS its canvas with SCENE.background, over any page
|
|
20
|
+
* CSS — so the CSS pin alone left a stale white on the canvas. The resolved
|
|
21
|
+
* colour is set on SCENE just before the renderer loads it. `applied` says
|
|
22
|
+
* whether the page had the load call to hook.
|
|
23
|
+
*/
|
|
24
|
+
export function pinSceneBackground(html, bg) {
|
|
25
|
+
if (!bg || !SAFE_COLOR.test(bg.trim()))
|
|
26
|
+
return { html, applied: false };
|
|
27
|
+
// `r.load(SCENE);` is a statement of its own in the engine's page.
|
|
28
|
+
const load = /(^|[;{}\n]\s*)([A-Za-z_$][\w$]*\.load\(SCENE\))/;
|
|
29
|
+
if (!load.test(html))
|
|
30
|
+
return { html, applied: false };
|
|
31
|
+
return { html: html.replace(load, (_m, pre, call) => `${pre}SCENE.background=${jsString(bg.trim())};${call}`), applied: true };
|
|
32
|
+
}
|
|
33
|
+
function backgroundStyle(bg) {
|
|
34
|
+
if (!bg || !SAFE_COLOR.test(bg.trim()))
|
|
35
|
+
return '';
|
|
36
|
+
return `\n<style>html,body,#w{background:${bg.trim()} !important}</style>`;
|
|
37
|
+
}
|
|
38
|
+
const esc = (v) => v.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
39
|
+
/** A string as a JS literal inside a <script> — JSON, with "</" broken so it cannot close the tag. */
|
|
40
|
+
const jsString = (v) => JSON.stringify(v).replace(/<\//g, '<\\/');
|
|
41
|
+
function injectHead(html, fragment) {
|
|
42
|
+
if (/<head[^>]*>/i.test(html))
|
|
43
|
+
return html.replace(/<head[^>]*>/i, (m) => `${m}\n${fragment}`);
|
|
44
|
+
if (/<html[^>]*>/i.test(html))
|
|
45
|
+
return html.replace(/<html[^>]*>/i, (m) => `${m}\n<head>\n${fragment}\n</head>`);
|
|
46
|
+
return `<head>\n${fragment}\n</head>\n${html}`;
|
|
47
|
+
}
|
|
48
|
+
function injectBodyEnd(html, fragment) {
|
|
49
|
+
if (/<\/body>/i.test(html))
|
|
50
|
+
return html.replace(/<\/body>/i, `${fragment}\n</body>`);
|
|
51
|
+
return `${html}\n${fragment}`;
|
|
52
|
+
}
|
|
53
|
+
function clickTarget(id, href, cta, label, position) {
|
|
54
|
+
const box = cta
|
|
55
|
+
? `left:${cta.left.toFixed(3)}%;top:${cta.top.toFixed(3)}%;width:${cta.width.toFixed(3)}%;height:${cta.height.toFixed(3)}%`
|
|
56
|
+
: 'left:0;top:0;width:100%;height:100%';
|
|
57
|
+
return `<a id="${id}" href="${href}" aria-label="${esc(label)}" style="position:${position};${box};z-index:2147483647;display:block;cursor:pointer;background:transparent"></a>`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Place the click target in the widget's own box. The page centres div#w at
|
|
61
|
+
* the scene's aspect ratio (position: relative) and letterboxes it on any
|
|
62
|
+
* other screen shape, so a CTA box in VIEWPORT percent lands off the button
|
|
63
|
+
* on a phone that is not the ad's shape. Inside #w, absolute percentages are
|
|
64
|
+
* of the canvas. (The widget appends its canvas to #w and never clears it.)
|
|
65
|
+
* A page without #w gets a viewport-fixed target.
|
|
66
|
+
*/
|
|
67
|
+
function placeTarget(html, make) {
|
|
68
|
+
const open = /<div id="w"[^>]*>/i;
|
|
69
|
+
if (open.test(html))
|
|
70
|
+
return html.replace(open, (m) => `${m}\n${make('absolute')}`);
|
|
71
|
+
return injectBodyEnd(html, make('fixed'));
|
|
72
|
+
}
|
|
73
|
+
export function buildHtml5Ad(html, o) {
|
|
74
|
+
html = pinSceneBackground(html, o.background).html;
|
|
75
|
+
const head = [
|
|
76
|
+
`<meta name="ad.size" content="width=${Math.round(o.width)},height=${Math.round(o.height)}">`,
|
|
77
|
+
// The network replaces clickTag at serve time; the value here is the
|
|
78
|
+
// landing page for a test, or empty.
|
|
79
|
+
`<script>var clickTag = ${jsString(o.clickUrl ?? '')};</script>`,
|
|
80
|
+
].join('\n') + backgroundStyle(o.background);
|
|
81
|
+
// The pattern the display networks document: an anchor that opens
|
|
82
|
+
// window.clickTag in a new window.
|
|
83
|
+
return placeTarget(injectHead(html, head), (pos) => clickTarget('pp-clicktag', 'javascript:window.open(window.clickTag)', o.cta, 'Open the advertiser page', pos));
|
|
84
|
+
}
|
|
85
|
+
export function buildPlayable(html, o) {
|
|
86
|
+
html = pinSceneBackground(html, o.background).html;
|
|
87
|
+
const head = `<script src="mraid.js"></script>` + backgroundStyle(o.background);
|
|
88
|
+
const script = `<script>
|
|
89
|
+
(function () {
|
|
90
|
+
var url = ${jsString(o.clickUrl ?? '')};
|
|
91
|
+
function openStore(e) {
|
|
92
|
+
if (e) e.preventDefault();
|
|
93
|
+
if (window.mraid && typeof mraid.open === 'function') mraid.open(url); else window.open(url);
|
|
94
|
+
}
|
|
95
|
+
function wire() {
|
|
96
|
+
var a = document.getElementById('pp-cta');
|
|
97
|
+
if (a) a.addEventListener('click', openStore);
|
|
98
|
+
}
|
|
99
|
+
if (window.mraid && typeof mraid.getState === 'function' && mraid.getState() === 'loading') {
|
|
100
|
+
mraid.addEventListener('ready', wire);
|
|
101
|
+
} else {
|
|
102
|
+
wire();
|
|
103
|
+
}
|
|
104
|
+
})();
|
|
105
|
+
</script>`;
|
|
106
|
+
return injectBodyEnd(placeTarget(injectHead(html, head), (pos) => clickTarget('pp-cta', '#', o.cta, 'Install', pos)), script);
|
|
107
|
+
}
|
|
108
|
+
/** Every absolute URL the page would fetch: src / href attributes and CSS url() / @import. */
|
|
109
|
+
export function externalRequests(html) {
|
|
110
|
+
const out = new Set();
|
|
111
|
+
const patterns = [
|
|
112
|
+
/\b(?:src|href)\s*=\s*["'](https?:\/\/[^"']+)["']/gi,
|
|
113
|
+
/url\(\s*["']?(https?:\/\/[^"')\s]+)/gi,
|
|
114
|
+
/@import\s+["'](https?:\/\/[^"']+)["']/gi,
|
|
115
|
+
];
|
|
116
|
+
for (const re of patterns)
|
|
117
|
+
for (const m of html.matchAll(re))
|
|
118
|
+
out.add(m[1]);
|
|
119
|
+
return [...out];
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=ad-package.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ad-package.js","sourceRoot":"","sources":["../../src/utils/ad-package.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SCC (Scenarist) captions: CEA-608, channel CC1, pop-on, 29.97 fps
|
|
3
|
+
* drop-frame timecode — the broadcast deliverable SRT / VTT are not.
|
|
4
|
+
*
|
|
5
|
+
* Each cue is loaded off screen (RCL, ENM, a preamble address code per row,
|
|
6
|
+
* the text) and swapped on with EOC at its start frame; EDM clears it at its
|
|
7
|
+
* stop unless the next cue swaps on at that frame. 608 carries two bytes a
|
|
8
|
+
* frame, so the load is scheduled to END before the start; when cues are too
|
|
9
|
+
* close for that, a cue goes on late and the result says by how much.
|
|
10
|
+
*
|
|
11
|
+
* Every byte carries odd parity. Control codes are sent twice, which is the
|
|
12
|
+
* convention decoders rely on to survive a dropped pair.
|
|
13
|
+
*/
|
|
14
|
+
export interface SccCue {
|
|
15
|
+
start: number;
|
|
16
|
+
stop: number;
|
|
17
|
+
text: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SccResult {
|
|
20
|
+
text: string;
|
|
21
|
+
cues: number;
|
|
22
|
+
truncated: number;
|
|
23
|
+
replacedChars: string[];
|
|
24
|
+
delayed: Array<{
|
|
25
|
+
cue: number;
|
|
26
|
+
frames: number;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
/** Odd parity on a 7-bit value. */
|
|
30
|
+
export declare function parity(b: number): number;
|
|
31
|
+
/** A PAC placing the cursor at `row`, column `indent` (a multiple of 4), white. */
|
|
32
|
+
export declare function pac(row: number, indent: number): string;
|
|
33
|
+
/** Wrap to at most 2 lines of 32; `truncated` when it did not fit. */
|
|
34
|
+
export declare function wrap(text: string): {
|
|
35
|
+
lines: string[];
|
|
36
|
+
truncated: boolean;
|
|
37
|
+
};
|
|
38
|
+
/** Frame count at 29.97 → drop-frame timecode HH:MM:SS;FF. */
|
|
39
|
+
export declare function dropFrameTimecode(frame: number): string;
|
|
40
|
+
export declare function buildScc(cues: SccCue[]): SccResult;
|
|
41
|
+
//# sourceMappingURL=scc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scc.d.ts","sourceRoot":"","sources":["../../src/utils/scc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,MAAM;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAErE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAMD,mCAAmC;AACnC,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxC;AAmBD,mFAAmF;AACnF,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGvD;AAoBD,sEAAsE;AACtE,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAgB1E;AAED,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CA8ElD"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SCC (Scenarist) captions: CEA-608, channel CC1, pop-on, 29.97 fps
|
|
3
|
+
* drop-frame timecode — the broadcast deliverable SRT / VTT are not.
|
|
4
|
+
*
|
|
5
|
+
* Each cue is loaded off screen (RCL, ENM, a preamble address code per row,
|
|
6
|
+
* the text) and swapped on with EOC at its start frame; EDM clears it at its
|
|
7
|
+
* stop unless the next cue swaps on at that frame. 608 carries two bytes a
|
|
8
|
+
* frame, so the load is scheduled to END before the start; when cues are too
|
|
9
|
+
* close for that, a cue goes on late and the result says by how much.
|
|
10
|
+
*
|
|
11
|
+
* Every byte carries odd parity. Control codes are sent twice, which is the
|
|
12
|
+
* convention decoders rely on to survive a dropped pair.
|
|
13
|
+
*/
|
|
14
|
+
const FPS = 30000 / 1001;
|
|
15
|
+
const COLS = 32;
|
|
16
|
+
const ROWS = [14, 15]; // the bottom two rows
|
|
17
|
+
/** Odd parity on a 7-bit value. */
|
|
18
|
+
export function parity(b) {
|
|
19
|
+
let ones = 0;
|
|
20
|
+
for (let v = b & 0x7f; v; v >>= 1)
|
|
21
|
+
ones += v & 1;
|
|
22
|
+
return ones % 2 === 1 ? b & 0x7f : (b & 0x7f) | 0x80;
|
|
23
|
+
}
|
|
24
|
+
const word = (hi, lo) => parity(hi).toString(16).padStart(2, '0') + parity(lo).toString(16).padStart(2, '0');
|
|
25
|
+
const CTRL = {
|
|
26
|
+
RCL: word(0x14, 0x20), // resume caption loading (pop-on)
|
|
27
|
+
ENM: word(0x14, 0x2e), // erase non-displayed memory
|
|
28
|
+
EOC: word(0x14, 0x2f), // end of caption: swap on
|
|
29
|
+
EDM: word(0x14, 0x2c), // erase displayed memory
|
|
30
|
+
};
|
|
31
|
+
/** Row → first byte and base second byte of its preamble address code (CC1). */
|
|
32
|
+
const PAC_ROW = {
|
|
33
|
+
1: [0x11, 0x40], 2: [0x11, 0x60], 3: [0x12, 0x40], 4: [0x12, 0x60], 5: [0x15, 0x40], 6: [0x15, 0x60],
|
|
34
|
+
7: [0x16, 0x40], 8: [0x16, 0x60], 9: [0x17, 0x40], 10: [0x17, 0x60], 11: [0x10, 0x40], 12: [0x13, 0x40],
|
|
35
|
+
13: [0x13, 0x60], 14: [0x14, 0x40], 15: [0x14, 0x60],
|
|
36
|
+
};
|
|
37
|
+
/** A PAC placing the cursor at `row`, column `indent` (a multiple of 4), white. */
|
|
38
|
+
export function pac(row, indent) {
|
|
39
|
+
const [hi, base] = PAC_ROW[row];
|
|
40
|
+
return word(hi, base + 0x10 + (indent / 4) * 2);
|
|
41
|
+
}
|
|
42
|
+
// The basic 608 set is ASCII except these positions, which hold accented
|
|
43
|
+
// letters instead of the ASCII characters.
|
|
44
|
+
const BASIC_ACCENTED = { 'á': 0x2a, 'é': 0x5c, 'í': 0x5e, 'ó': 0x5f, 'ú': 0x60, 'ç': 0x7b, '÷': 0x7c, 'Ñ': 0x7d, 'ñ': 0x7e };
|
|
45
|
+
const ASCII_NOT_IN_608 = new Set(['*', '\\', '^', '_', '`', '{', '|', '}', '~']);
|
|
46
|
+
function encodeChar(ch, replaced) {
|
|
47
|
+
if (BASIC_ACCENTED[ch] !== undefined)
|
|
48
|
+
return BASIC_ACCENTED[ch];
|
|
49
|
+
const c = ch.charCodeAt(0);
|
|
50
|
+
if (ch.length === 1 && c >= 0x20 && c < 0x7f && !ASCII_NOT_IN_608.has(ch))
|
|
51
|
+
return c;
|
|
52
|
+
// (Typographic quotes, dashes and ellipses were made plain by normalise.)
|
|
53
|
+
replaced.add(ch);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function normalise(text) {
|
|
57
|
+
return text.replace(/[‘’]/g, "'").replace(/[“”]/g, '"').replace(/[–—]/g, '-').replace(/…/g, '...').replace(/\s+/g, ' ').trim();
|
|
58
|
+
}
|
|
59
|
+
/** Wrap to at most 2 lines of 32; `truncated` when it did not fit. */
|
|
60
|
+
export function wrap(text) {
|
|
61
|
+
const lines = [];
|
|
62
|
+
let truncated = false;
|
|
63
|
+
for (const para of text.split(/\n+/)) {
|
|
64
|
+
let line = '';
|
|
65
|
+
for (const w of normalise(para).split(' ')) {
|
|
66
|
+
if (!w)
|
|
67
|
+
continue;
|
|
68
|
+
const next = line ? `${line} ${w}` : w;
|
|
69
|
+
if (next.length <= COLS) {
|
|
70
|
+
line = next;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (line)
|
|
74
|
+
lines.push(line);
|
|
75
|
+
line = w.length > COLS ? (truncated = true, w.slice(0, COLS)) : w;
|
|
76
|
+
}
|
|
77
|
+
if (line)
|
|
78
|
+
lines.push(line);
|
|
79
|
+
}
|
|
80
|
+
if (lines.length > ROWS.length) {
|
|
81
|
+
truncated = true;
|
|
82
|
+
lines.length = ROWS.length;
|
|
83
|
+
}
|
|
84
|
+
return { lines, truncated };
|
|
85
|
+
}
|
|
86
|
+
/** Frame count at 29.97 → drop-frame timecode HH:MM:SS;FF. */
|
|
87
|
+
export function dropFrameTimecode(frame) {
|
|
88
|
+
const D = Math.floor(frame / 17982);
|
|
89
|
+
const M = frame % 17982;
|
|
90
|
+
const f = frame + 18 * D + (M < 2 ? 0 : 2 * Math.floor((M - 2) / 1798));
|
|
91
|
+
const p = (n) => String(n).padStart(2, '0');
|
|
92
|
+
return `${p(Math.floor(f / 108000))}:${p(Math.floor(f / 1800) % 60)}:${p(Math.floor(f / 30) % 60)};${p(f % 30)}`;
|
|
93
|
+
}
|
|
94
|
+
export function buildScc(cues) {
|
|
95
|
+
const replaced = new Set();
|
|
96
|
+
let truncated = 0;
|
|
97
|
+
const sorted = [...cues].sort((a, b) => a.start - b.start);
|
|
98
|
+
const out = [];
|
|
99
|
+
const delayed = [];
|
|
100
|
+
let cursor = 0; // the first frame free for the next word (one word a frame)
|
|
101
|
+
const emit = (want, words) => {
|
|
102
|
+
const at = Math.max(want, cursor, 0);
|
|
103
|
+
out.push(`${dropFrameTimecode(at)}\t${words.join(' ')}`);
|
|
104
|
+
cursor = at + words.length;
|
|
105
|
+
return at;
|
|
106
|
+
};
|
|
107
|
+
// A cue's clear waits for the next cue: it is skipped when that cue swaps on
|
|
108
|
+
// at (or before) the stop, since the swap replaces it.
|
|
109
|
+
let pendingClear = null;
|
|
110
|
+
sorted.forEach((c, i) => {
|
|
111
|
+
const { lines, truncated: cut } = wrap(c.text);
|
|
112
|
+
if (cut)
|
|
113
|
+
truncated++;
|
|
114
|
+
const words = [CTRL.RCL, CTRL.RCL, CTRL.ENM, CTRL.ENM];
|
|
115
|
+
const rows = ROWS.slice(ROWS.length - lines.length);
|
|
116
|
+
lines.forEach((line, li) => {
|
|
117
|
+
const bytes = [];
|
|
118
|
+
for (const ch of line) {
|
|
119
|
+
const b = encodeChar(ch, replaced);
|
|
120
|
+
if (b !== null)
|
|
121
|
+
bytes.push(b);
|
|
122
|
+
}
|
|
123
|
+
const col = Math.max(0, Math.floor((COLS - bytes.length) / 2));
|
|
124
|
+
const indent = col - (col % 4);
|
|
125
|
+
const p = pac(rows[li], indent);
|
|
126
|
+
words.push(p, p);
|
|
127
|
+
if (col % 4) {
|
|
128
|
+
const t = word(0x17, 0x20 + (col % 4));
|
|
129
|
+
words.push(t, t);
|
|
130
|
+
} // tab offset 1-3
|
|
131
|
+
for (let k = 0; k < bytes.length; k += 2) {
|
|
132
|
+
words.push(parity(bytes[k]).toString(16).padStart(2, '0') + parity(bytes[k + 1] ?? 0x00).toString(16).padStart(2, '0'));
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
const startF = Math.round(c.start * FPS);
|
|
136
|
+
const stopF = Math.max(startF + 1, Math.round(c.stop * FPS));
|
|
137
|
+
const loadWant = startF - words.length;
|
|
138
|
+
// The previous cue's clear and this cue's load, in time order. Loading
|
|
139
|
+
// goes to off-screen memory, so it may run while the previous cue shows;
|
|
140
|
+
// both come before this cue's swap.
|
|
141
|
+
// The clear lands ON the stop frame: the next load goes before it when it
|
|
142
|
+
// fits (loading is off screen, so it may run while this cue shows), and
|
|
143
|
+
// otherwise after it — never over it, which held cues on screen until the
|
|
144
|
+
// next load finished (half a second late).
|
|
145
|
+
// When the clear falls inside the load, the load is split around it: EDM
|
|
146
|
+
// erases only the DISPLAYED caption, so it is valid mid-load.
|
|
147
|
+
if (pendingClear !== null && pendingClear < startF) {
|
|
148
|
+
const EDM2 = [CTRL.EDM, CTRL.EDM];
|
|
149
|
+
if (Math.max(cursor, 0) + words.length <= pendingClear) {
|
|
150
|
+
emit(Math.max(cursor, pendingClear - words.length), words);
|
|
151
|
+
emit(pendingClear, EDM2);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const s0 = Math.max(cursor, startF - words.length - EDM2.length, 0);
|
|
155
|
+
if (s0 >= pendingClear) {
|
|
156
|
+
emit(pendingClear, EDM2);
|
|
157
|
+
emit(loadWant, words);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
const k = pendingClear - s0;
|
|
161
|
+
emit(s0, words.slice(0, k));
|
|
162
|
+
emit(pendingClear, EDM2);
|
|
163
|
+
emit(cursor, words.slice(k));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
emit(loadWant, words);
|
|
169
|
+
}
|
|
170
|
+
const shownAt = emit(startF, [CTRL.EOC, CTRL.EOC]);
|
|
171
|
+
if (shownAt > startF)
|
|
172
|
+
delayed.push({ cue: i, frames: shownAt - startF });
|
|
173
|
+
pendingClear = stopF;
|
|
174
|
+
});
|
|
175
|
+
if (pendingClear !== null)
|
|
176
|
+
emit(pendingClear, [CTRL.EDM, CTRL.EDM]);
|
|
177
|
+
return {
|
|
178
|
+
text: `Scenarist_SCC V1.0\n\n${out.join('\n\n')}\n`,
|
|
179
|
+
cues: sorted.length,
|
|
180
|
+
truncated,
|
|
181
|
+
replacedChars: [...replaced],
|
|
182
|
+
delayed,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=scc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scc.js","sourceRoot":"","sources":["../../src/utils/scc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../src/utils/zip.ts"],"names":[],"mappings":"AAoBA,wBAAgB,KAAK,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAI7C;AAED,MAAM,WAAW,QAAQ;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAAA;CAAE;AAMrE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CAuDpD"}
|