fix: use mention accts within a status to render links (#955)
This commit is contained in:
parent
f9509f8987
commit
c2850a34ae
|
@ -17,6 +17,7 @@ const vnode = $computed(() => {
|
||||||
return null
|
return null
|
||||||
const vnode = contentToVNode(status.content, {
|
const vnode = contentToVNode(status.content, {
|
||||||
emojis: emojisObject.value,
|
emojis: emojisObject.value,
|
||||||
|
mentions: 'mentions' in status ? status.mentions : undefined,
|
||||||
markdown: true,
|
markdown: true,
|
||||||
})
|
})
|
||||||
return vnode
|
return vnode
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { emojiRegEx, getEmojiAttributes } from '../config/emojis'
|
||||||
|
|
||||||
export interface ContentParseOptions {
|
export interface ContentParseOptions {
|
||||||
emojis?: Record<string, mastodon.v1.CustomEmoji>
|
emojis?: Record<string, mastodon.v1.CustomEmoji>
|
||||||
|
mentions?: mastodon.v1.StatusMention[]
|
||||||
markdown?: boolean
|
markdown?: boolean
|
||||||
replaceUnicodeEmoji?: boolean
|
replaceUnicodeEmoji?: boolean
|
||||||
astTransforms?: Transform[]
|
astTransforms?: Transform[]
|
||||||
|
@ -47,6 +48,7 @@ export function parseMastodonHTML(
|
||||||
markdown = true,
|
markdown = true,
|
||||||
replaceUnicodeEmoji = true,
|
replaceUnicodeEmoji = true,
|
||||||
convertMentionLink = false,
|
convertMentionLink = false,
|
||||||
|
mentions,
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
if (markdown) {
|
if (markdown) {
|
||||||
|
@ -74,6 +76,9 @@ export function parseMastodonHTML(
|
||||||
if (markdown)
|
if (markdown)
|
||||||
transforms.push(transformMarkdown)
|
transforms.push(transformMarkdown)
|
||||||
|
|
||||||
|
if (mentions?.length)
|
||||||
|
transforms.push(createTransformNamedMentions(mentions))
|
||||||
|
|
||||||
if (convertMentionLink)
|
if (convertMentionLink)
|
||||||
transforms.push(transformMentionLink)
|
transforms.push(transformMentionLink)
|
||||||
|
|
||||||
|
@ -377,3 +382,18 @@ function transformMentionLink(node: Node): string | Node | (string | Node)[] | n
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createTransformNamedMentions(mentions: mastodon.v1.StatusMention[]) {
|
||||||
|
return (node: Node): string | Node | (string | Node)[] | null => {
|
||||||
|
if (node.name === 'a' && node.attributes.class?.includes('mention')) {
|
||||||
|
const href = node.attributes.href
|
||||||
|
const mention = href && mentions.find(m => m.url === href)
|
||||||
|
if (mention) {
|
||||||
|
node.attributes.href = `/${currentServer.value}/@${mention.acct}`
|
||||||
|
node.children = [h('span', { 'data-type': 'mention', 'data-id': mention.acct }, `@${mention.username}`)]
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -40,6 +40,19 @@ exports[`content-rich > custom emoji 1`] = `
|
||||||
|
|
||||||
exports[`content-rich > empty 1`] = `""`;
|
exports[`content-rich > empty 1`] = `""`;
|
||||||
|
|
||||||
|
exports[`content-rich > group mention > html 1`] = `
|
||||||
|
"<p>
|
||||||
|
<span class=\\"h-card\\"
|
||||||
|
><a
|
||||||
|
class=\\"u-url mention\\"
|
||||||
|
rel=\\"nofollow noopener noreferrer\\"
|
||||||
|
to=\\"//@pilipinas@lemmy.ml\\"
|
||||||
|
></a
|
||||||
|
></span>
|
||||||
|
</p>
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`content-rich > handles html within code blocks 1`] = `
|
exports[`content-rich > handles html within code blocks 1`] = `
|
||||||
"<p>
|
"<p>
|
||||||
HTML block code:<br />
|
HTML block code:<br />
|
||||||
|
|
|
@ -20,6 +20,11 @@ describe('content-rich', () => {
|
||||||
expect(formatted).toMatchSnapshot()
|
expect(formatted).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('group mention', async () => {
|
||||||
|
const { formatted } = await render('<p><span class="h-card"><a href="https://lemmy.ml/c/pilipinas" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>pilipinas</span></a></span></p>', undefined, [{ id: '', username: 'pilipinas', url: 'https://lemmy.ml/c/pilipinas', acct: 'pilipinas@lemmy.ml' }])
|
||||||
|
expect(formatted).toMatchSnapshot('html')
|
||||||
|
})
|
||||||
|
|
||||||
it('inline code with link', async () => {
|
it('inline code with link', async () => {
|
||||||
const { formatted } = await render('<p>Inline code with link: `<a href="https://api.iconify.design/noto.css?icons=1st-place-medal,2nd-place-medal" target="_blank" rel="nofollow noopener noreferrer" class="status-link unhandled-link" title="https://api.iconify.design/noto.css?icons=1st-place-medal,2nd-place-medal"><span class="invisible">https://</span><span class="ellipsis">api.iconify.design/noto.css?ic</span><span class="invisible">ons=1st-place-medal,2nd-place-medal</span></a>`</p>')
|
const { formatted } = await render('<p>Inline code with link: `<a href="https://api.iconify.design/noto.css?icons=1st-place-medal,2nd-place-medal" target="_blank" rel="nofollow noopener noreferrer" class="status-link unhandled-link" title="https://api.iconify.design/noto.css?icons=1st-place-medal,2nd-place-medal"><span class="invisible">https://</span><span class="ellipsis">api.iconify.design/noto.css?ic</span><span class="invisible">ons=1st-place-medal,2nd-place-medal</span></a>`</p>')
|
||||||
expect(formatted).toMatchSnapshot()
|
expect(formatted).toMatchSnapshot()
|
||||||
|
@ -64,8 +69,8 @@ describe('content-rich', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
async function render(content: string, emojis?: Record<string, mastodon.v1.CustomEmoji>) {
|
async function render(content: string, emojis?: Record<string, mastodon.v1.CustomEmoji>, mentions?: mastodon.v1.StatusMention[]) {
|
||||||
const vnode = contentToVNode(content, { emojis })
|
const vnode = contentToVNode(content, { emojis, mentions })
|
||||||
const html = (await renderToString(vnode))
|
const html = (await renderToString(vnode))
|
||||||
.replace(/<!--[\[\]]-->/g, '')
|
.replace(/<!--[\[\]]-->/g, '')
|
||||||
let formatted = ''
|
let formatted = ''
|
||||||
|
|
Loading…
Reference in a new issue