ghost 5.82.12 → 5.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/components/tryghost-adapter-cache-memory-ttl-5.84.0.tgz +0 -0
  2. package/components/tryghost-adapter-cache-redis-5.84.0.tgz +0 -0
  3. package/components/{tryghost-adapter-manager-5.82.12.tgz → tryghost-adapter-manager-5.84.0.tgz} +0 -0
  4. package/components/tryghost-announcement-bar-settings-5.84.0.tgz +0 -0
  5. package/components/{tryghost-api-framework-5.82.12.tgz → tryghost-api-framework-5.84.0.tgz} +0 -0
  6. package/components/tryghost-api-version-compatibility-service-5.84.0.tgz +0 -0
  7. package/components/tryghost-audience-feedback-5.84.0.tgz +0 -0
  8. package/components/tryghost-bookshelf-repository-5.84.0.tgz +0 -0
  9. package/components/tryghost-bootstrap-socket-5.84.0.tgz +0 -0
  10. package/components/tryghost-collections-5.84.0.tgz +0 -0
  11. package/components/tryghost-constants-5.84.0.tgz +0 -0
  12. package/components/tryghost-custom-theme-settings-service-5.84.0.tgz +0 -0
  13. package/components/tryghost-data-generator-5.84.0.tgz +0 -0
  14. package/components/tryghost-domain-events-5.84.0.tgz +0 -0
  15. package/components/tryghost-donations-5.84.0.tgz +0 -0
  16. package/components/tryghost-dynamic-routing-events-5.84.0.tgz +0 -0
  17. package/components/tryghost-email-addresses-5.84.0.tgz +0 -0
  18. package/components/tryghost-email-analytics-provider-mailgun-5.84.0.tgz +0 -0
  19. package/components/tryghost-email-analytics-service-5.84.0.tgz +0 -0
  20. package/components/tryghost-email-content-generator-5.84.0.tgz +0 -0
  21. package/components/tryghost-email-events-5.84.0.tgz +0 -0
  22. package/components/tryghost-email-service-5.84.0.tgz +0 -0
  23. package/components/tryghost-email-suppression-list-5.84.0.tgz +0 -0
  24. package/components/tryghost-express-dynamic-redirects-5.84.0.tgz +0 -0
  25. package/components/tryghost-external-media-inliner-5.84.0.tgz +0 -0
  26. package/components/tryghost-extract-api-key-5.84.0.tgz +0 -0
  27. package/components/tryghost-ghost-5.84.0.tgz +0 -0
  28. package/components/tryghost-html-to-plaintext-5.84.0.tgz +0 -0
  29. package/components/tryghost-i18n-5.84.0.tgz +0 -0
  30. package/components/tryghost-importer-handler-content-files-5.84.0.tgz +0 -0
  31. package/components/tryghost-importer-revue-5.84.0.tgz +0 -0
  32. package/components/tryghost-in-memory-repository-5.84.0.tgz +0 -0
  33. package/components/{tryghost-job-manager-5.82.12.tgz → tryghost-job-manager-5.84.0.tgz} +0 -0
  34. package/components/tryghost-link-redirects-5.84.0.tgz +0 -0
  35. package/components/tryghost-link-replacer-5.84.0.tgz +0 -0
  36. package/components/tryghost-link-tracking-5.84.0.tgz +0 -0
  37. package/components/tryghost-magic-link-5.84.0.tgz +0 -0
  38. package/components/tryghost-mail-events-5.84.0.tgz +0 -0
  39. package/components/tryghost-mailgun-client-5.84.0.tgz +0 -0
  40. package/components/tryghost-member-attribution-5.84.0.tgz +0 -0
  41. package/components/tryghost-member-events-5.84.0.tgz +0 -0
  42. package/components/tryghost-members-api-5.84.0.tgz +0 -0
  43. package/components/tryghost-members-csv-5.84.0.tgz +0 -0
  44. package/components/tryghost-members-events-service-5.84.0.tgz +0 -0
  45. package/components/{tryghost-members-importer-5.82.12.tgz → tryghost-members-importer-5.84.0.tgz} +0 -0
  46. package/components/{tryghost-members-offers-5.82.12.tgz → tryghost-members-offers-5.84.0.tgz} +0 -0
  47. package/components/tryghost-members-payments-5.84.0.tgz +0 -0
  48. package/components/tryghost-members-ssr-5.84.0.tgz +0 -0
  49. package/components/tryghost-members-stripe-service-5.84.0.tgz +0 -0
  50. package/components/tryghost-mentions-email-report-5.84.0.tgz +0 -0
  51. package/components/tryghost-milestones-5.84.0.tgz +0 -0
  52. package/components/tryghost-minifier-5.84.0.tgz +0 -0
  53. package/components/tryghost-model-to-domain-event-interceptor-5.84.0.tgz +0 -0
  54. package/components/tryghost-mw-api-version-mismatch-5.84.0.tgz +0 -0
  55. package/components/tryghost-mw-cache-control-5.84.0.tgz +0 -0
  56. package/components/tryghost-mw-error-handler-5.84.0.tgz +0 -0
  57. package/components/tryghost-mw-session-from-token-5.84.0.tgz +0 -0
  58. package/components/tryghost-mw-update-user-last-seen-5.84.0.tgz +0 -0
  59. package/components/tryghost-mw-version-match-5.84.0.tgz +0 -0
  60. package/components/tryghost-mw-vhost-5.84.0.tgz +0 -0
  61. package/components/tryghost-nql-filter-expansions-5.84.0.tgz +0 -0
  62. package/components/tryghost-oembed-service-5.84.0.tgz +0 -0
  63. package/components/tryghost-package-json-5.84.0.tgz +0 -0
  64. package/components/tryghost-post-events-5.84.0.tgz +0 -0
  65. package/components/tryghost-post-revisions-5.84.0.tgz +0 -0
  66. package/components/tryghost-posts-service-5.84.0.tgz +0 -0
  67. package/components/tryghost-recommendations-5.84.0.tgz +0 -0
  68. package/components/tryghost-referrers-5.84.0.tgz +0 -0
  69. package/components/{tryghost-security-5.82.12.tgz → tryghost-security-5.84.0.tgz} +0 -0
  70. package/components/tryghost-session-service-5.84.0.tgz +0 -0
  71. package/components/tryghost-settings-path-manager-5.84.0.tgz +0 -0
  72. package/components/tryghost-slack-notifications-5.84.0.tgz +0 -0
  73. package/components/{tryghost-staff-service-5.82.12.tgz → tryghost-staff-service-5.84.0.tgz} +0 -0
  74. package/components/tryghost-stats-service-5.84.0.tgz +0 -0
  75. package/components/tryghost-tiers-5.84.0.tgz +0 -0
  76. package/components/tryghost-update-check-service-5.84.0.tgz +0 -0
  77. package/components/{tryghost-verification-trigger-5.82.12.tgz → tryghost-verification-trigger-5.84.0.tgz} +0 -0
  78. package/components/{tryghost-version-notifications-data-service-5.82.12.tgz → tryghost-version-notifications-data-service-5.84.0.tgz} +0 -0
  79. package/components/tryghost-webmentions-5.84.0.tgz +0 -0
  80. package/content/themes/source/default.hbs +5 -0
  81. package/content/themes/source/package.json +1 -1
  82. package/core/built/admin/assets/admin-x-demo/admin-x-demo.js +1 -1
  83. package/core/built/admin/assets/admin-x-demo/{index-672397d7.mjs → index-ca021c9d.mjs} +200 -198
  84. package/core/built/admin/assets/admin-x-demo/{modals-e68b00c5.mjs → modals-0eb36d36.mjs} +2 -2
  85. package/core/built/admin/assets/admin-x-settings/{CodeEditorView-e6ecff28.mjs → CodeEditorView-eaf264d3.mjs} +2 -2
  86. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +2 -2
  87. package/core/built/admin/assets/admin-x-settings/{index-ee4ab0db.mjs → index-39468f31.mjs} +305 -305
  88. package/core/built/admin/assets/admin-x-settings/{index-3a124f37.mjs → index-b0e98052.mjs} +3045 -3016
  89. package/core/built/admin/assets/admin-x-settings/{modals-8b47269b.mjs → modals-8fb51a51.mjs} +4514 -4482
  90. package/core/built/admin/assets/{chunk.300.07bd40373843db34827c.js → chunk.509.d6d53e741bc279357eaf.js} +1904 -1880
  91. package/core/built/admin/assets/{chunk.524.d0e760b5fbf40755f861.js → chunk.524.dd2adb7618502394b0fa.js} +5 -5
  92. package/core/built/admin/assets/chunk.582.7b12fec8907e5aeb732c.js +37 -0
  93. package/core/built/admin/assets/{ghost-6f45467fa855b0c1da51c5f6c31f4744.js → ghost-2bb48a3a355571aa30056b2bb30b9c2a.js} +149 -132
  94. package/core/built/admin/assets/{ghost-67652794f5902e84ccb0c67948563c1e.css → ghost-da719d2c50388e7f72e596e1a8b99e80.css} +1 -1
  95. package/core/built/admin/assets/{ghost-dark-e0cbaf72cee27f9de1eff5aea1152c46.css → ghost-dark-3cbc750010886456986b77ff03283139.css} +1 -1
  96. package/core/built/admin/assets/koenig-lexical/index.css +1 -1
  97. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +14565 -14132
  98. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +128 -128
  99. package/core/built/admin/index.html +5 -5
  100. package/core/server/api/endpoints/utils/serializers/input/posts.js +2 -9
  101. package/core/server/data/migrations/versions/5.83/2024-05-28-02-20-55-add-show-subhead-column-newsletters.js +9 -0
  102. package/core/server/data/migrations/versions/5.84/2024-06-04-09-13-33-rename-newsletters-show-subhead.js +3 -0
  103. package/core/server/data/migrations/versions/5.84/2024-06-04-11-10-37-add-custom-excerpt-to-post-revisions.js +7 -0
  104. package/core/server/data/migrations/versions/5.84/2024-06-05-08-42-34-populate-post-revisions-custom-excerpt.js +32 -0
  105. package/core/server/data/migrations/versions/5.84/2024-06-05-13-48-35-rename-newsletters-show-subtitle.js +3 -0
  106. package/core/server/data/schema/schema.js +3 -1
  107. package/core/server/models/newsletter.js +2 -1
  108. package/core/server/models/post.js +1 -0
  109. package/core/server/services/members/middleware.js +5 -1
  110. package/core/server/services/slack.js +22 -2
  111. package/core/server/web/api/middleware/upload.js +32 -3
  112. package/core/shared/labs.js +6 -3
  113. package/package.json +170 -171
  114. package/yarn.lock +345 -355
  115. package/components/tryghost-adapter-cache-memory-ttl-5.82.12.tgz +0 -0
  116. package/components/tryghost-adapter-cache-redis-5.82.12.tgz +0 -0
  117. package/components/tryghost-announcement-bar-settings-5.82.12.tgz +0 -0
  118. package/components/tryghost-api-version-compatibility-service-5.82.12.tgz +0 -0
  119. package/components/tryghost-audience-feedback-5.82.12.tgz +0 -0
  120. package/components/tryghost-bookshelf-repository-5.82.12.tgz +0 -0
  121. package/components/tryghost-bootstrap-socket-5.82.12.tgz +0 -0
  122. package/components/tryghost-collections-5.82.12.tgz +0 -0
  123. package/components/tryghost-constants-5.82.12.tgz +0 -0
  124. package/components/tryghost-custom-theme-settings-service-5.82.12.tgz +0 -0
  125. package/components/tryghost-data-generator-5.82.12.tgz +0 -0
  126. package/components/tryghost-domain-events-5.82.12.tgz +0 -0
  127. package/components/tryghost-donations-5.82.12.tgz +0 -0
  128. package/components/tryghost-dynamic-routing-events-5.82.12.tgz +0 -0
  129. package/components/tryghost-email-addresses-5.82.12.tgz +0 -0
  130. package/components/tryghost-email-analytics-provider-mailgun-5.82.12.tgz +0 -0
  131. package/components/tryghost-email-analytics-service-5.82.12.tgz +0 -0
  132. package/components/tryghost-email-content-generator-5.82.12.tgz +0 -0
  133. package/components/tryghost-email-events-5.82.12.tgz +0 -0
  134. package/components/tryghost-email-service-5.82.12.tgz +0 -0
  135. package/components/tryghost-email-suppression-list-5.82.12.tgz +0 -0
  136. package/components/tryghost-express-dynamic-redirects-5.82.12.tgz +0 -0
  137. package/components/tryghost-external-media-inliner-5.82.12.tgz +0 -0
  138. package/components/tryghost-extract-api-key-5.82.12.tgz +0 -0
  139. package/components/tryghost-ghost-5.82.12.tgz +0 -0
  140. package/components/tryghost-html-to-plaintext-5.82.12.tgz +0 -0
  141. package/components/tryghost-i18n-5.82.12.tgz +0 -0
  142. package/components/tryghost-importer-handler-content-files-5.82.12.tgz +0 -0
  143. package/components/tryghost-importer-revue-5.82.12.tgz +0 -0
  144. package/components/tryghost-in-memory-repository-5.82.12.tgz +0 -0
  145. package/components/tryghost-link-redirects-5.82.12.tgz +0 -0
  146. package/components/tryghost-link-replacer-5.82.12.tgz +0 -0
  147. package/components/tryghost-link-tracking-5.82.12.tgz +0 -0
  148. package/components/tryghost-magic-link-5.82.12.tgz +0 -0
  149. package/components/tryghost-mail-events-5.82.12.tgz +0 -0
  150. package/components/tryghost-mailgun-client-5.82.12.tgz +0 -0
  151. package/components/tryghost-member-attribution-5.82.12.tgz +0 -0
  152. package/components/tryghost-member-events-5.82.12.tgz +0 -0
  153. package/components/tryghost-members-api-5.82.12.tgz +0 -0
  154. package/components/tryghost-members-csv-5.82.12.tgz +0 -0
  155. package/components/tryghost-members-events-service-5.82.12.tgz +0 -0
  156. package/components/tryghost-members-payments-5.82.12.tgz +0 -0
  157. package/components/tryghost-members-ssr-5.82.12.tgz +0 -0
  158. package/components/tryghost-members-stripe-service-5.82.12.tgz +0 -0
  159. package/components/tryghost-mentions-email-report-5.82.12.tgz +0 -0
  160. package/components/tryghost-milestones-5.82.12.tgz +0 -0
  161. package/components/tryghost-minifier-5.82.12.tgz +0 -0
  162. package/components/tryghost-model-to-domain-event-interceptor-5.82.12.tgz +0 -0
  163. package/components/tryghost-mw-api-version-mismatch-5.82.12.tgz +0 -0
  164. package/components/tryghost-mw-cache-control-5.82.12.tgz +0 -0
  165. package/components/tryghost-mw-error-handler-5.82.12.tgz +0 -0
  166. package/components/tryghost-mw-session-from-token-5.82.12.tgz +0 -0
  167. package/components/tryghost-mw-update-user-last-seen-5.82.12.tgz +0 -0
  168. package/components/tryghost-mw-version-match-5.82.12.tgz +0 -0
  169. package/components/tryghost-mw-vhost-5.82.12.tgz +0 -0
  170. package/components/tryghost-nql-filter-expansions-5.82.12.tgz +0 -0
  171. package/components/tryghost-oembed-service-5.82.12.tgz +0 -0
  172. package/components/tryghost-package-json-5.82.12.tgz +0 -0
  173. package/components/tryghost-post-events-5.82.12.tgz +0 -0
  174. package/components/tryghost-post-revisions-5.82.12.tgz +0 -0
  175. package/components/tryghost-posts-service-5.82.12.tgz +0 -0
  176. package/components/tryghost-recommendations-5.82.12.tgz +0 -0
  177. package/components/tryghost-referrers-5.82.12.tgz +0 -0
  178. package/components/tryghost-session-service-5.82.12.tgz +0 -0
  179. package/components/tryghost-settings-path-manager-5.82.12.tgz +0 -0
  180. package/components/tryghost-slack-notifications-5.82.12.tgz +0 -0
  181. package/components/tryghost-stats-service-5.82.12.tgz +0 -0
  182. package/components/tryghost-tiers-5.82.12.tgz +0 -0
  183. package/components/tryghost-update-check-service-5.82.12.tgz +0 -0
  184. package/components/tryghost-webmentions-5.82.12.tgz +0 -0
  185. package/core/built/admin/assets/chunk.582.b5b5252c47ef49f8f87a.js +0 -11
  186. /package/core/built/admin/assets/{chunk.300.07bd40373843db34827c.js.LICENSE.txt → chunk.509.d6d53e741bc279357eaf.js.LICENSE.txt} +0 -0
