4c8179312d
fixes https://github.com/TryGhost/Product/issues/3687 After this change, relative URLs in emails will be replaced with absolute URLs using the post URL. Making relative Portal URLs possible etc. Updates the test data generator to fix invalid URL encoding (somehow a backslash + escaped double quote was added when it wasn't required).
50 lines
1.8 KiB
JavaScript
50 lines
1.8 KiB
JavaScript
class LinkReplacer {
|
|
/**
|
|
* Replaces the links in the provided HTML
|
|
* @param {string} html
|
|
* @param {(url: URL, originalPath: string): Promise<URL|string|false>} replaceLink
|
|
* @param {object} options
|
|
* @param {string} [options.base] If you want to replace relative links, this will replace them to an absolute link and call the replaceLink method too
|
|
* @returns {Promise<string>}
|
|
*/
|
|
async replace(html, replaceLink, options = {}) {
|
|
const cheerio = require('cheerio');
|
|
const entities = require('entities');
|
|
try {
|
|
const $ = cheerio.load(html, {
|
|
xml: {
|
|
// This makes sure we use the faster and less destructive htmlparser2 parser
|
|
xmlMode: false
|
|
},
|
|
// Do not replace &, ', " and others with HTML entities (is bugged because it replaces &map_ with something weird (↦))
|
|
decodeEntities: false
|
|
}, false);
|
|
|
|
for (const el of $('a').toArray()) {
|
|
const href = $(el).attr('href');
|
|
if (href) {
|
|
let url;
|
|
const path = entities.decode(href);
|
|
try {
|
|
url = new URL(path, options.base);
|
|
} catch (e) {
|
|
// Ignore invalid URLs
|
|
}
|
|
if (url) {
|
|
url = await replaceLink(url, path);
|
|
const str = url.toString();
|
|
$(el).attr('href', str);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $.html();
|
|
} catch (e) {
|
|
// Catch errors from cheerio
|
|
return html;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = new LinkReplacer();
|