Build static Astro pilot for Happy Tails
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
import { existsSync } from 'node:fs';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const key = process.env.SITE_KEY;
|
||||
if (!key || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(key) || !existsSync(`sites/${key}/site.json`)) {
|
||||
throw new Error('SITE_KEY must be a manifest-defined site directory.');
|
||||
}
|
||||
|
||||
const result = spawnSync('npm', ['run', 'build', '--', '--outDir', `dist/${key}`], {
|
||||
env: { ...process.env, SITE_KEY: key },
|
||||
stdio: 'inherit'
|
||||
});
|
||||
if (result.status !== 0) process.exit(result.status ?? 1);
|
||||
@@ -0,0 +1,22 @@
|
||||
import Ajv2020 from 'ajv/dist/2020.js';
|
||||
import addFormats from 'ajv-formats';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
|
||||
const readJson = async (path) => JSON.parse(await readFile(path, 'utf8'));
|
||||
const ajv = new Ajv2020({ allErrors: true, strict: true });
|
||||
addFormats(ajv);
|
||||
|
||||
const [intakeSchema, sitesSchema, validIntake, invalidIntake, sites] = await Promise.all([
|
||||
readJson('schemas/intake.v1.schema.json'),
|
||||
readJson('schemas/sites.schema.json'),
|
||||
readJson('fixtures/intake.v1.valid.json'),
|
||||
readJson('fixtures/intake.v1.invalid.json'),
|
||||
readJson('sites.json')
|
||||
]);
|
||||
|
||||
const validIntakeCheck = ajv.compile(intakeSchema);
|
||||
const sitesCheck = ajv.compile(sitesSchema);
|
||||
if (!validIntakeCheck(validIntake)) throw new Error(`Valid intake rejected: ${ajv.errorsText(validIntakeCheck.errors)}`);
|
||||
if (validIntakeCheck(invalidIntake)) throw new Error('Invalid intake fixture was accepted');
|
||||
if (!sitesCheck(sites)) throw new Error(`Sites manifest rejected: ${ajv.errorsText(sitesCheck.errors)}`);
|
||||
console.log('Schema fixtures and sites manifest are valid.');
|
||||
@@ -0,0 +1,17 @@
|
||||
import { access, readFile } from 'node:fs/promises';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
const key = process.env.SITE_KEY;
|
||||
if (!key) throw new Error('SITE_KEY is required.');
|
||||
const root = resolve(`dist/${key}`);
|
||||
const required = ['index.html', '404.html'];
|
||||
if (key === 'www') required.push('about/index.html', 'services/index.html', 'contact/index.html');
|
||||
for (const file of required) await access(resolve(root, file));
|
||||
|
||||
const pages = await Promise.all(required.filter((file) => file.endsWith('.html')).map(async (file) => ({ file, html: await readFile(resolve(root, file), 'utf8') })));
|
||||
for (const { file, html } of pages) {
|
||||
if (html.includes('{{') || html.includes('{%')) throw new Error(`${file} contains an unresolved template placeholder.`);
|
||||
if (!/<title>[^<]+<\/title>/.test(html)) throw new Error(`${file} is missing a title.`);
|
||||
for (const match of html.matchAll(/(?:src|href)="(\/images\/[^"?#]+)"/g)) await access(resolve(root, `.${match[1]}`));
|
||||
}
|
||||
console.log(`Verified ${key}: ${required.join(', ')}`);
|
||||
Reference in New Issue
Block a user