ghost 5.7.0 → 5.8.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.
Files changed (451) hide show
  1. package/components/tryghost-custom-theme-settings-service-0.0.0.tgz +0 -0
  2. package/components/tryghost-email-analytics-service-0.0.0.tgz +0 -0
  3. package/components/tryghost-html-to-plaintext-0.0.0.tgz +0 -0
  4. package/components/tryghost-job-manager-0.0.0.tgz +0 -0
  5. package/components/tryghost-magic-link-0.0.0.tgz +0 -0
  6. package/components/tryghost-members-api-0.0.0.tgz +0 -0
  7. package/components/tryghost-members-offers-0.0.0.tgz +0 -0
  8. package/components/tryghost-members-ssr-0.0.0.tgz +0 -0
  9. package/components/tryghost-members-stripe-service-0.0.0.tgz +0 -0
  10. package/components/tryghost-minifier-0.0.0.tgz +0 -0
  11. package/components/tryghost-security-0.0.0.tgz +0 -0
  12. package/content/themes/casper/assets/built/screen.css +1 -1
  13. package/content/themes/casper/assets/built/screen.css.map +1 -1
  14. package/content/themes/casper/assets/css/screen.css +21 -0
  15. package/content/themes/casper/package.json +1 -1
  16. package/core/built/admin/assets/chunk.143.904e017ad397bb681e9d.js +41 -0
  17. package/core/built/admin/assets/chunk.174.eec7f6398cef4c3e2485.js +239 -0
  18. package/core/built/admin/assets/chunk.178.9541bdb92bded29cd60d.js +11 -0
  19. package/core/built/admin/assets/chunk.351.cbc224ca65c14ef5322d.js +9272 -0
  20. package/core/built/admin/assets/chunk.351.cbc224ca65c14ef5322d.js.LICENSE.txt +138 -0
  21. package/core/built/{assets/codemirror/codemirror-30201ab2cff61db847193fc9f5ed922d.js → admin/assets/codemirror/codemirror-1b460af155bb0ecaab9591678ac8c942.js} +1 -1
  22. package/core/built/{assets → admin/assets}/fonts/Inter.ttf +0 -0
  23. package/core/built/{assets/ghost.min-ff9ba089fd81cb40831f4b62e63a2ca9.js → admin/assets/ghost-a66a04418efe85083a3adca0fb16bb52.js} +320 -306
  24. package/core/built/admin/assets/ghost-b469423d0fbe5e40af17b560f7e3cead.css +1 -0
  25. package/core/built/admin/assets/ghost-dark-bcb6f4517a2dfe23a0a280632bfca00c.css +1 -0
  26. package/core/built/{assets → admin/assets}/icons/account-group.svg +0 -0
  27. package/core/built/{assets → admin/assets}/icons/activity-placeholder.svg +0 -0
  28. package/core/built/{assets → admin/assets}/icons/add-stroke.svg +0 -0
  29. package/core/built/{assets → admin/assets}/icons/add-view.svg +0 -0
  30. package/core/built/{assets → admin/assets}/icons/add.svg +0 -0
  31. package/core/built/{assets → admin/assets}/icons/align-center.svg +0 -0
  32. package/core/built/{assets → admin/assets}/icons/align-left.svg +0 -0
  33. package/core/built/{assets → admin/assets}/icons/ambulance.svg +0 -0
  34. package/core/built/{assets → admin/assets}/icons/analytics.svg +0 -0
  35. package/core/built/{assets → admin/assets}/icons/arrow-down-small.svg +0 -0
  36. package/core/built/{assets → admin/assets}/icons/arrow-down-stroke.svg +0 -0
  37. package/core/built/{assets → admin/assets}/icons/arrow-down.svg +0 -0
  38. package/core/built/{assets → admin/assets}/icons/arrow-left-small.svg +0 -0
  39. package/core/built/{assets → admin/assets}/icons/arrow-left-stroke.svg +0 -0
  40. package/core/built/{assets → admin/assets}/icons/arrow-left-tail.svg +0 -0
  41. package/core/built/{assets → admin/assets}/icons/arrow-left.svg +0 -0
  42. package/core/built/{assets → admin/assets}/icons/arrow-right-small.svg +0 -0
  43. package/core/built/{assets → admin/assets}/icons/arrow-right-stroke.svg +0 -0
  44. package/core/built/{assets → admin/assets}/icons/arrow-right-tail.svg +0 -0
  45. package/core/built/{assets → admin/assets}/icons/arrow-right.svg +0 -0
  46. package/core/built/{assets → admin/assets}/icons/arrow-up-small.svg +0 -0
  47. package/core/built/{assets → admin/assets}/icons/arrow-up-stroke.svg +0 -0
  48. package/core/built/{assets → admin/assets}/icons/arrow-up.svg +0 -0
  49. package/core/built/{assets → admin/assets}/icons/arrow2-down.svg +0 -0
  50. package/core/built/{assets → admin/assets}/icons/arrow2-right.svg +0 -0
  51. package/core/built/{assets → admin/assets}/icons/audio-file.svg +0 -0
  52. package/core/built/{assets → admin/assets}/icons/audio-upload.svg +0 -0
  53. package/core/built/{assets → admin/assets}/icons/book-open.svg +0 -0
  54. package/core/built/{assets → admin/assets}/icons/bookmark-article.svg +0 -0
  55. package/core/built/{assets → admin/assets}/icons/box-hands.svg +0 -0
  56. package/core/built/{assets → admin/assets}/icons/box.svg +0 -0
  57. package/core/built/{assets → admin/assets}/icons/boxes.svg +0 -0
  58. package/core/built/{assets → admin/assets}/icons/brackets.svg +0 -0
  59. package/core/built/{assets → admin/assets}/icons/button.svg +0 -0
  60. package/core/built/{assets → admin/assets}/icons/calendar.svg +0 -0
  61. package/core/built/{assets → admin/assets}/icons/cash.svg +0 -0
  62. package/core/built/{assets → admin/assets}/icons/chat-double-bubble.svg +0 -0
  63. package/core/built/{assets → admin/assets}/icons/check-2.svg +0 -0
  64. package/core/built/{assets → admin/assets}/icons/check-circle-stroke.svg +0 -0
  65. package/core/built/{assets → admin/assets}/icons/check-circle.svg +0 -0
  66. package/core/built/{assets → admin/assets}/icons/check.svg +0 -0
  67. package/core/built/{assets → admin/assets}/icons/cheeseburger.svg +0 -0
  68. package/core/built/{assets → admin/assets}/icons/circle-ellipsis.svg +0 -0
  69. package/core/built/{assets → admin/assets}/icons/clock.svg +0 -0
  70. package/core/built/{assets → admin/assets}/icons/clockface.svg +0 -0
  71. package/core/built/{assets → admin/assets}/icons/close-stroke.svg +0 -0
  72. package/core/built/{assets → admin/assets}/icons/close.svg +0 -0
  73. package/core/built/{assets → admin/assets}/icons/cloud.svg +0 -0
  74. package/core/built/{assets → admin/assets}/icons/compass-2.svg +0 -0
  75. package/core/built/{assets → admin/assets}/icons/compass.svg +0 -0
  76. package/core/built/{assets → admin/assets}/icons/computer.svg +0 -0
  77. package/core/built/{assets → admin/assets}/icons/confetti.svg +0 -0
  78. package/core/built/{assets → admin/assets}/icons/content-bold.svg +0 -0
  79. package/core/built/{assets → admin/assets}/icons/content.svg +0 -0
  80. package/core/built/{assets → admin/assets}/icons/copy.svg +0 -0
  81. package/core/built/{assets → admin/assets}/icons/credit-card.svg +0 -0
  82. package/core/built/{assets → admin/assets}/icons/cross-circle.svg +0 -0
  83. package/core/built/{assets → admin/assets}/icons/cycle.svg +0 -0
  84. package/core/built/{assets → admin/assets}/icons/default-favicon.svg +0 -0
  85. package/core/built/{assets → admin/assets}/icons/desert.svg +0 -0
  86. package/core/built/{assets → admin/assets}/icons/desktop.svg +0 -0
  87. package/core/built/{assets → admin/assets}/icons/diamond.svg +0 -0
  88. package/core/built/{assets → admin/assets}/icons/discount-bubble.svg +0 -0
  89. package/core/built/{assets → admin/assets}/icons/dividers.svg +0 -0
  90. package/core/built/{assets → admin/assets}/icons/dotdotdot.svg +0 -0
  91. package/core/built/{assets → admin/assets}/icons/download-circle.svg +0 -0
  92. package/core/built/{assets → admin/assets}/icons/download.svg +0 -0
  93. package/core/built/{assets → admin/assets}/icons/eco-globe.svg +0 -0
  94. package/core/built/{assets → admin/assets}/icons/eco-lightbulb.svg +0 -0
  95. package/core/built/{assets → admin/assets}/icons/edit-view.svg +0 -0
  96. package/core/built/{assets → admin/assets}/icons/ellipsis.svg +0 -0
  97. package/core/built/{assets → admin/assets}/icons/email-at.svg +0 -0
  98. package/core/built/{assets → admin/assets}/icons/email-body.svg +0 -0
  99. package/core/built/{assets → admin/assets}/icons/email-footer.svg +0 -0
  100. package/core/built/{assets → admin/assets}/icons/email-header.svg +0 -0
  101. package/core/built/{assets → admin/assets}/icons/email-love-letter.svg +0 -0
  102. package/core/built/{assets → admin/assets}/icons/email-member.svg +0 -0
  103. package/core/built/{assets → admin/assets}/icons/email-name.svg +0 -0
  104. package/core/built/{assets → admin/assets}/icons/email-send.svg +0 -0
  105. package/core/built/{assets → admin/assets}/icons/email-stroke.svg +0 -0
  106. package/core/built/{assets → admin/assets}/icons/email-unread.svg +0 -0
  107. package/core/built/{assets → admin/assets}/icons/email.svg +0 -0
  108. package/core/built/{assets → admin/assets}/icons/event-canceled-subscription.svg +0 -0
  109. package/core/built/{assets → admin/assets}/icons/event-comment.svg +0 -0
  110. package/core/built/{assets → admin/assets}/icons/event-email-delivery-failed.svg +0 -0
  111. package/core/built/{assets → admin/assets}/icons/event-logged-in.svg +0 -0
  112. package/core/built/{assets → admin/assets}/icons/event-made-a-payment.svg +0 -0
  113. package/core/built/{assets → admin/assets}/icons/event-opened-email.svg +0 -0
  114. package/core/built/{assets → admin/assets}/icons/event-received-email.svg +0 -0
  115. package/core/built/{assets → admin/assets}/icons/event-signed-up.svg +0 -0
  116. package/core/built/{assets → admin/assets}/icons/event-subscribed-to-email.svg +0 -0
  117. package/core/built/{assets → admin/assets}/icons/event-subscriptions.svg +0 -0
  118. package/core/built/{assets → admin/assets}/icons/event-unsubscribed-from-email.svg +0 -0
  119. package/core/built/{assets → admin/assets}/icons/expand.svg +0 -0
  120. package/core/built/{assets → admin/assets}/icons/external.svg +0 -0
  121. package/core/built/{assets → admin/assets}/icons/eye.svg +0 -0
  122. package/core/built/{assets → admin/assets}/icons/facebook-heart.svg +0 -0
  123. package/core/built/{assets → admin/assets}/icons/facebook-like.svg +0 -0
  124. package/core/built/{assets → admin/assets}/icons/facebook.svg +0 -0
  125. package/core/built/{assets → admin/assets}/icons/feature-image.svg +0 -0
  126. package/core/built/{assets → admin/assets}/icons/file-download.svg +0 -0
  127. package/core/built/{assets → admin/assets}/icons/file-tabular-data.svg +0 -0
  128. package/core/built/{assets → admin/assets}/icons/file-text-document.svg +0 -0
  129. package/core/built/{assets → admin/assets}/icons/file-upload.svg +0 -0
  130. package/core/built/{assets → admin/assets}/icons/film-camera.svg +0 -0
  131. package/core/built/{assets → admin/assets}/icons/filter.svg +0 -0
  132. package/core/built/{assets → admin/assets}/icons/firstpromoter-ce8b5219e5b5ebda463bd60396c6ab81.png +0 -0
  133. package/core/built/{assets → admin/assets}/icons/folder.svg +0 -0
  134. package/core/built/{assets → admin/assets}/icons/gallery-placeholder.svg +0 -0
  135. package/core/built/{assets → admin/assets}/icons/get-started-import.svg +0 -0
  136. package/core/built/{assets → admin/assets}/icons/get-started-members.svg +0 -0
  137. package/core/built/{assets → admin/assets}/icons/get-started-migrations.svg +0 -0
  138. package/core/built/{assets → admin/assets}/icons/get-started.svg +0 -0
  139. package/core/built/{assets → admin/assets}/icons/ghost-logo-orb.svg +0 -0
  140. package/core/built/{assets → admin/assets}/icons/ghost-logo.svg +0 -0
  141. package/core/built/{assets → admin/assets}/icons/ghost-orb.svg +0 -0
  142. package/core/built/{assets → admin/assets}/icons/ghost-squircle.svg +0 -0
  143. package/core/built/{assets → admin/assets}/icons/gift.svg +0 -0
  144. package/core/built/{assets → admin/assets}/icons/github-outline.svg +0 -0
  145. package/core/built/{assets → admin/assets}/icons/github-star.svg +0 -0
  146. package/core/built/{assets → admin/assets}/icons/github.svg +0 -0
  147. package/core/built/{assets → admin/assets}/icons/globe.svg +0 -0
  148. package/core/built/{assets → admin/assets}/icons/google-favicon.svg +0 -0
  149. package/core/built/{assets → admin/assets}/icons/google-search.svg +0 -0
  150. package/core/built/{assets → admin/assets}/icons/google.svg +0 -0
  151. package/core/built/{assets → admin/assets}/icons/grab.svg +0 -0
  152. package/core/built/{assets → admin/assets}/icons/graph-line.svg +0 -0
  153. package/core/built/{assets → admin/assets}/icons/heart-beat.svg +0 -0
  154. package/core/built/{assets → admin/assets}/icons/heart-circle.svg +0 -0
  155. package/core/built/{assets → admin/assets}/icons/heart.svg +0 -0
  156. package/core/built/{assets → admin/assets}/icons/help.svg +0 -0
  157. package/core/built/{assets → admin/assets}/icons/hotspot.svg +0 -0
  158. package/core/built/{assets → admin/assets}/icons/house-bold.svg +0 -0
  159. package/core/built/{assets → admin/assets}/icons/house.svg +0 -0
  160. package/core/built/{assets → admin/assets}/icons/icon.svg +0 -0
  161. package/core/built/{assets → admin/assets}/icons/id-card.svg +0 -0
  162. package/core/built/{assets → admin/assets}/icons/idea.svg +0 -0
  163. package/core/built/{assets → admin/assets}/icons/info.svg +0 -0
  164. package/core/built/{assets → admin/assets}/icons/instagram.svg +0 -0
  165. package/core/built/{assets → admin/assets}/icons/integration.svg +0 -0
  166. package/core/built/{assets → admin/assets}/icons/labs.svg +0 -0
  167. package/core/built/{assets → admin/assets}/icons/laptop.svg +0 -0
  168. package/core/built/{assets → admin/assets}/icons/line.svg +0 -0
  169. package/core/built/{assets → admin/assets}/icons/link.svg +0 -0
  170. package/core/built/{assets → admin/assets}/icons/list-bullet.svg +0 -0
  171. package/core/built/{assets → admin/assets}/icons/list-number.svg +0 -0
  172. package/core/built/{assets → admin/assets}/icons/lock.svg +0 -0
  173. package/core/built/{assets → admin/assets}/icons/lock2.svg +0 -0
  174. package/core/built/{assets → admin/assets}/icons/loop-infinite.svg +0 -0
  175. package/core/built/{assets → admin/assets}/icons/lotus.svg +0 -0
  176. package/core/built/{assets → admin/assets}/icons/markdown.svg +0 -0
  177. package/core/built/{assets → admin/assets}/icons/member-add.svg +0 -0
  178. package/core/built/{assets → admin/assets}/icons/member.svg +0 -0
  179. package/core/built/{assets → admin/assets}/icons/members-all.svg +0 -0
  180. package/core/built/{assets → admin/assets}/icons/members-bold.svg +0 -0
  181. package/core/built/{assets → admin/assets}/icons/members-outline.svg +0 -0
  182. package/core/built/{assets → admin/assets}/icons/members-paid.svg +0 -0
  183. package/core/built/{assets → admin/assets}/icons/members-placeholder.svg +0 -0
  184. package/core/built/{assets → admin/assets}/icons/members-post.svg +0 -0
  185. package/core/built/{assets → admin/assets}/icons/members-segment.svg +0 -0
  186. package/core/built/{assets → admin/assets}/icons/members.svg +0 -0
  187. package/core/built/{assets → admin/assets}/icons/mobile-phone-heart.svg +0 -0
  188. package/core/built/{assets → admin/assets}/icons/mobile-phone.svg +0 -0
  189. package/core/built/{assets → admin/assets}/icons/module.svg +0 -0
  190. package/core/built/{assets → admin/assets}/icons/modules.svg +0 -0
  191. package/core/built/{assets → admin/assets}/icons/monitor-labs.svg +0 -0
  192. package/core/built/{assets → admin/assets}/icons/moon.svg +0 -0
  193. package/core/built/{assets → admin/assets}/icons/mountains.svg +0 -0
  194. package/core/built/{assets → admin/assets}/icons/mute.svg +0 -0
  195. package/core/built/{assets → admin/assets}/icons/navigation.svg +0 -0
  196. package/core/built/{assets → admin/assets}/icons/network.svg +0 -0
  197. package/core/built/{assets → admin/assets}/icons/news-article.svg +0 -0
  198. package/core/built/{assets → admin/assets}/icons/nightshift.svg +0 -0
  199. package/core/built/{assets → admin/assets}/icons/no-data-line-chart.svg +0 -0
  200. package/core/built/{assets → admin/assets}/icons/no-data-list.svg +0 -0
  201. package/core/built/{assets → admin/assets}/icons/no-data-subscription.svg +0 -0
  202. package/core/built/{assets → admin/assets}/icons/no-email.svg +0 -0
  203. package/core/built/{assets → admin/assets}/icons/no-members.svg +0 -0
  204. package/core/built/{assets → admin/assets}/icons/offer.svg +0 -0
  205. package/core/built/{assets → admin/assets}/icons/page-bold.svg +0 -0
  206. package/core/built/{assets → admin/assets}/icons/page.svg +0 -0
  207. package/core/built/{assets → admin/assets}/icons/pages-placeholder.svg +0 -0
  208. package/core/built/{assets → admin/assets}/icons/paint-palette.svg +0 -0
  209. package/core/built/{assets → admin/assets}/icons/paintbrush.svg +0 -0
  210. package/core/built/{assets → admin/assets}/icons/pause.svg +0 -0
  211. package/core/built/{assets → admin/assets}/icons/pen.svg +0 -0
  212. package/core/built/{assets → admin/assets}/icons/pencil-circle.svg +0 -0
  213. package/core/built/{assets → admin/assets}/icons/pencil.svg +0 -0
  214. package/core/built/{assets → admin/assets}/icons/percentage.svg +0 -0
  215. package/core/built/{assets → admin/assets}/icons/photos-people.svg +0 -0
  216. package/core/built/{assets → admin/assets}/icons/photos.svg +0 -0
  217. package/core/built/{assets → admin/assets}/icons/piggy-bank.svg +0 -0
  218. package/core/built/{assets → admin/assets}/icons/pin.svg +0 -0
  219. package/core/built/{assets → admin/assets}/icons/plane.svg +0 -0
  220. package/core/built/{assets → admin/assets}/icons/play.svg +0 -0
  221. package/core/built/{assets → admin/assets}/icons/plus.svg +0 -0
  222. package/core/built/{assets → admin/assets}/icons/portal-icon-1.svg +0 -0
  223. package/core/built/{assets → admin/assets}/icons/portal-icon-2.svg +0 -0
  224. package/core/built/{assets → admin/assets}/icons/portal-icon-3.svg +0 -0
  225. package/core/built/{assets → admin/assets}/icons/portal-icon-4.svg +0 -0
  226. package/core/built/{assets → admin/assets}/icons/portal-icon-5.svg +0 -0
  227. package/core/built/{assets → admin/assets}/icons/portal-logo-stroke.svg +0 -0
  228. package/core/built/{assets → admin/assets}/icons/portal-logo.svg +0 -0
  229. package/core/built/{assets → admin/assets}/icons/post.svg +0 -0
  230. package/core/built/{assets → admin/assets}/icons/posts-placeholder.svg +0 -0
  231. package/core/built/{assets → admin/assets}/icons/posts.svg +0 -0
  232. package/core/built/{assets → admin/assets}/icons/powered-by-stripe.svg +0 -0
  233. package/core/built/{assets → admin/assets}/icons/powered-by-tenor.svg +0 -0
  234. package/core/built/{assets → admin/assets}/icons/presentation-code.svg +0 -0
  235. package/core/built/{assets → admin/assets}/icons/published-post.svg +0 -0
  236. package/core/built/{assets → admin/assets}/icons/recycle.svg +0 -0
  237. package/core/built/{assets → admin/assets}/icons/reload.svg +0 -0
  238. package/core/built/{assets → admin/assets}/icons/repo.svg +0 -0
  239. package/core/built/{assets → admin/assets}/icons/retry.svg +0 -0
  240. package/core/built/{assets → admin/assets}/icons/satellite.svg +0 -0
  241. package/core/built/{assets → admin/assets}/icons/search.svg +0 -0
  242. package/core/built/{assets → admin/assets}/icons/send-email.svg +0 -0
  243. package/core/built/{assets → admin/assets}/icons/server.svg +0 -0
  244. package/core/built/{assets → admin/assets}/icons/settings.svg +0 -0
  245. package/core/built/{assets → admin/assets}/icons/shield-lock.svg +0 -0
  246. package/core/built/{assets → admin/assets}/icons/shield.svg +0 -0
  247. package/core/built/{assets → admin/assets}/icons/sidemenu-open.svg +0 -0
  248. package/core/built/{assets → admin/assets}/icons/sidemenu.svg +0 -0
  249. package/core/built/{assets → admin/assets}/icons/signal-tower.svg +0 -0
  250. package/core/built/{assets → admin/assets}/icons/signout.svg +0 -0
  251. package/core/built/{assets → admin/assets}/icons/smiley.svg +0 -0
  252. package/core/built/{assets → admin/assets}/icons/social-facebook.svg +0 -0
  253. package/core/built/{assets → admin/assets}/icons/social-share.svg +0 -0
  254. package/core/built/{assets → admin/assets}/icons/social-twitter.svg +0 -0
  255. package/core/built/{assets → admin/assets}/icons/spinner.svg +0 -0
  256. package/core/built/{assets → admin/assets}/icons/staff.svg +0 -0
  257. package/core/built/{assets → admin/assets}/icons/star-filled.svg +0 -0
  258. package/core/built/{assets → admin/assets}/icons/store.svg +0 -0
  259. package/core/built/{assets → admin/assets}/icons/stripe-verified-partner-badge.svg +0 -0
  260. package/core/built/{assets → admin/assets}/icons/summer.svg +0 -0
  261. package/core/built/{assets → admin/assets}/icons/sun.svg +0 -0
  262. package/core/built/{assets → admin/assets}/icons/support.svg +0 -0
  263. package/core/built/{assets → admin/assets}/icons/sync.svg +0 -0
  264. package/core/built/{assets → admin/assets}/icons/tag.svg +0 -0
  265. package/core/built/{assets → admin/assets}/icons/tags-placeholder.svg +0 -0
  266. package/core/built/{assets → admin/assets}/icons/tenor.svg +0 -0
  267. package/core/built/{assets → admin/assets}/icons/terminal.svg +0 -0
  268. package/core/built/{assets → admin/assets}/icons/text-vector.svg +0 -0
  269. package/core/built/{assets → admin/assets}/icons/text.svg +0 -0
  270. package/core/built/{assets → admin/assets}/icons/theme.svg +0 -0
  271. package/core/built/{assets → admin/assets}/icons/ticket.svg +0 -0
  272. package/core/built/{assets → admin/assets}/icons/trash.svg +0 -0
  273. package/core/built/{assets → admin/assets}/icons/trophy.svg +0 -0
  274. package/core/built/{assets → admin/assets}/icons/tumbleweed.svg +0 -0
  275. package/core/built/{assets → admin/assets}/icons/twitter-comment.svg +0 -0
  276. package/core/built/{assets → admin/assets}/icons/twitter-like.svg +0 -0
  277. package/core/built/{assets → admin/assets}/icons/twitter-link.svg +0 -0
  278. package/core/built/{assets → admin/assets}/icons/twitter-logo.svg +0 -0
  279. package/core/built/{assets → admin/assets}/icons/twitter-retweet.svg +0 -0
  280. package/core/built/{assets → admin/assets}/icons/twitter-share.svg +0 -0
  281. package/core/built/{assets → admin/assets}/icons/twitter.svg +0 -0
  282. package/core/built/{assets → admin/assets}/icons/ufo-attack.svg +0 -0
  283. package/core/built/{assets → admin/assets}/icons/unmute.svg +0 -0
  284. package/core/built/{assets → admin/assets}/icons/unsplash-heart.svg +0 -0
  285. package/core/built/{assets → admin/assets}/icons/unsplash.svg +0 -0
  286. package/core/built/{assets → admin/assets}/icons/unsubscribed.svg +0 -0
  287. package/core/built/{assets → admin/assets}/icons/upload-fill.svg +0 -0
  288. package/core/built/{assets → admin/assets}/icons/upload.svg +0 -0
  289. package/core/built/{assets → admin/assets}/icons/user-circle.svg +0 -0
  290. package/core/built/{assets → admin/assets}/icons/user-group.svg +0 -0
  291. package/core/built/{assets → admin/assets}/icons/user-group2.svg +0 -0
  292. package/core/built/{assets → admin/assets}/icons/v-ellipsis.svg +0 -0
  293. package/core/built/{assets → admin/assets}/icons/view-site.svg +0 -0
  294. package/core/built/{assets → admin/assets}/icons/warning-stroke.svg +0 -0
  295. package/core/built/{assets → admin/assets}/icons/warning.svg +0 -0
  296. package/core/built/{assets → admin/assets}/icons/window-app.svg +0 -0
  297. package/core/built/{assets → admin/assets}/icons/window-pulse.svg +0 -0
  298. package/core/built/{assets → admin/assets}/icons/wrench-double.svg +0 -0
  299. package/core/built/{assets → admin/assets}/icons/zap.svg +0 -0
  300. package/core/built/{assets → admin/assets}/img/404-ghost-e112dbfadde79cf30dbca8e8cfe7a21a.png +0 -0
  301. package/core/built/{assets → admin/assets}/img/404-ghost@2x-34c1119ed15cc3ea71e4406f80c8e810.png +0 -0
  302. package/core/built/{assets → admin/assets}/img/abstract-2-2937e2902b64360d0cbe4cec8bd8479b.jpg +0 -0
  303. package/core/built/{assets → admin/assets}/img/abstract-c52b2f4208e7fd2e7b8abd8b1eec4f7b.jpg +0 -0
  304. package/core/built/{assets → admin/assets}/img/amp.svg +0 -0
  305. package/core/built/{assets → admin/assets}/img/apple-touch-icon-74680e326a7e87b159d366c7d4fb3d4b.png +0 -0
  306. package/core/built/{assets → admin/assets}/img/buffer-db31f6b5dc27a298050e16312619c586.png +0 -0
  307. package/core/built/{assets → admin/assets}/img/community-background-3f501ff1d764d0cb81f7c2cbacfc6503.jpg +0 -0
  308. package/core/built/{assets → admin/assets}/img/community-be8c1dcecfb157f2bfba5cababc8e686.jpg +0 -0
  309. package/core/built/{assets → admin/assets}/img/dashboard/bp1-03a13253453b372d0bbd5e6a19b20fca.jpg +0 -0
  310. package/core/built/{assets → admin/assets}/img/dashboard/bp2-ed14f9f48c56d5d6fe997dc637a8b1ad.jpg +0 -0
  311. package/core/built/{assets → admin/assets}/img/dashboard/join-community-bb5478f7dca6c04a2d0baf2b02f880fb.jpg +0 -0
  312. package/core/built/{assets → admin/assets}/img/dashboard-feature-image-8949197550decb94a8f1dea57ad47819.jpeg +0 -0
  313. package/core/built/{assets → admin/assets}/img/disqus.svg +0 -0
  314. package/core/built/{assets → admin/assets}/img/favicon.ico +0 -0
  315. package/core/built/{assets → admin/assets}/img/firstpromoter-ce8b5219e5b5ebda463bd60396c6ab81.png +0 -0
  316. package/core/built/{assets → admin/assets}/img/footer-marketplace-bg-572b6c6486a7e26316954d599eaa9f30.png +0 -0
  317. package/core/built/{assets → admin/assets}/img/get-started-995c36b9ede90bb3777c83751e798ef7.jpg +0 -0
  318. package/core/built/{assets → admin/assets}/img/github.svg +0 -0
  319. package/core/built/{assets → admin/assets}/img/google-analytics-e05fc1327377939663407200d4978eba.png +0 -0
  320. package/core/built/{assets → admin/assets}/img/google-docs.svg +0 -0
  321. package/core/built/{assets → admin/assets}/img/install-welcome-ff3912d18bf8949df89c83b1c3b8bb66.png +0 -0
  322. package/core/built/{assets → admin/assets}/img/invite-placeholder-4b3731d47c6c8f6cb3aaa6bc4d870c9f.png +0 -0
  323. package/core/built/{assets → admin/assets}/img/large-ac90af7c93a4b47e8d956fa9fef31d9d.png +0 -0
  324. package/core/built/{assets → admin/assets}/img/launch-wizard-bg-13b995b1f02bce34b269db3190897384.png +0 -0
  325. package/core/built/{assets → admin/assets}/img/loadingcat-5f501b7a8c7bd54b253463e261c99634.gif +0 -0
  326. package/core/built/{assets → admin/assets}/img/logos/ghost-logo-black-1-fb561a374422b405ec90fa586b05ebdf.png +0 -0
  327. package/core/built/{assets → admin/assets}/img/logos/orb-black-1-32b72766be2164fdea6ab2565fb1c137.png +0 -0
  328. package/core/built/{assets → admin/assets}/img/logos/orb-black-2-4b0baef1ec34816af6f3fbede7ab191d.png +0 -0
  329. package/core/built/{assets → admin/assets}/img/logos/orb-black-3-9780c5e9991b69ed2303b526aa3e3252.png +0 -0
  330. package/core/built/{assets → admin/assets}/img/logos/orb-black-4-d9c3caacb8d2ba98a52517ff2971433c.png +0 -0
  331. package/core/built/{assets → admin/assets}/img/logos/orb-black-5-063a200f749e09c587b9443ffd2c4cfa.png +0 -0
  332. package/core/built/{assets → admin/assets}/img/mailchimp.svg +0 -0
  333. package/core/built/{assets → admin/assets}/img/marketing/members-1-8b89a1f48fe7b336754e91a429531f65.jpg +0 -0
  334. package/core/built/{assets → admin/assets}/img/marketing/members-2-791205c82d5cf221f8c99a74f9ee1739.jpg +0 -0
  335. package/core/built/{assets → admin/assets}/img/marketing/offers-1-f2e1b653c4d5bb90eea9d7a2862530f9.jpg +0 -0
  336. package/core/built/{assets → admin/assets}/img/marketing/offers-2-28a225d34cc39d133748431536961d00.jpg +0 -0
  337. package/core/built/{assets → admin/assets}/img/marketing/offers-3-2094c91ab21a16c37fbe6ec16c140160.jpg +0 -0
  338. package/core/built/{assets → admin/assets}/img/medium-fef07013cffd5c45a655a250912a0ad7.png +0 -0
  339. package/core/built/{assets → admin/assets}/img/more-fe5480ab76c7be7aec28bcfe844f41c1.png +0 -0
  340. package/core/built/{assets → admin/assets}/img/newsletter-1-197ae8063dfb2e22278d355198029c9e.jpg +0 -0
  341. package/core/built/{assets → admin/assets}/img/newsletter-2-5a2c7693ea9380d4282061302c01267a.jpg +0 -0
  342. package/core/built/{assets → admin/assets}/img/orb-squircle-645fd62e92a80557905c0cb60874b699.png +0 -0
  343. package/core/built/{assets → admin/assets}/img/patreon.svg +0 -0
  344. package/core/built/{assets → admin/assets}/img/paypal.svg +0 -0
  345. package/core/built/{assets → admin/assets}/img/plausible-1b754a95e19a6d935e0bc8bf6790ba56.png +0 -0
  346. package/core/built/{assets → admin/assets}/img/resource-1-722f202795856e4a5596c8a3b7bedc43.jpg +0 -0
  347. package/core/built/{assets → admin/assets}/img/slackicon-406aadea8994ca2ddee9c1d7157208db.png +0 -0
  348. package/core/built/{assets → admin/assets}/img/small-b90396925485f17b2ca82c31be42de5f.png +0 -0
  349. package/core/built/{assets → admin/assets}/img/themes/Alto-a5172a42994782321d8c9f268928d987.jpg +0 -0
  350. package/core/built/{assets → admin/assets}/img/themes/Alto-cut-c667d9d6457c5e981aa7bdc8946b215a.jpg +0 -0
  351. package/core/built/{assets → admin/assets}/img/themes/Alto-f4db5af43ca9771c7ac1f754de3ddf2f.png +0 -0
  352. package/core/built/{assets → admin/assets}/img/themes/Bulletin-57d45b992ff0e26e0acdce7ed4cccd67.png +0 -0
  353. package/core/built/{assets → admin/assets}/img/themes/Casper-19b7267aac5acc6abfaaed7e41eddae8.jpg +0 -0
  354. package/core/built/{assets → admin/assets}/img/themes/Dawn-be81aa8c8caae8fcfb5d5fbec823fdcc.png +0 -0
  355. package/core/built/{assets → admin/assets}/img/themes/Digest-d3467ac22a290e1ad3a543014758286e.png +0 -0
  356. package/core/built/{assets → admin/assets}/img/themes/Dope-6f8e0bbc199ce4af9a60859e9e6a74ad.png +0 -0
  357. package/core/built/{assets → admin/assets}/img/themes/Ease-7cfb8f06f9b66b1aa04b92493a471fef.jpg +0 -0
  358. package/core/built/{assets → admin/assets}/img/themes/Ease-9c279ea6cec3c0f1823f81c9dd24b116.png +0 -0
  359. package/core/built/{assets → admin/assets}/img/themes/Ease-cut-78d5aa00682bee6a4cf22155f09e49e8.jpg +0 -0
  360. package/core/built/{assets → admin/assets}/img/themes/Edge-0258906309e11fd075a1d9880aa09b20.png +0 -0
  361. package/core/built/{assets → admin/assets}/img/themes/Edition-b94372eb5c88fce0f4befba39148ff28.jpg +0 -0
  362. package/core/built/{assets → admin/assets}/img/themes/Edition-cut-e6545bab2768aafa1996100774f310ff.jpg +0 -0
  363. package/core/built/{assets → admin/assets}/img/themes/Edition-d8f508e93bc24bdf2716ae6f8b3d44f8.png +0 -0
  364. package/core/built/{assets → admin/assets}/img/themes/Headline-c5070cf549e797a6a72b87237caa1617.jpg +0 -0
  365. package/core/built/{assets → admin/assets}/img/themes/Journal-accf0031bbae0919900a049061e65a04.png +0 -0
  366. package/core/built/{assets → admin/assets}/img/themes/London-3f07efcee9e5bfb9a33827064eb77e70.jpg +0 -0
  367. package/core/built/{assets → admin/assets}/img/themes/London-cut-599cba221f81a15ad37fe395cf4e572c.jpg +0 -0
  368. package/core/built/{assets → admin/assets}/img/themes/Ruby-11a53c62015612f4b3aca8f503121225.png +0 -0
  369. package/core/built/{assets → admin/assets}/img/themes/Wave-86e8044c2d76cb57a9030e4c24ac9520.png +0 -0
  370. package/core/built/{assets → admin/assets}/img/touch-icon-ipad-2e78629d62ad05746f980f14623dfadb.png +0 -0
  371. package/core/built/{assets → admin/assets}/img/touch-icon-iphone-93ed4382d391be9180093fd77ce8f410.png +0 -0
  372. package/core/built/{assets → admin/assets}/img/twitter.svg +0 -0
  373. package/core/built/{assets → admin/assets}/img/typeform.svg +0 -0
  374. package/core/built/{assets → admin/assets}/img/ulysses-3c66b59fb45c285bf336b4b613dc86e4.png +0 -0
  375. package/core/built/{assets → admin/assets}/img/unsplash-404-71ab3705c9920a9706bb822c3d7e34d1.png +0 -0
  376. package/core/built/{assets → admin/assets}/img/user-cover-e8f42b12b5fcba292a8b5dfa81e13dd2.png +0 -0
  377. package/core/built/{assets → admin/assets}/img/user-image-639a88b784fb5f10964be8b975ca9fdf.png +0 -0
  378. package/core/built/{assets → admin/assets}/img/users-33427addfe0f11c78b42cccaf83be073.png +0 -0
  379. package/core/built/{assets → admin/assets}/img/whats-new-header-bg.svg +0 -0
  380. package/core/built/{assets → admin/assets}/img/zapier-logo.svg +0 -0
  381. package/core/built/{assets → admin/assets}/img/zapier.svg +0 -0
  382. package/core/built/{assets → admin/assets}/img/zero-bounce-ee799eddb1f88e33ab8c462858cbfed9.png +0 -0
  383. package/core/built/{assets/simplemde/simplemde-fb4527da6e489b34dc24b28ea870b286.js → admin/assets/simplemde/simplemde-0cd04dbb388ed0cf571a6808464ea57e.js} +1 -1
  384. package/core/built/admin/assets/vendor-46baf13852f545c6c89756c8e0ccbff2.js +13821 -0
  385. package/core/built/{assets/vendor.min-4a6661c574707ceca220aa2e76558995.css → admin/assets/vendor-bc9d2c9e5c8a33f0c92e81189d48e04c.css} +17 -9
  386. package/core/{server/web/admin/views/default.html → built/admin/index.html} +13 -15
  387. package/core/frontend/helpers/comment_count.js +15 -9
  388. package/core/frontend/helpers/title.js +1 -1
  389. package/core/frontend/services/admin-auth-assets/service.js +19 -3
  390. package/core/frontend/src/admin-auth/message-handler.js +7 -3
  391. package/core/frontend/src/comment-counts/js/comment-counts.js +17 -2
  392. package/core/server/adapters/cache/Base.js +12 -0
  393. package/core/server/adapters/cache/Memory.js +36 -0
  394. package/core/server/adapters/cache/index.js +17 -0
  395. package/core/server/api/endpoints/comments-members.js +2 -19
  396. package/core/server/api/endpoints/index.js +1 -1
  397. package/core/server/api/endpoints/integrations.js +12 -8
  398. package/core/server/api/endpoints/utils/index.js +4 -0
  399. package/core/server/api/endpoints/utils/serializers/input/tiers.js +5 -0
  400. package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +8 -1
  401. package/core/server/api/endpoints/utils/serializers/output/tiers.js +5 -0
  402. package/core/server/api/endpoints/utils/serializers/output/utils/post-gating.js +1 -1
  403. package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -1
  404. package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -1
  405. package/core/server/data/migrations/versions/5.0/2022-05-21-00-00-regenerate-posts-html.js +1 -1
  406. package/core/server/data/migrations/versions/5.8/2022-08-02-06-09-add-trial-period-days-column-to-tiers.js +8 -0
  407. package/core/server/data/migrations/versions/5.8/2022-08-03-15-28-add-trial-start-column-to-stripe-subscriptions.js +6 -0
  408. package/core/server/data/migrations/versions/5.8/2022-08-03-15-29-add-trial-end-column-to-stripe-subscriptions.js +6 -0
  409. package/core/server/data/schema/schema.js +3 -0
  410. package/core/server/ghost-server.js +7 -0
  411. package/core/server/models/base/index.js +1 -1
  412. package/core/server/models/base/plugins/filtered-collection.js +3 -3
  413. package/core/server/models/comment.js +47 -15
  414. package/core/server/models/post.js +1 -1
  415. package/core/server/models/product.js +2 -1
  416. package/core/server/models/tag.js +1 -1
  417. package/core/server/models/user.js +2 -2
  418. package/core/server/services/adapter-manager/index.js +2 -1
  419. package/core/server/services/comments/controller.js +11 -1
  420. package/core/server/services/comments/email-templates/new-comment-reply.hbs +9 -11
  421. package/core/server/services/comments/email-templates/new-comment-reply.txt.js +1 -1
  422. package/core/server/services/comments/email-templates/new-comment.hbs +8 -10
  423. package/core/server/services/comments/email-templates/new-comment.txt.js +1 -1
  424. package/core/server/services/comments/email-templates/report.hbs +7 -9
  425. package/core/server/services/comments/email-templates/report.txt.js +1 -1
  426. package/core/server/services/comments/emails.js +4 -4
  427. package/core/server/services/comments/index.js +5 -1
  428. package/core/server/services/comments/service.js +3 -3
  429. package/core/server/services/comments/stats.js +44 -0
  430. package/core/server/services/mega/mega.js +1 -1
  431. package/core/server/services/mega/post-email-serializer.js +1 -1
  432. package/core/server/services/members/middleware.js +1 -1
  433. package/core/server/services/members/utils.js +1 -0
  434. package/core/server/services/settings/settings-service.js +3 -1
  435. package/core/server/services/url/Resources.js +1 -1
  436. package/core/server/web/admin/app.js +2 -1
  437. package/core/server/web/admin/controller.js +1 -2
  438. package/core/shared/config/defaults.json +7 -4
  439. package/core/shared/config/overrides.json +1 -2
  440. package/core/shared/labs.js +1 -1
  441. package/core/shared/settings-cache/cache.js +124 -87
  442. package/core/shared/settings-cache/index.js +6 -9
  443. package/loggingrc.js +1 -1
  444. package/package.json +33 -38
  445. package/yarn.lock +14494 -3715
  446. package/core/built/assets/chunk.3.33097bb5eb150719bdd2.js +0 -197
  447. package/core/built/assets/ghost-dark-1bdd57aba1fa4a23388121740454dab2.css +0 -1
  448. package/core/built/assets/ghost.min-8f5c061e0892b93adecc2b9e37ad2f3a.css +0 -1
  449. package/core/built/assets/vendor.min-3dd40d3052381526f38fd290d13baa47.js +0 -22339
  450. package/core/server/web/admin/views/default-prod.html +0 -63
  451. package/core/shared/html-to-plaintext.js +0 -80
