Skip to the content

Capsid menu

app/routes/cv.charts[.json].ts

34 lines and 2 functions in DrDustinEdwards/dustinedwards-info, at commit 1590ba4 on 2026-10-24. This file on GitHub.

Functions

The functions of cv.charts[.json].ts
FunctionLinesComplexityCoveredCRAPMutation
widthParam20 to 243No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
loader26 to 381No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code

Imports

It imports app/db/cv.ts, app/lib/context.ts, app/lib/cv/entries.mjs, app/lib/cv/render-charts.ts, app/lib/cv/route.ts, app/lib/cv/view.mjs, app/lib/seo.ts. No module of this repo imports it.

Source

import { readCv } from "~/db/cv";
import { getEnv } from "~/lib/context";
import { cvFacts } from "~/lib/cv/entries.mjs";
import { renderCvCharts } from "~/lib/cv/render-charts";
import { CV_CACHE_TAG } from "~/lib/cv/route";
import { parseState } from "~/lib/cv/view.mjs";
import { SHARED_CACHE_CONTROL } from "~/lib/seo";

import type { Route } from "./+types/cv.charts[.json]";

/*
 * The CV's charts for one filter state, as the markup /cv renders them, for app/enhance/cv.ts to swap
 * in when a filter changes. Drawn here rather than in the browser so the page does not download a
 * chart renderer: Enarratio draws with Observable Plot and linkedom, about 480 KB of script, and its
 * browser layer (enarratio/enhance) needs only the markup. A function of the query string and the CV
 * alone, so it is shared-cached like the page, and carries the CV's tag so a CV save purges it.
 */

/** Widths come in 40px steps between a phone and a wide screen, so the cache sees a few dozen keys. */
function widthParam(raw: string | null) {
  const n = Number(raw);
  if (!Number.isFinite(n) || n <= 0) return undefined;
  return Math.min(1600, Math.max(280, Math.round(n / 40) * 40));
}

export async function loader({ request, context }: Route.LoaderArgs) {
  const facts = cvFacts((await readCv(getEnv(context))).entries);
  const url = new URL(request.url);
  const charts = renderCvCharts(facts, parseState(url.searchParams), { width: widthParam(url.searchParams.get("w")) });
  return new Response(JSON.stringify(charts), {
    headers: {
      "content-type": "application/json; charset=utf-8",
      "cache-control": SHARED_CACHE_CONTROL,
      "cache-tag": CV_CACHE_TAG,
      "x-robots-tag": "noindex",
    },
  });
}