ontoref-outreach/scripts/decks/lib/variants.mjs
2026-07-17 01:00:53 +01:00

59 lines
2.7 KiB
JavaScript

// The deck → artifact key rule, in ONE place, because it has already drifted once.
//
// A bilingual deck is TWO sources (decks.ncl: `pages[].source` overrides the deck's), and each
// source is its own build, its own capture and its own asset dir — sharing them is how an English
// URL ends up serving Spanish slides. So the artifact is keyed by the VARIANT (`ai-infra-es`),
// not by the deck (`ai-infra`), whose bare dir holds only thumbnails.
//
// That rule was re-derived in three places: here (project.mjs), gen-deck-pages.nu, and the
// justfile's `jq -r '.decks[].id'`. The third never learned the split. It kept handing `ai-infra`
// to the artifact gate, which ENOENT'd on a deck.css that was never written there — and PASSED on
// ontoref-ontologia-reflexion, whose PRE-SPLIT bundle was still lying on disk. A green gate over a
// file no page loads is worse than the crash: the crash is the only reason anyone looked.
//
// A rule copied is a rule that drifts. Every consumer asks this module now; nobody re-derives it.
//
// Usage: node lib/variants.mjs → JSON [{ deck, key, source, langs }]
// node lib/variants.mjs --ids → one artifact key per line
import { execFileSync } from 'node:child_process'
import { fileURLToPath } from 'node:url'
import { join } from 'node:path'
import { OUTREACH } from './paths.mjs'
export function readManifest() {
return JSON.parse(execFileSync(
'nickel', ['export', '--format', 'json', join(OUTREACH, 'scripts/decks/decks.ncl')],
{ encoding: 'utf8' },
))
}
// Group a deck's pages by the source they actually come from: each distinct source is its own
// build, capture and asset dir. One source → the deck's own id (nothing to disambiguate).
// Several → one key per source, named by its languages, because the CSS, the fonts and the images
// of two different sources are two different decks' worth of artifact.
export function variants(deck) {
const by = new Map()
for (const p of deck.pages) {
const source = p.source ?? deck.source
if (!by.has(source)) by.set(source, [])
by.get(source).push(p)
}
return [...by.entries()].map(([source, pages]) => ({
source,
pages,
key: by.size === 1 ? deck.id : `${deck.id}-${pages.map(p => p.lang).join('-')}`,
}))
}
export function allVariants(manifest = readManifest()) {
return manifest.decks.flatMap(d => variants(d).map(v => ({
deck: d.id, key: v.key, source: v.source, langs: v.pages.map(p => p.lang),
})))
}
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
const all = allVariants()
console.log(process.argv.includes('--ids')
? all.map(v => v.key).join('\n')
: JSON.stringify(all, null, 2))
}