@pinepaper.studio/mcp-server 1.6.27 → 1.6.29

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 (100) hide show
  1. package/README.md +112 -2
  2. package/SECURITY.md +6 -6
  3. package/dist/agent/export-manager.js +125 -125
  4. package/dist/assets/repositories/fontawesome.d.ts.map +1 -1
  5. package/dist/assets/repositories/fontawesome.js +2 -1
  6. package/dist/assets/repositories/fontawesome.js.map +1 -1
  7. package/dist/assets/repositories/iconify.d.ts.map +1 -1
  8. package/dist/assets/repositories/iconify.js +4 -3
  9. package/dist/assets/repositories/iconify.js.map +1 -1
  10. package/dist/browser/puppeteer-controller.js +38 -23
  11. package/dist/build-info.json +2 -2
  12. package/dist/cli.js +54 -54
  13. package/dist/execution/canvas-state.js +25 -25
  14. package/dist/i18n/locales/en.js +22 -22
  15. package/dist/i18n/locales/fil.js +44 -44
  16. package/dist/i18n/locales/is.js +22 -22
  17. package/dist/i18n/locales/ur.js +22 -22
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +5563 -5560
  20. package/dist/index.js.map +1 -1
  21. package/dist/ontology/upstream-vocabulary.d.ts +2 -2
  22. package/dist/ontology/upstream-vocabulary.js +6 -6
  23. package/dist/tools/choreograph.d.ts.map +1 -1
  24. package/dist/tools/choreograph.js +7 -0
  25. package/dist/tools/choreograph.js.map +1 -1
  26. package/dist/tools/craft-tools.js +18 -18
  27. package/dist/tools/definitions.d.ts.map +1 -1
  28. package/dist/tools/definitions.js +2830 -2812
  29. package/dist/tools/definitions.js.map +1 -1
  30. package/dist/tools/effect-check.js +68 -68
  31. package/dist/tools/engine-lists.d.ts +11 -4
  32. package/dist/tools/engine-lists.d.ts.map +1 -1
  33. package/dist/tools/engine-lists.js +49 -4
  34. package/dist/tools/engine-lists.js.map +1 -1
  35. package/dist/tools/engine-methods.d.ts.map +1 -1
  36. package/dist/tools/engine-methods.js +2 -1
  37. package/dist/tools/engine-methods.js.map +1 -1
  38. package/dist/tools/engine-surface.d.ts +1 -1
  39. package/dist/tools/engine-surface.d.ts.map +1 -1
  40. package/dist/tools/engine-surface.js +16 -4
  41. package/dist/tools/engine-surface.js.map +1 -1
  42. package/dist/tools/export-file-receipt.d.ts +21 -0
  43. package/dist/tools/export-file-receipt.d.ts.map +1 -1
  44. package/dist/tools/export-file-receipt.js +36 -13
  45. package/dist/tools/export-file-receipt.js.map +1 -1
  46. package/dist/tools/handlers/export.d.ts.map +1 -1
  47. package/dist/tools/handlers/export.js +6 -2
  48. package/dist/tools/handlers/export.js.map +1 -1
  49. package/dist/tools/handlers/font.js +22 -22
  50. package/dist/tools/handlers/generate.d.ts.map +1 -1
  51. package/dist/tools/handlers/generate.js +4 -3
  52. package/dist/tools/handlers/generate.js.map +1 -1
  53. package/dist/tools/handlers.d.ts +5 -0
  54. package/dist/tools/handlers.d.ts.map +1 -1
  55. package/dist/tools/handlers.js +29 -16
  56. package/dist/tools/handlers.js.map +1 -1
  57. package/dist/tools/lane.d.ts +7 -3
  58. package/dist/tools/lane.d.ts.map +1 -1
  59. package/dist/tools/lane.js +82 -67
  60. package/dist/tools/lane.js.map +1 -1
  61. package/dist/tools/p5-compat/p5-helpers.js +341 -341
  62. package/dist/tools/scene-cache-export.d.ts.map +1 -1
  63. package/dist/tools/scene-cache-export.js +8 -4
  64. package/dist/tools/scene-cache-export.js.map +1 -1
  65. package/dist/tools/shape-params.d.ts +2 -2
  66. package/dist/tools/shape-params.js +2 -2
  67. package/dist/tools/stick-vocabulary.d.ts +1 -1
  68. package/dist/tools/stick-vocabulary.js +1 -1
  69. package/dist/tools/timeline.js +82 -82
  70. package/dist/tools/toolkits.d.ts +1 -1
  71. package/dist/tools/toolkits.d.ts.map +1 -1
  72. package/dist/tools/toolkits.js +8 -2
  73. package/dist/tools/toolkits.js.map +1 -1
  74. package/dist/types/code-generator.d.ts.map +1 -1
  75. package/dist/types/code-generator.js +6682 -5832
  76. package/dist/types/code-generator.js.map +1 -1
  77. package/dist/types/schemas.d.ts +29 -2
  78. package/dist/types/schemas.d.ts.map +1 -1
  79. package/dist/types/schemas.js +9 -23
  80. package/dist/types/schemas.js.map +1 -1
  81. package/dist/utils/asset-paths.d.ts.map +1 -1
  82. package/dist/utils/asset-paths.js +11 -0
  83. package/dist/utils/asset-paths.js.map +1 -1
  84. package/dist/utils/capabilities.d.ts +15 -0
  85. package/dist/utils/capabilities.d.ts.map +1 -0
  86. package/dist/utils/capabilities.js +63 -0
  87. package/dist/utils/capabilities.js.map +1 -0
  88. package/dist/utils/env.d.ts.map +1 -1
  89. package/dist/utils/env.js +2 -1
  90. package/dist/utils/env.js.map +1 -1
  91. package/dist/utils/safe-fetch.d.ts +8 -0
  92. package/dist/utils/safe-fetch.d.ts.map +1 -1
  93. package/dist/utils/safe-fetch.js +125 -34
  94. package/dist/utils/safe-fetch.js.map +1 -1
  95. package/dist/vendor/design/device-mockup-generator.js +167 -150
  96. package/dist/vendor/design/recursive-subdivision-generator.js +107 -107
  97. package/dist/vendor/design/textile-weave-generator.js +429 -429
  98. package/dist/vendor/design/ui-kit-runtime.js +674 -674
  99. package/manifest.json +18 -2
  100. package/package.json +7 -4
