fundus 0.28.0 → 0.29.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 (179) hide show
  1. package/README.md +41 -33
  2. package/build/client/_app/immutable/chunks/{CRFKGnag.js → BCmR1_e0.js} +1 -1
  3. package/build/client/_app/immutable/chunks/BCmR1_e0.js.br +0 -0
  4. package/build/client/_app/immutable/chunks/BCmR1_e0.js.gz +0 -0
  5. package/build/client/_app/immutable/chunks/{apKHI4vq.js → C0uU_Rhe.js} +2 -2
  6. package/build/client/_app/immutable/chunks/C0uU_Rhe.js.br +0 -0
  7. package/build/client/_app/immutable/chunks/C0uU_Rhe.js.gz +0 -0
  8. package/build/client/_app/immutable/chunks/{g2rma9Ym.js → CMJ10zbJ.js} +1 -1
  9. package/build/client/_app/immutable/chunks/CMJ10zbJ.js.br +0 -0
  10. package/build/client/_app/immutable/chunks/CMJ10zbJ.js.gz +0 -0
  11. package/build/client/_app/immutable/chunks/{rtFCvv3j.js → kkVEh3_1.js} +1 -1
  12. package/build/client/_app/immutable/chunks/kkVEh3_1.js.br +2 -0
  13. package/build/client/_app/immutable/chunks/kkVEh3_1.js.gz +0 -0
  14. package/build/client/_app/immutable/chunks/{BSzEzOBI.js → wBLhaPea.js} +1 -1
  15. package/build/client/_app/immutable/chunks/wBLhaPea.js.br +0 -0
  16. package/build/client/_app/immutable/chunks/wBLhaPea.js.gz +0 -0
  17. package/build/client/_app/immutable/entry/{app.BiYJKHq5.js → app.DCXSqiQ1.js} +2 -2
  18. package/build/client/_app/immutable/entry/app.DCXSqiQ1.js.br +0 -0
  19. package/build/client/_app/immutable/entry/app.DCXSqiQ1.js.gz +0 -0
  20. package/build/client/_app/immutable/entry/start.BOUpxuMU.js +1 -0
  21. package/build/client/_app/immutable/entry/start.BOUpxuMU.js.br +0 -0
  22. package/build/client/_app/immutable/entry/start.BOUpxuMU.js.gz +0 -0
  23. package/build/client/_app/immutable/nodes/{0.kL9OGUbr.js → 0.CsqkK05g.js} +1 -1
  24. package/build/client/_app/immutable/nodes/0.CsqkK05g.js.br +0 -0
  25. package/build/client/_app/immutable/nodes/0.CsqkK05g.js.gz +0 -0
  26. package/build/client/_app/immutable/nodes/{1.DQGC5ZQg.js → 1.BVSXvtU9.js} +1 -1
  27. package/build/client/_app/immutable/nodes/1.BVSXvtU9.js.br +2 -0
  28. package/build/client/_app/immutable/nodes/1.BVSXvtU9.js.gz +0 -0
  29. package/build/client/_app/immutable/nodes/2.BJEXWmrT.js +4 -0
  30. package/build/client/_app/immutable/nodes/2.BJEXWmrT.js.br +0 -0
  31. package/build/client/_app/immutable/nodes/2.BJEXWmrT.js.gz +0 -0
  32. package/build/client/_app/immutable/nodes/{3.DkyIyoNd.js → 3.BDMmDyL1.js} +1 -1
  33. package/build/client/_app/immutable/nodes/3.BDMmDyL1.js.br +0 -0
  34. package/build/client/_app/immutable/nodes/3.BDMmDyL1.js.gz +0 -0
  35. package/build/client/_app/immutable/nodes/{4.D1JY4Ttk.js → 4.dd49_qQE.js} +1 -1
  36. package/build/client/_app/immutable/nodes/4.dd49_qQE.js.br +0 -0
  37. package/build/client/_app/immutable/nodes/4.dd49_qQE.js.gz +0 -0
  38. package/build/client/_app/version.json +1 -1
  39. package/build/client/_app/version.json.br +0 -0
  40. package/build/client/_app/version.json.gz +0 -0
  41. package/build/handler.js +7 -7
  42. package/build/index.js +7 -7
  43. package/build/server/chunks/chunks/{context.js-BZSZNuAd.js → context.js-DFZgDxCD.js} +157 -95
  44. package/build/server/chunks/chunks/context.js-DFZgDxCD.js.map +1 -0
  45. package/build/server/chunks/chunks/{contract.js-B4JdXFgm.js → contract.js-DGZXpcNX.js} +7 -7
  46. package/build/server/chunks/chunks/{contract.js-B4JdXFgm.js.map → contract.js-DGZXpcNX.js.map} +1 -1
  47. package/build/server/chunks/chunks/{core.js-BHxa3VBo.js → core.js-AGKlECJ0.js} +32 -32
  48. package/build/server/chunks/chunks/core.js-AGKlECJ0.js.map +1 -0
  49. package/build/server/chunks/chunks/{exports.js-Cncv1qoG.js → exports.js-BsVKSGJk.js} +2 -2
  50. package/build/server/chunks/chunks/{exports.js-Cncv1qoG.js.map → exports.js-BsVKSGJk.js.map} +1 -1
  51. package/build/server/chunks/chunks/{http.js-DYYKvppy.js → http.js-BQhjMaW9.js} +2 -2
  52. package/build/server/chunks/chunks/{http.js-DYYKvppy.js.map → http.js-BQhjMaW9.js.map} +1 -1
  53. package/build/server/chunks/chunks/{internal.js-C2FKw_9R.js → internal.js-DJGcNryj.js} +3 -3
  54. package/build/server/chunks/chunks/{internal.js-C2FKw_9R.js.map → internal.js-DJGcNryj.js.map} +1 -1
  55. package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -1
  56. package/build/server/chunks/chunks/{manifest-membership.js-BkrPsM_r.js → manifest-membership.js-DkHaPk2F.js} +2 -2
  57. package/build/server/chunks/chunks/{manifest-membership.js-BkrPsM_r.js.map → manifest-membership.js-DkHaPk2F.js.map} +1 -1
  58. package/build/server/chunks/chunks/{raw-reconciliation.js-DPnNXe0b.js → raw-reconciliation.js-D2sI2C-t.js} +3 -3
  59. package/build/server/chunks/chunks/raw-reconciliation.js-D2sI2C-t.js.map +1 -0
  60. package/build/server/chunks/chunks/{raw-reconciliation2.js-DKOpJ8if.js → raw-reconciliation2.js-CMpUvuMd.js} +2 -2
  61. package/build/server/chunks/chunks/{raw-reconciliation2.js-DKOpJ8if.js.map → raw-reconciliation2.js-CMpUvuMd.js.map} +1 -1
  62. package/build/server/chunks/chunks/{shared.js-BGsWd7z-.js → shared.js-BtmYg0tL.js} +2 -2
  63. package/build/server/chunks/chunks/{shared.js-BGsWd7z-.js.map → shared.js-BtmYg0tL.js.map} +1 -1
  64. package/build/server/chunks/chunks/{utils.js-C0ADATvf.js → utils.js-CqXk0Ug6.js} +3 -3
  65. package/build/server/chunks/chunks/{utils.js-C0ADATvf.js.map → utils.js-CqXk0Ug6.js.map} +1 -1
  66. package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-Dw2MW5Tm.js → _server.ts.js-DKGD9Jk2.js} +6 -6
  67. package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-Dw2MW5Tm.js.map → _server.ts.js-DKGD9Jk2.js.map} +1 -1
  68. package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-GQDuJGug.js → _server.ts.js-C1UfF0EO.js} +7 -7
  69. package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-GQDuJGug.js.map → _server.ts.js-C1UfF0EO.js.map} +1 -1
  70. package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-JbLSv7Xx.js → _server.ts.js-DpASkk00.js} +7 -7
  71. package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-JbLSv7Xx.js.map → _server.ts.js-DpASkk00.js.map} +1 -1
  72. package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-BPae-BYF.js → _server.ts.js-C3jU2vC8.js} +7 -7
  73. package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-BPae-BYF.js.map → _server.ts.js-C3jU2vC8.js.map} +1 -1
  74. package/build/server/chunks/entries/endpoints/api/assets/_id_/retag/{_server.ts.js-BafrrUxu.js → _server.ts.js-B7OwufF3.js} +7 -7
  75. package/build/server/chunks/entries/endpoints/api/assets/_id_/retag/{_server.ts.js-BafrrUxu.js.map → _server.ts.js-B7OwufF3.js.map} +1 -1
  76. package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-UOlSNEi9.js → _server.ts.js-COhg1nYk.js} +7 -7
  77. package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-UOlSNEi9.js.map → _server.ts.js-COhg1nYk.js.map} +1 -1
  78. package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-QE1vUuAx.js → _server.ts.js-DAEE17eM.js} +7 -7
  79. package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-QE1vUuAx.js.map → _server.ts.js-DAEE17eM.js.map} +1 -1
  80. package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-DIVfppGt.js → _server.ts.js-BrZSS4gm.js} +7 -7
  81. package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-DIVfppGt.js.map → _server.ts.js-BrZSS4gm.js.map} +1 -1
  82. package/build/server/chunks/entries/endpoints/api/events/{_server.ts.js-B6R_kqP8.js → _server.ts.js-Cfst-Brd.js} +7 -7
  83. package/build/server/chunks/entries/endpoints/api/events/{_server.ts.js-B6R_kqP8.js.map → _server.ts.js-Cfst-Brd.js.map} +1 -1
  84. package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-CertbDsH.js → _server.ts.js-aN_h2Ifo.js} +7 -7
  85. package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-CertbDsH.js.map → _server.ts.js-aN_h2Ifo.js.map} +1 -1
  86. package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-DEIF3Hu2.js → _server.ts.js-CX2A66ij.js} +7 -7
  87. package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-DEIF3Hu2.js.map → _server.ts.js-CX2A66ij.js.map} +1 -1
  88. package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-DNFsNGr4.js → _server.ts.js-CwTiaheP.js} +7 -7
  89. package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-DNFsNGr4.js.map → _server.ts.js-CwTiaheP.js.map} +1 -1
  90. package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-DDW8XRPe.js → _server.ts.js-fIbsr_2e.js} +7 -7
  91. package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-DDW8XRPe.js.map → _server.ts.js-fIbsr_2e.js.map} +1 -1
  92. package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-C222-xli.js → _server.ts.js-Dvo1bsLi.js} +7 -7
  93. package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-C222-xli.js.map → _server.ts.js-Dvo1bsLi.js.map} +1 -1
  94. package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-CI1P1uyd.js → _server.ts.js-VLg1G3mN.js} +7 -7
  95. package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-CI1P1uyd.js.map → _server.ts.js-VLg1G3mN.js.map} +1 -1
  96. package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-DpiUwaSh.js → _server.ts.js-DqctsOop.js} +7 -7
  97. package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-DpiUwaSh.js.map → _server.ts.js-DqctsOop.js.map} +1 -1
  98. package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-DT0VPqPT.js → _server.ts.js-CoxSU5iO.js} +7 -7
  99. package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-DT0VPqPT.js.map → _server.ts.js-CoxSU5iO.js.map} +1 -1
  100. package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-DBpHM42g.js → _server.ts.js-wUxsLZdr.js} +7 -7
  101. package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-DBpHM42g.js.map → _server.ts.js-wUxsLZdr.js.map} +1 -1
  102. package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-Cxu5b6Au.js → _server.ts.js-BKsF0Oit.js} +7 -7
  103. package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-Cxu5b6Au.js.map → _server.ts.js-BKsF0Oit.js.map} +1 -1
  104. package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-W4dhMo8Y.js → _server.ts.js-Dk9oOZwM.js} +7 -7
  105. package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-W4dhMo8Y.js.map → _server.ts.js-Dk9oOZwM.js.map} +1 -1
  106. package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-DJ_adxbT.js → _server.ts.js-DxjNmmtL.js} +7 -7
  107. package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-DJ_adxbT.js.map → _server.ts.js-DxjNmmtL.js.map} +1 -1
  108. package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-BisoHihD.js → _server.ts.js-DD0b38VV.js} +6 -6
  109. package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-BisoHihD.js.map → _server.ts.js-DD0b38VV.js.map} +1 -1
  110. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-D4jLLuko.js → _server.ts.js-DId6F2i_.js} +7 -7
  111. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-D4jLLuko.js.map → _server.ts.js-DId6F2i_.js.map} +1 -1
  112. package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-Dfv2ItjT.js → _server.ts.js-DKKkGoK2.js} +7 -7
  113. package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-Dfv2ItjT.js.map → _server.ts.js-DKKkGoK2.js.map} +1 -1
  114. package/build/server/chunks/entries/{hooks.server.js-oHJX5INm.js → hooks.server.js-B5Ctvorj.js} +6 -6
  115. package/build/server/chunks/entries/{hooks.server.js-oHJX5INm.js.map → hooks.server.js-B5Ctvorj.js.map} +1 -1
  116. package/build/server/chunks/{handler-uc4GLvWI.js → handler-DwVfBx6r.js} +5 -5
  117. package/build/server/chunks/{handler-uc4GLvWI.js.map → handler-DwVfBx6r.js.map} +1 -1
  118. package/build/server/chunks/{index.js-BTlSiK4q.js → index.js-DgPuPQJn.js} +5 -5
  119. package/build/server/chunks/{index.js-BTlSiK4q.js.map → index.js-DgPuPQJn.js.map} +1 -1
  120. package/build/server/chunks/{manifest.js-BB8iIVbZ.js → manifest.js-B054EcAf.js} +31 -31
  121. package/build/server/chunks/{manifest.js-BB8iIVbZ.js.map → manifest.js-B054EcAf.js.map} +1 -1
  122. package/build/server/chunks/nodes/{0.js-CccZDEdX.js → 0.js-DoHZTmnT.js} +2 -2
  123. package/build/server/chunks/nodes/{0.js-CccZDEdX.js.map → 0.js-DoHZTmnT.js.map} +1 -1
  124. package/build/server/chunks/nodes/1.js-BcPlsloO.js +7 -0
  125. package/build/server/chunks/nodes/{1.js-_Ms77u64.js.map → 1.js-BcPlsloO.js.map} +1 -1
  126. package/build/server/chunks/nodes/{2.js-BpyFsilO.js → 2.js-5qCXkvzl.js} +2 -2
  127. package/build/server/chunks/nodes/{2.js-BpyFsilO.js.map → 2.js-5qCXkvzl.js.map} +1 -1
  128. package/build/server/chunks/nodes/3.js-D6fAMX1w.js +7 -0
  129. package/build/server/chunks/nodes/{3.js-D7RUEviu.js.map → 3.js-D6fAMX1w.js.map} +1 -1
  130. package/build/server/chunks/nodes/4.js-CGkeT0SQ.js +7 -0
  131. package/build/server/chunks/nodes/{4.js-Cfc3G2Gv.js.map → 4.js-CGkeT0SQ.js.map} +1 -1
  132. package/dist/cli.js +3 -4
  133. package/dist/core/figma-tag-links.d.ts +66 -0
  134. package/dist/core/figma-tag-links.js +97 -0
  135. package/dist/core/index.d.ts +2 -2
  136. package/dist/core/index.js +1 -1
  137. package/dist/server/cli-commands.d.ts +1 -1
  138. package/dist/server/cli-commands.js +1 -1
  139. package/dist/server/cli-figma-tags.d.ts +1 -1
  140. package/dist/server/cli-figma-tags.js +149 -88
  141. package/dist/server/figma-tags.d.ts +72 -24
  142. package/dist/server/figma-tags.js +130 -79
  143. package/dist/server/importers/figma.d.ts +20 -15
  144. package/dist/server/importers/figma.js +172 -92
  145. package/package.json +1 -1
  146. package/build/client/_app/immutable/chunks/BSzEzOBI.js.br +0 -0
  147. package/build/client/_app/immutable/chunks/BSzEzOBI.js.gz +0 -0
  148. package/build/client/_app/immutable/chunks/CRFKGnag.js.br +0 -0
  149. package/build/client/_app/immutable/chunks/CRFKGnag.js.gz +0 -0
  150. package/build/client/_app/immutable/chunks/apKHI4vq.js.br +0 -0
  151. package/build/client/_app/immutable/chunks/apKHI4vq.js.gz +0 -0
  152. package/build/client/_app/immutable/chunks/g2rma9Ym.js.br +0 -0
  153. package/build/client/_app/immutable/chunks/g2rma9Ym.js.gz +0 -0
  154. package/build/client/_app/immutable/chunks/rtFCvv3j.js.br +0 -0
  155. package/build/client/_app/immutable/chunks/rtFCvv3j.js.gz +0 -0
  156. package/build/client/_app/immutable/entry/app.BiYJKHq5.js.br +0 -0
  157. package/build/client/_app/immutable/entry/app.BiYJKHq5.js.gz +0 -0
  158. package/build/client/_app/immutable/entry/start.BGYYpgAJ.js +0 -1
  159. package/build/client/_app/immutable/entry/start.BGYYpgAJ.js.br +0 -0
  160. package/build/client/_app/immutable/entry/start.BGYYpgAJ.js.gz +0 -0
  161. package/build/client/_app/immutable/nodes/0.kL9OGUbr.js.br +0 -0
  162. package/build/client/_app/immutable/nodes/0.kL9OGUbr.js.gz +0 -0
  163. package/build/client/_app/immutable/nodes/1.DQGC5ZQg.js.br +0 -0
  164. package/build/client/_app/immutable/nodes/1.DQGC5ZQg.js.gz +0 -0
  165. package/build/client/_app/immutable/nodes/2.DXo6NZ8U.js +0 -4
  166. package/build/client/_app/immutable/nodes/2.DXo6NZ8U.js.br +0 -0
  167. package/build/client/_app/immutable/nodes/2.DXo6NZ8U.js.gz +0 -0
  168. package/build/client/_app/immutable/nodes/3.DkyIyoNd.js.br +0 -0
  169. package/build/client/_app/immutable/nodes/3.DkyIyoNd.js.gz +0 -0
  170. package/build/client/_app/immutable/nodes/4.D1JY4Ttk.js.br +0 -0
  171. package/build/client/_app/immutable/nodes/4.D1JY4Ttk.js.gz +0 -0
  172. package/build/server/chunks/chunks/context.js-BZSZNuAd.js.map +0 -1
  173. package/build/server/chunks/chunks/core.js-BHxa3VBo.js.map +0 -1
  174. package/build/server/chunks/chunks/raw-reconciliation.js-DPnNXe0b.js.map +0 -1
  175. package/build/server/chunks/nodes/1.js-_Ms77u64.js +0 -7
  176. package/build/server/chunks/nodes/3.js-D7RUEviu.js +0 -7
  177. package/build/server/chunks/nodes/4.js-Cfc3G2Gv.js +0 -7
  178. package/dist/core/figma-tag-script.d.ts +0 -154
  179. package/dist/core/figma-tag-script.js +0 -248
