From 9d4d6688d8c4510729e481fccf218e64d6051a70 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Fri, 13 May 2022 16:23:30 +0100 Subject: [PATCH] Removed links and figcaptions from excerpts refs: https://github.com/TryGhost/Team/issues/1609 refs: https://github.com/TryGhost/Ghost/issues/11532 refs: https://github.com/TryGhost/Ghost/issues/11407 - these don't read correctly in an excert context --- core/shared/html-to-plaintext.js | 31 +++++- .../content/__snapshots__/pages.test.js.snap | 13 +-- .../content/__snapshots__/posts.test.js.snap | 96 +++++++++---------- test/regression/api/content/posts.test.js | 2 +- test/regression/models/model_posts.test.js | 4 +- test/unit/shared/html-to-plaintext.test.js | 22 ++++- 6 files changed, 103 insertions(+), 65 deletions(-) diff --git a/core/shared/html-to-plaintext.js b/core/shared/html-to-plaintext.js index a7784a192e..1ccba54a96 100644 --- a/core/shared/html-to-plaintext.js +++ b/core/shared/html-to-plaintext.js @@ -1,3 +1,13 @@ +const _ = require('lodash'); + +const mergeSettings = (extraSettings) => { + return _.mergeWith({}, baseSettings, extraSettings, function customizer(objValue, srcValue) { + if (_.isArray(objValue)) { + return objValue.concat(srcValue); + } + }); +}; + const baseSettings = { wordwrap: false, preserveNewlines: true, @@ -17,9 +27,6 @@ const baseSettings = { {selector: 'h6', options: {uppercase: false}}, {selector: 'table', options: {uppercaseHeaderCells: false}}, - // equiv hideLinkHrefIfSameAsText: true - {selector: 'a', options: {hideLinkHrefIfSameAsText: true}}, - // Backwards compatibility with html-to-text 5.1.1 {selector: 'div', format: 'inline'} ] @@ -35,8 +42,22 @@ const loadConverters = () => { const {compile} = require('html-to-text'); - excerptConverter = compile(baseSettings); - emailConverter = compile(baseSettings); + const excerptSettings = mergeSettings({ + selectors: [ + {selector: 'a', options: {ignoreHref: true}}, + {selector: 'figcaption', format: 'skip'} + ] + }); + + const emailSettings = mergeSettings({ + selectors: [ + // equiv hideLinkHrefIfSameAsText: true + {selector: 'a', options: {hideLinkHrefIfSameAsText: true}} + ] + }); + + excerptConverter = compile(excerptSettings); + emailConverter = compile(emailSettings); }; module.exports.excerpt = (html) => { diff --git a/test/e2e-api/content/__snapshots__/pages.test.js.snap b/test/e2e-api/content/__snapshots__/pages.test.js.snap index 4a985bc33c..d746b0e834 100644 --- a/test/e2e-api/content/__snapshots__/pages.test.js.snap +++ b/test/e2e-api/content/__snapshots__/pages.test.js.snap @@ -122,11 +122,11 @@ An about page is a great example of one you might want to set up early on so peo For example, here's how to reach us! - * @Ghost [https://twitter.com/ghost] on Twitter - * @Ghost [https://www.facebook.com/ghost] on Facebook - * @Ghost [https://instagram.com/ghost] on Instagram + * @Ghost on Twitter + * @Ghost on Facebook + * @Ghost on Instagram -If you prefer to use a contact form, almost all of the great embedded form services work great with Ghost and a", +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:", "feature_image": null, "feature_image_alt": null, "feature_image_caption": null, @@ -165,7 +165,8 @@ If you prefer to use a contact form, almost all of the great embedded form servi 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 [https://gith", + * Contribute code via GitHub + * Contribute", "feature_image": null, "feature_image_alt": null, "feature_image_caption": null, @@ -273,7 +274,7 @@ exports[`Pages Content API Can request pages 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "9196", + "content-length": "9124", "content-type": "application/json; charset=utf-8", "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "vary": "Accept-Encoding", diff --git a/test/e2e-api/content/__snapshots__/posts.test.js.snap b/test/e2e-api/content/__snapshots__/posts.test.js.snap index 2431c5015b..7ce27121e7 100644 --- a/test/e2e-api/content/__snapshots__/posts.test.js.snap +++ b/test/e2e-api/content/__snapshots__/posts.test.js.snap @@ -260,9 +260,9 @@ Object { "custom_template": null, "email_subject": null, "excerpt": " * Lorem - * Aliquam [http://127.0.0.1:2369/about#nowhere] - * Tortor [//somewhere.com/link#nowhere] - * Morbi [http://somewhere.com/link#nowhere] + * Aliquam + * Tortor + * Morbi * Praesent * Pellentesque @@ -270,7 +270,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu 1234abcdefghijkl -Definition listConsectetur ad", +Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia", "feature_image": null, "feature_image_alt": null, "feature_image_caption": null, @@ -619,9 +619,11 @@ Definition listConsectetur ad", "email_subject": null, "excerpt": "For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business. -Connect your Stripe [https://stripe.com] account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. +Connect your Stripe account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. -Ghost takes 0% payment fees, so everything you make is yours to ", +Ghost takes 0% payment fees, so everything you make is yours to keep! + +Using subscrip", "feature_image": "https://static.ghost.org/v4.0.0/images/organizing-your-content.png", "feature_image_alt": null, "feature_image_caption": null, @@ -636,16 +638,14 @@ Ghost takes 0% payment fees, so everything you make is yours to ", "og_title": null, "plaintext": "For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business. -Connect your Stripe [https://stripe.com] account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. +Connect your Stripe account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. Ghost takes 0% payment fees, so everything you make is yours to keep! -Using subscriptions, you can build an independent media business like Stratechery [https://stratechery.com], The Information [https://www.theinformation.com], or The Browser [https://thebrowser.com]. +Using subscriptions, you can build an independent media business like Stratechery, The Information, or The Browser. The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control. -https://thebrowser.comThe Browser has over 10,000 paying subscribers - 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...", "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", @@ -1036,7 +1036,7 @@ exports[`Posts Content API Can filter posts by authors 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "54894", + "content-length": "54719", "content-type": "application/json; charset=utf-8", "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "vary": "Accept-Encoding", @@ -1068,9 +1068,9 @@ Object { "custom_template": null, "email_subject": null, "excerpt": " * Lorem - * Aliquam [http://127.0.0.1:2369/about#nowhere] - * Tortor [//somewhere.com/link#nowhere] - * Morbi [http://somewhere.com/link#nowhere] + * Aliquam + * Tortor + * Morbi * Praesent * Pellentesque @@ -1078,7 +1078,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu 1234abcdefghijkl -Definition listConsectetur ad", +Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia", "feature_image": null, "feature_image_alt": null, "feature_image_caption": null, @@ -1748,9 +1748,11 @@ Object { "email_subject": null, "excerpt": "For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business. -Connect your Stripe [https://stripe.com] account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. +Connect your Stripe account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. -Ghost takes 0% payment fees, so everything you make is yours to ", +Ghost takes 0% payment fees, so everything you make is yours to keep! + +Using subscrip", "feature_image": "https://static.ghost.org/v4.0.0/images/organizing-your-content.png", "feature_image_alt": null, "feature_image_caption": null, @@ -1765,16 +1767,14 @@ Ghost takes 0% payment fees, so everything you make is yours to ", "og_title": null, "plaintext": "For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business. -Connect your Stripe [https://stripe.com] account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. +Connect your Stripe account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. Ghost takes 0% payment fees, so everything you make is yours to keep! -Using subscriptions, you can build an independent media business like Stratechery [https://stratechery.com], The Information [https://www.theinformation.com], or The Browser [https://thebrowser.com]. +Using subscriptions, you can build an independent media business like Stratechery, The Information, or The Browser. The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control. -https://thebrowser.comThe Browser has over 10,000 paying subscribers - 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...", "primary_author": Object { "bio": "You can delete this user to remove all the welcome posts", @@ -1984,9 +1984,9 @@ Most successful subscription businesses publish a mix of free and paid posts to "custom_template": null, "email_subject": null, "excerpt": " * Lorem - * Aliquam [http://127.0.0.1:2369/about#nowhere] - * Tortor [//somewhere.com/link#nowhere] - * Morbi [http://somewhere.com/link#nowhere] + * Aliquam + * Tortor + * Morbi * Praesent * Pellentesque @@ -1994,7 +1994,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu 1234abcdefghijkl -Definition listConsectetur ad", +Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia", "feature_image": null, "feature_image_alt": null, "feature_image_caption": null, @@ -2281,7 +2281,7 @@ exports[`Posts Content API Can include relations 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "65223", + "content-length": "65048", "content-type": "application/json; charset=utf-8", "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "vary": "Accept-Encoding", @@ -2582,9 +2582,11 @@ Object { "email_subject": null, "excerpt": "For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business. -Connect your Stripe [https://stripe.com] account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. +Connect your Stripe account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. -Ghost takes 0% payment fees, so everything you make is yours to ", +Ghost takes 0% payment fees, so everything you make is yours to keep! + +Using subscrip", "feature_image": "https://static.ghost.org/v4.0.0/images/organizing-your-content.png", "feature_image_alt": null, "feature_image_caption": null, @@ -2599,16 +2601,14 @@ Ghost takes 0% payment fees, so everything you make is yours to ", "og_title": null, "plaintext": "For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business. -Connect your Stripe [https://stripe.com] account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. +Connect your Stripe account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. Ghost takes 0% payment fees, so everything you make is yours to keep! -Using subscriptions, you can build an independent media business like Stratechery [https://stratechery.com], The Information [https://www.theinformation.com], or The Browser [https://thebrowser.com]. +Using subscriptions, you can build an independent media business like Stratechery, The Information, or The Browser. The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control. -https://thebrowser.comThe Browser has over 10,000 paying subscribers - 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...", "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, @@ -2704,9 +2704,9 @@ Most successful subscription businesses publish a mix of free and paid posts to "custom_template": null, "email_subject": null, "excerpt": " * Lorem - * Aliquam [http://127.0.0.1:2369/about#nowhere] - * Tortor [//somewhere.com/link#nowhere] - * Morbi [http://somewhere.com/link#nowhere] + * Aliquam + * Tortor + * Morbi * Praesent * Pellentesque @@ -2714,7 +2714,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu 1234abcdefghijkl -Definition listConsectetur ad", +Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia", "feature_image": null, "feature_image_alt": null, "feature_image_caption": null, @@ -2870,7 +2870,7 @@ exports[`Posts Content API Can request posts 2: [headers] 1`] = ` Object { "access-control-allow-origin": "*", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "46342", + "content-length": "46167", "content-type": "application/json; charset=utf-8", "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "vary": "Accept-Encoding", @@ -3055,9 +3055,11 @@ Object { "email_subject": null, "excerpt": "For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business. -Connect your Stripe [https://stripe.com] account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. +Connect your Stripe account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. -Ghost takes 0% payment fees, so everything you make is yours to ", +Ghost takes 0% payment fees, so everything you make is yours to keep! + +Using subscrip", "feature_image": "https://static.ghost.org/v4.0.0/images/organizing-your-content.png", "feature_image_alt": null, "feature_image_caption": null, @@ -3072,16 +3074,14 @@ Ghost takes 0% payment fees, so everything you make is yours to ", "og_title": null, "plaintext": "For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business. -Connect your Stripe [https://stripe.com] account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. +Connect your Stripe account to Ghost, and you'll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family. Ghost takes 0% payment fees, so everything you make is yours to keep! -Using subscriptions, you can build an independent media business like Stratechery [https://stratechery.com], The Information [https://www.theinformation.com], or The Browser [https://thebrowser.com]. +Using subscriptions, you can build an independent media business like Stratechery, The Information, or The Browser. The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control. -https://thebrowser.comThe Browser has over 10,000 paying subscribers - 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...", "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, "reading_time": 1, @@ -3177,9 +3177,9 @@ Most successful subscription businesses publish a mix of free and paid posts to "custom_template": null, "email_subject": null, "excerpt": " * Lorem - * Aliquam [http://127.0.0.1:2369/about#nowhere] - * Tortor [//somewhere.com/link#nowhere] - * Morbi [http://somewhere.com/link#nowhere] + * Aliquam + * Tortor + * Morbi * Praesent * Pellentesque @@ -3187,7 +3187,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu 1234abcdefghijkl -Definition listConsectetur ad", +Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia", "feature_image": null, "feature_image_alt": null, "feature_image_caption": null, @@ -3343,7 +3343,7 @@ exports[`Posts Content API Can request posts from different origin 2: [headers] Object { "access-control-allow-origin": "*", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "46342", + "content-length": "46167", "content-type": "application/json; charset=utf-8", "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "vary": "Accept-Encoding", diff --git a/test/regression/api/content/posts.test.js b/test/regression/api/content/posts.test.js index bf2cf41abe..faa59442f7 100644 --- a/test/regression/api/content/posts.test.js +++ b/test/regression/api/content/posts.test.js @@ -249,7 +249,7 @@ describe('api/canary/content/posts', function () { localUtils.API.checkResponse(res.body.posts[0], 'post', null, null, ['id', 'title', 'slug', 'excerpt', 'plaintext']); // excerpt should transform links to absolute URLs - res.body.posts[0].excerpt.should.match(/\* Aliquam \[http:\/\/127.0.0.1:2369\/about#nowhere\]/); + res.body.posts[0].excerpt.should.match(/\* Aliquam/); }); }); diff --git a/test/regression/models/model_posts.test.js b/test/regression/models/model_posts.test.js index 62363bc08d..ede8837df0 100644 --- a/test/regression/models/model_posts.test.js +++ b/test/regression/models/model_posts.test.js @@ -1146,7 +1146,7 @@ describe('Post Model', function () { models.Post.add(post, context).then((createdPost) => { createdPost.get('mobiledoc').should.equal('{"version":"0.3.1","atoms":[],"cards":[["image",{"src":"http://127.0.0.1:2369/content/images/card.jpg"}]],"markups":[["a",["href","http://127.0.0.1:2369/test"]]],"sections":[[1,"p",[[0,[0],1,"Testing"]]],[10,0]]}'); createdPost.get('html').should.equal('

