feat: inline some mentions to reduce spacing (#1307)

This commit is contained in:
patak 2023-01-19 11:26:01 +01:00 committed by GitHub
parent 1f427e2538
commit a48524e7ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 23 deletions

View file

@ -469,6 +469,7 @@ function transformCollapseMentions(status?: mastodon.v1.Status, inReplyToStatus?
return node return node
const mentions: (Node | undefined)[] = [] const mentions: (Node | undefined)[] = []
const children = node.children as Node[] const children = node.children as Node[]
let trimContentStart: (() => void) | undefined
for (const child of children) { for (const child of children) {
// mention // mention
if (isMention(child)) { if (isMention(child)) {
@ -480,8 +481,11 @@ function transformCollapseMentions(status?: mastodon.v1.Status, inReplyToStatus?
} }
// other content, stop collapsing // other content, stop collapsing
else { else {
if (child.type === TEXT_NODE) if (child.type === TEXT_NODE) {
trimContentStart = () => {
child.value = child.value.trimStart() child.value = child.value.trimStart()
}
}
// remove <br> after mention // remove <br> after mention
if (child.name === 'br') if (child.name === 'br')
mentions.push(undefined) mentions.push(undefined)
@ -495,6 +499,7 @@ function transformCollapseMentions(status?: mastodon.v1.Status, inReplyToStatus?
let mentionsCount = 0 let mentionsCount = 0
let contextualMentionsCount = 0 let contextualMentionsCount = 0
let removeNextSpacing = false let removeNextSpacing = false
const contextualMentions = mentions.filter((mention) => { const contextualMentions = mentions.filter((mention) => {
if (!mention) if (!mention)
return false return false
@ -508,24 +513,30 @@ function transformCollapseMentions(status?: mastodon.v1.Status, inReplyToStatus?
mentionsCount++ mentionsCount++
if (inReplyToStatus) { if (inReplyToStatus) {
const mentionHandle = getMentionHandle(mention) const mentionHandle = getMentionHandle(mention)
if (inReplyToStatus.account.acct === mentionHandle || inReplyToStatus.mentions.some(m => m.acct === mentionHandle)) if (inReplyToStatus.account.acct === mentionHandle || inReplyToStatus.mentions.some(m => m.acct === mentionHandle)) {
removeNextSpacing = true
return false return false
} }
}
contextualMentionsCount++ contextualMentionsCount++
} }
return true return true
}) }) as Node[]
// We have a special case for single mentions that are part of a reply. // We have a special case for single mentions that are part of a reply.
// We already have the replying to badge in this case or the status is connected to the previous one. // We already have the replying to badge in this case or the status is connected to the previous one.
// This is needed because the status doesn't included the in Reply to handle, only the account id. // This is needed because the status doesn't included the in Reply to handle, only the account id.
// But this covers the majority of cases. // But this covers the majority of cases.
const showMentions = !(contextualMentionsCount === 0 || (mentionsCount === 1 && status?.inReplyToAccountId)) const showMentions = !(contextualMentionsCount === 0 || (mentionsCount === 1 && status?.inReplyToAccountId))
const grouped = contextualMentionsCount > 2
if (grouped)
trimContentStart?.()
const contextualChildren = children.slice(mentions.length) const contextualChildren = children.slice(mentions.length)
const mentionNodes = showMentions ? (grouped ? [h('mention-group', null, ...contextualMentions)] : contextualMentions) : []
return { return {
...node, ...node,
children: showMentions ? [h('mention-group', null, ...contextualMentions), ...contextualChildren] : contextualChildren, children: [...mentionNodes, ...contextualChildren],
} }
} }
} }

View file

@ -91,8 +91,7 @@ describe('content-rich', () => {
}) })
expect(formatted).toMatchInlineSnapshot(` expect(formatted).toMatchInlineSnapshot(`
"<p> "<p>
<mention-group <span class=\\"h-card\\"
><span class=\\"h-card\\"
><a ><a
class=\\"u-url mention\\" class=\\"u-url mention\\"
rel=\\"nofollow noopener noreferrer\\" rel=\\"nofollow noopener noreferrer\\"
@ -104,8 +103,9 @@ describe('content-rich', () => {
class=\\"u-url mention\\" class=\\"u-url mention\\"
rel=\\"nofollow noopener noreferrer\\" rel=\\"nofollow noopener noreferrer\\"
to=\\"/m.webtoo.ls/@elk\\" to=\\"/m.webtoo.ls/@elk\\"
></a></span></mention-group ></a
>content ></span>
content
<span class=\\"h-card\\" <span class=\\"h-card\\"
><a ><a
class=\\"u-url mention\\" class=\\"u-url mention\\"
@ -151,19 +151,53 @@ describe('content-rich', () => {
`) `)
}) })
it('shows some collapsed mentions', async () => { it('shows some collapsed mentions inline', async () => {
const { formatted } = await render('<p><span class="h-card"><a href="https://m.webtoo.ls/@elk" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>elk</span></a></span> <span class="h-card"><a href="https://m.webtoo.ls/@antfu" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>antfu</span></a></span> content</p>', { const { formatted } = await render('<p><span class="h-card"><a href="https://m.webtoo.ls/@elk" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>elk</span></a></span> <span class="h-card"><a href="https://m.webtoo.ls/@antfu" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>antfu</span></a></span> content</p>', {
collapseMentionLink: true, collapseMentionLink: true,
inReplyToStatus: { account: { acct: 'elk@webtoo.ls' }, mentions: [] as mastodon.v1.StatusMention[] } as mastodon.v1.Status, inReplyToStatus: { account: { acct: 'elk@webtoo.ls' }, mentions: [] as mastodon.v1.StatusMention[] } as mastodon.v1.Status,
}) })
expect(formatted).toMatchInlineSnapshot(` expect(formatted).toMatchInlineSnapshot(`
"<p> "<p>
<mention-group>
<span class=\\"h-card\\" <span class=\\"h-card\\"
><a ><a
class=\\"u-url mention\\" class=\\"u-url mention\\"
rel=\\"nofollow noopener noreferrer\\" rel=\\"nofollow noopener noreferrer\\"
to=\\"/m.webtoo.ls/@antfu\\" to=\\"/m.webtoo.ls/@antfu\\"
></a
></span>
content
</p>
"
`)
})
it('shows some collapsed mentions grouped', async () => {
const { formatted } = await render('<p><span class="h-card"><a href="https://m.webtoo.ls/@elk" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>elk</span></a></span> <span class="h-card"><a href="https://m.webtoo.ls/@antfu" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>antfu</span></a></span> <span class="h-card"><a href="https://m.webtoo.ls/@patak" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>patak</span></a></span> <span class="h-card"><a href="https://m.webtoo.ls/@sxzz" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@<span>sxzz</span></a></span>content</p>', {
collapseMentionLink: true,
inReplyToStatus: { account: { acct: 'elk@webtoo.ls' }, mentions: [] as mastodon.v1.StatusMention[] } as mastodon.v1.Status,
})
expect(formatted).toMatchInlineSnapshot(`
"<p>
<mention-group
><span class=\\"h-card\\"
><a
class=\\"u-url mention\\"
rel=\\"nofollow noopener noreferrer\\"
to=\\"/m.webtoo.ls/@antfu\\"
></a
></span>
<span class=\\"h-card\\"
><a
class=\\"u-url mention\\"
rel=\\"nofollow noopener noreferrer\\"
to=\\"/m.webtoo.ls/@patak\\"
></a
></span>
<span class=\\"h-card\\"
><a
class=\\"u-url mention\\"
rel=\\"nofollow noopener noreferrer\\"
to=\\"/m.webtoo.ls/@sxzz\\"
></a></span></mention-group ></a></span></mention-group
>content >content
</p> </p>