@jokerized/decksmith 0.3.1 → 0.4.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/README.md +208 -15
- package/dist/cli.js +3125 -742
- package/dist/deck-player-element.js +1 -0
- package/dist/deck-player.js +1 -0
- package/dist/deck-runtime.js +27 -2
- package/dist/embed.html +243 -0
- package/dist/index.js +3211 -886
- package/dist/mcp.js +3189 -844
- package/dist/types/deck/player-element.d.ts +1 -0
- package/dist/types/deck/player.d.ts +37 -0
- package/dist/types/deck/protocol.d.ts +80 -0
- package/dist/types/deck/runtime.d.ts +163 -0
- package/dist/types/emit/archetypes/claim-figure.d.ts +0 -7
- package/dist/types/emit/camera.d.ts +14 -6
- package/dist/types/emit/composition.d.ts +13 -0
- package/dist/types/emit/kit.d.ts +66 -8
- package/dist/types/emit/svg.d.ts +27 -0
- package/dist/types/images/providers.d.ts +14 -5
- package/dist/types/index.d.ts +32 -0
- package/dist/types/mcp/tools.d.ts +20 -0
- package/dist/types/net/fetch.d.ts +81 -0
- package/dist/types/pack/media.d.ts +12 -0
- package/dist/types/plan/prompt.d.ts +2 -1
- package/dist/types/server/pipeline.d.ts +51 -8
- package/dist/types/server/upload.d.ts +29 -5
- package/dist/types/source/assets.d.ts +77 -4
- package/dist/types/source/harvest.d.ts +250 -0
- package/dist/types/source/readability.d.ts +120 -0
- package/dist/types/source/transcode.d.ts +83 -0
- package/dist/types/tmpdir.d.ts +33 -0
- package/dist/types/types.d.ts +49 -0
- package/package.json +2 -2
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHICH PART OF A PAGE IS THE ARTICLE — the Readability scoring algorithm,
|
|
3
|
+
* implemented here rather than depended on.
|
|
4
|
+
*
|
|
5
|
+
* `src/source/harvest.ts` picks its content region with three rules: believe
|
|
6
|
+
* `<main>`, believe `<article>`, else take the deepest element whose block text
|
|
7
|
+
* minus its link text is maximal. Its own comment says that is deliberately not
|
|
8
|
+
* a Readability implementation, and it holds up on the shapes it was written
|
|
9
|
+
* against. It loses on the shapes it was not: a `<main>` that also wraps the
|
|
10
|
+
* comment thread is believed whole and short-circuits before the loop ever runs;
|
|
11
|
+
* a `<div role="dialog">` cookie banner matches nothing in the walker's SKIP set,
|
|
12
|
+
* so it is neither scored down nor skipped; and the score counts text inside
|
|
13
|
+
* `nav`/`aside`/`footer` subtrees that the walker will then throw away, so a
|
|
14
|
+
* wrapper can be chosen on the strength of text that never reaches the markdown.
|
|
15
|
+
*
|
|
16
|
+
* This is Mozilla Readability's `grabArticle`, in the shape that fits here:
|
|
17
|
+
* strip the elements whose tag, role, class or id say chrome; score every
|
|
18
|
+
* paragraph by its length and its comma count; propagate that score to the
|
|
19
|
+
* parent, the grandparent and up to five levels of ancestor, dividing as it
|
|
20
|
+
* climbs; discount each candidate by its LINK DENSITY, which is the term that
|
|
21
|
+
* tells a rail of headlines from prose; take the highest, climb to a parent that
|
|
22
|
+
* scores higher still, then merge in the siblings that score close to it.
|
|
23
|
+
*
|
|
24
|
+
* WHAT THIS IS NOT. It is not a semantic understanding of the page. Nothing here
|
|
25
|
+
* reads the article; it is arithmetic over text length, punctuation, and the
|
|
26
|
+
* words site authors happen to put in class names. It is much better than one
|
|
27
|
+
* subtraction and it is wrong in ways that are structural rather than accidental,
|
|
28
|
+
* so they are worth naming:
|
|
29
|
+
*
|
|
30
|
+
* - A PAGINATED ARTICLE harvests as page one and nothing says so. Readability
|
|
31
|
+
* proper follows "next page" links; this cannot, because `harvest` fetches
|
|
32
|
+
* exactly one document and every subresource is aborted.
|
|
33
|
+
* - A PAGE WHOSE CONTENT IS A LIST OF LINKS — a link blog, a search result, a
|
|
34
|
+
* documentation index — is scored down by the very term that makes the pass
|
|
35
|
+
* work. Link density cannot tell a nav from a page that is a nav on purpose.
|
|
36
|
+
* - A GALLERY loses. Pictures carry no text, `<li>` is not a scored tag, and a
|
|
37
|
+
* page of captioned images scores near zero everywhere, so the winner is
|
|
38
|
+
* whichever caption block happened to be longest.
|
|
39
|
+
* - CLASS NAMES ARE A GUESS, and the same word list that rescues
|
|
40
|
+
* `<div class="article-body">` rescues `<div class="comment-body">`.
|
|
41
|
+
* - AN ELEMENT THE STRIP REMOVES TAKES ITS `<video>` WITH IT. That matters more
|
|
42
|
+
* here than in a reader: harvest's poster is the join that lets `attachClips`
|
|
43
|
+
* keep a clip's id, section and mention, so a silently dropped player demotes
|
|
44
|
+
* a clip with every gate green. Hence `mediaDropped` in the report — this pass
|
|
45
|
+
* counts what it lost rather than leaving the caller to find out later.
|
|
46
|
+
*
|
|
47
|
+
* When it declines it says so, PUTS BACK EVERY NODE IT REMOVED, and changes
|
|
48
|
+
* nothing else, so `harvest`'s own heuristic runs against the document it would
|
|
49
|
+
* have seen. Declining is the retry Readability performs with its flags off;
|
|
50
|
+
* here the simpler pass IS that retry, and it already exists.
|
|
51
|
+
*
|
|
52
|
+
* IT RUNS INSIDE THE PAGE. `harvest` ships code into the browser as a function
|
|
53
|
+
* reference — `page.evaluate(readDom)` — which puppeteer serialises with
|
|
54
|
+
* `Function.prototype.toString()` and evaluates as source text. `readContentRegion`
|
|
55
|
+
* is shipped the same way and carries the same rule: it may not close over
|
|
56
|
+
* anything in this module, so every constant and every helper it uses is declared
|
|
57
|
+
* inside it, INCLUDING the marker attribute that `CONTENT_MARKER` below spells a
|
|
58
|
+
* second time. A closed-over constant does not fail here, where a test would see
|
|
59
|
+
* it; it fails in the page, as a `ReferenceError`, on somebody's ingest — so
|
|
60
|
+
* test/readability.test.ts asserts the two spellings agree and that the source
|
|
61
|
+
* names nothing from Node. The node bundle is built with `minify: false`
|
|
62
|
+
* (scripts/build.mjs), which is what keeps the serialised text intact.
|
|
63
|
+
*/
|
|
64
|
+
/**
|
|
65
|
+
* The attribute the pass puts on the region it chose.
|
|
66
|
+
*
|
|
67
|
+
* A marker rather than a return value because an `Element` cannot cross the
|
|
68
|
+
* `page.evaluate` boundary — what comes back is structured-clone data. Marking
|
|
69
|
+
* is also what lets this stay a second self-contained function beside `readDom`
|
|
70
|
+
* rather than something `readDom` has to grow a second job for: the walker's
|
|
71
|
+
* `pickRoot` need only look for this attribute first and keep its own three
|
|
72
|
+
* rules as the fallback for when this pass declines.
|
|
73
|
+
*/
|
|
74
|
+
export declare const CONTENT_MARKER = "data-ds-content";
|
|
75
|
+
/** One element the scorer considered, in the terms it was judged on. */
|
|
76
|
+
export interface Candidate {
|
|
77
|
+
/** Up to three levels, `div#page > div#content > article.post`, to name it. */
|
|
78
|
+
path: string;
|
|
79
|
+
/** Paragraph scores propagated up, plus this element's tag and class weight. */
|
|
80
|
+
content: number;
|
|
81
|
+
/** Anchor text over all text, 0..1 — a rail of headlines is near 1. */
|
|
82
|
+
linkDensity: number;
|
|
83
|
+
/** `content * (1 - linkDensity)`. This is what the winner is chosen on. */
|
|
84
|
+
score: number;
|
|
85
|
+
/** Characters of text held, whitespace collapsed. */
|
|
86
|
+
text: number;
|
|
87
|
+
}
|
|
88
|
+
/** What the pass hands back across the `page.evaluate` boundary. */
|
|
89
|
+
export interface ContentPick {
|
|
90
|
+
/** True when some element in the document now carries `CONTENT_MARKER`. */
|
|
91
|
+
marked: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Why, in a sentence a `warnings` entry can carry verbatim. Populated on
|
|
94
|
+
* every path, including the ones that change nothing.
|
|
95
|
+
*/
|
|
96
|
+
reason: string;
|
|
97
|
+
/** The best few candidates, best first, so a failure names which part broke. */
|
|
98
|
+
candidates: Candidate[];
|
|
99
|
+
/** Siblings merged in beside the winner, the winner itself not counted. */
|
|
100
|
+
merged: number;
|
|
101
|
+
/** Elements the strip removed. Zero when the pass declined and put them back. */
|
|
102
|
+
stripped: number;
|
|
103
|
+
/** Characters of text in the marked region. */
|
|
104
|
+
text: number;
|
|
105
|
+
/**
|
|
106
|
+
* `<video>` and `<iframe>` elements the page had that the region does not.
|
|
107
|
+
* Not an error — a related-videos rail SHOULD be lost — but the clip path is
|
|
108
|
+
* load-bearing enough downstream that the number is reported rather than
|
|
109
|
+
* discovered.
|
|
110
|
+
*/
|
|
111
|
+
mediaDropped: number;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Choose the content region, mark it, and report what that cost.
|
|
115
|
+
*
|
|
116
|
+
* Evaluated INSIDE THE PAGE, so nothing outside this function body exists at
|
|
117
|
+
* run time. Type annotations are erased by the build and are the only thing
|
|
118
|
+
* here that refers to anything above.
|
|
119
|
+
*/
|
|
120
|
+
export declare function readContentRegion(): ContentPick;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export interface TranscodeOptions {
|
|
2
|
+
/** Longest edge of the box to fit inside, in pixels. Default 1280. */
|
|
3
|
+
maxEdgePx?: number;
|
|
4
|
+
/** Seconds to keep. A longer video is TRUNCATED, and the trim is warned. */
|
|
5
|
+
maxSeconds?: number;
|
|
6
|
+
/** Wall clock for the ffmpeg run before it is killed. Default 10 minutes. */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
/**
|
|
9
|
+
* TEST SEAM: the binary to run. Only ever "ffmpeg" in src.
|
|
10
|
+
*
|
|
11
|
+
* It exists so test/transcode.test.ts can prove the skip path by naming a
|
|
12
|
+
* binary that is not installed, which is the one branch here that cannot be
|
|
13
|
+
* exercised on a machine where the feature works.
|
|
14
|
+
*/
|
|
15
|
+
ffmpeg?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface Transcoded {
|
|
18
|
+
/** The `out` given, or the `input` given back when nothing was done to it. */
|
|
19
|
+
path: string;
|
|
20
|
+
/** Measured off the file `path` names — never the arithmetic that asked for it. */
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
/** Absent when the container declares no usable duration, as `Measured` says. */
|
|
24
|
+
seconds?: number;
|
|
25
|
+
/** False when `path` is still the original's bytes. */
|
|
26
|
+
transcoded: boolean;
|
|
27
|
+
/** What was skipped or traded, and why. Empty when nothing was. */
|
|
28
|
+
warnings: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The even box `width`x`height` fits inside, never larger than it started.
|
|
32
|
+
*
|
|
33
|
+
* FLOOR to even rather than round, on both edges. Even because VP9 in yuv420p
|
|
34
|
+
* refuses odd dimensions and says so in a way nobody reads as "your width is
|
|
35
|
+
* odd"; floor because rounding UP a 1919-wide source that needs no scaling at
|
|
36
|
+
* all would enlarge it by a pixel, and "never upscale" is easier to keep than to
|
|
37
|
+
* qualify.
|
|
38
|
+
*
|
|
39
|
+
* Rounding each edge independently moves the aspect ratio by up to a pixel's
|
|
40
|
+
* worth, and there is one place downstream where that is visible: claim-figure
|
|
41
|
+
* picks a full-width layout at exactly `width / height >= 3` (claim-figure.ts:197),
|
|
42
|
+
* so a source sitting on that boundary can land either side of it afterwards.
|
|
43
|
+
* That is a layout choice moving one step, not a deck disagreeing with its file
|
|
44
|
+
* — the figure carries the measured box, so the planner and the emitter still
|
|
45
|
+
* describe the same rectangle.
|
|
46
|
+
*/
|
|
47
|
+
export declare function fitBox(width: number, height: number, maxEdgePx: number): {
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* The command, built where it can be read and tested without running anything.
|
|
53
|
+
*
|
|
54
|
+
* The house pattern from src/render/ffmpeg.ts: an exported pure args builder and
|
|
55
|
+
* a one-line `runTool` at the use site, so the flags are assertable on a machine
|
|
56
|
+
* with no ffmpeg on it.
|
|
57
|
+
*
|
|
58
|
+
* `-an` drops the audio track outright. A clip is emitted muted on purpose — the
|
|
59
|
+
* deck already spends its single audio track on narration (claim-figure.ts:121)
|
|
60
|
+
* — so carrying the audio is pure bytes for something nothing will ever unmute.
|
|
61
|
+
*
|
|
62
|
+
* `-crf 32 -b:v 0` is libvpx-vp9's constant-quality mode; `-deadline good
|
|
63
|
+
* -cpu-used 4 -row-mt 1` is the speed setting that makes this affordable at
|
|
64
|
+
* ingest time (4 seconds of 1080p in 0.8s of wall clock, measured) rather than
|
|
65
|
+
* the several-minutes-per-clip the encoder's defaults cost. The three bitexact
|
|
66
|
+
* and metadata flags are the determinism story in the header.
|
|
67
|
+
*/
|
|
68
|
+
export declare function transcodeArgs(input: string, out: string, plan: {
|
|
69
|
+
width: number;
|
|
70
|
+
height: number;
|
|
71
|
+
seconds?: number;
|
|
72
|
+
}): string[];
|
|
73
|
+
/**
|
|
74
|
+
* Shrink `input` into `out`, and say what the result actually is.
|
|
75
|
+
*
|
|
76
|
+
* Throws for exactly one thing: an `input` this cannot measure. That is a bug at
|
|
77
|
+
* the call site rather than a machine missing a tool — `grabVideo` in harvest
|
|
78
|
+
* measures the same bytes with the same function before it writes them, and
|
|
79
|
+
* refuses what it cannot read — and there is no honest box to hand back for a
|
|
80
|
+
* file whose header says nothing. Everything else that can go wrong comes back
|
|
81
|
+
* as the original plus a warning.
|
|
82
|
+
*/
|
|
83
|
+
export declare function transcode(input: string, out: string, opts?: TranscodeOptions): Promise<Transcoded>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The directory holding our own `package.json`, found by RESOLVING it rather
|
|
3
|
+
* than by counting `..` segments off `import.meta.url`.
|
|
4
|
+
*
|
|
5
|
+
* The positional form gives the same answer everywhere this module can land
|
|
6
|
+
* today — `src/` under vitest, and the depth-one bundles `dist/cli.js`,
|
|
7
|
+
* `dist/mcp.js` and `dist/index.js`, which is the convention `src/version.ts`
|
|
8
|
+
* relies on and explains at length. The problem is how it FAILS: at any other
|
|
9
|
+
* depth the root silently becomes `dist/`, nothing is ever inside it, and the
|
|
10
|
+
* guard turns into a no-op that prints nothing and throws nothing. Nobody would
|
|
11
|
+
* notice until the directories came back. `require.resolve` throws
|
|
12
|
+
* MODULE_NOT_FOUND there instead, which is the whole reason for the detour.
|
|
13
|
+
*
|
|
14
|
+
* One consequence, stated rather than left to be discovered: in a published
|
|
15
|
+
* install this resolves to `node_modules/@jokerized/decksmith`, and nobody's
|
|
16
|
+
* TMPDIR is inside that, so the guard is a deliberate no-op for consumers. It
|
|
17
|
+
* protects this checkout — the mess is ours. Do NOT "fix" the asymmetry by
|
|
18
|
+
* testing `process.cwd()`: a user who legitimately works inside their temp
|
|
19
|
+
* directory would have their `TMPDIR` deleted for it.
|
|
20
|
+
*
|
|
21
|
+
* Exported for the test that asserts the depth is still right.
|
|
22
|
+
*/
|
|
23
|
+
export declare function packageRoot(): string;
|
|
24
|
+
/** True when `dir` is the package root or sits inside it, symlinks resolved. */
|
|
25
|
+
export declare function insideRoot(dir: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Unset a `TMPDIR` that resolves inside the package root, and say so.
|
|
28
|
+
*
|
|
29
|
+
* Idempotent by construction rather than by a flag: once the variable is gone
|
|
30
|
+
* `os.tmpdir()` answers from the platform default, so a second call finds
|
|
31
|
+
* nothing to do and stays silent.
|
|
32
|
+
*/
|
|
33
|
+
export declare function guardTmpdir(): void;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -23,12 +23,19 @@ export declare const refSchema: z.ZodObject<{
|
|
|
23
23
|
}, z.core.$strip>;
|
|
24
24
|
export declare const figureSchema: z.ZodObject<{
|
|
25
25
|
id: z.ZodString;
|
|
26
|
+
kind: z.ZodDefault<z.ZodEnum<{
|
|
27
|
+
image: "image";
|
|
28
|
+
clip: "clip";
|
|
29
|
+
}>>;
|
|
26
30
|
src: z.ZodString;
|
|
27
31
|
caption: z.ZodString;
|
|
28
32
|
width: z.ZodInt;
|
|
29
33
|
height: z.ZodInt;
|
|
30
34
|
sectionId: z.ZodOptional<z.ZodString>;
|
|
31
35
|
mention: z.ZodOptional<z.ZodString>;
|
|
36
|
+
poster: z.ZodOptional<z.ZodString>;
|
|
37
|
+
seconds: z.ZodOptional<z.ZodNumber>;
|
|
38
|
+
href: z.ZodOptional<z.ZodString>;
|
|
32
39
|
}, z.core.$strip>;
|
|
33
40
|
export declare const equationSchema: z.ZodObject<{
|
|
34
41
|
id: z.ZodString;
|
|
@@ -59,12 +66,19 @@ export declare const sourceSchema: z.ZodObject<{
|
|
|
59
66
|
}, z.core.$strip>>;
|
|
60
67
|
figures: z.ZodArray<z.ZodObject<{
|
|
61
68
|
id: z.ZodString;
|
|
69
|
+
kind: z.ZodDefault<z.ZodEnum<{
|
|
70
|
+
image: "image";
|
|
71
|
+
clip: "clip";
|
|
72
|
+
}>>;
|
|
62
73
|
src: z.ZodString;
|
|
63
74
|
caption: z.ZodString;
|
|
64
75
|
width: z.ZodInt;
|
|
65
76
|
height: z.ZodInt;
|
|
66
77
|
sectionId: z.ZodOptional<z.ZodString>;
|
|
67
78
|
mention: z.ZodOptional<z.ZodString>;
|
|
79
|
+
poster: z.ZodOptional<z.ZodString>;
|
|
80
|
+
seconds: z.ZodOptional<z.ZodNumber>;
|
|
81
|
+
href: z.ZodOptional<z.ZodString>;
|
|
68
82
|
}, z.core.$strip>>;
|
|
69
83
|
equations: z.ZodArray<z.ZodObject<{
|
|
70
84
|
id: z.ZodString;
|
|
@@ -191,6 +205,13 @@ export declare const lineChartParamsSchema: z.ZodObject<{
|
|
|
191
205
|
}, z.core.$strip>>;
|
|
192
206
|
deltas: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
193
207
|
readout: z.ZodOptional<z.ZodString>;
|
|
208
|
+
compare: z.ZodOptional<z.ZodObject<{
|
|
209
|
+
label: z.ZodString;
|
|
210
|
+
points: z.ZodArray<z.ZodObject<{
|
|
211
|
+
x: z.ZodString;
|
|
212
|
+
y: z.ZodNumber;
|
|
213
|
+
}, z.core.$strip>>;
|
|
214
|
+
}, z.core.$strip>>;
|
|
194
215
|
}, z.core.$strip>;
|
|
195
216
|
export declare const calloutParamsSchema: z.ZodObject<{
|
|
196
217
|
eyebrow: z.ZodOptional<z.ZodString>;
|
|
@@ -595,6 +616,13 @@ export declare const beatSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
595
616
|
}, z.core.$strip>>;
|
|
596
617
|
deltas: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
597
618
|
readout: z.ZodOptional<z.ZodString>;
|
|
619
|
+
compare: z.ZodOptional<z.ZodObject<{
|
|
620
|
+
label: z.ZodString;
|
|
621
|
+
points: z.ZodArray<z.ZodObject<{
|
|
622
|
+
x: z.ZodString;
|
|
623
|
+
y: z.ZodNumber;
|
|
624
|
+
}, z.core.$strip>>;
|
|
625
|
+
}, z.core.$strip>>;
|
|
598
626
|
}, z.core.$strip>;
|
|
599
627
|
id: z.ZodString;
|
|
600
628
|
intent: z.ZodString;
|
|
@@ -1194,6 +1222,13 @@ export declare const storyboardSchema: z.ZodObject<{
|
|
|
1194
1222
|
}, z.core.$strip>>;
|
|
1195
1223
|
deltas: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1196
1224
|
readout: z.ZodOptional<z.ZodString>;
|
|
1225
|
+
compare: z.ZodOptional<z.ZodObject<{
|
|
1226
|
+
label: z.ZodString;
|
|
1227
|
+
points: z.ZodArray<z.ZodObject<{
|
|
1228
|
+
x: z.ZodString;
|
|
1229
|
+
y: z.ZodNumber;
|
|
1230
|
+
}, z.core.$strip>>;
|
|
1231
|
+
}, z.core.$strip>>;
|
|
1197
1232
|
}, z.core.$strip>;
|
|
1198
1233
|
id: z.ZodString;
|
|
1199
1234
|
intent: z.ZodString;
|
|
@@ -1720,12 +1755,19 @@ export declare const packSchema: z.ZodObject<{
|
|
|
1720
1755
|
}, z.core.$strip>>;
|
|
1721
1756
|
figures: z.ZodArray<z.ZodObject<{
|
|
1722
1757
|
id: z.ZodString;
|
|
1758
|
+
kind: z.ZodDefault<z.ZodEnum<{
|
|
1759
|
+
image: "image";
|
|
1760
|
+
clip: "clip";
|
|
1761
|
+
}>>;
|
|
1723
1762
|
src: z.ZodString;
|
|
1724
1763
|
caption: z.ZodString;
|
|
1725
1764
|
width: z.ZodInt;
|
|
1726
1765
|
height: z.ZodInt;
|
|
1727
1766
|
sectionId: z.ZodOptional<z.ZodString>;
|
|
1728
1767
|
mention: z.ZodOptional<z.ZodString>;
|
|
1768
|
+
poster: z.ZodOptional<z.ZodString>;
|
|
1769
|
+
seconds: z.ZodOptional<z.ZodNumber>;
|
|
1770
|
+
href: z.ZodOptional<z.ZodString>;
|
|
1729
1771
|
}, z.core.$strip>>;
|
|
1730
1772
|
equations: z.ZodArray<z.ZodObject<{
|
|
1731
1773
|
id: z.ZodString;
|
|
@@ -1960,6 +2002,13 @@ export declare const packSchema: z.ZodObject<{
|
|
|
1960
2002
|
}, z.core.$strip>>;
|
|
1961
2003
|
deltas: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1962
2004
|
readout: z.ZodOptional<z.ZodString>;
|
|
2005
|
+
compare: z.ZodOptional<z.ZodObject<{
|
|
2006
|
+
label: z.ZodString;
|
|
2007
|
+
points: z.ZodArray<z.ZodObject<{
|
|
2008
|
+
x: z.ZodString;
|
|
2009
|
+
y: z.ZodNumber;
|
|
2010
|
+
}, z.core.$strip>>;
|
|
2011
|
+
}, z.core.$strip>>;
|
|
1963
2012
|
}, z.core.$strip>;
|
|
1964
2013
|
id: z.ZodString;
|
|
1965
2014
|
intent: z.ZodString;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jokerized/decksmith",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Turn a source document into an animated explanation deck.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"commander": "^14.0.1",
|
|
64
64
|
"fflate": "^0.8.3",
|
|
65
65
|
"gsap": "^3.14.2",
|
|
66
|
-
"hyperframes": "0.8.
|
|
66
|
+
"hyperframes": "0.8.33",
|
|
67
67
|
"katex": "^0.16.11",
|
|
68
68
|
"puppeteer-core": "^25.3.0",
|
|
69
69
|
"remark-gfm": "^4.0.1",
|