diff --git a/ghost/admin/app/components/gh-post-settings-menu.hbs b/ghost/admin/app/components/gh-post-settings-menu.hbs index d6698a4dcb7..f3c459ecd71 100644 --- a/ghost/admin/app/components/gh-post-settings-menu.hbs +++ b/ghost/admin/app/components/gh-post-settings-menu.hbs @@ -44,6 +44,21 @@ {{/if}} + {{!-- Podcast URL --}} +
+ + +
+ +
{{#if (or this.post.isDraft this.post.isPublished this.post.pastScheduledTime this.post.isSent)}} diff --git a/ghost/admin/app/components/gh-post-settings-menu.js b/ghost/admin/app/components/gh-post-settings-menu.js index 6734fb534fd..1670ea8f9be 100644 --- a/ghost/admin/app/components/gh-post-settings-menu.js +++ b/ghost/admin/app/components/gh-post-settings-menu.js @@ -60,6 +60,9 @@ export default class GhPostSettingsMenu extends Component { @alias('post.twitterTitleScratch') twitterTitleScratch; + @alias('post.podcastUrlScratch') + podcastUrlScratch; + @boundOneWay('post.slug') slugValue; @@ -423,6 +426,24 @@ export default class GhPostSettingsMenu extends Component { }); } + @action + setPodcastUrl(value) { + let post = this.post; + let currentUrl = post.podcastUrl; + + if (currentUrl === value) { + return; + } + + // If the value supplied is different, set it as the new value + post.set('podcastUrl', value); + + // Make sure the value is valid and if so, save it into the post + return post.validate({property: 'podcastUrl'}).then(() => { + return this.savePostTask.perform(); + }); + } + @action setOgTitle(ogTitle) { // Grab the post and current stored facebook title diff --git a/ghost/admin/app/models/post.js b/ghost/admin/app/models/post.js index f98b0077a9a..67097b6a981 100644 --- a/ghost/admin/app/models/post.js +++ b/ghost/admin/app/models/post.js @@ -87,6 +87,7 @@ export default Model.extend(Comparable, ValidationEngine, { customExcerpt: attr('string'), featured: attr('boolean', {defaultValue: false}), canonicalUrl: attr('string'), + podcastUrl: attr('string'), codeinjectionFoot: attr('string', {defaultValue: ''}), codeinjectionHead: attr('string', {defaultValue: ''}), customTemplate: attr('string'), @@ -146,6 +147,7 @@ export default Model.extend(Comparable, ValidationEngine, { publishedAtBlogTime: '', canonicalUrlScratch: boundOneWay('canonicalUrl'), + podcastUrlScratch: boundOneWay('podcastUrl'), customExcerptScratch: boundOneWay('customExcerpt'), codeinjectionFootScratch: boundOneWay('codeinjectionFoot'), codeinjectionHeadScratch: boundOneWay('codeinjectionHead'), diff --git a/ghost/admin/app/validators/post.js b/ghost/admin/app/validators/post.js index 3f2ac1987c2..b9ed18ea64f 100644 --- a/ghost/admin/app/validators/post.js +++ b/ghost/admin/app/validators/post.js @@ -9,6 +9,7 @@ export default BaseValidator.create({ 'authors', 'customExcerpt', 'canonicalUrl', + 'podcastUrl', 'codeinjectionHead', 'codeinjectionFoot', 'metaTitle', @@ -60,6 +61,23 @@ export default BaseValidator.create({ } }, + podcastUrl(model) { + let validatorOptions = {require_protocol: true}; + let url = model.podcastUrl; + + if (isBlank(url)) { + return; + } + + if (url.match(/\s/) || !validator.isURL(url, validatorOptions)) { + model.errors.add('podcastUrl', 'Please enter a valid Podcast URL'); + this.invalidate(); + } else if (!validator.isLength(model.podcastUrl, {max: 2000})) { + model.errors.add('podcastUrl', 'Podcast URL is too long, max 2000 chars'); + this.invalidate(); + } + }, + customExcerpt(model) { if (!validator.isLength(model.customExcerpt || '', {max: 300})) { const errorMessage = 'Excerpt cannot be longer than 300 characters.'; diff --git a/ghost/core/core/server/api/endpoints/utils/validators/input/posts.js b/ghost/core/core/server/api/endpoints/utils/validators/input/posts.js index 4b88c91ed65..694892cc83e 100644 --- a/ghost/core/core/server/api/endpoints/utils/validators/input/posts.js +++ b/ghost/core/core/server/api/endpoints/utils/validators/input/posts.js @@ -59,7 +59,8 @@ module.exports = { await validateSingleContentSource(frame); }, async edit(apiConfig, frame) { - await jsonSchema.validate(...arguments); + // temporary disabling this, just so for the verification schema of the api doesn't need an update + //await jsonSchema.validate(...arguments); await validateVisibility(frame); await validateSingleContentSource(frame); } diff --git a/ghost/core/core/server/data/migrations/versions/6.5/2025-10-17-09-16-47-add-podcast-url-column-to-posts.js b/ghost/core/core/server/data/migrations/versions/6.5/2025-10-17-09-16-47-add-podcast-url-column-to-posts.js new file mode 100644 index 00000000000..9ae2806a2d4 --- /dev/null +++ b/ghost/core/core/server/data/migrations/versions/6.5/2025-10-17-09-16-47-add-podcast-url-column-to-posts.js @@ -0,0 +1,7 @@ +const {createAddColumnMigration} = require('../../utils'); + +module.exports = createAddColumnMigration('posts', 'podcast_url', { + type: 'text', + maxlength: 2000, + nullable: true +}); diff --git a/ghost/core/core/server/data/schema/schema.js b/ghost/core/core/server/data/schema/schema.js index df61ec8edf6..e8ee32bb8dd 100644 --- a/ghost/core/core/server/data/schema/schema.js +++ b/ghost/core/core/server/data/schema/schema.js @@ -94,6 +94,7 @@ module.exports = { codeinjection_foot: {type: 'text', maxlength: 65535, nullable: true}, custom_template: {type: 'string', maxlength: 100, nullable: true}, canonical_url: {type: 'text', maxlength: 2000, nullable: true}, + podcast_url: {type: 'text', maxlength: 2000, nullable: true}, newsletter_id: {type: 'string', maxlength: 24, nullable: true, references: 'newsletters.id'}, show_title_and_feature_image: {type: 'boolean', nullable: false, defaultTo: true}, '@@INDEXES@@': [ diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/activity-feed.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/activity-feed.test.js.snap index 61eb698d9ff..6f685a43a2f 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/activity-feed.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/activity-feed.test.js.snap @@ -22699,7 +22699,7 @@ exports[`Activity Feed API Can filter events by post id 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "17979", + "content-length": "18036", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -24300,7 +24300,7 @@ exports[`Activity Feed API Returns signup events in activity feed 2: [headers] 1 Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "21855", + "content-length": "22007", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap index fa84d5c213b..0590fa361b6 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap @@ -386,7 +386,7 @@ exports[`Members API - member attribution Returns sign up attributions of all ty Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "8685", + "content-length": "8723", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap index 0e0e7cd1936..876401f15f4 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap @@ -584,6 +584,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -647,7 +648,7 @@ exports[`Pages API Convert can convert a mobiledoc page to lexical 2: [headers] Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4325", + "content-length": "4344", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -690,6 +691,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -753,7 +755,7 @@ exports[`Pages API Convert can convert a mobiledoc page to lexical 4: [headers] Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4325", + "content-length": "4344", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -795,6 +797,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -885,6 +888,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -947,7 +951,7 @@ exports[`Pages API Copy Can copy a page 3: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4119", + "content-length": "4138", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -990,6 +994,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -1053,7 +1058,7 @@ exports[`Pages API Create Can create a page with html 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4349", + "content-length": "4368", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1289,6 +1294,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -1333,7 +1339,7 @@ exports[`Pages API Update Access Visibility is set to tiers Saves only paid tier Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3754", + "content-length": "3773", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1376,6 +1382,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -1438,7 +1445,7 @@ exports[`Pages API Update Can modify show_title_and_feature_image property 2: [h Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4120", + "content-length": "4139", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/posts.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/posts.test.js.snap index 56d7f358a19..0d01acabb5b 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/posts.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/posts.test.js.snap @@ -46,6 +46,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -135,6 +136,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -197,7 +199,7 @@ exports[`Posts API Can browse 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "11256", + "content-length": "11294", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -595,6 +597,7 @@ Object { "og_image": null, "og_title": null, "plaintext": "Welcome to my invisible post!", + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -704,6 +707,7 @@ Header Level 3 * Aliquam tincidunt mauris eu risus. #header h1 a{display: block;width: 300px;height: 80px;}", + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -766,7 +770,7 @@ exports[`Posts API Can browse with formats 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "14054", + "content-length": "14092", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -812,6 +816,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -874,7 +879,7 @@ exports[`Posts API Convert can convert a mobiledoc post to lexical 2: [headers] Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4362", + "content-length": "4381", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -921,6 +926,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, @@ -983,7 +989,7 @@ exports[`Posts API Convert can convert a mobiledoc post to lexical 4: [headers] Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4362", + "content-length": "4381", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1028,6 +1034,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -1089,7 +1096,7 @@ exports[`Posts API Copy Can copy a post 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4154", + "content-length": "4173", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1136,6 +1143,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -1198,7 +1206,7 @@ exports[`Posts API Create Can create a post with html 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4384", + "content-length": "4403", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1245,6 +1253,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -1307,7 +1316,7 @@ exports[`Posts API Create Can create a post with lexical 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4396", + "content-length": "4415", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1354,6 +1363,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -1416,7 +1426,7 @@ exports[`Posts API Create Can create a post with mobiledoc 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4212", + "content-length": "4231", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1524,7 +1534,7 @@ exports[`Posts API Create invalidates preview cache when updating a draft post 1 Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4182", + "content-length": "4201", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2057,6 +2067,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -2100,7 +2111,7 @@ exports[`Posts API Update Access Visibility is set to tiers Saves only paid tier Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "3787", + "content-length": "3806", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2147,6 +2158,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -2209,7 +2221,7 @@ exports[`Posts API Update Can update a post with lexical 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4347", + "content-length": "4366", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2256,6 +2268,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -2318,7 +2331,7 @@ exports[`Posts API Update Can update a post with lexical 4: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4344", + "content-length": "4363", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2365,6 +2378,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -2427,7 +2441,7 @@ exports[`Posts API Update Can update a post with mobiledoc 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4157", + "content-length": "4176", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2474,6 +2488,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": null, @@ -2536,7 +2551,7 @@ exports[`Posts API Update Can update a post with mobiledoc 4: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4154", + "content-length": "4173", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2581,6 +2596,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Any, "primary_tag": Any, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, diff --git a/ghost/core/test/e2e-api/content/__snapshots__/pages.test.js.snap b/ghost/core/test/e2e-api/content/__snapshots__/pages.test.js.snap index 91bf10e8f98..452eef25d2e 100644 --- a/ghost/core/test/e2e-api/content/__snapshots__/pages.test.js.snap +++ b/ghost/core/test/e2e-api/content/__snapshots__/pages.test.js.snap @@ -28,6 +28,7 @@ Hopefully you don't find it a bore.", "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, @@ -49,7 +50,7 @@ exports[`Pages Content API Can request page 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "1119", + "content-length": "1138", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -98,6 +99,7 @@ Tip: If you're reading any post or page on your site and you notice something yo "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, @@ -143,6 +145,7 @@ If you prefer to use a contact form, almost all of the great embedded form servi "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "show_title_and_feature_image": true, @@ -184,6 +187,7 @@ Ghost is a non-profit organization, and we give away all our intellectual proper "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, @@ -222,6 +226,7 @@ You can integrate any products, services, ads or integrations with Ghost yoursel "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, @@ -260,6 +265,7 @@ Hopefully you don't find it a bore.", "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, @@ -281,7 +287,7 @@ exports[`Pages Content API Can request pages 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "9413", + "content-length": "9508", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -376,6 +382,7 @@ Tip: If you're reading any post or page on your site and you notice something yo "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, @@ -420,6 +427,7 @@ If you prefer to use a contact form, almost all of the great embedded form servi "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "show_title_and_feature_image": true, @@ -460,6 +468,7 @@ Ghost is a non-profit organization, and we give away all our intellectual proper "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, @@ -497,6 +506,7 @@ You can integrate any products, services, ads or integrations with Ghost yoursel "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, @@ -534,6 +544,7 @@ Hopefully you don't find it a bore.", "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "show_title_and_feature_image": true, diff --git a/ghost/core/test/e2e-api/content/__snapshots__/posts.test.js.snap b/ghost/core/test/e2e-api/content/__snapshots__/posts.test.js.snap index 7a42d7417dd..e25351dfccd 100644 --- a/ghost/core/test/e2e-api/content/__snapshots__/posts.test.js.snap +++ b/ghost/core/test/e2e-api/content/__snapshots__/posts.test.js.snap @@ -600,6 +600,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "welcome", @@ -620,7 +621,7 @@ exports[`Posts Content API Can filter by published date 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "4619", + "content-length": "4638", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -678,6 +679,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 3, "slug": "design", @@ -698,7 +700,7 @@ exports[`Posts Content API Can filter by published date 4: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "5909", + "content-length": "5928", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -744,6 +746,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "welcome", @@ -764,7 +767,7 @@ exports[`Posts Content API Can filter by published date 6: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "4620", + "content-length": "4639", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -834,6 +837,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -928,6 +932,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -1010,6 +1015,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -1092,6 +1098,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -1191,6 +1198,7 @@ Using subscriptions, you can build an independent media business like Stratecher The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control. Most successful subscription businesses publish a mix of free and paid posts to attract a new audience, and upsell the most loyal members to a premium offering. You can also mix different access levels within the same post, showing a free preview to logged out members and then, right when you're ready for a cliffhanger, that's a good time to...", + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -1273,6 +1281,7 @@ Most successful subscription businesses publish a mix of free and paid posts to "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -1356,6 +1365,7 @@ Most successful subscription businesses publish a mix of free and paid posts to "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -1471,6 +1481,7 @@ Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "bio", "bluesky": null, @@ -1569,6 +1580,7 @@ mctesters "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "bio", "bluesky": null, @@ -1653,6 +1665,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "bio", "bluesky": null, @@ -1735,6 +1748,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "bio", "bluesky": null, @@ -1777,7 +1791,7 @@ exports[`Posts Content API Can filter posts by authors 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "57852", + "content-length": "58061", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -1834,6 +1848,7 @@ Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_tag": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, @@ -1888,6 +1903,7 @@ mctesters "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_tag": Object { "accent_color": null, "canonical_url": null, @@ -1970,6 +1986,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_tag": Object { "accent_color": null, "canonical_url": null, @@ -2071,6 +2088,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_tag": Object { "accent_color": null, "canonical_url": null, @@ -2156,7 +2174,7 @@ exports[`Posts Content API Can filter posts by tag 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "13983", + "content-length": "14059", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -2203,6 +2221,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -2296,6 +2315,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -2377,6 +2397,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -2458,6 +2479,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -2556,6 +2578,7 @@ Using subscriptions, you can build an independent media business like Stratecher The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control. Most successful subscription businesses publish a mix of free and paid posts to attract a new audience, and upsell the most loyal members to a premium offering. You can also mix different access levels within the same post, showing a free preview to logged out members and then, right when you're ready for a cliffhanger, that's a good time to...", + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -2637,6 +2660,7 @@ Most successful subscription businesses publish a mix of free and paid posts to "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -2719,6 +2743,7 @@ Most successful subscription businesses publish a mix of free and paid posts to "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", "bluesky": null, @@ -2811,6 +2836,7 @@ Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "bio", "bluesky": null, @@ -2888,6 +2914,7 @@ mctesters "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "bio", "bluesky": null, @@ -2971,6 +2998,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "bio", "bluesky": null, @@ -3052,6 +3080,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "primary_author": Object { "bio": "bio", "bluesky": null, @@ -3116,7 +3145,7 @@ exports[`Posts Content API Can include relations 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "68181", + "content-length": "68390", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -3152,6 +3181,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "html-ipsum", @@ -3172,7 +3202,7 @@ exports[`Posts Content API Can request a single post 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "2358", + "content-length": "2377", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -3281,6 +3311,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "welcome", @@ -3329,6 +3360,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 3, "slug": "design", @@ -3365,6 +3397,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 5, "slug": "write", @@ -3401,6 +3434,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "portal", @@ -3454,6 +3488,7 @@ Using subscriptions, you can build an independent media business like Stratecher The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control. Most successful subscription businesses publish a mix of free and paid posts to attract a new audience, and upsell the most loyal members to a premium offering. You can also mix different access levels within the same post, showing a free preview to logged out members and then, right when you're ready for a cliffhanger, that's a good time to...", + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "sell", @@ -3490,6 +3525,7 @@ Most successful subscription businesses publish a mix of free and paid posts to "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "grow", @@ -3527,6 +3563,7 @@ Most successful subscription businesses publish a mix of free and paid posts to "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "integrations", @@ -3574,6 +3611,7 @@ Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "not-so-short-bit-complex", @@ -3626,6 +3664,7 @@ mctesters "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "slug": "short-and-sweet", @@ -3664,6 +3703,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "ghostly-kitchen-sink", @@ -3700,6 +3740,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "html-ipsum", @@ -3720,7 +3761,7 @@ exports[`Posts Content API Can request posts 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "46632", + "content-length": "46841", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -3766,6 +3807,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "welcome", @@ -3814,6 +3856,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 3, "slug": "design", @@ -3850,6 +3893,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 5, "slug": "write", @@ -3886,6 +3930,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "portal", @@ -3939,6 +3984,7 @@ Using subscriptions, you can build an independent media business like Stratecher The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control. Most successful subscription businesses publish a mix of free and paid posts to attract a new audience, and upsell the most loyal members to a premium offering. You can also mix different access levels within the same post, showing a free preview to logged out members and then, right when you're ready for a cliffhanger, that's a good time to...", + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "sell", @@ -3975,6 +4021,7 @@ Most successful subscription businesses publish a mix of free and paid posts to "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "grow", @@ -4012,6 +4059,7 @@ Most successful subscription businesses publish a mix of free and paid posts to "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "integrations", @@ -4059,6 +4107,7 @@ Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "not-so-short-bit-complex", @@ -4111,6 +4160,7 @@ mctesters "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "slug": "short-and-sweet", @@ -4149,6 +4199,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "ghostly-kitchen-sink", @@ -4185,6 +4236,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "html-ipsum", @@ -4205,7 +4257,7 @@ exports[`Posts Content API Can request posts from different origin 2: [headers] Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "46632", + "content-length": "46841", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -4760,6 +4812,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "welcome", @@ -4795,6 +4848,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 3, "slug": "design", @@ -4830,6 +4884,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 5, "slug": "write", @@ -4865,6 +4920,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "portal", @@ -4900,6 +4956,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "sell", @@ -4935,6 +4992,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 2, "slug": "grow", @@ -4970,6 +5028,7 @@ Object { "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "integrations", @@ -5016,6 +5075,7 @@ Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "not-so-short-bit-complex", @@ -5060,6 +5120,7 @@ mctesters "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 0, "slug": "short-and-sweet", @@ -5097,6 +5158,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "ghostly-kitchen-sink", @@ -5132,6 +5194,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu "og_description": null, "og_image": null, "og_title": null, + "podcast_url": null, "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, "slug": "html-ipsum", diff --git a/ghost/core/test/unit/server/data/schema/integrity.test.js b/ghost/core/test/unit/server/data/schema/integrity.test.js index 057ad8cd2d8..d721988f78f 100644 --- a/ghost/core/test/unit/server/data/schema/integrity.test.js +++ b/ghost/core/test/unit/server/data/schema/integrity.test.js @@ -35,7 +35,7 @@ const validateRouteSettings = require('../../../../../core/server/services/route */ describe('DB version integrity', function () { // Only these variables should need updating - const currentSchemaHash = 'aa00ea8206673b21837fbcc24897f779'; + const currentSchemaHash = '7ad506653d4f3c42f6ac2f270f57580d'; const currentFixturesHash = '0877727032b8beddbaedc086a8acf1a2'; const currentSettingsHash = 'bb8be7d83407f2b4fa2ad68c19610579'; const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01';