ghost 4.22.3 → 4.25.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 (230) hide show
  1. package/.c8rc.json +24 -0
  2. package/.eslintrc.js +39 -0
  3. package/Gruntfile.js +0 -1
  4. package/content/public/README.md +3 -0
  5. package/content/themes/casper/assets/built/casper.js +1 -1
  6. package/content/themes/casper/assets/built/casper.js.map +1 -1
  7. package/content/themes/casper/assets/built/global.css +1 -1
  8. package/content/themes/casper/assets/built/global.css.map +1 -1
  9. package/content/themes/casper/assets/built/screen.css +1 -1
  10. package/content/themes/casper/assets/built/screen.css.map +1 -1
  11. package/content/themes/casper/assets/css/global.css +6 -1
  12. package/content/themes/casper/assets/css/screen.css +32 -216
  13. package/content/themes/casper/default.hbs +2 -2
  14. package/content/themes/casper/package.json +3 -2
  15. package/content/themes/casper/post.hbs +1 -1
  16. package/content/themes/casper/yarn.lock +173 -123
  17. package/core/app.js +12 -1
  18. package/core/boot.js +47 -28
  19. package/core/bridge.js +10 -10
  20. package/core/built/assets/{chunk.3.324fd0cc598c73650219.js → chunk.3.8f95b516d88ff4eec64c.js} +18 -18
  21. package/core/built/assets/ghost-dark-d690e732e17ffc794e2e59c1467ca282.css +1 -0
  22. package/core/built/assets/ghost.min-043bb7480a0810109b130f13b2a4235e.css +1 -0
  23. package/core/built/assets/{ghost.min-7da921f6c6cac3fe10da1ba104575440.js → ghost.min-bc72f685c1c9adc9885925c1412435a5.js} +563 -605
  24. package/core/built/assets/icons/audio-upload.svg +8 -0
  25. package/core/built/assets/icons/powered-by-tenor.svg +35 -0
  26. package/core/built/assets/icons/tenor.svg +7 -0
  27. package/core/built/assets/{vendor.min-413f887176a041e6dbf88214ca9a7481.js → vendor.min-d1234c632a54502777c34e50752fa3fc.js} +4622 -3631
  28. package/core/frontend/apps/amp/lib/helpers/amp_content.js +2 -2
  29. package/core/frontend/apps/amp/lib/views/amp.hbs +112 -0
  30. package/core/frontend/apps/private-blogging/index.js +1 -1
  31. package/core/frontend/apps/private-blogging/lib/router.js +1 -1
  32. package/core/frontend/services/apps/index.js +1 -1
  33. package/core/frontend/services/apps/loader.js +3 -3
  34. package/core/frontend/services/card-assets/index.js +0 -12
  35. package/core/frontend/services/card-assets/service.js +29 -28
  36. package/core/frontend/services/helpers/handlebars.js +1 -1
  37. package/core/frontend/services/routing/CollectionRouter.js +4 -5
  38. package/core/frontend/services/routing/EmailRouter.js +1 -1
  39. package/core/frontend/services/routing/ParentRouter.js +0 -8
  40. package/core/frontend/services/routing/PreviewRouter.js +1 -1
  41. package/core/frontend/services/routing/StaticPagesRouter.js +1 -1
  42. package/core/frontend/services/routing/StaticRoutesRouter.js +4 -4
  43. package/core/frontend/services/routing/TaxonomyRouter.js +3 -3
  44. package/core/frontend/services/routing/{middlewares → middleware}/index.js +0 -0
  45. package/core/frontend/services/routing/{middlewares → middleware}/page-param.js +0 -0
  46. package/core/frontend/services/routing/router-manager.js +7 -2
  47. package/core/frontend/services/rss/generate-feed.js +2 -1
  48. package/core/frontend/services/theme-engine/middleware/ensure-active-theme.js +34 -0
  49. package/core/frontend/services/theme-engine/middleware/index.js +6 -0
  50. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +116 -0
  51. package/core/frontend/services/theme-engine/middleware/update-local-template-data.js +9 -0
  52. package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +57 -0
  53. package/core/frontend/src/cards/css/bookmark.css +72 -47
  54. package/core/frontend/src/cards/css/button.css +4 -0
  55. package/core/frontend/src/cards/css/callout.css +40 -3
  56. package/core/frontend/src/cards/css/gallery.css +15 -10
  57. package/core/frontend/src/cards/css/nft.css +20 -11
  58. package/core/frontend/src/cards/css/toggle.css +58 -0
  59. package/core/frontend/src/cards/js/toggle.js +16 -0
  60. package/core/frontend/web/middleware/error-handler.js +93 -0
  61. package/core/frontend/web/middleware/handle-image-sizes.js +3 -6
  62. package/core/frontend/web/middleware/index.js +1 -0
  63. package/core/frontend/web/middleware/serve-public-file.js +39 -16
  64. package/core/frontend/web/site.js +11 -14
  65. package/core/server/adapters/scheduling/SchedulingDefault.js +2 -2
  66. package/core/server/adapters/storage/LocalStorageBase.js +2 -2
  67. package/core/server/api/canary/authentication.js +1 -1
  68. package/core/server/api/canary/db.js +2 -2
  69. package/core/server/api/canary/media.js +3 -2
  70. package/core/server/api/canary/oembed.js +16 -1
  71. package/core/server/api/canary/session.js +1 -1
  72. package/core/server/api/canary/slugs.js +1 -1
  73. package/core/server/api/canary/utils/permissions.js +2 -2
  74. package/core/server/api/canary/utils/serializers/output/config.js +2 -6
  75. package/core/server/api/v2/authentication.js +1 -1
  76. package/core/server/api/v2/db.js +2 -2
  77. package/core/server/api/v2/session.js +1 -1
  78. package/core/server/api/v2/slugs.js +1 -1
  79. package/core/server/api/v2/utils/permissions.js +2 -2
  80. package/core/server/api/v3/authentication.js +1 -1
  81. package/core/server/api/v3/db.js +2 -2
  82. package/core/server/api/v3/session.js +1 -1
  83. package/core/server/api/v3/slugs.js +1 -1
  84. package/core/server/api/v3/utils/permissions.js +2 -2
  85. package/core/server/data/db/connection.js +7 -0
  86. package/core/server/data/db/state-manager.js +4 -4
  87. package/core/server/data/exporter/export-filename.js +1 -1
  88. package/core/server/data/importer/handlers/json.js +1 -1
  89. package/core/server/data/importer/import-manager.js +1 -1
  90. package/core/server/data/importer/importers/data/base.js +1 -1
  91. package/core/server/data/importer/importers/data/data-importer.js +3 -3
  92. package/core/server/data/migrations/init/2-create-fixtures.js +3 -20
  93. package/core/server/data/migrations/utils.js +2 -2
  94. package/core/server/data/migrations/versions/1.21/1-add-contributor-role.js +5 -5
  95. package/core/server/data/migrations/versions/1.25/1-update-koenig-beta-html.js +1 -0
  96. package/core/server/data/migrations/versions/2.15/2-insert-zapier-integration.js +3 -3
  97. package/core/server/data/migrations/versions/2.2/3-insert-admin-integration-role.js +5 -5
  98. package/core/server/data/migrations/versions/2.27/1-insert-ghost-db-backup-role.js +5 -6
  99. package/core/server/data/migrations/versions/2.27/2-insert-db-backup-integration.js +3 -4
  100. package/core/server/data/migrations/versions/2.28/3-insert-ghost-scheduler-role.js +7 -7
  101. package/core/server/data/migrations/versions/2.28/4-insert-scheduler-integration.js +3 -3
  102. package/core/server/data/migrations/versions/3.1/08-add-uuid-values-to-members.js +1 -0
  103. package/core/server/data/migrations/versions/3.22/02-settings-key-renames.js +2 -0
  104. package/core/server/data/migrations/versions/3.22/05-migrate-members-subscription-settings.js +3 -0
  105. package/core/server/data/migrations/versions/3.22/06-migrate-stripe-connect-settings.js +2 -0
  106. package/core/server/data/migrations/versions/3.23/01-migrate-bulk-email-settings.js +1 -0
  107. package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -0
  108. package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -0
  109. package/core/server/data/migrations/versions/3.38/04-populate-recipient-filter-column.js +2 -0
  110. package/core/server/data/migrations/versions/4.0/01-update-mobiledoc.js +2 -0
  111. package/core/server/data/migrations/versions/4.0/03-populate-status-column-for-members.js +4 -0
  112. package/core/server/data/migrations/versions/4.0/06-populate-members-subscribe-events-table.js +1 -0
  113. package/core/server/data/migrations/versions/4.0/17-populate-members-status-events-table.js +1 -0
  114. package/core/server/data/migrations/versions/4.0/18-transform-urls-absolute-to-transform-ready.js +5 -0
  115. package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +1 -0
  116. package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -0
  117. package/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +2 -1
  118. package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +1 -0
  119. package/core/server/data/migrations/versions/4.14/01-fix-comped-member-statuses.js +3 -0
  120. package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +1 -0
  121. package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +2 -0
  122. package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +59 -0
  123. package/core/server/data/migrations/versions/4.3/04-attach-members-to-product.js +1 -0
  124. package/core/server/data/migrations/versions/4.4/01-restore-free-members-signup-setting-from-backup.js +1 -0
  125. package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +1 -0
  126. package/core/server/data/migrations/versions/4.8/04-migrate-show-newsletter-header-setting.js +1 -0
  127. package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -0
  128. package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +1 -0
  129. package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +1 -0
  130. package/core/server/data/schema/commands.js +2 -2
  131. package/core/server/data/schema/fixtures/fixture-manager.js +340 -0
  132. package/core/server/data/schema/fixtures/index.js +8 -2
  133. package/core/server/ghost-server.js +2 -2
  134. package/core/server/lib/image/image-size.js +2 -2
  135. package/core/server/models/base/listeners.js +2 -2
  136. package/core/server/models/member-email-change-event.js +2 -2
  137. package/core/server/models/member-login-event.js +2 -2
  138. package/core/server/models/member-paid-subscription-event.js +3 -3
  139. package/core/server/models/member-payment-event.js +3 -3
  140. package/core/server/models/member-product-event.js +6 -6
  141. package/core/server/models/member-status-event.js +5 -3
  142. package/core/server/models/member-subscribe-event.js +9 -3
  143. package/core/server/models/relations/authors.js +1 -1
  144. package/core/server/models/settings.js +1 -1
  145. package/core/server/services/auth/passwordreset.js +1 -1
  146. package/core/server/services/auth/setup.js +1 -1
  147. package/core/server/services/email-analytics/jobs/index.js +1 -1
  148. package/core/server/services/mega/mega.js +6 -4
  149. package/core/server/services/mega/post-email-serializer.js +5 -1
  150. package/core/server/services/mega/segment-parser.js +1 -2
  151. package/core/server/services/mega/template.js +52 -37
  152. package/core/server/services/members/api.js +22 -0
  153. package/core/server/services/members/config.js +1 -1
  154. package/core/server/services/members/emails/signup-paid.js +168 -0
  155. package/core/server/services/members/service.js +6 -2
  156. package/core/server/services/members/stripe-connect.js +4 -2
  157. package/core/server/services/nft-oembed.js +13 -22
  158. package/core/server/services/oembed.js +28 -24
  159. package/core/server/services/permissions/can-this.js +1 -1
  160. package/core/server/services/public-config/config.js +1 -1
  161. package/core/server/services/redirects/api.js +20 -25
  162. package/core/server/services/redirects/index.js +18 -10
  163. package/core/server/services/redirects/utils.js +14 -0
  164. package/core/server/services/redirects/validation.js +10 -0
  165. package/core/server/services/route-settings/default-settings-manager.js +1 -1
  166. package/core/server/services/route-settings/index.js +40 -17
  167. package/core/server/services/route-settings/route-settings.js +120 -115
  168. package/core/server/services/route-settings/settings-loader.js +18 -36
  169. package/core/server/services/route-settings/yaml-parser.js +1 -1
  170. package/core/server/services/slack.js +1 -1
  171. package/core/server/services/themes/activation-bridge.js +3 -3
  172. package/core/server/services/themes/storage.js +2 -2
  173. package/core/server/services/twitter-embed.js +80 -0
  174. package/core/server/services/url/LocalFileCache.js +75 -0
  175. package/core/server/services/url/Resources.js +8 -2
  176. package/core/server/services/url/UrlGenerator.js +23 -20
  177. package/core/server/services/url/UrlService.js +75 -63
  178. package/core/server/services/url/index.js +17 -3
  179. package/core/server/services/xmlrpc.js +2 -2
  180. package/core/server/web/admin/app.js +7 -10
  181. package/core/server/web/admin/controller.js +35 -12
  182. package/core/server/web/admin/middleware/redirect-admin-urls.js +15 -0
  183. package/core/server/web/admin/views/default-prod.html +4 -4
  184. package/core/server/web/admin/views/default.html +4 -4
  185. package/core/server/web/api/app.js +1 -1
  186. package/core/server/web/api/canary/admin/app.js +3 -6
  187. package/core/server/web/api/canary/admin/middleware.js +7 -7
  188. package/core/server/web/api/canary/admin/routes.js +5 -5
  189. package/core/server/web/api/canary/content/app.js +3 -6
  190. package/core/server/web/api/canary/content/middleware.js +3 -3
  191. package/core/server/web/api/v2/admin/app.js +3 -6
  192. package/core/server/web/api/v2/admin/middleware.js +7 -7
  193. package/core/server/web/api/v2/admin/routes.js +5 -5
  194. package/core/server/web/api/v2/content/app.js +3 -6
  195. package/core/server/web/api/v2/content/middleware.js +3 -3
  196. package/core/server/web/api/v3/admin/app.js +3 -6
  197. package/core/server/web/api/v3/admin/middleware.js +7 -7
  198. package/core/server/web/api/v3/admin/routes.js +5 -5
  199. package/core/server/web/api/v3/content/app.js +3 -6
  200. package/core/server/web/api/v3/content/middleware.js +3 -3
  201. package/core/server/web/members/app.js +6 -9
  202. package/core/server/web/oauth/app.js +0 -4
  203. package/core/server/web/parent/app.js +17 -9
  204. package/core/server/web/parent/frontend.js +1 -1
  205. package/core/server/web/shared/index.js +2 -2
  206. package/core/server/web/shared/{middlewares → middleware}/api/index.js +0 -0
  207. package/core/server/web/shared/{middlewares → middleware}/api/spam-prevention.js +0 -0
  208. package/core/server/web/shared/{middlewares → middleware}/brute.js +0 -0
  209. package/core/server/web/shared/{middlewares → middleware}/cache-control.js +0 -0
  210. package/core/server/web/shared/middleware/error-handler.js +224 -0
  211. package/core/server/web/shared/{middlewares → middleware}/index.js +0 -4
  212. package/core/server/web/shared/{middlewares → middleware}/pretty-urls.js +0 -0
  213. package/core/server/web/shared/{middlewares → middleware}/uncapitalise.js +0 -0
  214. package/core/server/web/shared/{middlewares → middleware}/url-redirects.js +0 -0
  215. package/core/shared/config/defaults.json +13 -1
  216. package/core/shared/config/helpers.js +42 -0
  217. package/core/shared/config/loader.js +1 -1
  218. package/core/shared/labs.js +9 -5
  219. package/core/shared/sentry.js +1 -1
  220. package/loggingrc.js +19 -20
  221. package/package.json +38 -37
  222. package/yarn.lock +1064 -892
  223. package/content/themes/casper/assets/js/gallery-card.js +0 -24
  224. package/core/built/assets/ghost-dark-39fb496d051565531062d7e047d1c0b1.css +0 -1
  225. package/core/built/assets/ghost.min-4207edfc1ae0a3f9f6505ca00d20b0c0.css +0 -1
  226. package/core/frontend/services/theme-engine/middleware.js +0 -209
  227. package/core/server/data/schema/fixtures/utils.js +0 -321
  228. package/core/server/web/parent/vhost-utils.js +0 -39
  229. package/core/server/web/shared/middlewares/error-handler.js +0 -329
  230. package/core/server/web/shared/middlewares/maintenance.js +0 -25
