foliko 1.1.0 → 1.1.2

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 (214) hide show
  1. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  2. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  3. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
  4. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  5. package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
  6. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  7. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
  8. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  9. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  10. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  11. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  12. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  13. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  14. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  15. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  16. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  17. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  18. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  19. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  20. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  21. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  22. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  23. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  24. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
  25. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  26. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  27. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
  28. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
  29. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
  30. package/.agent/ARCHITECTURE.md +288 -0
  31. package/.agent/agents/ambient-agent.md +57 -0
  32. package/.agent/agents/debugger.md +55 -0
  33. package/.agent/agents/email-assistant.md +49 -0
  34. package/.agent/agents/file-manager.md +42 -0
  35. package/.agent/agents/python-developer.md +60 -0
  36. package/.agent/agents/scheduler.md +59 -0
  37. package/.agent/agents/web-developer.md +45 -0
  38. package/.agent/data/default.json +412 -3
  39. package/.agent/data/plugins-state.json +173 -174
  40. package/.agent/data/puppeteer-sessions/undefined.json +6 -0
  41. package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
  42. package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
  43. package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
  44. package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
  45. package/.agent/mcp_config_updated.json +12 -0
  46. package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
  47. package/.agent/plugins/poster-plugin/package.json +2 -1
  48. package/.agent/plugins/poster-plugin/src/canvas.js +70 -7
  49. package/.agent/plugins/poster-plugin/src/components/barcode.js +120 -0
  50. package/.agent/plugins/poster-plugin/src/components/bubble.js +153 -0
  51. package/.agent/plugins/poster-plugin/src/components/button.js +124 -0
  52. package/.agent/plugins/poster-plugin/src/components/cta.js +26 -24
  53. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +22 -17
  54. package/.agent/plugins/poster-plugin/src/components/frame.js +230 -0
  55. package/.agent/plugins/poster-plugin/src/components/highlightText.js +144 -0
  56. package/.agent/plugins/poster-plugin/src/components/icon.js +94 -0
  57. package/.agent/plugins/poster-plugin/src/components/index.js +19 -0
  58. package/.agent/plugins/poster-plugin/src/components/listItem.js +6 -5
  59. package/.agent/plugins/poster-plugin/src/components/qrcode.js +74 -0
  60. package/.agent/plugins/poster-plugin/src/components/ribbon.js +193 -0
  61. package/.agent/plugins/poster-plugin/src/components/seal.js +146 -0
  62. package/.agent/plugins/poster-plugin/src/components/table.js +17 -9
  63. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +24 -17
  64. package/.agent/plugins/poster-plugin/src/components/timeline.js +24 -12
  65. package/.agent/plugins/poster-plugin/src/composer.js +392 -150
  66. package/.agent/plugins/poster-plugin/src/elements/background.js +36 -4
  67. package/.agent/plugins/poster-plugin/src/elements/image.js +4 -47
  68. package/.agent/plugins/poster-plugin/src/elements/index.js +2 -0
  69. package/.agent/plugins/poster-plugin/src/elements/polygon.js +37 -6
  70. package/.agent/plugins/poster-plugin/src/elements/richText.js +230 -0
  71. package/.agent/plugins/poster-plugin/src/elements/svg.js +35 -19
  72. package/.agent/plugins/poster-plugin/src/elements/text.js +71 -2
  73. package/.agent/plugins/poster-plugin/src/fonts.js +123 -8
  74. package/.agent/plugins/poster-plugin/src/index.js +445 -23
  75. package/.agent/plugins/poster-plugin/src/utils/imageLoader.js +84 -0
  76. package/.agent/plugins/poster-plugin/test-background.svg +1 -0
  77. package/.agent/plugins/poster-plugin/test-full-poster.svg +2 -0
  78. package/.agent/plugins/poster-plugin/test-image.png +0 -0
  79. package/.agent/plugins/puppeteer-plugin/README.md +147 -0
  80. package/.agent/plugins/puppeteer-plugin/index.js +1418 -0
  81. package/.agent/plugins/puppeteer-plugin/package.json +9 -0
  82. package/.agent/plugins.json +5 -11
  83. package/.agent/rules/GEMINI.md +273 -0
  84. package/.agent/rules/allow-rule.md +77 -0
  85. package/.agent/rules/log-rule.md +83 -0
  86. package/.agent/rules/security-rule.md +93 -0
  87. package/.agent/scripts/auto_preview.py +148 -0
  88. package/.agent/scripts/checklist.py +217 -0
  89. package/.agent/scripts/session_manager.py +120 -0
  90. package/.agent/scripts/verify_all.py +327 -0
  91. package/.agent/sessions/cli_default.json +678 -23580
  92. package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +11097 -0
  93. package/.agent/skills/api-patterns/SKILL.md +81 -0
  94. package/.agent/skills/api-patterns/api-style.md +42 -0
  95. package/.agent/skills/api-patterns/auth.md +24 -0
  96. package/.agent/skills/api-patterns/documentation.md +26 -0
  97. package/.agent/skills/api-patterns/graphql.md +41 -0
  98. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  99. package/.agent/skills/api-patterns/response.md +37 -0
  100. package/.agent/skills/api-patterns/rest.md +40 -0
  101. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  102. package/.agent/skills/api-patterns/security-testing.md +122 -0
  103. package/.agent/skills/api-patterns/trpc.md +41 -0
  104. package/.agent/skills/api-patterns/versioning.md +22 -0
  105. package/.agent/skills/app-builder/SKILL.md +75 -0
  106. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  107. package/.agent/skills/app-builder/feature-building.md +53 -0
  108. package/.agent/skills/app-builder/project-detection.md +34 -0
  109. package/.agent/skills/app-builder/scaffolding.md +118 -0
  110. package/.agent/skills/app-builder/tech-stack.md +40 -0
  111. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  112. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  113. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  114. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  115. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  116. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  117. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  118. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  119. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  120. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  121. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  122. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  123. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  124. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  125. package/.agent/skills/architecture/SKILL.md +55 -0
  126. package/.agent/skills/architecture/context-discovery.md +43 -0
  127. package/.agent/skills/architecture/examples.md +94 -0
  128. package/.agent/skills/architecture/pattern-selection.md +68 -0
  129. package/.agent/skills/architecture/patterns-reference.md +50 -0
  130. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  131. package/.agent/skills/clean-code/SKILL.md +201 -0
  132. package/.agent/skills/doc.md +177 -0
  133. package/.agent/skills/frontend-design/SKILL.md +418 -0
  134. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  135. package/.agent/skills/frontend-design/color-system.md +311 -0
  136. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  137. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  138. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  139. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  140. package/.agent/skills/frontend-design/typography-system.md +345 -0
  141. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  142. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  143. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  144. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  145. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  146. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  147. package/.agent/workflows/brainstorm.md +113 -0
  148. package/.agent/workflows/create.md +59 -0
  149. package/.agent/workflows/debug.md +103 -0
  150. package/.agent/workflows/deploy.md +176 -0
  151. package/.agent/workflows/enhance.md +63 -0
  152. package/.agent/workflows/orchestrate.md +237 -0
  153. package/.agent/workflows/plan.md +89 -0
  154. package/.agent/workflows/preview.md +81 -0
  155. package/.agent/workflows/simple-test.md +42 -0
  156. package/.agent/workflows/status.md +86 -0
  157. package/.agent/workflows/structured-orchestrate.md +180 -0
  158. package/.agent/workflows/test.md +144 -0
  159. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  160. package/.claude/settings.local.json +21 -1
  161. package/.env.example +56 -56
  162. package/README.md +441 -441
  163. package/cli/src/commands/chat.js +2 -1
  164. package/output/international-news-daily.png +0 -0
  165. package/package.json +2 -1
  166. package/plugins/extension-executor-plugin.js +91 -12
  167. package/plugins/file-system-plugin.js +4 -19
  168. package/plugins/subagent-plugin.js +37 -14
  169. package/plugins/weixin-plugin.js +168 -40
  170. package/poster-test-2.png +0 -0
  171. package/skills/find-skills/AGENTS.md +162 -162
  172. package/skills/find-skills/SKILL.md +133 -133
  173. package/skills/poster-guide/SKILL.md +1435 -627
  174. package/src/core/agent-chat.js +223 -11
  175. package/src/core/agent.js +6 -3
  176. package/.agent/agents/code-assistant.json +0 -14
  177. package/.agent/agents/email-assistant.json +0 -14
  178. package/.agent/agents/file-assistant.json +0 -15
  179. package/.agent/agents/system-assistant.json +0 -15
  180. package/.agent/agents/web-assistant.json +0 -12
  181. package/.agent/data/ambient/goals.json +0 -50
  182. package/.agent/data/ambient/memories.json +0 -7
  183. package/.agent/data/scheduler/tasks.json +0 -1
  184. package/.agent/memory/core.md +0 -1
  185. package/.agent/memory/project/mnn93ogy-ypjn27.md +0 -9
  186. package/.agent/memory/project/mnn98fqy-5nhc1u.md +0 -25
  187. package/.agent/memory/user/mnm67t9m-x8rekk.md +0 -9
  188. package/.agent/memory/user/mnn5mmqh-w6aktx.md +0 -11
  189. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +0 -22
  190. package/.agent/package.json +0 -8
  191. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  192. package/.agent/plugins/daytona/README.md +0 -89
  193. package/.agent/plugins/daytona/index.js +0 -377
  194. package/.agent/plugins/daytona/package.json +0 -12
  195. package/.agent/plugins/marknative/README.md +0 -134
  196. package/.agent/plugins/marknative/index.js +0 -228
  197. package/.agent/plugins/marknative/package.json +0 -12
  198. package/.agent/plugins/marknative/update-readme.js +0 -134
  199. package/.agent/plugins/system-info/index.js +0 -387
  200. package/.agent/plugins/system-info/package.json +0 -4
  201. package/.agent/plugins/system-info/test.js +0 -40
  202. package/.agent/python-scripts/test_sample.py +0 -24
  203. package/.agent/skills/agent-browser/SKILL.md +0 -311
  204. package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
  205. package/.agent/skills/sysinfo/SKILL.md +0 -38
  206. package/.agent/skills/sysinfo/system-info.sh +0 -130
  207. package/.agent/skills/workflow/SKILL.md +0 -324
  208. package/.agent/weixin.json +0 -6
  209. package/.agent/workflows/email-digest.json +0 -50
  210. package/.agent/workflows/file-backup.json +0 -21
  211. package/.agent/workflows/get-ip-notify.json +0 -32
  212. package/.agent/workflows/news-aggregator.json +0 -93
  213. package/.agent/workflows/news-dashboard-v2.json +0 -94
  214. package/.agent/workflows/notification-batch.json +0 -32
