Migrate legacy archive pages
This commit is contained in:
parent
e90920ce86
commit
cbedd9b723
25 changed files with 652 additions and 1 deletions
134
src/lib/archive.ts
Normal file
134
src/lib/archive.ts
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
import type { CollectionEntry } from "astro:content";
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
export type ArchiveEntry = CollectionEntry<"archive">;
|
||||
|
||||
const entityMap: Record<string, string> = {
|
||||
amp: "&",
|
||||
apos: "'",
|
||||
hellip: "...",
|
||||
laquo: "<<",
|
||||
nbsp: " ",
|
||||
quot: '"',
|
||||
raquo: ">>",
|
||||
rsquo: "'",
|
||||
lsquo: "'",
|
||||
rdquo: '"',
|
||||
ldquo: '"',
|
||||
};
|
||||
|
||||
export function decodeEntities(value = ""): string {
|
||||
return value.replace(/&(#x?[0-9a-f]+|[a-z]+);/gi, (match, entity) => {
|
||||
const key = entity.toLowerCase();
|
||||
if (key.startsWith("#x")) {
|
||||
return String.fromCodePoint(Number.parseInt(key.slice(2), 16));
|
||||
}
|
||||
if (key.startsWith("#")) {
|
||||
return String.fromCodePoint(Number.parseInt(key.slice(1), 10));
|
||||
}
|
||||
return entityMap[key] ?? match;
|
||||
});
|
||||
}
|
||||
|
||||
export function textFromHtml(html = ""): string {
|
||||
return decodeEntities(
|
||||
html
|
||||
.replace(/<script[\s\S]*?<\/script>/gi, " ")
|
||||
.replace(/<style[\s\S]*?<\/style>/gi, " ")
|
||||
.replace(/<[^>]+>/g, " "),
|
||||
)
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
export function excerptFromBody(body = "", maxLength = 230): string {
|
||||
const text = textFromHtml(body);
|
||||
if (text.length <= maxLength) {
|
||||
return text;
|
||||
}
|
||||
|
||||
const clipped = text.slice(0, maxLength - 3);
|
||||
const finalSpace = clipped.lastIndexOf(" ");
|
||||
return `${finalSpace > 80 ? clipped.slice(0, finalSpace) : clipped}...`;
|
||||
}
|
||||
|
||||
export function slugify(value: string): string {
|
||||
return value
|
||||
.toLowerCase()
|
||||
.replace(/&/g, "and")
|
||||
.replace(/[^a-z0-9]+/g, "-")
|
||||
.replace(/^-|-$/g, "");
|
||||
}
|
||||
|
||||
export function formatDate(value?: string): string | undefined {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.valueOf())) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return new Intl.DateTimeFormat("en-US", {
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
export function sortByPublishedDesc(entries: ArchiveEntry[]): ArchiveEntry[] {
|
||||
return [...entries].sort((a, b) => {
|
||||
const dateA = Date.parse(a.data.published ?? "");
|
||||
const dateB = Date.parse(b.data.published ?? "");
|
||||
|
||||
if (!Number.isNaN(dateA) && !Number.isNaN(dateB) && dateA !== dateB) {
|
||||
return dateB - dateA;
|
||||
}
|
||||
|
||||
return (a.data.title ?? a.id).localeCompare(b.data.title ?? b.id);
|
||||
});
|
||||
}
|
||||
|
||||
export async function getArchiveEntries(type?: "blog" | "speech"): Promise<ArchiveEntry[]> {
|
||||
const entries = await getCollection("archive");
|
||||
return sortByPublishedDesc(type ? entries.filter((entry) => entry.data.type === type) : entries);
|
||||
}
|
||||
|
||||
export function uniqueSorted(values: string[]): string[] {
|
||||
return Array.from(new Set(values.filter(Boolean))).sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
export function blogCategorySlug(category: string): string {
|
||||
return slugify(category);
|
||||
}
|
||||
|
||||
export function blogTagSlug(tag: string): string {
|
||||
return slugify(tag);
|
||||
}
|
||||
|
||||
export function speechCategorySlug(category: string): string {
|
||||
if (category.toLowerCase().includes("hak ja han moon")) {
|
||||
return "mrs-hak-ja-han-moon";
|
||||
}
|
||||
|
||||
const year = category.match(/\b(1\d{3}|20\d{2})\b/)?.[1];
|
||||
if (year === "1956") {
|
||||
return "rev-sun-myung-moon";
|
||||
}
|
||||
|
||||
return year ? `rev-sun-myung-moon-${year}` : "rev-sun-myung-moon";
|
||||
}
|
||||
|
||||
export function categoryHref(entry: ArchiveEntry, category: string): string {
|
||||
if (entry.data.type === "speech") {
|
||||
return `/speeches/categories/${speechCategorySlug(category)}.html`;
|
||||
}
|
||||
|
||||
return `/blog/categories/${blogCategorySlug(category)}.html`;
|
||||
}
|
||||
|
||||
export function tagHref(tag: string): string {
|
||||
return `/blog/tags/${blogTagSlug(tag)}.html`;
|
||||
}
|
||||
|
||||
15
src/lib/legacy-page.ts
Normal file
15
src/lib/legacy-page.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { legacyHtmlRoot } from "./static-pages";
|
||||
|
||||
export function legacyPageArticle(relativePath: string): string {
|
||||
const html = fs.readFileSync(path.join(legacyHtmlRoot, relativePath), "utf8");
|
||||
const match = html.match(/<div id="post-[\s\S]*?<\/div><!-- #post-## -->/);
|
||||
|
||||
if (!match) {
|
||||
throw new Error(`Could not find page article in ${relativePath}`);
|
||||
}
|
||||
|
||||
return match[0];
|
||||
}
|
||||
|
||||
|
|
@ -4,16 +4,37 @@ import path from "node:path";
|
|||
export const repoRoot = process.cwd();
|
||||
export const legacyHtmlRoot = path.join(repoRoot, "archive-source");
|
||||
export const migratedHtmlPages = new Set([
|
||||
"2013-sunday-service-archive.html",
|
||||
"2014-sunday-services.html",
|
||||
"2015-sunday-services-archive.html",
|
||||
"2016-sunday-service-archive.html",
|
||||
"2017-sunday-service-archive.html",
|
||||
"2018-sunday-service-archive.html",
|
||||
"about.html",
|
||||
"about-us-organizations.html",
|
||||
"archive-sunday-services-2013.html",
|
||||
"archive-sunday-services-2014.html",
|
||||
"archive-sunday-services-2015.html",
|
||||
"archive-sunday-services-2016.html",
|
||||
"archive-sunday-services-2017.html",
|
||||
"archive-sunday-services-2018.html",
|
||||
"contact.html",
|
||||
"events.html",
|
||||
"index.html",
|
||||
"register.html",
|
||||
"services.html",
|
||||
"speeches/index.html",
|
||||
"the-founders.html",
|
||||
"videos.html",
|
||||
]);
|
||||
|
||||
const migratedHtmlPrefixes = [
|
||||
"blog/categories/",
|
||||
"blog/tags/",
|
||||
"speeches/categories/",
|
||||
"speeches/rev-dr-sun-myung-moon/",
|
||||
];
|
||||
|
||||
export function walkHtmlFiles(dir = legacyHtmlRoot): string[] {
|
||||
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
|
@ -37,7 +58,7 @@ export function routeFromRelativePath(relativePath: string): string {
|
|||
}
|
||||
|
||||
export function isMigratedHtmlPage(relativePath: string): boolean {
|
||||
return migratedHtmlPages.has(relativePath);
|
||||
return migratedHtmlPages.has(relativePath) || migratedHtmlPrefixes.some((prefix) => relativePath.startsWith(prefix));
|
||||
}
|
||||
|
||||
export function sourcePathFromRoute(route = ""): string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue