Remove .html from internal links
Some checks are pending
/ deploy (push) Waiting to run

This commit is contained in:
Loyyd 2026-07-02 19:44:40 +02:00
parent 670d90cb15
commit f85aca7d58
43 changed files with 202 additions and 97 deletions

View file

@ -122,13 +122,12 @@ export function speechCategorySlug(category: string): string {
export function categoryHref(entry: ArchiveEntry, category: string): string {
if (entry.data.type === "speech") {
return `/speeches/categories/${speechCategorySlug(category)}.html`;
return `/speeches/categories/${speechCategorySlug(category)}`;
}
return `/blog/categories/${blogCategorySlug(category)}.html`;
return `/blog/categories/${blogCategorySlug(category)}`;
}
export function tagHref(tag: string): string {
return `/blog/tags/${blogTagSlug(tag)}.html`;
return `/blog/tags/${blogTagSlug(tag)}`;
}

View file

@ -1,5 +1,6 @@
import fs from "node:fs";
import path from "node:path";
import { stripHtmlExtensionFromInternalUrl } from "./urls";
const repoRoot = process.cwd();
const speechesRoot = path.join(repoRoot, "content", "speeches");
@ -190,7 +191,7 @@ function itemFromFile(filePath: string): SpeechArchiveItem {
return {
id: relativePath.replace(/\.md$/, ""),
title,
url: frontmatter.source ?? "#",
url: stripHtmlExtensionFromInternalUrl(frontmatter.source) ?? "#",
year,
speaker,
category,

39
src/lib/urls.ts Normal file
View file

@ -0,0 +1,39 @@
const internalHosts = new Set(["familyfed.ie", "www.familyfed.ie", "familyfed.bcgen.ie"]);
const ignoredProtocolPattern = /^(?:mailto|tel|javascript|data|blob):/i;
function splitSuffix(value: string): { pathname: string; suffix: string } {
const match = value.match(/^([^?#]*)([?#].*)?$/);
return {
pathname: match?.[1] ?? value,
suffix: match?.[2] ?? "",
};
}
function stripHtmlPath(pathname: string): string {
return pathname.replace(/\.html$/i, "");
}
export function stripHtmlExtensionFromInternalUrl<T extends string | undefined>(value: T): T {
if (!value || value.startsWith("#") || value.startsWith("?") || value.startsWith("//") || ignoredProtocolPattern.test(value)) {
return value;
}
const absoluteMatch = value.match(/^(https?:\/\/([^/?#]+))([^?#]*)([?#].*)?$/i);
if (absoluteMatch) {
const [, origin, host, pathname = "", suffix = ""] = absoluteMatch;
if (!internalHosts.has(host.toLowerCase())) {
return value;
}
return `${origin}${stripHtmlPath(pathname)}${suffix}` as T;
}
const { pathname, suffix } = splitSuffix(value);
return `${stripHtmlPath(pathname)}${suffix}` as T;
}
export function normalizeInternalHtmlLinks(html = ""): string {
return html.replace(/\b(href|action)=(["'])(.*?)\2/gis, (_match, attr, quote, value) => {
return `${attr}=${quote}${stripHtmlExtensionFromInternalUrl(value)}${quote}`;
});
}