dsh-ppt 0.4.3 → 0.4.4
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/CHANGELOG.md +6 -0
- package/LICENSE +21 -21
- package/README.en.md +4 -0
- package/README.md +4 -0
- package/cordis.patch.yml +19 -19
- package/lib/tools.js +2 -2
- package/package.json +2 -2
- package/skills/dsh-ppt/SKILL.md +69 -69
- package/skills/dsh-ppt/references/copywriting.md +59 -59
- package/skills/dsh-ppt/references/syntax.md +2 -2
- package/skills/dsh-ppt/references/themes.md +59 -59
- package/skills/dsh-ppt/references/troubleshooting.md +13 -13
- package/skills/dsh-ppt/scripts/build-deck.mjs +135 -135
- package/skills/dsh-ppt/scripts/deck-core.mjs +1750 -1718
|
@@ -1,135 +1,135 @@
|
|
|
1
|
-
#! /usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* build-deck.mjs —— dsh-ppt 的跨 harness 裸 CLI。
|
|
4
|
-
*
|
|
5
|
-
* DSH 插件内请优先使用 ppt_create 工具;把 skills/dsh-ppt 目录复制到
|
|
6
|
-
* Claude Code / Cursor / Gemini CLI / Codex 等 agent 时,用本脚本生成三件套。
|
|
7
|
-
*
|
|
8
|
-
* 示例:
|
|
9
|
-
* node build-deck.mjs --title "产品发布" --content "deck.md" --theme data --lang zh --out dist/deck
|
|
10
|
-
* node build-deck.mjs --title "Pitch" --content "一句话介绍我们的产品。" --theme velvet --lang bilingual
|
|
11
|
-
* node build-deck.mjs --list-themes
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { existsSync, readFileSync } from 'node:fs'
|
|
15
|
-
import { resolve as resolvePath } from 'node:path'
|
|
16
|
-
import { pathToFileURL } from 'node:url'
|
|
17
|
-
import { buildDeck, listThemes, THEME_IDS, DEFAULT_THEME } from './deck-core.mjs'
|
|
18
|
-
|
|
19
|
-
const HELP = `dsh-ppt —— 一句话 / 一篇文档 → HTML 放映 + PPTX 导出
|
|
20
|
-
|
|
21
|
-
用法:
|
|
22
|
-
node build-deck.mjs --title <标题> --content <Markdown 或文件路径> [选项]
|
|
23
|
-
|
|
24
|
-
选项:
|
|
25
|
-
--title <text> 演示文稿标题(必填)
|
|
26
|
-
--content <text|@path> Markdown 正文;或文件路径(自动读取);或 @- 从 stdin 读
|
|
27
|
-
--slides <json> 结构化 slides JSON(可选,与 --content 二选一)
|
|
28
|
-
--theme <id> 视觉主题:${THEME_IDS.join(' / ')}(默认 ${DEFAULT_THEME})
|
|
29
|
-
--lang <id> 界面语言:zh / en / bilingual(默认 zh)
|
|
30
|
-
--motion <on|off> 页间转场与要点入场动画(默认 on;off 产出纯静态)
|
|
31
|
-
--out <dir> 输出目录(默认当前目录)
|
|
32
|
-
--file <name> 文件名前缀(默认取标题)
|
|
33
|
-
--overwrite 显式覆盖同名三件套(默认自动追加 -1/-2…)
|
|
34
|
-
--list-themes 列出内置主题
|
|
35
|
-
--help 显示本帮助
|
|
36
|
-
|
|
37
|
-
输出:
|
|
38
|
-
<file>.html 独立网页放映(无外链,可直接双击打开)
|
|
39
|
-
<file>.pptx 可编辑 PPTX(16:9)
|
|
40
|
-
<file>.json deck manifest
|
|
41
|
-
`
|
|
42
|
-
|
|
43
|
-
export function parseArgv(argv) {
|
|
44
|
-
const args = { content: '', slides: null, lang: 'zh', theme: DEFAULT_THEME, motion: undefined, out: '.', file: '', title: '', overwrite: false }
|
|
45
|
-
const positional = []
|
|
46
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
47
|
-
const raw = String(argv[i])
|
|
48
|
-
const eq = raw.indexOf('=')
|
|
49
|
-
const key = eq >= 0 ? raw.slice(0, eq) : raw
|
|
50
|
-
const inline = eq >= 0 ? raw.slice(eq + 1) : null
|
|
51
|
-
const nextValue = () => {
|
|
52
|
-
if (inline !== null) return inline
|
|
53
|
-
if (i + 1 >= argv.length) throw new Error('dsh-ppt CLI:' + key + ' 需要一个值')
|
|
54
|
-
i += 1
|
|
55
|
-
return String(argv[i])
|
|
56
|
-
}
|
|
57
|
-
if (key === '--help' || key === '-h') args.help = true
|
|
58
|
-
else if (key === '--list-themes') args.listThemes = true
|
|
59
|
-
else if (key === '--overwrite') args.overwrite = true
|
|
60
|
-
else if (key === '--title') args.title = nextValue()
|
|
61
|
-
else if (key === '--content') args.content = nextValue()
|
|
62
|
-
else if (key === '--slides') args.slides = JSON.parse(nextValue())
|
|
63
|
-
else if (key === '--theme') args.theme = nextValue()
|
|
64
|
-
else if (key === '--lang') args.lang = nextValue()
|
|
65
|
-
else if (key === '--motion') args.motion = nextValue()
|
|
66
|
-
else if (key === '--out') args.out = nextValue()
|
|
67
|
-
else if (key === '--file') args.file = nextValue()
|
|
68
|
-
else positional.push(raw)
|
|
69
|
-
}
|
|
70
|
-
args.positional = positional
|
|
71
|
-
return args
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async function readStdin(stream) {
|
|
75
|
-
let text = ''
|
|
76
|
-
stream.setEncoding('utf8')
|
|
77
|
-
for await (const chunk of stream) text += chunk
|
|
78
|
-
return text
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export async function main(argv = process.argv.slice(2), io = {}) {
|
|
82
|
-
const log = io.log ?? ((message) => console.log(message))
|
|
83
|
-
const args = parseArgv(argv)
|
|
84
|
-
|
|
85
|
-
if (args.help) {
|
|
86
|
-
log(HELP.trim())
|
|
87
|
-
return 0
|
|
88
|
-
}
|
|
89
|
-
if (args.listThemes) {
|
|
90
|
-
for (const theme of listThemes('zh')) {
|
|
91
|
-
log('- ' + theme.id.padEnd(8) + theme.name + '|' + theme.mood + '|适合:' + theme.bestFor)
|
|
92
|
-
}
|
|
93
|
-
return 0
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
let content = String(args.content ?? '')
|
|
97
|
-
let slides = args.slides
|
|
98
|
-
if (content === '@-') {
|
|
99
|
-
content = await readStdin(io.stdin ?? process.stdin)
|
|
100
|
-
} else if (content.startsWith('@')) {
|
|
101
|
-
content = readFileSync(resolvePath(content.slice(1)), 'utf8')
|
|
102
|
-
} else if (content.trim() !== '' && existsSync(resolvePath(content.trim()))) {
|
|
103
|
-
// README / SKILL.md 的示例直接传文件路径(不带 @)时也按文件读取
|
|
104
|
-
content = readFileSync(resolvePath(content.trim()), 'utf8')
|
|
105
|
-
} else if (content.trim() === '' && slides === null) {
|
|
106
|
-
throw new Error('dsh-ppt CLI:--content 不能为空(或用 --slides 传结构化幻灯片)')
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const options = {
|
|
110
|
-
title: args.title,
|
|
111
|
-
content,
|
|
112
|
-
slides,
|
|
113
|
-
theme: args.theme,
|
|
114
|
-
lang: args.lang,
|
|
115
|
-
motion: args.motion,
|
|
116
|
-
outputDir: resolvePath(args.out || '.'),
|
|
117
|
-
fileName: args.file,
|
|
118
|
-
overwrite: args.overwrite,
|
|
119
|
-
}
|
|
120
|
-
const result = buildDeck(options)
|
|
121
|
-
log('dsh-ppt 已生成 ' + result.slideCount + ' 页演示文稿:')
|
|
122
|
-
log(' HTML 放映:' + result.htmlPath)
|
|
123
|
-
log(' PPTX 导出:' + result.pptxPath)
|
|
124
|
-
log(' Manifest :' + result.jsonPath)
|
|
125
|
-
return 0
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
|
|
129
|
-
main().then((code) => {
|
|
130
|
-
process.exitCode = code ?? 0
|
|
131
|
-
}).catch((err) => {
|
|
132
|
-
console.error('[dsh-ppt] ' + (err instanceof Error ? err.message : String(err)))
|
|
133
|
-
process.exitCode = 1
|
|
134
|
-
})
|
|
135
|
-
}
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* build-deck.mjs —— dsh-ppt 的跨 harness 裸 CLI。
|
|
4
|
+
*
|
|
5
|
+
* DSH 插件内请优先使用 ppt_create 工具;把 skills/dsh-ppt 目录复制到
|
|
6
|
+
* Claude Code / Cursor / Gemini CLI / Codex 等 agent 时,用本脚本生成三件套。
|
|
7
|
+
*
|
|
8
|
+
* 示例:
|
|
9
|
+
* node build-deck.mjs --title "产品发布" --content "deck.md" --theme data --lang zh --out dist/deck
|
|
10
|
+
* node build-deck.mjs --title "Pitch" --content "一句话介绍我们的产品。" --theme velvet --lang bilingual
|
|
11
|
+
* node build-deck.mjs --list-themes
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
15
|
+
import { resolve as resolvePath } from 'node:path'
|
|
16
|
+
import { pathToFileURL } from 'node:url'
|
|
17
|
+
import { buildDeck, listThemes, THEME_IDS, DEFAULT_THEME } from './deck-core.mjs'
|
|
18
|
+
|
|
19
|
+
const HELP = `dsh-ppt —— 一句话 / 一篇文档 → HTML 放映 + PPTX 导出
|
|
20
|
+
|
|
21
|
+
用法:
|
|
22
|
+
node build-deck.mjs --title <标题> --content <Markdown 或文件路径> [选项]
|
|
23
|
+
|
|
24
|
+
选项:
|
|
25
|
+
--title <text> 演示文稿标题(必填)
|
|
26
|
+
--content <text|@path> Markdown 正文;或文件路径(自动读取);或 @- 从 stdin 读
|
|
27
|
+
--slides <json> 结构化 slides JSON(可选,与 --content 二选一)
|
|
28
|
+
--theme <id> 视觉主题:${THEME_IDS.join(' / ')}(默认 ${DEFAULT_THEME})
|
|
29
|
+
--lang <id> 界面语言:zh / en / bilingual(默认 zh)
|
|
30
|
+
--motion <on|off> 页间转场与要点入场动画(默认 on;off 产出纯静态)
|
|
31
|
+
--out <dir> 输出目录(默认当前目录)
|
|
32
|
+
--file <name> 文件名前缀(默认取标题)
|
|
33
|
+
--overwrite 显式覆盖同名三件套(默认自动追加 -1/-2…)
|
|
34
|
+
--list-themes 列出内置主题
|
|
35
|
+
--help 显示本帮助
|
|
36
|
+
|
|
37
|
+
输出:
|
|
38
|
+
<file>.html 独立网页放映(无外链,可直接双击打开)
|
|
39
|
+
<file>.pptx 可编辑 PPTX(16:9)
|
|
40
|
+
<file>.json deck manifest
|
|
41
|
+
`
|
|
42
|
+
|
|
43
|
+
export function parseArgv(argv) {
|
|
44
|
+
const args = { content: '', slides: null, lang: 'zh', theme: DEFAULT_THEME, motion: undefined, out: '.', file: '', title: '', overwrite: false }
|
|
45
|
+
const positional = []
|
|
46
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
47
|
+
const raw = String(argv[i])
|
|
48
|
+
const eq = raw.indexOf('=')
|
|
49
|
+
const key = eq >= 0 ? raw.slice(0, eq) : raw
|
|
50
|
+
const inline = eq >= 0 ? raw.slice(eq + 1) : null
|
|
51
|
+
const nextValue = () => {
|
|
52
|
+
if (inline !== null) return inline
|
|
53
|
+
if (i + 1 >= argv.length) throw new Error('dsh-ppt CLI:' + key + ' 需要一个值')
|
|
54
|
+
i += 1
|
|
55
|
+
return String(argv[i])
|
|
56
|
+
}
|
|
57
|
+
if (key === '--help' || key === '-h') args.help = true
|
|
58
|
+
else if (key === '--list-themes') args.listThemes = true
|
|
59
|
+
else if (key === '--overwrite') args.overwrite = true
|
|
60
|
+
else if (key === '--title') args.title = nextValue()
|
|
61
|
+
else if (key === '--content') args.content = nextValue()
|
|
62
|
+
else if (key === '--slides') args.slides = JSON.parse(nextValue())
|
|
63
|
+
else if (key === '--theme') args.theme = nextValue()
|
|
64
|
+
else if (key === '--lang') args.lang = nextValue()
|
|
65
|
+
else if (key === '--motion') args.motion = nextValue()
|
|
66
|
+
else if (key === '--out') args.out = nextValue()
|
|
67
|
+
else if (key === '--file') args.file = nextValue()
|
|
68
|
+
else positional.push(raw)
|
|
69
|
+
}
|
|
70
|
+
args.positional = positional
|
|
71
|
+
return args
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function readStdin(stream) {
|
|
75
|
+
let text = ''
|
|
76
|
+
stream.setEncoding('utf8')
|
|
77
|
+
for await (const chunk of stream) text += chunk
|
|
78
|
+
return text
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function main(argv = process.argv.slice(2), io = {}) {
|
|
82
|
+
const log = io.log ?? ((message) => console.log(message))
|
|
83
|
+
const args = parseArgv(argv)
|
|
84
|
+
|
|
85
|
+
if (args.help) {
|
|
86
|
+
log(HELP.trim())
|
|
87
|
+
return 0
|
|
88
|
+
}
|
|
89
|
+
if (args.listThemes) {
|
|
90
|
+
for (const theme of listThemes('zh')) {
|
|
91
|
+
log('- ' + theme.id.padEnd(8) + theme.name + '|' + theme.mood + '|适合:' + theme.bestFor)
|
|
92
|
+
}
|
|
93
|
+
return 0
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let content = String(args.content ?? '')
|
|
97
|
+
let slides = args.slides
|
|
98
|
+
if (content === '@-') {
|
|
99
|
+
content = await readStdin(io.stdin ?? process.stdin)
|
|
100
|
+
} else if (content.startsWith('@')) {
|
|
101
|
+
content = readFileSync(resolvePath(content.slice(1)), 'utf8')
|
|
102
|
+
} else if (content.trim() !== '' && existsSync(resolvePath(content.trim()))) {
|
|
103
|
+
// README / SKILL.md 的示例直接传文件路径(不带 @)时也按文件读取
|
|
104
|
+
content = readFileSync(resolvePath(content.trim()), 'utf8')
|
|
105
|
+
} else if (content.trim() === '' && slides === null) {
|
|
106
|
+
throw new Error('dsh-ppt CLI:--content 不能为空(或用 --slides 传结构化幻灯片)')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const options = {
|
|
110
|
+
title: args.title,
|
|
111
|
+
content,
|
|
112
|
+
slides,
|
|
113
|
+
theme: args.theme,
|
|
114
|
+
lang: args.lang,
|
|
115
|
+
motion: args.motion,
|
|
116
|
+
outputDir: resolvePath(args.out || '.'),
|
|
117
|
+
fileName: args.file,
|
|
118
|
+
overwrite: args.overwrite,
|
|
119
|
+
}
|
|
120
|
+
const result = buildDeck(options)
|
|
121
|
+
log('dsh-ppt 已生成 ' + result.slideCount + ' 页演示文稿:')
|
|
122
|
+
log(' HTML 放映:' + result.htmlPath)
|
|
123
|
+
log(' PPTX 导出:' + result.pptxPath)
|
|
124
|
+
log(' Manifest :' + result.jsonPath)
|
|
125
|
+
return 0
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
|
|
129
|
+
main().then((code) => {
|
|
130
|
+
process.exitCode = code ?? 0
|
|
131
|
+
}).catch((err) => {
|
|
132
|
+
console.error('[dsh-ppt] ' + (err instanceof Error ? err.message : String(err)))
|
|
133
|
+
process.exitCode = 1
|
|
134
|
+
})
|
|
135
|
+
}
|