fundus 0.5.0 → 0.7.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.
- package/README.md +137 -130
- package/build/client/_app/immutable/assets/0.CHekvMpo.css +1 -0
- package/build/client/_app/immutable/assets/0.CHekvMpo.css.br +0 -0
- package/build/client/_app/immutable/assets/0.CHekvMpo.css.gz +0 -0
- package/build/client/_app/immutable/assets/2.Bf0JkVBM.css +1 -0
- package/build/client/_app/immutable/assets/2.Bf0JkVBM.css.br +0 -0
- package/build/client/_app/immutable/assets/2.Bf0JkVBM.css.gz +0 -0
- package/build/client/_app/immutable/assets/FileChangeBadge.C6wwUZJS.css +1 -0
- package/build/client/_app/immutable/assets/FileChangeBadge.C6wwUZJS.css.br +0 -0
- package/build/client/_app/immutable/assets/FileChangeBadge.C6wwUZJS.css.gz +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.BSnKt_Is.css +1 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.BSnKt_Is.css.br +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.BSnKt_Is.css.gz +0 -0
- package/build/client/_app/immutable/assets/ManifestSelector.Cue3sCA1.css +1 -0
- package/build/client/_app/immutable/assets/ManifestSelector.Cue3sCA1.css.br +0 -0
- package/build/client/_app/immutable/assets/ManifestSelector.Cue3sCA1.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B9iWbZmZ.js +1 -0
- package/build/client/_app/immutable/chunks/B9iWbZmZ.js.br +0 -0
- package/build/client/_app/immutable/chunks/B9iWbZmZ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BD3hQKzV.js +1 -0
- package/build/client/_app/immutable/chunks/BD3hQKzV.js.br +0 -0
- package/build/client/_app/immutable/chunks/BD3hQKzV.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Blpvahbd.js +108 -0
- package/build/client/_app/immutable/chunks/Blpvahbd.js.br +0 -0
- package/build/client/_app/immutable/chunks/Blpvahbd.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C7Cs5PXV.js +1 -0
- package/build/client/_app/immutable/chunks/C7Cs5PXV.js.br +0 -0
- package/build/client/_app/immutable/chunks/C7Cs5PXV.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DPZDGjcn.js +1 -0
- package/build/client/_app/immutable/chunks/DPZDGjcn.js.br +0 -0
- package/build/client/_app/immutable/chunks/DPZDGjcn.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CN-G-m-B.js → DrsNq6gf.js} +1 -1
- package/build/client/_app/immutable/chunks/DrsNq6gf.js.br +0 -0
- package/build/client/_app/immutable/chunks/DrsNq6gf.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DylBiD8l.js +1 -0
- package/build/client/_app/immutable/chunks/DylBiD8l.js.br +0 -0
- package/build/client/_app/immutable/chunks/DylBiD8l.js.gz +0 -0
- package/build/client/_app/immutable/chunks/NblqapDQ.js +3 -0
- package/build/client/_app/immutable/chunks/NblqapDQ.js.br +0 -0
- package/build/client/_app/immutable/chunks/NblqapDQ.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.CFPPKVrc.js +2 -0
- package/build/client/_app/immutable/entry/app.CFPPKVrc.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CFPPKVrc.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.tn-ZAKbY.js +1 -0
- package/build/client/_app/immutable/entry/start.tn-ZAKbY.js.br +0 -0
- package/build/client/_app/immutable/entry/start.tn-ZAKbY.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.BS8VwNas.js +2 -0
- package/build/client/_app/immutable/nodes/0.BS8VwNas.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.BS8VwNas.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.Dpaug5O_.js +1 -0
- package/build/client/_app/immutable/nodes/1.Dpaug5O_.js.br +2 -0
- package/build/client/_app/immutable/nodes/1.Dpaug5O_.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.KyqEUB3M.js +3 -0
- package/build/client/_app/immutable/nodes/2.KyqEUB3M.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.KyqEUB3M.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.j8JVBjzd.js +1 -0
- package/build/client/_app/immutable/nodes/3.j8JVBjzd.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.j8JVBjzd.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.CiYE8hwS.js +2 -0
- package/build/client/_app/immutable/nodes/4.CiYE8hwS.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.CiYE8hwS.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/handler.js +7 -7
- package/build/index.js +7 -7
- package/build/server/chunks/chunks/{context.js-bXe5hzjI.js → context.js-CLnT3cF3.js} +124 -7
- package/build/server/chunks/chunks/context.js-CLnT3cF3.js.map +1 -0
- package/build/server/chunks/chunks/{contract.js-sHny3b-s.js → contract.js-DGMufT2e.js} +191 -178
- package/build/server/chunks/chunks/contract.js-DGMufT2e.js.map +1 -0
- package/build/server/chunks/chunks/{core.js-Clg1CHb6.js → core.js-DNIuZ9y-.js} +88 -2
- package/build/server/chunks/chunks/core.js-DNIuZ9y-.js.map +1 -0
- package/build/server/chunks/chunks/{exports.js-FRj9eAnR.js → exports.js-CAJ9ZQQx.js} +2 -2
- package/build/server/chunks/chunks/{exports.js-FRj9eAnR.js.map → exports.js-CAJ9ZQQx.js.map} +1 -1
- package/build/server/chunks/chunks/{http.js--6sDZFfm.js → http.js-DWYlsbZd.js} +2 -2
- package/build/server/chunks/chunks/{http.js--6sDZFfm.js.map → http.js-DWYlsbZd.js.map} +1 -1
- package/build/server/chunks/chunks/{internal.js-D2Tk-vi1.js → internal.js-CdY4S4Uy.js} +3 -3
- package/build/server/chunks/chunks/{internal.js-D2Tk-vi1.js.map → internal.js-CdY4S4Uy.js.map} +1 -1
- package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -1
- package/build/server/chunks/chunks/manifest-membership.js-CJnQXrL4.js +213 -0
- package/build/server/chunks/chunks/manifest-membership.js-CJnQXrL4.js.map +1 -0
- package/build/server/chunks/chunks/raw-reconciliation.js-_D9lZ_sc.js +11 -0
- package/build/server/chunks/chunks/raw-reconciliation.js-_D9lZ_sc.js.map +1 -0
- package/build/server/chunks/chunks/{raw-reconciliation.js-DOFtjkgu.js → raw-reconciliation2.js-C2No1QIL.js} +3 -34
- package/build/server/chunks/chunks/raw-reconciliation2.js-C2No1QIL.js.map +1 -0
- package/build/server/chunks/chunks/{shared.js-hvokB2mY.js → shared.js-C34rGnTQ.js} +2 -2
- package/build/server/chunks/chunks/{shared.js-hvokB2mY.js.map → shared.js-C34rGnTQ.js.map} +1 -1
- package/build/server/chunks/chunks/{utils.js-VGlYdWt0.js → utils.js-BMCQVogA.js} +3 -3
- package/build/server/chunks/chunks/{utils.js-VGlYdWt0.js.map → utils.js-BMCQVogA.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-CkSErIdC.js → _server.ts.js-Bmyh2WUa.js} +7 -6
- package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-CkSErIdC.js.map → _server.ts.js-Bmyh2WUa.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-Csnt5ISN.js → _server.ts.js-IMleqOQb.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-Csnt5ISN.js.map → _server.ts.js-IMleqOQb.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-BVEQaFEu.js → _server.ts.js-DzFoWnCN.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-BVEQaFEu.js.map → _server.ts.js-DzFoWnCN.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-DIaT5h8R.js → _server.ts.js-0LjvQ5dF.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-DIaT5h8R.js.map → _server.ts.js-0LjvQ5dF.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-CgCr-jFC.js → _server.ts.js-BUbO2k7N.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-CgCr-jFC.js.map → _server.ts.js-BUbO2k7N.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-BCvv4wq4.js → _server.ts.js-CwFLvCzR.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-BCvv4wq4.js.map → _server.ts.js-CwFLvCzR.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-GbxbM9uI.js → _server.ts.js-BA6bgOR_.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-GbxbM9uI.js.map → _server.ts.js-BA6bgOR_.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-BGjOvpRm.js → _server.ts.js-CzzmQqXq.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-BGjOvpRm.js.map → _server.ts.js-CzzmQqXq.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-CJuzJXPs.js → _server.ts.js-aqJkae-h.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-CJuzJXPs.js.map → _server.ts.js-aqJkae-h.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-BYp42p6V.js → _server.ts.js-CGsIZ1tO.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-BYp42p6V.js.map → _server.ts.js-CGsIZ1tO.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-l_tkhnQ-.js → _server.ts.js-DbaeknBw.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-l_tkhnQ-.js.map → _server.ts.js-DbaeknBw.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-B-VXO3Xr.js → _server.ts.js-BhY5m7VP.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-B-VXO3Xr.js.map → _server.ts.js-BhY5m7VP.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-DV7s20GV.js → _server.ts.js-PT92H6EE.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-DV7s20GV.js.map → _server.ts.js-PT92H6EE.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-CYgOpWYC.js → _server.ts.js-DtiUkpdM.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-CYgOpWYC.js.map → _server.ts.js-DtiUkpdM.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-7loll6HR.js → _server.ts.js-tVkpwUwF.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-7loll6HR.js.map → _server.ts.js-tVkpwUwF.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-CdxeTMZj.js → _server.ts.js-Cq85RWhU.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-CdxeTMZj.js.map → _server.ts.js-Cq85RWhU.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-CZWIskM4.js → _server.ts.js-DDdYWvN4.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-CZWIskM4.js.map → _server.ts.js-DDdYWvN4.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-CZFfpJkl.js → _server.ts.js-DxSPXWoT.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-CZFfpJkl.js.map → _server.ts.js-DxSPXWoT.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-DB3i4juR.js → _server.ts.js-DVtQlFHS.js} +7 -6
- package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-DB3i4juR.js.map → _server.ts.js-DVtQlFHS.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-BqarqenW.js → _server.ts.js-DuStxYsU.js} +8 -7
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-BqarqenW.js.map → _server.ts.js-DuStxYsU.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-CXbrUCmh.js → _server.ts.js-CxoKyl-h.js} +8 -7
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-CXbrUCmh.js.map → _server.ts.js-CxoKyl-h.js.map} +1 -1
- package/build/server/chunks/entries/{hooks.server.js-6Yf-GF0J.js → hooks.server.js-DLJAlp7i.js} +7 -6
- package/build/server/chunks/entries/{hooks.server.js-6Yf-GF0J.js.map → hooks.server.js-DLJAlp7i.js.map} +1 -1
- package/build/server/chunks/{handler-DHAu99Rv.js → handler-Bn4TsL93.js} +5 -5
- package/build/server/chunks/{handler-DHAu99Rv.js.map → handler-Bn4TsL93.js.map} +1 -1
- package/build/server/chunks/{index.js-Bm1XIAPD.js → index.js-DzYQtf0T.js} +5 -5
- package/build/server/chunks/{index.js-Bm1XIAPD.js.map → index.js-DzYQtf0T.js.map} +1 -1
- package/build/server/chunks/{manifest.js-CCc26-hb.js → manifest.js-DewM2Q1D.js} +28 -28
- package/build/server/chunks/{manifest.js-CCc26-hb.js.map → manifest.js-DewM2Q1D.js.map} +1 -1
- package/build/server/chunks/nodes/0.js-CZe1W9_P.js +11 -0
- package/build/server/chunks/nodes/0.js-CZe1W9_P.js.map +1 -0
- package/build/server/chunks/nodes/1.js-DKVH5bGU.js +7 -0
- package/build/server/chunks/nodes/{1.js-CXgbNa8h.js.map → 1.js-DKVH5bGU.js.map} +1 -1
- package/build/server/chunks/nodes/2.js-BpN0Hxjo.js +7 -0
- package/build/server/chunks/nodes/2.js-BpN0Hxjo.js.map +1 -0
- package/build/server/chunks/nodes/3.js-D3kgOm0S.js +7 -0
- package/build/server/chunks/nodes/3.js-D3kgOm0S.js.map +1 -0
- package/build/server/chunks/nodes/4.js-CZwje1Lo.js +7 -0
- package/build/server/chunks/nodes/{4.js-BUgaRCEY.js.map → 4.js-CZwje1Lo.js.map} +1 -1
- package/dist/core/api-types.d.ts +4 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/core/plugins/slice.d.ts +28 -4
- package/dist/core/plugins/slice.js +50 -0
- package/dist/server/cli-commands.d.ts +1 -1
- package/dist/server/cli-commands.js +125 -11
- package/dist/server/config-loader.d.ts +2 -0
- package/dist/server/config-loader.js +1 -0
- package/dist/server/git.d.ts +9 -0
- package/dist/server/git.js +121 -0
- package/dist/server/library-store.d.ts +1 -1
- package/dist/server/library-store.js +5 -1
- package/dist/server/operations.js +28 -2
- package/dist/server/plugins/slice.d.ts +3 -2
- package/dist/server/plugins/slice.js +21 -9
- package/dist/server/processing/slice-processing.d.ts +14 -0
- package/dist/server/processing/slice-processing.js +148 -0
- package/package.json +1 -1
- package/build/client/_app/immutable/assets/0.inkPq3ni.css +0 -1
- package/build/client/_app/immutable/assets/0.inkPq3ni.css.br +0 -0
- package/build/client/_app/immutable/assets/0.inkPq3ni.css.gz +0 -0
- package/build/client/_app/immutable/assets/2.DLP0pEak.css +0 -1
- package/build/client/_app/immutable/assets/2.DLP0pEak.css.br +0 -0
- package/build/client/_app/immutable/assets/2.DLP0pEak.css.gz +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.CVb-Lqdf.css +0 -1
- package/build/client/_app/immutable/assets/LibraryContextMenu.CVb-Lqdf.css.br +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.CVb-Lqdf.css.gz +0 -0
- package/build/client/_app/immutable/assets/ManifestSelector.Il8p28r8.css +0 -1
- package/build/client/_app/immutable/assets/ManifestSelector.Il8p28r8.css.br +0 -0
- package/build/client/_app/immutable/assets/ManifestSelector.Il8p28r8.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B1UabfW7.js +0 -1
- package/build/client/_app/immutable/chunks/B1UabfW7.js.br +0 -0
- package/build/client/_app/immutable/chunks/B1UabfW7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BmCZn5E-.js +0 -108
- package/build/client/_app/immutable/chunks/BmCZn5E-.js.br +0 -0
- package/build/client/_app/immutable/chunks/BmCZn5E-.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BoEHtxM8.js +0 -1
- package/build/client/_app/immutable/chunks/BoEHtxM8.js.br +0 -0
- package/build/client/_app/immutable/chunks/BoEHtxM8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C-T1_s5P.js +0 -1
- package/build/client/_app/immutable/chunks/C-T1_s5P.js.br +0 -0
- package/build/client/_app/immutable/chunks/C-T1_s5P.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CN-G-m-B.js.br +0 -4
- package/build/client/_app/immutable/chunks/CN-G-m-B.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D5sQSsUv.js +0 -1
- package/build/client/_app/immutable/chunks/D5sQSsUv.js.br +0 -0
- package/build/client/_app/immutable/chunks/D5sQSsUv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D65cSBhe.js +0 -3
- package/build/client/_app/immutable/chunks/D65cSBhe.js.br +0 -0
- package/build/client/_app/immutable/chunks/D65cSBhe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D6VoU_x4.js +0 -1
- package/build/client/_app/immutable/chunks/D6VoU_x4.js.br +0 -0
- package/build/client/_app/immutable/chunks/D6VoU_x4.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.fVDDVV_y.js +0 -2
- package/build/client/_app/immutable/entry/app.fVDDVV_y.js.br +0 -0
- package/build/client/_app/immutable/entry/app.fVDDVV_y.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BiWgLLju.js +0 -1
- package/build/client/_app/immutable/entry/start.BiWgLLju.js.br +0 -1
- package/build/client/_app/immutable/entry/start.BiWgLLju.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.BLnSe7Ya.js +0 -2
- package/build/client/_app/immutable/nodes/0.BLnSe7Ya.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.BLnSe7Ya.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.DEw3d5yL.js +0 -1
- package/build/client/_app/immutable/nodes/1.DEw3d5yL.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.DEw3d5yL.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.DnVTXPVk.js +0 -3
- package/build/client/_app/immutable/nodes/2.DnVTXPVk.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.DnVTXPVk.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.1Hco6zU7.js +0 -1
- package/build/client/_app/immutable/nodes/3.1Hco6zU7.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.1Hco6zU7.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.CKbcoBw2.js +0 -2
- package/build/client/_app/immutable/nodes/4.CKbcoBw2.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.CKbcoBw2.js.gz +0 -0
- package/build/server/chunks/chunks/asset-id.js-CFsW8jeL.js +0 -48
- package/build/server/chunks/chunks/asset-id.js-CFsW8jeL.js.map +0 -1
- package/build/server/chunks/chunks/context.js-bXe5hzjI.js.map +0 -1
- package/build/server/chunks/chunks/contract.js-sHny3b-s.js.map +0 -1
- package/build/server/chunks/chunks/core.js-Clg1CHb6.js.map +0 -1
- package/build/server/chunks/chunks/raw-reconciliation.js-DOFtjkgu.js.map +0 -1
- package/build/server/chunks/chunks/raw-reconciliation2.js-DFwky2ou.js +0 -11
- package/build/server/chunks/chunks/raw-reconciliation2.js-DFwky2ou.js.map +0 -1
- package/build/server/chunks/nodes/0.js-Bpzcq6LZ.js +0 -11
- package/build/server/chunks/nodes/0.js-Bpzcq6LZ.js.map +0 -1
- package/build/server/chunks/nodes/1.js-CXgbNa8h.js +0 -7
- package/build/server/chunks/nodes/2.js-D56ryWAu.js +0 -7
- package/build/server/chunks/nodes/2.js-D56ryWAu.js.map +0 -1
- package/build/server/chunks/nodes/3.js-DMaZRwrN.js +0 -7
- package/build/server/chunks/nodes/3.js-DMaZRwrN.js.map +0 -1
- package/build/server/chunks/nodes/4.js-BUgaRCEY.js +0 -7
|
@@ -257,10 +257,13 @@ Example:
|
|
|
257
257
|
export const ASSET_INGEST_HELP = `fundus asset ingest — acquire a file or Figma selection as a typed asset
|
|
258
258
|
|
|
259
259
|
Usage: fundus asset ingest <file> [--type <type>] [--id <id>] [--folder <path|root>]
|
|
260
|
-
[--manifests <a,b>] [--parameters <json>]
|
|
260
|
+
[--manifests <a,b>] [--parameters <json>]
|
|
261
|
+
[--compression-x <0-100>] [--compression-y <0-100>]
|
|
262
|
+
[--from file] [--json]
|
|
261
263
|
fundus asset ingest <figma-selection-link> --from figma --type <image|slice> --id <id>
|
|
262
264
|
[--scale <1|2|3|4>] [--folder <path|root>]
|
|
263
|
-
[--manifests <a,b>] [--parameters <json>]
|
|
265
|
+
[--manifests <a,b>] [--parameters <json>]
|
|
266
|
+
[--compression-x <0-100>] [--compression-y <0-100>] [--json]
|
|
264
267
|
|
|
265
268
|
File ingest remains the default and behaves like an editor upload. Figma
|
|
266
269
|
ingest materializes one selection as PNG through the same importer-neutral
|
|
@@ -278,6 +281,10 @@ Flags:
|
|
|
278
281
|
--manifests <a,b> explicit manifest membership (every name must exist)
|
|
279
282
|
--parameters <json> shallow parameter patch merged after ingest seeding
|
|
280
283
|
(see \`fundus asset set --help\`)
|
|
284
|
+
--compression-x <0-100>
|
|
285
|
+
--compression-y <0-100>
|
|
286
|
+
percentage compression of a Slice asset's horizontal or
|
|
287
|
+
vertical stretch region; omitted axes default to 0
|
|
281
288
|
--scale <1|2|3|4> Figma export scale; default:
|
|
282
289
|
import.figma.defaults.scale from fundus.config.ts
|
|
283
290
|
(invalid for file ingest)
|
|
@@ -287,7 +294,8 @@ Flags:
|
|
|
287
294
|
A failed ingest leaves neither a raw file nor a record behind.
|
|
288
295
|
|
|
289
296
|
Example:
|
|
290
|
-
fundus asset ingest ./exports/navigation_panel@2x.png --type slice
|
|
297
|
+
fundus asset ingest ./exports/navigation_panel@2x.png --type slice \\
|
|
298
|
+
--compression-x 75 --compression-y 25 --json
|
|
291
299
|
fundus asset ingest 'https://www.figma.com/design/abc/UI?node-id=12-34' \\
|
|
292
300
|
--from figma --type slice --id navigationPanel --scale 3 --json
|
|
293
301
|
`;
|
|
@@ -332,10 +340,11 @@ Example:
|
|
|
332
340
|
`;
|
|
333
341
|
export const ASSET_SET_HELP = `fundus asset set — update an asset's parameters and/or memberships
|
|
334
342
|
|
|
335
|
-
Usage: fundus asset set <id> [--parameters <json>] [--manifests <a,b>]
|
|
343
|
+
Usage: fundus asset set <id> [--parameters <json>] [--manifests <a,b>]
|
|
344
|
+
[--compression-x <0-100>] [--compression-y <0-100>] [--json]
|
|
336
345
|
|
|
337
|
-
At least one
|
|
338
|
-
|
|
346
|
+
At least one change flag is required. Runs the full autosave chain
|
|
347
|
+
(write library → process → regenerate manifest modules).
|
|
339
348
|
|
|
340
349
|
Flags:
|
|
341
350
|
--parameters <json> SHALLOW MERGE at the top level onto the current
|
|
@@ -351,6 +360,12 @@ Flags:
|
|
|
351
360
|
reference
|
|
352
361
|
--manifests <a,b> REPLACES the explicit membership set (declarative,
|
|
353
362
|
idempotent); --manifests "" clears it
|
|
363
|
+
--compression-x <0-100>
|
|
364
|
+
--compression-y <0-100>
|
|
365
|
+
set one Slice stretch-compression axis while preserving
|
|
366
|
+
the omitted axis; setting both axes to 0 removes
|
|
367
|
+
compression. These values override compression supplied
|
|
368
|
+
through --parameters in the same invocation
|
|
354
369
|
--json print {"ok": true, "asset": <AssetStateDto>, "issues": […]}
|
|
355
370
|
--help this help
|
|
356
371
|
|
|
@@ -360,6 +375,7 @@ asset, a reference cycle, or an unknown manifest name. Ingest reference
|
|
|
360
375
|
targets before pointing at them.
|
|
361
376
|
|
|
362
377
|
Example:
|
|
378
|
+
fundus asset set navigationPanel --compression-x 75 --compression-y 25 --json
|
|
363
379
|
fundus asset set characterIdle \\
|
|
364
380
|
--parameters '{"mask": {"$asset": "characterIdleMask"}}' --json
|
|
365
381
|
`;
|
|
@@ -492,6 +508,70 @@ function inferTypeForFileName(fileName) {
|
|
|
492
508
|
}
|
|
493
509
|
throw new Error(`The ".${extension}" extension is ambiguous — pass --type <${candidates.join('|')}>.`);
|
|
494
510
|
}
|
|
511
|
+
function parseCompressionPercentage(name, value, commandPath) {
|
|
512
|
+
if (value === undefined)
|
|
513
|
+
return undefined;
|
|
514
|
+
if (typeof value !== 'string' || !/^\d+$/.test(value) || Number(value) > 100) {
|
|
515
|
+
throw new CliUsageError(`Flag "--${name}" must be an integer from 0 to 100 — run \`${commandPath} --help\`.`);
|
|
516
|
+
}
|
|
517
|
+
return Number(value);
|
|
518
|
+
}
|
|
519
|
+
function parseSliceCompressionFlags(flags, commandPath) {
|
|
520
|
+
const x = parseCompressionPercentage('compression-x', flags['compression-x'], commandPath);
|
|
521
|
+
const y = parseCompressionPercentage('compression-y', flags['compression-y'], commandPath);
|
|
522
|
+
if (x === undefined && y === undefined)
|
|
523
|
+
return undefined;
|
|
524
|
+
return {
|
|
525
|
+
...(x !== undefined ? { x } : {}),
|
|
526
|
+
...(y !== undefined ? { y } : {})
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
function parameterPatchRecord(parametersPatch) {
|
|
530
|
+
if (typeof parametersPatch !== 'object' ||
|
|
531
|
+
parametersPatch === null ||
|
|
532
|
+
Array.isArray(parametersPatch)) {
|
|
533
|
+
throw new Error('The parameter patch must be a JSON object, e.g. {"preset": "default"}.');
|
|
534
|
+
}
|
|
535
|
+
return parametersPatch;
|
|
536
|
+
}
|
|
537
|
+
function compressionFromParameters(parameters) {
|
|
538
|
+
if (typeof parameters !== 'object' || parameters === null || Array.isArray(parameters)) {
|
|
539
|
+
return { x: 0, y: 0 };
|
|
540
|
+
}
|
|
541
|
+
const compression = parameters.compression;
|
|
542
|
+
if (typeof compression !== 'object' || compression === null || Array.isArray(compression)) {
|
|
543
|
+
return { x: 0, y: 0 };
|
|
544
|
+
}
|
|
545
|
+
return compression;
|
|
546
|
+
}
|
|
547
|
+
/** Add the ergonomic per-axis flags to the generic top-level parameter patch. */
|
|
548
|
+
function applySliceCompressionFlags(options) {
|
|
549
|
+
if (options.flags === undefined)
|
|
550
|
+
return options.parametersPatch;
|
|
551
|
+
if (options.type !== 'slice') {
|
|
552
|
+
throw new CliUsageError(`Flags "--compression-x" and "--compression-y" are only valid for Slice assets — run \`${options.commandPath} --help\`.`);
|
|
553
|
+
}
|
|
554
|
+
const patch = options.parametersPatch === undefined ? {} : parameterPatchRecord(options.parametersPatch);
|
|
555
|
+
let compression = compressionFromParameters(options.currentParameters);
|
|
556
|
+
if (Object.hasOwn(patch, 'compression')) {
|
|
557
|
+
if (patch.compression === null) {
|
|
558
|
+
compression = { x: 0, y: 0 };
|
|
559
|
+
}
|
|
560
|
+
else if (typeof patch.compression === 'object' &&
|
|
561
|
+
patch.compression !== null &&
|
|
562
|
+
!Array.isArray(patch.compression)) {
|
|
563
|
+
compression = { ...compression, ...patch.compression };
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
throw new Error('Slice compression must be an object with x/y percentages.');
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
const nextCompression = { ...compression, ...options.flags };
|
|
570
|
+
return {
|
|
571
|
+
...patch,
|
|
572
|
+
compression: nextCompression.x === 0 && nextCompression.y === 0 ? null : nextCompression
|
|
573
|
+
};
|
|
574
|
+
}
|
|
495
575
|
async function runAssetIngest(argumentList) {
|
|
496
576
|
const parsed = parseArguments(argumentList, {
|
|
497
577
|
...COMMON_FLAGS,
|
|
@@ -499,6 +579,8 @@ async function runAssetIngest(argumentList) {
|
|
|
499
579
|
id: { takesValue: true },
|
|
500
580
|
manifests: { takesValue: true },
|
|
501
581
|
parameters: { takesValue: true },
|
|
582
|
+
'compression-x': { takesValue: true },
|
|
583
|
+
'compression-y': { takesValue: true },
|
|
502
584
|
folder: { takesValue: true },
|
|
503
585
|
from: { takesValue: true },
|
|
504
586
|
scale: { takesValue: true }
|
|
@@ -514,9 +596,10 @@ async function runAssetIngest(argumentList) {
|
|
|
514
596
|
if (from === 'file' && scale !== undefined) {
|
|
515
597
|
throw new CliUsageError('Flag "--scale" is only valid with `--from figma` — run `fundus asset ingest --help`.');
|
|
516
598
|
}
|
|
517
|
-
|
|
599
|
+
let parametersPatch = typeof parsed.flags.parameters === 'string'
|
|
518
600
|
? parseJsonFlag('parameters', parsed.flags.parameters)
|
|
519
601
|
: undefined;
|
|
602
|
+
const compressionFlags = parseSliceCompressionFlags(parsed.flags, 'fundus asset ingest');
|
|
520
603
|
const manifests = typeof parsed.flags.manifests === 'string'
|
|
521
604
|
? parseManifestList(parsed.flags.manifests)
|
|
522
605
|
: undefined;
|
|
@@ -531,6 +614,12 @@ async function runAssetIngest(argumentList) {
|
|
|
531
614
|
}
|
|
532
615
|
const id = parsed.flags.id;
|
|
533
616
|
const type = parsed.flags.type;
|
|
617
|
+
parametersPatch = applySliceCompressionFlags({
|
|
618
|
+
type,
|
|
619
|
+
flags: compressionFlags,
|
|
620
|
+
parametersPatch,
|
|
621
|
+
commandPath: 'fundus asset ingest'
|
|
622
|
+
});
|
|
534
623
|
const operations = await createOperations();
|
|
535
624
|
const state = await operations.importAsset({
|
|
536
625
|
importer: 'figma',
|
|
@@ -561,6 +650,12 @@ async function runAssetIngest(argumentList) {
|
|
|
561
650
|
const fileName = basename(absolutePath);
|
|
562
651
|
const type = typeof parsed.flags.type === 'string' ? parsed.flags.type : inferTypeForFileName(fileName);
|
|
563
652
|
const id = typeof parsed.flags.id === 'string' ? parsed.flags.id : proposeAssetId(fileName);
|
|
653
|
+
parametersPatch = applySliceCompressionFlags({
|
|
654
|
+
type,
|
|
655
|
+
flags: compressionFlags,
|
|
656
|
+
parametersPatch,
|
|
657
|
+
commandPath: 'fundus asset ingest'
|
|
658
|
+
});
|
|
564
659
|
const operations = await createOperations();
|
|
565
660
|
const state = await operations.ingest({
|
|
566
661
|
fileName,
|
|
@@ -649,18 +744,37 @@ async function runAssetReplace(argumentList) {
|
|
|
649
744
|
printMutationResult(`Replaced raw file for asset "${id}" with "${fileName}".`, asset, state);
|
|
650
745
|
}
|
|
651
746
|
async function runAssetSet(argumentList) {
|
|
652
|
-
const parsed = parseArguments(argumentList, {
|
|
747
|
+
const parsed = parseArguments(argumentList, {
|
|
748
|
+
...COMMON_FLAGS,
|
|
749
|
+
parameters: { takesValue: true },
|
|
750
|
+
manifests: { takesValue: true },
|
|
751
|
+
'compression-x': { takesValue: true },
|
|
752
|
+
'compression-y': { takesValue: true }
|
|
753
|
+
}, 'fundus asset set');
|
|
653
754
|
const [id] = requirePositionals(parsed, ['<id>'], 'fundus asset set');
|
|
654
|
-
|
|
655
|
-
|
|
755
|
+
const compressionFlags = parseSliceCompressionFlags(parsed.flags, 'fundus asset set');
|
|
756
|
+
if (parsed.flags.parameters === undefined &&
|
|
757
|
+
parsed.flags.manifests === undefined &&
|
|
758
|
+
compressionFlags === undefined) {
|
|
759
|
+
throw new CliUsageError('`fundus asset set` needs --parameters and/or --manifests, or a compression flag — run `fundus asset set --help`.');
|
|
656
760
|
}
|
|
657
|
-
|
|
761
|
+
let parametersPatch = typeof parsed.flags.parameters === 'string'
|
|
658
762
|
? parseJsonFlag('parameters', parsed.flags.parameters)
|
|
659
763
|
: undefined;
|
|
660
764
|
const manifests = typeof parsed.flags.manifests === 'string'
|
|
661
765
|
? parseManifestList(parsed.flags.manifests)
|
|
662
766
|
: undefined;
|
|
663
767
|
const operations = await createOperations();
|
|
768
|
+
if (compressionFlags !== undefined) {
|
|
769
|
+
const currentAsset = assetById(await operations.state(), id);
|
|
770
|
+
parametersPatch = applySliceCompressionFlags({
|
|
771
|
+
type: currentAsset.type,
|
|
772
|
+
flags: compressionFlags,
|
|
773
|
+
parametersPatch,
|
|
774
|
+
currentParameters: currentAsset.parameters,
|
|
775
|
+
commandPath: 'fundus asset set'
|
|
776
|
+
});
|
|
777
|
+
}
|
|
664
778
|
const state = await operations.setAsset(id, { parametersPatch, manifests });
|
|
665
779
|
const asset = assetById(state, id);
|
|
666
780
|
if (parsed.flags.json) {
|
|
@@ -14,6 +14,8 @@ export interface ResolvedAudioPluginConfig {
|
|
|
14
14
|
presets: Record<string, AudioPreset>;
|
|
15
15
|
}
|
|
16
16
|
export interface ResolvedFundusConfig {
|
|
17
|
+
/** Absolute host project directory containing fundus.config.ts. */
|
|
18
|
+
projectRoot: string;
|
|
17
19
|
/** All paths absolute. */
|
|
18
20
|
rawDir: string;
|
|
19
21
|
proxyDir: string;
|
|
@@ -71,6 +71,7 @@ export function resolveConfig(projectRoot, value, registry = serverPluginsByType
|
|
|
71
71
|
throw new Error('fundus.config: "import.figma.defaults.scale" must be 1, 2, 3, or 4.');
|
|
72
72
|
}
|
|
73
73
|
return {
|
|
74
|
+
projectRoot: resolve(projectRoot),
|
|
74
75
|
rawDir: resolvePath(projectRoot, requiredString(value, 'rawDir')),
|
|
75
76
|
proxyDir: resolvePath(projectRoot, requiredString(value, 'proxyDir')),
|
|
76
77
|
library: resolvePath(projectRoot, requiredString(value, 'library')),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type GitFileChange = 'new' | 'edited';
|
|
2
|
+
/** Current branch of the repository containing projectRoot; null outside Git or when detached. */
|
|
3
|
+
export declare function currentGitBranch(projectRoot: string): Promise<string | null>;
|
|
4
|
+
/**
|
|
5
|
+
* Raw Git file changes made since this branch diverged from the repository's
|
|
6
|
+
* default branch. Staged, unstaged, and untracked files are included so the
|
|
7
|
+
* editor updates immediately after an asset mutation, before the next commit.
|
|
8
|
+
*/
|
|
9
|
+
export declare function gitFileChanges(projectRoot: string): Promise<Map<string, GitFileChange>>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
async function git(projectRoot, args) {
|
|
6
|
+
const { stdout } = await execFileAsync('git', ['-C', projectRoot, ...args], {
|
|
7
|
+
encoding: 'utf8'
|
|
8
|
+
});
|
|
9
|
+
return stdout;
|
|
10
|
+
}
|
|
11
|
+
/** Current branch of the repository containing projectRoot; null outside Git or when detached. */
|
|
12
|
+
export async function currentGitBranch(projectRoot) {
|
|
13
|
+
try {
|
|
14
|
+
return (await git(projectRoot, ['branch', '--show-current'])).trim() || null;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function firstExistingRef(projectRoot, refs) {
|
|
21
|
+
for (const ref of refs) {
|
|
22
|
+
try {
|
|
23
|
+
await git(projectRoot, ['rev-parse', '--verify', '--quiet', ref]);
|
|
24
|
+
return ref;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Try the next conventional default-branch ref.
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
async function defaultBranchRef(projectRoot) {
|
|
33
|
+
try {
|
|
34
|
+
const remoteHead = (await git(projectRoot, ['symbolic-ref', '--quiet', '--short', 'refs/remotes/origin/HEAD'])).trim();
|
|
35
|
+
if (remoteHead)
|
|
36
|
+
return remoteHead;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Repositories without an origin/HEAD fall back to conventional branch names.
|
|
40
|
+
}
|
|
41
|
+
return firstExistingRef(projectRoot, [
|
|
42
|
+
'refs/remotes/origin/main',
|
|
43
|
+
'refs/remotes/origin/master',
|
|
44
|
+
'refs/heads/main',
|
|
45
|
+
'refs/heads/master'
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
function parseDiffNames(output, root) {
|
|
49
|
+
const changes = new Map();
|
|
50
|
+
const fields = output.split('\0');
|
|
51
|
+
for (let index = 0; index < fields.length;) {
|
|
52
|
+
const status = fields[index++];
|
|
53
|
+
if (!status)
|
|
54
|
+
continue;
|
|
55
|
+
const sourcePath = fields[index++];
|
|
56
|
+
if (!sourcePath)
|
|
57
|
+
continue;
|
|
58
|
+
if (status.startsWith('R') || status.startsWith('C')) {
|
|
59
|
+
const destinationPath = fields[index++];
|
|
60
|
+
if (!destinationPath)
|
|
61
|
+
continue;
|
|
62
|
+
changes.set(resolve(root, destinationPath), status.startsWith('C') ? 'new' : 'edited');
|
|
63
|
+
}
|
|
64
|
+
else if (status === 'A') {
|
|
65
|
+
changes.set(resolve(root, sourcePath), 'new');
|
|
66
|
+
}
|
|
67
|
+
else if (status !== 'D') {
|
|
68
|
+
changes.set(resolve(root, sourcePath), 'edited');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return changes;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Raw Git file changes made since this branch diverged from the repository's
|
|
75
|
+
* default branch. Staged, unstaged, and untracked files are included so the
|
|
76
|
+
* editor updates immediately after an asset mutation, before the next commit.
|
|
77
|
+
*/
|
|
78
|
+
export async function gitFileChanges(projectRoot) {
|
|
79
|
+
try {
|
|
80
|
+
const prefixParts = (await git(projectRoot, ['rev-parse', '--show-prefix']))
|
|
81
|
+
.trim()
|
|
82
|
+
.split('/')
|
|
83
|
+
.filter(Boolean);
|
|
84
|
+
const root = resolve(projectRoot, ...prefixParts.map(() => '..'));
|
|
85
|
+
const defaultRef = await defaultBranchRef(projectRoot);
|
|
86
|
+
let changes = new Map();
|
|
87
|
+
if (defaultRef) {
|
|
88
|
+
try {
|
|
89
|
+
const mergeBase = (await git(projectRoot, ['merge-base', 'HEAD', defaultRef])).trim();
|
|
90
|
+
if (mergeBase) {
|
|
91
|
+
changes = parseDiffNames(await git(projectRoot, [
|
|
92
|
+
'diff',
|
|
93
|
+
'--name-status',
|
|
94
|
+
'-z',
|
|
95
|
+
'--find-renames',
|
|
96
|
+
mergeBase,
|
|
97
|
+
'--'
|
|
98
|
+
]), root);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// An unborn or unrelated branch still has useful untracked-file state.
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const untracked = await git(projectRoot, [
|
|
106
|
+
'ls-files',
|
|
107
|
+
'--others',
|
|
108
|
+
'--exclude-standard',
|
|
109
|
+
'--full-name',
|
|
110
|
+
'-z'
|
|
111
|
+
]);
|
|
112
|
+
for (const path of untracked.split('\0')) {
|
|
113
|
+
if (path)
|
|
114
|
+
changes.set(resolve(root, path), 'new');
|
|
115
|
+
}
|
|
116
|
+
return changes;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return new Map();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -77,7 +77,7 @@ export declare class LibraryStore {
|
|
|
77
77
|
*/
|
|
78
78
|
replaceRawFile(id: string, options: ReplaceRawFileOptions): Promise<Library>;
|
|
79
79
|
/** CAS-protected replacement used only by a repeatable import source. */
|
|
80
|
-
replaceRawFromImportSource(id: string, bytes: Uint8Array, expected: ImportSourceExpectation, nextSource?: ImportSourceRecord): Promise<Library>;
|
|
80
|
+
replaceRawFromImportSource(id: string, bytes: Uint8Array, expected: ImportSourceExpectation, nextSource?: ImportSourceRecord, updateParameters?: (parameters: unknown) => unknown): Promise<Library>;
|
|
81
81
|
/** Replace an asset's parameters (validated by the owning plugin). */
|
|
82
82
|
updateParameters(id: string, parameters: unknown): Promise<Library>;
|
|
83
83
|
/** Replace an asset's manifest membership (every name must exist). */
|
|
@@ -248,7 +248,7 @@ export class LibraryStore {
|
|
|
248
248
|
return library;
|
|
249
249
|
}
|
|
250
250
|
/** CAS-protected replacement used only by a repeatable import source. */
|
|
251
|
-
async replaceRawFromImportSource(id, bytes, expected, nextSource) {
|
|
251
|
+
async replaceRawFromImportSource(id, bytes, expected, nextSource, updateParameters) {
|
|
252
252
|
return this.#enqueue(async () => {
|
|
253
253
|
const library = await this.read();
|
|
254
254
|
const record = this.#requireAsset(library, id);
|
|
@@ -272,6 +272,7 @@ export class LibraryStore {
|
|
|
272
272
|
const backupPath = `${absolutePath}.fundus-reimport-${token}`;
|
|
273
273
|
const previousHash = record.rawHash;
|
|
274
274
|
const previousSource = structuredClone(record.importSource);
|
|
275
|
+
const previousParameters = structuredClone(record.parameters);
|
|
275
276
|
let staged = false;
|
|
276
277
|
let installed = false;
|
|
277
278
|
try {
|
|
@@ -283,11 +284,14 @@ export class LibraryStore {
|
|
|
283
284
|
record.rawHash = sha256Hex(bytes);
|
|
284
285
|
if (nextSource)
|
|
285
286
|
record.importSource = structuredClone(nextSource);
|
|
287
|
+
if (updateParameters)
|
|
288
|
+
record.parameters = updateParameters(record.parameters);
|
|
286
289
|
await this.write(library);
|
|
287
290
|
}
|
|
288
291
|
catch (cause) {
|
|
289
292
|
record.rawHash = previousHash;
|
|
290
293
|
record.importSource = previousSource;
|
|
294
|
+
record.parameters = previousParameters;
|
|
291
295
|
if (installed)
|
|
292
296
|
await unlink(absolutePath).catch(() => { });
|
|
293
297
|
if (staged)
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and the CLI consume this class, so every
|
|
6
6
|
* operation has exactly one implementation and there is no other save path.
|
|
7
7
|
*/
|
|
8
|
-
import { join } from 'node:path';
|
|
8
|
+
import { join, resolve } from 'node:path';
|
|
9
9
|
import { assetIdError, allDeliveredAssetIds, canonicalizeParameters, collectAllReferences, compareCodeUnits, computeLibraryMembership, folderOfRawPath, normalizeFolderPath, parentFolderPath, portableFolderPathKey, proposeAssetId, rawFileNameOfPath, typesForFileName } from '../core/index.js';
|
|
10
10
|
import { LibraryStore } from './library-store.js';
|
|
11
11
|
import { generateManifestModules } from './codegen.js';
|
|
@@ -16,6 +16,8 @@ import { classifyRawDirectory, verifyStableRawFile } from './raw-reconciliation.
|
|
|
16
16
|
import { rawSafetyIssues } from './raw-safety.js';
|
|
17
17
|
import { serverImporters } from './importers.js';
|
|
18
18
|
import { SourceImportError } from './importers/contract.js';
|
|
19
|
+
import { validateFigmaSourceParameters } from './importers/figma.js';
|
|
20
|
+
import { currentGitBranch, gitFileChanges } from './git.js';
|
|
19
21
|
/**
|
|
20
22
|
* The CLI's `--parameters` merge semantics (M7): a SHALLOW merge at the top
|
|
21
23
|
* level onto the current parameters — a nested object value replaces the whole
|
|
@@ -42,6 +44,11 @@ export function mergeParameterPatch(currentParameters, patch) {
|
|
|
42
44
|
}
|
|
43
45
|
return merged;
|
|
44
46
|
}
|
|
47
|
+
function figmaSlicePixelRatio(raw, type) {
|
|
48
|
+
if (type !== 'slice' || raw.importSource?.importer !== 'figma')
|
|
49
|
+
return undefined;
|
|
50
|
+
return validateFigmaSourceParameters(raw.importSource.parameters).scale;
|
|
51
|
+
}
|
|
45
52
|
export class FundusOperations {
|
|
46
53
|
#config;
|
|
47
54
|
#registry;
|
|
@@ -310,9 +317,17 @@ export class FundusOperations {
|
|
|
310
317
|
if (!plugin.descriptor.accepts.includes(raw.extension)) {
|
|
311
318
|
throw new SourceImportError('invalid-response', `The ${snapshot.expected.type} type does not accept ".${raw.extension}" files.`);
|
|
312
319
|
}
|
|
320
|
+
// A missing input is a refresh of the saved source and deliberately
|
|
321
|
+
// preserves authored parameters. An explicit input is a reimport and
|
|
322
|
+
// synchronizes a Figma slice's pixel ratio to its new export scale.
|
|
323
|
+
const pixelRatio = snapshot.input === undefined
|
|
324
|
+
? undefined
|
|
325
|
+
: figmaSlicePixelRatio(raw, snapshot.expected.type);
|
|
313
326
|
let library;
|
|
314
327
|
try {
|
|
315
|
-
library = await this.#store.replaceRawFromImportSource(id, raw.bytes, snapshot.expected, raw.importSource
|
|
328
|
+
library = await this.#store.replaceRawFromImportSource(id, raw.bytes, snapshot.expected, raw.importSource, pixelRatio === undefined
|
|
329
|
+
? undefined
|
|
330
|
+
: (parameters) => plugin.descriptor.validateParameters(mergeParameterPatch(parameters, { pixelRatio })));
|
|
316
331
|
}
|
|
317
332
|
catch (cause) {
|
|
318
333
|
if (cause instanceof Error && cause.message === 'stale-import') {
|
|
@@ -347,6 +362,11 @@ export class FundusOperations {
|
|
|
347
362
|
if (seeded !== undefined)
|
|
348
363
|
next = seeded;
|
|
349
364
|
}
|
|
365
|
+
// Source scale is a default: an explicit parametersPatch below still wins.
|
|
366
|
+
const pixelRatio = figmaSlicePixelRatio(raw, options.type);
|
|
367
|
+
if (pixelRatio !== undefined) {
|
|
368
|
+
next = mergeParameterPatch(next, { pixelRatio });
|
|
369
|
+
}
|
|
350
370
|
if (options.parametersPatch !== undefined) {
|
|
351
371
|
next = mergeParameterPatch(next, options.parametersPatch);
|
|
352
372
|
}
|
|
@@ -642,6 +662,10 @@ export class FundusOperations {
|
|
|
642
662
|
};
|
|
643
663
|
}
|
|
644
664
|
async #buildState(library, issues, classification) {
|
|
665
|
+
const [gitBranch, changedGitFiles] = await Promise.all([
|
|
666
|
+
currentGitBranch(this.#config.projectRoot),
|
|
667
|
+
gitFileChanges(this.#config.projectRoot)
|
|
668
|
+
]);
|
|
645
669
|
const referencesByAsset = collectAllReferences(library, descriptorsByType(this.#registry));
|
|
646
670
|
const membershipByManifest = computeLibraryMembership(library, referencesByAsset);
|
|
647
671
|
const delivered = allDeliveredAssetIds(membershipByManifest);
|
|
@@ -706,6 +730,7 @@ export class FundusOperations {
|
|
|
706
730
|
folder: folderOfRawPath(record.raw),
|
|
707
731
|
rawUrl: `/files/raw/${encodeRelativePathForUrl(record.raw)}?v=${record.rawHash.slice(0, 12)}`,
|
|
708
732
|
rawHash: record.rawHash,
|
|
733
|
+
gitStatus: changedGitFiles.get(resolve(this.#config.rawDir, record.raw)) ?? null,
|
|
709
734
|
importSource: record.importSource,
|
|
710
735
|
parameters: record.parameters,
|
|
711
736
|
manifests: record.manifests,
|
|
@@ -747,6 +772,7 @@ export class FundusOperations {
|
|
|
747
772
|
}
|
|
748
773
|
const rawIngestionQueue = this.#buildRawIngestionQueue(library, classification);
|
|
749
774
|
return {
|
|
775
|
+
gitBranch,
|
|
750
776
|
library,
|
|
751
777
|
assets,
|
|
752
778
|
importDefaults: { figma: { scale: this.#config.import.figma.defaults.scale } },
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Slice plugin (server part): the same sharp conversion as the image plugin,
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* fixed caps keep their source-pixel size, while optional compression removes
|
|
4
|
+
* redundant pixels from the stretchable regions. The slicing data itself is
|
|
5
|
+
* entry-only.
|
|
5
6
|
*/
|
|
6
7
|
import { type ImagePreset, type SliceParameters } from '../../core/index.js';
|
|
7
8
|
import { type ServerAssetTypePlugin, type ServerPluginConfigDefinition } from './contract.js';
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Slice plugin (server part): the same sharp conversion as the image plugin,
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* fixed caps keep their source-pixel size, while optional compression removes
|
|
4
|
+
* redundant pixels from the stretchable regions. The slicing data itself is
|
|
5
|
+
* entry-only.
|
|
5
6
|
*/
|
|
6
|
-
import { SLICE_BUILT_IN_PRESETS, defaultInsetsForSize, slicePlugin, validateImagePreset } from '../../core/index.js';
|
|
7
|
-
import {
|
|
7
|
+
import { SLICE_BUILT_IN_PRESETS, defaultInsetsForSize, processedSliceInsets, slicePlugin, validateImagePreset } from '../../core/index.js';
|
|
8
|
+
import { readImageDimensions } from '../processing/image-processing.js';
|
|
9
|
+
import { processSliceImageFile } from '../processing/slice-processing.js';
|
|
8
10
|
import { extensionForImageFormat } from './image.js';
|
|
9
11
|
import { mergePresets } from './config.js';
|
|
10
12
|
import { requireProxyField, resolveNamedPreset } from './contract.js';
|
|
@@ -51,16 +53,26 @@ export const sliceServerPlugin = {
|
|
|
51
53
|
pixelRatio: detectPixelRatio(rawFileName)
|
|
52
54
|
};
|
|
53
55
|
},
|
|
54
|
-
process: (job) =>
|
|
56
|
+
process: (job) => processSliceImageFile({
|
|
55
57
|
sourcePath: job.sourcePath,
|
|
56
58
|
targetPath: job.targetPath,
|
|
57
|
-
preset: job.preset
|
|
59
|
+
preset: job.preset,
|
|
60
|
+
mode: job.parameters.mode,
|
|
61
|
+
insets: job.parameters.insets,
|
|
62
|
+
overdraw: job.parameters.overdraw,
|
|
63
|
+
compression: job.parameters.compression
|
|
58
64
|
}),
|
|
59
65
|
readProxyInfo: (proxyPath) => readImageDimensions(proxyPath),
|
|
60
66
|
buildManifestEntry: ({ parameters, src, proxy }) => {
|
|
67
|
+
const sourceWidth = requireProxyField(proxy, 'width');
|
|
68
|
+
const sourceHeight = requireProxyField(proxy, 'height');
|
|
61
69
|
const slicing = {
|
|
62
70
|
mode: parameters.mode,
|
|
63
|
-
insets:
|
|
71
|
+
insets: processedSliceInsets({
|
|
72
|
+
...parameters,
|
|
73
|
+
width: sourceWidth,
|
|
74
|
+
height: sourceHeight
|
|
75
|
+
}),
|
|
64
76
|
pixelRatio: parameters.pixelRatio,
|
|
65
77
|
// An all-zero overdraw is semantically "none" — keep the entry minimal.
|
|
66
78
|
...(hasAnySide(parameters.overdraw) ? { overdraw: parameters.overdraw } : {})
|
|
@@ -69,8 +81,8 @@ export const sliceServerPlugin = {
|
|
|
69
81
|
kind: 'slice',
|
|
70
82
|
src,
|
|
71
83
|
slicing,
|
|
72
|
-
sourceWidth
|
|
73
|
-
sourceHeight
|
|
84
|
+
sourceWidth,
|
|
85
|
+
sourceHeight
|
|
74
86
|
};
|
|
75
87
|
}
|
|
76
88
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ImagePreset, type SliceCompression, type SliceInsets, type SliceMode } from '../../core/index.js';
|
|
2
|
+
import { type ImageProcessingOutput } from './image-processing.js';
|
|
3
|
+
/** The length after percentage-based compression, with one stretch pixel kept. */
|
|
4
|
+
export declare function compressedStretchSize(size: number, compression: number): number;
|
|
5
|
+
export declare function assertSliceCompressionDimensions(width: number, height: number): void;
|
|
6
|
+
export declare function processSliceImageFile(options: {
|
|
7
|
+
sourcePath: string;
|
|
8
|
+
targetPath: string;
|
|
9
|
+
preset: ImagePreset;
|
|
10
|
+
mode: SliceMode;
|
|
11
|
+
insets: SliceInsets;
|
|
12
|
+
overdraw?: SliceInsets;
|
|
13
|
+
compression?: SliceCompression;
|
|
14
|
+
}): Promise<ImageProcessingOutput>;
|