diff --git a/core/server/controllers/frontend.js b/core/server/controllers/frontend.js index 4a60cf778b..0ca6ac78fd 100644 --- a/core/server/controllers/frontend.js +++ b/core/server/controllers/frontend.js @@ -513,11 +513,51 @@ frontendControllers = { // convert relative resource urls to absolute ['href', 'src'].forEach(function (attributeName) { htmlContent('[' + attributeName + ']').each(function (ix, el) { + var baseUrl, + attributeValue, + parsed; + el = htmlContent(el); - var attributeValue = el.attr(attributeName); - attributeValue = url.resolve(siteUrl, attributeValue); + attributeValue = el.attr(attributeName); + // if URL is absolute move on to the next element + try { + parsed = url.parse(attributeValue); + + if (parsed.protocol) { + 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 : item.url; + + // prevent double slashes + if (baseUrl.slice(-1) === '/' && attributeValue[0] === '/') { + attributeValue = attributeValue.substr(1); + } + + // make sure URL has a trailing slash + try { + parsed = url.parse(attributeValue); + + if (parsed.pathname && parsed.pathname.slice(-1) !== '/') { + parsed.pathname += '/'; + + attributeValue = url.format(parsed); + } + } catch (e) { + // if the URL we've built cannot be parsed, fall back to the unprocessed URL + return; + } + + attributeValue = baseUrl + attributeValue; el.attr(attributeName, attributeValue); }); });