mirror of https://github.com/VERT-sh/VERT.git
feat: statically generate conversion slugs
needs refinement cause building takes forever
This commit is contained in:
parent
d89a343eed
commit
95284a84d4
|
@ -46,8 +46,8 @@
|
|||
const color = $derived(
|
||||
Object.values(colors).find((p) => p.matcher(page.url.pathname)) || {
|
||||
matcher: () => false,
|
||||
color: "transparent",
|
||||
at: 0,
|
||||
color: "var(--bg-gradient-from)",
|
||||
at: 100,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -64,9 +64,14 @@
|
|||
const maskImage = $derived(
|
||||
`linear-gradient(to top, transparent ${100 - at.current}%, black 100%)`,
|
||||
);
|
||||
|
||||
const showLogo = $derived(
|
||||
page.url.pathname === "/" ||
|
||||
/^[\w-]+-[\w-]+$/.test(page.url.pathname.replace(/^\/|\/$/g, "")),
|
||||
);
|
||||
</script>
|
||||
|
||||
{#if page.url.pathname === "/"}
|
||||
{#if showLogo}
|
||||
<div
|
||||
class="fixed -z-30 top-0 left-0 w-screen h-screen flex items-center justify-center overflow-hidden"
|
||||
transition:fade={{
|
||||
|
|
|
@ -37,7 +37,9 @@
|
|||
{
|
||||
name: m["navbar.upload"](),
|
||||
url: "/",
|
||||
activeMatch: (pathname) => pathname === "/",
|
||||
activeMatch: (pathname) =>
|
||||
pathname === "/" ||
|
||||
/^[\w-]+-[\w-]+$/.test(pathname.replace(/^\/|\/$/g, "")),
|
||||
icon: UploadIcon,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
import { converters } from "$lib/converters";
|
||||
import type { EntryGenerator } from "./$types";
|
||||
|
||||
// generate conversion pairs at build time (e.g. mkv-mp4) for SEO
|
||||
export const entries: EntryGenerator = () => {
|
||||
const seenPairs = new Set<string>();
|
||||
|
||||
const addPair = (
|
||||
fromName: string,
|
||||
fromSupported: boolean,
|
||||
toName: string,
|
||||
toSupported: boolean,
|
||||
) => {
|
||||
if (!fromSupported || !toSupported || fromName === toName) return;
|
||||
|
||||
const from = fromName.replace(".", "").toLowerCase();
|
||||
const to = toName.replace(".", "").toLowerCase();
|
||||
const slug = `${from}-${to}`;
|
||||
|
||||
if (!seenPairs.has(slug)) seenPairs.add(slug);
|
||||
};
|
||||
|
||||
// check all conversions (same converter and cross-converter)
|
||||
for (const fromConverter of converters) {
|
||||
for (const toConverter of converters) {
|
||||
const sameConverter = fromConverter.name === toConverter.name;
|
||||
|
||||
for (const fromFormat of fromConverter.supportedFormats) {
|
||||
for (const toFormat of toConverter.supportedFormats) {
|
||||
// skip if same converter and same format, or if different converter but formats are the same
|
||||
if (sameConverter && fromFormat.name === toFormat.name)
|
||||
continue;
|
||||
if (!sameConverter && fromFormat.name === toFormat.name)
|
||||
continue;
|
||||
|
||||
addPair(
|
||||
fromFormat.name,
|
||||
fromFormat.fromSupported,
|
||||
toFormat.name,
|
||||
toFormat.toSupported,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = Array.from(seenPairs).map((slug) => ({ formats: slug }));
|
||||
console.log(`[SEO] generating ${result.length} format conversion routes`);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
export const load = ({ params }) => {
|
||||
const { formats } = params;
|
||||
|
||||
// parse the slug (e.g. { from: "mkv", to: "mp4" })
|
||||
const parts = formats.split("-");
|
||||
|
||||
if (parts.length !== 2) {
|
||||
return {
|
||||
fromFormat: null,
|
||||
toFormat: null,
|
||||
error: "Invalid format slug",
|
||||
};
|
||||
}
|
||||
|
||||
const [from, to] = parts;
|
||||
const fromFormat = `.${from}`;
|
||||
const toFormat = `.${to}`;
|
||||
|
||||
let fromValid = false;
|
||||
let toValid = false;
|
||||
|
||||
for (const converter of converters) {
|
||||
for (const format of converter.supportedFormats) {
|
||||
if (format.name === fromFormat && format.fromSupported)
|
||||
fromValid = true;
|
||||
if (format.name === toFormat && format.toSupported) toValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fromValid || !toValid) {
|
||||
return {
|
||||
fromFormat: null,
|
||||
toFormat: null,
|
||||
error: "Invalid conversion pair",
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
fromFormat,
|
||||
toFormat,
|
||||
error: null,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
<script lang="ts">
|
||||
import { error, log } from "$lib/logger";
|
||||
import Index from "../+page.svelte";
|
||||
const { data } = $props();
|
||||
|
||||
$effect(() => {
|
||||
if (data.fromFormat && data.toFormat) {
|
||||
log(["SEO"], `converting from: ${data.fromFormat}`);
|
||||
log(["SEO"], `converting to: ${data.toFormat}`);
|
||||
} else if (data.error) {
|
||||
error(["SEO"], `invalid slug: ${data.error}`);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{#if data.fromFormat && data.toFormat}
|
||||
<title
|
||||
>Convert {data.fromFormat.replace(".", "").toUpperCase()} to {data.toFormat
|
||||
.replace(".", "")
|
||||
.toUpperCase()} - VERT</title
|
||||
>
|
||||
<meta
|
||||
name="description"
|
||||
content="Convert {data.fromFormat
|
||||
.replace('.', '')
|
||||
.toUpperCase()} files to {data.toFormat
|
||||
.replace('.', '')
|
||||
.toUpperCase()} with VERT. No ads, no tracking, open source, and all processing (other than video) is done on your device."
|
||||
/>
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
<!-- render main upload page -->
|
||||
<Index />
|
Loading…
Reference in New Issue