ghost 5.68.0 → 5.69.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 (191) hide show
  1. package/components/tryghost-adapter-cache-memory-ttl-5.69.1.tgz +0 -0
  2. package/components/tryghost-adapter-cache-redis-5.69.1.tgz +0 -0
  3. package/components/tryghost-adapter-manager-5.69.1.tgz +0 -0
  4. package/components/tryghost-announcement-bar-settings-5.69.1.tgz +0 -0
  5. package/components/{tryghost-api-framework-5.68.0.tgz → tryghost-api-framework-5.69.1.tgz} +0 -0
  6. package/components/tryghost-api-version-compatibility-service-5.69.1.tgz +0 -0
  7. package/components/tryghost-audience-feedback-5.69.1.tgz +0 -0
  8. package/components/tryghost-bookshelf-repository-5.69.1.tgz +0 -0
  9. package/components/tryghost-bootstrap-socket-5.69.1.tgz +0 -0
  10. package/components/tryghost-collections-5.69.1.tgz +0 -0
  11. package/components/tryghost-constants-5.69.1.tgz +0 -0
  12. package/components/tryghost-custom-theme-settings-service-5.69.1.tgz +0 -0
  13. package/components/{tryghost-data-generator-5.68.0.tgz → tryghost-data-generator-5.69.1.tgz} +0 -0
  14. package/components/tryghost-domain-events-5.69.1.tgz +0 -0
  15. package/components/tryghost-donations-5.69.1.tgz +0 -0
  16. package/components/tryghost-dynamic-routing-events-5.69.1.tgz +0 -0
  17. package/components/tryghost-email-analytics-provider-mailgun-5.69.1.tgz +0 -0
  18. package/components/tryghost-email-analytics-service-5.69.1.tgz +0 -0
  19. package/components/tryghost-email-content-generator-5.69.1.tgz +0 -0
  20. package/components/tryghost-email-events-5.69.1.tgz +0 -0
  21. package/components/{tryghost-email-service-5.68.0.tgz → tryghost-email-service-5.69.1.tgz} +0 -0
  22. package/components/tryghost-email-suppression-list-5.69.1.tgz +0 -0
  23. package/components/tryghost-event-aware-cache-wrapper-5.69.1.tgz +0 -0
  24. package/components/tryghost-express-dynamic-redirects-5.69.1.tgz +0 -0
  25. package/components/tryghost-external-media-inliner-5.69.1.tgz +0 -0
  26. package/components/tryghost-extract-api-key-5.69.1.tgz +0 -0
  27. package/components/tryghost-html-to-plaintext-5.69.1.tgz +0 -0
  28. package/components/tryghost-i18n-5.69.1.tgz +0 -0
  29. package/components/tryghost-importer-handler-content-files-5.69.1.tgz +0 -0
  30. package/components/tryghost-importer-revue-5.69.1.tgz +0 -0
  31. package/components/tryghost-in-memory-repository-5.69.1.tgz +0 -0
  32. package/components/tryghost-job-manager-5.69.1.tgz +0 -0
  33. package/components/tryghost-link-redirects-5.69.1.tgz +0 -0
  34. package/components/tryghost-link-replacer-5.69.1.tgz +0 -0
  35. package/components/tryghost-link-tracking-5.69.1.tgz +0 -0
  36. package/components/tryghost-magic-link-5.69.1.tgz +0 -0
  37. package/components/tryghost-mail-events-5.69.1.tgz +0 -0
  38. package/components/tryghost-mailgun-client-5.69.1.tgz +0 -0
  39. package/components/tryghost-member-attribution-5.69.1.tgz +0 -0
  40. package/components/tryghost-member-events-5.69.1.tgz +0 -0
  41. package/components/{tryghost-members-api-5.68.0.tgz → tryghost-members-api-5.69.1.tgz} +0 -0
  42. package/components/tryghost-members-csv-5.69.1.tgz +0 -0
  43. package/components/tryghost-members-events-service-5.69.1.tgz +0 -0
  44. package/components/{tryghost-members-importer-5.68.0.tgz → tryghost-members-importer-5.69.1.tgz} +0 -0
  45. package/components/tryghost-members-offers-5.69.1.tgz +0 -0
  46. package/components/tryghost-members-payments-5.69.1.tgz +0 -0
  47. package/components/tryghost-members-ssr-5.69.1.tgz +0 -0
  48. package/components/tryghost-members-stripe-service-5.69.1.tgz +0 -0
  49. package/components/tryghost-mentions-email-report-5.69.1.tgz +0 -0
  50. package/components/{tryghost-milestones-5.68.0.tgz → tryghost-milestones-5.69.1.tgz} +0 -0
  51. package/components/tryghost-minifier-5.69.1.tgz +0 -0
  52. package/components/tryghost-model-to-domain-event-interceptor-5.69.1.tgz +0 -0
  53. package/components/tryghost-mw-api-version-mismatch-5.69.1.tgz +0 -0
  54. package/components/tryghost-mw-cache-control-5.69.1.tgz +0 -0
  55. package/components/tryghost-mw-error-handler-5.69.1.tgz +0 -0
  56. package/components/tryghost-mw-session-from-token-5.69.1.tgz +0 -0
  57. package/components/tryghost-mw-update-user-last-seen-5.69.1.tgz +0 -0
  58. package/components/tryghost-mw-version-match-5.69.1.tgz +0 -0
  59. package/components/tryghost-mw-vhost-5.69.1.tgz +0 -0
  60. package/components/tryghost-nql-filter-expansions-5.69.1.tgz +0 -0
  61. package/components/tryghost-oembed-service-5.69.1.tgz +0 -0
  62. package/components/tryghost-package-json-5.69.1.tgz +0 -0
  63. package/components/tryghost-post-events-5.69.1.tgz +0 -0
  64. package/components/tryghost-post-revisions-5.69.1.tgz +0 -0
  65. package/components/tryghost-posts-service-5.69.1.tgz +0 -0
  66. package/components/tryghost-recommendations-5.69.1.tgz +0 -0
  67. package/components/tryghost-referrers-5.69.1.tgz +0 -0
  68. package/components/tryghost-security-5.69.1.tgz +0 -0
  69. package/components/tryghost-session-service-5.69.1.tgz +0 -0
  70. package/components/tryghost-settings-path-manager-5.69.1.tgz +0 -0
  71. package/components/tryghost-slack-notifications-5.69.1.tgz +0 -0
  72. package/components/tryghost-staff-service-5.69.1.tgz +0 -0
  73. package/components/tryghost-stats-service-5.69.1.tgz +0 -0
  74. package/components/{tryghost-tiers-5.68.0.tgz → tryghost-tiers-5.69.1.tgz} +0 -0
  75. package/components/tryghost-update-check-service-5.69.1.tgz +0 -0
  76. package/components/tryghost-verification-trigger-5.69.1.tgz +0 -0
  77. package/components/tryghost-version-notifications-data-service-5.69.1.tgz +0 -0
  78. package/components/tryghost-webmentions-5.69.1.tgz +0 -0
  79. package/content/themes/source/assets/built/source.js +1 -1
  80. package/content/themes/source/assets/built/source.js.map +1 -1
  81. package/content/themes/source/assets/js/casper.js +1 -1
  82. package/content/themes/source/package.json +1 -1
  83. package/core/built/admin/assets/admin-x-settings/{CodeEditorView-73bd35b1.mjs → CodeEditorView-79c17af2.mjs} +156 -156
  84. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +2 -2
  85. package/core/built/admin/assets/admin-x-settings/{index-b8520e93.mjs → index-e3c2bcd4.mjs} +5065 -4969
  86. package/core/built/admin/assets/admin-x-settings/{limit-service-cc4a15e2.mjs → limit-service-d41dd8a7.mjs} +2 -2
  87. package/core/built/admin/assets/admin-x-settings/{modals-fc330da9.mjs → modals-e8170b93.mjs} +10591 -10266
  88. package/core/built/admin/assets/{chunk.143.5770521695d411ee098e.js → chunk.143.5515dcb02de04c657261.js} +11 -11
  89. package/core/built/admin/assets/{chunk.178.717d4af1747380378833.js → chunk.178.f75e8567214e853052de.js} +4 -4
  90. package/core/built/admin/assets/{chunk.940.f55d8073f4fd2738aa11.js → chunk.649.1ce887e24e7688045296.js} +7529 -8877
  91. package/core/built/admin/assets/{chunk.940.f55d8073f4fd2738aa11.js.LICENSE.txt → chunk.649.1ce887e24e7688045296.js.LICENSE.txt} +0 -23
  92. package/core/built/admin/assets/{ghost-fb0f793a8d8d9df304bc501fbcad01e4.js → ghost-831787c0c608f25507fb45807b60374c.js} +344 -575
  93. package/core/built/admin/assets/ghost-dark-074a63e61346f3533e60ceff7253f07d.css +1 -0
  94. package/core/built/admin/assets/ghost-de20b1dc1f76d9dd196738a479610681.css +1 -0
  95. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +14440 -14288
  96. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +118 -118
  97. package/core/built/admin/assets/{vendor-3e6947aa681f0fb82b193090e520dc73.css → vendor-0ede59da8efb5e28fa929557f7ff7154.css} +0 -7
  98. package/core/built/admin/assets/{vendor-71d23939faaa5d1478ead73d917111b9.js → vendor-d4aa86641c6080ce3bc58e6d54252774.js} +3865 -6979
  99. package/core/built/admin/index.html +7 -7
  100. package/core/frontend/helpers/img_url.js +6 -6
  101. package/core/frontend/helpers/readable_url.js +32 -0
  102. package/core/frontend/helpers/tpl/recommendations.hbs +3 -2
  103. package/core/server/api/endpoints/utils/serializers/input/pages.js +1 -1
  104. package/core/server/api/endpoints/utils/serializers/input/posts.js +1 -1
  105. package/core/server/data/migrations/utils/schema.js +31 -2
  106. package/core/server/data/migrations/versions/5.69/2023-10-06-15-06-00-rename-recommendations-reason-to-description.js +3 -0
  107. package/core/server/data/schema/commands.js +20 -0
  108. package/core/server/data/schema/schema.js +1 -1
  109. package/core/server/models/member.js +4 -2
  110. package/core/server/services/lexical-multiplayer/service.js +1 -1
  111. package/core/server/services/newsletters/NewslettersService.js +2 -2
  112. package/core/server/services/oembed/TwitterOEmbedProvider.js +5 -1
  113. package/core/server/services/settings/SettingsBREADService.js +1 -5
  114. package/core/shared/labs.js +0 -1
  115. package/package.json +158 -160
  116. package/yarn.lock +330 -450
  117. package/components/tryghost-adapter-cache-memory-ttl-5.68.0.tgz +0 -0
  118. package/components/tryghost-adapter-cache-redis-5.68.0.tgz +0 -0
  119. package/components/tryghost-adapter-manager-5.68.0.tgz +0 -0
  120. package/components/tryghost-announcement-bar-settings-5.68.0.tgz +0 -0
  121. package/components/tryghost-api-version-compatibility-service-5.68.0.tgz +0 -0
  122. package/components/tryghost-audience-feedback-5.68.0.tgz +0 -0
  123. package/components/tryghost-bookshelf-repository-5.68.0.tgz +0 -0
  124. package/components/tryghost-bootstrap-socket-5.68.0.tgz +0 -0
  125. package/components/tryghost-collections-5.68.0.tgz +0 -0
  126. package/components/tryghost-constants-5.68.0.tgz +0 -0
  127. package/components/tryghost-custom-theme-settings-service-5.68.0.tgz +0 -0
  128. package/components/tryghost-domain-events-5.68.0.tgz +0 -0
  129. package/components/tryghost-donations-5.68.0.tgz +0 -0
  130. package/components/tryghost-dynamic-routing-events-5.68.0.tgz +0 -0
  131. package/components/tryghost-email-analytics-provider-mailgun-5.68.0.tgz +0 -0
  132. package/components/tryghost-email-analytics-service-5.68.0.tgz +0 -0
  133. package/components/tryghost-email-content-generator-5.68.0.tgz +0 -0
  134. package/components/tryghost-email-events-5.68.0.tgz +0 -0
  135. package/components/tryghost-email-suppression-list-5.68.0.tgz +0 -0
  136. package/components/tryghost-event-aware-cache-wrapper-5.68.0.tgz +0 -0
  137. package/components/tryghost-express-dynamic-redirects-5.68.0.tgz +0 -0
  138. package/components/tryghost-external-media-inliner-5.68.0.tgz +0 -0
  139. package/components/tryghost-extract-api-key-5.68.0.tgz +0 -0
  140. package/components/tryghost-html-to-plaintext-5.68.0.tgz +0 -0
  141. package/components/tryghost-i18n-5.68.0.tgz +0 -0
  142. package/components/tryghost-importer-handler-content-files-5.68.0.tgz +0 -0
  143. package/components/tryghost-importer-revue-5.68.0.tgz +0 -0
  144. package/components/tryghost-in-memory-repository-5.68.0.tgz +0 -0
  145. package/components/tryghost-job-manager-5.68.0.tgz +0 -0
  146. package/components/tryghost-link-redirects-5.68.0.tgz +0 -0
  147. package/components/tryghost-link-replacer-5.68.0.tgz +0 -0
  148. package/components/tryghost-link-tracking-5.68.0.tgz +0 -0
  149. package/components/tryghost-magic-link-5.68.0.tgz +0 -0
  150. package/components/tryghost-mail-events-5.68.0.tgz +0 -0
  151. package/components/tryghost-mailgun-client-5.68.0.tgz +0 -0
  152. package/components/tryghost-member-attribution-5.68.0.tgz +0 -0
  153. package/components/tryghost-member-events-5.68.0.tgz +0 -0
  154. package/components/tryghost-members-csv-5.68.0.tgz +0 -0
  155. package/components/tryghost-members-events-service-5.68.0.tgz +0 -0
  156. package/components/tryghost-members-offers-5.68.0.tgz +0 -0
  157. package/components/tryghost-members-payments-5.68.0.tgz +0 -0
  158. package/components/tryghost-members-ssr-5.68.0.tgz +0 -0
  159. package/components/tryghost-members-stripe-service-5.68.0.tgz +0 -0
  160. package/components/tryghost-mentions-email-report-5.68.0.tgz +0 -0
  161. package/components/tryghost-minifier-5.68.0.tgz +0 -0
  162. package/components/tryghost-model-to-domain-event-interceptor-5.68.0.tgz +0 -0
  163. package/components/tryghost-mw-api-version-mismatch-5.68.0.tgz +0 -0
  164. package/components/tryghost-mw-cache-control-5.68.0.tgz +0 -0
  165. package/components/tryghost-mw-error-handler-5.68.0.tgz +0 -0
  166. package/components/tryghost-mw-session-from-token-5.68.0.tgz +0 -0
  167. package/components/tryghost-mw-update-user-last-seen-5.68.0.tgz +0 -0
  168. package/components/tryghost-mw-version-match-5.68.0.tgz +0 -0
  169. package/components/tryghost-mw-vhost-5.68.0.tgz +0 -0
  170. package/components/tryghost-nql-filter-expansions-5.68.0.tgz +0 -0
  171. package/components/tryghost-oembed-service-5.68.0.tgz +0 -0
  172. package/components/tryghost-package-json-5.68.0.tgz +0 -0
  173. package/components/tryghost-post-events-5.68.0.tgz +0 -0
  174. package/components/tryghost-post-revisions-5.68.0.tgz +0 -0
  175. package/components/tryghost-posts-service-5.68.0.tgz +0 -0
  176. package/components/tryghost-recommendations-5.68.0.tgz +0 -0
  177. package/components/tryghost-referrers-5.68.0.tgz +0 -0
  178. package/components/tryghost-security-5.68.0.tgz +0 -0
  179. package/components/tryghost-session-service-5.68.0.tgz +0 -0
  180. package/components/tryghost-settings-path-manager-5.68.0.tgz +0 -0
  181. package/components/tryghost-slack-notifications-5.68.0.tgz +0 -0
  182. package/components/tryghost-staff-service-5.68.0.tgz +0 -0
  183. package/components/tryghost-stats-service-5.68.0.tgz +0 -0
  184. package/components/tryghost-update-check-service-5.68.0.tgz +0 -0
  185. package/components/tryghost-verification-trigger-5.68.0.tgz +0 -0
  186. package/components/tryghost-version-notifications-data-service-5.68.0.tgz +0 -0
  187. package/components/tryghost-webmentions-5.68.0.tgz +0 -0
  188. package/core/built/admin/assets/ghost-04f331b095bb184b7ee00f43f65466e4.css +0 -1
  189. package/core/built/admin/assets/ghost-dark-9744221e76ff089f6176ad97379c9599.css +0 -1
  190. package/core/built/admin/assets/simplemde/simplemde-8f638be9b49c6c5fc95902d6e470c1a3.js +0 -1874
  191. package/core/cli/record-test.js +0 -30
