ghost 4.22.2 → 4.24.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 (118) hide show
  1. package/.c8rc.json +24 -0
  2. package/Gruntfile.js +0 -1
  3. package/content/public/README.md +3 -0
  4. package/core/app.js +12 -1
  5. package/core/boot.js +45 -26
  6. package/core/bridge.js +10 -10
  7. package/core/built/assets/{chunk.3.324fd0cc598c73650219.js → chunk.3.8f95b516d88ff4eec64c.js} +18 -18
  8. package/core/built/assets/{ghost-dark-39fb496d051565531062d7e047d1c0b1.css → ghost-dark-e7b57ab951512c5719aee89b16b9a448.css} +1 -1
  9. package/core/built/assets/{ghost.min-4207edfc1ae0a3f9f6505ca00d20b0c0.css → ghost.min-7f3603dbeb5ebf0ec09e207ae82fb4e3.css} +1 -1
  10. package/core/built/assets/{ghost.min-7da921f6c6cac3fe10da1ba104575440.js → ghost.min-d5595f9c71ebc534ccf9ac78483d357c.js} +138 -105
  11. package/core/built/assets/icons/powered-by-tenor.svg +35 -0
  12. package/core/built/assets/icons/tenor.svg +7 -0
  13. package/core/built/assets/{vendor.min-413f887176a041e6dbf88214ca9a7481.js → vendor.min-1a84ac3ef74edf31c6e86810b45221cc.js} +2964 -2434
  14. package/core/frontend/apps/amp/lib/views/amp.hbs +104 -0
  15. package/core/frontend/apps/private-blogging/lib/router.js +1 -1
  16. package/core/frontend/services/card-assets/index.js +0 -12
  17. package/core/frontend/services/card-assets/service.js +35 -26
  18. package/core/frontend/services/routing/CollectionRouter.js +4 -5
  19. package/core/frontend/services/routing/EmailRouter.js +1 -1
  20. package/core/frontend/services/routing/ParentRouter.js +0 -8
  21. package/core/frontend/services/routing/PreviewRouter.js +1 -1
  22. package/core/frontend/services/routing/StaticPagesRouter.js +1 -1
  23. package/core/frontend/services/routing/StaticRoutesRouter.js +4 -4
  24. package/core/frontend/services/routing/TaxonomyRouter.js +3 -3
  25. package/core/frontend/services/routing/{middlewares → middleware}/index.js +0 -0
  26. package/core/frontend/services/routing/{middlewares → middleware}/page-param.js +0 -0
  27. package/core/frontend/services/routing/router-manager.js +7 -2
  28. package/core/frontend/services/rss/generate-feed.js +2 -1
  29. package/core/frontend/src/cards/css/bookmark.css +72 -47
  30. package/core/frontend/src/cards/css/callout.css +41 -4
  31. package/core/frontend/src/cards/css/gallery.css +15 -10
  32. package/core/frontend/src/cards/css/nft.css +20 -11
  33. package/core/frontend/src/cards/css/toggle.css +58 -0
  34. package/core/frontend/src/cards/js/toggle.js +16 -0
  35. package/core/frontend/web/middleware/serve-public-file.js +39 -16
  36. package/core/frontend/web/site.js +11 -14
  37. package/core/server/api/canary/authentication.js +1 -1
  38. package/core/server/api/canary/utils/serializers/output/config.js +1 -1
  39. package/core/server/api/v2/authentication.js +1 -1
  40. package/core/server/api/v3/authentication.js +1 -1
  41. package/core/server/data/db/connection.js +7 -0
  42. package/core/server/data/importer/importers/data/data-importer.js +3 -3
  43. package/core/server/data/migrations/init/2-create-fixtures.js +3 -20
  44. package/core/server/data/migrations/versions/1.21/1-add-contributor-role.js +5 -5
  45. package/core/server/data/migrations/versions/2.15/2-insert-zapier-integration.js +3 -3
  46. package/core/server/data/migrations/versions/2.2/3-insert-admin-integration-role.js +5 -5
  47. package/core/server/data/migrations/versions/2.27/1-insert-ghost-db-backup-role.js +5 -6
  48. package/core/server/data/migrations/versions/2.27/2-insert-db-backup-integration.js +3 -4
  49. package/core/server/data/migrations/versions/2.28/3-insert-ghost-scheduler-role.js +7 -7
  50. package/core/server/data/migrations/versions/2.28/4-insert-scheduler-integration.js +3 -3
  51. package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +58 -0
  52. package/core/server/data/schema/fixtures/fixture-manager.js +340 -0
  53. package/core/server/data/schema/fixtures/index.js +8 -2
  54. package/core/server/services/email-analytics/jobs/index.js +1 -1
  55. package/core/server/services/mega/post-email-serializer.js +5 -1
  56. package/core/server/services/mega/segment-parser.js +1 -2
  57. package/core/server/services/mega/template.js +52 -37
  58. package/core/server/services/nft-oembed.js +7 -21
  59. package/core/server/services/oembed.js +24 -24
  60. package/core/server/services/public-config/config.js +1 -1
  61. package/core/server/services/redirects/api.js +18 -23
  62. package/core/server/services/redirects/index.js +18 -10
  63. package/core/server/services/redirects/utils.js +14 -0
  64. package/core/server/services/redirects/validation.js +10 -0
  65. package/core/server/services/route-settings/index.js +40 -17
  66. package/core/server/services/route-settings/route-settings.js +127 -114
  67. package/core/server/services/route-settings/settings-loader.js +14 -32
  68. package/core/server/services/themes/activation-bridge.js +3 -3
  69. package/core/server/services/url/LocalFileCache.js +75 -0
  70. package/core/server/services/url/Resources.js +8 -2
  71. package/core/server/services/url/UrlGenerator.js +23 -20
  72. package/core/server/services/url/UrlService.js +75 -63
  73. package/core/server/services/url/index.js +17 -3
  74. package/core/server/web/admin/app.js +7 -10
  75. package/core/server/web/admin/controller.js +35 -12
  76. package/core/server/web/admin/middleware/redirect-admin-urls.js +15 -0
  77. package/core/server/web/admin/views/default-prod.html +4 -4
  78. package/core/server/web/admin/views/default.html +4 -4
  79. package/core/server/web/api/app.js +1 -1
  80. package/core/server/web/api/canary/admin/app.js +3 -6
  81. package/core/server/web/api/canary/admin/middleware.js +6 -6
  82. package/core/server/web/api/canary/admin/routes.js +5 -5
  83. package/core/server/web/api/canary/content/app.js +3 -6
  84. package/core/server/web/api/canary/content/middleware.js +3 -3
  85. package/core/server/web/api/v2/admin/app.js +3 -6
  86. package/core/server/web/api/v2/admin/middleware.js +6 -6
  87. package/core/server/web/api/v2/admin/routes.js +5 -5
  88. package/core/server/web/api/v2/content/app.js +3 -6
  89. package/core/server/web/api/v2/content/middleware.js +3 -3
  90. package/core/server/web/api/v3/admin/app.js +3 -6
  91. package/core/server/web/api/v3/admin/middleware.js +6 -6
  92. package/core/server/web/api/v3/admin/routes.js +5 -5
  93. package/core/server/web/api/v3/content/app.js +3 -6
  94. package/core/server/web/api/v3/content/middleware.js +3 -3
  95. package/core/server/web/members/app.js +6 -9
  96. package/core/server/web/oauth/app.js +0 -4
  97. package/core/server/web/parent/app.js +17 -9
  98. package/core/server/web/parent/frontend.js +1 -1
  99. package/core/server/web/shared/index.js +2 -2
  100. package/core/server/web/shared/{middlewares → middleware}/api/index.js +0 -0
  101. package/core/server/web/shared/{middlewares → middleware}/api/spam-prevention.js +0 -0
  102. package/core/server/web/shared/{middlewares → middleware}/brute.js +0 -0
  103. package/core/server/web/shared/{middlewares → middleware}/cache-control.js +0 -0
  104. package/core/server/web/shared/{middlewares → middleware}/error-handler.js +70 -53
  105. package/core/server/web/shared/{middlewares → middleware}/index.js +0 -4
  106. package/core/server/web/shared/{middlewares → middleware}/pretty-urls.js +0 -0
  107. package/core/server/web/shared/{middlewares → middleware}/uncapitalise.js +0 -0
  108. package/core/server/web/shared/{middlewares → middleware}/url-redirects.js +0 -0
  109. package/core/shared/config/defaults.json +7 -1
  110. package/core/shared/config/helpers.js +42 -0
  111. package/core/shared/config/loader.js +1 -1
  112. package/core/shared/labs.js +7 -2
  113. package/loggingrc.js +19 -20
  114. package/package.json +35 -34
  115. package/yarn.lock +822 -345
  116. package/core/server/data/schema/fixtures/utils.js +0 -321
  117. package/core/server/web/parent/vhost-utils.js +0 -39
  118. package/core/server/web/shared/middlewares/maintenance.js +0 -25
