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