next-site: plugin detail page with per-plugin OG tags
This commit is contained in:
parent
c52eb517b8
commit
98999b57f3
2 changed files with 63 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { getAllChannels, getAllOverrides } from './db'
|
||||
import { renderBrowsePage } from './pages/browse'
|
||||
import { renderDetailPage } from './pages/detail'
|
||||
import { buildPublicIndex } from './publicIndex'
|
||||
import type { Env } from './env'
|
||||
import type { BaseIndex } from './publicIndex'
|
||||
|
|
@ -42,6 +43,27 @@ export default {
|
|||
})
|
||||
}
|
||||
|
||||
const detailMatch = url.pathname.match(/^\/plugins\/([\w.-]+)$/)
|
||||
if (detailMatch) {
|
||||
const id = detailMatch[1]
|
||||
const baseRes = await env.ASSETS.fetch(
|
||||
new URL('/index.json', request.url),
|
||||
)
|
||||
const base = await baseRes.json<BaseIndex>()
|
||||
const [overrides, channels] = await Promise.all([
|
||||
getAllOverrides(env),
|
||||
getAllChannels(env),
|
||||
])
|
||||
const merged = buildPublicIndex(base, overrides, channels)
|
||||
|
||||
const plugin = merged.plugins[id]
|
||||
if (!plugin) return new Response('Not found', { status: 404 })
|
||||
|
||||
return new Response(renderDetailPage(plugin, overrides[id] ?? null), {
|
||||
headers: { 'content-type': 'text/html; charset=utf-8' },
|
||||
})
|
||||
}
|
||||
|
||||
return env.ASSETS.fetch(request)
|
||||
},
|
||||
}
|
||||
|
|
|
|||
41
worker/src/pages/detail.ts
Normal file
41
worker/src/pages/detail.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { escapeHtml, htmlShell } from '../theme'
|
||||
import type { Override } from '../db'
|
||||
import type { IndexPlugin } from '../publicIndex'
|
||||
|
||||
export function renderDetailPage(
|
||||
plugin: IndexPlugin,
|
||||
override: Override | null,
|
||||
): string {
|
||||
const description = override?.description ?? plugin.description
|
||||
const tagline = override?.tagline ?? description
|
||||
const version = plugin.channels.latest ?? Object.keys(plugin.versions)[0]
|
||||
|
||||
const featuresHtml = override?.features?.length
|
||||
? `<ul>${override.features.map(f => `<li>${escapeHtml(f)}</li>`).join('')}</ul>`
|
||||
: ''
|
||||
|
||||
const body = `
|
||||
<header>
|
||||
<div class="brand">
|
||||
<a href="/" class="brand-mark" style="text-decoration:none;">N</a>
|
||||
<div class="brand-name">${escapeHtml(plugin.name)}</div>
|
||||
</div>
|
||||
<nav><a href="/">All plugins</a></nav>
|
||||
</header>
|
||||
<div class="wrap">
|
||||
<div class="page-title" style="margin-top: 22px;">${escapeHtml(plugin.name)}</div>
|
||||
<div class="page-sub">${escapeHtml(tagline)}</div>
|
||||
<p style="font-size:13px;line-height:1.6;color:rgba(255,255,255,0.75);">${escapeHtml(description)}</p>
|
||||
${featuresHtml}
|
||||
<div class="card-meta" style="margin: 16px 0;">${escapeHtml(plugin.author)} · v${escapeHtml(version ?? '?')}</div>
|
||||
<a class="btn" href="/index.json">Add repository in Revenge Next</a>
|
||||
</div>`
|
||||
|
||||
return htmlShell({
|
||||
title: `${plugin.name} - Revenge Next`,
|
||||
description: tagline,
|
||||
ogTitle: plugin.name,
|
||||
ogDescription: tagline,
|
||||
body,
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue