mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-24 19:33:02 +03:00
Added {{readable_url}} helper (#18564)
refs https://github.com/TryGhost/Product/issues/4021 - used in the recommendations template to display urls in a short readable way, e.g. google.com instead of https://www.google.com?query=1#section
This commit is contained in:
parent
0ffe4dd144
commit
3cc60bc7ea
@ -54,7 +54,7 @@ module.exports = function imgUrl(requestedImageUrl, options) {
|
||||
// ignore errors and just return the original URL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return requestedImageUrl;
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ function getUnsplashImage(imagePath, sizeOptions) {
|
||||
const parsedUrl = new URL(imagePath);
|
||||
const {requestedSize, imageSizes, requestedFormat} = sizeOptions;
|
||||
|
||||
if (requestedFormat) {
|
||||
if (requestedFormat) {
|
||||
const supportedFormats = ['avif', 'gif', 'jpg', 'png', 'webp'];
|
||||
if (supportedFormats.includes(requestedFormat)) {
|
||||
parsedUrl.searchParams.set('fm', requestedFormat);
|
||||
@ -150,13 +150,13 @@ function getUnsplashImage(imagePath, sizeOptions) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} imagePath
|
||||
* @param {Object} sizeOptions
|
||||
*
|
||||
* @param {string} imagePath
|
||||
* @param {Object} sizeOptions
|
||||
* @param {string} sizeOptions.requestedSize
|
||||
* @param {Object[]} sizeOptions.imageSizes
|
||||
* @param {string} [sizeOptions.requestedFormat]
|
||||
* @returns
|
||||
* @returns
|
||||
*/
|
||||
function getImageWithSize(imagePath, sizeOptions) {
|
||||
const hasLeadingSlash = imagePath[0] === '/';
|
||||
|
32
ghost/core/core/frontend/helpers/readable_url.js
Normal file
32
ghost/core/core/frontend/helpers/readable_url.js
Normal file
@ -0,0 +1,32 @@
|
||||
// # Readable URL helper
|
||||
// Usage: `{{readable_url "https://google.com"}}`
|
||||
//
|
||||
// Returns a human readable URL for the given URL, e.g. google.com for https://www.google.com?query=1#section
|
||||
|
||||
const logging = require('@tryghost/logging');
|
||||
const sentry = require('../../shared/sentry');
|
||||
const errors = require('@tryghost/errors');
|
||||
const {SafeString} = require('../services/handlebars');
|
||||
|
||||
function captureError(message) {
|
||||
const error = new errors.IncorrectUsageError({message});
|
||||
sentry.captureException(error);
|
||||
logging.error(error);
|
||||
}
|
||||
|
||||
module.exports = function readableUrl(inputUrl) {
|
||||
if (!inputUrl || typeof inputUrl !== 'string') {
|
||||
captureError(`Expected a string, received ${inputUrl}.`);
|
||||
return new SafeString('');
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(inputUrl);
|
||||
const readable = url.hostname.replace(/^www\./, '') + url.pathname.replace(/\/$/, '');
|
||||
|
||||
return new SafeString(readable);
|
||||
} catch (e) {
|
||||
captureError(`The string "${inputUrl}" could not be parsed as URL.`);
|
||||
return new SafeString(inputUrl);
|
||||
}
|
||||
};
|
@ -4,6 +4,7 @@
|
||||
<li class="recommendation">
|
||||
<a href="{{rec.url}}" data-recommendation="{{rec.id}}" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="{{rec.favicon}}" alt="{{rec.title}}">
|
||||
<span class="recommendation-url">{{readable_url rec.url}}</span>
|
||||
<h5 class="recommendation-title">{{rec.title}}</h5>
|
||||
<p class="recommendation-description">{{rec.description}}</p>
|
||||
</a>
|
||||
|
31
ghost/core/test/unit/frontend/helpers/readable_url.test.js
Normal file
31
ghost/core/test/unit/frontend/helpers/readable_url.test.js
Normal file
@ -0,0 +1,31 @@
|
||||
const should = require('should');
|
||||
const readable_url = require('../../../../core/frontend/helpers/readable_url');
|
||||
|
||||
describe('{{#readable_url}} helper', function () {
|
||||
it('renders a short URL, without protocol, www, query params nor hash fragments', function () {
|
||||
const readable = readable_url.call(
|
||||
{},
|
||||
'https://www.foobar.com/some/path/?query=param#hash/'
|
||||
);
|
||||
|
||||
readable.string.should.equal('foobar.com/some/path');
|
||||
});
|
||||
|
||||
it('renders an empty string when the input is not a string', function () {
|
||||
const readable = readable_url.call(
|
||||
{},
|
||||
{foo: 'bar'}
|
||||
);
|
||||
|
||||
readable.string.should.equal('');
|
||||
});
|
||||
|
||||
it('returns the input string if not parsable as URL', function () {
|
||||
const readable = readable_url.call(
|
||||
{},
|
||||
'hello world'
|
||||
);
|
||||
|
||||
readable.string.should.equal('hello world');
|
||||
});
|
||||
});
|
@ -10,6 +10,7 @@ const proxy = require('../../../../core/frontend/services/proxy');
|
||||
|
||||
const recommendations = require('../../../../core/frontend/helpers/recommendations');
|
||||
const foreach = require('../../../../core/frontend/helpers/foreach');
|
||||
const readable_url = require('../../../../core/frontend/helpers/readable_url');
|
||||
const {settingsCache} = proxy;
|
||||
|
||||
function trimSpaces(string) {
|
||||
@ -30,6 +31,7 @@ describe('{{#recommendations}} helper', function () {
|
||||
|
||||
// The recommendation template expects this helper
|
||||
hbs.registerHelper('foreach', foreach);
|
||||
hbs.registerHelper('readable_url', readable_url);
|
||||
|
||||
// Stub settings cache
|
||||
sinon.stub(settingsCache, 'get');
|
||||
@ -42,10 +44,7 @@ describe('{{#recommendations}} helper', function () {
|
||||
return {
|
||||
browse: sinon.stub().resolves({recommendations: [
|
||||
{id: '1', title: 'Recommendation 1', url: 'https://recommendations1.com', favicon: 'https://recommendations1.com/favicon.ico', description: 'Description 1'},
|
||||
{id: '2', title: 'Recommendation 2', url: 'https://recommendations2.com', favicon: 'https://recommendations2.com/favicon.ico', description: 'Description 2'},
|
||||
{id: '3', title: 'Recommendation 3', url: 'https://recommendations3.com', favicon: 'https://recommendations3.com/favicon.ico', description: 'Description 3'},
|
||||
{id: '4', title: 'Recommendation 4', url: 'https://recommendations4.com', favicon: 'https://recommendations4.com/favicon.ico', description: 'Description 4'},
|
||||
{id: '5', title: 'Recommendation 5', url: 'https://recommendations5.com', favicon: 'https://recommendations5.com/favicon.ico', description: 'Description 5'}
|
||||
{id: '2', title: 'Recommendation 2', url: 'https://recommendations2.com', favicon: 'https://recommendations2.com/favicon.ico', description: 'Description 2'}
|
||||
], meta: meta})
|
||||
};
|
||||
});
|
||||
@ -73,6 +72,7 @@ describe('{{#recommendations}} helper', function () {
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations1.com" data-recommendation="1" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations1.com/favicon.ico" alt="Recommendation 1">
|
||||
<span class="recommendation-url">recommendations1.com</span>
|
||||
<h5 class="recommendation-title">Recommendation 1</h5>
|
||||
<p class="recommendation-description">Description 1</p>
|
||||
</a>
|
||||
@ -80,31 +80,11 @@ describe('{{#recommendations}} helper', function () {
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations2.com" data-recommendation="2" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations2.com/favicon.ico" alt="Recommendation 2">
|
||||
<span class="recommendation-url">recommendations2.com</span>
|
||||
<h5 class="recommendation-title">Recommendation 2</h5>
|
||||
<p class="recommendation-description">Description 2</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations3.com" data-recommendation="3" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations3.com/favicon.ico" alt="Recommendation 3">
|
||||
<h5 class="recommendation-title">Recommendation 3</h5>
|
||||
<p class="recommendation-description">Description 3</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations4.com" data-recommendation="4" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations4.com/favicon.ico" alt="Recommendation 4">
|
||||
<h5 class="recommendation-title">Recommendation 4</h5>
|
||||
<p class="recommendation-description">Description 4</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations5.com" data-recommendation="5" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations5.com/favicon.ico" alt="Recommendation 5">
|
||||
<h5 class="recommendation-title">Recommendation 5</h5>
|
||||
<p class="recommendation-description">Description 5</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
`);
|
||||
const actual = trimSpaces(response.string);
|
||||
|
@ -11,7 +11,7 @@ describe('Helpers', function () {
|
||||
'asset', 'authors', 'body_class', 'cancel_link', 'concat', 'content', 'date', 'encode', 'excerpt', 'facebook_url', 'foreach', 'get',
|
||||
'ghost_foot', 'ghost_head', 'has', 'img_url', 'is', 'link', 'link_class', 'meta_description', 'meta_title', 'navigation',
|
||||
'next_post', 'page_url', 'pagination', 'plural', 'post_class', 'prev_post', 'price', 'raw', 'reading_time', 't', 'tags', 'title','total_members', 'total_paid_members', 'twitter_url',
|
||||
'url', 'comment_count', 'collection', 'recommendations'
|
||||
'url', 'comment_count', 'collection', 'recommendations', 'readable_url'
|
||||
];
|
||||
const experimentalHelpers = ['match', 'tiers', 'comments', 'search'];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user