foliko 1.1.7 → 1.1.9

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 (113) hide show
  1. package/.agent/agents/poster-expert.md +228 -0
  2. package/.agent/data/default.json +10 -0
  3. package/.agent/data/plugins-state.json +1 -1
  4. package/.agent/mcp_config.json +0 -6
  5. package/.agent/plugins/test-plugin.py +15 -0
  6. package/.agent/plugins/test_nested_plugin.py +85 -0
  7. package/.agent/sessions/cli_default.json +83 -803
  8. package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +189 -0
  9. package/.claude/settings.local.json +8 -1
  10. package/cli/src/ui/chat-ui.js +32 -21
  11. package/foliko_poster.png +0 -0
  12. package/output/business_poster_final.png +0 -0
  13. package/output/emoji_test_v2.png +0 -0
  14. package/output/foliko-ai-launch-poster.png +0 -0
  15. package/output/foliko-poster.png +0 -0
  16. package/output/muji_style_poster.png +0 -0
  17. package/output/new_product_launch.png +0 -0
  18. package/output/news_poster_625yi_subsidy.png +0 -0
  19. package/output/tech_future_2026.png +0 -0
  20. package/output/tech_future_poster.png +0 -0
  21. package/package.json +2 -2
  22. package/plugins/default-plugins.js +60 -7
  23. package/plugins/extension-executor-plugin.js +32 -22
  24. package/plugins/feishu-plugin.js +2 -2
  25. package/plugins/python-plugin-loader.js +461 -40
  26. package/plugins/python-plugin-loader.js.bak +856 -0
  27. package/plugins/subagent-plugin.js +0 -121
  28. package/plugins/telegram-plugin.js +2 -2
  29. package/plugins/weixin-plugin.js +40 -31
  30. package/poster.png +0 -0
  31. package/skills/foliko-dev/SKILL.md +6 -0
  32. package/skills/python-plugin-dev/SKILL.md +124 -2
  33. package/src/core/agent-chat.js +220 -281
  34. package/src/core/agent.js +127 -29
  35. package/src/executors/mcp-executor.js +282 -26
  36. package/src/utils/plugin-helpers.js +22 -4
  37. package/system.md +362 -109
  38. package/test-scan.js +18 -0
  39. package/.agent/memory/feedback/mnt7jrlt-d67qs7.md +0 -15
  40. package/.agent/memory/feedback/mnt88ja3-al4fuy.md +0 -9
  41. package/.agent/plugins/poster-plugin/README.md +0 -304
  42. package/.agent/plugins/poster-plugin/emojis/rocket.png +0 -1
  43. package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
  44. package/.agent/plugins/poster-plugin/fonts/SegoeUI Emoji.ttf +0 -0
  45. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  46. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221/347/262/227/344/275/223.ttf +0 -0
  47. package/.agent/plugins/poster-plugin/index.js +0 -13
  48. package/.agent/plugins/poster-plugin/package.json +0 -29
  49. package/.agent/plugins/poster-plugin/src/canvas.js +0 -224
  50. package/.agent/plugins/poster-plugin/src/components/arrow.js +0 -84
  51. package/.agent/plugins/poster-plugin/src/components/avatar.js +0 -71
  52. package/.agent/plugins/poster-plugin/src/components/badge.js +0 -85
  53. package/.agent/plugins/poster-plugin/src/components/barcode.js +0 -120
  54. package/.agent/plugins/poster-plugin/src/components/bubble.js +0 -153
  55. package/.agent/plugins/poster-plugin/src/components/button.js +0 -124
  56. package/.agent/plugins/poster-plugin/src/components/card.js +0 -88
  57. package/.agent/plugins/poster-plugin/src/components/chart.js +0 -127
  58. package/.agent/plugins/poster-plugin/src/components/chip.js +0 -88
  59. package/.agent/plugins/poster-plugin/src/components/columns.js +0 -107
  60. package/.agent/plugins/poster-plugin/src/components/cta.js +0 -87
  61. package/.agent/plugins/poster-plugin/src/components/divider.js +0 -55
  62. package/.agent/plugins/poster-plugin/src/components/feature.js +0 -85
  63. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +0 -117
  64. package/.agent/plugins/poster-plugin/src/components/frame.js +0 -230
  65. package/.agent/plugins/poster-plugin/src/components/grid.js +0 -118
  66. package/.agent/plugins/poster-plugin/src/components/highlightText.js +0 -144
  67. package/.agent/plugins/poster-plugin/src/components/icon.js +0 -94
  68. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +0 -155
  69. package/.agent/plugins/poster-plugin/src/components/index.js +0 -81
  70. package/.agent/plugins/poster-plugin/src/components/listItem.js +0 -147
  71. package/.agent/plugins/poster-plugin/src/components/notification.js +0 -123
  72. package/.agent/plugins/poster-plugin/src/components/progress.js +0 -79
  73. package/.agent/plugins/poster-plugin/src/components/progressCircle.js +0 -117
  74. package/.agent/plugins/poster-plugin/src/components/qrcode.js +0 -74
  75. package/.agent/plugins/poster-plugin/src/components/quote.js +0 -97
  76. package/.agent/plugins/poster-plugin/src/components/rating.js +0 -85
  77. package/.agent/plugins/poster-plugin/src/components/ribbon.js +0 -193
  78. package/.agent/plugins/poster-plugin/src/components/seal.js +0 -146
  79. package/.agent/plugins/poster-plugin/src/components/star.js +0 -70
  80. package/.agent/plugins/poster-plugin/src/components/statCard.js +0 -105
  81. package/.agent/plugins/poster-plugin/src/components/stepper.js +0 -118
  82. package/.agent/plugins/poster-plugin/src/components/table.js +0 -167
  83. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +0 -85
  84. package/.agent/plugins/poster-plugin/src/components/timeline.js +0 -117
  85. package/.agent/plugins/poster-plugin/src/components/watermark.js +0 -52
  86. package/.agent/plugins/poster-plugin/src/composer.js +0 -2146
  87. package/.agent/plugins/poster-plugin/src/elements/artText.js +0 -60
  88. package/.agent/plugins/poster-plugin/src/elements/background.js +0 -84
  89. package/.agent/plugins/poster-plugin/src/elements/circle.js +0 -31
  90. package/.agent/plugins/poster-plugin/src/elements/image.js +0 -28
  91. package/.agent/plugins/poster-plugin/src/elements/index.js +0 -28
  92. package/.agent/plugins/poster-plugin/src/elements/line.js +0 -23
  93. package/.agent/plugins/poster-plugin/src/elements/polygon.js +0 -63
  94. package/.agent/plugins/poster-plugin/src/elements/rectangle.js +0 -32
  95. package/.agent/plugins/poster-plugin/src/elements/richText.js +0 -230
  96. package/.agent/plugins/poster-plugin/src/elements/svg.js +0 -108
  97. package/.agent/plugins/poster-plugin/src/elements/text.js +0 -109
  98. package/.agent/plugins/poster-plugin/src/fonts.js +0 -243
  99. package/.agent/plugins/poster-plugin/src/index.js +0 -2081
  100. package/.agent/plugins/poster-plugin/src/presets.js +0 -36
  101. package/.agent/plugins/poster-plugin/src/templates/business.js +0 -60
  102. package/.agent/plugins/poster-plugin/src/templates/gradient.js +0 -64
  103. package/.agent/plugins/poster-plugin/src/templates/index.js +0 -43
  104. package/.agent/plugins/poster-plugin/src/templates/modern.js +0 -69
  105. package/.agent/plugins/poster-plugin/src/templates/simple.js +0 -58
  106. package/.agent/plugins/poster-plugin/src/templates/social.js +0 -62
  107. package/.agent/plugins/poster-plugin/src/templates/tech.js +0 -84
  108. package/.agent/plugins/poster-plugin/src/utils/imageLoader.js +0 -84
  109. package/.agent/plugins/poster-plugin/test-background.svg +0 -1
  110. package/.agent/plugins/poster-plugin/test-full-poster.svg +0 -2
  111. package/.agent/plugins/poster-plugin/test-image.png +0 -0
  112. package/.agent/plugins/poster-plugin/yarn.lock +0 -1007
  113. package/output/zen_silence.png +0 -0
