From c3dbd0e56b3632f47ccd777403566343685feb60 Mon Sep 17 00:00:00 2001 From: Aileen Nowak Date: Mon, 19 Jun 2017 21:11:53 +0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20=20Remove=20trailing=20slash=20f?= =?UTF-8?q?or=20`{{@blog.url}}`=20(#8596)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #8569 - remove the trailing slash for `{{@blog.url}}` data in theme middleware --- core/server/themes/middleware.js | 3 ++- core/server/utils/url.js | 6 ++++++ core/test/functional/routes/frontend_spec.js | 4 ++-- core/test/unit/themes/middleware_spec.js | 6 +++--- core/test/unit/utils/url_spec.js | 21 ++++++++++++++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/core/server/themes/middleware.js b/core/server/themes/middleware.js index 9257691074..6bd7fdc862 100644 --- a/core/server/themes/middleware.js +++ b/core/server/themes/middleware.js @@ -68,7 +68,8 @@ themeMiddleware.updateTemplateData = function updateTemplateData(req, res, next) // Request-specific information // These things are super dependent on the request, so they need to be in middleware - blogData.url = utils.url.urlFor('home', {secure: req.secure}, true); + // Serve the blog url without trailing slash + blogData.url = utils.url.urlFor('home', {secure: req.secure, trailingSlash: false}, true); // Pass 'secure' flag to the view engine // so that templates can choose to render https or http 'url', see url utility diff --git a/core/server/utils/url.js b/core/server/utils/url.js index 7b28c08a26..2022205d98 100644 --- a/core/server/utils/url.js +++ b/core/server/utils/url.js @@ -297,6 +297,12 @@ function urlFor(context, data, absolute) { if (data && data.cors) { urlPath = urlPath.replace(/^.*?:\/\//g, '//'); } + + // CASE: there are cases where urlFor('home') needs to be returned without trailing + // slash e. g. the `{{@blog.url}}` helper. See https://github.com/TryGhost/Ghost/issues/8569 + if (data && data.trailingSlash === false) { + urlPath = urlPath.replace(/\/$/, ''); + } } else if (context === 'admin') { urlPath = getAdminUrl() || getBlogUrl(); diff --git a/core/test/functional/routes/frontend_spec.js b/core/test/functional/routes/frontend_spec.js index c9af3be79a..89b9a07dcb 100644 --- a/core/test/functional/routes/frontend_spec.js +++ b/core/test/functional/routes/frontend_spec.js @@ -729,7 +729,7 @@ describe('Frontend Routing', function () { request.get('/') .expect(200) .expect(//) - .expect(/Ghost<\/a\>/) + .expect(/Ghost<\/a\>/) .end(doEnd(done)); }); @@ -738,7 +738,7 @@ describe('Frontend Routing', function () { .set('X-Forwarded-Proto', 'https') .expect(200) .expect(//) - .expect(/Ghost<\/a\>/) + .expect(/Ghost<\/a\>/) .end(doEnd(done)); }); }); diff --git a/core/test/unit/themes/middleware_spec.js b/core/test/unit/themes/middleware_spec.js index d095cec722..9ac12ff131 100644 --- a/core/test/unit/themes/middleware_spec.js +++ b/core/test/unit/themes/middleware_spec.js @@ -136,7 +136,7 @@ describe('Themes', function () { .with.properties(blogDataExpectedProps) .and.size(blogDataExpectedProps.length); // url should be correct - templateOptions.data.blog.url.should.eql('http://127.0.0.1:2369/'); + templateOptions.data.blog.url.should.eql('http://127.0.0.1:2369'); // should get the title templateOptions.data.blog.title.should.eql('Bloggy McBlogface'); @@ -173,7 +173,7 @@ describe('Themes', function () { .with.properties(blogDataExpectedProps) .and.size(blogDataExpectedProps.length); // url should be correct - templateOptions.data.blog.url.should.eql('http://127.0.0.1:2369/'); + templateOptions.data.blog.url.should.eql('http://127.0.0.1:2369'); // should get the title templateOptions.data.blog.title.should.eql('Bloggy McBlogface'); @@ -209,7 +209,7 @@ describe('Themes', function () { .with.properties(blogDataExpectedProps) .and.size(blogDataExpectedProps.length); // url should be correct HTTPS! - templateOptions.data.blog.url.should.eql('https://127.0.0.1:2369/'); + templateOptions.data.blog.url.should.eql('https://127.0.0.1:2369'); // should get the title templateOptions.data.blog.title.should.eql('Bloggy McBlogface'); diff --git a/core/test/unit/utils/url_spec.js b/core/test/unit/utils/url_spec.js index d700331fb5..d7dd209ba2 100644 --- a/core/test/unit/utils/url_spec.js +++ b/core/test/unit/utils/url_spec.js @@ -124,6 +124,27 @@ describe('Url', function () { utils.url.urlFor(testContext).should.equal('/blog/'); utils.url.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/'); utils.url.urlFor(testContext, {secure: true}, true).should.equal('https://my-ghost-blog.com/blog/'); + + // Output blog url without trailing slash + configUtils.set({url: 'http://my-ghost-blog.com'}); + utils.url.urlFor(testContext).should.equal('/'); + utils.url.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/'); + utils.url.urlFor(testContext, {secure: true, trailingSlash: false}, true).should.equal('https://my-ghost-blog.com'); + + configUtils.set({url: 'http://my-ghost-blog.com/'}); + utils.url.urlFor(testContext).should.equal('/'); + utils.url.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/'); + utils.url.urlFor(testContext, {secure: true, trailingSlash: false}, true).should.equal('https://my-ghost-blog.com'); + + configUtils.set({url: 'http://my-ghost-blog.com/blog'}); + utils.url.urlFor(testContext).should.equal('/blog/'); + utils.url.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/'); + utils.url.urlFor(testContext, {secure: true, trailingSlash: false}, true).should.equal('https://my-ghost-blog.com/blog'); + + configUtils.set({url: 'http://my-ghost-blog.com/blog/'}); + utils.url.urlFor(testContext).should.equal('/blog/'); + utils.url.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/'); + utils.url.urlFor(testContext, {secure: true, trailingSlash: false}, true).should.equal('https://my-ghost-blog.com/blog'); }); it('should return rss url when asked for', function () {