Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions layers/identity/server/utils/weekly-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,18 +437,20 @@ function row(t: Tokens, options: {
/**
* A dense trending row.
*
* Seven full editorial rows turned the email into a feed. The Skill name,
* exact source, ranking reason, and evidence account stay. Descriptions,
* quotes, and the duplicate source action remain in the plain-text version.
* Show a short description below the Skill name.
* Keep the source, ranking reason, and evidence account compact.
* Quotes and the duplicate source action remain in the plain-text version.
*/
function trendingRow(t: Tokens, options: {
siteUrl: string
owner: string
title: string
href: string
description: string | null
meta: string
evidence: WeeklyEvidence | null
}): string {
const description = trimDescription(options.description)
const evidence = options.evidence
? ` Β· <a href="${esc(options.evidence.url)}" style="color:${t.muted};text-decoration:underline;text-underline-offset:3px;">@${esc(options.evidence.authorHandle)} ${options.evidence.platform === 'x' ? 'on X' : 'on Bluesky'}</a>`
: ''
Expand All @@ -462,6 +464,7 @@ function trendingRow(t: Tokens, options: {
</td>
<td valign="top">
<a href="${esc(options.href)}" style="display:inline-block;padding:0 0 3px;font-family:${MONO};font-size:14px;line-height:1.45;font-weight:600;color:${t.text};text-decoration:underline;text-decoration-color:${t.borderStrong};text-underline-offset:3px;">${esc(options.title)}</a>
${description ? `<div style="margin-top:3px;font-family:${SANS};font-size:14px;line-height:1.55;color:${t.body};">${esc(description)}</div>` : ''}
<div style="margin-top:3px;font-family:${MONO};font-size:14px;line-height:1.45;color:${t.muted};font-variant-numeric:tabular-nums;">${esc(options.meta)}${evidence}</div>
</td>
</tr>
Expand Down Expand Up @@ -709,6 +712,7 @@ export function renderWeekly(input: WeeklyRenderInput): WeeklyRender {
owner: skill.owner,
title: skill.canonicalName,
href: sourceUrl,
description: skill.description,
meta: trendingMeta(skill, now),
evidence: skill.evidence,
})
Expand Down
26 changes: 22 additions & 4 deletions test/unit/weekly-template.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,12 @@ describe('weekly template', () => {
expect(text).not.toContain('t.co/abc')
})

it('keeps descriptions out of compact HTML rows but retains them in text', () => {
it('shortens long descriptions in HTML and text on a word boundary', () => {
const long = 'Forces the laziest solution that actually works, simplest, shortest, most minimal. Channels a senior dev who has seen everything: question whether the task needs to exist at all.'
const { html, text } = renderWeekly(input({ trending: [trending({ description: long })] }))

expect(html).not.toContain('Forces the laziest solution')
expect(html).toContain('Forces the laziest solution')
expect(html).not.toContain('needs to exist at all')
expect(text).toContain('Forces the laziest solution')
expect(text).not.toContain('needs to exist at all')
// Cut on a word boundary: the last word before the ellipsis is a whole
Expand All @@ -230,13 +231,30 @@ describe('weekly template', () => {
expect(long).toContain(` ${tail} `)
})

it('leaves a short description in the plain-text alternative', () => {
it('shows a short description in HTML and text', () => {
const { html, text } = renderWeekly(input({ trending: [trending({ description: 'Testing conventions.' })] }))

expect(html).not.toContain('Testing conventions.')
expect(html).toContain('Testing conventions.')
expect(text).toContain('Testing conventions.')
})

it('escapes description markup in HTML and preserves it in text', () => {
const description = 'Use <script>alert("skill")</script> & test.'
const { html, text } = renderWeekly(input({ trending: [trending({ description })] }))

expect(html).toContain('Use &lt;script&gt;alert(&quot;skill&quot;)&lt;/script&gt; &amp; test.')
expect(html).not.toContain('<script>')
expect(text).toContain(description)
})

it.each([null, '', ' \n '])('omits an empty description: %j', (description) => {
const { html, text } = renderWeekly(input({ trending: [trending({ description })] }))
const absent = renderWeekly(input({ trending: [trending({ description: null })] }))

expect(html).toBe(absent.html)
expect(text).toBe(absent.text)
})

it('shows the top seven trending Skills', () => {
const skills = Array.from({ length: 9 }, (_, index) => trending({
owner: `owner-${index + 1}`,
Expand Down