ghost 6.44.0 → 6.44.1
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/core/boot.js +9 -13
- package/core/bridge.js +6 -10
- package/core/built/admin/assets/{PolarAngleAxis-eFuSrR7S.js → PolarAngleAxis-DWP6qq-Z.js} +2 -2
- package/core/built/admin/assets/{_baseAssignValue-XVHfKew7.js → _baseAssignValue-N9f4o_XK.js} +1 -1
- package/core/built/admin/assets/{a-large-small-DOzPDzKp.js → a-large-small-BOAtcFiE.js} +1 -1
- package/core/built/admin/assets/{account-migration-Cx45M5qm.js → account-migration-CtZx_5ib.js} +1 -1
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
- package/core/built/admin/assets/admin-x-settings/{code-editor-view-Bi8Orhyj.mjs → code-editor-view-BMovCjer.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-1_V9g9Pt.mjs → index-BT1n-g2b.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-e9saYQJa.mjs → index-BnowNBGd.mjs} +5 -5
- package/core/built/admin/assets/admin-x-settings/{index-CnvQi01U.mjs → index-CRpK6gF8.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-BmU6BOfy.mjs → index-CfXS3AZ8.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-EuMiBt6I.mjs → index-Cs8zML6u.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-B43MPc5u.mjs → index-DmpwO1w3.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-DOgG0XZa.mjs → index-DwFIdhcR.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-CWdxMIcZ.mjs → index-sNyPiIJA.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-Ojg_pBvq.mjs → index-xTILut54.mjs} +1259 -1259
- package/core/built/admin/assets/admin-x-settings/{modals-Ckbx9UQF.mjs → modals-Cm5t13os.mjs} +9 -9
- package/core/built/admin/assets/{arrow-right-DckEQtp9.js → arrow-right-BxdHN_En.js} +1 -1
- package/core/built/admin/assets/{at-sign-BChf68aS.js → at-sign-Cajf-dOf.js} +1 -1
- package/core/built/admin/assets/{audience-BYU5Bd7D.js → audience-CHNb9mCT.js} +1 -1
- package/core/built/admin/assets/{automated-email-design-Z26Qit0_.js → automated-email-design-B9C9mKUS.js} +2 -2
- package/core/built/admin/assets/{automated-emails-aBicreLv.js → automated-emails-DhLhkq8L.js} +1 -1
- package/core/built/admin/assets/{automations-vpH-d72N.js → automations-6-cgZovk.js} +1 -1
- package/core/built/admin/assets/{automations-Ddo22yPk.js → automations-CxJ-N_YK.js} +1 -1
- package/core/built/admin/assets/{avatar-flipboard-CoI3LQ-o.js → avatar-flipboard-f5nSMmek.js} +1 -1
- package/core/built/admin/assets/{bluesky-sharing-iVDkCMKN.js → bluesky-sharing-Dm2k8qZH.js} +1 -1
- package/core/built/admin/assets/{chart-CjM1VQqH.js → chart-BbJnjWey.js} +23 -23
- package/core/built/admin/assets/{checkbox-CC5kd_Kf.js → checkbox-CT7DNFAI.js} +1 -1
- package/core/built/admin/assets/{chevron-up-D__wzyXT.js → chevron-up-BxijmTT9.js} +1 -1
- package/core/built/admin/assets/{chunk.696.79505fa556d329d6e824.js → chunk.167.37bb0d7f6ac67fefa679.js} +3184 -3523
- package/core/built/admin/assets/{chunk.696.79505fa556d329d6e824.js.LICENSE.txt → chunk.167.37bb0d7f6ac67fefa679.js.LICENSE.txt} +1 -1
- package/core/built/admin/assets/{chunk.524.1ff649a6cc62dc38f538.js → chunk.524.ed812b62217210a913d4.js} +5 -5
- package/core/built/admin/assets/{chunk.582.408a40e0095e479e3d11.js → chunk.582.7db5c9f17bca5a484049.js} +6 -6
- package/core/built/admin/assets/{chunk.945.835812fcb16029abd7f9.js → chunk.834.f9db7c62b9457db93e8c.js} +3 -3
- package/core/built/admin/assets/{code-editor-view-C735d5EA.js → code-editor-view-D8slE0IA.js} +1 -1
- package/core/built/admin/assets/{comments-DgFPax3Y.js → comments-BvfR-fA8.js} +1 -1
- package/core/built/admin/assets/{content-helpers-DjugSfvm.js → content-helpers-DUWGLvgL.js} +1 -1
- package/core/built/admin/assets/{copy-D9JONGcK.js → copy-ht18t5gu.js} +1 -1
- package/core/built/admin/assets/{data-list-QWLEHG4y.js → data-list-Daha2dIs.js} +1 -1
- package/core/built/admin/assets/{deleted-feed-item-CwSCflTW.js → deleted-feed-item-ChP5bwgi.js} +1 -1
- package/core/built/admin/assets/{dropzone-lK_4vpWS.js → dropzone-h_qyk514.js} +1 -1
- package/core/built/admin/assets/{edit-profile-BmioJZHv.js → edit-profile-BT8RQpAG.js} +1 -1
- package/core/built/admin/assets/editor-s1mqd9_o.js +8 -0
- package/core/built/admin/assets/{empty-indicator-Dg64lT_g.js → empty-indicator-BIUvv6JE.js} +1 -1
- package/core/built/admin/assets/{en-DCwBNJ98.js → en-BEcDl42w.js} +1 -1
- package/core/built/admin/assets/{eye-psLxWnjO.js → eye-TPnIdamu.js} +1 -1
- package/core/built/admin/assets/{feed-TUcCSZHL.js → feed-BK3qvLWi.js} +1 -1
- package/core/built/admin/assets/{field-Uk8NOvtc.js → field-CSFsrvVy.js} +1 -1
- package/core/built/admin/assets/{filter-query-core-CbH_VKcG.js → filter-query-core-R8cQCO2w.js} +1 -1
- package/core/built/admin/assets/{filters-DmawZ5Uu.js → filters-Cp1voB1e.js} +1 -1
- package/core/built/admin/assets/gh-chart-BFsyOJD_.js +1 -0
- package/core/built/admin/assets/{ghost-2baa7ddc3630015f41c0efd13bd586b8.js → ghost-1881362e8a92dae1e3333a0484c173a3.js} +7 -6
- package/core/built/admin/assets/{growth-BAl-TyMy.js → growth-DIigOxF1.js} +1 -1
- package/core/built/admin/assets/{hash-Q1ou0OMZ.js → hash-B3iFVeCl.js} +1 -1
- package/core/built/admin/assets/{inbox-BAOtR6tN.js → inbox-2bPMLikt.js} +1 -1
- package/core/built/admin/assets/{index-BnJp51QE.js → index-52qUC8yv.js} +5 -5
- package/core/built/admin/assets/{index-BDIwushG.js → index-9j01Aj_X.js} +1 -1
- package/core/built/admin/assets/index-B9UVpmey.js +1 -0
- package/core/built/admin/assets/{index-DTeOW3Se.js → index-BXc5OF6x.js} +1 -1
- package/core/built/admin/assets/{index-Duc21aJ7.js → index-BaGL3IFe.js} +1 -1
- package/core/built/admin/assets/{index-DKC8uXHk.js → index-BdozZbt2.js} +2 -2
- package/core/built/admin/assets/{index-z951kI4K.js → index-Bgpz7M7i.js} +1 -1
- package/core/built/admin/assets/{index-BfSvX9is.js → index-Bp4O7TVf.js} +1 -1
- package/core/built/admin/assets/{index-C5S08C6P.js → index-BuqUmpe9.js} +1 -1
- package/core/built/admin/assets/{index-D7OtVnbo.js → index-CEF_Ofn0.js} +1 -1
- package/core/built/admin/assets/{index-Bs6rUYFS.js → index-CgSVv5Up.js} +58 -58
- package/core/built/admin/assets/{index-Ro9qXetv.js → index-Cr6x2czK.js} +1 -1
- package/core/built/admin/assets/{index-DJbgQjV6.js → index-CrbZj3Ju.js} +1 -1
- package/core/built/admin/assets/{index-BTBcWw_z.js → index-CrlAPDdD.js} +2 -2
- package/core/built/admin/assets/{index-B6SD2Qs-.js → index-CtrmMGWT.js} +1 -1
- package/core/built/admin/assets/{index-Bw0oyOFd.js → index-D-V_DAdt.js} +1 -1
- package/core/built/admin/assets/{index-DAJduTBl.js → index-D0poOSjw.js} +4 -4
- package/core/built/admin/assets/{index-CGT3W8fi.js → index-DWVGCPEC.js} +3 -3
- package/core/built/admin/assets/index-Dozbr_4s.css +1 -0
- package/core/built/admin/assets/{index-FyplpnYQ.js → index-S3Ai3lDy.js} +1 -1
- package/core/built/admin/assets/{index-DLr8D_Ks.js → index-VDhA5kgU.js} +1 -1
- package/core/built/admin/assets/{index-DRA1fORQ.js → index-fnIFqFMt.js} +1 -1
- package/core/built/admin/assets/{index-BhWQZObu.js → index-kA3UcdW7.js} +1 -1
- package/core/built/admin/assets/{input-group-DH32syTz.js → input-group-Fdl0S6pw.js} +1 -1
- package/core/built/admin/assets/{koenig-lexical-CxVcbgsH.js → koenig-lexical-REiYtzGD.js} +1 -1
- package/core/built/admin/assets/{kpi-card-DBWHDi3l.js → kpi-card-BS8vEj4c.js} +1 -1
- package/core/built/admin/assets/{kpi-card-BYhzWV5F.js → kpi-card-D3HEfOCP.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-Kxc-utyg.js → kpi-tabs-8vaI7yWq.js} +1 -1
- package/core/built/admin/assets/kpis-CkD0Xteg.js +1 -0
- package/core/built/admin/assets/label-DT38Gd2T.js +1 -0
- package/core/built/admin/assets/{links-Cg8O8ZGP.js → links-BK-azjCL.js} +1 -1
- package/core/built/admin/assets/{list-page-D2KCBsiy.js → list-page-DVpac3lc.js} +1 -1
- package/core/built/admin/assets/{loader-circle-nmLqhMZL.js → loader-circle-CIq5Cv-9.js} +1 -1
- package/core/built/admin/assets/{mail-D7cxYMd5.js → mail-gdeIU06V.js} +1 -1
- package/core/built/admin/assets/{main-layout-BXdUkeCo.js → main-layout-B2t-RiNE.js} +1 -1
- package/core/built/admin/assets/members-7z-tESWd.js +10 -0
- package/core/built/admin/assets/minus-BbGfVkll.js +1 -0
- package/core/built/admin/assets/{modals-VRvX8mK0.js → modals-DVIfijEz.js} +3 -3
- package/core/built/admin/assets/{moderation-DkT8qVJs.js → moderation-DwzDOhih.js} +1 -1
- package/core/built/admin/assets/{newsletter-sUT4ciRJ.js → newsletter-D1N8bUfp.js} +1 -1
- package/core/built/admin/assets/{newsletters-BNvAF2Oi.js → newsletters-7GSeQdQe.js} +1 -1
- package/core/built/admin/assets/{note-B0JhJv7s.js → note-Bn1-ZWDE.js} +1 -1
- package/core/built/admin/assets/offers-BsuLKYy9.js +1 -0
- package/core/built/admin/assets/{onboarding-route-IrO_SCb3.js → onboarding-route-C73r9kyO.js} +1 -1
- package/core/built/admin/assets/{overview-C2nk_B6i.js → overview-6U5p38zx.js} +1 -1
- package/core/built/admin/assets/{pagemenu-BGhty1iq.js → pagemenu-DrueoEX9.js} +1 -1
- package/core/built/admin/assets/{pencil-DiA3J4m5.js → pencil-Csnv8udS.js} +1 -1
- package/core/built/admin/assets/{pin-off-HWos3YHh.js → pin-off-BDeHGsSQ.js} +1 -1
- package/core/built/admin/assets/{post-analytics-context-BJwP-XAB.js → post-analytics-context-jKeUh2Ka.js} +1 -1
- package/core/built/admin/assets/{post-analytics-header-CZF5QmAD.js → post-analytics-header-C5QLn6Lm.js} +1 -1
- package/core/built/admin/assets/{post-analytics-DBUHbt1b.js → post-analytics-ngMqqbt9.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-Bb8R05dH.js → post-share-modal-04B7JT4R.js} +1 -1
- package/core/built/admin/assets/posts/{alert-dialog-mmQvJUHQ.mjs → alert-dialog-CYvHtOQ5.mjs} +4 -4
- package/core/built/admin/assets/posts/{app-utils-CD0bhOLs.mjs → app-utils-Cs-8qje1.mjs} +3 -3
- package/core/built/admin/assets/posts/{automations-BL0WaXHA.mjs → automations-DE2rwx-Z.mjs} +25 -25
- package/core/built/admin/assets/posts/{automations-BmGKngyG.mjs → automations-Dq0_cprS.mjs} +4 -4
- package/core/built/admin/assets/posts/{avatar-CeJ0Zq_A.mjs → avatar-Dt_bGEgl.mjs} +7 -7
- package/core/built/admin/assets/posts/{button-CQCNdxY6.mjs → button-DO7JrPsL.mjs} +2 -2
- package/core/built/admin/assets/posts/{chevron-up-DaikhWC2.mjs → chevron-up-B8WyJjCr.mjs} +3 -3
- package/core/built/admin/assets/posts/{comments-DUSJ25vf.mjs → comments-B3-RpqJU.mjs} +1933 -1905
- package/core/built/admin/assets/posts/{data-list-BiiYXQes.mjs → data-list-BiZFP6Co.mjs} +5 -5
- package/core/built/admin/assets/posts/{dialog-DRN6olky.mjs → dialog-Bvl2PD8s.mjs} +3 -3
- package/core/built/admin/assets/posts/{editor-DN_Zz0m2.mjs → editor-BCtdAD74.mjs} +3230 -3130
- package/core/built/admin/assets/posts/{ellipsis-BIs4PL5-.mjs → ellipsis-B5H7Hudx.mjs} +2 -2
- package/core/built/admin/assets/posts/{empty-indicator-Wiukrx4T.mjs → empty-indicator-BRoAf6Jv.mjs} +2 -2
- package/core/built/admin/assets/posts/{filters-CJl5ebXd.mjs → filters-CffYQY_8.mjs} +12 -12
- package/core/built/admin/assets/posts/{get-site-timezone-JepxGwVr.mjs → get-site-timezone-CSrPVUfX.mjs} +2 -2
- package/core/built/admin/assets/posts/{growth-cNlqbz-x.mjs → growth--LVGRPtS.mjs} +13 -13
- package/core/built/admin/assets/posts/{heading-C_V6Ckxx.mjs → heading-BRQEP7IA.mjs} +2 -2
- package/core/built/admin/assets/posts/{heart-BMBWsLs2.mjs → heart-CC2f1qWb.mjs} +2 -2
- package/core/built/admin/assets/posts/{hooks-D4pJ_p_P.mjs → hooks-J2WpDj1d.mjs} +2 -2
- package/core/built/admin/assets/posts/{index-DzWTmJMy.mjs → index-D-vhKzUJ.mjs} +3 -3
- package/core/built/admin/assets/posts/{index-CDwlVw9E.mjs → index-LnPyGojr.mjs} +2 -2
- package/core/built/admin/assets/posts/{index-BuIZkUhD.mjs → index-nxfIbREV.mjs} +11 -11
- package/core/built/admin/assets/posts/{input-DUvSHOFz.mjs → input-DTtfruk_.mjs} +3 -3
- package/core/built/admin/assets/posts/{input-surface-CO8-j6V2.mjs → input-surface-DXTGCuo2.mjs} +2 -2
- package/core/built/admin/assets/posts/{koenig-lexical-cRm7bY-6.mjs → koenig-lexical-CNcifuT7.mjs} +2 -2
- package/core/built/admin/assets/posts/{kpis-BXukzbg6.mjs → kpis-n8L4BlMi.mjs} +5843 -5854
- package/core/built/admin/assets/posts/{label-TTt0QyDb.mjs → label-yl8B8ADj.mjs} +6 -6
- package/core/built/admin/assets/posts/{links-BAXELE82.mjs → links-DDApMJfk.mjs} +4 -4
- package/core/built/admin/assets/posts/{list-page-DQIiFvFP.mjs → list-page-BJJ9amzJ.mjs} +4 -4
- package/core/built/admin/assets/posts/{loading-indicator-BsY7eGY6.mjs → loading-indicator-CQBDNvdo.mjs} +3 -3
- package/core/built/admin/assets/posts/{mail-Bi1gt3MU.mjs → mail-BHg0SvNu.mjs} +2 -2
- package/core/built/admin/assets/posts/{main-layout-DejRuxP8.mjs → main-layout-DXveCJ5W.mjs} +2 -2
- package/core/built/admin/assets/posts/{newsletter-PCUtHW6Z.mjs → newsletter-DUpVmnKN.mjs} +19 -19
- package/core/built/admin/assets/posts/{overview-f4eDWazr.mjs → overview-sv6i-2h9.mjs} +18 -18
- package/core/built/admin/assets/posts/{pencil-DDnfXQqn.mjs → pencil-DsGDLJp6.mjs} +2 -2
- package/core/built/admin/assets/posts/{plus-DW3bG6ui.mjs → plus-DjZ_REvJ.mjs} +2 -2
- package/core/built/admin/assets/posts/{popover-Du2NcggM.mjs → popover-2PA9zdiD.mjs} +4 -4
- package/core/built/admin/assets/posts/{post-analytics-BmnHyWJq.mjs → post-analytics-CKHoiJFY.mjs} +6 -6
- package/core/built/admin/assets/posts/{post-analytics-context-0fieM91Y.mjs → post-analytics-context-D17CB7nm.mjs} +6 -6
- package/core/built/admin/assets/posts/{post-analytics-header-Bxi56AWV.mjs → post-analytics-header-aQLnrdWi.mjs} +12 -12
- package/core/built/admin/assets/posts/{post-share-modal-DiuT4GFO.mjs → post-share-modal-C8-8CZw8.mjs} +6 -6
- package/core/built/admin/assets/posts/{posts-CYjfxmgX.mjs → posts-BA2vu_T2.mjs} +2 -2
- package/core/built/admin/assets/posts/posts.js +1 -1
- package/core/built/admin/assets/posts/{search-Dz7F6ifc.mjs → search-Bx6BvCRk.mjs} +2 -2
- package/core/built/admin/assets/posts/{select-FX6QYAFU.mjs → select-QOJ2OvL0.mjs} +7 -7
- package/core/built/admin/assets/posts/{separator-C7QPCSjM.mjs → separator-CHtBa4OX.mjs} +3 -3
- package/core/built/admin/assets/posts/{settings-DJqx19W1.mjs → settings-CxhTCxXg.mjs} +2 -2
- package/core/built/admin/assets/posts/{sheet-wg_8-w45.mjs → sheet-DO5nhiru.mjs} +4 -4
- package/core/built/admin/assets/posts/{site-Bxv-L5Dn.mjs → site-6g4pKVnR.mjs} +2 -2
- package/core/built/admin/assets/posts/{skeleton-DrFcKwP3.mjs → skeleton-DgWx-52p.mjs} +3 -3
- package/core/built/admin/assets/posts/{source-icon-DD_bmIqg.mjs → source-icon-_zLbYeab.mjs} +4 -4
- package/core/built/admin/assets/posts/{stats-DkOg80Vt.mjs → stats-BGJFxx5f.mjs} +4 -4
- package/core/built/admin/assets/posts/{switch-DZFGAF_Y.mjs → switch-Djipx7gc.mjs} +5 -5
- package/core/built/admin/assets/posts/{table-CZCVviNy.mjs → table-DpDCE80J.mjs} +2 -2
- package/core/built/admin/assets/posts/{tabs-1fkhM4p8.mjs → tabs-CLWGiyQ4.mjs} +4 -4
- package/core/built/admin/assets/posts/{tags-CkyGqwqi.mjs → tags-B4KIn7er.mjs} +2 -2
- package/core/built/admin/assets/posts/{tags-BAmugIR1.mjs → tags-Dn1L_Z_4.mjs} +16 -16
- package/core/built/admin/assets/posts/{toggle-group-B_ubMZvo.mjs → toggle-group-DMMjXGB3.mjs} +4 -4
- package/core/built/admin/assets/posts/{tooltip-D1X0uVas.mjs → tooltip-DlCjZwmt.mjs} +5 -5
- package/core/built/admin/assets/posts/{underline-CV8OJ7qc.mjs → underline-WN3ZSFyI.mjs} +2 -2
- package/core/built/admin/assets/posts/{value-DhEK7_uT.mjs → value-BWiEmo45.mjs} +2 -2
- package/core/built/admin/assets/posts/{virtual-list-window-DqbQUkIo.mjs → virtual-list-window-F3Tvi9H5.mjs} +3 -3
- package/core/built/admin/assets/posts/{web-5jcYGeBz.mjs → web-C8PxkHvH.mjs} +18 -18
- package/core/built/admin/assets/posts/{x-Cl72IwQm.mjs → x-BdlZ3sG3.mjs} +2 -2
- package/core/built/admin/assets/posts/{zap-BPDyHF1u.mjs → zap-BuAk2C7n.mjs} +33 -21
- package/core/built/admin/assets/{posts-D6K0FKB9.js → posts-bRma2Aji.js} +1 -1
- package/core/built/admin/assets/power-B4VCYMPn.js +1 -0
- package/core/built/admin/assets/{referrers-C9UK_aF_.js → referrers-BgXy4ZDF.js} +1 -1
- package/core/built/admin/assets/{repeat-BwgUDBQn.js → repeat-BElPLZnh.js} +1 -1
- package/core/built/admin/assets/{reply-DbknkQhJ.js → reply-qlUFZ_G8.js} +1 -1
- package/core/built/admin/assets/{rocket-1EqU2MzS.js → rocket-CXYckFbm.js} +1 -1
- package/core/built/admin/assets/{select-BGJXWb8i.js → select-MGAxyhXP.js} +1 -1
- package/core/built/admin/assets/{send-_CqvCQBY.js → send-DcU5LcPI.js} +1 -1
- package/core/built/admin/assets/{settings-Bnep890F.js → settings-DGSAz4oa.js} +4 -4
- package/core/built/admin/assets/{settings-Ct244PHl.js → settings-DI95fXs5.js} +1 -1
- package/core/built/admin/assets/{share-modal-B8pN_3tk.js → share-modal-CsNAIPeN.js} +1 -1
- package/core/built/admin/assets/{sort-button-EXsVVSdw.js → sort-button-wV9PBd2P.js} +1 -1
- package/core/built/admin/assets/{source-icon-XMs0toB0.js → source-icon-CYt4X1-M.js} +1 -1
- package/core/built/admin/assets/{sprout-uA_pVmDr.js → sprout-5QqpAoO8.js} +1 -1
- package/core/built/admin/assets/{square-atKnWQyw.js → square-YHeYyKG9.js} +1 -1
- package/core/built/admin/assets/{stats-CPNnZGD9.js → stats-PD64opSw.js} +1 -1
- package/core/built/admin/assets/{stats-view-BP8LU5rf.js → stats-view-C4fnD3uG.js} +1 -1
- package/core/built/admin/assets/{step-1-FHeGC4GW.js → step-1-BqeM_LxC.js} +1 -1
- package/core/built/admin/assets/{step-2-BFhgD2N8.js → step-2-C7AcokE9.js} +1 -1
- package/core/built/admin/assets/{step-3-BZMKjY5n.js → step-3-9Z0qkfpM.js} +2 -2
- package/core/built/admin/assets/{table-kGA62bBZ.js → table-C8Mxw8fs.js} +1 -1
- package/core/built/admin/assets/{tabs-Dl3BXr4Z.js → tabs-2KXMNRG-.js} +1 -1
- package/core/built/admin/assets/{tags-CLhASxwZ.js → tags-Cx-Jx8Yb.js} +1 -1
- package/core/built/admin/assets/{tags-D-W0kJMe.js → tags-cn7wgGit.js} +1 -1
- package/core/built/admin/assets/{textarea-DMub6CsU.js → textarea-dKwIcAK5.js} +1 -1
- package/core/built/admin/assets/{thumbs-up-DZu4SX5N.js → thumbs-up-gzGza05L.js} +1 -1
- package/core/built/admin/assets/{tiers-2bg8BCFj.js → tiers-D--LgD9v.js} +1 -1
- package/core/built/admin/assets/{toggle-group-ByS0KZ3G.js → toggle-group-C8KbiBQS.js} +1 -1
- package/core/built/admin/assets/{topic-filter-oRqwlePZ.js → topic-filter--VQn4A7D.js} +1 -1
- package/core/built/admin/assets/{trash-BHoSD8mS.js → trash-CnBwlhjN.js} +1 -1
- package/core/built/admin/assets/{underline-1YSgOpPm.js → underline-B2FjHOE0.js} +1 -1
- package/core/built/admin/assets/{undo-2-BwYMlB8G.js → undo-2-fUPuO2Zt.js} +1 -1
- package/core/built/admin/assets/{upload-BDz0_o9b.js → upload-BPOrFdtp.js} +1 -1
- package/core/built/admin/assets/{use-growth-stats-PRVcCUT7.js → use-growth-stats-By0ZDqFi.js} +1 -1
- package/core/built/admin/assets/{use-pintura-config-CROsgSEd.js → use-pintura-config-0ykvCF7U.js} +1 -1
- package/core/built/admin/assets/{use-simple-pagination-CBjKBNNI.js → use-simple-pagination-TruuCHV6.js} +1 -1
- package/core/built/admin/assets/{user-round-check-DKooQiV7.js → user-round-check-C1Vahz0b.js} +1 -1
- package/core/built/admin/assets/{user-round-x-B94nAYJb.js → user-round-x-CzKFo5GY.js} +1 -1
- package/core/built/admin/assets/{virtual-list-window-Cf_vCQFb.js → virtual-list-window-BWEknk_A.js} +1 -1
- package/core/built/admin/assets/{wallet-cards-BorRQari.js → wallet-cards-CRHrrjiy.js} +1 -1
- package/core/built/admin/assets/{web-BVHy-80k.js → web-C2H0oAut.js} +1 -1
- package/core/built/admin/index.html +7 -7
- package/core/frontend/services/llms/service.js +37 -10
- package/core/frontend/services/routing/config.js +5 -3
- package/core/frontend/services/routing/config.ts +59 -0
- package/core/frontend/services/sitemap/handler.js +2 -14
- package/core/frontend/services/sitemap/site-map-manager.js +9 -214
- package/core/server/api/endpoints/comment-replies.js +1 -2
- package/core/server/api/endpoints/members.js +4 -1
- package/core/server/api/endpoints/search-index-public.js +12 -1
- package/core/server/api/endpoints/search-index.js +13 -2
- package/core/server/lib/bootstrap-socket.js +31 -36
- package/core/server/lib/bootstrap-socket.ts +114 -0
- package/core/server/lib/common/to-plain.js +9 -21
- package/core/server/lib/common/to-plain.ts +25 -0
- package/core/server/models/role-utils.js +5 -7
- package/core/server/models/role-utils.ts +56 -0
- package/core/server/services/adapter-manager/adapter-manager.js +5 -1
- package/core/server/services/audience-feedback/audience-feedback-service.js +1 -1
- package/core/server/services/automations/automations-api.js +37 -2
- package/core/server/services/automations/automations-api.ts +43 -2
- package/core/server/services/comments/comments-controller.js +87 -55
- package/core/server/services/comments/comments-service-emails.js +1 -1
- package/core/server/services/comments/comments-service.js +249 -79
- package/core/server/services/mail/templates/notification.html +157 -0
- package/core/server/services/member-attribution/url-translator.js +1 -1
- package/core/server/services/members/members-api/services/token-service.js +21 -2
- package/core/server/services/notifications/notification-email.js +38 -0
- package/core/server/services/notifications/notification-email.ts +66 -0
- package/core/server/services/notifications/sanitize-email-html.js +37 -0
- package/core/server/services/notifications/sanitize-email-html.ts +35 -0
- package/core/server/services/route-settings/route-settings.js +2 -18
- package/core/server/services/route-settings/validate.js +2 -1
- package/core/server/services/update-check/index.js +10 -3
- package/core/server/services/update-check/update-check-service.js +18 -25
- package/core/server/services/url/index.js +1 -16
- package/core/shared/config/defaults.json +0 -1
- package/package.json +2 -1
- package/pnpm-lock.yaml +11 -1
- package/pnpm-workspace.yaml +2 -0
- package/core/built/admin/assets/editor-G3BxjP48.js +0 -8
- package/core/built/admin/assets/gh-chart-vpcpdiS9.js +0 -1
- package/core/built/admin/assets/index-BP5ial3p.js +0 -1
- package/core/built/admin/assets/index-Bd9VZ28k.css +0 -1
- package/core/built/admin/assets/kpis-B8pv3wne.js +0 -1
- package/core/built/admin/assets/label-BjHICZC1.js +0 -1
- package/core/built/admin/assets/members-DcuuSs_v.js +0 -10
- package/core/built/admin/assets/minus-Dv51QEND.js +0 -1
- package/core/built/admin/assets/offers-DKZ0qsmb.js +0 -1
- package/core/built/admin/assets/power-D5QO6MjY.js +0 -1
- package/core/server/services/url/lazy-find-resource.js +0 -49
- package/core/server/services/url/lazy-find-resource.ts +0 -62
- package/core/server/services/url/lazy-url-service.js +0 -262
- package/core/server/services/url/lazy-url-service.ts +0 -308
|
@@ -23,13 +23,55 @@ const messages = {
|
|
|
23
23
|
|
|
24
24
|
const COMMENT_LIKE_SCORE = 1;
|
|
25
25
|
const COMMENT_DISLIKE_SCORE = -1;
|
|
26
|
+
const COMMENT_STATUS_PUBLISHED = 'published';
|
|
27
|
+
const COMMENT_STATUS_HIDDEN = 'hidden';
|
|
28
|
+
const COMMENT_STATUS_DELETED = 'deleted';
|
|
29
|
+
const COMMENT_STATUSES_READABLE = [COMMENT_STATUS_PUBLISHED, COMMENT_STATUS_HIDDEN];
|
|
30
|
+
const COMMENT_STATUSES_REPLY_PARENT = [COMMENT_STATUS_PUBLISHED, COMMENT_STATUS_HIDDEN, COMMENT_STATUS_DELETED];
|
|
31
|
+
const COMMENT_STATUSES_IN_REPLY_TO = [COMMENT_STATUS_PUBLISHED, COMMENT_STATUS_HIDDEN];
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
// Columns each action reads from the comment row beyond `id`/`status`, which the
|
|
34
|
+
// lookup helpers always select. Keeping these lists together makes the coupling
|
|
35
|
+
// between "fields read after the fetch" and "columns requested" explicit, so a
|
|
36
|
+
// new `comment.get(...)` call has one obvious place to register its column.
|
|
37
|
+
const REPLY_PARENT_REQUIRED_COLUMNS = ['parent_id', 'post_id'];
|
|
38
|
+
const IN_REPLY_TO_REQUIRED_COLUMNS = ['parent_id'];
|
|
39
|
+
const OWNERSHIP_REQUIRED_COLUMNS = ['member_id'];
|
|
40
|
+
const REPORT_REQUIRED_COLUMNS = ['post_id', 'member_id', 'html', 'created_at'];
|
|
41
|
+
|
|
42
|
+
function getColumnList(columns) {
|
|
43
|
+
if (!columns) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (Array.isArray(columns)) {
|
|
48
|
+
return columns;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return columns.split(',').map(column => column.trim()).filter(Boolean);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function withRequiredColumns(options = {}, requiredColumns = []) {
|
|
55
|
+
const columns = getColumnList(options.columns);
|
|
56
|
+
|
|
57
|
+
if (!columns) {
|
|
58
|
+
return {...options};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
...options,
|
|
63
|
+
columns: Array.from(new Set(['id', ...columns, ...requiredColumns]))
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function withPinnedSelect(options = {}, {includeHidden = false} = {}) {
|
|
68
|
+
const columns = getColumnList(options.columns);
|
|
69
|
+
|
|
70
|
+
if (!columns?.includes('pinned')) {
|
|
71
|
+
return {...options};
|
|
30
72
|
}
|
|
31
73
|
|
|
32
|
-
const statusClause =
|
|
74
|
+
const statusClause = includeHidden ? '' : ' AND comments.status = \'published\'';
|
|
33
75
|
const pinnedSelect = `CASE WHEN comments.parent_id IS NULL AND comments.pinned_at IS NOT NULL${statusClause} THEN 1 ELSE 0 END AS pinned`;
|
|
34
76
|
|
|
35
77
|
return {
|
|
@@ -38,6 +80,19 @@ function withPinnedSelect(options = {}) {
|
|
|
38
80
|
};
|
|
39
81
|
}
|
|
40
82
|
|
|
83
|
+
function getSafeFetchOptions(options = {}, columns = []) {
|
|
84
|
+
return {
|
|
85
|
+
...(options.transacting ? {transacting: options.transacting} : {}),
|
|
86
|
+
columns: Array.from(new Set(['id', ...columns]))
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function getSafeWriteOptions(options = {}) {
|
|
91
|
+
return {
|
|
92
|
+
...(options.transacting ? {transacting: options.transacting} : {})
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
41
96
|
class CommentsService {
|
|
42
97
|
constructor({config, logging, models, mailer, settingsCache, settingsHelpers, urlService, urlUtils, contentGating, labs}) {
|
|
43
98
|
/** @private */
|
|
@@ -119,14 +174,148 @@ class CommentsService {
|
|
|
119
174
|
});
|
|
120
175
|
}
|
|
121
176
|
|
|
177
|
+
/**
|
|
178
|
+
* @private
|
|
179
|
+
* Primary comment lookup: a single keyed fetch with the allowed statuses
|
|
180
|
+
* applied in the query (`WHERE id = ? AND status IN (...)`), optionally locked
|
|
181
|
+
* with `FOR UPDATE` inside a transaction. It deliberately does not load the
|
|
182
|
+
* member-facing relation graph; the one read that needs those relations
|
|
183
|
+
* (#getReadableCommentByID, backing getCommentByID) uses `findOne` instead.
|
|
184
|
+
*/
|
|
185
|
+
async #fetchCommentByID(id, options = {}, {requiredColumns = [], statuses = [], forUpdate = false} = {}) {
|
|
186
|
+
const model = this.models.Comment.forge();
|
|
187
|
+
model.query((qb) => {
|
|
188
|
+
qb.where('comments.id', id);
|
|
189
|
+
|
|
190
|
+
if (statuses.length === 1) {
|
|
191
|
+
qb.where('comments.status', statuses[0]);
|
|
192
|
+
} else if (statuses.length > 1) {
|
|
193
|
+
qb.whereIn('comments.status', statuses);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (forUpdate && options.transacting) {
|
|
197
|
+
qb.forUpdate();
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
return await model.fetch(getSafeFetchOptions(options, requiredColumns));
|
|
202
|
+
}
|
|
203
|
+
|
|
122
204
|
/** @private */
|
|
123
|
-
async #
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
205
|
+
async #getPublishedCommentForAction(id, options = {}, requiredColumns = [], {forUpdate = false} = {}) {
|
|
206
|
+
const model = await this.#fetchCommentByID(id, options, {
|
|
207
|
+
requiredColumns,
|
|
208
|
+
statuses: [COMMENT_STATUS_PUBLISHED],
|
|
209
|
+
forUpdate
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
if (!model) {
|
|
213
|
+
throw new errors.NotFoundError({
|
|
214
|
+
message: tpl(messages.commentNotFound)
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return model;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @private
|
|
223
|
+
* Member-facing read: goes through `findOne` (not the lean primitive) so the
|
|
224
|
+
* serializer's default relation graph (member, counts, in_reply_to, replies)
|
|
225
|
+
* is loaded. Readable statuses are constrained in the query via an NQL filter,
|
|
226
|
+
* so a non-readable comment is never fetched and its relations never loaded — a
|
|
227
|
+
* missing or non-readable id is a 404. `status` stays selected for the
|
|
228
|
+
* serializer's hidden/deleted redaction.
|
|
229
|
+
*/
|
|
230
|
+
async #getReadableCommentByID(id, options = {}, requiredColumns = []) {
|
|
231
|
+
const readableFilter = `status:[${COMMENT_STATUSES_READABLE.join(',')}]`;
|
|
232
|
+
const model = await this.models.Comment.findOne(
|
|
233
|
+
{id},
|
|
234
|
+
withRequiredColumns(
|
|
235
|
+
{
|
|
236
|
+
...options,
|
|
237
|
+
filter: options.filter ? `(${options.filter})+${readableFilter}` : readableFilter
|
|
238
|
+
},
|
|
239
|
+
['status', ...requiredColumns]
|
|
240
|
+
)
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
if (!model) {
|
|
244
|
+
throw new errors.NotFoundError({
|
|
245
|
+
message: tpl(messages.commentNotFound)
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return model;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** @private */
|
|
253
|
+
async #getReplyParentCommentByID(id, options = {}) {
|
|
254
|
+
// Deleted parent comments intentionally remain valid thread anchors: a reply
|
|
255
|
+
// can still be posted under a top-level comment whose root was removed.
|
|
256
|
+
const model = await this.#fetchCommentByID(id, options, {
|
|
257
|
+
requiredColumns: REPLY_PARENT_REQUIRED_COLUMNS,
|
|
258
|
+
statuses: COMMENT_STATUSES_REPLY_PARENT
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
if (!model) {
|
|
262
|
+
throw new errors.NotFoundError({
|
|
263
|
+
message: tpl(messages.commentNotFound)
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return model;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** @private */
|
|
271
|
+
async #getInReplyToCommentByID(id, parent, options = {}) {
|
|
272
|
+
const model = await this.#fetchCommentByID(id, options, {
|
|
273
|
+
requiredColumns: IN_REPLY_TO_REQUIRED_COLUMNS,
|
|
274
|
+
statuses: COMMENT_STATUSES_IN_REPLY_TO
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// A target that is missing, deleted, or not a readable sibling is simply not
|
|
278
|
+
// a valid direct-reply anchor: drop the reference and let the reply post
|
|
279
|
+
// anyway (you can reply within the thread, just not "to" a dead comment). The
|
|
280
|
+
// query already excluded disallowed statuses, so only the cross-thread
|
|
281
|
+
// relationship check remains here. Hidden-target snippets are redacted
|
|
282
|
+
// downstream.
|
|
283
|
+
if (!model || model.get('parent_id') !== parent) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return model;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** @private */
|
|
291
|
+
async #assertCommentExists(commentId, options = {}) {
|
|
292
|
+
const model = await this.#fetchCommentByID(commentId, options, {
|
|
293
|
+
requiredColumns: ['id']
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
if (!model) {
|
|
297
|
+
throw new errors.NotFoundError({
|
|
298
|
+
message: tpl(messages.commentNotFound)
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** @private */
|
|
304
|
+
async #getMemberCommentVotes({commentId, memberId, score}, options) {
|
|
305
|
+
const collection = this.models.CommentLike.forge();
|
|
306
|
+
collection.query((qb) => {
|
|
307
|
+
qb.where('comment_likes.comment_id', commentId)
|
|
308
|
+
.where('comment_likes.member_id', memberId);
|
|
309
|
+
|
|
310
|
+
if (score !== undefined) {
|
|
311
|
+
qb.where('comment_likes.score', score);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
qb.orderBy('comment_likes.created_at', 'asc');
|
|
128
315
|
});
|
|
129
316
|
|
|
317
|
+
const votes = await collection.fetchAll(options);
|
|
318
|
+
|
|
130
319
|
return votes.models || [];
|
|
131
320
|
}
|
|
132
321
|
|
|
@@ -148,7 +337,12 @@ class CommentsService {
|
|
|
148
337
|
this.checkCommentAccess(memberModel);
|
|
149
338
|
|
|
150
339
|
return await this.#withTransaction(options, async (transactionOptions) => {
|
|
151
|
-
|
|
340
|
+
await this.#getPublishedCommentForAction(commentId, transactionOptions, [], {forUpdate: true});
|
|
341
|
+
|
|
342
|
+
const votes = await this.#getMemberCommentVotes({
|
|
343
|
+
commentId,
|
|
344
|
+
memberId: memberModel.id
|
|
345
|
+
}, transactionOptions);
|
|
152
346
|
const alreadyHasSingleTargetVote = votes.length === 1 && Number(votes[0].get('score')) === targetScore;
|
|
153
347
|
|
|
154
348
|
if (alreadyHasSingleTargetVote) {
|
|
@@ -170,8 +364,13 @@ class CommentsService {
|
|
|
170
364
|
/** @private */
|
|
171
365
|
async #clearCommentVote(commentId, member, targetScore, notFoundMessage, options = {}) {
|
|
172
366
|
await this.#withTransaction(options, async (transactionOptions) => {
|
|
173
|
-
|
|
174
|
-
|
|
367
|
+
await this.#getPublishedCommentForAction(commentId, transactionOptions, [], {forUpdate: true});
|
|
368
|
+
|
|
369
|
+
const votesToRemove = await this.#getMemberCommentVotes({
|
|
370
|
+
commentId,
|
|
371
|
+
memberId: member.id,
|
|
372
|
+
score: targetScore
|
|
373
|
+
}, transactionOptions);
|
|
175
374
|
|
|
176
375
|
if (votesToRemove.length === 0) {
|
|
177
376
|
throw new errors.NotFoundError({
|
|
@@ -219,15 +418,16 @@ class CommentsService {
|
|
|
219
418
|
await this.#clearCommentVote(commentId, member, COMMENT_DISLIKE_SCORE, messages.dislikeNotFound, options);
|
|
220
419
|
}
|
|
221
420
|
|
|
222
|
-
async reportComment(commentId, reporter) {
|
|
421
|
+
async reportComment(commentId, reporter, options = {}) {
|
|
223
422
|
this.checkEnabled();
|
|
224
|
-
const comment = await this
|
|
423
|
+
const comment = await this.#getPublishedCommentForAction(commentId, options, REPORT_REQUIRED_COLUMNS);
|
|
424
|
+
const writeOptions = getSafeWriteOptions(options);
|
|
225
425
|
|
|
226
426
|
// Check if this reporter already reported this comment (then don't send an email)?
|
|
227
427
|
const existing = await this.models.CommentReport.findOne({
|
|
228
428
|
comment_id: comment.id,
|
|
229
429
|
member_id: reporter.id
|
|
230
|
-
});
|
|
430
|
+
}, writeOptions);
|
|
231
431
|
|
|
232
432
|
if (existing) {
|
|
233
433
|
// Ignore silently for now
|
|
@@ -238,7 +438,7 @@ class CommentsService {
|
|
|
238
438
|
await this.models.CommentReport.add({
|
|
239
439
|
comment_id: comment.id,
|
|
240
440
|
member_id: reporter.id
|
|
241
|
-
});
|
|
441
|
+
}, writeOptions);
|
|
242
442
|
|
|
243
443
|
await this.emails.notifyReport(comment, reporter);
|
|
244
444
|
}
|
|
@@ -295,7 +495,12 @@ class CommentsService {
|
|
|
295
495
|
async getAdminComments(options) {
|
|
296
496
|
this.checkEnabled();
|
|
297
497
|
const pinnedFirst = this.labs?.isSet('commentsPinning');
|
|
298
|
-
const page = await this.models.Comment.findPage(withPinnedSelect({
|
|
498
|
+
const page = await this.models.Comment.findPage(withPinnedSelect({
|
|
499
|
+
...options,
|
|
500
|
+
parentId: null,
|
|
501
|
+
isAdmin: true,
|
|
502
|
+
pinnedFirst
|
|
503
|
+
}, {includeHidden: true}));
|
|
299
504
|
|
|
300
505
|
return page;
|
|
301
506
|
}
|
|
@@ -306,7 +511,7 @@ class CommentsService {
|
|
|
306
511
|
if (Object.prototype.hasOwnProperty.call(data, 'status')) {
|
|
307
512
|
editData.status = data.status;
|
|
308
513
|
|
|
309
|
-
if (data.status ===
|
|
514
|
+
if (data.status === COMMENT_STATUS_DELETED) {
|
|
310
515
|
editData.pinned_at = null;
|
|
311
516
|
}
|
|
312
517
|
}
|
|
@@ -334,7 +539,7 @@ class CommentsService {
|
|
|
334
539
|
});
|
|
335
540
|
}
|
|
336
541
|
|
|
337
|
-
if (existingComment.get('status') ===
|
|
542
|
+
if (existingComment.get('status') === COMMENT_STATUS_DELETED || data.status === COMMENT_STATUS_DELETED) {
|
|
338
543
|
throw new errors.BadRequestError({
|
|
339
544
|
message: tpl(messages.cannotPinDeletedComment)
|
|
340
545
|
});
|
|
@@ -355,25 +560,27 @@ class CommentsService {
|
|
|
355
560
|
* @param {string} id - The ID of the Comment to get replies from
|
|
356
561
|
* @param {any} options
|
|
357
562
|
*/
|
|
358
|
-
async getReplies(id, options) {
|
|
563
|
+
async getReplies(id, options, {includeHidden = false} = {}) {
|
|
359
564
|
this.checkEnabled();
|
|
360
|
-
const page = await this.models.Comment.findPage(withPinnedSelect({...options, parentId: id}));
|
|
565
|
+
const page = await this.models.Comment.findPage(withPinnedSelect({...options, parentId: id}, {includeHidden}));
|
|
361
566
|
|
|
362
567
|
return page;
|
|
363
568
|
}
|
|
364
569
|
|
|
570
|
+
async getAdminReplies(id, options) {
|
|
571
|
+
return await this.getReplies(id, {
|
|
572
|
+
...options,
|
|
573
|
+
isAdmin: true
|
|
574
|
+
}, {includeHidden: true});
|
|
575
|
+
}
|
|
576
|
+
|
|
365
577
|
/**
|
|
366
578
|
* Get reporters for a comment (admin only)
|
|
367
579
|
* @param {string} commentId - The ID of the Comment to get reporters for
|
|
368
580
|
* @param {any} options - Query options (page, limit)
|
|
369
581
|
*/
|
|
370
582
|
async getCommentReporters(commentId, options = {}) {
|
|
371
|
-
|
|
372
|
-
if (!comment) {
|
|
373
|
-
throw new errors.NotFoundError({
|
|
374
|
-
message: tpl(messages.commentNotFound)
|
|
375
|
-
});
|
|
376
|
-
}
|
|
583
|
+
await this.#assertCommentExists(commentId);
|
|
377
584
|
|
|
378
585
|
const {page, limit} = options;
|
|
379
586
|
const result = await this.models.CommentReport.findPage({
|
|
@@ -393,12 +600,7 @@ class CommentsService {
|
|
|
393
600
|
* @param {any} options - Query options (page, limit)
|
|
394
601
|
*/
|
|
395
602
|
async getCommentLikes(commentId, options = {}) {
|
|
396
|
-
|
|
397
|
-
if (!comment) {
|
|
398
|
-
throw new errors.NotFoundError({
|
|
399
|
-
message: tpl(messages.commentNotFound)
|
|
400
|
-
});
|
|
401
|
-
}
|
|
603
|
+
await this.#assertCommentExists(commentId);
|
|
402
604
|
|
|
403
605
|
const {page, limit} = options;
|
|
404
606
|
const result = await this.models.CommentLike.findPage({
|
|
@@ -418,12 +620,7 @@ class CommentsService {
|
|
|
418
620
|
* @param {any} options - Query options (page, limit)
|
|
419
621
|
*/
|
|
420
622
|
async getCommentDislikes(commentId, options = {}) {
|
|
421
|
-
|
|
422
|
-
if (!comment) {
|
|
423
|
-
throw new errors.NotFoundError({
|
|
424
|
-
message: tpl(messages.commentNotFound)
|
|
425
|
-
});
|
|
426
|
-
}
|
|
623
|
+
await this.#assertCommentExists(commentId);
|
|
427
624
|
|
|
428
625
|
const {page, limit} = options;
|
|
429
626
|
const result = await this.models.CommentLike.findPage({
|
|
@@ -437,21 +634,10 @@ class CommentsService {
|
|
|
437
634
|
return result;
|
|
438
635
|
}
|
|
439
636
|
|
|
440
|
-
|
|
441
|
-
* @param {string} id - The ID of the Comment to get
|
|
442
|
-
* @param {any} options
|
|
443
|
-
*/
|
|
444
|
-
async getCommentByID(id, options) {
|
|
637
|
+
async getCommentByID(id, options = {}) {
|
|
445
638
|
this.checkEnabled();
|
|
446
|
-
const model = await this.models.Comment.findOne({id}, withPinnedSelect(options));
|
|
447
|
-
|
|
448
|
-
if (!model) {
|
|
449
|
-
throw new errors.NotFoundError({
|
|
450
|
-
message: tpl(messages.commentNotFound)
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
639
|
|
|
454
|
-
return
|
|
640
|
+
return await this.#getReadableCommentByID(id, options);
|
|
455
641
|
}
|
|
456
642
|
|
|
457
643
|
/**
|
|
@@ -488,7 +674,7 @@ class CommentsService {
|
|
|
488
674
|
member_id: member,
|
|
489
675
|
parent_id: null,
|
|
490
676
|
html: comment,
|
|
491
|
-
status:
|
|
677
|
+
status: COMMENT_STATUS_PUBLISHED
|
|
492
678
|
};
|
|
493
679
|
|
|
494
680
|
if (createdAt) {
|
|
@@ -531,12 +717,7 @@ class CommentsService {
|
|
|
531
717
|
|
|
532
718
|
this.checkCommentAccess(memberModel);
|
|
533
719
|
|
|
534
|
-
const parentComment = await this
|
|
535
|
-
if (!parentComment) {
|
|
536
|
-
throw new errors.BadRequestError({
|
|
537
|
-
message: tpl(messages.commentNotFound)
|
|
538
|
-
});
|
|
539
|
-
}
|
|
720
|
+
const parentComment = await this.#getReplyParentCommentByID(parent, options);
|
|
540
721
|
|
|
541
722
|
if (parentComment.get('parent_id') !== null) {
|
|
542
723
|
throw new errors.BadRequestError({
|
|
@@ -556,18 +737,7 @@ class CommentsService {
|
|
|
556
737
|
|
|
557
738
|
let inReplyToComment;
|
|
558
739
|
if (parent && inReplyTo) {
|
|
559
|
-
inReplyToComment = await this
|
|
560
|
-
|
|
561
|
-
// we only allow references to published comments to avoid leaking
|
|
562
|
-
// hidden data via the snippet included in API responses
|
|
563
|
-
if (inReplyToComment && inReplyToComment.get('status') !== 'published') {
|
|
564
|
-
inReplyToComment = null;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// we don't allow in_reply_to references across different parents
|
|
568
|
-
if (inReplyToComment && inReplyToComment.get('parent_id') !== parent) {
|
|
569
|
-
inReplyToComment = null;
|
|
570
|
-
}
|
|
740
|
+
inReplyToComment = await this.#getInReplyToCommentByID(inReplyTo, parent, options);
|
|
571
741
|
}
|
|
572
742
|
|
|
573
743
|
const commentData = {
|
|
@@ -576,7 +746,7 @@ class CommentsService {
|
|
|
576
746
|
parent_id: parentComment.id,
|
|
577
747
|
in_reply_to_id: inReplyToComment && inReplyToComment.get('id'),
|
|
578
748
|
html: comment,
|
|
579
|
-
status:
|
|
749
|
+
status: COMMENT_STATUS_PUBLISHED
|
|
580
750
|
};
|
|
581
751
|
|
|
582
752
|
if (createdAt) {
|
|
@@ -606,7 +776,7 @@ class CommentsService {
|
|
|
606
776
|
*/
|
|
607
777
|
async deleteComment(id, member, options) {
|
|
608
778
|
this.checkEnabled();
|
|
609
|
-
const existingComment = await this
|
|
779
|
+
const existingComment = await this.#getPublishedCommentForAction(id, options, OWNERSHIP_REQUIRED_COLUMNS);
|
|
610
780
|
|
|
611
781
|
if (existingComment.get('member_id') !== member) {
|
|
612
782
|
throw new errors.NoPermissionError({
|
|
@@ -616,7 +786,7 @@ class CommentsService {
|
|
|
616
786
|
}
|
|
617
787
|
|
|
618
788
|
const model = await this.models.Comment.edit({
|
|
619
|
-
status:
|
|
789
|
+
status: COMMENT_STATUS_DELETED,
|
|
620
790
|
pinned_at: null
|
|
621
791
|
}, {
|
|
622
792
|
id,
|
|
@@ -635,11 +805,7 @@ class CommentsService {
|
|
|
635
805
|
*/
|
|
636
806
|
async editCommentContent(id, member, comment, options) {
|
|
637
807
|
this.checkEnabled();
|
|
638
|
-
const existingComment = await this
|
|
639
|
-
|
|
640
|
-
if (!comment) {
|
|
641
|
-
return existingComment;
|
|
642
|
-
}
|
|
808
|
+
const existingComment = await this.#getPublishedCommentForAction(id, options, OWNERSHIP_REQUIRED_COLUMNS);
|
|
643
809
|
|
|
644
810
|
if (existingComment.get('member_id') !== member) {
|
|
645
811
|
throw new errors.NoPermissionError({
|
|
@@ -647,6 +813,10 @@ class CommentsService {
|
|
|
647
813
|
});
|
|
648
814
|
}
|
|
649
815
|
|
|
816
|
+
if (!comment) {
|
|
817
|
+
return existingComment;
|
|
818
|
+
}
|
|
819
|
+
|
|
650
820
|
const model = await this.models.Comment.edit({
|
|
651
821
|
html: comment,
|
|
652
822
|
edited_at: new Date()
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta name="viewport" content="width=device-width">
|
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
6
|
+
<title>Ghost notification</title>
|
|
7
|
+
<style>
|
|
8
|
+
@media only screen and (max-width: 620px) {
|
|
9
|
+
table[class=body] h1 {
|
|
10
|
+
font-size: 28px !important;
|
|
11
|
+
margin-bottom: 10px !important;
|
|
12
|
+
}
|
|
13
|
+
table[class=body] p,
|
|
14
|
+
table[class=body] ul,
|
|
15
|
+
table[class=body] ol,
|
|
16
|
+
table[class=body] td,
|
|
17
|
+
table[class=body] span,
|
|
18
|
+
table[class=body] a {
|
|
19
|
+
font-size: 16px !important;
|
|
20
|
+
}
|
|
21
|
+
table[class=body] .wrapper,
|
|
22
|
+
table[class=body] .article {
|
|
23
|
+
padding: 10px !important;
|
|
24
|
+
}
|
|
25
|
+
table[class=body] .content {
|
|
26
|
+
padding: 0 !important;
|
|
27
|
+
}
|
|
28
|
+
table[class=body] .container {
|
|
29
|
+
padding: 0 !important;
|
|
30
|
+
width: 100% !important;
|
|
31
|
+
}
|
|
32
|
+
table[class=body] .main {
|
|
33
|
+
border-left-width: 0 !important;
|
|
34
|
+
border-radius: 0 !important;
|
|
35
|
+
border-right-width: 0 !important;
|
|
36
|
+
}
|
|
37
|
+
table[class=body] .img-responsive {
|
|
38
|
+
height: auto !important;
|
|
39
|
+
max-width: 100% !important;
|
|
40
|
+
width: auto !important;
|
|
41
|
+
}
|
|
42
|
+
table[class=body] p[class=small],
|
|
43
|
+
table[class=body] a[class=small] {
|
|
44
|
+
font-size: 12px !important;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
@media all {
|
|
48
|
+
.ExternalClass {
|
|
49
|
+
width: 100%;
|
|
50
|
+
}
|
|
51
|
+
.ExternalClass,
|
|
52
|
+
.ExternalClass p,
|
|
53
|
+
.ExternalClass span,
|
|
54
|
+
.ExternalClass font,
|
|
55
|
+
.ExternalClass td,
|
|
56
|
+
.ExternalClass div {
|
|
57
|
+
line-height: 100%;
|
|
58
|
+
}
|
|
59
|
+
.recipient-link a {
|
|
60
|
+
color: inherit !important;
|
|
61
|
+
font-family: inherit !important;
|
|
62
|
+
font-size: inherit !important;
|
|
63
|
+
font-weight: inherit !important;
|
|
64
|
+
line-height: inherit !important;
|
|
65
|
+
text-decoration: none !important;
|
|
66
|
+
}
|
|
67
|
+
#MessageViewBody a {
|
|
68
|
+
color: inherit;
|
|
69
|
+
text-decoration: none;
|
|
70
|
+
font-size: inherit;
|
|
71
|
+
font-family: inherit;
|
|
72
|
+
font-weight: inherit;
|
|
73
|
+
line-height: inherit;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
.message {
|
|
77
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
|
78
|
+
font-size: 16px;
|
|
79
|
+
color: #3A464C;
|
|
80
|
+
line-height: 25px;
|
|
81
|
+
}
|
|
82
|
+
.message p {
|
|
83
|
+
margin: 0 0 20px 0;
|
|
84
|
+
}
|
|
85
|
+
.message a {
|
|
86
|
+
color: #15212A;
|
|
87
|
+
word-break: break-all;
|
|
88
|
+
}
|
|
89
|
+
.message hr {
|
|
90
|
+
border: 0;
|
|
91
|
+
border-top: 1px solid #EEF5F8;
|
|
92
|
+
margin: 28px 0;
|
|
93
|
+
}
|
|
94
|
+
.message ul,
|
|
95
|
+
.message ol {
|
|
96
|
+
margin: 0 0 20px 0;
|
|
97
|
+
padding-left: 20px;
|
|
98
|
+
}
|
|
99
|
+
.message blockquote {
|
|
100
|
+
margin: 0 0 20px 0;
|
|
101
|
+
padding-left: 16px;
|
|
102
|
+
border-left: 3px solid #EEF5F8;
|
|
103
|
+
color: #738A94;
|
|
104
|
+
}
|
|
105
|
+
.message code {
|
|
106
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
107
|
+
background: #F2F6F8;
|
|
108
|
+
padding: 1px 4px;
|
|
109
|
+
border-radius: 3px;
|
|
110
|
+
}
|
|
111
|
+
a {
|
|
112
|
+
color: #3A464C;
|
|
113
|
+
}
|
|
114
|
+
</style>
|
|
115
|
+
</head>
|
|
116
|
+
<body style="background-color: #ffffff; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
|
117
|
+
|
|
118
|
+
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
119
|
+
<tr>
|
|
120
|
+
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;"> </td>
|
|
121
|
+
<td class="container" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 540px; padding: 10px; width: 540px;">
|
|
122
|
+
|
|
123
|
+
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 600px; padding: 30px 20px;">
|
|
124
|
+
|
|
125
|
+
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 8px;">
|
|
126
|
+
|
|
127
|
+
<tr>
|
|
128
|
+
<td class="wrapper" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 8px 8px 0;">
|
|
129
|
+
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
130
|
+
<tr>
|
|
131
|
+
<td align="center" style="padding-top: 20px; padding-bottom: 12px;"><img src="https://static.ghost.org/v4.0.0/images/ghost-orb-2.png" width="60" height="60" style="width: 60px; height: 60px;" alt="Ghost" /></td>
|
|
132
|
+
</tr>
|
|
133
|
+
<tr>
|
|
134
|
+
<td class="message" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; line-height: 25px; vertical-align: top; padding-top: 24px; padding-bottom: 10px;">
|
|
135
|
+
{{message}}
|
|
136
|
+
</td>
|
|
137
|
+
</tr>
|
|
138
|
+
</table>
|
|
139
|
+
</td>
|
|
140
|
+
</tr>
|
|
141
|
+
<tr>
|
|
142
|
+
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; vertical-align: top; padding-top: 80px; padding-bottom: 10px;">
|
|
143
|
+
<div class="footer">
|
|
144
|
+
<p class="small" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; color: #738A94; font-weight: normal; margin: 0; line-height: 18px; margin-bottom: 0px; font-size: 11px;">This email was sent from <a href="{{siteUrl}}" style="color: #738A94;">{{siteUrl}}</a> to <a href="mailto:{{recipientEmail}}" style="color: #738A94;">{{recipientEmail}}</a></p>
|
|
145
|
+
</div>
|
|
146
|
+
</td>
|
|
147
|
+
</tr>
|
|
148
|
+
|
|
149
|
+
</table>
|
|
150
|
+
|
|
151
|
+
</div>
|
|
152
|
+
</td>
|
|
153
|
+
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;"> </td>
|
|
154
|
+
</tr>
|
|
155
|
+
</table>
|
|
156
|
+
</body>
|
|
157
|
+
</html>
|