@@ -2,13 +2,30 @@ const ghostBookshelf = require('./base');
2
2
  const _ = require('lodash');
3
3
  const errors = require('@tryghost/errors');
4
4
  const tpl = require('@tryghost/tpl');
5
+ const {ValidationError} = require('@tryghost/errors');
5
6
 
6
7
  const messages = {
8
+ emptyComment: 'The body of a comment cannot be empty',
7
9
  commentNotFound: 'Comment could not be found',
8
10
  notYourCommentToEdit: 'You may only edit your own comments',
9
- notYourCommentToDestroy: 'You may only delete your own comments'
11
+ notYourCommentToDestroy: 'You may only delete your own comments',
12
+ cannotEditDeletedComment: 'You may only edit published comments'
10
13
  };
11
14
 
15
+ /**
16
+ * Remove empty paragraps from the start and end
17
+ * + remove duplicate empty paragrapsh (only one empty line allowed)
18
+ */
19
+ function trimParagraphs(str) {
20
+ const paragraph = '<p></p>';
21
+ const escapedParagraph = '<p>\\s*?</p>';
22
+
23
+ const startReg = new RegExp('^(' + escapedParagraph + ')+');
24
+ const endReg = new RegExp('(' + escapedParagraph + ')+$');
25
+ const duplicates = new RegExp('(' + escapedParagraph + ')+');
26
+ return str.replace(startReg, '').replace(endReg, '').replace(duplicates, paragraph);
27
+ }
28
+
12
29
  const Comment = ghostBookshelf.Model.extend({
13
30
  tableName: 'comments',
14
31
 
@@ -46,23 +63,38 @@ const Comment = ghostBookshelf.Model.extend({
46
63
  onSaving() {
47
64
  ghostBookshelf.Model.prototype.onSaving.apply(this, arguments);
48
65
 
66
+ if (this.hasChanged('html') && this.get('status') !== 'published') {
67
+ throw new ValidationError({
68
+ message: tpl(messages.cannotEditDeletedComment)
69
+ });
70
+ }
71
+
49
72
  if (this.hasChanged('html')) {
50
73
  const sanitizeHtml = require('sanitize-html');
51
74
 
52
- this.set('html', sanitizeHtml(this.get('html'), {
53
- allowedTags: ['p', 'br', 'a', 'blockquote'],
54
- allowedAttributes: {
55
- a: ['href', 'target', 'rel']
56
- },
57
- selfClosing: ['br'],
58
- // Enforce _blank and safe URLs
59
- transformTags: {
60
- a: sanitizeHtml.simpleTransform('a', {
61
- target: '_blank',
62
- rel: 'ugc noopener noreferrer nofollow'
63
- })
64
- }
65
- }));
75
+ const html = trimParagraphs(
76
+ sanitizeHtml(this.get('html'), {
77
+ allowedTags: ['p', 'br', 'a', 'blockquote'],
78
+ allowedAttributes: {
79
+ a: ['href', 'target', 'rel']
80
+ },
81
+ selfClosing: ['br'],
82
+ // Enforce _blank and safe URLs
83
+ transformTags: {
84
+ a: sanitizeHtml.simpleTransform('a', {
85
+ target: '_blank',
86
+ rel: 'ugc noopener noreferrer nofollow'
87
+ })
88
+ }
89
+ })
90
+ ).trim();
91
+
92
+ if (html.length === 0) {
93
+ throw new ValidationError({
94
+ message: tpl(messages.emptyComment)
95
+ });
96
+ }
97
+ this.set('html', html);
66
98
  }
67
99
  },
68
100
 
@@ -7,7 +7,7 @@ const {sequence} = require('@tryghost/promise');
7
7
  const tpl = require('@tryghost/tpl');
8
8
  const errors = require('@tryghost/errors');
9
9
  const nql = require('@tryghost/nql');
10
- const htmlToPlaintext = require('../../shared/html-to-plaintext');
10
+ const htmlToPlaintext = require('@tryghost/html-to-plaintext');
11
11
  const ghostBookshelf = require('./base');
12
12
  const config = require('../../shared/config');
13
13
  const settingsCache = require('../../shared/settings-cache');
@@ -6,7 +6,8 @@ const Product = ghostBookshelf.Model.extend({
6
6
 
7
7
  defaults: {
8
8
  active: true,
9
- visibility: 'none'
9
+ visibility: 'none',
10
+ trial_days: 0
10
11
  },
11
12
 
12
13
  relationships: ['benefits'],
@@ -103,7 +103,7 @@ Tag = ghostBookshelf.Model.extend({
103
103
  // Support tag creation with `posts: [{..., tags: [{slug: 'new'}]}]`
104
104
  // In that situation we have a slug but no name so validation will fail
105
105
  // unless we set one automatically. Re-using slug for name matches our
106
- // opposite name->slug behaviour.
106
+ // opposite name->slug behavior.
107
107
  if (!newTag.get('name') && newTag.get('slug')) {
108
108
  this.set('name', newTag.get('slug'));
109
109
  }
@@ -234,7 +234,7 @@ User = ghostBookshelf.Model.extend({
234
234
  * - we do some pre-validation checks, because onValidate is called AFTER onSaving
235
235
  * - when importing, we set the password to a random uid and don't validate, just hash it and lock the user
236
236
  * - when importing with `importPersistUser` we check if the password is a bcrypt hash already and fall back to
237
- * normal behaviour if not (set random password, lock user, and hash password)
237
+ * normal behavior if not (set random password, lock user, and hash password)
238
238
  * - no validations should run, when importing
239
239
  */
240
240
  if (self.hasChanged('password')) {
@@ -242,7 +242,7 @@ User = ghostBookshelf.Model.extend({
242
242
 
243
243
  // CASE: import with `importPersistUser` should always be an bcrypt password already,
244
244
  // and won't re-hash or overwrite it.
245
- // In case the password is not bcrypt hashed we fall back to the standard behaviour.
245
+ // In case the password is not bcrypt hashed we fall back to the standard behavior.
246
246
  if (options.importPersistUser && this.get('password').match(/^\$2[ayb]\$.{56}$/i)) {
247
247
  return;
248
248
  }
@@ -15,11 +15,12 @@ const adapterManager = new AdapterManager({
15
15
  adapterManager.registerAdapter('storage', require('ghost-storage-base'));
16
16
  adapterManager.registerAdapter('scheduling', require('../../adapters/scheduling/SchedulingBase'));
17
17
  adapterManager.registerAdapter('sso', require('../../adapters/sso/Base'));
18
+ adapterManager.registerAdapter('cache', require('../../adapters/cache/Base'));
18
19
 
19
20
  module.exports = {
20
21
  /**
21
22
  *
22
- * @param {String} name - one of 'storage', 'scheduling', 'sso' etc. Or can contain a "resource" extension like "storage:image"
23
+ * @param {String} name - one of 'storage', 'scheduling', 'sso', 'cache' etc. Or can contain a "resource" extension like "storage:image"
23
24
  * @returns {Object} instance of an adapter
24
25
  */
25
26
  getAdapter(name) {
@@ -12,9 +12,11 @@ const messages = {
12
12
  module.exports = class CommentsController {
13
13
  /**
14
14
  * @param {import('./service')} service
15
+ * @param {import('./stats')} stats
15
16
  */
16
- constructor(service) {
17
+ constructor(service, stats) {
17
18
  this.service = service;
19
+ this.stats = stats;
18
20
  }
19
21
 
20
22
  /**
@@ -79,4 +81,12 @@ module.exports = class CommentsController {
79
81
  message: tpl(messages.cannotDestroyComments)
80
82
  });
81
83
  }
84
+
85
+ async count(frame) {
86
+ if (!frame?.data?.ids) {
87
+ return await this.stats.getAllCounts();
88
+ }
89
+
90
+ return await this.stats.getCountsByPost(frame.data.ids);
91
+ }
82
92
  };
@@ -106,7 +106,7 @@
106
106
  <div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 600px; padding: 30px 20px;">
107
107
 
108
108
  <!-- START CENTERED CONTAINER -->
109
- <span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">Someone left a comment on your post</span>
109
+ <span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">Someone just replied to your comment</span>
110
110
  <table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 8px;">
111
111
 
112
112
  <!-- START MAIN CONTENT AREA -->
@@ -116,20 +116,18 @@
116
116
  <tr>
117
117
  <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;">
118
118
  <p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 20px; color: #15212A; font-weight: bold; line-height: 25px; margin: 0; margin-bottom: 15px;">Hey there,</p>
119
- <p 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; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 32px;">Someone just replied to your comment on <a href="{{postUrl}}" target="_blank">{{postTitle}}</a>.</p>
119
+ <p 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; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 32px;">Someone just replied to your comment on <a href="{{postUrl}}" target="_blank" style="font-weight: bold; text-decoration: underline;">{{postTitle}}</a>.</p>
120
120
 
121
- <table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box; background: #F9F9FA; border-radius: 7px;">
121
+ <table width="100" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; table-layout: fixed; width: 100%; min-width: 100%; box-sizing: border-box; background: #F9F9FA; border-radius: 7px;">
122
122
  <tbody>
123
123
  <tr>
124
124
  <td align="left" style="padding: 16px;">
125
125
  <table border="0" cellpadding="0" cellspacing="0">
126
126
  <tr>
127
- <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: 16px; padding-right: 8px;">
128
- <table border="0" cellpadding="0" cellspacing="0" width="44" height="44" style="width: 44px; height: 44px; background-color: #15171A; border-radius: 999px;">
129
- <tr>
130
- <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: 18px; color: #FFFFFF; text-align: center; font-weight: 500; height: 44px; width: 44px;">{{memberInitials}}</td>
131
- </tr>
132
- </table>
127
+ <td style="padding-right: 8px;">
128
+ <div style="width: 44px; height: 44px; background-color: #15171A; border-radius: 999px; 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: #FFFFFF; text-align: center; vertical-align: center; font-weight: 500; line-height: 42px;">
129
+ {{memberInitials}}
130
+ </div>
133
131
  </td>
134
132
  <td style="padding-right: 8px;">
135
133
  <p 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; padding-right: 8px; padding: 0; margin: 0; color: #15171A; font-weight: 600;">{{memberName}}</p>
@@ -154,7 +152,7 @@
154
152
  <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
155
153
  <tbody>
156
154
  <tr>
157
- <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: 16px; vertical-align: top; background-color: {{accentColor}}; border-radius: 5px; text-align: center;"> <a href="{{postUrl}}#ghost-comments-root" target="_blank" style="display: inline-block; color: #ffffff; background-color: {{accentColor}}; border: solid 1px {{accentColor}}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: {{accentColor}};">View comments</a> </td>
155
+ <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: 16px; vertical-align: top; background-color: {{accentColor}}; border-radius: 5px; text-align: center;"> <a href="{{postUrl}}#ghost-comments" target="_blank" style="display: inline-block; color: #ffffff; background-color: {{accentColor}}; border: solid 1px {{accentColor}}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: {{accentColor}};">View comments</a> </td>
158
156
  </tr>
159
157
  </tbody>
160
158
  </table>
@@ -164,7 +162,7 @@
164
162
  </table>
165
163
  <hr/>
166
164
  <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; color: #3A464C; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 5px;">You can also copy & paste this URL into your browser:</p>
167
- <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 25px; margin-top:0; color: #3A464C;">{{postUrl}}#ghost-comments-root</p>
165
+ <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 25px; margin-top:0; color: #3A464C;">{{postUrl}}#ghost-comments</p>
168
166
  </td>
169
167
  </tr>
170
168
 
@@ -4,7 +4,7 @@ module.exports = function (data) {
4
4
 
5
5
  Someone just replied to your comment on "${data.postTitle}"
6
6
 
7
- ${data.postUrl}#ghost-comments-root
7
+ ${data.postUrl}#ghost-comments
8
8
 
9
9
  ---
10
10
 
@@ -116,20 +116,18 @@
116
116
  <tr>
117
117
  <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;">
118
118
  <p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 20px; color: #15212A; font-weight: bold; line-height: 25px; margin: 0; margin-bottom: 15px;">Hey there,</p>
119
- <p 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; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 32px;">Someone just left a comment on your post <a href="{{postUrl}}" target="_blank">{{postTitle}}</a>.</p>
119
+ <p 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; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 32px;">Someone just left a comment on your post <a href="{{postUrl}}" target="_blank" style="font-weight: bold; text-decoration: underline;">{{postTitle}}</a>.</p>
120
120
 
121
- <table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box; background: #F9F9FA; border-radius: 7px;">
121
+ <table width="100" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; table-layout: fixed; width: 100%; min-width: 100%; box-sizing: border-box; background: #F9F9FA; border-radius: 7px;">
122
122
  <tbody>
123
123
  <tr>
124
124
  <td align="left" style="padding: 16px;">
125
125
  <table border="0" cellpadding="0" cellspacing="0">
126
126
  <tr>
127
- <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: 16px; padding-right: 8px;">
128
- <table border="0" cellpadding="0" cellspacing="0" width="44" height="44" style="width: 44px; height: 44px; background-color: #15171A; border-radius: 999px;">
129
- <tr>
130
- <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: 18px; color: #FFFFFF; text-align: center; font-weight: 500; height: 44px; width: 44px;">{{memberInitials}}</td>
131
- </tr>
132
- </table>
127
+ <td style="padding-right: 8px;">
128
+ <div style="width: 44px; height: 44px; background-color: #15171A; border-radius: 999px; 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: #FFFFFF; text-align: center; vertical-align: center; font-weight: 500; line-height: 42px;">
129
+ {{memberInitials}}
130
+ </div>
133
131
  </td>
134
132
  <td style="padding-right: 8px;">
135
133
  <p 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; padding-right: 8px; padding: 0; margin: 0; color: #15171A; font-weight: 600;">{{memberName}}</p>
@@ -154,7 +152,7 @@
154
152
  <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
155
153
  <tbody>
156
154
  <tr>
157
- <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: 16px; vertical-align: top; background-color: {{accentColor}}; border-radius: 5px; text-align: center;"> <a href="{{postUrl}}#ghost-comments-root" target="_blank" style="display: inline-block; color: #ffffff; background-color: {{accentColor}}; border: solid 1px {{accentColor}}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: {{accentColor}};">View comments</a> </td>
155
+ <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: 16px; vertical-align: top; background-color: {{accentColor}}; border-radius: 5px; text-align: center;"> <a href="{{postUrl}}#ghost-comments" target="_blank" style="display: inline-block; color: #ffffff; background-color: {{accentColor}}; border: solid 1px {{accentColor}}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: {{accentColor}};">View comments</a> </td>
158
156
  </tr>
159
157
  </tbody>
160
158
  </table>
@@ -164,7 +162,7 @@
164
162
  </table>
165
163
  <hr/>
166
164
  <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; color: #3A464C; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 5px;">You can also copy & paste this URL into your browser:</p>
167
- <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 25px; margin-top:0; color: #3A464C;">{{postUrl}}#ghost-comments-root</p>
165
+ <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 25px; margin-top:0; color: #3A464C;">{{postUrl}}#ghost-comments</p>
168
166
  </td>
169
167
  </tr>
170
168
 
@@ -5,7 +5,7 @@ Hey there,
5
5
 
6
6
  Someone just posted a comment on your post "${data.postTitle}"
7
7
 
8
- ${data.postUrl}#ghost-comments-root
8
+ ${data.postUrl}#ghost-comments
9
9
 
10
10
  ---
11
11
 
@@ -118,18 +118,16 @@
118
118
  <p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 20px; color: #15212A; font-weight: bold; line-height: 25px; margin: 0; margin-bottom: 15px;">Hey there,</p>
119
119
  <p 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; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 32px;">{{reporter}} has reported the comment below on <a href="{{postUrl}}" target="_blank">{{postTitle}}</a>. This comment will remain visible until you choose to remove it, which can be done directly on the post.</p>
120
120
 
121
- <table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box; background: #F9F9FA; border-radius: 7px;">
121
+ <table width="100" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; table-layout: fixed; width: 100%; min-width: 100%; box-sizing: border-box; background: #F9F9FA; border-radius: 7px;">
122
122
  <tbody>
123
123
  <tr>
124
124
  <td align="left" style="padding: 16px;">
125
125
  <table border="0" cellpadding="0" cellspacing="0">
126
126
  <tr>
127
- <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: 16px; padding-right: 8px;">
128
- <table border="0" cellpadding="0" cellspacing="0" width="44" height="44" style="width: 44px; height: 44px; background-color: #15171A; border-radius: 999px;">
129
- <tr>
130
- <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: 18px; color: #FFFFFF; text-align: center; font-weight: 500; height: 44px; width: 44px;">{{memberInitials}}</td>
131
- </tr>
132
- </table>
127
+ <td style="padding-right: 8px;">
128
+ <div style="width: 44px; height: 44px; background-color: #15171A; border-radius: 999px; 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: #FFFFFF; text-align: center; vertical-align: center; font-weight: 500; line-height: 42px;">
129
+ {{memberInitials}}
130
+ </div>
133
131
  </td>
134
132
  <td style="padding-right: 8px;">
135
133
  <p 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; padding-right: 8px; padding: 0; margin: 0; color: #15171A; font-weight: 600;">{{memberName}}</p>
@@ -154,7 +152,7 @@
154
152
  <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
155
153
  <tbody>
156
154
  <tr>
157
- <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: 16px; vertical-align: top; background-color: {{accentColor}}; border-radius: 5px; text-align: center;"> <a href="{{postUrl}}#ghost-comments-root" target="_blank" style="display: inline-block; color: #ffffff; background-color: {{accentColor}}; border: solid 1px {{accentColor}}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: {{accentColor}};">View comment</a> </td>
155
+ <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: 16px; vertical-align: top; background-color: {{accentColor}}; border-radius: 5px; text-align: center;"> <a href="{{postUrl}}#ghost-comments" target="_blank" style="display: inline-block; color: #ffffff; background-color: {{accentColor}}; border: solid 1px {{accentColor}}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: {{accentColor}};">View comment</a> </td>
158
156
  </tr>
159
157
  </tbody>
160
158
  </table>
@@ -164,7 +162,7 @@
164
162
  </table>
165
163
  <hr/>
166
164
  <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; color: #3A464C; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 5px;">You can also copy & paste this URL into your browser:</p>
167
- <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 25px; margin-top:0; color: #3A464C;">{{postUrl}}#ghost-comments-root</p>
165
+ <p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 25px; margin-top:0; color: #3A464C;">{{postUrl}}#ghost-comments</p>
168
166
  </td>
169
167
  </tr>
170
168
 
@@ -7,7 +7,7 @@ ${data.reporter} has reported the comment below on ${data.postTitle}. This comme
7
7
  ${data.memberName} (${data.memberEmail}):
8
8
  ${data.commentText}
9
9
 
10
- ${data.postUrl}#ghost-comments-root
10
+ ${data.postUrl}#ghost-comments
11
11
 
12
12
  ---
13
13
 
@@ -1,7 +1,7 @@
1
1
  const {promises: fs} = require('fs');
2
2
  const path = require('path');
3
3
  const moment = require('moment');
4
- const htmlToPlaintext = require('../../../shared/html-to-plaintext');
4
+ const htmlToPlaintext = require('@tryghost/html-to-plaintext');
5
5
 
6
6
  class CommentsServiceEmails {
7
7
  constructor({config, logging, models, mailer, settingsCache, urlService, urlUtils}) {
@@ -26,7 +26,7 @@ class CommentsServiceEmails {
26
26
  }
27
27
 
28
28
  const to = author.get('email');
29
- const subject = '💬 You have a new comment on one of your posts';
29
+ const subject = '💬 New comment on your post: ' + post.get('title');
30
30
 
31
31
  const memberName = member.get('name') || 'Anonymous';
32
32
 
@@ -72,7 +72,7 @@ class CommentsServiceEmails {
72
72
  }
73
73
 
74
74
  const to = parentMember.get('email');
75
- const subject = '💬 You have a new reply on one of your comments';
75
+ const subject = '↪️ New reply to your comment on ' + this.settingsCache.get('title');
76
76
 
77
77
  const post = await this.models.Post.findOne({id: reply.get('post_id')});
78
78
  const member = await this.models.Member.findOne({id: reply.get('member_id')});
@@ -129,7 +129,7 @@ class CommentsServiceEmails {
129
129
  postTitle: post.get('title'),
130
130
  postUrl: this.urlService.getUrlByResourceId(post.get('id'), {absolute: true}),
131
131
  commentHtml: comment.get('html'),
132
- commentText: htmlToPlaintext.email(comment.get('html')),
132
+ commentText: htmlToPlaintext.comment(comment.get('html')),
133
133
  commentDate: moment(comment.get('created_at')).tz(this.settingsCache.get('timezone')).format('D MMM YYYY'),
134
134
 
135
135
  reporterName: reporter.name,
@@ -2,6 +2,7 @@ class CommentsServiceWrapper {
2
2
  init() {
3
3
  const CommentsService = require('./service');
4
4
  const CommentsController = require('./controller');
5
+ const CommentsStats = require('./stats');
5
6
 
6
7
  const config = require('../../../shared/config');
7
8
  const logging = require('@tryghost/logging');
@@ -12,6 +13,7 @@ class CommentsServiceWrapper {
12
13
  const urlService = require('../url');
13
14
  const urlUtils = require('../../../shared/url-utils');
14
15
  const membersService = require('../members');
16
+ const db = require('../../data/db');
15
17
 
16
18
  this.api = new CommentsService({
17
19
  config,
@@ -24,7 +26,9 @@ class CommentsServiceWrapper {
24
26
  contentGating: membersService.contentGating
25
27
  });
26
28
 
27
- this.controller = new CommentsController(this.api);
29
+ const stats = new CommentsStats({db});
30
+
31
+ this.controller = new CommentsController(this.api, stats);
28
32
  }
29
33
  }
30
34
 
@@ -10,7 +10,8 @@ const messages = {
10
10
  alreadyLiked: 'This comment was liked already',
11
11
  replyToReply: 'Can not reply to a reply',
12
12
  commentsNotEnabled: 'Comments are not enabled for this site.',
13
- cannotCommentOnPost: 'You do not have permission to comment on this post.'
13
+ cannotCommentOnPost: 'You do not have permission to comment on this post.',
14
+ cannotEditComment: 'You do not have permission to edit comments'
14
15
  };
15
16
 
16
17
  class CommentsService {
@@ -285,8 +286,7 @@ class CommentsService {
285
286
 
286
287
  if (existingComment.get('member_id') !== member) {
287
288
  throw new errors.NoPermissionError({
288
- // todo fix message
289
- message: tpl(messages.memberNotFound)
289
+ message: tpl(messages.cannotEditComment)
290
290
  });
291
291
  }
292
292
 
@@ -0,0 +1,44 @@
1
+ module.exports = class CommentsStatsService {
2
+ constructor(deps) {
3
+ this.db = deps.db;
4
+ }
5
+
6
+ /**
7
+ * @param {string[]} ids - List of post ids to fetch counts for
8
+ * @returns {Promise<Object<string, number>>}
9
+ */
10
+ async getCountsByPost(ids) {
11
+ const results = await this.db.knex('comments')
12
+ .select(this.db.knex.raw(`COUNT(*) AS count, post_id`))
13
+ .groupBy('post_id')
14
+ .whereIn('post_id', ids);
15
+
16
+ const counts = ids.reduce((memo, id) => {
17
+ const result = results.find(x => x.post_id === id);
18
+ return {
19
+ ...memo,
20
+ [id]: result?.count || 0
21
+ };
22
+ }, {});
23
+
24
+ return counts;
25
+ }
26
+
27
+ /**
28
+ * @returns {Promise<Object<string, number>>}
29
+ */
30
+ async getAllCounts() {
31
+ const results = await this.db.knex('comments')
32
+ .select(this.db.knex.raw(`COUNT(*) AS count, post_id`))
33
+ .groupBy('post_id');
34
+
35
+ /** @type Object<string, number> */
36
+ let counts = {};
37
+
38
+ for (const row of results) {
39
+ counts[row.post_id] = row.count;
40
+ }
41
+
42
+ return counts;
43
+ }
44
+ };
@@ -104,7 +104,7 @@ const sendTestEmail = async (postModel, toEmails, memberSegment) => {
104
104
  };
105
105
  }));
106
106
 
107
- // enable tracking for previews to match real-world behaviour
107
+ // enable tracking for previews to match real-world behavior
108
108
  emailData.track_opens = !!settingsCache.get('email_track_opens');
109
109
 
110
110
  const response = await bulkEmailService.send(emailData, recipients, memberSegment);
@@ -8,7 +8,7 @@ const api = require('../../api').endpoints;
8
8
  const apiShared = require('../../api').shared;
9
9
  const {URL} = require('url');
10
10
  const mobiledocLib = require('../../lib/mobiledoc');
11
- const htmlToPlaintext = require('../../../shared/html-to-plaintext');
11
+ const htmlToPlaintext = require('@tryghost/html-to-plaintext');
12
12
  const membersService = require('../members');
13
13
  const {isUnsplashImage, isLocalContentImage} = require('@tryghost/kg-default-cards/lib/utils');
14
14
  const {textColorForBackgroundColor, darkenToContrastThreshold} = require('@tryghost/color-utils');
@@ -116,7 +116,7 @@ const updateMemberNewsletters = async function (req, res) {
116
116
 
117
117
  const updateMemberData = async function (req, res) {
118
118
  try {
119
- const data = _.pick(req.body, 'name', 'subscribed', 'newsletters', 'enable_comment_notifications');
119
+ const data = _.pick(req.body, 'name', 'bio', 'subscribed', 'newsletters', 'enable_comment_notifications');
120
120
  const member = await membersService.ssr.getMemberDataFromSession(req, res);
121
121
  if (member) {
122
122
  const options = {
@@ -13,6 +13,7 @@ module.exports.formattedMemberResponse = function formattedMemberResponse(member
13
13
  email: member.email,
14
14
  name: member.name,
15
15
  firstname: member.name && member.name.split(' ')[0],
16
+ bio: member.bio,
16
17
  avatar_image: member.avatar_image,
17
18
  subscribed: !!member.subscribed,
18
19
  subscriptions: member.subscriptions || [],
@@ -9,6 +9,7 @@ const events = require('../../lib/common/events');
9
9
  const models = require('../../models');
10
10
  const labs = require('../../../shared/labs');
11
11
  const config = require('../../../shared/config');
12
+ const adapterManager = require('../adapter-manager');
12
13
  const SettingsCache = require('../../../shared/settings-cache');
13
14
  const SettingsBREADService = require('./settings-bread-service');
14
15
  const {obfuscatedSetting, isSecretSetting, hideValueIfSecret} = require('./settings-utils');
@@ -66,8 +67,9 @@ module.exports = {
66
67
  * Initialize the cache, used in boot and in testing
67
68
  */
68
69
  async init() {
70
+ const cacheStore = adapterManager.getAdapter('cache');
69
71
  const settingsCollection = await models.Settings.populateDefaults();
70
- SettingsCache.init(events, settingsCollection, this.getCalculatedFields());
72
+ SettingsCache.init(events, settingsCollection, this.getCalculatedFields(), cacheStore);
71
73
  },
72
74
 
73
75
  /**
@@ -159,7 +159,7 @@ class Resources {
159
159
  * @description Call the model layer to fetch a single resource via raw knex queries.
160
160
  *
161
161
  * This function was invented, because the model event is a generic event, which is independent of any
162
- * api version behaviour. We have to ensure that a model matches the conditions of the configured api version
162
+ * api version behavior. We have to ensure that a model matches the conditions of the configured api version
163
163
  * in the theme.
164
164
  *
165
165
  * See https://github.com/TryGhost/Ghost/issues/10124.
@@ -1,4 +1,5 @@
1
1
  const debug = require('@tryghost/debug')('web:admin:app');
2
+ const path = require('path');
2
3
  const express = require('../../../shared/express');
3
4
  const serveStatic = express.static;
4
5
  const config = require('../../../shared/config');
@@ -17,7 +18,7 @@ module.exports = function setupAdminApp() {
17
18
  // @TODO ensure this gets a local 404 error handler
18
19
  const configMaxAge = config.get('caching:admin:maxAge');
19
20
  adminApp.use('/assets', serveStatic(
20
- config.get('paths').adminAssets,
21
+ path.join(config.get('paths').adminAssets, 'assets'),
21
22
  {maxAge: (configMaxAge || configMaxAge === 0) ? configMaxAge : constants.ONE_YEAR_MS, fallthrough: false}
22
23
  ));
23
24
 
@@ -29,8 +29,7 @@ module.exports = function adminController(req, res) {
29
29
  // CASE: trigger update check unit and let it run in background, don't block the admin rendering
30
30
  updateCheck();
31
31
 
32
- const defaultTemplate = config.get('env') === 'production' ? 'default-prod.html' : 'default.html';
33
- const templatePath = path.resolve(config.get('paths').adminViews, defaultTemplate);
32
+ const templatePath = path.resolve(config.get('paths').adminAssets, 'index.html');
34
33
  const headers = {};
35
34
 
36
35
  try {