@mark1russell7/site-pages 0.2.12 → 0.2.13
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 +3 -1
- package/build/chunks/build.js +1 -1
- package/build/chunks/freshness.js +1 -1
- package/build/index.js +1 -1
- package/build/vite.d.ts +9 -0
- package/build/vite.d.ts.map +1 -1
- package/build/vite.js +16 -2
- package/build/vite.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -166,7 +166,7 @@ Two fields of a stamp change the age rule:
|
|
|
166
166
|
- `"study": true` marks a fixed study. The data has no age limit, and the rule 3 does not apply. The run names the method or the run, the date and the engine version. The stamp line tells in plain words that the page is a fixed study of that version. A page with a claim about the current engine is not a fixed study.
|
|
167
167
|
- `"limit"` sets a longer age limit: `{ "days": 7, "reason": "The scan is weekly.", "workflow": ".github/workflows/scan.yml" }`. The stamp line shows the limit and the reason. The schedule of that workflow must meet the limit, or the gate fails. A limit with no schedule fails. A limit over 14 days (`MAX_LIMIT_DAYS_WITHOUT_RULING`) also needs a `ruling`, a public https link for that site.
|
|
168
168
|
|
|
169
|
-
When npm does not answer, the gate prints the rule 3 under `Not run` and does not fail. A workflow turns the gate on with the input `data-stamps` of `reusable-pages.yml`. The gate then runs from the template commit, so it needs no install.
|
|
169
|
+
When npm does not answer, the gate prints the rule 3 under `Not run` and does not fail. A workflow turns the gate on with the input `data-stamps` of `reusable-pages.yml`. A site with its own Pages workflow uses the action `data-stamps` of the template. The gate then runs from the template commit, so it needs no install.
|
|
170
170
|
|
|
171
171
|
`renderDataStamp(stamp)` gives the line that the page shows with its data: the run, its date, its engine versions and the run in flight.
|
|
172
172
|
|
|
@@ -432,6 +432,8 @@ The theme `auto` removes `data-theme`, and the CSS of the site then obeys `prefe
|
|
|
432
432
|
|
|
433
433
|
The file `kpi.json` at the root of a site holds the measures of the project, in the format `kpi/1`. A reader outside the site takes the numbers from this file.
|
|
434
434
|
|
|
435
|
+
A count that the build reads from the source is true at the commit of the build. Use `commitTime()` from `@mark1russell7/site-pages/vite` for its `at`.
|
|
436
|
+
|
|
435
437
|
```ts
|
|
436
438
|
import { defineConfig } from "vite";
|
|
437
439
|
import { siteKpi } from "@mark1russell7/site-pages/vite";
|
package/build/chunks/build.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as readKpi, D as
|
|
1
|
+
import { A as originRepository, C as readKpi, D as headCommit, E as gitTagDates, F as parseVersion, I as versionOfTag, M as npmPublishTimes, N as compareVersions, O as headingDate, P as kindOf, _ as KPI_FILE, d as escapeHtml, f as inlineMarkdown, h as plural, k as isShallow, m as listText, p as link, y as KpiError } from "./freshness.js";
|
|
2
2
|
import { stripTypeScriptTypes } from "node:module";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, posix, resolve } from "node:path";
|
|
@@ -754,6 +754,6 @@ async function runFreshnessCli(argv, io, fetcher) {
|
|
|
754
754
|
io.stdout(`The data stamps of ${parsed.stamps.pages.length} pages pass.\n`);
|
|
755
755
|
return 0;
|
|
756
756
|
}
|
|
757
|
-
export {
|
|
757
|
+
export { originRepository as A, readKpi as C, headCommit as D, gitTagDates as E, parseVersion as F, versionOfTag as I, npmPublishTimes as M, compareVersions as N, headingDate as O, kindOf as P, kpiText as S, git as T, KPI_FILE as _, checkFreshness as a, kpiFile as b, minorsBehind as c, escapeHtml as d, inlineMarkdown as f, safeUrl as g, plural as h, MAX_MINORS_BEHIND as i, NPM_REGISTRY as j, isShallow as k, parseDataStamps as l, listText as m, MAX_DATA_AGE_DAYS as n, cronLines as o, link as p, MAX_LIMIT_DAYS_WITHOUT_RULING as r, latestAt as s, DATA_STAMP_SCHEMA as t, runFreshnessCli as u, KPI_FORMAT as v, writeKpi as w, kpiProblems as x, KpiError as y };
|
|
758
758
|
|
|
759
759
|
//# sourceMappingURL=freshness.js.map
|
package/build/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as originRepository, C as readKpi, D as headCommit, E as gitTagDates, F as parseVersion, I as versionOfTag, M as npmPublishTimes, N as compareVersions, O as headingDate, P as kindOf, S as kpiText, _ as KPI_FILE, a as checkFreshness, b as kpiFile, c as minorsBehind, d as escapeHtml, f as inlineMarkdown, g as safeUrl, i as MAX_MINORS_BEHIND, j as NPM_REGISTRY, k as isShallow, l as parseDataStamps, n as MAX_DATA_AGE_DAYS, o as cronLines, r as MAX_LIMIT_DAYS_WITHOUT_RULING, s as latestAt, t as DATA_STAMP_SCHEMA, v as KPI_FORMAT, w as writeKpi, x as kpiProblems, y as KpiError } from "./chunks/freshness.js";
|
|
2
2
|
import { $ as parseChangelog, A as STATUS_CLASSES, B as DEFAULT_CHANGELOGS, C as pageShell, D as utcDay, E as shortDate, F as plainText, G as globFiles, H as mergeReleases, I as readStatusBoard, J as checkStateOf, K as GITHUB_API, L as roadmapItems, M as linksOf, N as markdownTables, O as OPEN_CLASSES, P as parseRoadmap, Q as headingAnchor, R as splitRow, S as BASE_CSS, T as longDate, U as readChangelogs, V as ReleaseDataError, W as readReleases, X as githubReleases, Y as githubOpenWork, Z as firstSentence, _ as renderReleasesPage, a as runCli, b as releaseSummary, c as STATUS_SCRIPT, d as renderStatusPage, et as releaseBodyEntries, f as sectionsOf, g as releasesLead, h as RELEASES_SCRIPT, i as parseBuildArgs, j as buildStatusBoard, k as RoadmapParseError, l as classCounts, m as statusLead, n as UsageError, o as TYPESCRIPT_PROBE, p as slugOf, q as GITHUB_GRAPHQL, r as build, s as probeScript, t as HELP, u as openGroups, v as laneCenter, w as dayRange, x as timelineLayout, y as oldestFirst, z as statusClassOf } from "./chunks/build.js";
|
|
3
3
|
import { t as renderDataStamp } from "./chunks/data-stamp.js";
|
|
4
4
|
export { BASE_CSS, DATA_STAMP_SCHEMA, DEFAULT_CHANGELOGS, GITHUB_API, GITHUB_GRAPHQL, HELP, KPI_FILE, KPI_FORMAT, KpiError, MAX_DATA_AGE_DAYS, MAX_LIMIT_DAYS_WITHOUT_RULING, MAX_MINORS_BEHIND, NPM_REGISTRY, OPEN_CLASSES, RELEASES_SCRIPT, ReleaseDataError, RoadmapParseError, STATUS_CLASSES, STATUS_SCRIPT, TYPESCRIPT_PROBE, UsageError, build, buildStatusBoard, checkFreshness, checkStateOf, classCounts, compareVersions, cronLines, dayRange, escapeHtml, firstSentence, gitTagDates, githubOpenWork, githubReleases, globFiles, headCommit, headingAnchor, headingDate, inlineMarkdown, isShallow, kindOf, kpiFile, kpiProblems, kpiText, laneCenter, latestAt, linksOf, longDate, markdownTables, mergeReleases, minorsBehind, npmPublishTimes, oldestFirst, openGroups, originRepository, pageShell, parseBuildArgs, parseChangelog, parseDataStamps, parseRoadmap, parseVersion, plainText, probeScript, readChangelogs, readKpi, readReleases, readStatusBoard, releaseBodyEntries, releaseSummary, releasesLead, renderDataStamp, renderReleasesPage, renderStatusPage, roadmapItems, runCli, safeUrl, sectionsOf, shortDate, slugOf, splitRow, statusClassOf, statusLead, timelineLayout, utcDay, versionOfTag, writeKpi };
|
package/build/vite.d.ts
CHANGED
|
@@ -108,6 +108,15 @@ export declare function themeScript(storageKey: string): string;
|
|
|
108
108
|
* workflow sets that variable to `/<name>`. A local build has no such variable, and gets `/`.
|
|
109
109
|
*/
|
|
110
110
|
export declare function siteBase(env?: SiteEnv): string;
|
|
111
|
+
/**
|
|
112
|
+
* This function gives the ISO time in UTC of the commit of a build. A count that a build reads from the source is
|
|
113
|
+
* true at that commit, so this time is the time of its data. It is not the time of the build.
|
|
114
|
+
*
|
|
115
|
+
* @param env - The environment variables. The function takes `GITHUB_SHA`, else `HEAD`.
|
|
116
|
+
* @param repoDir - The folder of the repository.
|
|
117
|
+
* @throws When git cannot read the commit. A file with no time of its data is a fault.
|
|
118
|
+
*/
|
|
119
|
+
export declare function commitTime(env?: SiteEnv, repoDir?: string): string;
|
|
111
120
|
/** This function gives the data of a build. Outside CI, `GITHUB_SHA` is not set, and `sha` is `local`. */
|
|
112
121
|
export declare function buildInfo(version?: string, env?: SiteEnv, now?: Date): BuildInfo;
|
|
113
122
|
/**
|
package/build/vite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.ts","names":[],"sources":["../src/vite.ts"],"mappings":";;;YAmBY,UAAU,SAAS;;iBAGd;;WAEN;;;;;WAKA;;;YAIC;;iBAGK;WACN;WACA;WACA;aAAmB,SAAS;;;;iBAItB;WACN;WACA;aAAkB,QAAQ;;WAC1B,QAAQ,SAAS;;;iBAIX;WACN;WACA;WACA;;;iBAIM;WACN;EACT,OAAO,QAAQ,uBAAuB;EACtC,sBAAsB;;;YAIZ,eAAe,KAAK;WAAiC;;;iBAGhD;EACf,SAAS;IAAQ;IAAe;IAAkB;;;;iBAInC;WACN;WACA;EACT,eAAA,MAAqB;;;;;;;;wBASP,QAAQ,OAAO,sBAAsB,eAAe,MAAK,UAAwB;;qBAapF;;qBAGA;;iBAGI;;WAEN;;;iBAIM;WACN;WACA;WACA;aAA+B;IAAc,QAAQ,cAAc,MAAM;;EAClF,eAAA,MAAqB;;;;;;;;;;wBAWP,WAAW,OAAO,oBAAoB,cAAc;;;;;;;;wBA2CpD,YAAY;;;;;wBASZ,SAAS,MAAK;;
|
|
1
|
+
{"version":3,"file":"vite.d.ts","names":[],"sources":["../src/vite.ts"],"mappings":";;;YAmBY,UAAU,SAAS;;iBAGd;;WAEN;;;;;WAKA;;;YAIC;;iBAGK;WACN;WACA;WACA;aAAmB,SAAS;;;;iBAItB;WACN;WACA;aAAkB,QAAQ;;WAC1B,QAAQ,SAAS;;;iBAIX;WACN;WACA;WACA;;;iBAIM;WACN;EACT,OAAO,QAAQ,uBAAuB;EACtC,sBAAsB;;;YAIZ,eAAe,KAAK;WAAiC;;;iBAGhD;EACf,SAAS;IAAQ;IAAe;IAAkB;;;;iBAInC;WACN;WACA;EACT,eAAA,MAAqB;;;;;;;;wBASP,QAAQ,OAAO,sBAAsB,eAAe,MAAK,UAAwB;;qBAapF;;qBAGA;;iBAGI;;WAEN;;;iBAIM;WACN;WACA;WACA;aAA+B;IAAc,QAAQ,cAAc,MAAM;;EAClF,eAAA,MAAqB;;;;;;;;;;wBAWP,WAAW,OAAO,oBAAoB,cAAc;;;;;;;;wBA2CpD,YAAY;;;;;wBASZ,SAAS,MAAK;;;;;;;;;wBAad,WAAW,MAAK,SAAuB;;wBAQvC,UAAU,kBAAkB,MAAK,SAAuB,MAAK,OAAoB;;;;;;;;;;;;wBAoBjF,UAAU,SAAS,mBAAmB"}
|
package/build/vite.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as headCommit, S as kpiText, T as git, _ as KPI_FILE, b as kpiFile, l as parseDataStamps } from "./chunks/freshness.js";
|
|
2
2
|
import { t as renderDataStamp } from "./chunks/data-stamp.js";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
@@ -101,6 +101,20 @@ function siteBase(env = process.env) {
|
|
|
101
101
|
const base = env["SITE_BASE"];
|
|
102
102
|
return base ? `${base.replace(/\/$/, "")}/` : "/";
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* This function gives the ISO time in UTC of the commit of a build. A count that a build reads from the source is
|
|
106
|
+
* true at that commit, so this time is the time of its data. It is not the time of the build.
|
|
107
|
+
*
|
|
108
|
+
* @param env - The environment variables. The function takes `GITHUB_SHA`, else `HEAD`.
|
|
109
|
+
* @param repoDir - The folder of the repository.
|
|
110
|
+
* @throws When git cannot read the commit. A file with no time of its data is a fault.
|
|
111
|
+
*/
|
|
112
|
+
function commitTime(env = process.env, repoDir = process.cwd()) {
|
|
113
|
+
const ref = env["GITHUB_SHA"] ?? "HEAD";
|
|
114
|
+
const time = git(repoDir, "show", "-s", "--format=%cI", ref)?.trim();
|
|
115
|
+
if (!time) throw new Error(`git cannot read the commit ${ref}, so the data has no time.`);
|
|
116
|
+
return new Date(time).toISOString();
|
|
117
|
+
}
|
|
104
118
|
/** This function gives the data of a build. Outside CI, `GITHUB_SHA` is not set, and `sha` is `local`. */
|
|
105
119
|
function buildInfo(version, env = process.env, now = /* @__PURE__ */ new Date()) {
|
|
106
120
|
return {
|
|
@@ -145,6 +159,6 @@ function siteShell(options) {
|
|
|
145
159
|
}
|
|
146
160
|
};
|
|
147
161
|
}
|
|
148
|
-
export { STAMPS_FILE, STAMP_MARK, buildInfo, siteBase, siteKpi, siteShell, siteStamps, themeScript };
|
|
162
|
+
export { STAMPS_FILE, STAMP_MARK, buildInfo, commitTime, siteBase, siteKpi, siteShell, siteStamps, themeScript };
|
|
149
163
|
|
|
150
164
|
//# sourceMappingURL=vite.js.map
|
package/build/vite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","names":[],"sources":["../src/vite.ts"],"sourcesContent":["/**\n * The build side of the shell of a site: a Vite plugin and its parts. Import this module from\n * `@mark1russell7/site-pages/vite`. It is for `vite.config.ts`, not for a browser.\n *\n * This module does not import Vite. The types of the plugin are the small part that it uses, so the\n * package keeps no dependency. A test examines that Vite accepts the plugin.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { BuildInfo } from \"./chrome.ts\";\nimport { parseDataStamps, type DataStamps } from \"./check/freshness.ts\";\nimport { headCommit } from \"./data/git.ts\";\nimport { KPI_FILE, kpiFile, kpiText, type KpiInput } from \"./data/kpi.ts\";\nimport { renderDataStamp } from \"./render/data-stamp.ts\";\n\nexport type { BuildInfo } from \"./chrome.ts\";\n\n/** The environment variables that this module reads. */\nexport type SiteEnv = Readonly<Record<string, string | undefined>>;\n\n/** The options of `siteShell`. */\nexport interface SiteShellOptions {\n /** The `localStorage` key of the theme. Give the same key to `setupTheme` in the page. */\n readonly themeKey: string;\n /**\n * The file with the version for `__BUILD__`, relative to the folder of the site. The default is\n * `../package.json`. The value `false` gives a build with no version.\n */\n readonly packageFile?: string | false | undefined;\n}\n\n/** The value of `build.target` in a Vite config. */\nexport type SiteTarget = string | string[] | false;\n\n/** The part of the Vite config that `siteShell` reads. */\nexport interface SiteShellConfigInput {\n readonly root?: string | undefined;\n readonly base?: string | undefined;\n readonly build?: { readonly target?: SiteTarget | undefined } | null | undefined;\n}\n\n/** The part of the Vite config that `siteShell` sets. Vite merges it into the config of the site. */\nexport interface SiteShellConfig {\n readonly base: string;\n readonly build: { readonly target: SiteTarget };\n readonly define: Readonly<Record<string, string>>;\n}\n\n/** A tag for the `head` of each HTML page. */\nexport interface SiteShellTag {\n readonly tag: \"script\";\n readonly children: string;\n readonly injectTo: \"head\";\n}\n\n/** The Vite plugin that `siteShell` gives. */\nexport interface SiteShellPlugin {\n readonly name: string;\n config(config: SiteShellConfigInput): SiteShellConfig;\n transformIndexHtml(): SiteShellTag[];\n}\n\n/** The input of `siteKpi`. Without a commit, the plugin takes `GITHUB_SHA`, else the head of the repository. */\nexport type SiteKpiInput = Omit<KpiInput, \"commit\"> & { readonly commit?: string | undefined };\n\n/** The part of the context of a Rollup hook that `siteKpi` uses. */\nexport interface SiteKpiContext {\n emitFile(file: { type: \"asset\"; fileName: string; source: string }): string;\n}\n\n/** The Vite plugin that `siteKpi` gives. */\nexport interface SiteKpiPlugin {\n readonly name: string;\n readonly apply: \"build\";\n generateBundle(this: SiteKpiContext): void;\n}\n\n/**\n * This function gives the Vite plugin that adds `kpi.json` to the root of a built site. A fault in the data stops the build.\n *\n * @param input - The data, or a function that reads it at the time of the build.\n * @param env - The environment variables. A test gives its own.\n */\nexport function siteKpi(input: SiteKpiInput | (() => SiteKpiInput), env: SiteEnv = process.env): SiteKpiPlugin {\n return {\n name: \"site-pages-kpi\",\n apply: \"build\",\n generateBundle() {\n const data = typeof input === \"function\" ? input() : input;\n const commit = data.commit ?? env[\"GITHUB_SHA\"] ?? headCommit(process.cwd()) ?? \"\";\n this.emitFile({ type: \"asset\", fileName: KPI_FILE, source: kpiText(kpiFile({ ...data, commit })) });\n },\n };\n}\n\n/** The file that `siteStamps` adds to the root of a built site. The input `data-stamps` of `reusable-pages.yml` names it. */\nexport const STAMPS_FILE = \"data-stamps.json\";\n\n/** The mark in the HTML of a measured page. `siteStamps` replaces it with the stamp line of the page. */\nexport const STAMP_MARK = \"<!-- data-stamp -->\";\n\n/** The part of the context of a page that `siteStamps` uses. */\nexport interface SiteStampsPage {\n /** The path of the page from the root of the site, with a `/` at the start. */\n readonly path: string;\n}\n\n/** The Vite plugin that `siteStamps` gives. */\nexport interface SiteStampsPlugin {\n readonly name: string;\n readonly apply: \"build\";\n readonly transformIndexHtml: { readonly order: \"pre\"; handler(html: string, page: SiteStampsPage): string };\n generateBundle(this: SiteKpiContext): void;\n}\n\n/**\n * This function gives the Vite plugin of the data stamps of a site. The plugin puts the stamp line in each measured page.\n * It also adds `data-stamps.json` to the root of the site. So the page and the freshness gate read one record.\n *\n * A fault stops the build. A fault is a bad stamp, a mark with no stamp or a stamp with no mark. A stamp of a page that the build does not hold is also a fault.\n *\n * @param input - The stamps, or a function that reads them at the time of the build.\n */\nexport function siteStamps(input: DataStamps | (() => DataStamps)): SiteStampsPlugin {\n let stamps: DataStamps | undefined;\n const read = (): DataStamps => {\n if (stamps !== undefined) return stamps;\n const parsed = parseDataStamps(typeof input === \"function\" ? input() : input);\n if (!parsed.ok) throw new Error(`The data stamps are not good:\\n- ${parsed.faults.join(\"\\n- \")}`);\n stamps = parsed.stamps;\n return stamps;\n };\n const seen = new Set<string>();\n return {\n name: \"site-pages-stamps\",\n apply: \"build\",\n transformIndexHtml: {\n order: \"pre\",\n handler(html, { path }) {\n const name = path.replace(/^\\//, \"\");\n const stamp = read().pages.find((page) => page.page === name);\n const marked = html.includes(STAMP_MARK);\n if (stamp === undefined && marked) throw new Error(`The page ${name} has the mark of a data stamp, and the stamps have no page ${name}.`);\n if (stamp === undefined) return html;\n if (!marked) throw new Error(`The stamps have the page ${name}, and the page has no mark ${STAMP_MARK}.`);\n seen.add(name);\n return html.replace(STAMP_MARK, renderDataStamp(stamp));\n },\n },\n generateBundle() {\n const missing = read()\n .pages.map((page) => page.page)\n .filter((page) => !seen.has(page));\n if (missing.length > 0) throw new Error(`The stamps have pages that the build does not hold: ${missing.join(\", \")}.`);\n this.emitFile({ type: \"asset\", fileName: STAMPS_FILE, source: `${JSON.stringify(read(), null, 2)}\\n` });\n },\n };\n}\n\n/**\n * This function gives the script that sets the saved theme before the first paint, so a dark page\n * does not show white for a moment. The script reads `storageKey`, as `applyTheme` writes it.\n *\n * @remarks The text goes in an inline `script` element. Thus the function escapes each `<` of the\n * key, so a key cannot close the element.\n */\nexport function themeScript(storageKey: string): string {\n const key = JSON.stringify(storageKey).replaceAll(\"<\", \"\\\\u003c\");\n return `try{const t=localStorage.getItem(${key});if(t===\"light\"||t===\"dark\")document.documentElement.dataset.theme=t}catch{}`;\n}\n\n/**\n * This function gives the `base` of Vite from `SITE_BASE`, with one `/` at the end. The Pages\n * workflow sets that variable to `/<name>`. A local build has no such variable, and gets `/`.\n */\nexport function siteBase(env: SiteEnv = process.env): string {\n const base = env[\"SITE_BASE\"];\n return base ? `${base.replace(/\\/$/, \"\")}/` : \"/\";\n}\n\n/** This function gives the data of a build. Outside CI, `GITHUB_SHA` is not set, and `sha` is `local`. */\nexport function buildInfo(version?: string, env: SiteEnv = process.env, now: Date = new Date()): BuildInfo {\n return { sha: (env[\"GITHUB_SHA\"] ?? \"local\").slice(0, 7), date: now.toISOString().slice(0, 10), version };\n}\n\n/** This function reads the field `version` of a `package.json` file. */\nfunction versionIn(file: string): string | undefined {\n return (JSON.parse(readFileSync(file, \"utf8\")) as { version?: string }).version;\n}\n\n/**\n * This function makes the Vite plugin of a site. The plugin does these four operations:\n *\n * - It sets `base` from `SITE_BASE`.\n * - It sets `build.target` to `es2022`.\n * - It defines `__BUILD__`, the value that `showBuild` shows.\n * - It adds `themeScript` to the `head` of each HTML page.\n *\n * A `base` or a `build.target` in the config of the site has priority. The other values of `build`\n * and `define` in that config stay, because Vite merges them.\n */\nexport function siteShell(options: SiteShellOptions): SiteShellPlugin {\n return {\n name: \"site-pages-shell\",\n config(config) {\n const packageFile = options.packageFile ?? \"../package.json\";\n const version = packageFile === false ? undefined : versionIn(resolve(config.root ?? \".\", packageFile));\n return {\n base: config.base ?? siteBase(),\n build: { target: config.build?.target ?? \"es2022\" },\n define: { __BUILD__: JSON.stringify(buildInfo(version)) },\n };\n },\n transformIndexHtml() {\n return [{ tag: \"script\", children: themeScript(options.themeKey), injectTo: \"head\" }];\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vite.js","names":[],"sources":["../src/vite.ts"],"sourcesContent":["/**\n * The build side of the shell of a site: a Vite plugin and its parts. Import this module from\n * `@mark1russell7/site-pages/vite`. It is for `vite.config.ts`, not for a browser.\n *\n * This module does not import Vite. The types of the plugin are the small part that it uses, so the\n * package keeps no dependency. A test examines that Vite accepts the plugin.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { BuildInfo } from \"./chrome.ts\";\nimport { parseDataStamps, type DataStamps } from \"./check/freshness.ts\";\nimport { git, headCommit } from \"./data/git.ts\";\nimport { KPI_FILE, kpiFile, kpiText, type KpiInput } from \"./data/kpi.ts\";\nimport { renderDataStamp } from \"./render/data-stamp.ts\";\n\nexport type { BuildInfo } from \"./chrome.ts\";\n\n/** The environment variables that this module reads. */\nexport type SiteEnv = Readonly<Record<string, string | undefined>>;\n\n/** The options of `siteShell`. */\nexport interface SiteShellOptions {\n /** The `localStorage` key of the theme. Give the same key to `setupTheme` in the page. */\n readonly themeKey: string;\n /**\n * The file with the version for `__BUILD__`, relative to the folder of the site. The default is\n * `../package.json`. The value `false` gives a build with no version.\n */\n readonly packageFile?: string | false | undefined;\n}\n\n/** The value of `build.target` in a Vite config. */\nexport type SiteTarget = string | string[] | false;\n\n/** The part of the Vite config that `siteShell` reads. */\nexport interface SiteShellConfigInput {\n readonly root?: string | undefined;\n readonly base?: string | undefined;\n readonly build?: { readonly target?: SiteTarget | undefined } | null | undefined;\n}\n\n/** The part of the Vite config that `siteShell` sets. Vite merges it into the config of the site. */\nexport interface SiteShellConfig {\n readonly base: string;\n readonly build: { readonly target: SiteTarget };\n readonly define: Readonly<Record<string, string>>;\n}\n\n/** A tag for the `head` of each HTML page. */\nexport interface SiteShellTag {\n readonly tag: \"script\";\n readonly children: string;\n readonly injectTo: \"head\";\n}\n\n/** The Vite plugin that `siteShell` gives. */\nexport interface SiteShellPlugin {\n readonly name: string;\n config(config: SiteShellConfigInput): SiteShellConfig;\n transformIndexHtml(): SiteShellTag[];\n}\n\n/** The input of `siteKpi`. Without a commit, the plugin takes `GITHUB_SHA`, else the head of the repository. */\nexport type SiteKpiInput = Omit<KpiInput, \"commit\"> & { readonly commit?: string | undefined };\n\n/** The part of the context of a Rollup hook that `siteKpi` uses. */\nexport interface SiteKpiContext {\n emitFile(file: { type: \"asset\"; fileName: string; source: string }): string;\n}\n\n/** The Vite plugin that `siteKpi` gives. */\nexport interface SiteKpiPlugin {\n readonly name: string;\n readonly apply: \"build\";\n generateBundle(this: SiteKpiContext): void;\n}\n\n/**\n * This function gives the Vite plugin that adds `kpi.json` to the root of a built site. A fault in the data stops the build.\n *\n * @param input - The data, or a function that reads it at the time of the build.\n * @param env - The environment variables. A test gives its own.\n */\nexport function siteKpi(input: SiteKpiInput | (() => SiteKpiInput), env: SiteEnv = process.env): SiteKpiPlugin {\n return {\n name: \"site-pages-kpi\",\n apply: \"build\",\n generateBundle() {\n const data = typeof input === \"function\" ? input() : input;\n const commit = data.commit ?? env[\"GITHUB_SHA\"] ?? headCommit(process.cwd()) ?? \"\";\n this.emitFile({ type: \"asset\", fileName: KPI_FILE, source: kpiText(kpiFile({ ...data, commit })) });\n },\n };\n}\n\n/** The file that `siteStamps` adds to the root of a built site. The input `data-stamps` of `reusable-pages.yml` names it. */\nexport const STAMPS_FILE = \"data-stamps.json\";\n\n/** The mark in the HTML of a measured page. `siteStamps` replaces it with the stamp line of the page. */\nexport const STAMP_MARK = \"<!-- data-stamp -->\";\n\n/** The part of the context of a page that `siteStamps` uses. */\nexport interface SiteStampsPage {\n /** The path of the page from the root of the site, with a `/` at the start. */\n readonly path: string;\n}\n\n/** The Vite plugin that `siteStamps` gives. */\nexport interface SiteStampsPlugin {\n readonly name: string;\n readonly apply: \"build\";\n readonly transformIndexHtml: { readonly order: \"pre\"; handler(html: string, page: SiteStampsPage): string };\n generateBundle(this: SiteKpiContext): void;\n}\n\n/**\n * This function gives the Vite plugin of the data stamps of a site. The plugin puts the stamp line in each measured page.\n * It also adds `data-stamps.json` to the root of the site. So the page and the freshness gate read one record.\n *\n * A fault stops the build. A fault is a bad stamp, a mark with no stamp or a stamp with no mark. A stamp of a page that the build does not hold is also a fault.\n *\n * @param input - The stamps, or a function that reads them at the time of the build.\n */\nexport function siteStamps(input: DataStamps | (() => DataStamps)): SiteStampsPlugin {\n let stamps: DataStamps | undefined;\n const read = (): DataStamps => {\n if (stamps !== undefined) return stamps;\n const parsed = parseDataStamps(typeof input === \"function\" ? input() : input);\n if (!parsed.ok) throw new Error(`The data stamps are not good:\\n- ${parsed.faults.join(\"\\n- \")}`);\n stamps = parsed.stamps;\n return stamps;\n };\n const seen = new Set<string>();\n return {\n name: \"site-pages-stamps\",\n apply: \"build\",\n transformIndexHtml: {\n order: \"pre\",\n handler(html, { path }) {\n const name = path.replace(/^\\//, \"\");\n const stamp = read().pages.find((page) => page.page === name);\n const marked = html.includes(STAMP_MARK);\n if (stamp === undefined && marked) throw new Error(`The page ${name} has the mark of a data stamp, and the stamps have no page ${name}.`);\n if (stamp === undefined) return html;\n if (!marked) throw new Error(`The stamps have the page ${name}, and the page has no mark ${STAMP_MARK}.`);\n seen.add(name);\n return html.replace(STAMP_MARK, renderDataStamp(stamp));\n },\n },\n generateBundle() {\n const missing = read()\n .pages.map((page) => page.page)\n .filter((page) => !seen.has(page));\n if (missing.length > 0) throw new Error(`The stamps have pages that the build does not hold: ${missing.join(\", \")}.`);\n this.emitFile({ type: \"asset\", fileName: STAMPS_FILE, source: `${JSON.stringify(read(), null, 2)}\\n` });\n },\n };\n}\n\n/**\n * This function gives the script that sets the saved theme before the first paint, so a dark page\n * does not show white for a moment. The script reads `storageKey`, as `applyTheme` writes it.\n *\n * @remarks The text goes in an inline `script` element. Thus the function escapes each `<` of the\n * key, so a key cannot close the element.\n */\nexport function themeScript(storageKey: string): string {\n const key = JSON.stringify(storageKey).replaceAll(\"<\", \"\\\\u003c\");\n return `try{const t=localStorage.getItem(${key});if(t===\"light\"||t===\"dark\")document.documentElement.dataset.theme=t}catch{}`;\n}\n\n/**\n * This function gives the `base` of Vite from `SITE_BASE`, with one `/` at the end. The Pages\n * workflow sets that variable to `/<name>`. A local build has no such variable, and gets `/`.\n */\nexport function siteBase(env: SiteEnv = process.env): string {\n const base = env[\"SITE_BASE\"];\n return base ? `${base.replace(/\\/$/, \"\")}/` : \"/\";\n}\n\n/**\n * This function gives the ISO time in UTC of the commit of a build. A count that a build reads from the source is\n * true at that commit, so this time is the time of its data. It is not the time of the build.\n *\n * @param env - The environment variables. The function takes `GITHUB_SHA`, else `HEAD`.\n * @param repoDir - The folder of the repository.\n * @throws When git cannot read the commit. A file with no time of its data is a fault.\n */\nexport function commitTime(env: SiteEnv = process.env, repoDir: string = process.cwd()): string {\n const ref = env[\"GITHUB_SHA\"] ?? \"HEAD\";\n const time = git(repoDir, \"show\", \"-s\", \"--format=%cI\", ref)?.trim();\n if (!time) throw new Error(`git cannot read the commit ${ref}, so the data has no time.`);\n return new Date(time).toISOString();\n}\n\n/** This function gives the data of a build. Outside CI, `GITHUB_SHA` is not set, and `sha` is `local`. */\nexport function buildInfo(version?: string, env: SiteEnv = process.env, now: Date = new Date()): BuildInfo {\n return { sha: (env[\"GITHUB_SHA\"] ?? \"local\").slice(0, 7), date: now.toISOString().slice(0, 10), version };\n}\n\n/** This function reads the field `version` of a `package.json` file. */\nfunction versionIn(file: string): string | undefined {\n return (JSON.parse(readFileSync(file, \"utf8\")) as { version?: string }).version;\n}\n\n/**\n * This function makes the Vite plugin of a site. The plugin does these four operations:\n *\n * - It sets `base` from `SITE_BASE`.\n * - It sets `build.target` to `es2022`.\n * - It defines `__BUILD__`, the value that `showBuild` shows.\n * - It adds `themeScript` to the `head` of each HTML page.\n *\n * A `base` or a `build.target` in the config of the site has priority. The other values of `build`\n * and `define` in that config stay, because Vite merges them.\n */\nexport function siteShell(options: SiteShellOptions): SiteShellPlugin {\n return {\n name: \"site-pages-shell\",\n config(config) {\n const packageFile = options.packageFile ?? \"../package.json\";\n const version = packageFile === false ? undefined : versionIn(resolve(config.root ?? \".\", packageFile));\n return {\n base: config.base ?? siteBase(),\n build: { target: config.build?.target ?? \"es2022\" },\n define: { __BUILD__: JSON.stringify(buildInfo(version)) },\n };\n },\n transformIndexHtml() {\n return [{ tag: \"script\", children: themeScript(options.themeKey), injectTo: \"head\" }];\n },\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@mark1russell7/site-pages",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.13",
|
|
5
5
|
"description": "A release timeline page and a live status page for the site of a GitHub repository: JSON data and standalone HTML, made at deploy time.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"github-pages",
|