@llc3233149/core 0.9.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 (457) hide show
  1. package/dist/canvaskit.d.ts +9 -0
  2. package/dist/canvaskit.d.ts.map +1 -0
  3. package/dist/canvaskit.js +55 -0
  4. package/dist/canvaskit.js.map +1 -0
  5. package/dist/clipboard.d.ts +32 -0
  6. package/dist/clipboard.d.ts.map +1 -0
  7. package/dist/clipboard.js +345 -0
  8. package/dist/clipboard.js.map +1 -0
  9. package/dist/color.d.ts +28 -0
  10. package/dist/color.d.ts.map +1 -0
  11. package/dist/color.js +67 -0
  12. package/dist/color.js.map +1 -0
  13. package/dist/constants.d.ts +159 -0
  14. package/dist/constants.d.ts.map +1 -0
  15. package/dist/constants.js +224 -0
  16. package/dist/constants.js.map +1 -0
  17. package/dist/copy.d.ts +20 -0
  18. package/dist/copy.d.ts.map +1 -0
  19. package/dist/copy.js +64 -0
  20. package/dist/copy.js.map +1 -0
  21. package/dist/fig-export-worker.d.ts +2 -0
  22. package/dist/fig-export-worker.d.ts.map +1 -0
  23. package/dist/fig-export-worker.js +17 -0
  24. package/dist/fig-export-worker.js.map +1 -0
  25. package/dist/fig-export.d.ts +13 -0
  26. package/dist/fig-export.d.ts.map +1 -0
  27. package/dist/fig-export.js +243 -0
  28. package/dist/fig-export.js.map +1 -0
  29. package/dist/figma-api.d.ts +268 -0
  30. package/dist/figma-api.d.ts.map +1 -0
  31. package/dist/figma-api.js +1074 -0
  32. package/dist/figma-api.js.map +1 -0
  33. package/dist/figma-rest-import.d.ts +122 -0
  34. package/dist/figma-rest-import.d.ts.map +1 -0
  35. package/dist/figma-rest-import.js +319 -0
  36. package/dist/figma-rest-import.js.map +1 -0
  37. package/dist/fonts.d.ts +24 -0
  38. package/dist/fonts.d.ts.map +1 -0
  39. package/dist/fonts.js +356 -0
  40. package/dist/fonts.js.map +1 -0
  41. package/dist/geometry.d.ts +14 -0
  42. package/dist/geometry.d.ts.map +1 -0
  43. package/dist/geometry.js +47 -0
  44. package/dist/geometry.js.map +1 -0
  45. package/dist/index.d.ts +38 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +32 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/kiwi/codec.d.ts +292 -0
  50. package/dist/kiwi/codec.d.ts.map +1 -0
  51. package/dist/kiwi/codec.js +340 -0
  52. package/dist/kiwi/codec.js.map +1 -0
  53. package/dist/kiwi/fig-file.d.ts +4 -0
  54. package/dist/kiwi/fig-file.d.ts.map +1 -0
  55. package/dist/kiwi/fig-file.js +236 -0
  56. package/dist/kiwi/fig-file.js.map +1 -0
  57. package/dist/kiwi/fig-import.d.ts +4 -0
  58. package/dist/kiwi/fig-import.d.ts.map +1 -0
  59. package/dist/kiwi/fig-import.js +248 -0
  60. package/dist/kiwi/fig-import.js.map +1 -0
  61. package/dist/kiwi/fig-parse-worker.d.ts +7 -0
  62. package/dist/kiwi/fig-parse-worker.d.ts.map +1 -0
  63. package/dist/kiwi/fig-parse-worker.js +184 -0
  64. package/dist/kiwi/fig-parse-worker.js.map +1 -0
  65. package/dist/kiwi/instance-overrides.d.ts +66 -0
  66. package/dist/kiwi/instance-overrides.d.ts.map +1 -0
  67. package/dist/kiwi/instance-overrides.js +644 -0
  68. package/dist/kiwi/instance-overrides.js.map +1 -0
  69. package/dist/kiwi/kiwi-convert.d.ts +19 -0
  70. package/dist/kiwi/kiwi-convert.d.ts.map +1 -0
  71. package/dist/kiwi/kiwi-convert.js +678 -0
  72. package/dist/kiwi/kiwi-convert.js.map +1 -0
  73. package/dist/kiwi/kiwi-schema/bb.d.ts +25 -0
  74. package/dist/kiwi/kiwi-schema/bb.d.ts.map +1 -0
  75. package/dist/kiwi/kiwi-schema/bb.js +225 -0
  76. package/dist/kiwi/kiwi-schema/bb.js.map +1 -0
  77. package/dist/kiwi/kiwi-schema/binary.d.ts +5 -0
  78. package/dist/kiwi/kiwi-schema/binary.d.ts.map +1 -0
  79. package/dist/kiwi/kiwi-schema/binary.js +86 -0
  80. package/dist/kiwi/kiwi-schema/binary.js.map +1 -0
  81. package/dist/kiwi/kiwi-schema/index.d.ts +6 -0
  82. package/dist/kiwi/kiwi-schema/index.d.ts.map +1 -0
  83. package/dist/kiwi/kiwi-schema/index.js +5 -0
  84. package/dist/kiwi/kiwi-schema/index.js.map +1 -0
  85. package/dist/kiwi/kiwi-schema/js.d.ts +4 -0
  86. package/dist/kiwi/kiwi-schema/js.d.ts.map +1 -0
  87. package/dist/kiwi/kiwi-schema/js.js +282 -0
  88. package/dist/kiwi/kiwi-schema/js.js.map +1 -0
  89. package/dist/kiwi/kiwi-schema/parser.d.ts +5 -0
  90. package/dist/kiwi/kiwi-schema/parser.d.ts.map +1 -0
  91. package/dist/kiwi/kiwi-schema/parser.js +228 -0
  92. package/dist/kiwi/kiwi-schema/parser.js.map +1 -0
  93. package/dist/kiwi/kiwi-schema/schema.d.ts +22 -0
  94. package/dist/kiwi/kiwi-schema/schema.d.ts.map +1 -0
  95. package/dist/kiwi/kiwi-schema/schema.js +2 -0
  96. package/dist/kiwi/kiwi-schema/schema.js.map +1 -0
  97. package/dist/kiwi/kiwi-schema/util.d.ts +3 -0
  98. package/dist/kiwi/kiwi-schema/util.d.ts.map +1 -0
  99. package/dist/kiwi/kiwi-schema/util.js +10 -0
  100. package/dist/kiwi/kiwi-schema/util.js.map +1 -0
  101. package/dist/kiwi/protocol.d.ts +172 -0
  102. package/dist/kiwi/protocol.d.ts.map +1 -0
  103. package/dist/kiwi/protocol.js +214 -0
  104. package/dist/kiwi/protocol.js.map +1 -0
  105. package/dist/kiwi/schema.d.ts +3 -0
  106. package/dist/kiwi/schema.d.ts.map +1 -0
  107. package/dist/kiwi/schema.js +2285 -0
  108. package/dist/kiwi/schema.js.map +1 -0
  109. package/dist/kiwi-serialize.d.ts +17 -0
  110. package/dist/kiwi-serialize.d.ts.map +1 -0
  111. package/dist/kiwi-serialize.js +419 -0
  112. package/dist/kiwi-serialize.js.map +1 -0
  113. package/dist/layout.d.ts +9 -0
  114. package/dist/layout.d.ts.map +1 -0
  115. package/dist/layout.js +533 -0
  116. package/dist/layout.js.map +1 -0
  117. package/dist/profiler/draw-call-counter.d.ts +9 -0
  118. package/dist/profiler/draw-call-counter.d.ts.map +1 -0
  119. package/dist/profiler/draw-call-counter.js +37 -0
  120. package/dist/profiler/draw-call-counter.js.map +1 -0
  121. package/dist/profiler/frame-capture.d.ts +34 -0
  122. package/dist/profiler/frame-capture.d.ts.map +1 -0
  123. package/dist/profiler/frame-capture.js +90 -0
  124. package/dist/profiler/frame-capture.js.map +1 -0
  125. package/dist/profiler/frame-stats.d.ts +33 -0
  126. package/dist/profiler/frame-stats.d.ts.map +1 -0
  127. package/dist/profiler/frame-stats.js +103 -0
  128. package/dist/profiler/frame-stats.js.map +1 -0
  129. package/dist/profiler/gpu-timer.d.ts +15 -0
  130. package/dist/profiler/gpu-timer.d.ts.map +1 -0
  131. package/dist/profiler/gpu-timer.js +77 -0
  132. package/dist/profiler/gpu-timer.js.map +1 -0
  133. package/dist/profiler/hud-renderer.d.ts +22 -0
  134. package/dist/profiler/hud-renderer.d.ts.map +1 -0
  135. package/dist/profiler/hud-renderer.js +200 -0
  136. package/dist/profiler/hud-renderer.js.map +1 -0
  137. package/dist/profiler/index.d.ts +9 -0
  138. package/dist/profiler/index.d.ts.map +1 -0
  139. package/dist/profiler/index.js +8 -0
  140. package/dist/profiler/index.js.map +1 -0
  141. package/dist/profiler/phase-timer.d.ts +9 -0
  142. package/dist/profiler/phase-timer.d.ts.map +1 -0
  143. package/dist/profiler/phase-timer.js +51 -0
  144. package/dist/profiler/phase-timer.js.map +1 -0
  145. package/dist/profiler/render-profiler.d.ts +41 -0
  146. package/dist/profiler/render-profiler.d.ts.map +1 -0
  147. package/dist/profiler/render-profiler.js +142 -0
  148. package/dist/profiler/render-profiler.js.map +1 -0
  149. package/dist/render/components.d.ts +25 -0
  150. package/dist/render/components.d.ts.map +1 -0
  151. package/dist/render/components.js +55 -0
  152. package/dist/render/components.js.map +1 -0
  153. package/dist/render/emoji-icons.d.ts +5 -0
  154. package/dist/render/emoji-icons.d.ts.map +1 -0
  155. package/dist/render/emoji-icons.js +55 -0
  156. package/dist/render/emoji-icons.js.map +1 -0
  157. package/dist/render/export-code.d.ts +9 -0
  158. package/dist/render/export-code.d.ts.map +1 -0
  159. package/dist/render/export-code.js +335 -0
  160. package/dist/render/export-code.js.map +1 -0
  161. package/dist/render/export-jsx.d.ts +5 -0
  162. package/dist/render/export-jsx.d.ts.map +1 -0
  163. package/dist/render/export-jsx.js +621 -0
  164. package/dist/render/export-jsx.js.map +1 -0
  165. package/dist/render/index.d.ts +8 -0
  166. package/dist/render/index.d.ts.map +1 -0
  167. package/dist/render/index.js +8 -0
  168. package/dist/render/index.js.map +1 -0
  169. package/dist/render/jsx-runtime.d.ts +31 -0
  170. package/dist/render/jsx-runtime.d.ts.map +1 -0
  171. package/dist/render/jsx-runtime.js +13 -0
  172. package/dist/render/jsx-runtime.js.map +1 -0
  173. package/dist/render/mini-react.d.ts +14 -0
  174. package/dist/render/mini-react.d.ts.map +1 -0
  175. package/dist/render/mini-react.js +16 -0
  176. package/dist/render/mini-react.js.map +1 -0
  177. package/dist/render/render-jsx.d.ts +24 -0
  178. package/dist/render/render-jsx.d.ts.map +1 -0
  179. package/dist/render/render-jsx.js +51 -0
  180. package/dist/render/render-jsx.js.map +1 -0
  181. package/dist/render/renderer.d.ts +16 -0
  182. package/dist/render/renderer.d.ts.map +1 -0
  183. package/dist/render/renderer.js +437 -0
  184. package/dist/render/renderer.js.map +1 -0
  185. package/dist/render/tailwind.d.ts +20 -0
  186. package/dist/render/tailwind.d.ts.map +1 -0
  187. package/dist/render/tailwind.js +115 -0
  188. package/dist/render/tailwind.js.map +1 -0
  189. package/dist/render/tree.d.ts +72 -0
  190. package/dist/render/tree.d.ts.map +1 -0
  191. package/dist/render/tree.js +63 -0
  192. package/dist/render/tree.js.map +1 -0
  193. package/dist/render-image.d.ts +19 -0
  194. package/dist/render-image.d.ts.map +1 -0
  195. package/dist/render-image.js +84 -0
  196. package/dist/render-image.js.map +1 -0
  197. package/dist/renderer/effects.d.ts +9 -0
  198. package/dist/renderer/effects.d.ts.map +1 -0
  199. package/dist/renderer/effects.js +44 -0
  200. package/dist/renderer/effects.js.map +1 -0
  201. package/dist/renderer/fills.d.ts +9 -0
  202. package/dist/renderer/fills.d.ts.map +1 -0
  203. package/dist/renderer/fills.js +189 -0
  204. package/dist/renderer/fills.js.map +1 -0
  205. package/dist/renderer/index.d.ts +2 -0
  206. package/dist/renderer/index.d.ts.map +1 -0
  207. package/dist/renderer/index.js +2 -0
  208. package/dist/renderer/index.js.map +1 -0
  209. package/dist/renderer/label-cache.d.ts +43 -0
  210. package/dist/renderer/label-cache.d.ts.map +1 -0
  211. package/dist/renderer/label-cache.js +85 -0
  212. package/dist/renderer/label-cache.js.map +1 -0
  213. package/dist/renderer/labels.d.ts +6 -0
  214. package/dist/renderer/labels.d.ts.map +1 -0
  215. package/dist/renderer/labels.js +126 -0
  216. package/dist/renderer/labels.js.map +1 -0
  217. package/dist/renderer/lru-cache.d.ts +20 -0
  218. package/dist/renderer/lru-cache.d.ts.map +1 -0
  219. package/dist/renderer/lru-cache.js +65 -0
  220. package/dist/renderer/lru-cache.js.map +1 -0
  221. package/dist/renderer/overlays.d.ts +25 -0
  222. package/dist/renderer/overlays.d.ts.map +1 -0
  223. package/dist/renderer/overlays.js +783 -0
  224. package/dist/renderer/overlays.js.map +1 -0
  225. package/dist/renderer/renderer.d.ts +229 -0
  226. package/dist/renderer/renderer.d.ts.map +1 -0
  227. package/dist/renderer/renderer.js +909 -0
  228. package/dist/renderer/renderer.js.map +1 -0
  229. package/dist/renderer/rulers.d.ts +8 -0
  230. package/dist/renderer/rulers.d.ts.map +1 -0
  231. package/dist/renderer/rulers.js +147 -0
  232. package/dist/renderer/rulers.js.map +1 -0
  233. package/dist/renderer/scene.d.ts +11 -0
  234. package/dist/renderer/scene.d.ts.map +1 -0
  235. package/dist/renderer/scene.js +392 -0
  236. package/dist/renderer/scene.js.map +1 -0
  237. package/dist/renderer/shapes.d.ts +13 -0
  238. package/dist/renderer/shapes.d.ts.map +1 -0
  239. package/dist/renderer/shapes.js +160 -0
  240. package/dist/renderer/shapes.js.map +1 -0
  241. package/dist/renderer/strokes.d.ts +9 -0
  242. package/dist/renderer/strokes.d.ts.map +1 -0
  243. package/dist/renderer/strokes.js +180 -0
  244. package/dist/renderer/strokes.js.map +1 -0
  245. package/dist/rpc/commands.d.ts +202 -0
  246. package/dist/rpc/commands.d.ts.map +1 -0
  247. package/dist/rpc/commands.js +429 -0
  248. package/dist/rpc/commands.js.map +1 -0
  249. package/dist/rpc/index.d.ts +3 -0
  250. package/dist/rpc/index.d.ts.map +1 -0
  251. package/dist/rpc/index.js +2 -0
  252. package/dist/rpc/index.js.map +1 -0
  253. package/dist/scene-graph.d.ts +318 -0
  254. package/dist/scene-graph.d.ts.map +1 -0
  255. package/dist/scene-graph.js +803 -0
  256. package/dist/scene-graph.js.map +1 -0
  257. package/dist/snap.d.ts +16 -0
  258. package/dist/snap.d.ts.map +1 -0
  259. package/dist/snap.js +97 -0
  260. package/dist/snap.js.map +1 -0
  261. package/dist/style-runs.d.ts +20 -0
  262. package/dist/style-runs.d.ts.map +1 -0
  263. package/dist/style-runs.js +168 -0
  264. package/dist/style-runs.js.map +1 -0
  265. package/dist/svg-export/defs.d.ts +19 -0
  266. package/dist/svg-export/defs.d.ts.map +1 -0
  267. package/dist/svg-export/defs.js +191 -0
  268. package/dist/svg-export/defs.js.map +1 -0
  269. package/dist/svg-export/index.d.ts +8 -0
  270. package/dist/svg-export/index.d.ts.map +1 -0
  271. package/dist/svg-export/index.js +318 -0
  272. package/dist/svg-export/index.js.map +1 -0
  273. package/dist/svg-export/paths.d.ts +9 -0
  274. package/dist/svg-export/paths.d.ts.map +1 -0
  275. package/dist/svg-export/paths.js +189 -0
  276. package/dist/svg-export/paths.js.map +1 -0
  277. package/dist/svg-node.d.ts +8 -0
  278. package/dist/svg-node.d.ts.map +1 -0
  279. package/dist/svg-node.js +48 -0
  280. package/dist/svg-node.js.map +1 -0
  281. package/dist/text-editor.d.ts +57 -0
  282. package/dist/text-editor.d.ts.map +1 -0
  283. package/dist/text-editor.js +337 -0
  284. package/dist/text-editor.js.map +1 -0
  285. package/dist/tools/ai-adapter.d.ts +22 -0
  286. package/dist/tools/ai-adapter.d.ts.map +1 -0
  287. package/dist/tools/ai-adapter.js +121 -0
  288. package/dist/tools/ai-adapter.js.map +1 -0
  289. package/dist/tools/analyze.d.ts +22 -0
  290. package/dist/tools/analyze.d.ts.map +1 -0
  291. package/dist/tools/analyze.js +677 -0
  292. package/dist/tools/analyze.js.map +1 -0
  293. package/dist/tools/create.d.ts +8 -0
  294. package/dist/tools/create.d.ts.map +1 -0
  295. package/dist/tools/create.js +204 -0
  296. package/dist/tools/create.js.map +1 -0
  297. package/dist/tools/describe.d.ts +9 -0
  298. package/dist/tools/describe.d.ts.map +1 -0
  299. package/dist/tools/describe.js +295 -0
  300. package/dist/tools/describe.js.map +1 -0
  301. package/dist/tools/export-code.d.ts +2 -0
  302. package/dist/tools/export-code.d.ts.map +1 -0
  303. package/dist/tools/export-code.js +34 -0
  304. package/dist/tools/export-code.js.map +1 -0
  305. package/dist/tools/export-tailwind-config.d.ts +27 -0
  306. package/dist/tools/export-tailwind-config.d.ts.map +1 -0
  307. package/dist/tools/export-tailwind-config.js +215 -0
  308. package/dist/tools/export-tailwind-config.js.map +1 -0
  309. package/dist/tools/icons.d.ts +5 -0
  310. package/dist/tools/icons.d.ts.map +1 -0
  311. package/dist/tools/icons.js +192 -0
  312. package/dist/tools/icons.js.map +1 -0
  313. package/dist/tools/index.d.ts +7 -0
  314. package/dist/tools/index.d.ts.map +1 -0
  315. package/dist/tools/index.js +6 -0
  316. package/dist/tools/index.js.map +1 -0
  317. package/dist/tools/modify.d.ts +22 -0
  318. package/dist/tools/modify.d.ts.map +1 -0
  319. package/dist/tools/modify.js +653 -0
  320. package/dist/tools/modify.js.map +1 -0
  321. package/dist/tools/patterns.d.ts +2 -0
  322. package/dist/tools/patterns.d.ts.map +1 -0
  323. package/dist/tools/patterns.js +173 -0
  324. package/dist/tools/patterns.js.map +1 -0
  325. package/dist/tools/read.d.ts +17 -0
  326. package/dist/tools/read.d.ts.map +1 -0
  327. package/dist/tools/read.js +379 -0
  328. package/dist/tools/read.js.map +1 -0
  329. package/dist/tools/registry.d.ts +3 -0
  330. package/dist/tools/registry.d.ts.map +1 -0
  331. package/dist/tools/registry.js +124 -0
  332. package/dist/tools/registry.js.map +1 -0
  333. package/dist/tools/schema.d.ts +46 -0
  334. package/dist/tools/schema.d.ts.map +1 -0
  335. package/dist/tools/schema.js +17 -0
  336. package/dist/tools/schema.js.map +1 -0
  337. package/dist/tools/structure.d.ts +18 -0
  338. package/dist/tools/structure.d.ts.map +1 -0
  339. package/dist/tools/structure.js +345 -0
  340. package/dist/tools/structure.js.map +1 -0
  341. package/dist/tools/variables.d.ts +12 -0
  342. package/dist/tools/variables.d.ts.map +1 -0
  343. package/dist/tools/variables.js +190 -0
  344. package/dist/tools/variables.js.map +1 -0
  345. package/dist/tools/vector.d.ts +15 -0
  346. package/dist/tools/vector.d.ts.map +1 -0
  347. package/dist/tools/vector.js +312 -0
  348. package/dist/tools/vector.js.map +1 -0
  349. package/dist/types.d.ts +29 -0
  350. package/dist/types.d.ts.map +1 -0
  351. package/dist/types.js +2 -0
  352. package/dist/types.js.map +1 -0
  353. package/dist/undo.d.ts +33 -0
  354. package/dist/undo.d.ts.map +1 -0
  355. package/dist/undo.js +98 -0
  356. package/dist/undo.js.map +1 -0
  357. package/dist/vector.d.ts +14 -0
  358. package/dist/vector.d.ts.map +1 -0
  359. package/dist/vector.js +334 -0
  360. package/dist/vector.js.map +1 -0
  361. package/dist/xpath.d.ts +8 -0
  362. package/dist/xpath.d.ts.map +1 -0
  363. package/dist/xpath.js +199 -0
  364. package/dist/xpath.js.map +1 -0
  365. package/package.json +54 -0
  366. package/src/canvaskit.ts +66 -0
  367. package/src/clipboard.ts +444 -0
  368. package/src/color.ts +83 -0
  369. package/src/constants.ts +277 -0
  370. package/src/copy.ts +75 -0
  371. package/src/fig-export-worker.ts +28 -0
  372. package/src/fig-export.ts +321 -0
  373. package/src/figma-api.ts +1297 -0
  374. package/src/figma-rest-import.ts +443 -0
  375. package/src/fonts.ts +369 -0
  376. package/src/geometry.ts +73 -0
  377. package/src/global.d.ts +20 -0
  378. package/src/index.ts +247 -0
  379. package/src/kiwi/codec.ts +614 -0
  380. package/src/kiwi/fig-file.ts +248 -0
  381. package/src/kiwi/fig-import.ts +300 -0
  382. package/src/kiwi/fig-parse-worker.ts +213 -0
  383. package/src/kiwi/instance-overrides.ts +682 -0
  384. package/src/kiwi/kiwi-convert.ts +771 -0
  385. package/src/kiwi/kiwi-schema/bb.ts +244 -0
  386. package/src/kiwi/kiwi-schema/binary.ts +102 -0
  387. package/src/kiwi/kiwi-schema/index.ts +5 -0
  388. package/src/kiwi/kiwi-schema/js.ts +339 -0
  389. package/src/kiwi/kiwi-schema/parser.ts +287 -0
  390. package/src/kiwi/kiwi-schema/schema.ts +24 -0
  391. package/src/kiwi/kiwi-schema/util.ts +10 -0
  392. package/src/kiwi/protocol.ts +237 -0
  393. package/src/kiwi/schema.ts +2286 -0
  394. package/src/kiwi-serialize.ts +467 -0
  395. package/src/layout.ts +608 -0
  396. package/src/profiler/draw-call-counter.ts +43 -0
  397. package/src/profiler/frame-capture.ts +139 -0
  398. package/src/profiler/frame-stats.ts +122 -0
  399. package/src/profiler/gpu-timer.ts +93 -0
  400. package/src/profiler/hud-renderer.ts +242 -0
  401. package/src/profiler/index.ts +8 -0
  402. package/src/profiler/phase-timer.ts +62 -0
  403. package/src/profiler/render-profiler.ts +163 -0
  404. package/src/render/components.ts +69 -0
  405. package/src/render/emoji-icons.ts +60 -0
  406. package/src/render/export-code.ts +366 -0
  407. package/src/render/export-jsx.ts +633 -0
  408. package/src/render/index.ts +38 -0
  409. package/src/render/jsx-runtime.ts +36 -0
  410. package/src/render/mini-react.ts +30 -0
  411. package/src/render/render-jsx.ts +74 -0
  412. package/src/render/renderer.ts +508 -0
  413. package/src/render/tailwind.ts +114 -0
  414. package/src/render/tree.ts +137 -0
  415. package/src/render-image.ts +139 -0
  416. package/src/renderer/effects.ts +64 -0
  417. package/src/renderer/fills.ts +248 -0
  418. package/src/renderer/index.ts +1 -0
  419. package/src/renderer/label-cache.ts +114 -0
  420. package/src/renderer/labels.ts +168 -0
  421. package/src/renderer/lru-cache.ts +71 -0
  422. package/src/renderer/overlays.ts +1089 -0
  423. package/src/renderer/renderer.ts +1226 -0
  424. package/src/renderer/rulers.ts +230 -0
  425. package/src/renderer/scene.ts +554 -0
  426. package/src/renderer/shapes.ts +193 -0
  427. package/src/renderer/strokes.ts +221 -0
  428. package/src/rpc/commands.ts +667 -0
  429. package/src/rpc/index.ts +25 -0
  430. package/src/scene-graph.ts +1254 -0
  431. package/src/snap.ts +122 -0
  432. package/src/style-runs.ts +234 -0
  433. package/src/svg-export/defs.ts +255 -0
  434. package/src/svg-export/index.ts +427 -0
  435. package/src/svg-export/paths.ts +212 -0
  436. package/src/svg-node.ts +62 -0
  437. package/src/text-editor.ts +349 -0
  438. package/src/tools/ai-adapter.ts +144 -0
  439. package/src/tools/analyze.ts +786 -0
  440. package/src/tools/create.ts +206 -0
  441. package/src/tools/describe.ts +280 -0
  442. package/src/tools/export-code.ts +41 -0
  443. package/src/tools/export-tailwind-config.ts +266 -0
  444. package/src/tools/icons.ts +213 -0
  445. package/src/tools/index.ts +6 -0
  446. package/src/tools/modify.ts +651 -0
  447. package/src/tools/patterns.ts +189 -0
  448. package/src/tools/read.ts +401 -0
  449. package/src/tools/registry.ts +155 -0
  450. package/src/tools/schema.ts +65 -0
  451. package/src/tools/structure.ts +348 -0
  452. package/src/tools/variables.ts +193 -0
  453. package/src/tools/vector.ts +311 -0
  454. package/src/types.ts +32 -0
  455. package/src/undo.ts +126 -0
  456. package/src/vector.ts +413 -0
  457. package/src/xpath.ts +259 -0
