Modernize frontend assets and security baseline
All checks were successful
Publish static bundles / publish (push) Successful in 3m19s

This commit is contained in:
Loyyd 2026-07-15 10:28:06 +02:00
parent 33d9509678
commit 1d55bdb691
995 changed files with 10228 additions and 16769 deletions

View file

@ -12,15 +12,30 @@ const {
robots = "max-image-preview:large",
ogType = "website",
image = "/assets/uploads/2013/10/BannerFamilyFed_23_10c1.jpg",
parabolaSettings = { masonry: "0", magazine: "0", mobile: "1", fitvids: "1" },
} = Astro.props;
const parabolaSettingsScript = `var parabola_settings = ${JSON.stringify(parabolaSettings)};`;
const siteOrigin = Astro.site?.origin ?? "https://familyfed.ie";
const absoluteUrl = (value) => value ? new URL(value, siteOrigin).toString() : undefined;
const canonicalUrl = absoluteUrl(stripHtmlExtensionFromInternalUrl(canonical ?? pathname));
const imageUrl = absoluteUrl(image);
const plausibleDomain = import.meta.env.PUBLIC_PLAUSIBLE_DOMAIN ?? "";
const plausibleScriptSrc = import.meta.env.PUBLIC_PLAUSIBLE_SCRIPT_SRC ?? "https://plausible.io/js/script.js";
const allowedScriptOrigins = new Set(["'self'", "'unsafe-inline'", "https://static.cloudflareinsights.com"]);
if (plausibleDomain) {
allowedScriptOrigins.add(new URL(plausibleScriptSrc, siteOrigin).origin);
}
const contentSecurityPolicy = [
"default-src 'self'",
"base-uri 'self'",
"object-src 'none'",
"img-src 'self' data: https:",
"font-src 'self' data:",
"style-src 'self' 'unsafe-inline'",
`script-src ${Array.from(allowedScriptOrigins).join(" ")}`,
"connect-src 'self' https:",
"frame-src https://www.youtube.com https://www.youtube-nocookie.com https://player.vimeo.com",
"form-action 'self' mailto: https:",
"upgrade-insecure-requests",
].join("; ");
const metaTitle = title
.replace(/–|–/g, "-")
.replace(/‘|’|‘|’/g, "'")
@ -33,6 +48,8 @@ const metaTitle = title
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Security-Policy" content={contentSecurityPolicy} />
<meta name="referrer" content="strict-origin-when-cross-origin" />
<title set:html={title} />
{description && <meta name="description" content={description} />}
{robots && <meta name="robots" content={robots} />}
@ -45,7 +62,15 @@ const metaTitle = title
<meta name="twitter:card" content="summary_large_image" />
<link rel="icon" href="/assets/icons/familyfed-favicon.png" type="image/png" />
<link rel="apple-touch-icon" href="/assets/icons/familyfed-favicon.png" />
<link rel="preload" href="/assets/uploads/2013/10/BannerFamilyFed_23_10c1.webp" as="image" type="image/webp" fetchpriority="high" />
<link
rel="preload"
href="/assets/uploads/2013/10/BannerFamilyFed_23_10c1-1050.avif"
imagesrcset="/assets/uploads/2013/10/BannerFamilyFed_23_10c1-480.avif 480w, /assets/uploads/2013/10/BannerFamilyFed_23_10c1-768.avif 768w, /assets/uploads/2013/10/BannerFamilyFed_23_10c1-1050.avif 1050w"
imagesizes="(max-width: 1050px) 100vw, 1050px"
as="image"
type="image/avif"
fetchpriority="high"
/>
<link rel="preload" href="/assets/theme/parabola/fonts/OpenSans-Regular-webfont.woff" as="font" type="font/woff" crossorigin />
<link rel="preload" href="/assets/theme/parabola/fonts/BebasNeue-webfont.woff" as="font" type="font/woff" crossorigin />
<link rel="preload" href="/assets/theme/parabola/fonts/yanonekaffeesatz-regular-webfont.woff" as="font" type="font/woff" crossorigin />
@ -54,24 +79,23 @@ const metaTitle = title
<link rel="stylesheet" id="parabola-fonts-css" href="/assets/theme/parabola/fonts/fontfaces.css?ver=2.4.1-perf1" type="text/css" media="all" />
<link rel="stylesheet" id="parabola-style-css" href="/assets/theme/parabola/style.css?ver=2.4.1" type="text/css" media="all" />
<link rel="stylesheet" id="familyfedie-theme-css" href="/css/theme.css" type="text/css" media="all" />
<link rel="stylesheet" id="familyfedie-site-css" href="/css/site.css?ver=20260710-4" type="text/css" media="all" />
<link rel="stylesheet" id="familyfedie-site-css" href="/css/site.css?ver=20260715-1" type="text/css" media="all" />
<link rel="stylesheet" id="parabola-mobile-css" href="/assets/theme/parabola/styles/style-mobile.css?ver=2.4.1" type="text/css" media="all" />
{plausibleDomain && <script defer data-domain={plausibleDomain} src={plausibleScriptSrc}></script>}
<script is:inline defer type="text/javascript" src="/js/jquery.min.js?ver=2.0.2" id="jquery-js"></script>
<script is:inline type="text/javascript" id="parabola-frontend-js-extra" set:html={parabolaSettingsScript}></script>
<script is:inline defer type="text/javascript" src="/assets/theme/parabola/js/frontend.js?ver=2.4.1" id="parabola-frontend-js"></script>
<script is:inline defer src="/js/site.js?ver=20260715-1"></script>
<slot name="head" />
{canonicalUrl && <link rel="canonical" href={canonicalUrl} />}
</head>
<body class={bodyClass}>
<div id="toTop"> </div>
<button id="toTop" type="button" aria-label="Back to top"></button>
<div id="wrapper" class="hfeed">
<div id="header-full">
<header id="header">
<div id="masthead">
<div id="branding" role="banner">
<picture>
<source type="image/webp" srcset="/assets/uploads/2013/10/BannerFamilyFed_23_10c1.webp" />
<source type="image/avif" srcset="/assets/uploads/2013/10/BannerFamilyFed_23_10c1-480.avif 480w, /assets/uploads/2013/10/BannerFamilyFed_23_10c1-768.avif 768w, /assets/uploads/2013/10/BannerFamilyFed_23_10c1-1050.avif 1050w" sizes="(max-width: 1050px) 100vw, 1050px" />
<source type="image/webp" srcset="/assets/uploads/2013/10/BannerFamilyFed_23_10c1-480.webp 480w, /assets/uploads/2013/10/BannerFamilyFed_23_10c1-768.webp 768w, /assets/uploads/2013/10/BannerFamilyFed_23_10c1-1050.webp 1050w" sizes="(max-width: 1050px) 100vw, 1050px" />
<img id="bg_image" alt="Family Federation for World Peace and Unification Ireland" src="/assets/uploads/2013/10/BannerFamilyFed_23_10c1.jpg" width="1050" height="120" fetchpriority="high" />
</picture>
<div id="header-container">
@ -91,13 +115,6 @@ const metaTitle = title
<SiteFooter />
</div>
<script is:inline>
(function (body) {
"use strict";
body.className = body.className.replace(/\btribe-no-js\b/, "tribe-js");
})(document.body);
</script>
<script type="text/javascript">var cryout_global_content_width = 800;</script>
<slot name="scripts" />
</body>
</html>

