ghost 4.15.0 → 4.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/.eslintrc.js +7 -1
  2. package/content/themes/casper/assets/built/screen.css +1 -1
  3. package/content/themes/casper/assets/built/screen.css.map +1 -1
  4. package/content/themes/casper/assets/css/screen.css +1 -1
  5. package/content/themes/casper/default.hbs +2 -2
  6. package/content/themes/casper/package.json +1 -1
  7. package/content/themes/casper/page.hbs +28 -26
  8. package/content/themes/casper/partials/post-card.hbs +2 -2
  9. package/content/themes/casper/post.hbs +67 -65
  10. package/content/themes/casper/tag.hbs +2 -2
  11. package/core/boot.js +7 -7
  12. package/core/bridge.js +4 -3
  13. package/core/built/assets/{chunk.3.4b1d9e20e57164ac9c29.js → chunk.3.b80d3e1e6b8556aaff3c.js} +72 -71
  14. package/core/built/assets/ghost-dark-f7bf2dd8d8c702716f75bfa4ccd92df2.css +1 -0
  15. package/core/built/assets/{ghost.min-e35cfee26d942c364166f57f3dcc9e75.js → ghost.min-52a5420ffcea6bf17761b5c59cf020e2.js} +979 -908
  16. package/core/built/assets/ghost.min-741246f42f000c073999a5363434ea2c.css +1 -0
  17. package/core/built/assets/icons/discount-bubble.svg +1 -0
  18. package/core/built/assets/{vendor.min-ca33abc718f21a51327841d58f8875d0.js → vendor.min-1bfc9d56d27508db88ef417deb55f16f.js} +454 -434
  19. package/core/frontend/apps/amp/lib/helpers/amp_analytics.js +2 -2
  20. package/core/frontend/apps/amp/lib/helpers/amp_components.js +2 -1
  21. package/core/frontend/apps/amp/lib/helpers/amp_content.js +5 -1
  22. package/core/frontend/apps/amp/lib/helpers/amp_style.js +1 -1
  23. package/core/frontend/apps/amp/lib/router.js +8 -4
  24. package/core/frontend/apps/private-blogging/index.js +13 -5
  25. package/core/frontend/apps/private-blogging/lib/helpers/input_password.js +1 -1
  26. package/core/frontend/apps/private-blogging/lib/middleware.js +8 -3
  27. package/core/frontend/helpers/asset.js +10 -2
  28. package/core/frontend/helpers/author.js +5 -3
  29. package/core/frontend/helpers/authors.js +4 -3
  30. package/core/frontend/helpers/body_class.js +1 -1
  31. package/core/frontend/helpers/cancel_link.js +9 -2
  32. package/core/frontend/helpers/concat.js +1 -1
  33. package/core/frontend/helpers/content.js +1 -1
  34. package/core/frontend/helpers/date.js +1 -1
  35. package/core/frontend/helpers/encode.js +1 -1
  36. package/core/frontend/helpers/excerpt.js +2 -1
  37. package/core/frontend/helpers/facebook_url.js +2 -1
  38. package/core/frontend/helpers/foreach.js +11 -2
  39. package/core/frontend/helpers/get.js +14 -3
  40. package/core/frontend/helpers/ghost_foot.js +2 -1
  41. package/core/frontend/helpers/ghost_head.js +10 -1
  42. package/core/frontend/helpers/has.js +8 -3
  43. package/core/frontend/helpers/img_url.js +9 -3
  44. package/core/frontend/helpers/is.js +7 -2
  45. package/core/frontend/helpers/lang.js +1 -1
  46. package/core/frontend/helpers/link.js +11 -2
  47. package/core/frontend/helpers/link_class.js +11 -2
  48. package/core/frontend/helpers/match.js +12 -3
  49. package/core/frontend/helpers/navigation.js +13 -4
  50. package/core/frontend/helpers/pagination.js +15 -5
  51. package/core/frontend/helpers/plural.js +8 -2
  52. package/core/frontend/helpers/post_class.js +1 -1
  53. package/core/frontend/helpers/prev_post.js +9 -2
  54. package/core/frontend/helpers/price.js +11 -6
  55. package/core/frontend/helpers/products.js +2 -1
  56. package/core/frontend/helpers/reading_time.js +4 -2
  57. package/core/frontend/helpers/t.js +1 -1
  58. package/core/frontend/helpers/tags.js +3 -1
  59. package/core/frontend/helpers/title.js +1 -1
  60. package/core/frontend/helpers/twitter_url.js +2 -1
  61. package/core/frontend/helpers/url.js +3 -1
  62. package/core/frontend/services/proxy.js +34 -57
  63. package/core/frontend/services/rendering.js +24 -0
  64. package/core/frontend/services/routing/controllers/channel.js +6 -2
  65. package/core/frontend/services/routing/controllers/collection.js +6 -2
  66. package/core/frontend/services/routing/middlewares/page-param.js +6 -2
  67. package/core/frontend/services/theme-engine/middleware.js +23 -6
  68. package/core/frontend/services/theme-engine/preview.js +31 -8
  69. package/core/server/adapters/scheduling/post-scheduling/scheduler-intergation.js +6 -4
  70. package/core/server/adapters/storage/LocalFileStorage.js +10 -4
  71. package/core/server/api/canary/custom-theme-settings.js +22 -0
  72. package/core/server/api/canary/index.js +4 -0
  73. package/core/server/api/canary/members.js +1 -1
  74. package/core/server/api/canary/redirects.js +5 -5
  75. package/core/server/api/canary/settings.js +16 -148
  76. package/core/server/api/canary/utils/serializers/output/custom-theme-settings.js +13 -0
  77. package/core/server/api/canary/utils/serializers/output/index.js +4 -0
  78. package/core/server/api/canary/utils/validators/input/settings.js +23 -1
  79. package/core/server/api/v2/redirects.js +3 -3
  80. package/core/server/api/v2/settings.js +3 -4
  81. package/core/server/api/v3/redirects.js +5 -5
  82. package/core/server/api/v3/settings.js +16 -136
  83. package/core/server/api/v3/utils/validators/input/settings.js +23 -1
  84. package/core/server/data/db/state-manager.js +1 -1
  85. package/core/server/data/exporter/table-lists.js +3 -1
  86. package/core/server/data/importer/import-manager.js +398 -0
  87. package/core/server/data/importer/importers/data/data-importer.js +162 -0
  88. package/core/server/data/importer/importers/data/index.js +1 -162
  89. package/core/server/data/importer/index.js +1 -379
  90. package/core/server/data/migrations/versions/4.16/01-add-custom-theme-settings-table.js +9 -0
  91. package/core/server/data/migrations/versions/4.17/01-add-custom-theme-settings-permissions.js +21 -0
  92. package/core/server/data/migrations/versions/4.17/02-add-offers-table.js +19 -0
  93. package/core/server/data/migrations/versions/4.17/03-add-offers-permissions.js +35 -0
  94. package/core/server/data/schema/fixtures/fixtures.json +32 -0
  95. package/core/server/data/schema/schema.js +33 -0
  96. package/core/server/models/custom-theme-setting.js +9 -0
  97. package/core/server/models/index.js +2 -0
  98. package/core/server/services/custom-theme-settings.js +8 -0
  99. package/core/server/services/members/api.js +4 -1
  100. package/core/server/services/redirects/index.js +15 -0
  101. package/core/{frontend → server}/services/redirects/settings.js +13 -6
  102. package/core/server/services/redirects/validation.js +44 -0
  103. package/core/{frontend/services/settings → server/services/route-settings}/default-routes.yaml +0 -0
  104. package/core/server/services/route-settings/default-settings-manager.js +62 -0
  105. package/core/server/services/route-settings/index.js +32 -1
  106. package/core/server/services/route-settings/route-settings.js +38 -12
  107. package/core/server/services/route-settings/settings-loader.js +102 -0
  108. package/core/{frontend/services/settings → server/services/route-settings}/validate.js +38 -28
  109. package/core/server/services/route-settings/yaml-parser.js +53 -0
  110. package/core/server/services/settings/index.js +13 -16
  111. package/core/server/services/settings/settings-bread-service.js +188 -0
  112. package/core/server/services/settings/settings-utils.js +32 -0
  113. package/core/server/services/themes/ThemeStorage.js +5 -4
  114. package/core/server/services/themes/activation-bridge.js +14 -0
  115. package/core/server/services/themes/validate.js +5 -2
  116. package/core/server/web/admin/views/default-prod.html +4 -4
  117. package/core/server/web/admin/views/default.html +4 -4
  118. package/core/server/web/api/canary/admin/routes.js +5 -1
  119. package/core/server/web/members/app.js +3 -0
  120. package/core/server/web/oauth/app.js +7 -8
  121. package/core/server/web/shared/middlewares/custom-redirects.js +82 -59
  122. package/core/server/web/site/routes.js +2 -2
  123. package/core/shared/config/defaults.json +2 -2
  124. package/core/shared/config/overrides.json +1 -1
  125. package/core/shared/custom-theme-settings-cache.js +3 -0
  126. package/core/shared/i18n/translations/en.json +2 -13
  127. package/core/shared/labs.js +2 -2
  128. package/package.json +42 -41
  129. package/yarn.lock +916 -901
  130. package/core/built/assets/ghost-dark-faf931d90e92535e6c03ca16793cbe7b.css +0 -1
  131. package/core/built/assets/ghost.min-7aa074ad556a8455155ac88ceaca03ab.css +0 -1
  132. package/core/frontend/services/redirects/index.js +0 -9
  133. package/core/frontend/services/redirects/validation.js +0 -28
  134. package/core/frontend/services/settings/ensure-settings.js +0 -47
  135. package/core/frontend/services/settings/index.js +0 -104
  136. package/core/frontend/services/settings/loader.js +0 -89
  137. package/core/frontend/services/settings/yaml-parser.js +0 -31