@@ -0,0 +1,614 @@
1
+ /**
2
+ * Message Encoding/Decoding for Figma Multiplayer
3
+ *
4
+ * Uses:
5
+ * - kiwi-schema: Binary serialization (by Evan Wallace, Figma co-founder)
6
+ * - fzstd: Browser-compatible Zstd decompression
7
+ */
8
+
9
+ import { decompress as zstdDecompress } from 'fzstd'
10
+
11
+ import { parseColor } from '../color'
12
+ import { compileSchema, encodeBinarySchema } from './kiwi-schema'
13
+ import { isZstdCompressed, getKiwiMessageType } from './protocol'
14
+ import figmaSchema from './schema'
15
+
16
+ interface CompiledSchema {
17
+ encodeMessage(message: unknown): Uint8Array
18
+ decodeMessage(data: Uint8Array): unknown
19
+ encodePaint(paint: unknown): Uint8Array
20
+ encodeNodeChange(nodeChange: unknown): Uint8Array
21
+ }
22
+
23
+ let compiledSchema: CompiledSchema | null = null
24
+
25
+ /**
26
+ * Initialize the codec (compiles Kiwi schema)
27
+ */
28
+ export async function initCodec(): Promise<void> {
29
+ if (compiledSchema) return
30
+ compiledSchema = compileSchema(figmaSchema) as CompiledSchema
31
+ }
32
+
33
+ export function getCompiledSchema() {
34
+ if (!compiledSchema) throw new Error('Codec not initialized')
35
+ return compiledSchema
36
+ }
37
+
38
+ export function getSchemaBytes(): Uint8Array {
39
+ return encodeBinarySchema(figmaSchema)
40
+ }
41
+
42
+ /**
43
+ * Check if codec is initialized
44
+ */
45
+ export function isCodecReady(): boolean {
46
+ return compiledSchema !== null
47
+ }
48
+
49
+ /**
50
+ * Compress data using Zstd (Bun native)
51
+ */
52
+ export function compress(data: Uint8Array): Uint8Array {
53
+ return data
54
+ }
55
+
56
+ /**
57
+ * Decompress Zstd data (Bun native)
58
+ */
59
+ export function decompress(data: Uint8Array): Uint8Array {
60
+ if (!isZstdCompressed(data)) return data
61
+ return zstdDecompress(data)
62
+ }
63
+
64
+ /**
65
+ * Encode a message for sending to Figma
66
+ * Handles variable bindings in fillPaints which require custom encoding
67
+ */
68
+ export function encodeMessage(message: FigmaMessage): Uint8Array {
69
+ if (!compiledSchema) {
70
+ throw new Error('Codec not initialized. Call initCodec() first.')
71
+ }
72
+
73
+ // Check if any nodeChange has variable bindings (fill or stroke)
74
+ const hasVariables = message.nodeChanges?.some(
75
+ (nc) =>
76
+ nc.fillPaints?.some((p) => p.colorVariableBinding) ||
77
+ nc.strokePaints?.some((p) => p.colorVariableBinding)
78
+ )
79
+
80
+ if (!hasVariables) {
81
+ // Standard encoding
82
+ const encoded = compiledSchema.encodeMessage(message)
83
+ return compress(encoded)
84
+ }
85
+
86
+ // Need custom encoding for variable bindings
87
+ // Strategy: encode each nodeChange separately, then combine
88
+ const messageWithoutNodes = { ...message, nodeChanges: [] }
89
+ const baseEncoded = compiledSchema.encodeMessage(messageWithoutNodes)
90
+ const baseHex = Buffer.from(baseEncoded).toString('hex')
91
+
92
+ // Encode nodeChanges with variable support
93
+ const nodeChangeBytes: Uint8Array[] = []
94
+ for (const nc of message.nodeChanges || []) {
95
+ const encoded = encodeNodeChangeWithVariables(nc)
96
+ nodeChangeBytes.push(encoded)
97
+ }
98
+
99
+ // Combine: base message + nodeChanges
100
+ // Message structure: type, sessionID, ackID, reconnectSeqNum, nodeChanges[]
101
+ // nodeChanges is field 5
102
+
103
+ // Message structure in kiwi:
104
+ // - Field 1 (type): enum MessageType
105
+ // - Field 2 (sessionID): uint
106
+ // - Field 3 (ackID): uint
107
+ // - Field 4 (nodeChanges): NodeChange[] - this is what we need to replace
108
+ // - Field 25 (reconnectSequenceNumber): uint
109
+ //
110
+ // Empty array: "04 00" (field 4, length 0)
111
+ // We need to replace "04 00" with "04 <count> <nodes>"
112
+
113
+ const emptyArrayPattern = '0400' // field 4, length 0
114
+ const emptyArrayIdx = baseHex.indexOf(emptyArrayPattern)
115
+
116
+ if (emptyArrayIdx === -1) {
117
+ // Fallback to standard encoding
118
+ const encoded = compiledSchema.encodeMessage(message)
119
+ return compress(encoded)
120
+ }
121
+
122
+ // Build nodeChanges array with our encoded nodes
123
+ const ncBytes: number[] = [0x04] // field 4
124
+ ncBytes.push(...encodeVarint(nodeChangeBytes.length)) // array length
125
+ for (const ncArr of nodeChangeBytes) {
126
+ ncBytes.push(...Array.from(ncArr))
127
+ }
128
+
129
+ // Replace "0400" with our nodeChanges
130
+ const beforeArray = baseHex.slice(0, emptyArrayIdx)
131
+ const afterArray = baseHex.slice(emptyArrayIdx + 4) // skip "0400"
132
+
133
+ const ncHex = Buffer.from(ncBytes).toString('hex')
134
+ const finalHex = beforeArray + ncHex + afterArray
135
+
136
+ const finalBytes = new Uint8Array(finalHex.match(/.{2}/g)?.map((b) => parseInt(b, 16)) ?? [])
137
+ return compress(finalBytes)
138
+ }
139
+
140
+ /**
141
+ * Decode a message received from Figma
142
+ */
143
+ export function decodeMessage(data: Uint8Array): FigmaMessage {
144
+ if (!compiledSchema) {
145
+ throw new Error('Codec not initialized. Call initCodec() first.')
146
+ }
147
+
148
+ const decompressed = decompress(data)
149
+ return compiledSchema.decodeMessage(decompressed) as FigmaMessage
150
+ }
151
+
152
+ /**
153
+ * Quick peek at message type without full decoding
154
+ */
155
+ export function peekMessageType(data: Uint8Array): number | null {
156
+ try {
157
+ const decompressed = decompress(data)
158
+ return getKiwiMessageType(decompressed)
159
+ } catch {
160
+ return null
161
+ }
162
+ }
163
+
164
+ // Type definitions
165
+
166
+ export type { GUID, Color } from '../types'
167
+
168
+ import type { Color, GUID, Matrix, Vector } from '../types'
169
+
170
+ export type { Matrix, Vector }
171
+
172
+ export interface ParentIndex {
173
+ guid: GUID
174
+ position: string
175
+ }
176
+
177
+ export interface VariableBinding {
178
+ variableID: GUID
179
+ }
180
+
181
+ export interface Paint {
182
+ type:
183
+ | 'SOLID'
184
+ | 'GRADIENT_LINEAR'
185
+ | 'GRADIENT_RADIAL'
186
+ | 'GRADIENT_ANGULAR'
187
+ | 'GRADIENT_DIAMOND'
188
+ | 'IMAGE'
189
+ color?: Color
190
+ opacity?: number
191
+ visible?: boolean
192
+ blendMode?: string
193
+ stops?: { color: Color; position: number }[]
194
+ transform?: Matrix
195
+ image?: { hash: string }
196
+ imageScaleMode?: string
197
+ colorVariableBinding?: VariableBinding
198
+ }
199
+
200
+ export interface Effect {
201
+ type: 'DROP_SHADOW' | 'INNER_SHADOW' | 'LAYER_BLUR' | 'BACKGROUND_BLUR' | 'FOREGROUND_BLUR'
202
+ color?: Color
203
+ offset?: Vector
204
+ radius?: number
205
+ visible?: boolean
206
+ spread?: number
207
+ blendMode?: string
208
+ }
209
+
210
+ export interface VariableAnyValue {
211
+ boolValue?: boolean
212
+ textValue?: string
213
+ floatValue?: number
214
+ colorValue?: Color
215
+ alias?: { guid: GUID }
216
+ }
217
+
218
+ export interface VariableDataEntry {
219
+ value?: VariableAnyValue
220
+ dataType?: string
221
+ resolvedDataType?: string
222
+ }
223
+
224
+ export interface VariableConsumptionEntry {
225
+ nodeField?: number
226
+ variableData?: VariableDataEntry
227
+ variableField?: string
228
+ }
229
+
230
+ export interface VariableDataValuesEntry {
231
+ modeID: GUID
232
+ variableData: VariableDataEntry
233
+ }
234
+
235
+ export interface NodeChange {
236
+ [key: string]: unknown
237
+ guid?: GUID
238
+ phase?: 'CREATED' | 'REMOVED'
239
+ parentIndex?: ParentIndex
240
+ type?: string
241
+ name?: string
242
+ visible?: boolean
243
+ locked?: boolean
244
+ opacity?: number
245
+ blendMode?: string
246
+ size?: Vector
247
+ transform?: Matrix
248
+ cornerRadius?: number
249
+ fillPaints?: Paint[]
250
+ strokePaints?: Paint[]
251
+ strokeWeight?: number
252
+ strokeAlign?: string
253
+ strokeCap?: string
254
+ strokeJoin?: string
255
+ dashPattern?: number[]
256
+ effects?: Effect[]
257
+ // Layout
258
+ stackMode?: 'NONE' | 'HORIZONTAL' | 'VERTICAL'
259
+ stackSpacing?: number
260
+ stackPadding?: number
261
+ stackPaddingRight?: number
262
+ stackPaddingBottom?: number
263
+ stackCounterAlign?: string
264
+ stackJustify?: string
265
+ stackCounterAlignItems?: string
266
+ stackPrimaryAlignItems?: string
267
+ stackPrimarySizing?: 'FIXED' | 'RESIZE_TO_FIT' | 'RESIZE_TO_FIT_WITH_IMPLICIT_SIZE'
268
+ stackCounterSizing?: 'FIXED' | 'RESIZE_TO_FIT' | 'RESIZE_TO_FIT_WITH_IMPLICIT_SIZE'
269
+ stackVerticalPadding?: number
270
+ stackHorizontalPadding?: number
271
+ stackWrap?: string
272
+ stackPositioning?: string
273
+ stackChildPrimaryGrow?: number
274
+ stackChildAlignSelf?: string
275
+ stackCounterSpacing?: number
276
+ // Frame
277
+ clipsContent?: boolean
278
+ frameMaskDisabled?: boolean
279
+ // Vector
280
+ vectorData?: unknown
281
+ fillGeometry?: Array<{ windingRule?: string; commandsBlob?: number }>
282
+ strokeGeometry?: Array<{ windingRule?: string; commandsBlob?: number }>
283
+ // Text
284
+ fontSize?: number
285
+ fontWeight?: number
286
+ fontName?: { family: string; style: string; postscript?: string }
287
+ textAlignHorizontal?: string
288
+ textAlignVertical?: string
289
+ textAutoResize?: string
290
+ textData?: {
291
+ characters: string
292
+ lines?: Array<{ lineType?: string; styleId?: number; indentationLevel?: number }>
293
+ characterStyleIDs?: number[]
294
+ styleOverrideTable?: NodeChange[]
295
+ }
296
+ derivedTextData?: {
297
+ layoutSize?: Vector
298
+ fontMetaData?: Array<{
299
+ key: { family: string; style: string; postscript?: string }
300
+ fontLineHeight: number
301
+ fontDigest?: Uint8Array | Record<string, number>
302
+ fontStyle?: string
303
+ fontWeight?: number
304
+ }>
305
+ truncationStartIndex?: number
306
+ truncatedHeight?: number
307
+ }
308
+ textUserLayoutVersion?: number
309
+ textDecoration?: string
310
+ lineHeight?: { value: number; units: string }
311
+ letterSpacing?: { value: number; units: string }
312
+ // Symbol/Instance
313
+ symbolData?: { symbolID: GUID }
314
+ // ComponentSet
315
+ isStateGroup?: boolean
316
+ stateGroupPropertyValueOrders?: Array<{ property: string; values: string[] }>
317
+ // Internal
318
+ internalOnly?: boolean
319
+ // Corners
320
+ rectangleTopLeftCornerRadius?: number
321
+ rectangleTopRightCornerRadius?: number
322
+ rectangleBottomLeftCornerRadius?: number
323
+ rectangleBottomRightCornerRadius?: number
324
+ rectangleCornerRadiiIndependent?: boolean
325
+ cornerSmoothing?: number
326
+ // Constraints
327
+ horizontalConstraint?: string
328
+ verticalConstraint?: string
329
+ // Variables
330
+ variableData?: VariableDataEntry
331
+ variableConsumptionMap?: { entries?: VariableConsumptionEntry[] }
332
+ variableSetModes?: Array<{ id: GUID; name: string; sortPosition?: string }>
333
+ variableSetID?: { guid: GUID }
334
+ variableResolvedType?: string
335
+ variableDataValues?: { entries?: VariableDataValuesEntry[] }
336
+ variableScopes?: string[]
337
+ }
338
+
339
+ export interface FigmaMessage {
340
+ type: string
341
+ sessionID?: number
342
+ ackID?: number
343
+ reconnectSequenceNumber?: number
344
+ nodeChanges?: NodeChange[]
345
+ blobs?: Array<{ bytes: Uint8Array }>
346
+ }
347
+
348
+ /**
349
+ * Create a NODE_CHANGES message
350
+ */
351
+ export function createNodeChangesMessage(
352
+ sessionID: number,
353
+ reconnectSequenceNumber: number,
354
+ nodeChanges: NodeChange[],
355
+ ackID = 1
356
+ ): FigmaMessage {
357
+ return {
358
+ type: 'NODE_CHANGES',
359
+ sessionID,
360
+ ackID,
361
+ reconnectSequenceNumber,
362
+ nodeChanges
363
+ }
364
+ }
365
+
366
+ /**
367
+ * Create a node change for a new shape
368
+ */
369
+ export function createNodeChange(opts: {
370
+ sessionID: number
371
+ localID: number
372
+ parentSessionID: number
373
+ parentLocalID: number
374
+ position?: string
375
+ type: string
376
+ name: string
377
+ x: number
378
+ y: number
379
+ width: number
380
+ height: number
381
+ fill?: Color | string
382
+ stroke?: Color | string
383
+ strokeWeight?: number
384
+ cornerRadius?: number
385
+ opacity?: number
386
+ }): NodeChange {
387
+ const change: NodeChange = {
388
+ guid: { sessionID: opts.sessionID, localID: opts.localID },
389
+ phase: 'CREATED',
390
+ parentIndex: {
391
+ guid: { sessionID: opts.parentSessionID, localID: opts.parentLocalID },
392
+ position: opts.position || '!'
393
+ },
394
+ type: opts.type,
395
+ name: opts.name,
396
+ visible: true,
397
+ opacity: opts.opacity ?? 1.0,
398
+ size: { x: opts.width, y: opts.height },
399
+ transform: {
400
+ m00: 1,
401
+ m01: 0,
402
+ m02: opts.x,
403
+ m10: 0,
404
+ m11: 1,
405
+ m12: opts.y
406
+ }
407
+ }
408
+
409
+ if (opts.fill) {
410
+ const color = typeof opts.fill === 'string' ? parseColor(opts.fill) : opts.fill
411
+ change.fillPaints = [
412
+ {
413
+ type: 'SOLID',
414
+ color,
415
+ opacity: 1.0,
416
+ visible: true,
417
+ blendMode: 'NORMAL'
418
+ }
419
+ ]
420
+ }
421
+
422
+ if (opts.stroke) {
423
+ const color = typeof opts.stroke === 'string' ? parseColor(opts.stroke) : opts.stroke
424
+ change.strokePaints = [
425
+ {
426
+ type: 'SOLID',
427
+ color,
428
+ opacity: 1.0,
429
+ visible: true,
430
+ blendMode: 'NORMAL'
431
+ }
432
+ ]
433
+ change.strokeWeight = opts.strokeWeight ?? 1
434
+ }
435
+
436
+ if (opts.cornerRadius !== undefined) {
437
+ change.cornerRadius = opts.cornerRadius
438
+ }
439
+
440
+ return change
441
+ }
442
+
443
+ /**
444
+ * Encode a varint (variable-length integer)
445
+ */
446
+ function encodeVarint(value: number): number[] {
447
+ const bytes: number[] = []
448
+ while (value > 0x7f) {
449
+ bytes.push((value & 0x7f) | 0x80)
450
+ value >>>= 7
451
+ }
452
+ bytes.push(value)
453
+ return bytes
454
+ }
455
+
456
+ /**
457
+ * Encode a Paint with optional variable binding
458
+ *
459
+ * Figma's variable binding format (discovered via WS traffic analysis):
460
+ * - Field 21 = 1 (binding type)
461
+ * - Field 4 = 1 (flag)
462
+ * - Raw sessionID varint (no field number)
463
+ * - Raw localID varint (no field number)
464
+ * - Terminators: 00 00 02 03 03 04 00 00
465
+ */
466
+ export function encodePaintWithVariableBinding(
467
+ paint: Paint,
468
+ variableSessionID: number,
469
+ variableLocalID: number
470
+ ): Uint8Array {
471
+ if (!compiledSchema) {
472
+ throw new Error('Codec not initialized. Call initCodec() first.')
473
+ }
474
+
475
+ const { colorVariableBinding: _, ...basePaint } = paint
476
+
477
+ const baseBytes = compiledSchema.encodePaint(basePaint)
478
+ const baseArray = Array.from(baseBytes)
479
+
480
+ // Remove trailing 00
481
+ if (baseArray[baseArray.length - 1] === 0) {
482
+ baseArray.pop()
483
+ }
484
+
485
+ // Add variable binding in Figma's exact format:
486
+ // Field 21 (0x15) = 1 (binding type)
487
+ baseArray.push(0x15, 0x01)
488
+ // Field 4 = 1 (flag)
489
+ baseArray.push(0x04, 0x01)
490
+ // Raw varints: sessionID, localID (no field numbers!)
491
+ baseArray.push(...encodeVarint(variableSessionID))
492
+ baseArray.push(...encodeVarint(variableLocalID))
493
+ // Terminators observed in Figma traffic
494
+ baseArray.push(0x00, 0x00, 0x02, 0x03, 0x03, 0x04)
495
+ // Final terminators
496
+ baseArray.push(0x00, 0x00)
497
+
498
+ return new Uint8Array(baseArray)
499
+ }
500
+
501
+ /**
502
+ * Parse a variable ID string (e.g., "VariableID:38448:122296")
503
+ * Returns sessionID and localID
504
+ */
505
+ export function parseVariableId(variableId: string): GUID | null {
506
+ const match = variableId.match(/VariableID:(\d+):(\d+)/)
507
+ if (!match) return null
508
+ return {
509
+ sessionID: parseInt(match[1] ?? '0', 10),
510
+ localID: parseInt(match[2] ?? '0', 10)
511
+ }
512
+ }
513
+
514
+ /**
515
+ * Encode a NodeChange with variable bindings in fillPaints and/or strokePaints
516
+ * This is needed because kiwi-schema cannot produce Figma's exact variable binding format
517
+ */
518
+ export function encodeNodeChangeWithVariables(nodeChange: NodeChange): Uint8Array {
519
+ if (!compiledSchema) {
520
+ throw new Error('Codec not initialized. Call initCodec() first.')
521
+ }
522
+
523
+ const hasFillBinding = nodeChange.fillPaints?.some((p) => p.colorVariableBinding)
524
+ const hasStrokeBinding = nodeChange.strokePaints?.some((p) => p.colorVariableBinding)
525
+
526
+ if (!hasFillBinding && !hasStrokeBinding) {
527
+ return compiledSchema.encodeNodeChange(nodeChange)
528
+ }
529
+
530
+ // Create a copy without variable bindings for base encoding
531
+ const cleanNodeChange = { ...nodeChange }
532
+ if (cleanNodeChange.fillPaints) {
533
+ cleanNodeChange.fillPaints = cleanNodeChange.fillPaints.map(
534
+ ({ colorVariableBinding: _, ...rest }) => rest
535
+ )
536
+ }
537
+ if (cleanNodeChange.strokePaints) {
538
+ cleanNodeChange.strokePaints = cleanNodeChange.strokePaints.map(
539
+ ({ colorVariableBinding: _, ...rest }) => rest
540
+ )
541
+ }
542
+
543
+ // Encode clean version
544
+ const baseBytes = compiledSchema.encodeNodeChange(cleanNodeChange)
545
+ let hex = Buffer.from(baseBytes).toString('hex')
546
+
547
+ // Inject fill variable binding (field 38 = 0x26)
548
+ const fillBinding = nodeChange.fillPaints?.[0]?.colorVariableBinding
549
+ if (hasFillBinding && fillBinding) {
550
+ hex = injectVariableBinding(hex, '2601', fillBinding)
551
+ }
552
+
553
+ // Inject stroke variable binding (field 39 = 0x27)
554
+ const strokeBinding = nodeChange.strokePaints?.[0]?.colorVariableBinding
555
+ if (hasStrokeBinding && strokeBinding) {
556
+ hex = injectVariableBinding(hex, '2701', strokeBinding)
557
+ }
558
+
559
+ return new Uint8Array(hex.match(/.{2}/g)?.map((b) => parseInt(b, 16)) ?? [])
560
+ }
561
+
562
+ /**
563
+ * Inject variable binding into a paint at the specified marker
564
+ */
565
+ function injectVariableBinding(
566
+ hex: string,
567
+ marker: string,
568
+ binding: { variableID: GUID }
569
+ ): string {
570
+ const markerIdx = hex.indexOf(marker)
571
+ if (markerIdx === -1) return hex
572
+
573
+ // Find visible=true pattern (04 01) after the marker
574
+ const visiblePattern = '0401'
575
+ let patternIdx = hex.indexOf(visiblePattern, markerIdx)
576
+ if (patternIdx === -1) return hex
577
+
578
+ // Move past 0401 to find where to insert
579
+ let insertPoint = patternIdx + visiblePattern.length
580
+
581
+ // Check if blendMode follows (05 01)
582
+ if (hex.slice(insertPoint, insertPoint + 4) === '0501') {
583
+ insertPoint += 4
584
+ }
585
+
586
+ // Build variable binding bytes
587
+ const varBytes = [
588
+ 0x15,
589
+ 0x01, // Field 21 (variableBinding) = 1
590
+ 0x04,
591
+ 0x01, // Nested field 4 = 1
592
+ ...encodeVarint(binding.variableID.sessionID),
593
+ ...encodeVarint(binding.variableID.localID),
594
+ 0x00,
595
+ 0x00,
596
+ 0x02,
597
+ 0x03,
598
+ 0x03,
599
+ 0x04,
600
+ 0x00,
601
+ 0x00 // Terminators
602
+ ]
603
+ const varHex = Buffer.from(varBytes).toString('hex')
604
+
605
+ const beforeVar = hex.slice(0, insertPoint)
606
+ // Skip original paint terminator (00) - our varHex includes terminators
607
+ let afterIdx = insertPoint
608
+ if (hex.slice(afterIdx, afterIdx + 2) === '00') {
609
+ afterIdx += 2
610
+ }
611
+ const afterVar = hex.slice(afterIdx)
612
+
613
+ return beforeVar + varHex + afterVar
614
+ }