View file

@ -9,6 +9,7 @@
<article class="home-carousel-slide is-active" data-carousel-slide aria-label="1 of 3" aria-roledescription="slide" aria-hidden="false">
<a href="/the-founders.html">
<picture>
<source type="image/avif" srcset="/assets/uploads/2013/10/TrueParentsSlider-640.avif 640w, /assets/uploads/2013/10/TrueParentsSlider-1050.avif 1050w" sizes="(max-width: 1050px) 100vw, 1050px" />
<source type="image/webp" srcset="/assets/uploads/2013/10/TrueParentsSlider-640.webp 640w, /assets/uploads/2013/10/TrueParentsSlider-1050.webp 1050w" sizes="(max-width: 1050px) 100vw, 1050px" />
<img src="/assets/uploads/2013/10/TrueParentsSlider.jpg" alt="Rev. Sun Myung Moon and Dr. Hak Ja Han Moon" width="1200" height="350" fetchpriority="high" />
</picture>
@ -17,6 +18,7 @@
<article class="home-carousel-slide" data-carousel-slide aria-label="2 of 3" aria-roledescription="slide" aria-hidden="true">
<a href="/about-us-organizations.html" tabindex="-1">
<picture>
<source type="image/avif" srcset="/assets/uploads/2013/10/Little-Angels-Presentationlight1-640.avif 640w, /assets/uploads/2013/10/Little-Angels-Presentationlight1-1050.avif 1050w" sizes="(max-width: 1050px) 100vw, 1050px" />
<source type="image/webp" srcset="/assets/uploads/2013/10/Little-Angels-Presentationlight1-640.webp 640w, /assets/uploads/2013/10/Little-Angels-Presentationlight1-1050.webp 1050w" sizes="(max-width: 1050px) 100vw, 1050px" />
<img src="/assets/uploads/2013/10/Little-Angels-Presentationlight1.jpg" alt="The Little Angels children's folk ballet performance" width="1200" height="350" loading="lazy" decoding="async" />
</picture>
@ -26,6 +28,7 @@
<article class="home-carousel-slide" data-carousel-slide aria-label="3 of 3" aria-roledescription="slide" aria-hidden="true">
<a href="/the-founders.html" tabindex="-1">
<picture>
<source type="image/avif" srcset="/assets/uploads/2013/10/father-Seung-Hwa_Presentation-640.avif 640w, /assets/uploads/2013/10/father-Seung-Hwa_Presentation-1050.avif 1050w" sizes="(max-width: 1050px) 100vw, 1050px" />
<source type="image/webp" srcset="/assets/uploads/2013/10/father-Seung-Hwa_Presentation-640.webp 640w, /assets/uploads/2013/10/father-Seung-Hwa_Presentation-1050.webp 1050w" sizes="(max-width: 1050px) 100vw, 1050px" />
<img src="/assets/uploads/2013/10/father-Seung-Hwa_Presentation.jpg" alt="Rev. Sun Myung Moon" width="1200" height="350" loading="lazy" decoding="async" />
</picture>
@ -47,6 +50,7 @@
<a href="/the-founders.html" >
<div class="column-image">
<picture>
<source type="image/avif" srcset="/assets/uploads/2013/10/True_Parents-336.avif 336w, /assets/uploads/2013/10/True_Parents-483.avif 483w" sizes="(max-width: 800px) 100vw, 336px" />
<source type="image/webp" srcset="/assets/uploads/2013/10/True_Parents-336.webp 336w, /assets/uploads/2013/10/True_Parents-483.webp 483w" sizes="(max-width: 800px) 100vw, 336px" />
<img src="/assets/uploads/2013/10/True_Parents.jpg" id="columnImage1" alt="Rev. Sun Myung Moon and Dr. Hak Ja Han Moon, founders of FFWPU International" width="483" height="329" fetchpriority="high" decoding="async" />
</picture>
@ -68,7 +72,8 @@
<a href="/videos.html" >
<div class="column-image">
<picture>
<source type="image/webp" srcset="/assets/uploads/2013/10/DP-Screenshot-336.webp 336w, /assets/uploads/2013/10/DP-Screenshot-672.webp 672w" sizes="(max-width: 800px) 100vw, 336px" />
<source type="image/avif" srcset="/assets/uploads/2013/10/DP-Screenshot-336.avif 336w, /assets/uploads/2013/10/DP-Screenshot-672.avif 672w, /assets/uploads/2013/10/DP-Screenshot-900.avif 900w" sizes="(max-width: 800px) 100vw, 336px" />
<source type="image/webp" srcset="/assets/uploads/2013/10/DP-Screenshot-336.webp 336w, /assets/uploads/2013/10/DP-Screenshot-672.webp 672w, /assets/uploads/2013/10/DP-Screenshot-900.webp 900w" sizes="(max-width: 800px) 100vw, 336px" />
<img src="/assets/uploads/2013/10/DP-Screenshot.jpg" id="columnImage2" alt="Divine Principle video presentation screenshot" width="900" height="500" decoding="async" />
</picture>
<h3 class='column-header-image'>The Divine Principle and Other teachings.</h3>
@ -89,6 +94,7 @@
<a href="/about-us-organizations.html" >
<div class="column-image">
<picture>
<source type="image/avif" srcset="/assets/uploads/2013/10/UPF-Prayer-Evening-336.avif 336w, /assets/uploads/2013/10/UPF-Prayer-Evening-656.avif 656w" sizes="(max-width: 800px) 100vw, 336px" />
<source type="image/webp" srcset="/assets/uploads/2013/10/UPF-Prayer-Evening-336.webp 336w, /assets/uploads/2013/10/UPF-Prayer-Evening-656.webp 656w" sizes="(max-width: 800px) 100vw, 336px" />
<img src="/assets/uploads/2013/10/UPF-Prayer-Evening.jpg" id="columnImage3" alt="UPF prayer evening gathering" width="656" height="448" decoding="async" />
</picture>

