@mark1russell7/site-pages 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/build/{build-xJqNIzdO.js → chunks/build.js} +24 -67
- package/build/chunks/build.js.map +1 -0
- package/build/chunks/kpi.d.ts +212 -0
- package/build/chunks/kpi.d.ts.map +1 -0
- package/build/chunks/kpi.js +222 -0
- package/build/chunks/kpi.js.map +1 -0
- package/build/cli.js +1 -1
- package/build/index.d.ts +5 -147
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -1
- package/build/vite.d.ts +26 -0
- package/build/vite.d.ts.map +1 -1
- package/build/vite.js +26 -1
- package/build/vite.js.map +1 -1
- package/package.json +1 -1
- package/styles/explorer.css +30 -8
- package/build/build-xJqNIzdO.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-xJqNIzdO.js","names":["object"],"sources":["../src/data/versions.ts","../src/data/changelog.ts","../src/data/github.ts","../src/data/npm.ts","../src/data/git.ts","../src/data/glob.ts","../src/data/releases.ts","../src/data/status.ts","../src/render/html.ts","../src/render/dates.ts","../src/render/theme.ts","../src/render/timeline.ts","../src/render/releases.ts","../src/render/status.ts","../src/check/probe.ts","../src/build.ts"],"sourcesContent":["/**\n * Versions: the SemVer parser, the sort, the kind of a version and the version of a git tag.\n */\n\nimport type { ReleaseKind } from \"./types.ts\";\n\n/** The parts of a SemVer 2.0.0 version. */\nexport interface ParsedVersion {\n major: number;\n minor: number;\n patch: number;\n prerelease: string[];\n}\n\nconst SEMVER = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n\n/** This function gives the parts of a version, or null when the text is not a SemVer version. */\nexport function parseVersion(version: string): ParsedVersion | null {\n const match = SEMVER.exec(version);\n if (!match) return null;\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n prerelease: match[4] ? match[4].split(\".\") : [],\n };\n}\n\n/**\n * This function compares two versions by the SemVer precedence. It gives a negative number when `a`\n * is older, a positive number when `a` is newer, and 0 for the same version. A text that is not a\n * version comes before each version.\n */\nexport function compareVersions(a: string, b: string): number {\n const x = parseVersion(a);\n const y = parseVersion(b);\n if (!x || !y) return x ? 1 : y ? -1 : a.localeCompare(b);\n const core = x.major - y.major || x.minor - y.minor || x.patch - y.patch;\n if (core !== 0) return core;\n // A prerelease comes before its release: 1.0.0-rc.1 < 1.0.0\n if (x.prerelease.length === 0 || y.prerelease.length === 0) return y.prerelease.length - x.prerelease.length;\n for (let index = 0; index < Math.max(x.prerelease.length, y.prerelease.length); index++) {\n const p = x.prerelease[index];\n const q = y.prerelease[index];\n if (p === undefined) return -1;\n if (q === undefined) return 1;\n if (p === q) continue;\n const pNumber = /^\\d+$/.test(p);\n const qNumber = /^\\d+$/.test(q);\n if (pNumber && qNumber) return Number(p) - Number(q);\n if (pNumber !== qNumber) return pNumber ? -1 : 1;\n return p < q ? -1 : 1;\n }\n return 0;\n}\n\n/**\n * This function gives the kind of a version. The oldest version of the list is \"first\". The caller\n * tells if the version is the oldest.\n */\nexport function kindOf(version: string, oldest: boolean): ReleaseKind {\n if (oldest) return \"first\";\n const parsed = parseVersion(version);\n if (!parsed) return \"patch\";\n if (parsed.major > 0 && parsed.minor === 0 && parsed.patch === 0) return \"major\";\n return parsed.patch === 0 ? \"minor\" : \"patch\";\n}\n\n/** The version of a git tag, and the package that the tag names (null for a tag like `v1.2.3`). */\nexport interface TagVersion {\n version: string;\n package: string | null;\n}\n\n/**\n * This function reads the version of a git tag. It knows `1.2.3`, `v1.2.3` and the tags of Changesets:\n * `name@1.2.3` and `@scope/name@1.2.3`. It gives null for another tag.\n */\nexport function versionOfTag(tag: string): TagVersion | null {\n const match = /^(?:(.+)@)?v?(\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.+-]*)?)$/.exec(tag.trim());\n if (!match || match[2] === undefined || !parseVersion(match[2])) return null;\n return { version: match[2], package: match[1] ?? null };\n}\n","/**\n * The changelog parser. Changesets writes a section for each version in the `CHANGELOG.md` of each\n * package. The section has a `## 0.13.2` heading and a `###` heading for each kind of change. Each\n * change is one `- <short sha>: <text>` entry. The next lines of an entry have an indent.\n */\n\n/** One entry of a changelog section or of a release text. */\nexport interface ChangelogEntry {\n /** The short SHA of the commit, or null for an entry without a commit. */\n commit: string | null;\n /** The first sentence of the entry, with its code spans. */\n text: string;\n}\n\n/** The entries of one version of a changelog. */\nexport interface ChangelogSection {\n version: string;\n /** The text of the version heading, without the `##` marks. */\n heading: string;\n entries: ChangelogEntry[];\n}\n\n// \"## 1.2.3\", \"## v1.2.3\", \"## [1.2.3] - 2026-10-18\" or \"## 1.2.3-rc.1\"\nconst VERSION_HEADING = /^##\\s+\\[?v?(\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?)\\]?(?:\\s.*)?$/;\nconst COMMIT_ENTRY = /^([0-9a-f]{7,40}):\\s+([\\s\\S]*)$/;\n// The lines of Changesets for a new version of a dependency: no change of the package itself\nconst DEPENDENCY_ENTRY = /^(?:Updated dependencies\\b|@?[\\w.-]+(?:\\/[\\w.-]+)?@\\S+\\s*$)/;\n// The generated release notes of GitHub: \"Fix it by @ann in https://github.com/o/r/pull/12\". The\n// pattern starts with one whitespace character, not \"\\s+\": with \"\\s+\", each space of a long run is\n// a start, and the time grows with the square of the length. entryOf removes the rest of the run.\nconst GENERATED_NOTE = /\\sby\\s+@[\\w-]+(?:\\[bot\\])?\\s+in\\s+(https:\\/\\/github\\.com\\/[\\w.-]+\\/[\\w.-]+\\/pull\\/(\\d+))\\s*$/;\nconst FIRST_CONTRIBUTION = /\\bmade their first contribution\\b/;\n\n/**\n * This function gives the first sentence of a text. A full stop, a question mark or an exclamation\n * mark ends the sentence when a space and no lowercase letter follow it.\n *\n * @remarks A mark in a code span does not end the sentence. A text that ends with a colon (a list\n * follows) ends with a full stop.\n */\nexport function firstSentence(text: string): string {\n const clean = text.replace(/\\s+/g, \" \").trim();\n let code = false;\n for (let index = 0; index < clean.length; index++) {\n const char = clean[index];\n if (char === \"`\") {\n code = !code;\n continue;\n }\n if (code || (char !== \".\" && char !== \"?\" && char !== \"!\")) continue;\n const next = clean[index + 1];\n if (next === undefined) break;\n if (next === \" \" && !/^[a-z]/.test(clean.slice(index + 2))) return clean.slice(0, index + 1);\n }\n return clean.replace(/:$/, \".\");\n}\n\n/**\n * This function makes one entry from the lines of a list item. The text is the first paragraph: the\n * lines before an empty line or a nested list. It gives null for an entry that is not a change.\n */\nfunction entryOf(lines: readonly string[]): ChangelogEntry | null {\n const paragraph: string[] = [];\n for (const [index, line] of lines.entries()) {\n if (index > 0 && (line.trim() === \"\" || /^\\s+[-*+]\\s/.test(line))) break;\n paragraph.push(line.trim());\n }\n const text = paragraph.join(\" \");\n const commit = COMMIT_ENTRY.exec(text);\n let body = (commit ? commit[2] : text) ?? \"\";\n if (body.trim() === \"\" || DEPENDENCY_ENTRY.test(body.trim()) || FIRST_CONTRIBUTION.test(body)) return null;\n const note = GENERATED_NOTE.exec(body);\n if (note) body = `${body.slice(0, note.index).trimEnd()} ([#${note[2] ?? \"\"}](${note[1] ?? \"\"}))`;\n return { commit: commit?.[1] ?? null, text: firstSentence(body) };\n}\n\n/**\n * This function gives the entries of each version of a changelog, in the sequence of the file.\n *\n * @remarks An entry is a line that starts with \"- \" and the indented lines under it. An entry for a\n * new dependency version is not a change.\n */\nexport function parseChangelog(markdown: string): ChangelogSection[] {\n const sections: Array<{ version: string; heading: string; raw: string[][] }> = [];\n let section: { version: string; heading: string; raw: string[][] } | null = null;\n let entry: string[] | null = null;\n const close = (): void => {\n if (entry && section) section.raw.push(entry);\n entry = null;\n };\n for (const line of markdown.split(/\\r?\\n/)) {\n const heading = VERSION_HEADING.exec(line);\n if (heading?.[1] !== undefined) {\n close();\n section = { version: heading[1], heading: line.replace(/^##\\s+/, \"\").trim(), raw: [] };\n sections.push(section);\n continue;\n }\n if (section === null) continue;\n if (line.startsWith(\"- \")) {\n close();\n entry = [line.slice(2)];\n } else if (entry && (line.trim() === \"\" || /^\\s/.test(line))) {\n (entry as string[]).push(line);\n } else {\n // A heading (\"### Patch Changes\") or a paragraph of the section ends the entry\n close();\n if (/^#{1,2}\\s/.test(line)) section = null;\n }\n }\n close();\n return sections.map(({ version, heading, raw }) => ({\n version,\n heading,\n entries: raw.map(entryOf).filter((change): change is ChangelogEntry => change !== null),\n }));\n}\n\n/**\n * This function gives the changes of the text of a GitHub release: one change for each top-level\n * list item. Fenced code is not read.\n */\nexport function releaseBodyEntries(body: string): ChangelogEntry[] {\n const entries: ChangelogEntry[] = [];\n let entry: string[] | null = null;\n let fence: string | null = null;\n const close = (): void => {\n const change = entry ? entryOf(entry) : null;\n if (change) entries.push(change);\n entry = null;\n };\n for (const line of body.split(/\\r?\\n/)) {\n const fenceMark = /^\\s*(`{3,}|~{3,})/.exec(line)?.[1];\n if (fenceMark !== undefined) {\n close();\n if (fence === null) fence = fenceMark[0] ?? null;\n else if (fenceMark[0] === fence) fence = null;\n continue;\n }\n if (fence !== null) continue;\n // \"\\s+(\\S.*)?\" and not \"\\s+(.*)\": the two parts cannot share a space, so a failed match does not backtrack\n const item = /^[-*+]\\s+(\\S.*)?$/.exec(line);\n if (item) {\n close();\n entry = [item[1] ?? \"\"];\n } else if (entry && (line.trim() === \"\" || /^\\s/.test(line))) {\n (entry as string[]).push(line);\n } else {\n close();\n }\n }\n close();\n return entries;\n}\n\n/**\n * This function gives the anchor of a heading on GitHub: lowercase, no punctuation, and a hyphen\n * for each space. The anchor of \"0.13.2\" is \"0132\".\n */\nexport function headingAnchor(heading: string): string {\n return heading\n .toLowerCase()\n .trim()\n .replace(/[^\\p{L}\\p{N}\\s_-]/gu, \"\")\n .replace(/\\s/g, \"-\");\n}\n","/**\n * The GitHub sources: the open pull requests and issues (GraphQL), and the releases (REST). Each\n * function gives `{ available: false, reason }` without a token or after an error. A failure of GitHub\n * does not stop the build.\n */\n\nimport type { BoardIssue, BoardPullRequest, CheckState, GitHubOpenWork, GitHubRelease, GitHubReleases } from \"./types.ts\";\n\n/** The GraphQL endpoint of GitHub. */\nexport const GITHUB_GRAPHQL = \"https://api.github.com/graphql\";\n/** The REST endpoint of GitHub. */\nexport const GITHUB_API = \"https://api.github.com\";\n\nconst USER_AGENT = \"site-pages\";\n\n/** The options of the GitHub functions. */\nexport interface GitHubOptions {\n owner: string;\n repo: string;\n /** A token with read access. Without it, the function sends no request. */\n token: string | undefined;\n /** The `fetch` function. The default is the global `fetch`. */\n fetch?: typeof fetch;\n /** The time limit of each request, in milliseconds. The default is 15000. */\n timeoutMs?: number;\n}\n\nconst OPEN_WORK_QUERY = `query OpenWork($owner: String!, $repo: String!, $first: Int!) {\n repository(owner: $owner, name: $repo) {\n pullRequests(states: OPEN, first: $first, orderBy: {field: UPDATED_AT, direction: DESC}) {\n totalCount\n nodes {\n number title url isDraft createdAt updatedAt headRefName\n author { login }\n labels(first: 10) { nodes { name } }\n commits(last: 1) { nodes { commit { statusCheckRollup { state } } } }\n }\n }\n issues(states: OPEN, first: $first, orderBy: {field: UPDATED_AT, direction: DESC}) {\n totalCount\n nodes {\n number title url createdAt updatedAt\n author { login }\n labels(first: 10) { nodes { name } }\n }\n }\n }\n}`;\n\n/** This function gives the combined check state of a commit: success, failure, pending or none. */\nexport function checkStateOf(rollup: { state?: string | null } | null | undefined): CheckState {\n switch (rollup?.state) {\n case \"SUCCESS\":\n return \"success\";\n case \"FAILURE\":\n case \"ERROR\":\n return \"failure\";\n case \"PENDING\":\n case \"EXPECTED\":\n return \"pending\";\n default:\n return \"none\";\n }\n}\n\n// The JSON of GitHub has no static type: these helpers read it with care.\ntype Json = Record<string, unknown>;\nconst object = (value: unknown): Json => (value !== null && typeof value === \"object\" ? (value as Json) : {});\nconst list = (value: unknown): unknown[] => (Array.isArray(value) ? value : []);\nconst text = (value: unknown, fallback = \"\"): string => (typeof value === \"string\" ? value : fallback);\nconst labelsOf = (node: Json): string[] =>\n list(object(node[\"labels\"])[\"nodes\"])\n .map((label) => object(label)[\"name\"])\n .filter((name): name is string => typeof name === \"string\");\nconst authorOf = (node: Json): string => text(object(node[\"author\"])[\"login\"], \"ghost\");\n\nfunction failure(error: unknown, timeoutMs: number): { available: false; reason: string } {\n const named = object(error);\n if (named[\"name\"] === \"TimeoutError\") return { available: false, reason: `GitHub did not answer in ${timeoutMs / 1000} s` };\n return { available: false, reason: `the request failed: ${error instanceof Error ? error.message : String(error)}` };\n}\n\nfunction precheck(options: GitHubOptions): { available: false; reason: string } | null {\n if (!options.owner || !options.repo) return { available: false, reason: \"no repository was given\" };\n if (!options.token) return { available: false, reason: \"the build had no GitHub token\" };\n if (typeof (options.fetch ?? globalThis.fetch) !== \"function\") return { available: false, reason: \"this Node has no fetch\" };\n return null;\n}\n\n/**\n * This function reads the open pull requests and issues of a repository with one GraphQL request,\n * the most recently updated first. It gives `{ available: false, reason }` without a token or after\n * an error. It does not throw.\n */\nexport async function githubOpenWork(options: GitHubOptions & { endpoint?: string; first?: number }): Promise<GitHubOpenWork> {\n const stop = precheck(options);\n if (stop) return stop;\n const { owner, repo, token, endpoint = GITHUB_GRAPHQL, first = 50, timeoutMs = 15_000 } = options;\n const fetcher = options.fetch ?? globalThis.fetch;\n try {\n const response = await fetcher(endpoint, {\n method: \"POST\",\n headers: { authorization: `bearer ${token}`, \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: JSON.stringify({ query: OPEN_WORK_QUERY, variables: { owner, repo, first } }),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!response.ok) return { available: false, reason: `GitHub answered with HTTP ${response.status}` };\n const body = object(await response.json());\n const errors = list(body[\"errors\"]);\n if (errors.length > 0) {\n return { available: false, reason: `GitHub gave an error: ${text(object(errors[0])[\"message\"], \"no message\")}` };\n }\n const repository = object(body[\"data\"])[\"repository\"];\n if (repository === null || typeof repository !== \"object\") return { available: false, reason: `GitHub has no repository ${owner}/${repo}` };\n const pulls = object((repository as Json)[\"pullRequests\"]);\n const open = object((repository as Json)[\"issues\"]);\n const pullRequests: BoardPullRequest[] = list(pulls[\"nodes\"])\n .filter((node) => node !== null && typeof node === \"object\")\n .map((value) => {\n const node = object(value);\n const lastCommit = object(object(list(object(node[\"commits\"])[\"nodes\"])[0])[\"commit\"]);\n return {\n number: Number(node[\"number\"]),\n title: text(node[\"title\"]),\n url: text(node[\"url\"]),\n author: authorOf(node),\n branch: text(node[\"headRefName\"]),\n draft: node[\"isDraft\"] === true,\n createdAt: text(node[\"createdAt\"]),\n updatedAt: text(node[\"updatedAt\"]),\n labels: labelsOf(node),\n checks: checkStateOf(object(lastCommit[\"statusCheckRollup\"]) as { state?: string }),\n };\n });\n const issues: BoardIssue[] = list(open[\"nodes\"])\n .filter((node) => node !== null && typeof node === \"object\")\n .map((value) => {\n const node = object(value);\n return {\n number: Number(node[\"number\"]),\n title: text(node[\"title\"]),\n url: text(node[\"url\"]),\n author: authorOf(node),\n createdAt: text(node[\"createdAt\"]),\n updatedAt: text(node[\"updatedAt\"]),\n labels: labelsOf(node),\n };\n });\n const total = (value: unknown, fallback: number): number => (typeof value === \"number\" ? value : fallback);\n return {\n available: true,\n pullRequests,\n issues,\n totals: { pullRequests: total(pulls[\"totalCount\"], pullRequests.length), issues: total(open[\"totalCount\"], issues.length) },\n };\n } catch (error) {\n return failure(error, timeoutMs);\n }\n}\n\n/** This function gives the URL of the next page from a `Link` header of GitHub, or null. */\nfunction nextPage(link: string | null): string | null {\n if (!link) return null;\n for (const part of link.split(\",\")) {\n const match = /<([^>]+)>\\s*;\\s*rel=\"next\"/.exec(part);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n\n/**\n * This function reads the published releases of a repository with the REST API, the newest first.\n * It skips the drafts. It gives `{ available: false, reason }` without a token or after an error.\n * It does not throw.\n *\n * @remarks The function reads 100 releases on each page, and at most `maxPages` pages (default 10).\n */\nexport async function githubReleases(options: GitHubOptions & { endpoint?: string; maxPages?: number }): Promise<GitHubReleases> {\n const stop = precheck(options);\n if (stop) return stop;\n const { owner, repo, token, endpoint = GITHUB_API, maxPages = 10, timeoutMs = 15_000 } = options;\n const fetcher = options.fetch ?? globalThis.fetch;\n const releases: GitHubRelease[] = [];\n let url: string | null = `${endpoint}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/releases?per_page=100`;\n try {\n for (let page = 0; url !== null && page < maxPages; page++) {\n const response: Response = await fetcher(url, {\n headers: {\n accept: \"application/vnd.github+json\",\n authorization: `Bearer ${token}`,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": \"2022-11-28\",\n },\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (response.status === 404) return { available: false, reason: `GitHub has no repository ${owner}/${repo}` };\n if (!response.ok) return { available: false, reason: `GitHub answered with HTTP ${response.status}` };\n const body: unknown = await response.json();\n if (!Array.isArray(body)) return { available: false, reason: \"GitHub gave no list of releases\" };\n for (const value of body) {\n const release = object(value);\n const tag = release[\"tag_name\"];\n if (release[\"draft\"] === true || typeof tag !== \"string\") continue;\n releases.push({\n tag,\n name: text(release[\"name\"]) || tag,\n body: text(release[\"body\"]),\n publishedAt: text(release[\"published_at\"]) || text(release[\"created_at\"]),\n url: text(release[\"html_url\"]),\n prerelease: release[\"prerelease\"] === true,\n });\n }\n url = nextPage(response.headers.get(\"link\"));\n }\n return { available: true, releases };\n } catch (error) {\n return failure(error, timeoutMs);\n }\n}\n","/**\n * The npm source: the publication time of each version of some packages. The release data uses\n * these times when git and GitHub give no date for a version.\n */\n\nimport type { NpmPublishTimes, NpmVersionTime } from \"./types.ts\";\n\n/** The public npm registry. */\nexport const NPM_REGISTRY = \"https://registry.npmjs.org\";\n\n/** The options of `npmPublishTimes`. */\nexport interface NpmOptions {\n /** The npm names of the packages, or a scope (for example `@procedures`) for all the packages of the scope. */\n packages: readonly string[];\n /** The `fetch` function. The default is the global `fetch`. */\n fetch?: typeof fetch;\n registry?: string;\n /** The time limit of each request, in milliseconds. The default is 15000. */\n timeoutMs?: number;\n}\n\ntype Json = Record<string, unknown>;\nconst object = (value: unknown): Json => (value !== null && typeof value === \"object\" ? (value as Json) : {});\n\nfunction message(error: unknown): string {\n if (object(error)[\"name\"] === \"TimeoutError\") return \"npm did not answer in time\";\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * This function reads the publication time of each version of the packages from the npm registry.\n * A scope (`@name`) gives each package of the scope. It does not throw. Each failure gives a\n * message in `problems`.\n */\nexport async function npmPublishTimes(options: NpmOptions): Promise<NpmPublishTimes> {\n const { registry = NPM_REGISTRY, timeoutMs = 15_000 } = options;\n const fetcher = options.fetch ?? globalThis.fetch;\n const problems: string[] = [];\n const times: NpmVersionTime[] = [];\n if (typeof fetcher !== \"function\") return { times, problems: [\"this Node has no fetch\"] };\n const get = async (url: string): Promise<unknown> => {\n const response = await fetcher(url, { headers: { accept: \"application/json\" }, signal: AbortSignal.timeout(timeoutMs) });\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n return response.json();\n };\n\n const names = new Set<string>();\n for (const entry of options.packages.map((name) => name.trim()).filter(Boolean)) {\n if (!/^@[^/]+$/.test(entry)) {\n names.add(entry);\n continue;\n }\n try {\n const found = object(await get(`${registry}/-/v1/search?text=scope:${encodeURIComponent(entry.slice(1))}&size=250`));\n const objects = Array.isArray(found[\"objects\"]) ? found[\"objects\"] : [];\n const before = names.size;\n for (const item of objects) {\n const name = object(object(item)[\"package\"])[\"name\"];\n if (typeof name === \"string\" && name.startsWith(`${entry}/`)) names.add(name);\n }\n if (names.size === before) problems.push(`npm has no package in the scope ${entry}`);\n } catch (error) {\n problems.push(`npm did not give the packages of ${entry}: ${message(error)}`);\n }\n }\n\n // Four requests at a time\n const queue = [...names].sort();\n const worker = async (): Promise<void> => {\n for (let name = queue.shift(); name !== undefined; name = queue.shift()) {\n try {\n const packument = object(await get(`${registry}/${name.replaceAll(\"/\", \"%2f\")}`));\n const published = object(packument[\"versions\"]);\n for (const [version, date] of Object.entries(object(packument[\"time\"]))) {\n if (version === \"created\" || version === \"modified\" || typeof date !== \"string\") continue;\n if (!(version in published)) continue;\n times.push({ name, version, date });\n }\n } catch (error) {\n problems.push(`npm did not give the versions of ${name}: ${message(error)}`);\n }\n }\n };\n await Promise.all(Array.from({ length: 4 }, worker));\n times.sort((a, b) => a.name.localeCompare(b.name) || a.date.localeCompare(b.date));\n return { times, problems };\n}\n","/**\n * The git source: the tags with their dates, the commit of the build and the GitHub remote. Each\n * function gives an empty result when git or the repository is not available.\n */\n\nimport { execFileSync } from \"node:child_process\";\n\n/** A git tag and the ISO date of its creation. */\nexport interface TagDate {\n tag: string;\n date: string;\n}\n\n/** This function starts git in a folder and gives its output, or null when git fails. */\nexport function git(repoDir: string, ...args: string[]): string | null {\n try {\n return execFileSync(\"git\", args, { cwd: repoDir, encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"], windowsHide: true });\n } catch {\n return null;\n }\n}\n\n/** This function tells if the clone is shallow. A shallow clone has not all the tags and commits. */\nexport function isShallow(repoDir: string): boolean {\n return git(repoDir, \"rev-parse\", \"--is-shallow-repository\")?.trim() === \"true\";\n}\n\n/** This function gives each tag of the repository with its date. An annotated tag has its own date. */\nexport function gitTagDates(repoDir: string): TagDate[] {\n const output = git(repoDir, \"for-each-ref\", \"--format=%(refname:strip=2) %(creatordate:iso-strict)\", \"refs/tags\");\n if (!output) return [];\n const tags: TagDate[] = [];\n for (const line of output.split(/\\r?\\n/)) {\n const match = /^(\\S+) (\\S+)$/.exec(line.trim());\n if (match?.[1] && match[2]) tags.push({ tag: match[1], date: match[2] });\n }\n return tags;\n}\n\n/**\n * This function gives the date of the oldest commit that added a version heading to a changelog,\n * or null. The path of the changelog starts at `repoDir`.\n */\nexport function headingDate(repoDir: string, version: string, file: string): string | null {\n const output = git(repoDir, \"log\", \"--format=%cI\", `-S## ${version}`, \"--\", file);\n const dates = (output ?? \"\").trim().split(/\\r?\\n/).filter(Boolean);\n return dates[dates.length - 1] ?? null;\n}\n\n/** This function gives the full SHA of `HEAD`, or null. */\nexport function headCommit(repoDir: string): string | null {\n const sha = git(repoDir, \"rev-parse\", \"HEAD\")?.trim();\n return sha && /^[0-9a-f]{40}$/.test(sha) ? sha : null;\n}\n\n/** This function gives \"owner/name\" of the GitHub remote \"origin\", or null. */\nexport function originRepository(repoDir: string): string | null {\n const url = git(repoDir, \"remote\", \"get-url\", \"origin\")?.trim() ?? \"\";\n const match = /github\\.com[:/]([^/]+)\\/(.+?)(?:\\.git)?\\/?$/.exec(url);\n return match ? `${match[1]}/${match[2]}` : null;\n}\n","/**\n * A small glob for the changelog files. The syntax has `*` and `?` in one path segment, and `**` for\n * zero or more folders.\n */\n\nimport { existsSync, readdirSync, statSync, type Dirent } from \"node:fs\";\nimport { join } from \"node:path\";\n\nfunction segmentPattern(segment: string): RegExp {\n const source = segment.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \"[^/]*\").replace(/\\?/g, \"[^/]\");\n return new RegExp(`^${source}$`);\n}\n\nconst SKIP = new Set([\"node_modules\", \".git\"]);\n\n/**\n * This function gives the files under `root` that match a pattern, as paths with `/` that start at\n * `root`, sorted. It does not go into `node_modules` or `.git`.\n */\nexport function globFiles(root: string, pattern: string): string[] {\n const segments = pattern.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").split(\"/\").filter(Boolean);\n const found = new Set<string>();\n const walk = (dir: string, prefix: string, index: number): void => {\n const segment = segments[index];\n if (segment === undefined) return;\n const last = index === segments.length - 1;\n if (segment === \"**\") {\n walk(dir, prefix, index + 1);\n for (const entry of safeList(dir)) {\n if (entry.isDirectory() && !SKIP.has(entry.name)) walk(join(dir, entry.name), `${prefix}${entry.name}/`, index);\n }\n return;\n }\n if (!/[*?]/.test(segment)) {\n const path = join(dir, segment);\n if (!existsSync(path)) return;\n if (last) {\n if (statSync(path).isFile()) found.add(`${prefix}${segment}`);\n } else if (statSync(path).isDirectory()) {\n walk(path, `${prefix}${segment}/`, index + 1);\n }\n return;\n }\n const matcher = segmentPattern(segment);\n for (const entry of safeList(dir)) {\n if (!matcher.test(entry.name) || SKIP.has(entry.name)) continue;\n if (last && entry.isFile()) found.add(`${prefix}${entry.name}`);\n else if (!last && entry.isDirectory()) walk(join(dir, entry.name), `${prefix}${entry.name}/`, index + 1);\n }\n };\n walk(root, \"\", 0);\n return [...found].sort();\n}\n\nfunction safeList(dir: string): Dirent[] {\n try {\n return readdirSync(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n","/**\n * The release data: one entry for each version. The sources are the changelogs of Changesets, the\n * GitHub releases, the git tags and the publication times on npm.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\nimport { headingAnchor, parseChangelog, releaseBodyEntries, type ChangelogEntry, type ChangelogSection } from \"./changelog.ts\";\nimport { gitTagDates, headingDate, isShallow, type TagDate } from \"./git.ts\";\nimport { githubReleases } from \"./github.ts\";\nimport { globFiles } from \"./glob.ts\";\nimport { npmPublishTimes } from \"./npm.ts\";\nimport type { GitHubRelease, Link, NpmVersionTime, Release, ReleaseChange, ReleaseKind } from \"./types.ts\";\nimport { compareVersions, kindOf, parseVersion, versionOfTag } from \"./versions.ts\";\n\n/** An error in the release sources, for example a group without a changelog. */\nexport class ReleaseDataError extends Error {}\n\n/** One changelog file and the npm name of its package. */\nexport interface ChangelogSource {\n /** The npm name of the package. */\n name: string;\n /** The path of the file in the repository, with `/`. */\n file: string;\n markdown: string;\n}\n\n/** The sources of `mergeReleases`. Each source is optional. */\nexport interface ReleaseSources {\n changelogs?: readonly ChangelogSource[];\n githubReleases?: readonly GitHubRelease[];\n tags?: readonly TagDate[];\n npm?: readonly NpmVersionTime[];\n /**\n * The npm name of the package whose changelog gives the versions, for a monorepo with one version\n * for all its packages. Without it, each version of each source is a version.\n */\n group?: string | undefined;\n /** \"owner/name\" of the repository, for the links. */\n repository?: string | undefined;\n /** The branch or the commit of the changelog links. The default is \"HEAD\". */\n ref?: string | undefined;\n /** This function gives the date of a version without another date: the commit that added its heading. */\n headingDate?: ((version: string, file: string) => string | null) | undefined;\n /** The time of the build, for a version without a date. The default is the time of the call. */\n now?: string | undefined;\n warn?: ((message: string) => void) | undefined;\n}\n\n/** The changes of one version, by commit (or by text, for an entry without a commit). */\ntype ChangeMap = Map<string, ReleaseChange>;\n\nfunction addChange(changes: ChangeMap, entry: ChangelogEntry, packageName: string | null): void {\n const key = entry.commit ?? `text:${entry.text}`;\n const change = changes.get(key) ?? { commit: entry.commit, text: entry.text, packages: [] };\n if (packageName && !change.packages.includes(packageName)) change.packages.push(packageName);\n changes.set(key, change);\n}\n\nfunction sortedChanges(changes: ChangeMap | undefined): ReleaseChange[] {\n return [...(changes?.values() ?? [])]\n .map((change) => ({ ...change, packages: [...change.packages].sort() }))\n .sort((a, b) => b.packages.length - a.packages.length || a.text.localeCompare(b.text));\n}\n\n/** The earliest of some ISO dates, or null. */\nfunction earliest(dates: ReadonlyArray<string | null | undefined>): string | null {\n let best: string | null = null;\n for (const date of dates) {\n if (!date || !Number.isFinite(Date.parse(date))) continue;\n if (best === null || Date.parse(date) < Date.parse(best)) best = date;\n }\n return best;\n}\n\n/** The URL path of a git ref: each character that a URL cannot hold is encoded, and \"@\" and \"/\" stay. */\nfunction refPath(ref: string): string {\n return encodeURI(ref).replace(/#/g, \"%23\").replace(/\\?/g, \"%3F\");\n}\n\n/** The kind of a version from the step after the previous version of its package. */\nfunction stepKind(version: string, previous: string | undefined): ReleaseKind {\n if (previous === undefined) return \"first\";\n const now = parseVersion(version);\n const before = parseVersion(previous);\n if (!now || !before) return kindOf(version, false);\n if (now.major !== before.major) return \"major\";\n return now.minor !== before.minor ? \"minor\" : \"patch\";\n}\n\n/**\n * This function gives the releases of the npm versions of some packages, for a repository without\n * a changelog and without GitHub releases (version 0.1.3). Each version of each package is one\n * release.\n *\n * - The label is the version when the times name one package. Else it is the name without its\n * scope and the version, for example `service@0.5.8`.\n * - The kind comes from the step after the previous version of the same package. The first\n * version of a package is the kind `first`.\n * - A version with a prerelease part is not a release. npm also keeps the placeholder\n * `0.0.0-bootstrap.0` of a new package.\n */\nfunction npmReleases(times: readonly NpmVersionTime[], group: string | undefined): Release[] {\n const stable = times.filter((time) => (!group || time.name === group) && parseVersion(time.version)?.prerelease.length === 0);\n const byPackage = new Map<string, NpmVersionTime[]>();\n for (const time of stable) {\n const list = byPackage.get(time.name) ?? [];\n if (!list.some((each) => each.version === time.version)) list.push(time);\n byPackage.set(time.name, list);\n }\n const shortNames = new Map<string, string>();\n const shortCount = new Map<string, number>();\n for (const name of byPackage.keys()) {\n const short = name.replace(/^@[^/]+\\//, \"\");\n shortNames.set(name, short);\n shortCount.set(short, (shortCount.get(short) ?? 0) + 1);\n }\n const several = byPackage.size > 1;\n const releases: Release[] = [];\n for (const [name, list] of byPackage) {\n list.sort((a, b) => compareVersions(a.version, b.version));\n const short = shortNames.get(name) ?? name;\n // Two scopes with one short name keep the full names\n const label = (shortCount.get(short) ?? 0) > 1 ? name : short;\n list.forEach((time, index) => {\n releases.push({\n version: several ? `${label}@${time.version}` : time.version,\n date: time.date,\n kind: stepKind(time.version, list[index - 1]?.version),\n changes: [{ commit: null, text: `Version ${time.version} of \\`${name}\\` on npm.`, packages: [name] }],\n links: [{ label: \"npm\", url: `https://www.npmjs.com/package/${name}/v/${time.version}` }],\n });\n });\n }\n return releases.sort((a, b) => Date.parse(b.date) - Date.parse(a.date) || a.version.localeCompare(b.version));\n}\n\n/**\n * This function merges the release sources into one entry for each version, the newest first.\n *\n * - The versions: the changelog of `group`, or else each changelog version and each GitHub release.\n * - The date: the git tag, else the GitHub release, else npm, else the commit of the changelog heading.\n * - The changes: the changelog entries, else the list items of the GitHub release text.\n * - Without a changelog version and without a GitHub release, each npm version of each package is a release.\n *\n * @throws ReleaseDataError when `group` has no changelog and other changelogs exist\n */\nexport function mergeReleases(sources: ReleaseSources): Release[] {\n const { group, repository, ref = \"HEAD\", warn = () => {} } = sources;\n const changelogs = sources.changelogs ?? [];\n const inGroup = (packageName: string | null): boolean => !group || packageName === null || packageName === group;\n\n // The changelog sections of each version\n const parsed: Array<{ source: ChangelogSource; sections: ChangelogSection[] }> = changelogs.map((source) => ({\n source,\n sections: parseChangelog(source.markdown),\n }));\n const groupChangelog = group ? parsed.find((entry) => entry.source.name === group) : undefined;\n if (group && parsed.length > 0 && !groupChangelog) throw new ReleaseDataError(`no changelog of ${group}`);\n\n const githubByVersion = new Map<string, Array<{ release: GitHubRelease; package: string | null }>>();\n for (const release of sources.githubReleases ?? []) {\n const tag = versionOfTag(release.tag);\n if (!tag) continue;\n const list = githubByVersion.get(tag.version) ?? [];\n list.push({ release, package: tag.package });\n githubByVersion.set(tag.version, list);\n }\n\n // The versions\n const versions = new Set<string>();\n if (groupChangelog) {\n for (const section of groupChangelog.sections) versions.add(section.version);\n } else {\n for (const { sections } of parsed) for (const section of sections) versions.add(section.version);\n for (const [version, list] of githubByVersion) if (list.some((entry) => inGroup(entry.package))) versions.add(version);\n }\n const ordered = [...versions].sort((a, b) => compareVersions(b, a));\n // No changelog and no GitHub release names a version: the versions on npm are the releases\n if (ordered.length === 0) return npmReleases(sources.npm ?? [], group);\n\n // The changes and the changelog section of each version\n const changelogChanges = new Map<string, ChangeMap>();\n const changelogOf = new Map<string, { source: ChangelogSource; heading: string }>();\n const groupFirst = groupChangelog ? [groupChangelog, ...parsed.filter((entry) => entry !== groupChangelog)] : parsed;\n for (const { source, sections } of groupFirst) {\n for (const section of sections) {\n if (!versions.has(section.version)) continue;\n if (!changelogOf.has(section.version)) changelogOf.set(section.version, { source, heading: section.heading });\n const changes = changelogChanges.get(section.version) ?? new Map<string, ReleaseChange>();\n for (const entry of section.entries) addChange(changes, entry, source.name);\n changelogChanges.set(section.version, changes);\n }\n }\n\n const tagsByVersion = new Map<string, TagDate[]>();\n for (const tag of sources.tags ?? []) {\n const parsedTag = versionOfTag(tag.tag);\n if (!parsedTag || !inGroup(parsedTag.package)) continue;\n const list = tagsByVersion.get(parsedTag.version) ?? [];\n list.push(tag);\n tagsByVersion.set(parsedTag.version, list);\n }\n const npmByVersion = new Map<string, NpmVersionTime[]>();\n for (const time of sources.npm ?? []) {\n const list = npmByVersion.get(time.version) ?? [];\n list.push(time);\n npmByVersion.set(time.version, list);\n }\n\n // The date of each version\n const dates = new Map<string, string>();\n const missing: string[] = [];\n for (const version of ordered) {\n const github = (githubByVersion.get(version) ?? []).filter((entry) => inGroup(entry.package));\n const npm = npmByVersion.get(version) ?? [];\n const npmGroup = group ? npm.filter((time) => time.name === group) : [];\n const changelog = changelogOf.get(version);\n const date =\n earliest((tagsByVersion.get(version) ?? []).map((tag) => tag.date)) ??\n earliest(github.map((entry) => entry.release.publishedAt)) ??\n earliest((npmGroup.length > 0 ? npmGroup : npm).map((time) => time.date)) ??\n (changelog && sources.headingDate ? sources.headingDate(version, changelog.source.file) : null);\n if (date) dates.set(version, date);\n else missing.push(version);\n }\n if (missing.length > 0) {\n // A version without a date gets the date of the next newer version, or the time of the build\n warn(`no source gives a date for ${missing.join(\", \")}. The page shows an approximate date.`);\n let newer = sources.now ?? new Date().toISOString();\n for (const version of ordered) {\n const date = dates.get(version);\n if (date) newer = date;\n else dates.set(version, newer);\n }\n }\n\n const oldest = ordered[ordered.length - 1];\n return ordered.map((version): Release => {\n const github = githubByVersion.get(version) ?? [];\n let changes: ChangeMap | undefined = changelogChanges.get(version);\n if (!changes) {\n // No changelog has the version: the list items of the GitHub releases are the changes\n changes = new Map();\n for (const { release, package: packageName } of github) {\n for (const entry of releaseBodyEntries(release.body)) addChange(changes, entry, packageName ?? (group || null));\n }\n }\n\n const links: Link[] = [];\n const githubRelease = github.find((entry) => entry.package === group) ?? github.find((entry) => entry.package === null) ?? github[0];\n if (githubRelease?.release.url) links.push({ label: \"GitHub release\", url: githubRelease.release.url });\n else if (repository) {\n const tag = (tagsByVersion.get(version) ?? [])[0];\n if (tag) links.push({ label: \"Tag\", url: `https://github.com/${repository}/releases/tag/${refPath(tag.tag)}` });\n }\n const changelog = changelogOf.get(version);\n if (changelog && repository) {\n links.push({ label: \"Changelog\", url: `https://github.com/${repository}/blob/${refPath(ref)}/${changelog.source.file}#${headingAnchor(changelog.heading)}` });\n }\n const npm = npmByVersion.get(version) ?? [];\n const npmPackage = npm.find((time) => time.name === group) ?? npm[0];\n if (npmPackage) links.push({ label: \"npm\", url: `https://www.npmjs.com/package/${npmPackage.name}/v/${version}` });\n\n return {\n version,\n date: dates.get(version) ?? sources.now ?? new Date().toISOString(),\n kind: kindOf(version, version === oldest),\n changes: sortedChanges(changes),\n links,\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// The sources on disk\n// ---------------------------------------------------------------------------\n\n/** The default patterns of the changelog files: the first pattern that finds a file wins. */\nexport const DEFAULT_CHANGELOGS: readonly string[] = [\"packages/*/CHANGELOG.md\", \"CHANGELOG.md\"];\n\n/**\n * This function reads the changelog files of a repository. The npm name of each changelog comes from\n * the `package.json` next to it, else from its folder.\n */\nexport function readChangelogs(repoDir: string, pattern?: string): ChangelogSource[] {\n const patterns = pattern ? [pattern] : DEFAULT_CHANGELOGS;\n for (const candidate of patterns) {\n const files = globFiles(repoDir, candidate);\n if (files.length === 0) continue;\n return files.map((file) => {\n const path = join(repoDir, ...file.split(\"/\"));\n const manifest = join(dirname(path), \"package.json\");\n let name = basename(dirname(path));\n if (existsSync(manifest)) {\n try {\n const parsed = JSON.parse(readFileSync(manifest, \"utf8\")) as { name?: unknown };\n if (typeof parsed.name === \"string\" && parsed.name) name = parsed.name;\n } catch {\n // A package.json that is not JSON: the folder gives the name\n }\n }\n return { name, file, markdown: readFileSync(path, \"utf8\") };\n });\n }\n return [];\n}\n\n/** The options of `readReleases`. */\nexport interface ReadReleasesOptions {\n /** The folder of the repository. The changelog patterns start here. */\n repoDir: string;\n /** \"owner/name\" of the repository on GitHub, for the GitHub releases and the links. */\n repository?: string | undefined;\n token?: string | undefined;\n /** The glob pattern of the changelog files. The default is `DEFAULT_CHANGELOGS`. */\n changesets?: string | undefined;\n /** The npm names or scopes for the npm dates. */\n packages?: readonly string[] | undefined;\n group?: string | undefined;\n /** The branch or the commit of the changelog links. */\n ref?: string | undefined;\n fetch?: typeof fetch | undefined;\n now?: string | undefined;\n warn?: ((message: string) => void) | undefined;\n}\n\n/**\n * This function reads all the release sources of a repository and merges them. A failure of GitHub\n * or npm does not stop it, but gives a warning.\n *\n * @throws ReleaseDataError when `group` has no changelog and other changelogs exist\n */\nexport async function readReleases(options: ReadReleasesOptions): Promise<Release[]> {\n const { repoDir, repository, warn = () => {} } = options;\n const changelogs = readChangelogs(repoDir, options.changesets);\n const tags = gitTagDates(repoDir);\n if (isShallow(repoDir)) warn(\"the clone is shallow, so the release dates are not exact. Check out the full history (fetch-depth 0).\");\n\n let releases: GitHubRelease[] = [];\n const [owner = \"\", repo = \"\"] = (repository ?? \"\").split(\"/\");\n if (owner && repo) {\n const result = await githubReleases({ owner, repo, token: options.token, ...(options.fetch ? { fetch: options.fetch } : {}) });\n if (result.available) releases = result.releases;\n else warn(`the releases page has no GitHub releases: ${result.reason}.`);\n }\n\n let npm: NpmVersionTime[] = [];\n if (options.packages && options.packages.length > 0) {\n const result = await npmPublishTimes({ packages: options.packages, ...(options.fetch ? { fetch: options.fetch } : {}) });\n npm = result.times;\n for (const problem of result.problems) warn(problem);\n }\n\n return mergeReleases({\n changelogs,\n githubReleases: releases,\n tags,\n npm,\n group: options.group,\n repository,\n ref: options.ref,\n headingDate: (version, file) => headingDate(repoDir, version, file),\n now: options.now,\n warn,\n });\n}\n","/**\n * The status data: the open work of a roadmap file, and the open pull requests and issues of a\n * GitHub repository. The build reads both, so the page shows the state at the time of the build.\n *\n * @remarks The roadmap parser reads two forms. The first form is each Markdown table with an `ID`\n * column and a `Status` column. The second form is each heading \"### `id`: Title\" under a \"##\" heading\n * that gives the status. The parser is strict: a row whose cells do not match the header stops the\n * build with the file and the line.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { join, posix } from \"node:path\";\nimport { githubOpenWork } from \"./github.ts\";\nimport type { BoardItem, GitHubOpenWork, Link, StatusBoardData, StatusClass } from \"./types.ts\";\n\n/** The classes of a status, in the sequence of the board. The open work comes first. */\nexport const STATUS_CLASSES: readonly StatusClass[] = [\"waiting\", \"blocked\", \"progress\", \"open\", \"later\", \"done\"];\n\n/** The open classes, in the sequence of the board. */\nexport const OPEN_CLASSES: readonly StatusClass[] = [\"waiting\", \"blocked\", \"progress\", \"open\", \"later\"];\n\n/** An error in the roadmap file, with the file and the line. */\nexport class RoadmapParseError extends Error {}\n\n// The keywords of each class. In a status text, the first keyword wins: \"done, needs a release\" is\n// done, and \"blocked, waits for X\" is blocked. A negation (\"not started\") comes first, so that the\n// word after it does not count.\nconst STATUS_KEYWORDS: ReadonlyArray<[StatusClass, RegExp]> = [\n [\"open\", /\\bnot\\s+(?:yet\\s+)?(?:started|done|fixed|merged|shipped|released)\\b|\\bto[ -]?do\\b/],\n // A closed item that did not ship (\"never\", \"dropped\") is not open work either\n [\"done\", /\\b(?:done|shipped|merged|fixed|released|complete|completed|closed|never|dropped|cancell?ed|wontfix)\\b|\\bwon't do\\b/],\n [\"progress\", /\\bin[ -]progress\\b|\\b(?:active|ongoing|started|wip)\\b/],\n [\"waiting\", /\\b(?:waiting|waits|awaiting|needs)\\b/],\n [\"blocked\", /\\bblocked\\b/],\n [\"later\", /\\b(?:later|deferred|postponed|someday)\\b/],\n];\n\n/**\n * This function gives the class of a free-text status: done, progress, waiting, blocked, later or\n * open. The first keyword of the text decides. A text without a keyword (\"next\", \"open\") is open.\n */\nexport function statusClassOf(text: string | null | undefined): StatusClass {\n const lower = String(text ?? \"\").toLowerCase();\n let best: { index: number; value: StatusClass } = { index: Infinity, value: \"open\" };\n for (const [value, pattern] of STATUS_KEYWORDS) {\n const match = pattern.exec(lower);\n if (match && match.index < best.index) best = { index: match.index, value };\n }\n return best.value;\n}\n\n/** This function gives the cells of a table row. A \"|\" in a code span or after \"\\\" is text. */\nexport function splitRow(line: string): string[] {\n const cells: string[] = [];\n let cell = \"\";\n let code = false;\n const text = line.trim().replace(/^\\|/, \"\").replace(/\\|$/, \"\");\n for (let index = 0; index < text.length; index++) {\n const char = text[index];\n if (char === \"\\\\\" && text[index + 1] === \"|\") {\n cell += \"|\";\n index++;\n } else if (char === \"`\") {\n code = !code;\n cell += char;\n } else if (char === \"|\" && !code) {\n cells.push(cell.trim());\n cell = \"\";\n } else {\n cell += char;\n }\n }\n cells.push(cell.trim());\n return cells;\n}\n\n/** A whitespace character, as `\\s` of a regular expression and `String.prototype.trim` read it. */\nconst SPACE = /\\s/;\n/** A character that `.` of a regular expression does not match. */\nconst LINE_TERMINATOR = /[\\n\\r\\u2028\\u2029]/;\n/** The first whitespace character at or after `lastIndex`. */\nconst NEXT_SPACE = /\\s/g;\n\n/**\n * This function replaces each Markdown link `[label](target)` of a text with the result of\n * `replace`. The label ends at the first `]`, and the target ends at the first `)`. In `strict`\n * mode, the label and the target are not empty, and the target has no whitespace.\n *\n * @remarks The function reads the text one time. A regular expression for these links can\n * backtrack (CodeQL `js/polynomial-redos`). For a long text with many `[` characters, its time\n * grows with the square of the length.\n */\nfunction replaceLinks(text: string, strict: boolean, replace: (label: string, target: string) => string): string {\n let result = \"\";\n let copied = 0;\n // The first \"]\" after the current \"[\", the first \")\" after its \"](\", and the first whitespace\n // after its \"](\". The values only increase, so each search starts where the last one stopped.\n let close = -1;\n let end = -1;\n let space = -1;\n for (let open = text.indexOf(\"[\"); open !== -1; open = text.indexOf(\"[\", open + 1)) {\n if (close <= open) close = text.indexOf(\"]\", open + 1);\n if (close === -1) break;\n if (text[close + 1] !== \"(\" || (strict && close === open + 1)) continue;\n const start = close + 2;\n if (end < start) end = text.indexOf(\")\", start);\n if (end === -1) break;\n if (strict) {\n if (space !== Infinity && space < start) {\n NEXT_SPACE.lastIndex = start;\n space = NEXT_SPACE.exec(text)?.index ?? Infinity;\n }\n if (end === start || space < end) continue;\n }\n result += text.slice(copied, open) + replace(text.slice(open + 1, close), text.slice(start, end));\n copied = end + 1;\n open = end;\n }\n return result + text.slice(copied);\n}\n\n/**\n * This function gives the text of an ATX heading without its closing sequence: the whitespace,\n * then the `#` characters, then the whitespace at the end. It gives null when the rest has a line\n * terminator, as the regular expression `(.*?)\\s*#*\\s*$` does.\n */\nfunction closeHeading(text: string): string | null {\n let end = text.length;\n while (end > 0 && SPACE.test(text[end - 1] ?? \"\")) end--;\n while (end > 0 && text[end - 1] === \"#\") end--;\n while (end > 0 && SPACE.test(text[end - 1] ?? \"\")) end--;\n const rest = text.slice(0, end);\n return LINE_TERMINATOR.test(rest) ? null : rest;\n}\n\n/** The start of an ATX heading. The text after the whitespace goes to `closeHeading`. */\nconst HEADING = /^(#{1,6})\\s+(\\S[\\s\\S]*)?$/;\n\n/** This function gives the level and the text of an ATX heading line, or null for another line. */\nfunction headingOf(line: string): { level: number; text: string } | null {\n const match = HEADING.exec(line);\n const text = match ? closeHeading(match[2] ?? \"\") : null;\n return match && text !== null ? { level: match[1]?.length ?? 0, text } : null;\n}\n\n/** This function gives the plain text of inline Markdown: no code marks, no emphasis, the text of each link. */\nexport function plainText(markdown: string | null | undefined): string {\n return replaceLinks(String(markdown ?? \"\"), false, (label) => label)\n .replace(/[`*_]/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/** A cell with no value: empty, or a dash. */\nfunction isEmpty(cell: string | undefined): boolean {\n return cell === undefined || /^(?:[-–—]|n\\/a)?$/i.test(cell.trim());\n}\n\n/** A table of a Markdown file. */\nexport interface MarkdownTable {\n /** The nearest heading above the table, as plain text. */\n section: string;\n /** The line of the header. */\n line: number;\n /** The header names, in lowercase plain text. */\n header: string[];\n rows: Array<{ line: number; cells: string[] }>;\n}\n\n/**\n * This function gives the tables of a Markdown file. Each table has its header names in lowercase\n * plain text, the nearest heading above it, the line of its header and its rows. Fenced code is not read.\n */\nexport function markdownTables(markdown: string): MarkdownTable[] {\n const lines = String(markdown).split(/\\r?\\n/);\n const tables: MarkdownTable[] = [];\n let section = \"\";\n let fence: string | null = null;\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? \"\";\n const fenceMark = /^\\s*(`{3,}|~{3,})/.exec(line)?.[1];\n if (fenceMark !== undefined) {\n if (fence === null) fence = fenceMark[0] ?? null;\n else if (fenceMark[0] === fence) fence = null;\n continue;\n }\n if (fence !== null) continue;\n const heading = headingOf(line);\n if (heading) {\n section = plainText(heading.text);\n continue;\n }\n if (!line.trim().startsWith(\"|\")) continue;\n const separator = lines[index + 1] ?? \"\";\n if (!/^\\s*(?:\\|\\s*)?:?-{3,}/.test(separator)) continue;\n const header = splitRow(line).map((name) => plainText(name).toLowerCase());\n const rows: MarkdownTable[\"rows\"] = [];\n let next = index + 2;\n for (; next < lines.length && (lines[next] ?? \"\").trim().startsWith(\"|\"); next++) {\n rows.push({ line: next + 1, cells: splitRow(lines[next] ?? \"\") });\n }\n tables.push({ section, line: index + 1, header, rows });\n index = next - 1;\n }\n return tables;\n}\n\n/** The options of the link functions. */\nexport interface LinkOptions {\n /** The path of the roadmap file in the repository. */\n file?: string;\n /** \"owner/name\" of the repository. */\n repository?: string;\n /** The branch or the commit of the relative links. The default is \"HEAD\". */\n ref?: string;\n}\n\n/** The columns whose cells hold the links of an item. */\nconst LINK_COLUMNS = [\"where\", \"commit\", \"commits\", \"link\", \"links\", \"pr\", \"prs\"];\n/** Words before a reference that do not name a repository. */\nconst NOT_REPOSITORIES = new Set(\n \"a an and also at by commit commits done fixed for from in into issue issues merged of on or plus pr prs run see the then to via with\".split(\" \"),\n);\n\n/** The URL of a link target of the roadmap file: an absolute URL stays, and a relative one goes to GitHub. */\nfunction linkUrl(target: string, { file = \"\", repository = \"\", ref = \"HEAD\" }: LinkOptions): string | null {\n if (/^[a-z][a-z0-9+.-]*:/i.test(target)) return target;\n if (!repository) return null;\n const [path = \"\", anchor = \"\"] = target.split(\"#\", 2);\n const resolved = path === \"\" ? file : posix.normalize(posix.join(posix.dirname(file), path));\n if (resolved.startsWith(\"..\")) return null;\n return `https://github.com/${repository}/blob/${ref}/${resolved}${anchor ? `#${anchor}` : \"\"}`;\n}\n\n/**\n * This function gives the word right before the whitespace that ends `text.slice(0, end)`, as the\n * regular expression `([A-Za-z][\\w.-]*)\\s+$` does. The word starts with a letter. The function\n * reads only the characters of the word and of the whitespace.\n */\nfunction wordBefore(text: string, end: number): string | undefined {\n let stop = end;\n while (stop > 0 && SPACE.test(text[stop - 1] ?? \"\")) stop--;\n if (stop === end) return undefined;\n let start = stop;\n while (start > 0 && /[\\w.-]/.test(text[start - 1] ?? \"\")) start--;\n while (start < stop && !/[A-Za-z]/.test(text[start] ?? \"\")) start++;\n return start < stop ? text.slice(start, stop) : undefined;\n}\n\n/**\n * This function gives the links of a cell: each Markdown link, then each bare reference in the rest\n * of the text. A reference is a pull request (\"PR #12\", \"#12\") or a commit hash in a code span.\n *\n * @remarks A repository name right before a reference (\"systems PR #16\") applies to it and to the\n * next references of the cell. Without a name, a reference belongs to `repository`.\n */\nexport function linksOf(cell: string | null | undefined, options: LinkOptions = {}): Link[] {\n const { repository = \"\" } = options;\n const links: Link[] = [];\n const seen = new Set<string>();\n const add = (label: string, url: string | null): void => {\n if (!url || seen.has(url)) return;\n seen.add(url);\n links.push({ label, url });\n };\n const rest = replaceLinks(String(cell ?? \"\"), true, (label, target) => {\n add(plainText(label), linkUrl(target, options));\n return \" \";\n });\n if (!repository) return links;\n const [owner, defaultRepo] = repository.split(\"/\");\n let current = defaultRepo;\n // After \"PR\", the next numbers of the cell are pull requests too: \"PRs #28, #29 and #30\"\n let pulls = false;\n const reference = /\\bPRs?\\s*#(\\d+)|(?<![\\w/&])#(\\d+)\\b|`([0-9a-f]{7,40})`/g;\n for (let match = reference.exec(rest); match; match = reference.exec(rest)) {\n const word = wordBefore(rest, match.index);\n if (word && !NOT_REPOSITORIES.has(word.toLowerCase())) current = word;\n const prefix = current === defaultRepo ? \"\" : `${current} `;\n if (match[1] !== undefined) pulls = true;\n const number = match[1] ?? match[2];\n if (number !== undefined) add(`${prefix}#${number}`, `https://github.com/${owner}/${current}/${pulls ? \"pull\" : \"issues\"}/${number}`);\n else if (match[3] !== undefined) add(`${prefix}${match[3].slice(0, 7)}`, `https://github.com/${owner}/${current}/commit/${match[3]}`);\n }\n return links;\n}\n\n/**\n * The heading of an item: \"### `id`: Title\". A dash can take the place of the colon. The title goes\n * to `closeHeading`.\n */\nconst ITEM_HEADING = /^###\\s+`([^`]+)`\\s*[:–—-]\\s*(\\S[\\s\\S]*)?$/;\n/** The other heading of an item: \"### S1 · Title\". The ID is one word before the middle dot. */\nconst ITEM_HEADING_DOT = /^###\\s+([A-Za-z0-9][\\w.-]*)\\s+·\\s+(\\S[\\s\\S]*)?$/;\n\n/** This function gives the ID and the title of an item heading, or null for another line. */\nfunction itemHeadingOf(line: string): { id: string; title: string } | null {\n for (const pattern of [ITEM_HEADING, ITEM_HEADING_DOT]) {\n const match = pattern.exec(line);\n const title = match ? closeHeading(match[2] ?? \"\") : null;\n if (match && title !== null) return { id: match[1] ?? \"\", title };\n }\n return null;\n}\n\n/**\n * A field of an item heading: \"- Area: Docs\", \"- **Area:** Docs\" or \"- **Area**: Docs\". The label\n * matches without case.\n */\nconst ITEM_FIELD = /^\\s*[-*]\\s+(\\*\\*|__)?([A-Za-z][A-Za-z ]*?)(?::\\1|\\1:)\\s*(\\S.*)?$/;\n/** The fields of an item heading that give the optional fields of an item. */\nconst ITEM_FIELDS: Readonly<Record<string, \"area\" | \"owner\" | \"needs\">> = {\n area: \"area\",\n owner: \"owner\",\n \"waits for\": \"needs\",\n needs: \"needs\",\n \"depends on\": \"needs\",\n};\n\n/**\n * This function gives the items of the second form of a roadmap: each heading \"### `id`: Title\" or\n * \"### id · Title\". The list item \"Status:\" gives the status. Without it, the \"##\" heading above\n * the item gives the status, for example \"Waiting on Mark\", \"Later\" or \"Shipped\". A heading without\n * a status is not an item.\n *\n * The list items \"Area:\", \"Owner:\" and \"Waits for:\" give the optional fields. The list item\n * \"Links:\" and the other list items give the links. Fenced code is not read.\n */\nfunction headingItems(markdown: string, options: LinkOptions & { file: string }): BoardItem[] {\n const lines = String(markdown).split(/\\r?\\n/);\n const items: BoardItem[] = [];\n let section = \"\";\n let current: BoardItem | undefined;\n let fence: string | null = null;\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? \"\";\n const fenceMark = /^\\s*(`{3,}|~{3,})/.exec(line)?.[1];\n if (fenceMark !== undefined) {\n if (fence === null) fence = fenceMark[0] ?? null;\n else if (fenceMark[0] === fence) fence = null;\n continue;\n }\n if (fence !== null) continue;\n const heading = headingOf(line);\n if (heading) {\n const { level } = heading;\n if (level > 3) continue;\n current = undefined;\n if (level === 2) section = plainText(heading.text);\n if (level === 1) section = \"\";\n if (level !== 3) continue;\n const item = itemHeadingOf(line);\n const id = plainText(item?.id);\n if (!item || isEmpty(id)) continue;\n current = { id, title: item.title, status: section, statusClass: statusClassOf(section), section, line: index + 1, links: [] };\n items.push(current);\n continue;\n }\n if (!current) continue;\n const field = ITEM_FIELD.exec(line);\n const label = (field?.[2] ?? \"\").trim().toLowerCase();\n const value = (field?.[3] ?? \"\").trim();\n const key = field ? ITEM_FIELDS[label] : undefined;\n if (field && label === \"status\") {\n // The field of the item wins over the section\n if (!isEmpty(value)) {\n current.status = value;\n current.statusClass = statusClassOf(plainText(value));\n }\n } else if (field && key !== undefined) {\n if (!isEmpty(value)) current[key] = value;\n } else if (/^\\s*[-*]\\s+/.test(line)) {\n const seen = new Set(current.links.map((link) => link.url));\n for (const link of linksOf(line, options)) if (!seen.has(link.url)) current.links.push(link);\n }\n }\n // A heading without a section and without a \"Status:\" field has no status: it is not an item\n return items.filter((item) => item.status !== \"\");\n}\n\n/**\n * This function gives the items of a roadmap file in the order of the file. It reads two forms:\n *\n * - Each row of each table with an `ID` column and a `Status` column. The header names match without\n * case. The title comes from `Item`, else from `Title`. `Owner`, `Area` and `Needs` are optional.\n * `Where`, `Commit` and `Links` give the links.\n * - Each heading \"### `id`: Title\" or \"### id · Title\". The list item \"Status:\", else the \"##\"\n * heading above it, gives the status. The list items \"Area:\", \"Owner:\" and \"Waits for:\" give the\n * optional fields, and \"Links:\" and the other list items give the links.\n *\n * @throws RoadmapParseError when the cells of a row do not match the header\n */\nexport function roadmapItems(markdown: string, options: LinkOptions = {}): BoardItem[] {\n const { file = \"ROADMAP.md\" } = options;\n const items: BoardItem[] = [];\n for (const table of markdownTables(markdown)) {\n const column = (...names: string[]): number => names.map((name) => table.header.indexOf(name)).find((index) => index >= 0) ?? -1;\n const id = column(\"id\");\n const status = column(\"status\");\n if (id < 0 || status < 0) continue;\n const title = column(\"item\", \"title\");\n const owner = column(\"owner\");\n const area = column(\"area\");\n const needs = column(\"needs\");\n const linkColumns = LINK_COLUMNS.map((name) => table.header.indexOf(name)).filter((index) => index >= 0);\n for (const row of table.rows) {\n if (row.cells.length !== table.header.length) {\n throw new RoadmapParseError(`${file}:${row.line}: the row has ${row.cells.length} cells, and the header has ${table.header.length}`);\n }\n const idText = plainText(row.cells[id]);\n if (isEmpty(idText)) continue;\n const statusText = row.cells[status] ?? \"\";\n const item: BoardItem = {\n id: idText,\n title: title >= 0 ? (row.cells[title] ?? \"\") : \"\",\n status: statusText,\n statusClass: statusClassOf(plainText(statusText)),\n section: table.section,\n line: row.line,\n links: linkColumns.flatMap((index) => linksOf(row.cells[index], { ...options, file })),\n };\n const optional = (index: number): string | undefined => (index >= 0 && !isEmpty(row.cells[index]) ? row.cells[index] : undefined);\n const ownerText = optional(owner);\n const areaText = optional(area);\n const needsText = optional(needs);\n if (ownerText !== undefined) item.owner = ownerText;\n if (areaText !== undefined) item.area = areaText;\n if (needsText !== undefined) item.needs = needsText;\n items.push(item);\n }\n }\n const headings = headingItems(markdown, { ...options, file });\n return headings.length === 0 ? items : [...items, ...headings].sort((a, b) => a.line - b.line);\n}\n\n// ---------------------------------------------------------------------------\n// The board\n// ---------------------------------------------------------------------------\n\n/** The input of `buildStatusBoard`. */\nexport interface StatusBoardInput {\n items: BoardItem[];\n /** The result of `githubOpenWork`. */\n github: GitHubOpenWork;\n /** The roadmap file in the repository, or null without a roadmap. */\n roadmap: string | null;\n /** \"owner/name\" of the repository. */\n repository: string;\n commit?: string | null;\n generatedAt?: string;\n}\n\n/**\n * This function gives the items of a roadmap file, as the Status page reads them. It fails when the file has no item.\n *\n * @throws RoadmapParseError when the cells of a row do not match the header\n * @throws RoadmapParseError when the roadmap has no item: no table with an ID and a Status column, and no item heading\n */\nexport function parseRoadmap(markdown: string, options: LinkOptions = {}): BoardItem[] {\n const { file = \"ROADMAP.md\" } = options;\n const items = roadmapItems(markdown, options);\n if (items.length === 0) throw new RoadmapParseError(`${file}: no table with an ID column and a Status column, and no heading \"### \\`id\\`: Title\"`);\n return items;\n}\n\n/** This function puts the roadmap items and the GitHub part into the shape of `status.json`. */\nexport function buildStatusBoard(input: StatusBoardInput): StatusBoardData {\n const { items, github, roadmap, repository, commit = null, generatedAt = new Date().toISOString() } = input;\n return {\n generatedAt,\n commit,\n source: { roadmap, github: repository },\n items,\n pullRequests: github.available ? github.pullRequests : [],\n issues: github.available ? github.issues : [],\n github: github.available ? { available: true, totals: github.totals } : { available: false, reason: github.reason },\n };\n}\n\n/** The options of `readStatusBoard`. */\nexport interface ReadStatusBoardOptions {\n repoDir: string;\n /** The path of the roadmap file from `repoDir`, with `/`. Without it, the board has only the GitHub part. */\n roadmap?: string | null | undefined;\n owner: string;\n repo: string;\n token: string | undefined;\n /** The commit of the build. The relative links of the roadmap go to it. */\n commit?: string | null | undefined;\n fetch?: typeof fetch | undefined;\n generatedAt?: string | undefined;\n}\n\n/**\n * This function reads the board of a repository on disk: the roadmap file, and the open work on GitHub.\n *\n * @throws RoadmapParseError when the roadmap has an incorrect row, or no item: no table with an ID\n * and a Status column, and no item heading\n */\nexport async function readStatusBoard(options: ReadStatusBoardOptions): Promise<StatusBoardData> {\n const { repoDir, roadmap = null, owner, repo, token, commit = null } = options;\n const repository = `${owner}/${repo}`;\n let items: BoardItem[] = [];\n if (roadmap) {\n const markdown = readFileSync(join(repoDir, ...roadmap.split(\"/\")), \"utf8\");\n items = parseRoadmap(markdown, { file: roadmap, repository, ref: commit ?? \"HEAD\" });\n }\n const github = await githubOpenWork({ owner, repo, token, ...(options.fetch ? { fetch: options.fetch } : {}) });\n return buildStatusBoard({\n items,\n github,\n roadmap: roadmap || null,\n repository,\n commit,\n ...(options.generatedAt ? { generatedAt: options.generatedAt } : {}),\n });\n}\n","/**\n * The HTML helpers of the pages: the escape functions and a small inline Markdown renderer.\n */\n\nconst ESCAPES: Record<string, string> = { \"&\": \"&\", \"<\": \"<\", \">\": \">\", '\"': \""\", \"'\": \"'\" };\n\n/** This function escapes a text for HTML content and for an attribute value in double quotes. */\nexport function escapeHtml(text: string): string {\n return String(text).replace(/[&<>\"']/g, (char) => ESCAPES[char] ?? char);\n}\n\n/**\n * This function removes the control characters and the spaces (U+0000 to U+0020) at the two ends\n * of a text. A loop does it, because the regular expression `[\\u0000- ]+$` backtracks. For a long\n * run of these characters, its time grows with the square of the length.\n */\nfunction trimControl(text: string): string {\n let start = 0;\n let end = text.length;\n while (start < end && text.charCodeAt(start) <= 0x20) start++;\n while (end > start && text.charCodeAt(end - 1) <= 0x20) end--;\n return text.slice(start, end);\n}\n\n/**\n * This function gives a URL that a link can hold, or null. It accepts `http:`, `https:` and\n * `mailto:` URLs, and relative URLs. It refuses each other scheme, for example `javascript:`.\n *\n * The URL parser of a browser removes each tab and line break, and the control characters and\n * spaces at the two ends. This function removes them before the scheme check, as the browser does.\n * Thus a control character before `javascript:` does not hide the scheme.\n */\nexport function safeUrl(url: string): string | null {\n const trimmed = trimControl(url.trim().replace(/[\\t\\n\\r]/g, \"\"));\n if (/^(?:https?:|mailto:)/i.test(trimmed)) return trimmed;\n // A browser reads \"\\\" as \"/\" in a URL of the page, so \"\\\\host\" and \"/\\host\" go to a different host, as \"//host\" does\n if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed) || /^[/\\\\]{2}/.test(trimmed)) return null;\n return trimmed;\n}\n\n/** This function gives an `<a>` element, or the escaped text when the URL is not safe. */\nexport function link(url: string, html: string, attributes = \"\"): string {\n const href = safeUrl(url);\n return href === null ? html : `<a href=\"${escapeHtml(href)}\"${attributes ? ` ${attributes}` : \"\"}>${html}</a>`;\n}\n\n/** The emphasis of a text without code spans or links. The text is already escaped. */\nfunction emphasis(escaped: string): string {\n return escaped\n .replace(/\\*\\*([^*]+?)\\*\\*/g, \"<strong>$1</strong>\")\n .replace(/(^|[^\\w*])\\*([^*\\s][^*]*?)\\*(?![\\w*])/g, \"$1<em>$2</em>\")\n .replace(/(^|[^\\w])_([^_\\s][^_]*?)_(?![\\w])/g, \"$1<em>$2</em>\");\n}\n\nconst INLINE = \"`([^`]+)`|\\\\[((?:[^\\\\]`]|`[^`]*`)+)\\\\]\\\\(([^)\\\\s]+)\\\\)\";\n\n/**\n * This function renders inline Markdown as HTML: code spans, links, strong text and emphasis. It\n * escapes all other text, so the result is safe.\n */\nexport function inlineMarkdown(markdown: string): string {\n const text = String(markdown ?? \"\");\n // A new expression for each call: the text of a link is rendered with a recursive call\n const pattern = new RegExp(INLINE, \"g\");\n let html = \"\";\n let last = 0;\n for (let match = pattern.exec(text); match; match = pattern.exec(text)) {\n html += emphasis(escapeHtml(text.slice(last, match.index)));\n if (match[1] !== undefined) html += `<code>${escapeHtml(match[1])}</code>`;\n else html += link(match[3] ?? \"\", inlineMarkdown(match[2] ?? \"\"));\n last = match.index + match[0].length;\n }\n return html + emphasis(escapeHtml(text.slice(last)));\n}\n\n/** This function gives \"1 item\" or \"2 items\". */\nexport function plural(count: number, word: string, many = `${word}s`): string {\n return `${count} ${count === 1 ? word : many}`;\n}\n\n/** This function gives \"a\", \"a and b\" or \"a, b and c\". */\nexport function listText(parts: readonly string[]): string {\n if (parts.length <= 1) return parts.join(\"\");\n return `${parts.slice(0, -1).join(\", \")} and ${parts[parts.length - 1]}`;\n}\n","/**\n * The dates of the pages. The pages show each date in UTC, so the build and the browser agree.\n */\n\n/** The milliseconds of one day. */\nexport const DAY_MS = 86_400_000;\nconst MONTHS = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\n\n/** This function gives the start of the UTC day of a time. */\nexport function utcDay(time: number): number {\n return Math.floor(time / DAY_MS) * DAY_MS;\n}\n\n/** This function gives \"Oct 18\": the UTC day of a time or of an ISO date. */\nexport function shortDate(date: string | number): string {\n const day = new Date(date);\n return `${MONTHS[day.getUTCMonth()]} ${day.getUTCDate()}`;\n}\n\n/** This function gives \"Oct 18, 2026, 19:34 UTC\", or \"an unknown time\" for a date that is not valid. */\nexport function longDate(date: string | number): string {\n const day = new Date(date);\n if (Number.isNaN(day.getTime())) return \"an unknown time\";\n const time = `${String(day.getUTCHours()).padStart(2, \"0\")}:${String(day.getUTCMinutes()).padStart(2, \"0\")}`;\n return `${shortDate(date)}, ${day.getUTCFullYear()}, ${time} UTC`;\n}\n\n/** This function gives \"Oct 13–15\", or \"Sep 30–Oct 2\" over the end of a month. */\nexport function dayRange(start: number, end: number): string {\n if (utcDay(start) === utcDay(end)) return shortDate(start);\n const first = new Date(start);\n const last = new Date(end);\n return first.getUTCMonth() === last.getUTCMonth() ? `${shortDate(start)}–${last.getUTCDate()}` : `${shortDate(start)}–${shortDate(end)}`;\n}\n","/**\n * The page shell and the CSS of the standalone pages. The CSS uses variables (`--sp-bg`, `--sp-fg`,\n * `--sp-accent` and the others), so a site can change the colors and the fonts with `extraCss`.\n */\n\nimport { longDate } from \"./dates.ts\";\nimport { escapeHtml, link } from \"./html.ts\";\n\n/** The options of each page. */\nexport interface PageOptions {\n /** \"owner/name\" of the repository on GitHub. */\n repository: string;\n /** The path of the site home, with a `/` at the start and at the end, for example `/client/`. */\n base: string;\n /** The name of the site in the header. The default is the name of the repository. */\n siteName?: string | undefined;\n /** More CSS for the page. It comes after the default CSS, so it can change each variable. */\n extraCss?: string | undefined;\n /** The ISO time of the build. */\n generatedAt: string;\n /** The commit of the build, or null. */\n commit: string | null;\n}\n\n// The dark colors: for [data-theme=\"dark\"], and for the dark system theme without [data-theme=\"light\"]\nconst DARK = `color-scheme:dark;--sp-bg:#0e1220;--sp-surface:#151a2b;--sp-sunken:#1c2236;--sp-fg:#e6e9f3;--sp-fg-2:#b3bad0;\n--sp-muted:#949cb3;--sp-rule:#2b3350;--sp-rule-strong:#46507a;--sp-accent:#93abff;--sp-accent-strong:#bccbff;--sp-accent-wash:#1f2a4f;\n--sp-good-ink:#4cc94c;--sp-warn-ink:#fab219;--sp-bad-ink:#ff8a8a;--sp-grid:#232a40;--sp-axis:#5d6683;`;\n\n/** The default CSS of the pages: the variables, the light and dark themes, and the parts of both pages. */\nexport const BASE_CSS: string = `\n:root{color-scheme:light;--sp-bg:#f5f6f9;--sp-surface:#ffffff;--sp-sunken:#eef1f6;--sp-fg:#151c2e;--sp-fg-2:#454f67;\n--sp-muted:#5f6880;--sp-rule:#d6dbe5;--sp-rule-strong:#aeb6c7;--sp-accent:#2346c4;--sp-accent-strong:#172f8f;--sp-accent-wash:#e7ecfd;\n--sp-good:#0ca30c;--sp-good-ink:#006300;--sp-warn:#fab219;--sp-warn-ink:#7a5200;--sp-bad:#d03b3b;--sp-bad-ink:#a3262a;\n--sp-neutral:#8a91a3;--sp-grid:#e6e9f0;--sp-axis:#9aa1b3;\n--sp-font:system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;\n--sp-mono:ui-monospace,\"Cascadia Mono\",\"SFMono-Regular\",Menlo,Consolas,monospace;--sp-radius:6px;--sp-width:64rem}\n:root[data-theme=\"dark\"]{${DARK}}\n@media (prefers-color-scheme:dark){:root:not([data-theme=\"light\"]){${DARK}}}\n*,*::before,*::after{box-sizing:border-box}\n[hidden]{display:none!important}\nhtml{-webkit-text-size-adjust:100%;text-size-adjust:100%}\nbody{margin:0;background:var(--sp-bg);color:var(--sp-fg);font-family:var(--sp-font);font-size:1rem;line-height:1.55}\na{color:var(--sp-accent);text-underline-offset:2px}\na:hover{color:var(--sp-accent-strong)}\n:focus-visible{outline:2px solid var(--sp-accent);outline-offset:2px}\ncode{font-family:var(--sp-mono);font-size:.9em;background:var(--sp-sunken);border-radius:3px;padding:0 .25em;overflow-wrap:anywhere}\nh1{font-size:2rem;line-height:1.2;margin:.5rem 0 .75rem}\nh2{font-size:1.35rem;line-height:1.3;margin:0 0 .5rem}\nh3{font-size:1.1rem;line-height:1.3}\np{margin:0 0 .75rem}\nbutton{font:inherit;color:inherit}\n.sp-skip{position:absolute;left:-9999px;top:0}\n.sp-skip:focus{left:16px;top:8px;z-index:10;background:var(--sp-surface);padding:.25rem .5rem}\n.sp-header{background:var(--sp-surface);border-bottom:1px solid var(--sp-rule)}\n.sp-header nav{max-width:var(--sp-width);margin:0 auto;padding:.6rem 16px;display:flex;flex-wrap:wrap;align-items:baseline;gap:.25rem 1.25rem}\n.sp-home{margin-right:auto;font-weight:700;color:var(--sp-fg);text-decoration:none;overflow-wrap:anywhere}\n.sp-header a[aria-current=\"page\"]{color:var(--sp-fg);font-weight:600;text-decoration:none}\n.sp-main{max-width:var(--sp-width);margin:0 auto;padding:16px;min-width:0;overflow-wrap:break-word}\n.sp-footer{max-width:var(--sp-width);margin:2rem auto 0;padding:16px;border-top:1px solid var(--sp-rule);color:var(--sp-muted);font-size:.875rem}\n.sp-lead{font-size:1.2rem;max-width:70ch}\n.sp-small{font-size:.875rem}\n.sp-muted{color:var(--sp-muted)}\n.sp-panel{background:var(--sp-surface);border:1px solid var(--sp-rule);border-radius:var(--sp-radius);padding:16px;min-width:0}\n.sp-pill{display:inline-block;border:1px solid var(--sp-rule-strong);border-radius:999px;padding:0 .5rem;font-size:.8125rem;line-height:1.5;color:var(--sp-fg-2);white-space:nowrap}\n.sp-pill.sp-accent{border-color:var(--sp-accent);background:var(--sp-accent-wash);color:var(--sp-accent-strong)}\n.sp-pill.sp-good{border-color:var(--sp-good);color:var(--sp-good-ink)}\n.sp-pill.sp-strong{border-color:var(--sp-accent-strong);background:var(--sp-accent-strong);color:var(--sp-surface);font-weight:700}\n.sp-chip{display:inline-flex;align-items:center;gap:.3rem;background:var(--sp-surface);border:1px solid var(--sp-rule-strong);border-radius:999px;padding:.1rem .7rem;font-size:.875rem;color:var(--sp-fg-2);cursor:pointer}\n.sp-chip:hover{border-color:var(--sp-accent)}\n.sp-chip[aria-pressed=\"true\"]{background:var(--sp-accent-wash);border-color:var(--sp-tone,var(--sp-accent));box-shadow:inset 0 0 0 1px var(--sp-tone,var(--sp-accent));color:var(--sp-fg)}\n.sp-count{font-family:var(--sp-mono);font-size:.8125rem;color:var(--sp-muted)}\n.sp-ghost{background:none;border:0;padding:.15rem 0;color:var(--sp-accent);text-decoration:underline;text-underline-offset:2px;cursor:pointer;font-size:.875rem}\n.sp-callout{background:var(--sp-sunken);border-left:3px solid var(--sp-rule-strong);border-radius:var(--sp-radius);padding:.6rem .8rem}\n.sp-visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n.sp-section{margin-top:2rem}\n\n/* The releases page */\n.sp-legend{display:flex;flex-wrap:wrap;gap:.25rem 1rem;margin:0 0 .5rem;padding:0;list-style:none;color:var(--sp-fg-2);font-size:.875rem}\n.sp-legend li{display:inline-flex;align-items:center;gap:.25rem}\n.sp-legend svg{flex:none;overflow:visible}\n.sp-timeline-box{overflow-x:auto;overflow-y:hidden;max-width:100%;overscroll-behavior-x:contain}\n.sp-timeline-box svg{display:block;overflow:visible;max-width:none}\n.sp-timeline-wide{display:none}\n@media (min-width:1000px){.sp-timeline-narrow{display:none}.sp-timeline-wide{display:block}}\n.sp-gap{fill:var(--sp-sunken)}\n.sp-grid{stroke:var(--sp-grid);stroke-width:1}\n.sp-axis{stroke:var(--sp-axis);stroke-width:1}\n.sp-day{fill:var(--sp-fg-2);font-family:var(--sp-font);font-size:12px;font-weight:600}\n.sp-day-count{fill:var(--sp-muted);font-family:var(--sp-font);font-size:11px}\n.sp-mark{cursor:pointer;outline:none}\n.sp-hit{fill:transparent}\n.sp-dot{fill:var(--sp-accent);stroke:var(--sp-surface);stroke-width:1.5}\n.sp-ring{fill:var(--sp-surface);stroke:var(--sp-accent);stroke-width:2}\n.sp-kind-first .sp-dot{fill:var(--sp-good)}\n.sp-kind-major .sp-dot{fill:var(--sp-accent-strong)}\n.sp-halo{fill:none;stroke:var(--sp-accent);stroke-width:2;pointer-events:none;display:none}\n.sp-mark.sp-selected .sp-halo{display:inline}\n.sp-label{fill:var(--sp-fg-2);font-family:var(--sp-mono);font-size:12px;paint-order:stroke;stroke:var(--sp-surface);stroke-width:3px;stroke-linejoin:round}\n.sp-mark:hover .sp-label,.sp-mark.sp-selected .sp-label{fill:var(--sp-accent-strong)}\n.sp-mark.sp-selected .sp-label{font-weight:700}\n.sp-mark:focus-visible .sp-hit{stroke:var(--sp-accent);stroke-width:2}\n.sp-release{margin:.75rem 0 1rem}\n.sp-release-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:.25rem .75rem;margin-bottom:.5rem}\n.sp-release-head h2{margin:0;font-family:var(--sp-mono);font-size:1.5rem}\n.sp-release-links{display:inline-flex;flex-wrap:wrap;gap:.25rem .75rem;margin-left:auto}\n.sp-changes{list-style:none;margin:.5rem 0 0;padding:0}\n.sp-change{padding:.5rem 0;border-top:1px solid var(--sp-rule);min-width:0}\n.sp-change p{margin:0 0 .25rem;overflow-wrap:anywhere}\n.sp-change-meta{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem .75rem}\n.sp-commit code{font-size:.8125rem}\n.sp-chips{display:inline-flex;flex-wrap:wrap;align-items:center;gap:.25rem}\n.sp-chips .sp-ghost{font-size:.8125rem}\n@media (max-width:560px){.sp-release-links{margin-left:0;width:100%}}\n\n/* The status page: each class has a tone, and the page always shows the tone with an icon and a label */\n.sp-c-waiting{--sp-tone:var(--sp-warn);--sp-ink:var(--sp-warn-ink)}\n.sp-c-blocked{--sp-tone:var(--sp-bad);--sp-ink:var(--sp-bad-ink)}\n.sp-c-progress{--sp-tone:var(--sp-accent);--sp-ink:var(--sp-accent-strong)}\n.sp-c-open{--sp-tone:var(--sp-neutral);--sp-ink:var(--sp-fg-2)}\n.sp-c-later{--sp-tone:var(--sp-rule-strong);--sp-ink:var(--sp-muted)}\n.sp-c-done{--sp-tone:var(--sp-good);--sp-ink:var(--sp-good-ink)}\n.sp-meter{display:flex;gap:2px;height:12px;border-radius:6px;overflow:hidden;background:var(--sp-rule);margin-top:.75rem}\n.sp-meter span{display:block;min-width:4px;background:var(--sp-tone)}\n.sp-meter-legend{display:flex;flex-wrap:wrap;gap:.25rem 1rem;list-style:none;margin:.5rem 0 1rem;padding:0;color:var(--sp-fg-2);font-size:.875rem}\n.sp-meter-legend li{display:inline-flex;align-items:center;gap:.25rem}\n.sp-meter-legend strong{font-family:var(--sp-mono);color:var(--sp-ink)}\n.sp-swatch{display:inline-block;width:12px;height:10px;border-radius:2px;background:var(--sp-tone)}\n.sp-filters{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem 1rem;margin-bottom:.5rem}\n.sp-filters>span{display:inline-flex;flex-wrap:wrap;gap:.25rem}\n.sp-group{margin-top:1.5rem}\n.sp-group h3{display:flex;align-items:center;gap:.5rem;margin:0;padding-bottom:.25rem;color:var(--sp-ink);border-bottom:2px solid var(--sp-tone)}\n.sp-group-count{font-family:var(--sp-mono);font-size:.875rem;font-weight:600;color:var(--sp-fg-2);background:var(--sp-sunken);border-radius:999px;padding:0 .5rem}\n.sp-table-box{max-width:100%;overflow-x:auto}\ntable.sp-table{width:100%;border-collapse:collapse;font-size:.9rem}\n.sp-table th,.sp-table td{text-align:left;vertical-align:top;padding:.5rem;border-bottom:1px solid var(--sp-rule)}\n.sp-table thead th{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:var(--sp-muted)}\n.sp-table th[scope=\"row\"]{font-family:var(--sp-mono);font-weight:600;white-space:nowrap;border-left:3px solid var(--sp-tone)}\n.sp-item{min-width:16rem;overflow-wrap:anywhere}\n.sp-item-meta{display:block;margin-top:2px}\n.sp-status{color:var(--sp-ink);overflow-wrap:anywhere}\n.sp-links{display:inline-flex;flex-wrap:wrap;gap:2px .5rem;overflow-wrap:anywhere}\n.sp-done{margin-top:1rem}\n.sp-done>summary{cursor:pointer;color:var(--sp-good-ink)}\n@media (max-width:760px){\n.sp-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}\n.sp-table,.sp-table tbody,.sp-table tr,.sp-table th,.sp-table td{display:block;width:100%}\n.sp-table tr{border:1px solid var(--sp-rule);border-left:4px solid var(--sp-tone);border-radius:var(--sp-radius);padding:.5rem .75rem;margin-top:.5rem;background:var(--sp-surface)}\n.sp-table th,.sp-table td{border:0;padding:2px 0}\n.sp-table th[scope=\"row\"]{border-left:0}\n.sp-table td{display:grid;grid-template-columns:4.5rem minmax(0,1fr);align-items:baseline;gap:.5rem}\n.sp-table td::before{content:attr(data-label);font-size:.75rem;color:var(--sp-muted)}\n.sp-table td.sp-item{display:block;min-width:0}\n.sp-table td.sp-item::before{content:none}\n}\n.sp-cards{list-style:none;margin:.75rem 0 0;padding:0;display:flex;flex-direction:column;gap:.5rem}\n.sp-card{background:var(--sp-surface);border:1px solid var(--sp-rule);border-radius:var(--sp-radius);padding:.5rem .75rem;min-width:0}\n.sp-card-title{display:block;font-weight:600;overflow-wrap:anywhere}\n.sp-number{font-family:var(--sp-mono);font-weight:400;color:var(--sp-muted)}\n.sp-card-meta{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem .75rem;margin-top:.25rem;color:var(--sp-fg-2);font-size:.875rem}\n.sp-branch{font-size:.8125rem;min-width:0}\n.sp-check{display:inline-flex;align-items:center;gap:.25rem;white-space:nowrap}\n.sp-dot-state{display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--sp-neutral)}\n.sp-check-success .sp-dot-state{background:var(--sp-good)}\n.sp-check-failure .sp-dot-state{background:var(--sp-bad)}\n.sp-check-pending .sp-dot-state{background:var(--sp-warn)}\n.sp-check-none .sp-dot-state{background:transparent;border:1.5px solid var(--sp-neutral)}\n.sp-labels{display:inline-flex;flex-wrap:wrap;gap:4px}\n@media (prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}\n`;\n\n// Without JavaScript, the page shows all its parts, and it hides the controls that need a script\nconst NO_SCRIPT_CSS = `.sp-release[hidden],.sp-extra[hidden]{display:block!important}li.sp-extra[hidden]{display:list-item!important}\n.sp-chips>.sp-extra[hidden]{display:inline-block!important}[data-sp-js]{display:none!important}`;\n\n/** The parts of one page. */\nexport interface PageParts {\n /** The title of the page, for example \"Releases\". */\n title: string;\n description: string;\n /** The page of the navigation that is current. */\n current: \"releases\" | \"status\";\n /** The HTML of the main content. */\n main: string;\n /** The ES module of the interactions. */\n script: string;\n}\n\n/** This function gives the name of the repository: \"client\" for \"mark1russell7/client\". */\nexport function repositoryName(repository: string): string {\n return repository.split(\"/\").pop() || repository;\n}\n\n/** This function makes the complete HTML document of a page. */\nexport function pageShell(parts: PageParts, options: PageOptions): string {\n const base = options.base.endsWith(\"/\") ? options.base : `${options.base}/`;\n const name = options.siteName || repositoryName(options.repository);\n const nav = (page: PageParts[\"current\"], label: string): string =>\n `<a href=\"${escapeHtml(`${base}${page}/`)}\"${parts.current === page ? ' aria-current=\"page\"' : \"\"}>${label}</a>`;\n const commit = options.commit\n ? ` from ${link(`https://github.com/${options.repository}/commit/${options.commit}`, `<code>${escapeHtml(options.commit.slice(0, 7))}</code>`)}`\n : \"\";\n const data = `${base}data/${parts.current}.json`;\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"color-scheme\" content=\"light dark\">\n<title>${escapeHtml(`${parts.title} · ${name}`)}</title>\n<meta name=\"description\" content=\"${escapeHtml(parts.description)}\">\n<style>${BASE_CSS}${options.extraCss ? `\\n${options.extraCss}` : \"\"}</style>\n<noscript><style>${NO_SCRIPT_CSS}</style></noscript>\n</head>\n<body>\n<a class=\"sp-skip\" href=\"#main\">Skip to the content</a>\n<header class=\"sp-header\"><nav aria-label=\"Site\"><a class=\"sp-home\" href=\"${escapeHtml(base)}\">${escapeHtml(name)}</a>${nav(\"releases\", \"Releases\")}${nav(\"status\", \"Status\")}</nav></header>\n<main id=\"main\" class=\"sp-main\">\n${parts.main}\n</main>\n<footer class=\"sp-footer\"><p>The build made this page at ${escapeHtml(longDate(options.generatedAt))}${commit}. The data is in <a href=\"${escapeHtml(data)}\"><code>${escapeHtml(`data/${parts.current}.json`)}</code></a>.</p></footer>\n<script type=\"module\">${parts.script}</script>\n</body>\n</html>\n`;\n}\n","/**\n * The layout of the release timeline: one mark for each version on a time axis.\n *\n * @remarks The axis has one band for each day with a release. A run of days without a release\n * becomes one narrow band, so the busy days get the width. In a day band, the time is linear. Marks\n * that are near each other go into lanes, so that no two labels overlap.\n */\n\nimport { compareVersions } from \"../data/versions.ts\";\nimport type { ReleaseKind } from \"../data/types.ts\";\nimport { DAY_MS, dayRange, utcDay } from \"./dates.ts\";\n\n/** What the timeline needs of a version. */\nexport interface ReleasePoint {\n version: string;\n date: string;\n kind: ReleaseKind;\n}\n\n/** The numbers of the lead line of the releases page. */\nexport interface ReleaseSummary {\n versions: number;\n major: number;\n minor: number;\n patch: number;\n /** The date of the oldest and of the newest version, or null without a release. */\n first: string | null;\n last: string | null;\n}\n\n/** This function counts the versions and the kinds. The first release counts as a version only. */\nexport function releaseSummary(releases: readonly ReleasePoint[]): ReleaseSummary {\n const times = releases.map((release) => Date.parse(release.date)).filter(Number.isFinite);\n const count = (kind: ReleaseKind): number => releases.filter((release) => release.kind === kind).length;\n return {\n versions: releases.length,\n major: count(\"major\"),\n minor: count(\"minor\"),\n patch: count(\"patch\"),\n first: times.length > 0 ? new Date(Math.min(...times)).toISOString() : null,\n last: times.length > 0 ? new Date(Math.max(...times)).toISOString() : null,\n };\n}\n\n/** This function sorts the versions from the oldest to the newest: the sequence of the marks and of the arrow keys. */\nexport function oldestFirst<T extends ReleasePoint>(releases: readonly T[]): T[] {\n return [...releases].sort((a, b) => Date.parse(a.date) - Date.parse(b.date) || compareVersions(a.version, b.version));\n}\n\n/** The options of the layout. */\nexport interface TimelineOptions {\n /** The width of the SVG, in pixels. */\n width: number;\n /** The space at each side, for the labels of the first and the last mark. */\n padX?: number;\n laneHeight?: number;\n /** The width of one character of a label (12 px monospace). */\n charWidth?: number;\n /** The minimum space between two labels in one lane. */\n gap?: number;\n /** The width of a run of days without a release, as a part of the width of a day with releases. */\n emptyWeight?: number;\n}\n\n/** A band of the axis: one day with releases, or a run of days with none. */\nexport interface TimelineBand {\n start: number;\n /** The end of the band: the start of the next day. */\n end: number;\n x0: number;\n x1: number;\n label: string;\n count: number;\n empty: boolean;\n}\n\n/** One mark of the timeline. */\nexport interface TimelineMark<T extends ReleasePoint = ReleasePoint> {\n release: T;\n time: number;\n x: number;\n /** The lane of the mark: 0 is the lane next to the axis. */\n lane: number;\n /** The half width of the label and of the target of the pointer. */\n half: number;\n}\n\n/** The layout of the timeline at one width. */\nexport interface TimelineLayout<T extends ReleasePoint = ReleasePoint> {\n width: number;\n height: number;\n plotTop: number;\n /** The y of the axis line. */\n plotBottom: number;\n laneHeight: number;\n lanes: number;\n bands: TimelineBand[];\n /** The marks from the oldest to the newest. */\n marks: Array<TimelineMark<T>>;\n}\n\n/** The top margin of the plot. */\nexport const PLOT_TOP = 6;\n/** The height of the axis labels under the plot. */\nexport const AXIS_HEIGHT = 46;\n\n/** This function gives the y of the center line of a lane. */\nexport function laneCenter(layout: { plotBottom: number; laneHeight: number }, lane: number): number {\n return layout.plotBottom - (lane + 0.5) * layout.laneHeight;\n}\n\n/** This function calculates the layout of the timeline at a width. */\nexport function timelineLayout<T extends ReleasePoint>(releases: readonly T[], options: TimelineOptions): TimelineLayout<T> {\n const { width, padX = 30, laneHeight = 38, charWidth = 7.4, gap = 8, emptyWeight = 0.6 } = options;\n const ordered = oldestFirst(releases).filter((release) => Number.isFinite(Date.parse(release.date)));\n const first = ordered[0];\n const last = ordered[ordered.length - 1];\n if (!first || !last) {\n return { width, height: PLOT_TOP + laneHeight + AXIS_HEIGHT, plotTop: PLOT_TOP, plotBottom: PLOT_TOP + laneHeight, laneHeight, lanes: 0, bands: [], marks: [] };\n }\n\n // The bands: each day with releases, and each run of days without\n const counts = new Map<number, number>();\n for (const release of ordered) {\n const day = utcDay(Date.parse(release.date));\n counts.set(day, (counts.get(day) ?? 0) + 1);\n }\n const raw: Array<{ start: number; end: number; count: number; empty: boolean; weight: number }> = [];\n for (let day = utcDay(Date.parse(first.date)); day <= utcDay(Date.parse(last.date)); day += DAY_MS) {\n const count = counts.get(day) ?? 0;\n const previous = raw[raw.length - 1];\n if (count === 0 && previous?.empty) previous.end = day + DAY_MS;\n else raw.push({ start: day, end: day + DAY_MS, count, empty: count === 0, weight: count === 0 ? emptyWeight : 1 });\n }\n const unit = (width - 2 * padX) / raw.reduce((sum, band) => sum + band.weight, 0);\n let cursor = padX;\n const bands: TimelineBand[] = raw.map((band) => {\n const x0 = cursor;\n cursor += band.weight * unit;\n return { start: band.start, end: band.end, x0, x1: cursor, label: dayRange(band.start, band.end - 1), count: band.count, empty: band.empty };\n });\n const xOf = (time: number): number => {\n const band = bands.find((candidate) => time >= candidate.start && time < candidate.end) ?? bands[bands.length - 1];\n if (!band) return padX;\n return band.x0 + ((time - band.start) / (band.end - band.start)) * (band.x1 - band.x0);\n };\n\n // The lanes: each mark goes into the lowest lane where its label does not touch the last label\n const laneEnds: number[] = [];\n const marks: Array<TimelineMark<T>> = ordered.map((release) => {\n const time = Date.parse(release.date);\n const x = xOf(time);\n const half = Math.max(release.version.length * charWidth, 24) / 2;\n let lane = laneEnds.findIndex((end) => end + gap <= x - half);\n if (lane === -1) {\n lane = laneEnds.length;\n laneEnds.push(0);\n }\n laneEnds[lane] = x + half;\n return { release, time, x, lane, half };\n });\n\n const lanes = laneEnds.length;\n const plotBottom = PLOT_TOP + lanes * laneHeight;\n return { width, height: plotBottom + AXIS_HEIGHT, plotTop: PLOT_TOP, plotBottom, laneHeight, lanes, bands, marks };\n}\n","/**\n * The standalone releases page: a lead line, a timeline of the versions and the changes of the\n * selected version. The build renders the HTML, and one small inline module adds the interactions.\n */\n\nimport type { Release, ReleaseChange, ReleaseKind } from \"../data/types.ts\";\nimport { longDate, shortDate } from \"./dates.ts\";\nimport { escapeHtml, inlineMarkdown, link, listText, plural } from \"./html.ts\";\nimport { pageShell, type PageOptions } from \"./theme.ts\";\nimport { laneCenter, oldestFirst, releaseSummary, timelineLayout, type TimelineLayout } from \"./timeline.ts\";\n\n/** The changes and the package chips that the page shows before \"Show all\". */\nconst FIRST_CHANGES = 8;\nconst FIRST_CHIPS = 4;\n/** The y of the mark below the center line of its lane. The label is above the line. */\nconst MARK_Y = 9;\n/** The widths of the two timelines: the narrow one for a phone or a tablet, the wide one for a desktop. */\nconst NARROW_WIDTH = 640;\nconst WIDE_WIDTH = 920;\n\nconst KIND_INFO: Record<ReleaseKind, { label: string; word: string; pill: string; legend: string }> = {\n first: { label: \"First release\", word: \"first release\", pill: \"sp-pill sp-good\", legend: \"The first release\" },\n major: { label: \"MAJOR\", word: \"major\", pill: \"sp-pill sp-strong\", legend: \"MAJOR: a change that breaks the API\" },\n minor: { label: \"MINOR\", word: \"minor\", pill: \"sp-pill sp-accent\", legend: \"MINOR: new features (before 1.0.0, also a change of the API)\" },\n patch: { label: \"PATCH\", word: \"patch\", pill: \"sp-pill\", legend: \"PATCH: fixes and small additions\" },\n};\n\n/** This function gives \"Oct 18, 2026\" for an ISO date. */\nfunction dayWithYear(date: string): string {\n return `${shortDate(date)}, ${new Date(date).getUTCFullYear()}`;\n}\n\n/**\n * This function gives the lead line of the releases page, for example \"23 versions from Oct 12 to\n * Oct 18, 2026. 7 MINOR releases and 15 PATCH releases came after the first release.\"\n */\nexport function releasesLead(releases: readonly Release[]): string {\n const summary = releaseSummary(releases);\n if (!summary.first || !summary.last) return \"The repository has no release yet.\";\n const sameYear = new Date(summary.first).getUTCFullYear() === new Date(summary.last).getUTCFullYear();\n const from = sameYear ? shortDate(summary.first) : dayWithYear(summary.first);\n const range = shortDate(summary.first) === shortDate(summary.last) && sameYear ? `on ${dayWithYear(summary.last)}` : `from ${from} to ${dayWithYear(summary.last)}`;\n if (summary.versions === 1) return `1 version, the first release, ${range}.`;\n const kinds = [\n summary.major > 0 ? plural(summary.major, \"MAJOR release\") : \"\",\n summary.minor > 0 ? plural(summary.minor, \"MINOR release\") : \"\",\n summary.patch > 0 ? plural(summary.patch, \"PATCH release\") : \"\",\n ].filter(Boolean);\n return `${plural(summary.versions, \"version\")} ${range}. ${listText(kinds)} came after the first release.`;\n}\n\n/** The shape of a mark. The first release is a diamond, a MAJOR is a large dot, a MINOR is a dot and a PATCH is a ring. */\nfunction markShape(kind: ReleaseKind, y: number): string {\n if (kind === \"first\") return `<rect class=\"sp-dot\" x=\"-5.5\" y=\"${y - 5.5}\" width=\"11\" height=\"11\" transform=\"rotate(45 0 ${y})\"/>`;\n if (kind === \"major\") return `<circle class=\"sp-dot\" cy=\"${y}\" r=\"8\"/>`;\n if (kind === \"minor\") return `<circle class=\"sp-dot\" cy=\"${y}\" r=\"6.5\"/>`;\n return `<circle class=\"sp-ring\" cy=\"${y}\" r=\"4.5\"/>`;\n}\n\nfunction legend(releases: readonly Release[]): string {\n const kinds = ([\"major\", \"minor\", \"patch\", \"first\"] as const).filter((kind) => releases.some((release) => release.kind === kind));\n const items = kinds.map(\n (kind) =>\n `<li><svg width=\"18\" height=\"18\" viewBox=\"-9 -9 18 18\" aria-hidden=\"true\"><g class=\"sp-kind-${kind}\">${markShape(kind, 0)}</g></svg>${escapeHtml(KIND_INFO[kind].legend)}</li>`,\n );\n return `<ul class=\"sp-legend\">${items.join(\"\")}</ul>`;\n}\n\nconst fixed = (value: number): string => value.toFixed(1).replace(/\\.0$/, \"\");\n\nfunction timelineSvg(releases: readonly Release[], width: number, selected: string): string {\n const layout: TimelineLayout<Release> = timelineLayout(releases, { width });\n const { plotTop, plotBottom } = layout;\n const parts: string[] = [];\n for (const band of layout.bands) {\n const middle = (band.x0 + band.x1) / 2;\n const room = band.x1 - band.x0;\n const count = band.empty ? \"no release\" : plural(band.count, \"release\");\n parts.push(`<g${band.empty ? ' class=\"sp-empty-band\"' : \"\"}>`);\n if (band.empty) parts.push(`<rect class=\"sp-gap\" x=\"${fixed(band.x0)}\" y=\"${plotTop}\" width=\"${fixed(room)}\" height=\"${plotBottom - plotTop}\"/>`);\n parts.push(`<line class=\"sp-grid\" x1=\"${fixed(band.x0)}\" x2=\"${fixed(band.x0)}\" y1=\"${plotTop}\" y2=\"${plotBottom + 6}\"/>`);\n if (room >= band.label.length * 7 + 6) {\n parts.push(`<text class=\"sp-day\" x=\"${fixed(middle)}\" y=\"${plotBottom + 21}\" text-anchor=\"middle\">${escapeHtml(band.label)}</text>`);\n }\n if (room >= count.length * 6 + 6) {\n parts.push(`<text class=\"sp-day-count\" x=\"${fixed(middle)}\" y=\"${plotBottom + 38}\" text-anchor=\"middle\">${escapeHtml(count)}</text>`);\n }\n parts.push(\"</g>\");\n }\n const lastBand = layout.bands[layout.bands.length - 1];\n if (lastBand) parts.push(`<line class=\"sp-grid\" x1=\"${fixed(lastBand.x1)}\" x2=\"${fixed(lastBand.x1)}\" y1=\"${plotTop}\" y2=\"${plotBottom + 6}\"/>`);\n parts.push(`<line class=\"sp-axis\" x1=\"${fixed(layout.bands[0]?.x0 ?? 0)}\" x2=\"${fixed(lastBand?.x1 ?? width)}\" y1=\"${plotBottom}\" y2=\"${plotBottom}\"/>`);\n const axis = `<g aria-hidden=\"true\">${parts.join(\"\")}</g>`;\n\n const marks = layout.marks.map((mark) => {\n const { release } = mark;\n const on = release.version === selected;\n const label = `${release.version}, ${KIND_INFO[release.kind].word}, ${shortDate(release.date)}, ${plural(release.changes.length, \"change\")}`;\n return (\n `<g class=\"sp-mark sp-kind-${release.kind}${on ? \" sp-selected\" : \"\"}\" data-sp-mark data-version=\"${escapeHtml(release.version)}\"` +\n ` data-x=\"${fixed(mark.x)}\" data-half=\"${fixed(mark.half)}\" transform=\"translate(${fixed(mark.x)} ${fixed(laneCenter(layout, mark.lane))})\"` +\n ` role=\"button\" tabindex=\"${on ? 0 : -1}\" aria-pressed=\"${on}\" aria-label=\"${escapeHtml(label)}\">` +\n `<rect class=\"sp-hit\" x=\"${fixed(-mark.half - 4)}\" y=\"${fixed(-layout.laneHeight / 2 + 1)}\" width=\"${fixed(mark.half * 2 + 8)}\" height=\"${layout.laneHeight - 2}\" rx=\"4\"/>` +\n `<circle class=\"sp-halo\" cy=\"${MARK_Y}\" r=\"11\"/>${markShape(release.kind, MARK_Y)}` +\n `<text class=\"sp-label\" y=\"-3\" text-anchor=\"middle\">${escapeHtml(release.version)}</text></g>`\n );\n });\n const name = `The release timeline, ${plural(layout.marks.length, \"version\")}. The arrow keys move between the versions.`;\n return (\n `<svg class=\"sp-timeline\" width=\"${layout.width}\" height=\"${layout.height}\" viewBox=\"0 0 ${layout.width} ${layout.height}\" role=\"group\" aria-label=\"${escapeHtml(name)}\">` +\n `${axis}${marks.join(\"\")}</svg>`\n );\n}\n\n/** The common scope of all the package names (\"@procedures/\"), or \"\" when the names have no common scope. */\nfunction commonScope(releases: readonly Release[]): string {\n const names = new Set(releases.flatMap((release) => release.changes.flatMap((change) => change.packages)));\n const scopes = new Set([...names].map((name) => /^(@[^/]+\\/)/.exec(name)?.[1] ?? \"\"));\n const [scope] = scopes;\n return scopes.size === 1 && scope ? scope : \"\";\n}\n\n/** The counter for the IDs of the lists that a button opens. */\ninterface Ids {\n next: number;\n}\n\nfunction toggleButton(ids: string, more: string, less: string, hidden = \"\"): string {\n return (\n `<button type=\"button\" class=\"sp-ghost\" data-sp-js data-sp-toggle aria-controls=\"${ids}\" aria-expanded=\"false\"` +\n ` data-more=\"${escapeHtml(more)}\" data-less=\"${escapeHtml(less)}\"><span data-sp-label>${escapeHtml(more)}</span>${hidden}</button>`\n );\n}\n\nfunction chips(packages: readonly string[], scope: string, ids: Ids): string {\n if (packages.length === 0) return \"\";\n const id = `k${ids.next++}`;\n const items = packages.map((name, index) => {\n const short = scope && name.startsWith(scope) ? name.slice(scope.length) : name;\n const extra = index >= FIRST_CHIPS;\n return `<span class=\"sp-pill${extra ? \" sp-extra\" : \"\"}\" title=\"${escapeHtml(name)}\"${extra ? \" hidden\" : \"\"}>${escapeHtml(short)}</span>`;\n });\n const more = packages.length - FIRST_CHIPS;\n const button = more > 0 ? toggleButton(id, `+${more} more`, \"Fewer\", '<span class=\"sp-visually-hidden\"> packages</span>') : \"\";\n return `<span class=\"sp-chips\" id=\"${id}\">${items.join(\"\")}${button}</span>`;\n}\n\nfunction changeItem(change: ReleaseChange, index: number, repository: string, scope: string, ids: Ids): string {\n const extra = index >= FIRST_CHANGES;\n const commit = change.commit\n ? link(`https://github.com/${repository}/commit/${change.commit}`, `<code>${escapeHtml(change.commit)}</code>`, `class=\"sp-commit\" title=\"${escapeHtml(`Commit ${change.commit} on GitHub`)}\"`)\n : \"\";\n const meta = commit || change.packages.length > 0 ? `<div class=\"sp-change-meta\">${commit}${chips(change.packages, scope, ids)}</div>` : \"\";\n return `<li class=\"sp-change${extra ? \" sp-extra\" : \"\"}\"${extra ? \" hidden\" : \"\"}><p>${inlineMarkdown(change.text)}</p>${meta}</li>`;\n}\n\nfunction details(release: Release, index: number, selected: boolean, repository: string, scope: string, ids: Ids): string {\n const info = KIND_INFO[release.kind];\n const links = release.links.map((each) => link(each.url, escapeHtml(each.label))).join(\"\");\n const head =\n `<div class=\"sp-release-head\"><h2 id=\"h${index}\">${escapeHtml(release.version)}</h2><span class=\"${info.pill}\">${escapeHtml(info.label)}</span>` +\n `<time class=\"sp-small sp-muted\" datetime=\"${escapeHtml(release.date)}\">${escapeHtml(longDate(release.date))}</time>` +\n (links ? `<span class=\"sp-release-links sp-small\">${links}</span>` : \"\") +\n \"</div>\";\n let body: string;\n if (release.changes.length === 0) {\n body = '<p class=\"sp-small sp-muted\">The sources have no change entry for this version.</p>';\n } else {\n const packages = new Set(release.changes.flatMap((change) => change.packages)).size;\n const count = packages > 0\n ? `${plural(release.changes.length, \"change\")} in ${plural(packages, \"package\")}. The changes with the most packages come first.`\n : `${plural(release.changes.length, \"change\")}.`;\n const listId = `c${index}`;\n const items = release.changes.map((change, position) => changeItem(change, position, repository, scope, ids));\n const all = release.changes.length > FIRST_CHANGES ? toggleButton(listId, `Show all ${release.changes.length} changes`, \"Show fewer changes\") : \"\";\n body = `<p class=\"sp-small sp-muted\">${escapeHtml(count)}</p><ul class=\"sp-changes\" id=\"${listId}\">${items.join(\"\")}</ul>${all}`;\n }\n return (\n `<section class=\"sp-panel sp-release\" id=\"v${escapeHtml(release.version)}\" data-sp-release data-version=\"${escapeHtml(release.version)}\"` +\n ` aria-labelledby=\"h${index}\"${selected ? \"\" : \" hidden\"}>${head}${body}</section>`\n );\n}\n\n/**\n * The inline module of the releases page. It selects a version on a click, with the arrow keys,\n * Home, End, Enter and Space. It also opens the long lists and keeps the version in the URL.\n */\nexport const RELEASES_SCRIPT: string = String.raw`\nconst boxes = Array.from(document.querySelectorAll(\"[data-sp-timeline]\"));\nconst panels = new Map(Array.from(document.querySelectorAll(\"[data-sp-release]\"), (panel) => [panel.dataset.version, panel]));\nconst reduced = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\nlet selected = (document.querySelector(\"[data-sp-release]:not([hidden])\") || {}).dataset?.version;\nconst markIn = (box, version) => Array.from(box.querySelectorAll(\"[data-sp-mark]\")).find((mark) => mark.dataset.version === version);\nfunction reveal(box, version, smooth) {\n const mark = markIn(box, version);\n if (!mark || box.scrollWidth <= box.clientWidth) return;\n const x = Number(mark.dataset.x);\n const margin = Number(mark.dataset.half) + 16;\n if (x - margin >= box.scrollLeft && x + margin <= box.scrollLeft + box.clientWidth) return;\n box.scrollTo({ left: x - box.clientWidth / 2, behavior: smooth && !reduced ? \"smooth\" : \"auto\" });\n}\nfunction select(version, box) {\n const panel = panels.get(version);\n if (!panel) return;\n selected = version;\n for (const each of boxes) {\n for (const mark of each.querySelectorAll(\"[data-sp-mark]\")) {\n const on = mark.dataset.version === version;\n mark.classList.toggle(\"sp-selected\", on);\n mark.setAttribute(\"aria-pressed\", String(on));\n mark.setAttribute(\"tabindex\", on ? \"0\" : \"-1\");\n }\n }\n for (const [key, each] of panels) each.hidden = key !== version;\n if (box) {\n const mark = markIn(box, version);\n if (mark) mark.focus({ preventScroll: true });\n reveal(box, version, true);\n }\n try {\n history.replaceState(null, \"\", \"#\" + encodeURIComponent(panel.id));\n } catch {}\n}\nfor (const box of boxes) {\n box.addEventListener(\"click\", (event) => {\n const mark = event.target.closest(\"[data-sp-mark]\");\n if (mark) select(mark.dataset.version, box);\n });\n box.addEventListener(\"keydown\", (event) => {\n const mark = event.target.closest(\"[data-sp-mark]\");\n if (!mark || event.altKey || event.ctrlKey || event.metaKey) return;\n const marks = Array.from(box.querySelectorAll(\"[data-sp-mark]\"));\n const position = marks.indexOf(mark);\n const targets = { ArrowLeft: position - 1, ArrowRight: position + 1, Home: 0, End: marks.length - 1, Enter: position, \" \": position };\n if (!(event.key in targets)) return;\n event.preventDefault();\n const next = marks[Math.max(0, Math.min(marks.length - 1, targets[event.key]))];\n if (next) select(next.dataset.version, box);\n });\n}\ndocument.addEventListener(\"click\", (event) => {\n const button = event.target.closest(\"[data-sp-toggle]\");\n const list = button && document.getElementById(button.getAttribute(\"aria-controls\"));\n if (!list) return;\n const open = button.getAttribute(\"aria-expanded\") !== \"true\";\n for (const extra of list.querySelectorAll(\":scope > .sp-extra\")) extra.hidden = !open;\n button.setAttribute(\"aria-expanded\", String(open));\n const label = button.querySelector(\"[data-sp-label]\");\n if (label) label.textContent = open ? button.dataset.less : button.dataset.more;\n});\n// A malformed hash, for example \"#100%\", must not stop the module\nlet hashed = \"\";\ntry {\n hashed = decodeURIComponent(location.hash.slice(1));\n} catch {}\nfor (const [version, panel] of panels) if (panel.id === hashed) select(version, null);\nconst revealAll = () => { for (const box of boxes) reveal(box, selected, false); };\nrevealAll();\nwindow.addEventListener(\"resize\", revealAll);\n`;\n\n/** This function renders the complete releases page from the data of `releases.json`. */\nexport function renderReleasesPage(releases: readonly Release[], options: PageOptions): string {\n const newest = releases[0];\n const ordered = oldestFirst(releases);\n const scope = commonScope(releases);\n const ids: Ids = { next: 0 };\n const lead = `<p class=\"sp-lead\">${escapeHtml(releasesLead(releases))}</p>`;\n let content = \"\";\n if (newest) {\n content =\n `<div class=\"sp-panel\"><p class=\"sp-small sp-muted\">Each mark is one version, on a time axis in UTC. Select a mark to show its changes.</p>` +\n legend(releases) +\n `<div class=\"sp-timeline-box sp-timeline-narrow\" data-sp-timeline>${timelineSvg(ordered, NARROW_WIDTH, newest.version)}</div>` +\n `<div class=\"sp-timeline-box sp-timeline-wide\" data-sp-timeline>${timelineSvg(ordered, WIDE_WIDTH, newest.version)}</div></div>` +\n releases.map((release, index) => details(release, index, index === 0, options.repository, scope, ids)).join(\"\");\n }\n const source =\n '<p class=\"sp-small sp-muted\">Source: the <code>CHANGELOG.md</code> files, the git tags, the GitHub releases and npm, read when the site was built.</p>';\n return pageShell(\n {\n title: \"Releases\",\n description: releasesLead(releases),\n current: \"releases\",\n main: `<h1>Releases</h1>${lead}${content}${source}`,\n script: RELEASES_SCRIPT,\n },\n options,\n );\n}\n","/**\n * The standalone status page: the open work of the roadmap file, the open pull requests and the\n * open issues. The build renders the HTML, and one small inline module adds the filters.\n */\n\nimport { OPEN_CLASSES } from \"../data/status.ts\";\nimport type { BoardItem, CheckState, StatusBoardData, StatusClass } from \"../data/types.ts\";\nimport { longDate } from \"./dates.ts\";\nimport { escapeHtml, inlineMarkdown, link, listText, plural } from \"./html.ts\";\nimport { pageShell, type PageOptions } from \"./theme.ts\";\n\n/** The label, the icon and the meaning of each class. The page always shows a color with an icon and a label. */\nconst CLASS_INFO: Record<StatusClass, { label: string; icon: string; meaning: string }> = {\n waiting: { label: \"Waiting\", icon: \"◷\", meaning: \"It waits for a person or a decision\" },\n blocked: { label: \"Blocked\", icon: \"⊘\", meaning: \"Other work must finish first\" },\n progress: { label: \"In progress\", icon: \"◐\", meaning: \"Work started\" },\n open: { label: \"Open\", icon: \"○\", meaning: \"Nobody started it\" },\n later: { label: \"Later\", icon: \"◌\", meaning: \"It is for later\" },\n done: { label: \"Done\", icon: \"✓\", meaning: \"It is finished\" },\n};\n\nconst CHECK_LABEL: Record<CheckState, string> = {\n success: \"Checks pass\",\n failure: \"Checks fail\",\n pending: \"Checks run\",\n none: \"No checks\",\n};\n\n/**\n * This function gives the lead line of the status page, for example \"12 open roadmap items, 9 open\n * pull requests and 0 open issues, read at Oct 19, 2026, 14:05 UTC from abc1234.\"\n */\nexport function statusLead(data: StatusBoardData): string {\n const parts: string[] = [];\n if (data.source.roadmap) parts.push(plural(data.items.filter((item) => item.statusClass !== \"done\").length, \"open roadmap item\"));\n if (data.github.available) {\n parts.push(plural(data.github.totals?.pullRequests ?? data.pullRequests.length, \"open pull request\"));\n parts.push(plural(data.github.totals?.issues ?? data.issues.length, \"open issue\"));\n }\n const commit = data.commit ? data.commit.slice(0, 7) : null;\n const read = `read at ${longDate(data.generatedAt)}${commit ? ` from ${commit}` : \"\"}`;\n const line = parts.length > 0 ? `${listText(parts)}, ${read}.` : `Read at ${read.slice(\"read at \".length)}.`;\n return data.github.available ? line : `${line} The build could not read GitHub.`;\n}\n\n/** This function gives the part of a URL for a text: \"The server stack (R37)\" gives \"the-server-stack-r37\". */\nexport function slugOf(text: string): string {\n return (\n text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n // After the line above, no two hyphens are next to each other. \"-+$\" backtracks, and \"-$\" does not.\n .replace(/^-|-$/g, \"\") || \"other\"\n );\n}\n\n/** A section of the roadmap, with the count of its open items and of its done items. */\nexport interface BoardSection {\n slug: string;\n label: string;\n open: number;\n done: number;\n}\n\n/** This function gives the sections of the items, in the sequence of the file. */\nexport function sectionsOf(items: readonly BoardItem[]): BoardSection[] {\n const sections = new Map<string, BoardSection>();\n for (const item of items) {\n const slug = slugOf(item.section);\n const section = sections.get(slug) ?? { slug, label: item.section || \"Other\", open: 0, done: 0 };\n if (item.statusClass === \"done\") section.done++;\n else section.open++;\n sections.set(slug, section);\n }\n return [...sections.values()];\n}\n\n/** A group of items with one class. */\nexport interface ItemGroup {\n statusClass: StatusClass;\n items: BoardItem[];\n}\n\n/** This function gives the groups of the open items in the sequence of `OPEN_CLASSES`, without the empty groups. */\nexport function openGroups(items: readonly BoardItem[]): ItemGroup[] {\n return OPEN_CLASSES.map((statusClass) => ({ statusClass, items: items.filter((item) => item.statusClass === statusClass) })).filter(\n (group) => group.items.length > 0,\n );\n}\n\n/** This function counts the items of each class. */\nexport function classCounts(items: readonly BoardItem[]): Record<StatusClass, number> {\n const counts: Record<StatusClass, number> = { waiting: 0, blocked: 0, progress: 0, open: 0, later: 0, done: 0 };\n for (const item of items) counts[item.statusClass]++;\n return counts;\n}\n\nfunction roadmapUrl(data: StatusBoardData): string {\n return `https://github.com/${data.source.github}/blob/${data.commit ?? \"HEAD\"}/${data.source.roadmap ?? \"\"}`;\n}\n\nfunction meter(items: readonly BoardItem[]): string {\n const counts = classCounts(items);\n const order: StatusClass[] = [\"done\", ...OPEN_CLASSES];\n const present = order.filter((value) => counts[value] > 0);\n const total = Math.max(1, items.length);\n const summary = present.map((value) => `${counts[value]} ${CLASS_INFO[value].label.toLowerCase()}`).join(\", \");\n const parts = present.map((value) => `<span class=\"sp-c-${value}\" style=\"flex-grow:${(counts[value] / total).toFixed(4)}\"></span>`);\n const legend = present.map(\n (value) => `<li class=\"sp-c-${value}\"><span class=\"sp-swatch\"></span>${CLASS_INFO[value].label} <strong>${counts[value]}</strong></li>`,\n );\n return (\n `<div class=\"sp-meter\" role=\"img\" aria-label=\"${escapeHtml(`${plural(items.length, \"item\")} of the roadmap: ${summary}`)}\">${parts.join(\"\")}</div>` +\n `<ul class=\"sp-meter-legend\" aria-hidden=\"true\">${legend.join(\"\")}</ul>`\n );\n}\n\nfunction itemTable(items: readonly BoardItem[], data: StatusBoardData, columns: { owner: boolean; links: boolean }): string {\n const fileUrl = roadmapUrl(data);\n const none = '<span class=\"sp-muted\">—</span>';\n const rows = items.map((item) => {\n const meta = [escapeHtml(item.section), item.area ? inlineMarkdown(item.area) : \"\", item.needs ? `needs ${inlineMarkdown(item.needs)}` : \"\"]\n .filter(Boolean)\n .join(\" · \");\n const links = item.links.length > 0 ? `<span class=\"sp-links\">${item.links.map((each) => link(each.url, escapeHtml(each.label))).join(\"\")}</span>` : none;\n return (\n `<tr class=\"sp-c-${item.statusClass}\" data-section=\"${escapeHtml(slugOf(item.section))}\">` +\n `<th scope=\"row\">${link(`${fileUrl}?plain=1#L${item.line}`, escapeHtml(item.id), `title=\"${escapeHtml(`The row of ${item.id} in the roadmap file`)}\"`)}</th>` +\n `<td data-label=\"Item\" class=\"sp-item\"><span>${item.title ? inlineMarkdown(item.title) : '<span class=\"sp-muted\">No title</span>'}</span>` +\n `<span class=\"sp-item-meta sp-small sp-muted\">${meta}</span></td>` +\n // One element in each cell: on a phone, the cell is a grid of its label and its content\n (columns.owner ? `<td data-label=\"Owner\">${item.owner ? `<span>${inlineMarkdown(item.owner)}</span>` : none}</td>` : \"\") +\n `<td data-label=\"Status\"><span class=\"sp-status\"><span aria-hidden=\"true\">${CLASS_INFO[item.statusClass].icon}</span> ` +\n `${inlineMarkdown(item.status || CLASS_INFO[item.statusClass].label)}</span></td>` +\n (columns.links ? `<td data-label=\"Links\">${links}</td>` : \"\") +\n \"</tr>\"\n );\n });\n const head =\n '<thead><tr><th scope=\"col\">ID</th><th scope=\"col\">Item</th>' +\n (columns.owner ? '<th scope=\"col\">Owner</th>' : \"\") +\n '<th scope=\"col\">Status</th>' +\n (columns.links ? '<th scope=\"col\">Links</th>' : \"\") +\n \"</tr></thead>\";\n return `<div class=\"sp-table-box\"><table class=\"sp-table\">${head}<tbody>${rows.join(\"\")}</tbody></table></div>`;\n}\n\nfunction openWork(data: StatusBoardData): string {\n const items = data.items;\n const open = items.filter((item) => item.statusClass !== \"done\");\n const done = items.filter((item) => item.statusClass === \"done\");\n const counts = classCounts(items);\n const columns = { owner: items.some((item) => item.owner), links: items.some((item) => item.links.length > 0) };\n const file = (data.source.roadmap ?? \"\").split(\"/\").pop() ?? \"\";\n const classChips = OPEN_CLASSES.map(\n (value) =>\n `<button type=\"button\" class=\"sp-chip sp-c-${value}\" data-sp-class=\"${value}\" aria-pressed=\"false\" title=\"${escapeHtml(CLASS_INFO[value].meaning)}\">` +\n `<span aria-hidden=\"true\">${CLASS_INFO[value].icon}</span> ${CLASS_INFO[value].label} <span class=\"sp-count\">${counts[value]}</span></button>`,\n );\n const sectionChips = sectionsOf(items)\n .filter((section) => section.open > 0)\n .map(\n (section) =>\n `<button type=\"button\" class=\"sp-chip\" data-sp-section=\"${escapeHtml(section.slug)}\" aria-pressed=\"false\">` +\n `${escapeHtml(section.label)} <span class=\"sp-count\">${section.open}</span></button>`,\n );\n const filters =\n `<div class=\"sp-filters\" role=\"group\" aria-label=\"Filters of the open work\" data-sp-js>` +\n `<span role=\"group\" aria-label=\"Status of the items\">${classChips.join(\"\")}</span>` +\n (sectionChips.length > 1 ? `<span role=\"group\" aria-label=\"Section of the roadmap\">${sectionChips.join(\"\")}</span>` : \"\") +\n `<button type=\"button\" class=\"sp-ghost\" data-sp-clear hidden>Clear the filters</button></div>`;\n const label = plural(open.length, \"open item\");\n const groups = openGroups(items).map(\n (group) =>\n `<section class=\"sp-group sp-c-${group.statusClass}\" data-sp-group data-class=\"${group.statusClass}\" aria-labelledby=\"group-${group.statusClass}\">` +\n `<h3 id=\"group-${group.statusClass}\"><span aria-hidden=\"true\">${CLASS_INFO[group.statusClass].icon}</span> ${CLASS_INFO[group.statusClass].label} ` +\n `<span class=\"sp-group-count\" data-sp-group-count>${group.items.length}</span></h3>${itemTable(group.items, data, columns)}</section>`,\n );\n const list =\n open.length === 0\n ? '<p class=\"sp-callout\">The roadmap has no open item.</p>'\n : `<p class=\"sp-small sp-muted\" aria-live=\"polite\" data-sp-shown data-label=\"${escapeHtml(label)}\">${open.length} of ${escapeHtml(label)}</p>` +\n groups.join(\"\") +\n '<p class=\"sp-callout\" data-sp-empty hidden>No open item matches the filters.</p>';\n const doneText = done.length === 1 ? \"1 item is done.\" : `${done.length} items are done.`;\n const doneList =\n done.length === 0\n ? `<p class=\"sp-done sp-small\"><span aria-hidden=\"true\">✓</span> No item is done.</p>`\n : `<details class=\"sp-done sp-c-done\" data-sp-done><summary><span aria-hidden=\"true\">✓</span> ${doneText} ` +\n `<span data-sp-done-label>Show the done items</span></summary>` +\n `<section class=\"sp-group sp-c-done\" data-sp-group data-class=\"done\" aria-label=\"The done items\">${itemTable(done, data, columns)}` +\n '<p class=\"sp-callout\" data-sp-done-empty hidden>No done item matches the filters.</p></section></details>';\n return (\n `<section class=\"sp-section\" aria-labelledby=\"open-work\" data-sp-board><h2 id=\"open-work\">Open work</h2>` +\n `<p class=\"sp-small sp-muted\">Each row of a table of ${link(roadmapUrl(data), `<code>${escapeHtml(file)}</code>`)} with an ID and a status that is not done. ` +\n \"The build reads the file, so this list follows each commit.</p>\" +\n meter(items) +\n (open.length > 0 ? filters : \"\") +\n list +\n doneList +\n \"</section>\"\n );\n}\n\nfunction when(date: string): string {\n const text = escapeHtml(longDate(date));\n return `<time datetime=\"${escapeHtml(date)}\" title=\"${text}\" data-sp-rel>${text}</time>`;\n}\n\nfunction labels(names: readonly string[]): string {\n return names.length === 0 ? \"\" : `<span class=\"sp-labels\">${names.map((name) => `<span class=\"sp-pill\">${escapeHtml(name)}</span>`).join(\"\")}</span>`;\n}\n\nfunction githubMissing(data: StatusBoardData): string {\n const reason = data.github.reason ? ` (${escapeHtml(data.github.reason)})` : \"\";\n return `<p class=\"sp-callout\">The build could not read GitHub${reason}. Refer to ${link(`https://github.com/${data.source.github}`, escapeHtml(data.source.github))} on GitHub.</p>`;\n}\n\nfunction pullRequests(data: StatusBoardData): string {\n const total = data.github.totals?.pullRequests ?? data.pullRequests.length;\n let body: string;\n if (!data.github.available) body = githubMissing(data);\n else if (data.pullRequests.length === 0) {\n body = `<p class=\"sp-callout\">No pull request is open. Refer to ${link(`https://github.com/${data.source.github}/pulls?q=is%3Apr`, \"all the pull requests\")}.</p>`;\n } else {\n const count =\n total > data.pullRequests.length\n ? `The ${data.pullRequests.length} most recently updated of ${plural(total, \"open pull request\")}.`\n : `${plural(total, \"open pull request\")}, the most recently updated first.`;\n const cards = data.pullRequests.map(\n (pull) =>\n `<li class=\"sp-card\">${link(pull.url, `<span class=\"sp-number\">#${pull.number}</span> ${escapeHtml(pull.title)}`, 'class=\"sp-card-title\"')}` +\n `<span class=\"sp-card-meta\"><span class=\"sp-pill${pull.draft ? \"\" : \" sp-accent\"}\">${pull.draft ? \"Draft\" : \"Ready\"}</span>` +\n `<span class=\"sp-check sp-check-${pull.checks}\"><span class=\"sp-dot-state\" aria-hidden=\"true\"></span>${CHECK_LABEL[pull.checks]}</span>` +\n `<span>by ${escapeHtml(pull.author)}</span><code class=\"sp-branch\">${escapeHtml(pull.branch)}</code>` +\n `<span class=\"sp-muted\">updated ${when(pull.updatedAt)}</span>${labels(pull.labels)}</span></li>`,\n );\n body = `<p class=\"sp-small sp-muted\">${escapeHtml(count)}</p><ul class=\"sp-cards\">${cards.join(\"\")}</ul>`;\n }\n return `<section class=\"sp-section\" aria-labelledby=\"pull-requests\"><h2 id=\"pull-requests\">Pull requests</h2>${body}</section>`;\n}\n\nfunction issues(data: StatusBoardData): string {\n const total = data.github.totals?.issues ?? data.issues.length;\n let body: string;\n if (!data.github.available) body = githubMissing(data);\n else if (data.issues.length === 0) {\n body = `<p class=\"sp-callout\">No issue is open. To report a problem, ${link(`https://github.com/${data.source.github}/issues/new`, \"open an issue\")}.</p>`;\n } else {\n const count =\n total > data.issues.length\n ? `The ${data.issues.length} most recently updated of ${plural(total, \"open issue\")}.`\n : `${plural(total, \"open issue\")}, the most recently updated first.`;\n const cards = data.issues.map(\n (issue) =>\n `<li class=\"sp-card\">${link(issue.url, `<span class=\"sp-number\">#${issue.number}</span> ${escapeHtml(issue.title)}`, 'class=\"sp-card-title\"')}` +\n `<span class=\"sp-card-meta\"><span>by ${escapeHtml(issue.author)}</span>` +\n `<span class=\"sp-muted\">updated ${when(issue.updatedAt)}</span>${labels(issue.labels)}</span></li>`,\n );\n body = `<p class=\"sp-small sp-muted\">${escapeHtml(count)}</p><ul class=\"sp-cards\">${cards.join(\"\")}</ul>`;\n }\n return `<section class=\"sp-section\" aria-labelledby=\"issues\"><h2 id=\"issues\">Issues</h2>${body}</section>`;\n}\n\n/** The pure helpers of the inline module of the status page. A test reads them from this text. */\nexport const STATUS_SCRIPT_HELPERS: string = String.raw`\nfunction relativeTime(then, now) {\n const seconds = Math.round((now - then) / 1000);\n if (!Number.isFinite(seconds)) return \"at an unknown time\";\n if (seconds < 60) return \"just now\";\n const steps = [[60, \"minute\"], [3600, \"hour\"], [86400, \"day\"], [2592000, \"month\"], [31536000, \"year\"]];\n let unit = steps[0];\n for (const step of steps) if (seconds >= step[0]) unit = step;\n const count = Math.floor(seconds / unit[0]);\n return count + \" \" + unit[1] + (count === 1 ? \"\" : \"s\") + \" ago\";\n}\nfunction listOf(text) {\n return (text || \"\").split(\",\").filter((part) => part !== \"\");\n}\n`;\n\n/**\n * The inline module of the status page. It filters the open work by class and by section, keeps the\n * filters in the URL, and shows the age of each GitHub time.\n */\nexport const STATUS_SCRIPT: string =\n STATUS_SCRIPT_HELPERS +\n String.raw`\nconst now = Date.now();\nfor (const time of document.querySelectorAll(\"time[data-sp-rel]\")) {\n time.textContent = relativeTime(Date.parse(time.dateTime), now) + \" (\" + time.title + \")\";\n}\nconst board = document.querySelector(\"[data-sp-board]\");\nif (board) {\n const classChips = Array.from(board.querySelectorAll(\"[data-sp-class]\"));\n const sectionChips = Array.from(board.querySelectorAll(\"[data-sp-section]\"));\n const groups = Array.from(board.querySelectorAll(\"[data-sp-group]\"));\n const shown = board.querySelector(\"[data-sp-shown]\");\n const empty = board.querySelector(\"[data-sp-empty]\");\n const clear = board.querySelector(\"[data-sp-clear]\");\n const done = board.querySelector(\"[data-sp-done]\");\n const query = new URLSearchParams(location.search);\n const state = {\n classes: listOf(query.get(\"status\")).filter((value) => classChips.some((chip) => chip.dataset.spClass === value)),\n sections: listOf(query.get(\"section\")),\n };\n if (done && query.get(\"done\") === \"1\") done.open = true;\n const apply = (write) => {\n for (const chip of classChips) chip.setAttribute(\"aria-pressed\", String(state.classes.includes(chip.dataset.spClass)));\n for (const chip of sectionChips) chip.setAttribute(\"aria-pressed\", String(state.sections.includes(chip.dataset.spSection)));\n let count = 0;\n for (const group of groups) {\n const isDone = group.dataset.class === \"done\";\n const classOn = isDone || state.classes.length === 0 || state.classes.includes(group.dataset.class);\n let visible = 0;\n for (const row of group.querySelectorAll(\"tr[data-section]\")) {\n const on = classOn && (state.sections.length === 0 || state.sections.includes(row.dataset.section));\n row.hidden = !on;\n if (on) visible++;\n }\n if (isDone) {\n const none = group.querySelector(\"[data-sp-done-empty]\");\n if (none) none.hidden = visible > 0;\n } else {\n group.hidden = visible === 0;\n const badge = group.querySelector(\"[data-sp-group-count]\");\n if (badge) badge.textContent = String(visible);\n count += visible;\n }\n }\n if (shown) shown.textContent = count + \" of \" + shown.dataset.label;\n if (empty) empty.hidden = count > 0;\n if (clear) clear.hidden = state.classes.length === 0 && state.sections.length === 0;\n if (done) {\n const label = done.querySelector(\"[data-sp-done-label]\");\n if (label) label.textContent = done.open ? \"Hide the done items\" : \"Show the done items\";\n }\n if (!write) return;\n const next = new URLSearchParams(location.search);\n const put = (key, value) => (value ? next.set(key, value) : next.delete(key));\n put(\"status\", state.classes.join(\",\"));\n put(\"section\", state.sections.join(\",\"));\n put(\"done\", done && done.open ? \"1\" : \"\");\n const search = next.toString();\n try {\n history.replaceState(null, \"\", location.pathname + (search ? \"?\" + search : \"\") + location.hash);\n } catch {}\n };\n const toggle = (list, value) => (list.includes(value) ? list.filter((each) => each !== value) : list.concat(value));\n board.addEventListener(\"click\", (event) => {\n const chip = event.target.closest(\"button\");\n if (!chip) return;\n if (chip.dataset.spClass) state.classes = toggle(state.classes, chip.dataset.spClass);\n else if (chip.dataset.spSection) state.sections = toggle(state.sections, chip.dataset.spSection);\n else if (chip.hasAttribute(\"data-sp-clear\")) {\n state.classes = [];\n state.sections = [];\n } else return;\n apply(true);\n });\n if (done) done.addEventListener(\"toggle\", () => apply(true));\n apply(false);\n}\n`;\n\n/** This function renders the complete status page from the data of `status.json`. */\nexport function renderStatusPage(data: StatusBoardData, options: PageOptions): string {\n const lead = statusLead(data);\n const main =\n `<h1>Status</h1><p class=\"sp-lead\">${escapeHtml(lead)}</p>` +\n '<p class=\"sp-small sp-muted\">The build reads the roadmap file and GitHub again after each commit and on a schedule.</p>' +\n (data.source.roadmap ? openWork(data) : \"\") +\n pullRequests(data) +\n issues(data);\n return pageShell({ title: \"Status\", description: lead, current: \"status\", main, script: STATUS_SCRIPT }, options);\n}\n","/**\n * The probe of `site-pages check` in TypeScript. A probe source can be TypeScript, so the typecheck of the site examines it.\n * The check removes its types before it runs the probe, so a site needs no build step for its probe.\n */\n\nimport { stripTypeScriptTypes } from \"node:module\";\n\n/** A probe file in TypeScript: `.ts`, `.mts` or `.cts`. */\nexport const TYPESCRIPT_PROBE: RegExp = /\\.[cm]?ts$/i;\n\n/**\n * This function gives the JavaScript of a probe in TypeScript. It removes the types, and the line `export {};` that makes the\n * file a module for the typecheck. Each line stays at its position, so the line of an error is the line of the source. Syntax\n * that is not only types (an `enum`, a `namespace`) causes an error.\n */\nexport function probeScript(source: string): string {\n return stripTypeScriptTypes(source, { mode: \"strip\" }).replace(/^export \\{\\s*\\};?[ \\t]*$/m, \"\");\n}\n","/**\n * The `site-pages build` command. It reads the sources. Then it writes the JSON data and the two\n * standalone pages into the built output folder of a site.\n */\n\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { headCommit, originRepository } from \"./data/git.ts\";\nimport { readReleases, ReleaseDataError } from \"./data/releases.ts\";\nimport { readStatusBoard, RoadmapParseError } from \"./data/status.ts\";\nimport type { Release, StatusBoardData } from \"./data/types.ts\";\nimport { plural } from \"./render/html.ts\";\nimport { renderReleasesPage } from \"./render/releases.ts\";\nimport { renderStatusPage } from \"./render/status.ts\";\nimport type { PageOptions } from \"./render/theme.ts\";\n\n/** An error in the command line. The CLI shows the help and exits with code 2. */\nexport class UsageError extends Error {}\n\n/** The options of `build`. */\nexport interface BuildOptions {\n /** The folder of the repository. Relative paths start here. */\n repoDir: string;\n /** \"owner/name\" of the repository on GitHub. */\n repository: string;\n /** The built output folder of the site. */\n out: string;\n /** The path of the site home, for example `/client/`. */\n base: string;\n /** The roadmap file, from `repoDir`. Without it, the status page has only the GitHub part. */\n roadmap?: string | undefined;\n /** The npm names or scopes for the npm dates. */\n packages?: readonly string[] | undefined;\n /** The glob pattern of the changelog files. */\n changesets?: string | undefined;\n /** The npm name of the package whose changelog gives the versions. */\n group?: string | undefined;\n token?: string | undefined;\n /** The commit of the build. */\n commit?: string | null | undefined;\n /** A CSS file whose content each page gets after the default CSS. */\n css?: string | undefined;\n /** The name of the site in the header of the pages. */\n siteName?: string | undefined;\n /** True to write only the JSON data, without the pages. */\n dataOnly?: boolean | undefined;\n fetch?: typeof fetch | undefined;\n /** The ISO time of the build. The default is the time of the call. */\n now?: string | undefined;\n warn?: ((message: string) => void) | undefined;\n}\n\n/** The result of `build`. */\nexport interface BuildResult {\n /** The written files, as absolute paths. */\n files: string[];\n releases: Release[];\n status: StatusBoardData;\n}\n\nfunction write(file: string, content: string, files: string[]): void {\n mkdirSync(dirname(file), { recursive: true });\n writeFileSync(file, content);\n files.push(file);\n}\n\n/**\n * This function reads the sources and writes `data/releases.json`, `data/status.json`,\n * `releases/index.html` and `status/index.html` into the output folder.\n *\n * @throws ReleaseDataError or RoadmapParseError when a source on disk is not correct\n */\nexport async function build(options: BuildOptions): Promise<BuildResult> {\n const { repoDir, repository, warn = () => {} } = options;\n const now = options.now ?? new Date().toISOString();\n const commit = options.commit === undefined ? headCommit(repoDir) : options.commit;\n const [owner = \"\", repo = \"\"] = repository.split(\"/\");\n const out = isAbsolute(options.out) ? options.out : resolve(repoDir, options.out);\n const fetcher = options.fetch ? { fetch: options.fetch } : {};\n\n const releases = await readReleases({\n repoDir,\n repository,\n token: options.token,\n changesets: options.changesets,\n packages: options.packages,\n group: options.group,\n ref: commit ?? undefined,\n now,\n warn,\n ...fetcher,\n });\n const status = await readStatusBoard({ repoDir, roadmap: options.roadmap ?? null, owner, repo, token: options.token, commit, generatedAt: now, ...fetcher });\n if (!status.github.available) warn(`the status page has no GitHub data: ${status.github.reason ?? \"no reason\"}.`);\n\n const files: string[] = [];\n write(join(out, \"data\", \"releases.json\"), `${JSON.stringify(releases, null, 2)}\\n`, files);\n write(join(out, \"data\", \"status.json\"), `${JSON.stringify(status, null, 2)}\\n`, files);\n if (!options.dataOnly) {\n const page: PageOptions = {\n repository,\n base: options.base,\n siteName: options.siteName,\n extraCss: options.css ? readFileSync(isAbsolute(options.css) ? options.css : resolve(repoDir, options.css), \"utf8\") : undefined,\n generatedAt: now,\n commit,\n };\n write(join(out, \"releases\", \"index.html\"), renderReleasesPage(releases, page), files);\n write(join(out, \"status\", \"index.html\"), renderStatusPage(status, page), files);\n }\n return { files, releases, status };\n}\n\n/** The help of the CLI. */\nexport const HELP = `Usage: site-pages build --out <dir> [options]\n\nWrites <out>/data/releases.json, <out>/data/status.json, <out>/releases/index.html\nand <out>/status/index.html. Start it in the repository, after the build of the site.\n\nOptions:\n --out <dir> The built output folder of the site (necessary)\n --repo <owner/name> The GitHub repository (default: $GITHUB_REPOSITORY, else the remote \"origin\")\n --base </name/> The path of the site home (default: \"/<name>/\", or \"/\" for <owner>.github.io)\n --roadmap <file> The roadmap file (default: none, the status page has only the GitHub part)\n --packages <names> npm names or a @scope, separated by commas, for the npm dates\n --changesets <glob> The changelog files (default: packages/*/CHANGELOG.md, else CHANGELOG.md)\n --group <name> The npm name of the package whose changelog gives the versions\n --token <token> A GitHub token with read access (default: $GITHUB_TOKEN)\n --css <file> A CSS file for the pages, after the default CSS\n --site-name <name> The name of the site in the header (default: the repository name)\n --data-only Write only the JSON data, not the pages\n -h, --help Show this help\n\nUsage: site-pages check (--out <dir> | --url <url>) [options]\n\nOpens the pages of the site in a headless Chromium at phone and desktop widths. Start\n\"site-pages check --help\" for its options.\n`;\n\n/** The input and output of `runCli`. A test gives its own values. */\nexport interface CliIo {\n cwd: string;\n env: Record<string, string | undefined>;\n stdout: (text: string) => void;\n stderr: (text: string) => void;\n fetch?: typeof fetch;\n now?: string;\n}\n\n/**\n * This function reads the command line into the options of `build`.\n *\n * @throws UsageError when the command line is not correct\n */\nexport function parseBuildArgs(argv: readonly string[], io: Pick<CliIo, \"cwd\" | \"env\">): BuildOptions | \"help\" {\n let parsed: ReturnType<typeof parseCommandLine>;\n try {\n parsed = parseCommandLine(argv);\n } catch (error) {\n throw new UsageError(error instanceof Error ? error.message : String(error));\n }\n const { values, positionals } = parsed;\n if (values.help) return \"help\";\n if (positionals[0] !== \"build\" || positionals.length > 1) {\n throw new UsageError(positionals.length === 0 ? \"no command was given\" : `unknown command: ${positionals.join(\" \")}`);\n }\n if (!values.out) throw new UsageError(\"--out is necessary\");\n const repository = values.repo || io.env[\"GITHUB_REPOSITORY\"] || originRepository(io.cwd) || \"\";\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repository)) {\n throw new UsageError(repository ? `--repo must be \"owner/name\", not \"${repository}\"` : \"give --repo <owner/name> or set GITHUB_REPOSITORY\");\n }\n const name = repository.split(\"/\")[1] ?? \"\";\n let base = values.base ?? (/\\.github\\.io$/i.test(name) ? \"/\" : `/${name}/`);\n if (!base.startsWith(\"/\")) base = `/${base}`;\n if (!base.endsWith(\"/\")) base = `${base}/`;\n const packages = (values.packages ?? []).flatMap((entry) => entry.split(\",\")).map((entry) => entry.trim()).filter(Boolean);\n const changesets = values.changesets;\n return {\n repoDir: io.cwd,\n repository,\n out: values.out,\n base,\n roadmap: values.roadmap,\n packages,\n changesets,\n group: values.group,\n token: values.token || io.env[\"GITHUB_TOKEN\"] || undefined,\n css: values.css,\n siteName: values[\"site-name\"],\n dataOnly: values[\"data-only\"] === true,\n };\n}\n\nfunction parseCommandLine(argv: readonly string[]) {\n return parseArgs({\n args: [...argv],\n allowPositionals: true,\n strict: true,\n options: {\n out: { type: \"string\" },\n repo: { type: \"string\" },\n base: { type: \"string\" },\n roadmap: { type: \"string\" },\n packages: { type: \"string\", multiple: true },\n changesets: { type: \"string\" },\n group: { type: \"string\" },\n token: { type: \"string\" },\n css: { type: \"string\" },\n \"site-name\": { type: \"string\" },\n \"data-only\": { type: \"boolean\" },\n help: { type: \"boolean\", short: \"h\" },\n },\n });\n}\n\n/**\n * This function starts the CLI and gives the exit code. The code is 0 after a build, 1 when a\n * source is not correct, and 2 for an incorrect command line.\n */\nexport async function runCli(argv: readonly string[], io: CliIo): Promise<number> {\n let options: BuildOptions | \"help\";\n try {\n options = parseBuildArgs(argv, io);\n } catch (error) {\n if (!(error instanceof UsageError)) throw error;\n io.stderr(`site-pages: ${error.message}\\n\\n${HELP}`);\n return 2;\n }\n if (options === \"help\") {\n io.stdout(HELP);\n return 0;\n }\n try {\n const result = await build({\n ...options,\n warn: (message) => io.stderr(`site-pages: ${message}\\n`),\n ...(io.fetch ? { fetch: io.fetch } : {}),\n ...(io.now ? { now: io.now } : {}),\n });\n const open = result.status.items.filter((item) => item.statusClass !== \"done\").length;\n const github = result.status.github.available\n ? `${plural(result.status.pullRequests.length, \"open pull request\")} and ${plural(result.status.issues.length, \"open issue\")}`\n : \"no GitHub data\";\n io.stdout(\n `site-pages: ${plural(result.releases.length, \"release\")}, ${plural(result.status.items.length, \"roadmap item\")} (${open} open), ${github}.\\n` +\n result.files.map((file) => ` ${file}\\n`).join(\"\"),\n );\n return 0;\n } catch (error) {\n if (error instanceof ReleaseDataError || error instanceof RoadmapParseError || (error as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n io.stderr(`site-pages: ${(error as Error).message}\\n`);\n return 1;\n }\n throw error;\n }\n}\n"],"mappings":"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"}
|