package/test-scan.js ADDED
@@ -0,0 +1,18 @@
1
+ const { scanPluginNames, resolvePluginPath } = require('./src/utils/plugin-helpers');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+
5
+ const pluginsDir = path.join(process.cwd(), '.agent', 'plugins');
6
+ console.log('Plugins directory:', pluginsDir);
7
+ console.log('Exists:', fs.existsSync(pluginsDir));
8
+
9
+ const names = scanPluginNames(pluginsDir);
10
+ console.log('Scanned plugin names:', names);
11
+
12
+ if (names.includes('poster-plugin')) {
13
+ console.log('poster-plugin found!');
14
+ const result = resolvePluginPath(pluginsDir, 'poster-plugin');
15
+ console.log('poster-plugin path resolved:', result);
16
+ } else {
17
+ console.log('poster-plugin NOT found in scan results');
18
+ }
@@ -1,15 +0,0 @@
1
- ---
2
- id: "mnt7jrlt-d67qs7"
3
- name: "【避免指南】避免在动作参数中使用未正确解析的模板变量"
4
- type: "feedback"
5
- project: "null"
6
- tags: [error, avoid, email, template-variable]
7
- created: "2026-04-10"
8
- ---
9
- 【下次这样做】在 Ambient Agent 动作参数中使用模板变量时,必须确保变量能正确解析。错误原因:${event.from} 模板变量未被解析为实际邮箱地址 'chnak@yandex.ru',导致 email_auto_reply 工具收到空的 to 参数。
10
-
11
- 【避免方法】
12
- 1. 在动作 args 中使用模板变量时,需检查变量路径是否正确,如 ${event.from} 应解析为发件人邮箱
13
- 2. 对于嵌套在 _eventRaw 中的数据,需使用正确的变量路径(如 ${event._eventRaw.data.email.from})
14
- 3. 建议在动作执行前添加日志或调试步骤验证变量是否正确解析
15
- 4. 对于 email_auto_reply,to 参数必须为有效的邮箱地址字符串,不能是未解析的模板变量
@@ -1,9 +0,0 @@
1
- ---
2
- id: "mnt88ja3-al4fuy"
3
- name: "【避免指南】避免重复启动已运行的服务或资源"
4
- type: "feedback"
5
- project: "null"
6
- tags: [error, avoid, duplicate-operation, state-conflict]
7
- created: "2026-04-10"
8
- ---
9
- 【下次这样做】在启动服务前应先检查其当前状态。如果服务已在运行,应跳过启动操作或返回明确提示,而非直接调用启动命令。错误原因:重复启动已运行中的邮件监控服务(email_watch),导致状态冲突。建议在启动前调用 status 接口确认服务状态,或确保工具本身实现幂等性。
@@ -1,304 +0,0 @@
1
- # Poster Plugin - 海报制作插件
2
-
3
- 基于 Paper.js 的海报/Banner 设计插件,支持**组件化**海报生成。
4
-
5
- ## 功能特性
6
-
7
- - **预设尺寸**:20+ 常用尺寸(海报、Banner、社交媒体)
8
- - **基础元素**:矩形、圆形、线条、多边形、图片、文字、艺术文字、图片框
9
- - **布局组件**:分栏布局、网格布局
10
- - **装饰组件**:星形、箭头、环形进度条、标签、图表、水印、表格
11
- - **高级组件**:卡片、徽章、CTA按钮、特性展示、特性网格、分隔线、头像、进度条、评分、引用、统计卡、标签云、步骤条、时间线、列表项、通知
12
- - **组件化生成**:通过 JSON 配置一次性生成完整海报
13
- - **模板系统**:modern、business、social、simple、tech、gradient 六种预设模板
14
-
15
- ## 工具列表(共 35 个组件)
16
-
17
- ### 画布管理
18
- | 工具 | 描述 |
19
- |------|------|
20
- | `list_poster_presets` | 列出所有预设尺寸 |
21
- | `create_poster_canvas` | 创建新画布 |
22
- | `get_poster_canvas_info` | 获取画布信息 |
23
- | `clear_poster_canvas` | 清除画布 |
24
- | `export_poster_canvas` | 导出为 PNG 文件 |
25
- | `export_poster_svg` | 导出为 SVG 矢量图 |
26
- | `export_poster_base64` | 导出为 Base64 |
27
-
28
- ### 基础元素 (10)
29
- | 工具 | 描述 |
30
- |------|------|
31
- | `add_poster_background` | 添加纯色/渐变背景 |
32
- | `add_poster_rectangle` | 添加矩形 |
33
- | `add_poster_circle` | 添加圆形/椭圆 |
34
- | `add_poster_line` | 添加线条 |
35
- | `add_poster_polygon` | 添加多边形 |
36
- | `add_poster_text` | 添加文字 |
37
- | `add_poster_art_text` | 添加艺术文字(渐变/描边) |
38
- | `add_poster_image` | 添加图片 |
39
- | `add_poster_svg` | 添加 SVG 矢量图 |
40
- | `add_poster_image_frame` | 添加图片框(带装饰边框) |
41
-
42
- ### 布局组件 (2)
43
- | 工具 | 描述 |
44
- |------|------|
45
- | `add_poster_columns` | 分栏布局(左右分栏、多栏) |
46
- | `add_poster_grid` | 网格布局(任意行列) |
47
-
48
- ### 装饰组件 (7)
49
- | 工具 | 描述 |
50
- |------|------|
51
- | `add_poster_star` | 星形/多角形装饰 |
52
- | `add_poster_arrow` | 箭头指示 |
53
- | `add_poster_progress_circle` | 环形进度条 |
54
- | `add_poster_chip` | 小型标签 |
55
- | `add_poster_chart` | 图表(柱状图、饼图) |
56
- | `add_poster_watermark` | 水印文字 |
57
- | `add_poster_table` | 数据表格 |
58
-
59
- ### 高级组件 (16)
60
- | 工具 | 描述 |
61
- |------|------|
62
- | `add_poster_card` | 卡片组件 |
63
- | `add_poster_badge` | 徽章/标签 |
64
- | `add_poster_cta` | CTA 行动号召按钮 |
65
- | `add_poster_feature` | 特性展示块 |
66
- | `add_poster_feature_grid` | 特性网格布局 |
67
- | `add_poster_divider` | 分隔线 |
68
- | `add_poster_avatar` | 用户头像 |
69
- | `add_poster_progress` | 线性进度条 |
70
- | `add_poster_rating` | 星级评分 |
71
- | `add_poster_quote` | 引用块 |
72
- | `add_poster_stat_card` | 统计卡片 |
73
- | `add_poster_tag_cloud` | 标签云 |
74
- | `add_poster_stepper` | 步骤指示器 |
75
- | `add_poster_timeline` | 时间线 |
76
- | `add_poster_list_item` | 列表项 |
77
- | `add_poster_notification` | 通知提示 |
78
-
79
- ### 组件化生成 & 模板
80
- | 工具 | 描述 |
81
- |------|------|
82
- | `compose_poster` | 使用组件配置生成海报 |
83
- | `list_poster_components` | 列出可用组件类型 |
84
- | `generate_poster` | 一键生成海报(6种模板) |
85
- | `list_poster_templates` | 列出可用模板 |
86
-
87
- ## 预设尺寸
88
-
89
- | Key | 尺寸 | 名称 |
90
- |-----|------|------|
91
- | `poster_a4` | 2480×3508 | A4海报 (300dpi) |
92
- | `poster_square` | 2000×2000 | 方形海报 |
93
- | `poster_16_9` | 1920×1080 | 16:9海报 |
94
- | `poster_9_16` | 1080×1920 | 9:16竖版海报 |
95
- | `banner_1920x500` | 1920×500 | 网站Banner |
96
- | `banner_twitter` | 1500×500 | Twitter封面 |
97
- | `social_instagram` | 1080×1080 | Instagram正方形 |
98
- | `social_story` | 1080×1920 | Instagram Story |
99
- | `social_facebook` | 1200×630 | Facebook封面 |
100
- | `social_linkedin` | 1200×627 | LinkedIn封面 |
101
- | `social_youtube` | 2560×1440 | YouTube封面 |
102
-
103
- ## 使用示例
104
-
105
- ### 1. 组件化生成(推荐)
106
-
107
- ```javascript
108
- compose_poster({
109
- components: [
110
- // 背景
111
- { type: 'background', color: '#1a1a2e' },
112
-
113
- // 装饰圆形
114
- { type: 'circle', cx: 1600, cy: 200, rx: 200, fill: '#00d9ff', opacity: 0.3 },
115
-
116
- // 星形装饰
117
- { type: 'star', cx: 200, cy: 200, points: 5, outerRadius: 60, fill: '#fbbf24' },
118
-
119
- // 主标题
120
- { type: 'artText', text: 'VB-Agent', x: 960, y: 400, fontSize: 120,
121
- gradient: { colors: ['#00d9ff', '#00ff88'] } },
122
-
123
- // 环形进度条
124
- { type: 'progressCircle', cx: 400, cy: 600, radius: 80, value: 85,
125
- strokeWidth: 15, fillColor: '#3b82f6', showLabel: true },
126
- { type: 'progressCircle', cx: 700, cy: 600, radius: 80, value: 92,
127
- strokeWidth: 15, fillColor: '#10b981', showLabel: true },
128
-
129
- // 图表
130
- { type: 'chart', type: 'bar', x: 1100, y: 450, width: 400, height: 250,
131
- data: [
132
- { label: '一月', value: 120, color: '#3b82f6' },
133
- { label: '二月', value: 90, color: '#10b981' },
134
- { label: '三月', value: 150, color: '#f59e0b' }
135
- ],
136
- showLabels: true, showValues: true },
137
-
138
- // 数据表格
139
- { type: 'table', x: 100, y: 700, width: 800,
140
- columns: [
141
- { title: '功能', width: 300, align: 'left' },
142
- { title: '状态', width: 200 },
143
- { title: '价格', width: 150 }
144
- ],
145
- rows: [
146
- ['智能对话', '可用', '免费'],
147
- ['图片生成', '可用', '$29'],
148
- ['代码助手', 'Beta', '免费']
149
- ],
150
- headerBg: '#1e293b', headerColor: '#ffffff', striped: true },
151
-
152
- // 标签
153
- { type: 'chip', x: 400, y: 850, text: 'AI驱动', background: '#3b82f6', color: '#ffffff' },
154
- { type: 'chip', x: 550, y: 850, text: '开源', background: '#10b981', color: '#ffffff' },
155
-
156
- // 水印
157
- { type: 'watermark', text: 'VB-Agent', cx: 960, cy: 1000, fontSize: 200,
158
- color: 'rgba(255,255,255,0.03)', rotation: -15 },
159
-
160
- // CTA 按钮
161
- { type: 'cta', x: 960, y: 950, text: '立即体验 →',
162
- background: '#00d9ff', color: '#0a0a0f', fontSize: 24, radius: 30 }
163
- ]
164
- })
165
- export_poster_canvas({ filename: 'my-poster', outputDir: '.' })
166
- ```
167
-
168
- ### 2. 基础使用
169
-
170
- ```javascript
171
- // 创建画布
172
- create_poster_canvas({ preset: 'poster_square', background: '#1a1a2e' })
173
-
174
- // 添加元素
175
- add_poster_circle({ cx: 500, cy: 500, rx: 100, fill: '#00d9ff' })
176
- add_poster_text({ text: 'Hello Foliko', x: 500, y: 600, fontSize: 48, color: '#ffffff', align: 'center' })
177
-
178
- // 导出
179
- export_poster_canvas({ filename: 'my-poster' })
180
- ```
181
-
182
- ## 新增组件详解
183
-
184
- ### 星形 (star)
185
- ```javascript
186
- add_poster_star({
187
- cx: 200, cy: 200, // 中心坐标
188
- points: 5, // 星形点数
189
- outerRadius: 60, // 外半径
190
- fill: '#fbbf24', // 填充颜色
191
- rotation: 0 // 旋转角度
192
- })
193
- ```
194
-
195
- ### 环形进度条 (progressCircle)
196
- ```javascript
197
- add_poster_progress_circle({
198
- cx: 200, cy: 200, // 圆心坐标
199
- radius: 80, // 圆环半径
200
- value: 75, // 进度值 0-100
201
- strokeWidth: 15, // 环宽度
202
- trackColor: '#e5e7eb', // 轨道颜色
203
- fillColor: '#3b82f6', // 进度颜色
204
- backgroundColor: '#ffffff', // 背景填充
205
- showLabel: true // 显示百分比
206
- })
207
- ```
208
-
209
- ### 图表 (chart)
210
- ```javascript
211
- // 柱状图
212
- add_poster_chart({
213
- type: 'bar', // bar 或 pie
214
- x: 100, y: 300,
215
- width: 500, height: 250,
216
- data: [
217
- { label: '一月', value: 120, color: '#3b82f6' },
218
- { label: '二月', value: 90, color: '#10b981' }
219
- ],
220
- showLabels: true,
221
- showValues: true
222
- })
223
-
224
- // 饼图
225
- add_poster_chart({
226
- type: 'pie',
227
- x: 700, y: 300,
228
- width: 250, height: 250,
229
- data: [
230
- { label: 'A', value: 45, color: '#3b82f6' },
231
- { label: 'B', value: 35, color: '#10b981' },
232
- { label: 'C', value: 20, color: '#f59e0b' }
233
- ],
234
- showLabels: true
235
- })
236
- ```
237
-
238
- ### 表格 (table)
239
- ```javascript
240
- add_poster_table({
241
- x: 100, y: 400,
242
- width: 800,
243
- columns: [
244
- { title: '功能', width: 300, align: 'left' },
245
- { title: '状态', width: 200 }
246
- ],
247
- rows: [
248
- ['智能对话', '可用'],
249
- ['代码助手', 'Beta']
250
- ],
251
- headerBg: '#1e293b',
252
- headerColor: '#ffffff',
253
- striped: true
254
- })
255
- ```
256
-
257
- ### 标签 (chip)
258
- ```javascript
259
- add_poster_chip({
260
- x: 200, y: 300,
261
- text: 'NEW', // 标签文字
262
- background: '#ef4444', // 背景色
263
- color: '#ffffff', // 文字颜色
264
- fontSize: 14,
265
- radius: 16, // 圆角
266
- icon: '⭐' // 前置图标(可选)
267
- })
268
- ```
269
-
270
- ## 项目结构
271
-
272
- ```
273
- poster-plugin/
274
- ├── index.js # 插件入口
275
- ├── package.json # 包配置
276
- ├── README.md # 文档
277
- ├── src/
278
- │ ├── index.js # 主模块
279
- │ ├── canvas.js # 画布管理器
280
- │ ├── presets.js # 预设尺寸
281
- │ ├── fonts.js # 字体管理
282
- │ ├── composer.js # 组件化生成器
283
- │ ├── elements/ # 基础元素
284
- │ ├── components/ # 高级组件
285
- │ └── templates/ # 模板
286
- └── fonts/ # 字体文件
287
- ```
288
-
289
- ## 更新日志
290
-
291
- ### v1.2.0
292
- - 新增布局组件:columns(分栏)、grid(网格)
293
- - 新增装饰组件:star(星形)、arrow(箭头)、progressCircle(环形进度条)
294
- - 新增 chip(标签)、chart(图表)、watermark(水印)、table(表格)
295
- - 新增 imageFrame(图片框)
296
- - 组件总数达到 **35 个**
297
- - 模板新增 tech(科技)、gradient(渐变)
298
- - 修复环形进度条绘制逻辑
299
-
300
- ### v1.1.0
301
- - 重构为模块化架构
302
- - 新增组件化海报生成(compose_poster)
303
- - 新增高级组件:card, badge, cta, feature, featureGrid, divider
304
- - 新增组件:avatar, progress, rating, quote, statCard, tagCloud, stepper, timeline, listItem, notification
@@ -1 +0,0 @@
1
- 404: Not Found
@@ -1,13 +0,0 @@
1
- /**
2
- * Poster Plugin - 海报制作插件
3
- *
4
- * 模块化架构,支持组件化海报生成
5
- *
6
- * 使用方法:
7
- * 1. 基础元素:add_poster_rectangle, add_poster_circle, add_poster_text 等
8
- * 2. 高级组件:add_poster_card, add_poster_badge, add_poster_cta 等
9
- * 3. 组件化生成:compose_poster - 通过配置 JSON 一次性生成海报
10
- * 4. 模板生成:generate_poster - 一键使用预设模板
11
- */
12
-
13
- module.exports = require('./src/index.js')
@@ -1,29 +0,0 @@
1
- {
2
- "name": "poster-plugin",
3
- "version": "1.2.0",
4
- "description": "海报/Banner 设计插件 - 基于 Paper.js 实现,支持 35 个组件",
5
- "main": "index.js",
6
- "dependencies": {
7
- "canvas": "^3.2.0",
8
- "fontkit": "^2.0.4",
9
- "jsdom": "^16.2.2",
10
- "paper": "^0.12.18",
11
- "qrcode": "^1.5.4"
12
- },
13
- "overrides": {
14
- "canvas": "^3.2.0"
15
- },
16
- "resolutions": {
17
- "**/canvas": "^3.2.0"
18
- },
19
- "author": "",
20
- "license": "MIT",
21
- "keywords": [
22
- "poster",
23
- "banner",
24
- "design",
25
- "canvas",
26
- "paper.js",
27
- "foliko"
28
- ]
29
- }
@@ -1,224 +0,0 @@
1
- /**
2
- * 画布管理模块
3
- */
4
-
5
- const paper = require('paper')
6
- const PRESETS = require('./presets')
7
- const fs = require('fs')
8
- const path = require('path')
9
-
10
- /**
11
- * 画布管理器类
12
- */
13
- class CanvasManager {
14
- constructor() {
15
- this._canvas = null
16
- this._project = null
17
- this._paper = null
18
- this._width = 0
19
- this._height = 0
20
- }
21
-
22
- /**
23
- * 创建画布
24
- */
25
- async create({ preset, width, height, background }) {
26
- let w, h
27
-
28
- if (preset) {
29
- const presetConfig = PRESETS[preset]
30
- if (!presetConfig) {
31
- throw new Error(`Unknown preset: ${preset}. Available: ${Object.keys(PRESETS).join(', ')}`)
32
- }
33
- w = presetConfig.width
34
- h = presetConfig.height
35
- } else if (width && height) {
36
- w = width
37
- h = height
38
- } else {
39
- throw new Error('Must provide preset or width/height')
40
- }
41
-
42
- this._canvas = paper.createCanvas(w, h)
43
- this._project = new paper.Project(this._canvas)
44
- // 确保活动层存在
45
- if (!paper.project || !paper.project.activeLayer) {
46
- paper.setup(this._canvas)
47
- }
48
- this._paper = paper
49
- this._width = w
50
- this._height = h
51
-
52
- // 添加背景
53
- if (background) {
54
- if (typeof background === 'string' && path.isAbsolute(background)) {
55
- // 背景是绝对路径图片
56
- await this._addBackgroundImage(background, w, h)
57
- } else if (typeof background === 'object' && background.image) {
58
- // 背景是对象形式 { image: 'path' }
59
- await this._addBackgroundImage(background.image, w, h)
60
- } else {
61
- // 背景是颜色
62
- const bg = new paper.Path.Rectangle({
63
- point: [0, 0],
64
- size: [w, h],
65
- fillColor: background,
66
- })
67
- bg.sendToBack()
68
- }
69
- }
70
-
71
- return {
72
- width: w,
73
- height: h,
74
- preset: preset || 'custom',
75
- background: background || null,
76
- }
77
- }
78
-
79
- /**
80
- * 添加背景图片
81
- */
82
- async _addBackgroundImage(imageSrc, w, h) {
83
- // 本地文件路径
84
- let absolutePath = imageSrc
85
- if (!path.isAbsolute(absolutePath)) {
86
- absolutePath = path.join(process.cwd(), absolutePath)
87
- }
88
-
89
- if (!fs.existsSync(absolutePath)) {
90
- throw new Error(`背景图片文件不存在: ${absolutePath}`)
91
- }
92
-
93
- // 使用 loadImage 获取图片数据
94
- const { loadImage } = require('canvas')
95
- const imageData = await loadImage(absolutePath)
96
-
97
- // 创建 Paper.js Raster
98
- const raster = new paper.Raster(imageData)
99
-
100
- // 等待 raster 加载完成
101
- await new Promise((resolve) => {
102
- if (raster.loaded) {
103
- resolve()
104
- } else {
105
- raster.onLoad = resolve
106
- }
107
- })
108
-
109
- // 计算 cover 模式缩放
110
- const canvasRatio = w / h
111
- const imageRatio = raster.width / raster.height
112
-
113
- let scaledWidth, scaledHeight, offsetX, offsetY
114
-
115
- if (imageRatio > canvasRatio) {
116
- scaledHeight = h
117
- scaledWidth = raster.width * (h / raster.height)
118
- offsetX = (w - scaledWidth) / 2
119
- offsetY = 0
120
- } else {
121
- scaledWidth = w
122
- scaledHeight = raster.height * (w / raster.width)
123
- offsetX = 0
124
- offsetY = (h - scaledHeight) / 2
125
- }
126
-
127
- raster.bounds = new paper.Rectangle(offsetX, offsetY, scaledWidth, scaledHeight)
128
- raster.sendToBack()
129
- }
130
-
131
- /**
132
- * 获取画布
133
- */
134
- getCanvas() {
135
- return this._canvas
136
- }
137
-
138
- /**
139
- * 获取 Paper.js 项目
140
- */
141
- getProject() {
142
- return this._project
143
- }
144
-
145
- /**
146
- * 获取画布尺寸
147
- */
148
- getSize() {
149
- return { width: this._width, height: this._height }
150
- }
151
-
152
- /**
153
- * 获取中心点
154
- */
155
- getCenter() {
156
- return { x: this._width / 2, y: this._height / 2 }
157
- }
158
-
159
- /**
160
- * 清除画布
161
- */
162
- clear() {
163
- if (this._project) {
164
- this._project.activeLayer.removeChildren()
165
- }
166
- }
167
-
168
- /**
169
- * 获取元素数量
170
- */
171
- getElementCount() {
172
- return this._project ? this._project.activeLayer.children.length : 0
173
- }
174
-
175
- /**
176
- * 导出为 Buffer
177
- */
178
- toBuffer(format = 'png', quality) {
179
- if (!this._canvas) {
180
- throw new Error('No canvas created')
181
- }
182
-
183
- this._project.view.update()
184
- this._project.view.draw()
185
-
186
- const mimeType = format === 'jpg' ? 'image/jpeg' : 'image/png'
187
- return this._canvas.toBuffer(mimeType, quality)
188
- }
189
-
190
- /**
191
- * 导出为 Base64
192
- */
193
- toBase64(format = 'png', quality) {
194
- if (!this._canvas) {
195
- throw new Error('No canvas created')
196
- }
197
-
198
- this._project.view.update()
199
- this._project.view.draw()
200
-
201
- const mimeType = format === 'jpg' ? 'image/jpeg' : 'image/png'
202
- return this._canvas.toDataURL(mimeType, quality)
203
- }
204
-
205
- /**
206
- * 检查画布是否已创建
207
- */
208
- isCreated() {
209
- return this._canvas !== null
210
- }
211
-
212
- /**
213
- * 重置画布
214
- */
215
- reset() {
216
- this._canvas = null
217
- this._project = null
218
- this._paper = null
219
- this._width = 0
220
- this._height = 0
221
- }
222
- }
223
-
224
- module.exports = CanvasManager