View file

@ -1,6 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { legacyHtmlRoot } from "./static-pages";
import { addResponsiveImageSources } from "./responsive-images";
export function legacyPageArticle(relativePath: string): string {
const html = fs.readFileSync(path.join(legacyHtmlRoot, relativePath), "utf8");
@ -10,6 +11,5 @@ export function legacyPageArticle(relativePath: string): string {
throw new Error(`Could not find page article in ${relativePath}`);
}
return match[0];
return addResponsiveImageSources(match[0]);
}

View file

@ -0,0 +1,35 @@
type ResponsiveImage = {
path: string;
widths: number[];
sizes: string;
};
const responsiveImages: ResponsiveImage[] = [
{ path: "/assets/uploads/2013/10/Logo_IRFF_Fit3.png", widths: [130], sizes: "117px" },
{ path: "/assets/uploads/2013/10/Logo_UC_Fit31.png", widths: [130], sizes: "117px" },
{ path: "/assets/uploads/2013/10/Logo_UPF_fit3.png", widths: [130], sizes: "117px" },
{ path: "/assets/uploads/2013/10/Logo_WFWP_Fit3.png", widths: [130], sizes: "117px" },
{ path: "/assets/uploads/2015/08/Fathers-3rd-SeongHwa-flier.png", widths: [320, 640, 724], sizes: "(max-width: 724px) 100vw, 724px" },
{ path: "/assets/uploads/2019/04/Blessing-PDF-for-BJD-June-2019.png", widths: [320, 640, 875], sizes: "(max-width: 875px) 100vw, 875px" },
];
function sourceSet(image: ResponsiveImage, format: "avif" | "webp") {
const parsed = image.path.replace(/\.[^.]+$/, "");
return image.widths.map((width) => `${parsed}-${width}.${format} ${width}w`).join(", ");
}
export function addResponsiveImageSources(html: string): string {
return responsiveImages.reduce((output, image) => {
const escapedPath = image.path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const imagePattern = new RegExp(`<img\\b(?=[^>]*\\bsrc=["']${escapedPath}["'])[^>]*>`, "gi");
return output.replace(imagePattern, (tag) => {
const avif = sourceSet(image, "avif");
const webp = sourceSet(image, "webp");
const fallback = tag
.replace(/\s+srcset=["'][^"']*["']/i, "")
.replace(/\s+sizes=["'][^"']*["']/i, "");
return `<picture><source type="image/avif" srcset="${avif}" sizes="${image.sizes}" /><source type="image/webp" srcset="${webp}" sizes="${image.sizes}" />${fallback}</picture>`;
});
}, html);
}

