kasaframe 0.1.3 → 0.1.5
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/NOTICE +298 -0
- package/README.md +16 -3
- package/docs/AGENTS.md +1 -1
- package/package.json +1 -1
- package/packages/adapters/src/project.ts +4 -0
- package/packages/adapters/src/texture.ts +94 -0
- package/packages/cli/src/cells.ts +227 -0
- package/packages/cli/src/commands/doctor.ts +15 -2
- package/packages/cli/src/commands/fonts.ts +118 -0
- package/packages/cli/src/commands/make.ts +77 -9
- package/packages/cli/src/commands/new.ts +2 -2
- package/packages/cli/src/commands/theme.ts +141 -10
- package/packages/cli/src/commands/update.ts +66 -0
- package/packages/cli/src/fonts.ts +405 -0
- package/packages/cli/src/kf.ts +5 -0
- package/packages/cli/src/lock.ts +8 -6
- package/packages/cli/src/pick.ts +110 -0
- package/packages/cli/src/update.ts +250 -0
- package/packages/cli/src/vary.ts +124 -0
- package/packages/core/src/index.ts +1 -1
- package/packages/core/src/project.ts +15 -0
- package/packages/director/src/assemble.ts +6 -3
- package/packages/motion/src/moves/menu.ts +2 -1
- package/packages/patterns/src/kit.ts +3 -2
- package/packages/plan/src/asks.ts +25 -16
- package/packages/plan/src/index.ts +2 -2
- package/packages/plan/src/plan.ts +4 -2
- package/packages/plan/src/themes.ts +71 -9
- package/packages/plan/src/types.ts +3 -0
- package/packages/themes/kit/THEME-MAKE.md +2 -1
- package/packages/themes/kit/fonts/display.json +3517 -0
- package/packages/themes/kit/fonts/sans.json +5155 -0
- package/packages/themes/kit/fonts/serif.json +5229 -0
- package/packages/themes/kit/fonts.json +907 -0
- package/packages/themes/package.json +8 -1
- package/packages/themes/src/color.ts +152 -0
- package/packages/themes/src/fontfile.ts +183 -0
- package/packages/themes/src/fonts.ts +296 -0
- package/packages/themes/src/fx.ts +4 -2
- package/packages/themes/src/index.ts +75 -3
- package/packages/themes/src/look.ts +249 -0
- package/packages/themes/src/name.ts +9 -0
- package/packages/themes/src/palette.ts +194 -0
- package/packages/themes/src/slotkit.ts +14 -1
- package/packages/themes/src/slots.ts +17 -2
- package/packages/themes/src/types.ts +89 -0
- package/packages/themes/src/vary.ts +291 -0
- package/presets/kawaii-pastel.json +2 -2
- package/skills/kasaframe/SKILL.md +1 -0
- package/themes/blueprint/THEME.md +64 -0
- package/themes/blueprint/effects.ts +570 -0
- package/themes/blueprint/sample/beats.json +1005 -0
- package/themes/blueprint/sample/index.html +11 -0
- package/themes/blueprint/sample/kf.json +59 -0
- package/themes/blueprint/sample/lib/facts.ts +29 -0
- package/themes/blueprint/sample/lib/sheet.ts +55 -0
- package/themes/blueprint/sample/main.ts +9 -0
- package/themes/blueprint/sample/scenes/end.ts +91 -0
- package/themes/blueprint/sample/scenes/gather.ts +75 -0
- package/themes/blueprint/sample/scenes/models.ts +117 -0
- package/themes/blueprint/sample/scenes/price.ts +94 -0
- package/themes/blueprint/sample/style.json +114 -0
- package/themes/blueprint/slots.ts +88 -0
- package/themes/blueprint/still.png +0 -0
- package/themes/blueprint/style.json +114 -0
- package/themes/blueprint/theme.json +139 -0
- package/themes/blueprint/variants/deep-rose-2.json +90 -0
- package/themes/blueprint/variants/deep-rose-suit.json +117 -0
- package/themes/blueprint/variants/deep-rose.json +117 -0
- package/themes/blueprint/variants/navy-coral-2.json +118 -0
- package/themes/blueprint/variants/navy-coral-suit.json +118 -0
- package/themes/blueprint/variants/navy-coral.json +128 -0
- package/themes/blueprint/variants/navy-orange-2.json +118 -0
- package/themes/blueprint/variants/navy-orange-3.json +91 -0
- package/themes/blueprint/variants/navy-orange-4.json +128 -0
- package/themes/blueprint/variants/navy-orange-mono.json +128 -0
- package/themes/blueprint/variants/navy-orange-plex.json +128 -0
- package/themes/blueprint/variants/navy-orange-suit.json +118 -0
- package/themes/blueprint/variants/navy-orange.json +118 -0
- package/themes/blueprint/variants/navy-rose-plex.json +127 -0
- package/themes/blueprint/variants/navy-rose.json +127 -0
- package/themes/cartography/THEME.md +61 -0
- package/themes/cartography/effects.ts +845 -0
- package/themes/cartography/sample/assets/og/logo.svg +12 -0
- package/themes/cartography/sample/beats.json +1005 -0
- package/themes/cartography/sample/index.html +11 -0
- package/themes/cartography/sample/kf.json +59 -0
- package/themes/cartography/sample/lib/facts.ts +29 -0
- package/themes/cartography/sample/lib/map.ts +39 -0
- package/themes/cartography/sample/main.ts +9 -0
- package/themes/cartography/sample/scenes/end.ts +56 -0
- package/themes/cartography/sample/scenes/gather.ts +46 -0
- package/themes/cartography/sample/scenes/models.ts +43 -0
- package/themes/cartography/sample/scenes/price.ts +73 -0
- package/themes/cartography/sample/style.json +103 -0
- package/themes/cartography/slots.ts +87 -0
- package/themes/cartography/still.png +0 -0
- package/themes/cartography/style.json +103 -0
- package/themes/cartography/theme.json +162 -0
- package/themes/cartography/variants/blush-amber.json +128 -0
- package/themes/cartography/variants/blush-indigo.json +128 -0
- package/themes/cartography/variants/blush-pink.json +136 -0
- package/themes/cartography/variants/chalk-plum.json +137 -0
- package/themes/cartography/variants/chalk-sky.json +100 -0
- package/themes/cartography/variants/cocoa-amber.json +128 -0
- package/themes/cartography/variants/deep-plum.json +125 -0
- package/themes/cartography/variants/dusk-coral.json +128 -0
- package/themes/cartography/variants/forest-lime.json +131 -0
- package/themes/cartography/variants/frost-teal.json +128 -0
- package/themes/cartography/variants/navy-green.json +131 -0
- package/themes/cartography/variants/navy-indigo.json +138 -0
- package/themes/cartography/variants/navy-sky.json +100 -0
- package/themes/cartography/variants/sage-green.json +127 -0
- package/themes/cartography/variants/wine-teal.json +128 -0
- package/themes/circuit-board/THEME.md +61 -0
- package/themes/circuit-board/effects.ts +576 -0
- package/themes/circuit-board/pcb.ts +103 -0
- package/themes/circuit-board/sample/assets/og/logo.svg +12 -0
- package/themes/circuit-board/sample/beats.json +1005 -0
- package/themes/circuit-board/sample/index.html +11 -0
- package/themes/circuit-board/sample/kf.json +59 -0
- package/themes/circuit-board/sample/lib/facts.ts +29 -0
- package/themes/circuit-board/sample/lib/kit.ts +45 -0
- package/themes/circuit-board/sample/main.ts +9 -0
- package/themes/circuit-board/sample/scenes/end.ts +102 -0
- package/themes/circuit-board/sample/scenes/gather.ts +76 -0
- package/themes/circuit-board/sample/scenes/models.ts +101 -0
- package/themes/circuit-board/sample/scenes/price.ts +109 -0
- package/themes/circuit-board/sample/style.json +104 -0
- package/themes/circuit-board/slots.ts +108 -0
- package/themes/circuit-board/still.png +0 -0
- package/themes/circuit-board/style.json +104 -0
- package/themes/circuit-board/theme.json +151 -0
- package/themes/circuit-board/variants/deep-gold-plex.json +133 -0
- package/themes/circuit-board/variants/deep-gold.json +123 -0
- package/themes/circuit-board/variants/dusk-gold-grain.json +138 -0
- package/themes/circuit-board/variants/dusk-gold-pretendard.json +118 -0
- package/themes/circuit-board/variants/dusk-gold.json +97 -0
- package/themes/circuit-board/variants/forest-gold-2.json +96 -0
- package/themes/circuit-board/variants/forest-gold-grain.json +129 -0
- package/themes/circuit-board/variants/forest-gold-mono.json +124 -0
- package/themes/circuit-board/variants/forest-gold.json +128 -0
- package/themes/circuit-board/variants/navy-gold-grain.json +124 -0
- package/themes/circuit-board/variants/navy-gold.json +101 -0
- package/themes/circuit-board/variants/wine-gold-grain.json +128 -0
- package/themes/circuit-board/variants/wine-gold-plex.json +133 -0
- package/themes/circuit-board/variants/wine-gold-pretendard.json +118 -0
- package/themes/circuit-board/variants/wine-gold.json +128 -0
- package/themes/clay-toy/THEME.md +73 -0
- package/themes/clay-toy/effects.ts +643 -0
- package/themes/clay-toy/glyphs.ts +32 -0
- package/themes/clay-toy/sample/assets/og/logo.svg +12 -0
- package/themes/clay-toy/sample/beats.json +1005 -0
- package/themes/clay-toy/sample/index.html +11 -0
- package/themes/clay-toy/sample/kf.json +59 -0
- package/themes/clay-toy/sample/lib/clay.ts +20 -0
- package/themes/clay-toy/sample/lib/facts.ts +29 -0
- package/themes/clay-toy/sample/main.ts +9 -0
- package/themes/clay-toy/sample/scenes/end.ts +81 -0
- package/themes/clay-toy/sample/scenes/gather.ts +53 -0
- package/themes/clay-toy/sample/scenes/models.ts +77 -0
- package/themes/clay-toy/sample/scenes/price.ts +91 -0
- package/themes/clay-toy/sample/style.json +101 -0
- package/themes/clay-toy/slots.ts +132 -0
- package/themes/clay-toy/still.png +0 -0
- package/themes/clay-toy/style.json +101 -0
- package/themes/clay-toy/theme.json +148 -0
- package/themes/clay-toy/variants/blush-coral-grain.json +126 -0
- package/themes/clay-toy/variants/blush-coral.json +123 -0
- package/themes/clay-toy/variants/chalk-indigo.json +97 -0
- package/themes/clay-toy/variants/chalk-jade.json +125 -0
- package/themes/clay-toy/variants/chalk-teal.json +120 -0
- package/themes/clay-toy/variants/frost-orange.json +125 -0
- package/themes/clay-toy/variants/frost-sky-grain.json +126 -0
- package/themes/clay-toy/variants/frost-sky.json +121 -0
- package/themes/clay-toy/variants/frost-teal.json +120 -0
- package/themes/clay-toy/variants/lilac-green.json +120 -0
- package/themes/clay-toy/variants/lilac-plum-round.json +120 -0
- package/themes/clay-toy/variants/lilac-plum.json +124 -0
- package/themes/clay-toy/variants/sage-indigo.json +125 -0
- package/themes/clay-toy/variants/sage-magenta.json +119 -0
- package/themes/clay-toy/variants/sand-amber.json +125 -0
- package/themes/conveyor-factory/THEME.md +71 -0
- package/themes/conveyor-factory/effects.ts +744 -0
- package/themes/conveyor-factory/sample/assets/og/logo.svg +12 -0
- package/themes/conveyor-factory/sample/beats.json +1005 -0
- package/themes/conveyor-factory/sample/index.html +11 -0
- package/themes/conveyor-factory/sample/kf.json +59 -0
- package/themes/conveyor-factory/sample/lib/factory.ts +48 -0
- package/themes/conveyor-factory/sample/lib/facts.ts +29 -0
- package/themes/conveyor-factory/sample/main.ts +9 -0
- package/themes/conveyor-factory/sample/scenes/end.ts +44 -0
- package/themes/conveyor-factory/sample/scenes/gather.ts +47 -0
- package/themes/conveyor-factory/sample/scenes/models.ts +91 -0
- package/themes/conveyor-factory/sample/scenes/price.ts +77 -0
- package/themes/conveyor-factory/sample/style.json +107 -0
- package/themes/conveyor-factory/slots.ts +121 -0
- package/themes/conveyor-factory/still.png +0 -0
- package/themes/conveyor-factory/style.json +107 -0
- package/themes/conveyor-factory/theme.json +144 -0
- package/themes/conveyor-factory/variants/cocoa-gold.json +125 -0
- package/themes/conveyor-factory/variants/dusk-gold.json +135 -0
- package/themes/conveyor-factory/variants/forest-gold.json +135 -0
- package/themes/conveyor-factory/variants/navy-amber.json +93 -0
- package/themes/conveyor-factory/variants/navy-gold.json +120 -0
- package/themes/conveyor-factory/variants/slate-amber-2.json +120 -0
- package/themes/conveyor-factory/variants/slate-amber-grain.json +125 -0
- package/themes/conveyor-factory/variants/slate-amber-suit.json +120 -0
- package/themes/conveyor-factory/variants/slate-amber.json +125 -0
- package/themes/conveyor-factory/variants/slate-gold-bold.json +120 -0
- package/themes/conveyor-factory/variants/slate-gold.json +120 -0
- package/themes/data-journal/THEME.md +74 -0
- package/themes/data-journal/effects.ts +570 -0
- package/themes/data-journal/sample/assets/og/logo.svg +12 -0
- package/themes/data-journal/sample/beats.json +1005 -0
- package/themes/data-journal/sample/index.html +11 -0
- package/themes/data-journal/sample/kf.json +59 -0
- package/themes/data-journal/sample/lib/facts.ts +29 -0
- package/themes/data-journal/sample/lib/page.ts +25 -0
- package/themes/data-journal/sample/main.ts +9 -0
- package/themes/data-journal/sample/scenes/end.ts +69 -0
- package/themes/data-journal/sample/scenes/gather.ts +58 -0
- package/themes/data-journal/sample/scenes/models.ts +51 -0
- package/themes/data-journal/sample/scenes/price.ts +73 -0
- package/themes/data-journal/sample/style.json +114 -0
- package/themes/data-journal/slots.ts +119 -0
- package/themes/data-journal/still.png +0 -0
- package/themes/data-journal/style.json +114 -0
- package/themes/data-journal/theme.json +142 -0
- package/themes/data-journal/variants/blush-green.json +129 -0
- package/themes/data-journal/variants/chalk-magenta.json +138 -0
- package/themes/data-journal/variants/cocoa-amber.json +140 -0
- package/themes/data-journal/variants/cocoa-sky.json +130 -0
- package/themes/data-journal/variants/deep-coral.json +135 -0
- package/themes/data-journal/variants/dusk-plum.json +132 -0
- package/themes/data-journal/variants/forest-green.json +138 -0
- package/themes/data-journal/variants/frost-indigo.json +141 -0
- package/themes/data-journal/variants/lilac-amber.json +141 -0
- package/themes/data-journal/variants/navy-indigo.json +131 -0
- package/themes/data-journal/variants/navy-lime.json +128 -0
- package/themes/data-journal/variants/snow-sky.json +125 -0
- package/themes/data-journal/variants/wine-indigo.json +129 -0
- package/themes/data-journal/variants/wine-magenta.json +138 -0
- package/themes/data-journal/variants/wine-teal.json +97 -0
- package/themes/debug-hud/sample/style.json +1 -1
- package/themes/debug-hud/style.json +1 -1
- package/themes/debug-hud/theme.json +57 -0
- package/themes/debug-hud/variants/cocoa-gold.json +113 -0
- package/themes/debug-hud/variants/cocoa-teal.json +119 -0
- package/themes/debug-hud/variants/deep-cyan.json +85 -0
- package/themes/debug-hud/variants/deep-teal-scan.json +118 -0
- package/themes/debug-hud/variants/deep-teal.json +112 -0
- package/themes/debug-hud/variants/dusk-plum.json +116 -0
- package/themes/debug-hud/variants/dusk-violet.json +112 -0
- package/themes/debug-hud/variants/forest-amber.json +86 -0
- package/themes/debug-hud/variants/forest-lime.json +117 -0
- package/themes/debug-hud/variants/forest-magenta.json +111 -0
- package/themes/debug-hud/variants/navy-jade.json +79 -0
- package/themes/debug-hud/variants/slate-green.json +112 -0
- package/themes/debug-hud/variants/wine-gold.json +119 -0
- package/themes/debug-hud/variants/wine-jade.json +83 -0
- package/themes/debug-hud/variants/wine-sky.json +112 -0
- package/themes/depth-flight/THEME.md +54 -0
- package/themes/depth-flight/effects.ts +396 -0
- package/themes/depth-flight/sample/assets/og/logo.svg +12 -0
- package/themes/depth-flight/sample/beats.json +1005 -0
- package/themes/depth-flight/sample/index.html +11 -0
- package/themes/depth-flight/sample/kf.json +59 -0
- package/themes/depth-flight/sample/lib/facts.ts +29 -0
- package/themes/depth-flight/sample/lib/fly.ts +15 -0
- package/themes/depth-flight/sample/main.ts +9 -0
- package/themes/depth-flight/sample/scenes/end.ts +51 -0
- package/themes/depth-flight/sample/scenes/gather.ts +40 -0
- package/themes/depth-flight/sample/scenes/models.ts +75 -0
- package/themes/depth-flight/sample/scenes/price.ts +50 -0
- package/themes/depth-flight/sample/style.json +94 -0
- package/themes/depth-flight/slots.ts +196 -0
- package/themes/depth-flight/still.png +0 -0
- package/themes/depth-flight/style.json +94 -0
- package/themes/depth-flight/theme.json +121 -0
- package/themes/depth-flight/variants/cocoa-cyan.json +121 -0
- package/themes/depth-flight/variants/cocoa-indigo.json +121 -0
- package/themes/depth-flight/variants/cocoa-violet.json +122 -0
- package/themes/depth-flight/variants/deep-sky.json +126 -0
- package/themes/depth-flight/variants/dusk-violet-bold.json +117 -0
- package/themes/depth-flight/variants/dusk-violet.json +132 -0
- package/themes/depth-flight/variants/forest-blue.json +116 -0
- package/themes/depth-flight/variants/forest-cyan.json +122 -0
- package/themes/depth-flight/variants/navy-sky-grain.json +122 -0
- package/themes/depth-flight/variants/navy-sky.json +116 -0
- package/themes/depth-flight/variants/night-teal.json +116 -0
- package/themes/depth-flight/variants/slate-cyan.json +127 -0
- package/themes/depth-flight/variants/slate-indigo.json +116 -0
- package/themes/depth-flight/variants/slate-sky.json +94 -0
- package/themes/depth-flight/variants/slate-violet.json +121 -0
- package/themes/film-reel/THEME.md +60 -0
- package/themes/film-reel/effects.ts +477 -0
- package/themes/film-reel/sample/assets/og/logo.svg +12 -0
- package/themes/film-reel/sample/beats.json +1005 -0
- package/themes/film-reel/sample/index.html +11 -0
- package/themes/film-reel/sample/kf.json +59 -0
- package/themes/film-reel/sample/lib/facts.ts +29 -0
- package/themes/film-reel/sample/lib/reel.ts +9 -0
- package/themes/film-reel/sample/main.ts +9 -0
- package/themes/film-reel/sample/scenes/end.ts +31 -0
- package/themes/film-reel/sample/scenes/gather.ts +40 -0
- package/themes/film-reel/sample/scenes/models.ts +37 -0
- package/themes/film-reel/sample/scenes/price.ts +63 -0
- package/themes/film-reel/sample/style.json +103 -0
- package/themes/film-reel/slots.ts +75 -0
- package/themes/film-reel/still.png +0 -0
- package/themes/film-reel/style.json +103 -0
- package/themes/film-reel/theme.json +144 -0
- package/themes/film-reel/variants/chalk-amber.json +124 -0
- package/themes/film-reel/variants/chalk-pink.json +123 -0
- package/themes/film-reel/variants/cream-violet.json +121 -0
- package/themes/film-reel/variants/frost-blue.json +126 -0
- package/themes/film-reel/variants/frost-green.json +123 -0
- package/themes/film-reel/variants/frost-indigo.json +121 -0
- package/themes/film-reel/variants/frost-jade.json +120 -0
- package/themes/film-reel/variants/frost-plum.json +120 -0
- package/themes/film-reel/variants/frost-teal.json +93 -0
- package/themes/film-reel/variants/lilac-gold.json +120 -0
- package/themes/film-reel/variants/lilac-jade.json +123 -0
- package/themes/film-reel/variants/lilac-magenta.json +125 -0
- package/themes/film-reel/variants/lilac-violet.json +122 -0
- package/themes/film-reel/variants/sand-cyan.json +124 -0
- package/themes/film-reel/variants/sand-lime.json +96 -0
- package/themes/glass-light/THEME.md +55 -0
- package/themes/glass-light/effects.ts +433 -0
- package/themes/glass-light/sample/assets/og/logo.svg +12 -0
- package/themes/glass-light/sample/beats.json +1005 -0
- package/themes/glass-light/sample/index.html +11 -0
- package/themes/glass-light/sample/kf.json +59 -0
- package/themes/glass-light/sample/lib/facts.ts +29 -0
- package/themes/glass-light/sample/lib/glass.ts +81 -0
- package/themes/glass-light/sample/main.ts +9 -0
- package/themes/glass-light/sample/scenes/end.ts +43 -0
- package/themes/glass-light/sample/scenes/gather.ts +38 -0
- package/themes/glass-light/sample/scenes/models.ts +46 -0
- package/themes/glass-light/sample/scenes/price.ts +46 -0
- package/themes/glass-light/sample/style.json +94 -0
- package/themes/glass-light/slots.ts +198 -0
- package/themes/glass-light/still.png +0 -0
- package/themes/glass-light/style.json +94 -0
- package/themes/glass-light/theme.json +121 -0
- package/themes/glass-light/variants/blush-coral.json +116 -0
- package/themes/glass-light/variants/blush-orange.json +115 -0
- package/themes/glass-light/variants/blush-pink.json +119 -0
- package/themes/glass-light/variants/blush-plum.json +115 -0
- package/themes/glass-light/variants/blush-teal.json +115 -0
- package/themes/glass-light/variants/cream-blue.json +125 -0
- package/themes/glass-light/variants/cream-pink.json +87 -0
- package/themes/glass-light/variants/cream-violet.json +119 -0
- package/themes/glass-light/variants/frost-green.json +115 -0
- package/themes/glass-light/variants/frost-sky-suit.json +115 -0
- package/themes/glass-light/variants/frost-sky.json +121 -0
- package/themes/glass-light/variants/lilac-gold.json +126 -0
- package/themes/glass-light/variants/lilac-plum.json +114 -0
- package/themes/glass-light/variants/sage-green.json +119 -0
- package/themes/glass-light/variants/sage-rose.json +114 -0
- package/themes/ink-wash/THEME.md +59 -0
- package/themes/ink-wash/effects.ts +574 -0
- package/themes/ink-wash/sample/assets/og/logo.svg +12 -0
- package/themes/ink-wash/sample/beats.json +1005 -0
- package/themes/ink-wash/sample/index.html +11 -0
- package/themes/ink-wash/sample/kf.json +59 -0
- package/themes/ink-wash/sample/lib/facts.ts +29 -0
- package/themes/ink-wash/sample/lib/ink.ts +35 -0
- package/themes/ink-wash/sample/main.ts +9 -0
- package/themes/ink-wash/sample/scenes/end.ts +72 -0
- package/themes/ink-wash/sample/scenes/gather.ts +53 -0
- package/themes/ink-wash/sample/scenes/models.ts +58 -0
- package/themes/ink-wash/sample/scenes/price.ts +85 -0
- package/themes/ink-wash/sample/style.json +108 -0
- package/themes/ink-wash/slots.ts +150 -0
- package/themes/ink-wash/still.png +0 -0
- package/themes/ink-wash/style.json +108 -0
- package/themes/ink-wash/theme.json +133 -0
- package/themes/ink-wash/variants/blush-orange.json +125 -0
- package/themes/ink-wash/variants/blush-rose.json +124 -0
- package/themes/ink-wash/variants/chalk-coral-grain.json +125 -0
- package/themes/ink-wash/variants/chalk-coral-serif.json +118 -0
- package/themes/ink-wash/variants/chalk-coral.json +120 -0
- package/themes/ink-wash/variants/chalk-orange-grain.json +97 -0
- package/themes/ink-wash/variants/chalk-orange-serif.json +120 -0
- package/themes/ink-wash/variants/chalk-orange.json +120 -0
- package/themes/ink-wash/variants/frost-coral.json +119 -0
- package/themes/ink-wash/variants/frost-rose.json +91 -0
- package/themes/ink-wash/variants/lilac-coral.json +96 -0
- package/themes/ink-wash/variants/sage-coral.json +119 -0
- package/themes/ink-wash/variants/sage-rose.json +119 -0
- package/themes/ink-wash/variants/sand-coral.json +125 -0
- package/themes/ink-wash/variants/sand-orange.json +120 -0
- package/themes/iso-diorama/THEME.md +54 -0
- package/themes/iso-diorama/effects.ts +374 -0
- package/themes/iso-diorama/sample/assets/og/logo.svg +12 -0
- package/themes/iso-diorama/sample/beats.json +1005 -0
- package/themes/iso-diorama/sample/index.html +11 -0
- package/themes/iso-diorama/sample/kf.json +59 -0
- package/themes/iso-diorama/sample/lib/facts.ts +29 -0
- package/themes/iso-diorama/sample/lib/iso.ts +22 -0
- package/themes/iso-diorama/sample/main.ts +9 -0
- package/themes/iso-diorama/sample/scenes/end.ts +41 -0
- package/themes/iso-diorama/sample/scenes/gather.ts +39 -0
- package/themes/iso-diorama/sample/scenes/models.ts +55 -0
- package/themes/iso-diorama/sample/scenes/price.ts +49 -0
- package/themes/iso-diorama/sample/style.json +98 -0
- package/themes/iso-diorama/slots.ts +222 -0
- package/themes/iso-diorama/still.png +0 -0
- package/themes/iso-diorama/style.json +98 -0
- package/themes/iso-diorama/theme.json +133 -0
- package/themes/iso-diorama/variants/chalk-plum.json +121 -0
- package/themes/iso-diorama/variants/cocoa-gold.json +93 -0
- package/themes/iso-diorama/variants/cocoa-indigo.json +122 -0
- package/themes/iso-diorama/variants/cocoa-rose.json +125 -0
- package/themes/iso-diorama/variants/deep-green.json +125 -0
- package/themes/iso-diorama/variants/deep-plum.json +120 -0
- package/themes/iso-diorama/variants/dusk-blue.json +126 -0
- package/themes/iso-diorama/variants/dusk-coral.json +122 -0
- package/themes/iso-diorama/variants/dusk-jade.json +121 -0
- package/themes/iso-diorama/variants/forest-cyan.json +127 -0
- package/themes/iso-diorama/variants/frost-blue.json +126 -0
- package/themes/iso-diorama/variants/frost-green.json +126 -0
- package/themes/iso-diorama/variants/frost-orange.json +125 -0
- package/themes/iso-diorama/variants/frost-teal.json +123 -0
- package/themes/iso-diorama/variants/navy-amber.json +125 -0
- package/themes/isotype/THEME.md +58 -0
- package/themes/isotype/effects.ts +297 -0
- package/themes/isotype/kit.ts +102 -0
- package/themes/isotype/sample/assets/og/logo.svg +12 -0
- package/themes/isotype/sample/beats.json +1005 -0
- package/themes/isotype/sample/index.html +11 -0
- package/themes/isotype/sample/kf.json +59 -0
- package/themes/isotype/sample/lib/chart.ts +47 -0
- package/themes/isotype/sample/lib/facts.ts +29 -0
- package/themes/isotype/sample/main.ts +9 -0
- package/themes/isotype/sample/scenes/end.ts +80 -0
- package/themes/isotype/sample/scenes/gather.ts +65 -0
- package/themes/isotype/sample/scenes/models.ts +75 -0
- package/themes/isotype/sample/scenes/price.ts +90 -0
- package/themes/isotype/sample/style.json +101 -0
- package/themes/isotype/slots.ts +74 -0
- package/themes/isotype/still.png +0 -0
- package/themes/isotype/style.json +101 -0
- package/themes/isotype/theme.json +141 -0
- package/themes/isotype/variants/blush-rose.json +127 -0
- package/themes/isotype/variants/chalk-amber.json +123 -0
- package/themes/isotype/variants/chalk-coral-bold.json +118 -0
- package/themes/isotype/variants/chalk-coral.json +117 -0
- package/themes/isotype/variants/chalk-orange.json +128 -0
- package/themes/isotype/variants/frost-amber-plex.json +128 -0
- package/themes/isotype/variants/frost-amber.json +123 -0
- package/themes/isotype/variants/frost-coral-grain.json +95 -0
- package/themes/isotype/variants/frost-coral.json +123 -0
- package/themes/isotype/variants/frost-orange.json +123 -0
- package/themes/isotype/variants/lilac-rose.json +127 -0
- package/themes/isotype/variants/sage-coral.json +90 -0
- package/themes/isotype/variants/sand-amber.json +118 -0
- package/themes/isotype/variants/sand-orange.json +128 -0
- package/themes/kawaii-sticker/THEME.md +44 -0
- package/themes/kawaii-sticker/effects.ts +412 -0
- package/themes/kawaii-sticker/sample/assets/stickers/bolt.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/bubble.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/clock.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/coin.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/moon.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/og-logo.svg +12 -0
- package/themes/kawaii-sticker/sample/assets/stickers/server.png +0 -0
- package/themes/kawaii-sticker/sample/beats.json +1 -0
- package/themes/kawaii-sticker/sample/index.html +11 -0
- package/themes/kawaii-sticker/sample/kf.json +66 -0
- package/themes/kawaii-sticker/sample/lib/og.ts +54 -0
- package/themes/kawaii-sticker/sample/main.ts +9 -0
- package/themes/kawaii-sticker/sample/scenes/end.ts +37 -0
- package/themes/kawaii-sticker/sample/scenes/gather.ts +50 -0
- package/themes/kawaii-sticker/sample/scenes/models.ts +43 -0
- package/themes/kawaii-sticker/sample/scenes/one.ts +45 -0
- package/themes/kawaii-sticker/sample/scenes/price.ts +47 -0
- package/themes/kawaii-sticker/sample/style.json +99 -0
- package/themes/kawaii-sticker/slots.ts +95 -0
- package/themes/kawaii-sticker/still.png +0 -0
- package/themes/kawaii-sticker/style.json +99 -0
- package/themes/kawaii-sticker/theme.json +147 -0
- package/themes/kawaii-sticker/variants/blush-coral.json +134 -0
- package/themes/kawaii-sticker/variants/blush-teal.json +129 -0
- package/themes/kawaii-sticker/variants/blush-violet.json +134 -0
- package/themes/kawaii-sticker/variants/cream-gold.json +135 -0
- package/themes/kawaii-sticker/variants/deep-jade.json +134 -0
- package/themes/kawaii-sticker/variants/dusk-green.json +134 -0
- package/themes/kawaii-sticker/variants/dusk-indigo.json +130 -0
- package/themes/kawaii-sticker/variants/dusk-sky.json +135 -0
- package/themes/kawaii-sticker/variants/dusk-teal.json +134 -0
- package/themes/kawaii-sticker/variants/frost-blue.json +135 -0
- package/themes/kawaii-sticker/variants/frost-plum.json +133 -0
- package/themes/kawaii-sticker/variants/lilac-violet.json +133 -0
- package/themes/kawaii-sticker/variants/navy-gold.json +134 -0
- package/themes/kawaii-sticker/variants/navy-plum.json +134 -0
- package/themes/kawaii-sticker/variants/sage-sky.json +107 -0
- package/themes/lab-notebook/THEME.md +56 -0
- package/themes/lab-notebook/effects.ts +423 -0
- package/themes/lab-notebook/kit.ts +84 -0
- package/themes/lab-notebook/sample/assets/og/logo.svg +12 -0
- package/themes/lab-notebook/sample/beats.json +1005 -0
- package/themes/lab-notebook/sample/index.html +11 -0
- package/themes/lab-notebook/sample/kf.json +59 -0
- package/themes/lab-notebook/sample/lib/facts.ts +29 -0
- package/themes/lab-notebook/sample/lib/note.ts +53 -0
- package/themes/lab-notebook/sample/main.ts +9 -0
- package/themes/lab-notebook/sample/scenes/end.ts +127 -0
- package/themes/lab-notebook/sample/scenes/gather.ts +83 -0
- package/themes/lab-notebook/sample/scenes/models.ts +73 -0
- package/themes/lab-notebook/sample/scenes/price.ts +89 -0
- package/themes/lab-notebook/sample/style.json +109 -0
- package/themes/lab-notebook/slots.ts +75 -0
- package/themes/lab-notebook/still.png +0 -0
- package/themes/lab-notebook/style.json +109 -0
- package/themes/lab-notebook/theme.json +142 -0
- package/themes/lab-notebook/variants/blush-orange.json +125 -0
- package/themes/lab-notebook/variants/chalk-coral.json +126 -0
- package/themes/lab-notebook/variants/chalk-orange.json +129 -0
- package/themes/lab-notebook/variants/chalk-rose-2.json +96 -0
- package/themes/lab-notebook/variants/chalk-rose.json +125 -0
- package/themes/lab-notebook/variants/frost-orange.json +101 -0
- package/themes/lab-notebook/variants/frost-rose-grain.json +101 -0
- package/themes/lab-notebook/variants/frost-rose.json +96 -0
- package/themes/lab-notebook/variants/lilac-rose-2.json +96 -0
- package/themes/lab-notebook/variants/lilac-rose.json +128 -0
- package/themes/lab-notebook/variants/sage-rose.json +124 -0
- package/themes/lab-notebook/variants/sand-orange-grain.json +101 -0
- package/themes/lab-notebook/variants/sand-orange.json +129 -0
- package/themes/lab-notebook/variants/snow-orange.json +129 -0
- package/themes/lab-notebook/variants/snow-rose.json +124 -0
- package/themes/manga-panel/THEME.md +60 -0
- package/themes/manga-panel/effects.ts +791 -0
- package/themes/manga-panel/sample/assets/og/logo.svg +12 -0
- package/themes/manga-panel/sample/beats.json +1005 -0
- package/themes/manga-panel/sample/index.html +11 -0
- package/themes/manga-panel/sample/kf.json +59 -0
- package/themes/manga-panel/sample/lib/facts.ts +29 -0
- package/themes/manga-panel/sample/lib/manga.ts +58 -0
- package/themes/manga-panel/sample/main.ts +9 -0
- package/themes/manga-panel/sample/scenes/end.ts +96 -0
- package/themes/manga-panel/sample/scenes/gather.ts +100 -0
- package/themes/manga-panel/sample/scenes/models.ts +96 -0
- package/themes/manga-panel/sample/scenes/price.ts +154 -0
- package/themes/manga-panel/sample/style.json +105 -0
- package/themes/manga-panel/slots.ts +127 -0
- package/themes/manga-panel/still.png +0 -0
- package/themes/manga-panel/style.json +105 -0
- package/themes/manga-panel/theme.json +150 -0
- package/themes/manga-panel/variants/chalk-cyan-dots.json +122 -0
- package/themes/manga-panel/variants/chalk-cyan.json +122 -0
- package/themes/manga-panel/variants/chalk-magenta.json +121 -0
- package/themes/manga-panel/variants/chalk-orange-bold.json +117 -0
- package/themes/manga-panel/variants/chalk-orange.json +122 -0
- package/themes/manga-panel/variants/chalk-rose-dots.json +121 -0
- package/themes/manga-panel/variants/chalk-rose.json +116 -0
- package/themes/manga-panel/variants/chalk-sky-bold.json +117 -0
- package/themes/manga-panel/variants/chalk-sky.json +117 -0
- package/themes/manga-panel/variants/snow-cyan.json +117 -0
- package/themes/manga-panel/variants/snow-magenta-dots.json +121 -0
- package/themes/manga-panel/variants/snow-magenta.json +116 -0
- package/themes/manga-panel/variants/snow-rose-dots.json +121 -0
- package/themes/manga-panel/variants/snow-rose.json +116 -0
- package/themes/manga-panel/variants/snow-sky.json +95 -0
- package/themes/marble-run/THEME.md +73 -0
- package/themes/marble-run/effects.ts +678 -0
- package/themes/marble-run/sample/assets/og/logo.svg +12 -0
- package/themes/marble-run/sample/beats.json +1005 -0
- package/themes/marble-run/sample/index.html +11 -0
- package/themes/marble-run/sample/kf.json +59 -0
- package/themes/marble-run/sample/lib/facts.ts +29 -0
- package/themes/marble-run/sample/lib/run.ts +30 -0
- package/themes/marble-run/sample/main.ts +9 -0
- package/themes/marble-run/sample/scenes/end.ts +58 -0
- package/themes/marble-run/sample/scenes/gather.ts +51 -0
- package/themes/marble-run/sample/scenes/models.ts +73 -0
- package/themes/marble-run/sample/scenes/price.ts +51 -0
- package/themes/marble-run/sample/style.json +109 -0
- package/themes/marble-run/slots.ts +116 -0
- package/themes/marble-run/still.png +0 -0
- package/themes/marble-run/style.json +109 -0
- package/themes/marble-run/theme.json +147 -0
- package/themes/marble-run/variants/cocoa-amber.json +128 -0
- package/themes/marble-run/variants/cocoa-orange.json +142 -0
- package/themes/marble-run/variants/dusk-orange.json +133 -0
- package/themes/marble-run/variants/forest-gold.json +128 -0
- package/themes/marble-run/variants/navy-gold.json +137 -0
- package/themes/marble-run/variants/night-gold-grain.json +105 -0
- package/themes/marble-run/variants/night-gold.json +137 -0
- package/themes/marble-run/variants/slate-gold-grain.json +133 -0
- package/themes/marble-run/variants/slate-gold.json +133 -0
- package/themes/marble-run/variants/slate-orange-grain.json +105 -0
- package/themes/marble-run/variants/slate-orange-mono.json +128 -0
- package/themes/marble-run/variants/slate-orange-serif.json +128 -0
- package/themes/marble-run/variants/slate-orange.json +131 -0
- package/themes/neon-sign/THEME.md +59 -0
- package/themes/neon-sign/effects.ts +424 -0
- package/themes/neon-sign/sample/assets/og/logo.svg +12 -0
- package/themes/neon-sign/sample/beats.json +1005 -0
- package/themes/neon-sign/sample/index.html +11 -0
- package/themes/neon-sign/sample/kf.json +59 -0
- package/themes/neon-sign/sample/lib/facts.ts +29 -0
- package/themes/neon-sign/sample/lib/neon.ts +50 -0
- package/themes/neon-sign/sample/main.ts +9 -0
- package/themes/neon-sign/sample/scenes/end.ts +62 -0
- package/themes/neon-sign/sample/scenes/gather.ts +59 -0
- package/themes/neon-sign/sample/scenes/models.ts +63 -0
- package/themes/neon-sign/sample/scenes/price.ts +74 -0
- package/themes/neon-sign/sample/style.json +104 -0
- package/themes/neon-sign/slots.ts +110 -0
- package/themes/neon-sign/still.png +0 -0
- package/themes/neon-sign/style.json +104 -0
- package/themes/neon-sign/theme.json +137 -0
- package/themes/neon-sign/variants/deep-plum.json +121 -0
- package/themes/neon-sign/variants/deep-violet.json +121 -0
- package/themes/neon-sign/variants/dusk-plum.json +121 -0
- package/themes/neon-sign/variants/forest-magenta.json +126 -0
- package/themes/neon-sign/variants/forest-plum.json +98 -0
- package/themes/neon-sign/variants/night-coral.json +122 -0
- package/themes/neon-sign/variants/night-magenta-round.json +121 -0
- package/themes/neon-sign/variants/night-magenta.json +126 -0
- package/themes/neon-sign/variants/night-pink.json +125 -0
- package/themes/neon-sign/variants/night-violet.json +126 -0
- package/themes/neon-sign/variants/slate-plum.json +120 -0
- package/themes/neon-sign/variants/slate-violet.json +127 -0
- package/themes/neon-sign/variants/wine-coral.json +127 -0
- package/themes/neon-sign/variants/wine-pink.json +125 -0
- package/themes/neon-sign/variants/wine-plum.json +126 -0
- package/themes/newspaper/THEME.md +67 -0
- package/themes/newspaper/effects.ts +347 -0
- package/themes/newspaper/sample/assets/og/logo.svg +12 -0
- package/themes/newspaper/sample/beats.json +1005 -0
- package/themes/newspaper/sample/index.html +11 -0
- package/themes/newspaper/sample/kf.json +59 -0
- package/themes/newspaper/sample/lib/facts.ts +29 -0
- package/themes/newspaper/sample/lib/page.ts +27 -0
- package/themes/newspaper/sample/main.ts +9 -0
- package/themes/newspaper/sample/scenes/end.ts +62 -0
- package/themes/newspaper/sample/scenes/gather.ts +66 -0
- package/themes/newspaper/sample/scenes/models.ts +61 -0
- package/themes/newspaper/sample/scenes/price.ts +103 -0
- package/themes/newspaper/sample/style.json +100 -0
- package/themes/newspaper/slots.ts +73 -0
- package/themes/newspaper/still.png +0 -0
- package/themes/newspaper/style.json +100 -0
- package/themes/newspaper/theme.json +141 -0
- package/themes/newspaper/variants/blush-amber.json +123 -0
- package/themes/newspaper/variants/blush-orange.json +125 -0
- package/themes/newspaper/variants/chalk-cyan.json +119 -0
- package/themes/newspaper/variants/chalk-indigo.json +124 -0
- package/themes/newspaper/variants/chalk-jade.json +95 -0
- package/themes/newspaper/variants/chalk-magenta.json +127 -0
- package/themes/newspaper/variants/frost-plum.json +123 -0
- package/themes/newspaper/variants/frost-sky.json +129 -0
- package/themes/newspaper/variants/frost-violet.json +96 -0
- package/themes/newspaper/variants/lilac-coral.json +124 -0
- package/themes/newspaper/variants/lilac-green.json +127 -0
- package/themes/newspaper/variants/sage-blue.json +124 -0
- package/themes/newspaper/variants/sage-lime.json +117 -0
- package/themes/newspaper/variants/sand-gold.json +124 -0
- package/themes/newspaper/variants/sand-jade.json +123 -0
- package/themes/og-measure/THEME.md +32 -6
- package/themes/og-measure/effects.ts +219 -115
- package/themes/og-measure/sample/assets/brand/og-logo.svg +11 -11
- package/themes/og-measure/sample/lib/data.ts +6 -0
- package/themes/og-measure/sample/scenes/end.ts +14 -10
- package/themes/og-measure/sample/scenes/gather.ts +12 -1
- package/themes/og-measure/sample/scenes/models.ts +13 -2
- package/themes/og-measure/sample/scenes/one.ts +8 -6
- package/themes/og-measure/sample/scenes/price.ts +20 -3
- package/themes/og-measure/sample/style.json +30 -35
- package/themes/og-measure/slots.ts +25 -30
- package/themes/og-measure/still.png +0 -0
- package/themes/og-measure/style.json +30 -35
- package/themes/og-measure/theme.json +91 -14
- package/themes/og-measure/variants/snow-blue.json +90 -0
- package/themes/orbit-system/THEME.md +77 -0
- package/themes/orbit-system/effects.ts +665 -0
- package/themes/orbit-system/sample/assets/og/logo.svg +12 -0
- package/themes/orbit-system/sample/beats.json +1005 -0
- package/themes/orbit-system/sample/index.html +11 -0
- package/themes/orbit-system/sample/kf.json +59 -0
- package/themes/orbit-system/sample/lib/facts.ts +29 -0
- package/themes/orbit-system/sample/lib/orbit.ts +84 -0
- package/themes/orbit-system/sample/main.ts +9 -0
- package/themes/orbit-system/sample/scenes/end.ts +50 -0
- package/themes/orbit-system/sample/scenes/gather.ts +35 -0
- package/themes/orbit-system/sample/scenes/models.ts +49 -0
- package/themes/orbit-system/sample/scenes/price.ts +57 -0
- package/themes/orbit-system/sample/style.json +108 -0
- package/themes/orbit-system/slots.ts +174 -0
- package/themes/orbit-system/still.png +0 -0
- package/themes/orbit-system/style.json +108 -0
- package/themes/orbit-system/theme.json +144 -0
- package/themes/orbit-system/variants/cocoa-amber.json +122 -0
- package/themes/orbit-system/variants/cocoa-coral.json +127 -0
- package/themes/orbit-system/variants/cocoa-cyan.json +127 -0
- package/themes/orbit-system/variants/deep-cyan.json +132 -0
- package/themes/orbit-system/variants/deep-sky.json +122 -0
- package/themes/orbit-system/variants/dusk-magenta.json +121 -0
- package/themes/orbit-system/variants/dusk-plum-pretendard.json +121 -0
- package/themes/orbit-system/variants/dusk-plum.json +127 -0
- package/themes/orbit-system/variants/dusk-violet.json +122 -0
- package/themes/orbit-system/variants/forest-coral.json +126 -0
- package/themes/orbit-system/variants/forest-plum.json +94 -0
- package/themes/orbit-system/variants/navy-amber.json +127 -0
- package/themes/orbit-system/variants/wine-amber.json +127 -0
- package/themes/orbit-system/variants/wine-coral.json +123 -0
- package/themes/orbit-system/variants/wine-magenta.json +126 -0
- package/themes/origami-fold/THEME.md +74 -0
- package/themes/origami-fold/effects.ts +535 -0
- package/themes/origami-fold/sample/assets/og/logo.svg +12 -0
- package/themes/origami-fold/sample/beats.json +1005 -0
- package/themes/origami-fold/sample/index.html +11 -0
- package/themes/origami-fold/sample/kf.json +59 -0
- package/themes/origami-fold/sample/lib/facts.ts +29 -0
- package/themes/origami-fold/sample/lib/fold.ts +53 -0
- package/themes/origami-fold/sample/main.ts +9 -0
- package/themes/origami-fold/sample/scenes/end.ts +51 -0
- package/themes/origami-fold/sample/scenes/gather.ts +37 -0
- package/themes/origami-fold/sample/scenes/models.ts +46 -0
- package/themes/origami-fold/sample/scenes/price.ts +54 -0
- package/themes/origami-fold/sample/style.json +108 -0
- package/themes/origami-fold/slots.ts +176 -0
- package/themes/origami-fold/still.png +0 -0
- package/themes/origami-fold/style.json +108 -0
- package/themes/origami-fold/theme.json +125 -0
- package/themes/origami-fold/variants/deep-amber-sunflower.json +122 -0
- package/themes/origami-fold/variants/deep-amber.json +122 -0
- package/themes/origami-fold/variants/deep-orange.json +128 -0
- package/themes/origami-fold/variants/forest-coral.json +127 -0
- package/themes/origami-fold/variants/forest-pink.json +123 -0
- package/themes/origami-fold/variants/forest-rose.json +100 -0
- package/themes/origami-fold/variants/frost-amber-grain.json +127 -0
- package/themes/origami-fold/variants/frost-amber-paper.json +128 -0
- package/themes/origami-fold/variants/frost-amber.json +95 -0
- package/themes/origami-fold/variants/sage-coral-grain.json +100 -0
- package/themes/origami-fold/variants/sage-coral-sunflower.json +122 -0
- package/themes/origami-fold/variants/sage-coral.json +128 -0
- package/themes/origami-fold/variants/sage-pink-grain.json +127 -0
- package/themes/origami-fold/variants/sage-pink-round.json +124 -0
- package/themes/origami-fold/variants/sage-pink.json +127 -0
- package/themes/paper-cutout/THEME.md +63 -0
- package/themes/paper-cutout/effects.ts +609 -0
- package/themes/paper-cutout/sample/assets/og/logo.svg +12 -0
- package/themes/paper-cutout/sample/beats.json +1005 -0
- package/themes/paper-cutout/sample/index.html +11 -0
- package/themes/paper-cutout/sample/kf.json +59 -0
- package/themes/paper-cutout/sample/lib/facts.ts +29 -0
- package/themes/paper-cutout/sample/lib/paper.ts +91 -0
- package/themes/paper-cutout/sample/main.ts +9 -0
- package/themes/paper-cutout/sample/scenes/end.ts +54 -0
- package/themes/paper-cutout/sample/scenes/gather.ts +63 -0
- package/themes/paper-cutout/sample/scenes/models.ts +93 -0
- package/themes/paper-cutout/sample/scenes/price.ts +100 -0
- package/themes/paper-cutout/sample/style.json +104 -0
- package/themes/paper-cutout/slots.ts +87 -0
- package/themes/paper-cutout/still.png +0 -0
- package/themes/paper-cutout/style.json +104 -0
- package/themes/paper-cutout/theme.json +146 -0
- package/themes/paper-cutout/variants/blush-coral.json +122 -0
- package/themes/paper-cutout/variants/blush-violet.json +122 -0
- package/themes/paper-cutout/variants/chalk-teal.json +122 -0
- package/themes/paper-cutout/variants/cream-gold.json +122 -0
- package/themes/paper-cutout/variants/frost-blue.json +123 -0
- package/themes/paper-cutout/variants/frost-lime.json +121 -0
- package/themes/paper-cutout/variants/frost-plum.json +122 -0
- package/themes/paper-cutout/variants/lilac-blue.json +123 -0
- package/themes/paper-cutout/variants/lilac-gold.json +122 -0
- package/themes/paper-cutout/variants/sage-cyan.json +122 -0
- package/themes/paper-cutout/variants/sage-green.json +122 -0
- package/themes/paper-cutout/variants/sage-pink.json +122 -0
- package/themes/paper-cutout/variants/sand-blue.json +123 -0
- package/themes/paper-cutout/variants/sand-green.json +121 -0
- package/themes/paper-cutout/variants/sand-plum.json +120 -0
- package/themes/pixel-quest/THEME.md +57 -0
- package/themes/pixel-quest/effects.ts +491 -0
- package/themes/pixel-quest/kit.ts +232 -0
- package/themes/pixel-quest/sample/assets/og/logo.svg +12 -0
- package/themes/pixel-quest/sample/beats.json +1005 -0
- package/themes/pixel-quest/sample/index.html +11 -0
- package/themes/pixel-quest/sample/kf.json +59 -0
- package/themes/pixel-quest/sample/lib/facts.ts +29 -0
- package/themes/pixel-quest/sample/lib/game.ts +71 -0
- package/themes/pixel-quest/sample/lib/logo.ts +51 -0
- package/themes/pixel-quest/sample/main.ts +9 -0
- package/themes/pixel-quest/sample/scenes/end.ts +75 -0
- package/themes/pixel-quest/sample/scenes/gather.ts +65 -0
- package/themes/pixel-quest/sample/scenes/models.ts +104 -0
- package/themes/pixel-quest/sample/scenes/price.ts +118 -0
- package/themes/pixel-quest/sample/style.json +115 -0
- package/themes/pixel-quest/slots.ts +94 -0
- package/themes/pixel-quest/still.png +0 -0
- package/themes/pixel-quest/style.json +115 -0
- package/themes/pixel-quest/theme.json +144 -0
- package/themes/pixel-quest/variants/navy-gold-2.json +98 -0
- package/themes/pixel-quest/variants/navy-gold-3.json +127 -0
- package/themes/pixel-quest/variants/navy-gold-4.json +95 -0
- package/themes/pixel-quest/variants/navy-gold-pixel.json +132 -0
- package/themes/pixel-quest/variants/navy-gold-scan.json +99 -0
- package/themes/pixel-quest/variants/navy-gold.json +131 -0
- package/themes/pixel-quest/variants/navy-lime-2.json +93 -0
- package/themes/pixel-quest/variants/navy-lime-3.json +124 -0
- package/themes/pixel-quest/variants/navy-lime-pixel.json +126 -0
- package/themes/pixel-quest/variants/navy-lime-scan.json +97 -0
- package/themes/pixel-quest/variants/navy-lime.json +130 -0
- package/themes/receipt/THEME.md +72 -0
- package/themes/receipt/effects.ts +257 -0
- package/themes/receipt/sample/assets/og/logo.svg +12 -0
- package/themes/receipt/sample/beats.json +1005 -0
- package/themes/receipt/sample/index.html +11 -0
- package/themes/receipt/sample/kf.json +59 -0
- package/themes/receipt/sample/lib/facts.ts +29 -0
- package/themes/receipt/sample/lib/sheet.ts +52 -0
- package/themes/receipt/sample/main.ts +9 -0
- package/themes/receipt/sample/scenes/end.ts +44 -0
- package/themes/receipt/sample/scenes/gather.ts +57 -0
- package/themes/receipt/sample/scenes/models.ts +48 -0
- package/themes/receipt/sample/scenes/price.ts +64 -0
- package/themes/receipt/sample/style.json +104 -0
- package/themes/receipt/slots.ts +89 -0
- package/themes/receipt/still.png +0 -0
- package/themes/receipt/style.json +104 -0
- package/themes/receipt/theme.json +133 -0
- package/themes/receipt/variants/blush-coral.json +89 -0
- package/themes/receipt/variants/sand-coral-2.json +89 -0
- package/themes/receipt/variants/sand-coral-3.json +89 -0
- package/themes/receipt/variants/sand-coral-4.json +90 -0
- package/themes/receipt/variants/sand-coral-5.json +89 -0
- package/themes/receipt/variants/sand-coral-6.json +88 -0
- package/themes/receipt/variants/sand-coral-7.json +88 -0
- package/themes/receipt/variants/sand-coral-8.json +89 -0
- package/themes/receipt/variants/sand-coral-9.json +89 -0
- package/themes/receipt/variants/sand-coral.json +88 -0
- package/themes/receipt/variants/sand-orange-2.json +89 -0
- package/themes/receipt/variants/sand-orange-3.json +90 -0
- package/themes/receipt/variants/sand-orange-4.json +89 -0
- package/themes/receipt/variants/sand-orange-5.json +89 -0
- package/themes/receipt/variants/sand-orange.json +89 -0
- package/themes/riso-zine/sample/style.json +2 -2
- package/themes/riso-zine/style.json +2 -2
- package/themes/riso-zine/theme.json +68 -0
- package/themes/riso-zine/variants/blush-coral.json +120 -0
- package/themes/riso-zine/variants/blush-gold.json +120 -0
- package/themes/riso-zine/variants/blush-pink.json +115 -0
- package/themes/riso-zine/variants/chalk-cyan.json +120 -0
- package/themes/riso-zine/variants/chalk-lime.json +119 -0
- package/themes/riso-zine/variants/cream-amber.json +89 -0
- package/themes/riso-zine/variants/frost-blue.json +119 -0
- package/themes/riso-zine/variants/frost-coral.json +118 -0
- package/themes/riso-zine/variants/frost-cyan.json +120 -0
- package/themes/riso-zine/variants/frost-green.json +120 -0
- package/themes/riso-zine/variants/lilac-plum.json +118 -0
- package/themes/riso-zine/variants/lilac-violet.json +123 -0
- package/themes/riso-zine/variants/sage-green.json +119 -0
- package/themes/riso-zine/variants/sand-jade.json +120 -0
- package/themes/riso-zine/variants/sand-plum.json +113 -0
- package/themes/server-hall/THEME.md +58 -0
- package/themes/server-hall/effects.ts +455 -0
- package/themes/server-hall/kit.ts +138 -0
- package/themes/server-hall/sample/assets/og/logo.svg +12 -0
- package/themes/server-hall/sample/beats.json +1005 -0
- package/themes/server-hall/sample/index.html +11 -0
- package/themes/server-hall/sample/kf.json +59 -0
- package/themes/server-hall/sample/lib/facts.ts +29 -0
- package/themes/server-hall/sample/lib/hall.ts +81 -0
- package/themes/server-hall/sample/main.ts +9 -0
- package/themes/server-hall/sample/scenes/end.ts +57 -0
- package/themes/server-hall/sample/scenes/gather.ts +38 -0
- package/themes/server-hall/sample/scenes/models.ts +49 -0
- package/themes/server-hall/sample/scenes/price.ts +65 -0
- package/themes/server-hall/sample/style.json +107 -0
- package/themes/server-hall/slots.ts +106 -0
- package/themes/server-hall/still.png +0 -0
- package/themes/server-hall/style.json +107 -0
- package/themes/server-hall/theme.json +145 -0
- package/themes/server-hall/variants/navy-indigo.json +140 -0
- package/themes/server-hall/variants/night-indigo.json +120 -0
- package/themes/server-hall/variants/wine-plum.json +130 -0
- package/themes/server-hall/variants/wine-violet.json +103 -0
- package/themes/subway-map/THEME.md +64 -0
- package/themes/subway-map/effects.ts +662 -0
- package/themes/subway-map/sample/assets/og/logo.svg +12 -0
- package/themes/subway-map/sample/beats.json +1005 -0
- package/themes/subway-map/sample/index.html +11 -0
- package/themes/subway-map/sample/kf.json +59 -0
- package/themes/subway-map/sample/lib/facts.ts +29 -0
- package/themes/subway-map/sample/lib/map.ts +58 -0
- package/themes/subway-map/sample/main.ts +9 -0
- package/themes/subway-map/sample/scenes/end.ts +94 -0
- package/themes/subway-map/sample/scenes/gather.ts +64 -0
- package/themes/subway-map/sample/scenes/models.ts +117 -0
- package/themes/subway-map/sample/scenes/price.ts +119 -0
- package/themes/subway-map/sample/style.json +108 -0
- package/themes/subway-map/slots.ts +66 -0
- package/themes/subway-map/still.png +0 -0
- package/themes/subway-map/style.json +108 -0
- package/themes/subway-map/theme.json +163 -0
- package/themes/subway-map/variants/blush-jade.json +131 -0
- package/themes/subway-map/variants/chalk-jade.json +141 -0
- package/themes/subway-map/variants/deep-green.json +131 -0
- package/themes/subway-map/variants/deep-teal.json +132 -0
- package/themes/subway-map/variants/dusk-teal-bold.json +132 -0
- package/themes/subway-map/variants/dusk-teal.json +105 -0
- package/themes/subway-map/variants/forest-green.json +141 -0
- package/themes/subway-map/variants/forest-jade.json +131 -0
- package/themes/subway-map/variants/frost-jade.json +131 -0
- package/themes/subway-map/variants/frost-teal.json +137 -0
- package/themes/subway-map/variants/sage-teal.json +132 -0
- package/themes/subway-map/variants/slate-green.json +136 -0
- package/themes/subway-map/variants/slate-jade.json +131 -0
- package/themes/subway-map/variants/snow-jade.json +136 -0
- package/themes/subway-map/variants/wine-green.json +104 -0
- package/themes/swiss-poster/THEME.md +59 -0
- package/themes/swiss-poster/effects.ts +339 -0
- package/themes/swiss-poster/grid.ts +35 -0
- package/themes/swiss-poster/sample/assets/og/logo.svg +12 -0
- package/themes/swiss-poster/sample/beats.json +1005 -0
- package/themes/swiss-poster/sample/index.html +11 -0
- package/themes/swiss-poster/sample/kf.json +59 -0
- package/themes/swiss-poster/sample/lib/facts.ts +29 -0
- package/themes/swiss-poster/sample/lib/poster.ts +36 -0
- package/themes/swiss-poster/sample/main.ts +9 -0
- package/themes/swiss-poster/sample/scenes/end.ts +70 -0
- package/themes/swiss-poster/sample/scenes/gather.ts +68 -0
- package/themes/swiss-poster/sample/scenes/models.ts +63 -0
- package/themes/swiss-poster/sample/scenes/price.ts +74 -0
- package/themes/swiss-poster/sample/style.json +100 -0
- package/themes/swiss-poster/slots.ts +69 -0
- package/themes/swiss-poster/still.png +0 -0
- package/themes/swiss-poster/style.json +100 -0
- package/themes/swiss-poster/theme.json +133 -0
- package/themes/swiss-poster/variants/blush-green.json +116 -0
- package/themes/swiss-poster/variants/chalk-plum.json +121 -0
- package/themes/swiss-poster/variants/chalk-sky.json +90 -0
- package/themes/swiss-poster/variants/cocoa-cyan.json +117 -0
- package/themes/swiss-poster/variants/dusk-coral.json +89 -0
- package/themes/swiss-poster/variants/dusk-magenta.json +117 -0
- package/themes/swiss-poster/variants/forest-amber.json +127 -0
- package/themes/swiss-poster/variants/forest-blue.json +118 -0
- package/themes/swiss-poster/variants/forest-jade.json +89 -0
- package/themes/swiss-poster/variants/frost-gold.json +128 -0
- package/themes/swiss-poster/variants/frost-indigo.json +117 -0
- package/themes/swiss-poster/variants/sand-magenta.json +126 -0
- package/themes/swiss-poster/variants/slate-orange.json +122 -0
- package/themes/swiss-poster/variants/slate-pink.json +126 -0
- package/themes/swiss-poster/variants/slate-violet.json +89 -0
- package/themes/water-works/THEME.md +61 -0
- package/themes/water-works/effects.ts +609 -0
- package/themes/water-works/sample/assets/og/logo.svg +12 -0
- package/themes/water-works/sample/beats.json +1005 -0
- package/themes/water-works/sample/index.html +11 -0
- package/themes/water-works/sample/kf.json +59 -0
- package/themes/water-works/sample/lib/facts.ts +29 -0
- package/themes/water-works/sample/lib/hall.ts +22 -0
- package/themes/water-works/sample/main.ts +9 -0
- package/themes/water-works/sample/scenes/end.ts +55 -0
- package/themes/water-works/sample/scenes/gather.ts +42 -0
- package/themes/water-works/sample/scenes/models.ts +51 -0
- package/themes/water-works/sample/scenes/price.ts +66 -0
- package/themes/water-works/sample/style.json +105 -0
- package/themes/water-works/slots.ts +140 -0
- package/themes/water-works/still.png +0 -0
- package/themes/water-works/style.json +105 -0
- package/themes/water-works/theme.json +140 -0
- package/themes/water-works/variants/blush-rose.json +123 -0
- package/themes/water-works/variants/chalk-blue.json +124 -0
- package/themes/water-works/variants/chalk-cyan-2.json +96 -0
- package/themes/water-works/variants/chalk-cyan.json +123 -0
- package/themes/water-works/variants/chalk-gold-mono.json +122 -0
- package/themes/water-works/variants/chalk-gold.json +123 -0
- package/themes/water-works/variants/chalk-green.json +123 -0
- package/themes/water-works/variants/frost-indigo.json +123 -0
- package/themes/water-works/variants/frost-rose.json +132 -0
- package/themes/water-works/variants/lilac-violet-mono.json +124 -0
- package/themes/water-works/variants/lilac-violet.json +133 -0
- package/themes/water-works/variants/sage-amber.json +133 -0
- package/themes/water-works/variants/sage-green.json +133 -0
- package/themes/water-works/variants/sand-amber.json +123 -0
- package/themes/water-works/variants/sand-plum.json +121 -0
- package/themes/whiteboard/THEME.md +78 -0
- package/themes/whiteboard/effects.ts +561 -0
- package/themes/whiteboard/sample/assets/og/logo.svg +12 -0
- package/themes/whiteboard/sample/beats.json +1005 -0
- package/themes/whiteboard/sample/index.html +11 -0
- package/themes/whiteboard/sample/kf.json +59 -0
- package/themes/whiteboard/sample/lib/board.ts +93 -0
- package/themes/whiteboard/sample/lib/facts.ts +29 -0
- package/themes/whiteboard/sample/main.ts +9 -0
- package/themes/whiteboard/sample/scenes/end.ts +59 -0
- package/themes/whiteboard/sample/scenes/gather.ts +50 -0
- package/themes/whiteboard/sample/scenes/models.ts +56 -0
- package/themes/whiteboard/sample/scenes/price.ts +79 -0
- package/themes/whiteboard/sample/style.json +106 -0
- package/themes/whiteboard/slots.ts +152 -0
- package/themes/whiteboard/still.png +0 -0
- package/themes/whiteboard/style.json +106 -0
- package/themes/whiteboard/theme.json +145 -0
- package/themes/whiteboard/variants/chalk-coral-do.json +126 -0
- package/themes/whiteboard/variants/chalk-coral.json +132 -0
- package/themes/whiteboard/variants/cream-lime.json +131 -0
- package/themes/whiteboard/variants/cream-plum.json +103 -0
- package/themes/whiteboard/variants/frost-teal-do.json +127 -0
- package/themes/whiteboard/variants/frost-teal.json +127 -0
- package/themes/whiteboard/variants/lilac-indigo.json +132 -0
- package/themes/whiteboard/variants/lilac-jade.json +103 -0
- package/themes/whiteboard/variants/sage-green.json +130 -0
- package/themes/whiteboard/variants/sage-plum.json +126 -0
- package/themes/whiteboard/variants/snow-amber.json +99 -0
- package/themes/whiteboard/variants/snow-cyan.json +132 -0
- package/themes/whiteboard/variants/snow-green.json +126 -0
- package/themes/whiteboard/variants/snow-magenta.json +126 -0
- package/themes/whiteboard/variants/snow-plum.json +130 -0
- /package/themes/{og-measure/sample/assets/brand/og-logo-full.svg → blueprint/sample/assets/og/logo.svg} +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// 테마 견본 칸 — 같은 문장 한 장면(쇼츠 첫 장면 hook-number)을 테마·변주마다 찍은 한 장. kf theme sheet·vary 와 kf make 테마 질문이 같이 쓴다.
|
|
2
|
+
// 변주는 세계 기본 판 표준 장면을 한 번 지어 두고 style.json 만 갈아 찍는다 — 감독이 고른 장면 문법이 같아야 겉모습만 견줄 수 있다.
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
|
+
import type { KfStyle } from "@kasaframe/core";
|
|
9
|
+
import { cellPath, loadTheme, themeDims, themesDir, type Theme } from "@kasaframe/themes";
|
|
10
|
+
import { launch } from "./browser.ts";
|
|
11
|
+
|
|
12
|
+
const kfBin = new URL("./kf.ts", import.meta.url).pathname;
|
|
13
|
+
const kf = (...a: string[]) => spawnSync(process.execPath, [kfBin, ...a], { encoding: "utf8" });
|
|
14
|
+
const tail = (r: { stdout?: string; stderr?: string }, n = 3) => `${r.stderr ?? ""}${r.stdout ?? ""}`.trim().split("\n").slice(-n).join(" / ");
|
|
15
|
+
|
|
16
|
+
export const SAMPLE = {
|
|
17
|
+
title: "kasaframe",
|
|
18
|
+
request: "테마 견본 — 같은 문장을 테마마다",
|
|
19
|
+
scenes: [{ id: "hook", type: "hook-number", value: 57, unit: "×", label: "KV 캐시가 이만큼 작아진다", source: "DeepSeek-V2 기술 보고서", dur: 4 }],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export interface Frame {
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
safe: { top: number; bottom: number; left: number; right: number };
|
|
26
|
+
/** 장면 끝 프레임 — 움직임이 다 앉은 자리 */
|
|
27
|
+
at: number;
|
|
28
|
+
dur: number;
|
|
29
|
+
pattern?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const readJson = (p: string) => JSON.parse(readFileSync(p, "utf8"));
|
|
33
|
+
|
|
34
|
+
function frameOf(dir: string): Frame {
|
|
35
|
+
const p = readJson(join(dir, "kf.json"));
|
|
36
|
+
const scene = p.scenes.find((x: { id: string }) => x.id === SAMPLE.scenes[0].id);
|
|
37
|
+
const d = existsSync(join(dir, "director.json")) ? readJson(join(dir, "director.json")) : null;
|
|
38
|
+
return { width: p.width, height: p.height, safe: p.safeArea, at: +(scene.from + scene.dur - 1 / p.fps).toFixed(4), dur: scene.dur, pattern: d?.scenes?.find((s: { id: string }) => s.id === scene.id)?.pattern };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** 표준 장면 프로젝트 — 감독이 짓고, check 면 검사 고리까지(떨어진 패턴은 감독이 다음 후보로). 1 = 다시 지어도 검사 오류가 남음 */
|
|
42
|
+
export function standardProject(theme: string, dir: string, o: { check: boolean }): { status: number; why: string; frame: Frame | null } {
|
|
43
|
+
rmSync(dir, { recursive: true, force: true });
|
|
44
|
+
let r = kf("new", dir, "--template", "shorts", "--theme", theme, "--title", SAMPLE.title, "--series", "none");
|
|
45
|
+
if (r.status === 0) {
|
|
46
|
+
writeFileSync(join(dir, "content.json"), `${JSON.stringify(SAMPLE, null, 2)}\n`);
|
|
47
|
+
r = kf("direct", dir, "--no-narrate", "--no-lock", ...(o.check ? [] : ["--no-check"]));
|
|
48
|
+
}
|
|
49
|
+
const built = r.status === 0 || r.status === 1;
|
|
50
|
+
return { status: r.status ?? 1, why: r.status === 0 ? "" : tail(r), frame: built && existsSync(join(dir, "director.json")) ? frameOf(dir) : null };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** 지어 둔 표준 장면에 테마(변주) style 만 갈아 끼운 복사본 — 장면 파일·패턴은 그대로 */
|
|
54
|
+
export function restyle(from: string, dir: string, id: string, style: KfStyle = loadTheme(id).style): void {
|
|
55
|
+
rmSync(dir, { recursive: true, force: true });
|
|
56
|
+
cpSync(from, dir, { recursive: true, filter: (src) => !src.startsWith(join(from, "out")) });
|
|
57
|
+
const was = readJson(join(from, "style.json"));
|
|
58
|
+
style = structuredClone(style);
|
|
59
|
+
// 틀의 움직임 규칙은 kf new 가 덮은 그대로 — 변주가 바꾸는 건 빠르기(durations)뿐
|
|
60
|
+
style.motion = { ...was.motion, ...(style.motion.durations ? { durations: style.motion.durations } : {}) };
|
|
61
|
+
writeFileSync(join(dir, "style.json"), `${JSON.stringify(style, null, 2)}\n`);
|
|
62
|
+
const p = readJson(join(dir, "kf.json"));
|
|
63
|
+
writeFileSync(join(dir, "kf.json"), `${JSON.stringify({ ...p, theme: id }, null, 2)}\n`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface Verdict {
|
|
67
|
+
ok: boolean;
|
|
68
|
+
/** 오류 규칙·한 줄 */
|
|
69
|
+
errors: string[];
|
|
70
|
+
ran: boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** kf check — 잠금은 부르는 쪽이 쥔다. from·to 를 주면 그 구간만(입체 세계는 무거워 끝 구간만) */
|
|
74
|
+
export function checkProject(dir: string, win?: { from: number; to: number }): Verdict {
|
|
75
|
+
const file = join(dir, "out", "check.json");
|
|
76
|
+
rmSync(file, { force: true });
|
|
77
|
+
const r = kf("check", dir, "--no-lock", "--tabs", "2", ...(win ? ["--from", String(win.from), "--to", String(win.to)] : []));
|
|
78
|
+
if (!existsSync(file)) return { ok: false, ran: false, errors: [`kf check 를 못 돌렸다(종료 ${r.status}) — ${tail(r)}`] };
|
|
79
|
+
const rep = readJson(file);
|
|
80
|
+
const errors = (rep.findings ?? []).filter((f: { severity: string }) => f.severity === "error").map((f: { rule: string; message: string }) => `${f.rule}: ${f.message}`);
|
|
81
|
+
return { ok: r.status === 0 && !errors.length, ran: true, errors };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function still(dir: string, at: number, out: string): string | null {
|
|
85
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
86
|
+
const r = kf("still", dir, "--t", String(at), "--out", out);
|
|
87
|
+
return r.status === 0 ? null : tail(r);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** 칸 그림을 36×64 로 줄인 RGB — 판끼리 얼마나 다른지 잰다 */
|
|
91
|
+
export function thumb(png: string): Uint8Array {
|
|
92
|
+
const r = spawnSync("ffmpeg", ["-v", "error", "-i", png, "-vf", "scale=36:64:flags=area", "-f", "rawvideo", "-pix_fmt", "rgb24", "-"], { maxBuffer: 1 << 20 });
|
|
93
|
+
return new Uint8Array(r.stdout ?? []);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** 0..1 — 평균 화소 차. 0.04 아래면 사람 눈에 같은 판 */
|
|
97
|
+
export function imageDiff(a: Uint8Array, b: Uint8Array): number {
|
|
98
|
+
if (!a.length || a.length !== b.length) return 1;
|
|
99
|
+
let s = 0;
|
|
100
|
+
for (let i = 0; i < a.length; i++) s += Math.abs(a[i] - b[i]);
|
|
101
|
+
return s / a.length / 255;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 칸 캐시 열쇠 — 겉모습(style)·견본 내용·세계 코드·견본 장면 문법(hook-number 패턴과 그 도구)이 같으면 같은 칸
|
|
105
|
+
const patternsDir = fileURLToPath(new URL("../../patterns/src/", import.meta.url));
|
|
106
|
+
const SAMPLE_CODE = [join(patternsDir, "kit.ts"), ...readdirSync(join(patternsDir, "hook-number")).sort().map((f) => join(patternsDir, "hook-number", f))];
|
|
107
|
+
|
|
108
|
+
export function cellKey(t: Theme): string {
|
|
109
|
+
const h = createHash("sha256");
|
|
110
|
+
h.update(JSON.stringify(t.style));
|
|
111
|
+
h.update(JSON.stringify(SAMPLE));
|
|
112
|
+
for (const f of ["effects.ts", "slots.ts"]) if (existsSync(join(themesDir, t.world, f))) h.update(readFileSync(join(themesDir, t.world, f)));
|
|
113
|
+
for (const f of SAMPLE_CODE) if (existsSync(f)) h.update(readFileSync(f));
|
|
114
|
+
return h.digest("hex").slice(0, 16);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const metaOf = (id: string) => cellPath(id).replace(/\.png$/, ".json");
|
|
118
|
+
|
|
119
|
+
export function cellFresh(t: Theme): boolean {
|
|
120
|
+
const m = metaOf(t.id);
|
|
121
|
+
return existsSync(cellPath(t.id)) && existsSync(m) && readJson(m).key === cellKey(t);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function markCell(t: Theme, frame: Frame): void {
|
|
125
|
+
writeFileSync(metaOf(t.id), `${JSON.stringify({ key: cellKey(t), at: frame.at, width: frame.width, height: frame.height, safe: frame.safe, pattern: frame.pattern ?? null }, null, 2)}\n`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const cellFrame = (id: string): Frame | null => (existsSync(metaOf(id)) ? readJson(metaOf(id)) : null);
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 칸이 없거나 낡은 테마만 찍는다(검사 없이 — 변주는 뽑을 때 검사를 넘었다). 세계마다 표준 장면을 한 번 짓고 변주는 style 만 갈아 찍는다.
|
|
132
|
+
* 돌려주는 것: id → 칸 경로(못 찍은 것은 빠진다)
|
|
133
|
+
*/
|
|
134
|
+
export function ensureCells(ids: string[], tmp: string, log: (l: string) => void = () => {}): Map<string, string> {
|
|
135
|
+
const out = new Map<string, string>();
|
|
136
|
+
const byWorld = new Map<string, Theme[]>();
|
|
137
|
+
for (const id of ids) {
|
|
138
|
+
const t = loadTheme(id);
|
|
139
|
+
if (cellFresh(t)) out.set(id, cellPath(id));
|
|
140
|
+
else byWorld.set(t.world, [...(byWorld.get(t.world) ?? []), t]);
|
|
141
|
+
}
|
|
142
|
+
for (const [world, list] of byWorld) {
|
|
143
|
+
const base = join(tmp, `${world}-base`);
|
|
144
|
+
const b = standardProject(world, base, { check: false });
|
|
145
|
+
if (!b.frame) {
|
|
146
|
+
log(`견본 칸 ${world}: 표준 장면을 못 지었다 — ${b.why}`);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
for (const t of list) {
|
|
150
|
+
const dir = t.variant ? join(tmp, t.id.replace("/", "--")) : base;
|
|
151
|
+
if (t.variant) restyle(base, dir, t.id);
|
|
152
|
+
const bad = still(dir, b.frame.at, cellPath(t.id));
|
|
153
|
+
if (bad) {
|
|
154
|
+
log(`견본 칸 ${t.id}: 못 찍음 — ${bad}`);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
markCell(t, b.frame);
|
|
158
|
+
out.set(t.id, cellPath(t.id));
|
|
159
|
+
log(`견본 칸 ${t.id}: ${cellPath(t.id)}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface GridCell {
|
|
166
|
+
png: string;
|
|
167
|
+
title: string;
|
|
168
|
+
sub?: string;
|
|
169
|
+
note?: string;
|
|
170
|
+
swatches?: string[];
|
|
171
|
+
badge?: string;
|
|
172
|
+
bad?: boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const esc = (s: string) => s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]!);
|
|
176
|
+
|
|
177
|
+
/** 칸 격자 한 장 — 안전 영역 점선, 이름·설명·색 견본 */
|
|
178
|
+
export async function gridSheet(cells: GridCell[], out: string, o: { heading: string; cols: number; w: number; frame: Pick<Frame, "width" | "height" | "safe"> }): Promise<string> {
|
|
179
|
+
const { w, cols, frame } = o;
|
|
180
|
+
const h = Math.round((w * frame.height) / frame.width);
|
|
181
|
+
const k = w / frame.width;
|
|
182
|
+
const html = `<!doctype html><meta charset="utf-8"><style>
|
|
183
|
+
body { margin: 0; padding: 24px; background: #111; font: 15px/1.35 -apple-system, "Apple SD Gothic Neo", sans-serif; color: #ddd; width: ${cols * w + (cols - 1) * 16}px; }
|
|
184
|
+
h1 { margin: 0 0 16px; font-size: 18px; font-weight: 600; color: #fff; }
|
|
185
|
+
main { display: grid; grid-template-columns: repeat(${cols}, ${w}px); gap: 22px 16px; }
|
|
186
|
+
figure { margin: 0; position: relative; }
|
|
187
|
+
.safe { position: absolute; left: 0; width: ${w}px; border-top: 2px dashed #ff4d4d; opacity: .8; }
|
|
188
|
+
img { display: block; width: ${w}px; height: ${h}px; outline: 1px solid #333; object-fit: cover; }
|
|
189
|
+
figcaption { padding: 8px 2px 0; }
|
|
190
|
+
b { color: #fff; }
|
|
191
|
+
.d { display: inline-block; margin-left: 6px; padding: 0 6px; border: 1px solid #666; border-radius: 4px; font-size: 12px; }
|
|
192
|
+
small { display: block; color: #999; font-size: 12.5px; word-break: keep-all; }
|
|
193
|
+
.sw { display: flex; gap: 3px; margin-top: 5px; }
|
|
194
|
+
.sw i { width: 18px; height: 12px; border-radius: 2px; outline: 1px solid #444; }
|
|
195
|
+
.bad { color: #ff6b6b; }
|
|
196
|
+
</style><h1>${esc(o.heading)}</h1><main>${cells
|
|
197
|
+
.map(
|
|
198
|
+
(c) =>
|
|
199
|
+
`<figure><img src="${pathToFileURL(c.png).href}"><div class="safe" style="top:${Math.round(frame.safe.top * k)}px"></div><div class="safe" style="top:${Math.round((frame.height - frame.safe.bottom) * k)}px"></div><figcaption><b>${esc(c.title)}</b>${c.badge ? `<span class="d">${esc(c.badge)}</span>` : ""}${c.sub ? `<small>${esc(c.sub)}</small>` : ""}${c.note ? `<small class="${c.bad ? "bad" : ""}">${esc(c.note)}</small>` : ""}${c.swatches ? `<div class="sw">${c.swatches.map((s) => `<i style="background:${s}"></i>`).join("")}</div>` : ""}</figcaption></figure>`,
|
|
200
|
+
)
|
|
201
|
+
.join("")}</main>`;
|
|
202
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
203
|
+
const page = out.replace(/\.png$/, ".html");
|
|
204
|
+
writeFileSync(page, html);
|
|
205
|
+
const browser = await launch();
|
|
206
|
+
try {
|
|
207
|
+
const p = await browser.newPage({ viewport: { width: 48 + cols * w + (cols - 1) * 16, height: 400 } });
|
|
208
|
+
await p.goto(pathToFileURL(page).href, { waitUntil: "load" });
|
|
209
|
+
writeFileSync(out, await p.screenshot({ fullPage: true, type: "png" }));
|
|
210
|
+
} finally {
|
|
211
|
+
await browser.close();
|
|
212
|
+
rmSync(page, { force: true });
|
|
213
|
+
}
|
|
214
|
+
return out;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** 격자 칸 글 — 이름·2D/3D·설명·색 견본 */
|
|
218
|
+
export function cellOf(t: Theme, png: string): GridCell {
|
|
219
|
+
const c = t.style.colors;
|
|
220
|
+
return {
|
|
221
|
+
png,
|
|
222
|
+
title: t.variant ? t.variant.name : `${t.name} · 기본`,
|
|
223
|
+
badge: themeDims(t),
|
|
224
|
+
sub: t.variant ? `${t.id} — ${t.variant.desc}` : `${t.id} — 세계 그대로`,
|
|
225
|
+
swatches: [c.bg, c.surface, c.ink, c.accent, c.success, c.danger],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
@@ -5,14 +5,27 @@ import { join } from "node:path";
|
|
|
5
5
|
import type { Command } from "../command.ts";
|
|
6
6
|
import { checks, pad, report } from "../deps.ts";
|
|
7
7
|
import { repoRoot } from "../serve.ts";
|
|
8
|
+
import { commandFor, isNewer, refresh } from "../update.ts";
|
|
9
|
+
|
|
10
|
+
async function versionLine(now: string): Promise<string> {
|
|
11
|
+
try {
|
|
12
|
+
const latest = await refresh(5000);
|
|
13
|
+
if (!isNewer(latest, now)) return `판: 지금 ${now} · 최신 ${latest} — 최신이다`;
|
|
14
|
+
const command = commandFor(latest);
|
|
15
|
+
return `판: 지금 ${now} · 최신 ${latest} · ${command ? `올리기 kf update (${command.join(" ")})` : "레포 체크아웃 — git pull"}`;
|
|
16
|
+
} catch (e) {
|
|
17
|
+
return `판: 지금 ${now} · 최신을 확인하지 못했다(${(e as Error).message}) — kf update --check`;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
8
20
|
|
|
9
21
|
const cmd: Command = {
|
|
10
|
-
summary: "바깥 도구 점검 — ffmpeg·크롬(Playwright)·python3+librosa·OG 키, 없으면 까는 명령",
|
|
22
|
+
summary: "바깥 도구 점검 — 판(지금·최신)·ffmpeg·크롬(Playwright)·python3+librosa·OG 키, 없으면 까는 명령",
|
|
11
23
|
usage: `kf doctor
|
|
12
24
|
없음 은 렌더가 안 되는 것, 선택 은 그 기능만 빠지는 것. 크롬·librosa 는 kf setup 이 깐다. 종료 코드: 없음 이 있으면 1`,
|
|
13
25
|
async run() {
|
|
14
26
|
const version = JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8")).version ?? "?";
|
|
15
|
-
console.log(`kasaframe ${version} · Node ${process.version} · ${platform()} ${arch()}
|
|
27
|
+
console.log(`kasaframe ${version} · Node ${process.version} · ${platform()} ${arch()}`);
|
|
28
|
+
console.log(`${await versionLine(version)}\n`);
|
|
16
29
|
const list = await checks();
|
|
17
30
|
report(list);
|
|
18
31
|
const missing = list.filter((c) => c.required && !c.ok);
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { basename, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { type FontPair, fontGroups, fontPairs } from "@kasaframe/themes/fonts";
|
|
7
|
+
import { type Command, parseFlags } from "../command.ts";
|
|
8
|
+
import { checkFonts, fontCacheDir, fontSheet, noticeSection, type PairReport, replaceNotice } from "../fonts.ts";
|
|
9
|
+
|
|
10
|
+
const cmd: Command = {
|
|
11
|
+
summary: "글꼴 짝 검사·견본 격자 — 주소·판·라이선스 글·한글 덮음·굵기, 크롬으로 찍어 투명·두부·떨어짐",
|
|
12
|
+
usage: `kf fonts list [--group <무리>]
|
|
13
|
+
kf fonts check [--group <무리>[,…]] [--id <짝>[,…]] [--json] [--no-render] [--offline]
|
|
14
|
+
kf fonts sheet [--group <무리>[,…]] [--id <짝>[,…]] [--out 파일.png] [--share]
|
|
15
|
+
kf fonts notice [--write]
|
|
16
|
+
|
|
17
|
+
짝 목록은 packages/themes/kit/fonts.json(무리 core)과 kit/fonts/<무리>.json 을 합친 것.
|
|
18
|
+
check 는 짝마다
|
|
19
|
+
- 칸: hangul(full|ks2350)·face 마다 license·source, 스택 첫 글꼴의 face, 모든 스택이 Pretendard Variable 로 끝남
|
|
20
|
+
- 주소: 파일·라이선스 글이 200, 판 박힘(jsdelivr gh@커밋|태그·npm@x.y.z — @main·@latest·@5 는 안 된다)
|
|
21
|
+
- 라이선스 글: OFL-1.1·Apache-2.0 은 글에 그 문구가 있는지. 목록 밖 이름은 사람이 읽을 것으로 남긴다
|
|
22
|
+
- 파일: 한글 음절 수(11,172 = full, KS X 1001 2,350 다 = ks2350, 그 아래는 탈락)와 적은 hangul 이 맞는지,
|
|
23
|
+
적은 굵기 범위가 파일(wght 축·usWeightClass)과 맞는지, 제목 굵기 단이 있는지(없으면 가짜 굵기)
|
|
24
|
+
- 크롬: 스택마다 한글·라틴·숫자 견본 한 줄을 찍어 투명·두부·시스템 글꼴로 떨어짐·예상과 다른 face 를 잡는다
|
|
25
|
+
받은 파일은 ${fontCacheDir()}/files 에 두고 다음부터는 주소가 살았는지만 묻는다. 문제가 있는 짝이 있으면 종료 1.
|
|
26
|
+
--json { pairs: [{ id, group, ok, hangul, syllables, boldest, licenses, problems, notes }], summary }
|
|
27
|
+
--no-render 크롬 없이(파일·주소만)
|
|
28
|
+
--offline 주소를 묻지 않고 캐시만(라이선스 글 대조도 건너뛴다)
|
|
29
|
+
sheet 는 짝마다 제목·본문·고정폭 견본 칸을 격자 한 장으로 — 기본 ${fontCacheDir()}/sheet[-<무리>].png.
|
|
30
|
+
--share 면 kasaterm 공유 폴더 kasaframe-글꼴 로 옮긴다.
|
|
31
|
+
notice 는 모든 무리를 합친 목록으로 NOTICE 의 글꼴 절(글꼴 이름 · 라이선스 · 라이선스 글)을 찍는다. --write 면 레포 NOTICE 에
|
|
32
|
+
그 절을 갈아 끼운다 — 무리 파일을 고친 뒤 한 번.`,
|
|
33
|
+
async run(argv) {
|
|
34
|
+
const [sub, ...rest] = argv;
|
|
35
|
+
const { opts } = parseFlags(rest);
|
|
36
|
+
const list = pick(opts);
|
|
37
|
+
if (!list) return 2;
|
|
38
|
+
if (sub === "list" || !sub) {
|
|
39
|
+
for (const { group, pair } of list) console.log(`${group.padEnd(10)} ${pair.id.padEnd(26)} ${String(pair.hangul ?? "?").padEnd(7)} ${pair.tags.join(",").padEnd(30)} ${pair.name}`);
|
|
40
|
+
console.log(`짝 ${list.length}`);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
if (sub === "check") {
|
|
44
|
+
const reports = await checkFonts(list, { offline: !!opts.offline, render: !opts["no-render"], log: (l) => console.error(l) });
|
|
45
|
+
const summary = summarize(reports);
|
|
46
|
+
if (opts.json) console.log(JSON.stringify({ pairs: reports, summary }, null, 1));
|
|
47
|
+
else print(reports, summary);
|
|
48
|
+
return reports.every((r) => r.ok) ? 0 : 1;
|
|
49
|
+
}
|
|
50
|
+
if (sub === "notice") {
|
|
51
|
+
const section = noticeSection(fontPairs());
|
|
52
|
+
if (!opts.write) {
|
|
53
|
+
process.stdout.write(section);
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
const file = fileURLToPath(new URL("../../../../NOTICE", import.meta.url));
|
|
57
|
+
writeFileSync(file, replaceNotice(readFileSync(file, "utf8"), section));
|
|
58
|
+
console.log(file);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
if (sub === "sheet") {
|
|
62
|
+
const groups = typeof opts.group === "string" ? opts.group.replace(/,/g, "+") : "";
|
|
63
|
+
const out = resolve(typeof opts.out === "string" ? opts.out : join(fontCacheDir(), `sheet${groups ? `-${groups}` : ""}.png`));
|
|
64
|
+
await fontSheet(list, out, { log: (l) => console.error(l) });
|
|
65
|
+
console.log(out);
|
|
66
|
+
if (opts.share) {
|
|
67
|
+
const r = spawnSync("kasaterm-cli", ["share", "new", "kasaframe-글꼴"], { encoding: "utf8" });
|
|
68
|
+
let dir = r.status === 0 ? (r.stdout.trim().split("\n").pop() ?? "") : "";
|
|
69
|
+
if (!dir || !existsSync(dir)) {
|
|
70
|
+
dir = join(homedir(), "Desktop", "kasaframe-글꼴");
|
|
71
|
+
mkdirSync(dir, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
copyFileSync(out, join(dir, basename(out)));
|
|
74
|
+
console.log(`공유 폴더 ${dir}`);
|
|
75
|
+
}
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
console.error(`kf fonts: 모르는 하위 명령 ${sub} — list·check·sheet·notice`);
|
|
79
|
+
return 2;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
function pick(opts: Record<string, string | boolean | undefined>): { group: string; pair: FontPair }[] | null {
|
|
84
|
+
const groups = fontGroups();
|
|
85
|
+
const want = typeof opts.group === "string" ? opts.group.split(",") : null;
|
|
86
|
+
const unknown = want?.filter((g) => !groups.some((x) => x.group === g));
|
|
87
|
+
if (unknown?.length) {
|
|
88
|
+
console.error(`kf fonts: 무리 ${unknown.join(",")} 가 없다 — 있는 무리: ${groups.map((g) => g.group).join(" ")}`);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const ids = typeof opts.id === "string" ? new Set(opts.id.split(",")) : null;
|
|
92
|
+
const list = groups.filter((g) => !want || want.includes(g.group)).flatMap((g) => g.pairs.map((pair) => ({ group: g.group, pair }))).filter(({ pair }) => !ids || ids.has(pair.id));
|
|
93
|
+
if (ids && list.length < ids.size) console.error(`kf fonts: 없는 짝 — ${[...ids].filter((i) => !list.some((x) => x.pair.id === i)).join(",")}`);
|
|
94
|
+
return list;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const tally = (xs: string[]) => Object.fromEntries([...new Set(xs)].sort().map((x) => [x, xs.filter((y) => y === x).length]));
|
|
98
|
+
|
|
99
|
+
function summarize(reports: PairReport[]) {
|
|
100
|
+
return {
|
|
101
|
+
pairs: reports.length,
|
|
102
|
+
ok: reports.filter((r) => r.ok).length,
|
|
103
|
+
hangul: tally(reports.map((r) => r.hangul ?? "?")),
|
|
104
|
+
licenses: tally(reports.flatMap((r) => r.licenses)),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function print(reports: PairReport[], s: ReturnType<typeof summarize>): void {
|
|
109
|
+
for (const r of reports) {
|
|
110
|
+
console.log(`${r.ok ? "ok " : "문제"} ${r.group.padEnd(10)} ${r.id.padEnd(26)} 한글 ${r.hangul ?? "?"}(${r.syllables ?? "?"}) · 굵은 단 ${r.boldest ?? "?"} · ${r.licenses.join(",")}`);
|
|
111
|
+
for (const p of r.problems) console.log(` ! ${p}`);
|
|
112
|
+
for (const n of r.notes) console.log(` · ${n}`);
|
|
113
|
+
}
|
|
114
|
+
const fmt = (o: Record<string, number>) => Object.entries(o).map(([k, v]) => `${k} ${v}`).join(" · ");
|
|
115
|
+
console.log(`\n짝 ${s.pairs} — 통과 ${s.ok} · 문제 ${s.pairs - s.ok} | 한글 ${fmt(s.hangul)} | 라이선스(짝 기준) ${fmt(s.licenses)}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export default cmd;
|
|
@@ -4,14 +4,15 @@ import { basename, dirname, extname, join, resolve } from "node:path";
|
|
|
4
4
|
import { createInterface } from "node:readline/promises";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { askTerminal, blenderLibDir, capabilities, genImage, genVideo, hasKey, NeedsApproval, parseAllow, type Question, questionsText, seam, seamFrames, settle, still, whereToPut } from "@kasaframe/gen";
|
|
7
|
-
import { applyAnswers, attachStudio, loadSeries, type Series, seriesFromRequest, chat, codeBlock, detect, formatLook, jsonBlock, listTemplates, loadTemplate, look, lookSheet, makePlan, type Message, type Plan, planQuestions, premiumBlock, projectBrief, PURPOSES, type Purpose, readProject, spend, spentLine, WAIT, writeCaptions, writeStats } from "@kasaframe/plan";
|
|
7
|
+
import { applyAnswers, attachStudio, type LookInput, loadSeries, suggestThemes, usableTheme, type Series, seriesFromRequest, chat, codeBlock, detect, formatLook, jsonBlock, listTemplates, loadTemplate, look, lookSheet, makePlan, type Message, type Plan, planQuestions, premiumBlock, projectBrief, PURPOSES, type Purpose, readProject, spend, spentLine, WAIT, writeCaptions, writeStats } from "@kasaframe/plan";
|
|
8
8
|
import { checkContent, contentPrompt, directBrief } from "@kasaframe/director";
|
|
9
9
|
import { transform } from "esbuild";
|
|
10
10
|
import { bundleFor, dressSeed, pickDress } from "@kasaframe/motion/menu";
|
|
11
|
-
import { themeStyle } from "@kasaframe/themes";
|
|
11
|
+
import { themeStyle, worldOf } from "@kasaframe/themes";
|
|
12
12
|
import { captionMode } from "@kasaframe/motion/captions";
|
|
13
13
|
import { jizuraCheck } from "@kasaframe/jizura/install";
|
|
14
14
|
import { openPage } from "../browser.ts";
|
|
15
|
+
import { askThemeTerminal, candidateSheet, refLook } from "../pick.ts";
|
|
15
16
|
import { librosa } from "../deps.ts";
|
|
16
17
|
import { lyricsCheck } from "./lyrics.ts";
|
|
17
18
|
import { type Command, num, parseFlags } from "../command.ts";
|
|
@@ -92,8 +93,11 @@ kf make --answer <폴더> --image <값> --video <값> … Claude Code 모드
|
|
|
92
93
|
끝날 때(성공·실패·중단) <작업 폴더>/make-stats.json 에 단계별 모델·ms·토큰·usd 와 합계를 남기고 「OG 호출 N번 · 토큰 · $」 한 줄을 찍는다
|
|
93
94
|
--series 시리즈 묶음(series/<id>.json) · none. 안 주면 요청이 짚은 시리즈(「OG 쇼츠」처럼) — 용도·테마·목소리·곡·자막·길이·끝 카드·생성 답을 묻지 않고 그 묶음대로
|
|
94
95
|
--purpose 용도를 못 박는다: ${PURPOSES.join(" · ")}
|
|
95
|
-
--theme 테마 id · auto(요청이 「리소 느낌」처럼 짚은 테마, 아니면
|
|
96
|
-
안 주면(시리즈가 정하지도 않았으면) 묻는다 — 보기는
|
|
96
|
+
--theme 테마 id·변주 「<세계>/<변주>」 · auto(요청이 「리소 느낌」처럼 짚은 테마, 아니면 요청·분위기에 맞는 approved 후보 중 첫째) · none(프리셋만)
|
|
97
|
+
안 주면(시리즈가 정하지도 않았으면) 묻는다 — 보기는 「알아서」(= auto)와 요청·용도·분위기 낱말에 맞는 approved 세계·변주 넷,
|
|
98
|
+
넷만 담은 견본 시트를 그 자리에서 만든다(칸은 캐시). 테마 이름이 아닌 말을 주면 분위기 한 마디로 읽는다
|
|
99
|
+
--theme-mood 분위기 한 마디(「따뜻한 종이 느낌」·「어두운 네온」) — 그걸로 후보 넷을 다시 고른다. --answer 와 함께 주면 다시 묻는다
|
|
100
|
+
--theme-ref 레퍼런스 그림 경로·그림 주소·웹 페이지 주소 — 바탕·강조색을 읽어 후보 넷을 다시 고른다
|
|
97
101
|
--yes 묻지 않고 권장 답으로 — 돈이 드는 그림·영상도 승인한다(지역 제한이 걸린 H3 는 --video h3-pod 로 짚어야만)
|
|
98
102
|
--max-usd 영상 하나 상한(기본 1)
|
|
99
103
|
--video-provider 영상 공급자를 못 박는다(예: h3-pod — KF_H3_URL·KF_H3_STEPS 필요). 기본은 KF_VIDEO_PROVIDER, 없으면 생성 담당 기본
|
|
@@ -228,6 +232,13 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
228
232
|
return 2;
|
|
229
233
|
}
|
|
230
234
|
const assetFiles = str("assets") ? listFiles(resolve(str("assets")!)) : [];
|
|
235
|
+
let themeLook: LookInput;
|
|
236
|
+
try {
|
|
237
|
+
themeLook = await lookFlags(opts);
|
|
238
|
+
} catch (e) {
|
|
239
|
+
console.error(`kf make: ${(e as Error).message}`);
|
|
240
|
+
return 2;
|
|
241
|
+
}
|
|
231
242
|
// 시리즈가 먼저 — 같은 시리즈면 매번 같은 묶음. 사람이 따로 준 플래그는 그대로 이긴다
|
|
232
243
|
const series: Series | null = str("series") === "none" ? null : str("series") ? loadSeries(str("series")!) : seriesFromRequest(request);
|
|
233
244
|
if (series) console.error(`시리즈 ${series.id}(${series.label}) — 용도·테마·목소리·곡·자막·길이·끝 카드를 묶음대로`);
|
|
@@ -256,8 +267,10 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
256
267
|
|
|
257
268
|
// 만들기 전에 묻는다 — 뼈대를 만들고 나서 멈추면 반쯤 만든 폴더가 남는다
|
|
258
269
|
const caps = await capabilities({ probe: true });
|
|
259
|
-
const draft = makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none" });
|
|
270
|
+
const draft = makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none", look: themeLook });
|
|
260
271
|
const { questions, auto } = planQuestions(draft, caps);
|
|
272
|
+
// 테마를 물을 거면 후보 넷 견본 시트를 그 자리에서 — 질문 글에 시트 경로가 붙는다
|
|
273
|
+
const themeQ = questions.find((q) => q.id === "theme");
|
|
261
274
|
const flags = { ...seriesAnswers(series), ...opts };
|
|
262
275
|
const settled = settle(questions, { given: flags, yes: !!opts.yes, noGen: !!opts["no-gen"], allow: parseAllow(opts.allow) });
|
|
263
276
|
// 묻지 않고 정한 답(있는 공짜 능력)도 사람이 준 플래그·시리즈 답이 이긴다. --no-gen 이면 공짜라도 생성 모델(그림·영상)은 뺀다
|
|
@@ -282,6 +295,20 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
282
295
|
answers = { ...answers, ...asked };
|
|
283
296
|
}
|
|
284
297
|
if (answers.beats === "none" && answers.music && !/^(gen:|none$)/.test(answers.music)) answers.music = "none";
|
|
298
|
+
if (themeQ && open.includes(themeQ)) await candidateSheet(themeQ, (l) => console.error(l));
|
|
299
|
+
// 터미널이면 테마는 따로 — 분위기 한 마디·그림 경로·주소를 치면 그걸로 후보를 다시 골라 다시 묻는다
|
|
300
|
+
if (themeQ && open.includes(themeQ) && model !== "claude-code") {
|
|
301
|
+
const picked = await askThemeTerminal(themeQ, async (r) => {
|
|
302
|
+
themeLook = { ...themeLook, ...r, ...(r.mood ? { mood: [themeLook.mood, r.mood].filter(Boolean).join(" ") } : {}) };
|
|
303
|
+
const q = planQuestions(makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none", look: themeLook }), caps).questions.find((x) => x.id === "theme")!;
|
|
304
|
+
await candidateSheet(q, (l) => console.error(l));
|
|
305
|
+
return q;
|
|
306
|
+
});
|
|
307
|
+
if (picked) {
|
|
308
|
+
answers.theme = picked;
|
|
309
|
+
open = open.filter((q) => q !== themeQ);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
285
312
|
if (open.length && model !== "claude-code") {
|
|
286
313
|
const asked = await askTerminal(open);
|
|
287
314
|
if (!asked) {
|
|
@@ -307,7 +334,10 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
307
334
|
if (song) newArgs.push("--music", song);
|
|
308
335
|
if (str("title")) newArgs.push("--title", str("title")!);
|
|
309
336
|
// 테마 질문의 답(플래그·터미널) → 아직 묻는 중이거나 묻지 않은 테마(시리즈·요청이 짚은 것)는 auto. 테마 없이 프리셋만 쓰려면 --theme none
|
|
310
|
-
|
|
337
|
+
// 「알아서」·묻는 중이면 후보 첫째 — 분위기·레퍼런스로 고른 넷이라 kf new 의 auto(요청 낱말만)와 다를 수 있다
|
|
338
|
+
const firstPick = themeQ?.choices.find((c) => c.value !== "auto")?.value;
|
|
339
|
+
const themeArg = answers.theme && answers.theme !== WAIT && answers.theme !== "auto" ? answers.theme : (str("theme") ?? (firstPick && (answers.theme === "auto" || open.includes(themeQ!)) ? firstPick : "auto"));
|
|
340
|
+
newArgs.push("--theme", themeArg);
|
|
311
341
|
if (opts.force) newArgs.push("--force");
|
|
312
342
|
const made = spawnSync(process.execPath, newArgs, { stdio: ["ignore", "inherit", "inherit"] });
|
|
313
343
|
if (made.status !== 0) return made.status ?? 1;
|
|
@@ -315,7 +345,7 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
315
345
|
const studio = await attachStudio({ dir, request, model, purpose });
|
|
316
346
|
const unmirror = studio?.mirror();
|
|
317
347
|
if (studio) console.log(`작업실: ${studio.url}`);
|
|
318
|
-
const plan: Plan = { ...applyAnswers(JSON.parse(readFileSync(join(dir, "plan.json"), "utf8")), answers).plan, asks: open };
|
|
348
|
+
const plan: Plan = { ...applyAnswers(JSON.parse(readFileSync(join(dir, "plan.json"), "utf8")), answers).plan, asks: open, ...(themeLook.mood || themeLook.ref ? { themeLook } : {}) };
|
|
319
349
|
// 새 프로젝트는 이 영상의 기본으로 적는다 — 계획 다듬기가 내레이션을 쓸지도 이걸 본다
|
|
320
350
|
if (captions) {
|
|
321
351
|
const kfPath = join(dir, "kf.json");
|
|
@@ -582,6 +612,19 @@ async function probeScene(dir: string, id: string): Promise<string[]> {
|
|
|
582
612
|
return [...new Set(problems)];
|
|
583
613
|
}
|
|
584
614
|
|
|
615
|
+
// 테마 고르기 플래그 — --theme-mood·--theme-ref, 그리고 테마 이름이 아닌 --theme 값(분위기 한 마디로 읽는다)
|
|
616
|
+
async function lookFlags(opts: Record<string, string | boolean | undefined>): Promise<LookInput> {
|
|
617
|
+
const look: LookInput = {};
|
|
618
|
+
const theme = typeof opts.theme === "string" ? opts.theme : undefined;
|
|
619
|
+
if (theme && theme !== "auto" && theme !== "none" && !usableTheme(theme)) {
|
|
620
|
+
look.mood = theme;
|
|
621
|
+
delete opts.theme;
|
|
622
|
+
}
|
|
623
|
+
if (typeof opts["theme-mood"] === "string") look.mood = [look.mood, opts["theme-mood"]].filter(Boolean).join(" ");
|
|
624
|
+
if (typeof opts["theme-ref"] === "string") look.ref = await refLook(opts["theme-ref"]);
|
|
625
|
+
return look;
|
|
626
|
+
}
|
|
627
|
+
|
|
585
628
|
// 테마 후보마다 첫 장면을 그 테마로 한 장 — 사람이 셋을 나란히 보고 고른다. style.json 만 잠깐 바꿔 찍고 되돌린다
|
|
586
629
|
function themeStills(dir: string, ids: string[]): void {
|
|
587
630
|
const stylePath = join(dir, "style.json");
|
|
@@ -734,6 +777,30 @@ async function answerProject(dir: string, opts: Record<string, string | boolean
|
|
|
734
777
|
return 2;
|
|
735
778
|
}
|
|
736
779
|
const plan: Plan = JSON.parse(readFileSync(file, "utf8"));
|
|
780
|
+
// 테마에 분위기 한 마디·레퍼런스를 줬으면 후보 넷을 다시 고르고 견본 시트를 새로 만들어 다시 묻는다 — 답은 그다음
|
|
781
|
+
let look: LookInput;
|
|
782
|
+
try {
|
|
783
|
+
look = await lookFlags(opts);
|
|
784
|
+
} catch (e) {
|
|
785
|
+
console.error(`kf make --answer: ${(e as Error).message}`);
|
|
786
|
+
return 2;
|
|
787
|
+
}
|
|
788
|
+
if (look.mood || look.ref) {
|
|
789
|
+
plan.themeLook = { ...plan.themeLook, ...look, ...(look.mood ? { mood: [plan.themeLook?.mood, look.mood].filter(Boolean).join(" ") } : {}) };
|
|
790
|
+
const q = planQuestions(plan, await capabilities({ probe: false })).questions.find((x) => x.id === "theme");
|
|
791
|
+
if (!q) {
|
|
792
|
+
console.error("kf make --answer: 이 프로젝트는 테마를 묻지 않는다(시리즈나 요청이 테마를 정했다) — --theme <id> 로 바꾼다");
|
|
793
|
+
return 2;
|
|
794
|
+
}
|
|
795
|
+
const sheet = await candidateSheet(q, (l) => console.error(l));
|
|
796
|
+
plan.asks = [...(plan.asks ?? []).filter((x) => x.id !== "theme"), q];
|
|
797
|
+
writeJson(file, plan);
|
|
798
|
+
writeFileSync(join(dir, "MAKE.md"), isDirect(dir) ? directBrief(dir) : projectBrief(dir));
|
|
799
|
+
console.log(`테마 후보를 다시 골랐다${sheet ? ` — 견본 시트 ${sheet}` : ""}:`);
|
|
800
|
+
for (const c of q.choices) console.log(` --theme ${c.value.padEnd(30)} ${c.label}${c.note ? ` — ${c.note}` : ""}`);
|
|
801
|
+
console.error("사람에게 다시 묻고 kf make --answer <폴더> --theme <값> 으로 답을 넣는다");
|
|
802
|
+
return 3;
|
|
803
|
+
}
|
|
737
804
|
const waiting = new Set((plan.asks ?? []).map((q) => q.id));
|
|
738
805
|
const fresh = planQuestions(plan, await capabilities({ probe: true })).questions.filter((q) => waiting.has(q.id));
|
|
739
806
|
const settled = settle(fresh, { given: opts, yes: !!opts.yes, noGen: !!opts["no-gen"], allow: parseAllow(opts.allow) });
|
|
@@ -765,7 +832,8 @@ function retheme(dir: string, answer: string): string | null {
|
|
|
765
832
|
const plan = readPlan(dir) as Plan;
|
|
766
833
|
const kfPath = join(dir, "kf.json");
|
|
767
834
|
const kf = JSON.parse(readFileSync(kfPath, "utf8"));
|
|
768
|
-
const id: string | null =
|
|
835
|
+
const id: string | null =
|
|
836
|
+
answer === "auto" ? (suggestThemes(plan.request, plan.purpose, plan.aspect, 1, plan.themeLook ?? {})[0]?.id ?? plan.themeCandidates?.[0]?.id ?? kf.theme ?? null) : answer === "none" ? null : answer;
|
|
769
837
|
if ((kf.theme ?? null) === id) return id;
|
|
770
838
|
const tpl = loadTemplate(plan.purpose);
|
|
771
839
|
// 프리셋으로 돌아가면 kf new 가 테마 없이 골랐을 프리셋 — 시리즈·요청 낱말·틀 차례
|
|
@@ -774,7 +842,7 @@ function retheme(dir: string, answer: string): string | null {
|
|
|
774
842
|
style.motion = { ...style.motion, ...tpl.motion };
|
|
775
843
|
writeJson(join(dir, "style.json"), style);
|
|
776
844
|
if (tpl.moves) {
|
|
777
|
-
const dress = pickDress(dressSeed(plan.request || plan.title, plan.purpose, id ?? preset!), plan.scenes, bundleFor(tpl.moves, id ?? undefined));
|
|
845
|
+
const dress = pickDress(dressSeed(plan.request || plan.title, plan.purpose, worldOf(id) ?? preset!), plan.scenes, bundleFor(tpl.moves, id ?? undefined));
|
|
778
846
|
const byId = new Map(plan.scenes.map((s, i) => [s.id, dress[i]]));
|
|
779
847
|
for (const s of kf.scenes as { id: string; file: string; dress?: Record<string, string> }[]) {
|
|
780
848
|
const next = byId.get(s.id);
|
|
@@ -3,7 +3,7 @@ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFi
|
|
|
3
3
|
import { basename, join, relative, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { bundleFor, dressSeed, NO_DRESS, pickDress } from "@kasaframe/motion/menu";
|
|
6
|
-
import { themeStyle } from "@kasaframe/themes";
|
|
6
|
+
import { themeStyle, worldOf } from "@kasaframe/themes";
|
|
7
7
|
import { type Aspect, type BeatsLike, type Plan, type Purpose, listTemplates, loadTemplate, makePlan, parseTitle, PURPOSES, sceneSkeleton, templatesDir } from "@kasaframe/plan";
|
|
8
8
|
import { type Command, num, parseFlags } from "../command.ts";
|
|
9
9
|
|
|
@@ -116,7 +116,7 @@ kf new <폴더> --plan plan.json kf make 가 세운 계
|
|
|
116
116
|
|
|
117
117
|
// 장면마다 연출 수(바탕·글·경계 덮기) — 용도 틀·테마 묶음에서 요청 글을 씨앗으로 고른다. 같은 요청이면 같은 수가 걸린다
|
|
118
118
|
// 틀에 묶음이 없으면(뮤비 — 가사 층이 화면을 맡는다) 무대 기본 그대로
|
|
119
|
-
const dress = tpl.moves ? pickDress(dressSeed(plan.request || plan.title, plan.purpose, plan.theme ?? plan.style), plan.scenes, bundleFor(tpl.moves, plan.theme ?? undefined)) : plan.scenes.map(() => ({ ...NO_DRESS }));
|
|
119
|
+
const dress = tpl.moves ? pickDress(dressSeed(plan.request || plan.title, plan.purpose, worldOf(plan.theme) ?? plan.style), plan.scenes, bundleFor(tpl.moves, plan.theme ?? undefined)) : plan.scenes.map(() => ({ ...NO_DRESS }));
|
|
120
120
|
|
|
121
121
|
const frame = { width: plan.width, height: plan.height };
|
|
122
122
|
const safeArea = plan.aspect === tpl.aspect ? tpl.safeArea : (tpl.variants?.[plan.aspect]?.safeArea ?? tpl.safeArea);
|