@@ -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.68%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%22ad022e25eb%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%2203b15b5c6c%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.69%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%22efb1df78c0%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%22144e5858ba%22%7D" />
12
12
 
13
13
  <meta name="HandheldFriendly" content="True" />
14
14
  <meta name="MobileOptimized" content="320" />
@@ -36,8 +36,8 @@
36
36
  }
37
37
  </style>
38
38
 
39
- <link integrity="" rel="stylesheet" href="assets/vendor-3e6947aa681f0fb82b193090e520dc73.css">
40
- <link integrity="" rel="stylesheet" href="assets/ghost-04f331b095bb184b7ee00f43f65466e4.css" title="light">
39
+ <link integrity="" rel="stylesheet" href="assets/vendor-0ede59da8efb5e28fa929557f7ff7154.css">
40
+ <link integrity="" rel="stylesheet" href="assets/ghost-de20b1dc1f76d9dd196738a479610681.css" title="light">
41
41
 
42
42
 
43
43
  </head>
@@ -56,9 +56,9 @@
56
56
 
57
57
  <div id="ember-basic-dropdown-wormhole"></div>
58
58
 
59
- <script src="assets/vendor-71d23939faaa5d1478ead73d917111b9.js"></script>
60
- <script src="assets/chunk.940.f55d8073f4fd2738aa11.js"></script>
61
- <script src="assets/chunk.143.5770521695d411ee098e.js"></script>
62
- <script src="assets/ghost-fb0f793a8d8d9df304bc501fbcad01e4.js"></script>
59
+ <script src="assets/vendor-d4aa86641c6080ce3bc58e6d54252774.js"></script>
60
+ <script src="assets/chunk.649.1ce887e24e7688045296.js"></script>
61
+ <script src="assets/chunk.143.5515dcb02de04c657261.js"></script>
62
+ <script src="assets/ghost-831787c0c608f25507fb45807b60374c.js"></script>
63
63
  </body>