@@ -21,6 +21,7 @@ const {
21
21
  addImage,
22
22
  addText,
23
23
  addArtText,
24
+ addRichText,
24
25
  addBackground,
25
26
  addSVG,
26
27
  } = require('./elements')
@@ -51,6 +52,15 @@ const {
51
52
  createChart,
52
53
  createWatermark,
53
54
  createTable,
55
+ createButton,
56
+ createIcon,
57
+ createQRCode,
58
+ createFrame,
59
+ createBubble,
60
+ createRibbon,
61
+ createSeal,
62
+ createHighlightText,
63
+ createBarcode,
54
64
  } = require('./components')
55
65
 
56
66
  module.exports = function (Plugin) {
@@ -66,20 +76,11 @@ module.exports = function (Plugin) {
66
76
  this._canvasManager = new CanvasManager()
67
77
  }
68
78
 
69
- async install(framework) {
70
- this._framework = framework
71
- console.log('[poster] Poster plugin installed (v1.1.0)')
72
- console.log('[poster] Components:', Object.keys(COMPONENT_TYPES).join(', '))
73
- return this
74
- }
75
-
76
- start(framework) {
77
- console.log('[poster] Poster plugin started')
78
- }
79
+
79
80
 
80
81
  // ==================== 工具定义 ====================
81
82
 
82
- all_tools = {
83
+ tools = {
83
84
  // ==================== 画布管理 ====================
84
85
 
85
86
  /**
@@ -103,11 +104,13 @@ module.exports = function (Plugin) {
103
104
  preset: z.string().optional().describe('预设尺寸key'),
104
105
  width: z.number().optional().describe('自定义宽度'),
105
106
  height: z.number().optional().describe('自定义高度'),
106
- background: z.string().optional().describe('背景颜色'),
107
+ background: z.union([z.string(), z.object({
108
+ image: z.string()
109
+ })]).optional().describe('背景颜色或图片路径'),
107
110
  }),
108
111
  execute: async (args) => {
109
112
  try {
110
- const result = this._canvasManager.create(args)
113
+ const result = await this._canvasManager.create(args)
111
114
  return { success: true, ...result }
112
115
  } catch (err) {
113
116
  return { success: false, error: err.message }
@@ -155,7 +158,7 @@ module.exports = function (Plugin) {
155
158
  * 添加背景
156
159
  */
157
160
  add_poster_background: {
158
- description: '为画布添加纯色或渐变背景',
161
+ description: '为画布添加纯色、渐变或图片背景',
159
162
  inputSchema: z.object({
160
163
  color: z.string().optional().describe('纯色背景'),
161
164
  gradient: z.object({
@@ -163,13 +166,14 @@ module.exports = function (Plugin) {
163
166
  colors: z.array(z.string()).describe('颜色数组'),
164
167
  direction: z.number().optional().describe('方向角度,默认45'),
165
168
  }).optional(),
169
+ image: z.string().optional().describe('背景图片路径(本地路径或URL)'),
166
170
  }),
167
171
  execute: async (args) => {
168
172
  try {
169
173
  if (!this._canvasManager.isCreated()) {
170
174
  return { success: false, error: 'No canvas created' }
171
175
  }
172
- return addBackground(
176
+ return await addBackground(
173
177
  this._canvasManager.getProject(),
174
178
  this._canvasManager.getCanvas(),
175
179
  args
@@ -355,6 +359,82 @@ module.exports = function (Plugin) {
355
359
  },
356
360
  },
357
361
 
362
+ /**
363
+ * 添加富文本(支持旋转和多种样式)
364
+ */
365
+ add_poster_rich_text: {
366
+ description: '添加富文本,支持旋转、描边、渐变、阴影等多种样式',
367
+ inputSchema: z.object({
368
+ // 位置和尺寸
369
+ x: z.number().describe('X坐标'),
370
+ y: z.number().describe('Y坐标'),
371
+ width: z.number().optional().describe('文本区域宽度(用于自动换行)'),
372
+
373
+ // 文本内容
374
+ text: z.string().describe('文字内容'),
375
+
376
+ // 字体样式
377
+ fontSize: z.number().optional().describe('字体大小,默认48'),
378
+ fontFamily: z.string().optional().describe('字体名称'),
379
+ fontWeight: z.union([z.string(), z.number()]).optional().describe('字重 normal/bold 或 100-900'),
380
+ fontStyle: z.enum(['normal', 'italic', 'oblique']).optional().describe('字体风格'),
381
+ bold: z.boolean().optional().describe('粗体'),
382
+ italic: z.boolean().optional().describe('斜体'),
383
+
384
+ // 文字装饰
385
+ underline: z.boolean().optional().describe('下划线'),
386
+ strikethrough: z.boolean().optional().describe('删除线'),
387
+
388
+ // 颜色
389
+ color: z.string().optional().describe('文字颜色,默认#ffffff'),
390
+ backgroundColor: z.string().optional().describe('文字背景色'),
391
+ gradient: z.object({
392
+ colors: z.array(z.string()).describe('渐变颜色数组'),
393
+ direction: z.number().optional().describe('方向角度'),
394
+ }).optional().describe('渐变填充'),
395
+
396
+ // 描边
397
+ strokeColor: z.string().optional().describe('描边颜色'),
398
+ strokeWidth: z.number().optional().describe('描边宽度'),
399
+
400
+ // 阴影
401
+ shadow: z.object({
402
+ color: z.string().optional().describe('阴影颜色'),
403
+ blur: z.number().optional().describe('模糊度'),
404
+ offsetX: z.number().optional().describe('X偏移'),
405
+ offsetY: z.number().optional().describe('Y偏移'),
406
+ }).optional(),
407
+
408
+ // 间距
409
+ letterSpacing: z.number().optional().describe('字间距'),
410
+ lineSpacing: z.number().optional().describe('行间距增量'),
411
+ lineHeight: z.number().optional().describe('行高'),
412
+
413
+ // 对齐
414
+ align: z.enum(['left', 'center', 'right', 'justify']).optional().describe('对齐方式'),
415
+
416
+ // 变换
417
+ rotation: z.number().optional().describe('旋转角度(度)'),
418
+ scale: z.union([z.number(), z.object({
419
+ x: z.number().optional(),
420
+ y: z.number().optional()
421
+ })]).optional().describe('缩放'),
422
+
423
+ // 透明度
424
+ opacity: z.number().optional().describe('透明度 0-1,默认1'),
425
+ }),
426
+ execute: async (args) => {
427
+ try {
428
+ if (!this._canvasManager.isCreated()) {
429
+ return { success: false, error: 'No canvas created' }
430
+ }
431
+ return addRichText(this._canvasManager.getProject(), args)
432
+ } catch (err) {
433
+ return { success: false, error: err.message }
434
+ }
435
+ },
436
+ },
437
+
358
438
  /**
359
439
  * 添加图片
360
440
  */
@@ -373,7 +453,7 @@ module.exports = function (Plugin) {
373
453
  if (!this._canvasManager.isCreated()) {
374
454
  return { success: false, error: 'No canvas created' }
375
455
  }
376
- return addImage(this._canvasManager.getProject(), args)
456
+ return await addImage(this._canvasManager.getProject(), args)
377
457
  } catch (err) {
378
458
  return { success: false, error: err.message }
379
459
  }
@@ -1454,6 +1534,339 @@ module.exports = function (Plugin) {
1454
1534
  },
1455
1535
  },
1456
1536
 
1537
+ /**
1538
+ * 添加按钮
1539
+ */
1540
+ add_poster_button: {
1541
+ description: '添加按钮组件',
1542
+ inputSchema: z.object({
1543
+ x: z.number().describe('X坐标'),
1544
+ y: z.number().describe('Y坐标'),
1545
+ width: z.number().optional().describe('宽度,默认200'),
1546
+ height: z.number().optional().describe('高度,默认60'),
1547
+ text: z.string().optional().describe('按钮文字'),
1548
+ fontSize: z.number().optional().describe('字体大小'),
1549
+ color: z.string().optional().describe('文字颜色'),
1550
+ backgroundColor: z.string().optional().describe('背景色'),
1551
+ borderColor: z.string().optional().describe('边框颜色'),
1552
+ borderWidth: z.number().optional().describe('边框宽度'),
1553
+ radius: z.number().optional().describe('圆角'),
1554
+ shadow: z.object({
1555
+ color: z.string().optional(),
1556
+ blur: z.number().optional(),
1557
+ offsetX: z.number().optional(),
1558
+ offsetY: z.number().optional(),
1559
+ }).optional(),
1560
+ gradient: z.object({
1561
+ colors: z.array(z.string()).describe('渐变颜色数组'),
1562
+ }).optional(),
1563
+ opacity: z.number().optional().describe('透明度'),
1564
+ }),
1565
+ execute: async (args) => {
1566
+ try {
1567
+ if (!this._canvasManager.isCreated()) {
1568
+ return { success: false, error: 'No canvas created' }
1569
+ }
1570
+ return await createButton(
1571
+ this._canvasManager.getProject(),
1572
+ this._canvasManager.getCanvas(),
1573
+ args
1574
+ )
1575
+ } catch (err) {
1576
+ return { success: false, error: err.message }
1577
+ }
1578
+ },
1579
+ },
1580
+
1581
+ /**
1582
+ * 添加图标
1583
+ */
1584
+ add_poster_icon: {
1585
+ description: '添加图标(emoji或图片)',
1586
+ inputSchema: z.object({
1587
+ x: z.number().describe('X坐标'),
1588
+ y: z.number().describe('Y坐标'),
1589
+ size: z.number().optional().describe('图标大小,默认64'),
1590
+ icon: z.string().describe('图标内容(emoji或图片URL)'),
1591
+ color: z.string().optional().describe('颜色'),
1592
+ backgroundColor: z.string().optional().describe('背景色'),
1593
+ borderColor: z.string().optional().describe('边框颜色'),
1594
+ borderWidth: z.number().optional().describe('边框宽度'),
1595
+ radius: z.number().optional().describe('圆角'),
1596
+ shadow: z.object({
1597
+ color: z.string().optional(),
1598
+ blur: z.number().optional(),
1599
+ offsetX: z.number().optional(),
1600
+ offsetY: z.number().optional(),
1601
+ }).optional(),
1602
+ opacity: z.number().optional().describe('透明度'),
1603
+ }),
1604
+ execute: async (args) => {
1605
+ try {
1606
+ if (!this._canvasManager.isCreated()) {
1607
+ return { success: false, error: 'No canvas created' }
1608
+ }
1609
+ return await createIcon(
1610
+ this._canvasManager.getProject(),
1611
+ args
1612
+ )
1613
+ } catch (err) {
1614
+ return { success: false, error: err.message }
1615
+ }
1616
+ },
1617
+ },
1618
+
1619
+ /**
1620
+ * 添加二维码
1621
+ */
1622
+ // add_poster_qrcode: {
1623
+ // description: '添加二维码',
1624
+ // inputSchema: z.object({
1625
+ // x: z.number().describe('X坐标'),
1626
+ // y: z.number().describe('Y坐标'),
1627
+ // size: z.number().optional().describe('二维码大小,默认200'),
1628
+ // content: z.string().describe('二维码内容'),
1629
+ // color: z.string().optional().describe('前景色'),
1630
+ // backgroundColor: z.string().optional().describe('背景色'),
1631
+ // logo: z.string().optional().describe('中间logo图片路径'),
1632
+ // logoSize: z.number().optional().describe('logo大小'),
1633
+ // opacity: z.number().optional().describe('透明度'),
1634
+ // }),
1635
+ // execute: async (args) => {
1636
+ // try {
1637
+ // if (!this._canvasManager.isCreated()) {
1638
+ // return { success: false, error: 'No canvas created' }
1639
+ // }
1640
+ // return await createQRCode(
1641
+ // this._canvasManager.getProject(),
1642
+ // this._canvasManager.getCanvas(),
1643
+ // args
1644
+ // )
1645
+ // } catch (err) {
1646
+ // return { success: false, error: err.message }
1647
+ // }
1648
+ // },
1649
+ // },
1650
+
1651
+ /**
1652
+ * 添加装饰边框
1653
+ */
1654
+ add_poster_frame: {
1655
+ description: '添加装饰边框',
1656
+ inputSchema: z.object({
1657
+ x: z.number().describe('X坐标'),
1658
+ y: z.number().describe('Y坐标'),
1659
+ width: z.number().describe('宽度'),
1660
+ height: z.number().describe('高度'),
1661
+ style: z.enum(['simple', 'double', 'dashed', 'dotted', 'corner', 'vintage', 'modern', 'floral']).optional().describe('边框样式'),
1662
+ color: z.string().optional().describe('边框颜色'),
1663
+ borderWidth: z.number().optional().describe('边框宽度'),
1664
+ radius: z.number().optional().describe('圆角'),
1665
+ padding: z.number().optional().describe('内边距'),
1666
+ opacity: z.number().optional().describe('透明度'),
1667
+ }),
1668
+ execute: async (args) => {
1669
+ try {
1670
+ if (!this._canvasManager.isCreated()) {
1671
+ return { success: false, error: 'No canvas created' }
1672
+ }
1673
+ return await createFrame(
1674
+ this._canvasManager.getProject(),
1675
+ this._canvasManager.getCanvas(),
1676
+ args
1677
+ )
1678
+ } catch (err) {
1679
+ return { success: false, error: err.message }
1680
+ }
1681
+ },
1682
+ },
1683
+
1684
+ /**
1685
+ * 添加对话气泡
1686
+ */
1687
+ add_poster_bubble: {
1688
+ description: '添加对话气泡',
1689
+ inputSchema: z.object({
1690
+ x: z.number().describe('X坐标'),
1691
+ y: z.number().describe('Y坐标'),
1692
+ width: z.number().optional().describe('宽度,默认300'),
1693
+ height: z.number().optional().describe('高度,默认100'),
1694
+ text: z.string().describe('气泡文字'),
1695
+ fontSize: z.number().optional().describe('字体大小'),
1696
+ color: z.string().optional().describe('文字颜色'),
1697
+ backgroundColor: z.string().optional().describe('背景色'),
1698
+ borderColor: z.string().optional().describe('边框颜色'),
1699
+ borderWidth: z.number().optional().describe('边框宽度'),
1700
+ radius: z.number().optional().describe('圆角'),
1701
+ tailDirection: z.enum(['bottom', 'top', 'left', 'right']).optional().describe('尾巴方向'),
1702
+ tailPosition: z.enum(['left', 'center', 'right']).optional().describe('尾巴位置'),
1703
+ shadow: z.object({
1704
+ color: z.string().optional(),
1705
+ blur: z.number().optional(),
1706
+ offsetX: z.number().optional(),
1707
+ offsetY: z.number().optional(),
1708
+ }).optional(),
1709
+ opacity: z.number().optional().describe('透明度'),
1710
+ }),
1711
+ execute: async (args) => {
1712
+ try {
1713
+ if (!this._canvasManager.isCreated()) {
1714
+ return { success: false, error: 'No canvas created' }
1715
+ }
1716
+ return await createBubble(
1717
+ this._canvasManager.getProject(),
1718
+ this._canvasManager.getCanvas(),
1719
+ args
1720
+ )
1721
+ } catch (err) {
1722
+ return { success: false, error: err.message }
1723
+ }
1724
+ },
1725
+ },
1726
+
1727
+ /**
1728
+ * 添加丝带
1729
+ */
1730
+ add_poster_ribbon: {
1731
+ description: '添加丝带飘带',
1732
+ inputSchema: z.object({
1733
+ x: z.number().describe('X坐标'),
1734
+ y: z.number().describe('Y坐标'),
1735
+ width: z.number().optional().describe('宽度,默认300'),
1736
+ text: z.string().optional().describe('丝带文字'),
1737
+ fontSize: z.number().optional().describe('字体大小'),
1738
+ color: z.string().optional().describe('文字颜色'),
1739
+ backgroundColor: z.string().optional().describe('背景色'),
1740
+ borderColor: z.string().optional().describe('边框颜色'),
1741
+ borderWidth: z.number().optional().describe('边框宽度'),
1742
+ style: z.enum(['fold', 'diagonal', 'corner']).optional().describe('丝带样式'),
1743
+ shadow: z.object({
1744
+ color: z.string().optional(),
1745
+ blur: z.number().optional(),
1746
+ offsetX: z.number().optional(),
1747
+ offsetY: z.number().optional(),
1748
+ }).optional(),
1749
+ opacity: z.number().optional().describe('透明度'),
1750
+ }),
1751
+ execute: async (args) => {
1752
+ try {
1753
+ if (!this._canvasManager.isCreated()) {
1754
+ return { success: false, error: 'No canvas created' }
1755
+ }
1756
+ return await createRibbon(
1757
+ this._canvasManager.getProject(),
1758
+ this._canvasManager.getCanvas(),
1759
+ args
1760
+ )
1761
+ } catch (err) {
1762
+ return { success: false, error: err.message }
1763
+ }
1764
+ },
1765
+ },
1766
+
1767
+ /**
1768
+ * 添加印章
1769
+ */
1770
+ add_poster_seal: {
1771
+ description: '添加印章效果',
1772
+ inputSchema: z.object({
1773
+ x: z.number().describe('X坐标'),
1774
+ y: z.number().describe('Y坐标'),
1775
+ size: z.number().optional().describe('印章大小,默认100'),
1776
+ text: z.string().optional().describe('印章文字'),
1777
+ fontSize: z.number().optional().describe('字体大小'),
1778
+ color: z.string().optional().describe('印章颜色'),
1779
+ style: z.enum(['circle', 'square', 'star', 'hexagon']).optional().describe('印章形状'),
1780
+ borderWidth: z.number().optional().describe('边框宽度'),
1781
+ opacity: z.number().optional().describe('透明度'),
1782
+ }),
1783
+ execute: async (args) => {
1784
+ try {
1785
+ if (!this._canvasManager.isCreated()) {
1786
+ return { success: false, error: 'No canvas created' }
1787
+ }
1788
+ return await createSeal(
1789
+ this._canvasManager.getProject(),
1790
+ this._canvasManager.getCanvas(),
1791
+ args
1792
+ )
1793
+ } catch (err) {
1794
+ return { success: false, error: err.message }
1795
+ }
1796
+ },
1797
+ },
1798
+
1799
+ /**
1800
+ * 添加高亮文字
1801
+ */
1802
+ add_poster_highlight_text: {
1803
+ description: '添加高亮文字(荧光笔效果)',
1804
+ inputSchema: z.object({
1805
+ x: z.number().describe('X坐标'),
1806
+ y: z.number().describe('Y坐标'),
1807
+ text: z.string().describe('文字内容'),
1808
+ fontSize: z.number().optional().describe('字体大小'),
1809
+ color: z.string().optional().describe('文字颜色'),
1810
+ highlightColor: z.string().optional().describe('高亮颜色'),
1811
+ highlightStyle: z.enum(['marker', 'underline', 'background', 'stroke', 'neon']).optional().describe('高亮样式'),
1812
+ strokeWidth: z.number().optional().describe('描边宽度'),
1813
+ shadow: z.object({
1814
+ color: z.string().optional(),
1815
+ blur: z.number().optional(),
1816
+ offsetX: z.number().optional(),
1817
+ offsetY: z.number().optional(),
1818
+ }).optional(),
1819
+ opacity: z.number().optional().describe('透明度'),
1820
+ }),
1821
+ execute: async (args) => {
1822
+ try {
1823
+ if (!this._canvasManager.isCreated()) {
1824
+ return { success: false, error: 'No canvas created' }
1825
+ }
1826
+ return await createHighlightText(
1827
+ this._canvasManager.getProject(),
1828
+ this._canvasManager.getCanvas(),
1829
+ args
1830
+ )
1831
+ } catch (err) {
1832
+ return { success: false, error: err.message }
1833
+ }
1834
+ },
1835
+ },
1836
+
1837
+ /**
1838
+ * 添加条形码
1839
+ */
1840
+ // add_poster_barcode: {
1841
+ // description: '添加条形码',
1842
+ // inputSchema: z.object({
1843
+ // x: z.number().describe('X坐标'),
1844
+ // y: z.number().describe('Y坐标'),
1845
+ // width: z.number().optional().describe('宽度,默认300'),
1846
+ // height: z.number().optional().describe('高度,默认100'),
1847
+ // content: z.string().describe('条形码内容'),
1848
+ // color: z.string().optional().describe('条形码颜色'),
1849
+ // showText: z.boolean().optional().describe('是否显示文字'),
1850
+ // textColor: z.string().optional().describe('文字颜色'),
1851
+ // fontSize: z.number().optional().describe('字体大小'),
1852
+ // opacity: z.number().optional().describe('透明度'),
1853
+ // }),
1854
+ // execute: async (args) => {
1855
+ // try {
1856
+ // if (!this._canvasManager.isCreated()) {
1857
+ // return { success: false, error: 'No canvas created' }
1858
+ // }
1859
+ // return await createBarcode(
1860
+ // this._canvasManager.getProject(),
1861
+ // this._canvasManager.getCanvas(),
1862
+ // args
1863
+ // )
1864
+ // } catch (err) {
1865
+ // return { success: false, error: err.message }
1866
+ // }
1867
+ // },
1868
+ // },
1869
+
1457
1870
  // ==================== 组件化海报生成 ====================
1458
1871
 
1459
1872
  /**
@@ -1465,11 +1878,12 @@ module.exports = function (Plugin) {
1465
1878
  components: z.array(z.object({
1466
1879
  type: z.enum([
1467
1880
  'background', 'rectangle', 'circle', 'line', 'polygon',
1468
- 'text', 'artText', 'image', 'svg', 'imageFrame',
1881
+ 'text', 'artText', 'richText', 'image', 'svg', 'imageFrame',
1469
1882
  'columns', 'grid', 'star', 'arrow', 'progressCircle', 'chip', 'chart', 'watermark', 'table',
1470
1883
  'card', 'badge', 'cta', 'feature', 'featureGrid', 'divider',
1471
- 'avatar', 'progress', 'rating', 'quote', 'statCard',
1884
+ 'avatar', 'progress', 'rating', 'quote', 'statCard',
1472
1885
  'tagCloud', 'stepper', 'timeline', 'listItem', 'notification',
1886
+ 'button', 'icon', 'qrcode', 'frame', 'bubble', 'ribbon', 'seal', 'highlightText', 'barcode',
1473
1887
  ]).describe('组件类型'),
1474
1888
  })).describe('组件配置数组'),
1475
1889
  }),
@@ -1636,13 +2050,21 @@ module.exports = function (Plugin) {
1636
2050
  },
1637
2051
  }
1638
2052
 
1639
- install(framework){
1640
- this._framework=framework
1641
- Object.keys(this.all_tools).map(key=>{
1642
- this._framework.registerTool({...this.all_tools[key],name:key})
1643
- })
2053
+
2054
+ async install(framework) {
2055
+ this._framework = framework
2056
+ console.log('[poster] Poster plugin installed (v1.1.0)')
2057
+ console.log('[poster] Components:', Object.keys(COMPONENT_TYPES).join(', '))
2058
+
2059
+ return this
1644
2060
  }
1645
2061
 
2062
+ start(framework) {
2063
+ // Object.keys(this.all_tools).map(key=>{
2064
+ // this._framework.registerTool({...this.all_tools[key],name:key})
2065
+ // })
2066
+ console.log('[poster] Poster plugin started')
2067
+ }
1646
2068
 
1647
2069
 
1648
2070
  reload(framework) {
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 图片加载工具 - 使用 canvas loadImage 加载图片(仅支持本地路径)
3
+ */
4
+
5
+ const { loadImage } = require('canvas')
6
+ const paper = require('paper')
7
+ const fs = require('fs')
8
+ const path = require('path')
9
+
10
+ /**
11
+ * 解析图片源(仅支持本地路径)
12
+ * @param {string} src - 图片源
13
+ * @returns {Promise<{path: string, type: 'local'}>}
14
+ */
15
+ async function resolveImageSource(src) {
16
+ if (!src) {
17
+ throw new Error('Image source is required')
18
+ }
19
+
20
+ // 确保 src 是字符串
21
+ if (typeof src !== 'string') {
22
+ throw new Error('Image source must be a string')
23
+ }
24
+
25
+ // 本地路径
26
+ let absolutePath = src
27
+ if (!path.isAbsolute(absolutePath)) {
28
+ absolutePath = path.join(process.cwd(), absolutePath)
29
+ }
30
+
31
+ if (!fs.existsSync(absolutePath)) {
32
+ throw new Error(`图片文件不存在: ${absolutePath}`)
33
+ }
34
+
35
+ return { path: absolutePath, type: 'local' }
36
+ }
37
+
38
+ /**
39
+ * 加载图片并创建 Paper.js Raster
40
+ * @param {paper.Project} project - Paper.js 项目
41
+ * @param {string} src - 图片源
42
+ * @param {Object} bounds - 边界 {x, y, width?, height?}
43
+ * @param {number} opacity - 透明度
44
+ * @returns {Promise<{raster: paper.Raster, cleanup: function}>}
45
+ */
46
+ async function loadImageAsRaster(project, src, bounds = {}, opacity = 1) {
47
+ const { x = 0, y = 0, width, height } = bounds
48
+
49
+ // 解析图片源
50
+ const { path: imgPath } = await resolveImageSource(src)
51
+
52
+ // 使用 canvas loadImage 加载
53
+ const imageData = await loadImage(imgPath)
54
+
55
+ // 创建 Paper.js Raster
56
+ const raster = new paper.Raster(imageData)
57
+
58
+ // 添加到项目的活动层
59
+ if (project && project.activeLayer) {
60
+ project.activeLayer.addChild(raster)
61
+ }
62
+
63
+ // 设置位置和尺寸
64
+ if (width && height) {
65
+ raster.bounds = new paper.Rectangle(x, y, width, height)
66
+ } else if (width) {
67
+ const scale = width / raster.width
68
+ raster.bounds = new paper.Rectangle(x, y, width, raster.height * scale)
69
+ } else if (height) {
70
+ const scale = height / raster.height
71
+ raster.bounds = new paper.Rectangle(x, y, raster.width * scale, height)
72
+ } else {
73
+ raster.position = new paper.Point(x, y)
74
+ }
75
+
76
+ if (opacity !== undefined) raster.opacity = opacity
77
+
78
+ return { raster, cleanup: () => {} }
79
+ }
80
+
81
+ module.exports = {
82
+ loadImageAsRaster,
83
+ resolveImageSource,
84
+ }
@@ -0,0 +1 @@
1
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800" height="600" viewBox="0,0,800,600"><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="sans-serif" font-weight="normal" font-size="40" text-anchor="middle" style="mix-blend-mode: normal"><text x="400" y="300">背景图片测试</text></g></svg>