foliko 1.0.86 → 1.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 (104) hide show
  1. package/.agent/data/default.json +3 -4310
  2. package/.agent/data/plugins-state.json +34 -1
  3. package/.agent/mcp_config.json +0 -1
  4. package/.agent/memory/core.md +1 -0
  5. package/.agent/memory/project/mnn93ogy-ypjn27.md +9 -0
  6. package/.agent/memory/project/mnn98fqy-5nhc1u.md +25 -0
  7. package/.agent/memory/user/mnm67t9m-x8rekk.md +9 -0
  8. package/.agent/memory/user/mnn5mmqh-w6aktx.md +11 -0
  9. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +22 -0
  10. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  11. package/.agent/plugins/marknative/index.js +2 -7
  12. package/.agent/plugins/poster-plugin/README.md +304 -0
  13. package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
  14. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  15. 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
  16. package/.agent/plugins/poster-plugin/index.js +13 -0
  17. package/.agent/plugins/poster-plugin/package.json +28 -0
  18. package/.agent/plugins/poster-plugin/src/canvas.js +161 -0
  19. package/.agent/plugins/poster-plugin/src/components/arrow.js +84 -0
  20. package/.agent/plugins/poster-plugin/src/components/avatar.js +71 -0
  21. package/.agent/plugins/poster-plugin/src/components/badge.js +85 -0
  22. package/.agent/plugins/poster-plugin/src/components/card.js +88 -0
  23. package/.agent/plugins/poster-plugin/src/components/chart.js +127 -0
  24. package/.agent/plugins/poster-plugin/src/components/chip.js +88 -0
  25. package/.agent/plugins/poster-plugin/src/components/columns.js +107 -0
  26. package/.agent/plugins/poster-plugin/src/components/cta.js +85 -0
  27. package/.agent/plugins/poster-plugin/src/components/divider.js +55 -0
  28. package/.agent/plugins/poster-plugin/src/components/feature.js +85 -0
  29. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +112 -0
  30. package/.agent/plugins/poster-plugin/src/components/grid.js +118 -0
  31. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +155 -0
  32. package/.agent/plugins/poster-plugin/src/components/index.js +62 -0
  33. package/.agent/plugins/poster-plugin/src/components/listItem.js +146 -0
  34. package/.agent/plugins/poster-plugin/src/components/notification.js +123 -0
  35. package/.agent/plugins/poster-plugin/src/components/progress.js +79 -0
  36. package/.agent/plugins/poster-plugin/src/components/progressCircle.js +117 -0
  37. package/.agent/plugins/poster-plugin/src/components/quote.js +97 -0
  38. package/.agent/plugins/poster-plugin/src/components/rating.js +85 -0
  39. package/.agent/plugins/poster-plugin/src/components/star.js +70 -0
  40. package/.agent/plugins/poster-plugin/src/components/statCard.js +105 -0
  41. package/.agent/plugins/poster-plugin/src/components/stepper.js +118 -0
  42. package/.agent/plugins/poster-plugin/src/components/table.js +159 -0
  43. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +78 -0
  44. package/.agent/plugins/poster-plugin/src/components/timeline.js +105 -0
  45. package/.agent/plugins/poster-plugin/src/components/watermark.js +52 -0
  46. package/.agent/plugins/poster-plugin/src/composer.js +1904 -0
  47. package/.agent/plugins/poster-plugin/src/elements/artText.js +60 -0
  48. package/.agent/plugins/poster-plugin/src/elements/background.js +52 -0
  49. package/.agent/plugins/poster-plugin/src/elements/circle.js +31 -0
  50. package/.agent/plugins/poster-plugin/src/elements/image.js +71 -0
  51. package/.agent/plugins/poster-plugin/src/elements/index.js +26 -0
  52. package/.agent/plugins/poster-plugin/src/elements/line.js +23 -0
  53. package/.agent/plugins/poster-plugin/src/elements/polygon.js +32 -0
  54. package/.agent/plugins/poster-plugin/src/elements/rectangle.js +32 -0
  55. package/.agent/plugins/poster-plugin/src/elements/svg.js +92 -0
  56. package/.agent/plugins/poster-plugin/src/elements/text.js +38 -0
  57. package/.agent/plugins/poster-plugin/src/fonts.js +118 -0
  58. package/.agent/plugins/poster-plugin/src/index.js +1659 -0
  59. package/.agent/plugins/poster-plugin/src/presets.js +36 -0
  60. package/.agent/plugins/poster-plugin/src/templates/business.js +60 -0
  61. package/.agent/plugins/poster-plugin/src/templates/gradient.js +64 -0
  62. package/.agent/plugins/poster-plugin/src/templates/index.js +43 -0
  63. package/.agent/plugins/poster-plugin/src/templates/modern.js +69 -0
  64. package/.agent/plugins/poster-plugin/src/templates/simple.js +58 -0
  65. package/.agent/plugins/poster-plugin/src/templates/social.js +62 -0
  66. package/.agent/plugins/poster-plugin/src/templates/tech.js +84 -0
  67. package/.agent/sessions/cli_default.json +24265 -0
  68. package/.agent/weixin.json +6 -0
  69. package/.claude/settings.local.json +176 -171
  70. package/CLAUDE.md +144 -108
  71. package/docs/CONTEXT_DESIGN.md +1596 -0
  72. package/examples/test-concurrent-chat.js +60 -0
  73. package/examples/test-long-chat.js +77 -0
  74. package/examples/test-session-chat.js +93 -0
  75. package/output/beef-love-poster.png +0 -0
  76. package/package.json +2 -2
  77. package/plugins/default-plugins.js +2 -1
  78. package/plugins/extension-executor-plugin.js +11 -0
  79. package/plugins/memory-plugin.js +984 -0
  80. package/plugins/session-plugin.js +78 -1
  81. package/plugins/weixin-plugin.js +24 -22
  82. package/skills/poster-guide/SKILL.md +743 -0
  83. package/skills/python-plugin-dev/SKILL.md +238 -238
  84. package/skills/skill-guide/SKILL.md +130 -108
  85. package/src/capabilities/skill-manager.js +99 -0
  86. package/src/core/agent-chat.js +627 -180
  87. package/src/core/agent-context.js +188 -0
  88. package/src/core/agent.js +9 -63
  89. package/src/core/context-manager.js +283 -0
  90. package/src/core/framework.js +264 -3
  91. package/src/core/plugin-manager.js +79 -2
  92. package/src/core/request-context.js +98 -0
  93. package/src/core/session-context.js +341 -0
  94. package/src/core/session-storage.js +274 -0
  95. package/src/executors/mcp-executor.js +2 -2
  96. package/src/utils/index.js +239 -67
  97. package/src/utils/plugin-helpers.js +17 -0
  98. package//346/265/267/346/212/245/346/217/222/344/273/266.md +621 -0
  99. package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
  100. package/.agent/plugins/temp-repo/LICENSE +0 -201
  101. package/.agent/plugins/temp-repo/puppeteer-plugin/README.md +0 -147
  102. package/.agent/plugins/temp-repo/puppeteer-plugin/index.js +0 -1418
  103. package/.agent/plugins/temp-repo/puppeteer-plugin/package.json +0 -9
  104. package/.agent/plugins/test_plugin.py +0 -304
