@koda-sl/baker-cli 0.569.0 → 0.571.0-dev.6a3439a0a
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 +20 -14
- package/dist/account-EXGRZIXS.js +82 -0
- package/dist/account-JVDP5ERG.js +82 -0
- package/dist/account-NSBALYYS.js +139 -0
- package/dist/account-assets-EPEYTJFD.js +290 -0
- package/dist/account-level-VD4NLB2D.js +611 -0
- package/dist/account-reads-Z467VAL4.js +219 -0
- package/dist/account-users-342OZALE.js +64 -0
- package/dist/account-writes-KEXINJ5D.js +68 -0
- package/dist/accounts-A47QUTTB.js +76 -0
- package/dist/accounts-E5TF2AFI.js +115 -0
- package/dist/accounts-QESGQJGZ.js +713 -0
- package/dist/accounts-QR6OQ3GC.js +119 -0
- package/dist/accounts-UWC2TT6R.js +80 -0
- package/dist/actions-NT3HXFFA.js +55 -0
- package/dist/active-entities-XRSJNBOV.js +103 -0
- package/dist/activecampaign-EYRHDSXY.js +938 -0
- package/dist/activities-ZDWREYR7.js +75 -0
- package/dist/ad-group-writes-SVR4RCKB.js +172 -0
- package/dist/ad-groups-C726HUXS.js +70 -0
- package/dist/ad-writes-RWJIWGEL.js +176 -0
- package/dist/add-25YZMFSH.js +85 -0
- package/dist/add-7MAL7JRX.js +81 -0
- package/dist/add-D44VCDRU.js +148 -0
- package/dist/add-EPOHDTUO.js +305 -0
- package/dist/add-JO4ZPS23.js +97 -0
- package/dist/add-NSW26HIM.js +107 -0
- package/dist/add-accounts-EKMSHAA4.js +91 -0
- package/dist/ads-3KK7VQPU.js +79 -0
- package/dist/ads-4YZYNU66.js +128 -0
- package/dist/ads-DGL5SGP3.js +120 -0
- package/dist/ads-EWZGIC4T.js +48 -0
- package/dist/adsets-PSVCPCE3.js +182 -0
- package/dist/advertisers-7NAPI5ZU.js +125 -0
- package/dist/advertisers-AHOWL3YL.js +123 -0
- package/dist/analytics-7H6NDVUQ.js +447 -0
- package/dist/analytics-GFFXCMLV.js +2437 -0
- package/dist/animate-GTUI7XX4.js +480 -0
- package/dist/approved-E4EZA5RT.js +73 -0
- package/dist/asset-writes-NDSHY5OT.js +50 -0
- package/dist/assign-SDPPWP3Q.js +80 -0
- package/dist/audience-size-LKDDHKED.js +76 -0
- package/dist/audience-writes-4KQXVGHO.js +327 -0
- package/dist/audiences-6L43K2T2.js +280 -0
- package/dist/audiences-T5LMTT3B.js +85 -0
- package/dist/audiences-UHLVATR6.js +106 -0
- package/dist/audit-46DO2HV3.js +88 -0
- package/dist/audit-TSZIQTUB.js +154 -0
- package/dist/autocomplete-5BSAOAMZ.js +114 -0
- package/dist/avatars-S6RRD7M3.js +38 -0
- package/dist/bid-pricing-5KUAINH4.js +103 -0
- package/dist/brand-KFK2MQWW.js +22 -0
- package/dist/brief-6DV2PKAU.js +543 -0
- package/dist/businesses-TRFYMZ4I.js +54 -0
- package/dist/campaign-groups-5RPZPDNW.js +99 -0
- package/dist/campaign-writes-FUIGN5OR.js +176 -0
- package/dist/campaign-writes-XMYBEVZF.js +168 -0
- package/dist/campaigns-2MTON2IE.js +130 -0
- package/dist/campaigns-5A3IE735.js +111 -0
- package/dist/campaigns-JNP3VDZK.js +113 -0
- package/dist/campaigns-N2SWSBYT.js +78 -0
- package/dist/canvas-CHFNQTLY.js +46 -0
- package/dist/capabilities-2W3SRZ2I.js +147 -0
- package/dist/cards-CXKIVM4D.js +85 -0
- package/dist/catalog-6BER3SF7.js +66 -0
- package/dist/catalogs-4DNLG4AM.js +782 -0
- package/dist/catalogs-G5NOKL4L.js +130 -0
- package/dist/changes-AS4RVEAL.js +167 -0
- package/dist/chatgpt-O6EEAYLF.js +47 -0
- package/dist/chats-4JLWMUAC.js +584 -0
- package/dist/check-BOKLY5WG.js +107 -0
- package/dist/chunk-2CC4CPDT.js +225 -0
- package/dist/chunk-3GXHML4V.js +106 -0
- package/dist/chunk-3KUNRKNV.js +430 -0
- package/dist/chunk-3QPG2D27.js +125 -0
- package/dist/chunk-3UNMVVSI.js +917 -0
- package/dist/chunk-3UNMVVSI.js.map +1 -0
- package/dist/chunk-3WN5GWX4.js +94 -0
- package/dist/chunk-4AO3LSYM.js +73 -0
- package/dist/chunk-4HFM5RCP.js +217 -0
- package/dist/chunk-4INBMXUS.js +930 -0
- package/dist/chunk-5NMKNHJI.js +46 -0
- package/dist/chunk-5QNW5PCM.js +106 -0
- package/dist/chunk-6AMN346B.js +114 -0
- package/dist/chunk-6D7WTUF3.js +98 -0
- package/dist/chunk-6DSPB6YA.js +7904 -0
- package/dist/chunk-6DSPB6YA.js.map +1 -0
- package/dist/chunk-6EOWBGGW.js +191 -0
- package/dist/chunk-6FQ7CJEX.js +57 -0
- package/dist/chunk-6MJKVNLL.js +25 -0
- package/dist/chunk-6OIKNJ7G.js +26 -0
- package/dist/chunk-6OZDN2FI.js +19 -0
- package/dist/chunk-75OGTGC4.js +89 -0
- package/dist/chunk-7NBQQOCU.js +97 -0
- package/dist/chunk-AQRBEPZL.js +138 -0
- package/dist/chunk-AXLKR3E4.js +66 -0
- package/dist/chunk-AZIXX73C.js +64 -0
- package/dist/chunk-B64KJW5C.js +476 -0
- package/dist/chunk-BEZEZHQ6.js +455 -0
- package/dist/chunk-BIBXZJZI.js +97 -0
- package/dist/chunk-BMK4F4CU.js +169 -0
- package/dist/chunk-C52Q3L4C.js +51 -0
- package/dist/chunk-CBVUO7SK.js +1744 -0
- package/dist/chunk-CF5I4Q5M.js +69 -0
- package/dist/chunk-CST52ZME.js +142 -0
- package/dist/chunk-CUTTTFAU.js +783 -0
- package/dist/chunk-D32EWSMB.js +150 -0
- package/dist/chunk-DGHSXHZR.js +136 -0
- package/dist/chunk-DHF4FXWS.js +58 -0
- package/dist/chunk-DPOUS5DN.js +287 -0
- package/dist/chunk-DW3H2XQA.js +91 -0
- package/dist/chunk-EAA273XW.js +2250 -0
- package/dist/chunk-EAA273XW.js.map +1 -0
- package/dist/chunk-EJ6EED6I.js +69 -0
- package/dist/chunk-EM5R3BYC.js +131 -0
- package/dist/chunk-EMR5KGNY.js +685 -0
- package/dist/chunk-EONUZOJV.js +962 -0
- package/dist/chunk-F3CZFUXZ.js +3187 -0
- package/dist/chunk-F3CZFUXZ.js.map +1 -0
- package/dist/chunk-FLTAPEVY.js +288 -0
- package/dist/chunk-GRX3JXSR.js +843 -0
- package/dist/chunk-H25GY4U4.js +139 -0
- package/dist/chunk-H4RHZJ65.js +207 -0
- package/dist/chunk-H6ASYVQX.js +544 -0
- package/dist/chunk-HFIHXIYY.js +547 -0
- package/dist/chunk-HOA74TOS.js +249 -0
- package/dist/chunk-HPF3USL2.js +52 -0
- package/dist/chunk-HQDNDKNR.js +5471 -0
- package/dist/chunk-HXSYWXLH.js +709 -0
- package/dist/chunk-I3QLWGKS.js +64 -0
- package/dist/chunk-IMS53EQU.js +4277 -0
- package/dist/chunk-IMS53EQU.js.map +1 -0
- package/dist/chunk-IYDESWW4.js +74 -0
- package/dist/chunk-J4AWNWKN.js +1919 -0
- package/dist/chunk-JAK5VDSG.js +103 -0
- package/dist/chunk-JAME5NBT.js +42 -0
- package/dist/chunk-JGSEHX2Q.js +3107 -0
- package/dist/chunk-JGSEHX2Q.js.map +1 -0
- package/dist/chunk-JLAFNORO.js +285 -0
- package/dist/chunk-KG5VNPKU.js +91 -0
- package/dist/chunk-KGJ6EIX3.js +76 -0
- package/dist/chunk-KJHG2DWS.js +170 -0
- package/dist/chunk-L4QEMWNJ.js +111 -0
- package/dist/chunk-L7I47VGM.js +46 -0
- package/dist/chunk-LAMSUL26.js +1518 -0
- package/dist/chunk-LJEJCIHR.js +246 -0
- package/dist/chunk-LLTHDEM2.js +479 -0
- package/dist/chunk-M4KFO256.js +188 -0
- package/dist/chunk-M5PZ6QQB.js +312 -0
- package/dist/chunk-MFGUR5OD.js +334 -0
- package/dist/chunk-MIHY534L.js +39 -0
- package/dist/chunk-MKOI6QYM.js +225 -0
- package/dist/chunk-MPTNN35I.js +325 -0
- package/dist/chunk-MSIOGH67.js +66 -0
- package/dist/chunk-MTW2NDDD.js +98 -0
- package/dist/chunk-MZLPOYCC.js +10058 -0
- package/dist/chunk-MZLPOYCC.js.map +1 -0
- package/dist/chunk-NOCBNING.js +638 -0
- package/dist/chunk-NWLK5RPA.js +197 -0
- package/dist/chunk-NXNOXZGB.js +2523 -0
- package/dist/chunk-NXNOXZGB.js.map +1 -0
- package/dist/chunk-O5VSYBUA.js +343 -0
- package/dist/chunk-PR5OPERY.js +167 -0
- package/dist/chunk-Q3G4ZI2U.js +84 -0
- package/dist/chunk-Q5XUFN2W.js +35 -0
- package/dist/chunk-Q736UFSD.js +75 -0
- package/dist/chunk-QGAUDVMR.js +148 -0
- package/dist/chunk-QRRAMUKV.js +468 -0
- package/dist/chunk-QZ4YHQLW.js +63 -0
- package/dist/chunk-RGLTITIH.js +494 -0
- package/dist/chunk-RIVQ4PQQ.js +225 -0
- package/dist/chunk-RLLPY62L.js +163 -0
- package/dist/chunk-RQHXWPET.js +61 -0
- package/dist/chunk-RRKUXGAU.js +26 -0
- package/dist/chunk-RULW4627.js +23 -0
- package/dist/chunk-S4RCF3YT.js +156 -0
- package/dist/chunk-S5S54J2K.js +56 -0
- package/dist/chunk-SIKCVWM3.js +76 -0
- package/dist/chunk-SIRRBWQ2.js +215 -0
- package/dist/chunk-TCLJRWST.js +831 -0
- package/dist/chunk-TLQY4QBW.js +84 -0
- package/dist/chunk-UK4XSLV2.js +296 -0
- package/dist/chunk-URGXEDFV.js +76 -0
- package/dist/chunk-UVUY6FLV.js +1254 -0
- package/dist/chunk-V4HS5JRL.js +1320 -0
- package/dist/chunk-V7EN5LFS.js +115 -0
- package/dist/chunk-WTOBG3YL.js +392 -0
- package/dist/chunk-WTPID22G.js +152 -0
- package/dist/chunk-WYMX3F47.js +399 -0
- package/dist/chunk-WZXMZFVB.js +238 -0
- package/dist/chunk-X5YHMGAT.js +224 -0
- package/dist/chunk-X7USE7IA.js +24026 -0
- package/dist/chunk-X7USE7IA.js.map +1 -0
- package/dist/chunk-XA76OGSL.js +718 -0
- package/dist/chunk-XA7JN7YE.js +297 -0
- package/dist/chunk-XHAGX4J4.js +604 -0
- package/dist/chunk-XY7W6MQN.js +274 -0
- package/dist/chunk-YAINUFSC.js +203 -0
- package/dist/chunk-YAMKCMAS.js +219 -0
- package/dist/chunk-YRWCXYWW.js +178 -0
- package/dist/chunk-Z5BG47PO.js +5752 -0
- package/dist/chunk-Z5BG47PO.js.map +1 -0
- package/dist/chunk-Z7ICQKC2.js +344 -0
- package/dist/chunk-ZBXV2KOQ.js +220 -0
- package/dist/chunk-ZBXV2KOQ.js.map +1 -0
- package/dist/chunk-ZCGM7ZWM.js +45 -0
- package/dist/chunk-ZMNRSTNV.js +454 -0
- package/dist/cite-WCAOCOO5.js +191 -0
- package/dist/claim-L4WLCVUL.js +200 -0
- package/dist/cli.js +49 -49
- package/dist/cli.js.map +1 -1
- package/dist/client-VCKP6WBR.js +19 -0
- package/dist/code-VXOTFGD2.js +76 -0
- package/dist/companies-HW46BRQG.js +198 -0
- package/dist/company-KCIDE7SL.js +308 -0
- package/dist/complete-JXM25FVW.js +84 -0
- package/dist/config-UR45YCIN.js +88 -0
- package/dist/connect-7TX7AAM5.js +45 -0
- package/dist/content-EQQIKG5H.js +85 -0
- package/dist/conversation-YIDUB6GL.js +96 -0
- package/dist/conversion-report-33SG7SHU.js +127 -0
- package/dist/conversion-upload-command-N3OMLLF2.js +439 -0
- package/dist/conversion-writes-XGGTBML5.js +122 -0
- package/dist/conversions-F4OZYUCT.js +140 -0
- package/dist/conversions-PPP4QK7U.js +78 -0
- package/dist/copy-writes-JVUX3YDL.js +170 -0
- package/dist/countries-GRCU4IGM.js +82 -0
- package/dist/create-6EAKNERA.js +239 -0
- package/dist/create-772LZHZR.js +218 -0
- package/dist/create-FDNMIVFX.js +62 -0
- package/dist/create-X2QM7GA7.js +135 -0
- package/dist/creatives-4EPM3RHG.js +118 -0
- package/dist/creatives-K2AAW6EL.js +58 -0
- package/dist/creatives-SNYN4KIM.js +229 -0
- package/dist/credentials-KZZVBO42.js +290 -0
- package/dist/critique-G5QXRHPF.js +1451 -0
- package/dist/critique-PUHOJI7V.js +232 -0
- package/dist/crm-4LZZVT4N.js +229 -0
- package/dist/crm-M6NXDU5B.js +323 -0
- package/dist/crop-NE7YX4SS.js +113 -0
- package/dist/currency-HK2ZW2VW.js +88 -0
- package/dist/custom-conversions-GQTU5E6X.js +128 -0
- package/dist/customers-V5NT4W7X.js +65 -0
- package/dist/decide-6Q5X3V3F.js +199 -0
- package/dist/delete-EKKOEB3N.js +69 -0
- package/dist/delete-GQIKNO53.js +57 -0
- package/dist/delete-LFZIPQEO.js +69 -0
- package/dist/delete-QHDDR66K.js +85 -0
- package/dist/delete-SP66F7ZV.js +71 -0
- package/dist/delete-YOEI63OT.js +67 -0
- package/dist/demographics-CEQ74O74.js +141 -0
- package/dist/describe-DJPIUEFE.js +97 -0
- package/dist/describe-MAGTSOW4.js +97 -0
- package/dist/dimensions-IC2H7V3H.js +101 -0
- package/dist/discard-5GDF3TP3.js +69 -0
- package/dist/discover-PSL2NBJL.js +93 -0
- package/dist/discover-Q5PAOIQQ.js +172 -0
- package/dist/domain-PKOUPHHF.js +101 -0
- package/dist/download-2WNTN7JQ.js +172 -0
- package/dist/download-EHDJXBAC.js +337 -0
- package/dist/draft-27NMTARB.js +134 -0
- package/dist/draft-CF4XNJG5.js +578 -0
- package/dist/draft-F4CVSL2I.js +332 -0
- package/dist/draft-JESKGZ6O.js +138 -0
- package/dist/draft-L2NXCIYT.js +315 -0
- package/dist/draft-MWYKIZC4.js +260 -0
- package/dist/draft-RZCTAOI2.js +374 -0
- package/dist/draft-UEVBUNKV.js +220 -0
- package/dist/engine/index.js +15 -15
- package/dist/env-NZXNMWSD.js +53 -0
- package/dist/experiment-XAYSEYTU.js +1397 -0
- package/dist/experiments-DWC6L72S.js +236 -0
- package/dist/export-W54UZ62P.js +168 -0
- package/dist/extract-6HJXSOZW.js +143 -0
- package/dist/facets-TBOXGYJT.js +117 -0
- package/dist/favorites-Y6CT6NSQ.js +178 -0
- package/dist/feed-35BRQPTH.js +177 -0
- package/dist/feedback-MSMFYAEY.js +114 -0
- package/dist/feedback-WAC6S42V.js +115 -0
- package/dist/feedback-record-XRQ2R2WD.js +269 -0
- package/dist/fetch-I6P72CDL.js +139 -0
- package/dist/fetch-LGX7B3IC.js +204 -0
- package/dist/find-SVGRA7IA.js +144 -0
- package/dist/fit-RVWPRBNO.js +65 -0
- package/dist/flows-LA6EYMLS.js +340 -0
- package/dist/follow-24QSDNAG.js +94 -0
- package/dist/follow-competitors-AG4E4XFA.js +112 -0
- package/dist/following-YGM6TBK3.js +113 -0
- package/dist/fonts-WRC34VSV.js +39 -0
- package/dist/forecast-6VHRGBJG.js +121 -0
- package/dist/forecast-OVKXBLJB.js +169 -0
- package/dist/funding-WZNGXRLJ.js +85 -0
- package/dist/funnel-U3GQIGND.js +397 -0
- package/dist/ga4-W3U5YTRT.js +55 -0
- package/dist/generate-Y4NJEYIH.js +263 -0
- package/dist/get-3MTAVNTP.js +56 -0
- package/dist/get-5SPNAIUQ.js +62 -0
- package/dist/get-AHI247JG.js +82 -0
- package/dist/get-GEUSRD5Y.js +59 -0
- package/dist/get-JIZPYK3Z.js +74 -0
- package/dist/get-PF3HGECD.js +62 -0
- package/dist/get-TS2ZJDCQ.js +38 -0
- package/dist/get-YWDZYEAC.js +92 -0
- package/dist/gif-NP6EDGEE.js +111 -0
- package/dist/google-BMUJKAUO.js +3300 -0
- package/dist/google-ZVAIFXQZ.js +163 -0
- package/dist/google-ads-6Z7P3SCD.js +198 -0
- package/dist/group-3DT4UYSR.js +43 -0
- package/dist/group-OEKKCFXT.js +43 -0
- package/dist/gsc-4FEFPFPB.js +30 -0
- package/dist/history-4QUV45ZJ.js +102 -0
- package/dist/history-PD7FCTDD.js +153 -0
- package/dist/history-VKRYKQ4C.js +69 -0
- package/dist/hubspot-WEFAFKVJ.js +814 -0
- package/dist/icon-43UJTGGE.js +138 -0
- package/dist/ideas-SMSEXKIA.js +45 -0
- package/dist/images-KAT4BPYV.js +92 -0
- package/dist/improve-IMXQN6OD.js +86 -0
- package/dist/ingest-IHKTSJ4H.js +28 -0
- package/dist/ingest-TOHQ6MZA.js +131 -0
- package/dist/insights-3IPSEBYW.js +132 -0
- package/dist/insights-BR3456EI.js +658 -0
- package/dist/inspect-5MZBPDYS.js +192 -0
- package/dist/inspiration-XZI5KCQW.js +53 -0
- package/dist/instant-experiences-2LKF7XVK.js +264 -0
- package/dist/intent-ZM4K623V.js +95 -0
- package/dist/job-GOX3KIKG.js +202 -0
- package/dist/job-create-F2PQSN3C.js +109 -0
- package/dist/job-status-3FMA5D7T.js +74 -0
- package/dist/keep-23ZYMWPG.js +78 -0
- package/dist/keyword-gap-FAAF2I6V.js +130 -0
- package/dist/keyword-metrics-EXNJRJBY.js +200 -0
- package/dist/keywords-for-site-5LW77QWF.js +131 -0
- package/dist/knowledge-7M7DSRF3.js +195 -0
- package/dist/landing-ZH4SD3DW.js +28 -0
- package/dist/landings-VNQ4VA2U.js +151 -0
- package/dist/languages-2X22HXM3.js +55 -0
- package/dist/languages-ZGDTERIQ.js +40 -0
- package/dist/launches-L4EUROCJ.js +19 -0
- package/dist/layerize-6QHQMA7Q.js +190 -0
- package/dist/lead-routes-5TPFJEVH.js +733 -0
- package/dist/leads-4TLOH47R.js +541 -0
- package/dist/leads-736RILZN.js +115 -0
- package/dist/learn-BESXWXEN.js +207 -0
- package/dist/library-MNJC24E4.js +212 -0
- package/dist/lighthouse-DJMAXFTD.js +75 -0
- package/dist/line-item-writes-FA72DHNQ.js +211 -0
- package/dist/line-items-XVYE3IYT.js +107 -0
- package/dist/link-6FPKFVC3.js +67 -0
- package/dist/linkedin-TE6P4RYN.js +1344 -0
- package/dist/linkedin-person-TZJ6VEXE.js +139 -0
- package/dist/list-2277GCPH.js +51 -0
- package/dist/list-4R5EMKUQ.js +154 -0
- package/dist/list-537S75BZ.js +76 -0
- package/dist/list-MN2FPF3T.js +306 -0
- package/dist/list-ORO4WDF4.js +67 -0
- package/dist/list-Q52FPW3H.js +50 -0
- package/dist/list-V4PSDBLX.js +93 -0
- package/dist/list-WIXQXNKB.js +65 -0
- package/dist/list-XK33NCSC.js +57 -0
- package/dist/locations-A65MFB7Q.js +69 -0
- package/dist/locations-WN6B3IJK.js +40 -0
- package/dist/log-ABBZLPRU.js +95 -0
- package/dist/logo-4LSFZ3ZO.js +19 -0
- package/dist/lookup-WIM5WR25.js +23 -0
- package/dist/make-QAFKU6WO.js +1367 -0
- package/dist/map-52P35OKE.js +445 -0
- package/dist/mcp-PZ3VBIF4.js +729 -0
- package/dist/media-34I7UB7Z.js +89 -0
- package/dist/media-KKI3KWLR.js +18 -0
- package/dist/media-sources-TT374PLN.js +35 -0
- package/dist/members-CF6VG6ZW.js +47 -0
- package/dist/meme-6NFYFQ7T.js +108 -0
- package/dist/meta-2UK7KIE4.js +124 -0
- package/dist/metrics-3U3ZO2RF.js +152 -0
- package/dist/models-VOSJJFO2.js +155 -0
- package/dist/normalize-4LZCLMTQ.js +144 -0
- package/dist/normalize-G75RDSE4.js +806 -0
- package/dist/options-6IRL7CL6.js +125 -0
- package/dist/organization-WMLLJE66.js +949 -0
- package/dist/output-ELEO2Z6R.js +24 -0
- package/dist/page-4X6IBUWG.js +105 -0
- package/dist/page-photos-KNBLMFLN.js +118 -0
- package/dist/pages-7HW5YOZV.js +67 -0
- package/dist/performance-A7CYFBW2.js +5565 -0
- package/dist/performance-HYSTXLTS.js +27 -0
- package/dist/pinterest-KA6VFDM4.js +105 -0
- package/dist/pixels-D5HF24FI.js +109 -0
- package/dist/pixels-U6UA662G.js +62 -0
- package/dist/plan-XCA6R3HZ.js +208 -0
- package/dist/posts-ALGM6ONV.js +36 -0
- package/dist/preview-55TRUF4Q.js +245 -0
- package/dist/preview-76ZP2QA3.js +101 -0
- package/dist/profile-NHUPUCBR.js +159 -0
- package/dist/promoted-tweet-writes-I5G4IDL5.js +183 -0
- package/dist/promoted-tweets-X5XNO7IT.js +119 -0
- package/dist/properties-2ZXA5BPJ.js +101 -0
- package/dist/publish-S2Z4EF4H.js +350 -0
- package/dist/query-63CTX2PH.js +231 -0
- package/dist/query-DMWY3TDD.js +236 -0
- package/dist/query-SAQADBM2.js +62 -0
- package/dist/questionnaire-WHE42RD4.js +94 -0
- package/dist/read-NESEKULG.js +141 -0
- package/dist/reddit-S2L5WDY7.js +29 -0
- package/dist/refresh-ILDEPU5A.js +42 -0
- package/dist/refresh-K2YTJSH3.js +97 -0
- package/dist/release-FX76IIVN.js +63 -0
- package/dist/relevant-pages-KTSODNNW.js +99 -0
- package/dist/remove-LOVWPLDO.js +53 -0
- package/dist/remove-NHE4UT7G.js +49 -0
- package/dist/reopen-DXV2Y6Z3.js +66 -0
- package/dist/rerun-TFQCRRFK.js +97 -0
- package/dist/research-7PGDAKC7.js +265 -0
- package/dist/research-HY5PSUCC.js +75 -0
- package/dist/reset-MEHUQJA4.js +57 -0
- package/dist/reset-Y5VZJRDQ.js +57 -0
- package/dist/resolve-FAVABEJW.js +124 -0
- package/dist/retry-5IY4MNDW.js +65 -0
- package/dist/retry-OMJ3C3AX.js +63 -0
- package/dist/retry-failed-R5HPQ3KQ.js +45 -0
- package/dist/revenue-S4KFZCOI.js +91 -0
- package/dist/rule-writes-QB4IWFCJ.js +530 -0
- package/dist/rules-66IGR2KA.js +99 -0
- package/dist/rules-FYVD2QBB.js +217 -0
- package/dist/rules-add-G7YGOYZJ.js +465 -0
- package/dist/run-LJVBH3JS.js +72 -0
- package/dist/run-XJBWDWN6.js +69 -0
- package/dist/scaffold-ad-GNMCB3QY.js +1513 -0
- package/dist/scaffold-static-ad-QIWKWURL.js +1013 -0
- package/dist/scaffold-static-ad-QIWKWURL.js.map +1 -0
- package/dist/scaffold-video-G6G2NPUF.js +885 -0
- package/dist/schedule-D7EDEM45.js +67 -0
- package/dist/schedule-OX5XHXLH.js +64 -0
- package/dist/scheduled-agents-A5ZFQB5X.js +55 -0
- package/dist/schema-NTGHAPR2.js +135 -0
- package/dist/schema-Z43AJOJ4.js +152 -0
- package/dist/scrape-VL2RWSTW.js +2209 -0
- package/dist/screenshot-Y6EEXS3Q.js +103 -0
- package/dist/search-CXC7N5XJ.js +51 -0
- package/dist/search-JEXYEAPQ.js +228 -0
- package/dist/search-L3GTZYRW.js +92 -0
- package/dist/search-TXBYKNQC.js +91 -0
- package/dist/search-WCXQBMMM.js +177 -0
- package/dist/search-XHSTUBDY.js +26 -0
- package/dist/search-copy-FIPG7OCC.js +168 -0
- package/dist/seeds-ADJKURNG.js +101 -0
- package/dist/select-5ZD7FVBT.js +110 -0
- package/dist/sends-RS4LWRAC.js +349 -0
- package/dist/sequences-2RPKDKGQ.js +146 -0
- package/dist/set-prompt-NGCVMQIQ.js +199 -0
- package/dist/setup-links-4HCSF55G.js +144 -0
- package/dist/shared-4GGUIOF2.js +32 -0
- package/dist/shopify-GDR5WGHH.js +4009 -0
- package/dist/site-B7LT6KAO.js +180 -0
- package/dist/sitemaps-Z6IELTQV.js +77 -0
- package/dist/sites-KLAKI2EY.js +97 -0
- package/dist/skills-OJP36EVR.js +47 -0
- package/dist/sources-6DPUEROC.js +30 -0
- package/dist/sources-OSUXCLID.js +457 -0
- package/dist/stale-YKFKPPOH.js +90 -0
- package/dist/stats-MIMFX4R7.js +34 -0
- package/dist/status-KIC3P5JV.js +65 -0
- package/dist/sticker-IREEEN7I.js +103 -0
- package/dist/stock-VWFUFRYV.js +212 -0
- package/dist/studies-YGYAH3JI.js +250 -0
- package/dist/studio-XLC37YGX.js +49 -0
- package/dist/study-writes-UPGJB36A.js +471 -0
- package/dist/suggest-5RTISDLI.js +66 -0
- package/dist/sync-OHIXI4I6.js +55 -0
- package/dist/sync-QBW4XH2H.js +57 -0
- package/dist/sync-VCAFAYW4.js +279 -0
- package/dist/sync-definition-4KMJK46H.js +70 -0
- package/dist/tag-DSCUKNC3.js +57 -0
- package/dist/tag-manager-IINALUEJ.js +43 -0
- package/dist/tags-4F5UBPYG.js +227 -0
- package/dist/tags-4O5FPEEY.js +26 -0
- package/dist/tags-7RKKCQ4X.js +23 -0
- package/dist/tags-CB4MWI3A.js +23 -0
- package/dist/tags-QZJIP4LJ.js +23 -0
- package/dist/targeting-BM72UTI6.js +762 -0
- package/dist/targeting-constants-54S3FXIF.js +118 -0
- package/dist/targeting-criteria-65UU7EYD.js +113 -0
- package/dist/targets-T742OPQI.js +106 -0
- package/dist/terms-OFHNLW6U.js +102 -0
- package/dist/testimonials-HKJJXONO.js +32 -0
- package/dist/themes-Q6LVMEMF.js +95 -0
- package/dist/top-companies-T6AMU4C6.js +111 -0
- package/dist/transcript-DOUYMZAP.js +165 -0
- package/dist/translate-WKOXFZTQ.js +603 -0
- package/dist/triggers-EYY4GSUL.js +144 -0
- package/dist/tweets-TRTXC6O4.js +123 -0
- package/dist/unfollow-DATOGPLZ.js +46 -0
- package/dist/unlink-JNM4WRZK.js +70 -0
- package/dist/unstage-LLQCMZ5H.js +96 -0
- package/dist/unstage-QF4JT5YP.js +88 -0
- package/dist/update-6V3RBRIE.js +101 -0
- package/dist/update-J4DURR4K.js +192 -0
- package/dist/update-J7Y6LZC5.js +155 -0
- package/dist/update-MQ4NYIU6.js +66 -0
- package/dist/update-SD5YQIJC.js +81 -0
- package/dist/upload-7PPMVWVA.js +155 -0
- package/dist/upload-CEIYYPID.js +137 -0
- package/dist/upscale-WVJZG76V.js +109 -0
- package/dist/url-options-6WC2XQKB.js +131 -0
- package/dist/url-params-OVBIP6UA.js +101 -0
- package/dist/use-6FADOAFZ.js +111 -0
- package/dist/validate-UHXI2ESE.js +135 -0
- package/dist/validate-UHXI2ESE.js.map +1 -0
- package/dist/variant-RNM36P4J.js +338 -0
- package/dist/videos-GHFCOTT7.js +146 -0
- package/dist/videos-Z72RXCRB.js +41 -0
- package/dist/view-YR6MDLWL.js +133 -0
- package/dist/viewer-check-655BZRML.js +83 -0
- package/dist/web-4QN6QB7L.js +173 -0
- package/dist/winners-4T5RFQXU.js +113 -0
- package/dist/winning-ads-2J2RIOLR.js +86 -0
- package/dist/write-commands-6D55SB56.js +206 -0
- package/dist/write-commands-AIWLEGO2.js +1169 -0
- package/dist/write-commands-UO3OQIHH.js +721 -0
- package/dist/write-commands-V7B4FBMX.js +1524 -0
- package/dist/x-7KXNCWTJ.js +47 -0
- package/package.json +1 -1
- package/dist/account-MYM2QNFO.js +0 -82
- package/dist/account-OUKPRB7C.js +0 -139
- package/dist/account-YJ2NNQYP.js +0 -82
- package/dist/account-assets-HOOPV5KR.js +0 -290
- package/dist/account-level-3QWMJTZQ.js +0 -611
- package/dist/account-reads-RKK5BA6L.js +0 -219
- package/dist/account-users-GHMPDZUM.js +0 -64
- package/dist/account-writes-HEXKGWXC.js +0 -68
- package/dist/accounts-DDNEHXXT.js +0 -713
- package/dist/accounts-K7VD47FG.js +0 -119
- package/dist/accounts-OSVXKNSI.js +0 -76
- package/dist/accounts-S7CEGWJL.js +0 -80
- package/dist/accounts-SJOO4MQX.js +0 -115
- package/dist/actions-JIXQEVIN.js +0 -55
- package/dist/active-entities-4KQQSMRZ.js +0 -103
- package/dist/activecampaign-4ST7BMHO.js +0 -938
- package/dist/activities-FRA33VZZ.js +0 -75
- package/dist/ad-group-writes-O2OP4NJ6.js +0 -172
- package/dist/ad-groups-AMMMWHHX.js +0 -70
- package/dist/ad-writes-IWLRLR2E.js +0 -176
- package/dist/add-IMKVYDQV.js +0 -85
- package/dist/add-NZ6SEWUR.js +0 -107
- package/dist/add-PZEVRQ7Z.js +0 -81
- package/dist/add-QXI627AS.js +0 -148
- package/dist/add-SPQ4MOCQ.js +0 -97
- package/dist/add-ZH5HJBUN.js +0 -305
- package/dist/add-accounts-D4V5K7SO.js +0 -91
- package/dist/ads-7TQKAH4B.js +0 -48
- package/dist/ads-KLSFKXUE.js +0 -79
- package/dist/ads-L6SMNOUM.js +0 -120
- package/dist/ads-RTRWWEP5.js +0 -128
- package/dist/adsets-R75LSEV5.js +0 -182
- package/dist/advertisers-2GKICB23.js +0 -125
- package/dist/advertisers-T37UHN3C.js +0 -123
- package/dist/analytics-ITBXTEIC.js +0 -2437
- package/dist/analytics-WXLRAXXN.js +0 -447
- package/dist/animate-WS63CZ3Y.js +0 -480
- package/dist/approved-3XFZNRJR.js +0 -73
- package/dist/asset-writes-DECROLE3.js +0 -50
- package/dist/assign-3CVJL35R.js +0 -80
- package/dist/audience-size-23UFSW6H.js +0 -76
- package/dist/audience-writes-VSC2BY4Y.js +0 -327
- package/dist/audiences-76S4WY7Q.js +0 -280
- package/dist/audiences-RN745R53.js +0 -85
- package/dist/audiences-V773XHP2.js +0 -106
- package/dist/audit-BIHMDO5K.js +0 -88
- package/dist/audit-OT42WBII.js +0 -154
- package/dist/autocomplete-T642QXBX.js +0 -114
- package/dist/avatars-33UGHCQA.js +0 -38
- package/dist/bid-pricing-UHU2HOAP.js +0 -103
- package/dist/brand-36YIAVGK.js +0 -22
- package/dist/brief-A5XFT6VH.js +0 -543
- package/dist/businesses-HECSW3EL.js +0 -54
- package/dist/campaign-groups-TAVIZR4L.js +0 -99
- package/dist/campaign-writes-72OPCWMG.js +0 -176
- package/dist/campaign-writes-AQ5T5TII.js +0 -168
- package/dist/campaigns-3P2UZWPD.js +0 -111
- package/dist/campaigns-D2V423FD.js +0 -113
- package/dist/campaigns-NW2H7SAR.js +0 -78
- package/dist/campaigns-S62KEFVL.js +0 -130
- package/dist/canvas-D7L7R4D2.js +0 -46
- package/dist/capabilities-YC36LOZU.js +0 -147
- package/dist/cards-RYQN5JLR.js +0 -85
- package/dist/catalog-URTZYAPU.js +0 -66
- package/dist/catalogs-G33WT5PS.js +0 -782
- package/dist/catalogs-XLWWM2Q3.js +0 -130
- package/dist/changes-SI2W2PZL.js +0 -167
- package/dist/chatgpt-PPWG5WOF.js +0 -47
- package/dist/chats-M3RP62YO.js +0 -584
- package/dist/check-FQYDJ5RS.js +0 -107
- package/dist/chunk-22RM3UOO.js +0 -63
- package/dist/chunk-23RVCBL7.js +0 -709
- package/dist/chunk-2JBPS2CV.js +0 -89
- package/dist/chunk-2N2R5YSN.js +0 -156
- package/dist/chunk-2Q7K4F4H.js +0 -7899
- package/dist/chunk-2Q7K4F4H.js.map +0 -1
- package/dist/chunk-2TS2ITSG.js +0 -392
- package/dist/chunk-2VW7S77J.js +0 -399
- package/dist/chunk-3LYT3NQX.js +0 -42
- package/dist/chunk-45D6WRCJ.js +0 -476
- package/dist/chunk-4H6XLX7E.js +0 -97
- package/dist/chunk-4OQG4HBG.js +0 -274
- package/dist/chunk-4PAGS7QH.js +0 -76
- package/dist/chunk-4UNJ4ENA.js +0 -106
- package/dist/chunk-5C4RRCKM.js +0 -69
- package/dist/chunk-5E4Y6RVY.js +0 -56
- package/dist/chunk-5ZHXLY7Y.js +0 -219
- package/dist/chunk-6E4KJMXO.js +0 -51
- package/dist/chunk-6PO3WSFJ.js +0 -97
- package/dist/chunk-6QINKM6T.js +0 -46
- package/dist/chunk-7CORYCEZ.js +0 -142
- package/dist/chunk-7TVVYP7K.js +0 -217
- package/dist/chunk-A4O3JL6D.js +0 -26
- package/dist/chunk-AC7WLPXF.js +0 -8954
- package/dist/chunk-AC7WLPXF.js.map +0 -1
- package/dist/chunk-AIK2HPDZ.js +0 -312
- package/dist/chunk-ANRTDNPQ.js +0 -115
- package/dist/chunk-B2BQ2Q64.js +0 -287
- package/dist/chunk-BESCYH3K.js +0 -125
- package/dist/chunk-BGMIO2FR.js +0 -64
- package/dist/chunk-BMMXYR7A.js +0 -238
- package/dist/chunk-CCYZJMZ7.js +0 -2522
- package/dist/chunk-CCYZJMZ7.js.map +0 -1
- package/dist/chunk-CDTAKCJR.js +0 -178
- package/dist/chunk-CORECUKT.js +0 -685
- package/dist/chunk-CP6RFWLW.js +0 -69
- package/dist/chunk-D3YAFC6K.js +0 -98
- package/dist/chunk-DEZBCK5P.js +0 -66
- package/dist/chunk-DLM5OSHM.js +0 -843
- package/dist/chunk-DRQI2CJJ.js +0 -138
- package/dist/chunk-DWPOAU4Z.js +0 -5471
- package/dist/chunk-E3PYHCQL.js +0 -344
- package/dist/chunk-E56V3RFO.js +0 -75
- package/dist/chunk-EFTYCX5C.js +0 -46
- package/dist/chunk-EIDHLGQM.js +0 -249
- package/dist/chunk-EJBLF2LI.js +0 -167
- package/dist/chunk-EL3TDR5S.js +0 -1744
- package/dist/chunk-FB5OU5HZ.js +0 -169
- package/dist/chunk-FGAXZ7ET.js +0 -23
- package/dist/chunk-FGTOOTYC.js +0 -91
- package/dist/chunk-FLQNIFG2.js +0 -84
- package/dist/chunk-FUIGPJZZ.js +0 -1320
- package/dist/chunk-G6U45QD3.js +0 -296
- package/dist/chunk-GDRJS2QJ.js +0 -197
- package/dist/chunk-GO6ISZUZ.js +0 -52
- package/dist/chunk-GUYFVYLY.js +0 -170
- package/dist/chunk-GWLP45WQ.js +0 -1518
- package/dist/chunk-H3HA22Z3.js +0 -1919
- package/dist/chunk-H3RCEM6L.js +0 -61
- package/dist/chunk-HBRXFQQV.js +0 -3510
- package/dist/chunk-HBRXFQQV.js.map +0 -1
- package/dist/chunk-HH5WM5VA.js +0 -430
- package/dist/chunk-HJ3Q4NOM.js +0 -58
- package/dist/chunk-IDDG4QKO.js +0 -39
- package/dist/chunk-IGCS3X4F.js +0 -150
- package/dist/chunk-IID2MAYZ.js +0 -91
- package/dist/chunk-IWNLW7ZC.js +0 -139
- package/dist/chunk-J32CYEIH.js +0 -74
- package/dist/chunk-JAC6JVCI.js +0 -26
- package/dist/chunk-JCDCIQMA.js +0 -479
- package/dist/chunk-JED4JBIK.js +0 -225
- package/dist/chunk-JIE45TKJ.js +0 -962
- package/dist/chunk-JSOOLOHP.js +0 -468
- package/dist/chunk-JTIWQLY5.js +0 -98
- package/dist/chunk-JWV7LUFM.js +0 -547
- package/dist/chunk-JXTNP3B5.js +0 -215
- package/dist/chunk-KDAINT54.js +0 -131
- package/dist/chunk-KDVYI4LC.js +0 -35
- package/dist/chunk-KH7AOX2R.js +0 -930
- package/dist/chunk-KJTMY7K6.js +0 -224
- package/dist/chunk-KNA3OWJC.js +0 -114
- package/dist/chunk-L5GFFF5G.js +0 -604
- package/dist/chunk-LC6PVPJX.js +0 -76
- package/dist/chunk-LQACNCAV.js +0 -334
- package/dist/chunk-MCJ5I5LR.js +0 -3187
- package/dist/chunk-MCJ5I5LR.js.map +0 -1
- package/dist/chunk-MK4HCMEA.js +0 -325
- package/dist/chunk-MKG57P2E.js +0 -783
- package/dist/chunk-MOKZ5XZO.js +0 -455
- package/dist/chunk-MXVP7Z54.js +0 -163
- package/dist/chunk-MYIOR35H.js +0 -225
- package/dist/chunk-MZPS46OR.js +0 -76
- package/dist/chunk-N3PASNUA.js +0 -136
- package/dist/chunk-O3O7PXMK.js +0 -103
- package/dist/chunk-OFMFBRSL.js +0 -25
- package/dist/chunk-OLPABGH3.js +0 -152
- package/dist/chunk-ORQ3WBM6.js +0 -225
- package/dist/chunk-PH3FZZIT.js +0 -544
- package/dist/chunk-Q5DFEVLE.js +0 -148
- package/dist/chunk-QEREDRZO.js +0 -246
- package/dist/chunk-QUSDGZFS.js +0 -188
- package/dist/chunk-QZSNT67Z.js +0 -24026
- package/dist/chunk-QZSNT67Z.js.map +0 -1
- package/dist/chunk-RF3TP643.js +0 -288
- package/dist/chunk-RIRSFFWA.js +0 -191
- package/dist/chunk-RJ2ETGAQ.js +0 -73
- package/dist/chunk-SIUYWLXB.js +0 -494
- package/dist/chunk-TYFXPC5D.js +0 -1902
- package/dist/chunk-TYFXPC5D.js.map +0 -1
- package/dist/chunk-TZTHGLWN.js +0 -66
- package/dist/chunk-UJTIMPEE.js +0 -203
- package/dist/chunk-UKZKLXTE.js +0 -638
- package/dist/chunk-UQZZM6UM.js +0 -831
- package/dist/chunk-UUXGSDUC.js +0 -297
- package/dist/chunk-UZHDNE6M.js +0 -2209
- package/dist/chunk-UZHDNE6M.js.map +0 -1
- package/dist/chunk-VJ4IOJQZ.js +0 -19
- package/dist/chunk-VMZ62LHB.js +0 -1254
- package/dist/chunk-W743FIEY.js +0 -207
- package/dist/chunk-WR5Y64OE.js +0 -718
- package/dist/chunk-X25XRSDP.js +0 -57
- package/dist/chunk-X3GWGFZP.js +0 -5368
- package/dist/chunk-X3GWGFZP.js.map +0 -1
- package/dist/chunk-X3YYZLBH.js +0 -285
- package/dist/chunk-X6U3B6YK.js +0 -343
- package/dist/chunk-XHWHBGKX.js +0 -4277
- package/dist/chunk-XHWHBGKX.js.map +0 -1
- package/dist/chunk-XRUB4KRV.js +0 -191
- package/dist/chunk-XRUB4KRV.js.map +0 -1
- package/dist/chunk-XZAVBONI.js +0 -64
- package/dist/chunk-Y5PNLB24.js +0 -84
- package/dist/chunk-Y6XWO4V4.js +0 -111
- package/dist/chunk-YB6G3B3L.js +0 -45
- package/dist/chunk-ZICB4OI5.js +0 -106
- package/dist/chunk-ZQ7JDYJB.js +0 -454
- package/dist/chunk-ZZ5B2ZRM.js +0 -94
- package/dist/cite-AJ5ZQWD2.js +0 -191
- package/dist/claim-CG3J32WS.js +0 -200
- package/dist/client-F6KOC77S.js +0 -19
- package/dist/code-NV4ARLFS.js +0 -76
- package/dist/companies-DQKUPFWT.js +0 -198
- package/dist/company-4CD2OJLB.js +0 -308
- package/dist/complete-JSP6VQYI.js +0 -84
- package/dist/config-GIETKZGS.js +0 -88
- package/dist/connect-O5NRDY4Y.js +0 -45
- package/dist/content-EQZKKIST.js +0 -85
- package/dist/conversation-YHKIB3CU.js +0 -96
- package/dist/conversion-report-JV6WZLB3.js +0 -127
- package/dist/conversion-upload-command-LXJYNNCK.js +0 -439
- package/dist/conversion-writes-NH3DKRQX.js +0 -122
- package/dist/conversions-E2KOXF3N.js +0 -140
- package/dist/conversions-TKPTZJVM.js +0 -78
- package/dist/copy-writes-FP3EI5LI.js +0 -170
- package/dist/countries-GZSBGSVT.js +0 -82
- package/dist/create-DQ5X5AJT.js +0 -62
- package/dist/create-FNPFVKLT.js +0 -239
- package/dist/create-GXOFZCR5.js +0 -135
- package/dist/create-VAZ65QNJ.js +0 -218
- package/dist/creatives-5EIDMQ66.js +0 -229
- package/dist/creatives-N7V2BSOW.js +0 -118
- package/dist/creatives-QWNQDPNE.js +0 -58
- package/dist/credentials-VCERJE24.js +0 -290
- package/dist/critique-62QFBC33.js +0 -1451
- package/dist/critique-MSL6EU5V.js +0 -232
- package/dist/crm-J3SCOR4L.js +0 -323
- package/dist/crm-PMPO6QJE.js +0 -229
- package/dist/crop-4V4P3SKI.js +0 -113
- package/dist/currency-NFKS6PRB.js +0 -88
- package/dist/custom-conversions-BFMGX2M3.js +0 -128
- package/dist/customers-EYVTYCGY.js +0 -65
- package/dist/decide-AM6B7WIL.js +0 -199
- package/dist/delete-46B7DSQV.js +0 -71
- package/dist/delete-7A6T6XBD.js +0 -69
- package/dist/delete-I3W3M6T7.js +0 -67
- package/dist/delete-RZCW3Y6L.js +0 -57
- package/dist/delete-WAPC4XC2.js +0 -69
- package/dist/delete-YYIM564B.js +0 -85
- package/dist/demographics-CPMNWMBZ.js +0 -141
- package/dist/describe-5OC7XX2U.js +0 -97
- package/dist/describe-EAPKNUUU.js +0 -97
- package/dist/dimensions-KI3OENZD.js +0 -101
- package/dist/discard-I773LYVR.js +0 -69
- package/dist/discover-DDYFCWQL.js +0 -172
- package/dist/discover-P7PBB3IV.js +0 -93
- package/dist/domain-7YO5HYHU.js +0 -101
- package/dist/download-IYK3UVBF.js +0 -172
- package/dist/download-YB2DVMRS.js +0 -337
- package/dist/draft-2EVXU5XB.js +0 -134
- package/dist/draft-2Z7EGKBO.js +0 -220
- package/dist/draft-4UTNI7BT.js +0 -332
- package/dist/draft-BCRW4RLR.js +0 -578
- package/dist/draft-CQPEGNPP.js +0 -374
- package/dist/draft-CQWYTMSS.js +0 -138
- package/dist/draft-JYZA3BFD.js +0 -260
- package/dist/draft-VT7DAOB7.js +0 -315
- package/dist/env-2RHPS2VF.js +0 -53
- package/dist/experiment-YAX26BOO.js +0 -1397
- package/dist/experiments-ZEN2H3RV.js +0 -236
- package/dist/export-RPNRPTDK.js +0 -168
- package/dist/extract-ZIW5JFTY.js +0 -143
- package/dist/facets-RNC4D4UH.js +0 -117
- package/dist/favorites-536I3GZD.js +0 -178
- package/dist/feed-W3ECHUEX.js +0 -177
- package/dist/feedback-2YJ24NV7.js +0 -115
- package/dist/feedback-X3GLQ2QF.js +0 -114
- package/dist/feedback-record-A5JLS3QY.js +0 -269
- package/dist/fetch-6XMRKLYH.js +0 -204
- package/dist/fetch-KB64NPDF.js +0 -139
- package/dist/find-UGFONLSD.js +0 -144
- package/dist/fit-BRJSLR7P.js +0 -65
- package/dist/flows-LXJHL3KW.js +0 -340
- package/dist/follow-5VX5JWAQ.js +0 -94
- package/dist/follow-competitors-D7I33T5C.js +0 -112
- package/dist/following-6DI4IZ7P.js +0 -113
- package/dist/fonts-UUSCLUHW.js +0 -39
- package/dist/forecast-YIDXHMST.js +0 -121
- package/dist/forecast-YO6BNYX7.js +0 -169
- package/dist/funding-QDKFNQI2.js +0 -85
- package/dist/funnel-M3SRPZQT.js +0 -397
- package/dist/ga4-N6EBLN2W.js +0 -55
- package/dist/generate-VGGXTZBP.js +0 -263
- package/dist/get-42V7UTNF.js +0 -59
- package/dist/get-5SCYUC4G.js +0 -38
- package/dist/get-BQBLPGFE.js +0 -74
- package/dist/get-JHOH74X5.js +0 -56
- package/dist/get-KVZSVN7U.js +0 -62
- package/dist/get-OZ7THI2W.js +0 -82
- package/dist/get-TBMTBGHJ.js +0 -62
- package/dist/get-V4NJXKUR.js +0 -92
- package/dist/gif-M2GMVWM4.js +0 -111
- package/dist/google-5U5KXEX7.js +0 -163
- package/dist/google-KTVWAA7F.js +0 -3300
- package/dist/google-ads-YZTK3YTW.js +0 -198
- package/dist/group-PLTVV7UZ.js +0 -43
- package/dist/group-THZPJALS.js +0 -43
- package/dist/gsc-FILOUFCG.js +0 -30
- package/dist/history-QATQCGVQ.js +0 -69
- package/dist/history-RYTNMGU5.js +0 -153
- package/dist/history-XDYDNQWK.js +0 -102
- package/dist/hubspot-IJERD4KT.js +0 -814
- package/dist/icon-THWS5VPO.js +0 -138
- package/dist/ideas-TT24LJR5.js +0 -45
- package/dist/images-PLYPUXM2.js +0 -92
- package/dist/improve-NWFQI63B.js +0 -86
- package/dist/ingest-CSPC3RUK.js +0 -131
- package/dist/ingest-MSPQX3Z6.js +0 -28
- package/dist/insights-AVNMRFQ4.js +0 -658
- package/dist/insights-OZ2EXOHH.js +0 -132
- package/dist/inspect-VD6CB2NA.js +0 -192
- package/dist/inspiration-FPB3IB7X.js +0 -53
- package/dist/instant-experiences-M2JYG2QS.js +0 -264
- package/dist/intent-HXRSLFIO.js +0 -95
- package/dist/job-OJB6KIDV.js +0 -202
- package/dist/job-create-C6FGCDW4.js +0 -109
- package/dist/job-status-4RJHESID.js +0 -74
- package/dist/keep-I6FLGJH4.js +0 -78
- package/dist/keyword-gap-WUHMSTNR.js +0 -130
- package/dist/keyword-metrics-NJV3WR75.js +0 -200
- package/dist/keywords-for-site-B7MUDHFH.js +0 -131
- package/dist/knowledge-H5PJ6LZB.js +0 -195
- package/dist/landing-RKOEVY7L.js +0 -28
- package/dist/landings-AELJXEYN.js +0 -151
- package/dist/languages-27QCKMNL.js +0 -40
- package/dist/languages-GCRI2PI3.js +0 -55
- package/dist/launches-CKPZFVMQ.js +0 -19
- package/dist/layerize-PHY25VNC.js +0 -190
- package/dist/lead-routes-ZMKRNL57.js +0 -733
- package/dist/leads-AEXWNBAT.js +0 -541
- package/dist/leads-O2NLCYDO.js +0 -115
- package/dist/learn-XNN3DGDF.js +0 -207
- package/dist/library-5YJCCEFL.js +0 -212
- package/dist/lighthouse-W3KAVW2G.js +0 -75
- package/dist/line-item-writes-VSP6WEYK.js +0 -211
- package/dist/line-items-BQ2CKMGL.js +0 -107
- package/dist/link-ENZQAISO.js +0 -67
- package/dist/linkedin-YALC66DF.js +0 -1344
- package/dist/linkedin-person-3RCX4MI3.js +0 -139
- package/dist/list-2EJ3XZ6I.js +0 -93
- package/dist/list-AF522LRC.js +0 -67
- package/dist/list-BQWHFEWY.js +0 -65
- package/dist/list-E7JG27WS.js +0 -50
- package/dist/list-ERCPPED6.js +0 -76
- package/dist/list-GPTYUCSX.js +0 -154
- package/dist/list-HYZL4576.js +0 -57
- package/dist/list-IKQFAJP7.js +0 -51
- package/dist/list-VYTHVUDP.js +0 -306
- package/dist/locations-EA5VGY56.js +0 -69
- package/dist/locations-OS24BBXE.js +0 -40
- package/dist/log-NJR3FJWN.js +0 -95
- package/dist/logo-ZSSR66WS.js +0 -19
- package/dist/lookup-QNLX2535.js +0 -23
- package/dist/make-4XUB6RSF.js +0 -1367
- package/dist/map-LIYQCWXU.js +0 -445
- package/dist/mcp-QDOAKB3A.js +0 -729
- package/dist/media-5SWJCRHI.js +0 -18
- package/dist/media-WGIEUEZW.js +0 -89
- package/dist/media-sources-LFSDIPUB.js +0 -35
- package/dist/members-KGKQQFMN.js +0 -47
- package/dist/meme-3QYKC4BF.js +0 -108
- package/dist/meta-DRDMT5X4.js +0 -124
- package/dist/metrics-NCAYDJNO.js +0 -152
- package/dist/models-SITHUNAA.js +0 -155
- package/dist/normalize-DQPKM3MG.js +0 -144
- package/dist/normalize-M3VMWF4W.js +0 -806
- package/dist/options-XIH7YPEG.js +0 -125
- package/dist/organization-BUSXIGA4.js +0 -949
- package/dist/output-HZW7LNUL.js +0 -24
- package/dist/page-GBLVAKU3.js +0 -105
- package/dist/page-photos-PDSKTR2Z.js +0 -118
- package/dist/pages-UH6XEZBO.js +0 -67
- package/dist/performance-PU4NHFUE.js +0 -27
- package/dist/performance-Y2DTYSFV.js +0 -5565
- package/dist/pinterest-235S7E6H.js +0 -105
- package/dist/pixels-GY4LKGJK.js +0 -62
- package/dist/pixels-PYNK73UG.js +0 -109
- package/dist/plan-4OYUV2EF.js +0 -208
- package/dist/posts-F327IP23.js +0 -36
- package/dist/preview-7E4E3QPT.js +0 -245
- package/dist/preview-NP3OFLT6.js +0 -101
- package/dist/profile-MKKJT2UF.js +0 -159
- package/dist/promoted-tweet-writes-XILB6VCP.js +0 -183
- package/dist/promoted-tweets-CBYZG6BG.js +0 -119
- package/dist/properties-RDOGNY2O.js +0 -101
- package/dist/publish-MDVPC77V.js +0 -350
- package/dist/query-K7R5GQ4E.js +0 -236
- package/dist/query-LJS64SEQ.js +0 -62
- package/dist/query-PO3RT7BR.js +0 -231
- package/dist/questionnaire-4OH6K2BF.js +0 -94
- package/dist/read-MU5XGWMK.js +0 -141
- package/dist/reddit-ZPKVVZGP.js +0 -29
- package/dist/refresh-JSCYTM4B.js +0 -42
- package/dist/refresh-V34YWN3W.js +0 -97
- package/dist/release-WRNUOSHB.js +0 -63
- package/dist/relevant-pages-OFKZYWR3.js +0 -99
- package/dist/remove-6FXTPEB6.js +0 -49
- package/dist/remove-HKWV7P27.js +0 -53
- package/dist/reopen-VHHYVAKC.js +0 -66
- package/dist/rerun-THE43RCG.js +0 -97
- package/dist/research-773Y7GT4.js +0 -75
- package/dist/research-G5A2WXVK.js +0 -265
- package/dist/reset-GFJ3AKF5.js +0 -57
- package/dist/reset-MVTWA3HT.js +0 -57
- package/dist/resolve-FCAP4LQ3.js +0 -124
- package/dist/retry-AGHA6IVT.js +0 -65
- package/dist/retry-LDJ6FZCZ.js +0 -63
- package/dist/retry-failed-FCS6PNUZ.js +0 -45
- package/dist/revenue-VFML2I5V.js +0 -91
- package/dist/rule-writes-KWJNFMJV.js +0 -530
- package/dist/rules-4A25K2P7.js +0 -99
- package/dist/rules-NRH2X4BM.js +0 -217
- package/dist/rules-add-GT7NCUB3.js +0 -465
- package/dist/run-NFLKYVIC.js +0 -72
- package/dist/run-ZLHQNLCF.js +0 -69
- package/dist/scaffold-ad-AJN67FWG.js +0 -1513
- package/dist/scaffold-static-ad-L6KXZ3TN.js +0 -1012
- package/dist/scaffold-static-ad-L6KXZ3TN.js.map +0 -1
- package/dist/scaffold-video-XQBZZ5TZ.js +0 -885
- package/dist/schedule-45CJDHIX.js +0 -64
- package/dist/schedule-XFEPEQTN.js +0 -67
- package/dist/scheduled-agents-72MWHK63.js +0 -55
- package/dist/schema-L4PETLZT.js +0 -152
- package/dist/schema-VX66FH4O.js +0 -135
- package/dist/scrape-D3XGARHR.js +0 -2209
- package/dist/screenshot-5LWUP5VN.js +0 -103
- package/dist/search-4DBP6EH5.js +0 -92
- package/dist/search-HNRANK6H.js +0 -51
- package/dist/search-KGE3BSSH.js +0 -228
- package/dist/search-O3AOWEXC.js +0 -26
- package/dist/search-QQDR74KQ.js +0 -91
- package/dist/search-Y6TS5UZS.js +0 -177
- package/dist/search-copy-EB3TONDS.js +0 -168
- package/dist/seeds-RGIFHHYC.js +0 -101
- package/dist/select-MZ2U7U5U.js +0 -110
- package/dist/sends-I2B6F5NW.js +0 -349
- package/dist/sequences-SSLZ3XTP.js +0 -146
- package/dist/set-prompt-YH6PXNXB.js +0 -199
- package/dist/setup-links-Y4YYDQBK.js +0 -144
- package/dist/shared-Z7INVKCZ.js +0 -32
- package/dist/shopify-AUDLALBS.js +0 -4009
- package/dist/site-WZ654OP3.js +0 -180
- package/dist/sitemaps-EOMSRKOD.js +0 -77
- package/dist/sites-6M73AONG.js +0 -97
- package/dist/skills-PDHUHP2T.js +0 -47
- package/dist/sources-FCBFLR2J.js +0 -30
- package/dist/sources-OR36YOTG.js +0 -457
- package/dist/stale-VSSDVB4H.js +0 -90
- package/dist/stats-MFEH2TSW.js +0 -34
- package/dist/status-L7LYUD3F.js +0 -65
- package/dist/sticker-MWICUYQM.js +0 -103
- package/dist/stock-73PLAUYU.js +0 -212
- package/dist/studies-XNJXWD7I.js +0 -250
- package/dist/studio-D2OMFCZZ.js +0 -49
- package/dist/study-writes-MFAJQHXK.js +0 -471
- package/dist/suggest-KCN2NDYE.js +0 -66
- package/dist/sync-SI25TKY5.js +0 -279
- package/dist/sync-TANGFXUN.js +0 -55
- package/dist/sync-XBC3PSSV.js +0 -57
- package/dist/sync-definition-IM2NY5QC.js +0 -70
- package/dist/tag-NKAHDL35.js +0 -57
- package/dist/tag-manager-JFC6YYVP.js +0 -43
- package/dist/tags-2KNOJ7A6.js +0 -26
- package/dist/tags-COALQ2CT.js +0 -23
- package/dist/tags-HCJTTLSR.js +0 -227
- package/dist/tags-MVC56SHA.js +0 -23
- package/dist/tags-UNUZVGUA.js +0 -23
- package/dist/targeting-ZBGR2PSX.js +0 -762
- package/dist/targeting-constants-RF2732EW.js +0 -118
- package/dist/targeting-criteria-HU7OAJUA.js +0 -113
- package/dist/targets-BNH37YAQ.js +0 -106
- package/dist/terms-XFL6QO7A.js +0 -102
- package/dist/testimonials-IIAT5IDM.js +0 -32
- package/dist/themes-SUNQVNES.js +0 -95
- package/dist/top-companies-MSLNT33I.js +0 -111
- package/dist/transcript-7WFXVRVW.js +0 -165
- package/dist/translate-IPTYPZF6.js +0 -603
- package/dist/triggers-RBD2XGNG.js +0 -144
- package/dist/tweets-6PQHJXJC.js +0 -123
- package/dist/unfollow-OEMFPAFS.js +0 -46
- package/dist/unlink-5IMEUVIS.js +0 -70
- package/dist/unstage-DSOVSWEK.js +0 -88
- package/dist/unstage-O23ILHCY.js +0 -96
- package/dist/update-7JVV5ZL3.js +0 -66
- package/dist/update-CADTFTYC.js +0 -81
- package/dist/update-FIU2ECYQ.js +0 -192
- package/dist/update-HSS6CVUK.js +0 -101
- package/dist/update-XWL3Q5QY.js +0 -155
- package/dist/upload-B5SM33MK.js +0 -137
- package/dist/upload-GXS5CTOR.js +0 -155
- package/dist/upscale-BCI42TCP.js +0 -109
- package/dist/url-options-NZAS37S5.js +0 -131
- package/dist/url-params-LUQMABZX.js +0 -101
- package/dist/use-26VARHJT.js +0 -111
- package/dist/validate-4NXKYAL2.js +0 -125
- package/dist/validate-4NXKYAL2.js.map +0 -1
- package/dist/variant-F4EEYQJ7.js +0 -338
- package/dist/videos-AHOLXU42.js +0 -146
- package/dist/videos-FMV4AVB2.js +0 -41
- package/dist/view-X65GETAV.js +0 -133
- package/dist/viewer-check-2W6BTVQV.js +0 -83
- package/dist/web-K2EMYVCD.js +0 -173
- package/dist/winners-5PRDG7GT.js +0 -113
- package/dist/winning-ads-Q3RXH7EC.js +0 -86
- package/dist/write-commands-5OFOD7TE.js +0 -1169
- package/dist/write-commands-LHEJESKL.js +0 -206
- package/dist/write-commands-SD6DXVNK.js +0 -721
- package/dist/write-commands-UEQR7ZXO.js +0 -1524
- package/dist/x-UNSHYLJJ.js +0 -47
- /package/dist/{account-MYM2QNFO.js.map → account-EXGRZIXS.js.map} +0 -0
- /package/dist/{account-YJ2NNQYP.js.map → account-JVDP5ERG.js.map} +0 -0
- /package/dist/{account-OUKPRB7C.js.map → account-NSBALYYS.js.map} +0 -0
- /package/dist/{account-assets-HOOPV5KR.js.map → account-assets-EPEYTJFD.js.map} +0 -0
- /package/dist/{account-level-3QWMJTZQ.js.map → account-level-VD4NLB2D.js.map} +0 -0
- /package/dist/{account-reads-RKK5BA6L.js.map → account-reads-Z467VAL4.js.map} +0 -0
- /package/dist/{account-users-GHMPDZUM.js.map → account-users-342OZALE.js.map} +0 -0
- /package/dist/{account-writes-HEXKGWXC.js.map → account-writes-KEXINJ5D.js.map} +0 -0
- /package/dist/{accounts-OSVXKNSI.js.map → accounts-A47QUTTB.js.map} +0 -0
- /package/dist/{accounts-SJOO4MQX.js.map → accounts-E5TF2AFI.js.map} +0 -0
- /package/dist/{accounts-DDNEHXXT.js.map → accounts-QESGQJGZ.js.map} +0 -0
- /package/dist/{accounts-K7VD47FG.js.map → accounts-QR6OQ3GC.js.map} +0 -0
- /package/dist/{accounts-S7CEGWJL.js.map → accounts-UWC2TT6R.js.map} +0 -0
- /package/dist/{actions-JIXQEVIN.js.map → actions-NT3HXFFA.js.map} +0 -0
- /package/dist/{active-entities-4KQQSMRZ.js.map → active-entities-XRSJNBOV.js.map} +0 -0
- /package/dist/{activecampaign-4ST7BMHO.js.map → activecampaign-EYRHDSXY.js.map} +0 -0
- /package/dist/{activities-FRA33VZZ.js.map → activities-ZDWREYR7.js.map} +0 -0
- /package/dist/{ad-group-writes-O2OP4NJ6.js.map → ad-group-writes-SVR4RCKB.js.map} +0 -0
- /package/dist/{ad-groups-AMMMWHHX.js.map → ad-groups-C726HUXS.js.map} +0 -0
- /package/dist/{ad-writes-IWLRLR2E.js.map → ad-writes-RWJIWGEL.js.map} +0 -0
- /package/dist/{add-IMKVYDQV.js.map → add-25YZMFSH.js.map} +0 -0
- /package/dist/{add-PZEVRQ7Z.js.map → add-7MAL7JRX.js.map} +0 -0
- /package/dist/{add-QXI627AS.js.map → add-D44VCDRU.js.map} +0 -0
- /package/dist/{add-ZH5HJBUN.js.map → add-EPOHDTUO.js.map} +0 -0
- /package/dist/{add-SPQ4MOCQ.js.map → add-JO4ZPS23.js.map} +0 -0
- /package/dist/{add-NZ6SEWUR.js.map → add-NSW26HIM.js.map} +0 -0
- /package/dist/{add-accounts-D4V5K7SO.js.map → add-accounts-EKMSHAA4.js.map} +0 -0
- /package/dist/{ads-KLSFKXUE.js.map → ads-3KK7VQPU.js.map} +0 -0
- /package/dist/{ads-RTRWWEP5.js.map → ads-4YZYNU66.js.map} +0 -0
- /package/dist/{ads-L6SMNOUM.js.map → ads-DGL5SGP3.js.map} +0 -0
- /package/dist/{ads-7TQKAH4B.js.map → ads-EWZGIC4T.js.map} +0 -0
- /package/dist/{adsets-R75LSEV5.js.map → adsets-PSVCPCE3.js.map} +0 -0
- /package/dist/{advertisers-2GKICB23.js.map → advertisers-7NAPI5ZU.js.map} +0 -0
- /package/dist/{advertisers-T37UHN3C.js.map → advertisers-AHOWL3YL.js.map} +0 -0
- /package/dist/{analytics-WXLRAXXN.js.map → analytics-7H6NDVUQ.js.map} +0 -0
- /package/dist/{analytics-ITBXTEIC.js.map → analytics-GFFXCMLV.js.map} +0 -0
- /package/dist/{animate-WS63CZ3Y.js.map → animate-GTUI7XX4.js.map} +0 -0
- /package/dist/{approved-3XFZNRJR.js.map → approved-E4EZA5RT.js.map} +0 -0
- /package/dist/{asset-writes-DECROLE3.js.map → asset-writes-NDSHY5OT.js.map} +0 -0
- /package/dist/{assign-3CVJL35R.js.map → assign-SDPPWP3Q.js.map} +0 -0
- /package/dist/{audience-size-23UFSW6H.js.map → audience-size-LKDDHKED.js.map} +0 -0
- /package/dist/{audience-writes-VSC2BY4Y.js.map → audience-writes-4KQXVGHO.js.map} +0 -0
- /package/dist/{audiences-76S4WY7Q.js.map → audiences-6L43K2T2.js.map} +0 -0
- /package/dist/{audiences-RN745R53.js.map → audiences-T5LMTT3B.js.map} +0 -0
- /package/dist/{audiences-V773XHP2.js.map → audiences-UHLVATR6.js.map} +0 -0
- /package/dist/{audit-BIHMDO5K.js.map → audit-46DO2HV3.js.map} +0 -0
- /package/dist/{audit-OT42WBII.js.map → audit-TSZIQTUB.js.map} +0 -0
- /package/dist/{autocomplete-T642QXBX.js.map → autocomplete-5BSAOAMZ.js.map} +0 -0
- /package/dist/{avatars-33UGHCQA.js.map → avatars-S6RRD7M3.js.map} +0 -0
- /package/dist/{bid-pricing-UHU2HOAP.js.map → bid-pricing-5KUAINH4.js.map} +0 -0
- /package/dist/{brand-36YIAVGK.js.map → brand-KFK2MQWW.js.map} +0 -0
- /package/dist/{brief-A5XFT6VH.js.map → brief-6DV2PKAU.js.map} +0 -0
- /package/dist/{businesses-HECSW3EL.js.map → businesses-TRFYMZ4I.js.map} +0 -0
- /package/dist/{campaign-groups-TAVIZR4L.js.map → campaign-groups-5RPZPDNW.js.map} +0 -0
- /package/dist/{campaign-writes-72OPCWMG.js.map → campaign-writes-FUIGN5OR.js.map} +0 -0
- /package/dist/{campaign-writes-AQ5T5TII.js.map → campaign-writes-XMYBEVZF.js.map} +0 -0
- /package/dist/{campaigns-S62KEFVL.js.map → campaigns-2MTON2IE.js.map} +0 -0
- /package/dist/{campaigns-3P2UZWPD.js.map → campaigns-5A3IE735.js.map} +0 -0
- /package/dist/{campaigns-D2V423FD.js.map → campaigns-JNP3VDZK.js.map} +0 -0
- /package/dist/{campaigns-NW2H7SAR.js.map → campaigns-N2SWSBYT.js.map} +0 -0
- /package/dist/{canvas-D7L7R4D2.js.map → canvas-CHFNQTLY.js.map} +0 -0
- /package/dist/{capabilities-YC36LOZU.js.map → capabilities-2W3SRZ2I.js.map} +0 -0
- /package/dist/{cards-RYQN5JLR.js.map → cards-CXKIVM4D.js.map} +0 -0
- /package/dist/{catalog-URTZYAPU.js.map → catalog-6BER3SF7.js.map} +0 -0
- /package/dist/{catalogs-G33WT5PS.js.map → catalogs-4DNLG4AM.js.map} +0 -0
- /package/dist/{catalogs-XLWWM2Q3.js.map → catalogs-G5NOKL4L.js.map} +0 -0
- /package/dist/{changes-SI2W2PZL.js.map → changes-AS4RVEAL.js.map} +0 -0
- /package/dist/{chatgpt-PPWG5WOF.js.map → chatgpt-O6EEAYLF.js.map} +0 -0
- /package/dist/{chats-M3RP62YO.js.map → chats-4JLWMUAC.js.map} +0 -0
- /package/dist/{check-FQYDJ5RS.js.map → check-BOKLY5WG.js.map} +0 -0
- /package/dist/{chunk-JED4JBIK.js.map → chunk-2CC4CPDT.js.map} +0 -0
- /package/dist/{chunk-ZICB4OI5.js.map → chunk-3GXHML4V.js.map} +0 -0
- /package/dist/{chunk-HH5WM5VA.js.map → chunk-3KUNRKNV.js.map} +0 -0
- /package/dist/{chunk-BESCYH3K.js.map → chunk-3QPG2D27.js.map} +0 -0
- /package/dist/{chunk-ZZ5B2ZRM.js.map → chunk-3WN5GWX4.js.map} +0 -0
- /package/dist/{chunk-RJ2ETGAQ.js.map → chunk-4AO3LSYM.js.map} +0 -0
- /package/dist/{chunk-7TVVYP7K.js.map → chunk-4HFM5RCP.js.map} +0 -0
- /package/dist/{chunk-KH7AOX2R.js.map → chunk-4INBMXUS.js.map} +0 -0
- /package/dist/{chunk-6QINKM6T.js.map → chunk-5NMKNHJI.js.map} +0 -0
- /package/dist/{chunk-4UNJ4ENA.js.map → chunk-5QNW5PCM.js.map} +0 -0
- /package/dist/{chunk-KNA3OWJC.js.map → chunk-6AMN346B.js.map} +0 -0
- /package/dist/{chunk-JTIWQLY5.js.map → chunk-6D7WTUF3.js.map} +0 -0
- /package/dist/{chunk-RIRSFFWA.js.map → chunk-6EOWBGGW.js.map} +0 -0
- /package/dist/{chunk-X25XRSDP.js.map → chunk-6FQ7CJEX.js.map} +0 -0
- /package/dist/{chunk-OFMFBRSL.js.map → chunk-6MJKVNLL.js.map} +0 -0
- /package/dist/{chunk-JAC6JVCI.js.map → chunk-6OIKNJ7G.js.map} +0 -0
- /package/dist/{chunk-VJ4IOJQZ.js.map → chunk-6OZDN2FI.js.map} +0 -0
- /package/dist/{chunk-2JBPS2CV.js.map → chunk-75OGTGC4.js.map} +0 -0
- /package/dist/{chunk-6PO3WSFJ.js.map → chunk-7NBQQOCU.js.map} +0 -0
- /package/dist/{chunk-DRQI2CJJ.js.map → chunk-AQRBEPZL.js.map} +0 -0
- /package/dist/{chunk-TZTHGLWN.js.map → chunk-AXLKR3E4.js.map} +0 -0
- /package/dist/{chunk-BGMIO2FR.js.map → chunk-AZIXX73C.js.map} +0 -0
- /package/dist/{chunk-45D6WRCJ.js.map → chunk-B64KJW5C.js.map} +0 -0
- /package/dist/{chunk-MOKZ5XZO.js.map → chunk-BEZEZHQ6.js.map} +0 -0
- /package/dist/{chunk-4H6XLX7E.js.map → chunk-BIBXZJZI.js.map} +0 -0
- /package/dist/{chunk-FB5OU5HZ.js.map → chunk-BMK4F4CU.js.map} +0 -0
- /package/dist/{chunk-6E4KJMXO.js.map → chunk-C52Q3L4C.js.map} +0 -0
- /package/dist/{chunk-EL3TDR5S.js.map → chunk-CBVUO7SK.js.map} +0 -0
- /package/dist/{chunk-CP6RFWLW.js.map → chunk-CF5I4Q5M.js.map} +0 -0
- /package/dist/{chunk-7CORYCEZ.js.map → chunk-CST52ZME.js.map} +0 -0
- /package/dist/{chunk-MKG57P2E.js.map → chunk-CUTTTFAU.js.map} +0 -0
- /package/dist/{chunk-IGCS3X4F.js.map → chunk-D32EWSMB.js.map} +0 -0
- /package/dist/{chunk-N3PASNUA.js.map → chunk-DGHSXHZR.js.map} +0 -0
- /package/dist/{chunk-HJ3Q4NOM.js.map → chunk-DHF4FXWS.js.map} +0 -0
- /package/dist/{chunk-B2BQ2Q64.js.map → chunk-DPOUS5DN.js.map} +0 -0
- /package/dist/{chunk-FGTOOTYC.js.map → chunk-DW3H2XQA.js.map} +0 -0
- /package/dist/{chunk-5C4RRCKM.js.map → chunk-EJ6EED6I.js.map} +0 -0
- /package/dist/{chunk-KDAINT54.js.map → chunk-EM5R3BYC.js.map} +0 -0
- /package/dist/{chunk-CORECUKT.js.map → chunk-EMR5KGNY.js.map} +0 -0
- /package/dist/{chunk-JIE45TKJ.js.map → chunk-EONUZOJV.js.map} +0 -0
- /package/dist/{chunk-RF3TP643.js.map → chunk-FLTAPEVY.js.map} +0 -0
- /package/dist/{chunk-DLM5OSHM.js.map → chunk-GRX3JXSR.js.map} +0 -0
- /package/dist/{chunk-IWNLW7ZC.js.map → chunk-H25GY4U4.js.map} +0 -0
- /package/dist/{chunk-W743FIEY.js.map → chunk-H4RHZJ65.js.map} +0 -0
- /package/dist/{chunk-PH3FZZIT.js.map → chunk-H6ASYVQX.js.map} +0 -0
- /package/dist/{chunk-JWV7LUFM.js.map → chunk-HFIHXIYY.js.map} +0 -0
- /package/dist/{chunk-EIDHLGQM.js.map → chunk-HOA74TOS.js.map} +0 -0
- /package/dist/{chunk-GO6ISZUZ.js.map → chunk-HPF3USL2.js.map} +0 -0
- /package/dist/{chunk-DWPOAU4Z.js.map → chunk-HQDNDKNR.js.map} +0 -0
- /package/dist/{chunk-23RVCBL7.js.map → chunk-HXSYWXLH.js.map} +0 -0
- /package/dist/{chunk-XZAVBONI.js.map → chunk-I3QLWGKS.js.map} +0 -0
- /package/dist/{chunk-J32CYEIH.js.map → chunk-IYDESWW4.js.map} +0 -0
- /package/dist/{chunk-H3HA22Z3.js.map → chunk-J4AWNWKN.js.map} +0 -0
- /package/dist/{chunk-O3O7PXMK.js.map → chunk-JAK5VDSG.js.map} +0 -0
- /package/dist/{chunk-3LYT3NQX.js.map → chunk-JAME5NBT.js.map} +0 -0
- /package/dist/{chunk-X3YYZLBH.js.map → chunk-JLAFNORO.js.map} +0 -0
- /package/dist/{chunk-IID2MAYZ.js.map → chunk-KG5VNPKU.js.map} +0 -0
- /package/dist/{chunk-LC6PVPJX.js.map → chunk-KGJ6EIX3.js.map} +0 -0
- /package/dist/{chunk-GUYFVYLY.js.map → chunk-KJHG2DWS.js.map} +0 -0
- /package/dist/{chunk-Y6XWO4V4.js.map → chunk-L4QEMWNJ.js.map} +0 -0
- /package/dist/{chunk-EFTYCX5C.js.map → chunk-L7I47VGM.js.map} +0 -0
- /package/dist/{chunk-GWLP45WQ.js.map → chunk-LAMSUL26.js.map} +0 -0
- /package/dist/{chunk-QEREDRZO.js.map → chunk-LJEJCIHR.js.map} +0 -0
- /package/dist/{chunk-JCDCIQMA.js.map → chunk-LLTHDEM2.js.map} +0 -0
- /package/dist/{chunk-QUSDGZFS.js.map → chunk-M4KFO256.js.map} +0 -0
- /package/dist/{chunk-AIK2HPDZ.js.map → chunk-M5PZ6QQB.js.map} +0 -0
- /package/dist/{chunk-LQACNCAV.js.map → chunk-MFGUR5OD.js.map} +0 -0
- /package/dist/{chunk-IDDG4QKO.js.map → chunk-MIHY534L.js.map} +0 -0
- /package/dist/{chunk-MYIOR35H.js.map → chunk-MKOI6QYM.js.map} +0 -0
- /package/dist/{chunk-MK4HCMEA.js.map → chunk-MPTNN35I.js.map} +0 -0
- /package/dist/{chunk-DEZBCK5P.js.map → chunk-MSIOGH67.js.map} +0 -0
- /package/dist/{chunk-D3YAFC6K.js.map → chunk-MTW2NDDD.js.map} +0 -0
- /package/dist/{chunk-UKZKLXTE.js.map → chunk-NOCBNING.js.map} +0 -0
- /package/dist/{chunk-GDRJS2QJ.js.map → chunk-NWLK5RPA.js.map} +0 -0
- /package/dist/{chunk-X6U3B6YK.js.map → chunk-O5VSYBUA.js.map} +0 -0
- /package/dist/{chunk-EJBLF2LI.js.map → chunk-PR5OPERY.js.map} +0 -0
- /package/dist/{chunk-Y5PNLB24.js.map → chunk-Q3G4ZI2U.js.map} +0 -0
- /package/dist/{chunk-KDVYI4LC.js.map → chunk-Q5XUFN2W.js.map} +0 -0
- /package/dist/{chunk-E56V3RFO.js.map → chunk-Q736UFSD.js.map} +0 -0
- /package/dist/{chunk-Q5DFEVLE.js.map → chunk-QGAUDVMR.js.map} +0 -0
- /package/dist/{chunk-JSOOLOHP.js.map → chunk-QRRAMUKV.js.map} +0 -0
- /package/dist/{chunk-22RM3UOO.js.map → chunk-QZ4YHQLW.js.map} +0 -0
- /package/dist/{chunk-SIUYWLXB.js.map → chunk-RGLTITIH.js.map} +0 -0
- /package/dist/{chunk-ORQ3WBM6.js.map → chunk-RIVQ4PQQ.js.map} +0 -0
- /package/dist/{chunk-MXVP7Z54.js.map → chunk-RLLPY62L.js.map} +0 -0
- /package/dist/{chunk-H3RCEM6L.js.map → chunk-RQHXWPET.js.map} +0 -0
- /package/dist/{chunk-A4O3JL6D.js.map → chunk-RRKUXGAU.js.map} +0 -0
- /package/dist/{chunk-FGAXZ7ET.js.map → chunk-RULW4627.js.map} +0 -0
- /package/dist/{chunk-2N2R5YSN.js.map → chunk-S4RCF3YT.js.map} +0 -0
- /package/dist/{chunk-5E4Y6RVY.js.map → chunk-S5S54J2K.js.map} +0 -0
- /package/dist/{chunk-MZPS46OR.js.map → chunk-SIKCVWM3.js.map} +0 -0
- /package/dist/{chunk-JXTNP3B5.js.map → chunk-SIRRBWQ2.js.map} +0 -0
- /package/dist/{chunk-UQZZM6UM.js.map → chunk-TCLJRWST.js.map} +0 -0
- /package/dist/{chunk-FLQNIFG2.js.map → chunk-TLQY4QBW.js.map} +0 -0
- /package/dist/{chunk-G6U45QD3.js.map → chunk-UK4XSLV2.js.map} +0 -0
- /package/dist/{chunk-4PAGS7QH.js.map → chunk-URGXEDFV.js.map} +0 -0
- /package/dist/{chunk-VMZ62LHB.js.map → chunk-UVUY6FLV.js.map} +0 -0
- /package/dist/{chunk-FUIGPJZZ.js.map → chunk-V4HS5JRL.js.map} +0 -0
- /package/dist/{chunk-ANRTDNPQ.js.map → chunk-V7EN5LFS.js.map} +0 -0
- /package/dist/{chunk-2TS2ITSG.js.map → chunk-WTOBG3YL.js.map} +0 -0
- /package/dist/{chunk-OLPABGH3.js.map → chunk-WTPID22G.js.map} +0 -0
- /package/dist/{chunk-2VW7S77J.js.map → chunk-WYMX3F47.js.map} +0 -0
- /package/dist/{chunk-BMMXYR7A.js.map → chunk-WZXMZFVB.js.map} +0 -0
- /package/dist/{chunk-KJTMY7K6.js.map → chunk-X5YHMGAT.js.map} +0 -0
- /package/dist/{chunk-WR5Y64OE.js.map → chunk-XA76OGSL.js.map} +0 -0
- /package/dist/{chunk-UUXGSDUC.js.map → chunk-XA7JN7YE.js.map} +0 -0
- /package/dist/{chunk-L5GFFF5G.js.map → chunk-XHAGX4J4.js.map} +0 -0
- /package/dist/{chunk-4OQG4HBG.js.map → chunk-XY7W6MQN.js.map} +0 -0
- /package/dist/{chunk-UJTIMPEE.js.map → chunk-YAINUFSC.js.map} +0 -0
- /package/dist/{chunk-5ZHXLY7Y.js.map → chunk-YAMKCMAS.js.map} +0 -0
- /package/dist/{chunk-CDTAKCJR.js.map → chunk-YRWCXYWW.js.map} +0 -0
- /package/dist/{chunk-E3PYHCQL.js.map → chunk-Z7ICQKC2.js.map} +0 -0
- /package/dist/{chunk-YB6G3B3L.js.map → chunk-ZCGM7ZWM.js.map} +0 -0
- /package/dist/{chunk-ZQ7JDYJB.js.map → chunk-ZMNRSTNV.js.map} +0 -0
- /package/dist/{cite-AJ5ZQWD2.js.map → cite-WCAOCOO5.js.map} +0 -0
- /package/dist/{claim-CG3J32WS.js.map → claim-L4WLCVUL.js.map} +0 -0
- /package/dist/{client-F6KOC77S.js.map → client-VCKP6WBR.js.map} +0 -0
- /package/dist/{code-NV4ARLFS.js.map → code-VXOTFGD2.js.map} +0 -0
- /package/dist/{companies-DQKUPFWT.js.map → companies-HW46BRQG.js.map} +0 -0
- /package/dist/{company-4CD2OJLB.js.map → company-KCIDE7SL.js.map} +0 -0
- /package/dist/{complete-JSP6VQYI.js.map → complete-JXM25FVW.js.map} +0 -0
- /package/dist/{config-GIETKZGS.js.map → config-UR45YCIN.js.map} +0 -0
- /package/dist/{connect-O5NRDY4Y.js.map → connect-7TX7AAM5.js.map} +0 -0
- /package/dist/{content-EQZKKIST.js.map → content-EQQIKG5H.js.map} +0 -0
- /package/dist/{conversation-YHKIB3CU.js.map → conversation-YIDUB6GL.js.map} +0 -0
- /package/dist/{conversion-report-JV6WZLB3.js.map → conversion-report-33SG7SHU.js.map} +0 -0
- /package/dist/{conversion-upload-command-LXJYNNCK.js.map → conversion-upload-command-N3OMLLF2.js.map} +0 -0
- /package/dist/{conversion-writes-NH3DKRQX.js.map → conversion-writes-XGGTBML5.js.map} +0 -0
- /package/dist/{conversions-E2KOXF3N.js.map → conversions-F4OZYUCT.js.map} +0 -0
- /package/dist/{conversions-TKPTZJVM.js.map → conversions-PPP4QK7U.js.map} +0 -0
- /package/dist/{copy-writes-FP3EI5LI.js.map → copy-writes-JVUX3YDL.js.map} +0 -0
- /package/dist/{countries-GZSBGSVT.js.map → countries-GRCU4IGM.js.map} +0 -0
- /package/dist/{create-FNPFVKLT.js.map → create-6EAKNERA.js.map} +0 -0
- /package/dist/{create-VAZ65QNJ.js.map → create-772LZHZR.js.map} +0 -0
- /package/dist/{create-DQ5X5AJT.js.map → create-FDNMIVFX.js.map} +0 -0
- /package/dist/{create-GXOFZCR5.js.map → create-X2QM7GA7.js.map} +0 -0
- /package/dist/{creatives-N7V2BSOW.js.map → creatives-4EPM3RHG.js.map} +0 -0
- /package/dist/{creatives-QWNQDPNE.js.map → creatives-K2AAW6EL.js.map} +0 -0
- /package/dist/{creatives-5EIDMQ66.js.map → creatives-SNYN4KIM.js.map} +0 -0
- /package/dist/{credentials-VCERJE24.js.map → credentials-KZZVBO42.js.map} +0 -0
- /package/dist/{critique-62QFBC33.js.map → critique-G5QXRHPF.js.map} +0 -0
- /package/dist/{critique-MSL6EU5V.js.map → critique-PUHOJI7V.js.map} +0 -0
- /package/dist/{crm-PMPO6QJE.js.map → crm-4LZZVT4N.js.map} +0 -0
- /package/dist/{crm-J3SCOR4L.js.map → crm-M6NXDU5B.js.map} +0 -0
- /package/dist/{crop-4V4P3SKI.js.map → crop-NE7YX4SS.js.map} +0 -0
- /package/dist/{currency-NFKS6PRB.js.map → currency-HK2ZW2VW.js.map} +0 -0
- /package/dist/{custom-conversions-BFMGX2M3.js.map → custom-conversions-GQTU5E6X.js.map} +0 -0
- /package/dist/{customers-EYVTYCGY.js.map → customers-V5NT4W7X.js.map} +0 -0
- /package/dist/{decide-AM6B7WIL.js.map → decide-6Q5X3V3F.js.map} +0 -0
- /package/dist/{delete-WAPC4XC2.js.map → delete-EKKOEB3N.js.map} +0 -0
- /package/dist/{delete-RZCW3Y6L.js.map → delete-GQIKNO53.js.map} +0 -0
- /package/dist/{delete-7A6T6XBD.js.map → delete-LFZIPQEO.js.map} +0 -0
- /package/dist/{delete-YYIM564B.js.map → delete-QHDDR66K.js.map} +0 -0
- /package/dist/{delete-46B7DSQV.js.map → delete-SP66F7ZV.js.map} +0 -0
- /package/dist/{delete-I3W3M6T7.js.map → delete-YOEI63OT.js.map} +0 -0
- /package/dist/{demographics-CPMNWMBZ.js.map → demographics-CEQ74O74.js.map} +0 -0
- /package/dist/{describe-5OC7XX2U.js.map → describe-DJPIUEFE.js.map} +0 -0
- /package/dist/{describe-EAPKNUUU.js.map → describe-MAGTSOW4.js.map} +0 -0
- /package/dist/{dimensions-KI3OENZD.js.map → dimensions-IC2H7V3H.js.map} +0 -0
- /package/dist/{discard-I773LYVR.js.map → discard-5GDF3TP3.js.map} +0 -0
- /package/dist/{discover-P7PBB3IV.js.map → discover-PSL2NBJL.js.map} +0 -0
- /package/dist/{discover-DDYFCWQL.js.map → discover-Q5PAOIQQ.js.map} +0 -0
- /package/dist/{domain-7YO5HYHU.js.map → domain-PKOUPHHF.js.map} +0 -0
- /package/dist/{download-IYK3UVBF.js.map → download-2WNTN7JQ.js.map} +0 -0
- /package/dist/{download-YB2DVMRS.js.map → download-EHDJXBAC.js.map} +0 -0
- /package/dist/{draft-2EVXU5XB.js.map → draft-27NMTARB.js.map} +0 -0
- /package/dist/{draft-BCRW4RLR.js.map → draft-CF4XNJG5.js.map} +0 -0
- /package/dist/{draft-4UTNI7BT.js.map → draft-F4CVSL2I.js.map} +0 -0
- /package/dist/{draft-CQWYTMSS.js.map → draft-JESKGZ6O.js.map} +0 -0
- /package/dist/{draft-VT7DAOB7.js.map → draft-L2NXCIYT.js.map} +0 -0
- /package/dist/{draft-JYZA3BFD.js.map → draft-MWYKIZC4.js.map} +0 -0
- /package/dist/{draft-CQPEGNPP.js.map → draft-RZCTAOI2.js.map} +0 -0
- /package/dist/{draft-2Z7EGKBO.js.map → draft-UEVBUNKV.js.map} +0 -0
- /package/dist/{env-2RHPS2VF.js.map → env-NZXNMWSD.js.map} +0 -0
- /package/dist/{experiment-YAX26BOO.js.map → experiment-XAYSEYTU.js.map} +0 -0
- /package/dist/{experiments-ZEN2H3RV.js.map → experiments-DWC6L72S.js.map} +0 -0
- /package/dist/{export-RPNRPTDK.js.map → export-W54UZ62P.js.map} +0 -0
- /package/dist/{extract-ZIW5JFTY.js.map → extract-6HJXSOZW.js.map} +0 -0
- /package/dist/{facets-RNC4D4UH.js.map → facets-TBOXGYJT.js.map} +0 -0
- /package/dist/{favorites-536I3GZD.js.map → favorites-Y6CT6NSQ.js.map} +0 -0
- /package/dist/{feed-W3ECHUEX.js.map → feed-35BRQPTH.js.map} +0 -0
- /package/dist/{feedback-X3GLQ2QF.js.map → feedback-MSMFYAEY.js.map} +0 -0
- /package/dist/{feedback-2YJ24NV7.js.map → feedback-WAC6S42V.js.map} +0 -0
- /package/dist/{feedback-record-A5JLS3QY.js.map → feedback-record-XRQ2R2WD.js.map} +0 -0
- /package/dist/{fetch-KB64NPDF.js.map → fetch-I6P72CDL.js.map} +0 -0
- /package/dist/{fetch-6XMRKLYH.js.map → fetch-LGX7B3IC.js.map} +0 -0
- /package/dist/{find-UGFONLSD.js.map → find-SVGRA7IA.js.map} +0 -0
- /package/dist/{fit-BRJSLR7P.js.map → fit-RVWPRBNO.js.map} +0 -0
- /package/dist/{flows-LXJHL3KW.js.map → flows-LA6EYMLS.js.map} +0 -0
- /package/dist/{follow-5VX5JWAQ.js.map → follow-24QSDNAG.js.map} +0 -0
- /package/dist/{follow-competitors-D7I33T5C.js.map → follow-competitors-AG4E4XFA.js.map} +0 -0
- /package/dist/{following-6DI4IZ7P.js.map → following-YGM6TBK3.js.map} +0 -0
- /package/dist/{fonts-UUSCLUHW.js.map → fonts-WRC34VSV.js.map} +0 -0
- /package/dist/{forecast-YIDXHMST.js.map → forecast-6VHRGBJG.js.map} +0 -0
- /package/dist/{forecast-YO6BNYX7.js.map → forecast-OVKXBLJB.js.map} +0 -0
- /package/dist/{funding-QDKFNQI2.js.map → funding-WZNGXRLJ.js.map} +0 -0
- /package/dist/{funnel-M3SRPZQT.js.map → funnel-U3GQIGND.js.map} +0 -0
- /package/dist/{ga4-N6EBLN2W.js.map → ga4-W3U5YTRT.js.map} +0 -0
- /package/dist/{generate-VGGXTZBP.js.map → generate-Y4NJEYIH.js.map} +0 -0
- /package/dist/{get-JHOH74X5.js.map → get-3MTAVNTP.js.map} +0 -0
- /package/dist/{get-TBMTBGHJ.js.map → get-5SPNAIUQ.js.map} +0 -0
- /package/dist/{get-OZ7THI2W.js.map → get-AHI247JG.js.map} +0 -0
- /package/dist/{get-42V7UTNF.js.map → get-GEUSRD5Y.js.map} +0 -0
- /package/dist/{get-BQBLPGFE.js.map → get-JIZPYK3Z.js.map} +0 -0
- /package/dist/{get-KVZSVN7U.js.map → get-PF3HGECD.js.map} +0 -0
- /package/dist/{get-5SCYUC4G.js.map → get-TS2ZJDCQ.js.map} +0 -0
- /package/dist/{get-V4NJXKUR.js.map → get-YWDZYEAC.js.map} +0 -0
- /package/dist/{gif-M2GMVWM4.js.map → gif-NP6EDGEE.js.map} +0 -0
- /package/dist/{google-KTVWAA7F.js.map → google-BMUJKAUO.js.map} +0 -0
- /package/dist/{google-5U5KXEX7.js.map → google-ZVAIFXQZ.js.map} +0 -0
- /package/dist/{google-ads-YZTK3YTW.js.map → google-ads-6Z7P3SCD.js.map} +0 -0
- /package/dist/{group-THZPJALS.js.map → group-3DT4UYSR.js.map} +0 -0
- /package/dist/{group-PLTVV7UZ.js.map → group-OEKKCFXT.js.map} +0 -0
- /package/dist/{gsc-FILOUFCG.js.map → gsc-4FEFPFPB.js.map} +0 -0
- /package/dist/{history-XDYDNQWK.js.map → history-4QUV45ZJ.js.map} +0 -0
- /package/dist/{history-RYTNMGU5.js.map → history-PD7FCTDD.js.map} +0 -0
- /package/dist/{history-QATQCGVQ.js.map → history-VKRYKQ4C.js.map} +0 -0
- /package/dist/{hubspot-IJERD4KT.js.map → hubspot-WEFAFKVJ.js.map} +0 -0
- /package/dist/{icon-THWS5VPO.js.map → icon-43UJTGGE.js.map} +0 -0
- /package/dist/{ideas-TT24LJR5.js.map → ideas-SMSEXKIA.js.map} +0 -0
- /package/dist/{images-PLYPUXM2.js.map → images-KAT4BPYV.js.map} +0 -0
- /package/dist/{improve-NWFQI63B.js.map → improve-IMXQN6OD.js.map} +0 -0
- /package/dist/{ingest-MSPQX3Z6.js.map → ingest-IHKTSJ4H.js.map} +0 -0
- /package/dist/{ingest-CSPC3RUK.js.map → ingest-TOHQ6MZA.js.map} +0 -0
- /package/dist/{insights-OZ2EXOHH.js.map → insights-3IPSEBYW.js.map} +0 -0
- /package/dist/{insights-AVNMRFQ4.js.map → insights-BR3456EI.js.map} +0 -0
- /package/dist/{inspect-VD6CB2NA.js.map → inspect-5MZBPDYS.js.map} +0 -0
- /package/dist/{inspiration-FPB3IB7X.js.map → inspiration-XZI5KCQW.js.map} +0 -0
- /package/dist/{instant-experiences-M2JYG2QS.js.map → instant-experiences-2LKF7XVK.js.map} +0 -0
- /package/dist/{intent-HXRSLFIO.js.map → intent-ZM4K623V.js.map} +0 -0
- /package/dist/{job-OJB6KIDV.js.map → job-GOX3KIKG.js.map} +0 -0
- /package/dist/{job-create-C6FGCDW4.js.map → job-create-F2PQSN3C.js.map} +0 -0
- /package/dist/{job-status-4RJHESID.js.map → job-status-3FMA5D7T.js.map} +0 -0
- /package/dist/{keep-I6FLGJH4.js.map → keep-23ZYMWPG.js.map} +0 -0
- /package/dist/{keyword-gap-WUHMSTNR.js.map → keyword-gap-FAAF2I6V.js.map} +0 -0
- /package/dist/{keyword-metrics-NJV3WR75.js.map → keyword-metrics-EXNJRJBY.js.map} +0 -0
- /package/dist/{keywords-for-site-B7MUDHFH.js.map → keywords-for-site-5LW77QWF.js.map} +0 -0
- /package/dist/{knowledge-H5PJ6LZB.js.map → knowledge-7M7DSRF3.js.map} +0 -0
- /package/dist/{landing-RKOEVY7L.js.map → landing-ZH4SD3DW.js.map} +0 -0
- /package/dist/{landings-AELJXEYN.js.map → landings-VNQ4VA2U.js.map} +0 -0
- /package/dist/{languages-GCRI2PI3.js.map → languages-2X22HXM3.js.map} +0 -0
- /package/dist/{languages-27QCKMNL.js.map → languages-ZGDTERIQ.js.map} +0 -0
- /package/dist/{launches-CKPZFVMQ.js.map → launches-L4EUROCJ.js.map} +0 -0
- /package/dist/{layerize-PHY25VNC.js.map → layerize-6QHQMA7Q.js.map} +0 -0
- /package/dist/{lead-routes-ZMKRNL57.js.map → lead-routes-5TPFJEVH.js.map} +0 -0
- /package/dist/{leads-AEXWNBAT.js.map → leads-4TLOH47R.js.map} +0 -0
- /package/dist/{leads-O2NLCYDO.js.map → leads-736RILZN.js.map} +0 -0
- /package/dist/{learn-XNN3DGDF.js.map → learn-BESXWXEN.js.map} +0 -0
- /package/dist/{library-5YJCCEFL.js.map → library-MNJC24E4.js.map} +0 -0
- /package/dist/{lighthouse-W3KAVW2G.js.map → lighthouse-DJMAXFTD.js.map} +0 -0
- /package/dist/{line-item-writes-VSP6WEYK.js.map → line-item-writes-FA72DHNQ.js.map} +0 -0
- /package/dist/{line-items-BQ2CKMGL.js.map → line-items-XVYE3IYT.js.map} +0 -0
- /package/dist/{link-ENZQAISO.js.map → link-6FPKFVC3.js.map} +0 -0
- /package/dist/{linkedin-YALC66DF.js.map → linkedin-TE6P4RYN.js.map} +0 -0
- /package/dist/{linkedin-person-3RCX4MI3.js.map → linkedin-person-TZJ6VEXE.js.map} +0 -0
- /package/dist/{list-IKQFAJP7.js.map → list-2277GCPH.js.map} +0 -0
- /package/dist/{list-GPTYUCSX.js.map → list-4R5EMKUQ.js.map} +0 -0
- /package/dist/{list-ERCPPED6.js.map → list-537S75BZ.js.map} +0 -0
- /package/dist/{list-VYTHVUDP.js.map → list-MN2FPF3T.js.map} +0 -0
- /package/dist/{list-AF522LRC.js.map → list-ORO4WDF4.js.map} +0 -0
- /package/dist/{list-E7JG27WS.js.map → list-Q52FPW3H.js.map} +0 -0
- /package/dist/{list-2EJ3XZ6I.js.map → list-V4PSDBLX.js.map} +0 -0
- /package/dist/{list-BQWHFEWY.js.map → list-WIXQXNKB.js.map} +0 -0
- /package/dist/{list-HYZL4576.js.map → list-XK33NCSC.js.map} +0 -0
- /package/dist/{locations-EA5VGY56.js.map → locations-A65MFB7Q.js.map} +0 -0
- /package/dist/{locations-OS24BBXE.js.map → locations-WN6B3IJK.js.map} +0 -0
- /package/dist/{log-NJR3FJWN.js.map → log-ABBZLPRU.js.map} +0 -0
- /package/dist/{logo-ZSSR66WS.js.map → logo-4LSFZ3ZO.js.map} +0 -0
- /package/dist/{lookup-QNLX2535.js.map → lookup-WIM5WR25.js.map} +0 -0
- /package/dist/{make-4XUB6RSF.js.map → make-QAFKU6WO.js.map} +0 -0
- /package/dist/{map-LIYQCWXU.js.map → map-52P35OKE.js.map} +0 -0
- /package/dist/{mcp-QDOAKB3A.js.map → mcp-PZ3VBIF4.js.map} +0 -0
- /package/dist/{media-WGIEUEZW.js.map → media-34I7UB7Z.js.map} +0 -0
- /package/dist/{media-5SWJCRHI.js.map → media-KKI3KWLR.js.map} +0 -0
- /package/dist/{media-sources-LFSDIPUB.js.map → media-sources-TT374PLN.js.map} +0 -0
- /package/dist/{members-KGKQQFMN.js.map → members-CF6VG6ZW.js.map} +0 -0
- /package/dist/{meme-3QYKC4BF.js.map → meme-6NFYFQ7T.js.map} +0 -0
- /package/dist/{meta-DRDMT5X4.js.map → meta-2UK7KIE4.js.map} +0 -0
- /package/dist/{metrics-NCAYDJNO.js.map → metrics-3U3ZO2RF.js.map} +0 -0
- /package/dist/{models-SITHUNAA.js.map → models-VOSJJFO2.js.map} +0 -0
- /package/dist/{normalize-DQPKM3MG.js.map → normalize-4LZCLMTQ.js.map} +0 -0
- /package/dist/{normalize-M3VMWF4W.js.map → normalize-G75RDSE4.js.map} +0 -0
- /package/dist/{options-XIH7YPEG.js.map → options-6IRL7CL6.js.map} +0 -0
- /package/dist/{organization-BUSXIGA4.js.map → organization-WMLLJE66.js.map} +0 -0
- /package/dist/{output-HZW7LNUL.js.map → output-ELEO2Z6R.js.map} +0 -0
- /package/dist/{page-GBLVAKU3.js.map → page-4X6IBUWG.js.map} +0 -0
- /package/dist/{page-photos-PDSKTR2Z.js.map → page-photos-KNBLMFLN.js.map} +0 -0
- /package/dist/{pages-UH6XEZBO.js.map → pages-7HW5YOZV.js.map} +0 -0
- /package/dist/{performance-Y2DTYSFV.js.map → performance-A7CYFBW2.js.map} +0 -0
- /package/dist/{performance-PU4NHFUE.js.map → performance-HYSTXLTS.js.map} +0 -0
- /package/dist/{pinterest-235S7E6H.js.map → pinterest-KA6VFDM4.js.map} +0 -0
- /package/dist/{pixels-PYNK73UG.js.map → pixels-D5HF24FI.js.map} +0 -0
- /package/dist/{pixels-GY4LKGJK.js.map → pixels-U6UA662G.js.map} +0 -0
- /package/dist/{plan-4OYUV2EF.js.map → plan-XCA6R3HZ.js.map} +0 -0
- /package/dist/{posts-F327IP23.js.map → posts-ALGM6ONV.js.map} +0 -0
- /package/dist/{preview-7E4E3QPT.js.map → preview-55TRUF4Q.js.map} +0 -0
- /package/dist/{preview-NP3OFLT6.js.map → preview-76ZP2QA3.js.map} +0 -0
- /package/dist/{profile-MKKJT2UF.js.map → profile-NHUPUCBR.js.map} +0 -0
- /package/dist/{promoted-tweet-writes-XILB6VCP.js.map → promoted-tweet-writes-I5G4IDL5.js.map} +0 -0
- /package/dist/{promoted-tweets-CBYZG6BG.js.map → promoted-tweets-X5XNO7IT.js.map} +0 -0
- /package/dist/{properties-RDOGNY2O.js.map → properties-2ZXA5BPJ.js.map} +0 -0
- /package/dist/{publish-MDVPC77V.js.map → publish-S2Z4EF4H.js.map} +0 -0
- /package/dist/{query-PO3RT7BR.js.map → query-63CTX2PH.js.map} +0 -0
- /package/dist/{query-K7R5GQ4E.js.map → query-DMWY3TDD.js.map} +0 -0
- /package/dist/{query-LJS64SEQ.js.map → query-SAQADBM2.js.map} +0 -0
- /package/dist/{questionnaire-4OH6K2BF.js.map → questionnaire-WHE42RD4.js.map} +0 -0
- /package/dist/{read-MU5XGWMK.js.map → read-NESEKULG.js.map} +0 -0
- /package/dist/{reddit-ZPKVVZGP.js.map → reddit-S2L5WDY7.js.map} +0 -0
- /package/dist/{refresh-JSCYTM4B.js.map → refresh-ILDEPU5A.js.map} +0 -0
- /package/dist/{refresh-V34YWN3W.js.map → refresh-K2YTJSH3.js.map} +0 -0
- /package/dist/{release-WRNUOSHB.js.map → release-FX76IIVN.js.map} +0 -0
- /package/dist/{relevant-pages-OFKZYWR3.js.map → relevant-pages-KTSODNNW.js.map} +0 -0
- /package/dist/{remove-HKWV7P27.js.map → remove-LOVWPLDO.js.map} +0 -0
- /package/dist/{remove-6FXTPEB6.js.map → remove-NHE4UT7G.js.map} +0 -0
- /package/dist/{reopen-VHHYVAKC.js.map → reopen-DXV2Y6Z3.js.map} +0 -0
- /package/dist/{rerun-THE43RCG.js.map → rerun-TFQCRRFK.js.map} +0 -0
- /package/dist/{research-G5A2WXVK.js.map → research-7PGDAKC7.js.map} +0 -0
- /package/dist/{research-773Y7GT4.js.map → research-HY5PSUCC.js.map} +0 -0
- /package/dist/{reset-GFJ3AKF5.js.map → reset-MEHUQJA4.js.map} +0 -0
- /package/dist/{reset-MVTWA3HT.js.map → reset-Y5VZJRDQ.js.map} +0 -0
- /package/dist/{resolve-FCAP4LQ3.js.map → resolve-FAVABEJW.js.map} +0 -0
- /package/dist/{retry-AGHA6IVT.js.map → retry-5IY4MNDW.js.map} +0 -0
- /package/dist/{retry-LDJ6FZCZ.js.map → retry-OMJ3C3AX.js.map} +0 -0
- /package/dist/{retry-failed-FCS6PNUZ.js.map → retry-failed-R5HPQ3KQ.js.map} +0 -0
- /package/dist/{revenue-VFML2I5V.js.map → revenue-S4KFZCOI.js.map} +0 -0
- /package/dist/{rule-writes-KWJNFMJV.js.map → rule-writes-QB4IWFCJ.js.map} +0 -0
- /package/dist/{rules-4A25K2P7.js.map → rules-66IGR2KA.js.map} +0 -0
- /package/dist/{rules-NRH2X4BM.js.map → rules-FYVD2QBB.js.map} +0 -0
- /package/dist/{rules-add-GT7NCUB3.js.map → rules-add-G7YGOYZJ.js.map} +0 -0
- /package/dist/{run-NFLKYVIC.js.map → run-LJVBH3JS.js.map} +0 -0
- /package/dist/{run-ZLHQNLCF.js.map → run-XJBWDWN6.js.map} +0 -0
- /package/dist/{scaffold-ad-AJN67FWG.js.map → scaffold-ad-GNMCB3QY.js.map} +0 -0
- /package/dist/{scaffold-video-XQBZZ5TZ.js.map → scaffold-video-G6G2NPUF.js.map} +0 -0
- /package/dist/{schedule-XFEPEQTN.js.map → schedule-D7EDEM45.js.map} +0 -0
- /package/dist/{schedule-45CJDHIX.js.map → schedule-OX5XHXLH.js.map} +0 -0
- /package/dist/{scheduled-agents-72MWHK63.js.map → scheduled-agents-A5ZFQB5X.js.map} +0 -0
- /package/dist/{schema-VX66FH4O.js.map → schema-NTGHAPR2.js.map} +0 -0
- /package/dist/{schema-L4PETLZT.js.map → schema-Z43AJOJ4.js.map} +0 -0
- /package/dist/{scrape-D3XGARHR.js.map → scrape-VL2RWSTW.js.map} +0 -0
- /package/dist/{screenshot-5LWUP5VN.js.map → screenshot-Y6EEXS3Q.js.map} +0 -0
- /package/dist/{search-HNRANK6H.js.map → search-CXC7N5XJ.js.map} +0 -0
- /package/dist/{search-KGE3BSSH.js.map → search-JEXYEAPQ.js.map} +0 -0
- /package/dist/{search-4DBP6EH5.js.map → search-L3GTZYRW.js.map} +0 -0
- /package/dist/{search-QQDR74KQ.js.map → search-TXBYKNQC.js.map} +0 -0
- /package/dist/{search-Y6TS5UZS.js.map → search-WCXQBMMM.js.map} +0 -0
- /package/dist/{search-O3AOWEXC.js.map → search-XHSTUBDY.js.map} +0 -0
- /package/dist/{search-copy-EB3TONDS.js.map → search-copy-FIPG7OCC.js.map} +0 -0
- /package/dist/{seeds-RGIFHHYC.js.map → seeds-ADJKURNG.js.map} +0 -0
- /package/dist/{select-MZ2U7U5U.js.map → select-5ZD7FVBT.js.map} +0 -0
- /package/dist/{sends-I2B6F5NW.js.map → sends-RS4LWRAC.js.map} +0 -0
- /package/dist/{sequences-SSLZ3XTP.js.map → sequences-2RPKDKGQ.js.map} +0 -0
- /package/dist/{set-prompt-YH6PXNXB.js.map → set-prompt-NGCVMQIQ.js.map} +0 -0
- /package/dist/{setup-links-Y4YYDQBK.js.map → setup-links-4HCSF55G.js.map} +0 -0
- /package/dist/{shared-Z7INVKCZ.js.map → shared-4GGUIOF2.js.map} +0 -0
- /package/dist/{shopify-AUDLALBS.js.map → shopify-GDR5WGHH.js.map} +0 -0
- /package/dist/{site-WZ654OP3.js.map → site-B7LT6KAO.js.map} +0 -0
- /package/dist/{sitemaps-EOMSRKOD.js.map → sitemaps-Z6IELTQV.js.map} +0 -0
- /package/dist/{sites-6M73AONG.js.map → sites-KLAKI2EY.js.map} +0 -0
- /package/dist/{skills-PDHUHP2T.js.map → skills-OJP36EVR.js.map} +0 -0
- /package/dist/{sources-FCBFLR2J.js.map → sources-6DPUEROC.js.map} +0 -0
- /package/dist/{sources-OR36YOTG.js.map → sources-OSUXCLID.js.map} +0 -0
- /package/dist/{stale-VSSDVB4H.js.map → stale-YKFKPPOH.js.map} +0 -0
- /package/dist/{stats-MFEH2TSW.js.map → stats-MIMFX4R7.js.map} +0 -0
- /package/dist/{status-L7LYUD3F.js.map → status-KIC3P5JV.js.map} +0 -0
- /package/dist/{sticker-MWICUYQM.js.map → sticker-IREEEN7I.js.map} +0 -0
- /package/dist/{stock-73PLAUYU.js.map → stock-VWFUFRYV.js.map} +0 -0
- /package/dist/{studies-XNJXWD7I.js.map → studies-YGYAH3JI.js.map} +0 -0
- /package/dist/{studio-D2OMFCZZ.js.map → studio-XLC37YGX.js.map} +0 -0
- /package/dist/{study-writes-MFAJQHXK.js.map → study-writes-UPGJB36A.js.map} +0 -0
- /package/dist/{suggest-KCN2NDYE.js.map → suggest-5RTISDLI.js.map} +0 -0
- /package/dist/{sync-TANGFXUN.js.map → sync-OHIXI4I6.js.map} +0 -0
- /package/dist/{sync-XBC3PSSV.js.map → sync-QBW4XH2H.js.map} +0 -0
- /package/dist/{sync-SI25TKY5.js.map → sync-VCAFAYW4.js.map} +0 -0
- /package/dist/{sync-definition-IM2NY5QC.js.map → sync-definition-4KMJK46H.js.map} +0 -0
- /package/dist/{tag-NKAHDL35.js.map → tag-DSCUKNC3.js.map} +0 -0
- /package/dist/{tag-manager-JFC6YYVP.js.map → tag-manager-IINALUEJ.js.map} +0 -0
- /package/dist/{tags-HCJTTLSR.js.map → tags-4F5UBPYG.js.map} +0 -0
- /package/dist/{tags-2KNOJ7A6.js.map → tags-4O5FPEEY.js.map} +0 -0
- /package/dist/{tags-MVC56SHA.js.map → tags-7RKKCQ4X.js.map} +0 -0
- /package/dist/{tags-UNUZVGUA.js.map → tags-CB4MWI3A.js.map} +0 -0
- /package/dist/{tags-COALQ2CT.js.map → tags-QZJIP4LJ.js.map} +0 -0
- /package/dist/{targeting-ZBGR2PSX.js.map → targeting-BM72UTI6.js.map} +0 -0
- /package/dist/{targeting-constants-RF2732EW.js.map → targeting-constants-54S3FXIF.js.map} +0 -0
- /package/dist/{targeting-criteria-HU7OAJUA.js.map → targeting-criteria-65UU7EYD.js.map} +0 -0
- /package/dist/{targets-BNH37YAQ.js.map → targets-T742OPQI.js.map} +0 -0
- /package/dist/{terms-XFL6QO7A.js.map → terms-OFHNLW6U.js.map} +0 -0
- /package/dist/{testimonials-IIAT5IDM.js.map → testimonials-HKJJXONO.js.map} +0 -0
- /package/dist/{themes-SUNQVNES.js.map → themes-Q6LVMEMF.js.map} +0 -0
- /package/dist/{top-companies-MSLNT33I.js.map → top-companies-T6AMU4C6.js.map} +0 -0
- /package/dist/{transcript-7WFXVRVW.js.map → transcript-DOUYMZAP.js.map} +0 -0
- /package/dist/{translate-IPTYPZF6.js.map → translate-WKOXFZTQ.js.map} +0 -0
- /package/dist/{triggers-RBD2XGNG.js.map → triggers-EYY4GSUL.js.map} +0 -0
- /package/dist/{tweets-6PQHJXJC.js.map → tweets-TRTXC6O4.js.map} +0 -0
- /package/dist/{unfollow-OEMFPAFS.js.map → unfollow-DATOGPLZ.js.map} +0 -0
- /package/dist/{unlink-5IMEUVIS.js.map → unlink-JNM4WRZK.js.map} +0 -0
- /package/dist/{unstage-O23ILHCY.js.map → unstage-LLQCMZ5H.js.map} +0 -0
- /package/dist/{unstage-DSOVSWEK.js.map → unstage-QF4JT5YP.js.map} +0 -0
- /package/dist/{update-HSS6CVUK.js.map → update-6V3RBRIE.js.map} +0 -0
- /package/dist/{update-FIU2ECYQ.js.map → update-J4DURR4K.js.map} +0 -0
- /package/dist/{update-XWL3Q5QY.js.map → update-J7Y6LZC5.js.map} +0 -0
- /package/dist/{update-7JVV5ZL3.js.map → update-MQ4NYIU6.js.map} +0 -0
- /package/dist/{update-CADTFTYC.js.map → update-SD5YQIJC.js.map} +0 -0
- /package/dist/{upload-GXS5CTOR.js.map → upload-7PPMVWVA.js.map} +0 -0
- /package/dist/{upload-B5SM33MK.js.map → upload-CEIYYPID.js.map} +0 -0
- /package/dist/{upscale-BCI42TCP.js.map → upscale-WVJZG76V.js.map} +0 -0
- /package/dist/{url-options-NZAS37S5.js.map → url-options-6WC2XQKB.js.map} +0 -0
- /package/dist/{url-params-LUQMABZX.js.map → url-params-OVBIP6UA.js.map} +0 -0
- /package/dist/{use-26VARHJT.js.map → use-6FADOAFZ.js.map} +0 -0
- /package/dist/{variant-F4EEYQJ7.js.map → variant-RNM36P4J.js.map} +0 -0
- /package/dist/{videos-AHOLXU42.js.map → videos-GHFCOTT7.js.map} +0 -0
- /package/dist/{videos-FMV4AVB2.js.map → videos-Z72RXCRB.js.map} +0 -0
- /package/dist/{view-X65GETAV.js.map → view-YR6MDLWL.js.map} +0 -0
- /package/dist/{viewer-check-2W6BTVQV.js.map → viewer-check-655BZRML.js.map} +0 -0
- /package/dist/{web-K2EMYVCD.js.map → web-4QN6QB7L.js.map} +0 -0
- /package/dist/{winners-5PRDG7GT.js.map → winners-4T5RFQXU.js.map} +0 -0
- /package/dist/{winning-ads-Q3RXH7EC.js.map → winning-ads-2J2RIOLR.js.map} +0 -0
- /package/dist/{write-commands-LHEJESKL.js.map → write-commands-6D55SB56.js.map} +0 -0
- /package/dist/{write-commands-5OFOD7TE.js.map → write-commands-AIWLEGO2.js.map} +0 -0
- /package/dist/{write-commands-SD6DXVNK.js.map → write-commands-UO3OQIHH.js.map} +0 -0
- /package/dist/{write-commands-UEQR7ZXO.js.map → write-commands-V7B4FBMX.js.map} +0 -0
- /package/dist/{x-UNSHYLJJ.js.map → x-7KXNCWTJ.js.map} +0 -0
|
@@ -0,0 +1,3107 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LOGO_POSITIONS,
|
|
3
|
+
SubjectBoxSchema,
|
|
4
|
+
chooseLogoSpot,
|
|
5
|
+
deliveredSize,
|
|
6
|
+
designerSpots,
|
|
7
|
+
greyTable,
|
|
8
|
+
imageOf,
|
|
9
|
+
isRead,
|
|
10
|
+
logoSlotLine,
|
|
11
|
+
pngOf,
|
|
12
|
+
rawOf,
|
|
13
|
+
readSubjectBoxes,
|
|
14
|
+
spreadUnder,
|
|
15
|
+
straightEdgeIn,
|
|
16
|
+
subjectsStep,
|
|
17
|
+
timedStep
|
|
18
|
+
} from "./chunk-Z5BG47PO.js";
|
|
19
|
+
import {
|
|
20
|
+
FRAME_CUT,
|
|
21
|
+
bandViolations,
|
|
22
|
+
blockingArea,
|
|
23
|
+
blockingPlacements,
|
|
24
|
+
boxesOfLine,
|
|
25
|
+
buttonShape,
|
|
26
|
+
bytesOf,
|
|
27
|
+
isButtonLine,
|
|
28
|
+
readTextBoxes,
|
|
29
|
+
roleKey,
|
|
30
|
+
shownBoxes,
|
|
31
|
+
withWordmark
|
|
32
|
+
} from "./chunk-LAMSUL26.js";
|
|
33
|
+
import {
|
|
34
|
+
askAboutImages
|
|
35
|
+
} from "./chunk-GRX3JXSR.js";
|
|
36
|
+
import {
|
|
37
|
+
IMAGE_GENERATE_MODELS,
|
|
38
|
+
IMAGE_TIER_CREDITS,
|
|
39
|
+
MODEL_REGISTRY,
|
|
40
|
+
SIZE_MATCH_MODEL,
|
|
41
|
+
imagePictureCredits,
|
|
42
|
+
modelIdsAccepted,
|
|
43
|
+
supportedAspectRatios
|
|
44
|
+
} from "./chunk-F3CZFUXZ.js";
|
|
45
|
+
import {
|
|
46
|
+
ImageRef,
|
|
47
|
+
callBackendExec,
|
|
48
|
+
defineNode,
|
|
49
|
+
delegated
|
|
50
|
+
} from "./chunk-CBVUO7SK.js";
|
|
51
|
+
|
|
52
|
+
// src/engine/nodes/remote/image.ts
|
|
53
|
+
import { z as z2 } from "zod";
|
|
54
|
+
|
|
55
|
+
// src/engine/nodes/remote/registry-params.ts
|
|
56
|
+
import { z } from "zod";
|
|
57
|
+
function registryParamShape(kind, overrides = {}) {
|
|
58
|
+
const specs = Object.values(MODEL_REGISTRY[kind]);
|
|
59
|
+
const byParam = /* @__PURE__ */ new Map();
|
|
60
|
+
for (const spec of specs) {
|
|
61
|
+
for (const [name, schema] of Object.entries(spec.params)) {
|
|
62
|
+
byParam.set(name, [...byParam.get(name) ?? [], schema]);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const shape = {};
|
|
66
|
+
for (const [name, schemas] of byParam) {
|
|
67
|
+
const type = overrides[name] ?? unionOf(schemas);
|
|
68
|
+
const requiredByAll = specs.every((spec) => spec.required.includes(name));
|
|
69
|
+
shape[name] = requiredByAll ? type : type.optional();
|
|
70
|
+
}
|
|
71
|
+
return shape;
|
|
72
|
+
}
|
|
73
|
+
function unionOf(schemas) {
|
|
74
|
+
const kinds = [...new Set(schemas.map((schema) => schema.kind))];
|
|
75
|
+
if (kinds.length > 1) {
|
|
76
|
+
const [first, second, ...rest] = kinds.map((k) => unionOf(schemas.filter((s) => s.kind === k)));
|
|
77
|
+
return z.union([first, second, ...rest]);
|
|
78
|
+
}
|
|
79
|
+
switch (kinds[0]) {
|
|
80
|
+
case "string":
|
|
81
|
+
return stringUnion(schemas);
|
|
82
|
+
case "number":
|
|
83
|
+
return numberUnion(schemas);
|
|
84
|
+
case "boolean":
|
|
85
|
+
return z.boolean();
|
|
86
|
+
default:
|
|
87
|
+
return z.unknown();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function stringUnion(schemas) {
|
|
91
|
+
if (schemas.some((schema) => !schema.enum)) return z.string();
|
|
92
|
+
const values = [...new Set(schemas.flatMap((schema) => schema.enum ?? []))];
|
|
93
|
+
return z.enum(values);
|
|
94
|
+
}
|
|
95
|
+
function numberUnion(schemas) {
|
|
96
|
+
if (schemas.some((schema) => !schema.enum)) return z.number();
|
|
97
|
+
const values = [...new Set(schemas.flatMap((schema) => schema.enum ?? []))].sort((a, b) => a - b);
|
|
98
|
+
return z.literal(values);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/engine/nodes/remote/image.ts
|
|
102
|
+
var imageModelEnum = z2.enum(IMAGE_GENERATE_MODELS.flatMap(modelIdsAccepted));
|
|
103
|
+
var ImageGenerateParams = z2.object({
|
|
104
|
+
model: imageModelEnum,
|
|
105
|
+
...registryParamShape("image_generate", {
|
|
106
|
+
prompt: z2.string().min(1),
|
|
107
|
+
// Recraft v4 vector controls, sent as the provider's own `controls` block. The
|
|
108
|
+
// registry types them as JSON; this is their shape.
|
|
109
|
+
rgb_colors: z2.array(z2.array(z2.number().int().min(0).max(255))),
|
|
110
|
+
background_rgb_color: z2.array(z2.number().int().min(0).max(255))
|
|
111
|
+
})
|
|
112
|
+
}).strict();
|
|
113
|
+
var PRO_QUALITY = "max";
|
|
114
|
+
function creditsPerImage(params) {
|
|
115
|
+
return params.quality === PRO_QUALITY ? IMAGE_TIER_CREDITS.pro : imagePictureCredits(String(params.model));
|
|
116
|
+
}
|
|
117
|
+
function imagesPerCall(params) {
|
|
118
|
+
return "n" in params && typeof params.n === "number" ? params.n : 1;
|
|
119
|
+
}
|
|
120
|
+
var imageGenerateNode = delegated({
|
|
121
|
+
id: "image_generate",
|
|
122
|
+
version: "2.2.0",
|
|
123
|
+
category: "image",
|
|
124
|
+
summary: "Generate images for ad creatives. Curated model set: GPT Image 2.5, Gemini 3.1 Flash Image, Gemini 3 Pro Image, Recraft v4.1 Pro Vector. Per-model param support comes from the canvas-engine model registry.",
|
|
125
|
+
when_to_use: "Use for hero shots, product photography, illustrations, and vector logos. `recraft/recraft-v4.1-pro-vector` for crisp vector / logo work; `openai/gpt-image-2` for photorealistic and in-image text (NOTE: it has no `image_size`, and no 4:5 / 5:4 \u2014 route portrait ad formats through Gemini or `image_aspect_adapt`); Gemini variants for fast iteration, extreme ratios, and editing via the `reference` input. `reference` accepts ONE image or an ARRAY of images \u2014 wire several to combine references in a single generation (e.g. a subject sheet + a font specimen + the original ad). Every reference is forwarded to the model in array order. `n` (only on models that declare it, e.g. `openai/gpt-image-2.5-sunburst`) returns several candidates of the same brief from one call, billed per image like separate calls; wire the whole `images` array into `image_select` to keep the best.",
|
|
126
|
+
// `reference` is one image or an ordered array of images. The backend forwards
|
|
127
|
+
// each as a separate `image_url` to the provider (OpenRouter accepts many).
|
|
128
|
+
inputs: z2.object({ reference: z2.union([ImageRef, z2.array(ImageRef).min(1)]).optional() }).loose(),
|
|
129
|
+
params: ImageGenerateParams,
|
|
130
|
+
outputs: z2.object({ images: z2.array(ImageRef).min(1) }).strict(),
|
|
131
|
+
outputKinds: { images: "image" },
|
|
132
|
+
// Per image: `n` asks one call for several, and the provider bills each (measured: n=3
|
|
133
|
+
// cost exactly 3x n=1, prompt tokens included). Usage-billed, so this is only the pre-run
|
|
134
|
+
// quote; the charge is the provider's reported cost.
|
|
135
|
+
cost: ({ params }) => ({
|
|
136
|
+
credits: creditsPerImage(params) * imagesPerCall(params),
|
|
137
|
+
seconds_estimate: 10
|
|
138
|
+
})
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// src/engine/nodes/local/staticFormat.ts
|
|
142
|
+
import sharp2 from "sharp";
|
|
143
|
+
import { z as z3 } from "zod";
|
|
144
|
+
|
|
145
|
+
// src/engine/nodes/local/lib/plate-panels.ts
|
|
146
|
+
var READ_WIDTH = 288;
|
|
147
|
+
var FLAT = 2;
|
|
148
|
+
var STEP = 3;
|
|
149
|
+
var RANGE = 12;
|
|
150
|
+
var MIN_AREA = 0.015;
|
|
151
|
+
var MIN_FILL = 0.6;
|
|
152
|
+
function blockMean(img, x, y, f, c) {
|
|
153
|
+
let sum = 0;
|
|
154
|
+
for (let dy = 0; dy < f; dy++) {
|
|
155
|
+
for (let dx = 0; dx < f; dx++) sum += img.data[((y + dy) * img.width + x + dx) * img.channels + c] ?? 0;
|
|
156
|
+
}
|
|
157
|
+
return sum / (f * f);
|
|
158
|
+
}
|
|
159
|
+
function shrunk(img, f) {
|
|
160
|
+
const width = Math.floor(img.width / f);
|
|
161
|
+
const height = Math.floor(img.height / f);
|
|
162
|
+
const data = Buffer.alloc(width * height * 3);
|
|
163
|
+
for (let i = 0; i < width * height; i++) {
|
|
164
|
+
const x = i % width;
|
|
165
|
+
const y = (i - x) / width;
|
|
166
|
+
for (let c = 0; c < 3; c++) data[i * 3 + c] = Math.round(blockMean(img, x * f, y * f, f, c));
|
|
167
|
+
}
|
|
168
|
+
return { data, width, height, channels: 3 };
|
|
169
|
+
}
|
|
170
|
+
function spreadAt(grey, width, x, y) {
|
|
171
|
+
let sum = 0;
|
|
172
|
+
let squares = 0;
|
|
173
|
+
for (let dy = -2; dy <= 2; dy++) {
|
|
174
|
+
for (let dx = -2; dx <= 2; dx++) {
|
|
175
|
+
const v = grey[(y + dy) * width + x + dx] ?? 0;
|
|
176
|
+
sum += v;
|
|
177
|
+
squares += v * v;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const mean = sum / 25;
|
|
181
|
+
return Math.sqrt(Math.max(0, squares / 25 - mean * mean));
|
|
182
|
+
}
|
|
183
|
+
function flatOf(img) {
|
|
184
|
+
const { width, height } = img;
|
|
185
|
+
const grey = new Float32Array(width * height);
|
|
186
|
+
for (let i = 0; i < grey.length; i++)
|
|
187
|
+
grey[i] = 0.299 * (img.data[i * 3] ?? 0) + 0.587 * (img.data[i * 3 + 1] ?? 0) + 0.114 * (img.data[i * 3 + 2] ?? 0);
|
|
188
|
+
const flat = new Uint8Array(width * height);
|
|
189
|
+
for (let y = 2; y < height - 2; y++) {
|
|
190
|
+
for (let x = 2; x < width - 2; x++) flat[y * width + x] = spreadAt(grey, width, x, y) < FLAT ? 1 : 0;
|
|
191
|
+
}
|
|
192
|
+
return flat;
|
|
193
|
+
}
|
|
194
|
+
function take(r, img, i, x, y) {
|
|
195
|
+
r.count++;
|
|
196
|
+
r.x0 = Math.min(r.x0, x);
|
|
197
|
+
r.x1 = Math.max(r.x1, x);
|
|
198
|
+
r.y0 = Math.min(r.y0, y);
|
|
199
|
+
r.y1 = Math.max(r.y1, y);
|
|
200
|
+
for (let c = 0; c < 3; c++) {
|
|
201
|
+
const v = img.data[i * 3 + c] ?? 0;
|
|
202
|
+
r.lo[c] = Math.min(r.lo[c] ?? 255, v);
|
|
203
|
+
r.hi[c] = Math.max(r.hi[c] ?? 0, v);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
var neighbours = (i, x, width, height) => [x > 0 ? i - 1 : -1, x < width - 1 ? i + 1 : -1, i - width, i + width].filter((j) => j >= 0 && j < width * height);
|
|
207
|
+
function regionFrom(img, flat, seen, seed) {
|
|
208
|
+
const { width, height } = img;
|
|
209
|
+
const r = { x0: width, y0: height, x1: -1, y1: -1, count: 0, range: 0, lo: [255, 255, 255], hi: [0, 0, 0] };
|
|
210
|
+
const near = (a, b) => [0, 1, 2].every((c) => Math.abs((img.data[a * 3 + c] ?? 0) - (img.data[b * 3 + c] ?? 0)) <= STEP);
|
|
211
|
+
seen[seed] = 1;
|
|
212
|
+
const stack = [seed];
|
|
213
|
+
for (let i = stack.pop(); i !== void 0; i = stack.pop()) {
|
|
214
|
+
const x = i % width;
|
|
215
|
+
take(r, img, i, x, (i - x) / width);
|
|
216
|
+
for (const j of neighbours(i, x, width, height)) {
|
|
217
|
+
if (!flat[j] || seen[j] || !near(i, j)) continue;
|
|
218
|
+
seen[j] = 1;
|
|
219
|
+
stack.push(j);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const range = Math.max(...[0, 1, 2].map((c) => (r.hi[c] ?? 0) - (r.lo[c] ?? 0)));
|
|
223
|
+
return { x0: r.x0, y0: r.y0, x1: r.x1, y1: r.y1, count: r.count, range };
|
|
224
|
+
}
|
|
225
|
+
function isPanel(r, width, height) {
|
|
226
|
+
const inside = r.x0 > 2 && r.y0 > 2 && r.x1 < width - 3 && r.y1 < height - 3;
|
|
227
|
+
const box = (r.x1 - r.x0 + 1) * (r.y1 - r.y0 + 1);
|
|
228
|
+
return inside && box >= MIN_AREA * width * height && r.count >= MIN_FILL * box && r.range <= RANGE;
|
|
229
|
+
}
|
|
230
|
+
function platePanels(img) {
|
|
231
|
+
const f = Math.max(1, Math.round(img.width / READ_WIDTH));
|
|
232
|
+
const small = f > 1 || img.channels !== 3 ? shrunk(img, f) : img;
|
|
233
|
+
const flat = flatOf(small);
|
|
234
|
+
const seen = new Uint8Array(flat.length);
|
|
235
|
+
const panels = [];
|
|
236
|
+
for (let i = 0; i < flat.length; i++) {
|
|
237
|
+
if (!flat[i] || seen[i]) continue;
|
|
238
|
+
const r = regionFrom(small, flat, seen, i);
|
|
239
|
+
if (!isPanel(r, small.width, small.height)) continue;
|
|
240
|
+
panels.push({
|
|
241
|
+
x0: r.x0 / small.width,
|
|
242
|
+
y0: r.y0 / small.height,
|
|
243
|
+
x1: (r.x1 + 1) / small.width,
|
|
244
|
+
y1: (r.y1 + 1) / small.height,
|
|
245
|
+
area: (r.x1 - r.x0 + 1) * (r.y1 - r.y0 + 1)
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
return panels.sort((a, b) => b.area - a.area).map(({ area: _area, ...span }) => span);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/engine/nodes/local/lib/subject-crop.ts
|
|
252
|
+
var SUBJECT_PAD = 0.02;
|
|
253
|
+
function ratioOf(ratio) {
|
|
254
|
+
const [w, h] = ratio.split(":").map(Number);
|
|
255
|
+
if (!w || !h || !Number.isFinite(w) || !Number.isFinite(h)) throw new Error(`not a W:H ratio: "${ratio}"`);
|
|
256
|
+
return w / h;
|
|
257
|
+
}
|
|
258
|
+
var unionOf2 = (spans) => spans.length === 0 ? null : { from: Math.min(...spans.map((s) => s.from)), to: Math.max(...spans.map((s) => s.to)) };
|
|
259
|
+
function placeAxis(full, length, hard, soft, core) {
|
|
260
|
+
const clampFull = (v) => Math.min(full - length, Math.max(0, v));
|
|
261
|
+
const want = soft ? soft.to - soft.from <= length ? (soft.from + soft.to) / 2 - length / 2 : soft.from - SUBJECT_PAD * full : (core.from + core.to) / 2 - length / 2;
|
|
262
|
+
if (!hard) return { at: Math.round(clampFull(want)), fits: true };
|
|
263
|
+
const pad = SUBJECT_PAD * full;
|
|
264
|
+
for (const p of [pad, 0]) {
|
|
265
|
+
const lo = Math.max(0, hard.to + p - length);
|
|
266
|
+
const hi = Math.min(full - length, hard.from - p);
|
|
267
|
+
if (lo <= hi + 1e-6) return { at: Math.round(Math.min(hi, Math.max(lo, want))), fits: true };
|
|
268
|
+
}
|
|
269
|
+
return { at: Math.round(clampFull((hard.from + hard.to) / 2 - length / 2)), fits: false };
|
|
270
|
+
}
|
|
271
|
+
function subjectCrop(plate, format, subjects, opts = {}) {
|
|
272
|
+
const cards = (opts.panels ?? []).map((p) => ({ kind: "product", label: "card", ...p }));
|
|
273
|
+
if (cards.length > 0) {
|
|
274
|
+
const withCards = cropAround(plate, format, [...subjects ?? [], ...cards], opts);
|
|
275
|
+
if (withCards.fits) return withCards;
|
|
276
|
+
}
|
|
277
|
+
return cropAround(plate, format, subjects, opts);
|
|
278
|
+
}
|
|
279
|
+
function cropAround(plate, format, subjects, opts) {
|
|
280
|
+
const r = ratioOf(format);
|
|
281
|
+
let width = plate.width;
|
|
282
|
+
let height = Math.round(plate.width / r);
|
|
283
|
+
if (height > plate.height) {
|
|
284
|
+
height = plate.height;
|
|
285
|
+
width = Math.round(plate.height * r);
|
|
286
|
+
}
|
|
287
|
+
const boxes = subjects ?? [];
|
|
288
|
+
const px = (b) => ({ from: b.x0 * plate.width, to: b.x1 * plate.width });
|
|
289
|
+
const py = (b) => ({ from: b.y0 * plate.height, to: b.y1 * plate.height });
|
|
290
|
+
const hardY = boxes.map((b) => b.kind === "person" ? { from: py(b).from, to: py(b).from } : py(b));
|
|
291
|
+
const core = opts.core ?? { x0: 0, y0: 0, x1: 1, y1: 1 };
|
|
292
|
+
const x = placeAxis(plate.width, width, unionOf2(boxes.map(px)), unionOf2(boxes.map(px)), {
|
|
293
|
+
from: core.x0 * plate.width,
|
|
294
|
+
to: core.x1 * plate.width
|
|
295
|
+
});
|
|
296
|
+
const y = placeAxis(plate.height, height, unionOf2(hardY), unionOf2(boxes.map(py)), {
|
|
297
|
+
from: core.y0 * plate.height,
|
|
298
|
+
to: core.y1 * plate.height
|
|
299
|
+
});
|
|
300
|
+
const rect = { x: x.at, y: y.at, width, height };
|
|
301
|
+
const cut = boxes.filter((b, i) => {
|
|
302
|
+
const hy = hardY[i] ?? py(b);
|
|
303
|
+
return px(b).from < rect.x - 0.5 || px(b).to > rect.x + rect.width + 0.5 || hy.from < rect.y - 0.5 || hy.to > rect.y + rect.height + 0.5;
|
|
304
|
+
}).map((b) => b.label);
|
|
305
|
+
return { rect, render: renderRect(plate, rect, format, opts.renderRatios), fits: cut.length === 0, cut };
|
|
306
|
+
}
|
|
307
|
+
function renderRect(plate, rect, format, ratios) {
|
|
308
|
+
if (!ratios || ratios.includes(format)) return { ...rect, ratio: format };
|
|
309
|
+
const r = rect.width / rect.height;
|
|
310
|
+
let best = null;
|
|
311
|
+
for (const ratio of ratios) {
|
|
312
|
+
const c = ratioOf(ratio);
|
|
313
|
+
const width = c <= r ? rect.width : Math.round(rect.height * c);
|
|
314
|
+
const height = c <= r ? Math.round(rect.width / c) : rect.height;
|
|
315
|
+
if (width > plate.width || height > plate.height) continue;
|
|
316
|
+
const place = (from, length, inner, full) => Math.min(
|
|
317
|
+
Math.min(from, full - length),
|
|
318
|
+
Math.max(Math.max(0, from + inner - length), from - (length - inner) / 2)
|
|
319
|
+
);
|
|
320
|
+
const candidate = {
|
|
321
|
+
x: Math.round(place(rect.x, width, rect.width, plate.width)),
|
|
322
|
+
y: Math.round(place(rect.y, height, rect.height, plate.height)),
|
|
323
|
+
width,
|
|
324
|
+
height,
|
|
325
|
+
ratio
|
|
326
|
+
};
|
|
327
|
+
if (!best || width * height < best.width * best.height) best = candidate;
|
|
328
|
+
}
|
|
329
|
+
return best ?? { ...rect, ratio: format };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// src/engine/nodes/local/lib/picture-memo.ts
|
|
333
|
+
var ids = /* @__PURE__ */ new WeakMap();
|
|
334
|
+
var nextId = 0;
|
|
335
|
+
function pictureId(picture) {
|
|
336
|
+
const known = ids.get(picture);
|
|
337
|
+
if (known !== void 0) return known;
|
|
338
|
+
const id = nextId++;
|
|
339
|
+
ids.set(picture, id);
|
|
340
|
+
return id;
|
|
341
|
+
}
|
|
342
|
+
function remembered() {
|
|
343
|
+
const readings = /* @__PURE__ */ new WeakMap();
|
|
344
|
+
return (picture, what, read) => {
|
|
345
|
+
const known = readings.get(picture) ?? /* @__PURE__ */ new Map();
|
|
346
|
+
readings.set(picture, known);
|
|
347
|
+
const kept = known.get(what);
|
|
348
|
+
if (kept !== void 0) return kept;
|
|
349
|
+
const value = read();
|
|
350
|
+
known.set(what, value);
|
|
351
|
+
return value;
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/engine/nodes/local/lib/words-band.ts
|
|
356
|
+
var GROUND_REACH = 0.06;
|
|
357
|
+
var LAID = 24;
|
|
358
|
+
var BAND_EDGE = 0.5;
|
|
359
|
+
var BAND_CLEAR = 0.1;
|
|
360
|
+
var SOLID = 0.7;
|
|
361
|
+
var RING = 0.01;
|
|
362
|
+
var LOOK_STRIP = 0.1;
|
|
363
|
+
var greyAt = (img, i) => 0.299 * (img.data[i * img.channels] ?? 0) + 0.587 * (img.data[i * img.channels + 1] ?? 0) + 0.114 * (img.data[i * img.channels + 2] ?? 0);
|
|
364
|
+
function laidMap(aligned, cut) {
|
|
365
|
+
const { width, height } = cut;
|
|
366
|
+
const laid = new Uint8Array(width * height);
|
|
367
|
+
for (let i = 0; i < laid.length; i++) laid[i] = Math.abs(greyAt(aligned, i) - greyAt(cut, i)) > LAID ? 1 : 0;
|
|
368
|
+
return { laid, width, height };
|
|
369
|
+
}
|
|
370
|
+
var rectOf = (s, width, height) => ({
|
|
371
|
+
x0: Math.floor(s.x0 * width),
|
|
372
|
+
y0: Math.floor(s.y0 * height),
|
|
373
|
+
x1: Math.ceil(s.x1 * width),
|
|
374
|
+
y1: Math.ceil(s.y1 * height)
|
|
375
|
+
});
|
|
376
|
+
var clipped = (r, width, height) => ({
|
|
377
|
+
x0: Math.max(0, r.x0),
|
|
378
|
+
y0: Math.max(0, r.y0),
|
|
379
|
+
x1: Math.min(width, r.x1),
|
|
380
|
+
y1: Math.min(height, r.y1)
|
|
381
|
+
});
|
|
382
|
+
var holds = (r, x, y) => x >= r.x0 && x < r.x1 && y >= r.y0 && y < r.y1;
|
|
383
|
+
function laidIn(m, r) {
|
|
384
|
+
const c = clipped(r, m.width, m.height);
|
|
385
|
+
let laid = 0;
|
|
386
|
+
for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) laid += m.laid[y * m.width + x] ?? 0;
|
|
387
|
+
return { laid, area: Math.max(0, c.x1 - c.x0) * Math.max(0, c.y1 - c.y0) };
|
|
388
|
+
}
|
|
389
|
+
function share(m, r) {
|
|
390
|
+
const { laid, area: area2 } = laidIn(m, r);
|
|
391
|
+
return area2 > 0 ? laid / area2 : 0;
|
|
392
|
+
}
|
|
393
|
+
function laidAround(m, box) {
|
|
394
|
+
const reach = {
|
|
395
|
+
x0: box.x0 - GROUND_REACH,
|
|
396
|
+
y0: box.y0 - GROUND_REACH,
|
|
397
|
+
x1: box.x1 + GROUND_REACH,
|
|
398
|
+
y1: box.y1 + GROUND_REACH
|
|
399
|
+
};
|
|
400
|
+
const outer = laidIn(m, rectOf(reach, m.width, m.height));
|
|
401
|
+
const inner = laidIn(m, rectOf(box, m.width, m.height));
|
|
402
|
+
const ring = outer.area - inner.area;
|
|
403
|
+
return ring > 0 ? (outer.laid - inner.laid) / ring : 0;
|
|
404
|
+
}
|
|
405
|
+
function past(r, side, depth) {
|
|
406
|
+
if (side === 0) return { ...r, y0: r.y0 - depth, y1: r.y0 };
|
|
407
|
+
if (side === 1) return { ...r, y0: r.y1, y1: r.y1 + depth };
|
|
408
|
+
if (side === 2) return { ...r, x0: r.x0 - depth, x1: r.x0 };
|
|
409
|
+
return { ...r, x0: r.x1, x1: r.x1 + depth };
|
|
410
|
+
}
|
|
411
|
+
function grown(r, side) {
|
|
412
|
+
if (side === 0) return { ...r, y0: r.y0 - 1 };
|
|
413
|
+
if (side === 1) return { ...r, y1: r.y1 + 1 };
|
|
414
|
+
if (side === 2) return { ...r, x0: r.x0 - 1 };
|
|
415
|
+
return { ...r, x1: r.x1 + 1 };
|
|
416
|
+
}
|
|
417
|
+
var atFrameEdge = (m, r, side) => side === 0 ? r.y0 <= 0 : side === 1 ? r.y1 >= m.height : side === 2 ? r.x0 <= 0 : r.x1 >= m.width;
|
|
418
|
+
function bandUnder(m, box) {
|
|
419
|
+
const block = clipped(rectOf(box, m.width, m.height), m.width, m.height);
|
|
420
|
+
const inset = Math.min(Math.floor((block.y1 - block.y0) / 4), Math.floor((block.x1 - block.x0 - 1) / 2));
|
|
421
|
+
const start = { x0: block.x0 + inset, y0: block.y0 + inset, x1: block.x1 - inset, y1: block.y1 - inset };
|
|
422
|
+
let r = start;
|
|
423
|
+
for (let grew = true; grew; ) {
|
|
424
|
+
grew = false;
|
|
425
|
+
for (let side = 0; side < 4; side++) {
|
|
426
|
+
if (atFrameEdge(m, r, side) || share(m, past(r, side, 1)) < BAND_EDGE) continue;
|
|
427
|
+
r = grown(r, side);
|
|
428
|
+
grew = true;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
const outgrown = [r.y0 < start.y0, r.y1 > start.y1, r.x0 < start.x0, r.x1 > start.x1];
|
|
432
|
+
const depth = Math.max(2, Math.round(RING * Math.max(m.width, m.height)));
|
|
433
|
+
for (let side = 0; side < 4; side++) {
|
|
434
|
+
if (!(outgrown[side] || atFrameEdge(m, r, side)) || share(m, past(r, side, depth)) >= BAND_CLEAR) return null;
|
|
435
|
+
}
|
|
436
|
+
if (share(m, r) < SOLID) return null;
|
|
437
|
+
return { x0: r.x0 / m.width, y0: r.y0 / m.height, x1: r.x1 / m.width, y1: r.y1 / m.height };
|
|
438
|
+
}
|
|
439
|
+
function sumsOf(g, strip, skip, ch) {
|
|
440
|
+
const { width } = g.cut;
|
|
441
|
+
const sums = { n: 0, x: 0, y: 0, xx: 0, xy: 0 };
|
|
442
|
+
for (let y = strip.y0; y < strip.y1; y++) {
|
|
443
|
+
for (let x = strip.x0; x < strip.x1; x++) {
|
|
444
|
+
if (skip.some((r) => holds(r, x, y))) continue;
|
|
445
|
+
const i = y * width + x;
|
|
446
|
+
const u = g.cut.data[i * g.cut.channels + ch] ?? 0;
|
|
447
|
+
const v = g.aligned.data[i * g.aligned.channels + ch] ?? 0;
|
|
448
|
+
sums.n++;
|
|
449
|
+
sums.x += u;
|
|
450
|
+
sums.y += v;
|
|
451
|
+
sums.xx += u * u;
|
|
452
|
+
sums.xy += u * v;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return sums;
|
|
456
|
+
}
|
|
457
|
+
function toneOf(g, strip, skip) {
|
|
458
|
+
const c = clipped(strip, g.cut.width, g.cut.height);
|
|
459
|
+
return [0, 1, 2].map((ch) => {
|
|
460
|
+
const s = sumsOf(g, c, skip, ch);
|
|
461
|
+
if (s.n === 0) return { a: 0, b: 0 };
|
|
462
|
+
const spread = s.xx - s.x * s.x / s.n;
|
|
463
|
+
const a = spread > s.n ? Math.min(1, Math.max(0, (s.xy - s.x * s.y / s.n) / spread)) : 0;
|
|
464
|
+
return { a, b: (s.y - a * s.x) / s.n };
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
var LIGHT_DEPTH = 0.02;
|
|
468
|
+
function ringPast(r, dx, dy, depth) {
|
|
469
|
+
if (dy < 0) return { ...r, y0: r.y1, y1: r.y1 + depth };
|
|
470
|
+
if (dy > 0) return { ...r, y0: r.y0 - depth, y1: r.y0 };
|
|
471
|
+
if (dx < 0) return { ...r, x0: r.x1, x1: r.x1 + depth };
|
|
472
|
+
return { ...r, x0: r.x0 - depth, x1: r.x0 };
|
|
473
|
+
}
|
|
474
|
+
function lightOn(g, ring) {
|
|
475
|
+
const { width, height } = g.cut;
|
|
476
|
+
const c = clipped(ring, width, height);
|
|
477
|
+
return [0, 1, 2].map((ch) => {
|
|
478
|
+
const ratios = [];
|
|
479
|
+
for (let y = c.y0; y < c.y1; y++) {
|
|
480
|
+
for (let x = c.x0; x < c.x1; x++) {
|
|
481
|
+
const i = y * width + x;
|
|
482
|
+
const under = g.cut.data[i * g.cut.channels + ch] ?? 0;
|
|
483
|
+
if (under >= 16) ratios.push((g.aligned.data[i * g.aligned.channels + ch] ?? 0) / under);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
ratios.sort((a, b) => a - b);
|
|
487
|
+
return Math.min(2, Math.max(0.5, ratios[Math.floor(ratios.length / 2)] ?? 1));
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
function edgeLeft(r, dx, dy, width, height) {
|
|
491
|
+
const deep = Math.max(1, Math.round(LOOK_STRIP * (r.y1 - r.y0)));
|
|
492
|
+
const wide = Math.max(1, Math.round(LOOK_STRIP * (r.x1 - r.x0)));
|
|
493
|
+
const across2 = r.x0 <= 2 && r.x1 >= width - 2;
|
|
494
|
+
const down = r.y0 <= 2 && r.y1 >= height - 2;
|
|
495
|
+
if (dy < 0 && across2 && r.y1 >= height - 2)
|
|
496
|
+
return { strip: { ...r, y0: r.y1 - deep }, zone: { ...r, y0: r.y1 + dy } };
|
|
497
|
+
if (dy > 0 && across2 && r.y0 <= 2) return { strip: { ...r, y1: r.y0 + deep }, zone: { ...r, y1: r.y0 + dy } };
|
|
498
|
+
if (dx < 0 && down && r.x1 >= width - 2) return { strip: { ...r, x0: r.x1 - wide }, zone: { ...r, x0: r.x1 + dx } };
|
|
499
|
+
if (dx > 0 && down && r.x0 <= 2) return { strip: { ...r, x1: r.x0 + wide }, zone: { ...r, x1: r.x0 + dx } };
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
var CORNER = 0.5;
|
|
503
|
+
function floodCorner(shape, w, c, reach, bare) {
|
|
504
|
+
const near = (x, y) => (x - c.x) * c.sx >= 0 && (x - c.x) * c.sx < reach && (y - c.y) * c.sy >= 0 && (y - c.y) * c.sy < reach;
|
|
505
|
+
shape[c.y * w + c.x] = 0;
|
|
506
|
+
const stack = [c.y * w + c.x];
|
|
507
|
+
for (let at = stack.pop(); at !== void 0; at = stack.pop()) {
|
|
508
|
+
const x = at % w;
|
|
509
|
+
const y = (at - x) / w;
|
|
510
|
+
for (const [nx, ny] of [
|
|
511
|
+
[x + 1, y],
|
|
512
|
+
[x - 1, y],
|
|
513
|
+
[x, y + 1],
|
|
514
|
+
[x, y - 1]
|
|
515
|
+
]) {
|
|
516
|
+
if (!near(nx, ny) || shape[ny * w + nx] === 0 || !bare(nx, ny)) continue;
|
|
517
|
+
shape[ny * w + nx] = 0;
|
|
518
|
+
stack.push(ny * w + nx);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
function shapeOf(g, r) {
|
|
523
|
+
const w = r.x1 - r.x0;
|
|
524
|
+
const h = r.y1 - r.y0;
|
|
525
|
+
const shape = new Uint8Array(Math.max(0, w * h)).fill(1);
|
|
526
|
+
if (w <= 0 || h <= 0) return shape;
|
|
527
|
+
const reach = Math.floor(CORNER * Math.min(w, h));
|
|
528
|
+
const bare = (x, y) => {
|
|
529
|
+
const i = (r.y0 + y) * g.cut.width + r.x0 + x;
|
|
530
|
+
return Math.abs(greyAt(g.aligned, i) - greyAt(g.cut, i)) <= LAID;
|
|
531
|
+
};
|
|
532
|
+
const corners = [
|
|
533
|
+
{ x: 0, y: 0, sx: 1, sy: 1, open: r.x0 > 0 && r.y0 > 0 },
|
|
534
|
+
{ x: w - 1, y: 0, sx: -1, sy: 1, open: r.x1 < g.cut.width && r.y0 > 0 },
|
|
535
|
+
{ x: 0, y: h - 1, sx: 1, sy: -1, open: r.x0 > 0 && r.y1 < g.cut.height },
|
|
536
|
+
{ x: w - 1, y: h - 1, sx: -1, sy: -1, open: r.x1 < g.cut.width && r.y1 < g.cut.height }
|
|
537
|
+
];
|
|
538
|
+
for (const c of corners) if (c.open && bare(c.x, c.y)) floodCorner(shape, w, c, reach, bare);
|
|
539
|
+
return shape;
|
|
540
|
+
}
|
|
541
|
+
function eachOf(r, shape, at) {
|
|
542
|
+
const w = r.x1 - r.x0;
|
|
543
|
+
for (let k = 0; k < shape.length; k++) if (shape[k]) at(r.x0 + k % w, r.y0 + Math.floor(k / w));
|
|
544
|
+
}
|
|
545
|
+
var SOFT_EDGE = 3e-3;
|
|
546
|
+
function eachIn(r, at) {
|
|
547
|
+
for (let y = r.y0; y < r.y1; y++) for (let x = r.x0; x < r.x1; x++) at(x, y);
|
|
548
|
+
}
|
|
549
|
+
function moveBand(g, move) {
|
|
550
|
+
const { width, height } = g.cut;
|
|
551
|
+
const r = clipped(rectOf(move.band, width, height), width, height);
|
|
552
|
+
const soft = Math.max(1, Math.round(SOFT_EDGE * Math.max(width, height)));
|
|
553
|
+
const left = clipped({ x0: r.x0 - soft, y0: r.y0 - soft, x1: r.x1 + soft, y1: r.y1 + soft }, width, height);
|
|
554
|
+
const dx = Math.round(move.dx * width);
|
|
555
|
+
const dy = Math.round(move.dy * height);
|
|
556
|
+
const data = Buffer.alloc(width * height * 3);
|
|
557
|
+
if (g.out.channels === 3) g.out.data.copy(data, 0, 0, width * height * 3);
|
|
558
|
+
else
|
|
559
|
+
for (let i = 0; i < width * height; i++) g.out.data.copy(data, i * 3, i * g.out.channels, i * g.out.channels + 3);
|
|
560
|
+
const shape = shapeOf(g, r);
|
|
561
|
+
const edge = edgeLeft(r, dx, dy, width, height);
|
|
562
|
+
const tone = edge ? toneOf(
|
|
563
|
+
g,
|
|
564
|
+
edge.strip,
|
|
565
|
+
move.words.map((w) => rectOf(w, width, height))
|
|
566
|
+
) : [];
|
|
567
|
+
const light = lightOn(g, ringPast(left, dx, dy, Math.max(4, Math.round(LIGHT_DEPTH * height))));
|
|
568
|
+
eachIn(left, (x, y) => {
|
|
569
|
+
const i = y * width + x;
|
|
570
|
+
const band = edge !== null && holds(edge.zone, x, y);
|
|
571
|
+
for (let ch = 0; ch < 3; ch++) {
|
|
572
|
+
const under = g.cut.data[i * g.cut.channels + ch] ?? 0;
|
|
573
|
+
const t = tone[ch] ?? { a: 0, b: 0 };
|
|
574
|
+
const v = band ? t.a * under + t.b : under * (light[ch] ?? 1);
|
|
575
|
+
data[i * 3 + ch] = Math.max(0, Math.min(255, Math.round(v)));
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
eachOf(r, shape, (x, y) => {
|
|
579
|
+
const to = { x: x + dx, y: y + dy };
|
|
580
|
+
if (to.x < 0 || to.y < 0 || to.x >= width || to.y >= height) return;
|
|
581
|
+
const from = y * width + x;
|
|
582
|
+
g.aligned.data.copy(data, (to.y * width + to.x) * 3, from * g.aligned.channels, from * g.aligned.channels + 3);
|
|
583
|
+
});
|
|
584
|
+
return { data, width, height, channels: 3 };
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// src/engine/nodes/local/lib/safe-fit.ts
|
|
588
|
+
import sharp from "sharp";
|
|
589
|
+
var FIT_HEADROOM = 0.01;
|
|
590
|
+
var MIN_FIT_SCALE = 0.85;
|
|
591
|
+
var MIN_FLAT_FIT_SCALE = 0.65;
|
|
592
|
+
function boxesToPlace(boxes, format, opts = {}) {
|
|
593
|
+
if (!opts.copy) return [...boxes];
|
|
594
|
+
const placements = blockingPlacements(opts.placements);
|
|
595
|
+
const past2 = (box) => bandViolations([box], format, { placements })[0];
|
|
596
|
+
const cut = (box) => (past2(box)?.clearance ?? 1) <= FRAME_CUT;
|
|
597
|
+
const logoWords = opts.copy.filter((l) => roleKey(l.role) === "logo").map((l) => l.text);
|
|
598
|
+
const read = withWordmark(boxes, logoWords);
|
|
599
|
+
const buttons = new Set(opts.copy.filter(isButtonLine).flatMap((line) => boxesOfLine(line, read)));
|
|
600
|
+
return shownBoxes(read, opts.copy, (box) => !past2(box)).filter((shown) => !shown.supporting || cut(shown.box)).map((shown) => buttons.has(shown.box) ? buttonShape(shown.box) : shown.box);
|
|
601
|
+
}
|
|
602
|
+
function targetArea(format, placements) {
|
|
603
|
+
const area2 = blockingArea(format, placements);
|
|
604
|
+
const covered = area2.covered;
|
|
605
|
+
if (!covered) return area2;
|
|
606
|
+
return { ...area2, top: covered.top, bottom: covered.bottom, ...covered.rail ? { rail: covered.rail } : {} };
|
|
607
|
+
}
|
|
608
|
+
function planSafeFit(boxes, format, opts = {}) {
|
|
609
|
+
const area2 = targetArea(format, opts.placements);
|
|
610
|
+
const violations = bandViolations(boxes, format, { placements: blockingPlacements(opts.placements) });
|
|
611
|
+
if (!violations.some((v) => v.covered || v.clearance <= FRAME_CUT)) return null;
|
|
612
|
+
const rail = area2.rail && boxes.some((b) => b.y1 > (area2.rail?.from ?? 1)) ? area2.rail.width : 0;
|
|
613
|
+
const union = {
|
|
614
|
+
x0: Math.min(...boxes.map((b) => b.x0)),
|
|
615
|
+
y0: Math.min(...boxes.map((b) => b.y0)),
|
|
616
|
+
x1: Math.max(...boxes.map((b) => b.x1)),
|
|
617
|
+
y1: Math.max(...boxes.map((b) => b.y1))
|
|
618
|
+
};
|
|
619
|
+
const band = {
|
|
620
|
+
x0: area2.left + FIT_HEADROOM,
|
|
621
|
+
y0: area2.top + FIT_HEADROOM,
|
|
622
|
+
x1: 1 - Math.max(area2.right, rail) - FIT_HEADROOM,
|
|
623
|
+
y1: 1 - area2.bottom - FIT_HEADROOM
|
|
624
|
+
};
|
|
625
|
+
const scale = Math.min(1, (band.y1 - band.y0) / (union.y1 - union.y0), (band.x1 - band.x0) / (union.x1 - union.x0));
|
|
626
|
+
if (opts.contain) return containedFit(union, band, opts.minScale ?? MIN_FIT_SCALE, scale);
|
|
627
|
+
if (scale < (opts.minScale ?? MIN_FIT_SCALE)) return null;
|
|
628
|
+
return {
|
|
629
|
+
scale,
|
|
630
|
+
x: offset(scale, union.x0, union.x1, band.x0, band.x1),
|
|
631
|
+
y: offset(scale, union.y0, union.y1, band.y0, band.y1)
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
var CONTAIN_STEP = 5e-3;
|
|
635
|
+
function containedFit(union, band, minScale, from) {
|
|
636
|
+
const start = (scale, lo0, hi0, b0, b1) => {
|
|
637
|
+
const lo = Math.max(0, b0 - scale * lo0);
|
|
638
|
+
const hi = Math.min(1 - scale, b1 - scale * hi0);
|
|
639
|
+
if (lo > hi + 1e-9) return null;
|
|
640
|
+
return Math.min(hi, Math.max(lo, 0));
|
|
641
|
+
};
|
|
642
|
+
for (let scale = Math.min(1, from); scale >= minScale - 1e-9; scale -= CONTAIN_STEP) {
|
|
643
|
+
const x = start(scale, union.x0, union.x1, band.x0, band.x1);
|
|
644
|
+
const y = start(scale, union.y0, union.y1, band.y0, band.y1);
|
|
645
|
+
if (x !== null && y !== null) {
|
|
646
|
+
const cx = Math.min(
|
|
647
|
+
Math.min(1 - scale, band.x1 - scale * union.x1),
|
|
648
|
+
Math.max(Math.max(0, band.x0 - scale * union.x0), (1 - scale) / 2)
|
|
649
|
+
);
|
|
650
|
+
return { scale, x: cx, y };
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
function offset(scale, from, to, bandFrom, bandTo) {
|
|
656
|
+
const lo = bandFrom - scale * from;
|
|
657
|
+
const hi = bandTo - scale * to;
|
|
658
|
+
if (lo > hi) return (lo + hi) / 2;
|
|
659
|
+
return Math.min(hi, Math.max(lo, (1 - scale) / 2));
|
|
660
|
+
}
|
|
661
|
+
var PLAIN_DEPTH = 0.03;
|
|
662
|
+
var PLAIN_DEPTH_STEP = 36;
|
|
663
|
+
var PLAIN_JUMP = 60;
|
|
664
|
+
var PLAIN_JUMPS = 2;
|
|
665
|
+
function edgeBorders(img, side) {
|
|
666
|
+
const along = side === "top" || side === "bottom" ? img.width : img.height;
|
|
667
|
+
const across2 = side === "top" || side === "bottom" ? img.height : img.width;
|
|
668
|
+
const depth = Math.max(1, Math.round(PLAIN_DEPTH * across2));
|
|
669
|
+
const at = (i, d) => {
|
|
670
|
+
const inward = side === "top" || side === "left" ? d : across2 - 1 - d;
|
|
671
|
+
const [x, y] = side === "top" || side === "bottom" ? [i, inward] : [inward, i];
|
|
672
|
+
return (y * img.width + x) * img.channels;
|
|
673
|
+
};
|
|
674
|
+
const step = (a, b) => {
|
|
675
|
+
let sum = 0;
|
|
676
|
+
for (let c = 0; c < Math.min(3, img.channels); c++)
|
|
677
|
+
sum += Math.abs((img.data[a + c] ?? 0) - (img.data[b + c] ?? 0));
|
|
678
|
+
return sum;
|
|
679
|
+
};
|
|
680
|
+
let jumps = 0;
|
|
681
|
+
for (let i = 0; i < along; i++) {
|
|
682
|
+
for (let d = 1; d <= depth; d++) if (step(at(i, 0), at(i, d)) > PLAIN_DEPTH_STEP) return null;
|
|
683
|
+
if (i > 0 && step(at(i - 1, 0), at(i, 0)) > PLAIN_JUMP) jumps++;
|
|
684
|
+
}
|
|
685
|
+
return jumps;
|
|
686
|
+
}
|
|
687
|
+
function plainEdge(img, side) {
|
|
688
|
+
const borders = edgeBorders(img, side);
|
|
689
|
+
return borders !== null && borders <= PLAIN_JUMPS;
|
|
690
|
+
}
|
|
691
|
+
async function minFitScale(image) {
|
|
692
|
+
const { data, info } = await sharp(image).removeAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
693
|
+
const raw = { data, width: info.width, height: info.height, channels: info.channels };
|
|
694
|
+
const flat = ["top", "bottom", "left", "right"].every((side) => edgeBorders(raw, side) === 0);
|
|
695
|
+
return flat ? MIN_FLAT_FIT_SCALE : MIN_FIT_SCALE;
|
|
696
|
+
}
|
|
697
|
+
async function fitPicture(image, fit) {
|
|
698
|
+
const { width = 0, height = 0 } = await sharp(image).metadata();
|
|
699
|
+
const sw = Math.max(1, Math.round(width * fit.scale));
|
|
700
|
+
const sh = Math.max(1, Math.round(height * fit.scale));
|
|
701
|
+
const px = Math.round(fit.x * width);
|
|
702
|
+
const py = Math.round(fit.y * height);
|
|
703
|
+
const left = Math.max(0, -px);
|
|
704
|
+
const top = Math.max(0, -py);
|
|
705
|
+
const w = Math.min(sw, width - px) - left;
|
|
706
|
+
const h = Math.min(sh, height - py) - top;
|
|
707
|
+
const shrunk2 = await sharp(image).removeAlpha().resize(sw, sh, { fit: "fill", kernel: "lanczos3" }).extract({ left, top, width: w, height: h }).raw().toBuffer({ resolveWithObject: true });
|
|
708
|
+
const pad = { left: Math.max(0, px), top: Math.max(0, py) };
|
|
709
|
+
const extend = { ...pad, right: width - pad.left - w, bottom: height - pad.top - h };
|
|
710
|
+
const raw = { data: shrunk2.data, width: w, height: h, channels: shrunk2.info.channels };
|
|
711
|
+
const sides = ["top", "bottom", "left", "right"].filter((side) => extend[side] > 0);
|
|
712
|
+
if (!sides.every((side) => plainEdge(raw, side))) return null;
|
|
713
|
+
return sharp(shrunk2.data, { raw: { width: w, height: h, channels: shrunk2.info.channels } }).extend({ ...extend, extendWith: "copy" }).png().toBuffer();
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// src/engine/nodes/local/lib/words-layer.ts
|
|
717
|
+
var inSpans = (spans, fx, fy) => spans.some((s) => fx >= s.x0 && fx <= s.x1 && fy >= s.y0 && fy <= s.y1);
|
|
718
|
+
function centresIn(lo, hi, size) {
|
|
719
|
+
const inside = new Uint8Array(size);
|
|
720
|
+
for (let t = 0; t < size; t++) {
|
|
721
|
+
const f = (t + 0.5) / size;
|
|
722
|
+
inside[t] = f >= lo && f <= hi ? 1 : 0;
|
|
723
|
+
}
|
|
724
|
+
return inside;
|
|
725
|
+
}
|
|
726
|
+
function spanMask(spans, width, height) {
|
|
727
|
+
const mask = new Uint8Array(width * height);
|
|
728
|
+
for (const s of spans) {
|
|
729
|
+
const across2 = centresIn(s.x0, s.x1, width);
|
|
730
|
+
const down = centresIn(s.y0, s.y1, height);
|
|
731
|
+
for (let y = 0; y < height; y++) {
|
|
732
|
+
if (down[y]) for (let x = 0; x < width; x++) mask[y * width + x] ||= across2[x] ?? 0;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
return mask;
|
|
736
|
+
}
|
|
737
|
+
function taps(u, v, width, height) {
|
|
738
|
+
const x = Math.min(width - 1, Math.max(0, u));
|
|
739
|
+
const y = Math.min(height - 1, Math.max(0, v));
|
|
740
|
+
const x0 = Math.floor(x);
|
|
741
|
+
const y0 = Math.floor(y);
|
|
742
|
+
const x1 = Math.min(width - 1, x0 + 1);
|
|
743
|
+
const y1 = Math.min(height - 1, y0 + 1);
|
|
744
|
+
const fx = x - x0;
|
|
745
|
+
const fy = y - y0;
|
|
746
|
+
return {
|
|
747
|
+
at: [y0 * width + x0, y0 * width + x1, y1 * width + x0, y1 * width + x1],
|
|
748
|
+
w: [(1 - fx) * (1 - fy), fx * (1 - fy), (1 - fx) * fy, fx * fy]
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
function tapped(values, t, stride = 1, c = 0, missing = 0) {
|
|
752
|
+
let sum = 0;
|
|
753
|
+
for (let k = 0; k < 4; k++) sum += (t.w[k] ?? 0) * (values[(t.at[k] ?? 0) * stride + c] ?? missing);
|
|
754
|
+
return sum;
|
|
755
|
+
}
|
|
756
|
+
function grayOf(img) {
|
|
757
|
+
const data = new Float32Array(img.width * img.height);
|
|
758
|
+
for (let i = 0; i < data.length; i++) {
|
|
759
|
+
const o = i * img.channels;
|
|
760
|
+
data[i] = 0.299 * (img.data[o] ?? 0) + 0.587 * (img.data[o + 1] ?? 0) + 0.114 * (img.data[o + 2] ?? 0);
|
|
761
|
+
}
|
|
762
|
+
return { data, width: img.width, height: img.height };
|
|
763
|
+
}
|
|
764
|
+
function shrink(g, edge) {
|
|
765
|
+
const f = Math.max(1, Math.ceil(Math.max(g.width, g.height) / edge));
|
|
766
|
+
if (f === 1) return g;
|
|
767
|
+
const width = Math.floor(g.width / f);
|
|
768
|
+
const height = Math.floor(g.height / f);
|
|
769
|
+
const data = new Float32Array(width * height);
|
|
770
|
+
for (let i = 0; i < width * height; i++) {
|
|
771
|
+
const x = i % width * f;
|
|
772
|
+
const y = Math.floor(i / width) * f;
|
|
773
|
+
let sum = 0;
|
|
774
|
+
for (let j = 0; j < f; j++) {
|
|
775
|
+
const row = (y + j) * g.width + x;
|
|
776
|
+
for (let k = 0; k < f; k++) sum += g.data[row + k] ?? 0;
|
|
777
|
+
}
|
|
778
|
+
data[i] = sum / (f * f);
|
|
779
|
+
}
|
|
780
|
+
return { data, width, height };
|
|
781
|
+
}
|
|
782
|
+
var JUDGED_MAX = 2e4;
|
|
783
|
+
function judgedPixels(g, exclude) {
|
|
784
|
+
const mx = Math.ceil(g.width * 0.04);
|
|
785
|
+
const my = Math.ceil(g.height * 0.04);
|
|
786
|
+
const step = g.width * g.height > JUDGED_MAX ? 2 : 1;
|
|
787
|
+
const out = [];
|
|
788
|
+
for (let i = 0; i < g.width * g.height; i++) {
|
|
789
|
+
const x = i % g.width;
|
|
790
|
+
const y = Math.floor(i / g.width);
|
|
791
|
+
if (x % step !== 0 || y % step !== 0) continue;
|
|
792
|
+
if (x < mx || y < my || x >= g.width - mx || y >= g.height - my) continue;
|
|
793
|
+
if (!inSpans(exclude, x / g.width, y / g.height)) out.push(i);
|
|
794
|
+
}
|
|
795
|
+
const rows = [];
|
|
796
|
+
const starts = [];
|
|
797
|
+
out.forEach((i, j) => {
|
|
798
|
+
const y = Math.floor(i / g.width);
|
|
799
|
+
if (rows[rows.length - 1] === y) return;
|
|
800
|
+
rows.push(y);
|
|
801
|
+
starts.push(j);
|
|
802
|
+
});
|
|
803
|
+
starts.push(out.length);
|
|
804
|
+
return {
|
|
805
|
+
at: Int32Array.from(out),
|
|
806
|
+
xs: Int32Array.from(out, (i) => i % g.width),
|
|
807
|
+
rows: Int32Array.from(rows),
|
|
808
|
+
starts: Int32Array.from(starts)
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
function axisOf(origin, scale, count, size) {
|
|
812
|
+
const near = new Int32Array(count);
|
|
813
|
+
const at = new Int32Array(count);
|
|
814
|
+
const frac = new Float64Array(count);
|
|
815
|
+
for (let t = 0; t < count; t++) {
|
|
816
|
+
const p = origin + scale * t;
|
|
817
|
+
near[t] = Math.min(size - 1, Math.max(0, Math.round(p)));
|
|
818
|
+
const q = Math.min(size - 1.001, Math.max(0, p));
|
|
819
|
+
at[t] = q | 0;
|
|
820
|
+
frac[t] = q - (at[t] ?? 0);
|
|
821
|
+
}
|
|
822
|
+
return { near, at, frac };
|
|
823
|
+
}
|
|
824
|
+
var MISFIT_CAP = 40;
|
|
825
|
+
var LINEUP_FLAT = 1.5;
|
|
826
|
+
function withFlat(g) {
|
|
827
|
+
const flat = new Uint8Array(g.width * g.height);
|
|
828
|
+
for (let i = 0; i < flat.length; i++) {
|
|
829
|
+
const x = i % g.width;
|
|
830
|
+
const y = (i - x) / g.width;
|
|
831
|
+
if (x === 0 || y === 0 || x === g.width - 1 || y === g.height - 1) continue;
|
|
832
|
+
let sum = 0;
|
|
833
|
+
let square = 0;
|
|
834
|
+
for (let k = 0; k < 9; k++) {
|
|
835
|
+
const v = g.data[(y + Math.floor(k / 3) - 1) * g.width + x + k % 3 - 1] ?? 0;
|
|
836
|
+
sum += v;
|
|
837
|
+
square += v * v;
|
|
838
|
+
}
|
|
839
|
+
flat[i] = Math.sqrt(Math.max(0, square / 9 - (sum / 9) ** 2)) < LINEUP_FLAT ? 1 : 0;
|
|
840
|
+
}
|
|
841
|
+
return { ...g, flat };
|
|
842
|
+
}
|
|
843
|
+
function misfit(cut, render, judged, k, c, cap = MISFIT_CAP, beat = Number.POSITIVE_INFINITY, above = Number.POSITIVE_INFINITY) {
|
|
844
|
+
const cx = cut.width / 2;
|
|
845
|
+
const cy = cut.height / 2;
|
|
846
|
+
const ox = cx - c.scale * cx + c.dx * k;
|
|
847
|
+
const oy = cy - c.scale * cy + c.dy * k;
|
|
848
|
+
const cols = axisOf(ox, c.scale, cut.width, render.width);
|
|
849
|
+
const rows = axisOf(oy, c.scale, cut.height, render.height);
|
|
850
|
+
const look = { cut, render, judged, cols, most: cap * cap };
|
|
851
|
+
const count = judged.at.length;
|
|
852
|
+
const acc = { sum: 0, n: 0 };
|
|
853
|
+
for (let r = 0; r < judged.rows.length; r++) {
|
|
854
|
+
const from = judged.starts[r] ?? 0;
|
|
855
|
+
const least = acc.sum / (acc.n + count - from);
|
|
856
|
+
if (least >= beat || least > above) return Number.POSITIVE_INFINITY;
|
|
857
|
+
rowMisfit(look, rows, judged.rows[r] ?? 0, from, judged.starts[r + 1] ?? count, acc);
|
|
858
|
+
}
|
|
859
|
+
return acc.n > 0 ? acc.sum / acc.n : Number.POSITIVE_INFINITY;
|
|
860
|
+
}
|
|
861
|
+
function bilinear(data, i, width, fx, fy) {
|
|
862
|
+
const top = (data[i] ?? 0) * (1 - fx) + (data[i + 1] ?? 0) * fx;
|
|
863
|
+
const bottom = (data[i + width] ?? 0) * (1 - fx) + (data[i + width + 1] ?? 0) * fx;
|
|
864
|
+
return top * (1 - fy) + bottom * fy;
|
|
865
|
+
}
|
|
866
|
+
function rowMisfit(s, rows, y, from, to, acc) {
|
|
867
|
+
const { width, data, flat } = s.render;
|
|
868
|
+
const { near, at, frac } = s.cols;
|
|
869
|
+
const flatRow = (rows.near[y] ?? 0) * width;
|
|
870
|
+
const row = (rows.at[y] ?? 0) * width;
|
|
871
|
+
const fy = rows.frac[y] ?? 0;
|
|
872
|
+
for (let j = from; j < to; j++) {
|
|
873
|
+
const x = s.judged.xs[j] ?? 0;
|
|
874
|
+
if (flat?.[flatRow + (near[x] ?? 0)]) continue;
|
|
875
|
+
const d = (s.cut.data[s.judged.at[j] ?? 0] ?? 0) - bilinear(data, row + (at[x] ?? 0), width, frac[x] ?? 0, fy);
|
|
876
|
+
acc.sum += Math.min(d * d, s.most);
|
|
877
|
+
acc.n++;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
var MAX_SHIFT = 0.03;
|
|
881
|
+
var MAX_SCALE_OFF = 0.03;
|
|
882
|
+
var LEVELS = [
|
|
883
|
+
{ edge: 128, scales: [-0.03, -0.02, -0.01, 0, 0.01, 0.02, 0.03], reach: null },
|
|
884
|
+
{ edge: 256, scales: [-5e-3, 0, 5e-3], reach: 2 },
|
|
885
|
+
{ edge: 512, scales: [-25e-4, 0, 25e-4], reach: 1 }
|
|
886
|
+
];
|
|
887
|
+
function searchLevel(cut, render, k, level, centre, exclude) {
|
|
888
|
+
const judged = judgedPixels(cut, exclude);
|
|
889
|
+
const reach = level.reach ?? Math.ceil(MAX_SHIFT * Math.max(cut.width, cut.height));
|
|
890
|
+
let best = centre;
|
|
891
|
+
let score = Number.POSITIVE_INFINITY;
|
|
892
|
+
const atCentre = misfit(cut, render, judged, k, centre);
|
|
893
|
+
const side = 2 * reach + 1;
|
|
894
|
+
for (const ds of level.scales) {
|
|
895
|
+
const scale = centre.scale + ds;
|
|
896
|
+
if (Math.abs(scale - 1) > MAX_SCALE_OFF + 1e-9) continue;
|
|
897
|
+
for (let s = 0; s < side * side; s++) {
|
|
898
|
+
const c = { scale, dx: centre.dx + (s % side - reach) / k, dy: centre.dy + (Math.floor(s / side) - reach) / k };
|
|
899
|
+
const m = misfit(cut, render, judged, k, c, MISFIT_CAP, score, atCentre);
|
|
900
|
+
if (m < score) {
|
|
901
|
+
score = m;
|
|
902
|
+
best = c;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
return { best, score };
|
|
907
|
+
}
|
|
908
|
+
function registerToSource(render, cut, exclude) {
|
|
909
|
+
return lineUps(render, `${pictureId(cut)} ${JSON.stringify(exclude)}`, () => lineUp(render, cut, exclude));
|
|
910
|
+
}
|
|
911
|
+
var lineUps = remembered();
|
|
912
|
+
var warps = remembered();
|
|
913
|
+
function lineUp(render, cut, exclude) {
|
|
914
|
+
const full = { cut: grayOf(cut), render: grayOf(render) };
|
|
915
|
+
let best = { scale: 1, dx: 0, dy: 0 };
|
|
916
|
+
let finest = { cut: full.cut, render: full.render, k: 1 };
|
|
917
|
+
for (const level of LEVELS) {
|
|
918
|
+
const c = shrink(full.cut, level.edge);
|
|
919
|
+
const r = withFlat(shrink(full.render, level.edge));
|
|
920
|
+
const k = c.width / cut.width;
|
|
921
|
+
best = searchLevel(c, r, k, level, best, exclude).best;
|
|
922
|
+
finest = { cut: c, render: r, k };
|
|
923
|
+
}
|
|
924
|
+
const judged = judgedPixels(finest.cut, exclude);
|
|
925
|
+
const residual = misfit(finest.cut, finest.render, judged, finest.k, best, Number.POSITIVE_INFINITY);
|
|
926
|
+
return { ...best, residual: Math.sqrt(residual) };
|
|
927
|
+
}
|
|
928
|
+
function bilinearAxis(centre, scale, shift, size) {
|
|
929
|
+
const lo = new Int32Array(size);
|
|
930
|
+
const hi = new Int32Array(size);
|
|
931
|
+
const frac = new Float64Array(size);
|
|
932
|
+
for (let t = 0; t < size; t++) {
|
|
933
|
+
const p = Math.min(size - 1, Math.max(0, centre + scale * (t - centre) + shift));
|
|
934
|
+
lo[t] = Math.floor(p);
|
|
935
|
+
hi[t] = Math.min(size - 1, (lo[t] ?? 0) + 1);
|
|
936
|
+
frac[t] = p - (lo[t] ?? 0);
|
|
937
|
+
}
|
|
938
|
+
return { lo, hi, frac };
|
|
939
|
+
}
|
|
940
|
+
function warpToCut(render, fit) {
|
|
941
|
+
return warps(render, `${fit.scale} ${fit.dx} ${fit.dy}`, () => warped(render, fit));
|
|
942
|
+
}
|
|
943
|
+
function warped(render, fit) {
|
|
944
|
+
const { width, height } = render;
|
|
945
|
+
const out = Buffer.alloc(width * height * 3);
|
|
946
|
+
const cols = bilinearAxis(width / 2, fit.scale, fit.dx, width);
|
|
947
|
+
const rows = bilinearAxis(height / 2, fit.scale, fit.dy, height);
|
|
948
|
+
for (let y = 0; y < height; y++) {
|
|
949
|
+
const row = { y, top: (rows.lo[y] ?? 0) * width, bottom: (rows.hi[y] ?? 0) * width, fy: rows.frac[y] ?? 0 };
|
|
950
|
+
warpRow(render, out, cols, row);
|
|
951
|
+
}
|
|
952
|
+
return { data: out, width, height, channels: 3 };
|
|
953
|
+
}
|
|
954
|
+
function warpRow(render, out, cols, row) {
|
|
955
|
+
const { width, channels, data } = render;
|
|
956
|
+
const { fy } = row;
|
|
957
|
+
for (let x = 0; x < width; x++) {
|
|
958
|
+
const fx = cols.frac[x] ?? 0;
|
|
959
|
+
const w = [(1 - fx) * (1 - fy), fx * (1 - fy), (1 - fx) * fy, fx * fy];
|
|
960
|
+
const lo = cols.lo[x] ?? 0;
|
|
961
|
+
const hi = cols.hi[x] ?? 0;
|
|
962
|
+
const a = [
|
|
963
|
+
(row.top + lo) * channels,
|
|
964
|
+
(row.top + hi) * channels,
|
|
965
|
+
(row.bottom + lo) * channels,
|
|
966
|
+
(row.bottom + hi) * channels
|
|
967
|
+
];
|
|
968
|
+
const o = (row.y * width + x) * 3;
|
|
969
|
+
for (let c = 0; c < 3; c++) {
|
|
970
|
+
out[o + c] = Math.round(
|
|
971
|
+
w[0] * (data[a[0] + c] ?? 0) + w[1] * (data[a[1] + c] ?? 0) + w[2] * (data[a[2] + c] ?? 0) + w[3] * (data[a[3] + c] ?? 0)
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
function emptyLayer(width, height) {
|
|
977
|
+
return {
|
|
978
|
+
width,
|
|
979
|
+
height,
|
|
980
|
+
alpha: new Float32Array(width * height),
|
|
981
|
+
ink: new Float32Array(width * height),
|
|
982
|
+
pixels: Buffer.alloc(width * height * 3),
|
|
983
|
+
gain: new Float32Array(width * height * 3).fill(1)
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
var CELL = 8;
|
|
987
|
+
var CHANGED = 14;
|
|
988
|
+
var MATTE_LO = 8;
|
|
989
|
+
var MATTE_HI = 32;
|
|
990
|
+
var BOX_PAD = 0.3;
|
|
991
|
+
var TOUCH = 0.02;
|
|
992
|
+
var GAIN_MAX = 4;
|
|
993
|
+
var TONE_MIN_PIXELS = CELL * CELL / 4;
|
|
994
|
+
var padded = (b, width, height) => {
|
|
995
|
+
const pad = BOX_PAD * (b.y1 - b.y0);
|
|
996
|
+
const padX = pad * height / width;
|
|
997
|
+
return { x0: b.x0 - padX, y0: b.y0 - pad, x1: b.x1 + padX, y1: b.y1 + pad };
|
|
998
|
+
};
|
|
999
|
+
function gridOf(width, height) {
|
|
1000
|
+
const gw = Math.ceil(width / CELL);
|
|
1001
|
+
const gh = Math.ceil(height / CELL);
|
|
1002
|
+
return {
|
|
1003
|
+
gw,
|
|
1004
|
+
gh,
|
|
1005
|
+
cell: (x, y) => Math.floor(y / CELL) * gw + Math.floor(x / CELL),
|
|
1006
|
+
span: (g) => {
|
|
1007
|
+
const gx = g % gw;
|
|
1008
|
+
const gy = Math.floor(g / gw);
|
|
1009
|
+
return {
|
|
1010
|
+
x0: gx * CELL / width,
|
|
1011
|
+
y0: gy * CELL / height,
|
|
1012
|
+
x1: (gx + 1) * CELL / width,
|
|
1013
|
+
y1: (gy + 1) * CELL / height
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
function neighbours2(g, grid) {
|
|
1019
|
+
const gx = g % grid.gw;
|
|
1020
|
+
const gy = Math.floor(g / grid.gw);
|
|
1021
|
+
const out = [];
|
|
1022
|
+
for (let k = 0; k < 9; k++) {
|
|
1023
|
+
const nx = gx + k % 3 - 1;
|
|
1024
|
+
const ny = gy + Math.floor(k / 3) - 1;
|
|
1025
|
+
if (k !== 4 && nx >= 0 && ny >= 0 && nx < grid.gw && ny < grid.gh) out.push(ny * grid.gw + nx);
|
|
1026
|
+
}
|
|
1027
|
+
return out;
|
|
1028
|
+
}
|
|
1029
|
+
function addPixel(s, aligned, cut, i, g, tone) {
|
|
1030
|
+
let d = 0;
|
|
1031
|
+
for (let c = 0; c < 3; c++) {
|
|
1032
|
+
const a = aligned.data[i * aligned.channels + c] ?? 0;
|
|
1033
|
+
const b = cut.data[i * cut.channels + c] ?? 0;
|
|
1034
|
+
d = Math.max(d, Math.abs(a - b));
|
|
1035
|
+
if (!tone) continue;
|
|
1036
|
+
s.meanA[g * 3 + c] = (s.meanA[g * 3 + c] ?? 0) + a;
|
|
1037
|
+
s.meanC[g * 3 + c] = (s.meanC[g * 3 + c] ?? 0) + b;
|
|
1038
|
+
}
|
|
1039
|
+
return d;
|
|
1040
|
+
}
|
|
1041
|
+
function cellStats(aligned, cut, words, grid) {
|
|
1042
|
+
const cells = grid.gw * grid.gh;
|
|
1043
|
+
const s = {
|
|
1044
|
+
diff: new Float32Array(cells),
|
|
1045
|
+
pixelDiff: new Float32Array(cut.width * cut.height),
|
|
1046
|
+
meanA: new Float32Array(cells * 3),
|
|
1047
|
+
meanC: new Float32Array(cells * 3),
|
|
1048
|
+
toneCount: new Float32Array(cells)
|
|
1049
|
+
};
|
|
1050
|
+
const count = new Float32Array(cells);
|
|
1051
|
+
for (let i = 0; i < cut.width * cut.height; i++) {
|
|
1052
|
+
const x = i % cut.width;
|
|
1053
|
+
const y = Math.floor(i / cut.width);
|
|
1054
|
+
const g = grid.cell(x, y);
|
|
1055
|
+
const tone = !words[i];
|
|
1056
|
+
const d = addPixel(s, aligned, cut, i, g, tone);
|
|
1057
|
+
s.pixelDiff[i] = d;
|
|
1058
|
+
s.diff[g] = (s.diff[g] ?? 0) + d;
|
|
1059
|
+
count[g] = (count[g] ?? 0) + 1;
|
|
1060
|
+
if (tone) s.toneCount[g] = (s.toneCount[g] ?? 0) + 1;
|
|
1061
|
+
}
|
|
1062
|
+
for (let k = 0; k < cells * 3; k++) {
|
|
1063
|
+
const g = Math.floor(k / 3);
|
|
1064
|
+
if (k % 3 === 0) s.diff[g] = (s.diff[g] ?? 0) / (count[g] || 1);
|
|
1065
|
+
s.meanA[k] = (s.meanA[k] ?? 0) / (s.toneCount[g] || 1);
|
|
1066
|
+
s.meanC[k] = (s.meanC[k] ?? 0) / (s.toneCount[g] || 1);
|
|
1067
|
+
}
|
|
1068
|
+
return s;
|
|
1069
|
+
}
|
|
1070
|
+
var isChanged = (diff, g) => (diff[g] ?? 0) >= CHANGED;
|
|
1071
|
+
function flood(start, id, diff, region, grid) {
|
|
1072
|
+
region[start] = id;
|
|
1073
|
+
const stack = [start];
|
|
1074
|
+
while (stack.length > 0) {
|
|
1075
|
+
const g = stack.pop() ?? 0;
|
|
1076
|
+
const next = neighbours2(g, grid).filter((n) => isChanged(diff, n) && (region[n] ?? -1) < 0);
|
|
1077
|
+
for (const n of next) region[n] = id;
|
|
1078
|
+
stack.push(...next);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
function changedRegions(diff, grid) {
|
|
1082
|
+
const region = new Int32Array(diff.length).fill(-1);
|
|
1083
|
+
let count = 0;
|
|
1084
|
+
for (let start = 0; start < diff.length; start++) {
|
|
1085
|
+
if (!isChanged(diff, start) || (region[start] ?? -1) >= 0) continue;
|
|
1086
|
+
flood(start, count, diff, region, grid);
|
|
1087
|
+
count++;
|
|
1088
|
+
}
|
|
1089
|
+
return { region, count };
|
|
1090
|
+
}
|
|
1091
|
+
function cellGain(s, g) {
|
|
1092
|
+
if ((s.toneCount[g] ?? 0) < TONE_MIN_PIXELS) return null;
|
|
1093
|
+
return [0, 1, 2].map((c) => {
|
|
1094
|
+
const ratio = ((s.meanA[g * 3 + c] ?? 0) + 8) / ((s.meanC[g * 3 + c] ?? 0) + 8);
|
|
1095
|
+
return Math.min(GAIN_MAX, Math.max(1 / GAIN_MAX, ratio));
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
function neighbourGain(gain, known, g, grid) {
|
|
1099
|
+
const around = neighbours2(g, grid).filter((n) => known[n]);
|
|
1100
|
+
if (around.length === 0) return null;
|
|
1101
|
+
return [0, 1, 2].map((c) => around.reduce((sum, n) => sum + (gain[n * 3 + c] ?? 1), 0) / around.length);
|
|
1102
|
+
}
|
|
1103
|
+
function spreadGains(gain, known, grid) {
|
|
1104
|
+
const filled = [];
|
|
1105
|
+
for (let g = 0; g < known.length; g++) {
|
|
1106
|
+
const from = known[g] ? null : neighbourGain(gain, known, g, grid);
|
|
1107
|
+
if (from) filled.push([g, from]);
|
|
1108
|
+
}
|
|
1109
|
+
for (const [g, value] of filled) {
|
|
1110
|
+
gain.set(value, g * 3);
|
|
1111
|
+
known[g] = 1;
|
|
1112
|
+
}
|
|
1113
|
+
return filled.length;
|
|
1114
|
+
}
|
|
1115
|
+
function toneGains(s, grid) {
|
|
1116
|
+
const cells = grid.gw * grid.gh;
|
|
1117
|
+
const gain = new Float32Array(cells * 3).fill(1);
|
|
1118
|
+
const known = new Uint8Array(cells);
|
|
1119
|
+
for (let g = 0; g < cells; g++) {
|
|
1120
|
+
const own = cellGain(s, g);
|
|
1121
|
+
if (!own) continue;
|
|
1122
|
+
gain.set(own, g * 3);
|
|
1123
|
+
known[g] = 1;
|
|
1124
|
+
}
|
|
1125
|
+
let spread = 1;
|
|
1126
|
+
while (spread > 0) spread = spreadGains(gain, known, grid);
|
|
1127
|
+
return gain;
|
|
1128
|
+
}
|
|
1129
|
+
function smoothGains(gains, grid) {
|
|
1130
|
+
const out = new Float32Array(gains.length);
|
|
1131
|
+
for (let g = 0; g < grid.gw * grid.gh; g++) {
|
|
1132
|
+
const around = [g, ...neighbours2(g, grid)];
|
|
1133
|
+
for (let c = 0; c < 3; c++) {
|
|
1134
|
+
out[g * 3 + c] = around.reduce((sum, n) => sum + (gains[n * 3 + c] ?? 1), 0) / around.length;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
return out;
|
|
1138
|
+
}
|
|
1139
|
+
var STRUCTURAL = 16;
|
|
1140
|
+
function toneMisfit(aligned, cut, gains, words, grid) {
|
|
1141
|
+
const sum = new Float32Array(grid.gw * grid.gh);
|
|
1142
|
+
const count = new Float32Array(grid.gw * grid.gh);
|
|
1143
|
+
for (let i = 0; i < cut.width * cut.height; i++) {
|
|
1144
|
+
const x = i % cut.width;
|
|
1145
|
+
const y = (i - x) / cut.width;
|
|
1146
|
+
if (words[i]) continue;
|
|
1147
|
+
const g = grid.cell(x, y);
|
|
1148
|
+
let d = 0;
|
|
1149
|
+
for (let c = 0; c < 3; c++) {
|
|
1150
|
+
const want = Math.min(255, (cut.data[i * cut.channels + c] ?? 0) * (gains[g * 3 + c] ?? 1));
|
|
1151
|
+
d = Math.max(d, Math.abs((aligned.data[i * aligned.channels + c] ?? 0) - want));
|
|
1152
|
+
}
|
|
1153
|
+
sum[g] = (sum[g] ?? 0) + d;
|
|
1154
|
+
count[g] = (count[g] ?? 0) + 1;
|
|
1155
|
+
}
|
|
1156
|
+
return sum.map((v, g) => count[g] ? v / (count[g] ?? 1) : 0);
|
|
1157
|
+
}
|
|
1158
|
+
function cellTaps(grid, x, y) {
|
|
1159
|
+
return taps((x + 0.5) / CELL - 0.5, (y + 0.5) / CELL - 0.5, grid.gw, grid.gh);
|
|
1160
|
+
}
|
|
1161
|
+
function wordsLayer(aligned, cut, designed, opts = {}) {
|
|
1162
|
+
const { width, height } = cut;
|
|
1163
|
+
const grid = gridOf(width, height);
|
|
1164
|
+
const boxes = designed.map((b) => padded(b, width, height));
|
|
1165
|
+
const tight = designed.map((b) => ({ ...b }));
|
|
1166
|
+
const inBoxes2 = spanMask(boxes, width, height);
|
|
1167
|
+
const stats = cellStats(aligned, cut, inBoxes2, grid);
|
|
1168
|
+
const kept = keptChange(stats.diff, boxes, grid, TOUCH * width / height);
|
|
1169
|
+
const gains = smoothGains(toneGains(stats, grid), grid);
|
|
1170
|
+
const misfit2 = opts.boxesOnly ? null : toneMisfit(aligned, cut, gains, inBoxes2, grid);
|
|
1171
|
+
const tone = kept.tone.map((t, g) => t > 0 && misfit2 && (misfit2[g] ?? 0) < STRUCTURAL ? 1 : 0);
|
|
1172
|
+
const dropped = kept.tone.reduce((n, t, g) => n + (t > 0 && !tone[g] ? 1 : 0), 0);
|
|
1173
|
+
const reverted = kept.reverted + dropped / kept.tone.length;
|
|
1174
|
+
const look = {
|
|
1175
|
+
aligned,
|
|
1176
|
+
stats,
|
|
1177
|
+
grid,
|
|
1178
|
+
boxes: inBoxes2,
|
|
1179
|
+
tone,
|
|
1180
|
+
gains,
|
|
1181
|
+
tight: spanMask(tight, width, height),
|
|
1182
|
+
subjects: spanMask(opts.subjects ?? [], width, height),
|
|
1183
|
+
keepOut: spanMask(opts.keepOut ?? [], width, height)
|
|
1184
|
+
};
|
|
1185
|
+
const layer = emptyLayer(width, height);
|
|
1186
|
+
for (let i = 0; i < width * height; i++) setLayerPixel(layer, look, i);
|
|
1187
|
+
return { layer, reverted };
|
|
1188
|
+
}
|
|
1189
|
+
var overlaps = (a, b) => a.x0 < b.x1 && a.x1 > b.x0 && a.y0 < b.y1 && a.y1 > b.y0;
|
|
1190
|
+
function keptChange(diff, boxes, grid, touchY) {
|
|
1191
|
+
const { region, count } = changedRegions(diff, grid);
|
|
1192
|
+
const near = boxes.map((b) => ({ x0: b.x0 - TOUCH, y0: b.y0 - touchY, x1: b.x1 + TOUCH, y1: b.y1 + touchY }));
|
|
1193
|
+
const kept = new Uint8Array(count);
|
|
1194
|
+
for (let g = 0; g < region.length; g++) {
|
|
1195
|
+
const id = region[g] ?? -1;
|
|
1196
|
+
if (id >= 0 && near.some((b) => overlaps(grid.span(g), b))) kept[id] = 1;
|
|
1197
|
+
}
|
|
1198
|
+
const tone = new Float32Array(region.length);
|
|
1199
|
+
let reverted = 0;
|
|
1200
|
+
for (let g = 0; g < region.length; g++) {
|
|
1201
|
+
const id = region[g] ?? -1;
|
|
1202
|
+
if (id < 0) continue;
|
|
1203
|
+
if (kept[id]) tone[g] = 1;
|
|
1204
|
+
else if (!boxes.some((b) => overlaps(grid.span(g), b))) reverted++;
|
|
1205
|
+
}
|
|
1206
|
+
return { tone, reverted: reverted / region.length };
|
|
1207
|
+
}
|
|
1208
|
+
function setLayerPixel(layer, look, i) {
|
|
1209
|
+
const x = i % layer.width;
|
|
1210
|
+
const y = Math.floor(i / layer.width);
|
|
1211
|
+
const onSubject = look.subjects[i] === 1;
|
|
1212
|
+
const inBox = (onSubject ? look.tight : look.boxes)[i] === 1;
|
|
1213
|
+
if (!inBox && look.keepOut[i]) return;
|
|
1214
|
+
const near = look.tone[look.grid.cell(x, y)] ? cellTaps(look.grid, x, y) : void 0;
|
|
1215
|
+
const toned = near ? tapped(look.tone, near, 1, 0, 1) : 0;
|
|
1216
|
+
const changed = ((look.stats.pixelDiff[i] ?? 0) - MATTE_LO) / (MATTE_HI - MATTE_LO);
|
|
1217
|
+
const matte = inBox ? Math.min(1, Math.max(0, changed)) : 0;
|
|
1218
|
+
const a = Math.max(matte, toned);
|
|
1219
|
+
if (a <= 0) return;
|
|
1220
|
+
layer.alpha[i] = a;
|
|
1221
|
+
layer.ink[i] = inBox ? 1 : 0;
|
|
1222
|
+
const cells = near ?? cellTaps(look.grid, x, y);
|
|
1223
|
+
for (let c = 0; c < 3; c++) {
|
|
1224
|
+
layer.pixels[i * 3 + c] = look.aligned.data[i * look.aligned.channels + c] ?? 0;
|
|
1225
|
+
layer.gain[i * 3 + c] = tapped(look.gains, cells, 3, c, 1);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
function protectFaces(layer, faces) {
|
|
1229
|
+
if (faces.length === 0) return { layer, covered: 0 };
|
|
1230
|
+
const alpha = Float32Array.from(layer.alpha);
|
|
1231
|
+
const ink = Float32Array.from(layer.ink);
|
|
1232
|
+
let onFace = 0;
|
|
1233
|
+
let covered = 0;
|
|
1234
|
+
for (let i = 0; i < alpha.length; i++) {
|
|
1235
|
+
const fx = (i % layer.width + 0.5) / layer.width;
|
|
1236
|
+
const fy = (Math.floor(i / layer.width) + 0.5) / layer.height;
|
|
1237
|
+
if (!inSpans(faces, fx, fy)) continue;
|
|
1238
|
+
onFace++;
|
|
1239
|
+
const k = ink[i] ?? 0;
|
|
1240
|
+
if (k <= 0 || (alpha[i] ?? 0) <= 0) continue;
|
|
1241
|
+
covered++;
|
|
1242
|
+
alpha[i] = (alpha[i] ?? 0) * (1 - k);
|
|
1243
|
+
ink[i] = 0;
|
|
1244
|
+
}
|
|
1245
|
+
return { layer: { ...layer, alpha, ink }, covered: onFace > 0 ? covered / onFace : 0 };
|
|
1246
|
+
}
|
|
1247
|
+
var HIDDEN = 0.5;
|
|
1248
|
+
function coveredSubjects(layer, subjects) {
|
|
1249
|
+
return subjects.filter((b) => b.kind === "product" || b.kind === "animal").filter((b) => {
|
|
1250
|
+
const x0 = Math.max(0, Math.floor(b.x0 * layer.width));
|
|
1251
|
+
const x1 = Math.min(layer.width, Math.ceil(b.x1 * layer.width));
|
|
1252
|
+
const y0 = Math.max(0, Math.floor(b.y0 * layer.height));
|
|
1253
|
+
const y1 = Math.min(layer.height, Math.ceil(b.y1 * layer.height));
|
|
1254
|
+
let covered = 0;
|
|
1255
|
+
for (let y = y0; y < y1; y++) {
|
|
1256
|
+
for (let x = x0; x < x1; x++) if ((layer.alpha[y * layer.width + x] ?? 0) >= 0.5) covered++;
|
|
1257
|
+
}
|
|
1258
|
+
const all = (x1 - x0) * (y1 - y0);
|
|
1259
|
+
return all > 0 && covered / all > HIDDEN;
|
|
1260
|
+
}).map((b) => b.label);
|
|
1261
|
+
}
|
|
1262
|
+
function compose(cut, layer) {
|
|
1263
|
+
const { width, height } = cut;
|
|
1264
|
+
const out = Buffer.alloc(width * height * 3);
|
|
1265
|
+
for (let k = 0; k < width * height * 3; k++) {
|
|
1266
|
+
const i = Math.floor(k / 3);
|
|
1267
|
+
const c = k % 3;
|
|
1268
|
+
const base = cut.data[i * cut.channels + c] ?? 0;
|
|
1269
|
+
const a = layer.alpha[i] ?? 0;
|
|
1270
|
+
if (a <= 0) {
|
|
1271
|
+
out[k] = base;
|
|
1272
|
+
continue;
|
|
1273
|
+
}
|
|
1274
|
+
const ink = layer.ink[i] ?? 0;
|
|
1275
|
+
const toned = Math.min(255, base * (layer.gain[k] ?? 1));
|
|
1276
|
+
out[k] = Math.round(base * (1 - a) + (ink * (layer.pixels[k] ?? 0) + (1 - ink) * toned) * a);
|
|
1277
|
+
}
|
|
1278
|
+
return { data: out, width, height, channels: 3 };
|
|
1279
|
+
}
|
|
1280
|
+
function identityOutside(out, cut, alpha) {
|
|
1281
|
+
let sum = 0;
|
|
1282
|
+
let n = 0;
|
|
1283
|
+
for (let k = 0; k < cut.width * cut.height * 3; k++) {
|
|
1284
|
+
const i = Math.floor(k / 3);
|
|
1285
|
+
if ((alpha[i] ?? 0) > 0) continue;
|
|
1286
|
+
sum += Math.abs((out.data[i * out.channels + k % 3] ?? 0) - (cut.data[i * cut.channels + k % 3] ?? 0));
|
|
1287
|
+
n++;
|
|
1288
|
+
}
|
|
1289
|
+
return n > 0 ? sum / n : 0;
|
|
1290
|
+
}
|
|
1291
|
+
var MIN_WORDS_SCALE = 0.8;
|
|
1292
|
+
var MAX_WORDS_MOVE = 0.12;
|
|
1293
|
+
var MAX_BAND_MOVE = 0.25;
|
|
1294
|
+
var GROUP_GAP = 0.04;
|
|
1295
|
+
var SCALE_STEP = 0.05;
|
|
1296
|
+
var MOVE_STEP = 5e-3;
|
|
1297
|
+
var into = (from, to, lo, hi) => Math.max(lo - from, 0) + Math.min(hi - to, 0);
|
|
1298
|
+
var unionOf3 = (boxes) => ({
|
|
1299
|
+
x0: Math.min(...boxes.map((b) => b.x0)),
|
|
1300
|
+
y0: Math.min(...boxes.map((b) => b.y0)),
|
|
1301
|
+
x1: Math.max(...boxes.map((b) => b.x1)),
|
|
1302
|
+
y1: Math.max(...boxes.map((b) => b.y1))
|
|
1303
|
+
});
|
|
1304
|
+
var overlap = (a, b) => a.x0 < b.x1 && a.x1 > b.x0 && a.y0 < b.y1 && a.y1 > b.y0;
|
|
1305
|
+
function clearAreas(format, placements, bottom) {
|
|
1306
|
+
const area2 = blockingArea(format, placements);
|
|
1307
|
+
const rail = area2.rail && bottom > area2.rail.from ? area2.rail.width : 0;
|
|
1308
|
+
const band = {
|
|
1309
|
+
x0: area2.left + FIT_HEADROOM,
|
|
1310
|
+
y0: area2.top + FIT_HEADROOM,
|
|
1311
|
+
x1: 1 - Math.max(area2.right, rail) - FIT_HEADROOM,
|
|
1312
|
+
y1: 1 - area2.bottom - FIT_HEADROOM
|
|
1313
|
+
};
|
|
1314
|
+
const covered = area2.covered;
|
|
1315
|
+
if (!covered) return [band];
|
|
1316
|
+
const drawn = covered.rail && bottom > covered.rail.from ? covered.rail.width : 0;
|
|
1317
|
+
return [
|
|
1318
|
+
band,
|
|
1319
|
+
{
|
|
1320
|
+
x0: band.x0,
|
|
1321
|
+
y0: covered.top + FIT_HEADROOM,
|
|
1322
|
+
x1: 1 - Math.max(area2.right, drawn) - FIT_HEADROOM,
|
|
1323
|
+
y1: 1 - covered.bottom - FIT_HEADROOM
|
|
1324
|
+
}
|
|
1325
|
+
];
|
|
1326
|
+
}
|
|
1327
|
+
function wordGroups(words) {
|
|
1328
|
+
const sorted = [...words].sort((a, b) => a.y0 - b.y0);
|
|
1329
|
+
const groups = [];
|
|
1330
|
+
for (const box of sorted) {
|
|
1331
|
+
const last = groups.at(-1);
|
|
1332
|
+
if (last && box.y0 - Math.max(...last.map((b) => b.y1)) < GROUP_GAP) last.push(box);
|
|
1333
|
+
else groups.push([box]);
|
|
1334
|
+
}
|
|
1335
|
+
return groups;
|
|
1336
|
+
}
|
|
1337
|
+
function placed(union, fit, area2, p, withFaces) {
|
|
1338
|
+
const m = movedSpan(union, fit);
|
|
1339
|
+
const inArea = m.x0 >= area2.x0 - 1e-9 && m.x1 <= area2.x1 + 1e-9 && m.y0 >= area2.y0 - 1e-9 && m.y1 <= area2.y1 + 1e-9;
|
|
1340
|
+
return inArea && !p.others.some((o) => overlap(m, o)) && !(withFaces && p.faces.some((f) => overlap(m, f)));
|
|
1341
|
+
}
|
|
1342
|
+
function shiftInto(union, at, area2, p, withFaces) {
|
|
1343
|
+
const half = at.scale * (union.x1 - union.x0) / 2;
|
|
1344
|
+
const dx = into(at.cx - half, at.cx + half, area2.x0, area2.x1);
|
|
1345
|
+
const steps = Math.round(p.reach / MOVE_STEP);
|
|
1346
|
+
for (let k = 0; k <= 2 * steps; k++) {
|
|
1347
|
+
const dy = (k % 2 === 0 ? 1 : -1) * Math.ceil(k / 2) * MOVE_STEP;
|
|
1348
|
+
const fit = { ...at, dx, dy };
|
|
1349
|
+
if (placed(union, fit, area2, p, withFaces)) return fit;
|
|
1350
|
+
}
|
|
1351
|
+
return null;
|
|
1352
|
+
}
|
|
1353
|
+
function blockMove(union, p, withFaces) {
|
|
1354
|
+
const cx = (union.x0 + union.x1) / 2;
|
|
1355
|
+
const cy = (union.y0 + union.y1) / 2;
|
|
1356
|
+
for (let scale = 1; scale >= p.minScale - 1e-9; scale -= SCALE_STEP) {
|
|
1357
|
+
for (const area2 of p.areas) {
|
|
1358
|
+
const fit = shiftInto(union, { scale, cx, cy }, area2, p, withFaces);
|
|
1359
|
+
if (fit) return fit;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
return null;
|
|
1363
|
+
}
|
|
1364
|
+
var unmoved = (fit) => fit.scale === 1 && fit.dx === 0 && fit.dy === 0;
|
|
1365
|
+
var across = (area2, union) => ({
|
|
1366
|
+
...area2,
|
|
1367
|
+
x0: Math.min(area2.x0, union.x0),
|
|
1368
|
+
x1: Math.max(area2.x1, union.x1)
|
|
1369
|
+
});
|
|
1370
|
+
function planWordsShift(words, format, opts = {}) {
|
|
1371
|
+
const faces = opts.faces ?? [];
|
|
1372
|
+
const obstacles = [...faces, ...opts.keepOut ?? []];
|
|
1373
|
+
const groups = wordGroups(words).map((g) => ({ boxes: g, union: unionOf3(g) }));
|
|
1374
|
+
const moves = [];
|
|
1375
|
+
let reason;
|
|
1376
|
+
for (const [i, group] of groups.entries()) {
|
|
1377
|
+
const violations = bandViolations(group.boxes, format, { placements: blockingPlacements(opts.placements) });
|
|
1378
|
+
const past2 = violations.length > 0;
|
|
1379
|
+
const onFace = faces.some((f) => overlap(group.union, f));
|
|
1380
|
+
if (!past2 && !onFace) continue;
|
|
1381
|
+
const sideways = violations.some((v) => v.edges.includes("left") || v.edges.includes("right"));
|
|
1382
|
+
const p = {
|
|
1383
|
+
areas: clearAreas(format, opts.placements, group.union.y1).map((a) => sideways ? a : across(a, group.union)),
|
|
1384
|
+
faces: obstacles,
|
|
1385
|
+
others: groups.filter((_, j) => j !== i).map((g) => g.union),
|
|
1386
|
+
minScale: opts.minScale ?? MIN_WORDS_SCALE,
|
|
1387
|
+
reach: past2 ? MAX_BAND_MOVE : MAX_WORDS_MOVE
|
|
1388
|
+
};
|
|
1389
|
+
const step = stepOf(group.union, past2, p);
|
|
1390
|
+
if (typeof step === "string") reason ??= step;
|
|
1391
|
+
else if (step) moves.push({ group: group.union, fit: step });
|
|
1392
|
+
}
|
|
1393
|
+
return reason ? { moves, reason } : { moves };
|
|
1394
|
+
}
|
|
1395
|
+
function stepOf(union, past2, p) {
|
|
1396
|
+
const fit = blockMove(union, p, true);
|
|
1397
|
+
if (fit) return unmoved(fit) ? null : fit;
|
|
1398
|
+
return blockMove(union, p, false) || !past2 ? "words_over_face" : "band_too_far";
|
|
1399
|
+
}
|
|
1400
|
+
function movedSpan(b, fit) {
|
|
1401
|
+
const at = (v, c, d) => c + fit.scale * (v - c) + d;
|
|
1402
|
+
return {
|
|
1403
|
+
...b,
|
|
1404
|
+
x0: at(b.x0, fit.cx, fit.dx),
|
|
1405
|
+
y0: at(b.y0, fit.cy, fit.dy),
|
|
1406
|
+
x1: at(b.x1, fit.cx, fit.dx),
|
|
1407
|
+
y1: at(b.y1, fit.cy, fit.dy)
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
var GROUP_REACH = 0.03;
|
|
1411
|
+
function blockAt(layer, moves, i) {
|
|
1412
|
+
const fx = (i % layer.width + 0.5) / layer.width;
|
|
1413
|
+
const fy = (Math.floor(i / layer.width) + 0.5) / layer.height;
|
|
1414
|
+
return moves.findIndex(
|
|
1415
|
+
(m) => fx >= m.group.x0 - GROUP_REACH && fx <= m.group.x1 + GROUP_REACH && fy >= m.group.y0 - GROUP_REACH && fy <= m.group.y1 + GROUP_REACH
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
function owners(layer, moves) {
|
|
1419
|
+
const { width } = layer;
|
|
1420
|
+
const own = new Int16Array(width * layer.height).fill(-1);
|
|
1421
|
+
for (let i = 0; i < own.length; i++) if ((layer.alpha[i] ?? 0) > 0) own[i] = blockAt(layer, moves, i);
|
|
1422
|
+
spreadOwners(own, layer.alpha, width);
|
|
1423
|
+
return own;
|
|
1424
|
+
}
|
|
1425
|
+
function spreadOwners(own, alpha, width) {
|
|
1426
|
+
const { stack, seeds } = seedsOf(own);
|
|
1427
|
+
let top = seeds;
|
|
1428
|
+
const free = (n) => n >= 0 && n < own.length && (own[n] ?? -1) < 0 && (alpha[n] ?? 0) > 0;
|
|
1429
|
+
while (top > 0) {
|
|
1430
|
+
const i = stack[--top] ?? 0;
|
|
1431
|
+
const block = own[i] ?? -1;
|
|
1432
|
+
for (const n of touching(i, width)) {
|
|
1433
|
+
if (!free(n)) continue;
|
|
1434
|
+
own[n] = block;
|
|
1435
|
+
stack[top++] = n;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
function seedsOf(own) {
|
|
1440
|
+
const stack = new Int32Array(own.length);
|
|
1441
|
+
let seeds = 0;
|
|
1442
|
+
for (let i = 0; i < own.length; i++) if ((own[i] ?? -1) >= 0) stack[seeds++] = i;
|
|
1443
|
+
return { stack, seeds };
|
|
1444
|
+
}
|
|
1445
|
+
function touching(i, width) {
|
|
1446
|
+
const x = i % width;
|
|
1447
|
+
return [x > 0 ? i - 1 : -1, x < width - 1 ? i + 1 : -1, i - width, i + width];
|
|
1448
|
+
}
|
|
1449
|
+
function takePixel(out, to, layer, t) {
|
|
1450
|
+
const a = tapped(layer.alpha, t);
|
|
1451
|
+
if (a <= (out.alpha[to] ?? 0)) return;
|
|
1452
|
+
out.alpha[to] = a;
|
|
1453
|
+
out.ink[to] = tapped(layer.ink, t);
|
|
1454
|
+
for (let c = 0; c < 3; c++) {
|
|
1455
|
+
out.pixels[to * 3 + c] = Math.round(tapped(layer.pixels, t, 3, c));
|
|
1456
|
+
out.gain[to * 3 + c] = tapped(layer.gain, t, 3, c, 1);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
function moveBlock(out, layer, own, k, fit) {
|
|
1460
|
+
const { width, height } = layer;
|
|
1461
|
+
const back = (p, c, d, size) => c * size + (p + 0.5 - c * size - d * size) / fit.scale - 0.5;
|
|
1462
|
+
for (let i = 0; i < width * height; i++) {
|
|
1463
|
+
const u = back(i % width, fit.cx, fit.dx, width);
|
|
1464
|
+
const v = back(Math.floor(i / width), fit.cy, fit.dy, height);
|
|
1465
|
+
const inside = u >= 0 && v >= 0 && u <= width - 1 && v <= height - 1;
|
|
1466
|
+
if (inside && own[Math.round(v) * width + Math.round(u)] === k) takePixel(out, i, layer, taps(u, v, width, height));
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
function movedPart(layer, moves) {
|
|
1470
|
+
const own = owners(layer, moves);
|
|
1471
|
+
const out = emptyLayer(layer.width, layer.height);
|
|
1472
|
+
for (let i = 0; i < own.length; i++) {
|
|
1473
|
+
if ((own[i] ?? -1) >= 0) takePixel(out, i, layer, { at: [i, i, i, i], w: [1, 0, 0, 0] });
|
|
1474
|
+
}
|
|
1475
|
+
return out;
|
|
1476
|
+
}
|
|
1477
|
+
function moveLayer(layer, moves) {
|
|
1478
|
+
const own = owners(layer, moves);
|
|
1479
|
+
const out = emptyLayer(layer.width, layer.height);
|
|
1480
|
+
for (let i = 0; i < own.length; i++) {
|
|
1481
|
+
if ((own[i] ?? -1) < 0 && (layer.alpha[i] ?? 0) > 0)
|
|
1482
|
+
takePixel(out, i, layer, { at: [i, i, i, i], w: [1, 0, 0, 0] });
|
|
1483
|
+
}
|
|
1484
|
+
for (const [k, { fit }] of moves.entries()) moveBlock(out, layer, own, k, fit);
|
|
1485
|
+
return out;
|
|
1486
|
+
}
|
|
1487
|
+
function cropLayer(layer, rect) {
|
|
1488
|
+
const out = emptyLayer(rect.width, rect.height);
|
|
1489
|
+
for (let y = 0; y < rect.height; y++) {
|
|
1490
|
+
const from = (rect.y + y) * layer.width + rect.x;
|
|
1491
|
+
const to = y * rect.width;
|
|
1492
|
+
out.alpha.set(layer.alpha.subarray(from, from + rect.width), to);
|
|
1493
|
+
out.ink.set(layer.ink.subarray(from, from + rect.width), to);
|
|
1494
|
+
out.gain.set(layer.gain.subarray(from * 3, (from + rect.width) * 3), to * 3);
|
|
1495
|
+
layer.pixels.copy(out.pixels, to * 3, from * 3, (from + rect.width) * 3);
|
|
1496
|
+
}
|
|
1497
|
+
return out;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// src/engine/nodes/local/lib/whole-render.ts
|
|
1501
|
+
var inSpans2 = (spans, fx, fy) => spans.some((s) => fx >= s.x0 && fx <= s.x1 && fy >= s.y0 && fy <= s.y1);
|
|
1502
|
+
function blurLine(src, out, start, step, n, r) {
|
|
1503
|
+
const last = start + (n - 1) * step;
|
|
1504
|
+
let acc = 0;
|
|
1505
|
+
for (let k = -r; k <= r; k++) acc += src[k <= 0 ? start : k >= n - 1 ? last : start + k * step] ?? 0;
|
|
1506
|
+
for (let k = 0; k < n; k++) {
|
|
1507
|
+
out[start + k * step] = acc / (2 * r + 1);
|
|
1508
|
+
const enter = k + r + 1;
|
|
1509
|
+
const leave = k - r;
|
|
1510
|
+
acc += (src[enter >= n - 1 ? last : start + enter * step] ?? 0) - (src[leave <= 0 ? start : start + leave * step] ?? 0);
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
function blurColumns(src, out, width, height, r) {
|
|
1514
|
+
const acc = new Float64Array(width);
|
|
1515
|
+
const row = (k) => (k <= 0 ? 0 : k >= height - 1 ? height - 1 : k) * width;
|
|
1516
|
+
for (let k = -r; k <= r; k++) {
|
|
1517
|
+
const from = row(k);
|
|
1518
|
+
for (let x = 0; x < width; x++) acc[x] = (acc[x] ?? 0) + (src[from + x] ?? 0);
|
|
1519
|
+
}
|
|
1520
|
+
for (let k = 0; k < height; k++) {
|
|
1521
|
+
const to = k * width;
|
|
1522
|
+
const enter = row(k + r + 1);
|
|
1523
|
+
const leave = row(k - r);
|
|
1524
|
+
for (let x = 0; x < width; x++) {
|
|
1525
|
+
out[to + x] = (acc[x] ?? 0) / (2 * r + 1);
|
|
1526
|
+
acc[x] = (acc[x] ?? 0) + ((src[enter + x] ?? 0) - (src[leave + x] ?? 0));
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
function boxBlur(src, width, height, r) {
|
|
1531
|
+
if (r < 1) return Float32Array.from(src);
|
|
1532
|
+
const along = new Float32Array(width * height);
|
|
1533
|
+
for (let y = 0; y < height; y++) blurLine(src, along, y * width, 1, width, r);
|
|
1534
|
+
const out = new Float32Array(width * height);
|
|
1535
|
+
blurColumns(along, out, width, height, r);
|
|
1536
|
+
return out;
|
|
1537
|
+
}
|
|
1538
|
+
var soften = (src, width, height, r) => boxBlur(boxBlur(src, width, height, r), width, height, r);
|
|
1539
|
+
function channelOf(img, c) {
|
|
1540
|
+
const out = new Float32Array(img.width * img.height);
|
|
1541
|
+
for (let i = 0; i < out.length; i++) out[i] = img.data[i * img.channels + c] ?? 0;
|
|
1542
|
+
return out;
|
|
1543
|
+
}
|
|
1544
|
+
var STRUCTURE_RADIUS = 8e-3;
|
|
1545
|
+
var GAIN_MAX2 = 2.5;
|
|
1546
|
+
var FLAT2 = 2.5;
|
|
1547
|
+
var STILL = 14;
|
|
1548
|
+
var MOVED = 28;
|
|
1549
|
+
function flatOf2(img) {
|
|
1550
|
+
const { width, height } = img;
|
|
1551
|
+
const grey = new Float32Array(width * height);
|
|
1552
|
+
for (let i = 0; i < grey.length; i++) {
|
|
1553
|
+
const o = i * img.channels;
|
|
1554
|
+
grey[i] = 0.299 * (img.data[o] ?? 0) + 0.587 * (img.data[o + 1] ?? 0) + 0.114 * (img.data[o + 2] ?? 0);
|
|
1555
|
+
}
|
|
1556
|
+
const squares = new Float32Array(grey.length);
|
|
1557
|
+
for (let i = 0; i < grey.length; i++) squares[i] = (grey[i] ?? 0) * (grey[i] ?? 0);
|
|
1558
|
+
const mean = boxBlur(grey, width, height, 2);
|
|
1559
|
+
const square = boxBlur(squares, width, height, 2);
|
|
1560
|
+
const flat = new Uint8Array(mean.length);
|
|
1561
|
+
for (let i = 0; i < mean.length; i++) {
|
|
1562
|
+
const m = mean[i] ?? 0;
|
|
1563
|
+
flat[i] = Math.sqrt(Math.max(0, (square[i] ?? 0) - m * m)) < FLAT2 ? 1 : 0;
|
|
1564
|
+
}
|
|
1565
|
+
return flat;
|
|
1566
|
+
}
|
|
1567
|
+
var gridOver = (width, height, size) => ({
|
|
1568
|
+
size,
|
|
1569
|
+
gw: Math.ceil(width / size),
|
|
1570
|
+
gh: Math.ceil(height / size)
|
|
1571
|
+
});
|
|
1572
|
+
function cellOf(grid, i, width) {
|
|
1573
|
+
const x = i % width;
|
|
1574
|
+
return Math.floor((i - x) / width / grid.size) * grid.gw + Math.floor(x / grid.size);
|
|
1575
|
+
}
|
|
1576
|
+
function cellsNear(grid, g, reach) {
|
|
1577
|
+
const gx = g % grid.gw;
|
|
1578
|
+
const gy = (g - gx) / grid.gw;
|
|
1579
|
+
const out = [];
|
|
1580
|
+
for (let ny = Math.max(0, gy - reach); ny <= Math.min(grid.gh - 1, gy + reach); ny++) {
|
|
1581
|
+
for (let nx = Math.max(0, gx - reach); nx <= Math.min(grid.gw - 1, gx + reach); nx++) out.push(ny * grid.gw + nx);
|
|
1582
|
+
}
|
|
1583
|
+
return out;
|
|
1584
|
+
}
|
|
1585
|
+
var SURFACE_CELL = 8;
|
|
1586
|
+
function laidCells(flat, structure, width, grid) {
|
|
1587
|
+
const laid = new Float32Array(grid.gw * grid.gh);
|
|
1588
|
+
const count = new Float32Array(grid.gw * grid.gh);
|
|
1589
|
+
for (let i = 0; i < flat.length; i++) {
|
|
1590
|
+
const g = cellOf(grid, i, width);
|
|
1591
|
+
count[g] = (count[g] ?? 0) + 1;
|
|
1592
|
+
if (flat[i] && (structure[i] ?? 0) > MOVED) laid[g] = (laid[g] ?? 0) + 1;
|
|
1593
|
+
}
|
|
1594
|
+
return Uint8Array.from(laid, (n, g) => n >= (count[g] ?? 1) / 2 ? 1 : 0);
|
|
1595
|
+
}
|
|
1596
|
+
function wordCells(words, width, height, grid) {
|
|
1597
|
+
const out = [];
|
|
1598
|
+
for (let g = 0; g < grid.gw * grid.gh; g++) {
|
|
1599
|
+
const gx = g % grid.gw;
|
|
1600
|
+
const gy = (g - gx) / grid.gw;
|
|
1601
|
+
const x0 = gx * grid.size / width;
|
|
1602
|
+
const y0 = gy * grid.size / height;
|
|
1603
|
+
const x1 = (gx + 1) * grid.size / width;
|
|
1604
|
+
const y1 = (gy + 1) * grid.size / height;
|
|
1605
|
+
if (words.some((w) => w.x0 < x1 && w.x1 > x0 && w.y0 < y1 && w.y1 > y0)) out.push(g);
|
|
1606
|
+
}
|
|
1607
|
+
return out;
|
|
1608
|
+
}
|
|
1609
|
+
function flood2(seeds, open, grid) {
|
|
1610
|
+
const reached = new Uint8Array(grid.gw * grid.gh);
|
|
1611
|
+
for (const g of seeds) reached[g] = 1;
|
|
1612
|
+
const stack = [...seeds];
|
|
1613
|
+
while (stack.length > 0) {
|
|
1614
|
+
const next = cellsNear(grid, stack.pop() ?? 0, 1).filter((n) => !reached[n] && open[n]);
|
|
1615
|
+
for (const n of next) reached[n] = 1;
|
|
1616
|
+
stack.push(...next);
|
|
1617
|
+
}
|
|
1618
|
+
return reached;
|
|
1619
|
+
}
|
|
1620
|
+
function surfaceOf(flat, structure, width, height, words) {
|
|
1621
|
+
const grid = gridOver(width, height, SURFACE_CELL);
|
|
1622
|
+
const reached = flood2(wordCells(words, width, height, grid), laidCells(flat, structure, width, grid), grid);
|
|
1623
|
+
const surface = new Uint8Array(structure.length);
|
|
1624
|
+
for (let y = 0; y < height; y++) {
|
|
1625
|
+
const row = Math.floor(y / grid.size) * grid.gw;
|
|
1626
|
+
for (let x = 0; x < width; x++) {
|
|
1627
|
+
const i = y * width + x;
|
|
1628
|
+
surface[i] = reached[row + Math.floor(x / grid.size)] && (structure[i] ?? 0) > MOVED ? 1 : 0;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
return surface;
|
|
1632
|
+
}
|
|
1633
|
+
var GROUND_LINE = 3;
|
|
1634
|
+
var CARD_TONE = 16;
|
|
1635
|
+
var CARD_RUN = 0.6;
|
|
1636
|
+
var inTone = (img, i, tone) => [0, 1, 2].every((c) => Math.abs((img.data[i * img.channels + c] ?? 0) - (tone[c] ?? 0)) <= CARD_TONE);
|
|
1637
|
+
function* pixelsOf(r, width, height) {
|
|
1638
|
+
for (let y = Math.max(0, r.y0); y < Math.min(height, r.y1); y++) {
|
|
1639
|
+
for (let x = Math.max(0, r.x0); x < Math.min(width, r.x1); x++) yield y * width + x;
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
var stripsPast = (r, depth) => [
|
|
1643
|
+
{ ...r, y0: r.y0 - depth, y1: r.y0 },
|
|
1644
|
+
{ ...r, y0: r.y1, y1: r.y1 + depth },
|
|
1645
|
+
{ ...r, x0: r.x0 - depth, x1: r.x0 },
|
|
1646
|
+
{ ...r, x0: r.x1, x1: r.x1 + depth }
|
|
1647
|
+
];
|
|
1648
|
+
var inBoxes = (boxes, i, width) => {
|
|
1649
|
+
const x = i % width;
|
|
1650
|
+
const y = (i - x) / width;
|
|
1651
|
+
return boxes.some((b) => x >= b.x0 && x < b.x1 && y >= b.y0 && y < b.y1);
|
|
1652
|
+
};
|
|
1653
|
+
function cardTone(img, flat, box, others = []) {
|
|
1654
|
+
const { width, height } = img;
|
|
1655
|
+
const around = stripsPast(box, GROUND_LINE).flatMap((s) => [...pixelsOf(s, width, height)]).filter((i) => !inBoxes(others, i, width));
|
|
1656
|
+
const flatOnes = around.filter((i) => flat[i]);
|
|
1657
|
+
if (around.length === 0 || flatOnes.length < around.length / 2) return null;
|
|
1658
|
+
return [0, 1, 2].map((c) => {
|
|
1659
|
+
const values = flatOnes.map((i) => img.data[i * img.channels + c] ?? 0).sort((a, b) => a - b);
|
|
1660
|
+
return values[Math.floor(values.length / 2)] ?? 0;
|
|
1661
|
+
});
|
|
1662
|
+
}
|
|
1663
|
+
var grownBy = (r, side, by) => side === 0 ? { ...r, y0: r.y0 - by } : side === 1 ? { ...r, y1: r.y1 + by } : side === 2 ? { ...r, x0: r.x0 - by } : { ...r, x1: r.x1 + by };
|
|
1664
|
+
function cardAround(img, box, tone) {
|
|
1665
|
+
const { width, height } = img;
|
|
1666
|
+
const share2 = (s) => {
|
|
1667
|
+
const px = [...pixelsOf(s, width, height)];
|
|
1668
|
+
return px.length > 0 ? px.filter((i) => inTone(img, i, tone)).length / px.length : 0;
|
|
1669
|
+
};
|
|
1670
|
+
const runs = (r2, side) => {
|
|
1671
|
+
for (let by = 1; by <= GROUND_LINE + 1; by++)
|
|
1672
|
+
if (share2(stripsPast(grownBy(r2, side, by - 1), 1)[side] ?? r2) >= CARD_RUN) return by;
|
|
1673
|
+
return 0;
|
|
1674
|
+
};
|
|
1675
|
+
let r = box;
|
|
1676
|
+
for (let grew = true; grew; ) {
|
|
1677
|
+
grew = false;
|
|
1678
|
+
for (let side = 0; side < 4; side++) {
|
|
1679
|
+
const by = runs(r, side);
|
|
1680
|
+
if (by === 0) continue;
|
|
1681
|
+
r = grownBy(r, side, by);
|
|
1682
|
+
grew = true;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
return r;
|
|
1686
|
+
}
|
|
1687
|
+
function groundOf(aligned, flat, words) {
|
|
1688
|
+
const { width, height } = aligned;
|
|
1689
|
+
const toned = new Float32Array(width * height);
|
|
1690
|
+
const inCard = new Uint8Array(width * height);
|
|
1691
|
+
const boxes = words.map((w) => ({
|
|
1692
|
+
x0: Math.max(0, Math.floor(w.x0 * width)),
|
|
1693
|
+
y0: Math.max(0, Math.floor(w.y0 * height)),
|
|
1694
|
+
x1: Math.min(width, Math.ceil(w.x1 * width)),
|
|
1695
|
+
y1: Math.min(height, Math.ceil(w.y1 * height))
|
|
1696
|
+
}));
|
|
1697
|
+
for (const box of boxes) {
|
|
1698
|
+
const tone = cardTone(
|
|
1699
|
+
aligned,
|
|
1700
|
+
flat,
|
|
1701
|
+
box,
|
|
1702
|
+
boxes.filter((b) => b !== box)
|
|
1703
|
+
);
|
|
1704
|
+
if (!tone) continue;
|
|
1705
|
+
for (const i of pixelsOf(cardAround(aligned, box, tone), width, height)) {
|
|
1706
|
+
inCard[i] = 1;
|
|
1707
|
+
if (inTone(aligned, i, tone)) toned[i] = 1;
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
const near = boxBlur(toned, width, height, GROUND_LINE);
|
|
1711
|
+
return Uint8Array.from(near, (v, i) => v > 0 && inCard[i] ? 1 : 0);
|
|
1712
|
+
}
|
|
1713
|
+
function trustOf(width, height, words) {
|
|
1714
|
+
const trust = new Float32Array(width * height);
|
|
1715
|
+
for (let i = 0; i < trust.length; i++) {
|
|
1716
|
+
const x = i % width;
|
|
1717
|
+
trust[i] = inSpans2(words, (x + 0.5) / width, ((i - x) / width + 0.5) / height) ? 0 : 1;
|
|
1718
|
+
}
|
|
1719
|
+
return trust;
|
|
1720
|
+
}
|
|
1721
|
+
var cutPlanes = remembered();
|
|
1722
|
+
var shrunkCuts = remembered();
|
|
1723
|
+
function planesOf(img, r1) {
|
|
1724
|
+
const own = [0, 1, 2].map((c) => channelOf(img, c));
|
|
1725
|
+
return {
|
|
1726
|
+
own,
|
|
1727
|
+
low: own.map((p) => soften(p, img.width, img.height, r1)),
|
|
1728
|
+
fine: own.map((p) => boxBlur(p, img.width, img.height, 1))
|
|
1729
|
+
};
|
|
1730
|
+
}
|
|
1731
|
+
var LIGHT_CELL = 0.015;
|
|
1732
|
+
var LIGHT_REACH = 3;
|
|
1733
|
+
function cellSums(a, b, open, width, grid) {
|
|
1734
|
+
const sums = new Float32Array(grid.gw * grid.gh * 7);
|
|
1735
|
+
const own = [...a.own, ...b.own];
|
|
1736
|
+
for (let i = 0; i < open.length; i++) {
|
|
1737
|
+
if (!open[i]) continue;
|
|
1738
|
+
const g = cellOf(grid, i, width) * 7;
|
|
1739
|
+
for (let c = 0; c < 6; c++) sums[g + c] = (sums[g + c] ?? 0) + (own[c]?.[i] ?? 0);
|
|
1740
|
+
sums[g + 6] = (sums[g + 6] ?? 0) + 1;
|
|
1741
|
+
}
|
|
1742
|
+
return sums;
|
|
1743
|
+
}
|
|
1744
|
+
function cellRatios(a, b, open, width, grid) {
|
|
1745
|
+
const sums = cellSums(a, b, open, width, grid);
|
|
1746
|
+
const ratio = new Float32Array(grid.gw * grid.gh * 3).fill(Number.NaN);
|
|
1747
|
+
for (let g = 0; g < grid.gw * grid.gh; g++) {
|
|
1748
|
+
const n = sums[g * 7 + 6] ?? 0;
|
|
1749
|
+
if (n < grid.size * grid.size / 4) continue;
|
|
1750
|
+
for (let c = 0; c < 3; c++) {
|
|
1751
|
+
ratio[g * 3 + c] = ((sums[g * 7 + c] ?? 0) / n + 8) / ((sums[g * 7 + 3 + c] ?? 0) / n + 8);
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
return ratio;
|
|
1755
|
+
}
|
|
1756
|
+
function medianNear(values, near, c, scratch) {
|
|
1757
|
+
let known = 0;
|
|
1758
|
+
for (const n of near) {
|
|
1759
|
+
const v = values[n * 3 + c] ?? Number.NaN;
|
|
1760
|
+
if (!Number.isNaN(v)) scratch[known++] = v;
|
|
1761
|
+
}
|
|
1762
|
+
if (known === 0) return 1;
|
|
1763
|
+
const sorted = scratch.subarray(0, known).sort();
|
|
1764
|
+
return sorted[Math.floor(known / 2)] ?? 1;
|
|
1765
|
+
}
|
|
1766
|
+
function medianLight(ratio, grid) {
|
|
1767
|
+
const cells = grid.gw * grid.gh;
|
|
1768
|
+
const median = new Float32Array(cells * 3);
|
|
1769
|
+
const scratch = new Float64Array((2 * LIGHT_REACH + 1) ** 2);
|
|
1770
|
+
for (let g = 0; g < cells; g++) {
|
|
1771
|
+
const near = cellsNear(grid, g, LIGHT_REACH);
|
|
1772
|
+
for (let c = 0; c < 3; c++) median[g * 3 + c] = medianNear(ratio, near, c, scratch);
|
|
1773
|
+
}
|
|
1774
|
+
const smooth = new Float32Array(cells * 3);
|
|
1775
|
+
for (let k = 0; k < cells * 3; k++) {
|
|
1776
|
+
const near = cellsNear(grid, Math.floor(k / 3), 1);
|
|
1777
|
+
smooth[k] = near.reduce((sum, n) => sum + (median[n * 3 + k % 3] ?? 1), 0) / near.length;
|
|
1778
|
+
}
|
|
1779
|
+
return smooth;
|
|
1780
|
+
}
|
|
1781
|
+
function lightOf(a, b, open, width, height) {
|
|
1782
|
+
const grid = gridOver(width, height, Math.max(8, Math.round(width * LIGHT_CELL)));
|
|
1783
|
+
const light = medianLight(cellRatios(a, b, open, width, grid), grid);
|
|
1784
|
+
const gain = enlarge(light, { width: grid.gw, height: grid.gh }, { width, height }, 3);
|
|
1785
|
+
const kept = new Float32Array(gain.length);
|
|
1786
|
+
for (let i = 0; i < gain.length; i++) kept[i] = Math.min(GAIN_MAX2, Math.max(1 / GAIN_MAX2, gain[i] ?? 0));
|
|
1787
|
+
return kept;
|
|
1788
|
+
}
|
|
1789
|
+
function compared(a, b, gain, n) {
|
|
1790
|
+
const structure = new Float32Array(n);
|
|
1791
|
+
const detail = new Float32Array(n);
|
|
1792
|
+
for (let c = 0; c < 3; c++) {
|
|
1793
|
+
const [aLow, bLow, aFine, bFine] = [a.low[c], b.low[c], a.fine[c], b.fine[c]];
|
|
1794
|
+
for (let i = 0; i < n; i++) {
|
|
1795
|
+
const g = gain[i * 3 + c] ?? 1;
|
|
1796
|
+
structure[i] = Math.max(structure[i] ?? 0, Math.abs((aLow?.[i] ?? 0) - g * (bLow?.[i] ?? 0)));
|
|
1797
|
+
detail[i] = Math.max(detail[i] ?? 0, Math.abs((aFine?.[i] ?? 0) - g * (bFine?.[i] ?? 0)));
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
return { structure, detail };
|
|
1801
|
+
}
|
|
1802
|
+
function renderDiff(aligned, cut, words) {
|
|
1803
|
+
const { width, height } = cut;
|
|
1804
|
+
const r1 = Math.max(2, Math.round(width * STRUCTURE_RADIUS));
|
|
1805
|
+
const a = planesOf(aligned, r1);
|
|
1806
|
+
const b = cutPlanes(cut, String(r1), () => planesOf(cut, r1));
|
|
1807
|
+
const gain = lightOf(a, b, trustOf(width, height, words), width, height);
|
|
1808
|
+
const { structure, detail } = compared(a, b, gain, width * height);
|
|
1809
|
+
const flat = flatOf2(aligned);
|
|
1810
|
+
const surface = surfaceOf(flat, structure, width, height, words);
|
|
1811
|
+
let ground;
|
|
1812
|
+
return {
|
|
1813
|
+
width,
|
|
1814
|
+
height,
|
|
1815
|
+
structure,
|
|
1816
|
+
detail,
|
|
1817
|
+
flat,
|
|
1818
|
+
surface,
|
|
1819
|
+
gain,
|
|
1820
|
+
// Read only to put a subject back: a render refused is never read for it.
|
|
1821
|
+
get ground() {
|
|
1822
|
+
ground ??= groundOf(aligned, flat, words);
|
|
1823
|
+
return ground;
|
|
1824
|
+
}
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
function subjectDrift(diff, subject, words) {
|
|
1828
|
+
const { width, height } = diff;
|
|
1829
|
+
const x0 = Math.max(0, Math.floor(subject.x0 * width));
|
|
1830
|
+
const x1 = Math.min(width, Math.ceil(subject.x1 * width));
|
|
1831
|
+
const y0 = Math.max(0, Math.floor(subject.y0 * height));
|
|
1832
|
+
const y1 = Math.min(height, Math.ceil(subject.y1 * height));
|
|
1833
|
+
const n = { all: 0, open: 0, covered: 0, moved: 0, drift: 0, held: 0 };
|
|
1834
|
+
for (let y = y0; y < y1; y++) {
|
|
1835
|
+
for (let x = x0; x < x1; x++) {
|
|
1836
|
+
n.all++;
|
|
1837
|
+
if (!inSpans2(words, (x + 0.5) / width, (y + 0.5) / height)) countDrift(n, diff, y * width + x);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
return {
|
|
1841
|
+
shown: n.all > 0 ? (n.open - n.covered) / n.all : 0,
|
|
1842
|
+
moved: n.open > 0 ? n.moved / n.open : 0,
|
|
1843
|
+
drift: n.held > 0 ? n.drift / n.held : 0
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
function countDrift(n, diff, i) {
|
|
1847
|
+
n.open++;
|
|
1848
|
+
if ((diff.structure[i] ?? 0) <= MOVED) {
|
|
1849
|
+
n.drift += diff.detail[i] ?? 0;
|
|
1850
|
+
n.held++;
|
|
1851
|
+
} else if (diff.surface[i]) n.covered++;
|
|
1852
|
+
else n.moved++;
|
|
1853
|
+
}
|
|
1854
|
+
var DRIFTED = 3;
|
|
1855
|
+
var MIN_KEPT = 0.75;
|
|
1856
|
+
var MAX_CARRIED = 5e-3;
|
|
1857
|
+
var REDRAWN = 0.2;
|
|
1858
|
+
var WHOLE_PROBLEMS = ["picture_moved", "subject_redrawn", "words_lost", "words_over_face"];
|
|
1859
|
+
function wholeVerdict(r) {
|
|
1860
|
+
if (r.kept < MIN_KEPT || r.carried > MAX_CARRIED) return { ok: false, problem: "picture_moved", what: [] };
|
|
1861
|
+
const redrawn = r.subjects.filter((s) => s.moved > REDRAWN).map((s) => s.label);
|
|
1862
|
+
if (redrawn.length > 0) return { ok: false, problem: "subject_redrawn", what: redrawn };
|
|
1863
|
+
if (r.lost.length > 0) return { ok: false, problem: "words_lost", what: [...r.lost] };
|
|
1864
|
+
if (r.onFace.length > 0) return { ok: false, problem: "words_over_face", what: [...r.onFace] };
|
|
1865
|
+
return { ok: true, restore: r.subjects.filter((s) => s.drift > DRIFTED).map((s) => s.label) };
|
|
1866
|
+
}
|
|
1867
|
+
function greyOf(img, f) {
|
|
1868
|
+
const width = Math.max(1, Math.floor(img.width / f));
|
|
1869
|
+
const height = Math.max(1, Math.floor(img.height / f));
|
|
1870
|
+
const data = new Float32Array(width * height);
|
|
1871
|
+
for (let i = 0; i < width * height; i++) {
|
|
1872
|
+
const x = i % width * f;
|
|
1873
|
+
const y = Math.floor(i / width) * f;
|
|
1874
|
+
let sum = 0;
|
|
1875
|
+
for (let j = 0; j < f; j++) {
|
|
1876
|
+
for (let k = 0; k < f; k++) {
|
|
1877
|
+
const o = ((y + j) * img.width + x + k) * img.channels;
|
|
1878
|
+
sum += 0.299 * (img.data[o] ?? 0) + 0.587 * (img.data[o + 1] ?? 0) + 0.114 * (img.data[o + 2] ?? 0);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
data[i] = sum / (f * f);
|
|
1882
|
+
}
|
|
1883
|
+
return { data, width, height };
|
|
1884
|
+
}
|
|
1885
|
+
function likeness(render, cut, box, place) {
|
|
1886
|
+
const cx = box.x + box.width / 2;
|
|
1887
|
+
const cy = box.y + box.height / 2;
|
|
1888
|
+
const n = { count: 0, a: 0, c: 0, aa: 0, cc: 0, ac: 0 };
|
|
1889
|
+
for (let y = box.y; y < box.y + box.height; y++) {
|
|
1890
|
+
for (let x = box.x; x < box.x + box.width; x++) {
|
|
1891
|
+
const u = Math.round(cx + place.scale * (x - cx) + place.dx);
|
|
1892
|
+
const v = Math.round(cy + place.scale * (y - cy) + place.dy);
|
|
1893
|
+
if (u < 0 || v < 0 || u >= render.width || v >= render.height) return -1;
|
|
1894
|
+
const a = render.data[v * render.width + u] ?? 0;
|
|
1895
|
+
const c = cut.data[y * cut.width + x] ?? 0;
|
|
1896
|
+
n.count++;
|
|
1897
|
+
n.a += a;
|
|
1898
|
+
n.c += c;
|
|
1899
|
+
n.aa += a * a;
|
|
1900
|
+
n.cc += c * c;
|
|
1901
|
+
n.ac += a * c;
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
const va = n.aa - n.a * n.a / n.count;
|
|
1905
|
+
const vc = n.cc - n.c * n.c / n.count;
|
|
1906
|
+
return va > 1e-6 && vc > 1e-6 ? (n.ac - n.a * n.c / n.count) / Math.sqrt(va * vc) : -1;
|
|
1907
|
+
}
|
|
1908
|
+
function boxIn(s, g, inset) {
|
|
1909
|
+
const w = (s.x1 - s.x0) * g.width;
|
|
1910
|
+
const h = (s.y1 - s.y0) * g.height;
|
|
1911
|
+
const x = Math.max(0, Math.round(s.x0 * g.width + inset * w));
|
|
1912
|
+
const y = Math.max(0, Math.round(s.y0 * g.height + inset * h));
|
|
1913
|
+
return {
|
|
1914
|
+
x,
|
|
1915
|
+
y,
|
|
1916
|
+
width: Math.max(1, Math.min(g.width - x, Math.round(w * (1 - 2 * inset)))),
|
|
1917
|
+
height: Math.max(1, Math.min(g.height - y, Math.round(h * (1 - 2 * inset))))
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
function bestPlace(render, cut, box, places) {
|
|
1921
|
+
let best = { dx: 0, dy: 0, scale: 1, score: -2 };
|
|
1922
|
+
for (const place of places) {
|
|
1923
|
+
const score = likeness(render, cut, box, place);
|
|
1924
|
+
if (score > best.score) best = { ...place, score };
|
|
1925
|
+
}
|
|
1926
|
+
return best;
|
|
1927
|
+
}
|
|
1928
|
+
var TRACK_REACH = 0.25;
|
|
1929
|
+
var TRACK_SCALES = [0.85, 0.92, 1, 1.08, 1.15];
|
|
1930
|
+
var TRACK_WIDTH = 180;
|
|
1931
|
+
function* placesNear(around, reach, scales) {
|
|
1932
|
+
for (const scale of scales) {
|
|
1933
|
+
for (let dy = -reach; dy <= reach; dy++) {
|
|
1934
|
+
for (let dx = -reach; dx <= reach; dx++) yield { dx: around.dx + dx, dy: around.dy + dy, scale };
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
function tracked(aligned, cut, subject) {
|
|
1939
|
+
const f = Math.max(1, Math.round(cut.width / TRACK_WIDTH));
|
|
1940
|
+
const coarse = { render: greyOf(aligned, f), cut: greyOf(cut, f) };
|
|
1941
|
+
const reach = Math.round(TRACK_REACH * coarse.cut.width);
|
|
1942
|
+
const found = bestPlace(
|
|
1943
|
+
coarse.render,
|
|
1944
|
+
coarse.cut,
|
|
1945
|
+
boxIn(subject, coarse.cut, 0.1),
|
|
1946
|
+
placesNear({ dx: 0, dy: 0, scale: 1 }, reach, TRACK_SCALES)
|
|
1947
|
+
);
|
|
1948
|
+
const fine = { render: greyOf(aligned, 1), cut: greyOf(cut, 1) };
|
|
1949
|
+
const near = [found.scale - 0.03, found.scale, found.scale + 0.03];
|
|
1950
|
+
const refined = bestPlace(
|
|
1951
|
+
fine.render,
|
|
1952
|
+
fine.cut,
|
|
1953
|
+
boxIn(subject, fine.cut, 0.1),
|
|
1954
|
+
placesNear({ dx: found.dx * f, dy: found.dy * f, scale: 1 }, f, near)
|
|
1955
|
+
);
|
|
1956
|
+
return {
|
|
1957
|
+
dx: refined.dx / cut.width,
|
|
1958
|
+
dy: refined.dy / cut.height,
|
|
1959
|
+
scale: refined.scale,
|
|
1960
|
+
score: refined.score
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
var FACE_EDGE = 0.15;
|
|
1964
|
+
function wordsOnFaces(words, faces) {
|
|
1965
|
+
return facesUnder(words, faces).map((f) => f.label);
|
|
1966
|
+
}
|
|
1967
|
+
function facesUnder(words, faces) {
|
|
1968
|
+
return faces.filter((f) => {
|
|
1969
|
+
const dx = FACE_EDGE * (f.x1 - f.x0);
|
|
1970
|
+
const dy = FACE_EDGE * (f.y1 - f.y0);
|
|
1971
|
+
return words.some((w) => w.x0 < f.x1 - dx && w.x1 > f.x0 + dx && w.y0 < f.y1 - dy && w.y1 > f.y0 + dy);
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
var FRAME_MARGIN = 0.01;
|
|
1975
|
+
function wordsLost(words, format, placements, keepOut = []) {
|
|
1976
|
+
const cut = words.filter(
|
|
1977
|
+
(b) => b.x0 < FRAME_MARGIN || b.y0 < FRAME_MARGIN || b.x1 > 1 - FRAME_MARGIN || b.y1 > 1 - FRAME_MARGIN || keepOut.some((k) => overlaps2(b, k))
|
|
1978
|
+
);
|
|
1979
|
+
const covered = bandViolations(
|
|
1980
|
+
words.filter((b) => !cut.includes(b)),
|
|
1981
|
+
format,
|
|
1982
|
+
{ placements: blockingPlacements(placements) }
|
|
1983
|
+
).filter((v) => v.covered);
|
|
1984
|
+
return [...cut.map((b) => b.text), ...covered.map((v) => v.text)];
|
|
1985
|
+
}
|
|
1986
|
+
var ZONE_MARGIN = 0.12;
|
|
1987
|
+
var FEATHER = 4e-3;
|
|
1988
|
+
function addZone(into2, zone, width, height) {
|
|
1989
|
+
const x0 = zone.x0 * width;
|
|
1990
|
+
const x1 = zone.x1 * width;
|
|
1991
|
+
const y0 = zone.y0 * height;
|
|
1992
|
+
const y1 = zone.y1 * height;
|
|
1993
|
+
const margin = Math.max(4, ZONE_MARGIN * Math.max(x1 - x0, y1 - y0));
|
|
1994
|
+
for (let y = Math.max(0, Math.floor(y0 - margin)); y < Math.min(height, Math.ceil(y1 + margin)); y++) {
|
|
1995
|
+
for (let x = Math.max(0, Math.floor(x0 - margin)); x < Math.min(width, Math.ceil(x1 + margin)); x++) {
|
|
1996
|
+
const dx = Math.max(0, x0 - (x + 0.5), x + 0.5 - x1);
|
|
1997
|
+
const dy = Math.max(0, y0 - (y + 0.5), y + 0.5 - y1);
|
|
1998
|
+
const t = 1 - Math.min(1, Math.sqrt(dx * dx + dy * dy) / margin);
|
|
1999
|
+
const i = y * width + x;
|
|
2000
|
+
into2[i] = Math.max(into2[i] ?? 0, t * t * (3 - 2 * t));
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
function restoreMask(diff, zones, words) {
|
|
2005
|
+
const { width, height } = diff;
|
|
2006
|
+
const zone = new Float32Array(width * height);
|
|
2007
|
+
for (const z5 of zones) addZone(zone, z5, width, height);
|
|
2008
|
+
const laid = boxBlur(
|
|
2009
|
+
Float32Array.from(diff.flat, (f, i) => f && (diff.detail[i] ?? 0) > KEPT_DETAIL || diff.ground[i] ? 1 : 0),
|
|
2010
|
+
width,
|
|
2011
|
+
height,
|
|
2012
|
+
1
|
|
2013
|
+
);
|
|
2014
|
+
const off = trustOf(width, height, words).map((t, i) => t > 0 && (laid[i] ?? 0) === 0 ? 0 : 1);
|
|
2015
|
+
const held = zone.map(
|
|
2016
|
+
(z5, i) => z5 > 0 && !off[i] ? z5 * Math.min(1, Math.max(0, (MOVED - (diff.structure[i] ?? 0)) / (MOVED - STILL))) : 0
|
|
2017
|
+
);
|
|
2018
|
+
const feathered = soften(held, width, height, Math.max(2, Math.round(width * FEATHER)));
|
|
2019
|
+
return feathered.map((m, i) => off[i] ? 0 : m);
|
|
2020
|
+
}
|
|
2021
|
+
function restoreSubjects(aligned, cut, gain, mask) {
|
|
2022
|
+
const { width, height } = cut;
|
|
2023
|
+
const out = Buffer.alloc(width * height * 3);
|
|
2024
|
+
for (let i = 0; i < width * height; i++) {
|
|
2025
|
+
const m = mask[i] ?? 0;
|
|
2026
|
+
for (let c = 0; c < 3; c++) {
|
|
2027
|
+
const own = aligned.data[i * aligned.channels + c] ?? 0;
|
|
2028
|
+
if (m <= 0) {
|
|
2029
|
+
out[i * 3 + c] = own;
|
|
2030
|
+
continue;
|
|
2031
|
+
}
|
|
2032
|
+
const back = Math.min(255, (cut.data[i * cut.channels + c] ?? 0) * (gain[i * 3 + c] ?? 1));
|
|
2033
|
+
out[i * 3 + c] = Math.round(own * (1 - m) + back * m);
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
return { data: out, width, height, channels: 3 };
|
|
2037
|
+
}
|
|
2038
|
+
var KEPT_DETAIL = 24;
|
|
2039
|
+
function keptShare(diff, words) {
|
|
2040
|
+
const { width, height } = diff;
|
|
2041
|
+
let textured = 0;
|
|
2042
|
+
let kept = 0;
|
|
2043
|
+
for (let i = 0; i < width * height; i++) {
|
|
2044
|
+
if (diff.flat[i] || diff.surface[i]) continue;
|
|
2045
|
+
const x = i % width;
|
|
2046
|
+
if (inSpans2(words, (x + 0.5) / width, ((i - x) / width + 0.5) / height)) continue;
|
|
2047
|
+
textured++;
|
|
2048
|
+
if ((diff.detail[i] ?? 0) < KEPT_DETAIL) kept++;
|
|
2049
|
+
}
|
|
2050
|
+
return textured > 0 ? kept / textured : 1;
|
|
2051
|
+
}
|
|
2052
|
+
function cropRaw(img, rect) {
|
|
2053
|
+
const data = Buffer.alloc(rect.width * rect.height * 3);
|
|
2054
|
+
for (let y = 0; y < rect.height; y++) {
|
|
2055
|
+
const from = ((rect.y + y) * img.width + rect.x) * img.channels;
|
|
2056
|
+
if (img.channels === 3) {
|
|
2057
|
+
img.data.copy(data, y * rect.width * 3, from, from + rect.width * 3);
|
|
2058
|
+
continue;
|
|
2059
|
+
}
|
|
2060
|
+
for (let x = 0; x < rect.width; x++) {
|
|
2061
|
+
for (let c = 0; c < 3; c++) data[(y * rect.width + x) * 3 + c] = img.data[from + x * img.channels + c] ?? 0;
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
return { data, width: rect.width, height: rect.height, channels: 3 };
|
|
2065
|
+
}
|
|
2066
|
+
function carriedBy(fit, frame, width, height) {
|
|
2067
|
+
const at = (x, y) => [
|
|
2068
|
+
width / 2 + fit.scale * (x - width / 2) + fit.dx,
|
|
2069
|
+
height / 2 + fit.scale * (y - height / 2) + fit.dy
|
|
2070
|
+
];
|
|
2071
|
+
const [left = 0, top = 0] = at(frame.x, frame.y);
|
|
2072
|
+
const [right = 0, bottom = 0] = at(frame.x + frame.width, frame.y + frame.height);
|
|
2073
|
+
return Math.max(
|
|
2074
|
+
0,
|
|
2075
|
+
-left / frame.width,
|
|
2076
|
+
-top / frame.height,
|
|
2077
|
+
(right - width) / frame.width,
|
|
2078
|
+
(bottom - height) / frame.height
|
|
2079
|
+
);
|
|
2080
|
+
}
|
|
2081
|
+
var SHOWN_MIN = 0.5;
|
|
2082
|
+
var JUDGED_WIDTH = 720;
|
|
2083
|
+
function shrinkRaw(img, f) {
|
|
2084
|
+
const width = Math.floor(img.width / f);
|
|
2085
|
+
const height = Math.floor(img.height / f);
|
|
2086
|
+
const data = Buffer.alloc(width * height * 3);
|
|
2087
|
+
for (let i = 0; i < width * height; i++) {
|
|
2088
|
+
const x = i % width * f;
|
|
2089
|
+
const y = Math.floor(i / width) * f;
|
|
2090
|
+
for (let c = 0; c < 3; c++) {
|
|
2091
|
+
let sum = 0;
|
|
2092
|
+
for (let j = 0; j < f; j++) {
|
|
2093
|
+
const row = ((y + j) * img.width + x) * img.channels + c;
|
|
2094
|
+
for (let k = 0; k < f; k++) sum += img.data[row + k * img.channels] ?? 0;
|
|
2095
|
+
}
|
|
2096
|
+
data[i * 3 + c] = Math.round(sum / (f * f));
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
return { data, width, height, channels: 3 };
|
|
2100
|
+
}
|
|
2101
|
+
function axisTaps(from, to) {
|
|
2102
|
+
const near = new Int32Array(to);
|
|
2103
|
+
const far = new Int32Array(to);
|
|
2104
|
+
const t = new Float32Array(to);
|
|
2105
|
+
for (let k = 0; k < to; k++) {
|
|
2106
|
+
const u = Math.min(from - 1, Math.max(0, (k + 0.5) * from / to - 0.5));
|
|
2107
|
+
near[k] = Math.floor(u);
|
|
2108
|
+
far[k] = Math.min(from - 1, Math.floor(u) + 1);
|
|
2109
|
+
t[k] = u - Math.floor(u);
|
|
2110
|
+
}
|
|
2111
|
+
return { near, far, t };
|
|
2112
|
+
}
|
|
2113
|
+
function enlargeRow(values, out, xs, row, stride) {
|
|
2114
|
+
const { top, bottom, fy } = row;
|
|
2115
|
+
for (let x = 0; x < row.width; x++) {
|
|
2116
|
+
const left = xs.near[x] ?? 0;
|
|
2117
|
+
const right = xs.far[x] ?? 0;
|
|
2118
|
+
const fx = xs.t[x] ?? 0;
|
|
2119
|
+
const o = (row.y * row.width + x) * stride;
|
|
2120
|
+
for (let c = 0; c < stride; c++) {
|
|
2121
|
+
const upper = (values[(top + left) * stride + c] ?? 0) * (1 - fx) + (values[(top + right) * stride + c] ?? 0) * fx;
|
|
2122
|
+
const lower = (values[(bottom + left) * stride + c] ?? 0) * (1 - fx) + (values[(bottom + right) * stride + c] ?? 0) * fx;
|
|
2123
|
+
out[o + c] = upper * (1 - fy) + lower * fy;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
function enlarge(values, from, to, stride) {
|
|
2128
|
+
if (from.width === to.width && from.height === to.height) return values;
|
|
2129
|
+
const xs = axisTaps(from.width, to.width);
|
|
2130
|
+
const ys = axisTaps(from.height, to.height);
|
|
2131
|
+
const out = new Float32Array(to.width * to.height * stride);
|
|
2132
|
+
for (let y = 0; y < to.height; y++) {
|
|
2133
|
+
const top = (ys.near[y] ?? 0) * from.width;
|
|
2134
|
+
const bottom = (ys.far[y] ?? 0) * from.width;
|
|
2135
|
+
enlargeRow(values, out, xs, { y, top, bottom, fy: ys.t[y] ?? 0, width: to.width }, stride);
|
|
2136
|
+
}
|
|
2137
|
+
return out;
|
|
2138
|
+
}
|
|
2139
|
+
function moveOnRender(m, frame, width, height) {
|
|
2140
|
+
const x = (v) => (frame.x + v * frame.width) / width;
|
|
2141
|
+
const y = (v) => (frame.y + v * frame.height) / height;
|
|
2142
|
+
return {
|
|
2143
|
+
group: { x0: x(m.group.x0), y0: y(m.group.y0), x1: x(m.group.x1), y1: y(m.group.y1) },
|
|
2144
|
+
fit: {
|
|
2145
|
+
scale: m.fit.scale,
|
|
2146
|
+
cx: x(m.fit.cx),
|
|
2147
|
+
cy: y(m.fit.cy),
|
|
2148
|
+
dx: m.fit.dx * frame.width / width,
|
|
2149
|
+
dy: m.fit.dy * frame.height / height
|
|
2150
|
+
}
|
|
2151
|
+
};
|
|
2152
|
+
}
|
|
2153
|
+
var overlaps2 = (a, b) => a.x0 < b.x1 && a.x1 > b.x0 && a.y0 < b.y1 && a.y1 > b.y0;
|
|
2154
|
+
var shifted = (box, dx, dy) => ({
|
|
2155
|
+
...box,
|
|
2156
|
+
x0: box.x0 + dx,
|
|
2157
|
+
y0: box.y0 + dy,
|
|
2158
|
+
x1: box.x1 + dx,
|
|
2159
|
+
y1: box.y1 + dy
|
|
2160
|
+
});
|
|
2161
|
+
var moveOf = (box, moves) => moves.find((m) => inSpans2([m.group], (box.x0 + box.x1) / 2, (box.y0 + box.y1) / 2));
|
|
2162
|
+
var hull = (a, b) => ({
|
|
2163
|
+
x0: Math.min(a.x0, b.x0),
|
|
2164
|
+
y0: Math.min(a.y0, b.y0),
|
|
2165
|
+
x1: Math.max(a.x1, b.x1),
|
|
2166
|
+
y1: Math.max(a.y1, b.y1)
|
|
2167
|
+
});
|
|
2168
|
+
var BARE = 0.02;
|
|
2169
|
+
var frameSpan = (frame, width, height) => ({
|
|
2170
|
+
x0: frame.x / width,
|
|
2171
|
+
y0: frame.y / height,
|
|
2172
|
+
x1: (frame.x + frame.width) / width,
|
|
2173
|
+
y1: (frame.y + frame.height) / height
|
|
2174
|
+
});
|
|
2175
|
+
var CARD_CUT = 5e-3;
|
|
2176
|
+
function cardCut(band, f) {
|
|
2177
|
+
const w = f.x1 - f.x0;
|
|
2178
|
+
const h = f.y1 - f.y0;
|
|
2179
|
+
const across2 = band.x0 <= f.x0 + FRAME_MARGIN * w && band.x1 >= f.x1 - FRAME_MARGIN * w;
|
|
2180
|
+
const down = band.y0 <= f.y0 + FRAME_MARGIN * h && band.y1 >= f.y1 - FRAME_MARGIN * h;
|
|
2181
|
+
const pastY = band.y0 < f.y0 - CARD_CUT * h || band.y1 > f.y1 + CARD_CUT * h;
|
|
2182
|
+
const pastX = band.x0 < f.x0 - CARD_CUT * w || band.x1 > f.x1 + CARD_CUT * w;
|
|
2183
|
+
return pastY && !across2 || pastX && !down;
|
|
2184
|
+
}
|
|
2185
|
+
function cutCardOf(laid, line, f) {
|
|
2186
|
+
const band = bandUnder(laid, line);
|
|
2187
|
+
return band && cardCut(band, f) ? band : null;
|
|
2188
|
+
}
|
|
2189
|
+
var unique = (boxes) => boxes.filter(
|
|
2190
|
+
(b, i) => boxes.findIndex((o) => o.x0 === b.x0 && o.y0 === b.y0 && o.x1 === b.x1 && o.y1 === b.y1) === i
|
|
2191
|
+
);
|
|
2192
|
+
function merged(spans) {
|
|
2193
|
+
const out = [];
|
|
2194
|
+
for (const s of spans) {
|
|
2195
|
+
let joined = s;
|
|
2196
|
+
for (let i = out.length - 1; i >= 0; i--) {
|
|
2197
|
+
const o = out[i];
|
|
2198
|
+
if (o && overlaps2(o, joined)) {
|
|
2199
|
+
joined = hull(o, joined);
|
|
2200
|
+
out.splice(i, 1);
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
out.push(joined);
|
|
2204
|
+
}
|
|
2205
|
+
return out;
|
|
2206
|
+
}
|
|
2207
|
+
function carriersOf(m, laid, designed) {
|
|
2208
|
+
const lines = designed.filter((b) => inSpans2([m.group], (b.x0 + b.x1) / 2, (b.y0 + b.y1) / 2));
|
|
2209
|
+
const bands = lines.flatMap((b) => {
|
|
2210
|
+
const band = bandUnder(laid, b);
|
|
2211
|
+
return band ? [band] : [];
|
|
2212
|
+
});
|
|
2213
|
+
if (bands.length === 0) return "picture";
|
|
2214
|
+
return bands.length < lines.length ? "mixed" : merged(bands);
|
|
2215
|
+
}
|
|
2216
|
+
function bandMoves(banded, moves, p, at) {
|
|
2217
|
+
const faces = p.subjects.filter((s) => s.kind === "face");
|
|
2218
|
+
const out = [];
|
|
2219
|
+
for (const { move: m, band } of banded) {
|
|
2220
|
+
if (m.fit.scale < 1 - 1e-9 || out.some((o) => overlaps2(o.band, band))) return null;
|
|
2221
|
+
const { dx, dy } = m.fit;
|
|
2222
|
+
const landing = shifted(band, dx, dy);
|
|
2223
|
+
const carried = p.words.designed.filter((b) => inSpans2([band], (b.x0 + b.x1) / 2, (b.y0 + b.y1) / 2));
|
|
2224
|
+
const others = p.words.designed.filter((b) => !carried.includes(b));
|
|
2225
|
+
const ends = (b) => {
|
|
2226
|
+
const own = moveOf(b, moves);
|
|
2227
|
+
return own ? movedSpan(at.extent(b), own.fit) : at.extent(b);
|
|
2228
|
+
};
|
|
2229
|
+
const lost = wordsLost(
|
|
2230
|
+
carried.map((b) => at.inFrame(shifted(b, dx, dy))),
|
|
2231
|
+
p.format,
|
|
2232
|
+
p.placements
|
|
2233
|
+
);
|
|
2234
|
+
const crossed = carried.some((b) => (moveOf(b, moves) ?? m) !== m) || others.some((b) => overlaps2(ends(b), hull(band, landing)));
|
|
2235
|
+
if (lost.length > 0 || crossed || facesUnder([landing], faces).length > 0) return null;
|
|
2236
|
+
out.push({ band, dx, dy, words: carried });
|
|
2237
|
+
}
|
|
2238
|
+
return out;
|
|
2239
|
+
}
|
|
2240
|
+
function wordsMoved(p, out, moves) {
|
|
2241
|
+
const { layer } = wordsLayer(p.aligned, p.cut, p.words.designed, {
|
|
2242
|
+
subjects: p.subjects,
|
|
2243
|
+
keepOut: p.words.inScene
|
|
2244
|
+
});
|
|
2245
|
+
const part = movedPart(layer, moves);
|
|
2246
|
+
const left = soften(
|
|
2247
|
+
part.alpha.map((a) => a > 0 ? 1 : 0),
|
|
2248
|
+
p.cut.width,
|
|
2249
|
+
p.cut.height,
|
|
2250
|
+
2
|
|
2251
|
+
).map((a, i) => Math.max(a, part.alpha[i] ?? 0));
|
|
2252
|
+
return compose(restoreSubjects(out, p.cut, p.gain, left), moveLayer(part, moves));
|
|
2253
|
+
}
|
|
2254
|
+
function placeWords(p) {
|
|
2255
|
+
const { width, height } = p.cut;
|
|
2256
|
+
const inFrame = (b) => ({
|
|
2257
|
+
...b,
|
|
2258
|
+
x0: (b.x0 * width - p.frame.x) / p.frame.width,
|
|
2259
|
+
x1: (b.x1 * width - p.frame.x) / p.frame.width,
|
|
2260
|
+
y0: (b.y0 * height - p.frame.y) / p.frame.height,
|
|
2261
|
+
y1: (b.y1 * height - p.frame.y) / p.frame.height
|
|
2262
|
+
});
|
|
2263
|
+
const showing = (b) => b.x1 > 0 && b.y1 > 0 && b.x0 < 1 && b.y0 < 1;
|
|
2264
|
+
const laid = laidMap(p.judged.aligned, p.judged.cut);
|
|
2265
|
+
const f = frameSpan(p.frame, width, height);
|
|
2266
|
+
const placed2 = p.words.designed.map((b) => {
|
|
2267
|
+
const card = cutCardOf(laid, b, f);
|
|
2268
|
+
return card ? { ...b, ...card } : b;
|
|
2269
|
+
});
|
|
2270
|
+
const plan = planWordsShift(unique(placed2).map(inFrame).filter(showing), p.format, {
|
|
2271
|
+
...p.placements ? { placements: p.placements } : {},
|
|
2272
|
+
...p.minScale !== void 0 ? { minScale: p.minScale } : {},
|
|
2273
|
+
faces: p.subjects.filter((s) => s.kind === "face").map(inFrame).filter(showing),
|
|
2274
|
+
// Never into the logo's slot, nor out of it: a block moved out of it had its band cut through the letters.
|
|
2275
|
+
...p.keepOut ? { keepOut: p.keepOut } : {}
|
|
2276
|
+
});
|
|
2277
|
+
if (plan.reason || plan.moves.length === 0) return null;
|
|
2278
|
+
const moves = plan.moves.map((m) => moveOnRender(m, p.frame, width, height));
|
|
2279
|
+
const under = moves.map((move) => ({ move, on: carriersOf(move, laid, p.words.designed) }));
|
|
2280
|
+
const unsure = (u) => u.on === "mixed" || u.on === "picture" && laidAround(laid, u.move.group) > BARE;
|
|
2281
|
+
if (under.some(unsure)) return null;
|
|
2282
|
+
const banded = under.flatMap((u) => Array.isArray(u.on) ? u.on.map((band) => ({ move: u.move, band })) : []);
|
|
2283
|
+
const bands = bandMoves(banded, moves, p, { inFrame, extent: (b) => bandUnder(laid, b) ?? b });
|
|
2284
|
+
if (!bands) return null;
|
|
2285
|
+
const loose = under.flatMap((u) => u.on === "picture" ? [u.move] : []);
|
|
2286
|
+
let out = loose.length > 0 ? wordsMoved(p, p.out, loose) : p.out;
|
|
2287
|
+
for (const band of bands) out = moveBand({ aligned: p.aligned, cut: p.cut, out }, band);
|
|
2288
|
+
return { out, moves: plan.moves };
|
|
2289
|
+
}
|
|
2290
|
+
function takeWhole(input) {
|
|
2291
|
+
const { render, cut, frame } = input;
|
|
2292
|
+
const fit = registerToSource(render, cut, input.words?.designed ?? []);
|
|
2293
|
+
const aligned = warpToCut(render, fit);
|
|
2294
|
+
if (!input.words) {
|
|
2295
|
+
const out2 = cropRaw(aligned, frame);
|
|
2296
|
+
return { ok: true, out: out2, restored: [], covered: [], moves: [], kept: 1, residual: fit.residual };
|
|
2297
|
+
}
|
|
2298
|
+
const judging = judge(input, input.words, fit, aligned);
|
|
2299
|
+
const { verdict, kept } = judging;
|
|
2300
|
+
const misplaced = !verdict.ok && (verdict.problem === "words_lost" || verdict.problem === "words_over_face");
|
|
2301
|
+
if (!verdict.ok && !misplaced) return { ...verdict, kept, residual: fit.residual };
|
|
2302
|
+
const { out, gain, taken } = putBack(input, input.words, aligned, judging);
|
|
2303
|
+
const done = { ...taken, kept, residual: fit.residual };
|
|
2304
|
+
if (verdict.ok) return { ok: true, out: cropRaw(out, frame), moves: [], ...done };
|
|
2305
|
+
const placed2 = placeWords({
|
|
2306
|
+
aligned,
|
|
2307
|
+
cut,
|
|
2308
|
+
out,
|
|
2309
|
+
gain: gain(),
|
|
2310
|
+
judged: judging.judged,
|
|
2311
|
+
frame,
|
|
2312
|
+
words: input.words,
|
|
2313
|
+
subjects: input.subjects,
|
|
2314
|
+
format: input.format,
|
|
2315
|
+
...input.placements ? { placements: input.placements } : {},
|
|
2316
|
+
...input.minScale !== void 0 ? { minScale: input.minScale } : {},
|
|
2317
|
+
...input.keepOut ? { keepOut: input.keepOut } : {}
|
|
2318
|
+
});
|
|
2319
|
+
if (!placed2) return { ...verdict, kept, residual: fit.residual, whole: { out: cropRaw(out, frame), ...taken } };
|
|
2320
|
+
return { ok: true, out: cropRaw(placed2.out, frame), moves: placed2.moves, ...done };
|
|
2321
|
+
}
|
|
2322
|
+
function judge(input, read, fit, aligned) {
|
|
2323
|
+
const { cut, frame } = input;
|
|
2324
|
+
const { width, height } = cut;
|
|
2325
|
+
const words = read.designed.map((b) => padded(b, width, height));
|
|
2326
|
+
const shrink2 = Math.max(1, Math.round(width / JUDGED_WIDTH));
|
|
2327
|
+
const judged = shrink2 > 1 ? { aligned: shrinkRaw(aligned, shrink2), cut: shrunkCuts(cut, String(shrink2), () => shrinkRaw(cut, shrink2)) } : { aligned, cut };
|
|
2328
|
+
const diff = renderDiff(judged.aligned, judged.cut, words);
|
|
2329
|
+
const drifts = input.subjects.map((s) => ({ subject: s, ...subjectDrift(diff, s, words) }));
|
|
2330
|
+
const inFrame = (b) => ({
|
|
2331
|
+
...b,
|
|
2332
|
+
x0: (b.x0 * width - frame.x) / frame.width,
|
|
2333
|
+
x1: (b.x1 * width - frame.x) / frame.width,
|
|
2334
|
+
y0: (b.y0 * height - frame.y) / frame.height,
|
|
2335
|
+
y1: (b.y1 * height - frame.y) / frame.height
|
|
2336
|
+
});
|
|
2337
|
+
const kept = keptShare(diff, words);
|
|
2338
|
+
const gone = /* @__PURE__ */ new Set();
|
|
2339
|
+
const laid = laidMap(judged.aligned, judged.cut);
|
|
2340
|
+
const f = frameSpan(frame, width, height);
|
|
2341
|
+
const carded = read.designed.filter((b) => cutCardOf(laid, b, f)).map((b) => b.text);
|
|
2342
|
+
const lost = wordsLost(read.designed.map(inFrame), input.format, input.placements, input.keepOut);
|
|
2343
|
+
const base = {
|
|
2344
|
+
kept,
|
|
2345
|
+
carried: carriedBy(fit, frame, width, height),
|
|
2346
|
+
lost: [...lost, ...carded.filter((t) => !lost.includes(t))]
|
|
2347
|
+
};
|
|
2348
|
+
const faces = () => input.subjects.filter((s) => s.kind === "face" && !gone.has(s));
|
|
2349
|
+
const readingNow = () => ({
|
|
2350
|
+
...base,
|
|
2351
|
+
subjects: drifts.filter((d) => !gone.has(d.subject)).map((d) => ({ label: d.subject.label, moved: d.moved, drift: d.drift, shown: d.shown })),
|
|
2352
|
+
onFace: wordsOnFaces(read.designed, faces())
|
|
2353
|
+
});
|
|
2354
|
+
let verdict = wholeVerdict(readingNow());
|
|
2355
|
+
const relocated = [];
|
|
2356
|
+
for (let round = 0; round < 2 && !verdict.ok && FOLLOWED.has(verdict.problem); round++) {
|
|
2357
|
+
const suspects = verdict.problem === "subject_redrawn" ? drifts.filter((d) => !gone.has(d.subject) && d.moved > REDRAWN).map((d) => d.subject) : facesUnder(read.designed, faces());
|
|
2358
|
+
const found = relocations(withTheirPeople(suspects, input.subjects), judged);
|
|
2359
|
+
if (!found) break;
|
|
2360
|
+
relocated.push(...found);
|
|
2361
|
+
for (const r of found) gone.add(r.subject);
|
|
2362
|
+
verdict = wholeVerdict(readingNow());
|
|
2363
|
+
}
|
|
2364
|
+
return { verdict, reading: readingNow(), kept, diff, judged, words, drifts, relocated };
|
|
2365
|
+
}
|
|
2366
|
+
function withTheirPeople(suspects, subjects) {
|
|
2367
|
+
const holds2 = (outer, inner) => outer.x0 <= inner.x0 + 0.01 && outer.y0 <= inner.y0 + 0.01 && outer.x1 >= inner.x1 - 0.01 && outer.y1 >= inner.y1 - 0.01;
|
|
2368
|
+
const people = subjects.filter(
|
|
2369
|
+
(p) => p.kind === "person" && suspects.some((f) => f.kind === "face" && f.label === p.label && holds2(p, f))
|
|
2370
|
+
);
|
|
2371
|
+
return [.../* @__PURE__ */ new Set([...suspects, ...people])];
|
|
2372
|
+
}
|
|
2373
|
+
var FOLLOWED = /* @__PURE__ */ new Set(["subject_redrawn", "words_over_face"]);
|
|
2374
|
+
function putBack(input, read, aligned, j) {
|
|
2375
|
+
const { cut } = input;
|
|
2376
|
+
const full = { width: cut.width, height: cut.height };
|
|
2377
|
+
const settled = j.verdict.ok ? j.verdict : wholeVerdict({ ...j.reading, lost: [], onFace: [] });
|
|
2378
|
+
const restored = settled.ok ? settled.restore : [];
|
|
2379
|
+
const back = input.subjects.filter((s) => restored.includes(s.label));
|
|
2380
|
+
const zones = [...back, ...read.inScene.map((b) => padded(b, full.width, full.height))];
|
|
2381
|
+
const covered = j.drifts.filter((d) => (d.subject.kind === "product" || d.subject.kind === "animal") && d.shown < SHOWN_MIN).map((d) => d.subject.label);
|
|
2382
|
+
let enlarged;
|
|
2383
|
+
const gain = () => {
|
|
2384
|
+
enlarged ??= enlarge(j.diff.gain, j.diff, full, 3);
|
|
2385
|
+
return enlarged;
|
|
2386
|
+
};
|
|
2387
|
+
let out = zones.length === 0 ? aligned : restoreSubjects(aligned, cut, gain(), enlarge(restoreMask(j.diff, zones, j.words), j.diff, full, 1));
|
|
2388
|
+
for (const r of j.relocated) out = putMoved(out, cut, r, j);
|
|
2389
|
+
const moved = j.relocated.map((r) => r.subject.label);
|
|
2390
|
+
return { out, gain, taken: { restored: [.../* @__PURE__ */ new Set([...restored, ...moved])], covered } };
|
|
2391
|
+
}
|
|
2392
|
+
var TRACK_MAX_AREA = 0.06;
|
|
2393
|
+
var RELOCATED = 0.8;
|
|
2394
|
+
var STAYED = 5e-3;
|
|
2395
|
+
function relocations(subjects, judged) {
|
|
2396
|
+
if (subjects.length === 0) return null;
|
|
2397
|
+
const out = [];
|
|
2398
|
+
for (const subject of subjects) {
|
|
2399
|
+
if ((subject.x1 - subject.x0) * (subject.y1 - subject.y0) > TRACK_MAX_AREA) return null;
|
|
2400
|
+
const place = tracked(judged.aligned, judged.cut, subject);
|
|
2401
|
+
const stayed = Math.hypot(place.dx, place.dy) < STAYED && Math.abs(place.scale - 1) < 0.02;
|
|
2402
|
+
if (place.score < RELOCATED || stayed) return null;
|
|
2403
|
+
out.push({ subject, place });
|
|
2404
|
+
}
|
|
2405
|
+
return out;
|
|
2406
|
+
}
|
|
2407
|
+
function movedBox(box, place) {
|
|
2408
|
+
const cx = (box.x0 + box.x1) / 2;
|
|
2409
|
+
const cy = (box.y0 + box.y1) / 2;
|
|
2410
|
+
return {
|
|
2411
|
+
x0: cx + place.dx + place.scale * (box.x0 - cx),
|
|
2412
|
+
y0: cy + place.dy + place.scale * (box.y0 - cy),
|
|
2413
|
+
x1: cx + place.dx + place.scale * (box.x1 - cx),
|
|
2414
|
+
y1: cy + place.dy + place.scale * (box.y1 - cy)
|
|
2415
|
+
};
|
|
2416
|
+
}
|
|
2417
|
+
function cutMoved(cut, box, place) {
|
|
2418
|
+
const { width, height } = cut;
|
|
2419
|
+
const out = Buffer.alloc(width * height * 3);
|
|
2420
|
+
if (cut.channels === 3) cut.data.copy(out, 0, 0, width * height * 3);
|
|
2421
|
+
else for (let i = 0; i < width * height; i++) cut.data.copy(out, i * 3, i * cut.channels, i * cut.channels + 3);
|
|
2422
|
+
const to = movedBox(box, place);
|
|
2423
|
+
const margin = (ZONE_MARGIN + FEATHER) * Math.max((to.x1 - to.x0) * width, (to.y1 - to.y0) * height) + 4;
|
|
2424
|
+
const cx = (box.x0 + box.x1) / 2 * width;
|
|
2425
|
+
const cy = (box.y0 + box.y1) / 2 * height;
|
|
2426
|
+
for (let y = Math.max(0, Math.floor(to.y0 * height - margin)); y < Math.min(height, to.y1 * height + margin); y++) {
|
|
2427
|
+
for (let x = Math.max(0, Math.floor(to.x0 * width - margin)); x < Math.min(width, to.x1 * width + margin); x++) {
|
|
2428
|
+
const u = Math.min(width - 1.001, Math.max(0, cx + (x - cx - place.dx * width) / place.scale));
|
|
2429
|
+
const v = Math.min(height - 1.001, Math.max(0, cy + (y - cy - place.dy * height) / place.scale));
|
|
2430
|
+
const x0 = Math.floor(u);
|
|
2431
|
+
const y0 = Math.floor(v);
|
|
2432
|
+
const fx = u - x0;
|
|
2433
|
+
const fy = v - y0;
|
|
2434
|
+
for (let c = 0; c < 3; c++) {
|
|
2435
|
+
const at = (px, py) => cut.data[(py * width + px) * cut.channels + c] ?? 0;
|
|
2436
|
+
const top = at(x0, y0) * (1 - fx) + at(x0 + 1, y0) * fx;
|
|
2437
|
+
const bottom = at(x0, y0 + 1) * (1 - fx) + at(x0 + 1, y0 + 1) * fx;
|
|
2438
|
+
out[(y * width + x) * 3 + c] = Math.round(top * (1 - fy) + bottom * fy);
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
return { data: out, width, height, channels: 3 };
|
|
2443
|
+
}
|
|
2444
|
+
function putMoved(out, cut, r, j) {
|
|
2445
|
+
const full = { width: cut.width, height: cut.height };
|
|
2446
|
+
const moved = cutMoved(cut, r.subject, r.place);
|
|
2447
|
+
const judgedMoved = j.judged.cut.width === cut.width ? moved : shrinkRaw(moved, Math.round(cut.width / j.judged.cut.width));
|
|
2448
|
+
const diff = renderDiff(j.judged.aligned, judgedMoved, j.words);
|
|
2449
|
+
const mask = restoreMask(diff, [movedBox(r.subject, r.place)], j.words);
|
|
2450
|
+
return restoreSubjects(out, moved, enlarge(diff.gain, diff, full, 3), enlarge(mask, diff, full, 1));
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
// src/engine/nodes/local/staticFormat.ts
|
|
2454
|
+
var Usage = z3.object({ model: z3.string(), inputTokens: z3.number(), outputTokens: z3.number(), costUsd: z3.number() }).strict();
|
|
2455
|
+
var Unit = z3.number().min(0).max(1);
|
|
2456
|
+
var SpanSchema = z3.object({ x0: Unit, y0: Unit, x1: Unit, y1: Unit }).strict();
|
|
2457
|
+
var Copy = z3.array(z3.object({ text: z3.string().min(1), role: z3.string().optional() }).strict());
|
|
2458
|
+
var Rect = z3.object({ x: z3.number(), y: z3.number(), width: z3.number(), height: z3.number() }).strict();
|
|
2459
|
+
var REASONS = [
|
|
2460
|
+
"band_too_far",
|
|
2461
|
+
"words_over_face",
|
|
2462
|
+
"subject_covered",
|
|
2463
|
+
"subject_cut",
|
|
2464
|
+
"words_misaligned",
|
|
2465
|
+
"words_not_read",
|
|
2466
|
+
"not_read"
|
|
2467
|
+
];
|
|
2468
|
+
var FormatFacts = z3.object({
|
|
2469
|
+
format: z3.string(),
|
|
2470
|
+
lead: z3.boolean(),
|
|
2471
|
+
plate: z3.object({ width: z3.number(), height: z3.number() }).strict(),
|
|
2472
|
+
crop: Rect,
|
|
2473
|
+
render_ratio: z3.string(),
|
|
2474
|
+
upscale: z3.number(),
|
|
2475
|
+
/** Each block of words code moved (into the band, off a face): its scale and shift, fractions of the size. */
|
|
2476
|
+
moves: z3.array(z3.object({ scale: z3.number(), dx: z3.number(), dy: z3.number() }).strict()),
|
|
2477
|
+
/** How far the words render sat from the cut once lined up (RMS grey levels): the spike's calibration of `MISALIGNED`. */
|
|
2478
|
+
residual: z3.number().optional(),
|
|
2479
|
+
reason: z3.enum(REASONS).optional(),
|
|
2480
|
+
/** `subject_covered`: the products and animals the words hide most of in this size, as the reader names them. */
|
|
2481
|
+
covered: z3.array(z3.string()).optional(),
|
|
2482
|
+
/**
|
|
2483
|
+
* How the words were laid: `whole`, the words model's whole render, its redrawn subjects put back
|
|
2484
|
+
* from the picture; `masked`, only what it changed at the words, on the picture (when its render
|
|
2485
|
+
* could not be taken whole twice). Absent when no words were set (`subject_cut`).
|
|
2486
|
+
*/
|
|
2487
|
+
words_mode: z3.enum(["whole", "masked"]).optional(),
|
|
2488
|
+
/** `whole`: the share of the picture's detail the render kept where it was (`keptShare`). */
|
|
2489
|
+
kept: z3.number().optional(),
|
|
2490
|
+
/** `whole`: the people, faces and products put back from the picture where the render redrew them. */
|
|
2491
|
+
restored: z3.array(z3.string()).optional(),
|
|
2492
|
+
/** Why the first render could not be taken whole, so the words were set a second time. */
|
|
2493
|
+
retried: z3.enum(WHOLE_PROBLEMS).optional(),
|
|
2494
|
+
/** `masked`: why the second render could not be taken whole either. */
|
|
2495
|
+
refused: z3.enum(WHOLE_PROBLEMS).optional(),
|
|
2496
|
+
reverted: z3.number(),
|
|
2497
|
+
/** `masked`: the mean difference from the cut outside the words layer, 0 by construction. */
|
|
2498
|
+
identity: z3.number().optional(),
|
|
2499
|
+
steps: z3.array(
|
|
2500
|
+
z3.object({
|
|
2501
|
+
name: z3.enum(["subjects", "words", "words_again", "boxes"]),
|
|
2502
|
+
cached: z3.boolean(),
|
|
2503
|
+
credits: z3.number(),
|
|
2504
|
+
ms: z3.number()
|
|
2505
|
+
}).strict()
|
|
2506
|
+
)
|
|
2507
|
+
}).strict();
|
|
2508
|
+
var Words = z3.object({
|
|
2509
|
+
model: z3.string().min(1),
|
|
2510
|
+
quality: z3.string().optional(),
|
|
2511
|
+
prompt: z3.string().min(1),
|
|
2512
|
+
/** A change to the words of this size (`--reword`, an autofix): the previous render (`inputs.previous`) leads. */
|
|
2513
|
+
edit: z3.object({ instruction: z3.string().min(1) }).strict().optional()
|
|
2514
|
+
}).strict();
|
|
2515
|
+
var MISALIGNED = 40;
|
|
2516
|
+
var FormatParamsSchema = z3.object({
|
|
2517
|
+
format: z3.string().regex(/^\d+(?:\.\d+)?:\d+(?:\.\d+)?$/),
|
|
2518
|
+
lead: z3.boolean().optional(),
|
|
2519
|
+
placements: z3.array(z3.string().min(1)).optional(),
|
|
2520
|
+
words: Words,
|
|
2521
|
+
copy: Copy.optional(),
|
|
2522
|
+
in_scene: z3.array(z3.string().min(1)).optional(),
|
|
2523
|
+
/** The plan's subject zone, fractions of the plate: what the cut centres on when no subject was read. */
|
|
2524
|
+
core: SpanSchema.optional(),
|
|
2525
|
+
band_min_scale: z3.number().min(0.5).max(1).optional(),
|
|
2526
|
+
/**
|
|
2527
|
+
* The other sizes cut from the same picture (a variant's lead is checked against them): when
|
|
2528
|
+
* one would cut a face, a product or a head, no words are paid for (`subject_cut`).
|
|
2529
|
+
*/
|
|
2530
|
+
check_formats: z3.array(z3.string().regex(/^\d+(?:\.\d+)?:\d+(?:\.\d+)?$/)).optional(),
|
|
2531
|
+
/**
|
|
2532
|
+
* The brand's logo file is placed on this size afterwards (`static_logo`): the words draw no logo
|
|
2533
|
+
* and keep its slot empty, planned here inside the size's safe area off every face and product,
|
|
2534
|
+
* from the logo's shape (`aspect`, width over height) and where the concept puts it (`position`).
|
|
2535
|
+
*/
|
|
2536
|
+
logo_slot: z3.object({ aspect: z3.number().positive(), position: z3.enum(LOGO_POSITIONS).optional() }).strict().optional()
|
|
2537
|
+
}).strict();
|
|
2538
|
+
var staticFormatNode = defineNode({
|
|
2539
|
+
id: "static_format",
|
|
2540
|
+
version: "1.9.0",
|
|
2541
|
+
category: "image",
|
|
2542
|
+
location: "local",
|
|
2543
|
+
billing: "reported",
|
|
2544
|
+
summary: "One delivered size of a static ad, from the ad's picture (`plate`): cuts the size at one scale around the people and products (`subjects`), and around the cards the picture draws for its words when it can, has the image model set the ad's designed words, logo and button on the cut (`params.words`, one paid call), and takes its whole render, lined up with the cut, putting back from the picture each person, face and product it redrew (soft-edged, in the render's light). Words the frame cuts, the app covers or a face sits under are moved by code on the render, with the band, card or pill they sit on. A render that moved the picture or redrew a subject, or whose words no move clears, is set again once; when that one moved or redrew too, only what it changed at the words is kept on the picture, and when its words are out of place twice, it stays whole and says where they are. Outputs the size (`image`), the cut it was set on (`cut`), the model's render (`words_raw`), where the words were laid when only they were kept (`words_alpha`) and what it did (`facts`).",
|
|
2545
|
+
when_to_use: "One per delivered size of a static ad built on one picture (`format_<size>`, role `static_format`). One image call at the words model's price (two when the first cannot be taken whole), kept apart from the free cut and compose: changing only the band, the placements or the node's version never pays for it again; `--regenerate format_<size>` does.",
|
|
2546
|
+
inputs: z3.object({
|
|
2547
|
+
plate: ImageRef,
|
|
2548
|
+
subjects: z3.array(SubjectBoxSchema).optional(),
|
|
2549
|
+
logo: ImageRef.optional(),
|
|
2550
|
+
type: ImageRef.optional(),
|
|
2551
|
+
style: ImageRef.optional(),
|
|
2552
|
+
refs: z3.array(ImageRef).optional(),
|
|
2553
|
+
previous: ImageRef.optional()
|
|
2554
|
+
}).strict(),
|
|
2555
|
+
params: FormatParamsSchema,
|
|
2556
|
+
outputs: z3.object({
|
|
2557
|
+
image: ImageRef,
|
|
2558
|
+
cut: ImageRef,
|
|
2559
|
+
words_raw: ImageRef.optional(),
|
|
2560
|
+
words_alpha: ImageRef.optional(),
|
|
2561
|
+
/** The slot the words left empty for the logo file, in the size's pixels (`params.logo_slot`). */
|
|
2562
|
+
logo_slot: Rect.optional(),
|
|
2563
|
+
facts: FormatFacts,
|
|
2564
|
+
usage: z3.array(Usage).optional()
|
|
2565
|
+
}).strict(),
|
|
2566
|
+
outputKinds: { image: "image", cut: "image", words_raw: "image", words_alpha: "image" },
|
|
2567
|
+
cost: ({ params }) => imageGenerateNode.cost?.({ params: wordsCallParams(params.words, "1:1") }) ?? {
|
|
2568
|
+
credits: 0,
|
|
2569
|
+
seconds_estimate: 60
|
|
2570
|
+
},
|
|
2571
|
+
async execute({ inputs, params, ctx }) {
|
|
2572
|
+
return await formatSize(inputs, params, ctx);
|
|
2573
|
+
}
|
|
2574
|
+
});
|
|
2575
|
+
function wordsCallParams(words, ratio) {
|
|
2576
|
+
const prompt = words.edit ? `Edit: ${words.edit.instruction}
|
|
2577
|
+
|
|
2578
|
+
${words.prompt}` : words.prompt;
|
|
2579
|
+
return { model: words.model, prompt, aspect_ratio: ratio, ...words.quality ? { quality: words.quality } : {} };
|
|
2580
|
+
}
|
|
2581
|
+
var percent = (v) => Math.round(Math.max(0, Math.min(1, v)) * 100);
|
|
2582
|
+
function wordsAvoid(faces) {
|
|
2583
|
+
if (faces.length === 0) return "";
|
|
2584
|
+
const where = faces.map(
|
|
2585
|
+
(f) => `a face ${percent(f.y0)}-${percent(f.y1)}% down, ${percent(f.x0)}-${percent(f.x1)}% across`
|
|
2586
|
+
);
|
|
2587
|
+
return `Keep every word, the logo and the button off ${where.join("; ")}.`;
|
|
2588
|
+
}
|
|
2589
|
+
function stripsOf(before, after, sides, depth) {
|
|
2590
|
+
const cut = [
|
|
2591
|
+
...percent(before) >= 1 ? [{ share: percent(before), side: sides[0] }] : [],
|
|
2592
|
+
...percent(after) >= 1 ? [{ share: percent(after), side: sides[1] }] : []
|
|
2593
|
+
];
|
|
2594
|
+
return cut.map(
|
|
2595
|
+
(s, i) => i === 0 ? `a strip ${s.share}% ${depth} at its ${s.side}` : `${s.share}% at its ${s.side}`
|
|
2596
|
+
);
|
|
2597
|
+
}
|
|
2598
|
+
function wordsFrame(frame, work, format) {
|
|
2599
|
+
const down = stripsOf(frame.y / work.height, 1 - (frame.y + frame.height) / work.height, ["top", "bottom"], "deep");
|
|
2600
|
+
const across2 = stripsOf(frame.x / work.width, 1 - (frame.x + frame.width) / work.width, ["left", "right"], "wide");
|
|
2601
|
+
const strips = [down.join(" and "), across2.join(" and ")].filter(Boolean);
|
|
2602
|
+
if (strips.length === 0) return "";
|
|
2603
|
+
const many = down.length + across2.length > 1;
|
|
2604
|
+
return `This picture is cut to ${format} afterwards: ${strips.join(", and ")} ${many ? "are" : "is"} cut away, so no word, logo or button comes near ${many ? "them" : "it"}.`;
|
|
2605
|
+
}
|
|
2606
|
+
function splitWordBoxes(boxes, copy, inScene) {
|
|
2607
|
+
const logoWords = copy.filter((l) => /logo/i.test(l.role ?? "")).map((l) => l.text);
|
|
2608
|
+
const read = withWordmark(boxes, logoWords);
|
|
2609
|
+
const lines = copy.filter((l) => !/logo/i.test(l.role ?? ""));
|
|
2610
|
+
const ours = new Set(lines.flatMap((line) => boxesOfLine(line, read)));
|
|
2611
|
+
const unnamed = (b) => lines.length > 0 && b.kind === "text" && !ours.has(b);
|
|
2612
|
+
const scene = /* @__PURE__ */ new Set([...inScene.flatMap((text) => boxesOfLine({ text }, read)), ...read.filter(unnamed)]);
|
|
2613
|
+
const buttons = new Set(copy.filter(isButtonLine).flatMap((line) => boxesOfLine(line, read)));
|
|
2614
|
+
return {
|
|
2615
|
+
designed: read.filter((b) => !scene.has(b)).map((b) => buttons.has(b) ? buttonShape(b) : b),
|
|
2616
|
+
inScene: read.filter((b) => scene.has(b))
|
|
2617
|
+
};
|
|
2618
|
+
}
|
|
2619
|
+
function toFrame(b, frame, work) {
|
|
2620
|
+
return {
|
|
2621
|
+
...b,
|
|
2622
|
+
x0: (b.x0 * work.width - frame.x) / frame.width,
|
|
2623
|
+
y0: (b.y0 * work.height - frame.y) / frame.height,
|
|
2624
|
+
x1: (b.x1 * work.width - frame.x) / frame.width,
|
|
2625
|
+
y1: (b.y1 * work.height - frame.y) / frame.height
|
|
2626
|
+
};
|
|
2627
|
+
}
|
|
2628
|
+
function subjectIn(b, rect, plate) {
|
|
2629
|
+
return {
|
|
2630
|
+
...b,
|
|
2631
|
+
x0: (b.x0 * plate.width - rect.x) / rect.width,
|
|
2632
|
+
y0: (b.y0 * plate.height - rect.y) / rect.height,
|
|
2633
|
+
x1: (b.x1 * plate.width - rect.x) / rect.width,
|
|
2634
|
+
y1: (b.y1 * plate.height - rect.y) / rect.height
|
|
2635
|
+
};
|
|
2636
|
+
}
|
|
2637
|
+
var visible = (b) => b.x1 > 0 && b.y1 > 0 && b.x0 < 1 && b.y0 < 1;
|
|
2638
|
+
async function frameSize(plateBytes, crop, format) {
|
|
2639
|
+
const delivered = deliveredSize(format);
|
|
2640
|
+
const upscale = delivered.width / crop.rect.width;
|
|
2641
|
+
const work = { width: Math.round(crop.render.width * upscale), height: Math.round(crop.render.height * upscale) };
|
|
2642
|
+
const frame = {
|
|
2643
|
+
x: Math.min(work.width - delivered.width, Math.max(0, Math.round((crop.rect.x - crop.render.x) * upscale))),
|
|
2644
|
+
y: Math.min(work.height - delivered.height, Math.max(0, Math.round((crop.rect.y - crop.render.y) * upscale))),
|
|
2645
|
+
width: delivered.width,
|
|
2646
|
+
height: delivered.height
|
|
2647
|
+
};
|
|
2648
|
+
const region = { left: crop.render.x, top: crop.render.y, width: crop.render.width, height: crop.render.height };
|
|
2649
|
+
const renderCut = await rawOf(await sharp2(plateBytes).extract(region).toBuffer(), work);
|
|
2650
|
+
return { upscale, work, frame, renderCut, cutFrame: cropRaw(renderCut, frame) };
|
|
2651
|
+
}
|
|
2652
|
+
function slotOnWork(rect, frame, work) {
|
|
2653
|
+
return {
|
|
2654
|
+
x0: (frame.x + rect.x) / work.width,
|
|
2655
|
+
y0: (frame.y + rect.y) / work.height,
|
|
2656
|
+
x1: (frame.x + rect.x + rect.width) / work.width,
|
|
2657
|
+
y1: (frame.y + rect.y + rect.height) / work.height
|
|
2658
|
+
};
|
|
2659
|
+
}
|
|
2660
|
+
var LOGO_AVOIDS = /* @__PURE__ */ new Set(["person", "face", "product", "animal"]);
|
|
2661
|
+
var PLAIN_GROUND_SPREAD = 18;
|
|
2662
|
+
function sizeLogoSlot(params, frame, work, subjects, picture) {
|
|
2663
|
+
if (!params.logo_slot) return void 0;
|
|
2664
|
+
const avoid = subjects.filter((s) => LOGO_AVOIDS.has(s.kind)).map((s) => ({
|
|
2665
|
+
x: Math.round(s.x0 * work.width - frame.x),
|
|
2666
|
+
y: Math.round(s.y0 * work.height - frame.y),
|
|
2667
|
+
width: Math.round((s.x1 - s.x0) * work.width),
|
|
2668
|
+
height: Math.round((s.y1 - s.y0) * work.height)
|
|
2669
|
+
}));
|
|
2670
|
+
const size = { width: frame.width, height: frame.height };
|
|
2671
|
+
const safe = blockingArea(params.format, params.placements);
|
|
2672
|
+
const shape = {
|
|
2673
|
+
aspect: params.logo_slot.aspect,
|
|
2674
|
+
...params.logo_slot.position ? { position: params.logo_slot.position } : {}
|
|
2675
|
+
};
|
|
2676
|
+
const spot = chooseLogoSpot(size, safe, {
|
|
2677
|
+
...shape,
|
|
2678
|
+
subjects: avoid,
|
|
2679
|
+
...picture ? {
|
|
2680
|
+
calm: (r) => spreadUnder(picture, r) <= PLAIN_GROUND_SPREAD,
|
|
2681
|
+
crossesEdge: (r) => straightEdgeIn(picture, r)
|
|
2682
|
+
} : {}
|
|
2683
|
+
});
|
|
2684
|
+
return spot?.slot ?? designerSpots(size, safe, shape)[0];
|
|
2685
|
+
}
|
|
2686
|
+
async function setWords(inputs, params, run, shown, again) {
|
|
2687
|
+
const callParams = wordsCallParams(params.words, shown.ratio);
|
|
2688
|
+
const prompt = [
|
|
2689
|
+
callParams.prompt,
|
|
2690
|
+
wordsAvoid(shown.faces),
|
|
2691
|
+
wordsFrame(shown.frame, shown.work, params.format),
|
|
2692
|
+
shown.logo ? logoSlotLine(slotOnWork(shown.logo.clear, shown.frame, shown.work), shown.logo.position) : "",
|
|
2693
|
+
again
|
|
2694
|
+
].filter(Boolean).join("\n\n");
|
|
2695
|
+
const references = [
|
|
2696
|
+
...inputs.previous && params.words.edit ? [inputs.previous] : [],
|
|
2697
|
+
shown.cut,
|
|
2698
|
+
...[inputs.logo, inputs.type, inputs.style].filter((r) => r !== void 0),
|
|
2699
|
+
...inputs.refs ?? []
|
|
2700
|
+
];
|
|
2701
|
+
const call = { ...callParams, prompt };
|
|
2702
|
+
return await timedStep(
|
|
2703
|
+
run,
|
|
2704
|
+
again ? "words_again" : "words",
|
|
2705
|
+
{ params: call, references: references.map((r) => r.sha256) },
|
|
2706
|
+
async (suffix, stepCtx) => {
|
|
2707
|
+
const out = await callBackendExec({
|
|
2708
|
+
nodeType: imageGenerateNode.id,
|
|
2709
|
+
nodeVersion: imageGenerateNode.version,
|
|
2710
|
+
params: imageGenerateNode.params.parse(call),
|
|
2711
|
+
inputs: { reference: references },
|
|
2712
|
+
outputKinds: { images: "image" },
|
|
2713
|
+
ctx: stepCtx,
|
|
2714
|
+
idempotencySuffix: suffix
|
|
2715
|
+
});
|
|
2716
|
+
const first = Array.isArray(out.images) ? out.images[0] : void 0;
|
|
2717
|
+
if (!first) throw new Error("static_format: the words call returned no picture");
|
|
2718
|
+
return first;
|
|
2719
|
+
}
|
|
2720
|
+
);
|
|
2721
|
+
}
|
|
2722
|
+
function wordsRead(reading, params) {
|
|
2723
|
+
if (reading.status === "read") return splitWordBoxes(reading.boxes, params.copy ?? [], params.in_scene ?? []);
|
|
2724
|
+
return { designed: [{ text: "", kind: "text", x0: 0, y0: 0, x1: 1, y1: 1 }], inScene: [] };
|
|
2725
|
+
}
|
|
2726
|
+
function liftWords(render, framing, words, subjects, params, keepOut = []) {
|
|
2727
|
+
const faces = subjects.filter((b) => b.kind === "face");
|
|
2728
|
+
const fit = registerToSource(render, framing.renderCut, words.read ? words.designed : []);
|
|
2729
|
+
const misaligned = fit.residual > MISALIGNED;
|
|
2730
|
+
const aligned = misaligned ? render : warpToCut(render, fit);
|
|
2731
|
+
const { layer, reverted } = wordsLayer(aligned, framing.renderCut, words.designed, {
|
|
2732
|
+
subjects,
|
|
2733
|
+
keepOut: words.inScene,
|
|
2734
|
+
boxesOnly: misaligned
|
|
2735
|
+
});
|
|
2736
|
+
const sized = cropLayer(layer, framing.frame);
|
|
2737
|
+
const inFrame = (b) => toFrame(b, framing.frame, framing.work);
|
|
2738
|
+
const frameFaces = faces.map(inFrame).filter(visible);
|
|
2739
|
+
const frameWords = words.designed.map(inFrame).filter(visible);
|
|
2740
|
+
const plan = words.read ? planWordsShift(frameWords, params.format, {
|
|
2741
|
+
...params.placements ? { placements: params.placements } : {},
|
|
2742
|
+
...params.band_min_scale !== void 0 ? { minScale: params.band_min_scale } : {},
|
|
2743
|
+
// A move never takes words into the slot kept for the logo, nor is made for it: moving a block
|
|
2744
|
+
// out of it cut its band through the letters (Cubicup 4:5, round 6); the logo goes elsewhere.
|
|
2745
|
+
faces: frameFaces,
|
|
2746
|
+
keepOut
|
|
2747
|
+
}) : { moves: [] };
|
|
2748
|
+
const { layer: placed2, covered } = protectFaces(
|
|
2749
|
+
plan.moves.length > 0 ? moveLayer(sized, plan.moves) : sized,
|
|
2750
|
+
frameFaces
|
|
2751
|
+
);
|
|
2752
|
+
const hidden = coveredSubjects(placed2, subjects.map(inFrame).filter(visible));
|
|
2753
|
+
const reason = (words.read ? void 0 : "words_not_read") ?? plan.reason ?? (misaligned ? "words_misaligned" : void 0) ?? (covered > 0 ? "words_over_face" : void 0) ?? (hidden.length > 0 ? "subject_covered" : void 0);
|
|
2754
|
+
return {
|
|
2755
|
+
out: compose(framing.cutFrame, placed2),
|
|
2756
|
+
alpha: placed2.alpha,
|
|
2757
|
+
moves: plan.moves,
|
|
2758
|
+
residual: fit.residual,
|
|
2759
|
+
reverted,
|
|
2760
|
+
covered: hidden,
|
|
2761
|
+
...reason ? { reason } : {}
|
|
2762
|
+
};
|
|
2763
|
+
}
|
|
2764
|
+
async function alphaPng(alpha, width, height) {
|
|
2765
|
+
return await sharp2(Buffer.from(alpha.map((a) => Math.round(a * 255))), { raw: { width, height, channels: 1 } }).png().toBuffer();
|
|
2766
|
+
}
|
|
2767
|
+
var round3 = (v) => Math.round(v * 1e3) / 1e3;
|
|
2768
|
+
var round1 = (v) => Math.round(v * 10) / 10;
|
|
2769
|
+
function liftedFacts(base, lifted, run) {
|
|
2770
|
+
const reason = lifted.reason ?? (run.subjectsRead ? void 0 : "not_read");
|
|
2771
|
+
return {
|
|
2772
|
+
...base,
|
|
2773
|
+
...reason ? { reason } : {},
|
|
2774
|
+
...lifted.covered.length > 0 ? { covered: lifted.covered } : {},
|
|
2775
|
+
moves: lifted.moves.map(({ fit }) => ({ scale: round3(fit.scale), dx: round3(fit.dx), dy: round3(fit.dy) })),
|
|
2776
|
+
residual: round1(lifted.residual),
|
|
2777
|
+
reverted: round3(lifted.reverted),
|
|
2778
|
+
identity: run.identity,
|
|
2779
|
+
steps: run.steps
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
async function wordsTry(inputs, params, run, shown, again) {
|
|
2783
|
+
const ref = await setWords(inputs, params, run, shown, again);
|
|
2784
|
+
const { bytes } = await imageOf(ref, "static_format");
|
|
2785
|
+
const reading = await timedStep(
|
|
2786
|
+
run,
|
|
2787
|
+
"boxes",
|
|
2788
|
+
{ render: ref.sha256 },
|
|
2789
|
+
() => readTextBoxes(bytes, { onSpend: (u) => run.usage.push(u) }),
|
|
2790
|
+
{ keep: isRead }
|
|
2791
|
+
);
|
|
2792
|
+
return { ref, render: await rawOf(bytes, run.framing.work), reading };
|
|
2793
|
+
}
|
|
2794
|
+
function takeOf(t, run, subjects, params) {
|
|
2795
|
+
const { framing } = run;
|
|
2796
|
+
return takeWhole({
|
|
2797
|
+
render: t.render,
|
|
2798
|
+
cut: framing.renderCut,
|
|
2799
|
+
frame: framing.frame,
|
|
2800
|
+
words: t.reading.status === "read" ? splitWordBoxes(t.reading.boxes, params.copy ?? [], params.in_scene ?? []) : null,
|
|
2801
|
+
subjects,
|
|
2802
|
+
format: params.format,
|
|
2803
|
+
...params.placements ? { placements: params.placements } : {},
|
|
2804
|
+
...params.band_min_scale !== void 0 ? { minScale: params.band_min_scale } : {},
|
|
2805
|
+
...run.keepOut.length > 0 ? { keepOut: run.keepOut } : {}
|
|
2806
|
+
});
|
|
2807
|
+
}
|
|
2808
|
+
var quoted = (what) => what.map((w) => `"${w}"`).join(", ");
|
|
2809
|
+
function setAgain(problem, what) {
|
|
2810
|
+
const said = {
|
|
2811
|
+
picture_moved: "Your last version moved or resized the picture to make room for the words. Keep Image 1 exactly where it is, at its size and framing; lay any band or card over its edge instead.",
|
|
2812
|
+
subject_redrawn: `Your last version drew ${what.join(" and ") || "a person"} again, elsewhere or in another pose. Keep them exactly as Image 1 shows them, where they are, and set the words around them.`,
|
|
2813
|
+
words_lost: `Your last version set ${quoted(what) || "words"} where this size is cut, the app's buttons cover them or the logo goes. Keep every word and the button inside the zones and out of the place kept plain for the logo.`,
|
|
2814
|
+
words_over_face: "Your last version set words over a face. Keep every word, the logo and the button off every face."
|
|
2815
|
+
};
|
|
2816
|
+
return said[problem];
|
|
2817
|
+
}
|
|
2818
|
+
var MISPLACED = {
|
|
2819
|
+
words_lost: "band_too_far",
|
|
2820
|
+
words_over_face: "words_over_face"
|
|
2821
|
+
};
|
|
2822
|
+
async function wholeSize(take2, t, run, base, why = {}) {
|
|
2823
|
+
const { retried } = why;
|
|
2824
|
+
const image = await run.ctx.assets.ingestBytes({
|
|
2825
|
+
bytes: await pngOf(take2.out),
|
|
2826
|
+
kind: "image",
|
|
2827
|
+
mime: "image/png"
|
|
2828
|
+
});
|
|
2829
|
+
const reason = (t.reading.status === "read" ? void 0 : "words_not_read") ?? (why.misplaced ? MISPLACED[why.misplaced] : void 0) ?? (take2.covered.length > 0 ? "subject_covered" : void 0) ?? (run.subjectsRead ? void 0 : "not_read");
|
|
2830
|
+
const facts = {
|
|
2831
|
+
...base,
|
|
2832
|
+
...reason ? { reason } : {},
|
|
2833
|
+
...take2.covered.length > 0 ? { covered: take2.covered } : {},
|
|
2834
|
+
words_mode: "whole",
|
|
2835
|
+
kept: round3(take2.kept),
|
|
2836
|
+
...take2.restored.length > 0 ? { restored: take2.restored } : {},
|
|
2837
|
+
...retried ? { retried } : {},
|
|
2838
|
+
moves: take2.moves.map(({ fit }) => ({ scale: round3(fit.scale), dx: round3(fit.dx), dy: round3(fit.dy) })),
|
|
2839
|
+
residual: round1(take2.residual),
|
|
2840
|
+
reverted: 0,
|
|
2841
|
+
steps: run.steps
|
|
2842
|
+
};
|
|
2843
|
+
run.ctx.log(
|
|
2844
|
+
`${base.format}: cut ${base.crop.width}x${base.crop.height} (x${base.upscale}), words whole${take2.moves.length > 0 ? ", moved" : ""}${take2.restored.length > 0 ? `, ${take2.restored.join(", ")} put back` : ""}${retried ? ` (set again: ${retried})` : ""}${reason ? `, ${reason}` : ""}`
|
|
2845
|
+
);
|
|
2846
|
+
return { image, cut: run.cut, words_raw: t.ref, facts };
|
|
2847
|
+
}
|
|
2848
|
+
async function maskedSize(t, run, base, subjects, params, why) {
|
|
2849
|
+
const { framing } = run;
|
|
2850
|
+
const lifted = liftWords(
|
|
2851
|
+
t.render,
|
|
2852
|
+
framing,
|
|
2853
|
+
{ ...wordsRead(t.reading, params), read: t.reading.status === "read" },
|
|
2854
|
+
subjects,
|
|
2855
|
+
params,
|
|
2856
|
+
run.keepOut
|
|
2857
|
+
);
|
|
2858
|
+
const identity = identityOutside(lifted.out, framing.cutFrame, lifted.alpha);
|
|
2859
|
+
if (identity !== 0) throw new Error(`static_format: the picture outside the words changed (${identity})`);
|
|
2860
|
+
const [image, alpha] = await Promise.all([
|
|
2861
|
+
run.ctx.assets.ingestBytes({ bytes: await pngOf(lifted.out), kind: "image", mime: "image/png" }),
|
|
2862
|
+
run.ctx.assets.ingestBytes({
|
|
2863
|
+
bytes: await alphaPng(lifted.alpha, framing.frame.width, framing.frame.height),
|
|
2864
|
+
kind: "image",
|
|
2865
|
+
mime: "image/png"
|
|
2866
|
+
})
|
|
2867
|
+
]);
|
|
2868
|
+
const facts = {
|
|
2869
|
+
...liftedFacts(base, lifted, { identity, steps: run.steps, subjectsRead: run.subjectsRead }),
|
|
2870
|
+
words_mode: "masked",
|
|
2871
|
+
retried: why.retried,
|
|
2872
|
+
refused: why.refused
|
|
2873
|
+
};
|
|
2874
|
+
run.ctx.log(
|
|
2875
|
+
`${base.format}: cut ${base.crop.width}x${base.crop.height} (x${base.upscale}), words set twice (${why.retried}, then ${why.refused}), only the words kept${lifted.moves.length > 0 ? ", moved" : ""}${facts.reason ? `, ${facts.reason}` : ""}`
|
|
2876
|
+
);
|
|
2877
|
+
return { image, cut: run.cut, words_raw: t.ref, words_alpha: alpha, facts };
|
|
2878
|
+
}
|
|
2879
|
+
async function formatSize(inputs, params, ctx) {
|
|
2880
|
+
const { bytes: plateBytes, size: plate } = await imageOf(inputs.plate, "static_format");
|
|
2881
|
+
const steps = [];
|
|
2882
|
+
const usage = [];
|
|
2883
|
+
const spend = () => usage.length > 0 ? { usage } : {};
|
|
2884
|
+
const subjects = inputs.subjects ?? await subjectsStep({ ctx, steps, usage }, inputs.plate, plateBytes);
|
|
2885
|
+
const ratios = supportedAspectRatios("image_generate", params.words.model);
|
|
2886
|
+
const panels = platePanels(await rawOf(plateBytes, plate));
|
|
2887
|
+
const crop = subjectCrop(plate, params.format, subjects, {
|
|
2888
|
+
...params.core ? { core: params.core } : {},
|
|
2889
|
+
...ratios ? { renderRatios: ratios } : {},
|
|
2890
|
+
...panels.length > 0 ? { panels } : {}
|
|
2891
|
+
});
|
|
2892
|
+
const framing = await frameSize(plateBytes, crop, params.format);
|
|
2893
|
+
const cutRef = await ctx.assets.ingestBytes({
|
|
2894
|
+
bytes: await pngOf(framing.cutFrame),
|
|
2895
|
+
kind: "image",
|
|
2896
|
+
mime: "image/png"
|
|
2897
|
+
});
|
|
2898
|
+
const base = {
|
|
2899
|
+
format: params.format,
|
|
2900
|
+
lead: params.lead ?? false,
|
|
2901
|
+
plate,
|
|
2902
|
+
crop: crop.rect,
|
|
2903
|
+
render_ratio: crop.render.ratio,
|
|
2904
|
+
upscale: round3(framing.upscale)
|
|
2905
|
+
};
|
|
2906
|
+
const shownSubjects = (subjects ?? []).map((s) => subjectIn(s, crop.render, plate)).filter(visible);
|
|
2907
|
+
const logo = sizeLogoSlot(params, framing.frame, framing.work, shownSubjects, greyTable(framing.cutFrame));
|
|
2908
|
+
const slotOut = logo ? { logo_slot: logo.rect } : {};
|
|
2909
|
+
const elsewhere = (params.check_formats ?? []).filter((f) => f !== params.format).map((f) => ({ format: f, crop: subjectCrop(plate, f, subjects, params.core ? { core: params.core } : {}) })).find((c) => !c.crop.fits);
|
|
2910
|
+
if (!crop.fits || elsewhere) {
|
|
2911
|
+
const lost = crop.fits && elsewhere ? `${elsewhere.format}: ${elsewhere.crop.cut.join(", ")}` : crop.cut.join(", ");
|
|
2912
|
+
ctx.log(`${params.format}: no cut keeps ${lost} whole; the words were not set`);
|
|
2913
|
+
const facts = { ...base, reason: "subject_cut", moves: [], reverted: 0, identity: 0, steps };
|
|
2914
|
+
return { image: cutRef, cut: cutRef, facts, ...slotOut, ...spend() };
|
|
2915
|
+
}
|
|
2916
|
+
const shownCut = await ctx.assets.ingestBytes({
|
|
2917
|
+
bytes: await pngOf(framing.renderCut),
|
|
2918
|
+
kind: "image",
|
|
2919
|
+
mime: "image/png"
|
|
2920
|
+
});
|
|
2921
|
+
const keepOut = logo ? [
|
|
2922
|
+
{
|
|
2923
|
+
x0: logo.clear.x / framing.frame.width,
|
|
2924
|
+
y0: logo.clear.y / framing.frame.height,
|
|
2925
|
+
x1: (logo.clear.x + logo.clear.width) / framing.frame.width,
|
|
2926
|
+
y1: (logo.clear.y + logo.clear.height) / framing.frame.height
|
|
2927
|
+
}
|
|
2928
|
+
] : [];
|
|
2929
|
+
const run = { ctx, steps, usage, subjectsRead: subjects !== null, cut: cutRef, framing, keepOut };
|
|
2930
|
+
const shown = {
|
|
2931
|
+
cut: shownCut,
|
|
2932
|
+
ratio: crop.render.ratio,
|
|
2933
|
+
faces: shownSubjects.filter((s) => s.kind === "face"),
|
|
2934
|
+
frame: framing.frame,
|
|
2935
|
+
work: framing.work,
|
|
2936
|
+
...logo ? { logo } : {}
|
|
2937
|
+
};
|
|
2938
|
+
return { ...await letter({ inputs, params, run, shown, base, subjects: shownSubjects }), ...slotOut, ...spend() };
|
|
2939
|
+
}
|
|
2940
|
+
async function letter(l) {
|
|
2941
|
+
const { inputs, params, run, shown, base, subjects } = l;
|
|
2942
|
+
const first = await wordsTry(inputs, params, run, shown);
|
|
2943
|
+
const firstTake = takeOf(first, run, subjects, params);
|
|
2944
|
+
if (firstTake.ok) return await wholeSize(firstTake, first, run, base);
|
|
2945
|
+
const second = await wordsTry(inputs, params, run, shown, setAgain(firstTake.problem, firstTake.what));
|
|
2946
|
+
const secondTake = takeOf(second, run, subjects, params);
|
|
2947
|
+
const retried = firstTake.problem;
|
|
2948
|
+
if (secondTake.ok) return await wholeSize(secondTake, second, run, base, { retried });
|
|
2949
|
+
const placed2 = [
|
|
2950
|
+
{ take: secondTake, t: second },
|
|
2951
|
+
{ take: firstTake, t: first }
|
|
2952
|
+
].find((p) => p.take.whole);
|
|
2953
|
+
const whole = placed2?.take.whole;
|
|
2954
|
+
if (placed2 && whole) {
|
|
2955
|
+
const taken = { ...whole, moves: [], kept: placed2.take.kept, residual: placed2.take.residual };
|
|
2956
|
+
return await wholeSize(taken, placed2.t, run, base, { retried, misplaced: placed2.take.problem });
|
|
2957
|
+
}
|
|
2958
|
+
const kept = secondTake.kept >= firstTake.kept ? second : first;
|
|
2959
|
+
return await maskedSize(kept, run, base, subjects, params, { retried, refused: secondTake.problem });
|
|
2960
|
+
}
|
|
2961
|
+
|
|
2962
|
+
// src/engine/nodes/local/lib/size-consistency.ts
|
|
2963
|
+
import sharp3 from "sharp";
|
|
2964
|
+
import { z as z4 } from "zod";
|
|
2965
|
+
var SHOWN_AREA = 0.01;
|
|
2966
|
+
var SEEN_AREA = SHOWN_AREA / 3;
|
|
2967
|
+
var SAME_BOX = 0.3;
|
|
2968
|
+
var COUNTED = [
|
|
2969
|
+
{ kind: "person", name: "people" },
|
|
2970
|
+
{ kind: "face", name: "faces" },
|
|
2971
|
+
{ kind: "animal", name: "animals" }
|
|
2972
|
+
];
|
|
2973
|
+
var area = (b) => Math.max(0, b.x1 - b.x0) * Math.max(0, b.y1 - b.y0);
|
|
2974
|
+
function overlap2(a, b) {
|
|
2975
|
+
const ix = Math.max(0, Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0));
|
|
2976
|
+
const iy = Math.max(0, Math.min(a.y1, b.y1) - Math.max(a.y0, b.y0));
|
|
2977
|
+
const union = area(a) + area(b) - ix * iy;
|
|
2978
|
+
return union > 0 ? ix * iy / union : 0;
|
|
2979
|
+
}
|
|
2980
|
+
function surely(image, kind) {
|
|
2981
|
+
const [first = [], ...rest] = image.reads.map((r) => r.filter((b) => b.kind === kind));
|
|
2982
|
+
return first.filter((b) => area(b) >= SHOWN_AREA && rest.every((r) => r.some((o) => overlap2(b, o) >= SAME_BOX)));
|
|
2983
|
+
}
|
|
2984
|
+
function atMost(image, kind) {
|
|
2985
|
+
return Math.max(0, ...image.reads.map((r) => r.filter((b) => b.kind === kind && area(b) >= SEEN_AREA).length));
|
|
2986
|
+
}
|
|
2987
|
+
function boxDifferences(master, size) {
|
|
2988
|
+
return COUNTED.flatMap(({ kind, name }) => {
|
|
2989
|
+
const shown = surely(size, kind).length;
|
|
2990
|
+
const shownBefore = atMost(master, kind);
|
|
2991
|
+
if (shown > shownBefore) {
|
|
2992
|
+
return [{ kind: "added", what: `shows ${shown} ${name} where the main size shows ${shownBefore}` }];
|
|
2993
|
+
}
|
|
2994
|
+
const before = surely(master, kind).length;
|
|
2995
|
+
const now = atMost(size, kind);
|
|
2996
|
+
if (before > now) return [{ kind: "missing", what: `shows ${now} ${name} where the main size shows ${before}` }];
|
|
2997
|
+
return [];
|
|
2998
|
+
});
|
|
2999
|
+
}
|
|
3000
|
+
var PAINTED = 0.6;
|
|
3001
|
+
function paintedSubjects(plate, paintedShare) {
|
|
3002
|
+
const words = (label) => label.toLowerCase().match(new RegExp("\\p{L}{3,}", "gu")) ?? [];
|
|
3003
|
+
const keptProducts = new Set(
|
|
3004
|
+
surely(plate, "product").filter((b) => paintedShare(b) < PAINTED).flatMap((b) => words(b.label))
|
|
3005
|
+
);
|
|
3006
|
+
return ["person", "face", "animal", "product"].flatMap(
|
|
3007
|
+
(kind) => surely(plate, kind).filter((b) => paintedShare(b) >= PAINTED).filter((b) => kind !== "product" || words(b.label).some((w) => keptProducts.has(w))).map((b) => b.label)
|
|
3008
|
+
);
|
|
3009
|
+
}
|
|
3010
|
+
var SIZE_MATCH_PROMPT = [
|
|
3011
|
+
"Image 1 is the main size of one static ad. Image 2 is the same ad made in another size. Image 2 may show more or less of the scene and lay the words out differently: that is expected and never a finding. Compare only the people, animals and products the two pictures show:",
|
|
3012
|
+
"- people: Image 2 shows a different number of the ad's people than Image 1, or a different person where Image 1 has one (another face, age, gender or clothing).",
|
|
3013
|
+
"- product: the product the ad is about (the thing sold or shown in use) is a different object in Image 2 (another model, shape, colour or label), or is missing from it.",
|
|
3014
|
+
"- duplicated: Image 2 shows the same person, animal or product twice where Image 1 shows it once.",
|
|
3015
|
+
"- stretched: a person, face or product in Image 2 is visibly stretched or squashed compared with Image 1 (wider or taller than it is).",
|
|
3016
|
+
"- framed: Image 2 holds Image 1's picture as a smaller rectangle inside a bigger frame, with a visible edge, border or seam around it.",
|
|
3017
|
+
"Someone in the far background, a crowd, and a prop a bigger frame shows more of are never findings. Say only what you see clearly at phone size; when unsure, it is the same.",
|
|
3018
|
+
'Reply with only this JSON: {"people":"same|different","product":"same|different|missing|none","duplicated":"<what is shown twice>|null","stretched":"<who or what>|null","framed":true|false,"what":"<one short sentence naming what differs, or empty>"}'
|
|
3019
|
+
].join("\n");
|
|
3020
|
+
var SizeMatchAnswer = z4.object({
|
|
3021
|
+
people: z4.enum(["same", "different"]),
|
|
3022
|
+
product: z4.enum(["same", "different", "missing", "none"]),
|
|
3023
|
+
duplicated: z4.string().nullable().optional(),
|
|
3024
|
+
stretched: z4.string().nullable().optional(),
|
|
3025
|
+
framed: z4.boolean()
|
|
3026
|
+
});
|
|
3027
|
+
var named = (text) => {
|
|
3028
|
+
const t = text?.trim();
|
|
3029
|
+
return t && t.toLowerCase() !== "null" ? t : null;
|
|
3030
|
+
};
|
|
3031
|
+
function sizeMatchFromAnswer(answer) {
|
|
3032
|
+
const parsed = SizeMatchAnswer.safeParse(answer);
|
|
3033
|
+
if (!parsed.success) return null;
|
|
3034
|
+
const a = parsed.data;
|
|
3035
|
+
const twice = named(a.duplicated);
|
|
3036
|
+
const stretched = named(a.stretched);
|
|
3037
|
+
return [
|
|
3038
|
+
...a.people === "different" ? [{ kind: "other_people", what: "shows other people than the main size" }] : [],
|
|
3039
|
+
...a.product === "different" ? [{ kind: "other_product", what: "shows another product than the main size" }] : a.product === "missing" ? [{ kind: "no_product", what: "no longer shows the product the main size shows" }] : [],
|
|
3040
|
+
...twice ? [{ kind: "duplicated", what: `shows ${twice} twice` }] : [],
|
|
3041
|
+
...stretched ? [{ kind: "stretched", what: `shows ${stretched} stretched or squashed` }] : [],
|
|
3042
|
+
...a.framed ? [{ kind: "framed", what: "shows the main size's picture boxed inside a bigger frame" }] : []
|
|
3043
|
+
];
|
|
3044
|
+
}
|
|
3045
|
+
var READS = 2;
|
|
3046
|
+
var MATCH_EDGE = 1024;
|
|
3047
|
+
async function readTwice(bytes, onSpend) {
|
|
3048
|
+
const meta = await sharp3(bytes).metadata();
|
|
3049
|
+
const reads = await Promise.all(Array.from({ length: READS }, () => readSubjectBoxes(bytes, { onSpend })));
|
|
3050
|
+
const boxes = reads.flatMap((r) => r.status === "read" ? [r.boxes] : []);
|
|
3051
|
+
return boxes.length === READS ? { size: { width: meta.width ?? 0, height: meta.height ?? 0 }, reads: boxes } : null;
|
|
3052
|
+
}
|
|
3053
|
+
var matchJpeg = async (bytes) => (await sharp3(bytes).resize(MATCH_EDGE, MATCH_EDGE, { fit: "inside", withoutEnlargement: true }).jpeg({ quality: 88 }).toBuffer()).toString("base64");
|
|
3054
|
+
var unique2 = (diffs) => diffs.filter((d, i) => diffs.findIndex((o) => o.what === d.what) === i);
|
|
3055
|
+
async function compareSizes(master, sizes, opts = {}) {
|
|
3056
|
+
const masterBytes = await bytesOf(master.path);
|
|
3057
|
+
const [masterReads, masterJpeg] = await Promise.all([readTwice(masterBytes, opts.onSpend), matchJpeg(masterBytes)]);
|
|
3058
|
+
return await Promise.all(
|
|
3059
|
+
sizes.map(async (size) => {
|
|
3060
|
+
const bytes = await bytesOf(size.path);
|
|
3061
|
+
const [reads, answer] = await Promise.all([
|
|
3062
|
+
readTwice(bytes, opts.onSpend),
|
|
3063
|
+
matchJpeg(bytes).then(
|
|
3064
|
+
(jpeg) => askAboutImages(SIZE_MATCH_MODEL, [masterJpeg, jpeg], SIZE_MATCH_PROMPT, opts.onSpend, 6e4, {
|
|
3065
|
+
effort: "low"
|
|
3066
|
+
})
|
|
3067
|
+
)
|
|
3068
|
+
]);
|
|
3069
|
+
const boxed = masterReads && reads ? boxDifferences(masterReads, reads) : null;
|
|
3070
|
+
const seen = sizeMatchFromAnswer(answer);
|
|
3071
|
+
return {
|
|
3072
|
+
format: size.format,
|
|
3073
|
+
compared: boxed !== null || seen !== null,
|
|
3074
|
+
differences: unique2([...boxed ?? [], ...seen ?? []])
|
|
3075
|
+
};
|
|
3076
|
+
})
|
|
3077
|
+
);
|
|
3078
|
+
}
|
|
3079
|
+
function sizeDifferenceFinding(format, differences) {
|
|
3080
|
+
const missing = differences.some((d) => d.kind === "missing" || d.kind === "no_product");
|
|
3081
|
+
return {
|
|
3082
|
+
severity: "blocking",
|
|
3083
|
+
what: `${format}: ${differences.map((d) => d.what).join("; ")}. It must show the main size's people and product, once each, at their own proportions.`,
|
|
3084
|
+
kind: { item: "sizes", element: "picture", defect: missing ? "missing" : "other", edges: [] }
|
|
3085
|
+
};
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3088
|
+
export {
|
|
3089
|
+
paintedSubjects,
|
|
3090
|
+
readTwice,
|
|
3091
|
+
compareSizes,
|
|
3092
|
+
sizeDifferenceFinding,
|
|
3093
|
+
registryParamShape,
|
|
3094
|
+
imageGenerateNode,
|
|
3095
|
+
subjectCrop,
|
|
3096
|
+
boxesToPlace,
|
|
3097
|
+
planSafeFit,
|
|
3098
|
+
plainEdge,
|
|
3099
|
+
minFitScale,
|
|
3100
|
+
fitPicture,
|
|
3101
|
+
registerToSource,
|
|
3102
|
+
warpToCut,
|
|
3103
|
+
MISALIGNED,
|
|
3104
|
+
staticFormatNode,
|
|
3105
|
+
splitWordBoxes
|
|
3106
|
+
};
|
|
3107
|
+
//# sourceMappingURL=chunk-JGSEHX2Q.js.map
|