@mark1russell7/site-pages 0.2.18 → 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 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`.
@@ -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.
@@ -2373,6 +2505,6 @@ async function runCli(argv, io) {
2373
2505
  throw error;
2374
2506
  }
2375
2507
  }
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 };
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 };
2377
2509
 
2378
2510
  //# sourceMappingURL=build.js.map