@@ -1,8 +1,8 @@
1
- import { c as compareCodeUnits, h as folderOfRawPath, j as rawFileNameOfPath, g as canonicalizeParameters, n as normalizeFolderPath, J as typesForFileName, k as parentFolderPath, u as portableFolderPathKey } from './core.js-BHxa3VBo.js';
2
- import { i as isRecord, s as serverPluginsByType, L as LibraryStore, d as descriptorsByType, m as manifestModuleFileName, l as locateGeneratedAssetDeclaration, a as serializeLibrary, b as serverPluginForType, S as SourceImportError, p as processAssets, g as generateManifestModules, r as readCurrentProxy, e as encodeRelativePathForUrl, c as invalidInput, f as parseLibrary } from './contract.js-B4JdXFgm.js';
3
- import { c as collectAllReferences, a as assetIdError, b as computeLibraryMembership, d as allDeliveredAssetIds, i as isValidAssetId } from './manifest-membership.js-BkrPsM_r.js';
1
+ import { c as compareCodeUnits, h as folderOfRawPath, j as rawFileNameOfPath, g as canonicalizeParameters, n as normalizeFolderPath, J as typesForFileName, k as parentFolderPath, u as portableFolderPathKey } from './core.js-AGKlECJ0.js';
2
+ import { i as isRecord, s as serverPluginsByType, L as LibraryStore, d as descriptorsByType, m as manifestModuleFileName, l as locateGeneratedAssetDeclaration, a as serializeLibrary, b as serverPluginForType, S as SourceImportError, p as processAssets, g as generateManifestModules, r as readCurrentProxy, e as encodeRelativePathForUrl, c as invalidInput, f as parseLibrary } from './contract.js-DGZXpcNX.js';
3
+ import { c as collectAllReferences, a as assetIdError, b as computeLibraryMembership, d as allDeliveredAssetIds, i as isValidAssetId } from './manifest-membership.js-DkHaPk2F.js';
4
4
  import { v as validateDependencyList, f as formatRequiredBy } from './dependencies.js-pUkjICr5.js';
