@liustack/pptfast 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/README.zh-CN.md +93 -0
- package/dist/chunk-4WISUDXE.js +34 -0
- package/dist/chunk-4WISUDXE.js.map +1 -0
- package/dist/chunk-DVMJWFDL.js +14465 -0
- package/dist/chunk-DVMJWFDL.js.map +1 -0
- package/dist/chunk-G76EVNVT.js +14 -0
- package/dist/chunk-G76EVNVT.js.map +1 -0
- package/dist/cli.js +155 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +1076 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +6 -0
- package/dist/node.js +11 -0
- package/dist/node.js.map +1 -0
- package/dist/registry-CYKxZ0-U.d.ts +11 -0
- package/package.json +87 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Leon Liu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# pptfast
|
|
2
|
+
|
|
3
|
+
Stable, editable PPTX generation for AI agents — semantic IR in, native
|
|
4
|
+
DrawingML out.
|
|
5
|
+
|
|
6
|
+
[English] | [简体中文](./README.zh-CN.md)
|
|
7
|
+
|
|
8
|
+
## Why
|
|
9
|
+
|
|
10
|
+
Freeform SVG/HTML-to-PPTX pipelines have a high ceiling but an unstable floor — a weak model (or a strong one having an off turn) produces a deck that's broken, off-brand, or unreadable. pptfast trades freeform drawing for a controlled vocabulary: a semantic IR (zod schema), 13 built-in themes driven by design tokens, an archetype/block layout library with seeded variety, and native DrawingML output where every shape stays editable — not a picture pasted onto a slide.
|
|
11
|
+
|
|
12
|
+
A deck is really five things: a content model, a 2D layout, a visual style, motion, and a narrative. pptfast owns the last four — you (or your agent) own the content model by writing the IR.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g @liustack/pptfast
|
|
18
|
+
pptfast --help
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Node >= 18. Or build from source: `git clone https://github.com/liustack/pptfast.git && cd pptfast && pnpm install && pnpm build`.
|
|
22
|
+
|
|
23
|
+
## Quick start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
node dist/cli.js validate examples/basic.json
|
|
27
|
+
# → OK — 5 slides, theme "consulting"
|
|
28
|
+
node dist/cli.js render examples/basic.json -o out/basic.pptx
|
|
29
|
+
# → wrote out/basic.pptx (5 slides, ~29 KB)
|
|
30
|
+
node dist/cli.js render examples/basic.json -o out/basic-tech.pptx --theme tech
|
|
31
|
+
node dist/cli.js preview examples/basic.json -o out/svgs # SVG per slide, for a visual self-check
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or drive the SDK directly (Node requires `installNodePlatform()` once, before
|
|
35
|
+
any render call — the CLI does this for you):
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { installNodePlatform } from "@liustack/pptfast/node"
|
|
39
|
+
import { generatePptx } from "@liustack/pptfast"
|
|
40
|
+
|
|
41
|
+
installNodePlatform()
|
|
42
|
+
const bytes = await generatePptx(ir) // Uint8Array, ready to write to a .pptx
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## CLI
|
|
46
|
+
|
|
47
|
+
| Command | Does |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `render <ir.json> -o <out.pptx> [--theme <id>]` | Validate + render to a `.pptx` |
|
|
50
|
+
| `validate <ir.json>` | Check the IR, print page-scoped errors |
|
|
51
|
+
| `schema` | Print the IR JSON Schema |
|
|
52
|
+
| `themes [--json]` | List the 13 built-in themes |
|
|
53
|
+
| `preview <ir.json> -o <dir>` | Render each slide to a standalone SVG |
|
|
54
|
+
|
|
55
|
+
## The IR
|
|
56
|
+
|
|
57
|
+
Run `node dist/cli.js schema` for the full JSON Schema — feed it to a model before asking it to write IR. A deck (`PptxIR`) is a required `filename`, `version`, `theme`, `meta`, `assets`, an optional `brand`, and an ordered list of `slides`; each slide has a `type` (`cover`, `chapter`, `content`, `ending`) and, for content slides, a list of typed `blocks` (`bullets`, `kpi_cards`, `image`, `chart`, …). `assets` is `{ images: { [id]: { src, alt? } } }` — blocks reference images by `asset_id`, so the same image can be reused across slides without duplication.
|
|
58
|
+
|
|
59
|
+
## Themes
|
|
60
|
+
|
|
61
|
+
Each theme is a token set (color, type, motif) plus a manifest of which archetypes it allows — themes never touch layout code.
|
|
62
|
+
|
|
63
|
+
| id | label |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `consulting` | Business Consulting |
|
|
66
|
+
| `enterprise` | Enterprise |
|
|
67
|
+
| `academic` | Academic |
|
|
68
|
+
| `insight` | Financial Insight |
|
|
69
|
+
| `campaign` | Marketing Campaign |
|
|
70
|
+
| `bloom` | Soft Bloom |
|
|
71
|
+
| `classroom` | Classroom |
|
|
72
|
+
| `ink` | Ink Wash |
|
|
73
|
+
| `tech` | Tech |
|
|
74
|
+
| `runway` | Fashion Runway |
|
|
75
|
+
| `journal` | Editorial Journal |
|
|
76
|
+
| `luxe` | Luxe |
|
|
77
|
+
| `heritage` | Heritage |
|
|
78
|
+
|
|
79
|
+
## For AI agents
|
|
80
|
+
|
|
81
|
+
The recommended loop for an agent generating a deck: read `pptfast schema` to learn the vocabulary, write an IR JSON, run `pptfast validate` and fix whatever it reports (errors carry a page number and a fixable-in-place message — the point is to close this loop without a human), then `pptfast render`. `pptfast preview` gives the agent SVG files it can look at to self-check layout before committing to a render. A Claude Code plugin that wraps this loop as a skill is planned for v0.2 (see Roadmap).
|
|
82
|
+
|
|
83
|
+
## Roadmap
|
|
84
|
+
|
|
85
|
+
- **v0.2** — Claude Code plugin + skills wrapping the render loop, design token overrides (`--tokens`), `init`/self-update commands.
|
|
86
|
+
- **v0.3** — theme-customization skill (brand colors → tokens), custom manifest slots, 1.0.
|
|
87
|
+
- **v0.4** — richer motion (more entrance animations), Office real-device testing, web playground.
|
|
88
|
+
|
|
89
|
+
## Credits
|
|
90
|
+
|
|
91
|
+
Icon primitives are extracted from [lucide](https://lucide.dev) (ISC License). pptfast itself was extracted from a production AI-deck-generation system and CJK-typography-tuned (full-width punctuation width, Chinese line breaking, a Chinese-first font stack) from day one.
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
[MIT](./LICENSE)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# pptfast
|
|
2
|
+
|
|
3
|
+
面向 AI agent 的稳定、可编辑 PPTX 生成工具:输入语义化 IR,输出原生 DrawingML。
|
|
4
|
+
|
|
5
|
+
[English](./README.md) | [简体中文]
|
|
6
|
+
|
|
7
|
+
## 为什么
|
|
8
|
+
|
|
9
|
+
自由绘制 SVG/HTML 再转 PPTX 的链路上限很高,但下限不稳定——弱模型(或强模型状态不好时)画出来的往往是版式错乱、脱离品牌规范、甚至无法阅读的产物。pptfast 用受控词汇取代自由绘制:一份语义化 IR(zod schema)、由 design tokens 驱动的 13 个内置主题、带 seed 多样性的 archetype/block 版式库,以及每个图形都保持可编辑的原生 DrawingML 输出——不是贴上去的一张图。
|
|
10
|
+
|
|
11
|
+
一份 PPT 本质上是五件事:内容模型、二维布局、视觉样式、动效、叙事。pptfast 负责后四项,内容模型交给你(或你的 agent)通过写 IR 来掌控。
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g @liustack/pptfast
|
|
17
|
+
pptfast --help
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
需要 Node >= 18。也可从源码构建:`git clone https://github.com/liustack/pptfast.git && cd pptfast && pnpm install && pnpm build`。
|
|
21
|
+
|
|
22
|
+
## 快速开始
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node dist/cli.js validate examples/basic.json
|
|
26
|
+
# → OK — 5 slides, theme "consulting"
|
|
27
|
+
node dist/cli.js render examples/basic.json -o out/basic.pptx
|
|
28
|
+
# → wrote out/basic.pptx (5 slides, ~29 KB)
|
|
29
|
+
node dist/cli.js render examples/basic.json -o out/basic-tech.pptx --theme tech
|
|
30
|
+
node dist/cli.js preview examples/basic.json -o out/svgs # 每页一张 SVG,供人工目检
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
也可以直接调用 SDK(Node 环境下渲染前需先调用一次 `installNodePlatform()`,CLI 内部已经帮你调过):
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { installNodePlatform } from "@liustack/pptfast/node"
|
|
37
|
+
import { generatePptx } from "@liustack/pptfast"
|
|
38
|
+
|
|
39
|
+
installNodePlatform()
|
|
40
|
+
const bytes = await generatePptx(ir) // Uint8Array,可直接写成 .pptx 文件
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## CLI
|
|
44
|
+
|
|
45
|
+
| 命令 | 作用 |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `render <ir.json> -o <out.pptx> [--theme <id>]` | 校验并渲染成 `.pptx` |
|
|
48
|
+
| `validate <ir.json>` | 校验 IR,输出带页码的错误信息 |
|
|
49
|
+
| `schema` | 输出 IR 的 JSON Schema |
|
|
50
|
+
| `themes [--json]` | 列出 13 个内置主题 |
|
|
51
|
+
| `preview <ir.json> -o <dir>` | 逐页渲染为独立 SVG |
|
|
52
|
+
|
|
53
|
+
## IR
|
|
54
|
+
|
|
55
|
+
运行 `node dist/cli.js schema` 获取完整 JSON Schema——让模型写 IR 之前先读它。一份 deck(`PptxIR`)由必填的 `filename`、`version`、`theme`、`meta`、`assets`、可选的 `brand`,和一个有序的 `slides` 列表组成。每张 slide 有一个 `type`(`cover`、`chapter`、`content`、`ending`),content 类型的 slide 还带一组带类型的 `blocks`(`bullets`、`kpi_cards`、`image`、`chart` 等)。`assets` 的形状是 `{ images: { [id]: { src, alt? } } }`,block 通过 `asset_id` 引用图片,同一张图可以在多页复用而不必重复内嵌。
|
|
56
|
+
|
|
57
|
+
## 主题
|
|
58
|
+
|
|
59
|
+
每个主题是一组 token(配色、字体、motif)加一份 manifest(声明允许使用哪些 archetype)——主题本身从不涉及布局代码。
|
|
60
|
+
|
|
61
|
+
| id | label |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `consulting` | Business Consulting |
|
|
64
|
+
| `enterprise` | Enterprise |
|
|
65
|
+
| `academic` | Academic |
|
|
66
|
+
| `insight` | Financial Insight |
|
|
67
|
+
| `campaign` | Marketing Campaign |
|
|
68
|
+
| `bloom` | Soft Bloom |
|
|
69
|
+
| `classroom` | Classroom |
|
|
70
|
+
| `ink` | Ink Wash |
|
|
71
|
+
| `tech` | Tech |
|
|
72
|
+
| `runway` | Fashion Runway |
|
|
73
|
+
| `journal` | Editorial Journal |
|
|
74
|
+
| `luxe` | Luxe |
|
|
75
|
+
| `heritage` | Heritage |
|
|
76
|
+
|
|
77
|
+
## 面向 AI agent
|
|
78
|
+
|
|
79
|
+
推荐给 agent 的生成回路:先读 `pptfast schema` 学词汇表,写出 IR JSON,跑 `pptfast validate` 并根据报错自纠(错误信息带页码和可直接照抄的修正方式,目的就是让这个回路不必依赖人工介入),再执行 `pptfast render`。`pptfast preview` 能让 agent 在正式渲染前先看一遍 SVG,自查版式是否合理。把这套回路封装成 skill 的 Claude Code plugin 计划在 v0.2 落地(见 Roadmap)。
|
|
80
|
+
|
|
81
|
+
## 路线图
|
|
82
|
+
|
|
83
|
+
- **v0.2**——封装该回路的 Claude Code plugin + skills、design token 覆盖(`--tokens`)、`init`/自更新命令。
|
|
84
|
+
- **v0.3**——主题定制 skill(品牌色 → tokens)、自定义 manifest 插槽、1.0 版本。
|
|
85
|
+
- **v0.4**——更丰富的动效(更多入场动画)、Office 真机实测、web playground。
|
|
86
|
+
|
|
87
|
+
## 致谢
|
|
88
|
+
|
|
89
|
+
图标原语抽取自 [lucide](https://lucide.dev)(ISC License)。pptfast 本身从一套生产环境的 AI 出 PPT 系统中抽取而来,从第一天起就针对 CJK 排版做了优化(全角标点宽度、中文换行、雅黑优先字体栈)。
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
installPlatform
|
|
3
|
+
} from "./chunk-G76EVNVT.js";
|
|
4
|
+
|
|
5
|
+
// src/platform/node.ts
|
|
6
|
+
import { DOMParser as LinkedomDOMParser } from "linkedom";
|
|
7
|
+
async function recodeWithSharp(dataUrl) {
|
|
8
|
+
let sharpMod;
|
|
9
|
+
try {
|
|
10
|
+
sharpMod = (await import("sharp")).default;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
const err = e;
|
|
13
|
+
if (err?.code === "ERR_MODULE_NOT_FOUND" || /Cannot find/.test(err?.message ?? "")) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
'Re-encoding non-PNG/JPEG/GIF images requires the optional dependency "sharp" (npm i sharp), or convert the image beforehand'
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
throw e;
|
|
19
|
+
}
|
|
20
|
+
const base64 = dataUrl.slice(dataUrl.indexOf(",") + 1);
|
|
21
|
+
const png = await sharpMod(Buffer.from(base64, "base64")).png().toBuffer();
|
|
22
|
+
return `data:image/png;base64,${png.toString("base64")}`;
|
|
23
|
+
}
|
|
24
|
+
function installNodePlatform() {
|
|
25
|
+
installPlatform({
|
|
26
|
+
domParser: LinkedomDOMParser,
|
|
27
|
+
recodeImageToPng: recodeWithSharp
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
installNodePlatform
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=chunk-4WISUDXE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/platform/node.ts"],"sourcesContent":["import { DOMParser as LinkedomDOMParser } from \"linkedom\"\nimport { installPlatform } from \"./registry\"\n\nasync function recodeWithSharp(dataUrl: string): Promise<string> {\n let sharpMod: typeof import(\"sharp\")\n try {\n sharpMod = (await import(\"sharp\")).default as unknown as typeof import(\"sharp\")\n } catch (e) {\n const err = e as NodeJS.ErrnoException\n if (err?.code === \"ERR_MODULE_NOT_FOUND\" || /Cannot find/.test(err?.message ?? \"\")) {\n throw new Error(\n 'Re-encoding non-PNG/JPEG/GIF images requires the optional dependency \"sharp\" (npm i sharp), or convert the image beforehand'\n )\n }\n throw e\n }\n const base64 = dataUrl.slice(dataUrl.indexOf(\",\") + 1)\n const png = await sharpMod(Buffer.from(base64, \"base64\")).png().toBuffer()\n return `data:image/png;base64,${png.toString(\"base64\")}`\n}\n\n/** Wire Node implementations (linkedom DOM, sharp image re-encode) into the SDK. */\nexport function installNodePlatform(): void {\n installPlatform({\n domParser: LinkedomDOMParser as unknown as typeof DOMParser,\n recodeImageToPng: recodeWithSharp,\n })\n}\n"],"mappings":";;;;;AAAA,SAAS,aAAa,yBAAyB;AAG/C,eAAe,gBAAgB,SAAkC;AAC/D,MAAI;AACJ,MAAI;AACF,gBAAY,MAAM,OAAO,OAAO,GAAG;AAAA,EACrC,SAAS,GAAG;AACV,UAAM,MAAM;AACZ,QAAI,KAAK,SAAS,0BAA0B,cAAc,KAAK,KAAK,WAAW,EAAE,GAAG;AAClF,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACA,QAAM,SAAS,QAAQ,MAAM,QAAQ,QAAQ,GAAG,IAAI,CAAC;AACrD,QAAM,MAAM,MAAM,SAAS,OAAO,KAAK,QAAQ,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS;AACzE,SAAO,yBAAyB,IAAI,SAAS,QAAQ,CAAC;AACxD;AAGO,SAAS,sBAA4B;AAC1C,kBAAgB;AAAA,IACd,WAAW;AAAA,IACX,kBAAkB;AAAA,EACpB,CAAC;AACH;","names":[]}
|