@tom2012/cc-web 1.5.72 → 1.5.75

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 (45) hide show
  1. package/README.md +1 -1
  2. package/backend/dist/index.d.ts.map +1 -1
  3. package/backend/dist/index.js +22 -0
  4. package/backend/dist/index.js.map +1 -1
  5. package/backend/dist/plugin-manager.d.ts +88 -0
  6. package/backend/dist/plugin-manager.d.ts.map +1 -0
  7. package/backend/dist/plugin-manager.js +307 -0
  8. package/backend/dist/plugin-manager.js.map +1 -0
  9. package/backend/dist/routes/claude.js +2 -2
  10. package/backend/dist/routes/claude.js.map +1 -1
  11. package/backend/dist/routes/plugin-bridge.d.ts +3 -0
  12. package/backend/dist/routes/plugin-bridge.d.ts.map +1 -0
  13. package/backend/dist/routes/plugin-bridge.js +141 -0
  14. package/backend/dist/routes/plugin-bridge.js.map +1 -0
  15. package/backend/dist/routes/plugins.d.ts +3 -0
  16. package/backend/dist/routes/plugins.d.ts.map +1 -0
  17. package/backend/dist/routes/plugins.js +193 -0
  18. package/backend/dist/routes/plugins.js.map +1 -0
  19. package/backend/dist/routes/skillhub.d.ts.map +1 -1
  20. package/backend/dist/routes/skillhub.js +22 -0
  21. package/backend/dist/routes/skillhub.js.map +1 -1
  22. package/bin/ccweb-plugin.js +268 -0
  23. package/frontend/dist/assets/{GraphPreview-QqDpOEoI.js → GraphPreview-CiL6ZjdW.js} +1 -1
  24. package/frontend/dist/assets/{OfficePreview-BC2woErg.js → OfficePreview-laIUc98k.js} +3 -3
  25. package/frontend/dist/assets/{ProjectPage-B8Tdoz_M.js → ProjectPage-BmYhTTYq.js} +57 -57
  26. package/frontend/dist/assets/{SettingsPage-C8572fFD.js → SettingsPage-C30iHtBo.js} +1 -1
  27. package/frontend/dist/assets/{ShareViewPage-PTSFe5df.js → ShareViewPage-BGAvzqO1.js} +1 -1
  28. package/frontend/dist/assets/SkillHubPage-BSb-9jya.js +11 -0
  29. package/frontend/dist/assets/{bot-CP4ljg4K.js → bot-hRRV5XmX.js} +1 -1
  30. package/frontend/dist/assets/{chevron-down-BPKbPuX9.js → chevron-down-BR0IMbA9.js} +1 -1
  31. package/frontend/dist/assets/{download-DJNy8XSX.js → download-UC5GvInE.js} +1 -1
  32. package/frontend/dist/assets/{index-CENzb-E2.js → index-BiYAwwZA.js} +24 -24
  33. package/frontend/dist/assets/index-D7mCoW2r.js +295 -0
  34. package/frontend/dist/assets/index-DgHvs3fU.css +1 -0
  35. package/frontend/dist/assets/{jszip.min-CPp1Je4B.js → jszip.min-YWYO5s4l.js} +1 -1
  36. package/frontend/dist/assets/{save-dexIyJWW.js → save-CdDjQhdC.js} +1 -1
  37. package/frontend/dist/assets/{user-BGUBSa7q.js → user-Bv38vpTL.js} +1 -1
  38. package/frontend/dist/index.html +2 -2
  39. package/package.json +6 -3
  40. package/plugin-sdk/ccweb-plugin-sdk.js +123 -0
  41. package/plugins/pomodoro/frontend/index.html +242 -0
  42. package/plugins/pomodoro/manifest.json +19 -0
  43. package/frontend/dist/assets/SkillHubPage-BHgZp94q.js +0 -6
  44. package/frontend/dist/assets/index-BPzNyZy4.js +0 -280
  45. package/frontend/dist/assets/index-PNcejD9U.css +0 -1
