fix(core/parameter): missing some tags handling (#9983)

Signed-off-by: Rongrong <i@rong.moe>
This commit is contained in:
Rongrong
2022-06-18 06:45:03 -09:00
committed by GitHub
parent f3aee1b3b5
commit 6a0d44348e
3 changed files with 70 additions and 31 deletions
+38 -30
View File
@@ -6,6 +6,18 @@ const config = require('@/config').value;
let mercury_parser;
const resolveRelativeLink = ($, elem, attr, baseUrl) => {
const $elem = $(elem);
if (baseUrl) {
try {
$elem.attr(attr, new URL($elem.attr(attr), baseUrl).href);
} catch (e) {
// no-empty
}
}
};
module.exports = async (ctx, next) => {
await next();
@@ -76,50 +88,46 @@ module.exports = async (ctx, next) => {
$('script').remove();
$('a').each((_, ele) => {
const $ele = $(ele);
// absolute link
if (baseUrl) {
try {
$ele.attr('href', new URL($ele.attr('href'), baseUrl).href);
} catch (e) {
// no-empty
}
}
});
$('img').each((_, ele) => {
const $ele = $(ele);
// fix lazyload
if (!$ele.attr('src')) {
for (const key in ele.attribs) {
const value = ele.attribs[key].trim();
if (['.gif', '.png', '.jpg', '.webp'].some((suffix) => value.includes(suffix))) {
$ele.attr('src', value);
break;
const lazySrc = $ele.attr('data-src') || $ele.attr('data-original');
if (lazySrc) {
$ele.attr('src', lazySrc);
} else {
for (const key in ele.attribs) {
const value = ele.attribs[key].trim();
if (['.gif', '.png', '.jpg', '.webp'].some((suffix) => value.includes(suffix))) {
$ele.attr('src', value);
break;
}
}
}
}
// absolute link
if (baseUrl) {
try {
$ele.attr('src', new URL($ele.attr('src'), baseUrl).href);
} catch (e) {
// no-empty
}
}
// referrerpolicy
$ele.attr('referrerpolicy', 'no-referrer');
// redundant attributes
['onclick', 'onerror', 'onload'].forEach((e) => {
$ele.removeAttr(e);
});
});
// resolve relative link & fix referrer policy
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
// https://www.w3schools.com/tags/att_href.asp
$('a, area').each((_, elem) => {
resolveRelativeLink($, elem, 'href', baseUrl);
// $(elem).attr('rel', 'noreferrer'); // currently no such a need
});
// https://www.w3schools.com/tags/att_src.asp
$('img, video, audio, source, iframe, embed, track').each((_, elem) => {
resolveRelativeLink($, elem, 'src', baseUrl);
});
$('img, iframe').each((_, elem) => {
$(elem).attr('referrerpolicy', 'no-referrer');
});
item.description = $('body').html() + '' + (config.suffix || '');
}
return item;
+16 -1
View File
@@ -98,6 +98,21 @@ module.exports = async (ctx) => {
link: `https://mock.com/DIYgod/RSSHub`,
author: `DIYgod`,
});
} else if (ctx.params.id === 'multimedia') {
item.push({
title: `Multimedia Title`,
description: `<img src="/DIYgod/RSSHub.jpg">
<video src="/DIYgod/RSSHub.mp4"></video>
<video>
<source src="/DIYgod/RSSHub.mp4" type="video/mp4">
<source src="/DIYgod/RSSHub.webm" type="video/webm">
</video>
<audio src="/DIYgod/RSSHub.mp3"></audio>
<iframe src="/DIYgod/RSSHub.html"></iframe>`,
pubDate: new Date(`2019-3-1`).toUTCString(),
link: `https://mock.com/DIYgod/RSSHub`,
author: `DIYgod`,
});
} else if (ctx.params.id === 'sort') {
item.push({
title: `Sort Title 0`,
@@ -187,6 +202,6 @@ module.exports = async (ctx) => {
link: 'https://github.com/DIYgod/RSSHub',
item,
allowEmpty: ctx.params.id === 'allow_empty',
description: ctx.params.id === 'complicated' ? '<img src="http://mock.com/DIYgod/DIYgod/RSSHub">' : 'A test route for RSSHub',
description: ctx.params.id === 'complicated' ? '<img src="http://mock.com/DIYgod/DIYgod/RSSHub">' : ctx.params.id === 'multimedia' ? '<video src="http://mock.com/DIYgod/DIYgod/RSSHub"></video>' : 'A test route for RSSHub',
};
};
+16
View File
@@ -280,6 +280,22 @@ describe('complicated_description', () => {
});
});
describe('multimedia_description', () => {
it(`multimedia_description`, async () => {
const response = await request.get('/test/multimedia');
expect(response.status).toBe(200);
const parsed = await parser.parseString(response.text);
expect(parsed.items[0].content).toBe(`<img src="https://mock.com/DIYgod/RSSHub.jpg" referrerpolicy="no-referrer">
<video src="https://mock.com/DIYgod/RSSHub.mp4"></video>
<video src="https://mock.com/DIYgod/undefined">
<source src="https://mock.com/DIYgod/RSSHub.mp4" type="video/mp4">
<source src="https://mock.com/DIYgod/RSSHub.webm" type="video/webm">
</video>
<audio src="https://mock.com/DIYgod/RSSHub.mp3"></audio>
<iframe src="https://mock.com/DIYgod/RSSHub.html" referrerpolicy="no-referrer"></iframe>`);
});
});
describe('sort', () => {
it(`sort`, async () => {
const response = await request.get('/test/sort');