@mark1russell7/site-pages 0.2.13 → 0.2.18

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 CHANGED
@@ -191,7 +191,7 @@ The command merges four sources by version:
191
191
  1. **The changelogs of Changesets.** Each `## 1.2.3` section of a `CHANGELOG.md` gives a version and its changes. Each change has its commit, the first sentence of its text, and the packages that list it.
192
192
  2. **The GitHub releases.** Each release gives a version (from its tag), a date and a link. When no changelog has the version, the list items of the release text are the changes.
193
193
  3. **The git tags.** The tags `1.2.3`, `v1.2.3` and `name@1.2.3` give the date of a version.
194
- 4. **npm.** The publication time of each version of `--packages` is the last source of a date.
194
+ 4. **npm.** The publication time of each version of `--packages` is the last source of a date. Each stable version of the group, or of the only package, is also a release. So a publication with no changelog heading stays on the list. With `--group`, a version of another package that the group does not have is a release with the name of its package, for example `viewer@0.4.1`.
195
195
 
196
196
  The date of a version comes from the git tag, else from the GitHub release, else from npm. Else it comes from the commit that added the version heading to the changelog. A version without a date gets the date of the next version, and the command writes a warning.
197
197
 
@@ -342,6 +342,9 @@ The functions of the command are also in the package:
342
342
  | --- | --- |
343
343
  | `readReleases(options)` | The releases of a repository on disk, with GitHub and npm |
344
344
  | `mergeReleases(sources)` | The releases from sources that the caller reads |
345
+ | `releaseReading(listed, sources, now)` | The versions that the changelog, the package or npm name and a list does not show, and the version in flight. Use it for a list that a site keeps itself |
346
+ | `versionCommitTime(repoDir, file)` | The time of the commit that set the version of a `package.json`, for the version in flight |
347
+ | `changelogVersions(markdown)` | The versions of the headings of a changelog |
345
348
  | `readStatusBoard(options)` | The status data of a repository on disk, with GitHub |
346
349
  | `githubReleases`, `githubOpenWork`, `npmPublishTimes` | The data of one source. After an error, each function gives `{ available: false, reason }`. It does not throw. |
347
350
  | `renderReleasesPage(releases, options)`, `renderStatusPage(data, options)` | The HTML of a page |
@@ -394,6 +397,14 @@ The class sets `overflow-x: auto` and the background color of the box. Set `--sc
394
397
  }
395
398
  ```
396
399
 
400
+ Markdown has no way to set the class of a table. For a Markdown page, add the plugin `rehypeScrollCue` of the entry `@mark1russell7/site-pages/vite`. It gives the class, a tab stop and a label to each table:
401
+
402
+ ```js
403
+ import { rehypeScrollCue } from "@mark1russell7/site-pages/vite";
404
+
405
+ export default defineConfig({ markdown: { rehypePlugins: [rehypeScrollCue] } });
406
+ ```
407
+
397
408
  ## The page helpers
398
409
 
399
410
  The entry `@mark1russell7/site-pages/chrome` has small helpers for the script of a page. It imports no Node.js module, so a site can bundle it for the browser. The package root does not export these helpers. Thus a Node.js program that imports the root gets no DOM types.
@@ -449,13 +460,14 @@ interface KpiFile {
449
460
  project: string;
450
461
  at: string; // the ISO time of the data in UTC, never the time of the build
451
462
  commit: string; // the full commit of the build
452
- measures: Array<{ id: string; value: number; unit?: string; at?: string }>;
463
+ measures: Array<{ id: string; value: number; unit?: string; at?: string; notCounted?: string }>;
453
464
  engines?: Array<{ name: string; version: string }>; // the Status page shows them
454
465
  }
