@mark1russell7/site-pages 0.2.14 → 0.2.19
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 +22 -1
- package/build/chunks/build.js +136 -2
- package/build/chunks/build.js.map +1 -1
- package/build/chunks/freshness.d.ts +2 -0
- package/build/chunks/freshness.d.ts.map +1 -1
- package/build/chunks/freshness.js +5 -3
- package/build/chunks/freshness.js.map +1 -1
- package/build/index.d.ts +44 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -2
- package/build/vite.d.ts +13 -0
- package/build/vite.d.ts.map +1 -1
- package/build/vite.js +23 -1
- package/build/vite.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -199,6 +199,18 @@ The pipeline needs the full history for the tags and the commits. Use `fetch-dep
|
|
|
199
199
|
|
|
200
200
|
For a monorepo with one version for all its packages, give `--group` and the name of one package. Then only its changelog gives the versions, and the dates come from its tags. Without `--group`, each version of each source is a version.
|
|
201
201
|
|
|
202
|
+
`changelogFaults(markdown, { from, fixedGroup })` examines a changelog and gives its faults:
|
|
203
|
+
|
|
204
|
+
- An empty section.
|
|
205
|
+
- A section with only dependency lines on a break of the version rule.
|
|
206
|
+
- A first statement that names only the version kind.
|
|
207
|
+
- A break of the version rule with no mark.
|
|
208
|
+
- A mark on a release with no break.
|
|
209
|
+
|
|
210
|
+
The option `from` leaves out older sections. The option `fixedGroup` passes a section with no change or with only PATCH changes, because its raise comes from another package of the group.
|
|
211
|
+
|
|
212
|
+
`sectionMarksBreak(section)` tells if the text of a section marks a break. The marks are the heading `### Breaking` and the words "has breaking changes". A page that counts breaks uses this function.
|
|
213
|
+
|
|
202
214
|
A repository can have no changelog and no GitHub release. Then each npm version of each package of `--packages` is a release:
|
|
203
215
|
|
|
204
216
|
- The label is the version when there is one package. With more packages, the label is the name without its scope and the version, for example `service@0.5.8`.
|
|
@@ -397,6 +409,14 @@ The class sets `overflow-x: auto` and the background color of the box. Set `--sc
|
|
|
397
409
|
}
|
|
398
410
|
```
|
|
399
411
|
|
|
412
|
+
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:
|
|
413
|
+
|
|
414
|
+
```js
|
|
415
|
+
import { rehypeScrollCue } from "@mark1russell7/site-pages/vite";
|
|
416
|
+
|
|
417
|
+
export default defineConfig({ markdown: { rehypePlugins: [rehypeScrollCue] } });
|
|
418
|
+
```
|
|
419
|
+
|
|
400
420
|
## The page helpers
|
|
401
421
|
|
|
402
422
|
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.
|
|
@@ -452,13 +472,14 @@ interface KpiFile {
|
|
|
452
472
|
project: string;
|
|
453
473
|
at: string; // the ISO time of the data in UTC, never the time of the build
|
|
454
474
|
commit: string; // the full commit of the build
|
|
455
|
-
measures: Array<{ id: string; value: number; unit?: string; at?: string }>;
|
|
475
|
+
measures: Array<{ id: string; value: number; unit?: string; at?: string; notCounted?: string }>;
|
|
456
476
|
engines?: Array<{ name: string; version: string }>; // the Status page shows them
|
|
457
477
|
}
|
|
458
478
|
```
|
|
459
479
|
|
|
460
480
|
- Give `at` from the record of the data. The writer has no default for this field, because a build time hides old data.
|
|
461
481
|
- 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.
|
|
482
|
+
- 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.
|
|
462
483
|
- Without `commit`, the plugin takes `GITHUB_SHA`, else the head of the repository.
|
|
463
484
|
- 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.
|
|
464
485
|
- A site with no Vite build calls `writeKpi(out, input)` from the root entry, before `site-pages build`.
|
package/build/chunks/build.js
CHANGED
|
@@ -96,6 +96,138 @@ function parseChangelog(markdown) {
|
|
|
96
96
|
entries: raw.map(entryOf).filter((change) => change !== null)
|
|
97
97
|
}));
|
|
98
98
|
}
|
|
99
|
+
const KIND_WORDS = /* @__PURE__ */ new Set([
|
|
100
|
+
"major",
|
|
101
|
+
"minor",
|
|
102
|
+
"patch"
|
|
103
|
+
]);
|
|
104
|
+
const FILL_WORDS = /* @__PURE__ */ new Set([
|
|
105
|
+
"a",
|
|
106
|
+
"the",
|
|
107
|
+
"this",
|
|
108
|
+
"is",
|
|
109
|
+
"raises",
|
|
110
|
+
"bumps",
|
|
111
|
+
"release",
|
|
112
|
+
"version",
|
|
113
|
+
"bump"
|
|
114
|
+
]);
|
|
115
|
+
const BREAK_HEADING = /^### Breaking\b/m;
|
|
116
|
+
const BREAK_SENTENCE = /\bhas breaking changes\b/;
|
|
117
|
+
/**
|
|
118
|
+
* This function tells if the text of a version section marks a break. The marks are the heading
|
|
119
|
+
* `### Breaking` and the words "has breaking changes", for a text that goes through Changesets.
|
|
120
|
+
*
|
|
121
|
+
* @remarks A page that counts breaks and {@link changelogFaults} use this one test, so they agree.
|
|
122
|
+
*/
|
|
123
|
+
function sectionMarksBreak(section) {
|
|
124
|
+
return BREAK_HEADING.test(section) || BREAK_SENTENCE.test(section);
|
|
125
|
+
}
|
|
126
|
+
/** This function tells if a statement has only the kind of the version and words that state no change. */
|
|
127
|
+
function namesOnlyKind(statement) {
|
|
128
|
+
const words = statement.toLowerCase().match(/[\p{L}\p{N}`]+/gu) ?? [];
|
|
129
|
+
return words.some((word) => KIND_WORDS.has(word)) && words.every((word) => KIND_WORDS.has(word) || FILL_WORDS.has(word));
|
|
130
|
+
}
|
|
131
|
+
/** This function gives the three numbers of a version without its pre-release text, or null for another text. */
|
|
132
|
+
function versionCore(version) {
|
|
133
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-|$)/.exec(version);
|
|
134
|
+
return match ? [
|
|
135
|
+
Number(match[1]),
|
|
136
|
+
Number(match[2]),
|
|
137
|
+
Number(match[3])
|
|
138
|
+
] : null;
|
|
139
|
+
}
|
|
140
|
+
/** This function compares two versions without their pre-release texts. */
|
|
141
|
+
function compareCores(a, b) {
|
|
142
|
+
return (a[0] ?? 0) - (b[0] ?? 0) || (a[1] ?? 0) - (b[1] ?? 0) || (a[2] ?? 0) - (b[2] ?? 0);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* This function tells if the version rule makes a release a break. Before 1.0.0, a break raises
|
|
146
|
+
* MINOR. From 1.0.0, a break raises MAJOR.
|
|
147
|
+
*/
|
|
148
|
+
function ruleGivesBreak([major, minor, patch]) {
|
|
149
|
+
if (patch !== 0) return false;
|
|
150
|
+
return major === 0 ? minor > 0 : minor === 0;
|
|
151
|
+
}
|
|
152
|
+
/** This function gives the version and the body of each version section. Another heading of level 1 or 2 ends a section. */
|
|
153
|
+
function versionSections(markdown) {
|
|
154
|
+
const sections = [];
|
|
155
|
+
let section = null;
|
|
156
|
+
for (const line of markdown.split(/\r?\n/)) {
|
|
157
|
+
const heading = VERSION_HEADING.exec(line);
|
|
158
|
+
if (heading?.[1] !== void 0) {
|
|
159
|
+
section = {
|
|
160
|
+
version: heading[1],
|
|
161
|
+
heading: line,
|
|
162
|
+
body: []
|
|
163
|
+
};
|
|
164
|
+
sections.push(section);
|
|
165
|
+
} else if (/^#{1,2}\s/.test(line)) section = null;
|
|
166
|
+
else section?.body.push(line);
|
|
167
|
+
}
|
|
168
|
+
return sections;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* This function gives the first statement of a section: the first sentence of its first paragraph,
|
|
172
|
+
* else the first change of its lists. A dependency line is not a change.
|
|
173
|
+
*/
|
|
174
|
+
function firstStatement(section) {
|
|
175
|
+
const first = section.body.join("\n").split(/\n[ \t]*\n/).map((block) => block.trim()).find((block) => block !== "" && !block.startsWith("#"));
|
|
176
|
+
if (first !== void 0 && !/^[-*+]\s/.test(first)) return firstSentence(first);
|
|
177
|
+
const [parsed] = parseChangelog([section.heading, ...section.body].join("\n"));
|
|
178
|
+
return parsed?.entries[0]?.text ?? "";
|
|
179
|
+
}
|
|
180
|
+
/** This function tells if a section of a fixed group has no change of its own above the level of PATCH. */
|
|
181
|
+
function raisedByGroup(text) {
|
|
182
|
+
if (/^### (?:Minor|Major) Changes\b/m.test(text)) return false;
|
|
183
|
+
return text.trim() === "" || /^### Patch Changes\b/m.test(text) || /^No changes in this release\.$/m.test(text);
|
|
184
|
+
}
|
|
185
|
+
/** This function tells if a section has a line that names a new version of a dependency. */
|
|
186
|
+
function hasDependencyLine(section) {
|
|
187
|
+
return section.body.some((line) => {
|
|
188
|
+
const item = /^[-*+]\s+(.*)$/.exec(line)?.[1];
|
|
189
|
+
return item !== void 0 && DEPENDENCY_ENTRY.test((COMMIT_ENTRY.exec(item)?.[2] ?? item).trim());
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* This function gives the faults of the version sections of a changelog, in the order of the file.
|
|
194
|
+
* A section can have two faults: one for its statement and one for its break mark.
|
|
195
|
+
*
|
|
196
|
+
* @remarks The break rule does not read a pre-release or the oldest section of the file, because
|
|
197
|
+
* the oldest section has no earlier release to break. A dependency line does not say why the API
|
|
198
|
+
* broke. Thus a section with only dependency lines has a fault on a break of the version rule. The
|
|
199
|
+
* option `fixedGroup` removes this fault.
|
|
200
|
+
*/
|
|
201
|
+
function changelogFaults(markdown, options = {}) {
|
|
202
|
+
const from = options.from === void 0 ? null : versionCore(options.from);
|
|
203
|
+
if (options.from !== void 0 && from === null) throw new RangeError(`"${options.from}" is not a version.`);
|
|
204
|
+
const sections = versionSections(markdown);
|
|
205
|
+
const oldest = sections.map((section) => versionCore(section.version)).filter((core) => core !== null).reduce((low, core) => low === null || compareCores(core, low) < 0 ? core : low, null);
|
|
206
|
+
const faults = [];
|
|
207
|
+
for (const section of sections) {
|
|
208
|
+
const core = versionCore(section.version);
|
|
209
|
+
if (core === null || from !== null && compareCores(core, from) < 0) continue;
|
|
210
|
+
const statement = firstStatement(section);
|
|
211
|
+
const fault = (kind) => {
|
|
212
|
+
faults.push({
|
|
213
|
+
version: section.version,
|
|
214
|
+
kind,
|
|
215
|
+
statement
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
if (statement === "" && options.fixedGroup === true) continue;
|
|
219
|
+
const ruled = !section.version.includes("-") && oldest !== null && compareCores(core, oldest) !== 0;
|
|
220
|
+
if (statement === "" && (!hasDependencyLine(section) || ruled && ruleGivesBreak(core))) fault("no-statement");
|
|
221
|
+
else if (statement !== "" && namesOnlyKind(statement)) fault("version-kind-only");
|
|
222
|
+
if (!ruled) continue;
|
|
223
|
+
const text = section.body.join("\n");
|
|
224
|
+
const marked = sectionMarksBreak(text);
|
|
225
|
+
if (!ruleGivesBreak(core)) {
|
|
226
|
+
if (marked) fault("mark-without-break");
|
|
227
|
+
} else if (!marked && !(options.fixedGroup === true && raisedByGroup(text))) fault("break-unmarked");
|
|
228
|
+
}
|
|
229
|
+
return faults;
|
|
230
|
+
}
|
|
99
231
|
/**
|
|
100
232
|
* This function gives the changes of the text of a GitHub release: one change for each top-level
|
|
101
233
|
* list item. Fenced code is not read.
|
|
@@ -1997,6 +2129,7 @@ function openWork(data) {
|
|
|
1997
2129
|
/**
|
|
1998
2130
|
* This function renders the measures of `kpi.json`: their values, the date of the data and the engines that made it.
|
|
1999
2131
|
* A measure with its own date shows that date in a column, so that the line above the table stays true.
|
|
2132
|
+
* A measure that names what it does not count shows that text under the table.
|
|
2000
2133
|
*/
|
|
2001
2134
|
function measures(data) {
|
|
2002
2135
|
const { kpi } = data;
|
|
@@ -2004,9 +2137,10 @@ function measures(data) {
|
|
|
2004
2137
|
const ownDates = kpi.measures.some((measure) => measure.at !== void 0);
|
|
2005
2138
|
const dateCell = (at) => ownDates ? `<td><time datetime="${escapeHtml(at)}">${escapeHtml(longDate(at))}</time></td>` : "";
|
|
2006
2139
|
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("");
|
|
2140
|
+
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("");
|
|
2007
2141
|
const engines = kpi.engines ?? [];
|
|
2008
2142
|
const commit = link(`https://github.com/${data.source.github}/commit/${kpi.commit}`, `<code>${kpi.commit.slice(0, 7)}</code>`);
|
|
2009
|
-
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
|
|
2143
|
+
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>";
|
|
2010
2144
|
}
|
|
2011
2145
|
function when(date) {
|
|
2012
2146
|
const text = escapeHtml(longDate(date));
|
|
@@ -2371,6 +2505,6 @@ async function runCli(argv, io) {
|
|
|
2371
2505
|
throw error;
|
|
2372
2506
|
}
|
|
2373
2507
|
}
|
|
2374
|
-
export {
|
|
2508
|
+
export { changelogVersions 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, changelogFaults 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, firstSentence as et, sectionsOf as f, releasesLead as g, RELEASES_SCRIPT as h, parseBuildArgs as i, sectionMarksBreak as it, buildStatusBoard as j, RoadmapParseError as k, classCounts as l, statusLead as m, UsageError as n, parseChangelog as nt, TYPESCRIPT_PROBE as o, slugOf as p, GITHUB_API as q, build as r, releaseBodyEntries as rt, probeScript as s, HELP as t, headingAnchor as tt, openGroups as u, laneCenter as v, dayRange as w, timelineLayout as x, oldestFirst as y, statusClassOf as z };
|
|
2375
2509
|
|
|
2376
2510
|
//# sourceMappingURL=build.js.map
|