ghost 5.96.0 → 5.96.2

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 (183) hide show
  1. package/components/tryghost-adapter-cache-memory-ttl-5.96.2.tgz +0 -0
  2. package/components/{tryghost-adapter-cache-redis-5.96.0.tgz → tryghost-adapter-cache-redis-5.96.2.tgz} +0 -0
  3. package/components/{tryghost-adapter-manager-5.96.0.tgz → tryghost-adapter-manager-5.96.2.tgz} +0 -0
  4. package/components/tryghost-announcement-bar-settings-5.96.2.tgz +0 -0
  5. package/components/{tryghost-api-framework-5.96.0.tgz → tryghost-api-framework-5.96.2.tgz} +0 -0
  6. package/components/{tryghost-api-version-compatibility-service-5.96.0.tgz → tryghost-api-version-compatibility-service-5.96.2.tgz} +0 -0
  7. package/components/{tryghost-audience-feedback-5.96.0.tgz → tryghost-audience-feedback-5.96.2.tgz} +0 -0
  8. package/components/tryghost-bookshelf-repository-5.96.2.tgz +0 -0
  9. package/components/{tryghost-bootstrap-socket-5.96.0.tgz → tryghost-bootstrap-socket-5.96.2.tgz} +0 -0
  10. package/components/tryghost-collections-5.96.2.tgz +0 -0
  11. package/components/tryghost-constants-5.96.2.tgz +0 -0
  12. package/components/{tryghost-custom-theme-settings-service-5.96.0.tgz → tryghost-custom-theme-settings-service-5.96.2.tgz} +0 -0
  13. package/components/{tryghost-data-generator-5.96.0.tgz → tryghost-data-generator-5.96.2.tgz} +0 -0
  14. package/components/tryghost-domain-events-5.96.2.tgz +0 -0
  15. package/components/{tryghost-donations-5.96.0.tgz → tryghost-donations-5.96.2.tgz} +0 -0
  16. package/components/tryghost-dynamic-routing-events-5.96.2.tgz +0 -0
  17. package/components/tryghost-email-addresses-5.96.2.tgz +0 -0
  18. package/components/tryghost-email-analytics-provider-mailgun-5.96.2.tgz +0 -0
  19. package/components/tryghost-email-analytics-service-5.96.2.tgz +0 -0
  20. package/components/{tryghost-email-content-generator-5.96.0.tgz → tryghost-email-content-generator-5.96.2.tgz} +0 -0
  21. package/components/tryghost-email-events-5.96.2.tgz +0 -0
  22. package/components/tryghost-email-service-5.96.2.tgz +0 -0
  23. package/components/tryghost-email-suppression-list-5.96.2.tgz +0 -0
  24. package/components/tryghost-express-dynamic-redirects-5.96.2.tgz +0 -0
  25. package/components/tryghost-external-media-inliner-5.96.2.tgz +0 -0
  26. package/components/tryghost-extract-api-key-5.96.2.tgz +0 -0
  27. package/components/tryghost-ghost-5.96.2.tgz +0 -0
  28. package/components/{tryghost-html-to-plaintext-5.96.0.tgz → tryghost-html-to-plaintext-5.96.2.tgz} +0 -0
  29. package/components/tryghost-i18n-5.96.2.tgz +0 -0
  30. package/components/tryghost-importer-handler-content-files-5.96.2.tgz +0 -0
  31. package/components/tryghost-importer-revue-5.96.2.tgz +0 -0
  32. package/components/tryghost-in-memory-repository-5.96.2.tgz +0 -0
  33. package/components/{tryghost-job-manager-5.96.0.tgz → tryghost-job-manager-5.96.2.tgz} +0 -0
  34. package/components/tryghost-link-redirects-5.96.2.tgz +0 -0
  35. package/components/{tryghost-link-replacer-5.96.0.tgz → tryghost-link-replacer-5.96.2.tgz} +0 -0
  36. package/components/{tryghost-link-tracking-5.96.0.tgz → tryghost-link-tracking-5.96.2.tgz} +0 -0
  37. package/components/{tryghost-magic-link-5.96.0.tgz → tryghost-magic-link-5.96.2.tgz} +0 -0
  38. package/components/{tryghost-mail-events-5.96.0.tgz → tryghost-mail-events-5.96.2.tgz} +0 -0
  39. package/components/{tryghost-mailgun-client-5.96.0.tgz → tryghost-mailgun-client-5.96.2.tgz} +0 -0
  40. package/components/{tryghost-member-attribution-5.96.0.tgz → tryghost-member-attribution-5.96.2.tgz} +0 -0
  41. package/components/{tryghost-member-events-5.96.0.tgz → tryghost-member-events-5.96.2.tgz} +0 -0
  42. package/components/{tryghost-members-api-5.96.0.tgz → tryghost-members-api-5.96.2.tgz} +0 -0
  43. package/components/{tryghost-members-csv-5.96.0.tgz → tryghost-members-csv-5.96.2.tgz} +0 -0
  44. package/components/{tryghost-members-events-service-5.96.0.tgz → tryghost-members-events-service-5.96.2.tgz} +0 -0
  45. package/components/{tryghost-members-importer-5.96.0.tgz → tryghost-members-importer-5.96.2.tgz} +0 -0
  46. package/components/tryghost-members-offers-5.96.2.tgz +0 -0
  47. package/components/tryghost-members-payments-5.96.2.tgz +0 -0
  48. package/components/tryghost-members-ssr-5.96.2.tgz +0 -0
  49. package/components/tryghost-members-stripe-service-5.96.2.tgz +0 -0
  50. package/components/{tryghost-mentions-email-report-5.96.0.tgz → tryghost-mentions-email-report-5.96.2.tgz} +0 -0
  51. package/components/tryghost-metrics-server-5.96.2.tgz +0 -0
  52. package/components/{tryghost-milestones-5.96.0.tgz → tryghost-milestones-5.96.2.tgz} +0 -0
  53. package/components/tryghost-minifier-5.96.2.tgz +0 -0
  54. package/components/tryghost-model-to-domain-event-interceptor-5.96.2.tgz +0 -0
  55. package/components/{tryghost-mw-api-version-mismatch-5.96.0.tgz → tryghost-mw-api-version-mismatch-5.96.2.tgz} +0 -0
  56. package/components/tryghost-mw-cache-control-5.96.2.tgz +0 -0
  57. package/components/tryghost-mw-error-handler-5.96.2.tgz +0 -0
  58. package/components/tryghost-mw-session-from-token-5.96.2.tgz +0 -0
  59. package/components/tryghost-mw-update-user-last-seen-5.96.2.tgz +0 -0
  60. package/components/tryghost-mw-version-match-5.96.2.tgz +0 -0
  61. package/components/tryghost-mw-vhost-5.96.2.tgz +0 -0
  62. package/components/tryghost-nql-filter-expansions-5.96.2.tgz +0 -0
  63. package/components/tryghost-oembed-service-5.96.2.tgz +0 -0
  64. package/components/{tryghost-package-json-5.96.0.tgz → tryghost-package-json-5.96.2.tgz} +0 -0
  65. package/components/tryghost-post-events-5.96.2.tgz +0 -0
  66. package/components/tryghost-post-revisions-5.96.2.tgz +0 -0
  67. package/components/{tryghost-posts-service-5.96.0.tgz → tryghost-posts-service-5.96.2.tgz} +0 -0
  68. package/components/tryghost-recommendations-5.96.2.tgz +0 -0
  69. package/components/tryghost-referrers-5.96.2.tgz +0 -0
  70. package/components/{tryghost-security-5.96.0.tgz → tryghost-security-5.96.2.tgz} +0 -0
  71. package/components/{tryghost-session-service-5.96.0.tgz → tryghost-session-service-5.96.2.tgz} +0 -0
  72. package/components/tryghost-settings-path-manager-5.96.2.tgz +0 -0
  73. package/components/tryghost-slack-notifications-5.96.2.tgz +0 -0
  74. package/components/{tryghost-staff-service-5.96.0.tgz → tryghost-staff-service-5.96.2.tgz} +0 -0
  75. package/components/{tryghost-stats-service-5.96.0.tgz → tryghost-stats-service-5.96.2.tgz} +0 -0
  76. package/components/{tryghost-tiers-5.96.0.tgz → tryghost-tiers-5.96.2.tgz} +0 -0
  77. package/components/tryghost-update-check-service-5.96.2.tgz +0 -0
  78. package/components/{tryghost-verification-trigger-5.96.0.tgz → tryghost-verification-trigger-5.96.2.tgz} +0 -0
  79. package/components/tryghost-version-notifications-data-service-5.96.2.tgz +0 -0
  80. package/components/tryghost-webmentions-5.96.2.tgz +0 -0
  81. package/core/bridge.js +11 -8
  82. package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +2 -2
  83. package/core/built/admin/assets/admin-x-activitypub/{index-043cbe5c.mjs → index-def21e23.mjs} +1606 -1608
  84. package/core/built/admin/assets/admin-x-activitypub/{modals-39d50cfc.mjs → modals-09282c4e.mjs} +2 -2
  85. package/core/built/admin/assets/admin-x-settings/{CodeEditorView-ef508830.mjs → CodeEditorView-85a3642c.mjs} +2 -2
  86. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
  87. package/core/built/admin/assets/admin-x-settings/{index-fb425884.mjs → index-ebbd8de9.mjs} +83 -90
  88. package/core/built/admin/assets/admin-x-settings/{index-9a5b6317.mjs → index-eeeca6f6.mjs} +2 -2
  89. package/core/built/admin/assets/admin-x-settings/{modals-12992e35.mjs → modals-8a98634b.mjs} +11206 -16095
  90. package/core/built/admin/assets/{chunk.524.c8d208efb3cca58fb564.js → chunk.524.e61cf6deaaec6bf6f9d2.js} +5 -5
  91. package/core/built/admin/assets/{chunk.582.e1e1c593838cdd38970d.js → chunk.582.6fb536052fa03fba4adb.js} +6 -6
  92. package/core/built/admin/assets/{chunk.874.2b603e6adcf3c2e9788c.js → chunk.874.e1d421507701daac30fb.js} +4529 -5591
  93. package/core/built/admin/assets/{ghost-6720b11b60bbdb3abbd6b3b5dd314d5d.js → ghost-286f9a114755e8c3c7e9c37550f624a9.js} +21 -21
  94. package/core/built/admin/assets/{ghost-0c7839fc6bdbca9bf08a2c1291159903.css → ghost-c75b9d653495f9cfce528f6e10900b3f.css} +1 -1
  95. package/core/built/admin/assets/{ghost-dark-40f095a0e0507e24e12b4bd7dd6bb5d5.css → ghost-dark-6ea629e177f77314f5d75c0ca97190ab.css} +1 -1
  96. package/core/built/admin/index.html +5 -5
  97. package/core/frontend/helpers/get.js +24 -41
  98. package/core/frontend/helpers/ghost_head.js +3 -3
  99. package/core/frontend/meta/generate-excerpt.js +1 -2
  100. package/core/frontend/services/{admin-auth-assets/AdminAuthAssetsService.js → assets-minification/AdminAuthAssets.js} +22 -62
  101. package/core/frontend/services/assets-minification/AssetsMinificationBase.js +79 -0
  102. package/core/frontend/services/{card-assets/CardAssetService.js → assets-minification/CardAssets.js} +20 -37
  103. package/core/frontend/services/assets-minification/CommentCountsAssets.js +34 -0
  104. package/core/frontend/services/assets-minification/MemberAttributionAssets.js +46 -0
  105. package/core/frontend/services/assets-minification/index.js +16 -0
  106. package/core/frontend/services/sitemap/BaseSiteMapGenerator.js +4 -1
  107. package/core/frontend/web/site.js +5 -4
  108. package/core/server/api/endpoints/utils/serializers/output/mappers/index.js +0 -1
  109. package/core/server/api/endpoints/utils/serializers/output/oembed.js +0 -7
  110. package/core/server/data/importer/importers/data/PostsImporter.js +2 -2
  111. package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -1
  112. package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -1
  113. package/core/server/data/migrations/versions/5.0/2022-05-21-00-00-regenerate-posts-html.js +1 -1
  114. package/core/server/lib/mobiledoc.js +4 -0
  115. package/core/server/models/member.js +1 -1
  116. package/core/server/models/mention.js +1 -1
  117. package/core/server/models/post.js +1 -1
  118. package/core/server/services/email-service/EmailServiceWrapper.js +1 -1
  119. package/core/server/services/oembed/service.js +1 -2
  120. package/core/server/services/themes/activate.js +2 -2
  121. package/core/server/services/themes/index.js +4 -1
  122. package/core/server/services/themes/validate.js +7 -5
  123. package/core/server/views/maintenance.html +3 -3
  124. package/core/server/web/admin/app.js +2 -1
  125. package/core/shared/config/defaults.json +3 -0
  126. package/core/shared/config/helpers.js +4 -1
  127. package/core/shared/config/utils.js +5 -6
  128. package/package.json +153 -153
  129. package/yarn.lock +129 -119
  130. package/components/tryghost-adapter-cache-memory-ttl-5.96.0.tgz +0 -0
  131. package/components/tryghost-announcement-bar-settings-5.96.0.tgz +0 -0
  132. package/components/tryghost-bookshelf-repository-5.96.0.tgz +0 -0
  133. package/components/tryghost-collections-5.96.0.tgz +0 -0
  134. package/components/tryghost-constants-5.96.0.tgz +0 -0
  135. package/components/tryghost-domain-events-5.96.0.tgz +0 -0
  136. package/components/tryghost-dynamic-routing-events-5.96.0.tgz +0 -0
  137. package/components/tryghost-email-addresses-5.96.0.tgz +0 -0
  138. package/components/tryghost-email-analytics-provider-mailgun-5.96.0.tgz +0 -0
  139. package/components/tryghost-email-analytics-service-5.96.0.tgz +0 -0
  140. package/components/tryghost-email-events-5.96.0.tgz +0 -0
  141. package/components/tryghost-email-service-5.96.0.tgz +0 -0
  142. package/components/tryghost-email-suppression-list-5.96.0.tgz +0 -0
  143. package/components/tryghost-express-dynamic-redirects-5.96.0.tgz +0 -0
  144. package/components/tryghost-external-media-inliner-5.96.0.tgz +0 -0
  145. package/components/tryghost-extract-api-key-5.96.0.tgz +0 -0
  146. package/components/tryghost-ghost-5.96.0.tgz +0 -0
  147. package/components/tryghost-i18n-5.96.0.tgz +0 -0
  148. package/components/tryghost-importer-handler-content-files-5.96.0.tgz +0 -0
  149. package/components/tryghost-importer-revue-5.96.0.tgz +0 -0
  150. package/components/tryghost-in-memory-repository-5.96.0.tgz +0 -0
  151. package/components/tryghost-link-redirects-5.96.0.tgz +0 -0
  152. package/components/tryghost-members-offers-5.96.0.tgz +0 -0
  153. package/components/tryghost-members-payments-5.96.0.tgz +0 -0
  154. package/components/tryghost-members-ssr-5.96.0.tgz +0 -0
  155. package/components/tryghost-members-stripe-service-5.96.0.tgz +0 -0
  156. package/components/tryghost-metrics-server-5.96.0.tgz +0 -0
  157. package/components/tryghost-minifier-5.96.0.tgz +0 -0
  158. package/components/tryghost-model-to-domain-event-interceptor-5.96.0.tgz +0 -0
  159. package/components/tryghost-mw-cache-control-5.96.0.tgz +0 -0
  160. package/components/tryghost-mw-error-handler-5.96.0.tgz +0 -0
  161. package/components/tryghost-mw-session-from-token-5.96.0.tgz +0 -0
  162. package/components/tryghost-mw-update-user-last-seen-5.96.0.tgz +0 -0
  163. package/components/tryghost-mw-version-match-5.96.0.tgz +0 -0
  164. package/components/tryghost-mw-vhost-5.96.0.tgz +0 -0
  165. package/components/tryghost-nql-filter-expansions-5.96.0.tgz +0 -0
  166. package/components/tryghost-oembed-service-5.96.0.tgz +0 -0
  167. package/components/tryghost-post-events-5.96.0.tgz +0 -0
  168. package/components/tryghost-post-revisions-5.96.0.tgz +0 -0
  169. package/components/tryghost-recommendations-5.96.0.tgz +0 -0
  170. package/components/tryghost-referrers-5.96.0.tgz +0 -0
  171. package/components/tryghost-settings-path-manager-5.96.0.tgz +0 -0
  172. package/components/tryghost-slack-notifications-5.96.0.tgz +0 -0
  173. package/components/tryghost-update-check-service-5.96.0.tgz +0 -0
  174. package/components/tryghost-version-notifications-data-service-5.96.0.tgz +0 -0
  175. package/components/tryghost-webmentions-5.96.0.tgz +0 -0
  176. package/core/frontend/services/admin-auth-assets/index.js +0 -4
  177. package/core/frontend/services/card-assets/index.js +0 -4
  178. package/core/frontend/services/comment-counts-assets/CommentCountsAssetsService.js +0 -59
  179. package/core/frontend/services/comment-counts-assets/index.js +0 -4
  180. package/core/frontend/services/member-attribution-assets/MemberAttributionAssetsService.js +0 -83
  181. package/core/frontend/services/member-attribution-assets/index.js +0 -4
  182. package/core/server/api/endpoints/utils/serializers/output/mappers/oembed.js +0 -5
  183. /package/core/built/admin/assets/{chunk.874.2b603e6adcf3c2e9788c.js.LICENSE.txt → chunk.874.e1d421507701daac30fb.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.96%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%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%22ee37f0b9eb%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%22eb50ad82db%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%226ee58b4615%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%22b5243a9829%22%2C%22adminXActivitypubCustomUrl%22%3A%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2F%40tryghost%2Fadmin-x-activitypub%400%2Fdist%2Fadmin-x-activitypub.js%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.96%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%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%22ee37f0b9eb%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%22eb50ad82db%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%223e886898df%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%2268888cb677%22%2C%22adminXActivitypubCustomUrl%22%3A%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2F%40tryghost%2Fadmin-x-activitypub%400%2Fdist%2Fadmin-x-activitypub.js%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-0c7839fc6bdbca9bf08a2c1291159903.css" title="light">
40
+ <link integrity="" rel="stylesheet" href="assets/ghost-c75b9d653495f9cfce528f6e10900b3f.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-88cd9f5cf5eba65221e2d2a636531eaa.js"></script>
60
- <script src="assets/chunk.874.2b603e6adcf3c2e9788c.js"></script>
61
- <script src="assets/chunk.524.c8d208efb3cca58fb564.js"></script>
62
- <script src="assets/ghost-6720b11b60bbdb3abbd6b3b5dd314d5d.js"></script>
60
+ <script src="assets/chunk.874.e1d421507701daac30fb.js"></script>
61
+ <script src="assets/chunk.524.e61cf6deaaec6bf6f9d2.js"></script>
62
+ <script src="assets/ghost-286f9a114755e8c3c7e9c37550f624a9.js"></script>
63
63
  </body>
64
64
  </html>
@@ -7,7 +7,6 @@ const {hbs, SafeString} = require('../services/handlebars');
7
7
  const logging = require('@tryghost/logging');
8
8
  const errors = require('@tryghost/errors');
9
9
  const tpl = require('@tryghost/tpl');
10
- const Sentry = require('@sentry/node');
11
10
 
12
11
  const _ = require('lodash');
13
12
  const jsonpath = require('jsonpath');
@@ -292,53 +291,37 @@ module.exports = async function get(resource, options) {
292
291
 
293
292
  // Parse the options we're going to pass to the API
294
293
  apiOptions = parseOptions(ghostGlobals, this, apiOptions);
295
- let apiOptionsString = Object.entries(apiOptions)
296
- .map(([key, value]) => ` ${key}="${value}"`)
297
- .join('');
298
294
  apiOptions.context = {member: data.member};
299
295
  try {
300
- const spanName = `{{#get "${resource}"${apiOptionsString}}} ${data.member ? 'member' : 'public'}`;
301
- const result = await Sentry.startSpan({
302
- op: 'frontend.helpers.get',
303
- name: spanName,
304
- tags: {
305
- resource,
306
- ...apiOptions,
307
- context: data.member ? 'member' : 'public'
308
- }
309
- }, async (span) => {
310
- const response = await makeAPICall(resource, controllerName, action, apiOptions);
311
-
312
- // prepare data properties for use with handlebars
313
- if (response[resource] && response[resource].length) {
314
- response[resource].forEach(prepareContextResource);
315
- }
296
+ const response = await makeAPICall(resource, controllerName, action, apiOptions);
316
297
 
317
- // used for logging details of slow requests
318
- returnedRowsCount = response[resource] && response[resource].length;
319
- span?.setTag('returnedRows', returnedRowsCount);
298
+ // prepare data properties for use with handlebars
299
+ if (response[resource] && response[resource].length) {
300
+ response[resource].forEach(prepareContextResource);
301
+ }
320
302
 
321
- // block params allows the theme developer to name the data using something like
322
- // `{{#get "posts" as |result pageInfo|}}`
323
- const blockParams = [response[resource]];
324
- if (response.meta && response.meta.pagination) {
325
- response.pagination = response.meta.pagination;
326
- blockParams.push(response.meta.pagination);
327
- }
303
+ // used for logging details of slow requests
304
+ returnedRowsCount = response[resource] && response[resource].length;
328
305
 
329
- // Call the main template function
330
- const rendered = options.fn(response, {
331
- data: data,
332
- blockParams: blockParams
333
- });
306
+ // block params allows the theme developer to name the data using something like
307
+ // `{{#get "posts" as |result pageInfo|}}`
308
+ const blockParams = [response[resource]];
309
+ if (response.meta && response.meta.pagination) {
310
+ response.pagination = response.meta.pagination;
311
+ blockParams.push(response.meta.pagination);
312
+ }
334
313
 
335
- if (response['@@ABORTED_GET_HELPER@@']) {
336
- return new SafeString(`<span data-aborted-get-helper>Could not load content</span>` + rendered);
337
- } else {
338
- return rendered;
339
- }
314
+ // Call the main template function
315
+ const rendered = options.fn(response, {
316
+ data: data,
317
+ blockParams: blockParams
340
318
  });
341
- return result;
319
+
320
+ if (response['@@ABORTED_GET_HELPER@@']) {
321
+ return new SafeString(`<span data-aborted-get-helper>Could not load content</span>` + rendered);
322
+ } else {
323
+ return rendered;
324
+ }
342
325
  } catch (error) {
343
326
  logging.error(error);
344
327
  data.error = error.message;
@@ -7,7 +7,7 @@ const {escapeExpression, SafeString} = require('../services/handlebars');
7
7
 
8
8
  // BAD REQUIRE
9
9
  // @TODO fix this require
10
- const cardAssetService = require('../services/card-assets');
10
+ const {cardAssets} = require('../services/assets-minification');
11
11
 
12
12
  const logging = require('@tryghost/logging');
13
13
  const _ = require('lodash');
@@ -297,10 +297,10 @@ module.exports = async function ghost_head(options) { // eslint-disable-line cam
297
297
  }
298
298
 
299
299
  // @TODO do this in a more "frameworky" way
300
- if (cardAssetService.hasFile('js')) {
300
+ if (cardAssets.hasFile('js')) {
301
301
  head.push(`<script defer src="${getAssetUrl('public/cards.min.js')}"></script>`);
302
302
  }
303
- if (cardAssetService.hasFile('css')) {
303
+ if (cardAssets.hasFile('css')) {
304
304
  head.push(`<link rel="stylesheet" type="text/css" href="${getAssetUrl('public/cards.min.css')}">`);
305
305
  }
306
306
 
@@ -1,5 +1,3 @@
1
- const downsize = require('downsize');
2
-
3
1
  function generateExcerpt(excerpt, truncateOptions) {
4
2
  truncateOptions = truncateOptions || {};
5
3
 
@@ -8,6 +6,7 @@ function generateExcerpt(excerpt, truncateOptions) {
8
6
  }
9
7
 
10
8
  // Just uses downsize to truncate, not format
9
+ const downsize = require('downsize');
11
10
  return downsize(excerpt, truncateOptions);
12
11
  }
13
12
 
@@ -1,23 +1,38 @@
1
1
  // const debug = require('@tryghost/debug')('comments-counts-assets');
2
2
  const Minifier = require('@tryghost/minifier');
3
3
  const path = require('path');
4
- const fs = require('fs').promises;
4
+ const fs = require('fs');
5
5
  const logging = require('@tryghost/logging');
6
6
  const config = require('../../../shared/config');
7
7
  const urlUtils = require('../../../shared/url-utils');
8
+ const AssetsMinificationBase = require('./AssetsMinificationBase');
8
9
 
9
- class AdminAuthAssetsService {
10
+ module.exports = class AdminAuthAssets extends AssetsMinificationBase {
10
11
  constructor(options = {}) {
11
- /** @private */
12
+ super(options);
13
+
12
14
  this.src = options.src || path.join(config.get('paths').assetSrc, 'admin-auth');
13
15
  /** @private */
14
16
  this.dest = options.dest || path.join(config.getContentPath('public'), 'admin-auth');
15
- /** @private */
17
+
16
18
  this.minifier = new Minifier({src: this.src, dest: this.dest});
19
+
20
+ try {
21
+ // TODO: don't do this synchronously
22
+ fs.mkdirSync(this.dest, {recursive: true});
23
+ fs.copyFileSync(path.join(this.src, 'index.html'), path.join(this.dest, 'index.html'));
24
+ } catch (error) {
25
+ if (error.code === 'EACCES') {
26
+ logging.error('Ghost was not able to write admin-auth asset files due to permissions.');
27
+ return;
28
+ }
29
+
30
+ throw error;
31
+ }
17
32
  }
18
33
 
19
34
  /**
20
- * @private
35
+ * @override
21
36
  */
22
37
  generateGlobs() {
23
38
  return {
@@ -39,62 +54,10 @@ class AdminAuthAssetsService {
39
54
  };
40
55
  }
41
56
 
42
- /**
43
- * @private
44
- * @returns {Promise<void>}
45
- */
46
- async minify(globs, options) {
47
- try {
48
- await this.minifier.minify(globs, options);
49
- } catch (error) {
50
- if (error.code === 'EACCES') {
51
- logging.error('Ghost was not able to write admin-auth asset files due to permissions.');
52
- return;
53
- }
54
-
55
- throw error;
56
- }
57
- }
58
-
59
- /**
60
- * @private
61
- * @returns {Promise<void>}
62
- */
63
- async copyStatic() {
64
- try {
65
- await fs.copyFile(path.join(this.src, 'index.html'), path.join(this.dest, 'index.html'));
66
- } catch (error) {
67
- if (error.code === 'EACCES') {
68
- logging.error('Ghost was not able to write admin-auth asset files due to permissions.');
69
- return;
70
- }
71
-
72
- throw error;
73
- }
74
- }
75
-
76
- /**
77
- * @private
78
- * @returns {Promise<void>}
79
- */
80
- async clearFiles() {
81
- const rmFile = async (name) => {
82
- await fs.unlink(path.join(this.dest, name));
83
- };
84
-
85
- let promises = [
86
- // @deprecated switch this to use fs.rm when we drop support for Node v12
87
- rmFile('admin-auth.min.js'),
88
- rmFile('index.html')
89
- ];
90
-
91
- // We don't care if removing these files fails as it's valid for them to not exist
92
- await Promise.allSettled(promises);
93
- }
94
-
95
57
  /**
96
58
  * Minify, move into the destination directory, and clear existing asset files.
97
59
  *
60
+ * @override
98
61
  * @returns {Promise<void>}
99
62
  */
100
63
  async load() {
@@ -102,8 +65,5 @@ class AdminAuthAssetsService {
102
65
  const replacements = this.generateReplacements();
103
66
  await this.clearFiles();
104
67
  await this.minify(globs, {replacements});
105
- await this.copyStatic();
106
68
  }
107
- }
108
-
109
- module.exports = AdminAuthAssetsService;
69
+ };
@@ -0,0 +1,79 @@
1
+ const path = require('path');
2
+ const fs = require('fs').promises;
3
+ const errors = require('@tryghost/errors');
4
+ const logging = require('@tryghost/logging');
5
+
6
+ module.exports = class AssetsMinificationBase {
7
+ minifier;
8
+
9
+ ready = false;
10
+
11
+ constructor(options = {}) {
12
+ this.options = options;
13
+ }
14
+
15
+ invalidate() {
16
+ this.ready = false;
17
+ }
18
+
19
+ generateGlobs() {
20
+ throw new errors.InternalServerError({
21
+ message: 'generateGlobs not implemented'
22
+ });
23
+ }
24
+
25
+ async load() {
26
+ throw new errors.InternalServerError({
27
+ message: 'load not implemented'
28
+ });
29
+ }
30
+
31
+ /**
32
+ * @returns {Promise<void>}
33
+ */
34
+ async clearFiles() {
35
+ const rmFile = async (name) => {
36
+ await fs.unlink(path.join(this.dest, name));
37
+ };
38
+
39
+ const promises = [];
40
+ for (const key of Object.keys(this.generateGlobs())) {
41
+ // @deprecated switch this to use fs.rm when we drop support for Node v12
42
+ promises.push(rmFile(key));
43
+ }
44
+
45
+ // We don't care if removing these files fails as it's valid for them to not exist
46
+ await Promise.allSettled(promises);
47
+ }
48
+
49
+ async minify(globs, options) {
50
+ try {
51
+ return await this.minifier.minify(globs, options);
52
+ } catch (error) {
53
+ if (error.code === 'EACCES') {
54
+ logging.error('Ghost was not able to write asset files due to permissions.');
55
+ return;
56
+ }
57
+
58
+ throw error;
59
+ } finally {
60
+ this.ready = true;
61
+ }
62
+ }
63
+
64
+ serveMiddleware() {
65
+ const self = this;
66
+ /**
67
+ * @param {import('express').Request} req
68
+ * @param {import('express').Response} res
69
+ * @param {import('express').NextFunction} next
70
+ */
71
+ return async function serveMiddleware(req, res, next) {
72
+ if (!self.ready) {
73
+ await self.load();
74
+ }
75
+
76
+ next();
77
+ };
78
+ }
79
+ };
@@ -2,12 +2,13 @@ const debug = require('@tryghost/debug')('card-assets');
2
2
  const Minifier = require('@tryghost/minifier');
3
3
  const _ = require('lodash');
4
4
  const path = require('path');
5
- const fs = require('fs').promises;
6
- const logging = require('@tryghost/logging');
7
5
  const config = require('../../../shared/config');
6
+ const AssetsMinificationBase = require('./AssetsMinificationBase');
8
7
 
9
- class CardAssetService {
8
+ module.exports = class CardAssets extends AssetsMinificationBase {
10
9
  constructor(options = {}) {
10
+ super(options);
11
+
11
12
  this.src = options.src || path.join(config.get('paths').assetSrc, 'cards');
12
13
  this.dest = options.dest || config.getContentPath('public');
13
14
  this.minifier = new Minifier({src: this.src, dest: this.dest});
@@ -19,6 +20,9 @@ class CardAssetService {
19
20
  this.files = [];
20
21
  }
21
22
 
23
+ /**
24
+ * @override
25
+ */
22
26
  generateGlobs() {
23
27
  // CASE: The theme has asked for all card assets to be included by default
24
28
  if (this.config === true) {
@@ -50,52 +54,33 @@ class CardAssetService {
50
54
  return {};
51
55
  }
52
56
 
53
- async minify(globs) {
54
- try {
55
- return await this.minifier.minify(globs);
56
- } catch (error) {
57
- if (error.code === 'EACCES') {
58
- logging.error('Ghost was not able to write card asset files due to permissions.');
59
- return;
60
- }
61
-
62
- throw error;
57
+ hasFile(type) {
58
+ if (this.files.length) {
59
+ return this.files.indexOf(`cards.min.${type}`) > -1;
63
60
  }
64
- }
65
-
66
- async clearFiles() {
67
- this.files = [];
68
61
 
69
- const rmFile = async (name) => {
70
- await fs.unlink(path.join(this.dest, name));
71
- };
72
-
73
- let promises = [
74
- // @deprecated switch this to use fs.rm when we drop support for Node v12
75
- rmFile('cards.min.css'),
76
- rmFile('cards.min.js')
77
- ];
78
-
79
- // We don't care if removing these files fails as it's valid for them to not exist
80
- return Promise.allSettled(promises);
62
+ return Object.keys(this.generateGlobs()).indexOf(`cards.min.${type}`) > -1;
81
63
  }
82
64
 
83
- hasFile(type) {
84
- return this.files.indexOf(`cards.min.${type}`) > -1;
65
+ invalidate(cardAssetConfig) {
66
+ if (cardAssetConfig) {
67
+ this.config = cardAssetConfig;
68
+ }
69
+
70
+ return super.invalidate();
85
71
  }
86
72
 
87
73
  /**
88
74
  * A theme can declare which cards it supports, and we'll do the rest
89
75
  *
90
- * @param {Array|boolean} cardAssetConfig
91
- * @returns
76
+ * @override
92
77
  */
93
78
  async load(cardAssetConfig) {
94
79
  if (cardAssetConfig) {
95
80
  this.config = cardAssetConfig;
96
81
  }
97
82
 
98
- debug('loading with config', cardAssetConfig);
83
+ debug('loading with config', this.config);
99
84
 
100
85
  await this.clearFiles();
101
86
 
@@ -105,6 +90,4 @@ class CardAssetService {
105
90
 
106
91
  this.files = await this.minify(globs) || [];
107
92
  }
108
- }
109
-
110
- module.exports = CardAssetService;
93
+ };
@@ -0,0 +1,34 @@
1
+ const Minifier = require('@tryghost/minifier');
2
+ const path = require('path');
3
+ const config = require('../../../shared/config');
4
+ const AssetsMinificationBase = require('./AssetsMinificationBase');
5
+
6
+ module.exports = class CommentCountsAssets extends AssetsMinificationBase {
7
+ constructor(options = {}) {
8
+ super(options);
9
+
10
+ this.src = options.src || path.join(config.get('paths').assetSrc, 'comment-counts');
11
+ this.dest = options.dest || config.getContentPath('public');
12
+ this.minifier = new Minifier({src: this.src, dest: this.dest});
13
+
14
+ this.files = [];
15
+ }
16
+
17
+ /**
18
+ * @override
19
+ */
20
+ generateGlobs() {
21
+ return {
22
+ 'comment-counts.min.js': 'js/*.js'
23
+ };
24
+ }
25
+
26
+ /**
27
+ * @override
28
+ */
29
+ async load() {
30
+ await this.clearFiles();
31
+ const globs = this.generateGlobs();
32
+ this.files = await this.minify(globs);
33
+ }
34
+ };
@@ -0,0 +1,46 @@
1
+ const Minifier = require('@tryghost/minifier');
2
+ const path = require('path');
3
+ const config = require('../../../shared/config');
4
+ const AssetsMinificationBase = require('./AssetsMinificationBase');
5
+
6
+ module.exports = class MemberAttributionAssets extends AssetsMinificationBase {
7
+ constructor(options = {}) {
8
+ super(options);
9
+
10
+ /** @private */
11
+ this.src = options.src || path.join(config.get('paths').assetSrc, 'member-attribution');
12
+ /** @private */
13
+ this.dest = options.dest || config.getContentPath('public');
14
+
15
+ this.minifier = new Minifier({src: this.src, dest: this.dest});
16
+ }
17
+
18
+ /**
19
+ * @override
20
+ */
21
+ generateGlobs() {
22
+ return {
23
+ 'member-attribution.min.js': '*.js'
24
+ };
25
+ }
26
+
27
+ /**
28
+ * @private
29
+ */
30
+ generateReplacements() {
31
+ return {};
32
+ }
33
+
34
+ /**
35
+ * Minify, move into the destination directory, and clear existing asset files.
36
+ *
37
+ * @override
38
+ * @returns {Promise<void>}
39
+ */
40
+ async load() {
41
+ const globs = this.generateGlobs();
42
+ const replacements = this.generateReplacements();
43
+ await this.clearFiles();
44
+ await this.minify(globs, {replacements});
45
+ }
46
+ };
@@ -0,0 +1,16 @@
1
+ const AdminAuthAssets = require('./AdminAuthAssets');
2
+ const CardAssets = require('./CardAssets');
3
+ const CommentCountsAssets = require('./CommentCountsAssets');
4
+ const MemberAttributionAssets = require('./MemberAttributionAssets');
5
+
6
+ const adminAuthAssets = new AdminAuthAssets();
7
+ const cardAssets = new CardAssets();
8
+ const commentCountsAssets = new CommentCountsAssets();
9
+ const memberAttributionAssets = new MemberAttributionAssets();
10
+
11
+ module.exports = {
12
+ adminAuthAssets,
13
+ cardAssets,
14
+ commentCountsAssets,
15
+ memberAttributionAssets
16
+ };
@@ -95,6 +95,9 @@ class BaseSiteMapGenerator {
95
95
  this.lastModified = Date.now();
96
96
  }
97
97
 
98
+ /**
99
+ * @returns {moment.Moment}
100
+ */
98
101
  getLastModifiedForDatum(datum) {
99
102
  if (datum.updated_at || datum.published_at || datum.created_at) {
100
103
  const modifiedDate = datum.updated_at || datum.published_at || datum.created_at;
@@ -126,7 +129,7 @@ class BaseSiteMapGenerator {
126
129
  node = {
127
130
  url: [
128
131
  {loc: url},
129
- {lastmod: moment(this.getLastModifiedForDatum(datum)).toISOString()}
132
+ {lastmod: this.getLastModifiedForDatum(datum).toISOString()}
130
133
  ]
131
134
  };
132
135
 
@@ -16,6 +16,7 @@ const membersService = require('../../server/services/members');
16
16
  const offersService = require('../../server/services/offers');
17
17
  const customRedirects = require('../../server/services/custom-redirects');
18
18
  const linkRedirects = require('../../server/services/link-redirection');
19
+ const {cardAssets, commentCountsAssets, memberAttributionAssets} = require('../services/assets-minification');
19
20
  const siteRoutes = require('./routes');
20
21
  const shared = require('../../server/web/shared');
21
22
  const errorHandler = require('@tryghost/mw-error-handler');
@@ -72,14 +73,14 @@ module.exports = function setupSiteApp(routerConfig) {
72
73
  siteApp.use(mw.servePublicFile('static', 'public/ghost.min.css', 'text/css', config.get('caching:publicAssets:maxAge')));
73
74
 
74
75
  // Card assets
75
- siteApp.use(mw.servePublicFile('built', 'public/cards.min.css', 'text/css', config.get('caching:publicAssets:maxAge')));
76
- siteApp.use(mw.servePublicFile('built', 'public/cards.min.js', 'application/javascript', config.get('caching:publicAssets:maxAge')));
76
+ siteApp.use(cardAssets.serveMiddleware(), mw.servePublicFile('built', 'public/cards.min.css', 'text/css', config.get('caching:publicAssets:maxAge')));
77
+ siteApp.use(cardAssets.serveMiddleware(), mw.servePublicFile('built', 'public/cards.min.js', 'application/javascript', config.get('caching:publicAssets:maxAge')));
77
78
 
78
79
  // Comment counts
79
- siteApp.use(mw.servePublicFile('built', 'public/comment-counts.min.js', 'application/javascript', config.get('caching:publicAssets:maxAge')));
80
+ siteApp.use(commentCountsAssets.serveMiddleware(), mw.servePublicFile('built', 'public/comment-counts.min.js', 'application/javascript', config.get('caching:publicAssets:maxAge')));
80
81
 
81
82
  // Member attribution
82
- siteApp.use(mw.servePublicFile('built', 'public/member-attribution.min.js', 'application/javascript', config.get('caching:publicAssets:maxAge')));
83
+ siteApp.use(memberAttributionAssets.serveMiddleware(), mw.servePublicFile('built', 'public/member-attribution.min.js', 'application/javascript', config.get('caching:publicAssets:maxAge')));
83
84
 
84
85
  // Serve site images using the storage adapter
85
86
  siteApp.use(STATIC_IMAGE_URL_PREFIX, mw.handleImageSizes, storage.getStorage('images').serve());
@@ -9,7 +9,6 @@ module.exports = {
9
9
  emailFailures: require('./email-failures'),
10
10
  images: require('./images'),
11
11
  integrations: require('./integrations'),
12
- oembed: require('./oembed'),
13
12
  pages: require('./pages'),
14
13
  posts: require('./posts'),
15
14
  settings: require('./settings'),
@@ -1,15 +1,8 @@
1
1
  const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:oembed');
2
- const mappers = require('./mappers');
3
2
 
4
3
  module.exports = {
5
4
  all(data, apiConfig, frame) {
6
5
  debug('all');
7
- if (data?.metadata?.thumbnail) {
8
- data.metadata.thumbnail = mappers.oembed(data.metadata.thumbnail);
9
- }
10
- if (data?.metadata?.icon) {
11
- data.metadata.icon = mappers.oembed(data.metadata.icon);
12
- }
13
6
  frame.response = data;
14
7
  }
15
8
  };
@@ -271,10 +271,10 @@ class PostsImporter extends BaseImporter {
271
271
  });
272
272
 
273
273
  model.mobiledoc = JSON.stringify(mobiledoc);
274
- model.html = mobiledocLib.mobiledocHtmlRenderer.render(JSON.parse(model.mobiledoc));
274
+ model.html = mobiledocLib.render(JSON.parse(model.mobiledoc));
275
275
  } else if (model.html && !model.lexical) {
276
276
  model.mobiledoc = JSON.stringify(mobiledocLib.htmlToMobiledocConverter(model.html));
277
- model.html = mobiledocLib.mobiledocHtmlRenderer.render(JSON.parse(model.mobiledoc));
277
+ model.html = mobiledocLib.render(JSON.parse(model.mobiledoc));
278
278
  }
279
279
 
280
280
  this.sanitizePostsMeta(model);
@@ -39,7 +39,7 @@ module.exports = createIrreversibleMigration(async (knex) => {
39
39
  continue;
40
40
  }
41
41
 
42
- const html = mobiledocLib.mobiledocHtmlRenderer.render(mobiledoc);
42
+ const html = mobiledocLib.render(mobiledoc);
43
43
 
44
44
  const updatedAttrs = {
45
45
  html: html
@@ -59,7 +59,7 @@ module.exports = createTransactionalMigration(
59
59
  }
60
60
 
61
61
  try {
62
- html = mobiledocLib.mobiledocHtmlRenderer.render(JSON.parse(mobiledoc));
62
+ html = mobiledocLib.render(JSON.parse(mobiledoc));
63
63
  } catch (err) {
64
64
  logging.warn(`Invalid mobiledoc content structure for ${id}, unable to render. Skipping`);
65
65
  continue;