pptclaw 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.
Files changed (66) hide show
  1. package/.output/nitro.json +15 -0
  2. package/.output/public/_nuxt/BAtwhwpp.js +1 -0
  3. package/.output/public/_nuxt/BEQoYl5X.js +2616 -0
  4. package/.output/public/_nuxt/BMr1Z083.js +1 -0
  5. package/.output/public/_nuxt/BXBiPOBE.js +1 -0
  6. package/.output/public/_nuxt/BuUsXmAh.js +1 -0
  7. package/.output/public/_nuxt/CPsbnj8a.js +1 -0
  8. package/.output/public/_nuxt/D9BEMGXo.js +1 -0
  9. package/.output/public/_nuxt/DQNz2huy.js +1 -0
  10. package/.output/public/_nuxt/DQxlKO7N.js +1 -0
  11. package/.output/public/_nuxt/_id_.C3K2GZV8.css +1 -0
  12. package/.output/public/_nuxt/builds/latest.json +1 -0
  13. package/.output/public/_nuxt/builds/meta/e405cd67-1e23-4b39-85e1-217b00c69ec7.json +1 -0
  14. package/.output/public/_nuxt/entry.BqkL7BC_.css +1 -0
  15. package/.output/public/_nuxt/error-404.BzoSHD6c.css +1 -0
  16. package/.output/public/_nuxt/error-500.DwAqVzgo.css +1 -0
  17. package/.output/public/_nuxt/j2eJltcB.js +2614 -0
  18. package/.output/public/alipay.svg +27 -0
  19. package/.output/public/android-chrome-192x192.png +0 -0
  20. package/.output/public/android-chrome-512x512.png +0 -0
  21. package/.output/public/animations/arrow.lottie +0 -0
  22. package/.output/public/animations/cubes.lottie +0 -0
  23. package/.output/public/animations/stars.lottie +0 -0
  24. package/.output/public/apple-touch-icon.png +0 -0
  25. package/.output/public/auth-bg.svg +30 -0
  26. package/.output/public/auth-logo.svg +4 -0
  27. package/.output/public/cursor.png +0 -0
  28. package/.output/public/customerServiceQr.png +0 -0
  29. package/.output/public/favicon-16x16.png +0 -0
  30. package/.output/public/favicon-32x32.png +0 -0
  31. package/.output/public/favicon.ico +0 -0
  32. package/.output/public/logo.svg +4 -0
  33. package/.output/public/rect.svg +9 -0
  34. package/.output/public/site.webmanifest +1 -0
  35. package/.output/public/templates.json +1623 -0
  36. package/.output/public/watermark.svg +7 -0
  37. package/.output/public/wechat-pay-sm.svg +9 -0
  38. package/.output/public/wechat-pay.svg +21 -0
  39. package/.output/server/chunks/_/error-500.mjs +1 -0
  40. package/.output/server/chunks/_/shared.cjs.prod.mjs +1 -0
  41. package/.output/server/chunks/build/client.precomputed.mjs +1 -0
  42. package/.output/server/chunks/nitro/nitro.mjs +1 -0
  43. package/.output/server/chunks/routes/api/auth/_...path_.mjs +1 -0
  44. package/.output/server/chunks/routes/api/auth/login.post.mjs +1 -0
  45. package/.output/server/chunks/routes/api/auth/logout.post.mjs +1 -0
  46. package/.output/server/chunks/routes/api/auth/user.get.mjs +1 -0
  47. package/.output/server/chunks/routes/api/cloud/_...path_.mjs +1 -0
  48. package/.output/server/chunks/routes/api/credits/_...path_.mjs +1 -0
  49. package/.output/server/chunks/routes/api/images/_...path_.mjs +1 -0
  50. package/.output/server/chunks/routes/api/payments/_...path_.mjs +1 -0
  51. package/.output/server/chunks/routes/api/public/ping.mjs +1 -0
  52. package/.output/server/chunks/routes/api/public/test.mjs +1 -0
  53. package/.output/server/chunks/routes/api/sync/assets/_session/_...filename_.get.mjs +1 -0
  54. package/.output/server/chunks/routes/api/sync/close.post.mjs +1 -0
  55. package/.output/server/chunks/routes/api/sync/open.post.mjs +1 -0
  56. package/.output/server/chunks/routes/api/sync/sessions.get.mjs +1 -0
  57. package/.output/server/chunks/routes/api/sync/switch.post.mjs +1 -0
  58. package/.output/server/chunks/routes/api/sync/upload.post.mjs +1 -0
  59. package/.output/server/chunks/routes/api/sync/validate.post.mjs +1 -0
  60. package/.output/server/chunks/routes/api/sync/ws.mjs +1 -0
  61. package/.output/server/chunks/routes/renderer.mjs +1 -0
  62. package/.output/server/chunks/virtual/_virtual_spa-template.mjs +1 -0
  63. package/.output/server/index.mjs +1 -0
  64. package/README.md +49 -0
  65. package/bin/pptclaw.mjs +165 -0
  66. package/package.json +130 -0