@@ -0,0 +1,146 @@
1
+ /**
2
+ * 列表项组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建列表项
9
+ *
10
+ * @param {Object} project - Paper.js 项目
11
+ * @param {Object} canvas - 画布对象
12
+ * @param {Object} args - 组件参数
13
+ * @param {number} args.x - X坐标
14
+ * @param {number} args.y - Y坐标
15
+ * @param {number} args.width - 宽度
16
+ * @param {string} args.icon - 图标
17
+ * @param {string} args.title - 标题
18
+ * @param {string} args.description - 描述
19
+ * @param {string} args.badge - 徽章文字
20
+ * @param {string} args.badgeColor - 徽章颜色
21
+ * @param {string} args.iconColor - 图标颜色
22
+ * @param {string} args.background - 背景色
23
+ * @param {string} args.borderColor - 边框颜色
24
+ * @param {number} args.height - 高度
25
+ * @param {number} args.radius - 圆角半径
26
+ */
27
+ function createListItem(project, canvas, args) {
28
+ const {
29
+ x, y,
30
+ width = 400,
31
+ icon = '→',
32
+ title,
33
+ description,
34
+ badge,
35
+ badgeColor = '#6366f1',
36
+ iconColor = '#6366f1',
37
+ background = '#ffffff',
38
+ borderColor = '#e5e7eb',
39
+ height = 60,
40
+ radius = 8,
41
+ } = args
42
+
43
+ const elements = []
44
+
45
+ // 绘制背景
46
+ const bg = new paper.Path.Rectangle({
47
+ point: [x, y],
48
+ size: [width, height],
49
+ radius: radius,
50
+ })
51
+ bg.fillColor = new paper.Color(background)
52
+ bg.strokeColor = new paper.Color(borderColor)
53
+ bg.strokeWidth = 1
54
+ elements.push({ type: 'rectangle', id: bg.id })
55
+
56
+ // 绘制图标
57
+ const iconText = new paper.PointText({
58
+ point: [x + 15, y + height / 2 + 6],
59
+ content: icon,
60
+ fontSize: 20,
61
+ fillColor: new paper.Color(iconColor),
62
+ justification: 'center',
63
+ })
64
+ elements.push({ type: 'text', id: iconText.id })
65
+
66
+ // 绘制标题
67
+ const titleText = new paper.PointText({
68
+ point: [x + 50, y + height / 2 - 5],
69
+ content: title || 'List Item',
70
+ fontSize: 16,
71
+ fillColor: new paper.Color('#1e293b'),
72
+ justification: 'left',
73
+ })
74
+ elements.push({ type: 'text', id: titleText.id })
75
+
76
+ // 绘制描述
77
+ if (description) {
78
+ const descText = new paper.PointText({
79
+ point: [x + 50, y + height / 2 + 15],
80
+ content: description,
81
+ fontSize: 12,
82
+ fillColor: new paper.Color('#64748b'),
83
+ justification: 'left',
84
+ })
85
+ elements.push({ type: 'text', id: descText.id })
86
+ }
87
+
88
+ // 绘制徽章
89
+ if (badge) {
90
+ const badgeWidth = badge.length * 10 + 20
91
+ const badgeX = x + width - badgeWidth - 15
92
+ const badgeY = y + (height - 24) / 2
93
+
94
+ const badgeBg = new paper.Path.Rectangle({
95
+ point: [badgeX, badgeY],
96
+ size: [badgeWidth, 24],
97
+ radius: 12,
98
+ })
99
+ badgeBg.fillColor = new paper.Color(badgeColor)
100
+ elements.push({ type: 'rectangle', id: badgeBg.id })
101
+
102
+ const badgeText = new paper.PointText({
103
+ point: [badgeX + badgeWidth / 2, badgeY + 16],
104
+ content: badge,
105
+ fontSize: 12,
106
+ fillColor: new paper.Color('#ffffff'),
107
+ justification: 'center',
108
+ })
109
+ elements.push({ type: 'text', id: badgeText.id })
110
+ }
111
+
112
+ return { success: true, elements }
113
+ }
114
+
115
+ /**
116
+ * 创建列表(多个列表项)
117
+ */
118
+ function createList(project, canvas, args) {
119
+ const {
120
+ x, y,
121
+ items = [],
122
+ gap = 10,
123
+ width = 400,
124
+ ...rest
125
+ } = args
126
+
127
+ const elements = []
128
+ let currentY = y
129
+
130
+ for (const item of items) {
131
+ const result = createListItem(project, canvas, {
132
+ x, y: currentY, width, ...item, ...rest,
133
+ })
134
+ elements.push(...result.elements)
135
+ currentY += 60 + gap
136
+ }
137
+
138
+ return {
139
+ success: true,
140
+ elements,
141
+ height: currentY - y,
142
+ }
143
+ }
144
+
145
+ module.exports = createListItem
146
+ module.exports.createList = createList
@@ -0,0 +1,123 @@
1
+ /**
2
+ * 通知/提示组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建通知提示
9
+ *
10
+ * @param {Object} project - Paper.js 项目
11
+ * @param {Object} canvas - 画布对象
12
+ * @param {Object} args - 组件参数
13
+ * @param {number} args.x - X坐标
14
+ * @param {number} args.y - Y坐标
15
+ * @param {number} args.width - 宽度
16
+ * @param {string} args.type - 类型: success, warning, error, info
17
+ * @param {string} args.title - 标题
18
+ * @param {string} args.message - 消息内容
19
+ * @param {boolean} args.showIcon - 是否显示图标
20
+ * @param {number} args.radius - 圆角半径
21
+ */
22
+ function createNotification(project, canvas, args) {
23
+ const {
24
+ x, y,
25
+ width = 360,
26
+ type = 'info',
27
+ title,
28
+ message,
29
+ showIcon = true,
30
+ radius = 12,
31
+ } = args
32
+
33
+ // 类型配置
34
+ const config = {
35
+ success: {
36
+ icon: '✓',
37
+ bgColor: '#dcfce7',
38
+ iconColor: '#22c55e',
39
+ borderColor: '#22c55e',
40
+ },
41
+ warning: {
42
+ icon: '⚠',
43
+ bgColor: '#fef9c3',
44
+ iconColor: '#eab308',
45
+ borderColor: '#eab308',
46
+ },
47
+ error: {
48
+ icon: '✕',
49
+ bgColor: '#fee2e2',
50
+ iconColor: '#ef4444',
51
+ borderColor: '#ef4444',
52
+ },
53
+ info: {
54
+ icon: 'ℹ',
55
+ bgColor: '#dbeafe',
56
+ iconColor: '#3b82f6',
57
+ borderColor: '#3b82f6',
58
+ },
59
+ }
60
+
61
+ const c = config[type] || config.info
62
+ const padding = 16
63
+ const lineHeight = 22
64
+ const iconSize = 24
65
+ const height = padding * 2 + (title ? lineHeight + 8 : 0) + (message ? lineHeight : 0)
66
+
67
+ const elements = []
68
+
69
+ // 绘制背景
70
+ const bg = new paper.Path.Rectangle({
71
+ point: [x, y],
72
+ size: [width, height],
73
+ radius: radius,
74
+ })
75
+ bg.fillColor = new paper.Color(c.bgColor)
76
+ bg.strokeColor = new paper.Color(c.borderColor)
77
+ bg.strokeWidth = 1
78
+ elements.push({ type: 'rectangle', id: bg.id })
79
+
80
+ // 绘制图标
81
+ if (showIcon) {
82
+ const iconText = new paper.PointText({
83
+ point: [x + padding + iconSize / 2, y + padding + iconSize / 2 + 6],
84
+ content: c.icon,
85
+ fontSize: iconSize,
86
+ fillColor: new paper.Color(c.iconColor),
87
+ justification: 'center',
88
+ })
89
+ elements.push({ type: 'text', id: iconText.id })
90
+ }
91
+
92
+ const textX = showIcon ? x + padding + iconSize + 12 : x + padding
93
+ let currentY = y + padding
94
+
95
+ // 绘制标题
96
+ if (title) {
97
+ const titleText = new paper.PointText({
98
+ point: [textX, currentY + 18],
99
+ content: title,
100
+ fontSize: 16,
101
+ fillColor: new paper.Color('#1e293b'),
102
+ justification: 'left',
103
+ })
104
+ elements.push({ type: 'text', id: titleText.id })
105
+ currentY += lineHeight + 8
106
+ }
107
+
108
+ // 绘制消息
109
+ if (message) {
110
+ const msgText = new paper.PointText({
111
+ point: [textX, currentY + 16],
112
+ content: message,
113
+ fontSize: 14,
114
+ fillColor: new paper.Color('#475569'),
115
+ justification: 'left',
116
+ })
117
+ elements.push({ type: 'text', id: msgText.id })
118
+ }
119
+
120
+ return { success: true, elements }
121
+ }
122
+
123
+ module.exports = createNotification
@@ -0,0 +1,79 @@
1
+ /**
2
+ * 进度条组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建进度条
9
+ *
10
+ * @param {Object} project - Paper.js 项目
11
+ * @param {Object} canvas - 画布对象
12
+ * @param {Object} args - 组件参数
13
+ * @param {number} args.x - X坐标
14
+ * @param {number} args.y - Y坐标
15
+ * @param {number} args.width - 进度条宽度
16
+ * @param {number} args.height - 进度条高度
17
+ * @param {number} args.value - 进度值 0-100
18
+ * @param {string} args.trackColor - 轨道颜色
19
+ * @param {string} args.fillColor - 填充颜色
20
+ * @param {number} args.radius - 圆角半径
21
+ * @param {boolean} args.showLabel - 是否显示标签
22
+ * @param {string} args.label - 标签文字
23
+ */
24
+ function createProgress(project, canvas, args) {
25
+ const {
26
+ x, y,
27
+ width = 300,
28
+ height = 20,
29
+ value = 50,
30
+ trackColor = '#e0e0e0',
31
+ fillColor = '#6366f1',
32
+ radius = 10,
33
+ showLabel = false,
34
+ label,
35
+ } = args
36
+
37
+ const elements = []
38
+
39
+ // 绘制轨道
40
+ const track = new paper.Path.Rectangle({
41
+ point: [x, y],
42
+ size: [width, height],
43
+ radius: radius,
44
+ })
45
+ track.fillColor = new paper.Color(trackColor)
46
+ elements.push({ type: 'rectangle', id: track.id })
47
+
48
+ // 绘制进度
49
+ const progressWidth = (value / 100) * width
50
+ if (progressWidth > 0) {
51
+ const fill = new paper.Path.Rectangle({
52
+ point: [x, y],
53
+ size: [progressWidth, height],
54
+ radius: radius,
55
+ })
56
+ fill.fillColor = new paper.Color(fillColor)
57
+ elements.push({ type: 'rectangle', id: fill.id })
58
+ }
59
+
60
+ // 显示标签
61
+ if (showLabel && label) {
62
+ const labelText = new paper.PointText({
63
+ point: [x + width / 2, y - 8],
64
+ content: label,
65
+ fontSize: 14,
66
+ fillColor: new paper.Color('#666666'),
67
+ justification: 'center',
68
+ })
69
+ elements.push({ type: 'text', id: labelText.id })
70
+ }
71
+
72
+ return {
73
+ success: true,
74
+ elements,
75
+ value,
76
+ }
77
+ }
78
+
79
+ module.exports = createProgress
@@ -0,0 +1,117 @@
1
+ /**
2
+ * 环形进度条组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建环形进度条组件
9
+ */
10
+ function createProgressCircle(project, canvas, params) {
11
+ const {
12
+ cx,
13
+ cy,
14
+ radius,
15
+ value,
16
+ strokeWidth = 10,
17
+ trackColor = '#e5e7eb',
18
+ fillColor = '#3b82f6',
19
+ backgroundColor,
20
+ showLabel = true,
21
+ labelColor,
22
+ startAngle = -90
23
+ } = params
24
+
25
+ const elements = []
26
+
27
+ // 绘制背景圆(可选)
28
+ if (backgroundColor) {
29
+ const bgCircle = new paper.Path.Circle({
30
+ center: [cx, cy],
31
+ radius: radius + strokeWidth / 2
32
+ })
33
+ bgCircle.fillColor = new paper.Color(backgroundColor)
34
+ if (project && project.activeLayer) {
35
+ project.activeLayer.addChild(bgCircle)
36
+ }
37
+ elements.push({ type: 'path', id: bgCircle.id })
38
+ }
39
+
40
+ // 绘制轨道(背景环)
41
+ const trackCircle = new paper.Path.Circle({
42
+ center: [cx, cy],
43
+ radius: radius
44
+ })
45
+ trackCircle.fillColor = null
46
+ trackCircle.strokeColor = new paper.Color(trackColor)
47
+ trackCircle.strokeWidth = strokeWidth
48
+ if (project && project.activeLayer) {
49
+ project.activeLayer.addChild(trackCircle)
50
+ }
51
+ elements.push({ type: 'path', id: trackCircle.id })
52
+
53
+ // 绘制进度弧线
54
+ if (value > 0 && value <= 100) {
55
+ const percentage = value / 100
56
+ const arcAngle = percentage * 360
57
+
58
+ // 转换为弧度
59
+ const startRad = startAngle * Math.PI / 180
60
+ const endRad = (startAngle + arcAngle) * Math.PI / 180
61
+
62
+ // 创建进度弧线路径
63
+ const progressArc = new paper.Path()
64
+
65
+ // 添加起点
66
+ progressArc.moveTo(
67
+ cx + radius * Math.cos(startRad),
68
+ cy + radius * Math.sin(startRad)
69
+ )
70
+
71
+ // 添加弧线上的点(用多个点模拟圆弧)
72
+ const segments = 36
73
+ const angleStep = (endRad - startRad) / segments
74
+ for (let i = 1; i <= segments; i++) {
75
+ const angle = startRad + angleStep * i
76
+ progressArc.lineTo(
77
+ cx + radius * Math.cos(angle),
78
+ cy + radius * Math.sin(angle)
79
+ )
80
+ }
81
+
82
+ progressArc.strokeColor = new paper.Color(fillColor)
83
+ progressArc.strokeWidth = strokeWidth
84
+ progressArc.strokeCap = 'round'
85
+
86
+ if (project && project.activeLayer) {
87
+ project.activeLayer.addChild(progressArc)
88
+ }
89
+ elements.push({ type: 'path', id: progressArc.id })
90
+ }
91
+
92
+ // 绘制标签文字
93
+ if (showLabel) {
94
+ const textColor = labelColor || fillColor
95
+ const fontSize = Math.min(Math.max(Math.round(radius * 0.35), 12), 48)
96
+ const label = new paper.PointText({
97
+ point: [cx, cy + fontSize * 0.35],
98
+ content: `${Math.round(value)}%`,
99
+ fontSize: fontSize,
100
+ fillColor: new paper.Color(textColor),
101
+ justification: 'center',
102
+ fontWeight: 'bold'
103
+ })
104
+ if (project && project.activeLayer) {
105
+ project.activeLayer.addChild(label)
106
+ }
107
+ elements.push({ type: 'text', id: label.id })
108
+ }
109
+
110
+ return {
111
+ success: true,
112
+ elements,
113
+ type: 'progressCircle'
114
+ }
115
+ }
116
+
117
+ module.exports = createProgressCircle
@@ -0,0 +1,97 @@
1
+ /**
2
+ * 引用块组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建引用块
9
+ *
10
+ * @param {Object} project - Paper.js 项目
11
+ * @param {Object} canvas - 画布对象
12
+ * @param {Object} args - 组件参数
13
+ * @param {number} args.x - X坐标
14
+ * @param {number} args.y - Y坐标
15
+ * @param {number} args.width - 宽度
16
+ * @param {string} args.text - 引用文字
17
+ * @param {string} args.author - 作者
18
+ * @param {string} args.background - 背景色
19
+ * @param {string} args.borderColor - 左边框颜色
20
+ * @param {number} args.borderWidth - 左边框宽度
21
+ * @param {number} args.padding - 内边距
22
+ * @param {number} args.radius - 圆角半径
23
+ * @param {string} args.textColor - 文字颜色
24
+ * @param {string} args.authorColor - 作者颜色
25
+ * @param {number} args.fontSize - 字体大小
26
+ */
27
+ function createQuote(project, canvas, args) {
28
+ const {
29
+ x, y,
30
+ width = 400,
31
+ text,
32
+ author,
33
+ background = '#f8fafc',
34
+ borderColor = '#6366f1',
35
+ borderWidth = 4,
36
+ padding = 20,
37
+ radius = 8,
38
+ textColor = '#1e293b',
39
+ authorColor = '#64748b',
40
+ fontSize = 18,
41
+ } = args
42
+
43
+ const elements = []
44
+
45
+ // 绘制背景
46
+ const bg = new paper.Path.Rectangle({
47
+ point: [x, y],
48
+ size: [width, author ? 80 + fontSize * 2 : 40 + fontSize * 1.5],
49
+ radius: radius,
50
+ })
51
+ bg.fillColor = new paper.Color(background)
52
+ elements.push({ type: 'rectangle', id: bg.id })
53
+
54
+ // 绘制左边框
55
+ const border = new paper.Path.Rectangle({
56
+ point: [x, y],
57
+ size: [borderWidth, author ? 80 + fontSize * 2 : 40 + fontSize * 1.5],
58
+ })
59
+ border.fillColor = new paper.Color(borderColor)
60
+ elements.push({ type: 'rectangle', id: border.id })
61
+
62
+ // 绘制引用符号
63
+ const quoteMark = new paper.PointText({
64
+ point: [x + padding + 10, y + padding + fontSize],
65
+ content: '"',
66
+ fontSize: fontSize * 2,
67
+ fillColor: new paper.Color(borderColor),
68
+ justification: 'left',
69
+ })
70
+ elements.push({ type: 'text', id: quoteMark.id })
71
+
72
+ // 绘制引用文字
73
+ const quoteText = new paper.PointText({
74
+ point: [x + padding + 30, y + padding + fontSize * 1.5],
75
+ content: text,
76
+ fontSize: fontSize,
77
+ fillColor: new paper.Color(textColor),
78
+ justification: 'left',
79
+ })
80
+ elements.push({ type: 'text', id: quoteText.id })
81
+
82
+ // 绘制作者
83
+ if (author) {
84
+ const authorText = new paper.PointText({
85
+ point: [x + padding, y + padding + fontSize * 2.5 + 10],
86
+ content: `— ${author}`,
87
+ fontSize: fontSize * 0.8,
88
+ fillColor: new paper.Color(authorColor),
89
+ justification: 'left',
90
+ })
91
+ elements.push({ type: 'text', id: authorText.id })
92
+ }
93
+
94
+ return { success: true, elements }
95
+ }
96
+
97
+ module.exports = createQuote
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 星级评分组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建星级评分
9
+ *
10
+ * @param {Object} project - Paper.js 项目
11
+ * @param {Object} canvas - 画布对象
12
+ * @param {Object} args - 组件参数
13
+ * @param {number} args.x - X坐标
14
+ * @param {number} args.y - Y坐标
15
+ * @param {number} args.value - 评分值 0-5
16
+ * @param {number} args.max - 最大值,默认5
17
+ * @param {number} args.size - 星星大小
18
+ * @param {string} args.filledColor - 填充颜色
19
+ * @param {string} args.emptyColor - 空心颜色
20
+ * @param {number} args.gap - 星星间距
21
+ */
22
+ function createRating(project, canvas, args) {
23
+ const {
24
+ x, y,
25
+ value = 4,
26
+ max = 5,
27
+ size = 24,
28
+ filledColor = '#fbbf24',
29
+ emptyColor = '#e5e7eb',
30
+ gap = 4,
31
+ } = args
32
+
33
+ const elements = []
34
+
35
+ for (let i = 0; i < max; i++) {
36
+ const starX = x + i * (size + gap)
37
+ const filled = i < Math.floor(value)
38
+ const partial = !filled && i < value
39
+
40
+ // 绘制星星(使用多边形)
41
+ const star = createStar(project, starX + size / 2, y + size / 2, size / 2, size / 4, 5)
42
+ star.fillColor = new paper.Color(partial ? filledColor : emptyColor)
43
+ star.opacity = partial ? value - Math.floor(value) : 1
44
+ elements.push({ type: 'polygon', id: star.id })
45
+
46
+ if (partial) {
47
+ // 半星效果用填充色覆盖一半
48
+ const halfStar = createStar(project, starX + size / 2, y + size / 2, size / 2, size / 4, 5)
49
+ const clipPath = new paper.Path.Rectangle({
50
+ point: [starX, y],
51
+ size: [size / 2, size],
52
+ })
53
+ halfStar.fillColor = new paper.Color(filledColor)
54
+ halfStar.opacity = 1
55
+ elements.push({ type: 'polygon', id: halfStar.id })
56
+ }
57
+ }
58
+
59
+ return {
60
+ success: true,
61
+ elements,
62
+ value,
63
+ }
64
+ }
65
+
66
+ /**
67
+ * 创建星星形状
68
+ */
69
+ function createStar(project, cx, cy, outerRadius, innerRadius, points) {
70
+ const star = new paper.Path()
71
+ const step = Math.PI / points
72
+
73
+ for (let i = 0; i < 2 * points; i++) {
74
+ const radius = i % 2 === 0 ? outerRadius : innerRadius
75
+ const angle = i * step - Math.PI / 2
76
+ const x = cx + Math.cos(angle) * radius
77
+ const y = cy + Math.sin(angle) * radius
78
+ star.add(new paper.Point(x, y))
79
+ }
80
+
81
+ star.closed = true
82
+ return star
83
+ }
84
+
85
+ module.exports = createRating
@@ -0,0 +1,70 @@
1
+ /**
2
+ * 星形组件 - 支持多角星形
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建星形组件
9
+ * @param {Object} project - Paper.js 项目
10
+ * @param {Object} canvas - 画布对象
11
+ * @param {Object} params - 组件参数
12
+ */
13
+ function createStar(project, canvas, params) {
14
+ const {
15
+ cx,
16
+ cy,
17
+ points = 5,
18
+ innerRadius: providedInnerRadius,
19
+ outerRadius,
20
+ fill,
21
+ stroke,
22
+ strokeWidth = 1,
23
+ opacity = 1,
24
+ rotation = 0
25
+ } = params
26
+
27
+ // 计算内半径
28
+ const innerRadius = providedInnerRadius || outerRadius * 0.4
29
+
30
+ // 创建星形路径
31
+ const path = new paper.Path()
32
+ const angleStep = Math.PI / points
33
+
34
+ for (let i = 0; i < points * 2; i++) {
35
+ const radius = i % 2 === 0 ? outerRadius : innerRadius
36
+ const angle = i * angleStep - Math.PI / 2 + (rotation * Math.PI / 180)
37
+ const x = cx + radius * Math.cos(angle)
38
+ const y = cy + radius * Math.sin(angle)
39
+
40
+ if (i === 0) {
41
+ path.moveTo(x, y)
42
+ } else {
43
+ path.lineTo(x, y)
44
+ }
45
+ }
46
+ path.closePath()
47
+
48
+ // 设置样式
49
+ if (fill) {
50
+ path.fillColor = new paper.Color(fill)
51
+ }
52
+ if (stroke) {
53
+ path.strokeColor = new paper.Color(stroke)
54
+ path.strokeWidth = strokeWidth
55
+ }
56
+ path.opacity = opacity
57
+
58
+ // 关键:将元素添加到活动层
59
+ if (project && project.activeLayer) {
60
+ project.activeLayer.addChild(path)
61
+ }
62
+
63
+ return {
64
+ success: true,
65
+ elements: [{ type: 'path', id: path.id }],
66
+ type: 'star'
67
+ }
68
+ }
69
+
70
+ module.exports = createStar