@@ -31,58 +31,58 @@ export function generatePlainWeaveCode(opts = {}) {
31
31
  const slubJitter = opts.slubJitter ?? 0;
32
32
  const opacity = opts.opacity ?? 0.85;
33
33
  const prefix = opts.idPrefix ?? "plain_weave";
34
- return `// Plain Weave / Tabby Vector Generator
35
- (function() {
36
- const items = [];
37
- const x0 = ${x}, y0 = ${y}, x1 = ${x + w}, y1 = ${y + h};
38
- const pitch = ${pitch};
39
- const strokeWidth = ${threadWidth};
40
- const slubJitter = ${slubJitter};
41
-
42
- // Vertical Warp threads
43
- let colIdx = 0;
44
- for (let vx = x0; vx <= x1; vx += pitch) {
45
- const jitterX = slubJitter ? (Math.sin(colIdx * 1.7) * slubJitter * 2) : 0;
46
- const warp = new paper.Path.Line({
47
- from: [vx + jitterX, y0],
48
- to: [vx + jitterX, y1],
49
- strokeColor: "${warpColor}",
50
- strokeWidth: strokeWidth,
51
- strokeCap: "round",
52
- dashArray: [pitch, pitch],
53
- dashOffset: (colIdx % 2 === 0) ? 0 : pitch,
54
- opacity: ${opacity}
55
- });
56
- const id = "${prefix}_warp_" + colIdx;
57
- if (typeof app.registerItem === "function") app.registerItem(warp, id, { source: "weave_generator", weave: "plain", role: "warp" });
58
- items.push(warp);
59
- colIdx++;
60
- }
61
-
62
- // Horizontal Weft threads
63
- let rowIdx = 0;
64
- for (let vy = y0; vy <= y1; vy += pitch) {
65
- const jitterY = slubJitter ? (Math.cos(rowIdx * 1.7) * slubJitter * 2) : 0;
66
- const weft = new paper.Path.Line({
67
- from: [x0, vy + jitterY],
68
- to: [x1, vy + jitterY],
69
- strokeColor: "${weftColor}",
70
- strokeWidth: strokeWidth,
71
- strokeCap: "round",
72
- dashArray: [pitch, pitch],
73
- dashOffset: (rowIdx % 2 === 0) ? pitch : 0,
74
- opacity: ${opacity}
75
- });
76
- const id = "${prefix}_weft_" + rowIdx;
77
- if (typeof app.registerItem === "function") app.registerItem(weft, id, { source: "weave_generator", weave: "plain", role: "weft" });
78
- items.push(weft);
79
- rowIdx++;
80
- }
81
-
82
- const group = new paper.Group(items);
83
- if (typeof app.registerItem === "function") app.registerItem(group, "${prefix}_group", { source: "weave_generator", weave: "plain" });
84
- return group;
85
- })();`;
34
+ return ("// Plain Weave / Tabby Vector Generator\n(function() {\n const items = [];\n const x0 = " +
35
+ String(x) +
36
+ ", y0 = " +
37
+ String(y) +
38
+ ", x1 = " +
39
+ String(x + w) +
40
+ ", y1 = " +
41
+ String(y + h) +
42
+ ";\n const pitch = " +
43
+ String(pitch) +
44
+ ";\n const strokeWidth = " +
45
+ String(threadWidth) +
46
+ ";\n const slubJitter = " +
47
+ String(slubJitter) +
48
+ ";\n\n // Vertical Warp threads\n let colIdx = 0;\n for (let vx = x0; vx <= x1; vx += pitch) {\n const jitterX = slubJitter ? (Math.sin(colIdx * 1.7) * slubJitter * 2) : 0;\n const warp = new paper.Path.Line({\n from: [vx + jitterX, y0],\n to: [vx + jitterX, y1],\n strokeColor: \"" +
49
+ String(warpColor) +
50
+ "\",\n strokeWidth: strokeWidth,\n strokeCap: \"round\",\n dashArray: [pitch, pitch],\n dashOffset: (colIdx % 2 === 0) ? 0 : pitch,\n opacity: " +
51
+ String(opacity) +
52
+ "\n });\n const id = \"" +
53
+ String(prefix) +
54
+ "_warp_\" + colIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(warp, id, { source: \"weave_generator\", weave: \"plain\", role: \"warp\" });\n items.push(warp);\n colIdx++;\n }\n\n // Horizontal Weft threads\n let rowIdx = 0;\n for (let vy = y0; vy <= y1; vy += pitch) {\n const jitterY = slubJitter ? (Math.cos(rowIdx * 1.7) * slubJitter * 2) : 0;\n const weft = new paper.Path.Line({\n from: [x0, vy + jitterY],\n to: [x1, vy + jitterY],\n strokeColor: \"" +
55
+ String(weftColor) +
56
+ "\",\n strokeWidth: strokeWidth,\n strokeCap: \"round\",\n dashArray: [pitch, pitch],\n dashOffset: (rowIdx % 2 === 0) ? pitch : 0,\n opacity: " +
57
+ String(opacity) +
58
+ "\n });\n const id = \"" +
59
+ String(prefix) +
60
+ "_weft_\" + rowIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(weft, id, { source: \"weave_generator\", weave: \"plain\", role: \"weft\" });\n items.push(weft);\n rowIdx++;\n }\n\n const group = new paper.Group(items);\n if (typeof app.registerItem === \"function\") app.registerItem(group, \"" +
61
+ String(prefix) +
62
+ "_group\", { source: \"weave_generator\", weave: \"plain\" });\n return group;\n})();"
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+ );
86
86
  }
