Compare commits

..

No commits in common. "e352a0baa16c69f9c19dd62fcebd84a508d3b742" and "b23bac3f83ace839d8d7165c9ebc1c8d618da1a5" have entirely different histories.

25 changed files with 1 additions and 652 deletions

View file

@ -1,121 +0,0 @@
---
import SiteLayout from "./SiteLayout.astro";
import SiteSidebar from "./SiteSidebar.astro";
import { categoryHref, excerptFromBody, formatDate, slugify, tagHref } from "../lib/archive";
const {
title,
heading,
description,
pathname,
entries = [],
currentPage = 1,
totalPages = 1,
pageHref,
} = Astro.props;
---
<SiteLayout
title={`${title} &#8211; FFWPU Ireland`}
description={description}
bodyClass="archive custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left"
pathname={pathname}
canonical={pathname}
>
<div id="main">
<div id="forbottom">
<div style="clear:both;"> </div>
<section id="container" class="two-columns-right">
<div id="content" role="main">
<header class="page-header">
<h1 class="page-title" set:html={heading} />
</header>
<div class="content-masonry archive-list">
{
entries.map((entry) => {
const categories = entry.data.categories ?? [];
const tags = entry.data.tags ?? [];
const title = entry.data.title ?? "Untitled";
const publishedDate = formatDate(entry.data.published);
return (
<article class:list={["post", "type-post", "status-publish", "format-standard", "hentry", categories.map((category) => `category-${slugify(category)}`)]}>
<h2 class="entry-title">
<a href={entry.data.source}>{title}</a>
</h2>
<div class="entry-meta">
&nbsp; <span class="author vcard">By <a class="url fn n" rel="author" href="#" title="View all posts by Fami1yfed">Fami1yfed</a></span>
{
publishedDate && entry.data.source && (
<span>
<time class="onDate date published" datetime={entry.data.published}>
{" "}
<a href={entry.data.source} rel="bookmark">{publishedDate}</a>
{" "}
</time>
</span>
)
}
{
categories.length > 0 && (
<span class="bl_categ">
{" "}
{categories.map((category, index) => (
<>
<a href={categoryHref(entry, category)} rel="tag">{category}</a>
{index < categories.length - 1 ? ", " : " "}
</>
))}
</span>
)
}
</div>
<div class="entry-content">
<p>{excerptFromBody(entry.body)}</p>
</div>
{
tags.length > 0 && (
<footer class="entry-meta">
<div class="footer-tags">
<span class="bl_posted">Tagged</span>&nbsp;{" "}
{tags.map((tag, index) => (
<>
<a href={tagHref(tag)} rel="tag">{tag}</a>
{index < tags.length - 1 ? ", " : "."}
</>
))}
</div>
</footer>
)
}
</article>
);
})
}
</div>
{
totalPages > 1 && pageHref && (
<div class="pagination_container">
<nav class="pagination" aria-label="Archive pagination">
{currentPage > 1 && <a href={pageHref(currentPage - 1)}>&lsaquo;</a>}
{Array.from({ length: totalPages }, (_, index) => index + 1).map((page) =>
page === currentPage ? <span class="current">{page}</span> : <a href={pageHref(page)} class="inactive">{page}</a>
)}
{currentPage < totalPages && <a href={pageHref(currentPage + 1)}>&rsaquo;</a>}
</nav>
</div>
)
}
</div>
<SiteSidebar />
</section>
<div style="clear:both;"></div>
</div>
</div>
</SiteLayout>

View file

@ -1,19 +0,0 @@
---
const { title, target } = Astro.props;
---
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="refresh" content={`0; url=${target}`} />
<link rel="canonical" href={target} />
<title>{title}</title>
<script is:inline set:html={`window.location.replace(${JSON.stringify(target)});`}></script>
</head>
<body>
<p>This page has moved to <a href={target}>{target}</a>.</p>
</body>
</html>

View file

