pagez

Checking a site

pagez check compiles every page build would, without Vite's bundle or dist/, and lists what to fix. Each page that fails prints its failure, one a line, with its id, and each warning prints too. So one run lists every page's mistake, where a build stops at its first.

A mistake in the site, or in what its pages share, is the one line, since every page would fail with it.

import { relative } from "node:path";
import { FileError, printedError } from "./elements/errors.ts";
import { checkShared, compile } from "./page.ts";
import { createLoader } from "./parts.ts";
import { readSite } from "./site.ts";

/** What a check found: each page's failure and each warning, a line each. */
export interface Checked {
  /** How many pages were checked, or none when the site itself fails. */
  pages?: number;
  failures: string[];
  warnings: string[];
}

The site at root, checked, with each file below from named from it, and any other by its whole path. A mistake that isn't in a file, such as a crash, still throws.

export async function check(root: string, from: string = process.cwd()): Promise<Checked> {
  const named = (file: string) => {
    const path = relative(from, file);
    return path && !path.startsWith("..") ? path : file;
  };
  const failures = new Set<string>();
  const warnings: string[] = [];
  let site;
  try {
    site = readSite(root);
    checkShared(site);
  } catch (error) {
    if (!(error instanceof FileError)) throw error;
    return { failures: [printedError(error, named(error.file))], warnings };
  }
  const pages = [...site.pages, ...(site.notFound ? [site.notFound] : [])];
  const loader = await createLoader(root);
  try {
    for (const { file } of pages) {
      try {
        const page = await compile(file, { site, loader });
        warnings.push(...page.warnings.map((warning) => `${named(file)}: ${warning}`));
      } catch (error) {
        if (!(error instanceof FileError)) throw error;
        failures.add(printedError(error, named(error.file)));
      }
    }
  } finally {
    await loader.close();
  }
  return { pages: pages.length, failures: [...failures], warnings };
}