455
466
  ```
456
467
 
457
468
  - Give `at` from the record of the data. The writer has no default for this field, because a build time hides old data.
458
469
  - Give `at` on a measure when its data is from another time than the file. The Status page then shows a date for each measure.
470
+ - Give `notCounted` on a count of faults, for example a count of old text. The text names what the count does not read, so a 0 does not seem to tell more than it measured. The Status page shows the text.
459
471
  - Without `commit`, the plugin takes `GITHUB_SHA`, else the head of the repository.
460
472
  - A fault in the data stops the build, and the old site stays. A fault is a wrong form, a value that is not finite, a repeated id or a time after the check. The time rules apply to the file and to each measure.
461
473
  - A site with no Vite build calls `writeKpi(out, input)` from the root entry, before `site-pages build`.
@@ -1,4 +1,4 @@
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";
1
+ import { A as originRepository, C as readKpi, D as headCommit, E as gitTagDates, F as kindOf, I as parseVersion, L as versionOfTag, N as npmPublishTimes, O as headingDate, P as compareVersions, _ 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";
@@ -135,6 +135,10 @@ function releaseBodyEntries(body) {
135
135
  function headingAnchor(heading) {
136
136
  return heading.toLowerCase().trim().replace(/[^\p{L}\p{N}\s_-]/gu, "").replace(/\s/g, "-");
137
137
  }
138
+ /** This function gives the versions of the headings of a changelog, in the order of the file. Another heading is not a version. */
139
+ function changelogVersions(markdown) {
140
+ return parseChangelog(markdown).map((section) => section.version);
141
+ }
138
142
  // src/data/github.ts
139
143
  /** The GraphQL endpoint of GitHub. */
140
144
  const GITHUB_GRAPHQL = "https://api.github.com/graphql";
@@ -467,8 +471,10 @@ function stepKind(version, previous) {
467
471
  * version of a package is the kind `first`.
468
472
  * - A version with a prerelease part is not a release. npm also keeps the placeholder
469
473
  * `0.0.0-bootstrap.0` of a new package.
474
+ * - With `label`, each version has the name of its package, also when the times name one package.
475
+ * - With `keep`, the function gives only the versions that `keep` accepts. The kind still comes from each version of the package.
470
476
  */
471
- function npmReleases(times, group) {
477
+ function npmReleases(times, group, options = {}) {
472
478
  const stable = times.filter((time) => (!group || time.name === group) && parseVersion(time.version)?.prerelease.length === 0);
473
479
  const byPackage = /* @__PURE__ */ new Map();
474
480
  for (const time of stable) {
@@ -483,13 +489,14 @@ function npmReleases(times, group) {
483
489
  shortNames.set(name, short);
484
490
  shortCount.set(short, (shortCount.get(short) ?? 0) + 1);
485
491
  }
486
- const several = byPackage.size > 1;
492
+ const several = options.label ?? byPackage.size > 1;
487
493
  const releases = [];
488
494
  for (const [name, list] of byPackage) {
489
495
  list.sort((a, b) => compareVersions(a.version, b.version));
490
496
  const short = shortNames.get(name) ?? name;
491
497
  const label = (shortCount.get(short) ?? 0) > 1 ? name : short;
492
498
  list.forEach((time, index) => {
499
+ if (options.keep && !options.keep(time.version)) return;
493
500
  releases.push({
494
501
  version: several ? `${label}@${time.version}` : time.version,
495
502
  date: time.date,
@@ -508,13 +515,34 @@ function npmReleases(times, group) {
508
515
  }
509
516
  return releases.sort((a, b) => Date.parse(b.date) - Date.parse(a.date) || a.version.localeCompare(b.version));
510
517
  }
518
+ /** The npm package whose versions a release list shows: the group, or else the only package of the npm times. */
519
+ function npmLine(times, group) {
520
+ if (group) return group;
521
+ const names = new Set(times.map((time) => time.name));
522
+ return names.size === 1 ? [...names][0] : void 0;
523
+ }
524
+ /**
525
+ * This function adds the lines of their own to the list of a group. A package of the group can have a version that the
526
+ * group does not have. The list names that version with its package, because a reader looks for the package by its name.
527
+ */
528
+ function withOwnLines(list, times, group) {
529
+ if (!group) return list;
530
+ const versions = new Set(list.map((release) => release.version));
531
+ const own = npmReleases(times.filter((time) => time.name !== group), void 0, {
532
+ label: true,
533
+ keep: (version) => !versions.has(version)
534
+ });
535
+ return own.length === 0 ? list : [...list, ...own].sort((a, b) => Date.parse(b.date) - Date.parse(a.date));
536
+ }
511
537
  /**
512
538
  * This function merges the release sources into one entry for each version, the newest first.
513
539
  *
514
540
  * - The versions: the changelog of `group`, or else each changelog version and each GitHub release.
541
+ * - The versions also include each stable npm version of the group, or of the only npm package. A publication with no changelog heading is still a release.
515
542
  * - The date: the git tag, else the GitHub release, else npm, else the commit of the changelog heading.
516
543
  * - The changes: the changelog entries, else the list items of the GitHub release text.
517
544
  * - Without a changelog version and without a GitHub release, each npm version of each package is a release.
545
+ * - With `group`, a version of another package that the group does not have is a release with the name of its package.
518
546
  *
519
547
  * @throws ReleaseDataError when `group` has no changelog and other changelogs exist
520
548
  */
@@ -545,8 +573,10 @@ function mergeReleases(sources) {
545
573
  for (const { sections } of parsed) for (const section of sections) versions.add(section.version);
546
574
  for (const [version, list] of githubByVersion) if (list.some((entry) => inGroup(entry.package))) versions.add(version);
547
575
  }
576
+ if (versions.size === 0) return withOwnLines(npmReleases(sources.npm ?? [], group), sources.npm ?? [], group);
577
+ const line = npmLine(sources.npm ?? [], group);
578
+ for (const time of sources.npm ?? []) if (time.name === line && parseVersion(time.version)?.prerelease.length === 0) versions.add(time.version);
548
579
  const ordered = [...versions].sort((a, b) => compareVersions(b, a));
549
- if (ordered.length === 0) return npmReleases(sources.npm ?? [], group);
550
580
  const changelogChanges = /* @__PURE__ */ new Map();
551
581
  const changelogOf = /* @__PURE__ */ new Map();
552
582
  const groupFirst = groupChangelog ? [groupChangelog, ...parsed.filter((entry) => entry !== groupChangelog)] : parsed;
@@ -595,12 +625,16 @@ function mergeReleases(sources) {
595
625
  }
596
626
  }
597
627
  const oldest = ordered[ordered.length - 1];
598
- return ordered.map((version) => {
628
+ return withOwnLines(ordered.map((version) => {
599
629
  const github = githubByVersion.get(version) ?? [];
600
630
  let changes = changelogChanges.get(version);
601
631
  if (!changes) {
602
632
  changes = /* @__PURE__ */ new Map();
603
633
  for (const { release, package: packageName } of github) for (const entry of releaseBodyEntries(release.body)) addChange(changes, entry, packageName ?? (group || null));
634
+ if (changes.size === 0 && line !== void 0 && npmByVersion.get(version)?.some((time) => time.name === line)) addChange(changes, {
635
+ commit: null,
636
+ text: `Version ${version} of \`${line}\` on npm.`
637
+ }, line);
604
638
  }
