@lemonppt/cli 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lemonforme
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/SKILL.md ADDED
@@ -0,0 +1,156 @@
1
+ # lemonPPT
2
+
3
+ 根据一句话主题或需求,自动生成精美 PPT(goal.json/HTML/PPTX/PDF)。
4
+
5
+ ## 能力
6
+
7
+ - 接受用户输入(主题、目标页数、主题风格、语言)
8
+ - 生成结构化演示文稿规划(goal.json)
9
+ - 渲染为可浏览的 HTML
10
+ - 导出为 PPTX 或 PDF
11
+
12
+ ## 使用流程
13
+
14
+ 用户说"帮我做一份 PPT"时,按以下三步执行:
15
+
16
+ ### 1. 生成 goal.json
17
+
18
+ ```bash
19
+ lemonppt generate "<主题>" --pages <页数> --theme <主题> --language zh --out ./goal.json
20
+ ```
21
+
22
+ - `--pages`:页数,建议 6~20 页
23
+ - `--theme`:主题 ID,可选 `minimal`、`dark-tech`、`warm-business`
24
+ - `--language`:`zh` 或 `en`
25
+ - `--api-key`:可选,OpenAI 兼容 API Key;不传则使用内置 fallback 示例
26
+
27
+ ### 2. 导出 PPTX / PDF
28
+
29
+ ```bash
30
+ lemonppt export ./goal.json --pptx ./deck.pptx --pdf ./deck.pdf
31
+ ```
32
+
33
+ 至少传 `--pptx` 或 `--pdf` 之一。
34
+
35
+ ### 3. 交付文件
36
+
37
+ 把生成的 `goal.json`、`deck.pptx`、`deck.pdf` 以及 `output/index.html` 展示给用户。
38
+
39
+ 如果用户只需要文件,交付 PPTX/PDF;如果用户想在线预览,交付 HTML。
40
+
41
+ ## goal.json 格式
42
+
43
+ ```json
44
+ {
45
+ "title": "演示文稿标题",
46
+ "goal": "演示目标",
47
+ "audience": "目标受众",
48
+ "owner": "汇报人",
49
+ "theme": "minimal",
50
+ "language": "zh",
51
+ "pageCount": 8,
52
+ "randomSeed": "可选种子",
53
+ "slides": [
54
+ {
55
+ "role": "cover",
56
+ "layout": "cover_v1",
57
+ "props": {
58
+ "title": "标题",
59
+ "subtitle": "副标题",
60
+ "date": "2026-07-18"
61
+ }
62
+ }
63
+ ]
64
+ }
65
+ ```
66
+
67
+ ### 字段说明
68
+
69
+ | 字段 | 必填 | 说明 |
70
+ |---|---|---|
71
+ | `title` | 是 | PPT 标题 |
72
+ | `goal` | 是 | 演示目标/背景 |
73
+ | `audience` | 是 | 受众描述 |
74
+ | `owner` | 否 | 汇报人 |
75
+ | `theme` | 是 | 主题 ID |
76
+ | `language` | 否 | `zh` 或 `en`,默认 `zh` |
77
+ | `pageCount` | 是 | 总页数,必须等于 `slides.length` |
78
+ | `randomSeed` | 否 | 随机种子,保证结果可复现 |
79
+ | `slides` | 是 | 幻灯片数组 |
80
+
81
+ 每个 slide:
82
+
83
+ | 字段 | 必填 | 说明 |
84
+ |---|---|---|
85
+ | `role` | 是 | 页面角色,见下方角色表 |
86
+ | `layout` | 否 | 具体版式 ID;留空时系统按 role 自动选择 |
87
+ | `props` | 是 | 该版式所需数据 |
88
+
89
+ ## 可用主题
90
+
91
+ | 主题 ID | 风格 |
92
+ |---|---|
93
+ | `minimal` | 极简商务 |
94
+ | `dark-tech` | 深色科技 |
95
+ | `warm-business` | 温暖商务 |
96
+
97
+ ## 页面角色与版式
98
+
99
+ Agent 选页时只需指定 `role`,系统会根据角色自动挑选合适版式。只有在明确需要某一款版式时才填 `layout`。
100
+
101
+ | role | 用途 | 可用版式 |
102
+ |---|---|---|
103
+ | `cover` | 封面 | `cover_v1` |
104
+ | `tableOfContents` | 目录 | `table_of_contents_v1` |
105
+ | `metric` | 关键指标 | `metric_v1`, `metric_v2` |
106
+ | `stats` | 2x2 统计网格 | `stats_v1` |
107
+ | `chart` | 图表 | `chart_v1` |
108
+ | `comparison` | 对比 | `comparison_v1`, `comparison_v2` |
109
+ | `pricing` | 价格方案 | `pricing_v1` |
110
+ | `process` | 流程步骤 | `process_v1`, `process_v2` |
111
+ | `timeline` | 时间线 | `timeline_v1` |
112
+ | `roadmap` | 路线图 | `roadmap_v1` |
113
+ | `quote` | 金句引用 | `quote_v1`, `quote_v2` |
114
+ | `testimonial` | 客户评价 | `testimonial_v1` |
115
+ | `content` | 内容页 | `content_v1`, `content_v2`, `content_v3`, `split_v1` |
116
+ | `faq` | 问答 | `faq_v1` |
117
+ | `feature` | 产品特性 | `feature_v1` |
118
+ | `team` | 团队介绍 | `team_v1` |
119
+ | `partners` | 合作伙伴墙 | `partners_v1` |
120
+ | `image` | 全屏图片 | `image_v1` |
121
+ | `gallery` | 图片画廊 | `gallery_v1` |
122
+ | `swot` | SWOT 分析 | `swot_v1` |
123
+ | `pest` | PEST 分析 | `pest_v1` |
124
+ | `closing` | 结尾页 | `closing_v1`, `closing_v2` |
125
+
126
+ ## 常见 props 字段
127
+
128
+ - `title`:页面主标题
129
+ - `kicker`:小标题/标签
130
+ - `subtitle`:副标题
131
+ - `items`:列表项数组
132
+ - `points`:要点数组
133
+ - `stats`:指标数组,元素含 `label`、`value`、`unit`、`change`
134
+ - `image` / `imageUrl`:图片 URL(远程 URL 在 PPTX 中可能显示占位符)
135
+ - `cta` / `contact` / `email` / `link`:结尾页联系方式
136
+
137
+ ## 常见错误处理
138
+
139
+ 1. **没有 API Key**:`lemonppt generate` 会 fallback 到内置示例内容,仍可生成完整文件。
140
+ 2. **页数太少**:建议封面 + 目录 + 3~5 页内容 + 结尾,最少 5 页。
141
+ 3. **远程图片在 PPTX 中不显示**:PPTX 导出优先使用本地图片或 base64;远程 URL 会显示占位符。
142
+ 4. **生成失败**:检查 JSON 是否合法、`slides.length` 是否等于 `pageCount`。
143
+
144
+ ## 完整示例
145
+
146
+ ```bash
147
+ lemonppt generate "AI 助手产品发布会" --pages 8 --theme dark-tech --language zh --out ./ai-launch.json
148
+ lemonppt render ./ai-launch.json --out ./output
149
+ lemonppt export ./ai-launch.json --pptx ./ai-launch.pptx --pdf ./ai-launch.pdf
150
+ ```
151
+
152
+ ## 注意事项
153
+
154
+ - 不要手动指定每个 slide 的 `layout`,优先只写 `role`。
155
+ - `goal.json` 是核心协议,生成后可以直接交给用户修改再导出。
156
+ - 所有命令在 lemonPPT 项目根目录执行;CLI 入口为 `packages/cli/dist/cli.js` 或安装后的 `lemonppt`。
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+ import { exportGoalToPdf, exportGoalToPptx, generateGoalToFile, readGoalFromFile, renderGoalToDir, } from './index.js';
3
+ import { installSkill } from './install-skill.js';
4
+ function printUsage() {
5
+ console.log(`Usage:
6
+ lemonppt generate "<input>" [--pages N] [--theme <id>] [--language zh|en] [--out goal.json] [--api-key KEY]
7
+ lemonppt render <goal.json> [--out ./output] [--editable]
8
+ lemonppt export <goal.json> --pptx out.pptx [--pdf out.pdf]
9
+ lemonppt install-skill [--claude] [--codex] [--cursor] [--all]
10
+ `);
11
+ }
12
+ function parseArgs(argv) {
13
+ const positional = [];
14
+ const options = {};
15
+ for (let i = 0; i < argv.length; i++) {
16
+ const arg = argv[i];
17
+ if (arg.startsWith('--')) {
18
+ const key = arg.replace(/^--/, '');
19
+ const next = argv[i + 1];
20
+ if (next && !next.startsWith('--')) {
21
+ options[key] = next;
22
+ i++;
23
+ }
24
+ else {
25
+ options[key] = true;
26
+ }
27
+ }
28
+ else {
29
+ positional.push(arg);
30
+ }
31
+ }
32
+ return { positional, options };
33
+ }
34
+ async function main() {
35
+ const argv = process.argv.slice(2);
36
+ if (argv.length === 0) {
37
+ printUsage();
38
+ process.exit(0);
39
+ }
40
+ const command = argv[0];
41
+ const args = parseArgs(argv.slice(1));
42
+ const positional = args.positional;
43
+ try {
44
+ switch (command) {
45
+ case 'generate': {
46
+ const input = positional[0];
47
+ if (!input) {
48
+ console.error('Error: generate command requires an input string.');
49
+ process.exit(1);
50
+ }
51
+ const goal = await generateGoalToFile({
52
+ input,
53
+ pageCount: args.options.pages ? Number(args.options.pages) : 8,
54
+ theme: args.options.theme,
55
+ language: args.options.language,
56
+ apiKey: args.options['api-key'],
57
+ baseUrl: args.options['base-url'],
58
+ model: args.options.model,
59
+ outFile: args.options.out || './goal.json',
60
+ });
61
+ console.log(`Generated goal: ${goal.title} (${goal.slides.length} slides)`);
62
+ break;
63
+ }
64
+ case 'render': {
65
+ const goalPath = positional[0];
66
+ if (!goalPath) {
67
+ console.error('Error: render command requires a goal.json path.');
68
+ process.exit(1);
69
+ }
70
+ const goal = await readGoalFromFile(goalPath);
71
+ const { indexPath } = await renderGoalToDir(goal, {
72
+ outDir: args.options.out || './output',
73
+ editable: args.options.editable === true,
74
+ });
75
+ console.log(`Rendered to ${indexPath}`);
76
+ break;
77
+ }
78
+ case 'export': {
79
+ const goalPath = positional[0];
80
+ if (!goalPath) {
81
+ console.error('Error: export command requires a goal.json path.');
82
+ process.exit(1);
83
+ }
84
+ const goal = await readGoalFromFile(goalPath);
85
+ if (args.options.pptx) {
86
+ await exportGoalToPptx(goal, { outFile: args.options.pptx });
87
+ console.log(`Exported PPTX to ${args.options.pptx}`);
88
+ }
89
+ if (args.options.pdf) {
90
+ await exportGoalToPdf(goal, { outFile: args.options.pdf });
91
+ console.log(`Exported PDF to ${args.options.pdf}`);
92
+ }
93
+ if (!args.options.pptx && !args.options.pdf) {
94
+ console.error('Error: export command requires --pptx or --pdf.');
95
+ process.exit(1);
96
+ }
97
+ break;
98
+ }
99
+ case 'install-skill': {
100
+ const agents = [];
101
+ if (args.options.claude)
102
+ agents.push('claude');
103
+ if (args.options.codex)
104
+ agents.push('codex');
105
+ if (args.options.cursor)
106
+ agents.push('cursor');
107
+ if (args.options.all || agents.length === 0) {
108
+ agents.length = 0;
109
+ agents.push('claude', 'codex', 'cursor');
110
+ }
111
+ await installSkill({ agents });
112
+ break;
113
+ }
114
+ default: {
115
+ console.error(`Unknown command: ${command}`);
116
+ printUsage();
117
+ process.exit(1);
118
+ }
119
+ }
120
+ }
121
+ catch (err) {
122
+ console.error(err);
123
+ process.exit(1);
124
+ }
125
+ }
126
+ void main();
@@ -0,0 +1,55 @@
1
+ import type { DeckGoal } from '@lemonppt/core';
2
+ import { type RenderOptions } from '@lemonppt/renderer';
3
+ export interface GenerateCliOptions {
4
+ /** 用户输入的主题/需求 */
5
+ input: string;
6
+ /** 页数,默认 8 */
7
+ pageCount?: number;
8
+ /** 主题 ID,默认 minimal */
9
+ theme?: string;
10
+ /** 语言,默认 zh */
11
+ language?: 'zh' | 'en';
12
+ /** OpenAI 兼容 API Key */
13
+ apiKey?: string;
14
+ /** OpenAI 兼容 Base URL */
15
+ baseUrl?: string;
16
+ /** 模型名称 */
17
+ model?: string;
18
+ /** 输出文件路径,默认 ./goal.json */
19
+ outFile?: string;
20
+ }
21
+ export interface RenderCliOptions extends RenderOptions {
22
+ /** 输出目录,默认 ./output */
23
+ outDir?: string;
24
+ /** 是否开启浏览器端编辑 */
25
+ editable?: boolean;
26
+ }
27
+ export interface ExportCliOptions {
28
+ /** 输出文件路径 */
29
+ outFile: string;
30
+ }
31
+ /**
32
+ * 生成 goal.json 并可选写入文件。
33
+ */
34
+ export declare function generateGoalToFile(options: GenerateCliOptions): Promise<DeckGoal>;
35
+ /**
36
+ * 从文件读取 goal.json。
37
+ */
38
+ export declare function readGoalFromFile(filePath: string): Promise<DeckGoal>;
39
+ /**
40
+ * 渲染 deck 到输出目录。
41
+ */
42
+ export declare function renderGoalToDir(goal: DeckGoal, options?: RenderCliOptions): Promise<{
43
+ html: string;
44
+ indexPath: string;
45
+ assetsDir: string;
46
+ assets: string[];
47
+ }>;
48
+ /**
49
+ * 导出 goal 为 PPTX。
50
+ */
51
+ export declare function exportGoalToPptx(goal: DeckGoal, options: ExportCliOptions): Promise<void>;
52
+ /**
53
+ * 导出 goal 为 PDF。
54
+ */
55
+ export declare function exportGoalToPdf(goal: DeckGoal, options: ExportCliOptions): Promise<void>;
package/dist/index.js ADDED
@@ -0,0 +1,84 @@
1
+ import { generateGoal } from '@lemonppt/agent-prompts';
2
+ import { exportDeckToPdf, exportDeckToPptx, renderDeck, } from '@lemonppt/renderer';
3
+ import { getTheme } from '@lemonppt/themes';
4
+ import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ function resolveTheme(themeId) {
8
+ const id = themeId || 'minimal';
9
+ return getTheme(id) ? id : 'minimal';
10
+ }
11
+ async function copyThemeAssets(themeId, assetsDir) {
12
+ const theme = resolveTheme(themeId);
13
+ await mkdir(assetsDir, { recursive: true });
14
+ const cssSource = resolvePackagePath('@lemonppt/themes', 'src', theme, 'styles.css');
15
+ const cssDest = path.join(assetsDir, `${theme}.css`);
16
+ await copyFile(cssSource, cssDest);
17
+ }
18
+ function resolvePackagePath(pkg, ...segments) {
19
+ const mainUrl = import.meta.resolve(pkg);
20
+ const pkgRoot = path.resolve(path.dirname(fileURLToPath(mainUrl)), '..');
21
+ return path.join(pkgRoot, ...segments);
22
+ }
23
+ /**
24
+ * 生成 goal.json 并可选写入文件。
25
+ */
26
+ export async function generateGoalToFile(options) {
27
+ const { input, pageCount = 8, theme = 'minimal', language = 'zh', apiKey, baseUrl, model, outFile, } = options;
28
+ const result = await generateGoal({
29
+ input,
30
+ pageCount,
31
+ theme,
32
+ language,
33
+ llm: {
34
+ apiKey: apiKey || process.env.OPENAI_API_KEY,
35
+ baseUrl: baseUrl || process.env.OPENAI_BASE_URL,
36
+ model: model || process.env.OPENAI_MODEL,
37
+ },
38
+ });
39
+ if (outFile) {
40
+ await mkdir(path.dirname(path.resolve(outFile)), { recursive: true });
41
+ await writeFile(path.resolve(outFile), JSON.stringify(result.goal, null, 2), 'utf-8');
42
+ }
43
+ return result.goal;
44
+ }
45
+ /**
46
+ * 从文件读取 goal.json。
47
+ */
48
+ export async function readGoalFromFile(filePath) {
49
+ const raw = await readFile(path.resolve(filePath), 'utf-8');
50
+ const parsed = JSON.parse(raw);
51
+ parsed.theme = resolveTheme(parsed.theme);
52
+ return parsed;
53
+ }
54
+ /**
55
+ * 渲染 deck 到输出目录。
56
+ */
57
+ export async function renderGoalToDir(goal, options = {}) {
58
+ const { outDir = './output', editable = false, width, height } = options;
59
+ const outputDir = path.resolve(outDir);
60
+ const assetsDir = path.join(outputDir, 'assets');
61
+ const result = renderDeck(goal, { width, height, editable });
62
+ await copyThemeAssets(goal.theme, assetsDir);
63
+ const indexName = editable ? 'editor.html' : 'index.html';
64
+ const indexPath = path.join(outputDir, indexName);
65
+ await mkdir(outputDir, { recursive: true });
66
+ await writeFile(indexPath, result.html, 'utf-8');
67
+ return { html: result.html, indexPath, assetsDir, assets: result.assets };
68
+ }
69
+ /**
70
+ * 导出 goal 为 PPTX。
71
+ */
72
+ export async function exportGoalToPptx(goal, options) {
73
+ const outFile = path.resolve(options.outFile);
74
+ await mkdir(path.dirname(outFile), { recursive: true });
75
+ await exportDeckToPptx(goal, { outFile });
76
+ }
77
+ /**
78
+ * 导出 goal 为 PDF。
79
+ */
80
+ export async function exportGoalToPdf(goal, options) {
81
+ const outFile = path.resolve(options.outFile);
82
+ await mkdir(path.dirname(outFile), { recursive: true });
83
+ await exportDeckToPdf(goal, { outFile });
84
+ }
@@ -0,0 +1,8 @@
1
+ export interface InstallSkillOptions {
2
+ /** 指定安装的 Agent,默认全部 */
3
+ agents?: string[];
4
+ }
5
+ /**
6
+ * 将 lemonPPT skill 安装到常见 AI Agent 的技能目录。
7
+ */
8
+ export declare function installSkill(options?: InstallSkillOptions): Promise<void>;
@@ -0,0 +1,52 @@
1
+ import { copyFile, mkdir, writeFile } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ const DEFAULT_AGENTS = ['claude', 'codex', 'cursor'];
7
+ function resolveSkillMdPath() {
8
+ // Published package: SKILL.md lives next to the package root (one level above dist/)
9
+ const mainUrl = import.meta.resolve('@lemonppt/cli');
10
+ const pkgRoot = path.resolve(path.dirname(fileURLToPath(mainUrl)), '..');
11
+ const published = path.join(pkgRoot, 'SKILL.md');
12
+ if (existsSync(published)) {
13
+ return published;
14
+ }
15
+ // Local monorepo dev: fallback to repo root SKILL.md
16
+ const local = path.resolve(pkgRoot, '..', '..', 'SKILL.md');
17
+ if (existsSync(local)) {
18
+ return local;
19
+ }
20
+ throw new Error('SKILL.md not found. It should be bundled with @lemonppt/cli or exist at the repo root.');
21
+ }
22
+ async function installAgent(agent) {
23
+ const homeDir = os.homedir();
24
+ const skillDir = path.join(homeDir, `.${agent}/skills/lemonppt`);
25
+ await mkdir(skillDir, { recursive: true });
26
+ const skillMdSource = resolveSkillMdPath();
27
+ await copyFile(skillMdSource, path.join(skillDir, 'SKILL.md'));
28
+ await copyFile(skillMdSource, path.join(skillDir, 'README.md'));
29
+ const scriptsDir = path.join(skillDir, 'scripts');
30
+ await mkdir(scriptsDir, { recursive: true });
31
+ const wrapperSh = `#!/bin/bash
32
+ set -e
33
+ exec npx @lemonppt/cli "$@"
34
+ `;
35
+ await writeFile(path.join(scriptsDir, 'lemonppt.sh'), wrapperSh, { mode: 0o755 });
36
+ const wrapperPs1 = `#Requires -Version 5.1
37
+ & npx @lemonppt/cli @args
38
+ `;
39
+ await writeFile(path.join(scriptsDir, 'lemonppt.ps1'), wrapperPs1, { mode: 0o755 });
40
+ console.log(`✓ Installed lemonPPT skill for ${agent} at ${skillDir}`);
41
+ }
42
+ /**
43
+ * 将 lemonPPT skill 安装到常见 AI Agent 的技能目录。
44
+ */
45
+ export async function installSkill(options = {}) {
46
+ const agents = options.agents?.length ? options.agents : DEFAULT_AGENTS;
47
+ for (const agent of agents) {
48
+ await installAgent(agent);
49
+ }
50
+ console.log('\nInstallation complete.');
51
+ console.log('Agents can now reference lemonPPT via SKILL.md in their skill directories.');
52
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@lemonppt/cli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "bin": {
8
+ "lemonppt": "./dist/cli.js"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "SKILL.md"
19
+ ],
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/lemonforme/lemonPPT.git",
26
+ "directory": "packages/cli"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/lemonforme/lemonPPT/issues"
30
+ },
31
+ "homepage": "https://github.com/lemonforme/lemonPPT#readme",
32
+ "dependencies": {
33
+ "@lemonppt/agent-prompts": "0.1.0",
34
+ "@lemonppt/core": "0.1.0",
35
+ "@lemonppt/themes": "0.1.0",
36
+ "@lemonppt/renderer": "0.1.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^20.0.0",
40
+ "typescript": "^5.5.0"
41
+ },
42
+ "license": "MIT",
43
+ "scripts": {
44
+ "build": "tsc",
45
+ "typecheck": "tsc --noEmit"
46
+ }
47
+ }