From 5d8ea7978814b7186f40db8ad09f5322e074cd31 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Wed, 5 Jul 2023 16:01:24 +0200 Subject: [PATCH] Implemented `pages.hide_title_and_feature_image` property in API (#17211) closes https://github.com/TryGhost/Product/issues/3557 - bumped `@tryghost/admin-api-schema` to allow passthrough of the new property in API requests - updated output mapper to ensure property always returns a boolean rather than `null` in the case where `posts_meta` doesn't exist for a page - updated `PostsService.copyPost()` to include the new property when copying - updated `checkResponse` test util and snapshots to expect `hide_title_and_feature_image` property in page API responses - fixed pages e2e test so it doesn't inadvertently modify the match object breaking later tests --- .../utils/serializers/output/mappers/pages.js | 3 - .../utils/serializers/output/mappers/posts.js | 4 +- ghost/core/package.json | 2 +- .../admin/__snapshots__/pages.test.js.snap | 137 +++++++++++++++--- ghost/core/test/e2e-api/admin/pages.test.js | 53 ++++++- ghost/core/test/e2e-api/admin/utils.js | 3 +- .../content/__snapshots__/pages.test.js.snap | 15 +- .../__snapshots__/pages.test.js.snap | 10 ++ ghost/posts-service/lib/PostsService.js | 3 +- yarn.lock | 8 +- 10 files changed, 199 insertions(+), 39 deletions(-) diff --git a/ghost/core/core/server/api/endpoints/utils/serializers/output/mappers/pages.js b/ghost/core/core/server/api/endpoints/utils/serializers/output/mappers/pages.js index 061b5a5387..c519fa3546 100644 --- a/ghost/core/core/server/api/endpoints/utils/serializers/output/mappers/pages.js +++ b/ghost/core/core/server/api/endpoints/utils/serializers/output/mappers/pages.js @@ -8,8 +8,5 @@ module.exports = async (model, frame, options) => { delete jsonModel.email_only; delete jsonModel.newsletter_id; - // TODO: remove this once full API support is in place - delete jsonModel.hide_title_and_feature_image; - return jsonModel; }; diff --git a/ghost/core/core/server/api/endpoints/utils/serializers/output/mappers/posts.js b/ghost/core/core/server/api/endpoints/utils/serializers/output/mappers/posts.js index 1a92f1f7ac..f40825eb07 100644 --- a/ghost/core/core/server/api/endpoints/utils/serializers/output/mappers/posts.js +++ b/ghost/core/core/server/api/endpoints/utils/serializers/output/mappers/posts.js @@ -29,7 +29,7 @@ module.exports = async (model, frame, options = {}) => { if (typeof model.toJSON === 'function') { jsonModel = model.toJSON(frame.options); } else { - // This is to satisy the interface which extraAttrs needs + // This is to satisfy the interface which extraAttrs needs model = { id: jsonModel.id, get(attr) { @@ -105,7 +105,7 @@ module.exports = async (model, frame, options = {}) => { // NOTE: the default of `email_only` is `false` which is why we default to `false` instead of `null` // The undefined value is possible because `posts_meta` table is lazily created only one of the // values is assigned. - const defaultValue = (attr === 'email_only') ? false : null; + const defaultValue = (attr === 'email_only' || attr === 'hide_title_and_feature_image') ? false : null; jsonModel[attr] = _.get(jsonModel.posts_meta, attr) || defaultValue; }); delete jsonModel.posts_meta; diff --git a/ghost/core/package.json b/ghost/core/package.json index d602a78eb2..66d599823a 100644 --- a/ghost/core/package.json +++ b/ghost/core/package.json @@ -66,7 +66,7 @@ "@tryghost/adapter-base-cache": "0.1.5", "@tryghost/adapter-cache-redis": "0.0.0", "@tryghost/adapter-manager": "0.0.0", - "@tryghost/admin-api-schema": "4.4.0", + "@tryghost/admin-api-schema": "4.5.0", "@tryghost/announcement-bar-settings": "0.0.0", "@tryghost/api-framework": "0.0.0", "@tryghost/api-version-compatibility-service": "0.0.0", 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 182299a667..bb2087f132 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 @@ -24,6 +24,99 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": Any, + "html": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "lexical": null, + "meta_description": null, + "meta_title": null, + "mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}", + "og_description": null, + "og_image": null, + "og_title": null, + "post_revisions": Any, + "primary_author": Any, + "primary_tag": Any, + "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "slug": "test-page-2", + "status": "published", + "tags": Any, + "tiers": Array [ + Object { + "active": true, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "currency": null, + "description": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "monthly_price": null, + "monthly_price_id": null, + "name": "Free", + "slug": "free", + "trial_days": 0, + "type": "free", + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "visibility": "public", + "welcome_page_url": null, + "yearly_price": null, + "yearly_price_id": null, + }, + Object { + "active": true, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "currency": "usd", + "description": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "monthly_price": 500, + "monthly_price_id": null, + "name": "Default Product", + "slug": "default-product", + "trial_days": 0, + "type": "paid", + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "visibility": "public", + "welcome_page_url": null, + "yearly_price": 5000, + "yearly_price_id": null, + }, + ], + "title": "Test Page", + "twitter_description": null, + "twitter_image": null, + "twitter_title": null, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "url": Any, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "visibility": "public", + }, + ], +} +`; + +exports[`Pages API Copy Can copy a page 2: [body] 1`] = ` +Object { + "pages": Array [ + Object { + "authors": Any, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": Any, + "count": Object { + "negative_feedback": 0, + "paid_conversions": 0, + "positive_feedback": 0, + "signups": 0, + }, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": null, + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "hide_title_and_feature_image": Any, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "lexical": null, "meta_description": null, @@ -90,7 +183,21 @@ Object { } `; -exports[`Pages API Copy Can copy a page 2: [body] 1`] = ` +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": "3668", + "content-type": "application/json; charset=utf-8", + "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/pages\\\\/\\[a-f0-9\\]\\{24\\}\\\\//, + "vary": "Accept-Version, Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Pages API Update Can modify hide_title_and_feature_image property 1: [body] 1`] = ` Object { "pages": Array [ Object { @@ -114,6 +221,8 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": true, + "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "lexical": null, "meta_description": null, @@ -122,11 +231,11 @@ Object { "og_description": null, "og_image": null, "og_title": null, - "post_revisions": Array [], + "post_revisions": Any, "primary_author": Any, "primary_tag": Any, "published_at": null, - "slug": "test-page-copy-2", + "slug": "test-page", "status": "draft", "tags": Any, "tiers": Array [ @@ -167,7 +276,7 @@ Object { "yearly_price_id": null, }, ], - "title": "Test Page (Copy)", + "title": "Test Page", "twitter_description": null, "twitter_image": null, "twitter_title": null, @@ -180,30 +289,16 @@ Object { } `; -exports[`Pages API Copy Can copy a page 2: [headers] 1`] = ` +exports[`Pages API Update Can modify hide_title_and_feature_image property 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": "3631", + "content-length": "3667", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, - "location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/pages\\\\/\\[a-f0-9\\]\\{24\\}\\\\//, - "vary": "Accept-Version, Origin, Accept-Encoding", - "x-powered-by": "Express", -} -`; - -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": "3633", - "content-type": "application/json; charset=utf-8", - "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, - "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, - "location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/pages\\\\/\\[a-f0-9\\]\\{24\\}\\\\//, "vary": "Accept-Version, Origin, Accept-Encoding", + "x-cache-invalidate": "/p/80038ac3-4ec7-4f4b-8b30-9aacf306ee1e/", "x-powered-by": "Express", } `; diff --git a/ghost/core/test/e2e-api/admin/pages.test.js b/ghost/core/test/e2e-api/admin/pages.test.js index f6e02db320..869516ffb8 100644 --- a/ghost/core/test/e2e-api/admin/pages.test.js +++ b/ghost/core/test/e2e-api/admin/pages.test.js @@ -1,5 +1,5 @@ const {agentProvider, fixtureManager, mockManager, matchers} = require('../../utils/e2e-framework'); -const {anyArray, anyContentVersion, anyEtag, anyLocationFor, anyObject, anyObjectId, anyISODateTime, anyString, anyUuid} = matchers; +const {anyArray, anyBoolean, anyContentVersion, anyEtag, anyLocationFor, anyObject, anyObjectId, anyISODateTime, anyString, anyUuid} = matchers; const tierSnapshot = { id: anyObjectId, @@ -20,7 +20,8 @@ const matchPageShallowIncludes = { created_at: anyISODateTime, updated_at: anyISODateTime, published_at: anyISODateTime, - post_revisions: anyArray + post_revisions: anyArray, + hide_title_and_feature_image: anyBoolean }; describe('Pages API', function () { @@ -36,6 +37,47 @@ describe('Pages API', function () { mockManager.restore(); }); + describe('Update', function () { + it('Can modify hide_title_and_feature_image property', async function () { + const page = { + title: 'Test Page', + status: 'draft' + }; + + const {body: pageBody} = await agent + .post('/pages/?formats=mobiledoc,lexical,html', { + headers: { + 'content-type': 'application/json' + } + }) + .body({pages: [page]}) + .expectStatus(201); + + const [pageResponse] = pageBody.pages; + + await agent + .put(`/pages/${pageResponse.id}/?formats=mobiledoc,lexical,html`) + .body({ + pages: [{ + id: pageResponse.id, + hide_title_and_feature_image: true, + updated_at: pageResponse.updated_at // satisfy collision detection + }] + }) + .expectStatus(200) + .matchBodySnapshot({ + pages: [Object.assign({}, matchPageShallowIncludes, { + published_at: null, + hide_title_and_feature_image: true + })] + }) + .matchHeaderSnapshot({ + 'content-version': anyContentVersion, + etag: anyEtag + }); + }); + }); + describe('Copy', function () { it('Can copy a page', async function () { const page = { @@ -50,7 +92,10 @@ describe('Pages API', function () { } }) .body({pages: [page]}) - .expectStatus(201); + .expectStatus(201) + .matchBodySnapshot({ + pages: [Object.assign({}, matchPageShallowIncludes)] + }); const [pageResponse] = pageBody.pages; @@ -58,7 +103,7 @@ describe('Pages API', function () { .post(`/pages/${pageResponse.id}/copy?formats=mobiledoc,lexical`) .expectStatus(201) .matchBodySnapshot({ - pages: [Object.assign(matchPageShallowIncludes, {published_at: null})] + pages: [Object.assign({}, matchPageShallowIncludes, {published_at: null})] }) .matchHeaderSnapshot({ 'content-version': anyContentVersion, diff --git a/ghost/core/test/e2e-api/admin/utils.js b/ghost/core/test/e2e-api/admin/utils.js index a4c0870c43..8d70d7042d 100644 --- a/ghost/core/test/e2e-api/admin/utils.js +++ b/ghost/core/test/e2e-api/admin/utils.js @@ -131,7 +131,8 @@ const expectedProperties = { 'frontmatter', 'tiers', 'count', - 'post_revisions' + 'post_revisions', + 'hide_title_and_feature_image' ], user: _(schema.users) 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 6929dc5151..7ceb75cdd9 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 @@ -21,6 +21,7 @@ Hopefully you don't find it a bore.", "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": "

Static page test is what this is for.

Hopefully you don't find it a bore.

", "id": "618ba1ffbe2896088840a6e9", "meta_description": null, @@ -48,7 +49,7 @@ exports[`Pages Content API Can request page 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "1083", + "content-length": "1120", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -90,6 +91,7 @@ Tip: If you're reading any post or page on your site and you notice something yo "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": "

Unlike posts, pages in Ghost don't appear in the main feed. They're separate, individual pages which only show up when you link to them. Great for content which is important, but separate from your usual posts.

An about page is a great example of one you might want to set up early on so people can find out more about you, and what you do. Why should people subscribe to your site and become a member? Details help!

Tip: If you're reading any post or page on your site and you notice something you want to edit, you can add /edit to the end of the URL – and you'll be taken directly to the Ghost editor.

Now tell the world what your site is all about.

", "id": "6194d3ce51e2700162531a78", "meta_description": null, @@ -134,6 +136,7 @@ If you prefer to use a contact form, almost all of the great embedded form servi "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": "

If you want to set up a contact page for people to be able to reach out to you, the simplest way is to set up a simple page like this and list the different ways people can reach out to you.

For example, here's how to reach us!

If you prefer to use a contact form, almost all of the great embedded form services work great with Ghost and are easy to set up:

", "id": "6194d3ce51e2700162531a79", "meta_description": null, @@ -174,6 +177,7 @@ Ghost is a non-profit organization, and we give away all our intellectual proper "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": "

Oh hey, you clicked every link of our starter content and even clicked this small link in the footer! If you like Ghost and you're enjoying the product so far, we'd hugely appreciate your support in any way you care to show it.

Ghost is a non-profit organization, and we give away all our intellectual property as open source software. If you believe in what we do, there are a number of ways you can give us a hand, and we hugely appreciate all of them:

  • Contribute code via GitHub
  • Contribute financially via GitHub Sponsors
  • Contribute financially via Open Collective
  • Contribute reviews via writing a blog post
  • Contribute good vibes via telling your friends about us

Thanks for checking us out!

", "id": "6194d3ce51e2700162531a7b", "meta_description": null, @@ -211,6 +215,7 @@ You can integrate any products, services, ads or integrations with Ghost yoursel "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": "

Wondering how Ghost fares when it comes to privacy and GDPR rules? Good news: Ghost does not use any tracking cookies of any kind.

You can integrate any products, services, ads or integrations with Ghost yourself if you want to, but it's always a good idea to disclose how subscriber data will be used by putting together a privacy page.

", "id": "6194d3ce51e2700162531a7a", "meta_description": null, @@ -248,6 +253,7 @@ Hopefully you don't find it a bore.", "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": "

Static page test is what this is for.

Hopefully you don't find it a bore.

", "id": "618ba1ffbe2896088840a6e9", "meta_description": null, @@ -275,7 +281,7 @@ exports[`Pages Content API Can request pages 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "public, max-age=0", - "content-length": "9233", + "content-length": "9418", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, @@ -317,6 +323,7 @@ Tip: If you're reading any post or page on your site and you notice something yo "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "id": "6194d3ce51e2700162531a78", "meta_description": null, "meta_title": null, @@ -360,6 +367,7 @@ If you prefer to use a contact form, almost all of the great embedded form servi "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "id": "6194d3ce51e2700162531a79", "meta_description": null, "meta_title": null, @@ -399,6 +407,7 @@ Ghost is a non-profit organization, and we give away all our intellectual proper "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "id": "6194d3ce51e2700162531a7b", "meta_description": null, "meta_title": null, @@ -435,6 +444,7 @@ You can integrate any products, services, ads or integrations with Ghost yoursel "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "id": "6194d3ce51e2700162531a7a", "meta_description": null, "meta_title": null, @@ -471,6 +481,7 @@ Hopefully you don't find it a bore.", "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "id": "618ba1ffbe2896088840a6e9", "meta_description": null, "meta_title": null, diff --git a/ghost/core/test/e2e-webhooks/__snapshots__/pages.test.js.snap b/ghost/core/test/e2e-webhooks/__snapshots__/pages.test.js.snap index b2e31e13c2..b3679a8c0b 100644 --- a/ghost/core/test/e2e-webhooks/__snapshots__/pages.test.js.snap +++ b/ghost/core/test/e2e-webhooks/__snapshots__/pages.test.js.snap @@ -57,6 +57,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -300,6 +301,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -517,6 +519,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -734,6 +737,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -950,6 +954,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -1166,6 +1171,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -1383,6 +1389,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -1644,6 +1651,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -1845,6 +1853,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, @@ -2061,6 +2070,7 @@ Object { "feature_image_caption": null, "featured": false, "frontmatter": null, + "hide_title_and_feature_image": false, "html": null, "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, "meta_description": null, diff --git a/ghost/posts-service/lib/PostsService.js b/ghost/posts-service/lib/PostsService.js index ad4d1274ee..0870f65299 100644 --- a/ghost/posts-service/lib/PostsService.js +++ b/ghost/posts-service/lib/PostsService.js @@ -556,7 +556,8 @@ class PostsService { 'meta_description', 'frontmatter', 'feature_image_alt', - 'feature_image_caption' + 'feature_image_caption', + 'hide_title_and_feature_image' ] ); } diff --git a/yarn.lock b/yarn.lock index 1cf21768d0..39e4efa143 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6772,10 +6772,10 @@ resolved "https://registry.yarnpkg.com/@tryghost/adapter-base-cache/-/adapter-base-cache-0.1.5.tgz#66021c4e3e92bc623c82728ab50ca497ac41f7ae" integrity sha512-ZAG7Qzn0RioU6yde67T9cneRtoD1ZxGcjwH81DdbL8ZqiPi66bmPw5TVOiEiFnny2XSDsPuUgc4/PxFO/RfV0g== -"@tryghost/admin-api-schema@4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@tryghost/admin-api-schema/-/admin-api-schema-4.4.0.tgz#aa33e7070c3195877df3a9e1284bed03f76ce7a8" - integrity sha512-so4LxkBYMqXqiFd/kJFNwOZ17Drx7uheeJTeUAcje7ZsLFqTYSOpLvpFr+OFnEhA00NiwgJxLyZbpm43kz60Nw== +"@tryghost/admin-api-schema@4.5.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@tryghost/admin-api-schema/-/admin-api-schema-4.5.0.tgz#d4ac7122a3ae1d6468ee1cbfbd234f5474c28d8c" + integrity sha512-Bt+uQsDWUr/uk+E3ifZ7UmcgxJTVgwk+qHetYX1UF+dXGzrVFvflsfpatjJYBMORZ/rqtLvMm8HjPbnA3Fbkzg== dependencies: "@tryghost/errors" "^1.0.0" ajv "^6.12.6"