@lalalic/markcut 2.9.0 → 3.0.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/B] +2 -0
- package/package.json +1 -1
- package/skills/markcut/docs/components.md +45 -2
- package/skills/markcut/docs/markdown-descriptive.md +5 -2
- package/src/components/Markdown.tsx +138 -24
- package/src/components/Mermaid.tsx +223 -22
- package/src/context/EventContext.tsx +3 -0
- package/src/descriptive/compiler.ts +64 -29
- package/src/descriptive/markdown.ts +18 -0
- package/src/player/bundle/player.js +303 -44
- package/src/player/pipeline.mjs +66 -19
- package/src/schema/index.ts +2 -1
- package/src/types/Component.tsx +27 -1
- package/src/types/Effect.tsx +13 -6
- package/src/types/Folder.tsx +1 -1
- package/src/utils/index.ts +14 -2
- package/tests/fixtures/md/animate-diagrams.md +40 -0
- package/tests/fixtures/md/electricity-grow.md +130 -0
- package/tests/tmp/vision-1785081637127-video/videos/.normalized/segments/test-clip_0to3_seg_1100to3000.mp4 +0 -0
- package/tests/tmp/vision-1785081637127-video/videos/.normalized/test-clip_0to3.mp4 +0 -0
- package/tests/tmp/vision-1785081637127-video/videos/.normalized/test-clip_audio.mp3 +0 -0
- package/tests/tmp/vision-1785081637127-video/videos/metadata.json +9 -0
- package/tests/tmp/vision-1785081637127-video/videos/test-clip.mp4 +0 -0
- package/tests/tmp/vision-1785081637127-video/videos/test-clip.vtt +5 -0
|
@@ -448,15 +448,21 @@ function wrapWithEffects(
|
|
|
448
448
|
const absEnd = innerStream.end ?? result.duration;
|
|
449
449
|
const duration = absEnd - absStart;
|
|
450
450
|
|
|
451
|
-
//
|
|
452
|
-
//
|
|
453
|
-
//
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
451
|
+
// For background nodes without explicit end, keep original timing
|
|
452
|
+
// (start/end undefined) so parent back-propagation fills the correct
|
|
453
|
+
// scene duration. The effect wrapper handles animation timing via
|
|
454
|
+
// durationInSeconds and the parent fills end for proper visibility span.
|
|
455
|
+
// Other nodes: reset to relative timing so the effect wrapper owns
|
|
456
|
+
// the absolute positioning in the parent timeline.
|
|
457
|
+
const isBgNoEnd = innerStream.isBackground && innerStream.end == null;
|
|
458
|
+
const resetStream = isBgNoEnd
|
|
459
|
+
? { ...innerStream }
|
|
460
|
+
: {
|
|
461
|
+
...innerStream,
|
|
462
|
+
start: 0,
|
|
463
|
+
end: duration,
|
|
464
|
+
durationInSeconds: duration,
|
|
465
|
+
} as any;
|
|
460
466
|
|
|
461
467
|
// Build nested effect wrappers from innermost → outermost.
|
|
462
468
|
// The outermost effect uses the original absolute timing;
|
|
@@ -476,14 +482,18 @@ function wrapWithEffects(
|
|
|
476
482
|
id: uid(),
|
|
477
483
|
type: "effect",
|
|
478
484
|
animation: spec.animation,
|
|
485
|
+
animationDurationSeconds: spec.duration,
|
|
479
486
|
durationInSeconds: spec.duration,
|
|
480
487
|
animationTimingFunction: spec.animationTimingFunction,
|
|
481
488
|
animationIterationCount: spec.animationIterationCount ?? 1,
|
|
482
489
|
customKeyframes: spec.customKeyframes,
|
|
483
490
|
children: [currentStream],
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
491
|
+
// For background inner nodes: propagate start/end as-is so parent
|
|
492
|
+
// back-propagation fills the correct scene duration. The effect's
|
|
493
|
+
// durationInSeconds (animation spec) controls animation timing.
|
|
494
|
+
start: isOutermost && isBgNoEnd ? innerStream.start : effStart,
|
|
495
|
+
end: isOutermost && isBgNoEnd ? undefined : effEnd,
|
|
496
|
+
visible: innerStream.visible ?? true,
|
|
487
497
|
...pickOn(node),
|
|
488
498
|
} as Effect;
|
|
489
499
|
}
|
|
@@ -492,7 +502,10 @@ function wrapWithEffects(
|
|
|
492
502
|
}
|
|
493
503
|
|
|
494
504
|
function compileLeaf(node: Exclude<DescriptiveNode, DescriptiveContainer | DescriptiveScene | DescriptiveInclude>, ctx: CompileContext, parentKind: "series" | "parallel" | "transitionSeries"): CompileResult {
|
|
495
|
-
|
|
505
|
+
// Only set id when explicitly provided — auto-generated uids would register
|
|
506
|
+
// in EventContext and may create invalid JS identifiers (starting with digit).
|
|
507
|
+
const id = node.id;
|
|
508
|
+
const hasExplicitId = node.id != null;
|
|
496
509
|
|
|
497
510
|
// Background nodes without explicit duration/endAt: let parent fill timing later
|
|
498
511
|
const hasOwnDuration = typeof node.duration === "number" || typeof node.endAt === "number";
|
|
@@ -506,7 +519,7 @@ function compileLeaf(node: Exclude<DescriptiveNode, DescriptiveContainer | Descr
|
|
|
506
519
|
const end = duration != null ? start! + duration : undefined;
|
|
507
520
|
|
|
508
521
|
const base = {
|
|
509
|
-
id,
|
|
522
|
+
...(id ? { id } : {}),
|
|
510
523
|
style: node.style,
|
|
511
524
|
visible: node.visible ?? true,
|
|
512
525
|
isBackground: node.isBackground,
|
|
@@ -557,11 +570,10 @@ function compileLeaf(node: Exclude<DescriptiveNode, DescriptiveContainer | Descr
|
|
|
557
570
|
"type", "jsx", "id", "instruction", "style", "visible",
|
|
558
571
|
"isBackground", "duration", "start", "on",
|
|
559
572
|
]);
|
|
560
|
-
const bindings: Record<string,
|
|
573
|
+
const bindings: Record<string, unknown> = {};
|
|
561
574
|
for (const key of Object.keys(node)) {
|
|
562
575
|
if (!KNOWN_COMPONENT_KEYS.has(key)) {
|
|
563
|
-
|
|
564
|
-
if (typeof val === "string") bindings[key] = val;
|
|
576
|
+
bindings[key] = (node as any)[key];
|
|
565
577
|
}
|
|
566
578
|
}
|
|
567
579
|
|
|
@@ -690,14 +702,27 @@ function compileScene(
|
|
|
690
702
|
: aggregateDuration(compiledChildren, sceneKind, resolved.time);
|
|
691
703
|
const localDuration = Math.max(node.duration ?? 0, sceneContentDuration);
|
|
692
704
|
|
|
693
|
-
// Back-propagate parent duration to
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
705
|
+
// Back-propagate parent duration to nodes without own timing.
|
|
706
|
+
// Also recurses into effect wrappers so nested background children
|
|
707
|
+
// (wrapped by effects) get the correct scene duration.
|
|
708
|
+
function backpropagate(stream: Record<string, any>, dur: number): void {
|
|
709
|
+
if (stream.end == null) {
|
|
710
|
+
stream.end = dur;
|
|
711
|
+
if (stream.durationInSeconds == null) {
|
|
712
|
+
stream.durationInSeconds = dur;
|
|
713
|
+
}
|
|
714
|
+
if (stream.start == null) stream.start = 0;
|
|
715
|
+
}
|
|
716
|
+
// Recursively walk into effect wrapper children
|
|
717
|
+
if (stream.type === "effect" && Array.isArray(stream.children)) {
|
|
718
|
+
for (const child of stream.children) {
|
|
719
|
+
backpropagate(child, dur);
|
|
720
|
+
}
|
|
699
721
|
}
|
|
700
722
|
}
|
|
723
|
+
for (const c of compiledChildren) {
|
|
724
|
+
backpropagate(c.stream, localDuration);
|
|
725
|
+
}
|
|
701
726
|
|
|
702
727
|
const start = parentKind === "parallel" ? Math.max(0, node.start ?? 0) : 0;
|
|
703
728
|
const end = start + localDuration;
|
|
@@ -837,14 +862,24 @@ function compileContainer(node: DescriptiveContainer, ctx: CompileContext, paren
|
|
|
837
862
|
const children = compileChildren(node.children, ctx, node.type);
|
|
838
863
|
const duration = aggregateDuration(children, node.type, resolved.time);
|
|
839
864
|
|
|
840
|
-
// Back-propagate parent duration to
|
|
841
|
-
|
|
842
|
-
if (
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
865
|
+
// Back-propagate parent duration to nodes without own timing.
|
|
866
|
+
function backpropagate(stream: Record<string, any>, dur: number): void {
|
|
867
|
+
if (stream.end == null) {
|
|
868
|
+
stream.end = dur;
|
|
869
|
+
if (stream.durationInSeconds == null) {
|
|
870
|
+
stream.durationInSeconds = dur;
|
|
871
|
+
}
|
|
872
|
+
if (stream.start == null) stream.start = 0;
|
|
873
|
+
}
|
|
874
|
+
if (stream.type === "effect" && Array.isArray(stream.children)) {
|
|
875
|
+
for (const child of stream.children) {
|
|
876
|
+
backpropagate(child, dur);
|
|
877
|
+
}
|
|
846
878
|
}
|
|
847
879
|
}
|
|
880
|
+
for (const c of children) {
|
|
881
|
+
backpropagate(c.stream, duration);
|
|
882
|
+
}
|
|
848
883
|
|
|
849
884
|
const stream: Folder = {
|
|
850
885
|
id,
|
|
@@ -38,6 +38,7 @@ const TYPE_TOKENS: Record<string, string> = {
|
|
|
38
38
|
video: "video",
|
|
39
39
|
audio: "audio",
|
|
40
40
|
component: "component",
|
|
41
|
+
event: "event",
|
|
41
42
|
rhythm: "rhythm",
|
|
42
43
|
include: "include",
|
|
43
44
|
map: "map",
|
|
@@ -251,6 +252,23 @@ function parseNodeLine(content: string, lineNum?: number): DescriptiveNode {
|
|
|
251
252
|
preserveVariantAttrs(node, attrs);
|
|
252
253
|
return node;
|
|
253
254
|
}
|
|
255
|
+
case "event": {
|
|
256
|
+
// Event-only stub: compiles to a component with empty JSX (renders nothing),
|
|
257
|
+
// just fires events on other registered components via `on`.
|
|
258
|
+
const node: DescriptiveComponent = {
|
|
259
|
+
type: "component",
|
|
260
|
+
id: attrs.id as any,
|
|
261
|
+
jsx: "",
|
|
262
|
+
duration: attrs.duration as any,
|
|
263
|
+
start: attrs.start as any,
|
|
264
|
+
instruction: attrs.instruction as any,
|
|
265
|
+
style: attrs.style as any,
|
|
266
|
+
effects: attrs.effects as any,
|
|
267
|
+
on: attrs.on as any,
|
|
268
|
+
};
|
|
269
|
+
preserveVariantAttrs(node, attrs);
|
|
270
|
+
return node;
|
|
271
|
+
}
|
|
254
272
|
case "rhythm": {
|
|
255
273
|
const src = firstPositional ?? (attrs.src as string | undefined);
|
|
256
274
|
if (!src) throw new DslError("rhythm requires src", ctx);
|
|
@@ -122,7 +122,7 @@ var require_react_production = __commonJS({
|
|
|
122
122
|
function cloneAndReplaceKey(oldElement, newKey) {
|
|
123
123
|
return ReactElement(oldElement.type, newKey, oldElement.props);
|
|
124
124
|
}
|
|
125
|
-
function
|
|
125
|
+
function isValidElement2(object4) {
|
|
126
126
|
return "object" === typeof object4 && null !== object4 && object4.$$typeof === REACT_ELEMENT_TYPE;
|
|
127
127
|
}
|
|
128
128
|
function escape3(key) {
|
|
@@ -189,7 +189,7 @@ var require_react_production = __commonJS({
|
|
|
189
189
|
if (invokeCallback)
|
|
190
190
|
return callback = callback(children2), invokeCallback = "" === nameSoFar ? "." + getElementKey(children2, 0) : nameSoFar, isArrayImpl(callback) ? (escapedPrefix = "", null != invokeCallback && (escapedPrefix = invokeCallback.replace(userProvidedKeyEscapeRegex, "$&/") + "/"), mapIntoArray(callback, array5, escapedPrefix, "", function(c5) {
|
|
191
191
|
return c5;
|
|
192
|
-
})) : null != callback && (
|
|
192
|
+
})) : null != callback && (isValidElement2(callback) && (callback = cloneAndReplaceKey(
|
|
193
193
|
callback,
|
|
194
194
|
escapedPrefix + (null == callback.key || children2 && children2.key === callback.key ? "" : ("" + callback.key).replace(
|
|
195
195
|
userProvidedKeyEscapeRegex,
|
|
@@ -298,7 +298,7 @@ var require_react_production = __commonJS({
|
|
|
298
298
|
}) || [];
|
|
299
299
|
},
|
|
300
300
|
only: function(children2) {
|
|
301
|
-
if (!
|
|
301
|
+
if (!isValidElement2(children2))
|
|
302
302
|
throw Error(
|
|
303
303
|
"React.Children.only expected to receive a single React element child."
|
|
304
304
|
);
|
|
@@ -385,7 +385,7 @@ var require_react_production = __commonJS({
|
|
|
385
385
|
exports2.forwardRef = function(render8) {
|
|
386
386
|
return { $$typeof: REACT_FORWARD_REF_TYPE, render: render8 };
|
|
387
387
|
};
|
|
388
|
-
exports2.isValidElement =
|
|
388
|
+
exports2.isValidElement = isValidElement2;
|
|
389
389
|
exports2.lazy = function(ctor) {
|
|
390
390
|
return {
|
|
391
391
|
$$typeof: REACT_LAZY_TYPE,
|
|
@@ -225416,10 +225416,100 @@ var mermaid_default = mermaid;
|
|
|
225416
225416
|
// src/components/Mermaid.tsx
|
|
225417
225417
|
var import_jsx_runtime60 = __toESM(require_jsx_runtime(), 1);
|
|
225418
225418
|
var initialized = false;
|
|
225419
|
-
function
|
|
225419
|
+
function extractText(x7) {
|
|
225420
|
+
if (typeof x7 === "string") return x7;
|
|
225421
|
+
if (Array.isArray(x7)) return x7.map(extractText).join("");
|
|
225422
|
+
if (x7 && typeof x7 === "object" && "props" in x7) {
|
|
225423
|
+
return extractText(x7.props?.children);
|
|
225424
|
+
}
|
|
225425
|
+
return "";
|
|
225426
|
+
}
|
|
225427
|
+
function findNodeGroup(svg4, name2) {
|
|
225428
|
+
const byId = svg4.querySelector(`[id*="-${CSS.escape(name2)}-"]`);
|
|
225429
|
+
if (byId) {
|
|
225430
|
+
let el = byId;
|
|
225431
|
+
while (el && el.tagName !== "g") el = el.parentElement;
|
|
225432
|
+
return el || byId;
|
|
225433
|
+
}
|
|
225434
|
+
for (const t4 of svg4.querySelectorAll("text")) {
|
|
225435
|
+
const text10 = t4.textContent?.trim() ?? "";
|
|
225436
|
+
if (text10.startsWith(name2)) {
|
|
225437
|
+
let el = t4;
|
|
225438
|
+
while (el && el.tagName !== "g") el = el.parentElement;
|
|
225439
|
+
return el || t4;
|
|
225440
|
+
}
|
|
225441
|
+
}
|
|
225442
|
+
for (const t4 of svg4.querySelectorAll("title")) {
|
|
225443
|
+
if ((t4.textContent?.trim() ?? "").startsWith(name2) && t4.parentElement) {
|
|
225444
|
+
return t4.parentElement;
|
|
225445
|
+
}
|
|
225446
|
+
}
|
|
225447
|
+
return null;
|
|
225448
|
+
}
|
|
225449
|
+
function applyEdgeAnimation(svg4, spec) {
|
|
225450
|
+
if (!spec) return;
|
|
225451
|
+
const allEdges = Array.from(svg4.querySelectorAll(
|
|
225452
|
+
'path[id*="-L_"]'
|
|
225453
|
+
));
|
|
225454
|
+
if (spec === true) {
|
|
225455
|
+
for (const path5 of allEdges) {
|
|
225456
|
+
path5.classList.add("edge-animated");
|
|
225457
|
+
}
|
|
225458
|
+
return;
|
|
225459
|
+
}
|
|
225460
|
+
for (const pattern of spec) {
|
|
225461
|
+
const match3 = pattern.match(/^(\w+)\s*->\s*(\w+)$/);
|
|
225462
|
+
if (!match3) continue;
|
|
225463
|
+
const source = match3[1];
|
|
225464
|
+
const target = match3[2];
|
|
225465
|
+
const suffix = `L_${source}_${target}_`;
|
|
225466
|
+
for (const path5 of allEdges) {
|
|
225467
|
+
if (path5.id.includes(suffix)) {
|
|
225468
|
+
path5.classList.add("edge-animated");
|
|
225469
|
+
}
|
|
225470
|
+
}
|
|
225471
|
+
}
|
|
225472
|
+
}
|
|
225473
|
+
function Mermaid({
|
|
225474
|
+
children: children2,
|
|
225475
|
+
source: sourceProp,
|
|
225476
|
+
theme = "dark",
|
|
225477
|
+
className: className2,
|
|
225478
|
+
style: style4,
|
|
225479
|
+
highlight,
|
|
225480
|
+
animateEdges
|
|
225481
|
+
}) {
|
|
225420
225482
|
const ref2 = React8.useRef(null);
|
|
225421
|
-
const
|
|
225483
|
+
const renderedRef = React8.useRef(false);
|
|
225484
|
+
const styleRef = React8.useRef(null);
|
|
225422
225485
|
React8.useEffect(() => {
|
|
225486
|
+
if (!styleRef.current) {
|
|
225487
|
+
const el = document.createElement("style");
|
|
225488
|
+
el.textContent = `
|
|
225489
|
+
@keyframes mermaid-edge-flow {
|
|
225490
|
+
to { stroke-dashoffset: -24; }
|
|
225491
|
+
}
|
|
225492
|
+
.edge-animated {
|
|
225493
|
+
stroke-dasharray: 8 6 !important;
|
|
225494
|
+
animation: mermaid-edge-flow 0.5s linear infinite !important;
|
|
225495
|
+
}
|
|
225496
|
+
`;
|
|
225497
|
+
document.head.appendChild(el);
|
|
225498
|
+
styleRef.current = el;
|
|
225499
|
+
}
|
|
225500
|
+
return () => {
|
|
225501
|
+
if (styleRef.current) {
|
|
225502
|
+
styleRef.current.remove();
|
|
225503
|
+
styleRef.current = null;
|
|
225504
|
+
}
|
|
225505
|
+
};
|
|
225506
|
+
}, []);
|
|
225507
|
+
const source = React8.useMemo(
|
|
225508
|
+
() => extractText(sourceProp ?? children2),
|
|
225509
|
+
[sourceProp, children2]
|
|
225510
|
+
);
|
|
225511
|
+
React8.useEffect(() => {
|
|
225512
|
+
let cancelled = false;
|
|
225423
225513
|
if (!source || !ref2.current) return;
|
|
225424
225514
|
if (!initialized) {
|
|
225425
225515
|
mermaid_default.initialize({
|
|
@@ -225431,52 +225521,186 @@ function Mermaid({ children: children2, source = children2, theme = "dark", clas
|
|
|
225431
225521
|
}
|
|
225432
225522
|
const id39 = "mmd-" + Math.random().toString(36).slice(2, 10);
|
|
225433
225523
|
mermaid_default.render(id39, source).then((result) => {
|
|
225434
|
-
if (ref2.current)
|
|
225435
|
-
|
|
225524
|
+
if (cancelled || !ref2.current) return;
|
|
225525
|
+
ref2.current.innerHTML = result.svg;
|
|
225526
|
+
const svg4 = ref2.current.querySelector("svg");
|
|
225527
|
+
if (svg4) {
|
|
225528
|
+
svg4.removeAttribute("width");
|
|
225529
|
+
svg4.removeAttribute("height");
|
|
225530
|
+
svg4.style.width = "100%";
|
|
225531
|
+
svg4.style.height = "100%";
|
|
225532
|
+
if (highlight) {
|
|
225533
|
+
const names = Array.isArray(highlight) ? highlight : [highlight];
|
|
225534
|
+
for (const name2 of names) {
|
|
225535
|
+
const node3 = findNodeGroup(svg4, name2);
|
|
225536
|
+
if (node3) node3.classList.add("highlight");
|
|
225537
|
+
}
|
|
225538
|
+
}
|
|
225539
|
+
applyEdgeAnimation(svg4, animateEdges);
|
|
225540
|
+
}
|
|
225541
|
+
renderedRef.current = true;
|
|
225436
225542
|
}).catch((err) => {
|
|
225543
|
+
if (cancelled) return;
|
|
225437
225544
|
console.error("Mermaid error:", err);
|
|
225438
225545
|
if (ref2.current) {
|
|
225439
225546
|
ref2.current.innerHTML = `<div style="color:#f87171;padding:1em;border:2px dashed #f87171;border-radius:8px;font-family:monospace;font-size:14px;">
|
|
225440
225547
|
<strong>\u26A0 Mermaid Error</strong><br/>${String(err).replace(/</g, "<").replace(/>/g, ">")}
|
|
225441
225548
|
</div>`;
|
|
225442
225549
|
}
|
|
225443
|
-
continueRender(handle2);
|
|
225444
225550
|
});
|
|
225445
|
-
|
|
225446
|
-
|
|
225447
|
-
|
|
225448
|
-
|
|
225449
|
-
|
|
225450
|
-
|
|
225551
|
+
return () => {
|
|
225552
|
+
cancelled = true;
|
|
225553
|
+
};
|
|
225554
|
+
}, [source, theme]);
|
|
225555
|
+
React8.useEffect(() => {
|
|
225556
|
+
const svg4 = ref2.current?.querySelector("svg");
|
|
225557
|
+
if (!svg4) return;
|
|
225558
|
+
svg4.querySelectorAll(".highlight").forEach((el) => {
|
|
225559
|
+
el.classList.remove("highlight");
|
|
225560
|
+
});
|
|
225561
|
+
const names = Array.isArray(highlight) ? highlight : highlight ? [highlight] : [];
|
|
225562
|
+
for (const name2 of names) {
|
|
225563
|
+
const node3 = findNodeGroup(svg4, name2);
|
|
225564
|
+
if (node3) {
|
|
225565
|
+
node3.classList.add("highlight");
|
|
225566
|
+
}
|
|
225451
225567
|
}
|
|
225452
|
-
);
|
|
225568
|
+
}, [highlight]);
|
|
225569
|
+
React8.useEffect(() => {
|
|
225570
|
+
const svg4 = ref2.current?.querySelector("svg");
|
|
225571
|
+
if (!svg4) return;
|
|
225572
|
+
svg4.querySelectorAll(".edge-animated").forEach((el) => {
|
|
225573
|
+
el.classList.remove("edge-animated");
|
|
225574
|
+
});
|
|
225575
|
+
applyEdgeAnimation(svg4, animateEdges);
|
|
225576
|
+
}, [animateEdges]);
|
|
225577
|
+
const containerStyle3 = {
|
|
225578
|
+
display: "flex",
|
|
225579
|
+
justifyContent: "center",
|
|
225580
|
+
alignItems: "center",
|
|
225581
|
+
width: "100%",
|
|
225582
|
+
height: "100%",
|
|
225583
|
+
...style4
|
|
225584
|
+
};
|
|
225585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { ref: ref2, className: className2, style: containerStyle3 });
|
|
225453
225586
|
}
|
|
225454
225587
|
|
|
225455
225588
|
// src/components/Markdown.tsx
|
|
225456
225589
|
var import_jsx_runtime61 = __toESM(require_jsx_runtime(), 1);
|
|
225457
|
-
|
|
225458
|
-
|
|
225590
|
+
var ListCtx = React9.createContext([]);
|
|
225591
|
+
function OrderedList({
|
|
225592
|
+
children: children2,
|
|
225593
|
+
...props
|
|
225594
|
+
}) {
|
|
225595
|
+
const hl = React9.useContext(ListCtx);
|
|
225596
|
+
const items = React9.Children.toArray(children2).filter(
|
|
225597
|
+
(c5) => React9.isValidElement(c5) && c5.type === "li"
|
|
225598
|
+
);
|
|
225599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("ol", { ...props, children: items.map((child, i5) => {
|
|
225600
|
+
if (hl.includes(i5)) {
|
|
225601
|
+
return React9.cloneElement(child, { className: "highlight-list-item", key: child.key });
|
|
225602
|
+
}
|
|
225603
|
+
return child;
|
|
225604
|
+
}) });
|
|
225605
|
+
}
|
|
225606
|
+
function UnorderedList({
|
|
225607
|
+
children: children2,
|
|
225608
|
+
...props
|
|
225609
|
+
}) {
|
|
225610
|
+
const hl = React9.useContext(ListCtx);
|
|
225611
|
+
const items = React9.Children.toArray(children2).filter(
|
|
225612
|
+
(c5) => React9.isValidElement(c5) && c5.type === "li"
|
|
225613
|
+
);
|
|
225614
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("ul", { ...props, children: items.map((child, i5) => {
|
|
225615
|
+
if (hl.includes(i5)) {
|
|
225616
|
+
return React9.cloneElement(child, { className: "highlight-list-item", key: child.key });
|
|
225617
|
+
}
|
|
225618
|
+
return child;
|
|
225619
|
+
}) });
|
|
225620
|
+
}
|
|
225621
|
+
function Markdown2({
|
|
225622
|
+
children: children2,
|
|
225623
|
+
source = children2,
|
|
225624
|
+
className: className2,
|
|
225625
|
+
plugins,
|
|
225626
|
+
components: propComponents,
|
|
225627
|
+
highlight
|
|
225628
|
+
}) {
|
|
225629
|
+
const hl = React9.useMemo(() => highlight ?? [], [highlight]);
|
|
225630
|
+
React9.useEffect(() => {
|
|
225631
|
+
const id39 = "markcut-markdown-defaults";
|
|
225632
|
+
if (document.getElementById(id39)) return;
|
|
225633
|
+
const el = document.createElement("style");
|
|
225634
|
+
el.id = id39;
|
|
225635
|
+
el.textContent = `
|
|
225636
|
+
.highlight-list-item {
|
|
225637
|
+
background: rgba(255, 215, 0, 0.15);
|
|
225638
|
+
border-left: 3px solid #ffd700;
|
|
225639
|
+
padding-left: 8px;
|
|
225640
|
+
border-radius: 0 4px 4px 0;
|
|
225641
|
+
}
|
|
225642
|
+
.slide {
|
|
225643
|
+
display: flex;
|
|
225644
|
+
flex-direction: column;
|
|
225645
|
+
align-items: center;
|
|
225646
|
+
justify-content: center;
|
|
225647
|
+
padding: 24px;
|
|
225648
|
+
text-align: center;
|
|
225649
|
+
}
|
|
225650
|
+
.slide h1 { font-size: 2em; margin: 0.4em 0; font-weight: 700; }
|
|
225651
|
+
.slide h2 { font-size: 1.6em; margin: 0.35em 0; font-weight: 600; }
|
|
225652
|
+
.slide h3 { font-size: 1.3em; margin: 0.3em 0; font-weight: 600; }
|
|
225653
|
+
.slide p { margin: 0.6em 0; line-height: 1.6; }
|
|
225654
|
+
.slide ul, .slide ol { margin: 0.5em 0; padding-left: 1.5em; text-align: left; }
|
|
225655
|
+
.slide li { margin: 0.3em 0; }
|
|
225656
|
+
.slide blockquote {
|
|
225657
|
+
margin: 0.6em 0;
|
|
225658
|
+
padding: 0.4em 1em;
|
|
225659
|
+
border-left: 3px solid rgba(255,255,255,.3);
|
|
225660
|
+
font-style: italic;
|
|
225661
|
+
opacity: .85;
|
|
225662
|
+
}
|
|
225663
|
+
.slide code {
|
|
225664
|
+
background: rgba(255,255,255,.08);
|
|
225665
|
+
padding: 0.15em 0.4em;
|
|
225666
|
+
border-radius: 4px;
|
|
225667
|
+
font-size: 0.9em;
|
|
225668
|
+
}
|
|
225669
|
+
.slide pre { margin: 0.6em 0; text-align: left; width: 100%; }
|
|
225670
|
+
.slide a { color: #4a9eff; text-decoration: none; }
|
|
225671
|
+
.slide a:hover { text-decoration: underline; }
|
|
225672
|
+
`;
|
|
225673
|
+
document.head.appendChild(el);
|
|
225674
|
+
return () => {
|
|
225675
|
+
document.getElementById(id39)?.remove();
|
|
225676
|
+
};
|
|
225677
|
+
}, []);
|
|
225678
|
+
const mergedComponents = React9.useMemo(
|
|
225679
|
+
() => ({
|
|
225680
|
+
...propComponents,
|
|
225681
|
+
ol: OrderedList,
|
|
225682
|
+
ul: UnorderedList,
|
|
225683
|
+
pre: ({ children: preChildren }) => {
|
|
225684
|
+
const code4 = React9.Children.toArray(preChildren)[0];
|
|
225685
|
+
if (code4?.props?.className === "language-mermaid") {
|
|
225686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Mermaid, { source: String(code4.props.children) });
|
|
225687
|
+
}
|
|
225688
|
+
if (propComponents?.pre) {
|
|
225689
|
+
return propComponents.pre({ children: preChildren });
|
|
225690
|
+
}
|
|
225691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("pre", { children: preChildren });
|
|
225692
|
+
}
|
|
225693
|
+
}),
|
|
225694
|
+
[propComponents]
|
|
225695
|
+
);
|
|
225696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(ListCtx.Provider, { value: hl, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: className2, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
225459
225697
|
Markdown,
|
|
225460
225698
|
{
|
|
225461
225699
|
remarkPlugins: React9.useMemo(() => [remarkGfm, ...plugins || []], [plugins]),
|
|
225462
|
-
components:
|
|
225463
|
-
() => ({
|
|
225464
|
-
...components3,
|
|
225465
|
-
pre: ({ children: children3 }) => {
|
|
225466
|
-
const code4 = React9.Children.toArray(children3)[0];
|
|
225467
|
-
if (code4?.props?.className === "language-mermaid") {
|
|
225468
|
-
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Mermaid, { source: String(code4.props.children) });
|
|
225469
|
-
} else if (components3.pre) {
|
|
225470
|
-
return components3.pre({ children: children3 });
|
|
225471
|
-
}
|
|
225472
|
-
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("pre", { children: children3 });
|
|
225473
|
-
}
|
|
225474
|
-
}),
|
|
225475
|
-
[components3]
|
|
225476
|
-
),
|
|
225700
|
+
components: mergedComponents,
|
|
225477
225701
|
children: source
|
|
225478
225702
|
}
|
|
225479
|
-
) });
|
|
225703
|
+
) }) });
|
|
225480
225704
|
}
|
|
225481
225705
|
|
|
225482
225706
|
// src/utils/component-import-map.ts
|
|
@@ -225588,6 +225812,8 @@ function EventProvider({ children: children2 }) {
|
|
|
225588
225812
|
const keys4 = Object.keys(scope);
|
|
225589
225813
|
const vals = Object.values(scope);
|
|
225590
225814
|
try {
|
|
225815
|
+
const codeChars = Array.from(code4).map((c5) => c5.charCodeAt(0));
|
|
225816
|
+
console.log(`EventContext.debug: keys=${JSON.stringify(keys4)}, codeLen=${code4.length}, codeChars=${JSON.stringify(codeChars)}, codeStr=${JSON.stringify(code4)}`);
|
|
225591
225817
|
const fn3 = new Function(...keys4, code4);
|
|
225592
225818
|
fn3(...vals);
|
|
225593
225819
|
console.info(`Event evaluation succeeded: "${code4}"`);
|
|
@@ -227900,7 +228126,13 @@ var clockWipe = (props) => {
|
|
|
227900
228126
|
|
|
227901
228127
|
// src/utils/index.ts
|
|
227902
228128
|
function uid() {
|
|
227903
|
-
|
|
228129
|
+
const raw = Math.random().toString(36).slice(2, 10);
|
|
228130
|
+
const first3 = raw[0];
|
|
228131
|
+
if (/^[0-9]/.test(first3)) {
|
|
228132
|
+
const letter = String.fromCharCode(97 + Math.floor(Math.random() * 26));
|
|
228133
|
+
return letter + raw;
|
|
228134
|
+
}
|
|
228135
|
+
return raw;
|
|
227904
228136
|
}
|
|
227905
228137
|
var KEBAB = /[^a-zA-Z0-9_-]+/g;
|
|
227906
228138
|
function toClassName(s3) {
|
|
@@ -227966,7 +228198,7 @@ function getDurationInSeconds(stream3, update2 = true) {
|
|
|
227966
228198
|
for (const child of stream3.children) {
|
|
227967
228199
|
getDurationInSeconds(child, update2);
|
|
227968
228200
|
}
|
|
227969
|
-
const visible = stream3.children.filter((c5) => !c5.isBackground);
|
|
228201
|
+
const visible = stream3.type === "effect" ? stream3.children : stream3.children.filter((c5) => !c5.isBackground);
|
|
227970
228202
|
if (stream3.isSeries) {
|
|
227971
228203
|
const overlap = stream3.transition ? stream3.transitionTime ?? 0.5 : 0;
|
|
227972
228204
|
for (let i5 = 0; i5 < visible.length; i5++) {
|
|
@@ -239667,7 +239899,30 @@ function ComponentLeaf({ stream: stream3 }) {
|
|
|
239667
239899
|
() => ({ ...components3, ...stream3.data, ...eventState }),
|
|
239668
239900
|
[stream3.data, components3, eventState]
|
|
239669
239901
|
);
|
|
239670
|
-
if (!stream3.jsx)
|
|
239902
|
+
if (!stream3.jsx) {
|
|
239903
|
+
const start5 = stream3.start ?? 0;
|
|
239904
|
+
const end3 = stream3.end ?? start5 + (stream3.duration ?? 1);
|
|
239905
|
+
const durFrames2 = Math.max(1, Math.floor(fps * (end3 - start5)));
|
|
239906
|
+
return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
239907
|
+
Sequence,
|
|
239908
|
+
{
|
|
239909
|
+
durationInFrames: durFrames2,
|
|
239910
|
+
from: Math.floor(fps * start5),
|
|
239911
|
+
layout: "none",
|
|
239912
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
239913
|
+
EventAwareComponent,
|
|
239914
|
+
{
|
|
239915
|
+
jsx: "",
|
|
239916
|
+
components: components3,
|
|
239917
|
+
data: bindings,
|
|
239918
|
+
action: { start: start5, end: end3 },
|
|
239919
|
+
durFrames: durFrames2,
|
|
239920
|
+
on: stream3.on
|
|
239921
|
+
}
|
|
239922
|
+
)
|
|
239923
|
+
}
|
|
239924
|
+
);
|
|
239925
|
+
}
|
|
239671
239926
|
const start4 = stream3.start ?? 0;
|
|
239672
239927
|
const end2 = stream3.end ?? start4 + (stream3.duration ?? 1);
|
|
239673
239928
|
const durFrames = Math.max(1, Math.floor(fps * (end2 - start4)));
|
|
@@ -239700,6 +239955,7 @@ function EventAwareComponent({
|
|
|
239700
239955
|
on: on3
|
|
239701
239956
|
}) {
|
|
239702
239957
|
useFrameEvents(on3, durFrames);
|
|
239958
|
+
if (!jsx84) return null;
|
|
239703
239959
|
return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
239704
239960
|
TweenedJsxParser,
|
|
239705
239961
|
{
|
|
@@ -242999,15 +243255,17 @@ function EffectWrapper({
|
|
|
242999
243255
|
const end2 = Math.ceil(endSec * fps);
|
|
243000
243256
|
const durationInFrames = end2 - start4;
|
|
243001
243257
|
if (durationInFrames <= 0) return [];
|
|
243258
|
+
const animDurationSec = stream3.animationDurationSeconds ?? stream3.durationInSeconds ?? durationInFrames / fps;
|
|
243259
|
+
const animDurationFrames = Math.ceil(animDurationSec * fps);
|
|
243002
243260
|
const animation2 = stream3.animation;
|
|
243003
243261
|
const timingFn = stream3.animationTimingFunction;
|
|
243004
243262
|
const iterCount = stream3.animationIterationCount ?? 1;
|
|
243005
243263
|
const style4 = cssJS(stream3.style) ?? {};
|
|
243006
243264
|
let currentFrame = frame2;
|
|
243007
|
-
if (iterCount > 0 &&
|
|
243008
|
-
const iteration = Math.floor((frame2 - start4) /
|
|
243265
|
+
if (iterCount > 0 && animDurationFrames > 0) {
|
|
243266
|
+
const iteration = Math.floor((frame2 - start4) / animDurationFrames);
|
|
243009
243267
|
if (iteration < iterCount) {
|
|
243010
|
-
currentFrame = start4 + (frame2 - start4) %
|
|
243268
|
+
currentFrame = start4 + (frame2 - start4) % animDurationFrames;
|
|
243011
243269
|
}
|
|
243012
243270
|
}
|
|
243013
243271
|
if (currentFrame >= start4 && currentFrame < end2) {
|
|
@@ -243017,7 +243275,7 @@ function EffectWrapper({
|
|
|
243017
243275
|
if (config4) {
|
|
243018
243276
|
const animStyle = interpolateKeyframes(config4, actionFrame, {
|
|
243019
243277
|
fps,
|
|
243020
|
-
durationInSeconds:
|
|
243278
|
+
durationInSeconds: animDurationSec,
|
|
243021
243279
|
timingFunction: timingFn
|
|
243022
243280
|
});
|
|
243023
243281
|
if (animStyle) Object.assign(style4, animStyle);
|
|
@@ -243025,7 +243283,7 @@ function EffectWrapper({
|
|
|
243025
243283
|
}
|
|
243026
243284
|
}
|
|
243027
243285
|
return Object.keys(style4).length > 0 ? [style4] : [];
|
|
243028
|
-
}, [frame2, fps, startSec, endSec, stream3.animation, stream3.animationTimingFunction, stream3.animationIterationCount, stream3.customKeyframes, stream3.style]);
|
|
243286
|
+
}, [frame2, fps, startSec, endSec, stream3.animation, stream3.animationTimingFunction, stream3.animationIterationCount, stream3.customKeyframes, stream3.style, stream3.animationDurationSeconds, stream3.durationInSeconds]);
|
|
243029
243287
|
if (styles7.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(import_jsx_runtime92.Fragment, { children: children2 });
|
|
243030
243288
|
return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
|
|
243031
243289
|
"div",
|
|
@@ -243070,7 +243328,7 @@ function FolderLeaf({ stream: stream3 }) {
|
|
|
243070
243328
|
const isRoot = stream3.id === "root";
|
|
243071
243329
|
const visibleChildren = stream3.children.filter((c5) => c5.visible !== false);
|
|
243072
243330
|
const bgChildren = visibleChildren.filter((c5) => c5.isBackground);
|
|
243073
|
-
const seriesChildren =
|
|
243331
|
+
const seriesChildren = visibleChildren.filter((c5) => !c5.isBackground);
|
|
243074
243332
|
const allAudio = seriesChildren.length > 0 && seriesChildren.every((c5) => c5.type === "audio");
|
|
243075
243333
|
const effectiveTransition = allAudio ? void 0 : transition2;
|
|
243076
243334
|
const TypedSeries = React47.useMemo(() => {
|
|
@@ -257457,11 +257715,12 @@ var image3 = base.extend({
|
|
|
257457
257715
|
var component2 = base.extend({
|
|
257458
257716
|
type: external_exports.literal("component").default("component"),
|
|
257459
257717
|
jsx: external_exports.string().describe("usage JSX expression compiled at runtime; tag names resolved from imports"),
|
|
257460
|
-
data: external_exports.record(external_exports.string(), external_exports.
|
|
257718
|
+
data: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("extra variables (e.g. from ~~~md source code fences) available in JSX scope")
|
|
257461
257719
|
});
|
|
257462
257720
|
var effect = base.extend({
|
|
257463
257721
|
type: external_exports.literal("effect").default("effect"),
|
|
257464
257722
|
animation: external_exports.string().optional().describe("builtin keyframe name or 'custom'"),
|
|
257723
|
+
animationDurationSeconds: external_exports.number().optional().describe("animation duration (separate from wrapper durationInSeconds which getDurationInSeconds may overwrite)"),
|
|
257465
257724
|
animationTimingFunction: external_exports.enum(["linear", "ease", "ease-in", "ease-out", "ease-in-out"]).optional(),
|
|
257466
257725
|
animationIterationCount: external_exports.number().default(1),
|
|
257467
257726
|
customKeyframes: external_exports.record(external_exports.string(), external_exports.record(external_exports.string(), external_exports.string())).optional().describe('inline keyframes: { "0": { opacity: "0" }, "100": { opacity: "1" } }'),
|