@@ -60,6 +60,32 @@ _private.createHbsEngine = () => {
60
60
  return engine.express4();
61
61
  };
62
62
 
63
+ _private.updateStack = (err) => {
64
+ let stackbits = err.stack.split(/\n/g);
65
+
66
+ // We build this up backwards, so we always insert at position 1
67
+
68
+ if (process.env.NODE_ENV === 'production' || err.statusCode === 404) {
69
+ // In production mode, remove the stack trace
70
+ stackbits.splice(1, stackbits.length - 1);
71
+ } else {
72
+ // In dev mode, clearly mark the strack trace
73
+ stackbits.splice(1, 0, `Stack Trace:`);
74
+ }
75
+
76
+ // Add in our custom cotext and help methods
77
+
78
+ if (err.help) {
79
+ stackbits.splice(1, 0, `${err.help}`);
80
+ }
81
+
82
+ if (err.context) {
83
+ stackbits.splice(1, 0, `${err.context}`);
84
+ }
85
+
86
+ return stackbits.join('\n');
87
+ };
88
+
63
89
  /**
64
90
  * Get an error ready to be shown the the user
65
91
  *
@@ -79,14 +105,6 @@ _private.prepareError = (err, req, res, next) => {
79
105
  err = new errors.NotFoundError({
80
106
  err: err
81
107
  });
82
- } else if (err.stack.match(/node_modules\/handlebars\//)) {
83
- // Temporary handling of theme errors from handlebars
84
- // @TODO remove this when #10496 is solved properly
85
- err = new errors.IncorrectUsageError({
86
- err: err,
87
- message: err.message,
88
- statusCode: err.statusCode
89
- });
90
108
  } else {
91
109
  err = new errors.GhostError({
92
110
  err: err,
@@ -102,6 +120,8 @@ _private.prepareError = (err, req, res, next) => {
102
120
  // alternative for res.status();
103
121
  res.statusCode = err.statusCode;
104
122
 
123
+ err.stack = _private.updateStack(err);
124
+
105
125
  // never cache errors
106
126
  res.set({
107
127
  'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
@@ -123,6 +143,23 @@ _private.JSONErrorRenderer = (err, req, res, next) => { // eslint-disable-line n
123
143
  });
124
144
  };
125
145
 
146
+ _private.JSONErrorRendererV2 = (err, req, res, next) => { // eslint-disable-line no-unused-vars
147
+ const userError = _private.prepareUserMessage(err, req);
148
+
149
+ res.json({
150
+ errors: [{
151
+ message: userError.message || null,
152
+ context: userError.context || null,
153
+ type: err.errorType || null,
154
+ details: err.errorDetails || null,
155
+ property: err.property || null,
156
+ help: err.help || null,
157
+ code: err.code || null,
158
+ id: err.id || null
159
+ }]
160
+ });
161
+ };
162
+
126
163
  _private.prepareUserMessage = (err, res) => {
127
164
  const userError = {
128
165
  message: err.message,
@@ -169,23 +206,6 @@ _private.prepareUserMessage = (err, res) => {
169
206
  return userError;
170
207
  };
171
208
 
172
- _private.JSONErrorRendererV2 = (err, req, res, next) => { // eslint-disable-line no-unused-vars
173
- const userError = _private.prepareUserMessage(err, req);
174
-
175
- res.json({
176
- errors: [{
177
- message: userError.message || null,
178
- context: userError.context || null,
179
- type: err.errorType || null,
180
- details: err.errorDetails || null,
181
- property: err.property || null,
182
- help: err.help || null,
183
- code: err.code || null,
184
- id: err.id || null
185
- }]
186
- });
187
- };
188
-
189
209
  _private.ErrorFallbackMessage = err => `<h1>${tpl(messages.oopsErrorTemplateHasError)}</h1>
190
210
  <p>${tpl(messages.encounteredError)}</p>
191
211
  <pre>${escapeExpression(err.message || err)}</pre>
@@ -241,39 +261,36 @@ _private.ThemeErrorRenderer = (err, req, res, next) => {
241
261
  });
242
262
  };
243
263
 
244
- _private.HTMLErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
245
- const data = {
246
- message: err.message,
247
- statusCode: err.statusCode,
248
- errorDetails: err.errorDetails || []
249
- };
250
-
251
- // e.g. if you serve the admin /ghost and Ghost returns a 503 because it generates the urls at the moment.
252
- // This ensures that no matter what res.render will work here
253
- // @TODO: put to prepare error function?
254
- if (_.isEmpty(req.app.engines)) {
255
- res._template = 'error';
256
- req.app.engine('hbs', _private.createHbsEngine());
257
- req.app.set('view engine', 'hbs');
258
- req.app.set('views', config.get('paths').defaultViews);
259
- }
260
-
261
- res.render('error', data, (_err, html) => {
262
- if (!_err) {
263
- return res.send(html);
264
- }
264
+ /**
265
+ * Borrowed heavily from finalHandler
266
+ */
265
267
 