@@ -8,7 +8,7 @@
8
8
  <title>Ghost Admin</title>
9
9
 
10
10
 
11
- <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.82%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22ember-websockets%22%3A%7B%22socketIO%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%2C%22editorFilename%22%3A%22koenig-lexical.umd.js%22%2C%22editorHash%22%3A%223eace8808c%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%226b30648e0d%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%22d91284430d%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%22c4fe53c34a%22%7D" />
11
+ <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.84%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22ember-websockets%22%3A%7B%22socketIO%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%2C%22editorFilename%22%3A%22koenig-lexical.umd.js%22%2C%22editorHash%22%3A%2255764a8e22%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%222de5d3a326%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%2274637d0e3a%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%22c4fe53c34a%22%7D" />
12
12
 
13
13
  <meta name="HandheldFriendly" content="True" />
14
14
  <meta name="MobileOptimized" content="320" />
@@ -37,7 +37,7 @@
37
37
  </style>
38
38
 
39
39
  <link integrity="" rel="stylesheet" href="assets/vendor-0ede59da8efb5e28fa929557f7ff7154.css">
40
- <link integrity="" rel="stylesheet" href="assets/ghost-67652794f5902e84ccb0c67948563c1e.css" title="light">
40
+ <link integrity="" rel="stylesheet" href="assets/ghost-da719d2c50388e7f72e596e1a8b99e80.css" title="light">
41
41
 