605
639
  const links = [];
606
640
  const githubRelease = github.find((entry) => entry.package === group) ?? github.find((entry) => entry.package === null) ?? github[0];
@@ -633,7 +667,42 @@ function mergeReleases(sources) {
633
667
  changes: sortedChanges(changes),
634
668
  links
635
669
  };
636
- });
670
+ }), sources.npm ?? [], group);
671
+ }
672
+ /** The time that a release can take. After this time, a version with no tag is a failed release. */
673
+ const IN_FLIGHT_MS = 864e5;
674
+ /**
675
+ * This function reads a release list against its sources. An old list and a list with a missing middle version both give
676
+ * a gap. A version in flight gives no gap, because its release has not ended. After 1 day it gives a gap, so a failed
677
+ * release shows. The check covers one line of versions, so give the plain versions of one package. It does not read a
678
+ * page: a page that does not show its list has no gap here.
679
+ *
680
+ * @param listed - The versions of the list.
681
+ * @param sources - The sources that name the versions.
682
+ * @param now - The time of the check, in milliseconds.
683
+ */
684
+ function releaseReading(listed, sources, now = Date.now()) {
685
+ const { current, tags, versionAt } = sources;
686
+ const inFlight = current !== void 0 && tags !== void 0 && versionAt !== void 0 && !tags.includes(current) && now - Date.parse(versionAt) < IN_FLIGHT_MS ? current : void 0;
687
+ const shown = new Set(listed);
688
+ const gaps = /* @__PURE__ */ new Map();
689
+ const add = (version, source) => {
690
+ if (shown.has(version) || version === inFlight) return;
691
+ const gap = gaps.get(version) ?? {
692
+ version,
693
+ sources: []
694
+ };
695
+ gap.sources.push(source);
696
+ gaps.set(version, gap);
697
+ };
698
+ for (const version of sources.changelog ?? []) add(version, "changelog");
699
+ if (sources.current !== void 0) add(sources.current, "current");
700
+ for (const version of sources.npm ?? []) if (parseVersion(version)?.prerelease.length === 0) add(version, "npm");
701
+ const ordered = [...gaps.values()].sort((a, b) => compareVersions(b.version, a.version));
702
+ return inFlight === void 0 ? { gaps: ordered } : {
703
+ gaps: ordered,
704
+ inFlight
705
+ };
637
706
  }