266
- // re-attach new error e.g. error template has syntax error or misusage
267
- req.err = _err;
268
+ const DOUBLE_SPACE_REGEXP = /\x20{2}/g;
269
+ const NEWLINE_REGEXP = /\n/g;
270
+
271
+ function createHtmlDocument(status, message) {
272
+ let body = escapeExpression(message)
273
+ .replace(NEWLINE_REGEXP, '<br>')
274
+ .replace(DOUBLE_SPACE_REGEXP, ' &nbsp;');
275
+
276
+ return `<!DOCTYPE html>\n
277
+ <html lang="en">\n
278
+ <head>\n
279
+ <meta charset="utf-8">\n
280
+ <title>${status} Error</title>\n
281
+ </head>\n
282
+ <body>\n
283
+ <pre>${status} ${body}</pre>\n
284
+ </body>\n
285
+ </html>\n`;
286
+ }
268
287
 
269
- // And then try to explain things to the user...
270
- // Cheat and output the error using handlebars escapeExpression
271
- return res.status(500).send(_private.ErrorFallbackMessage(_err));
272
- });
288
+ _private.HTMLErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
289
+ return res.send(createHtmlDocument(res.statusCode, err.stack));
273
290
  };
274
291
 
275
292
  _private.BasicErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
276
- return res.send(res.statusCode + ' ' + err.message);
293
+ return res.send(res.statusCode + ' ' + err.stack);
277
294
  };