5
- import { v as verifyStableRawFile, c as classifyRawDirectory } from './raw-reconciliation2.js-DKOpJ8if.js';
5
+ import { v as verifyStableRawFile, c as classifyRawDirectory } from './raw-reconciliation2.js-CMpUvuMd.js';
6
6
  import { createRequire } from 'node:module';
7
7
  import { isAbsolute, resolve, basename, dirname, join, extname, relative, sep } from 'node:path';
8
8
  import { existsSync, watch, readFileSync } from 'node:fs';
@@ -16,14 +16,59 @@ import { lookup } from 'node:dns/promises';
16
16
  import { isIP } from 'node:net';
17
17
  import { request } from 'node:https';
18
18
 
19
- //#region src/lib/core/figma-tag-script.ts
20
19
  /**
21
- * Whether the id names a node inside an instance (`I<instance>;<source>`).
22
- * Such nodes inherit the shared plugin data of the main component's node, so
23
- * they report its tag without being a separate taggable node.
20
+ * The tag a link URL names, or `null`. An exact string match (no URL parsing)
21
+ * makes any path segment, query, fragment or percent-escape fail the tag grammar.
24
22
  */
25
- function isInstanceSublayerId(id) {
26
- return id.startsWith("I");
23
+ function parseFundusTagLink(url) {
24
+ if (!url.startsWith("https://fundus.invalid/asset/")) return null;
25
+ const tag = url.slice(29);
26
+ return isValidAssetId(tag) ? tag : null;
27
+ }
28
+ var TAGGABLE_NODE_ID = /^\d+:\d+$/;
29
+ /**
30
+ * The Fundus tags carried by own links on plain scene-node ids; inherited,
31
+ * sublayer, foreign and unparsable links are dropped. One entry per link, so
32
+ * several tags on one node stay several entries. Sorted by tag, then node id.
33
+ */
34
+ function figmaTagEntries(links) {
35
+ const entries = [];
36
+ for (const link of links) {
37
+ if (link.inherited || !TAGGABLE_NODE_ID.test(link.nodeId)) continue;
38
+ const tag = parseFundusTagLink(link.url);
39
+ if (tag === null) continue;
40
+ entries.push(link.linkId === void 0 ? {
41
+ tag,
42
+ nodeId: link.nodeId
43
+ } : {
44
+ tag,
45
+ nodeId: link.nodeId,
46
+ linkId: link.linkId
47
+ });
48
+ }
49
+ return entries.sort((left, right) => compareCodeUnits(left.tag, right.tag) || compareCodeUnits(left.nodeId, right.nodeId));
50
+ }
51
+ /**
52
+ * The links in a REST `GET /v1/files/:key/dev_resources` body, or `null` when
53
+ * `dev_resources` is not an array. Entries without string `id`/`url`/`node_id`
54
+ * are skipped.
55
+ */
56
+ function figmaLinksFromRest(body) {
57
+ const resources = typeof body === "object" && body !== null ? body.dev_resources : void 0;
58
+ if (!Array.isArray(resources)) return null;
59
+ const links = [];
60
+ for (const resource of resources) {
61
+ if (typeof resource !== "object" || resource === null) continue;
62
+ const { id, url, node_id: nodeId } = resource;
63
+ if (typeof id !== "string" || typeof url !== "string" || typeof nodeId !== "string") continue;
64
+ links.push({
65
+ nodeId,
66
+ url,
67
+ inherited: false,
68
+ linkId: id
69
+ });
70
+ }
71
+ return links;
27
72
  }
28
73
  //#endregion
29
74
  //#region src/lib/core/propose-asset-id.ts
@@ -427,6 +472,9 @@ var PNG_SIGNATURE = Uint8Array.from([
427
472
  26,
428
473
  10
429
474
  ]);
475
+ /** Worst case per API call: 3 attempts × 30 s timeout + 2 waits × 10 s = 110 s. */
476
+ var FIGMA_RATE_LIMIT_ATTEMPTS = 3;
477
+ var FIGMA_RATE_LIMIT_MAX_WAIT_SECONDS = 10;
430
478
  function record(value) {
431
479
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
432
480
  }
@@ -506,12 +554,12 @@ function retryAfter(response) {
506
554
  const seconds = Number(raw);
507
555
  return Number.isSafeInteger(seconds) ? seconds : void 0;
508
556
  }
509
- function upstreamStatusError(response) {
557
+ function upstreamStatusError(response, scope) {
510
558
  if (response.status === 401) return new SourceImportError("unauthorized", "Figma authentication failed.");
511
- if (response.status === 403) return new SourceImportError("forbidden", "Figma authentication or access failed. The token may be invalid or expired, or it may not have access to this file.");
559
+ if (response.status === 403) return new SourceImportError("forbidden", scope ? `Figma authentication or access failed. The token may be invalid or expired, may lack the ${scope} scope, or may not have access to this file.` : "Figma authentication or access failed. The token may be invalid or expired, or it may not have access to this file.");
512
560
  if (response.status === 404) return new SourceImportError("not-found", "The Figma file or node was not found.");
513
561
  if (response.status === 429) return new SourceImportError("rate-limited", "Figma rate-limited this request.", retryAfter(response));
514
- return new SourceImportError("upstream-failed", `Figma export failed with status ${response.status}.`);
562
+ return new SourceImportError("upstream-failed", `Figma request failed with status ${response.status}.`);
515
563
  }
516
564
  function isForbiddenIpv4(address) {
517
565
  const parts = address.split(".").map(Number);
@@ -570,7 +618,7 @@ async function resolveSafeDownloadTarget(value) {
570
618
  addresses
571
619
  };
572
620
  }
573
- async function fetchWithDeadline(fetcher, url, init, consume) {
621
+ async function fetchWithDeadline(fetcher, url, init, scope) {
574
622
  const controller = new AbortController();
575
623
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
576
624
  try {
@@ -578,12 +626,12 @@ async function fetchWithDeadline(fetcher, url, init, consume) {
578
626
  ...init,
579
627
  signal: controller.signal
580
628
  });
581
- if (!response.ok) throw upstreamStatusError(response);
582
- return await consume(response);
629
+ if (!response.ok) throw upstreamStatusError(response, scope);
630
+ return new Uint8Array(await response.arrayBuffer());
583
631
  } catch (cause) {
584
- if (controller.signal.aborted || cause instanceof Error && cause.name === "AbortError") throw new SourceImportError("download-timeout", "Figma export timed out.");
632
+ if (controller.signal.aborted || cause instanceof Error && cause.name === "AbortError") throw new SourceImportError("download-timeout", "Figma request timed out.");
585
633
  if (cause instanceof SourceImportError) throw cause;
586
- throw new SourceImportError("upstream-failed", "Figma export request failed.");
634
+ throw new SourceImportError("upstream-failed", "Figma request failed.");
587
635
  } finally {
588
636
  clearTimeout(timeout);
589
637
  }
@@ -684,44 +732,28 @@ async function validatePng(bytes) {
684
732
  if (!metadata.width || !metadata.height) throw new SourceImportError("invalid-response", "Figma export has invalid dimensions.");
685
733
  if (metadata.width * metadata.height > MAX_PIXELS) throw new SourceImportError("image-too-large", "Figma export exceeds the 32 megapixel limit.");
686
734
  }
687
- /**
688
- * Every taggable node in a REST document tree (`plugin_data=shared`), in
689
- * document order. Nodes inside instances are skipped: they echo the main
690
- * component node's tag, and Fundus imports only plain `12:34` node ids.
691
- */
692
- function figmaDocumentNodes(document) {
693
- const nodes = [];
694
- const visit = (value, page) => {
695
- const current = record(value);
696
- if (!current) return;
697
- const name = typeof current.name === "string" ? current.name : "";
698
- const pageName = current.type === "CANVAS" ? name : page;
699
- if (typeof current.id === "string" && current.type !== "DOCUMENT" && current.type !== "CANVAS" && !isInstanceSublayerId(current.id)) {
700
- const shared = record(current.sharedPluginData);
701
- const fundus = shared ? record(shared.fundus) : null;
702
- const tag = fundus && typeof fundus.assetId === "string" ? fundus.assetId : "";
703
- nodes.push({
704
- nodeId: current.id,
705
- nodeName: name,
706
- page: pageName,
707
- tag: tag === "" ? null : tag
708
- });
709
- }
710
- if (Array.isArray(current.children)) for (const child of current.children) visit(child, pageName);
711
- };
712
- visit(record(document), "");
713
- return nodes;
735
+ async function fetchFigmaApiBytes(endpoint, init, scope, context) {
736
+ for (let attempt = 1;; attempt++) try {
737
+ return await fetchWithDeadline(context.fetch, endpoint, init, scope);
738
+ } catch (cause) {
739
+ const wait = cause instanceof SourceImportError && cause.code === "rate-limited" ? cause.retryAfterSeconds : void 0;
740
+ if (wait === void 0 || wait > FIGMA_RATE_LIMIT_MAX_WAIT_SECONDS || attempt >= FIGMA_RATE_LIMIT_ATTEMPTS) throw cause;
741
+ await new Promise((resolve) => setTimeout(resolve, wait * 1e3));
742
+ }
714
743
  }
715
- /** The whole document tree of a Figma file, including every node's shared plugin data. */
716
- async function fetchFigmaDocument(fileKey, context) {
744
+ async function requestFigmaApi(endpoint, context, request) {
717
745
  const token = context.config.import.figma.token;
718
746
  if (!token) throw new SourceImportError("not-configured", "Figma access is not configured.");
719
- const endpoint = new URL(`https://api.figma.com/v1/files/${encodeURIComponent(fileKey)}`);
720
- endpoint.searchParams.set("plugin_data", "shared");
721
- const jsonBytes = await fetchWithDeadline(context.fetch, endpoint, {
747
+ const jsonBytes = await fetchFigmaApiBytes(endpoint, {
748
+ method: request.method ?? "GET",
722
749
  redirect: "error",
723
- headers: { "X-Figma-Token": token }
724
- }, async (response) => new Uint8Array(await response.arrayBuffer()));
750
+ headers: {
751
+ "X-Figma-Token": token,
752
+ ...request.body !== void 0 ? { "Content-Type": "application/json" } : {}
753
+ },
754
+ ...request.body !== void 0 ? { body: JSON.stringify(request.body) } : {}
755
+ }, request.scope, context);
756
+ if (jsonBytes.byteLength === 0) return {};
725
757
  let payload;
726
758
  try {
727
759
  payload = JSON.parse(new TextDecoder().decode(jsonBytes));
@@ -729,38 +761,64 @@ async function fetchFigmaDocument(fileKey, context) {
729
761
  throw new SourceImportError("invalid-response", "Figma returned an invalid response.");
730
762
  }
731
763
  const body = record(payload);
732
- if (!body || body.err || typeof body.status === "number" && body.status >= 400) throw new SourceImportError("invalid-response", "Figma returned an invalid response.");
733
- return body.document;
764
+ if (!body || body.err || body.error === true || typeof body.status === "number" && body.status >= 400) throw new SourceImportError("invalid-response", request.errorMessage);
765
+ if (Array.isArray(body.errors) && body.errors.length > 0) throw new SourceImportError("upstream-failed", `Figma rejected the request: ${body.errors.map((entry) => {
766
+ const reason = record(entry)?.error;
767
+ return typeof reason === "string" ? reason : "unknown error";
768
+ }).join("; ")}`);
769
+ return body;
770
+ }
771
+ function figmaFileEndpoint(fileKey, path) {
772
+ return new URL(`https://api.figma.com/v1/files/${encodeURIComponent(fileKey)}${path}`);
773
+ }
774
+ /** Every Fundus tag link in the file (orphaned ones included); each entry has its `linkId`. */
775
+ async function listFigmaTagEntries(fileKey, context) {
776
+ const links = figmaLinksFromRest(await requestFigmaApi(figmaFileEndpoint(fileKey, "/dev_resources"), context, {
777
+ scope: "file_dev_resources:read",
778
+ errorMessage: "Figma returned an invalid response."
779
+ }));
780
+ if (!links) throw new SourceImportError("invalid-response", "Figma returned an invalid Dev Resources list.");
781
+ return figmaTagEntries(links).filter((entry) => entry.linkId !== void 0);
782
+ }
783
+ /** Export URLs for the nodes in one `/images` call; `null` for a node Figma cannot render. */
784
+ async function exportImageUrls(fileKey, nodeIds, scale, context) {
785
+ const endpoint = new URL(`https://api.figma.com/v1/images/${encodeURIComponent(fileKey)}`);
786
+ endpoint.searchParams.set("ids", nodeIds.join(","));
787
+ endpoint.searchParams.set("format", "png");
788
+ endpoint.searchParams.set("scale", String(scale));
789
+ const images = record((await requestFigmaApi(endpoint, context, {
790
+ scope: "file_content:read",
791
+ errorMessage: "Figma could not render this node."
792
+ })).images);
793
+ const urls = {};
794
+ for (const nodeId of nodeIds) {
795
+ if (!images || !Object.hasOwn(images, nodeId)) throw new SourceImportError("invalid-response", "Figma did not return the requested node.");
796
+ const imageUrl = images[nodeId];
797
+ urls[nodeId] = typeof imageUrl === "string" && imageUrl.length > 0 ? imageUrl : null;
798
+ }
799
+ return urls;
734
800
  }
735
- async function resolveTagToNode(fileKey, tag, context) {
736
- const matches = figmaDocumentNodes(await fetchFigmaDocument(fileKey, context)).filter((node) => node.tag === tag);
737
- if (matches.length === 0) throw new SourceImportError("not-found", `No Figma node is tagged "${tag}" in this file.`);
738
- if (matches.length > 1) throw new SourceImportError("ambiguous-tag", `More than one Figma node is tagged "${tag}" in this file.`);
739
- return matches[0].nodeId;
801
+ /**
802
+ * The one renderable node carrying `tag`. All candidates go into a single
803
+ * `/images` call, which answers deleted nodes with `null`; a live but
804
+ * unrenderable second candidate therefore goes unnoticed.
805
+ */
806
+ async function resolveTaggedNode(fileKey, tag, scale, context) {
807
+ const candidates = [...new Set((await listFigmaTagEntries(fileKey, context)).filter((entry) => entry.tag === tag).map((entry) => entry.nodeId))];
808
+ if (candidates.length === 0) throw new SourceImportError("not-found", `No Figma node is tagged "${tag}" in this file.`);
809
+ const urls = await exportImageUrls(fileKey, candidates, scale, context);
810
+ const live = candidates.flatMap((nodeId) => {
811
+ const imageUrl = urls[nodeId];
812
+ return imageUrl ? [{
813
+ nodeId,
814
+ imageUrl
815
+ }] : [];
816
+ });
817
+ if (live.length === 0) throw new SourceImportError("not-found", `Every Figma node tagged "${tag}" (${candidates.join(", ")}) is deleted or cannot be rendered.`);
818
+ if (live.length > 1) throw new SourceImportError("ambiguous-tag", `More than one Figma node is tagged "${tag}" in this file (${live.map((node) => node.nodeId).join(", ")}).`);
819
+ return live[0];
740
820
  }
741
- async function materialize(source, context) {
742
- const token = context.config.import.figma.token;
743
- if (!token) throw new SourceImportError("not-configured", "Figma access is not configured.");
744
- const endpoint = new URL(`https://api.figma.com/v1/images/${encodeURIComponent(source.fileKey)}`);
745
- endpoint.searchParams.set("ids", source.nodeId);
746
- endpoint.searchParams.set("format", source.format);
747
- endpoint.searchParams.set("scale", String(source.scale));
748
- const jsonBytes = await fetchWithDeadline(context.fetch, endpoint, {
749
- redirect: "error",
750
- headers: { "X-Figma-Token": token }
751
- }, async (response) => new Uint8Array(await response.arrayBuffer()));
752
- let payload;
753
- try {
754
- payload = JSON.parse(new TextDecoder().decode(jsonBytes));
755
- } catch {
756
- throw new SourceImportError("invalid-response", "Figma returned an invalid response.");
757
- }
758
- const body = record(payload);
759
- if (!body || body.err || typeof body.status === "number" && body.status >= 400) throw new SourceImportError("invalid-response", "Figma could not render this node.");
760
- const images = record(body.images);
761
- if (!images || !Object.hasOwn(images, source.nodeId)) throw new SourceImportError("invalid-response", "Figma did not return the requested node.");
762
- const imageUrl = images[source.nodeId];
763
- if (typeof imageUrl !== "string" || imageUrl.length === 0) throw new SourceImportError("invalid-response", "Figma could not render the requested node.");
821
+ async function downloadRaw(source, imageUrl, context) {
764
822
  const bytes = await downloadExport(context.httpsTransport ?? requestPinnedHttps, imageUrl);
765
823
  await validatePng(bytes);
766
824
  return {
@@ -772,6 +830,18 @@ async function materialize(source, context) {
772
830
  }
773
831
  };
774
832
  }
833
+ async function importNode(source, context) {
834
+ const imageUrl = (await exportImageUrls(source.fileKey, [source.nodeId], source.scale, context))[source.nodeId];
835
+ if (!imageUrl) throw new SourceImportError("invalid-response", "Figma could not render the requested node.");
836
+ return downloadRaw(source, imageUrl, context);
837
+ }
838
+ async function importTag(source, context) {
839
+ const { nodeId, imageUrl } = await resolveTaggedNode(source.fileKey, source.fundusTag, source.scale, context);
840
+ return downloadRaw({
841
+ ...source,
842
+ nodeId
843
+ }, imageUrl, context);
844
+ }
775
845
  var figmaSourceImporter = {
776
846
  kind: "figma",
777
847
  label: "Figma",
@@ -780,18 +850,16 @@ var figmaSourceImporter = {
780
850
  if (input.mode === "tag") {
781
851
  const fileKey = input.fileKey ?? context.config.import.figma.defaultFileKey;
782
852
  if (!fileKey) throw new SourceImportError("not-configured", "Figma tag import needs a fileKey or import.figma.defaultFileKey in fundus.config.");
783
- const nodeId = await resolveTagToNode(fileKey, input.tag, context);
784
- return materialize({
853
+ return importTag({
785
854
  mode: "tag",
786
855
  fileKey,
787
856
  fundusTag: input.tag,
788
- nodeId,
789
857
  format: "png",
790
858
  scale: input.scale ?? context.config.import.figma.defaults.scale
791
859
  }, context);
792
860
  }
793
861
  const parsed = parseFigmaSelectionUrl(input.url);
794
- return materialize({
862
+ return importNode({
795
863
  fileKey: parsed.fileKey,
796
864
  nodeId: parsed.nodeId,
797
865
  format: "png",
@@ -800,14 +868,8 @@ var figmaSourceImporter = {
800
868
  },
801
869
  validateSourceParameters: validateFigmaSourceParameters,
802
870
  async reimportRaw(source, context) {
803
- if (source.mode === "tag") {
804
- const nodeId = await resolveTagToNode(source.fileKey, source.fundusTag, context);
805
- return materialize({
806
- ...source,
807
- nodeId
808
- }, context);
809
- }
810
- return materialize(source, context);
871
+ if (source.mode === "tag") return importTag(source, context);
872
+ return importNode(source, context);
811
873
  }
812
874
  };
813
875
  //#endregion
@@ -2514,4 +2576,4 @@ async function createFundusContext() {
2514
2576
  }
2515
2577
 
2516
2578
  export { getFundusContext as g, initializeFundusContext as i };
2517
- //# sourceMappingURL=context.js-BZSZNuAd.js.map
2579
+ //# sourceMappingURL=context.js-DFZgDxCD.js.map