Files
website/layers/cv/server/utils/cv.ts
T
2026-10-02 17:32:02 +02:00

80 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { H3Event } from 'h3'
interface SelectValue {
value: string
}
interface FileValue {
url: string
visible_name: string
}
export interface CvRow {
id: number
From: string | null
To: string | null
Type: SelectValue | null
Institution: string | null
Area: string | null
area_german?: string | null
Place: SelectValue | null
Grade: string | null
file?: FileValue[] | null
urls?: string | null
}
export function cvTable(event: H3Event): string {
const { baserowCvTableId } = useRuntimeConfig(event)
if (!baserowCvTableId) {
throw createError({ statusCode: 500, statusMessage: 'NUXT_BASEROW_CV_TABLE_ID is not set' })
}
return baserowCvTableId
}
/** Baserow hands out file URLs with its internal protocol (http); serve them from the configured Baserow URL instead */
function fileUrl(url: string, baserowUrl: string): string {
const { pathname } = new URL(url)
return new URL(pathname, baserowUrl).href
}
function toCvLink(line: string): CvLink | null {
// "https://…", or "Label https://…" for custom link text
const match = line.match(/^(.*?)[\s:|–-]*(https?:\/\/\S+)$/)
if (!match) return null
let url: URL
try {
url = new URL(match[2]!)
} catch {
return null
}
const path = url.pathname.replace(/\/+$/, '')
const kind = url.hostname === 'github.com' ? 'github' : 'web'
const fallback = kind === 'github' ? path.slice(1) : url.hostname + path
return { label: match[1]!.trim() || fallback, url: url.href, kind }
}
/** One URL per line; a blank line starts a new group */
function toCvLinks(text: string | null | undefined): CvLink[][] {
return (text ?? '')
.split(/\n\s*\n/)
.map(block => block.split('\n').map(line => toCvLink(line.trim())).filter((link): link is CvLink => !!link))
.filter(group => group.length)
}
export function toCvEntry(row: CvRow, baserowUrl: string): CvEntry | null {
if (!row.From) return null
return {
id: row.id,
from: row.From,
to: row.To || null,
type: (row.Type?.value as CvType | undefined) ?? null,
institution: (row.Institution ?? '').trim(),
area: (row.Area ?? '').trim(),
areaGerman: (row.area_german ?? '').trim(),
place: row.Place?.value ?? null,
grade: row.Grade ?? null,
files: (row.file ?? []).map(file => ({ name: file.visible_name, url: fileUrl(file.url, baserowUrl) })),
links: toCvLinks(row.urls)
}
}