64
64
  </html>
@@ -54,7 +54,7 @@ module.exports = function imgUrl(requestedImageUrl, options) {
54
54
  // ignore errors and just return the original URL
55
55
  }
56
56
  }
57
-
57
+
58
58
  return requestedImageUrl;
59
59
  }
60
60
 
@@ -117,7 +117,7 @@ function getUnsplashImage(imagePath, sizeOptions) {
117
117
  const parsedUrl = new URL(imagePath);
118
118
  const {requestedSize, imageSizes, requestedFormat} = sizeOptions;
119
119
 
120
- if (requestedFormat) {
120
+ if (requestedFormat) {
121
121
  const supportedFormats = ['avif', 'gif', 'jpg', 'png', 'webp'];
122
122
  if (supportedFormats.includes(requestedFormat)) {
123
123
  parsedUrl.searchParams.set('fm', requestedFormat);
@@ -150,13 +150,13 @@ function getUnsplashImage(imagePath, sizeOptions) {
150
150
  }
151
151
 
152
152
  /**
153
- *
154
- * @param {string} imagePath
155
- * @param {Object} sizeOptions
153
+ *
154
+ * @param {string} imagePath
155
+ * @param {Object} sizeOptions
156
156
  * @param {string} sizeOptions.requestedSize
157
157
  * @param {Object[]} sizeOptions.imageSizes
158
158
  * @param {string} [sizeOptions.requestedFormat]
159
- * @returns
159
+ * @returns
160
160
  */
161
161
  function getImageWithSize(imagePath, sizeOptions) {
162
162
  const hasLeadingSlash = imagePath[0] === '/';
@@ -0,0 +1,32 @@
1
+ // # Readable URL helper
2
+ // Usage: `{{readable_url "https://google.com"}}`
3
+ //
4
+ // Returns a human readable URL for the given URL, e.g. google.com for https://www.google.com?query=1#section
5
+
6
+ const logging = require('@tryghost/logging');
7
+ const sentry = require('../../shared/sentry');
8
+ const errors = require('@tryghost/errors');
9
+ const {SafeString} = require('../services/handlebars');
10
+
11
+ function captureError(message) {
12
+ const error = new errors.IncorrectUsageError({message});
13
+ sentry.captureException(error);
14
+ logging.error(error);
15
+ }
16
+
17
+ module.exports = function readableUrl(inputUrl) {
18
+ if (!inputUrl || typeof inputUrl !== 'string') {
19
+ captureError(`Expected a string, received ${inputUrl}.`);
20
+ return new SafeString('');
21
+ }
22
+
23
+ try {
24
+ const url = new URL(inputUrl);
25
+ const readable = url.hostname.replace(/^www\./, '') + url.pathname.replace(/\/$/, '');
26
+
27
+ return new SafeString(readable);
28
+ } catch (e) {
29
+ captureError(`The string "${inputUrl}" could not be parsed as URL.`);
30
+ return new SafeString(inputUrl);
31
+ }
32
+ };
@@ -3,9 +3,10 @@
3
3
  {{#each recommendations as |rec|}}
4
4
  <li class="recommendation">
5
5
  <a href="{{rec.url}}" data-recommendation="{{rec.id}}" target="_blank" rel="noopener">
6
- <img class="recommendation-favicon" src="{{rec.favicon}}" alt="{{rec.title}}">
6
+ <img class="recommendation-favicon" src="{{rec.favicon}}" alt="{{rec.title}}" loading="lazy">
7
7
  <h5 class="recommendation-title">{{rec.title}}</h5>
8
- <p class="recommendation-reason">{{rec.reason}}</p>
8
+ <span class="recommendation-url">{{readable_url rec.url}}</span>
9
+ <p class="recommendation-description">{{rec.description}}</p>
9
10
  </a>
10
11
  </li>
11
12
  {{/each}}
@@ -26,7 +26,7 @@ function defaultRelations(frame) {
26
26
  return false;
27
27
  }
28
28
 
29
- frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'tiers', 'count.signups', 'count.paid_conversions', 'post_revisions', 'post_revisions.author'];
29
+ frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'tiers', 'count.signups', 'count.paid_conversions'];
30
30
  }
31
31
 
32
32
  function setDefaultOrder(frame) {
@@ -43,7 +43,7 @@ function defaultRelations(frame) {
43
43
  return false;
44
44
  }
45
45
 
46
- frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'email', 'tiers', 'newsletter', 'count.clicks', 'post_revisions', 'post_revisions.author'];
46
+ frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'email', 'tiers', 'newsletter', 'count.clicks'];
47
47
  }
48
48
 
49
49
  function setDefaultOrder(frame) {
@@ -91,7 +91,35 @@ function createSetNullableMigration(table, column, options = {}) {
91
91
  if (options.disableForeignKeyChecks) {
92
92
  await knex.raw('SET FOREIGN_KEY_CHECKS=1;').transacting(knex);
93
93
  }
94
- }
94
+ }
95
+ }
96
+ );
97
+ }
98
+
99
+ /**
100
+ * @param {string} table
101
+ * @param {string} from
102
+ * @param {string} to
103
+ *
104
+ * @returns {Migration}
105
+ */
106
+ function createRenameColumnMigration(table, from, to) {
107
+ return createNonTransactionalMigration(
108
+ async function up(knex) {
109
+ const hasColumn = await knex.schema.hasColumn(table, to);
110
+ if (hasColumn) {
111
+ logging.warn(`Renaming ${table}.${from} to ${table}.${to} column - skipping as column ${table}.${to} already exists`);
112
+ } else {
113
+ await commands.renameColumn(table, from, to, knex);
114
+ }
115
+ },
116
+ async function down(knex) {
117
+ const hasColumn = await knex.schema.hasColumn(table, from);
118
+ if (hasColumn) {
119
+ logging.warn(`Renaming ${table}.${to} to ${table}.${from} column - skipping as column ${table}.${from} already exists`);
120
+ } else {
121
+ await commands.renameColumn(table, to, from, knex);
122
+ }
95
123
  }
96
124
  );
97
125
  }