Testing

'); - createdPost.get('plaintext').should.containEql('Testing [http://127.0.0.1:2369/test]'); + createdPost.get('plaintext').should.containEql('Testing'); createdPost.get('custom_excerpt').should.equal('Testing links in custom excerpts'); createdPost.get('codeinjection_head').should.equal(''); createdPost.get('codeinjection_foot').should.equal(''); @@ -1175,7 +1175,7 @@ describe('Post Model', function () { const [knexPost] = knexResult; knexPost.mobiledoc.should.equal('{"version":"0.3.1","atoms":[],"cards":[["image",{"src":"__GHOST_URL__/content/images/card.jpg"}]],"markups":[["a",["href","__GHOST_URL__/test"]]],"sections":[[1,"p",[[0,[0],1,"Testing"]]],[10,0]]}'); knexPost.html.should.equal('

Testing

'); - knexPost.plaintext.should.containEql('Testing [__GHOST_URL__/test]'); + knexPost.plaintext.should.containEql('Testing'); knexPost.custom_excerpt.should.equal('Testing links in custom excerpts'); knexPost.codeinjection_head.should.equal(''); knexPost.codeinjection_foot.should.equal(''); diff --git a/test/unit/shared/html-to-plaintext.test.js b/test/unit/shared/html-to-plaintext.test.js index aa2fda694e..c8e06c0006 100644 --- a/test/unit/shared/html-to-plaintext.test.js +++ b/test/unit/shared/html-to-plaintext.test.js @@ -15,7 +15,7 @@ describe('Html to Plaintext', function () { const {excerpt, email} = getEmailandExcert(input); - assert.equal(excerpt, 'Some thing Google [https://google.com] once told me.\n\nAnd another thing.'); + assert.equal(excerpt, 'Some thing Google once told me.\n\nAnd another thing.'); assert.equal(email, 'Some thing Google [https://google.com] once told me.\n\nAnd another thing.'); }); @@ -24,7 +24,7 @@ describe('Html to Plaintext', function () { const {excerpt, email} = getEmailandExcert(input); - assert.equal(excerpt, 'A snippet from a post template\n\nSee? Not that scary! But still completely optional.'); + assert.equal(excerpt, 'See? Not that scary! But still completely optional.'); assert.equal(email, 'A snippet from a post template\n\nSee? Not that scary! But still completely optional.'); }); @@ -33,8 +33,24 @@ describe('Html to Plaintext', function () { const {excerpt, email} = getEmailandExcert(input); - assert.equal(excerpt, 'A snippet from a post template [https://mysite.com]\n\nSee? Not that scary! But still completely optional.'); + assert.equal(excerpt, 'See? Not that scary! But still completely optional.'); assert.equal(email, 'A snippet from a post template [https://mysite.com]\n\nSee? Not that scary! But still completely optional.'); }); + + it('longer example', function () { + const input = '

As discussed in the introduction post, one of the best things about Ghost is just how much you can customize to turn your site into something unique. Everything about your layout and design can be changed, so you\'re not stuck with yet another clone of a social network profile.

How far you want to go with customization is completely up to you, there\'s no right or wrong approach! The majority of people use one of Ghost\'s built-in themes to get started, and then progress to something more bespoke later on as their site grows.

The best way to get started is with Ghost\'s branding settings, where you can set up colors, images and logos to fit with your brand.

Ghost Admin → Settings → Branding

Any Ghost theme that\'s up to date and compatible with Ghost 4.0 and higher will reflect your branding settings in the preview window, so you can see what your site will look like as you experiment with different options.

When selecting an accent color, try to choose something which will contrast well with white text. Many themes will use your accent color as the background for buttons, headers and navigational elements. Vibrant colors with a darker hue tend to work best, as a general rule.

Installing Ghost themes

By default, new sites are created with Ghost\'s friendly publication theme, called Casper. Everything in Casper is optimized to work for the most common types of blog, newsletter and publication that people create with Ghost — so it\'s a perfect place to start.

However, there are hundreds of different themes available to install, so you can pick out a look and feel that suits you best.

Ghost Admin → Settings → Theme

Inside Ghost\'s theme settings you\'ll find 4 more official themes that can be directly installed and activated. Each theme is suited to slightly different use-cases.

And if none of those feel quite right, head on over to the Ghost Marketplace, where you\'ll find a huge variety of both free and premium themes.

Building something custom

Finally, if you want something completely bespoke for your site, you can always build a custom theme from scratch and upload it to your site.

Ghost\'s theming template files are very easy to work with, and can be picked up in the space of a few hours by anyone who has just a little bit of knowledge of HTML and CSS. Templates from other platforms can also be ported to Ghost with relatively little effort.

If you want to take a quick look at the theme syntax to see what it\'s like, you can browse through the files of the default Casper theme. We\'ve added tons of inline code comments to make it easy to learn, and the structure is very readable.

{{#post}}\n<article class="article {{post_class}}">\n\n <h1>{{title}}</h1>\n \n {{#if feature_image}}\n \t<img src="{{feature_image}}" alt="Feature image" />\n {{/if}}\n \n {{content}}\n\n</article>\n{{/post}}
A snippet from a post template

See? Not that scary! But still completely optional.

If you\'re interested in creating your own Ghost theme, check out our extensive theme documentation for a full guide to all the different template variables and helpers which are available.

'; + + const {excerpt, email} = getEmailandExcert(input); + + // No link + assert.doesNotMatch(excerpt, /https:\/\/demo\.ghost\.io\/welcome/); + // No figcaption + assert.doesNotMatch(excerpt, /Ghost Admin → Settings → Theme/); + + // contains link + assert.match(email, /https:\/\/demo\.ghost\.io\/welcome/); + // contains figcaption + assert.match(email, /Ghost Admin → Settings → Theme/); + }); }); });