@@ -1,9 +0,0 @@
1
- module.exports = {
2
- get settings() {
3
- return require('./settings');
4
- },
5
-
6
- get validation() {
7
- return require('./validation');
8
- }
9
- };
@@ -1,28 +0,0 @@
1
- const _ = require('lodash');
2
- const i18n = require('../../../shared/i18n');
3
- const errors = require('@tryghost/errors');
4
-
5
- /**
6
- * Redirects are file based at the moment, but they will live in the database in the future.
7
- * See V2 of https://github.com/TryGhost/Ghost/issues/7707.
8
- */
9
- const validate = (redirects) => {
10
- if (!_.isArray(redirects)) {
11
- throw new errors.ValidationError({
12
- message: i18n.t('errors.utils.redirectsWrongFormat'),
13
- help: 'https://ghost.org/docs/themes/routing/#redirects'
14
- });
15
- }
16
-
17
- _.each(redirects, function (redirect) {
18
- if (!redirect.from || !redirect.to) {
19
- throw new errors.ValidationError({
20
- message: i18n.t('errors.utils.redirectsWrongFormat'),
21
- context: redirect,
22
- help: 'https://ghost.org/docs/themes/routing/#redirects'
23
- });
24
- }
25
- });
26
- };
27
-
28
- module.exports.validate = validate;
@@ -1,47 +0,0 @@
1
- const fs = require('fs-extra');
2
- const Promise = require('bluebird');
3
- const path = require('path');
4
- const debug = require('@tryghost/debug')('frontend:services:settings:ensure-settings');
5
- const {i18n} = require('../proxy');
6
- const errors = require('@tryghost/errors');
7
- const config = require('../../../shared/config');
8
-
9
- /**
10
- * Makes sure that all supported settings files are in the
11
- * `/content/settings` directory. If not, copy the default files
12
- * over.
13
- * @param {Array} knownSettings
14
- * @returns {Promise}
15
- * @description Reads the `/settings` folder of the content path and makes
16
- * sure that the associated yaml file for each setting exists. If it doesn't
17
- * copy the default yaml file over.
18
- */
19
- module.exports = function ensureSettingsFiles(knownSettings) {
20
- const contentPath = config.getContentPath('settings');
21
- const defaultSettingsPath = config.get('paths').defaultSettings;
22
-
23
- return Promise.each(knownSettings, function (setting) {
24
- const fileName = `${setting}.yaml`;
25
- const defaultFileName = `default-${fileName}`;
26
- const filePath = path.join(contentPath, fileName);
27
-
28
- return Promise.resolve(fs.readFile(filePath, 'utf8'))
29
- .catch({code: 'ENOENT'}, () => {
30
- const defaultFilePath = path.join(defaultSettingsPath, defaultFileName);
31
- // CASE: file doesn't exist, copy it from our defaults
32
- return fs.copy(
33
- defaultFilePath,
34
- filePath
35
- ).then(() => {
36
- debug(`'${defaultFileName}' copied to ${contentPath}.`);
37
- });
38
- }).catch((error) => {
39
- // CASE: we might have a permission error, as we can't access the directory
40
- throw new errors.GhostError({
41
- message: i18n.t('errors.services.settings.ensureSettings', {path: contentPath}),
42
- err: error,
43
- context: error.path
44
- });
45
- });
46
- });
47
- };
@@ -1,104 +0,0 @@
1
- const _ = require('lodash');
2
- const crypto = require('crypto');
3
- const debug = require('@tryghost/debug')('frontend:services:settings:index');
4
- const SettingsLoader = require('./loader');
5
- const ensureSettingsFiles = require('./ensure-settings');
6
-
7
- const errors = require('@tryghost/errors');
8
-
9
- /**
10
- * md5 hashes of default settings
11
- */
12
- const defaultHashes = {
13
- routes: '3d180d52c663d173a6be791ef411ed01'
14
- };
15
-
16
- const calculateHash = (data) => {
17
- return crypto.createHash('md5')
18
- .update(data, 'binary')
19
- .digest('hex');
20
- };
21
-
22
- module.exports = {
23
- init: function () {
24
- const knownSettings = this.knownSettings();
25
-
26
- debug('init settings service for:', knownSettings);
27
-
28
- // Make sure that supported settings files are available
29
- // inside of the `content/setting` directory
30
- return ensureSettingsFiles(knownSettings);
31
- },
32
-
33
- /**
34
- * Global place to switch on more available settings.
35
- */
36
- knownSettings: function knownSettings() {
37
- return ['routes'];
38
- },
39
-
40
- /**
41
- * Getter for YAML settings.
42
- * Example: `settings.get('routes').then(...)`
43
- * will return an Object like this:
44
- * {routes: {}, collections: {}, resources: {}}
45
- * @param {String} setting type of supported setting.
46
- * @returns {Object} settingsFile
47
- * @description Returns settings object as defined per YAML files in
48
- * `/content/settings` directory.
49
- */
50
- get: function get(setting) {
51
- const knownSettings = this.knownSettings();
52
-
53
- // CASE: this should be an edge case and only if internal usage of the
54
- // getter is incorrect.
55
- if (!setting || _.indexOf(knownSettings, setting) < 0) {
56
- throw new errors.IncorrectUsageError({
57
- message: `Requested setting is not supported: '${setting}'.`,
58
- help: `Please use only the supported settings: ${knownSettings}.`
59
- });
60
- }
61
-
62
- return SettingsLoader(setting);
63
- },
64
-
65
- /**
66
- * Getter for all YAML settings.
67
- * Example: `settings.getAll().then(...)`
68
- * will return an Object like this (assuming we're supporting `routes`
69
- * and `globals`):
70
- * {
71
- * routes: {
72
- * routes: null,
73
- * collections: { '/': [Object] },
74
- * resources: { tag: '/tag/{slug}/', author: '/author/{slug}/' }
75
- * },
76
- * globals: {
77
- * config: { url: 'testblog.com' }
78
- * }
79
- * }
80
- * @returns {Object} settingsObject
81
- * @description Returns all settings object as defined per YAML files in
82
- * `/content/settings` directory.
83
- */
84
- getAll: function getAll() {
85
- const knownSettings = this.knownSettings();
86
- const settingsToReturn = {};
87
-
88
- _.each(knownSettings, function (setting) {
89
- settingsToReturn[setting] = SettingsLoader(setting);
90
- });
91
-
92
- return settingsToReturn;
93
- },
94
-
95
- getDefaulHash: (setting) => {
96
- return defaultHashes[setting];
97
- },
98
-
99
- getCurrentHash: async (setting) => {
100
- const data = await SettingsLoader.loadSettings(setting);
101
-
102
- return calculateHash(JSON.stringify(data));
103
- }
104
- };
@@ -1,89 +0,0 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
3
- const debug = require('@tryghost/debug')('frontend:services:settings:settings-loader');
4
- const {i18n} = require('../proxy');
5
- const errors = require('@tryghost/errors');
6
- const config = require('../../../shared/config');
7
- const yamlParser = require('./yaml-parser');
8
- const validate = require('./validate');
9
-
10
- const getSettingFilePath = (setting) => {
11
- // we only support the `yaml` file extension. `yml` will be ignored.
12
- const fileName = `${setting}.yaml`;
13
- const contentPath = config.getContentPath('settings');
14
- const filePath = path.join(contentPath, fileName);
15
-
16
- return {
17
- fileName,
18
- contentPath,
19
- filePath
20
- };
21
- };
22
-
23
- /**
24
- * Functionally same as loadSettingsSync with exception of loading
25
- * settigs asyncronously. This method is used at new places to read settings
26
- * to prevent blocking the eventloop
27
- *
28
- * @param {String} setting the requested settings as defined in setting knownSettings
29
- * @returns {Object} settingsFile
30
- */
31
- const loadSettings = async (setting) => {
32
- const {fileName, contentPath, filePath} = getSettingFilePath(setting);
33
-
34
- try {
35
- const file = await fs.readFile(filePath, 'utf8');
36
- debug('settings file found for', setting);
37
-
38
- const object = yamlParser(file, fileName);
39
- return validate(object);
40
- } catch (err) {
41
- if (errors.utils.isIgnitionError(err)) {
42
- throw err;
43
- }
44
-
45
- throw new errors.GhostError({
46
- message: i18n.t('errors.services.settings.loader', {
47
- setting: setting,
48
- path: contentPath
49
- }),
50
- context: filePath,
51
- err: err
52
- });
53
- }
54
- };
55
-
56
- /**
57
- * Reads the desired settings YAML file and passes the
58
- * file to the YAML parser which then returns a JSON object.
59
- * NOTE: loading happens syncronously
60
- *
61
- * @param {String} setting the requested settings as defined in setting knownSettings
62
- * @returns {Object} settingsFile
63
- */
64
- module.exports = function loadSettingsSync(setting) {
65
- const {fileName, contentPath, filePath} = getSettingFilePath(setting);
66
-
67
- try {
68
- const file = fs.readFileSync(filePath, 'utf8');
69
- debug('settings file found for', setting);
70
-
71
- const object = yamlParser(file, fileName);
72
- return validate(object);
73
- } catch (err) {
74
- if (errors.utils.isIgnitionError(err)) {
75
- throw err;
76
- }
77
-
78
- throw new errors.GhostError({
79
- message: i18n.t('errors.services.settings.loader', {
80
- setting: setting,
81
- path: contentPath
82
- }),
83
- context: filePath,
84
- err: err
85
- });
86
- }
87
- };
88
-
89
- module.exports.loadSettings = loadSettings;
@@ -1,31 +0,0 @@
1
- const yaml = require('js-yaml');
2
- const debug = require('@tryghost/debug')('frontend:services:settings:yaml-parser');
3
- const {i18n} = require('../proxy');
4
- const errors = require('@tryghost/errors');
5
-
6
- /**
7
- * Takes a YAML file, parses it and returns a JSON Object
8
- * @param {YAML} file the YAML file utf8 encoded
9
- * @param {String} fileName the name of the file incl. extension
10
- * @returns {Object} parsed
11
- */
12
- module.exports = function parseYaml(file, fileName) {
13
- try {
14
- const parsed = yaml.load(file);
15
-
16
- debug('YAML settings file parsed:', fileName);
17
-
18
- return parsed;
19
- } catch (error) {
20
- // CASE: parsing failed, `js-yaml` tells us exactly what and where in the
21
- // `reason` property as well as in the message.
22
- // As the file uploaded is invalid, the person uploading must fix this - it's a 4xx error
23
- throw new errors.IncorrectUsageError({
24
- message: i18n.t('errors.services.settings.yaml.error', {file: fileName, context: error.reason}),
25
- code: 'YAML_PARSER_ERROR',
26
- context: error.message,
27
- err: error,
28
- help: i18n.t('errors.services.settings.yaml.help', {file: fileName})
29
- });
30
- }
31
- };