@@ -134,7 +162,8 @@ module.exports = {
134
162
  createAddColumnMigration,
135
163
  createDropColumnMigration,
136
164
  createSetNullableMigration,
137
- createDropNullableMigration
165
+ createDropNullableMigration,
166
+ createRenameColumnMigration
138
167
  };
139
168
 
140
169
  /**
@@ -0,0 +1,3 @@
1
+ const {createRenameColumnMigration} = require('../../utils');
2
+
3
+ module.exports = createRenameColumnMigration('recommendations', 'reason', 'description');
@@ -156,6 +156,25 @@ async function dropColumn(tableName, column, transaction = db.knex, columnSpec =
156
156
  }
157
157
  }
158
158
 
159
+ /**
160
+ * @param {string} tableName
161
+ * @param {string} from
162
+ * @param {string} to
163
+ * @param {import('knex').Knex.Transaction} [transaction]
164
+ */
165
+ async function renameColumn(tableName, from, to, transaction = db.knex) {
166
+ logging.info(`Renaming column '${from}' to '${to}' in table '${tableName}'`);
167
+
168
+ if (DatabaseInfo.isMySQL(transaction)) {
169
+ // The knex helper does a lot of interesting things with foreign keys that are slow on bigger MySQL clusters
170
+ return await transaction.raw(`ALTER TABLE \`${tableName}\` RENAME COLUMN \`${from}\` TO \`${to}\`;`);
171
+ }
172
+
173
+ return await transaction.schema.table(tableName, function (table) {
174
+ table.renameColumn(from, to);
175
+ });
176
+ }
177
+
159
178
  /**
160
179
  * Adds an unique index to a table over the given columns.
161
180
  *
@@ -520,6 +539,7 @@ module.exports = {
520
539
  addForeign,
521
540
  dropForeign,
522
541
  addColumn,
542
+ renameColumn,
523
543
  dropColumn,
524
544
  setNullable,
525
545
  dropNullable,
@@ -1076,7 +1076,7 @@ module.exports = {
1076
1076
  excerpt: {type: 'string', maxlength: 2000, nullable: true},
1077
1077
  featured_image: {type: 'string', maxlength: 2000, nullable: true},
1078
1078
  favicon: {type: 'string', maxlength: 2000, nullable: true},
1079
- reason: {type: 'string', maxlength: 2000, nullable: true},
1079
+ description: {type: 'string', maxlength: 2000, nullable: true},
1080
1080
  one_click_subscribe: {type: 'boolean', nullable: false, defaultTo: false},
1081
1081
  created_at: {type: 'dateTime', nullable: false},
1082
1082
  updated_at: {type: 'dateTime', nullable: true}
@@ -373,8 +373,10 @@ const Member = ghostBookshelf.Model.extend({
373
373
  },
374
374
 
375
375
  searchQuery: function searchQuery(queryBuilder, query) {
376
- queryBuilder.where('members.name', 'like', `%${query}%`);
377
- queryBuilder.orWhere('members.email', 'like', `%${query}%`);
376
+ queryBuilder.where(function () {
377
+ this.where('members.name', 'like', `%${query}%`)
378
+ .orWhere('members.email', 'like', `%${query}%`);
379
+ });
378
380
  },
379
381
 
380
382
  orderRawQuery(field, direction) {
@@ -93,7 +93,7 @@ module.exports = {
93
93
 
94
94
  _disable = async () => {
95
95
  logging.info('Stopping lexical multiplayer websockets service');
96
- ghostServer.httpServer.off('upgrade', handleUpgrade);
96
+ ghostServer.httpServer?.off('upgrade', handleUpgrade);
97
97
 
98
98
  if (wss) {
99
99
  _isClosing = true;
@@ -199,7 +199,7 @@ class NewslettersService {
199
199
  }
200
200
 
201
201
  let updatedNewsletter;
202
-
202
+
203
203
  try {
204
204
  updatedNewsletter = await this.NewsletterModel.edit(cleanedAttrs, options);
205
205
  } catch (error) {
@@ -215,7 +215,7 @@ class NewslettersService {
215
215
 
216
216
  // Load relations correctly in the response
217
217
  updatedNewsletter = await this.NewsletterModel.findOne({id: updatedNewsletter.id}, {...options, require: true});
218
-
218
+
219
219
  await this.respondWithEmailVerification(updatedNewsletter, emailsToVerify);
220
220
  return updatedNewsletter;
221
221
  }
@@ -23,7 +23,7 @@ class TwitterOEmbedProvider {
23
23
  * @returns {Promise<boolean>}
24
24
  */
