@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
package/src/vector.ts ADDED
@@ -0,0 +1,413 @@
1
+ import type {
2
+ HandleMirroring,
3
+ VectorNetwork,
4
+ VectorRegion,
5
+ VectorSegment,
6
+ VectorVertex,
7
+ WindingRule
8
+ } from './scene-graph'
9
+ import type { CanvasKit, Path } from 'canvaskit-wasm'
10
+ import type { Rect } from './types'
11
+
12
+ // --- vectorNetworkBlob binary format ---
13
+ // Header: [numVertices:u32, numSegments:u32, numRegions:u32] (12 bytes)
14
+ // Vertex: [styleOverrideIdx:u32, x:f32, y:f32] (12 bytes)
15
+ // Segment: [styleOverrideIdx:u32, start:u32, tsX:f32, tsY:f32, end:u32, teX:f32, teY:f32] (28 bytes)
16
+ // Region: [windingRule:u32, numLoops:u32, {numSegs:u32, segIdx...}... ] (variable)
17
+
18
+ interface StyleOverride {
19
+ styleID: number
20
+ handleMirroring?: string
21
+ }
22
+
23
+ export function decodeVectorNetworkBlob(
24
+ data: Uint8Array,
25
+ styleOverrideTable?: StyleOverride[]
26
+ ): VectorNetwork {
27
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength)
28
+ let o = 0
29
+
30
+ const nV = view.getUint32(o, true)
31
+ o += 4
32
+ const nS = view.getUint32(o, true)
33
+ o += 4
34
+ const nR = view.getUint32(o, true)
35
+ o += 4
36
+
37
+ const styleMap = new Map<number, StyleOverride>()
38
+ if (styleOverrideTable) {
39
+ for (const entry of styleOverrideTable) {
40
+ styleMap.set(entry.styleID, entry)
41
+ }
42
+ }
43
+
44
+ const vertices: VectorVertex[] = []
45
+ for (let i = 0; i < nV; i++) {
46
+ const styleIdx = view.getUint32(o, true)
47
+ o += 4
48
+ const x = view.getFloat32(o, true)
49
+ o += 4
50
+ const y = view.getFloat32(o, true)
51
+ o += 4
52
+
53
+ const override = styleMap.get(styleIdx)
54
+ vertices.push({
55
+ x,
56
+ y,
57
+ handleMirroring: (override?.handleMirroring as HandleMirroring | undefined) ?? 'NONE'
58
+ })
59
+ }
60
+
61
+ const segments: VectorSegment[] = []
62
+ for (let i = 0; i < nS; i++) {
63
+ o += 4 // styleOverrideIdx (unused for segments currently)
64
+ const start = view.getUint32(o, true)
65
+ o += 4
66
+ const tsX = view.getFloat32(o, true)
67
+ o += 4
68
+ const tsY = view.getFloat32(o, true)
69
+ o += 4
70
+ const end = view.getUint32(o, true)
71
+ o += 4
72
+ const teX = view.getFloat32(o, true)
73
+ o += 4
74
+ const teY = view.getFloat32(o, true)
75
+ o += 4
76
+
77
+ segments.push({
78
+ start,
79
+ end,
80
+ tangentStart: { x: tsX, y: tsY },
81
+ tangentEnd: { x: teX, y: teY }
82
+ })
83
+ }
84
+
85
+ const regions: VectorRegion[] = []
86
+ for (let i = 0; i < nR; i++) {
87
+ const windingRuleU32 = view.getUint32(o, true)
88
+ o += 4
89
+ const windingRule: WindingRule = windingRuleU32 === 0 ? 'EVENODD' : 'NONZERO'
90
+ const numLoops = view.getUint32(o, true)
91
+ o += 4
92
+ const loops: number[][] = []
93
+ for (let j = 0; j < numLoops; j++) {
94
+ const numSegs = view.getUint32(o, true)
95
+ o += 4
96
+ const loop: number[] = []
97
+ for (let k = 0; k < numSegs; k++) {
98
+ loop.push(view.getUint32(o, true))
99
+ o += 4
100
+ }
101
+ loops.push(loop)
102
+ }
103
+ regions.push({ windingRule, loops })
104
+ }
105
+
106
+ return { vertices, segments, regions }
107
+ }
108
+
109
+ export function encodeVectorNetworkBlob(network: VectorNetwork): Uint8Array {
110
+ const { vertices, segments, regions } = network
111
+
112
+ let regionBytes = 0
113
+ for (const region of regions) {
114
+ regionBytes += 8 // windingRule + numLoops
115
+ for (const loop of region.loops) {
116
+ regionBytes += 4 + loop.length * 4 // numSegs + indices
117
+ }
118
+ }
119
+
120
+ const totalBytes = 12 + vertices.length * 12 + segments.length * 28 + regionBytes
121
+ const buf = new ArrayBuffer(totalBytes)
122
+ const view = new DataView(buf)
123
+ let o = 0
124
+
125
+ view.setUint32(o, vertices.length, true)
126
+ o += 4
127
+ view.setUint32(o, segments.length, true)
128
+ o += 4
129
+ view.setUint32(o, regions.length, true)
130
+ o += 4
131
+
132
+ for (const v of vertices) {
133
+ view.setUint32(o, 0, true)
134
+ o += 4 // styleOverrideIdx (TODO: encode handleMirroring)
135
+ view.setFloat32(o, v.x, true)
136
+ o += 4
137
+ view.setFloat32(o, v.y, true)
138
+ o += 4
139
+ }
140
+
141
+ for (const seg of segments) {
142
+ view.setUint32(o, 0, true)
143
+ o += 4 // styleOverrideIdx
144
+ view.setUint32(o, seg.start, true)
145
+ o += 4
146
+ view.setFloat32(o, seg.tangentStart.x, true)
147
+ o += 4
148
+ view.setFloat32(o, seg.tangentStart.y, true)
149
+ o += 4
150
+ view.setUint32(o, seg.end, true)
151
+ o += 4
152
+ view.setFloat32(o, seg.tangentEnd.x, true)
153
+ o += 4
154
+ view.setFloat32(o, seg.tangentEnd.y, true)
155
+ o += 4
156
+ }
157
+
158
+ for (const region of regions) {
159
+ view.setUint32(o, region.windingRule === 'EVENODD' ? 0 : 1, true)
160
+ o += 4
161
+ view.setUint32(o, region.loops.length, true)
162
+ o += 4
163
+ for (const loop of region.loops) {
164
+ view.setUint32(o, loop.length, true)
165
+ o += 4
166
+ for (const segIdx of loop) {
167
+ view.setUint32(o, segIdx, true)
168
+ o += 4
169
+ }
170
+ }
171
+ }
172
+
173
+ return new Uint8Array(buf)
174
+ }
175
+
176
+ export function vectorNetworkToPath(ck: CanvasKit, network: VectorNetwork): Path[] {
177
+ const { vertices, segments, regions } = network
178
+
179
+ if (regions.length > 0) {
180
+ const paths: Path[] = []
181
+ for (const region of regions) {
182
+ const regionPath = new ck.Path()
183
+ for (const loop of region.loops) {
184
+ addLoopToPath(regionPath, loop, segments, vertices)
185
+ }
186
+ regionPath.setFillType(
187
+ region.windingRule === 'EVENODD' ? ck.FillType.EvenOdd : ck.FillType.Winding
188
+ )
189
+ paths.push(regionPath)
190
+ }
191
+ return paths
192
+ }
193
+
194
+ // No regions — draw all segments as open paths, tracking direction
195
+ const path = new ck.Path()
196
+ const visited = new Set<number>()
197
+ const chains = buildChains(segments, vertices.length)
198
+
199
+ for (const chain of chains) {
200
+ if (chain.length === 0) continue
201
+ // Determine starting vertex by tracing chain direction
202
+ let current = findChainStart(chain, segments)
203
+ path.moveTo(vertices[current].x, vertices[current].y)
204
+
205
+ for (const segIdx of chain) {
206
+ visited.add(segIdx)
207
+ const seg = segments[segIdx]
208
+ const forward = seg.start === current
209
+ addSegmentDirected(path, seg, vertices, forward)
210
+ current = forward ? seg.end : seg.start
211
+ }
212
+ }
213
+
214
+ for (let i = 0; i < segments.length; i++) {
215
+ if (visited.has(i)) continue
216
+ const seg = segments[i]
217
+ path.moveTo(vertices[seg.start].x, vertices[seg.start].y)
218
+ addSegmentDirected(path, seg, vertices, true)
219
+ }
220
+
221
+ return [path]
222
+ }
223
+
224
+ function addLoopToPath(
225
+ path: Path,
226
+ loop: number[],
227
+ segments: VectorSegment[],
228
+ vertices: VectorVertex[]
229
+ ): void {
230
+ if (loop.length === 0) return
231
+
232
+ // Region loops have pre-oriented segments — always draw forward
233
+ const firstSeg = segments[loop[0]]
234
+ path.moveTo(vertices[firstSeg.start].x, vertices[firstSeg.start].y)
235
+
236
+ for (const segIdx of loop) {
237
+ addSegmentDirected(path, segments[segIdx], vertices, true)
238
+ }
239
+
240
+ const lastSeg = segments[loop[loop.length - 1]]
241
+ if (lastSeg.end === firstSeg.start) {
242
+ path.close()
243
+ }
244
+ }
245
+
246
+ function addSegmentDirected(
247
+ path: Path,
248
+ seg: VectorSegment,
249
+ vertices: VectorVertex[],
250
+ forward: boolean
251
+ ): void {
252
+ const p0 = forward ? vertices[seg.start] : vertices[seg.end]
253
+ const p3 = forward ? vertices[seg.end] : vertices[seg.start]
254
+ const ts = seg.tangentStart
255
+ const te = seg.tangentEnd
256
+
257
+ const isLine = ts.x === 0 && ts.y === 0 && te.x === 0 && te.y === 0
258
+ if (isLine) {
259
+ path.lineTo(p3.x, p3.y)
260
+ } else if (forward) {
261
+ path.cubicTo(p0.x + ts.x, p0.y + ts.y, p3.x + te.x, p3.y + te.y, p3.x, p3.y)
262
+ } else {
263
+ // Reversed cubic: swap control points
264
+ path.cubicTo(p0.x + te.x, p0.y + te.y, p3.x + ts.x, p3.y + ts.y, p3.x, p3.y)
265
+ }
266
+ }
267
+
268
+ function findChainStart(chain: number[], segments: VectorSegment[]): number {
269
+ if (chain.length < 2) return segments[chain[0]].start
270
+
271
+ const first = segments[chain[0]]
272
+ const second = segments[chain[1]]
273
+ // The shared vertex between first and second is the "end" of the first
274
+ // segment in this chain — so the start is the other vertex.
275
+ if (first.start === second.start || first.start === second.end) return first.end
276
+ return first.start
277
+ }
278
+
279
+ function buildChains(segments: VectorSegment[], _vertexCount: number): number[][] {
280
+ if (segments.length === 0) return []
281
+
282
+ // Build adjacency: for each vertex, which segments connect to it
283
+ const adj = new Map<number, number[]>()
284
+ for (let i = 0; i < segments.length; i++) {
285
+ const s = segments[i]
286
+ if (!adj.has(s.start)) adj.set(s.start, [])
287
+ if (!adj.has(s.end)) adj.set(s.end, [])
288
+ adj.get(s.start)?.push(i)
289
+ adj.get(s.end)?.push(i)
290
+ }
291
+
292
+ const visited = new Set<number>()
293
+ const chains: number[][] = []
294
+
295
+ // Start from degree-1 vertices (endpoints) or any unvisited
296
+ const degree1 = [...adj.entries()].filter(([, segs]) => segs.length === 1).map(([v]) => v)
297
+
298
+ const startVertices = degree1.length > 0 ? degree1 : [segments[0].start]
299
+
300
+ for (const startVertex of startVertices) {
301
+ let current = startVertex
302
+ const chain: number[] = []
303
+
304
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
305
+ while (true) {
306
+ const segs = adj.get(current)
307
+ if (!segs) break
308
+
309
+ const nextSeg = segs.find((s) => !visited.has(s))
310
+ if (nextSeg === undefined) break
311
+
312
+ visited.add(nextSeg)
313
+ chain.push(nextSeg)
314
+
315
+ const seg = segments[nextSeg]
316
+ current = seg.start === current ? seg.end : seg.start
317
+ }
318
+
319
+ if (chain.length > 0) chains.push(chain)
320
+ }
321
+
322
+ return chains
323
+ }
324
+
325
+ export function computeVectorBounds(network: VectorNetwork): Rect {
326
+ if (network.vertices.length === 0) {
327
+ return { x: 0, y: 0, width: 0, height: 0 }
328
+ }
329
+
330
+ let minX = Infinity
331
+ let minY = Infinity
332
+ let maxX = -Infinity
333
+ let maxY = -Infinity
334
+
335
+ for (const v of network.vertices) {
336
+ minX = Math.min(minX, v.x)
337
+ minY = Math.min(minY, v.y)
338
+ maxX = Math.max(maxX, v.x)
339
+ maxY = Math.max(maxY, v.y)
340
+ }
341
+
342
+ // Also consider bezier control points for tighter bounds
343
+ for (const seg of network.segments) {
344
+ const start = network.vertices[seg.start]
345
+ const end = network.vertices[seg.end]
346
+ const cp1x = start.x + seg.tangentStart.x
347
+ const cp1y = start.y + seg.tangentStart.y
348
+ const cp2x = end.x + seg.tangentEnd.x
349
+ const cp2y = end.y + seg.tangentEnd.y
350
+
351
+ minX = Math.min(minX, cp1x, cp2x)
352
+ minY = Math.min(minY, cp1y, cp2y)
353
+ maxX = Math.max(maxX, cp1x, cp2x)
354
+ maxY = Math.max(maxY, cp1y, cp2y)
355
+ }
356
+
357
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }
358
+ }
359
+
360
+ const CMD_CLOSE = 0
361
+ const CMD_MOVE_TO = 1
362
+ const CMD_LINE_TO = 2
363
+ const CMD_CUBIC_TO = 4
364
+
365
+ export function geometryBlobToPath(
366
+ ck: CanvasKit,
367
+ blob: Uint8Array,
368
+ windingRule: WindingRule
369
+ ): Path {
370
+ const path = new ck.Path()
371
+ if (!(blob.buffer instanceof ArrayBuffer)) return path
372
+ const dv = new DataView(blob.buffer, blob.byteOffset, blob.byteLength)
373
+ let o = 0
374
+
375
+ while (o < blob.length) {
376
+ const cmd = blob[o++]
377
+ switch (cmd) {
378
+ case CMD_CLOSE:
379
+ path.close()
380
+ break
381
+ case CMD_MOVE_TO: {
382
+ const x = dv.getFloat32(o, true)
383
+ const y = dv.getFloat32(o + 4, true)
384
+ o += 8
385
+ path.moveTo(x, y)
386
+ break
387
+ }
388
+ case CMD_LINE_TO: {
389
+ const x = dv.getFloat32(o, true)
390
+ const y = dv.getFloat32(o + 4, true)
391
+ o += 8
392
+ path.lineTo(x, y)
393
+ break
394
+ }
395
+ case CMD_CUBIC_TO: {
396
+ const x1 = dv.getFloat32(o, true)
397
+ const y1 = dv.getFloat32(o + 4, true)
398
+ const x2 = dv.getFloat32(o + 8, true)
399
+ const y2 = dv.getFloat32(o + 12, true)
400
+ const x = dv.getFloat32(o + 16, true)
401
+ const y = dv.getFloat32(o + 20, true)
402
+ o += 24
403
+ path.cubicTo(x1, y1, x2, y2, x, y)
404
+ break
405
+ }
406
+ default:
407
+ return path
408
+ }
409
+ }
410
+
411
+ path.setFillType(windingRule === 'EVENODD' ? ck.FillType.EvenOdd : ck.FillType.Winding)
412
+ return path
413
+ }
package/src/xpath.ts ADDED
@@ -0,0 +1,259 @@
1
+ import type { IDomFacade } from 'fontoxpath'
2
+ import type { SceneGraph, SceneNode } from './scene-graph'
3
+
4
+ const NODE_TYPES = {
5
+ ELEMENT_NODE: 1,
6
+ ATTRIBUTE_NODE: 2,
7
+ TEXT_NODE: 3,
8
+ DOCUMENT_NODE: 9
9
+ }
10
+
11
+ const QUERYABLE_ATTRS = [
12
+ 'name',
13
+ 'width',
14
+ 'height',
15
+ 'x',
16
+ 'y',
17
+ 'visible',
18
+ 'opacity',
19
+ 'cornerRadius',
20
+ 'fontSize',
21
+ 'fontFamily',
22
+ 'fontWeight',
23
+ 'layoutMode',
24
+ 'itemSpacing',
25
+ 'paddingTop',
26
+ 'paddingBottom',
27
+ 'paddingLeft',
28
+ 'paddingRight',
29
+ 'strokeWeight',
30
+ 'rotation',
31
+ 'locked',
32
+ 'blendMode',
33
+ 'text',
34
+ 'lineHeight',
35
+ 'letterSpacing'
36
+ ]
37
+
38
+ interface XPathDocument {
39
+ nodeType: number
40
+ nodeName: string
41
+ documentElement: XPathNode
42
+ _children?: XPathNode[]
43
+ }
44
+
45
+ interface XPathAttr {
46
+ nodeType: number
47
+ nodeName: string
48
+ name: string
49
+ localName: string
50
+ namespaceURI: null
51
+ prefix: null
52
+ value: string
53
+ ownerElement: XPathNode
54
+ }
55
+
56
+ interface XPathNode {
57
+ nodeType: number
58
+ nodeName: string
59
+ localName: string
60
+ namespaceURI: null
61
+ prefix: null
62
+ _sceneNode: SceneNode
63
+ _attrs?: XPathAttr[]
64
+ _parent?: XPathNode | null
65
+ _children?: XPathNode[]
66
+ }
67
+
68
+ function wrapNode(
69
+ _graph: SceneGraph,
70
+ node: SceneNode,
71
+ parent?: XPathNode | XPathDocument | null
72
+ ): XPathNode {
73
+ const wrapped: XPathNode = {
74
+ nodeType: NODE_TYPES.ELEMENT_NODE,
75
+ nodeName: node.type,
76
+ localName: node.type,
77
+ namespaceURI: null,
78
+ prefix: null,
79
+ _sceneNode: node,
80
+ _parent: parent as XPathNode | null
81
+ }
82
+ return wrapped
83
+ }
84
+
85
+ function createDocument(graph: SceneGraph, rootNode: SceneNode): XPathDocument {
86
+ const doc: XPathDocument = {
87
+ nodeType: NODE_TYPES.DOCUMENT_NODE,
88
+ nodeName: '#document',
89
+ documentElement: null as unknown as XPathNode
90
+ }
91
+ const root = wrapNode(graph, rootNode, doc as unknown as XPathNode)
92
+ doc.documentElement = root
93
+ doc._children = [root]
94
+ return doc
95
+ }
96
+
97
+ function getAttrs(wrapped: XPathNode): XPathAttr[] {
98
+ if (wrapped._attrs) return wrapped._attrs
99
+
100
+ const node = wrapped._sceneNode
101
+ const attrs: XPathAttr[] = []
102
+
103
+ for (const attrName of QUERYABLE_ATTRS) {
104
+ if (attrName in node) {
105
+ const value = (node as unknown as Record<string, unknown>)[attrName]
106
+ if (value === undefined || value === null || typeof value === 'symbol') continue
107
+ const stringValue =
108
+ typeof value === 'object' ? JSON.stringify(value) : String(value as string | number | boolean)
109
+ attrs.push({
110
+ nodeType: NODE_TYPES.ATTRIBUTE_NODE,
111
+ nodeName: attrName,
112
+ name: attrName,
113
+ localName: attrName,
114
+ namespaceURI: null,
115
+ prefix: null,
116
+ value: stringValue,
117
+ ownerElement: wrapped
118
+ })
119
+ }
120
+ }
121
+
122
+ wrapped._attrs = attrs
123
+ return attrs
124
+ }
125
+
126
+ function getChildren(graph: SceneGraph, wrapped: XPathNode): XPathNode[] {
127
+ if (wrapped._children) return wrapped._children
128
+
129
+ const node = wrapped._sceneNode
130
+ wrapped._children = node.childIds
131
+ .map((id) => graph.getNode(id))
132
+ .filter((n): n is SceneNode => n !== undefined)
133
+ .map((child) => wrapNode(graph, child, wrapped))
134
+
135
+ return wrapped._children
136
+ }
137
+
138
+ function isDocument(node: unknown): node is XPathDocument {
139
+ return (node as XPathDocument).nodeType === NODE_TYPES.DOCUMENT_NODE
140
+ }
141
+
142
+ function createDomFacade(graph: SceneGraph) {
143
+ return {
144
+ getAllAttributes(node: XPathNode | XPathDocument): XPathAttr[] {
145
+ if (isDocument(node)) return []
146
+ return getAttrs(node)
147
+ },
148
+
149
+ getAttribute(node: XPathNode | XPathDocument, attributeName: string): string | null {
150
+ if (isDocument(node)) return null
151
+ const sceneNode = node._sceneNode
152
+ if (attributeName in sceneNode) {
153
+ const value = (sceneNode as unknown as Record<string, unknown>)[attributeName]
154
+ if (value === undefined || value === null || typeof value === 'symbol') return null
155
+ return typeof value === 'object' ? JSON.stringify(value) : String(value as string | number | boolean)
156
+ }
157
+ return null
158
+ },
159
+
160
+ getChildNodes(node: XPathNode | XPathDocument): XPathNode[] {
161
+ if (isDocument(node)) return node._children ?? []
162
+ return getChildren(graph, node)
163
+ },
164
+
165
+ getData(node: XPathAttr): string {
166
+ return node.value
167
+ },
168
+
169
+ getFirstChild(node: XPathNode | XPathDocument): XPathNode | null {
170
+ if (isDocument(node)) return node.documentElement
171
+ const children = getChildren(graph, node)
172
+ return children[0] ?? null
173
+ },
174
+
175
+ getLastChild(node: XPathNode | XPathDocument): XPathNode | null {
176
+ if (isDocument(node)) return node.documentElement
177
+ const children = getChildren(graph, node)
178
+ return children[children.length - 1] ?? null
179
+ },
180
+
181
+ getNextSibling(node: XPathNode | XPathDocument): XPathNode | null {
182
+ if (isDocument(node)) return null
183
+ const parent = node._parent
184
+ if (!parent) return null
185
+ const siblings = getChildren(graph, parent)
186
+ const idx = siblings.indexOf(node)
187
+ return siblings[idx + 1] ?? null
188
+ },
189
+
190
+ getParentNode(node: XPathNode | XPathDocument): XPathNode | XPathDocument | null {
191
+ if (isDocument(node)) return null
192
+ return node._parent ?? null
193
+ },
194
+
195
+ getPreviousSibling(node: XPathNode | XPathDocument): XPathNode | null {
196
+ if (isDocument(node)) return null
197
+ const parent = node._parent
198
+ if (!parent) return null
199
+ const siblings = getChildren(graph, parent)
200
+ const idx = siblings.indexOf(node)
201
+ return idx > 0 ? siblings[idx - 1] : null
202
+ }
203
+ }
204
+ }
205
+
206
+ export interface XPathQueryOptions {
207
+ limit?: number
208
+ page?: string
209
+ }
210
+
211
+ export async function queryByXPath(
212
+ graph: SceneGraph,
213
+ selector: string,
214
+ options: XPathQueryOptions = {}
215
+ ): Promise<SceneNode[]> {
216
+ const { limit = 1000 } = options
217
+ const pages = graph.getPages()
218
+ const targetPages = options.page
219
+ ? pages.filter((p) => p.name === options.page)
220
+ : pages
221
+
222
+ if (targetPages.length === 0) return []
223
+
224
+ const { evaluateXPathToNodes } = await import('fontoxpath')
225
+ const domFacade = createDomFacade(graph) as unknown as IDomFacade
226
+ const results: SceneNode[] = []
227
+
228
+ for (const page of targetPages) {
229
+ const doc = createDocument(graph, page)
230
+ const nodes = evaluateXPathToNodes(selector, doc, domFacade)
231
+
232
+ for (const node of nodes) {
233
+ if (results.length >= limit) break
234
+ const sceneNode = (node as XPathNode)._sceneNode
235
+ if (sceneNode.type !== 'CANVAS') {
236
+ results.push(sceneNode)
237
+ }
238
+ }
239
+
240
+ if (results.length >= limit) break
241
+ }
242
+
243
+ return results
244
+ }
245
+
246
+ export async function matchByXPath(
247
+ graph: SceneGraph,
248
+ selector: string,
249
+ node: SceneNode
250
+ ): Promise<boolean> {
251
+ const { evaluateXPathToBoolean } = await import('fontoxpath')
252
+ const domFacade = createDomFacade(graph) as unknown as IDomFacade
253
+ const wrapped = wrapNode(graph, node)
254
+ try {
255
+ return evaluateXPathToBoolean(`self::*[${selector}]`, wrapped, domFacade)
256
+ } catch {
257
+ return false
258
+ }
259
+ }