638
707
  /** The default patterns of the changelog files: the first pattern that finds a file wins. */
639
708
  const DEFAULT_CHANGELOGS = ["packages/*/CHANGELOG.md", "CHANGELOG.md"];
@@ -1928,6 +1997,7 @@ function openWork(data) {
1928
1997
  /**
1929
1998
  * This function renders the measures of `kpi.json`: their values, the date of the data and the engines that made it.
1930
1999
  * A measure with its own date shows that date in a column, so that the line above the table stays true.
2000
+ * A measure that names what it does not count shows that text under the table.
1931
2001
  */
1932
2002
  function measures(data) {
1933
2003
  const { kpi } = data;
@@ -1935,9 +2005,10 @@ function measures(data) {
1935
2005
  const ownDates = kpi.measures.some((measure) => measure.at !== void 0);
1936
2006
  const dateCell = (at) => ownDates ? `<td><time datetime="${escapeHtml(at)}">${escapeHtml(longDate(at))}</time></td>` : "";
1937
2007
  const rows = kpi.measures.map((measure) => `<tr><th scope="row">${escapeHtml(measure.id)}</th><td>${measure.value}${measure.unit === void 0 ? "" : ` ${escapeHtml(measure.unit)}`}</td>${dateCell(measure.at ?? kpi.at)}</tr>`).join("");
2008
+ const limits = kpi.measures.filter((measure) => measure.notCounted !== void 0).map((measure) => `<p><code>${escapeHtml(measure.id)}</code> does not count: ${escapeHtml(measure.notCounted ?? "")}</p>`).join("");
1938
2009
  const engines = kpi.engines ?? [];
1939
2010
  const commit = link(`https://github.com/${data.source.github}/commit/${kpi.commit}`, `<code>${kpi.commit.slice(0, 7)}</code>`);
1940
- return `<section class="sp-section" aria-labelledby="measures"><h2 id="measures">Measures</h2><p>${ownDates ? "The data date of the file is" : "The data of these numbers is from"} <time datetime="${escapeHtml(kpi.at)}" data-sp-data-date>${escapeHtml(longDate(kpi.at))}</time>. The build of ${commit} published them.</p>` + (engines.length > 0 ? `<p>The engines of the data: ${listText(engines.map((engine) => `<code>${escapeHtml(engine.name)}</code> ${escapeHtml(engine.version)}`))}.</p>` : "") + `<div class="sp-table-box" tabindex="0" role="region" aria-label="Measures"><table class="sp-table"><thead><tr><th scope="col">Measure</th><th scope="col">Value</th>${ownDates ? "<th scope=\"col\">Data date</th>" : ""}</tr></thead><tbody>${rows}</tbody></table></div></section>`;
2011
+ return `<section class="sp-section" aria-labelledby="measures"><h2 id="measures">Measures</h2><p>${ownDates ? "The data date of the file is" : "The data of these numbers is from"} <time datetime="${escapeHtml(kpi.at)}" data-sp-data-date>${escapeHtml(longDate(kpi.at))}</time>. The build of ${commit} published them.</p>` + (engines.length > 0 ? `<p>The engines of the data: ${listText(engines.map((engine) => `<code>${escapeHtml(engine.name)}</code> ${escapeHtml(engine.version)}`))}.</p>` : "") + `<div class="sp-table-box" tabindex="0" role="region" aria-label="Measures"><table class="sp-table"><thead><tr><th scope="col">Measure</th><th scope="col">Value</th>${ownDates ? "<th scope=\"col\">Data date</th>" : ""}</tr></thead><tbody>${rows}</tbody></table></div>` + limits + "</section>";
1941
2012
  }
1942
2013
  function when(date) {
1943
2014
  const text = escapeHtml(longDate(date));
@@ -2302,6 +2373,6 @@ async function runCli(argv, io) {
2302
2373
  throw error;
2303
2374
  }
2304
2375
  }
2305
- export { parseChangelog as $, STATUS_CLASSES as A, DEFAULT_CHANGELOGS as B, pageShell as C, utcDay as D, shortDate as E, plainText as F, globFiles as G, mergeReleases as H, readStatusBoard as I, checkStateOf as J, GITHUB_API as K, roadmapItems as L, linksOf as M, markdownTables as N, OPEN_CLASSES as O, parseRoadmap as P, headingAnchor as Q, splitRow as R, BASE_CSS as S, longDate as T, readChangelogs as U, ReleaseDataError as V, readReleases as W, githubReleases as X, githubOpenWork as Y, firstSentence as Z, renderReleasesPage as _, runCli as a, releaseSummary as b, STATUS_SCRIPT as c, renderStatusPage as d, releaseBodyEntries as et, sectionsOf as f, releasesLead as g, RELEASES_SCRIPT as h, parseBuildArgs as i, buildStatusBoard as j, RoadmapParseError as k, classCounts as l, statusLead as m, UsageError as n, TYPESCRIPT_PROBE as o, slugOf as p, GITHUB_GRAPHQL as q, build as r, probeScript as s, HELP as t, openGroups as u, laneCenter as v, dayRange as w, timelineLayout as x, oldestFirst as y, statusClassOf as z };
2376
+ export { firstSentence as $, STATUS_CLASSES as A, DEFAULT_CHANGELOGS as B, pageShell as C, utcDay as D, shortDate as E, plainText as F, releaseReading as G, mergeReleases as H, readStatusBoard as I, GITHUB_GRAPHQL as J, globFiles as K, roadmapItems as L, linksOf as M, markdownTables as N, OPEN_CLASSES as O, parseRoadmap as P, changelogVersions as Q, splitRow as R, BASE_CSS as S, longDate as T, readChangelogs as U, ReleaseDataError as V, readReleases as W, githubOpenWork as X, checkStateOf as Y, githubReleases as Z, renderReleasesPage as _, runCli as a, releaseSummary as b, STATUS_SCRIPT as c, renderStatusPage as d, headingAnchor as et, sectionsOf as f, releasesLead as g, RELEASES_SCRIPT as h, parseBuildArgs as i, buildStatusBoard as j, RoadmapParseError as k, classCounts as l, statusLead as m, UsageError as n, releaseBodyEntries as nt, TYPESCRIPT_PROBE as o, slugOf as p, GITHUB_API as q, build as r, probeScript as s, HELP as t, parseChangelog as tt, openGroups as u, laneCenter as v, dayRange as w, timelineLayout as x, oldestFirst as y, statusClassOf as z };
2306
2377
 
2307
2378
  //# sourceMappingURL=build.js.map