ghost 4.25.0 → 4.27.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.
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/built/screen.css.map +1 -1
- package/content/themes/casper/assets/css/screen.css +54 -10
- package/content/themes/casper/package.json +1 -1
- package/core/app.js +8 -4
- package/core/boot.js +50 -23
- package/core/built/assets/{chunk.3.8f95b516d88ff4eec64c.js → chunk.3.e54be01b5124e4e27958.js} +7 -7
- package/core/built/assets/ghost-dark-ae67fe157509b6e82c607ba560fc52e9.css +1 -0
- package/core/built/assets/{ghost.min-bc72f685c1c9adc9885925c1412435a5.js → ghost.min-2d534cce15c43c646814b26f4beefb78.js} +134 -131
- package/core/built/assets/ghost.min-b1e58e098721e467388682a85a7c187d.css +1 -0
- package/core/built/assets/{vendor.min-d1234c632a54502777c34e50752fa3fc.js → vendor.min-e433aa7d5620e7837f30e170cd43f84e.js} +597 -563
- package/core/frontend/apps/amp/lib/views/amp.hbs +67 -0
- package/core/frontend/helpers/url.js +18 -1
- package/core/frontend/src/cards/css/audio.css +258 -0
- package/core/frontend/src/cards/css/blockquote.css +23 -0
- package/core/frontend/src/cards/css/callout.css +13 -4
- package/core/frontend/src/cards/css/product.css +101 -0
- package/core/frontend/src/cards/css/toggle.css +42 -20
- package/core/frontend/src/cards/js/audio.js +147 -0
- package/core/frontend/web/site.js +1 -1
- package/core/server/notify.js +1 -2
- package/core/server/services/mega/template.js +31 -5
- package/core/server/services/members/api.js +2 -2
- package/core/server/services/members/emails/signup-paid.js +4 -4
- package/core/server/services/nft-oembed.js +1 -1
- package/core/server/services/oembed.js +9 -1
- package/core/server/services/twitter-embed.js +3 -1
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/server/web/parent/app.js +2 -22
- package/core/server/web/parent/backend.js +2 -0
- package/core/shared/express.js +1 -1
- package/core/shared/labs.js +6 -4
- package/package.json +36 -36
- package/yarn.lock +362 -447
- package/core/built/assets/ghost-dark-d690e732e17ffc794e2e59c1467ca282.css +0 -1
- package/core/built/assets/ghost.min-043bb7480a0810109b130f13b2a4235e.css +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const handleAudioPlayer = function (audioElementContainer) {
|
|
2
|
+
const audioPlayerContainer = audioElementContainer.querySelector('.kg-player-container');
|
|
3
|
+
const playIconContainer = audioElementContainer.querySelector('.kg-audio-play-icon');
|
|
4
|
+
const pauseIconContainer = audioElementContainer.querySelector('.kg-audio-pause-icon');
|
|
5
|
+
const seekSlider = audioElementContainer.querySelector('.kg-audio-seek-slider');
|
|
6
|
+
const playbackRateContainer = audioElementContainer.querySelector('.kg-audio-playback-rate');
|
|
7
|
+
const muteIconContainer = audioElementContainer.querySelector('.kg-audio-mute-icon');
|
|
8
|
+
const unmuteIconContainer = audioElementContainer.querySelector('.kg-audio-unmute-icon');
|
|
9
|
+
const volumeSlider = audioElementContainer.querySelector('.kg-audio-volume-slider');
|
|
10
|
+
const audio = audioElementContainer.querySelector('audio');
|
|
11
|
+
const durationContainer = audioElementContainer.querySelector('.kg-audio-duration');
|
|
12
|
+
const currentTimeContainer = audioElementContainer.querySelector('.kg-audio-current-time');
|
|
13
|
+
let playbackRates = [{
|
|
14
|
+
rate: 0.75,
|
|
15
|
+
label: '0.7×'
|
|
16
|
+
}, {
|
|
17
|
+
rate: 1.0,
|
|
18
|
+
label: '1×'
|
|
19
|
+
}, {
|
|
20
|
+
rate: 1.25,
|
|
21
|
+
label: '1.2×'
|
|
22
|
+
}, {
|
|
23
|
+
rate: 1.75,
|
|
24
|
+
label: '1.7×'
|
|
25
|
+
}, {
|
|
26
|
+
rate: 2.0,
|
|
27
|
+
label: '2×'
|
|
28
|
+
}];
|
|
29
|
+
|
|
30
|
+
let raf = null;
|
|
31
|
+
let currentPlaybackRateIdx = 1;
|
|
32
|
+
|
|
33
|
+
audio.src = audioElementContainer.getAttribute('data-kg-audio-src');
|
|
34
|
+
|
|
35
|
+
const whilePlaying = () => {
|
|
36
|
+
seekSlider.value = Math.floor(audio.currentTime);
|
|
37
|
+
currentTimeContainer.textContent = calculateTime(seekSlider.value);
|
|
38
|
+
audioPlayerContainer.style.setProperty('--seek-before-width', `${seekSlider.value / seekSlider.max * 100}%`);
|
|
39
|
+
raf = requestAnimationFrame(whilePlaying);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const showRangeProgress = (rangeInput) => {
|
|
43
|
+
if (rangeInput === seekSlider) {
|
|
44
|
+
audioPlayerContainer.style.setProperty('--seek-before-width', rangeInput.value / rangeInput.max * 100 + '%');
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
audioPlayerContainer.style.setProperty('--volume-before-width', rangeInput.value / rangeInput.max * 100 + '%');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const calculateTime = (secs) => {
|
|
52
|
+
const minutes = Math.floor(secs / 60);
|
|
53
|
+
const seconds = Math.floor(secs % 60);
|
|
54
|
+
const returnedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
|
|
55
|
+
return `${minutes}:${returnedSeconds}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const displayDuration = () => {
|
|
59
|
+
durationContainer.textContent = calculateTime(audio.duration);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const setSliderMax = () => {
|
|
63
|
+
seekSlider.max = Math.floor(audio.duration);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const displayBufferedAmount = () => {
|
|
67
|
+
if (audio.buffered.length > 0) {
|
|
68
|
+
const bufferedAmount = Math.floor(audio.buffered.end(audio.buffered.length - 1));
|
|
69
|
+
audioPlayerContainer.style.setProperty('--buffered-width', `${(bufferedAmount / seekSlider.max) * 100}%`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (audio.readyState > 0) {
|
|
74
|
+
displayDuration();
|
|
75
|
+
setSliderMax();
|
|
76
|
+
displayBufferedAmount();
|
|
77
|
+
} else {
|
|
78
|
+
audio.addEventListener('loadedmetadata', () => {
|
|
79
|
+
displayDuration();
|
|
80
|
+
setSliderMax();
|
|
81
|
+
displayBufferedAmount();
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
playIconContainer.addEventListener('click', () => {
|
|
86
|
+
playIconContainer.classList.add("kg-audio-hide");
|
|
87
|
+
pauseIconContainer.classList.remove("kg-audio-hide");
|
|
88
|
+
audio.play();
|
|
89
|
+
requestAnimationFrame(whilePlaying);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
pauseIconContainer.addEventListener('click', () => {
|
|
93
|
+
pauseIconContainer.classList.add("kg-audio-hide");
|
|
94
|
+
playIconContainer.classList.remove("kg-audio-hide");
|
|
95
|
+
audio.pause();
|
|
96
|
+
cancelAnimationFrame(raf);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
muteIconContainer.addEventListener('click', () => {
|
|
100
|
+
muteIconContainer.classList.add("kg-audio-hide");
|
|
101
|
+
unmuteIconContainer.classList.remove("kg-audio-hide");
|
|
102
|
+
audio.muted = false;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
unmuteIconContainer.addEventListener('click', () => {
|
|
106
|
+
unmuteIconContainer.classList.add("kg-audio-hide");
|
|
107
|
+
muteIconContainer.classList.remove("kg-audio-hide");
|
|
108
|
+
audio.muted = true;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
playbackRateContainer.addEventListener('click', () => {
|
|
112
|
+
let nextPlaybackRate = playbackRates[(currentPlaybackRateIdx + 1) % 5];
|
|
113
|
+
currentPlaybackRateIdx = currentPlaybackRateIdx + 1;
|
|
114
|
+
audio.playbackRate = nextPlaybackRate.rate;
|
|
115
|
+
playbackRateContainer.textContent = nextPlaybackRate.label;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
audio.addEventListener('progress', displayBufferedAmount);
|
|
119
|
+
|
|
120
|
+
seekSlider.addEventListener('input', (e) => {
|
|
121
|
+
showRangeProgress(e.target);
|
|
122
|
+
currentTimeContainer.textContent = calculateTime(seekSlider.value);
|
|
123
|
+
if (!audio.paused) {
|
|
124
|
+
cancelAnimationFrame(raf);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
seekSlider.addEventListener('change', () => {
|
|
129
|
+
audio.currentTime = seekSlider.value;
|
|
130
|
+
if (!audio.paused) {
|
|
131
|
+
requestAnimationFrame(whilePlaying);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
volumeSlider.addEventListener('input', (e) => {
|
|
136
|
+
const value = e.target.value;
|
|
137
|
+
showRangeProgress(e.target);
|
|
138
|
+
audio.volume = value / 100;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const audioCardElements = document.querySelectorAll('.kg-audio-card');
|
|
143
|
+
|
|
144
|
+
for (let i = 0; i < audioCardElements.length; i++) {
|
|
145
|
+
handleAudioPlayer(audioCardElements[i]);
|
|
146
|
+
}
|
|
147
|
+
|
|
@@ -112,7 +112,7 @@ module.exports = function setupSiteApp(options = {}) {
|
|
|
112
112
|
|
|
113
113
|
// Card assets
|
|
114
114
|
siteApp.use(mw.servePublicFile('built', 'public/cards.min.css', 'text/css', constants.ONE_YEAR_S));
|
|
115
|
-
siteApp.use(mw.servePublicFile('built', 'public/cards.min.js', '
|
|
115
|
+
siteApp.use(mw.servePublicFile('built', 'public/cards.min.js', 'application/javascript', constants.ONE_YEAR_S));
|
|
116
116
|
|
|
117
117
|
// Serve blog images using the storage adapter
|
|
118
118
|
siteApp.use(STATIC_IMAGE_URL_PREFIX, mw.handleImageSizes, storage.getStorage('images').serve());
|
package/core/server/notify.js
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
// Required Ghost internals
|
|
10
10
|
const config = require('../shared/config');
|
|
11
|
-
const logging = require('@tryghost/logging');
|
|
12
11
|
|
|
13
12
|
let notified = {
|
|
14
13
|
started: false,
|
|
@@ -53,7 +52,7 @@ async function notify(type, error = null) {
|
|
|
53
52
|
let socketAddress = config.get('bootstrap-socket');
|
|
54
53
|
if (socketAddress) {
|
|
55
54
|
const bootstrapSocket = require('@tryghost/bootstrap-socket');
|
|
56
|
-
return bootstrapSocket.connectAndSend(socketAddress,
|
|
55
|
+
return bootstrapSocket.connectAndSend(socketAddress, message);
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
return Promise.resolve();
|
|
@@ -148,7 +148,7 @@ dd {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
blockquote {
|
|
151
|
-
margin: 2em 0;
|
|
151
|
+
margin: 2em 0 2em 0;
|
|
152
152
|
padding: 0 25px 0 25px;
|
|
153
153
|
border-left: ${templateSettings.accentColor || '#15212A'} 2px solid;
|
|
154
154
|
font-size: 17px;
|
|
@@ -157,6 +157,15 @@ blockquote {
|
|
|
157
157
|
letter-spacing: -0.2px;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
blockquote.kg-blockquote-alt {
|
|
161
|
+
border-left: 0 none;
|
|
162
|
+
padding: 0 50px 0 50px;
|
|
163
|
+
text-align: center;
|
|
164
|
+
font-size: 1.2em;
|
|
165
|
+
font-style: italic;
|
|
166
|
+
color: #999999;
|
|
167
|
+
}
|
|
168
|
+
|
|
160
169
|
blockquote p {
|
|
161
170
|
margin: 0.8em 0;
|
|
162
171
|
font-size: 1em;
|
|
@@ -557,6 +566,16 @@ figure blockquote p {
|
|
|
557
566
|
padding-bottom: 4px;
|
|
558
567
|
}
|
|
559
568
|
|
|
569
|
+
.kg-twitter-link {
|
|
570
|
+
display: block;
|
|
571
|
+
text-decoration: none !important;
|
|
572
|
+
color: #15212A !important;
|
|
573
|
+
font-family: inherit !important;
|
|
574
|
+
font-size: 15px;
|
|
575
|
+
padding: 8px;
|
|
576
|
+
line-height: 1.3em;
|
|
577
|
+
}
|
|
578
|
+
|
|
560
579
|
.kg-callout-card {
|
|
561
580
|
display: flex;
|
|
562
581
|
margin: 0 0 1.5em 0;
|
|
@@ -888,10 +907,17 @@ figure blockquote p {
|
|
|
888
907
|
}
|
|
889
908
|
|
|
890
909
|
table.body blockquote {
|
|
891
|
-
font-size: 17px
|
|
892
|
-
line-height: 1.6em
|
|
893
|
-
margin-bottom: 0
|
|
894
|
-
padding-left: 15px
|
|
910
|
+
font-size: 17px;
|
|
911
|
+
line-height: 1.6em;
|
|
912
|
+
margin-bottom: 0;
|
|
913
|
+
padding-left: 15px;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
table.body blockquote.kg-blockquote-alt {
|
|
917
|
+
border-left: 0 none !important;
|
|
918
|
+
margin: 0 0 2.5em 0 !important;
|
|
919
|
+
padding: 0 50px 0 50px !important;
|
|
920
|
+
font-size: 1.2em;
|
|
895
921
|
}
|
|
896
922
|
|
|
897
923
|
table.body blockquote + * {
|
|
@@ -98,9 +98,9 @@ function createApiInstance(config) {
|
|
|
98
98
|
`;
|
|
99
99
|
case 'signup-paid':
|
|
100
100
|
return `
|
|
101
|
-
|
|
101
|
+
Hey there!
|
|
102
102
|
|
|
103
|
-
Tap the link below to be automatically signed in:
|
|
103
|
+
Thank you for subscribing to ${siteTitle}. Tap the link below to be automatically signed in:
|
|
104
104
|
|
|
105
105
|
${url}
|
|
106
106
|
|
|
@@ -107,7 +107,7 @@ module.exports = ({siteTitle, email, url, accentColor = '#15212A', siteDomain, s
|
|
|
107
107
|
<div class="content" style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 600px; padding: 30px 20px;">
|
|
108
108
|
|
|
109
109
|
<!-- START CENTERED WHITE CONTAINER -->
|
|
110
|
-
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">
|
|
110
|
+
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">Thank you for subscribing to ${siteTitle}.</span>
|
|
111
111
|
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 8px;">
|
|
112
112
|
|
|
113
113
|
<!-- START MAIN CONTENT AREA -->
|
|
@@ -116,8 +116,8 @@ module.exports = ({siteTitle, email, url, accentColor = '#15212A', siteDomain, s
|
|
|
116
116
|
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
117
117
|
<tr>
|
|
118
118
|
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">
|
|
119
|
-
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 20px; color: #15212A; font-weight: bold; line-height: 25px; margin: 0; margin-bottom: 15px;">
|
|
120
|
-
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; font-weight: normal; line-height: 25px; margin: 0; margin-bottom: 32px;">Tap the link below to be automatically signed in:</p>
|
|
119
|
+
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 20px; color: #15212A; font-weight: bold; line-height: 25px; margin: 0; margin-bottom: 15px;">Hey there!</p>
|
|
120
|
+
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; font-weight: normal; line-height: 25px; margin: 0; margin-bottom: 32px;">Thank you for subscribing to ${siteTitle}. Tap the link below to be automatically signed in:</p>
|
|
121
121
|
<table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box;">
|
|
122
122
|
<tbody>
|
|
123
123
|
<tr>
|
|
@@ -125,7 +125,7 @@ module.exports = ({siteTitle, email, url, accentColor = '#15212A', siteDomain, s
|
|
|
125
125
|
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
|
|
126
126
|
<tbody>
|
|
127
127
|
<tr>
|
|
128
|
-
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; vertical-align: top; background-color: ${accentColor}; border-radius: 5px; text-align: center;"> <a href="${url}" target="_blank" style="display: inline-block; color: #ffffff; background-color: ${accentColor}; border: solid 1px ${accentColor}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: ${accentColor};">
|
|
128
|
+
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; vertical-align: top; background-color: ${accentColor}; border-radius: 5px; text-align: center;"> <a href="${url}" target="_blank" style="display: inline-block; color: #ffffff; background-color: ${accentColor}; border: solid 1px ${accentColor}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: ${accentColor};">Sign in</a> </td>
|
|
129
129
|
</tr>
|
|
130
130
|
</tbody>
|
|
131
131
|
</table>
|
|
@@ -46,7 +46,7 @@ class NFTOEmbedProvider {
|
|
|
46
46
|
return {
|
|
47
47
|
version: '1.0',
|
|
48
48
|
type: 'nft',
|
|
49
|
-
title: result.body.name
|
|
49
|
+
title: result.body.name ? result.body.name : `#${result.body.token_id}`,
|
|
50
50
|
author_name: result.body.creator.user.username,
|
|
51
51
|
author_url: `https://opensea.io/${result.body.creator.user.username}`,
|
|
52
52
|
provider_name: 'OpenSea',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const errors = require('@tryghost/errors');
|
|
2
2
|
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const logging = require('@tryghost/logging');
|
|
4
|
+
const sentry = require('../../shared/sentry');
|
|
4
5
|
const {extract, hasProvider} = require('oembed-parser');
|
|
5
6
|
const cheerio = require('cheerio');
|
|
6
7
|
const _ = require('lodash');
|
|
@@ -128,7 +129,14 @@ class OEmbed {
|
|
|
128
129
|
const response = await this.externalRequest(url, {cookieJar});
|
|
129
130
|
|
|
130
131
|
const html = response.body;
|
|
131
|
-
|
|
132
|
+
try {
|
|
133
|
+
scraperResponse = await metascraper({html, url});
|
|
134
|
+
} catch (err) {
|
|
135
|
+
// Log to avoid being blind to errors happenning in metascraper
|
|
136
|
+
sentry.captureException(err);
|
|
137
|
+
logging.error(err);
|
|
138
|
+
return this.unknownProvider(url);
|
|
139
|
+
}
|
|
132
140
|
|
|
133
141
|
const metadata = Object.assign({}, scraperResponse, {
|
|
134
142
|
thumbnail: scraperResponse.image,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const {extract} = require('oembed-parser');
|
|
2
|
+
const labs = require('../../shared/labs');
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* @typedef {import('./oembed').ICustomProvider} ICustomProvider
|
|
@@ -41,7 +42,7 @@ class TwitterOEmbedProvider {
|
|
|
41
42
|
/** @type {object} */
|
|
42
43
|
const oembedData = await extract(url.href);
|
|
43
44
|
|
|
44
|
-
if (this.dependencies.config.bearerToken) {
|
|
45
|
+
if (this.dependencies.config.bearerToken && labs.isSet('richTwitterNewsletters')) {
|
|
45
46
|
const query = {
|
|
46
47
|
expansions: ['attachments.poll_ids', 'attachments.media_keys', 'author_id', 'entities.mentions.username', 'geo.place_id', 'in_reply_to_user_id', 'referenced_tweets.id', 'referenced_tweets.id.author_id'],
|
|
47
48
|
'media.fields': ['duration_ms', 'height', 'media_key', 'preview_image_url', 'type', 'url', 'width', 'public_metrics', 'alt_text'],
|
|
@@ -66,6 +67,7 @@ class TwitterOEmbedProvider {
|
|
|
66
67
|
const body = JSON.parse(result.body);
|
|
67
68
|
|
|
68
69
|
oembedData.tweet_data = body.data;
|
|
70
|
+
oembedData.tweet_data.includes = body.includes;
|
|
69
71
|
} catch (err) {
|
|
70
72
|
this.dependencies.logging.error(err);
|
|
71
73
|
}
|
|
@@ -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%22rootURL%22%3A%22%2F%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%224.
|
|
11
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%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%224.27%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22emberKeyboard%22%3A%7B%22disableInputsInitializer%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%7D" />
|
|
12
12
|
|
|
13
13
|
<meta name="HandheldFriendly" content="True" />
|
|
14
14
|
<meta name="MobileOptimized" content="320" />
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
<link rel="stylesheet" href="assets/vendor.min-987af30228885bce50f05c4723fe6f53.css">
|
|
44
|
-
<link rel="stylesheet" href="assets/ghost.min-
|
|
44
|
+
<link rel="stylesheet" href="assets/ghost.min-b1e58e098721e467388682a85a7c187d.css" title="light">
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
<div id="ember-basic-dropdown-wormhole"></div>
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
<script src="assets/vendor.min-
|
|
63
|
-
<script src="assets/ghost.min-
|
|
62
|
+
<script src="assets/vendor.min-e433aa7d5620e7837f30e170cd43f84e.js"></script>
|
|
63
|
+
<script src="assets/ghost.min-2d534cce15c43c646814b26f4beefb78.js"></script>
|
|
64
64
|
|
|
65
65
|
</body>
|
|
66
66
|
</html>
|
|
@@ -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%22rootURL%22%3A%22%2F%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%224.
|
|
11
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%2F%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%224.27%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22emberKeyboard%22%3A%7B%22disableInputsInitializer%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%7D" />
|
|
12
12
|
|
|
13
13
|
<meta name="HandheldFriendly" content="True" />
|
|
14
14
|
<meta name="MobileOptimized" content="320" />
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
<link rel="stylesheet" href="assets/vendor.min-987af30228885bce50f05c4723fe6f53.css">
|
|
44
|
-
<link rel="stylesheet" href="assets/ghost.min-
|
|
44
|
+
<link rel="stylesheet" href="assets/ghost.min-b1e58e098721e467388682a85a7c187d.css" title="light">
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
<div id="ember-basic-dropdown-wormhole"></div>
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
<script src="assets/vendor.min-
|
|
63
|
-
<script src="assets/ghost.min-
|
|
62
|
+
<script src="assets/vendor.min-e433aa7d5620e7837f30e170cd43f84e.js"></script>
|
|
63
|
+
<script src="assets/ghost.min-2d534cce15c43c646814b26f4beefb78.js"></script>
|
|
64
64
|
|
|
65
65
|
</body>
|
|
66
66
|
</html>
|
|
@@ -3,22 +3,15 @@ const config = require('../../../shared/config');
|
|
|
3
3
|
const express = require('../../../shared/express');
|
|
4
4
|
const compress = require('compression');
|
|
5
5
|
const mw = require('./middleware');
|
|
6
|
-
const vhost = require('@tryghost/vhost-middleware');
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
* @param {Object} options
|
|
10
|
-
* @param {Boolean} [options.start]
|
|
11
|
-
* @param {Boolean} [options.backend]
|
|
12
|
-
* @param {Boolean} [options.frontend]
|
|
13
|
-
*/
|
|
14
|
-
module.exports = function setupParentApp({start, frontend = true, backend = true}) {
|
|
7
|
+
module.exports = function setupParentApp() {
|
|
15
8
|
debug('ParentApp setup start');
|
|
16
9
|
const parentApp = express('parent');
|
|
17
10
|
|
|
18
11
|
parentApp.use(mw.requestId);
|
|
19
12
|
parentApp.use(mw.logRequest);
|
|
20
13
|
|
|
21
|
-
// Register event
|
|
14
|
+
// Register event emitter on req/res to trigger cache invalidation webhook event
|
|
22
15
|
parentApp.use(mw.emitEvents);
|
|
23
16
|
|
|
24
17
|
// enabled gzip compression by default
|
|
@@ -30,19 +23,6 @@ module.exports = function setupParentApp({start, frontend = true, backend = true
|
|
|
30
23
|
// @TODO: figure out if this is really needed everywhere? Is it not frontend only...
|
|
31
24
|
parentApp.use(mw.ghostLocals);
|
|
32
25
|
|
|
33
|
-
// Mount the express apps on the parentApp
|
|
34
|
-
|
|
35
|
-
if (backend) {
|
|
36
|
-
debug('Mounting bakcend: ADMIN + API');
|
|
37
|
-
const backendApp = require('./backend')();
|
|
38
|
-
parentApp.use(vhost(config.getBackendMountPath(), backendApp));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (frontend) {
|
|
42
|
-
debug('Mounting frontend: SITE + MEMBERS');
|
|
43
|
-
const frontendApp = require('./frontend')({start});
|
|
44
|
-
parentApp.use(vhost(config.getFrontendMountPath(), frontendApp));
|
|
45
|
-
}
|
|
46
26
|
debug('ParentApp setup end');
|
|
47
27
|
|
|
48
28
|
return parentApp;
|
|
@@ -10,9 +10,11 @@ module.exports = () => {
|
|
|
10
10
|
// BACKEND
|
|
11
11
|
// Wrap the admin and API apps into a single express app for use with vhost
|
|
12
12
|
const backendApp = express('backend');
|
|
13
|
+
|
|
13
14
|
backendApp.lazyUse('/ghost/api', require('../api'));
|
|
14
15
|
backendApp.lazyUse('/ghost/oauth', require('../oauth'));
|
|
15
16
|
backendApp.lazyUse('/ghost/.well-known', require('../well-known'));
|
|
17
|
+
|
|
16
18
|
backendApp.use('/ghost', require('../../services/auth/session').createSessionFromToken, require('../admin')());
|
|
17
19
|
|
|
18
20
|
return backendApp;
|
package/core/shared/express.js
CHANGED
|
@@ -29,7 +29,7 @@ module.exports = (name) => {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
// Wrap the main express router call
|
|
32
|
-
// This is mostly an
|
|
32
|
+
// This is mostly an experiment, and can likely be removed soon
|
|
33
33
|
module.exports.Router = (name, options) => {
|
|
34
34
|
debug('new Router start', name);
|
|
35
35
|
const router = express.Router(options);
|
package/core/shared/labs.js
CHANGED
|
@@ -16,7 +16,10 @@ const messages = {
|
|
|
16
16
|
// flags in this list always return `true`, allows quick global enable prior to full flag removal
|
|
17
17
|
const GA_FEATURES = [
|
|
18
18
|
'customThemeSettings',
|
|
19
|
-
'nftCard'
|
|
19
|
+
'nftCard',
|
|
20
|
+
'calloutCard',
|
|
21
|
+
'accordionCard',
|
|
22
|
+
'richTwitterNewsletters'
|
|
20
23
|
];
|
|
21
24
|
|
|
22
25
|
// NOTE: this allowlist is meant to be used to filter out any unexpected
|
|
@@ -34,13 +37,12 @@ const ALPHA_FEATURES = [
|
|
|
34
37
|
'mediaAPI',
|
|
35
38
|
'filesAPI',
|
|
36
39
|
'membersAutoLogin',
|
|
37
|
-
'calloutCard',
|
|
38
|
-
'accordionCard',
|
|
39
40
|
'fileCard',
|
|
40
41
|
'audioCard',
|
|
41
42
|
'videoCard',
|
|
42
43
|
'productCard',
|
|
43
|
-
'
|
|
44
|
+
'beforeAfterCard',
|
|
45
|
+
'tweetGridCard'
|
|
44
46
|
];
|
|
45
47
|
|
|
46
48
|
module.exports.GA_KEYS = [...GA_FEATURES];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ghost",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.27.0",
|
|
4
4
|
"description": "The professional publishing platform",
|
|
5
5
|
"author": "Ghost Foundation",
|
|
6
6
|
"homepage": "https://ghost.org",
|
|
@@ -54,53 +54,53 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@nexes/nql": "0.6.0",
|
|
57
|
-
"@sentry/node": "6.
|
|
58
|
-
"@tryghost/adapter-manager": "0.2.
|
|
57
|
+
"@sentry/node": "6.16.0",
|
|
58
|
+
"@tryghost/adapter-manager": "0.2.24",
|
|
59
59
|
"@tryghost/admin-api-schema": "2.6.1",
|
|
60
|
-
"@tryghost/bookshelf-plugins": "0.3.
|
|
61
|
-
"@tryghost/bootstrap-socket": "0.2.
|
|
60
|
+
"@tryghost/bookshelf-plugins": "0.3.5",
|
|
61
|
+
"@tryghost/bootstrap-socket": "0.2.14",
|
|
62
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",
|
|
66
66
|
"@tryghost/debug": "0.1.9",
|
|
67
|
-
"@tryghost/email-analytics-provider-mailgun": "1.0.
|
|
68
|
-
"@tryghost/email-analytics-service": "1.0.
|
|
67
|
+
"@tryghost/email-analytics-provider-mailgun": "1.0.6",
|
|
68
|
+
"@tryghost/email-analytics-service": "1.0.5",
|
|
69
69
|
"@tryghost/errors": "1.0.4",
|
|
70
70
|
"@tryghost/express-dynamic-redirects": "0.2.2",
|
|
71
71
|
"@tryghost/helpers": "1.1.54",
|
|
72
|
-
"@tryghost/image-transform": "1.0.
|
|
73
|
-
"@tryghost/job-manager": "0.8.
|
|
72
|
+
"@tryghost/image-transform": "1.0.24",
|
|
73
|
+
"@tryghost/job-manager": "0.8.16",
|
|
74
74
|
"@tryghost/kg-card-factory": "3.1.0",
|
|
75
75
|
"@tryghost/kg-default-atoms": "3.1.0",
|
|
76
|
-
"@tryghost/kg-default-cards": "5.
|
|
76
|
+
"@tryghost/kg-default-cards": "5.11.5",
|
|
77
77
|
"@tryghost/kg-markdown-html-renderer": "5.1.0",
|
|
78
|
-
"@tryghost/kg-mobiledoc-html-renderer": "5.3.
|
|
79
|
-
"@tryghost/limit-service": "1.0.
|
|
80
|
-
"@tryghost/logging": "1.0.
|
|
78
|
+
"@tryghost/kg-mobiledoc-html-renderer": "5.3.1",
|
|
79
|
+
"@tryghost/limit-service": "1.0.6",
|
|
80
|
+
"@tryghost/logging": "1.0.2",
|
|
81
81
|
"@tryghost/magic-link": "1.0.14",
|
|
82
|
-
"@tryghost/members-api": "2.8.
|
|
83
|
-
"@tryghost/members-csv": "1.
|
|
84
|
-
"@tryghost/members-importer": "0.3.
|
|
82
|
+
"@tryghost/members-api": "2.8.4",
|
|
83
|
+
"@tryghost/members-csv": "1.2.0",
|
|
84
|
+
"@tryghost/members-importer": "0.3.5",
|
|
85
85
|
"@tryghost/members-offers": "0.10.3",
|
|
86
|
-
"@tryghost/members-ssr": "1.0.
|
|
86
|
+
"@tryghost/members-ssr": "1.0.16",
|
|
87
87
|
"@tryghost/metrics": "1.0.1",
|
|
88
|
-
"@tryghost/minifier": "0.1.
|
|
88
|
+
"@tryghost/minifier": "0.1.7",
|
|
89
89
|
"@tryghost/mw-session-from-token": "0.1.26",
|
|
90
|
-
"@tryghost/nodemailer": "0.3.
|
|
91
|
-
"@tryghost/package-json": "1.0.
|
|
90
|
+
"@tryghost/nodemailer": "0.3.8",
|
|
91
|
+
"@tryghost/package-json": "1.0.12",
|
|
92
92
|
"@tryghost/promise": "0.1.13",
|
|
93
|
-
"@tryghost/request": "0.1.
|
|
93
|
+
"@tryghost/request": "0.1.10",
|
|
94
94
|
"@tryghost/root-utils": "0.3.7",
|
|
95
95
|
"@tryghost/security": "0.2.13",
|
|
96
|
-
"@tryghost/session-service": "0.1.
|
|
96
|
+
"@tryghost/session-service": "0.1.34",
|
|
97
97
|
"@tryghost/settings-path-manager": "0.1.2",
|
|
98
98
|
"@tryghost/social-urls": "0.1.27",
|
|
99
99
|
"@tryghost/string": "0.1.21",
|
|
100
100
|
"@tryghost/tpl": "0.1.8",
|
|
101
101
|
"@tryghost/update-check-service": "0.2.5",
|
|
102
102
|
"@tryghost/url-utils": "2.0.4",
|
|
103
|
-
"@tryghost/validator": "0.1.
|
|
103
|
+
"@tryghost/validator": "0.1.9",
|
|
104
104
|
"@tryghost/version": "0.1.7",
|
|
105
105
|
"@tryghost/vhost-middleware": "1.0.19",
|
|
106
106
|
"@tryghost/zip": "1.1.18",
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
"ghost-storage-base": "1.0.0",
|
|
131
131
|
"glob": "7.2.0",
|
|
132
132
|
"got": "9.6.0",
|
|
133
|
-
"gscan": "4.
|
|
133
|
+
"gscan": "4.16.0",
|
|
134
134
|
"html-to-text": "5.1.1",
|
|
135
135
|
"image-size": "1.0.0",
|
|
136
136
|
"intl": "1.2.5",
|
|
@@ -145,18 +145,18 @@
|
|
|
145
145
|
"lodash": "4.17.21",
|
|
146
146
|
"luxon": "2.1.1",
|
|
147
147
|
"mailgun-js": "0.22.0",
|
|
148
|
-
"metascraper": "5.25.
|
|
149
|
-
"metascraper-author": "5.25.
|
|
150
|
-
"metascraper-description": "5.25.
|
|
151
|
-
"metascraper-image": "5.25.
|
|
152
|
-
"metascraper-logo": "5.25.
|
|
153
|
-
"metascraper-logo-favicon": "5.25.
|
|
154
|
-
"metascraper-publisher": "5.25.
|
|
155
|
-
"metascraper-title": "5.25.
|
|
156
|
-
"metascraper-url": "5.25.
|
|
148
|
+
"metascraper": "5.25.5",
|
|
149
|
+
"metascraper-author": "5.25.5",
|
|
150
|
+
"metascraper-description": "5.25.5",
|
|
151
|
+
"metascraper-image": "5.25.5",
|
|
152
|
+
"metascraper-logo": "5.25.5",
|
|
153
|
+
"metascraper-logo-favicon": "5.25.5",
|
|
154
|
+
"metascraper-publisher": "5.25.5",
|
|
155
|
+
"metascraper-title": "5.25.5",
|
|
156
|
+
"metascraper-url": "5.25.5",
|
|
157
157
|
"moment": "2.24.0",
|
|
158
158
|
"moment-timezone": "0.5.23",
|
|
159
|
-
"multer": "1.4.
|
|
159
|
+
"multer": "1.4.4",
|
|
160
160
|
"mysql": "2.18.1",
|
|
161
161
|
"nconf": "0.11.3",
|
|
162
162
|
"node-jose": "2.0.0",
|
|
@@ -174,7 +174,7 @@
|
|
|
174
174
|
"xml": "1.0.1"
|
|
175
175
|
},
|
|
176
176
|
"optionalDependencies": {
|
|
177
|
-
"@tryghost/html-to-mobiledoc": "1.
|
|
177
|
+
"@tryghost/html-to-mobiledoc": "1.5.0",
|
|
178
178
|
"sqlite3": "5.0.2"
|
|
179
179
|
},
|
|
180
180
|
"devDependencies": {
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
"coffeescript": "2.6.1",
|
|
184
184
|
"cssnano": "5.0.12",
|
|
185
185
|
"eslint": "7.32.0",
|
|
186
|
-
"eslint-plugin-ghost": "2.
|
|
186
|
+
"eslint-plugin-ghost": "2.11.0",
|
|
187
187
|
"grunt": "1.4.1",
|
|
188
188
|
"grunt-bg-shell": "2.3.3",
|
|
189
189
|
"grunt-contrib-clean": "2.0.0",
|