@@ -0,0 +1 @@
1
+ const o="";export{o as template};
@@ -0,0 +1 @@
1
+ import o from"node:process";globalThis._importMeta_={url:import.meta.url,env:o.env};import"node:http";import"node:https";export{R as default}from"./chunks/nitro/nitro.mjs";import"node:crypto";import"stream";import"events";import"http";import"crypto";import"buffer";import"zlib";import"https";import"net";import"tls";import"url";import"node:events";import"node:buffer";import"node:fs";import"node:path";import"node:fs/promises";import"fs";import"fs/promises";import"path";import"node:stream";import"os";import"node:os";import"node:url";
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # PPTClaw
2
+
3
+ Local-first presentation editor for AI coding tools. Edit slides on your machine with a browser-based editor, synced bidirectionally via WebSocket.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g pptclaw
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ # Start the editor server
15
+ pptclaw serve
16
+
17
+ # Start and open a deck
18
+ pptclaw serve ./my-deck
19
+
20
+ # Open a deck in a running server
21
+ pptclaw open ./my-deck
22
+
23
+ # Validate a deck folder
24
+ pptclaw validate ./my-deck
25
+
26
+ # List active sessions
27
+ pptclaw list-decks
28
+
29
+ # Install the Claude Code skill
30
+ pptclaw init
31
+ ```
32
+
33
+ ## Deck Format
34
+
35
+ A deck is a folder containing:
36
+
37
+ ```
38
+ my-deck/
39
+ manifest.json
40
+ slides/
41
+ 001-abc.json
42
+ 002-def.json
43
+ assets/
44
+ image.png
45
+ ```
46
+
47
+ ## License
48
+
49
+ Proprietary
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander'
3
+ import { spawn } from 'node:child_process'
4
+ import { resolve, join } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+ import { existsSync, mkdirSync, copyFileSync } from 'node:fs'
7
+
8
+ const __dirname = fileURLToPath(new URL('.', import.meta.url))
9
+ const program = new Command()
10
+
11
+ program
12
+ .name('pptclaw')
13
+ .description('Local-first presentation editor for AI coding tools')
14
+ .version('0.1.0')
15
+
16
+ // pptclaw serve [deck] --port <port>
17
+ program
18
+ .command('serve')
19
+ .description('Start the PPTClaw editor server')
20
+ .argument('[deck]', 'Deck folder to open immediately')
21
+ .option('-p, --port <port>', 'Port number', '3009')
22
+ .action(async (deck, opts) => {
23
+ const serverEntry = join(__dirname, '..', '.output', 'server', 'index.mjs')
24
+ if (!existsSync(serverEntry)) {
25
+ console.error('Server not built. Run `nuxt build` first.')
26
+ process.exit(1)
27
+ }
28
+
29
+ const env = { ...process.env, PORT: opts.port, NUXT_PORT: opts.port }
30
+ const child = spawn('node', [serverEntry], { env, stdio: 'inherit' })
31
+
32
+ // If a deck path was provided, open it after server starts
33
+ if (deck) {
34
+ const deckPath = resolve(deck)
35
+ try {
36
+ await waitForServer(opts.port)
37
+ const result = await openDeck(deckPath, opts.port)
38
+ console.log(`Deck opened: ${result.sessionId}`)
39
+ console.log(` Path: ${result.deckPath}`)
40
+ console.log(` Slides: ${result.slideCount}`)
41
+ }
42
+ catch (err) {
43
+ console.error('Failed to open deck after server start:', err.message)
44
+ }
45
+ }
46
+
47
+ child.on('exit', (code) => process.exit(code ?? 0))
48
+ })
49
+
50
+ // pptclaw open <path> --session <id>
51
+ program
52
+ .command('open')
53
+ .description('Open a deck folder in the running editor')
54
+ .argument('<path>', 'Path to deck folder')
55
+ .option('-s, --session <id>', 'Session ID (auto-generated if omitted)')
56
+ .option('-p, --port <port>', 'Server port', '3009')
57
+ .action(async (path, opts) => {
58
+ const deckPath = resolve(path)
59
+ try {
60
+ const result = await openDeck(deckPath, opts.port, opts.session)
61
+ console.log(`Deck opened: ${result.sessionId}`)
62
+ console.log(` Path: ${result.deckPath}`)
63
+ console.log(` Slides: ${result.slideCount}`)
64
+ }
65
+ catch (err) {
66
+ console.error('Failed to open deck. Is the server running?')
67
+ console.error('Start it with: pptclaw serve')
68
+ process.exit(1)
69
+ }
70
+ })
71
+
72
+ // pptclaw validate <path>
73
+ program
74
+ .command('validate')
75
+ .description('Validate a deck folder')
76
+ .argument('<path>', 'Path to deck folder')
77
+ .option('-p, --port <port>', 'Server port', '3009')
78
+ .action(async (path, opts) => {
79
+ const deckPath = resolve(path)
80
+ try {
81
+ const res = await fetch(`http://localhost:${opts.port}/api/sync/validate`, {
82
+ method: 'POST',
83
+ headers: { 'Content-Type': 'application/json' },
84
+ body: JSON.stringify({ path: deckPath }),
85
+ })
86
+ const result = await res.json()
87
+ console.log(JSON.stringify(result, null, 2))
88
+ process.exit(result.valid ? 0 : 1)
89
+ }
90
+ catch {
91
+ console.error('Server not running. Start it with: pptclaw serve')
92
+ process.exit(1)
93
+ }
94
+ })
95
+
96
+ // pptclaw list-decks
97
+ program
98
+ .command('list-decks')
99
+ .description('List active sessions (open decks)')
100
+ .option('-p, --port <port>', 'Server port', '3009')
101
+ .action(async (opts) => {
102
+ try {
103
+ const res = await fetch(`http://localhost:${opts.port}/api/sync/sessions`)
104
+ const sessions = await res.json()
105
+ if (sessions.length === 0) {
106
+ console.log('No active sessions. Open a deck with: pptclaw open <path>')
107
+ return
108
+ }
109
+ console.log('Active sessions:')
110
+ for (const s of sessions) {
111
+ const active = s.activeInEditor ? ' (active)' : ''
112
+ console.log(` ${s.id}${active} — ${s.deckPath} (${s.slideCount} slides)`)
113
+ }
114
+ }
115
+ catch {
116
+ console.error('Server not running. Start it with: pptclaw serve')
117
+ process.exit(1)
118
+ }
119
+ })
120
+
121
+ // pptclaw init
122
+ program
123
+ .command('init')
124
+ .description('Copy the PPTClaw skill file to .claude/skills/')
125
+ .action(() => {
126
+ const skillSrc = join(__dirname, '..', 'skill', 'pptclaw.md')
127
+ const skillDest = join(process.cwd(), '.claude', 'skills', 'pptclaw.md')
128
+
129
+ if (!existsSync(skillSrc)) {
130
+ console.error('Skill file not found in package.')
131
+ process.exit(1)
132
+ }
133
+
134
+ mkdirSync(join(process.cwd(), '.claude', 'skills'), { recursive: true })
135
+ copyFileSync(skillSrc, skillDest)
136
+ console.log(`Skill file installed: ${skillDest}`)
137
+ })
138
+
139
+ program.parse()
140
+
141
+ // --- Helper functions ---
142
+
143
+ async function waitForServer(port, maxRetries = 30) {
144
+ for (let i = 0; i < maxRetries; i++) {
145
+ try {
146
+ const res = await fetch(`http://localhost:${port}/api/public/ping`)
147
+ if (res.ok) return
148
+ }
149
+ catch {
150
+ // Server not ready yet
151
+ }
152
+ await new Promise(r => setTimeout(r, 1000))
153
+ }
154
+ throw new Error('Server did not start in time')
155
+ }
156
+
157
+ async function openDeck(deckPath, port, sessionId) {
158
+ const res = await fetch(`http://localhost:${port}/api/sync/open`, {
159
+ method: 'POST',
160
+ headers: { 'Content-Type': 'application/json' },
161
+ body: JSON.stringify({ path: deckPath, ...(sessionId && { sessionId }) }),
162
+ })
163
+ if (!res.ok) throw new Error(await res.text())
164
+ return res.json()
165
+ }
package/package.json ADDED
@@ -0,0 +1,130 @@
1
+ {
2
+ "name": "pptclaw",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Local-first presentation editor for AI coding tools",
6
+ "license": "UNLICENSED",
7
+ "files": [
8
+ "bin/",
9
+ ".output/",
10
+ "skill/"
11
+ ],
12
+ "bin": {
13
+ "pptclaw": "bin/pptclaw.mjs"
14
+ },
15
+ "scripts": {
16
+ "typecheck": "tsc --noEmit",
17
+ "dev": "nuxi prepare && nuxi dev",
18
+ "debug": "nuxi prepare && nuxi dev --inspect=9340",
19
+ "build": "nuxi build",
20
+ "start": "nuxi preview",
21
+ "generate": "nuxi generate",
22
+ "postinstall": "nuxt prepare"
23
+ },
24
+ "dependencies": {
25
+ "commander": "^13.1.0"
26
+ },
27
+ "devDependencies": {
28
+ "@ai-sdk/openai": "^3.0.28",
29
+ "@ai-sdk/vue": "3.0.41",
30
+ "@antv/infographic": "^0.2.1",
31
+ "@icon-park/vue-next": "^1.4.2",
32
+ "@launchdarkly/observability": "^1.0.3",
33
+ "@launchdarkly/session-replay": "^1.0.3",
34
+ "@nuxt/eslint": "1.13.0",
35
+ "@openrouter/ai-sdk-provider": "^1.2.0",
36
+ "@primeuix/themes": "^1.0.0",
37
+ "@tanstack/vue-query": "^5.91.1",
38
+ "@vueuse/core": "^11.1.0",
39
+ "@vueuse/integrations": "^13.3.0",
40
+ "@zumer/snapdom": "^2.0.1",
41
+ "ai": "6.0.81",
42
+ "animate.css": "^4.1.1",
43
+ "axios": "^1.7.7",
44
+ "chokidar": "^4.0.3",
45
+ "chroma-js": "^3.1.2",
46
+ "class-variance-authority": "^0.7.1",
47
+ "clipboard": "^2.0.11",
48
+ "clsx": "^2.1.1",
49
+ "crypto-js": "^4.2.0",
50
+ "dayjs": "^1.11.13",
51
+ "dexie": "^4.2.0",
52
+ "dom-to-svg": "^0.12.2",
53
+ "echarts": "^5.5.1",
54
+ "eslint": "^9.0.0",
55
+ "file-saver": "^2.0.5",
56
+ "gsap": "^3.12.7",
57
+ "hfmath": "^0.0.2",
58
+ "html-to-image": "^1.11.13",
59
+ "html-to-text": "^9.0.5",
60
+ "jszip": "^3.10.1",
61
+ "launchdarkly-vue-client-sdk": "^2.4.1",
62
+ "lodash-es": "^4.17.21",
63
+ "lucide-vue-next": "^0.563.0",
64
+ "lz-string": "^1.5.0",
65
+ "mitt": "^3.0.1",
66
+ "motion-v": "1.0.0-beta.2",
67
+ "nanoid": "^5.1.4",
68
+ "number-precision": "^1.6.0",
69
+ "nuxt": "^4.3.0",
70
+ "openai": "^5.10.2",
71
+ "pptxtojson": "^1.6.0",
72
+ "primeicons": "^7.0.0",
73
+ "primevue": "^4.3.6",
74
+ "prosemirror-commands": "^1.7.1",
75
+ "prosemirror-dropcursor": "^1.8.2",
76
+ "prosemirror-gapcursor": "^1.3.2",
77
+ "prosemirror-history": "^1.4.1",
78
+ "prosemirror-inputrules": "^1.5.0",
79
+ "prosemirror-keymap": "^1.2.3",
80
+ "prosemirror-model": "^1.25.3",
81
+ "prosemirror-schema-basic": "^1.2.4",
82
+ "prosemirror-schema-list": "^1.5.1",
83
+ "prosemirror-state": "^1.4.3",
84
+ "prosemirror-view": "^1.41.2",
85
+ "qrcode": "^1.5.4",
86
+ "reka-ui": "^2.8.0",
87
+ "sanitize-html": "^2.17.0",
88
+ "shiki": "^3.22.0",
89
+ "svg-arc-to-cubic-bezier": "^3.2.0",
90
+ "svg-pathdata": "^8.0.0",
91
+ "tailwind-merge": "^3.4.0",
92
+ "tinycolor2": "^1.6.0",
93
+ "tippy.js": "^6.3.7",
94
+ "vue": "^3.5.27",
95
+ "vue-draggable-plus": "^0.6.0",
96
+ "vue-echarts": "^7.0.3",
97
+ "vue-router": "^4.6.4",
98
+ "vue-stick-to-bottom": "^0.1.0",
99
+ "vue-stream-markdown": "^0.3.4",
100
+ "vuedraggable": "^4.1.0",
101
+ "zod": "^4.1.12",
102
+ "@iconify-json/icon-park-outline": "^1.2.4",
103
+ "@iconify-json/icon-park-twotone": "^1.2.4",
104
+ "@iconify-json/material-symbols": "^1.2.5",
105
+ "@iconify-json/ph": "^1.2.1",
106
+ "@pinia/nuxt": "^0.11.3",
107
+ "@primevue/auto-import-resolver": "^4.3.6",
108
+ "@primevue/nuxt-module": "^4.3.6",
109
+ "@types/chroma-js": "^2.4.4",
110
+ "@types/crypto-js": "^4.2.2",
111
+ "@types/file-saver": "^2.0.7",
112
+ "@types/lodash-es": "^4.17.12",
113
+ "@types/node": "^18.19.44",
114
+ "@types/svg-arc-to-cubic-bezier": "^3.2.3",
115
+ "@types/tinycolor2": "^1.4.6",
116
+ "@unocss/nuxt": "^66.6.0",
117
+ "@unocss/preset-wind3": "^66.6.0",
118
+ "@unocss/reset": "^66.3.3",
119
+ "sass": "^1.93.2",
120
+ "shadcn-nuxt": "^2.4.3",
121
+ "typescript": "^5.5.4",
122
+ "unocss": "^66.3.3",
123
+ "unocss-preset-animations": "^1.3.0",
124
+ "unocss-preset-shadcn": "^1.0.1",
125
+ "unplugin-vue-components": "^28.8.0",
126
+ "vite-bundle-analyzer": "^1.1.0",
127
+ "vue-tsc": "^2.0.29"
128
+ },
129
+ "packageManager": "pnpm@10.32.1"
130
+ }