@@ -0,0 +1,268 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const readline = require('readline');
7
+
8
+ const args = process.argv.slice(2);
9
+ const command = args[0];
10
+
11
+ if (!command || command === '--help' || command === '-h') {
12
+ console.log(`
13
+ ccweb-plugin — CLI scaffold for ccweb plugins
14
+
15
+ Usage:
16
+ ccweb-plugin create <name> Create a new plugin project
17
+ ccweb-plugin build Build plugin into a zip
18
+ ccweb-plugin --help Show this help
19
+ `);
20
+ process.exit(0);
21
+ }
22
+
23
+ // ── create ──────────────────────────────────────────────────────────────────
24
+
25
+ if (command === 'create') {
26
+ const name = args[1];
27
+ if (!name) {
28
+ console.error('Usage: ccweb-plugin create <name>');
29
+ process.exit(1);
30
+ }
31
+
32
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
33
+ const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
34
+
35
+ (async () => {
36
+ const id = name.replace(/[^a-z0-9-]/gi, '-').toLowerCase();
37
+ const displayName = await ask(`Plugin display name [${name}]: `) || name;
38
+ const author = await ask('Author: ') || 'anonymous';
39
+ const description = await ask('Description: ') || '';
40
+ const hasBackend = (await ask('Include backend? (y/N): ')).toLowerCase() === 'y';
41
+
42
+ const scopeInput = await ask('Scope (global/dashboard/project) [global]: ') || 'global';
43
+ const scopes = scopeInput.split(',').map(s => s.trim()).filter(Boolean);
44
+
45
+ const permInput = await ask('Permissions (comma-separated, e.g. system:info,project:list): ') || '';
46
+ const permissions = permInput.split(',').map(s => s.trim()).filter(Boolean);
47
+
48
+ const width = parseInt(await ask('Default width [320]: ') || '320', 10);
49
+ const height = parseInt(await ask('Default height [240]: ') || '240', 10);
50
+
51
+ rl.close();
52
+
53
+ const dir = path.resolve(id);
54
+ if (fs.existsSync(dir)) {
55
+ console.error(`Directory "${id}" already exists`);
56
+ process.exit(1);
57
+ }
58
+
59
+ // Create directory structure
60
+ fs.mkdirSync(path.join(dir, 'frontend'), { recursive: true });
61
+ if (hasBackend) fs.mkdirSync(path.join(dir, 'backend'), { recursive: true });
62
+
63
+ // manifest.json
64
+ const manifest = {
65
+ id,
66
+ name: displayName,
67
+ version: '1.0.0',
68
+ author,
69
+ description,
70
+ type: 'float',
71
+ float: {
72
+ defaultWidth: width,
73
+ defaultHeight: height,
74
+ minWidth: 200,
75
+ minHeight: 150,
76
+ resizable: true,
77
+ scope: { allowed: scopes, default: scopes[0] || 'global' },
78
+ clickable: { allowed: [true, false], default: true },
79
+ },
80
+ permissions,
81
+ frontend: { entry: 'frontend/index.html' },
82
+ };
83
+ if (hasBackend) manifest.backend = { entry: 'backend/index.js' };
84
+ fs.writeFileSync(path.join(dir, 'manifest.json'), JSON.stringify(manifest, null, 2));
85
+
86
+ // frontend/index.html
87
+ fs.writeFileSync(path.join(dir, 'frontend', 'index.html'), `<!DOCTYPE html>
88
+ <html lang="en">
89
+ <head>
90
+ <meta charset="UTF-8">
91
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
92
+ <title>${displayName}</title>
93
+ <script src="/plugin-sdk/ccweb-plugin-sdk.js"><\/script>
94
+ <style>
95
+ * { margin: 0; padding: 0; box-sizing: border-box; }
96
+ body {
97
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
98
+ background: #0a0a0a;
99
+ color: #e4e4e7;
100
+ padding: 12px;
101
+ font-size: 13px;
102
+ }
103
+ h3 { font-size: 14px; margin-bottom: 8px; color: #a1a1aa; }
104
+ .value { font-size: 20px; font-weight: 600; color: #fafafa; }
105
+ .label { font-size: 11px; color: #71717a; margin-top: 2px; }
106
+ .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
107
+ .card {
108
+ background: #18181b;
109
+ border: 1px solid #27272a;
110
+ border-radius: 8px;
111
+ padding: 10px;
112
+ }
113
+ </style>
114
+ </head>
115
+ <body>
116
+ <h3>${displayName}</h3>
117
+ <div class="grid" id="content">
118
+ <div class="card">
119
+ <div class="value" id="main-value">--</div>
120
+ <div class="label">Loading...</div>
121
+ </div>
122
+ </div>
123
+
124
+ <script>
125
+ // Example: fetch data and display
126
+ async function update() {
127
+ try {
128
+ ${permissions.includes('system:info')
129
+ ? `const info = await ccweb.getSystemInfo();
130
+ document.getElementById('main-value').textContent = info.cpu.usage + '%';
131
+ document.querySelector('.label').textContent = 'CPU Usage';`
132
+ : `document.getElementById('main-value').textContent = 'Hello!';
133
+ document.querySelector('.label').textContent = '${displayName} is running';`}
134
+ } catch (err) {
135
+ document.getElementById('main-value').textContent = 'Error';
136
+ document.querySelector('.label').textContent = err.message;
137
+ }
138
+ }
139
+ update();
140
+ setInterval(update, 3000);
141
+ <\/script>
142
+ </body>
143
+ </html>
144
+ `);
145
+
146
+ // backend/index.js (optional)
147
+ if (hasBackend) {
148
+ fs.writeFileSync(path.join(dir, 'backend', 'index.js'), `'use strict';
149
+
150
+ const { Router } = require('express');
151
+ const router = Router();
152
+
153
+ // Plugin backend API routes
154
+ // These are mounted at /api/plugins/${id}/
155
+
156
+ router.get('/status', (_req, res) => {
157
+ res.json({ status: 'ok', plugin: '${id}' });
158
+ });
159
+
160
+ // Optional lifecycle hooks
161
+ function onStart() {
162
+ console.log('[${id}] Plugin backend started');
163
+ }
164
+
165
+ function onStop() {
166
+ console.log('[${id}] Plugin backend stopped');
167
+ }
168
+
169
+ module.exports = { router, onStart, onStop };
170
+ `);
171
+ }
172
+
173
+ // package.json
174
+ fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({
175
+ name: `ccweb-plugin-${id}`,
176
+ version: '1.0.0',
177
+ description,
178
+ private: true,
179
+ scripts: {
180
+ build: 'node build.js',
181
+ },
182
+ }, null, 2));
183
+
184
+ // build.js
185
+ fs.writeFileSync(path.join(dir, 'build.js'), `'use strict';
186
+ const { execSync } = require('child_process');
187
+ const fs = require('fs');
188
+ const path = require('path');
189
+
190
+ const id = require('./manifest.json').id;
191
+ const version = require('./manifest.json').version;
192
+ const outFile = \`\${id}-\${version}.zip\`;
193
+
194
+ // Remove old zip if exists
195
+ if (fs.existsSync(outFile)) fs.unlinkSync(outFile);
196
+
197
+ // Create zip excluding node_modules and build artifacts
198
+ execSync(\`zip -r "\${outFile}" manifest.json frontend/ ${hasBackend ? 'backend/' : ''} -x "*.DS_Store"\`, { stdio: 'inherit' });
199
+
200
+ console.log(\`\\nBuilt: \${outFile} (\${(fs.statSync(outFile).size / 1024).toFixed(1)} KB)\`);
201
+ `);
202
+
203
+ // README.md
204
+ fs.writeFileSync(path.join(dir, 'README.md'), `# ${displayName}
205
+
206
+ ${description}
207
+
208
+ ## Development
209
+
210
+ 1. Edit \`frontend/index.html\` — the plugin UI (runs in iframe)
211
+ ${hasBackend ? '2. Edit `backend/index.js` — Express router (mounted at `/api/plugins/' + id + '/`)\n' : ''}
212
+ ## Build
213
+
214
+ \`\`\`bash
215
+ npm run build
216
+ \`\`\`
217
+
218
+ This creates \`${id}-1.0.0.zip\` which can be uploaded to the ccweb Plugin Hub.
219
+
220
+ ## SDK API
221
+
222
+ In your \`index.html\`, include the SDK:
223
+ \`\`\`html
224
+ <script src="/plugin-sdk/ccweb-plugin-sdk.js"></script>
225
+ \`\`\`
226
+
227
+ Available methods:
228
+ - \`ccweb.getSystemInfo()\` — CPU, memory, uptime (requires \`system:info\`)
229
+ - \`ccweb.getProjectList()\` — list all projects (requires \`project:list\`)
230
+ - \`ccweb.getProjectStatus(id)\` — project status (requires \`project:status\`)
231
+ - \`ccweb.sendTerminal(id, data)\` — send to terminal (requires \`terminal:send\`)
232
+ - \`ccweb.getSessionHistory(id)\` — chat history (requires \`session:read\`)
233
+ - \`ccweb.getStorage()\` / \`ccweb.setStorage(data)\` — private persistent data
234
+ - \`ccweb.backendApi(method, path, body)\` — call plugin's own backend
235
+ `);
236
+
237
+ console.log(`\n✅ Plugin "${displayName}" created in ./${id}/`);
238
+ console.log(`\nNext steps:`);
239
+ console.log(` cd ${id}`);
240
+ console.log(` # Edit frontend/index.html`);
241
+ ${hasBackend ? "console.log(` # Edit backend/index.js`);" : ''}
242
+ console.log(` npm run build # Create zip for Hub upload`);
243
+ })();
244
+ }
245
+
246
+ // ── build ───────────────────────────────────────────────────────────────────
247
+
248
+ if (command === 'build') {
249
+ const manifestPath = path.resolve('manifest.json');
250
+ if (!fs.existsSync(manifestPath)) {
251
+ console.error('manifest.json not found. Run this command from a plugin directory.');
252
+ process.exit(1);
253
+ }
254
+ // Delegate to build.js if it exists, else do inline build
255
+ const buildScript = path.resolve('build.js');
256
+ if (fs.existsSync(buildScript)) {
257
+ require(buildScript);
258
+ } else {
259
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
260
+ const outFile = `${manifest.id}-${manifest.version}.zip`;
261
+ const { execSync } = require('child_process');
262
+ const parts = ['manifest.json', 'frontend/'];
263
+ if (manifest.backend) parts.push('backend/');
264
+ if (fs.existsSync('icon.svg')) parts.push('icon.svg');
265
+ execSync(`zip -r "${outFile}" ${parts.join(' ')} -x "*.DS_Store"`, { stdio: 'inherit' });
266
+ console.log(`\nBuilt: ${outFile} (${(fs.statSync(outFile).size / 1024).toFixed(1)} KB)`);
267
+ }
268
+ }
@@ -1,4 +1,4 @@
1
- import{c as je,r as C,d as De,j as y,B as q,m as he}from"./index-BPzNyZy4.js";import{L as Ye,Z as Pe,a as Be}from"./ProjectPage-B8Tdoz_M.js";import"./save-dexIyJWW.js";import"./download-DJNy8XSX.js";import"./chevron-down-BPKbPuX9.js";import"./bot-CP4ljg4K.js";import"./user-BGUBSa7q.js";/**
1
+ import{c as je,r as C,d as De,j as y,B as q,m as he}from"./index-D7mCoW2r.js";import{L as Ye,Z as Pe,a as Be}from"./ProjectPage-BmYhTTYq.js";import"./save-CdDjQhdC.js";import"./download-UC5GvInE.js";import"./chevron-down-BR0IMbA9.js";import"./bot-hRRV5XmX.js";import"./user-Bv38vpTL.js";/**
2
2
  * @license lucide-react v0.309.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,5 +1,5 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-CENzb-E2.js","assets/index-BPzNyZy4.js","assets/index-PNcejD9U.css","assets/jszip.min-CPp1Je4B.js"])))=>i.map(i=>d[i]);
2
- import{j as e,r as c,_ as m,b as y,h as S}from"./index-BPzNyZy4.js";async function h(a){let l=S(a);const s=y();s&&(l+=`${l.includes("?")?"&":"?"}token=${encodeURIComponent(s)}`);const d=await fetch(l);if(!d.ok)throw new Error(`Failed to fetch file: ${d.status}`);return d.arrayBuffer()}function j({filePath:a,zoom:l}){const[s,d]=c.useState(""),[x,n]=c.useState(null),[u,i]=c.useState(!0);return c.useEffect(()=>{let t=!1;return i(!0),n(null),(async()=>{try{const r=await m(()=>import("./index-CENzb-E2.js").then(f=>f.i),__vite__mapDeps([0,1,2,3])),o=await h(a),p=await r.convertToHtml({arrayBuffer:o});t||d(p.value)}catch(r){t||n(r instanceof Error?r.message:"Failed to render docx")}finally{t||i(!1)}})(),()=>{t=!0}},[a]),u?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"加载 Word 文档中..."}):x?e.jsx("p",{className:"text-sm text-destructive p-4",children:x}):e.jsx("div",{className:"p-6 prose dark:prose-invert max-w-none",style:{fontSize:`${12*l/100}px`},dangerouslySetInnerHTML:{__html:s}})}function _({filePath:a,zoom:l}){var o;const[s,d]=c.useState([]),[x,n]=c.useState(0),[u,i]=c.useState(null),[t,r]=c.useState(!0);return c.useEffect(()=>{let p=!1;return r(!0),i(null),(async()=>{try{const f=await m(()=>import("./xlsx-D_0l8YDs.js"),[]),v=await h(a),g=f.read(v,{type:"array"}),b=g.SheetNames.map(w=>({name:w,html:f.utils.sheet_to_html(g.Sheets[w],{editable:!1})}));p||(d(b),n(0))}catch(f){p||i(f instanceof Error?f.message:"Failed to render xlsx")}finally{p||r(!1)}})(),()=>{p=!0}},[a]),t?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"加载 Excel 文件中..."}):u?e.jsx("p",{className:"text-sm text-destructive p-4",children:u}):s.length===0?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"空文件"}):e.jsxs("div",{className:"flex flex-col h-full",children:[s.length>1&&e.jsx("div",{className:"flex gap-0.5 px-3 py-1.5 border-b border-border bg-muted/30 flex-shrink-0 overflow-x-auto",children:s.map((p,f)=>e.jsx("button",{onClick:()=>n(f),className:`px-3 py-1 text-xs rounded-t transition-colors whitespace-nowrap ${f===x?"bg-background text-foreground border border-b-0 border-border":"text-muted-foreground hover:text-foreground"}`,children:p.name},f))}),e.jsx("div",{className:"flex-1 overflow-auto p-2 xlsx-preview",style:{fontSize:`${12*l/100}px`},dangerouslySetInnerHTML:{__html:((o=s[x])==null?void 0:o.html)??""}}),e.jsx("style",{children:`
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-BiYAwwZA.js","assets/index-D7mCoW2r.js","assets/index-DgHvs3fU.css","assets/jszip.min-YWYO5s4l.js"])))=>i.map(i=>d[i]);
2
+ import{j as e,r as c,_ as m,b as y,h as S}from"./index-D7mCoW2r.js";async function h(a){let l=S(a);const s=y();s&&(l+=`${l.includes("?")?"&":"?"}token=${encodeURIComponent(s)}`);const d=await fetch(l);if(!d.ok)throw new Error(`Failed to fetch file: ${d.status}`);return d.arrayBuffer()}function j({filePath:a,zoom:l}){const[s,d]=c.useState(""),[x,n]=c.useState(null),[u,i]=c.useState(!0);return c.useEffect(()=>{let t=!1;return i(!0),n(null),(async()=>{try{const r=await m(()=>import("./index-BiYAwwZA.js").then(f=>f.i),__vite__mapDeps([0,1,2,3])),o=await h(a),p=await r.convertToHtml({arrayBuffer:o});t||d(p.value)}catch(r){t||n(r instanceof Error?r.message:"Failed to render docx")}finally{t||i(!1)}})(),()=>{t=!0}},[a]),u?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"加载 Word 文档中..."}):x?e.jsx("p",{className:"text-sm text-destructive p-4",children:x}):e.jsx("div",{className:"p-6 prose dark:prose-invert max-w-none",style:{fontSize:`${12*l/100}px`},dangerouslySetInnerHTML:{__html:s}})}function _({filePath:a,zoom:l}){var o;const[s,d]=c.useState([]),[x,n]=c.useState(0),[u,i]=c.useState(null),[t,r]=c.useState(!0);return c.useEffect(()=>{let p=!1;return r(!0),i(null),(async()=>{try{const f=await m(()=>import("./xlsx-D_0l8YDs.js"),[]),v=await h(a),g=f.read(v,{type:"array"}),b=g.SheetNames.map(w=>({name:w,html:f.utils.sheet_to_html(g.Sheets[w],{editable:!1})}));p||(d(b),n(0))}catch(f){p||i(f instanceof Error?f.message:"Failed to render xlsx")}finally{p||r(!1)}})(),()=>{p=!0}},[a]),t?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"加载 Excel 文件中..."}):u?e.jsx("p",{className:"text-sm text-destructive p-4",children:u}):s.length===0?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"空文件"}):e.jsxs("div",{className:"flex flex-col h-full",children:[s.length>1&&e.jsx("div",{className:"flex gap-0.5 px-3 py-1.5 border-b border-border bg-muted/30 flex-shrink-0 overflow-x-auto",children:s.map((p,f)=>e.jsx("button",{onClick:()=>n(f),className:`px-3 py-1 text-xs rounded-t transition-colors whitespace-nowrap ${f===x?"bg-background text-foreground border border-b-0 border-border":"text-muted-foreground hover:text-foreground"}`,children:p.name},f))}),e.jsx("div",{className:"flex-1 overflow-auto p-2 xlsx-preview",style:{fontSize:`${12*l/100}px`},dangerouslySetInnerHTML:{__html:((o=s[x])==null?void 0:o.html)??""}}),e.jsx("style",{children:`
3
3
  .xlsx-preview table { border-collapse: collapse; width: auto; min-width: 100%; }
4
4
  .xlsx-preview td, .xlsx-preview th {
5
5
  border: 1px solid hsl(var(--border));
@@ -10,4 +10,4 @@ import{j as e,r as c,_ as m,b as y,h as S}from"./index-BPzNyZy4.js";async functi
10
10
  }
11
11
  .xlsx-preview th { background: hsl(var(--muted)); font-weight: 600; }
12
12
  .xlsx-preview tr:hover td { background: hsl(var(--accent) / 0.3); }
13
- `})]})}async function E(a){const{default:l}=await m(async()=>{const{default:n}=await import("./jszip.min-CPp1Je4B.js").then(u=>u.j);return{default:n}},__vite__mapDeps([3,1,2])),s=await l.loadAsync(a),d=[],x=Object.keys(s.files).filter(n=>/^ppt\/slides\/slide\d+\.xml$/i.test(n)).sort((n,u)=>{var r,o;const i=parseInt(((r=n.match(/slide(\d+)/))==null?void 0:r[1])??"0"),t=parseInt(((o=u.match(/slide(\d+)/))==null?void 0:o[1])??"0");return i-t});for(let n=0;n<x.length;n++){const u=await s.file(x[n]).async("text"),i=[],t=/<a:t[^>]*>([\s\S]*?)<\/a:t>/g;let r;for(;(r=t.exec(u))!==null;){const o=r[1].replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').trim();o&&i.push(o)}d.push({index:n+1,texts:i})}return d}function N({filePath:a,zoom:l}){const[s,d]=c.useState([]),[x,n]=c.useState(null),[u,i]=c.useState(!0);return c.useEffect(()=>{let t=!1;return i(!0),n(null),(async()=>{try{const r=await h(a),o=await E(r);t||d(o)}catch(r){t||n(r instanceof Error?r.message:"Failed to render pptx")}finally{t||i(!1)}})(),()=>{t=!0}},[a]),u?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"加载 PPT 文件中..."}):x?e.jsx("p",{className:"text-sm text-destructive p-4",children:x}):s.length===0?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"空文件"}):e.jsx("div",{className:"p-4 space-y-4",style:{fontSize:`${12*l/100}px`},children:s.map(t=>e.jsxs("div",{className:"border border-border rounded-lg p-5 bg-muted/20",children:[e.jsxs("div",{className:"text-xs text-muted-foreground mb-2 font-medium",children:["Slide ",t.index]}),t.texts.length>0?e.jsx("div",{className:"space-y-1.5",children:t.texts.map((r,o)=>e.jsx("p",{className:"text-foreground leading-relaxed",style:{fontSize:"inherit"},children:r},o))}):e.jsx("p",{className:"text-muted-foreground text-sm italic",children:"(无文本内容)"})]},t.index))})}const I=new Set(["docx","xlsx","xls","pptx"]);function L({filePath:a,ext:l,zoom:s}){return l==="docx"?e.jsx(j,{filePath:a,zoom:s}):l==="xlsx"||l==="xls"?e.jsx(_,{filePath:a,zoom:s}):l==="pptx"?e.jsx(N,{filePath:a,zoom:s}):null}export{I as OFFICE_EXTS,L as OfficePreview};
13
+ `})]})}async function E(a){const{default:l}=await m(async()=>{const{default:n}=await import("./jszip.min-YWYO5s4l.js").then(u=>u.j);return{default:n}},__vite__mapDeps([3,1,2])),s=await l.loadAsync(a),d=[],x=Object.keys(s.files).filter(n=>/^ppt\/slides\/slide\d+\.xml$/i.test(n)).sort((n,u)=>{var r,o;const i=parseInt(((r=n.match(/slide(\d+)/))==null?void 0:r[1])??"0"),t=parseInt(((o=u.match(/slide(\d+)/))==null?void 0:o[1])??"0");return i-t});for(let n=0;n<x.length;n++){const u=await s.file(x[n]).async("text"),i=[],t=/<a:t[^>]*>([\s\S]*?)<\/a:t>/g;let r;for(;(r=t.exec(u))!==null;){const o=r[1].replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').trim();o&&i.push(o)}d.push({index:n+1,texts:i})}return d}function N({filePath:a,zoom:l}){const[s,d]=c.useState([]),[x,n]=c.useState(null),[u,i]=c.useState(!0);return c.useEffect(()=>{let t=!1;return i(!0),n(null),(async()=>{try{const r=await h(a),o=await E(r);t||d(o)}catch(r){t||n(r instanceof Error?r.message:"Failed to render pptx")}finally{t||i(!1)}})(),()=>{t=!0}},[a]),u?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"加载 PPT 文件中..."}):x?e.jsx("p",{className:"text-sm text-destructive p-4",children:x}):s.length===0?e.jsx("p",{className:"text-sm text-muted-foreground p-4",children:"空文件"}):e.jsx("div",{className:"p-4 space-y-4",style:{fontSize:`${12*l/100}px`},children:s.map(t=>e.jsxs("div",{className:"border border-border rounded-lg p-5 bg-muted/20",children:[e.jsxs("div",{className:"text-xs text-muted-foreground mb-2 font-medium",children:["Slide ",t.index]}),t.texts.length>0?e.jsx("div",{className:"space-y-1.5",children:t.texts.map((r,o)=>e.jsx("p",{className:"text-foreground leading-relaxed",style:{fontSize:"inherit"},children:r},o))}):e.jsx("p",{className:"text-muted-foreground text-sm italic",children:"(无文本内容)"})]},t.index))})}const I=new Set(["docx","xlsx","xls","pptx"]);function L({filePath:a,ext:l,zoom:s}){return l==="docx"?e.jsx(j,{filePath:a,zoom:s}):l==="xlsx"||l==="xls"?e.jsx(_,{filePath:a,zoom:s}):l==="pptx"?e.jsx(N,{filePath:a,zoom:s}):null}export{I as OFFICE_EXTS,L as OfficePreview};