@@ -0,0 +1,9 @@
1
+ function updateLocalTemplateData(req, res, next) {
2
+ // Pass 'secure' flag to the view engine
3
+ // so that templates can choose to render https or http 'url', see url utility
4
+ res.locals.secure = req.secure;
5
+
6
+ next();
7
+ }
8
+
9
+ module.exports = updateLocalTemplateData;
@@ -0,0 +1,57 @@
1
+ const _ = require('lodash');
2
+ const hbs = require('../engine');
3
+ const urlUtils = require('../../../../shared/url-utils');
4
+ const customThemeSettingsCache = require('../../../../shared/custom-theme-settings-cache');
5
+ const labs = require('../../../../shared/labs');
6
+ const preview = require('../preview');
7
+
8
+ function updateLocalTemplateOptions(req, res, next) {
9
+ const localTemplateOptions = hbs.getLocalTemplateOptions(res.locals);
10
+
11
+ // adjust @site.url for http/https based on the incoming request
12
+ const siteData = {
13
+ url: urlUtils.urlFor('home', {secure: req.secure, trailingSlash: false}, true)
14
+ };
15
+
16
+ // @TODO: it would be nicer if this was proper middleware somehow...
17
+ const previewData = preview.handle(req, Object.keys(customThemeSettingsCache.getAll()));
18
+
19
+ // strip custom off of preview data so it doesn't get merged into @site
20
+ const customThemeSettingsPreviewData = previewData.custom;
21
+ delete previewData.custom;
22
+ let customData = {};
23
+ if (labs.isSet('customThemeSettings')) {
24
+ customData = customThemeSettingsPreviewData;
25
+ }
26
+
27
+ // update site data with any preview values from the request
28
+ Object.assign(siteData, previewData);
29
+
30
+ const member = req.member ? {
31
+ uuid: req.member.uuid,
32
+ email: req.member.email,
33
+ name: req.member.name,
34
+ firstname: req.member.name && req.member.name.split(' ')[0],
35
+ avatar_image: req.member.avatar_image,
36
+ subscriptions: req.member.subscriptions && req.member.subscriptions.map((sub) => {
37
+ return Object.assign({}, sub, {
38
+ default_payment_card_last4: sub.default_payment_card_last4 || '****'
39
+ });
40
+ }),
41
+ paid: req.member.status !== 'free'
42
+ } : null;
43
+
44
+ hbs.updateLocalTemplateOptions(res.locals, _.merge({}, localTemplateOptions, {
45
+ data: {
46
+ member: member,
47
+ site: siteData,
48
+ custom: customData,
49
+ // @deprecated: a gscan warning for @blog was added before 3.0 which replaced it with @site
50
+ blog: siteData
51
+ }
52
+ }));
53
+
54
+ next();
55
+ }
56
+
57
+ module.exports = updateLocalTemplateOptions;
@@ -1,83 +1,108 @@
1
- /* style.css */
2
-
3
- .kg-bookmark-card {
4
- width: 100%;
1
+ .kg-bookmark-card,
2
+ .kg-bookmark-publisher {
5
3
  position: relative;
4
+ width: 100%;
6
5
  }
7
6
 
8
- .kg-bookmark-container {
9
- display: flex;
10
- flex-wrap: wrap;
11
- flex-direction: row-reverse;
12
- color: currentColor;
13
- font-family: inherit;
14
- text-decoration: none;
15
- border: 1px solid rgba(0, 0, 0, 0.1);
16
- }
17
-
7
+ .kg-bookmark-container,
18
8
  .kg-bookmark-container:hover {
9
+ display: flex;
19
10
  text-decoration: none;
11
+ border-radius: 4px;
12
+ box-shadow: inset 0 0 0 1px rgb(124 139 154 / 25%);
13
+ overflow: hidden;
20
14
  }
21
15
 
22
16
  .kg-bookmark-content {
23
- flex-basis: 0;
24
- flex-grow: 999;
17
+ display: flex;
18
+ flex-direction: column;
19
+ flex-grow: 1;
20
+ flex-basis: 100%;
21
+ align-items: flex-start;
22
+ justify-content: flex-start;
25
23
  padding: 20px;
26
- order: 1;
24
+ overflow: hidden;
27
25
  }
28
26
 
29
27
  .kg-bookmark-title {
28
+ font-size: 1.5rem;
29
+ line-height: 1.4em;
30
30
  font-weight: 600;
31
31
  }
32
32
 
33
- .kg-bookmark-metadata,
34
33
  .kg-bookmark-description {
35
- margin-top: .5em;
34
+ display: -webkit-box;
35
+ font-size: 1.4rem;
36
+ line-height: 1.5em;
37
+ margin-top: 3px;
38
+ font-weight: 400;
39
+ max-height: 44px;
40
+ overflow-y: hidden;
41
+ opacity: 0.7;
42
+ -webkit-line-clamp: 2;
43
+ -webkit-box-orient: vertical;
36
44
  }
37
45
 
38
46
  .kg-bookmark-metadata {
47
+ display: flex;
39
48
  align-items: center;
49
+ margin-top: 22px;
50
+ width: 100%;
51
+ font-size: 1.4rem;
52
+ font-weight: 500;
40
53
  white-space: nowrap;
41
- overflow: hidden;
42
- text-overflow: ellipsis;
43
54
  }
44
55
 
45
- .kg-bookmark-description {
46
- display: -webkit-box;
47
- -webkit-box-orient: vertical;
48
- -webkit-line-clamp: 2;
49
- overflow: hidden;
56
+ .kg-bookmark-metadata > *:not(img) {
57
+ opacity: 0.7;
50
58
  }
51
59
 
52
60
  .kg-bookmark-icon {
53
- display: inline-block;
54
- width: 1em;
55
- height: 1em;
56
- vertical-align: text-bottom;
57
- margin-right: .5em;
58
- margin-bottom: .05em;
61
+ width: 20px;
62
+ height: 20px;
63
+ margin-right: 6px;
59
64
  }
60
65
 
61
- .kg-bookmark-thumbnail {
62
- display: flex;
63
- flex-basis: 24rem;
64
- flex-grow: 1;
65
- }
66
-
67
- .kg-bookmark-thumbnail img {
68
- max-width: 100%;
69
- height: auto;
70
- vertical-align: bottom;
71
- object-fit: cover;
66
+ .kg-bookmark-author,
67
+ .kg-bookmark-publisher {
68
+ display: inline;
72
69
  }
73
70
 
74
- .kg-bookmark-author {
75
- white-space: nowrap;
71
+ .kg-bookmark-publisher {
76
72
  text-overflow: ellipsis;
77
73
  overflow: hidden;
74
+ max-width: 240px;
75
+ white-space: nowrap;
76
+ display: block;
77
+ line-height: 1.65em;
78
+ }
79
+
80
+ .kg-bookmark-metadata > span:nth-of-type(2) {
81
+ font-weight: 400;
78
82
  }
79
83
 
80
- .kg-bookmark-publisher::before {
84
+ .kg-bookmark-metadata > span:nth-of-type(2):before {
81
85
  content: "•";
82
- margin: 0 .5em;
86
+ margin: 0 6px;
87
+ }
88
+
89
+ .kg-bookmark-metadata > span:last-of-type {
90
+ overflow: hidden;
91
+ text-overflow: ellipsis;
92
+ }
93
+
94
+ .kg-bookmark-thumbnail {
95
+ position: relative;
96
+ flex-grow: 1;
97
+ min-width: 33%;
98
+ }
99
+
100
+ .kg-bookmark-thumbnail img {
101
+ width: 100%;
102
+ height: 100%;
103
+ object-fit: cover;
104
+ position: absolute;
105
+ top: 0;
106
+ left: 0;
107
+ border-radius: 0 4px 4px 0;
83
108
  }
@@ -6,6 +6,10 @@
6
6
  justify-content: center;
7
7
  }
8
8
 
9
+ .kg-button-card.kg-align-left {
10
+ justify-content: flex-start;
11
+ }
12
+
9
13
  a.kg-btn {
10
14
  display: flex;
11
15
  position: static;
@@ -1,12 +1,49 @@
1
1
  .kg-callout-card {
2
2
  display: flex;
3
- padding: 16px 24px;
4
- background: #f1f3f4;
3
+ padding: 20px 28px;
5
4
  border-radius: 3px;
6
5
  }
7
6
 
7
+ .kg-callout-card-grey {
8
+ background: rgba(124, 139, 154, 0.13);
9
+ }
10
+
11
+ .kg-callout-card-white {
12
+ background: transparent;
13
+ box-shadow: inset 0 0 0 1px rgba(124, 139, 154, 0.25);
14
+ }
15
+
16
+ .kg-callout-card-blue {
17
+ background: rgba(33, 172, 232, 0.12);
18
+ }
19
+
20
+ .kg-callout-card-green {
21
+ background: rgba(52, 183, 67, 0.12);
22
+ }
23
+
24
+ .kg-callout-card-yellow {
25
+ background: rgba(240, 165, 15, 0.13);
26
+ }
27
+
28
+ .kg-callout-card-red {
29
+ background: rgba(209, 46, 46, 0.11);
30
+ }
31
+
32
+ .kg-callout-card-pink {
33
+ background: rgba(225, 71, 174, 0.11);
34
+ }
35
+
36
+ .kg-callout-card-purple {
37
+ background: rgba(135, 85, 236, 0.12);
38
+ }
39
+
40
+ .kg-callout-card-accent {
41
+ background: var(--ghost-accent-color);
42
+ color: #fff;
43
+ }
44
+
8
45
  .kg-callout-emoji {
9
- padding-right: 12px;
46
+ padding-right: 16px;
10
47
  line-height: 1.6;
11
48
  font-size: 2rem;
12
49
  }
@@ -1,17 +1,16 @@
1
1
  .kg-gallery-card {
2
- margin: 0 0 1.5em;
2
+ --gap: 1.2rem;
3
3
  }
4
4
 
5
- .kg-gallery-card figcaption {
6
- margin: -1.0em 0 1.5em;
5
+ .kg-image-card:not(.kg-card-hascaption) + .kg-image-card,
6
+ .kg-image-card:not(.kg-card-hascaption) + .kg-gallery-card,
7
+ .kg-gallery-card:not(.kg-card-hascaption) + .kg-image-card,
8
+ .kg-gallery-card:not(.kg-card-hascaption) + .kg-gallery-card {
9
+ margin-top: var(--gap);
7
10
  }
8
11
 
9
12
  .kg-gallery-container {
10
- display: flex;
11
- flex-direction: column;
12
- margin: 1.5em auto;
13
- max-width: 1040px;
14
- width: 100vw;
13
+ position: relative;
15
14
  }
16
15
 
17
16
  .kg-gallery-row {
@@ -28,9 +27,15 @@
28
27
  }
29
28
 
30
29
  .kg-gallery-row:not(:first-of-type) {
31
- margin: 0.75em 0 0 0;
30
+ margin: var(--gap) 0 0;
32
31
  }
33
32
 
34
33
  .kg-gallery-image:not(:first-of-type) {
35
- margin: 0 0 0 0.75em;
34
+ margin: 0 0 0 var(--gap);
36
35
  }
36
+
37
+ @media (max-width: 600px) {
38
+ .kg-gallery-card {
39
+ --gap: 0.6rem;
40
+ }
41
+ }
@@ -1,4 +1,11 @@
1
- a.kg-nft-card {
1
+ .kg-nft-card {
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: center;
5
+ width: 100%;
6
+ }
7
+
8
+ .kg-nft-card-container {
2
9
  position: static;
3
10
  display: flex;
4
11
  flex: auto;
@@ -22,31 +29,30 @@ a.kg-nft-card {
22
29
  transition: none;
23
30
  }
24
31
 
25
- a.kg-nft-card:hover {
32
+ .kg-nft-card:hover {
26
33
  color: #333;
27
34
  opacity: 1.0;
28
35
  transition: none;
29
36
  }
30
37
 
31
- a.kg-nft-card * {
38
+ .kg-nft-card * {
32
39
  position: static;
33
- line-height: 1;
34
40
  }
35
41
 
36
42
  .kg-nft-metadata {
37
43
  padding: 2.0rem;
44
+ width: 100%;
38
45
  }
39
46
 
40
- .kg-nft-card img {
41
- min-width: unset;
42
- max-width: unset;
43
- margin: -1px;
47
+ .kg-nft-image {
44
48
  border-radius: 5px 5px 0 0;
49
+ width: 100%;
45
50
  }
46
51
 
47
52
  .kg-nft-header {
48
53
  display: flex;
49
54
  justify-content: space-between;
55
+ align-items: flex-start;
50
56
  gap: 20px;
51
57
  }
52
58
 
@@ -54,20 +60,23 @@ a.kg-nft-card * {
54
60
  font-family: inherit;
55
61
  font-size: 1.9rem;
56
62
  font-weight: 700;
63
+ line-height: 1.3em;
57
64
  min-width: unset;
58
65
  max-width: unset;
59
66
  margin: 0;
60
67
  color: #222;
61
68
  }
62
69
 
63
- .kg-nft-header svg {
70
+ .kg-nft-opensea-logo {
71
+ margin-top: 2px;
64
72
  width: 100px;
65
- height: auto;
73
+ object-fit: scale-down;
66
74
  }
67
75
 
68
76
  .kg-nft-creator {
69
77
  font-family: inherit;
70
- margin: 0.8rem 0 0;
78
+ line-height: 1.4em;
79
+ margin: 0.4rem 0 0;
71
80
  color: #ababab;
72
81
  }
73
82
 
@@ -0,0 +1,58 @@
1
+ .kg-toggle-card[data-kg-toggle-state="close"] .kg-toggle-content{
2
+ visibility: hidden;
3
+ opacity: 0;
4
+ max-height: 0;
5
+ padding-top: 0px;
6
+ }
7
+
8
+ .kg-toggle-card[data-kg-toggle-state="close"] svg {
9
+ transform: unset;
10
+ }
11
+
12
+ .kg-toggle-card {
13
+ background: transparent;
14
+ box-shadow: inset 0 0 0 1px rgba(124, 139, 154, 0.25);
15
+ border-radius: 4px;
16
+ padding: 20px;
17
+ }
18
+
19
+ .kg-toggle-heading {
20
+ font-weight: 600;
21
+ cursor: pointer;
22
+ display: flex;
23
+ justify-content: space-between;
24
+ align-items: flex-start;
25
+ }
26
+
27
+ .kg-toggle-card-icon {
28
+ height: 24px;
29
+ width: 24px;
30
+ display: flex;
31
+ justify-content: center;
32
+ align-items: center;
33
+ margin-left: 16px;
34
+ }
35
+
36
+ .kg-toggle-heading svg {
37
+ width: 14px;
38
+ color: rgba(124, 139, 154, 0.5);
39
+ transition: transform 0.3s;
40
+ transform: rotate(-180deg);
41
+ }
42
+
43
+ .kg-toggle-heading-text {
44
+ margin-top: 0;
45
+ margin-bottom: 0;
46
+ }
47
+
48
+ .kg-toggle-content {
49
+ transition: all .3s;
50
+ padding-top: 1.5rem;
51
+ max-height: 100vh;
52
+ overflow: hidden;
53
+ opacity: 1;
54
+ }
55
+
56
+ .kg-toggle-content > *+* {
57
+
58
+ }
@@ -0,0 +1,16 @@
1
+ const toggleHeadingElements = document.getElementsByClassName("kg-toggle-heading");
2
+
3
+ const toggleFn = function(event) {
4
+ const targetElement = event.target;
5
+ const parentElement = targetElement.closest('.kg-toggle-card');
6
+ var toggleState = parentElement.getAttribute("data-kg-toggle-state");
7
+ if (toggleState === 'close') {
8
+ parentElement.setAttribute('data-kg-toggle-state', 'open');
9
+ } else {
10
+ parentElement.setAttribute('data-kg-toggle-state', 'close');
11
+ }
12
+ };
13
+
14
+ for (let i = 0; i < toggleHeadingElements.length; i++) {
15
+ toggleHeadingElements[i].addEventListener('click', toggleFn, false);
16
+ }
@@ -0,0 +1,93 @@
1
+ const hbs = require('express-hbs');
2
+ const _ = require('lodash');
3
+ const tpl = require('@tryghost/tpl');
4
+ const sentry = require('../../../shared/sentry');
5
+
6
+ const config = require('../../../shared/config');
7
+ const helpers = require('../../services/routing/helpers');
8
+
9
+ // @TODO: make this properly shared code
10
+ const shared = require('../../../server/web/shared/middleware/error-handler');
11
+
12
+ const messages = {
13
+ oopsErrorTemplateHasError: 'Oops, seems there is an error in the error template.',
14
+ encounteredError: 'Encountered the error: ',
15
+ whilstTryingToRender: 'whilst trying to render an error page for the error: '
16
+ };
17
+
18
+ const escapeExpression = hbs.Utils.escapeExpression;
19
+
20
+ /**
21
+ * This is a bare minimum setup, which allows us to render the error page
22
+ * It uses the {{asset}} helper, and nothing more
23
+ */
24
+ const createHbsEngine = () => {
25
+ const engine = hbs.create();
26
+ engine.registerHelper('asset', require('../../helpers/asset'));
27
+
28
+ return engine.express4();
29
+ };
30
+
31
+ const errorFallbackMessage = err => `<h1>${tpl(messages.oopsErrorTemplateHasError)}</h1>
32
+ <p>${tpl(messages.encounteredError)}</p>
33
+ <pre>${escapeExpression(err.message || err)}</pre>
34
+ <br ><p>${tpl(messages.whilstTryingToRender)}</p>
35
+ ${err.statusCode} <pre>${escapeExpression(err.message || err)}</pre>`;
36
+
37
+ const themeErrorRenderer = (err, req, res, next) => {
38
+ // If the error code is explicitly set to STATIC_FILE_NOT_FOUND,
39
+ // Skip trying to render an HTML error, and move on to the basic error renderer
40
+ // We do this because customised 404 templates could reference the image that's missing
41
+ // A better long term solution might be to do this based on extension
42
+ if (err.code === 'STATIC_FILE_NOT_FOUND') {
43
+ return next(err);
44
+ }
45
+
46
+ // Renderer begin
47
+ // Format Data
48
+ const data = {
49
+ message: err.message,
50
+ // @deprecated Remove in Ghost 5.0
51
+ code: err.statusCode,
52
+ statusCode: err.statusCode,
53
+ errorDetails: err.errorDetails || []
54
+ };
55
+
56
+ // Template
57
+ // @TODO: very dirty !!!!!!
58
+ helpers.templates.setTemplate(req, res);
59
+
60
+ // It can be that something went wrong with the theme or otherwise loading handlebars
61
+ // This ensures that no matter what res.render will work here
62
+ // @TODO: split the error handler for assets, admin & theme to refactor this away
63
+ if (_.isEmpty(req.app.engines)) {
64
+ res._template = 'error';
65
+ req.app.engine('hbs', createHbsEngine());
66
+ req.app.set('view engine', 'hbs');
67
+ req.app.set('views', config.get('paths').defaultViews);
68
+ }
69
+
70
+ // @TODO use renderer here?!
71
+ // Render Call - featuring an error handler for what happens if rendering fails
72
+ res.render(res._template, data, (_err, html) => {
73
+ if (!_err) {
74
+ return res.send(html);
75
+ }
76
+
77
+ // re-attach new error e.g. error template has syntax error or misusage
78
+ req.err = _err;
79
+
80
+ // And then try to explain things to the user...
81
+ // Cheat and output the error using handlebars escapeExpression
82
+ return res.status(500).send(errorFallbackMessage(_err));
83
+ });
84
+ };
85
+
86
+ module.exports.handleThemeResponse = [
87
+ // Make sure the error can be served
88
+ shared.prepareError,
89
+ // Handle the error in Sentry
90
+ sentry.errorHandler,
91
+ // Render the error using theme template
92
+ themeErrorRenderer
93
+ ];
@@ -1,6 +1,6 @@
1
1
  const _ = require('lodash');
2
2
  const path = require('path');
3
- const {GhostError} = require('@tryghost/errors');
3
+ const {NoContentError} = require('@tryghost/errors');
4
4
  const imageTransform = require('@tryghost/image-transform');
5
5
  const storage = require('../../../server/adapters/storage');
6
6
  const activeTheme = require('../../services/theme-engine/active');
@@ -102,10 +102,7 @@ module.exports = function (req, res, next) {
102
102
  })
103
103
  .then((originalImageBuffer) => {
104
104
  if (originalImageBuffer.length <= 0) {
105
- throw new GhostError({
106
- errorType: 'NoContentError',
107
- statusCode: 204
108
- });
105
+ throw new NoContentError();
109
106
  }
110
107
  return imageTransform.resizeFromBuffer(originalImageBuffer, imageDimensionConfig);
111
108
  })
@@ -115,7 +112,7 @@ module.exports = function (req, res, next) {
115
112
  }).then(() => {
116
113
  next();
117
114
  }).catch(function (err) {
118
- if (err.code === 'SHARP_INSTALLATION' || err.errorType === 'NoContentError') {
115
+ if (err.code === 'SHARP_INSTALLATION' || err.code === 'IMAGE_PROCESSING' || err.errorType === 'NoContentError') {
119
116
  return redirectToOriginal();
120
117
  }
121
118
  next(err);
@@ -1,4 +1,5 @@
1
1
  module.exports = {
2
+ errorHandler: require('./error-handler'),
2
3
  handleImageSizes: require('./handle-image-sizes'),
3
4
  redirectGhostToAdmin: require('./redirect-ghost-to-admin'),
4
5
  serveFavicon: require('./serve-favicon'),