25
25
  async canSupportRequest(url) {
26
- return url.host === 'twitter.com' && TWITTER_PATH_REGEX.test(url.pathname);
26
+ return (url.host === 'twitter.com' || url.host === 'x.com') && TWITTER_PATH_REGEX.test(url.pathname);
27
27
  }
28
28
 
29
29
  /**
@@ -33,6 +33,10 @@ class TwitterOEmbedProvider {
33
33
  * @returns {Promise<object>}
34
34
  */
35
35
  async getOEmbedData(url, externalRequest) {
36
+ if (url.host === 'x.com') { // api is still at twitter.com... also not certain how people are getting x urls because twitter currently redirects every x host to twitter
37
+ url = new URL('https://twitter.com' + url.pathname);
38
+ }
39
+
36
40
  const [match, tweetId] = url.pathname.match(TWITTER_PATH_REGEX);
37
41
  if (!match) {
38
42
  return null;
@@ -65,11 +65,7 @@ class SettingsBREADService {
65
65
  // @todo: need to make this more generic?
66
66
  const adminUrl = urlUtils.urlFor('admin', true);
67
67
  const signinURL = new URL(adminUrl);
68
- signinURL.hash = `/settings/members/?verifyEmail=${token}`;
69
- // NOTE: to be removed in future, this is to ensure that the new settings are used when enabled
70
- if (labsService && labsService.isSet('adminXSettings')) {
71
- signinURL.hash = `/settings-x/portal/edit?verifyEmail=${token}`;
72
- }
68
+ signinURL.hash = `/settings/portal/edit?verifyEmail=${token}`;
73
69
 
74
70
  return signinURL.href;
75
71
  }
@@ -37,7 +37,6 @@ const ALPHA_FEATURES = [
37
37
  'websockets',
38
38
  'stripeAutomaticTax',
39
39
  'emailCustomization',
40
- 'adminXSettings',
41
40
  'mailEvents',
42
41
  'collectionsCard',
43
42
  'tipsAndDonations',