278
295
 
279
296
  errorHandler.resourceNotFound = (req, res, next) => {
@@ -15,10 +15,6 @@ module.exports = {
15
15
  return require('./error-handler');
16
16
  },
17
17
 
18
- get maintenance() {
19
- return require('./maintenance');
20
- },
21
-
22
18
  get prettyUrls() {
23
19
  return require('./pretty-urls');
24
20
  },
@@ -15,7 +15,9 @@
15
15
  "privacy": false,
16
16
  "useMinFiles": true,
17
17
  "paths": {
18
- "contentPath": "content/"
18
+ "contentPath": "content/",
19
+ "fixtures": "core/server/data/schema/fixtures/fixtures",
20
+ "assetSrc": "core/frontend/src"
19
21
  },
20
22
  "adapters": {
21
23
  "sso": {
@@ -127,5 +129,9 @@
127
129
  "portal": {
128
130
  "url": "https://unpkg.com/@tryghost/portal@~1.12.0/umd/portal.min.js",
129
131
  "version": "1.12"
132
+ },
133
+ "tenor": {
134
+ "apiKey": null,
135
+ "contentFilter": "off"
130
136
  }
131
137
  }
@@ -1,4 +1,42 @@
1
1
  const path = require('path');
2
+ const escapeRegExp = require('lodash/escapeRegExp');
3
+ const {URL} = require('url');
4
+
5
+ const DEFAULT_HOST_ARG = /.*/;
6
+
7
+ const getHostInfo = (config) => {
8
+ const frontendHost = new URL(config.getSiteUrl()).hostname;
9
+
10
+ const backendHost = config.getAdminUrl() ? (new URL(config.getAdminUrl()).hostname) : '';
11
+ const hasSeparateBackendHost = backendHost && backendHost !== frontendHost;
12
+
13
+ return {
14
+ backendHost,
15
+ hasSeparateBackendHost
16
+ };
17
+ };
18
+
19
+ /**
20
+ *
21
+ * @returns {string|RegExp}
22
+ */
23
+ const getBackendMountPath = function getFrontendMountPath() {
24
+ const {backendHost, hasSeparateBackendHost} = getHostInfo(this);
25
+
26
+ // with a separate admin url only serve on that host, otherwise serve on all hosts
27
+ return (hasSeparateBackendHost) && backendHost ? backendHost : DEFAULT_HOST_ARG;
28
+ };
29
+
30
+ /**
31
+ *
32
+ * @returns {string|RegExp}
33
+ */
34
+ const getFrontendMountPath = function getFrontendMountPath() {
35
+ const {backendHost, hasSeparateBackendHost} = getHostInfo(this);
36
+
37
+ // with a separate admin url we adjust the frontend vhost to exclude requests to that host, otherwise serve on all hosts
38
+ return (hasSeparateBackendHost && backendHost) ? new RegExp(`^(?!${escapeRegExp(backendHost)}).*`) : DEFAULT_HOST_ARG;
39
+ };
2
40
 
3
41
  /**
4
42
  * @callback isPrivacyDisabledFn
@@ -46,6 +84,8 @@ const getContentPath = function getContentPath(type) {
46
84
  return path.join(this.get('paths:contentPath'), 'data/');
47
85
  case 'settings':
48
86
  return path.join(this.get('paths:contentPath'), 'settings/');
87
+ case 'public':
88
+ return path.join(this.get('paths:contentPath'), 'public/');
49
89
  default:
50
90
  // new Error is allowed here, as we do not want config to depend on @tryghost/error
51
91
  // @TODO: revisit this decision when @tryghost/error is no longer dependent on all of ghost-ignition
@@ -62,4 +102,6 @@ const getContentPath = function getContentPath(type) {
62
102
  module.exports.bindAll = (nconf) => {
63
103
  nconf.isPrivacyDisabled = isPrivacyDisabled.bind(nconf);
64
104
  nconf.getContentPath = getContentPath.bind(nconf);
105
+ nconf.getBackendMountPath = getBackendMountPath.bind(nconf);
106
+ nconf.getFrontendMountPath = getFrontendMountPath.bind(nconf);
65
107
  };
@@ -41,8 +41,8 @@ function loadNconf(options) {
41
41
  // ## Config Methods
42
42
 
43
43
  // Expose dynamic utility methods
44
- helpers.bindAll(nconf);
45
44
  urlHelpers.bindAll(nconf);
45
+ helpers.bindAll(nconf);
46
46
 
47
47
  // ## Sanitization
48
48
 
@@ -37,7 +37,12 @@ const ALPHA_FEATURES = [
37
37
  'calloutCard',
38
38
  'nftCard',
39
39
  'accordionCard',
40
- 'gifsCard'
40
+ 'gifsCard',
41
+ 'fileCard',
42
+ 'audioCard',
43
+ 'videoCard',
44
+ 'productCard',
45
+ 'quoteStyles'
41
46
  ];
42
47
 
43
48
  module.exports.GA_KEYS = [...GA_FEATURES];
@@ -47,7 +52,7 @@ module.exports.getAll = () => {
47
52
  const labs = _.cloneDeep(settingsCache.get('labs')) || {};
48
53
 
49
54
  ALPHA_FEATURES.forEach((alphaKey) => {
50
- if (labs[alphaKey] && !(config.get('enableDeveloperExperiments') || process.env.NODE_ENV.match(/^testing/))) {
55
+ if (labs[alphaKey] && !(config.get('enableDeveloperExperiments') || process.env.NODE_ENV.startsWith('test'))) {
51
56
  delete labs[alphaKey];
52
57
  }
53
58
  });
package/loggingrc.js CHANGED
@@ -1,25 +1,24 @@
1
1
  const config = require('./core/shared/config');
2
2
  const ghostVersion = require('@tryghost/version');
3
3
 
4
- module.exports = {
5
- name: config.get('logging:name'),
6
- env: config.get('env'),
7
- path: config.get('logging:path') || config.getContentPath('logs'),
4
+ // Config for logging
5
+ const loggingConfig = config.get('logging') || {};
6
+
7
+ if (!loggingConfig.path) {
8
+ loggingConfig.path = config.getContentPath('logs');
9
+ }
10
+
11
+ // Additional values used by logging
12
+ loggingConfig.env = config.get('env');
13
+ loggingConfig.domain = config.get('url');
14
+
15
+ // Config for metrics
16
+ loggingConfig.metrics = config.get('logging:metrics') || {};
17
+ loggingConfig.metrics.metadata = {
18
+ // Undefined if unavailable
19
+ siteId: config.get('hostSettings:siteId'),
8
20
  domain: config.get('url'),
9
- mode: config.get('logging:mode'),
10
- level: config.get('logging:level'),
11
- transports: config.get('logging:transports'),
12
- metrics: {
13
- transports: config.get('logging:metrics:transports'),
14
- metadata: {
15
- // Undefined if unavailable
16
- siteId: config.get('hostSettings:siteId'),
17
- domain: config.get('url'),
18
- version: ghostVersion.safe
19
- }
20
- },
21
- gelf: config.get('logging:gelf'),
22
- loggly: config.get('logging:loggly'),
23
- elasticsearch: config.get('logging:elasticsearch'),
24
- rotation: config.get('logging:rotation')
21
+ version: ghostVersion.safe
25
22
  };
23
+
24
+ module.exports = loggingConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ghost",
3
- "version": "4.22.2",
3
+ "version": "4.24.0",
4
4
  "description": "The professional publishing platform",
5
5
  "author": "Ghost Foundation",
6
6
  "homepage": "https://ghost.org",
@@ -29,7 +29,7 @@
29
29
  "test": "mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js --timeout=60000",
30
30
  "test:all": "yarn test:unit && yarn test:integration && yarn test:e2e && yarn lint",
31
31
  "test:debug": "DEBUG=ghost:test* yarn test",
32
- "test:unit": "c8 --all -n 'core/{*.js,frontend,server,shared}' --reporter text-summary --reporter cobertura mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js './test/unit' --timeout=2000",
32
+ "test:unit": "c8 --reporter text-summary --reporter cobertura mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js './test/unit' --timeout=2000",
33
33
  "test:integration": "mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js './test/integration' --timeout=5000",
34
34
  "test:e2e": "mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js './test/e2e-api' './test/e2e-frontend' './test/e2e-server' --timeout=10000",
35
35
  "test:regression": "mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js './test/regression' --timeout=60000",
@@ -37,7 +37,7 @@
37
37
  "test:int:slow": "yarn test:integration --reporter=mocha-slow-test-reporter",
38
38
  "test:e2e:slow": "yarn test:e2e --reporter=mocha-slow-test-reporter",
39
39
  "test:reg:slow": "mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js './test/regression' --timeout=60000 --reporter=mocha-slow-test-reporter",
40
- "cov:unit": "c8 report --all -n 'core/{*.js,frontend,server,shared}' -x 'core/frontend/public' --reporter text --reporter html",
40
+ "cov:unit": "c8 report --reporter text --reporter html",
41
41
  "lint:server": "eslint --ignore-path .eslintignore 'core/server/**/*.js' 'core/*.js' '*.js'",
42
42
  "lint:shared": "eslint --ignore-path .eslintignore 'core/shared/**/*.js'",
43
43
  "lint:frontend": "eslint --ignore-path .eslintignore 'core/frontend/**/*.js'",
@@ -54,12 +54,12 @@
54
54
  },
55
55
  "dependencies": {
56
56
  "@nexes/nql": "0.6.0",
57
- "@sentry/node": "6.14.3",
57
+ "@sentry/node": "6.15.0",
58
58
  "@tryghost/adapter-manager": "0.2.18",
59
59
  "@tryghost/admin-api-schema": "2.6.1",
60
60
  "@tryghost/bookshelf-plugins": "0.3.4",
61
61
  "@tryghost/bootstrap-socket": "0.2.13",
62
- "@tryghost/color-utils": "0.1.4",
62
+ "@tryghost/color-utils": "0.1.5",
63
63
  "@tryghost/config-url-helpers": "0.1.3",
64
64
  "@tryghost/constants": "1.0.0",
65
65
  "@tryghost/custom-theme-settings-service": "0.3.1",
@@ -68,43 +68,44 @@
68
68
  "@tryghost/email-analytics-service": "1.0.4",
69
69
  "@tryghost/errors": "0.2.17",
70
70
  "@tryghost/express-dynamic-redirects": "0.2.1",
71
- "@tryghost/helpers": "1.1.53",
71
+ "@tryghost/helpers": "1.1.54",
72
72
  "@tryghost/image-transform": "1.0.18",
73
- "@tryghost/job-manager": "0.8.12",
73
+ "@tryghost/job-manager": "0.8.13",
74
74
  "@tryghost/kg-card-factory": "3.1.0",
75
75
  "@tryghost/kg-default-atoms": "3.1.0",
76
- "@tryghost/kg-default-cards": "5.5.1",
76
+ "@tryghost/kg-default-cards": "5.8.5",
77
77
  "@tryghost/kg-markdown-html-renderer": "5.1.0",
78
78
  "@tryghost/kg-mobiledoc-html-renderer": "5.2.0",
79
79
  "@tryghost/limit-service": "1.0.0",
80
- "@tryghost/logging": "1.0.0",
80
+ "@tryghost/logging": "1.0.1",
81
81
  "@tryghost/magic-link": "1.0.14",
82
- "@tryghost/members-api": "2.7.4",
82
+ "@tryghost/members-api": "2.7.5",
83
83
  "@tryghost/members-csv": "1.1.8",
84
84
  "@tryghost/members-importer": "0.3.4",
85
- "@tryghost/members-offers": "0.10.2",
85
+ "@tryghost/members-offers": "0.10.3",
86
86
  "@tryghost/members-ssr": "1.0.15",
87
- "@tryghost/metrics": "1.0.0",
88
- "@tryghost/minifier": "0.1.0",
87
+ "@tryghost/metrics": "1.0.1",
88
+ "@tryghost/minifier": "0.1.1",
89
89
  "@tryghost/mw-session-from-token": "0.1.26",
90
- "@tryghost/nodemailer": "0.3.6",
90
+ "@tryghost/nodemailer": "0.3.7",
91
91
  "@tryghost/package-json": "1.0.6",
92
92
  "@tryghost/promise": "0.1.13",
93
- "@tryghost/request": "0.1.8",
93
+ "@tryghost/request": "0.1.9",
94
94
  "@tryghost/root-utils": "0.3.7",
95
95
  "@tryghost/security": "0.2.13",
96
96
  "@tryghost/session-service": "0.1.28",
97
+ "@tryghost/settings-path-manager": "0.1.2",
97
98
  "@tryghost/social-urls": "0.1.27",
98
99
  "@tryghost/string": "0.1.21",
99
100
  "@tryghost/tpl": "0.1.8",
100
101
  "@tryghost/update-check-service": "0.2.5",
101
- "@tryghost/url-utils": "2.0.3",
102
+ "@tryghost/url-utils": "2.0.4",
102
103
  "@tryghost/validator": "0.1.8",
103
104
  "@tryghost/version": "0.1.7",
104
105
  "@tryghost/vhost-middleware": "1.0.19",
105
106
  "@tryghost/zip": "1.1.18",
106
107
  "amperize": "0.6.1",
107
- "analytics-node": "5.1.2",
108
+ "analytics-node": "6.0.0",
108
109
  "bluebird": "3.7.2",
109
110
  "body-parser": "1.19.0",
110
111
  "bookshelf": "1.2.0",
@@ -129,7 +130,7 @@
129
130
  "ghost-storage-base": "1.0.0",
130
131
  "glob": "7.2.0",
131
132
  "got": "9.6.0",
132
- "gscan": "4.10.1",
133
+ "gscan": "4.13.2",
133
134
  "html-to-text": "5.1.1",
134
135
  "image-size": "1.0.0",
135
136
  "intl": "1.2.5",
@@ -140,32 +141,32 @@
140
141
  "juice": "8.0.0",
141
142
  "keypair": "1.0.4",
142
143
  "knex": "0.21.21",
143
- "knex-migrator": "4.1.1",
144
+ "knex-migrator": "4.1.3",
144
145
  "lodash": "4.17.21",
145
146
  "luxon": "2.1.1",
146
147
  "mailgun-js": "0.22.0",
147
- "metascraper": "5.25.0",
148
- "metascraper-author": "5.25.0",
149
- "metascraper-description": "5.25.0",
150
- "metascraper-image": "5.25.0",
151
- "metascraper-logo": "5.25.0",
152
- "metascraper-logo-favicon": "5.25.0",
153
- "metascraper-publisher": "5.25.0",
154
- "metascraper-title": "5.25.0",
155
- "metascraper-url": "5.25.0",
148
+ "metascraper": "5.25.2",
149
+ "metascraper-author": "5.25.2",
150
+ "metascraper-description": "5.25.2",
151
+ "metascraper-image": "5.25.2",
152
+ "metascraper-logo": "5.25.2",
153
+ "metascraper-logo-favicon": "5.25.2",
154
+ "metascraper-publisher": "5.25.2",
155
+ "metascraper-title": "5.25.2",
156
+ "metascraper-url": "5.25.2",
156
157
  "moment": "2.24.0",
157
158
  "moment-timezone": "0.5.23",
158
159
  "multer": "1.4.3",
159
160
  "mysql": "2.18.1",
160
161
  "nconf": "0.11.3",
161
162
  "node-jose": "2.0.0",
162
- "oembed-parser": "1.5.2",
163
+ "oembed-parser": "1.4.9",
163
164
  "passport": "0.5.0",
164
165
  "passport-google-oauth": "2.0.0",
165
166
  "path-match": "1.2.4",
166
167
  "probe-image-size": "5.0.0",
167
168
  "rss": "1.2.2",
168
- "sanitize-html": "2.5.3",
169
+ "sanitize-html": "2.6.0",
169
170
  "semver": "7.3.5",
170
171
  "stoppable": "1.1.0",
171
172
  "tough-cookie": "4.0.0",
@@ -173,16 +174,16 @@
173
174
  "xml": "1.0.1"
174
175
  },
175
176
  "optionalDependencies": {
176
- "@tryghost/html-to-mobiledoc": "1.2.2",
177
+ "@tryghost/html-to-mobiledoc": "1.3.4",
177
178
  "sqlite3": "5.0.2"
178
179
  },
179
180
  "devDependencies": {
180
181
  "@lodder/grunt-postcss": "3.1.1",
181
182
  "c8": "7.10.0",
182
183
  "coffeescript": "2.6.1",
183
- "cssnano": "5.0.10",
184
+ "cssnano": "5.0.11",
184
185
  "eslint": "7.32.0",
185
- "eslint-plugin-ghost": "2.7.0",
186
+ "eslint-plugin-ghost": "2.8.0",
186
187
  "grunt": "1.4.1",
187
188
  "grunt-bg-shell": "2.3.3",
188
189
  "grunt-contrib-clean": "2.0.0",
@@ -200,7 +201,7 @@
200
201
  "mock-knex": "0.4.10",
201
202
  "nock": "13.2.1",
202
203
  "papaparse": "5.3.1",
203
- "postcss": "8.3.11",
204
+ "postcss": "8.4.1",
204
205
  "rewire": "5.0.0",
205
206
  "should": "13.2.3",
206
207
  "sinon": "11.1.2",