87
87
  /**
88
88
  * Generate Paper.js code for a Twill / Herringbone Weave.
@@ -103,80 +103,80 @@ export function generateTwillWeaveCode(opts = {}) {
103
103
  const weftColor = opts.weftColor ?? "rgba(203, 213, 225, 0.5)";
104
104
  const opacity = opts.opacity ?? 0.9;
105
105
  const prefix = opts.idPrefix ?? (isHerringbone ? "herringbone_weave" : "twill_weave");
106
- return `// Twill Weave & Herringbone Vector Generator
107
- (function() {
108
- const items = [];
109
- const x0 = ${x}, y0 = ${y}, x1 = ${x + w}, y1 = ${y + h};
110
- const pitch = ${pitch};
111
- const floatLen = pitch * ${floatRatio};
112
- const isHerringbone = ${isHerringbone};
113
- const chevronWidth = ${chevronW};
114
-
115
- // Warp lines (base grid)
116
- let colIdx = 0;
117
- for (let vx = x0; vx <= x1; vx += pitch) {
118
- const warp = new paper.Path.Line({
119
- from: [vx, y0],
120
- to: [vx, y1],
121
- strokeColor: "${warpColor}",
122
- strokeWidth: ${threadWidth},
123
- strokeCap: "round",
124
- opacity: ${opacity * 0.7}
125
- });
126
- const id = "${prefix}_warp_" + colIdx;
127
- if (typeof app.registerItem === "function") app.registerItem(warp, id, { source: "weave_generator", weave: "twill", role: "warp" });
128
- items.push(warp);
129
- colIdx++;
130
- }
131
-
132
- // Weft float lines with diagonal stepped offsets
133
- let rowIdx = 0;
134
- for (let vy = y0; vy <= y1; vy += pitch) {
135
- if (isHerringbone) {
136
- // Split into chevron blocks with reversing slants
137
- for (let bx = x0; bx < x1; bx += chevronWidth) {
138
- const segEnd = Math.min(x1, bx + chevronWidth);
139
- const blockIdx = Math.floor((bx - x0) / chevronWidth);
140
- const dir = (blockIdx % 2 === 0) ? 1 : -1;
141
- const phase = dir === 1 ? ((rowIdx * pitch) % (floatLen * 2)) : (((1000 - rowIdx) * pitch) % (floatLen * 2));
142
- const weftSeg = new paper.Path.Line({
143
- from: [bx, vy],
144
- to: [segEnd, vy],
145
- strokeColor: "${weftColor}",
146
- strokeWidth: ${threadWidth},
147
- strokeCap: "round",
148
- dashArray: [floatLen, pitch],
149
- dashOffset: phase,
150
- opacity: ${opacity}
151
- });
152
- const id = "${prefix}_weft_" + rowIdx + "_" + blockIdx;
153
- if (typeof app.registerItem === "function") app.registerItem(weftSeg, id, { source: "weave_generator", weave: "herringbone", role: "weft" });
154
- items.push(weftSeg);
155
- }
156
- } else {
157
- // Classic diagonal twill
158
- const phase = (rowIdx * pitch) % (floatLen * 2);
159
- const weft = new paper.Path.Line({
160
- from: [x0, vy],
161
- to: [x1, vy],
162
- strokeColor: "${weftColor}",
163
- strokeWidth: ${threadWidth},
164
- strokeCap: "round",
165
- dashArray: [floatLen, pitch],
166
- dashOffset: phase,
167
- opacity: ${opacity}
168
- });
169
- const id = "${prefix}_weft_" + rowIdx;
170
- if (typeof app.registerItem === "function") app.registerItem(weft, id, { source: "weave_generator", weave: "twill", role: "weft" });
171
- items.push(weft);
172
- }
173
- rowIdx++;
174
- }
106
+ return ("// Twill Weave & Herringbone Vector Generator\n(function() {\n const items = [];\n const x0 = " +
107
+ String(x) +
108
+ ", y0 = " +
109
+ String(y) +
110
+ ", x1 = " +
111
+ String(x + w) +
112
+ ", y1 = " +
113
+ String(y + h) +
114
+ ";\n const pitch = " +
115
+ String(pitch) +
116
+ ";\n const floatLen = pitch * " +
117
+ String(floatRatio) +
118
+ ";\n const isHerringbone = " +
119
+ String(isHerringbone) +
120
+ ";\n const chevronWidth = " +
121
+ String(chevronW) +
122
+ ";\n\n // Warp lines (base grid)\n let colIdx = 0;\n for (let vx = x0; vx <= x1; vx += pitch) {\n const warp = new paper.Path.Line({\n from: [vx, y0],\n to: [vx, y1],\n strokeColor: \"" +
123
+ String(warpColor) +
124
+ "\",\n strokeWidth: " +
125
+ String(threadWidth) +
126
+ ",\n strokeCap: \"round\",\n opacity: " +
127
+ String(opacity * 0.7) +
128
+ "\n });\n const id = \"" +
129
+ String(prefix) +
130
+ "_warp_\" + colIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(warp, id, { source: \"weave_generator\", weave: \"twill\", role: \"warp\" });\n items.push(warp);\n colIdx++;\n }\n\n // Weft float lines with diagonal stepped offsets\n let rowIdx = 0;\n for (let vy = y0; vy <= y1; vy += pitch) {\n if (isHerringbone) {\n // Split into chevron blocks with reversing slants\n for (let bx = x0; bx < x1; bx += chevronWidth) {\n const segEnd = Math.min(x1, bx + chevronWidth);\n const blockIdx = Math.floor((bx - x0) / chevronWidth);\n const dir = (blockIdx % 2 === 0) ? 1 : -1;\n const phase = dir === 1 ? ((rowIdx * pitch) % (f" +
131
+ "loatLen * 2)) : (((1000 - rowIdx) * pitch) % (floatLen * 2));\n const weftSeg = new paper.Path.Line({\n from: [bx, vy],\n to: [segEnd, vy],\n strokeColor: \"" +
132
+ String(weftColor) +
133
+ "\",\n strokeWidth: " +
134
+ String(threadWidth) +
135
+ ",\n strokeCap: \"round\",\n dashArray: [floatLen, pitch],\n dashOffset: phase,\n opacity: " +
136
+ String(opacity) +
137
+ "\n });\n const id = \"" +
138
+ String(prefix) +
139
+ "_weft_\" + rowIdx + \"_\" + blockIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(weftSeg, id, { source: \"weave_generator\", weave: \"herringbone\", role: \"weft\" });\n items.push(weftSeg);\n }\n } else {\n // Classic diagonal twill\n const phase = (rowIdx * pitch) % (floatLen * 2);\n const weft = new paper.Path.Line({\n from: [x0, vy],\n to: [x1, vy],\n strokeColor: \"" +
140
+ String(weftColor) +
141
+ "\",\n strokeWidth: " +
142
+ String(threadWidth) +
143
+ ",\n strokeCap: \"round\",\n dashArray: [floatLen, pitch],\n dashOffset: phase,\n opacity: " +
144
+ String(opacity) +
145
+ "\n });\n const id = \"" +
146
+ String(prefix) +
147
+ "_weft_\" + rowIdx;\n if (typeof app.registerItem === \"function\") app.registerItem(weft, id, { source: \"weave_generator\", weave: \"twill\", role: \"weft\" });\n items.push(weft);\n }\n rowIdx++;\n }\n\n const group = new paper.Group(items);\n if (typeof app.registerItem === \"function\") app.registerItem(group, \"" +
148
+ String(prefix) +
149
+ "_group\", { source: \"weave_generator\", weave: isHerringbone ? \"herringbone\" : \"twill\" });\n return group;\n})();"
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
175
161
 
176
- const group = new paper.Group(items);
177
- if (typeof app.registerItem === "function") app.registerItem(group, "${prefix}_group", { source: "weave_generator", weave: isHerringbone ? "herringbone" : "twill" });
178
- return group;
179
- })();`;
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
179
+ );
180
180
  }
181
181
  /**
182
182
  * Generate Paper.js code for a Basketweave (Panama) pattern.
@@ -195,54 +195,54 @@ export function generateBasketWeaveCode(opts = {}) {
195
195
  const colorB = opts.colorB ?? opts.weftColor ?? "rgba(217, 119, 6, 0.6)";
196
196
  const opacity = opts.opacity ?? 0.85;
197
197
  const prefix = opts.idPrefix ?? "basket_weave";
198
- return `// Basketweave Vector Generator
199
- (function() {
200
- const items = [];
201
- const x0 = ${x}, y0 = ${y}, x1 = ${x + w}, y1 = ${y + h};
202
- const pitch = ${pitch};
203
- const bundleSize = ${bundleSize};
204
- const bundleGap = ${bundleGap};
205
- const blockSize = (bundleSize * pitch) + bundleGap;
206
- const threadWidth = ${threadWidth};
207
-
208
- let rIdx = 0;
209
- for (let vy = y0; vy <= y1; vy += blockSize) {
210
- let cIdx = 0;
211
- for (let vx = x0; vx <= x1; vx += blockSize) {
212
- const isHorizontal = (rIdx + cIdx) % 2 === 0;
213
- for (let t = 0; t < bundleSize; t++) {
214
- const offset = t * pitch + pitch / 2;
215
- let line;
216
- if (isHorizontal) {
217
- line = new paper.Path.Line({
218
- from: [vx, vy + offset],
219
- to: [Math.min(x1, vx + blockSize - bundleGap), vy + offset],
220
- strokeColor: "${colorA}",
221
- strokeWidth: threadWidth,
222
- strokeCap: "round",
223
- opacity: ${opacity}
224
- });
225
- } else {
226
- line = new paper.Path.Line({
227
- from: [vx + offset, vy],
228
- to: [vx + offset, Math.min(y1, vy + blockSize - bundleGap)],
229
- strokeColor: "${colorB}",
230
- strokeWidth: threadWidth,
231
- strokeCap: "round",
232
- opacity: ${opacity}
233
- });
234
- }
235
- items.push(line);
236
- }
237
- cIdx++;
238
- }
239
- rIdx++;
240
- }
198
+ return ("// Basketweave Vector Generator\n(function() {\n const items = [];\n const x0 = " +
199
+ String(x) +
200
+ ", y0 = " +
201
+ String(y) +
202
+ ", x1 = " +
203
+ String(x + w) +
204
+ ", y1 = " +
205
+ String(y + h) +
206
+ ";\n const pitch = " +
207
+ String(pitch) +
208
+ ";\n const bundleSize = " +
209
+ String(bundleSize) +
210
+ ";\n const bundleGap = " +
211
+ String(bundleGap) +
212
+ ";\n const blockSize = (bundleSize * pitch) + bundleGap;\n const threadWidth = " +
213
+ String(threadWidth) +
214
+ ";\n\n let rIdx = 0;\n for (let vy = y0; vy <= y1; vy += blockSize) {\n let cIdx = 0;\n for (let vx = x0; vx <= x1; vx += blockSize) {\n const isHorizontal = (rIdx + cIdx) % 2 === 0;\n for (let t = 0; t < bundleSize; t++) {\n const offset = t * pitch + pitch / 2;\n let line;\n if (isHorizontal) {\n line = new paper.Path.Line({\n from: [vx, vy + offset],\n to: [Math.min(x1, vx + blockSize - bundleGap), vy + offset],\n strokeColor: \"" +
215
+ String(colorA) +
216
+ "\",\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n opacity: " +
217
+ String(opacity) +
218
+ "\n });\n } else {\n line = new paper.Path.Line({\n from: [vx + offset, vy],\n to: [vx + offset, Math.min(y1, vy + blockSize - bundleGap)],\n strokeColor: \"" +
219
+ String(colorB) +
220
+ "\",\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n opacity: " +
221
+ String(opacity) +
222
+ "\n });\n }\n items.push(line);\n }\n cIdx++;\n }\n rIdx++;\n }\n\n const group = new paper.Group(items);\n if (typeof app.registerItem === \"function\") app.registerItem(group, \"" +
223
+ String(prefix) +
224
+ "_group\", { source: \"weave_generator\", weave: \"basket\" });\n return group;\n})();"
225
+
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+
238
+
239
+
241
240
 
242
- const group = new paper.Group(items);
243
- if (typeof app.registerItem === "function") app.registerItem(group, "${prefix}_group", { source: "weave_generator", weave: "basket" });
244
- return group;
245
- })();`;
241
+
242
+
243
+
244
+
245
+ );
246
246
  }
247
247
  /**
248
248
  * Generate Paper.js code for tactile 3D Embroidered Knots (French knots, bullion coils, knot anchors).
@@ -256,130 +256,130 @@ export function generateKnotCode(opts = {}) {
256
256
  const defaultShadow = opts.shadowColor ?? opts.defaultShadow ?? "rgba(15, 23, 42, 0.4)";
257
257
  const prefix = opts.idPrefix ?? "embroidery_knot";
258
258
  const serializedKnots = JSON.stringify(knots);
259
- return `// Embroidered Knots & Anchor Relief Vector Generator
260
- (function() {
261
- const items = [];
262
- const knotList = ${serializedKnots};
263
- const knotType = "${knotType}";
264
- const defR = ${defaultRadius};
265
- const defCol = "${defaultColor}";
266
- const defHi = "${defaultHighlight}";
267
- const defShadow = "${defaultShadow}";
268
-
269
- knotList.forEach((k, idx) => {
270
- const kx = k.x, ky = k.y;
271
- const kr = k.radius || defR;
272
- const col = k.color || defCol;
273
- const hi = k.highlightColor || defHi;
274
- const sh = k.shadowColor || defShadow;
275
- const knotParts = [];
276
-
277
- if (knotType === "bullion_roll") {
278
- // Bullion roll coils along directional vector
279
- const len = k.length || (kr * 4);
280
- const angRad = ((k.angle || 0) * Math.PI) / 180;
281
- const dx = Math.cos(angRad);
282
- const dy = Math.sin(angRad);
283
- const steps = Math.max(3, Math.round(len / (kr * 0.8)));
284
-
285
- // Base shadow line
286
- const baseShadow = new paper.Path.Line({
287
- from: [kx + 1, ky + 1.5],
288
- to: [kx + dx * len + 1, ky + dy * len + 1.5],
289
- strokeColor: sh,
290
- strokeWidth: kr * 1.8,
291
- strokeCap: "round"
292
- });
293
- knotParts.push(baseShadow);
294
-
295
- // Overlapping coil loops
296
- for (let s = 0; s < steps; s++) {
297
- const t = s / steps;
298
- const cx = kx + dx * (len * t);
299
- const cy = ky + dy * (len * t);
300
- const coil = new paper.Path.Circle({
301
- center: [cx, cy],
302
- radius: kr,
303
- fillColor: col,
304
- strokeColor: hi,
305
- strokeWidth: 0.8
306
- });
307
- knotParts.push(coil);
308
- }
309
- } else if (knotType === "knot_anchor") {
310
- // Anchor tack cross stitches
311
- const tackLen = kr * 1.5;
312
- const line1 = new paper.Path.Line({
313
- from: [kx - tackLen, ky - tackLen],
314
- to: [kx + tackLen, ky + tackLen],
315
- strokeColor: col,
316
- strokeWidth: Math.max(1, kr * 0.4),
317
- strokeCap: "round"
318
- });
319
- const line2 = new paper.Path.Line({
320
- from: [kx - tackLen, ky + tackLen],
321
- to: [kx + tackLen, ky - tackLen],
322
- strokeColor: col,
323
- strokeWidth: Math.max(1, kr * 0.4),
324
- strokeCap: "round"
325
- });
326
- const centerDot = new paper.Path.Circle({
327
- center: [kx, ky],
328
- radius: kr * 0.6,
329
- fillColor: hi
330
- });
331
- knotParts.push(line1, line2, centerDot);
332
- } else {
333
- // Standard tactile French knot relief
334
- // 1. French knot shadow crescent anchor beneath knot
335
- const shadow = new paper.Path.Circle({
336
- center: [kx + 1, ky + 1.5],
337
- radius: kr,
338
- fillColor: sh,
339
- strokeColor: null
340
- });
341
- knotParts.push(shadow);
342
-
343
- // 2. French knot coil body outer thread
344
- const body = new paper.Path.Circle({
345
- center: [kx, ky],
346
- radius: kr,
347
- fillColor: col,
348
- strokeColor: "#f8fafc",
349
- strokeWidth: 1
350
- });
351
- knotParts.push(body);
352
-
353
- // 3. Inner coiled thread wrap
354
- const innerCoil = new paper.Path.Circle({
355
- center: [kx + kr * 0.1, ky + kr * 0.1],
356
- radius: Math.max(1, kr * 0.55),
357
- fillColor: null,
358
- strokeColor: col,
359
- strokeWidth: Math.max(0.8, kr * 0.28)
360
- });
361
- knotParts.push(innerCoil);
362
-
363
- // 4. Specular glint highlight
364
- const glint = new paper.Path.Circle({
365
- center: [kx - kr * 0.32, ky - kr * 0.32],
366
- radius: Math.max(0.8, kr * 0.3),
367
- fillColor: hi,
368
- strokeColor: null
369
- });
370
- knotParts.push(glint);
371
- }
259
+ return ("// Embroidered Knots & Anchor Relief Vector Generator\n(function() {\n const items = [];\n const knotList = " +
260
+ String(serializedKnots) +
261
+ ";\n const knotType = \"" +
262
+ String(knotType) +
263
+ "\";\n const defR = " +
264
+ String(defaultRadius) +
265
+ ";\n const defCol = \"" +
266
+ String(defaultColor) +
267
+ "\";\n const defHi = \"" +
268
+ String(defaultHighlight) +
269
+ "\";\n const defShadow = \"" +
270
+ String(defaultShadow) +
271
+ "\";\n\n knotList.forEach((k, idx) => {\n const kx = k.x, ky = k.y;\n const kr = k.radius || defR;\n const col = k.color || defCol;\n const hi = k.highlightColor || defHi;\n const sh = k.shadowColor || defShadow;\n const knotParts = [];\n\n if (knotType === \"bullion_roll\") {\n // Bullion roll coils along directional vector\n const len = k.length || (kr * 4);\n const angRad = ((k.angle || 0) * Math.PI) / 180;\n const dx = Math.cos(angRad);\n const dy = Math.sin(angRad);\n const steps = Math.max(3, Math.round(len / (kr * 0.8)));\n\n // Base shadow line\n const baseShadow = new paper.Path.Line({\n from: [kx + 1, ky + 1.5]," +
272
+ "\n to: [kx + dx * len + 1, ky + dy * len + 1.5],\n strokeColor: sh,\n strokeWidth: kr * 1.8,\n strokeCap: \"round\"\n });\n knotParts.push(baseShadow);\n\n // Overlapping coil loops\n for (let s = 0; s < steps; s++) {\n const t = s / steps;\n const cx = kx + dx * (len * t);\n const cy = ky + dy * (len * t);\n const coil = new paper.Path.Circle({\n center: [cx, cy],\n radius: kr,\n fillColor: col,\n strokeColor: hi,\n strokeWidth: 0.8\n });\n knotParts.push(coil);\n }\n } else if (knotType === \"knot_anchor\") {\n // Anchor tack cross stitches\n" +
273
+ " const tackLen = kr * 1.5;\n const line1 = new paper.Path.Line({\n from: [kx - tackLen, ky - tackLen],\n to: [kx + tackLen, ky + tackLen],\n strokeColor: col,\n strokeWidth: Math.max(1, kr * 0.4),\n strokeCap: \"round\"\n });\n const line2 = new paper.Path.Line({\n from: [kx - tackLen, ky + tackLen],\n to: [kx + tackLen, ky - tackLen],\n strokeColor: col,\n strokeWidth: Math.max(1, kr * 0.4),\n strokeCap: \"round\"\n });\n const centerDot = new paper.Path.Circle({\n center: [kx, ky],\n radius: kr * 0.6,\n fillColor: hi\n });\n knotParts.push(line1, line2, cente" +
274
+ "rDot);\n } else {\n // Standard tactile French knot relief\n // 1. French knot shadow crescent anchor beneath knot\n const shadow = new paper.Path.Circle({\n center: [kx + 1, ky + 1.5],\n radius: kr,\n fillColor: sh,\n strokeColor: null\n });\n knotParts.push(shadow);\n\n // 2. French knot coil body outer thread\n const body = new paper.Path.Circle({\n center: [kx, ky],\n radius: kr,\n fillColor: col,\n strokeColor: \"#f8fafc\",\n strokeWidth: 1\n });\n knotParts.push(body);\n\n // 3. Inner coiled thread wrap\n const innerCoil = new paper.Path.Circle({\n center: [" +
275
+ "kx + kr * 0.1, ky + kr * 0.1],\n radius: Math.max(1, kr * 0.55),\n fillColor: null,\n strokeColor: col,\n strokeWidth: Math.max(0.8, kr * 0.28)\n });\n knotParts.push(innerCoil);\n\n // 4. Specular glint highlight\n const glint = new paper.Path.Circle({\n center: [kx - kr * 0.32, ky - kr * 0.32],\n radius: Math.max(0.8, kr * 0.3),\n fillColor: hi,\n strokeColor: null\n });\n knotParts.push(glint);\n }\n\n const knotGroup = new paper.Group(knotParts);\n const id = \"" +
276
+ String(prefix) +
277
+ "_\" + idx;\n if (typeof app.registerItem === \"function\") app.registerItem(knotGroup, id, { source: \"knot_generator\", x: kx, y: ky, radius: kr });\n items.push(knotGroup);\n });\n\n const masterGroup = new paper.Group(items);\n if (typeof app.registerItem === \"function\") app.registerItem(masterGroup, \"" +
278
+ String(prefix) +
279
+ "_collection\", { source: \"knot_generator\", count: items.length });\n return masterGroup;\n})();"
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
+
308
+
309
+
310
+
311
+
312
+
313
+
314
+
315
+
316
+
317
+
318
+
319
+
320
+
321
+
322
+
323
+
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+
332
+
333
+
334
+
335
+
336
+
337
+
338
+
339
+
340
+
341
+
372
342
 
373
- const knotGroup = new paper.Group(knotParts);
374
- const id = "${prefix}_" + idx;
375
- if (typeof app.registerItem === "function") app.registerItem(knotGroup, id, { source: "knot_generator", x: kx, y: ky, radius: kr });
376
- items.push(knotGroup);
377
- });
378
343
 
379
- const masterGroup = new paper.Group(items);
380
- if (typeof app.registerItem === "function") app.registerItem(masterGroup, "${prefix}_collection", { source: "knot_generator", count: items.length });
381
- return masterGroup;
382
- })();`;
344
+
345
+
346
+
347
+
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+
363
+
364
+
365
+
366
+
367
+
368
+
369
+
370
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+
381
+
382
+ );
383
383
  }
384
384
  /**
385
385
  * Generate Paper.js code for Japanese Sashiko geometric folk embroidery.
@@ -401,141 +401,141 @@ export function generateSashikoCode(opts = {}) {
401
401
  const concentricArcs = Math.max(1, opts.concentricArcs ?? 3);
402
402
  const opacity = opts.opacity ?? 0.92;
403
403
  const prefix = opts.idPrefix ?? `sashiko_${pattern}`;
404
- return `// Sashiko Geometric Folk Embroidery Generator (${pattern})
405
- (function() {
406
- const items = [];
407
- const x0 = ${x}, y0 = ${y}, x1 = ${x + w}, y1 = ${y + h};
408
- const threadColor = "${threadColor}";
409
- const threadWidth = ${threadWidth};
410
- const stitchLen = ${stitchLen};
411
- const gapLen = ${gapLen};
412
- const vertexGap = ${vertexGap};
413
- const scale = ${scale};
414
- const concentricArcs = ${concentricArcs};
415
- const opacity = ${opacity};
416
-
417
- // 0. Ground cloth plate
418
- const bgPlate = new paper.Path.Rectangle({
419
- point: [x0, y0],
420
- size: [x1 - x0, y1 - y0],
421
- fillColor: "${groundColor}",
422
- strokeColor: null
423
- });
424
- items.push(bgPlate);
425
-
426
- if ("${pattern}" === "seigaiha") {
427
- // Seigaiha: Overlapping concentric ocean wave arcs with staggered centers
428
- const R = scale;
429
- const dy = R * 0.55;
430
- let row = 0;
431
- for (let cy = y0 + R * 0.4; cy <= y1 + R; cy += dy) {
432
- const offsetX = (row % 2 === 0) ? 0 : R;
433
- let col = 0;
434
- for (let cx = x0 - R + offsetX; cx <= x1 + R; cx += R * 2) {
435
- for (let a = 1; a <= concentricArcs; a++) {
436
- const arcR = (R * a) / concentricArcs;
437
- const fromPt = [cx - arcR + vertexGap * 0.5, cy - vertexGap * 0.2];
438
- const throughPt = [cx, cy - arcR];
439
- const toPt = [cx + arcR - vertexGap * 0.5, cy - vertexGap * 0.2];
440
- const arc = new paper.Path.Arc(fromPt, throughPt, toPt);
441
- arc.strokeColor = threadColor;
442
- arc.strokeWidth = threadWidth;
443
- arc.strokeCap = "round";
444
- arc.dashArray = [stitchLen, gapLen];
445
- arc.opacity = opacity;
446
- items.push(arc);
447
- }
448
- col++;
449
- }
450
- row++;
451
- }
452
- } else if ("${pattern}" === "asanoha") {
453
- // Asanoha: Hexagonal star / hemp-leaf isometric lattice with vertex gap clearance
454
- const S = scale;
455
- const H = S * Math.sqrt(3) / 2;
456
- let rIdx = 0;
457
- for (let py = y0; py <= y1 + H; py += H) {
458
- const offX = (rIdx % 2 === 0) ? 0 : S * 0.5;
459
- for (let px = x0 - S + offX; px <= x1 + S; px += S) {
460
- const mx = px;
461
- const my = py;
462
- const angles = [0, 60, 120, 180, 240, 300];
463
- angles.forEach(angDeg => {
464
- const rad = (angDeg * Math.PI) / 180;
465
- const targetX = mx + Math.cos(rad) * S * 0.55;
466
- const targetY = my + Math.sin(rad) * S * 0.55;
467
-
468
- const startX = mx + Math.cos(rad) * vertexGap;
469
- const startY = my + Math.sin(rad) * vertexGap;
470
- const endX = targetX - Math.cos(rad) * vertexGap;
471
- const endY = targetY - Math.sin(rad) * vertexGap;
472
-
473
- const spoke = new paper.Path.Line({
474
- from: [startX, startY],
475
- to: [endX, endY],
476
- strokeColor: threadColor,
477
- strokeWidth: threadWidth,
478
- strokeCap: "round",
479
- dashArray: [stitchLen, gapLen],
480
- opacity: opacity
481
- });
482
- items.push(spoke);
483
- });
484
- }
485
- rIdx++;
486
- }
487
- } else {
488
- // Hishi / Kaki no Hana: Diamond grid with vertex gap junctions
489
- const P = scale;
490
- for (let diag = -Math.max(w, h); diag <= w + h; diag += P) {
491
- for (let t = 0; t <= w + h; t += P) {
492
- const p1x = t + vertexGap;
493
- const p1y = t + diag + vertexGap;
494
- const p2x = t + P - vertexGap;
495
- const p2y = t + P + diag - vertexGap;
496
- if (p1x >= x0 - P && p1x <= x1 + P && p1y >= y0 - P && p1y <= y1 + P) {
497
- const seg1 = new paper.Path.Line({
498
- from: [p1x, p1y],
499
- to: [p2x, p2y],
500
- strokeColor: threadColor,
501
- strokeWidth: threadWidth,
502
- strokeCap: "round",
503
- dashArray: [stitchLen, gapLen],
504
- opacity: opacity
505
- });
506
- items.push(seg1);
507
- }
508
-
509
- const q1x = t + vertexGap;
510
- const q1y = -t + diag + vertexGap;
511
- const q2x = t + P - vertexGap;
512
- const q2y = -(t + P) + diag - vertexGap;
513
- if (q1x >= x0 - P && q1x <= x1 + P && q1y >= y0 - P && q1y <= y1 + P) {
514
- const seg2 = new paper.Path.Line({
515
- from: [q1x, q1y],
516
- to: [q2x, q2y],
517
- strokeColor: threadColor,
518
- strokeWidth: threadWidth,
519
- strokeCap: "round",
520
- dashArray: [stitchLen, gapLen],
521
- opacity: opacity
522
- });
523
- items.push(seg2);
524
- }
525
- }
526
- }
527
- }
528
-
529
- const group = new paper.Group(items);
530
- if (typeof app.registerItem === "function") {
531
- app.registerItem(group, "${prefix}_group", {
532
- source: "sashiko_generator",
533
- pattern: "${pattern}",
534
- stitchCount: items.length
535
- });
536
- }
537
- return group;
538
- })();`;
404
+ return ("// Sashiko Geometric Folk Embroidery Generator (" +
405
+ String(pattern) +
406
+ ")\n(function() {\n const items = [];\n const x0 = " +
407
+ String(x) +
408
+ ", y0 = " +
409
+ String(y) +
410
+ ", x1 = " +
411
+ String(x + w) +
412
+ ", y1 = " +
413
+ String(y + h) +
414
+ ";\n const threadColor = \"" +
415
+ String(threadColor) +
416
+ "\";\n const threadWidth = " +
417
+ String(threadWidth) +
418
+ ";\n const stitchLen = " +
419
+ String(stitchLen) +
420
+ ";\n const gapLen = " +
421
+ String(gapLen) +
422
+ ";\n const vertexGap = " +
423
+ String(vertexGap) +
424
+ ";\n const scale = " +
425
+ String(scale) +
426
+ ";\n const concentricArcs = " +
427
+ String(concentricArcs) +
428
+ ";\n const opacity = " +
429
+ String(opacity) +
430
+ ";\n\n // 0. Ground cloth plate\n const bgPlate = new paper.Path.Rectangle({\n point: [x0, y0],\n size: [x1 - x0, y1 - y0],\n fillColor: \"" +
431
+ String(groundColor) +
432
+ "\",\n strokeColor: null\n });\n items.push(bgPlate);\n\n if (\"" +
433
+ String(pattern) +
434
+ "\" === \"seigaiha\") {\n // Seigaiha: Overlapping concentric ocean wave arcs with staggered centers\n const R = scale;\n const dy = R * 0.55;\n let row = 0;\n for (let cy = y0 + R * 0.4; cy <= y1 + R; cy += dy) {\n const offsetX = (row % 2 === 0) ? 0 : R;\n let col = 0;\n for (let cx = x0 - R + offsetX; cx <= x1 + R; cx += R * 2) {\n for (let a = 1; a <= concentricArcs; a++) {\n const arcR = (R * a) / concentricArcs;\n const fromPt = [cx - arcR + vertexGap * 0.5, cy - vertexGap * 0.2];\n const throughPt = [cx, cy - arcR];\n const toPt = [cx + arcR - vertexGap * 0.5, cy - vertexGap * 0.2];\n const arc = new pa" +
435
+ "per.Path.Arc(fromPt, throughPt, toPt);\n arc.strokeColor = threadColor;\n arc.strokeWidth = threadWidth;\n arc.strokeCap = \"round\";\n arc.dashArray = [stitchLen, gapLen];\n arc.opacity = opacity;\n items.push(arc);\n }\n col++;\n }\n row++;\n }\n } else if (\"" +
436
+ String(pattern) +
437
+ "\" === \"asanoha\") {\n // Asanoha: Hexagonal star / hemp-leaf isometric lattice with vertex gap clearance\n const S = scale;\n const H = S * Math.sqrt(3) / 2;\n let rIdx = 0;\n for (let py = y0; py <= y1 + H; py += H) {\n const offX = (rIdx % 2 === 0) ? 0 : S * 0.5;\n for (let px = x0 - S + offX; px <= x1 + S; px += S) {\n const mx = px;\n const my = py;\n const angles = [0, 60, 120, 180, 240, 300];\n angles.forEach(angDeg => {\n const rad = (angDeg * Math.PI) / 180;\n const targetX = mx + Math.cos(rad) * S * 0.55;\n const targetY = my + Math.sin(rad) * S * 0.55;\n\n const startX = mx + Math.cos(rad) " +
438
+ "* vertexGap;\n const startY = my + Math.sin(rad) * vertexGap;\n const endX = targetX - Math.cos(rad) * vertexGap;\n const endY = targetY - Math.sin(rad) * vertexGap;\n\n const spoke = new paper.Path.Line({\n from: [startX, startY],\n to: [endX, endY],\n strokeColor: threadColor,\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n dashArray: [stitchLen, gapLen],\n opacity: opacity\n });\n items.push(spoke);\n });\n }\n rIdx++;\n }\n } else {\n // Hishi / Kaki no Hana: Diamond grid with vertex gap junctions\n const P = scale;\n for" +
439
+ " (let diag = -Math.max(w, h); diag <= w + h; diag += P) {\n for (let t = 0; t <= w + h; t += P) {\n const p1x = t + vertexGap;\n const p1y = t + diag + vertexGap;\n const p2x = t + P - vertexGap;\n const p2y = t + P + diag - vertexGap;\n if (p1x >= x0 - P && p1x <= x1 + P && p1y >= y0 - P && p1y <= y1 + P) {\n const seg1 = new paper.Path.Line({\n from: [p1x, p1y],\n to: [p2x, p2y],\n strokeColor: threadColor,\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n dashArray: [stitchLen, gapLen],\n opacity: opacity\n });\n items.push(seg1);\n }" +
440
+ "\n\n const q1x = t + vertexGap;\n const q1y = -t + diag + vertexGap;\n const q2x = t + P - vertexGap;\n const q2y = -(t + P) + diag - vertexGap;\n if (q1x >= x0 - P && q1x <= x1 + P && q1y >= y0 - P && q1y <= y1 + P) {\n const seg2 = new paper.Path.Line({\n from: [q1x, q1y],\n to: [q2x, q2y],\n strokeColor: threadColor,\n strokeWidth: threadWidth,\n strokeCap: \"round\",\n dashArray: [stitchLen, gapLen],\n opacity: opacity\n });\n items.push(seg2);\n }\n }\n }\n }\n\n const group = new paper.Group(items);\n if (typeof app.registerItem " +
441
+ "=== \"function\") {\n app.registerItem(group, \"" +
442
+ String(prefix) +
443
+ "_group\", {\n source: \"sashiko_generator\",\n pattern: \"" +
444
+ String(pattern) +
445
+ "\",\n stitchCount: items.length\n });\n }\n return group;\n})();"
446
+
447
+
448
+
449
+
450
+
451
+
452
+
453
+
454
+
455
+
456
+
457
+
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+
469
+
470
+
471
+
472
+
473
+
474
+
475
+
476
+
477
+
478
+
479
+
480
+
481
+
482
+
483
+
484
+
485
+
486
+
487
+
488
+
489
+
490
+
491
+
492
+
493
+
494
+
495
+
496
+
497
+
498
+
499
+
500
+
501
+
502
+
503
+
504
+
505
+
506
+
507
+
508
+
509
+
510
+
511
+
512
+
513
+
514
+
515
+
516
+
517
+
518
+
519
+
520
+
521
+
522
+
523
+
524
+
525
+
526
+
527
+
528
+
529
+
530
+
531
+
532
+
533
+
534
+
535
+
536
+
537
+
538
+ );
539
539
  }
540
540
  /**
541
541
  * Master dispatcher for textile and embroidery vector code generation.