mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
🎨 Util to convert relative urls in absolute (#7264)
no issue This PR takes the existing function `processUrls` in `data/xml/rss` and refactors it to be a stand-alone util. The change is needed, as this functionality will be accessed from `apps/amp` to convert relative URLs.
This commit is contained in:
parent
5739411c51
commit
f7129a0e39
3 changed files with 105 additions and 52 deletions
|
@ -1,15 +1,14 @@
|
||||||
var _ = require('lodash'),
|
var _ = require('lodash'),
|
||||||
cheerio = require('cheerio'),
|
crypto = require('crypto'),
|
||||||
crypto = require('crypto'),
|
downsize = require('downsize'),
|
||||||
downsize = require('downsize'),
|
RSS = require('rss'),
|
||||||
RSS = require('rss'),
|
config = require('../../../config'),
|
||||||
url = require('url'),
|
errors = require('../../../errors'),
|
||||||
config = require('../../../config'),
|
filters = require('../../../filters'),
|
||||||
errors = require('../../../errors'),
|
processUrls = require('../../../utils/make-absolute-urls'),
|
||||||
filters = require('../../../filters'),
|
|
||||||
|
|
||||||
// Really ugly temporary hack for location of things
|
// Really ugly temporary hack for location of things
|
||||||
fetchData = require('../../../controllers/frontend/fetch-data'),
|
fetchData = require('../../../controllers/frontend/fetch-data'),
|
||||||
|
|
||||||
generate,
|
generate,
|
||||||
generateFeed,
|
generateFeed,
|
||||||
|
@ -65,48 +64,6 @@ function getBaseUrl(req, slugParam) {
|
||||||
return baseUrl;
|
return baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
function processUrls(html, siteUrl, itemUrl) {
|
|
||||||
var htmlContent = cheerio.load(html, {decodeEntities: false});
|
|
||||||
// convert relative resource urls to absolute
|
|
||||||
['href', 'src'].forEach(function forEach(attributeName) {
|
|
||||||
htmlContent('[' + attributeName + ']').each(function each(ix, el) {
|
|
||||||
var baseUrl,
|
|
||||||
attributeValue,
|
|
||||||
parsed;
|
|
||||||
|
|
||||||
el = htmlContent(el);
|
|
||||||
|
|
||||||
attributeValue = el.attr(attributeName);
|
|
||||||
|
|
||||||
// if URL is absolute move on to the next element
|
|
||||||
try {
|
|
||||||
parsed = url.parse(attributeValue);
|
|
||||||
|
|
||||||
if (parsed.protocol) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not convert protocol relative URLs
|
|
||||||
if (attributeValue.lastIndexOf('//', 0) === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compose an absolute URL
|
|
||||||
|
|
||||||
// if the relative URL begins with a '/' use the blog URL (including sub-directory)
|
|
||||||
// as the base URL, otherwise use the post's URL.
|
|
||||||
baseUrl = attributeValue[0] === '/' ? siteUrl : itemUrl;
|
|
||||||
attributeValue = config.urlJoin(baseUrl, attributeValue);
|
|
||||||
el.attr(attributeName, attributeValue);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return htmlContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
getFeedXml = function getFeedXml(path, data) {
|
getFeedXml = function getFeedXml(path, data) {
|
||||||
var dataHash = crypto.createHash('md5').update(JSON.stringify(data)).digest('hex');
|
var dataHash = crypto.createHash('md5').update(JSON.stringify(data)).digest('hex');
|
||||||
if (!feedCache[path] || feedCache[path].hash !== dataHash) {
|
if (!feedCache[path] || feedCache[path].hash !== dataHash) {
|
||||||
|
|
57
core/server/utils/make-absolute-urls.js
Normal file
57
core/server/utils/make-absolute-urls.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
var cheerio = require('cheerio'),
|
||||||
|
url = require('url'),
|
||||||
|
config = require('../config');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make absolute URLs
|
||||||
|
* @param {string} html
|
||||||
|
* @param {string} siteUrl (blog URL)
|
||||||
|
* @param {string} itemUrl (URL of current context)
|
||||||
|
* @returns {object} htmlContent
|
||||||
|
* @description Takes html, blog url and item url and converts relative url into
|
||||||
|
* absolute urls. Returns an object. The html string can be accessed by calling `html()` on
|
||||||
|
* the variable that takes the result of this function
|
||||||
|
*/
|
||||||
|
function makeAbsoluteUrls(html, siteUrl, itemUrl) {
|
||||||
|
var htmlContent = cheerio.load(html, {decodeEntities: false});
|
||||||
|
// convert relative resource urls to absolute
|
||||||
|
['href', 'src'].forEach(function forEach(attributeName) {
|
||||||
|
htmlContent('[' + attributeName + ']').each(function each(ix, el) {
|
||||||
|
var baseUrl,
|
||||||
|
attributeValue,
|
||||||
|
parsed;
|
||||||
|
|
||||||
|
el = htmlContent(el);
|
||||||
|
|
||||||
|
attributeValue = el.attr(attributeName);
|
||||||
|
|
||||||
|
// if URL is absolute move on to the next element
|
||||||
|
try {
|
||||||
|
parsed = url.parse(attributeValue);
|
||||||
|
|
||||||
|
if (parsed.protocol) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not convert protocol relative URLs
|
||||||
|
if (attributeValue.lastIndexOf('//', 0) === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compose an absolute URL
|
||||||
|
|
||||||
|
// if the relative URL begins with a '/' use the blog URL (including sub-directory)
|
||||||
|
// as the base URL, otherwise use the post's URL.
|
||||||
|
baseUrl = attributeValue[0] === '/' ? siteUrl : itemUrl;
|
||||||
|
attributeValue = config.urlJoin(baseUrl, attributeValue);
|
||||||
|
el.attr(attributeName, attributeValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return htmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = makeAbsoluteUrls;
|
39
core/test/unit/utils/make-absolute-urls_spec.js
Normal file
39
core/test/unit/utils/make-absolute-urls_spec.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
var makeAbsoluteUrls = require('../../../server/utils/make-absolute-urls'),
|
||||||
|
configUtils = require('../../utils/configUtils');
|
||||||
|
|
||||||
|
describe('Make absolute URLs ', function () {
|
||||||
|
var siteUrl = 'http://my-ghost-blog.com',
|
||||||
|
itemUrl = 'my-awesome-post';
|
||||||
|
beforeEach(function () {
|
||||||
|
configUtils.set({url: 'http://my-ghost-blog.com'});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
configUtils.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not convert absolute URLs', function () {
|
||||||
|
var html = '<a href="http://my-ghost-blog.com/content/images" title="Absolute URL">',
|
||||||
|
result = makeAbsoluteUrls(html, siteUrl, itemUrl).html();
|
||||||
|
|
||||||
|
result.should.match(/<a href="http:\/\/my-ghost-blog.com\/content\/images" title="Absolute URL">/);
|
||||||
|
});
|
||||||
|
it('does not convert protocol relative `//` URLs', function () {
|
||||||
|
var html = '<a href="//my-ghost-blog.com/content/images" title="Absolute URL">',
|
||||||
|
result = makeAbsoluteUrls(html, siteUrl, itemUrl).html();
|
||||||
|
|
||||||
|
result.should.match(/<a href="\/\/my-ghost-blog.com\/content\/images" title="Absolute URL">/);
|
||||||
|
});
|
||||||
|
it('succesfully converts a relative URL', function () {
|
||||||
|
var html = '<a href="/about#nowhere" title="Relative URL">',
|
||||||
|
result = makeAbsoluteUrls(html, siteUrl, itemUrl).html();
|
||||||
|
|
||||||
|
result.should.match(/<a href="http:\/\/my-ghost-blog.com\/about#nowhere" title="Relative URL">/);
|
||||||
|
});
|
||||||
|
it('succesfully converts a relative URL including subdirectories', function () {
|
||||||
|
var html = '<a href="/about#nowhere" title="Relative URL">',
|
||||||
|
result = makeAbsoluteUrls(html, 'http://my-ghost-blog.com/blog', itemUrl).html();
|
||||||
|
|
||||||
|
result.should.match(/<a href="http:\/\/my-ghost-blog.com\/blog\/about#nowhere" title="Relative URL">/);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue