fix: restore missing live-site page imagery
- recover and self-host HubSpot-injected page hero assets - map source heroes to page and library layouts - restore the consultation form background - add page imagery auditing - update asset inventory and migration documentation
@@ -118,6 +118,7 @@ Astro prints the preview URL, normally `http://localhost:4321`.
|
|||||||
```sh
|
```sh
|
||||||
npm run build
|
npm run build
|
||||||
npm run audit:links
|
npm run audit:links
|
||||||
|
npm run audit:images
|
||||||
```
|
```
|
||||||
|
|
||||||
The link audit reads `dist/` after a successful build. If rendered output is
|
The link audit reads `dist/` after a successful build. If rendered output is
|
||||||
@@ -281,6 +282,7 @@ npm run generate:sitemap
|
|||||||
npm run generate:redirects
|
npm run generate:redirects
|
||||||
npm run build
|
npm run build
|
||||||
npm run audit:links
|
npm run audit:links
|
||||||
|
npm run audit:images
|
||||||
```
|
```
|
||||||
|
|
||||||
Extraction regenerates content files, copied assets, and inventories. Review
|
Extraction regenerates content files, copied assets, and inventories. Review
|
||||||
@@ -332,6 +334,7 @@ Build first:
|
|||||||
```sh
|
```sh
|
||||||
npm run build
|
npm run build
|
||||||
npm run audit:links
|
npm run audit:links
|
||||||
|
npm run audit:images
|
||||||
```
|
```
|
||||||
|
|
||||||
### A content page is missing
|
### A content page is missing
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"extract:full": "node tools/extract-site.mjs",
|
"extract:full": "node tools/extract-site.mjs",
|
||||||
"crawl:live": "node tools/crawl-live-site.mjs",
|
"crawl:live": "node tools/crawl-live-site.mjs",
|
||||||
"audit:links": "node tools/audit-links.mjs",
|
"audit:links": "node tools/audit-links.mjs",
|
||||||
|
"audit:images": "node tools/audit-page-imagery.mjs",
|
||||||
"generate:sitemap": "node tools/generate-sitemap.mjs",
|
"generate:sitemap": "node tools/generate-sitemap.mjs",
|
||||||
"generate:redirects": "node tools/generate-redirects.mjs"
|
"generate:redirects": "node tools/generate-redirects.mjs"
|
||||||
},
|
},
|
||||||
|
|||||||
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -170,3 +170,21 @@ source,target,size,kind
|
|||||||
"hubfs/team-timirah-clay.webp","public/assets/images/team-timirah-clay.webp","16496","images"
|
"hubfs/team-timirah-clay.webp","public/assets/images/team-timirah-clay.webp","16496","images"
|
||||||
"hubfs/toddler-bcba-support.webp","public/assets/images/toddler-bcba-support.webp","11182","images"
|
"hubfs/toddler-bcba-support.webp","public/assets/images/toddler-bcba-support.webp","11182","images"
|
||||||
"hubfs/united-healthcare-logo-1.webp","public/assets/images/united-healthcare-logo-1.webp","4368","images"
|
"hubfs/united-healthcare-logo-1.webp","public/assets/images/united-healthcare-logo-1.webp","4368","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-aba-therapy-intake-process.webp","public/assets/images/hero-aba-therapy-intake-process.webp","14392","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-services-behavioral-aba.webp","public/assets/images/hero-services-behavioral-aba.webp","15330","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-about.webp","public/assets/images/hero-about.webp","24764","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-services-psychological.webp","public/assets/images/hero-services-psychological.webp","15490","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-careers.webp","public/assets/images/hero-careers.webp","24728","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-bg-blank.png","public/assets/images/hero-bg-blank.png","41772","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-client-forms.webp","public/assets/images/hero-client-forms.webp","13878","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-contact-aia.webp","public/assets/images/hero-contact-aia.webp","20230","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-ways-to-giveback.webp","public/assets/images/hero-ways-to-giveback.webp","11654","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-aba-employee-portal.webp","public/assets/images/hero-aba-employee-portal.webp","19798","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-faq.webp","public/assets/images/hero-faq.webp","14624","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-insurance-coverage-guide.webp","public/assets/images/hero-insurance-coverage-guide.webp","21624","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-services-sociological.webp","public/assets/images/hero-services-sociological.webp","16046","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-referrals.webp","public/assets/images/hero-referrals.webp","16646","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-pediatric-services.webp","public/assets/images/hero-pediatric-services.webp","18120","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-meet-the-aia-team.webp","public/assets/images/hero-meet-the-aia-team.webp","15310","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-schedule-aia-tour.webp","public/assets/images/hero-schedule-aia-tour.webp","13290","images"
|
||||||
|
"live:https://www.azinstitute4autism.com/hubfs/hero-library-index.webp","public/assets/images/hero-library-index.webp","14392","images"
|
||||||
|
|||||||
|
@@ -22,5 +22,10 @@
|
|||||||
- Repaired mirror-rewritten PDF, lightbox, CTA, and relative content links.
|
- Repaired mirror-rewritten PDF, lightbox, CTA, and relative content links.
|
||||||
- Limited language-switcher choices to translations that have generated routes.
|
- Limited language-switcher choices to translations that have generated routes.
|
||||||
- Verified and implemented the current production likes/views API contract.
|
- Verified and implemented the current production likes/views API contract.
|
||||||
|
- Recovered 18 live page-banner assets that the wget mirror missed because
|
||||||
|
HubSpot injected them through malformed inline `background-image` styles.
|
||||||
|
- Restored the live library banner and consultation form section background.
|
||||||
|
- Added a mapped-page-imagery audit to prevent missing visual assets from
|
||||||
|
silently passing the source link audit.
|
||||||
- Added language-qualified content collection IDs to prevent English, Spanish,
|
- Added language-qualified content collection IDs to prevent English, Spanish,
|
||||||
and Arabic entries with the same slug from overwriting each other.
|
and Arabic entries with the same slug from overwriting each other.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ family, team page, library indexes, and blog-post family.
|
|||||||
- 46 English, 12 Spanish, and 7 Arabic library posts.
|
- 46 English, 12 Spanish, and 7 Arabic library posts.
|
||||||
- 21 English, 9 Spanish, and 2 Arabic page records.
|
- 21 English, 9 Spanish, and 2 Arabic page records.
|
||||||
- One author record per language.
|
- One author record per language.
|
||||||
- 149 self-hosted images, 20 font files, and two PDF downloads.
|
- 167 self-hosted images, 20 font files, and two PDF downloads.
|
||||||
- Current June and May 2026 English library articles are included.
|
- Current June and May 2026 English library articles are included.
|
||||||
|
|
||||||
The raw mirror remains untouched. HubSpot-generated wrappers, analytics,
|
The raw mirror remains untouched. HubSpot-generated wrappers, analytics,
|
||||||
@@ -37,6 +37,9 @@ Implemented fidelity work includes:
|
|||||||
order using one reusable Astro component and self-hosted source assets.
|
order using one reusable Astro component and self-hosted source assets.
|
||||||
- Rebuilt service pages around the live compact title banner and editorial
|
- Rebuilt service pages around the live compact title banner and editorial
|
||||||
presentation, with current visible headings and working calls to action.
|
presentation, with current visible headings and working calls to action.
|
||||||
|
- Recovered and restored the live decorative hero imagery for all mapped
|
||||||
|
English and Spanish page routes plus every language's library index.
|
||||||
|
- Restored the consultation form section's injected background image.
|
||||||
- Added a dedicated live-derived team card grid rather than presenting the
|
- Added a dedicated live-derived team card grid rather than presenting the
|
||||||
extracted team content as a generic article.
|
extracted team content as a generic article.
|
||||||
- Rebuilt library indexes and blog-post presentation around the live sidebar,
|
- Rebuilt library indexes and blog-post presentation around the live sidebar,
|
||||||
@@ -109,6 +112,8 @@ unavailable.
|
|||||||
- `npm run audit:links`: passed with zero broken internal source links. The
|
- `npm run audit:links`: passed with zero broken internal source links. The
|
||||||
audit now checks generated routes, root-relative references, relative
|
audit now checks generated routes, root-relative references, relative
|
||||||
Markdown links, and public assets when rendered output is unavailable.
|
Markdown links, and public assets when rendered output is unavailable.
|
||||||
|
- `npm run audit:images`: passed with no missing mapped page banners, section
|
||||||
|
backgrounds, or blog featured images.
|
||||||
- `npm run generate:sitemap`: passed; generated 97 URLs.
|
- `npm run generate:sitemap`: passed; generated 97 URLs.
|
||||||
- `npm run generate:redirects`: passed.
|
- `npm run generate:redirects`: passed.
|
||||||
- All migration `.mjs` tools and the sandbox DNS helper pass `node --check`.
|
- All migration `.mjs` tools and the sandbox DNS helper pass `node --check`.
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Page Imagery Audit
|
||||||
|
|
||||||
|
Checked 84 page-banner, section-background, and blog-featured-image references.
|
||||||
|
|
||||||
|
No missing mapped page imagery was detected.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
const { title = 'Schedule Your Free Consultation' } = Astro.props;
|
const { title = 'Schedule Your Free Consultation', showBackground = false } = Astro.props;
|
||||||
---
|
---
|
||||||
<section class="form-section" aria-labelledby="form-title">
|
<section class:list={['form-section', { 'form-section-background': showBackground }]} aria-labelledby="form-title">
|
||||||
<div class="container form-grid">
|
<div class="container form-grid">
|
||||||
<div><p class="eyebrow">Get started</p><h2 id="form-title">{title}</h2><p>Tell our client advocates how we can help. Submission is disabled until a production form backend is selected.</p></div>
|
<div><p class="eyebrow">Get started</p><h2 id="form-title">{title}</h2><p>Tell our client advocates how we can help. Submission is disabled until a production form backend is selected.</p></div>
|
||||||
<form class="form" method="post" action="">
|
<form class="form" method="post" action="">
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export const pageHeroImages: Record<string, string> = {
|
||||||
|
'aba-therapy-intake-process': '/assets/images/hero-aba-therapy-intake-process.webp',
|
||||||
|
'aba-therapy': '/assets/images/hero-services-behavioral-aba.webp',
|
||||||
|
about: '/assets/images/hero-about.webp',
|
||||||
|
'autism-evaluations': '/assets/images/hero-services-psychological.webp',
|
||||||
|
careers: '/assets/images/hero-careers.webp',
|
||||||
|
'client-consultation': '/assets/images/hero-bg-blank.png',
|
||||||
|
'client-forms': '/assets/images/hero-client-forms.webp',
|
||||||
|
contact: '/assets/images/hero-contact-aia.webp',
|
||||||
|
'donate-autism-giveback': '/assets/images/hero-ways-to-giveback.webp',
|
||||||
|
'employee-portal': '/assets/images/hero-aba-employee-portal.webp',
|
||||||
|
faqs: '/assets/images/hero-faq.webp',
|
||||||
|
insurance: '/assets/images/hero-insurance-coverage-guide.webp',
|
||||||
|
'learner-social-club': '/assets/images/hero-services-sociological.webp',
|
||||||
|
'privacy-policy': '/assets/images/hero-bg-blank.png',
|
||||||
|
referrals: '/assets/images/hero-referrals.webp',
|
||||||
|
services: '/assets/images/hero-pediatric-services.webp',
|
||||||
|
team: '/assets/images/hero-meet-the-aia-team.webp',
|
||||||
|
tour: '/assets/images/hero-schedule-aia-tour.webp'
|
||||||
|
};
|
||||||
@@ -5,7 +5,7 @@ const languagePrefix = lang === 'en' ? '' : `/${lang}`;
|
|||||||
const canonical = `https://www.azinstitute4autism.com${languagePrefix}/library`;
|
const canonical = `https://www.azinstitute4autism.com${languagePrefix}/library`;
|
||||||
---
|
---
|
||||||
<BaseLayout title={title} description={description} canonical={canonical} lang={lang}>
|
<BaseLayout title={title} description={description} canonical={canonical} lang={lang}>
|
||||||
<header class="library-banner"><div class="container"><p class="script-label">Welcome to</p><h1>{title}</h1></div></header>
|
<header class="library-banner"><div class="container"><div class="library-banner-copy"><p class="script-label">Welcome to</p><h1>{title}</h1></div></div></header>
|
||||||
<section class="library-intro"><div class="container"><h2>Library</h2><p>{description}</p></div></section>
|
<section class="library-intro"><div class="container"><h2>Library</h2><p>{description}</p></div></section>
|
||||||
<div class="container section library-layout"><slot /></div>
|
<div class="container section library-layout"><slot /></div>
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import BaseLayout from './BaseLayout.astro';
|
import BaseLayout from './BaseLayout.astro';
|
||||||
import FormShell from '../components/FormShell.astro';
|
import FormShell from '../components/FormShell.astro';
|
||||||
import TeamPage from '../components/TeamPage.astro';
|
import TeamPage from '../components/TeamPage.astro';
|
||||||
|
import { pageHeroImages } from '../data/page-visuals';
|
||||||
const { entry } = Astro.props;
|
const { entry } = Astro.props;
|
||||||
const showForm = ['client-consultation', 'contact', 'schedule-consultation', 'referrals'].includes(entry.data.slug);
|
const showForm = ['client-consultation', 'contact', 'schedule-consultation', 'referrals'].includes(entry.data.slug);
|
||||||
const serviceTitles: Record<string, Record<string, string>> = {
|
const serviceTitles: Record<string, Record<string, string>> = {
|
||||||
@@ -44,13 +45,14 @@ const pageTitles: Record<string, Record<string, string>> = {
|
|||||||
};
|
};
|
||||||
const bannerTitle = serviceTitles[entry.data.lang]?.[entry.data.slug] || pageTitles[entry.data.lang]?.[entry.data.slug] || entry.data.title.split('|')[0].trim();
|
const bannerTitle = serviceTitles[entry.data.lang]?.[entry.data.slug] || pageTitles[entry.data.lang]?.[entry.data.slug] || entry.data.title.split('|')[0].trim();
|
||||||
const isService = Boolean(serviceTitles[entry.data.lang]?.[entry.data.slug]);
|
const isService = Boolean(serviceTitles[entry.data.lang]?.[entry.data.slug]);
|
||||||
|
const heroImage = pageHeroImages[entry.data.slug];
|
||||||
---
|
---
|
||||||
<BaseLayout title={entry.data.title} description={entry.data.description} canonical={entry.data.canonical} image={entry.data.featuredImage} lang={entry.data.lang}>
|
<BaseLayout title={entry.data.title} description={entry.data.description} canonical={entry.data.canonical} image={entry.data.featuredImage || heroImage} lang={entry.data.lang}>
|
||||||
<header class:list={['source-page-banner', { 'service-banner': isService }]}>
|
<header class:list={['source-page-banner', { 'has-source-image': heroImage, 'service-banner': isService }]} style={heroImage ? `background-image: url("${heroImage}")` : undefined}>
|
||||||
<div class="container"><h1>{bannerTitle}</h1></div>
|
<div class="container"><h1>{bannerTitle}</h1></div>
|
||||||
</header>
|
</header>
|
||||||
{entry.data.slug === 'team' && entry.data.lang === 'en'
|
{entry.data.slug === 'team' && entry.data.lang === 'en'
|
||||||
? <TeamPage />
|
? <TeamPage />
|
||||||
: <article class:list={['prose', 'source-page', 'container', { 'service-page': isService }]}><slot /></article>}
|
: <article class:list={['prose', 'source-page', 'container', { 'service-page': isService }]}><slot /></article>}
|
||||||
{showForm && <FormShell title={bannerTitle} />}
|
{showForm && <FormShell title={bannerTitle} showBackground={entry.data.slug === 'client-consultation'} />}
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|||||||
@@ -54,8 +54,10 @@
|
|||||||
.faq summary { cursor: pointer; font-weight: 700; }
|
.faq summary { cursor: pointer; font-weight: 700; }
|
||||||
.source-page-banner { background: var(--color-tint); padding-block: 4rem; text-align: center; }
|
.source-page-banner { background: var(--color-tint); padding-block: 4rem; text-align: center; }
|
||||||
.source-page-banner h1 { margin: 0; }
|
.source-page-banner h1 { margin: 0; }
|
||||||
.service-banner { background-color: #e8f1ee; background-image: radial-gradient(circle at 14% 45%, rgb(37 64 128 / 9%) 0 54px, transparent 55px), radial-gradient(circle at 28% 25%, rgb(37 64 128 / 10%) 0 22px, transparent 23px), radial-gradient(circle at 74% 50%, rgb(37 64 128 / 8%) 0 42px, transparent 43px); padding-block: 7rem; }
|
.source-page-banner.has-source-image { background-color: var(--color-tint); background-position: center; background-repeat: no-repeat; background-size: cover; padding-block: 10rem; text-align: left; }
|
||||||
.library-banner { background: var(--color-tint); padding-block: 5rem; text-align: center; }
|
.source-page-banner.has-source-image h1 { max-width: 600px; }
|
||||||
|
.library-banner { background-color: var(--color-tint); background-image: url('/assets/images/hero-library-index.webp'); background-position: center; background-repeat: no-repeat; background-size: cover; padding-block: 10rem; text-align: left; }
|
||||||
|
.library-banner-copy { max-width: 600px; }
|
||||||
.library-banner h1 { margin: 0; }
|
.library-banner h1 { margin: 0; }
|
||||||
.library-intro { background: var(--color-primary); color: white; padding-block: 3rem; }
|
.library-intro { background: var(--color-primary); color: white; padding-block: 3rem; }
|
||||||
.library-intro h2 { color: white; }
|
.library-intro h2 { color: white; }
|
||||||
@@ -140,5 +142,7 @@
|
|||||||
.blog-list .blog-card { grid-template-columns: 1fr; }
|
.blog-list .blog-card { grid-template-columns: 1fr; }
|
||||||
.article-featured { height: auto; }
|
.article-featured { height: auto; }
|
||||||
.team-grid { grid-template-columns: 1fr; }
|
.team-grid { grid-template-columns: 1fr; }
|
||||||
|
.source-page-banner.has-source-image, .library-banner { padding-block: 6.25rem; text-align: center; }
|
||||||
|
.source-page-banner.has-source-image h1, .library-banner-copy { margin-inline: auto; }
|
||||||
}
|
}
|
||||||
@media (min-width: 761px) and (max-width: 1050px) { .team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
@media (min-width: 761px) and (max-width: 1050px) { .team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
.form-section { background: var(--color-tint); padding-block: var(--space-xl); }
|
.form-section { background: var(--color-tint); padding-block: var(--space-xl); }
|
||||||
|
.form-section.form-section-background { background-image: url('/assets/images/rbt-toddler-play.webp'); background-position: center bottom; background-repeat: no-repeat; background-size: contain; }
|
||||||
.form-grid { display: grid; gap: var(--space-xl); grid-template-columns: .8fr 1.2fr; }
|
.form-grid { display: grid; gap: var(--space-xl); grid-template-columns: .8fr 1.2fr; }
|
||||||
.form { background: white; border-radius: var(--radius-md); box-shadow: var(--shadow-sm); display: grid; gap: var(--space-md); padding: var(--space-lg); }
|
.form { background: white; border-radius: var(--radius-md); box-shadow: var(--shadow-sm); display: grid; gap: var(--space-md); padding: var(--space-lg); }
|
||||||
.form label { display: grid; font-weight: 700; gap: var(--space-xs); }
|
.form label { display: grid; font-weight: 700; gap: var(--space-xs); }
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import fg from 'fast-glob';
|
||||||
|
import matter from 'gray-matter';
|
||||||
|
|
||||||
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||||
|
const publicRoot = path.join(root, 'public');
|
||||||
|
const failures = [];
|
||||||
|
const checked = [];
|
||||||
|
|
||||||
|
async function checkAsset(reference, owner) {
|
||||||
|
if (!reference?.startsWith('/assets/')) return;
|
||||||
|
const target = path.join(publicRoot, reference);
|
||||||
|
const exists = await fs.access(target).then(() => true).catch(() => false);
|
||||||
|
checked.push({ owner, reference, exists });
|
||||||
|
if (!exists) failures.push(`${owner}: ${reference}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const visualSource = await fs.readFile(path.join(root, 'src/data/page-visuals.ts'), 'utf8');
|
||||||
|
for (const match of visualSource.matchAll(/['"](?<reference>\/assets\/images\/[^'"]+)['"]/g)) {
|
||||||
|
await checkAsset(match.groups.reference, 'page hero mapping');
|
||||||
|
}
|
||||||
|
await checkAsset('/assets/images/hero-library-index.webp', 'library banner');
|
||||||
|
await checkAsset('/assets/images/rbt-toddler-play.webp', 'consultation form background');
|
||||||
|
|
||||||
|
for (const file of await fg('src/content/blog/**/*.{md,mdx}', { cwd: root, absolute: true })) {
|
||||||
|
const { data } = matter(await fs.readFile(file, 'utf8'));
|
||||||
|
if (!data.draft) await checkAsset(data.featuredImage, path.relative(root, file));
|
||||||
|
}
|
||||||
|
|
||||||
|
const uniqueChecked = new Map(checked.map((item) => [`${item.owner}:${item.reference}`, item]));
|
||||||
|
const report = [
|
||||||
|
'# Page Imagery Audit',
|
||||||
|
'',
|
||||||
|
`Checked ${uniqueChecked.size} page-banner, section-background, and blog-featured-image references.`,
|
||||||
|
'',
|
||||||
|
failures.length
|
||||||
|
? `## Missing Assets\n\n${failures.map((item) => `- ${item}`).join('\n')}`
|
||||||
|
: 'No missing mapped page imagery was detected.',
|
||||||
|
''
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
await fs.writeFile(path.join(root, 'reports/page-imagery-audit.md'), report);
|
||||||
|
console.log(`${failures.length} missing mapped page images.`);
|
||||||
|
if (failures.length) process.exitCode = 1;
|
||||||