@ -1,134 +0,0 @@
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(/&amp;/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`;
}

View file

@ -1,15 +0,0 @@
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];
}

View file

@ -4,37 +4,16 @@ 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);
@ -58,7 +37,7 @@ export function routeFromRelativePath(relativePath: string): string {
}
export function isMigratedHtmlPage(relativePath: string): boolean {
return migratedHtmlPages.has(relativePath) || migratedHtmlPrefixes.some((prefix) => relativePath.startsWith(prefix));
return migratedHtmlPages.has(relativePath);
}
export function sourcePathFromRoute(route = ""): string {

View file

@ -1,6 +0,0 @@
---
import LegacyRedirectPage from "../components/LegacyRedirectPage.astro";
---
<LegacyRedirectPage title="2013 Sunday Services Archive - FFWPU Ireland" target="/archive-sunday-services-2013.html" />

View file

@ -1,6 +0,0 @@
---
import LegacyRedirectPage from "../components/LegacyRedirectPage.astro";
---
<LegacyRedirectPage title="2014 Sunday Services Archive - FFWPU Ireland" target="/archive-sunday-services-2014.html" />

View file

@ -1,6 +0,0 @@
---
import LegacyRedirectPage from "../components/LegacyRedirectPage.astro";
---
<LegacyRedirectPage title="2015 Sunday Services Archive - FFWPU Ireland" target="/archive-sunday-services-2015.html" />

View file

@ -1,6 +0,0 @@
---
import LegacyRedirectPage from "../components/LegacyRedirectPage.astro";
---
<LegacyRedirectPage title="2016 Sunday Services Archive - FFWPU Ireland" target="/archive-sunday-services-2016.html" />

View file

@ -1,6 +0,0 @@
---
import LegacyRedirectPage from "../components/LegacyRedirectPage.astro";
---
<LegacyRedirectPage title="2017 Sunday Services Archive - FFWPU Ireland" target="/archive-sunday-services-2017.html" />

View file

@ -1,6 +0,0 @@
---
import LegacyRedirectPage from "../components/LegacyRedirectPage.astro";
---
<LegacyRedirectPage title="2018 Sunday Services Archive - FFWPU Ireland" target="/archive-sunday-services-2018.html" />

View file

@ -1,18 +0,0 @@
---
import SiteLayout from "../components/SiteLayout.astro";
import TwoColumnPage from "../components/TwoColumnPage.astro";
import { legacyPageArticle } from "../lib/legacy-page";
const articleHtml = legacyPageArticle("about-us-organizations.html");
---
<SiteLayout
title="Organizations &#8211; FFWPU Ireland"
description="Explore organizations connected with Rev. Sun Myung Moon and Dr. Hak Ja Han Moon, including UPF, WFWP, IRFF, and the Unification Church."
bodyClass="page-template page-template-templates page-template-template-twocolumns-right page-template-templatestemplate-twocolumns-right-php page page-id-124 page-child parent-pageid-29 custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left"
pathname="/about-us-organizations.html"
canonical="/about-us-organizations.html"
>
<TwoColumnPage articleHtml={articleHtml} />
</SiteLayout>

View file

@ -1,12 +0,0 @@
---
import SiteLayout from "../components/SiteLayout.astro";
import TwoColumnPage from "../components/TwoColumnPage.astro";
import { legacyPageArticle } from "../lib/legacy-page";
const articleHtml = legacyPageArticle("archive-sunday-services-2013.html");
---
<SiteLayout title="2013 Sunday Service Archive &#8211; FFWPU Ireland" description="Archived FFWPU Ireland Sunday service videos from 2013." bodyClass="page-template-default page page-id-405 custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left" pathname="/archive-sunday-services-2013.html" canonical="/archive-sunday-services-2013.html">
<TwoColumnPage articleHtml={articleHtml} />
</SiteLayout>

View file

@ -1,12 +0,0 @@
---
import SiteLayout from "../components/SiteLayout.astro";
import TwoColumnPage from "../components/TwoColumnPage.astro";
import { legacyPageArticle } from "../lib/legacy-page";
const articleHtml = legacyPageArticle("archive-sunday-services-2014.html");
---
<SiteLayout title="2014 Sunday Services &#8211; FFWPU Ireland" description="Archived FFWPU Ireland Sunday service videos from 2014." bodyClass="page-template-default page page-id-403 custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left" pathname="/archive-sunday-services-2014.html" canonical="/archive-sunday-services-2014.html">
<TwoColumnPage articleHtml={articleHtml} />
</SiteLayout>

View file

@ -1,12 +0,0 @@
---
import SiteLayout from "../components/SiteLayout.astro";
import TwoColumnPage from "../components/TwoColumnPage.astro";
import { legacyPageArticle } from "../lib/legacy-page";
const articleHtml = legacyPageArticle("archive-sunday-services-2015.html");
---
<SiteLayout title="2015 Sunday Services Archive &#8211; FFWPU Ireland" description="Archived FFWPU Ireland Sunday service videos from 2015." bodyClass="page-template-default page page-id-398 custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left" pathname="/archive-sunday-services-2015.html" canonical="/archive-sunday-services-2015.html">
<TwoColumnPage articleHtml={articleHtml} />
</SiteLayout>

View file

@ -1,12 +0,0 @@
---
import SiteLayout from "../components/SiteLayout.astro";
import TwoColumnPage from "../components/TwoColumnPage.astro";
import { legacyPageArticle } from "../lib/legacy-page";
const articleHtml = legacyPageArticle("archive-sunday-services-2016.html");
---
<SiteLayout title="2016 Sunday Service Archive &#8211; FFWPU Ireland" description="Archived FFWPU Ireland Sunday service videos from 2016." bodyClass="page-template-default page page-id-396 custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left" pathname="/archive-sunday-services-2016.html" canonical="/archive-sunday-services-2016.html">
<TwoColumnPage articleHtml={articleHtml} />
</SiteLayout>

View file

@ -1,12 +0,0 @@
---
import SiteLayout from "../components/SiteLayout.astro";
import TwoColumnPage from "../components/TwoColumnPage.astro";
import { legacyPageArticle } from "../lib/legacy-page";
const articleHtml = legacyPageArticle("archive-sunday-services-2017.html");
---
<SiteLayout title="2017 Sunday Service Archive &#8211; FFWPU Ireland" description="Archived FFWPU Ireland Sunday service videos from 2017." bodyClass="page-template-default page page-id-394 custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left" pathname="/archive-sunday-services-2017.html" canonical="/archive-sunday-services-2017.html">
<TwoColumnPage articleHtml={articleHtml} />
</SiteLayout>

View file

@ -1,12 +0,0 @@
---
import SiteLayout from "../components/SiteLayout.astro";
import TwoColumnPage from "../components/TwoColumnPage.astro";
import { legacyPageArticle } from "../lib/legacy-page";
const articleHtml = legacyPageArticle("archive-sunday-services-2018.html");
---
<SiteLayout title="2018 Sunday Service Archive &#8211; FFWPU Ireland" description="Archived FFWPU Ireland Sunday service videos from 2018." bodyClass="page-template-default page page-id-390 custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left" pathname="/archive-sunday-services-2018.html" canonical="/archive-sunday-services-2018.html">
<TwoColumnPage articleHtml={articleHtml} />
</SiteLayout>

View file

@ -1,16 +0,0 @@
---
import LegacyRedirectPage from "../../../../components/LegacyRedirectPage.astro";
export function getStaticPaths() {
const years = ["2013", "2014", "2015", "2016", "2017", "2018"];
return years.map((year) => ({
params: { year },
props: { year },
}));
}
const { year } = Astro.props;
---
<LegacyRedirectPage title={`${year} Sunday Services Archive - FFWPU Ireland`} target={`/archive-sunday-services-${year}.html`} />

View file

@ -1,28 +0,0 @@
---
import ArchiveListPage from "../../../components/ArchiveListPage.astro";
import { blogCategorySlug, getArchiveEntries, uniqueSorted } from "../../../lib/archive";
export async function getStaticPaths() {
const entries = await getArchiveEntries("blog");
const categories = uniqueSorted(entries.flatMap((entry) => entry.data.categories ?? []));
return categories.map((category) => ({
params: { category: blogCategorySlug(category) },
props: {
category,
entries: entries.filter((entry) => (entry.data.categories ?? []).includes(category)),
},
}));
}
const { category, entries } = Astro.props;
---
<ArchiveListPage
title={`Category: ${category}`}
heading={`Category: <span>${category}</span>`}
description={`Browse FFWPU Ireland blog posts in the ${category} category.`}
pathname={`/blog/categories/${blogCategorySlug(category)}.html`}
entries={entries}
/>

View file

@ -1,14 +0,0 @@
---
import ArchiveListPage from "../../components/ArchiveListPage.astro";
import { getArchiveEntries } from "../../lib/archive";
const entries = await getArchiveEntries("blog");
---
<ArchiveListPage
title="Blog"
heading="Blog"
description="Browse FFWPU Ireland blog posts, announcements, event notes, and news."
pathname="/blog.html"
entries={entries}
/>

View file

@ -1,28 +0,0 @@
---
import ArchiveListPage from "../../../components/ArchiveListPage.astro";
import { blogTagSlug, getArchiveEntries, uniqueSorted } from "../../../lib/archive";
export async function getStaticPaths() {
const entries = await getArchiveEntries("blog");
const tags = uniqueSorted(entries.flatMap((entry) => entry.data.tags ?? []));
return tags.map((tag) => ({
params: { tag: blogTagSlug(tag) },
props: {
tag,
entries: entries.filter((entry) => (entry.data.tags ?? []).includes(tag)),
},
}));
}
const { tag, entries } = Astro.props;
---
<ArchiveListPage
title={`Tag: ${tag}`}
heading={`Tag: <span>${tag}</span>`}
description={`Browse FFWPU Ireland blog posts tagged ${tag}.`}
pathname={`/blog/tags/${blogTagSlug(tag)}.html`}
entries={entries}
/>

View file

@ -1,20 +0,0 @@
---
import SiteLayout from "../components/SiteLayout.astro";
import TwoColumnPage from "../components/TwoColumnPage.astro";
import { legacyPageArticle } from "../lib/legacy-page";
const articleHtml = legacyPageArticle("register.html");
---
<SiteLayout
title="Marriage Blessing Celebration &#8211; FFWPU Ireland"
description="Marriage Blessing Celebration event details and registration information from FFWPU Ireland."
bodyClass="page-template-default page page-id-2522 custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left"
pathname="/register.html"
canonical="/register.html"
>
<link slot="head" rel="stylesheet" href="/assets/vendor/forms/public/assets/css/visual-form-builder.min.css?ver=3.0.9" type="text/css" media="all" />
<link slot="head" rel="stylesheet" href="/assets/vendor/forms/public/assets/css/smoothness/jquery-ui-1.10.3.min.css?ver=3.0.9" type="text/css" media="all" />
<TwoColumnPage articleHtml={articleHtml} />
</SiteLayout>

View file

@ -1,53 +0,0 @@
---
import ArchiveListPage from "../../../components/ArchiveListPage.astro";
import { getArchiveEntries, speechCategorySlug, uniqueSorted } from "../../../lib/archive";
function pageSlug(baseSlug, page) {
return page === 1 ? baseSlug : `${baseSlug}-page-${page}`;
}
function pageHref(baseSlug) {
return (page) => `/speeches/categories/${pageSlug(baseSlug, page)}.html`;
}
export async function getStaticPaths() {
const pageSize = 10;
const entries = await getArchiveEntries("speech");
const categories = uniqueSorted(entries.flatMap((entry) => entry.data.categories ?? []));
return categories.flatMap((category) => {
const baseSlug = speechCategorySlug(category);
const categoryEntries = entries.filter((entry) => (entry.data.categories ?? []).includes(category));
const totalPages = Math.max(1, Math.ceil(categoryEntries.length / pageSize));
return Array.from({ length: totalPages }, (_, index) => {
const currentPage = index + 1;
const currentSlug = currentPage === 1 ? baseSlug : `${baseSlug}-page-${currentPage}`;
return {
params: { category: currentSlug },
props: {
category,
baseSlug,
currentPage,
totalPages,
entries: categoryEntries.slice(index * pageSize, index * pageSize + pageSize),
},
};
});
});
}
const { category, baseSlug, currentPage, entries, totalPages } = Astro.props;
const title = `Category: ${category}`;
---
<ArchiveListPage
title={title}
heading={`Category: <span>${category}</span>`}
description={`Browse FFWPU Ireland speeches in ${category}.`}
pathname={`/speeches/categories/${pageSlug(baseSlug, currentPage)}.html`}
entries={entries}
currentPage={currentPage}
totalPages={totalPages}
pageHref={pageHref(baseSlug)}
/>

View file

@ -1,56 +0,0 @@
---
import SiteLayout from "../../../components/SiteLayout.astro";
import { excerptFromBody, getArchiveEntries, uniqueSorted } from "../../../lib/archive";
export async function getStaticPaths() {
const entries = await getArchiveEntries("speech");
const years = uniqueSorted(entries.map((entry) => entry.data.speechYear ?? "").filter(Boolean));
return years.map((year) => ({
params: { year },
props: {
year,
entries: entries.filter((entry) => entry.data.speechYear === year),
},
}));
}
const { year, entries } = Astro.props;
---
<SiteLayout
title={`Speeches by Rev. Dr. Sun Myung Moon ${year} &#8211; FFWPU Ireland`}
description={`Browse FFWPU Ireland speech archive entries from ${year}.`}
bodyClass="page-template-default page custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left"
pathname={`/speeches/rev-dr-sun-myung-moon/${year}.html`}
canonical={`/speeches/rev-dr-sun-myung-moon/${year}.html`}
>
<div id="main">
<div id="forbottom">
<div style="clear:both;"> </div>
<section id="container" class="one-column">
<div id="content" role="main">
<div class="post page type-page status-publish hentry">
<h1 class="entry-title">Speeches by Rev. Dr. Sun Myung Moon {year}</h1>
<div class="entry-content">
<ul class="speech-year-list">
{
entries.map((entry) => (
<li>
<a href={entry.data.source}>{entry.data.title ?? "Untitled"}</a>
<div class="post-excerpt">{excerptFromBody(entry.body, 150)}</div>
</li>
))
}
</ul>
</div>
</div>
</div>
</section>
<div style="clear:both;"></div>
</div>
</div>
</SiteLayout>