View file

@ -1,5 +1,6 @@
import fs from "node:fs/promises";
import { contentSourceRoutes } from "../lib/content-routes";
import { addResponsiveImageSources } from "../lib/responsive-images";
import { isMigratedHtmlPage, relativeWebsitePath, routeFromRelativePath, sourcePathFromRoute, walkHtmlFiles } from "../lib/static-pages";
import { normalizeInternalHtmlLinks } from "../lib/urls";
@ -17,7 +18,7 @@ export async function getStaticPaths() {
}
export async function GET({ params }: { params: { route?: string } }) {
const html = normalizeInternalHtmlLinks(await fs.readFile(sourcePathFromRoute(params.route), "utf8"));
const html = addResponsiveImageSources(normalizeInternalHtmlLinks(await fs.readFile(sourcePathFromRoute(params.route), "utf8")));
return new Response(html, {
headers: {

View file

@ -12,15 +12,14 @@ const normalizedMainHtml = normalizeInternalHtmlLinks(mainHtml);
bodyClass="home blog custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles magazine-layout parabola-menu-left"
pathname="/index"
canonical="/index"
parabolaSettings={{ masonry: "0", magazine: "0", mobile: "1", fitvids: "1" }}
>
<link
slot="head"
rel="preload"
as="image"
type="image/webp"
href="/assets/uploads/2013/10/TrueParentsSlider-1050.webp"
imagesrcset="/assets/uploads/2013/10/TrueParentsSlider-640.webp 640w, /assets/uploads/2013/10/TrueParentsSlider-1050.webp 1050w"
type="image/avif"
href="/assets/uploads/2013/10/TrueParentsSlider-1050.avif"
imagesrcset="/assets/uploads/2013/10/TrueParentsSlider-640.avif 640w, /assets/uploads/2013/10/TrueParentsSlider-1050.avif 1050w"
imagesizes="(max-width: 1050px) 100vw, 1050px"
fetchpriority="high"
/>