@dnyantra/dtly 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +172 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +95 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/anim.d.ts +3 -0
- package/dist/core/anim.js +61 -0
- package/dist/core/anim.js.map +1 -0
- package/dist/core/color.d.ts +4 -0
- package/dist/core/color.js +28 -0
- package/dist/core/color.js.map +1 -0
- package/dist/core/ease.d.ts +8 -0
- package/dist/core/ease.js +90 -0
- package/dist/core/ease.js.map +1 -0
- package/dist/core/model.d.ts +229 -0
- package/dist/core/model.js +4 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/text.d.ts +41 -0
- package/dist/core/text.js +222 -0
- package/dist/core/text.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.js +193 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/node.d.ts +4 -0
- package/dist/node.js +6 -0
- package/dist/node.js.map +1 -0
- package/dist/ops/ops.d.ts +39 -0
- package/dist/ops/ops.js +259 -0
- package/dist/ops/ops.js.map +1 -0
- package/dist/ops/store.d.ts +4 -0
- package/dist/ops/store.js +22 -0
- package/dist/ops/store.js.map +1 -0
- package/dist/presets/index.d.ts +14 -0
- package/dist/presets/index.js +235 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/text.d.ts +5 -0
- package/dist/presets/text.js +19 -0
- package/dist/presets/text.js.map +1 -0
- package/dist/render/export.d.ts +43 -0
- package/dist/render/export.js +215 -0
- package/dist/render/export.js.map +1 -0
- package/dist/render/ffmpeg.d.ts +1 -0
- package/dist/render/ffmpeg.js +16 -0
- package/dist/render/ffmpeg.js.map +1 -0
- package/dist/render/node-host.d.ts +18 -0
- package/dist/render/node-host.js +168 -0
- package/dist/render/node-host.js.map +1 -0
- package/dist/render/renderer.d.ts +36 -0
- package/dist/render/renderer.js +372 -0
- package/dist/render/renderer.js.map +1 -0
- package/dist/starter.d.ts +5 -0
- package/dist/starter.js +32 -0
- package/dist/starter.js.map +1 -0
- package/dist/studio/server.d.ts +12 -0
- package/dist/studio/server.js +190 -0
- package/dist/studio/server.js.map +1 -0
- package/dist/studio-app/app.css +2 -0
- package/dist/studio-app/app.css.map +7 -0
- package/dist/studio-app/app.js +5 -0
- package/dist/studio-app/app.js.map +7 -0
- package/dist/studio-app/index.html +15 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/fonts/Baloo2.ttf +0 -0
- package/fonts/Mukta-Bold.ttf +0 -0
- package/fonts/OFL-Baloo2.txt +93 -0
- package/fonts/OFL-Mukta.txt +93 -0
- package/package.json +84 -4
- package/plugin/skills/dtly/SKILL.md +94 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DT.ly — from the creator of CustomerPro.in
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Bundled fonts in fonts/ (Baloo 2, Mukta) are licensed under the SIL Open Font
|
|
26
|
+
License 1.1; see fonts/OFL-Baloo2.txt and fonts/OFL-Mukta.txt.
|
package/README.md
CHANGED
|
@@ -1,3 +1,173 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DT.ly
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@dnyantra/dtly) [](LICENSE)
|
|
4
|
+
|
|
5
|
+
**After Effects-style motion graphics for code and AI agents.**
|
|
6
|
+
*From the creator of [CustomerPro.in](https://customerpro.in).*
|
|
7
|
+
|
|
8
|
+
DT.ly describes a video as plain JSON — compositions, layers, keyframes with easing curves,
|
|
9
|
+
text animators, masks, track mattes, trim paths, parenting, effects and motion blur — and renders
|
|
10
|
+
it to MP4. An MCP server lets AI agents edit projects keyframe by keyframe and look at the frames
|
|
11
|
+
they make.
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
- **Fine-grained animation** — any property can be keyframed with AE-style eases, bezier curves or physical springs; `wiggle` included.
|
|
16
|
+
- **Text animators** — per grapheme, word or line, with stagger, order, blur, tracking, colour and masked line reveals. Indian scripts (Devanagari etc.) keep their conjuncts while animating.
|
|
17
|
+
- **Presets** — kinetic typography, logo openers, colour-bar openers, slideshows with Ken Burns, push/whip/wipe/zoom transitions, lower thirds, highlight plates. Presets write ordinary layers, so everything stays editable.
|
|
18
|
+
- **Media** — video, image and audio layers, volume keyframes, music mixing.
|
|
19
|
+
- **Studio** — a browser preview and After Effects-style timeline editor that stays in sync with agents.
|
|
20
|
+
- **Agent-native** — 23 MCP tools plus a skill that teaches motion-design rules.
|
|
21
|
+
- **No browser, no lock-in** — renders with skia-canvas and FFmpeg. MIT licensed.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
Requires **Node.js 20+** and **FFmpeg** on your PATH (`brew install ffmpeg`, `sudo apt install ffmpeg`, or `winget install ffmpeg`).
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @dnyantra/dtly
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Try it without installing:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx @dnyantra/dtly init hello.json --starter kinetic --title "Hello"
|
|
35
|
+
npx @dnyantra/dtly render hello.json hello.mp4
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Use it from Claude Code
|
|
39
|
+
|
|
40
|
+
Install the plugin (MCP server + skill) in one step:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
/plugin install dtly --marketplace dnyantra/dtly
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or add the pieces yourself:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
claude mcp add --scope user dtly -- npx -y @dnyantra/dtly mcp
|
|
50
|
+
npx @dnyantra/dtly skill install
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then ask for things like *"make a 10 second kinetic typography opener for my bakery"* or
|
|
54
|
+
*"ease the call-to-action in with a spring and move it 0.3 s later"*.
|
|
55
|
+
|
|
56
|
+
## Studio — browser preview and timeline editor
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx @dnyantra/dtly studio project.json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
- **Live preview** with the same renderer as the MP4 export, playback with audio, frame stepping.
|
|
65
|
+
- **Timeline**: drag layer bars to move them, drag the ends to trim, twirl open a layer to see every
|
|
66
|
+
animated property, drag keyframes to retime them, double-click a property row to add a key.
|
|
67
|
+
Everything snaps to frames and to the playhead.
|
|
68
|
+
- **Inspector**: After Effects-style stopwatches (⏱ animates a property, ◆ adds/removes a key at the
|
|
69
|
+
playhead, ◀ ▶ jump between keys), scrubby numbers (drag sideways; Shift ×10, Alt ×0.1), colour
|
|
70
|
+
pickers, text, an ease editor with curve preview (named eases, bezier, springs), raw JSON for the rest.
|
|
71
|
+
- **Viewer**: click to select the layer under the cursor, drag to move it (keyframes it if animated).
|
|
72
|
+
- **Undo/redo**, autosave to the project file, **Render MP4** with progress.
|
|
73
|
+
- **Live with agents**: edits an agent makes through MCP appear instantly; the agent can open the
|
|
74
|
+
studio for you with the `studio_open` tool.
|
|
75
|
+
|
|
76
|
+
| Shortcut | Action |
|
|
77
|
+
|---|---|
|
|
78
|
+
| Space | Play / pause |
|
|
79
|
+
| ← / → (Shift: 10 frames) | Step one frame |
|
|
80
|
+
| Home / End | First / last frame |
|
|
81
|
+
| J / K | Previous / next keyframe of the selected layer |
|
|
82
|
+
| [ / ] | Move layer start to playhead / trim layer end at playhead |
|
|
83
|
+
| ⌘Z / ⇧⌘Z | Undo / redo |
|
|
84
|
+
| ⌘D | Duplicate layer |
|
|
85
|
+
| Delete | Delete selected keyframe (or layer) |
|
|
86
|
+
| ⌘/Ctrl + scroll, + / − | Zoom the timeline |
|
|
87
|
+
|
|
88
|
+
The studio listens on 127.0.0.1 only and its API needs a per-session token.
|
|
89
|
+
|
|
90
|
+
## Command line
|
|
91
|
+
|
|
92
|
+
After `npm install -g @dnyantra/dtly` (or via `npx @dnyantra/dtly …`):
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
dtly init <project.json> [--starter opener|kinetic|bars] [--title "Text"]
|
|
96
|
+
dtly render <project.json> <out.mp4> [--from s] [--to s] [--comp id] [--workers n]
|
|
97
|
+
dtly still <project.json> <time> <out.png> [--scale 0.5]
|
|
98
|
+
dtly sheet <project.json> <out.png> <t1,t2,...>
|
|
99
|
+
dtly studio <project.json> [--port 4400] [--no-open]
|
|
100
|
+
dtly presets
|
|
101
|
+
dtly mcp
|
|
102
|
+
dtly skill install [--dir path]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Library
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import {newProject, addLayer, setKeyframe, PRESETS} from '@dnyantra/dtly';
|
|
109
|
+
import {writeProject, renderVideo} from '@dnyantra/dtly/node';
|
|
110
|
+
|
|
111
|
+
const p = newProject({name: 'Promo', duration: 5, background: '#111'});
|
|
112
|
+
addLayer(p, 'main', {
|
|
113
|
+
type: 'text', id: 'title', text: 'Fresh bread daily', size: 120, color: '#ffffff',
|
|
114
|
+
animators: [{unit: 'word', stagger: 0.1, duration: 0.6, ease: 'backOut', from: {opacity: 0, y: 60}}],
|
|
115
|
+
});
|
|
116
|
+
setKeyframe(p, 'title', 'transform.scale', 0, [90, 90], {spring: {stiffness: 180, damping: 12}});
|
|
117
|
+
setKeyframe(p, 'title', 'transform.scale', 1, [100, 100]);
|
|
118
|
+
PRESETS['element.highlightWord'].apply(p, 'main', {layer: 'title', at: 1});
|
|
119
|
+
|
|
120
|
+
writeProject('promo.json', p);
|
|
121
|
+
await renderVideo('promo.json', 'promo.mp4');
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Entry points: `@dnyantra/dtly` (model, edits, presets, renderer — browser-safe),
|
|
125
|
+
`@dnyantra/dtly/node` (MP4/PNG rendering, project files), `@dnyantra/dtly/mcp` (MCP server).
|
|
126
|
+
Installing the package also gives you the `dtly` command.
|
|
127
|
+
|
|
128
|
+
## The model
|
|
129
|
+
|
|
130
|
+
| After Effects | DT.ly |
|
|
131
|
+
|---|---|
|
|
132
|
+
| Composition / precomp | `comps[]`, layer `type: "precomp"` |
|
|
133
|
+
| Layer in/out | `inPoint`, `outPoint` (seconds) |
|
|
134
|
+
| Transform | `transform.anchor/position/scale(%)/rotation(°)/opacity(%)/skew` |
|
|
135
|
+
| Keyframes + easing | `{keyframes: [{t, v, ease}]}` — `easyEase`, `expoOut`, `backOut`, `[x1,y1,x2,y2]`, `{spring: {...}}`, `hold` |
|
|
136
|
+
| `wiggle()` | `{keyframes, wiggle: {freq, amp}}` |
|
|
137
|
+
| Parenting / null | `parent: id`, `type: "null"` |
|
|
138
|
+
| Masks / track mattes | `masks: [...]`, `matte: {layer, mode}` |
|
|
139
|
+
| Trim paths | shape `trim: {start, end}` |
|
|
140
|
+
| Text animators | `animators: [{unit, stagger, duration, ease, from: {...}, clip, mode}]` |
|
|
141
|
+
| Effects | `blur`, `dropShadow`, `glow`, `fill`, `brightness`, `saturate`, `contrast` |
|
|
142
|
+
| Motion blur | `motionBlur: {samples, shutter}` |
|
|
143
|
+
|
|
144
|
+
Layer index 0 is the top of the stack, as in After Effects. See
|
|
145
|
+
[`plugin/skills/dtly/SKILL.md`](plugin/skills/dtly/SKILL.md) for the full guide.
|
|
146
|
+
|
|
147
|
+
## Development
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
git clone https://github.com/dnyantra/dtly && cd dtly
|
|
151
|
+
npm install # also builds dist/
|
|
152
|
+
npm test # typecheck + end-to-end smoke test (renders + MCP round trip)
|
|
153
|
+
npm run test:studio # drives the Studio in your installed Chrome (puppeteer-core)
|
|
154
|
+
npm run dev -- render examples/kinetic.json out.mp4
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Opening Claude Code in the repo loads the local MCP server (`.mcp.json`) and the skill.
|
|
158
|
+
|
|
159
|
+
## Roadmap
|
|
160
|
+
|
|
161
|
+
- Studio: graph editor, drag-to-reorder layers, multi-select, media import by drag and drop
|
|
162
|
+
- Faster rendering: layer-bounds buffers, caching finished layers
|
|
163
|
+
- Templates with brand kits and media slots for fixed 30/60 s videos
|
|
164
|
+
- More AE features: 3D layers and camera, repeaters, path morphing, LUTs
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT for the code. Bundled fonts (Baloo 2, Mukta) are under the SIL Open Font License 1.1.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
DT.ly is made by the creator of [CustomerPro.in](https://customerpro.in) — WhatsApp marketing,
|
|
173
|
+
campaigns and AI agents for small businesses.
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { listPresets } from './presets/index.js';
|
|
7
|
+
import { renderContactSheet, renderStill, renderVideo, renderVideoParallel } from './render/export.js';
|
|
8
|
+
import { writeProject } from './ops/store.js';
|
|
9
|
+
import { STARTERS } from './starter.js';
|
|
10
|
+
import { BRAND, VERSION } from './version.js';
|
|
11
|
+
const [cmd, ...rest] = process.argv.slice(2);
|
|
12
|
+
const usage = `${BRAND} v${VERSION}
|
|
13
|
+
After Effects-style motion graphics as JSON, rendered to MP4.
|
|
14
|
+
|
|
15
|
+
dtly init <project.json> [--starter opener|kinetic|bars] [--title "Text"]
|
|
16
|
+
dtly render <project.json> <out.mp4> [--from s] [--to s] [--comp id] [--workers n]
|
|
17
|
+
dtly still <project.json> <time> <out.png> [--scale 0.5] [--comp id]
|
|
18
|
+
dtly sheet <project.json> <out.png> <t1,t2,...> [--comp id]
|
|
19
|
+
dtly presets list text animators, openers, slides, transitions
|
|
20
|
+
dtly studio <project.json> [--port 4400] [--no-open] browser preview + timeline editor
|
|
21
|
+
dtly mcp run the MCP server (stdio) for AI agents
|
|
22
|
+
dtly skill install [--dir d] copy the agent skill into ~/.claude/skills
|
|
23
|
+
|
|
24
|
+
Docs: https://github.com/dnyantra/dtly`;
|
|
25
|
+
const flag = (name) => { const i = rest.indexOf(`--${name}`); return i >= 0 ? rest[i + 1] : undefined; };
|
|
26
|
+
const num = (s) => (s === undefined ? undefined : Number(s));
|
|
27
|
+
const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
28
|
+
try {
|
|
29
|
+
if (cmd === 'render' && rest[1]) {
|
|
30
|
+
const t0 = Date.now();
|
|
31
|
+
const r = await renderVideoParallel(rest[0], rest[1], {
|
|
32
|
+
from: num(flag('from')), to: num(flag('to')), comp: flag('comp'), workers: num(flag('workers')),
|
|
33
|
+
onProgress: (d, n) => { if (d % 30 === 0 || d === n)
|
|
34
|
+
process.stderr.write(`\r${d}/${n} frames`); },
|
|
35
|
+
});
|
|
36
|
+
console.error(`\nRendered ${r.out}: ${r.frames} frames, ${r.audioTracks} audio tracks in ${((Date.now() - t0) / 1000).toFixed(1)}s`);
|
|
37
|
+
}
|
|
38
|
+
else if (cmd === 'chunk') {
|
|
39
|
+
// Internal: one parallel-render worker. Reports progress to the parent over IPC.
|
|
40
|
+
const [project, out, from, to, comp, crf] = rest;
|
|
41
|
+
await renderVideo(project, out, { from: Number(from), to: Number(to), comp: comp || undefined, crf: Number(crf), audio: false, onProgress: (d) => process.send?.({ done: d }) });
|
|
42
|
+
}
|
|
43
|
+
else if (cmd === 'still' && rest[2]) {
|
|
44
|
+
console.log(await renderStill(rest[0], Number(rest[1]), rest[2], { scale: num(flag('scale')), comp: flag('comp') }));
|
|
45
|
+
}
|
|
46
|
+
else if (cmd === 'sheet' && rest[2]) {
|
|
47
|
+
console.log(await renderContactSheet(rest[0], rest[2].split(',').map(Number), rest[1], { comp: flag('comp') }));
|
|
48
|
+
}
|
|
49
|
+
else if (cmd === 'init' && rest[0]) {
|
|
50
|
+
const name = flag('starter') ?? 'opener';
|
|
51
|
+
const starter = STARTERS[name];
|
|
52
|
+
if (!starter)
|
|
53
|
+
throw new Error(`Unknown starter "${name}". Options: ${Object.keys(STARTERS).join(', ')}`);
|
|
54
|
+
if (fs.existsSync(rest[0]))
|
|
55
|
+
throw new Error(`${rest[0]} already exists`);
|
|
56
|
+
writeProject(rest[0], starter.build(flag('title') ?? 'DT.ly'));
|
|
57
|
+
console.log(`Created ${rest[0]} (${starter.description})\nNext: dtly render ${rest[0]} ${rest[0].replace(/\.json$/, '')}.mp4`);
|
|
58
|
+
}
|
|
59
|
+
else if (cmd === 'presets') {
|
|
60
|
+
console.log(listPresets());
|
|
61
|
+
}
|
|
62
|
+
else if (cmd === 'studio' && rest[0]) {
|
|
63
|
+
const { startStudio } = await import('./studio/server.js');
|
|
64
|
+
const { url } = await startStudio({ project: rest[0], port: num(flag('port')) });
|
|
65
|
+
console.log(`${BRAND}\nStudio for ${rest[0]} → ${url}\nEdits save to the file; changes made by agents or other tools appear live. Ctrl+C to stop.`);
|
|
66
|
+
if (!rest.includes('--no-open')) {
|
|
67
|
+
const { spawn } = await import('node:child_process');
|
|
68
|
+
const opener = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'explorer' : 'xdg-open';
|
|
69
|
+
spawn(opener, [url], { stdio: 'ignore', detached: true }).unref();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else if (cmd === 'mcp') {
|
|
73
|
+
const { startMcpServer } = await import('./mcp/server.js');
|
|
74
|
+
await startMcpServer();
|
|
75
|
+
}
|
|
76
|
+
else if (cmd === 'skill' && rest[0] === 'install') {
|
|
77
|
+
const base = flag('dir') ?? path.join(process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), '.claude'), 'skills');
|
|
78
|
+
const dest = path.join(base, 'dtly');
|
|
79
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
80
|
+
fs.cpSync(path.join(pkgRoot, 'plugin/skills/dtly'), dest, { recursive: true });
|
|
81
|
+
console.log(`Installed the DT.ly skill to ${dest}`);
|
|
82
|
+
}
|
|
83
|
+
else if (cmd === '--version' || cmd === '-v' || cmd === 'version') {
|
|
84
|
+
console.log(VERSION);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
console.log(usage);
|
|
88
|
+
process.exit(cmd && cmd !== 'help' && cmd !== '--help' ? 1 : 0);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
console.error(`dtly: ${e.message}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { applyEase } from './ease.js';
|
|
2
|
+
import { parseColor, rgbaString } from './color.js';
|
|
3
|
+
import { isAnimated } from './model.js';
|
|
4
|
+
const lerp = (a, b, p) => a + (b - a) * p;
|
|
5
|
+
const interpolate = (a, b, p) => {
|
|
6
|
+
if (typeof a === 'number' && typeof b === 'number')
|
|
7
|
+
return lerp(a, b, p);
|
|
8
|
+
if (Array.isArray(a) && Array.isArray(b))
|
|
9
|
+
return a.map((v, i) => lerp(v, b[i] ?? v, p));
|
|
10
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
11
|
+
const ca = parseColor(a), cb = parseColor(b);
|
|
12
|
+
if (ca && cb)
|
|
13
|
+
return rgbaString(ca.map((v, i) => lerp(v, cb[i], p)));
|
|
14
|
+
}
|
|
15
|
+
return p < 1 ? a : b;
|
|
16
|
+
};
|
|
17
|
+
// Smooth 1D value noise for wiggle(); deterministic per seed so renders are repeatable.
|
|
18
|
+
const hash = (n) => {
|
|
19
|
+
const x = Math.sin(n * 127.1 + 311.7) * 43758.5453;
|
|
20
|
+
return x - Math.floor(x);
|
|
21
|
+
};
|
|
22
|
+
const noise = (x, seed) => {
|
|
23
|
+
const i = Math.floor(x), f = x - i;
|
|
24
|
+
const u = f * f * (3 - 2 * f);
|
|
25
|
+
return lerp(hash(i + seed * 1000) * 2 - 1, hash(i + 1 + seed * 1000) * 2 - 1, u);
|
|
26
|
+
};
|
|
27
|
+
const wiggle = (value, t, w) => {
|
|
28
|
+
const off = (dim) => noise(t * w.freq, (w.seed ?? 1) + dim * 17.3) * w.amp;
|
|
29
|
+
if (typeof value === 'number')
|
|
30
|
+
return value + off(0);
|
|
31
|
+
if (Array.isArray(value))
|
|
32
|
+
return value.map((v, i) => v + off(i));
|
|
33
|
+
return value;
|
|
34
|
+
};
|
|
35
|
+
export const evalKeyframes = (kfs, t) => {
|
|
36
|
+
if (kfs.length === 0)
|
|
37
|
+
throw new Error('empty keyframes');
|
|
38
|
+
if (t <= kfs[0].t)
|
|
39
|
+
return kfs[0].v;
|
|
40
|
+
const last = kfs[kfs.length - 1];
|
|
41
|
+
if (t >= last.t)
|
|
42
|
+
return last.v;
|
|
43
|
+
let i = 0;
|
|
44
|
+
while (i < kfs.length - 2 && t >= kfs[i + 1].t)
|
|
45
|
+
i++;
|
|
46
|
+
const a = kfs[i], b = kfs[i + 1];
|
|
47
|
+
const seg = b.t - a.t;
|
|
48
|
+
const p = applyEase(a.ease, seg <= 0 ? 1 : (t - a.t) / seg, seg);
|
|
49
|
+
return interpolate(a.v, b.v, p);
|
|
50
|
+
};
|
|
51
|
+
// Evaluate any property at time t (seconds, in the layer's composition time).
|
|
52
|
+
export function val(p, t, fallback) {
|
|
53
|
+
if (p === undefined || p === null)
|
|
54
|
+
return fallback;
|
|
55
|
+
if (!isAnimated(p))
|
|
56
|
+
return p;
|
|
57
|
+
const sorted = [...p.keyframes].sort((a, b) => a.t - b.t);
|
|
58
|
+
const v = evalKeyframes(sorted, t);
|
|
59
|
+
return (p.wiggle ? wiggle(v, t, p.wiggle) : v);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=anim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anim.js","sourceRoot":"","sources":["../../src/core/anim.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const NAMED = {
|
|
2
|
+
white: '#ffffff', black: '#000000', red: '#ff0000', green: '#008000', blue: '#0000ff',
|
|
3
|
+
yellow: '#ffff00', orange: '#ffa500', transparent: '#00000000', gray: '#808080', grey: '#808080',
|
|
4
|
+
};
|
|
5
|
+
export const parseColor = (c) => {
|
|
6
|
+
const s = (NAMED[c.trim().toLowerCase()] ?? c).trim();
|
|
7
|
+
if (s.startsWith('#')) {
|
|
8
|
+
let h = s.slice(1);
|
|
9
|
+
if (h.length === 3 || h.length === 4)
|
|
10
|
+
h = [...h].map((ch) => ch + ch).join('');
|
|
11
|
+
if (h.length !== 6 && h.length !== 8)
|
|
12
|
+
return null;
|
|
13
|
+
const n = (i) => parseInt(h.slice(i, i + 2), 16);
|
|
14
|
+
return [n(0), n(2), n(4), h.length === 8 ? n(6) / 255 : 1];
|
|
15
|
+
}
|
|
16
|
+
const m = s.match(/^rgba?\(([^)]+)\)$/i);
|
|
17
|
+
if (m) {
|
|
18
|
+
const p = m[1].split(/[\s,\/]+/).filter(Boolean).map(Number);
|
|
19
|
+
return [p[0], p[1], p[2], p[3] ?? 1];
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
export const rgbaString = ([r, g, b, a]) => `rgba(${Math.round(r)},${Math.round(g)},${Math.round(b)},${Math.max(0, Math.min(1, a)).toFixed(4)})`;
|
|
24
|
+
export const withAlpha = (c, alpha) => {
|
|
25
|
+
const p = parseColor(c);
|
|
26
|
+
return p ? rgbaString([p[0], p[1], p[2], p[3] * alpha]) : c;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","sourceRoot":"","sources":["../../src/core/color.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Ease } from './model.js';
|
|
2
|
+
export declare const spring: (elapsed: number, { stiffness, damping, mass }?: {
|
|
3
|
+
damping?: number | undefined;
|
|
4
|
+
mass?: number | undefined;
|
|
5
|
+
stiffness?: number | undefined;
|
|
6
|
+
}) => number;
|
|
7
|
+
export declare const applyEase: (ease: Ease | undefined, x: number, segSeconds?: number) => number;
|
|
8
|
+
export declare const EASE_NAMES: string[];
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Cubic-bezier solver (same curve definition as CSS / AE's speed graph handles).
|
|
2
|
+
const bezier = (x1, y1, x2, y2) => {
|
|
3
|
+
const cx = 3 * x1, bx = 3 * (x2 - x1) - cx, ax = 1 - cx - bx;
|
|
4
|
+
const cy = 3 * y1, by = 3 * (y2 - y1) - cy, ay = 1 - cy - by;
|
|
5
|
+
const sx = (t) => ((ax * t + bx) * t + cx) * t;
|
|
6
|
+
const sy = (t) => ((ay * t + by) * t + cy) * t;
|
|
7
|
+
const dx = (t) => (3 * ax * t + 2 * bx) * t + cx;
|
|
8
|
+
return (x) => {
|
|
9
|
+
let t = x;
|
|
10
|
+
for (let i = 0; i < 8; i++) {
|
|
11
|
+
const e = sx(t) - x;
|
|
12
|
+
if (Math.abs(e) < 1e-6)
|
|
13
|
+
return sy(t);
|
|
14
|
+
const d = dx(t);
|
|
15
|
+
if (Math.abs(d) < 1e-6)
|
|
16
|
+
break;
|
|
17
|
+
t -= e / d;
|
|
18
|
+
}
|
|
19
|
+
let lo = 0, hi = 1;
|
|
20
|
+
t = x;
|
|
21
|
+
for (let i = 0; i < 40; i++) {
|
|
22
|
+
const v = sx(t);
|
|
23
|
+
if (Math.abs(v - x) < 1e-6)
|
|
24
|
+
break;
|
|
25
|
+
if (v < x)
|
|
26
|
+
lo = t;
|
|
27
|
+
else
|
|
28
|
+
hi = t;
|
|
29
|
+
t = (lo + hi) / 2;
|
|
30
|
+
}
|
|
31
|
+
return sy(t);
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
const CURVES = {
|
|
35
|
+
easeIn: [0.42, 0, 1, 1],
|
|
36
|
+
easeOut: [0, 0, 0.58, 1],
|
|
37
|
+
easyEase: [0.333, 0, 0.667, 1], // AE "Easy Ease" (33% influence both sides)
|
|
38
|
+
quadOut: [0.25, 0.46, 0.45, 0.94],
|
|
39
|
+
cubicOut: [0.215, 0.61, 0.355, 1],
|
|
40
|
+
expoIn: [0.95, 0.05, 0.795, 0.035],
|
|
41
|
+
expoOut: [0.19, 1, 0.22, 1],
|
|
42
|
+
expoInOut: [1, 0, 0, 1],
|
|
43
|
+
backOut: [0.175, 0.885, 0.32, 1.275],
|
|
44
|
+
backIn: [0.6, -0.28, 0.735, 0.045],
|
|
45
|
+
};
|
|
46
|
+
const cache = new Map();
|
|
47
|
+
const elasticOut = (x) => x === 0 || x === 1 ? x : Math.pow(2, -10 * x) * Math.sin((x * 10 - 0.75) * ((2 * Math.PI) / 3)) + 1;
|
|
48
|
+
const bounceOut = (x) => {
|
|
49
|
+
const n = 7.5625, d = 2.75;
|
|
50
|
+
if (x < 1 / d)
|
|
51
|
+
return n * x * x;
|
|
52
|
+
if (x < 2 / d)
|
|
53
|
+
return n * (x -= 1.5 / d) * x + 0.75;
|
|
54
|
+
if (x < 2.5 / d)
|
|
55
|
+
return n * (x -= 2.25 / d) * x + 0.9375;
|
|
56
|
+
return n * (x -= 2.625 / d) * x + 0.984375;
|
|
57
|
+
};
|
|
58
|
+
// Damped spring from 0 to 1; `elapsed` in seconds so the motion is physical, not stretched.
|
|
59
|
+
export const spring = (elapsed, { stiffness = 170, damping = 18, mass = 1 } = {}) => {
|
|
60
|
+
const w0 = Math.sqrt(stiffness / mass);
|
|
61
|
+
const zeta = damping / (2 * Math.sqrt(stiffness * mass));
|
|
62
|
+
if (zeta < 1) {
|
|
63
|
+
const wd = w0 * Math.sqrt(1 - zeta * zeta);
|
|
64
|
+
return 1 - Math.exp(-zeta * w0 * elapsed) * (Math.cos(wd * elapsed) + ((zeta * w0) / wd) * Math.sin(wd * elapsed));
|
|
65
|
+
}
|
|
66
|
+
return 1 - Math.exp(-w0 * elapsed) * (1 + w0 * elapsed);
|
|
67
|
+
};
|
|
68
|
+
// Progress 0..1 (may overshoot) for a segment, given linear progress x and segment length in seconds.
|
|
69
|
+
export const applyEase = (ease, x, segSeconds = 1) => {
|
|
70
|
+
if (!ease || ease === 'linear')
|
|
71
|
+
return x;
|
|
72
|
+
if (ease === 'hold')
|
|
73
|
+
return x >= 1 ? 1 : 0;
|
|
74
|
+
if (ease === 'elasticOut')
|
|
75
|
+
return elasticOut(x);
|
|
76
|
+
if (ease === 'bounceOut')
|
|
77
|
+
return bounceOut(x);
|
|
78
|
+
if (typeof ease === 'object' && !Array.isArray(ease))
|
|
79
|
+
return x >= 1 ? 1 : spring(x * segSeconds, ease.spring);
|
|
80
|
+
const pts = Array.isArray(ease) ? ease : CURVES[ease];
|
|
81
|
+
if (!pts)
|
|
82
|
+
return x;
|
|
83
|
+
const key = pts.join(',');
|
|
84
|
+
let fn = cache.get(key);
|
|
85
|
+
if (!fn)
|
|
86
|
+
cache.set(key, (fn = bezier(...pts)));
|
|
87
|
+
return fn(x);
|
|
88
|
+
};
|
|
89
|
+
export const EASE_NAMES = ['linear', 'hold', ...Object.keys(CURVES), 'elasticOut', 'bounceOut'];
|
|
90
|
+
//# sourceMappingURL=ease.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ease.js","sourceRoot":"","sources":["../../src/core/ease.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAE;IAChE,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAC7D,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAC7D,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;IACzD,OAAO,CAAC,CAAS,EAAE,EAAE;QACnB,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACpB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI;gBAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAChB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI;gBAAE,MAAM;YAC9B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,CAAC;QACD,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACnB,CAAC,GAAG,CAAC,CAAC;QACN,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAChB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI;gBAAE,MAAM;YAClC,IAAI,CAAC,GAAG,CAAC;gBAAE,EAAE,GAAG,CAAC,CAAC;;gBAAM,EAAE,GAAG,CAAC,CAAC;YAC/B,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACf,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,MAAM,GAAqD;IAC/D,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,4CAA4C;IAC5E,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;IACjC,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACjC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC;IAClC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3B,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;IACpC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC;CACnC,CAAC;AAEF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiC,CAAC;AAEvD,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAC/B,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACtG,MAAM,SAAS,GAAG,CAAC,CAAS,EAAE,EAAE;IAC9B,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACpD,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;AAC7C,CAAC,CAAC;AAEF,4FAA4F;AAC5F,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,EAAC,SAAS,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,IAAI,GAAG,CAAC,EAAC,GAAG,EAAE,EAAE,EAAE;IACxF,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC;IACzD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IACrH,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF,sGAAsG;AACtG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAsB,EAAE,CAAS,EAAE,UAAU,GAAG,CAAC,EAAU,EAAE;IACrF,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACzC,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAChD,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9G,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtD,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,CAAC;IACnB,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/C,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC"}
|