feat: cleanup the link in comments with target.

This commit is contained in:
Yufan Sheng 2024-06-17 04:10:51 +08:00
parent c3616a73fd
commit 5dc964b9dd
Signed by: syhily
GPG Key ID: DEB186763C308C31
2 changed files with 15 additions and 3 deletions

View File

@ -179,7 +179,6 @@ For instance, the [giscus](https://giscus.app) is an opinionated choice.
- [ ] Check article grammar errors by using ChatGPT. Remain **54** posts. - [ ] Check article grammar errors by using ChatGPT. Remain **54** posts.
- [ ] Add music to the articles. Remain **54** posts. - [ ] Add music to the articles. Remain **54** posts.
- [ ] Clean up the legacy links in the weblog comments.
- [ ] External the article inner links with different target. - [ ] External the article inner links with different target.
- [ ] Slide share components integration. - [ ] Slide share components integration.

View File

@ -14,7 +14,7 @@ import { getSecret } from 'astro:env/server';
import _ from 'lodash'; import _ from 'lodash';
import { marked } from 'marked'; import { marked } from 'marked';
import * as querystring from 'node:querystring'; import * as querystring from 'node:querystring';
import { transform } from 'ultrahtml'; import { ELEMENT_NODE, transform, walk } from 'ultrahtml';
import sanitize from 'ultrahtml/transformers/sanitize'; import sanitize from 'ultrahtml/transformers/sanitize';
// Access the artalk in internal docker host when it was deployed on zeabur. // Access the artalk in internal docker host when it was deployed on zeabur.
@ -104,6 +104,18 @@ const parseContent = async (content: string): Promise<string> => {
const parsed = await marked.parse(escapedContent); const parsed = await marked.parse(escapedContent);
// Avoid the XSS attack. // Avoid the XSS attack.
return transform(parsed, [ return transform(parsed, [
async (node) => {
await walk(node, (node) => {
if (node.type === ELEMENT_NODE) {
if (node.name === 'a' && !node.attributes.href?.startsWith('https://yufan.me')) {
node.attributes.target = '_blank';
node.attributes.rel = 'nofollow';
}
}
});
return node;
},
sanitize({ sanitize({
allowElements: [ allowElements: [
'h1', 'h1',
@ -135,7 +147,8 @@ const parseContent = async (content: string): Promise<string> => {
'li', 'li',
], ],
allowAttributes: { allowAttributes: {
img: ['src', 'width', 'height', 'rel', 'target'], img: ['src', 'width', 'height'],
a: ['rel', 'target'],
}, },
allowComments: false, allowComments: false,
}), }),