42
42
 
43
43
  </head>
@@ -57,8 +57,8 @@
57
57
  <div id="ember-basic-dropdown-wormhole"></div>
58
58
 
59
59
  <script src="assets/vendor-0d51bbe51e0393cca143d7b52d073d8a.js"></script>
60
- <script src="assets/chunk.300.07bd40373843db34827c.js"></script>
61
- <script src="assets/chunk.524.d0e760b5fbf40755f861.js"></script>
62
- <script src="assets/ghost-6f45467fa855b0c1da51c5f6c31f4744.js"></script>
60
+ <script src="assets/chunk.509.d6d53e741bc279357eaf.js"></script>
61
+ <script src="assets/chunk.524.dd2adb7618502394b0fa.js"></script>
62
+ <script src="assets/ghost-2bb48a3a355571aa30056b2bb30b9c2a.js"></script>
63
63
  </body>
64
64
  </html>
@@ -92,18 +92,11 @@ function defaultRelations(frame) {
92
92
  }
93
93
 
94
94
  function setDefaultOrder(frame) {
95
- let includesOrderedRelations = false;
96
-
97
- if (frame.options.withRelated) {
98
- const orderedRelations = ['author', 'authors', 'tag', 'tags'];
99
- includesOrderedRelations = _.intersection(orderedRelations, frame.options.withRelated).length > 0;
100
- }
101
-
102
- if (!frame.options.order && !includesOrderedRelations && frame.options.filter) {
95
+ if (!frame.options.order && frame.options.filter) {
103
96
  frame.options.autoOrder = slugFilterOrder('posts', frame.options.filter);
104
97
  }
105
98
 
106
- if (!frame.options.order && !frame.options.autoOrder && !includesOrderedRelations) {
99
+ if (!frame.options.order && !frame.options.autoOrder) {
107
100
  frame.options.order = 'published_at desc';
108
101
  }
109
102
  }
@@ -0,0 +1,9 @@
1
+ // For information on writing migrations, see https://www.notion.so/ghost/Database-migrations-eb5b78c435d741d2b34a582d57c24253
2
+
3
+ const {createAddColumnMigration} = require('../../utils');
4
+
5
+ module.exports = createAddColumnMigration('newsletters', 'show_subhead', {
6
+ type: 'boolean',
7
+ nullable: false,
8
+ defaultTo: false
9
+ });
@@ -0,0 +1,3 @@
1
+ const {createRenameColumnMigration} = require('../../utils');
2
+
3
+ module.exports = createRenameColumnMigration('newsletters', 'show_subhead', 'show_subtitle');
@@ -0,0 +1,7 @@
1
+ const {createAddColumnMigration} = require('../../utils');
2
+
3
+ module.exports = createAddColumnMigration('post_revisions', 'custom_excerpt', {
4
+ type: 'string',
5
+ maxlength: 2000,
6
+ nullable: true
7
+ });
@@ -0,0 +1,32 @@
1
+ const logging = require('@tryghost/logging');
2
+ const {createTransactionalMigration} = require('../../utils');
3
+ const DatabaseInfo = require('@tryghost/database-info');
4
+
5
+ module.exports = createTransactionalMigration(
6
+ async function up(knex) {
7
+ logging.info('Populating post_revisions.custom_excerpt with post.excerpt');
8
+
9
+ if (DatabaseInfo.isSQLite(knex)) {
10
+ // SQLite doesn't support JOINs in UPDATE queries
11
+ await knex.raw(`
12
+ UPDATE post_revisions
13
+ SET custom_excerpt = (
14
+ SELECT posts.custom_excerpt
15
+ FROM posts
16
+ WHERE post_revisions.post_id = posts.id
17
+ )
18
+ `);
19
+ } else {
20
+ await knex.raw(`
21
+ UPDATE post_revisions
22
+ JOIN posts ON post_revisions.post_id = posts.id
23
+ SET post_revisions.custom_excerpt = posts.custom_excerpt
24
+ `);
25
+ }
26
+
27
+ logging.info('Finished populating post_revisions.custom_excerpt');
28
+ },
29
+ async function down() {
30
+ // Not required
31
+ }
32
+ );
@@ -0,0 +1,3 @@
1
+ const {createRenameColumnMigration} = require('../../utils');
2
+
3
+ module.exports = createRenameColumnMigration('newsletters', 'show_subtitle', 'show_excerpt');
@@ -30,6 +30,7 @@ module.exports = {
30
30
  header_image: {type: 'string', maxlength: 2000, nullable: true},
31
31
  show_header_icon: {type: 'boolean', nullable: false, defaultTo: true},
32
32
  show_header_title: {type: 'boolean', nullable: false, defaultTo: true},
33
+ show_excerpt: {type: 'boolean', nullable: false, defaultTo: false},
33
34
  title_font_category: {type: 'string', maxlength: 191, nullable: false, defaultTo: 'sans_serif', validations: {isIn: [['serif', 'sans_serif']]}},
34
35
  title_alignment: {type: 'string', maxlength: 191, nullable: false, defaultTo: 'center', validations: {isIn: [['center', 'left']]}},
35
36
  show_feature_image: {type: 'boolean', nullable: false, defaultTo: true},
@@ -412,7 +413,8 @@ module.exports = {
412
413
  reason: {type: 'string', maxlength: 50, nullable: true},
413
414
  feature_image: {type: 'string', maxlength: 2000, nullable: true},
414
415
  feature_image_alt: {type: 'string', maxlength: 191, nullable: true, validations: {isLength: {max: 125}}},
415
- feature_image_caption: {type: 'text', maxlength: 65535, nullable: true}
416
+ feature_image_caption: {type: 'text', maxlength: 65535, nullable: true},
417
+ custom_excerpt: {type: 'string', maxlength: 2000, nullable: true, validations: {isLength: {max: 300}}}
416
418
  },
417
419
  members: {
418
420
  id: {type: 'string', maxlength: 24, nullable: false, primary: true},
@@ -29,7 +29,8 @@ const Newsletter = ghostBookshelf.Model.extend({
29
29
  background_color: 'light',
30
30
  border_color: null,
31
31
  title_color: null,
32
- feedback_enabled: false
32
+ feedback_enabled: false,
33
+ show_excerpt: false
33
34
  };
34
35
  },
35
36
 
@@ -973,6 +973,7 @@ Post = ghostBookshelf.Model.extend({
973
973
  feature_image_alt: model.get('posts_meta')?.feature_image_alt,
974
974
  feature_image_caption: model.get('posts_meta')?.feature_image_caption,
975
975
  title: model.get('title'),
976
+ custom_excerpt: model.get('custom_excerpt'),
976
977
  post_status: model.get('status')
977
978
  };
978
979
 
@@ -47,12 +47,16 @@ const setAccessCookies = function setAccessCookies(member = undefined, res, free
47
47
  if (!hmacSecret) {
48
48
  return;
49
49
  }
50
+ const hmacSecretBuffer = Buffer.from(hmacSecret, 'base64');
51
+ if (hmacSecretBuffer.length === 0) {
52
+ return;
53
+ }
50
54
  const activeSubscription = member.subscriptions?.find(sub => sub.status === 'active');
51
55
 
52
56
  const cookieTimestamp = Math.floor(Date.now() / 1000); // to mitigate a cookie replay attack
53
57
  const memberTier = activeSubscription && activeSubscription.tier.id || freeTier.id;
54
58
  const memberTierAndTimestamp = `${memberTier}:${cookieTimestamp}`;
55
- const memberTierHmac = crypto.createHmac('sha256', hmacSecret).update(memberTierAndTimestamp).digest('hex');
59
+ const memberTierHmac = crypto.createHmac('sha256', hmacSecretBuffer).update(memberTierAndTimestamp).digest('hex');
56
60
 
57
61
  const maxAge = 3600;
58
62
  const accessCookie = `ghost-access=${memberTierAndTimestamp}; Max-Age=${maxAge}; Path=/; HttpOnly; SameSite=Strict;`;
@@ -63,7 +63,24 @@ function ping(post) {
63
63
  if (post.custom_excerpt) {
64
64
  description = post.custom_excerpt;
65
65
  } else if (post.html) {
66
- description = `${post.html.replace(/<[^>]+>/g, '').split('.').slice(0, 3).join('.')}.`;
66
+ const membersContentIdx = post.html.indexOf('<!--members-only-->');
67
+ const substringEnd = membersContentIdx > -1 ? membersContentIdx : post.html.length;
68
+
69
+ description = `${
70
+ post.html
71
+ // Remove members-only content
72
+ .substring(0, substringEnd)
73
+ // Strip out HTML
74
+ .replace(/<[^>]+>/g, '')
75
+ // Split into sentences
76
+ .split('.')
77
+ // Remove empty strings
78
+ .filter(sentence => sentence.trim() !== '')
79
+ // Get the first three sentences
80
+ .slice(0, 3)
81
+ // Join 'em back together
82
+ .join('.')
83
+ }.`;
67
84
  } else {
68
85
  description = null;
69
86
  }
@@ -160,7 +177,10 @@ function slackListener(model, options) {
160
177
  return;
161
178
  }
162
179
 
163
- ping(model.toJSON());
180
+ ping({
181
+ ...model.toJSON(),
182
+ authors: model.related('authors').toJSON()
183
+ });
164
184
  }
165
185
 
166
186
  function slackTestPing() {
@@ -6,6 +6,7 @@ const errors = require('@tryghost/errors');
6
6
  const config = require('../../../../shared/config');
7
7
  const tpl = require('@tryghost/tpl');
8
8
  const logging = require('@tryghost/logging');
9
+ const {JSDOM} = require('jsdom');
9
10
 
10
11
  const messages = {
11
12
  db: {
@@ -144,14 +145,33 @@ const checkFileExists = (fileData) => {
144
145
 
145
146
  const checkFileIsValid = (fileData, types, extensions) => {
146
147
  const type = fileData.mimetype;
147
-
148
148
  if (types.includes(type) && extensions.includes(fileData.ext)) {
149
149
  return true;
150
150
  }
151
-
152
151
  return false;
153
152
  };
154
153
 
154
+ /**
155
+ *
156
+ * @param {String} filepath
157
+ * @returns {Boolean}
158
+ *
159
+ * Checks for the presence of <script> tags or 'on' attributes in an SVG file
160
+ *
161
+ */
162
+ const isSvgSafe = (filepath) => {
163
+ const fileContent = fs.readFileSync(filepath, 'utf8');
164
+ const document = new JSDOM(fileContent).window.document;
165
+ document.body.innerHTML = fileContent;
166
+ const svgEl = document.body.firstElementChild;
167
+
168
+ const attributes = Array.from(svgEl.attributes).map(({name}) => name);
169
+ const hasScriptAttr = !!attributes.find(attr => attr.startsWith('on'));
170
+ const scripts = svgEl.getElementsByTagName('script');
171
+
172
+ return scripts.length === 0 && !hasScriptAttr ? true : false;
173
+ };
174
+
155
175
  /**
156
176
  *
157
177
  * @param {Object} options
@@ -190,6 +210,14 @@ const validation = function ({type}) {
190
210
  }));
191
211
  }
192
212
 
213
+ if (req.file.ext === '.svg') {
214
+ if (!isSvgSafe(req.file.path)) {
215
+ return next(new errors.UnsupportedMediaTypeError({
216
+ message: 'SVG files cannot contain <script> tags or "on" attributes.'
217
+ }));
218
+ }
219
+ }
220
+
193
221
  next();
194
222
  };
195
223
  };
@@ -261,5 +289,6 @@ module.exports = {
261
289
  // Exports for testing only
262
290
  module.exports._test = {
263
291
  checkFileExists,
264
- checkFileIsValid
292
+ checkFileIsValid,
293
+ isSvgSafe
265
294
  };
@@ -25,7 +25,8 @@ const GA_FEATURES = [
25
25
  'filterEmailDisabled',
26
26
  'newEmailAddresses',
27
27
  'portalImprovements',
28
- 'onboardingChecklist'
28
+ 'onboardingChecklist',
29
+ 'newsletterExcerpt'
29
30
  ];
30
31
 
31
32
  // NOTE: this allowlist is meant to be used to filter out any unexpected
@@ -36,7 +37,8 @@ const BETA_FEATURES = [
36
37
  'activitypub',
37
38
  'internalLinking',
38
39
  'stripeAutomaticTax',
39
- 'webmentions'
40
+ 'webmentions',
41
+ 'editorExcerpt'
40
42
  ];
41
43
 
42
44
  const ALPHA_FEATURES = [
@@ -51,7 +53,8 @@ const ALPHA_FEATURES = [
51
53
  'tipsAndDonations',
52
54
  'importMemberTier',
53
55
  'lexicalIndicators',
54
- 'adminXDemo'
56
+ 'adminXDemo',
57
+ 'internalLinkingAtLinks'
55
58
  ];
56
59
 
57
60
  module.exports.GA_KEYS = [...GA_FEATURES];