@mark1russell7/site-pages 0.1.0 → 0.1.2

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
@@ -76,6 +76,10 @@ The kind of a version:
76
76
 
77
77
  ## The status
78
78
 
79
+ The command reads two forms of a roadmap file. It reads both forms in one file, and it keeps the items in the order of the file.
80
+
81
+ ### The tables
82
+
79
83
  The command reads each Markdown table of the roadmap file with an `ID` column and a `Status` column. Each row is one item, and the heading above the table is its section. The header names match without case.
80
84
 
81
85
  | Column | Use |
@@ -95,10 +99,40 @@ The classes, in the sequence of the page:
95
99
  | `progress` | in progress, active, ongoing, started, wip |
96
100
  | `open` | not started, to do, and a status without a keyword |
97
101
  | `later` | later, deferred, postponed, someday |
98
- | `done` | done, shipped, merged, fixed, released, complete, closed |
102
+ | `done` | done, shipped, merged, fixed, released, complete, closed, dropped, cancelled, wontfix, and the word in `## Never` |
99
103
 
100
104
  A row whose cells do not match the header stops the build with the file and the line. Thus the page does not lose an item without a message.
101
105
 
106
+ ### The item headings
107
+
108
+ The command also reads each heading `` ### `id`: Title `` under a `##` heading. The `##` heading is the section and the status of its items, for example `## Waiting on Mark`, `## Later` or `## Shipped`. A dash can replace the colon.
109
+
110
+ ```md
111
+ ## Waiting on Mark
112
+
113
+ ### `eval-b`: Eval, part B
114
+
115
+ - Area: Site and growth
116
+ - Waits for: `eval`
117
+ - [crawler #22](https://github.com/acme/crawler/pull/22)
118
+ ```
119
+
120
+ The command also reads the heading `### S1 · Title`: the ID is one word before the middle dot. A list item `Status:` gives the status of its item, and it wins over the `##` heading.
121
+
122
+ ```md
123
+ ### S1 · Detection and divergence in Docker
124
+
125
+ - **Status:** in progress
126
+ - **Area:** program
127
+ - **Depends on:** S0
128
+ - **Links:** [The results](https://example.com/results/)
129
+ ```
130
+
131
+ - The list items `Area:`, `Owner:` and `Waits for:` (or `Depends on:`) give the optional fields. A label can be bold.
132
+ - The list item `Links:` and the other list items give the links: Markdown links, `#12`, `PR #12` and commit hashes in code spans.
133
+ - A `###` heading without an ID is not an item. A heading without a `##` heading above it and without a `Status:` item is not an item either. The text of an item is not read.
134
+ - A roadmap without a table and without an item heading stops the build.
135
+
102
136
  The GitHub part comes from one GraphQL request: the 50 open pull requests and the 50 open issues that changed last, with the totals.
103
137
 
104
138
  ## The data shapes
@@ -851,8 +851,10 @@ async function readReleases(options) {
851
851
  * The status data: the open work of a roadmap file, and the open pull requests and issues of a
852
852
  * GitHub repository. The build reads both, so the page shows the state at the time of the build.
853
853
  *
854
- * @remarks The roadmap parser reads each Markdown table with an `ID` column and a `Status` column.
855
- * It is strict: a row whose cells do not match the header stops the build with the file and the line.
854
+ * @remarks The roadmap parser reads two forms. The first form is each Markdown table with an `ID`
855
+ * column and a `Status` column. The second form is each heading "### `id`: Title" under a "##" heading
856
+ * that gives the status. The parser is strict: a row whose cells do not match the header stops the
857
+ * build with the file and the line.
856
858
  */
857
859
  /** The classes of a status, in the sequence of the board. The open work comes first. */
858
860
  const STATUS_CLASSES = [
@@ -875,7 +877,7 @@ const OPEN_CLASSES = [
875
877
  var RoadmapParseError = class extends Error {};
876
878
  const STATUS_KEYWORDS = [
877
879
  ["open", /\bnot\s+(?:yet\s+)?(?:started|done|fixed|merged|shipped|released)\b|\bto[ -]?do\b/],
878
- ["done", /\b(?:done|shipped|merged|fixed|released|complete|completed|closed)\b/],
880
+ ["done", /\b(?:done|shipped|merged|fixed|released|complete|completed|closed|never|dropped|cancell?ed|wontfix)\b|\bwon't do\b/],
879
881
  ["progress", /\bin[ -]progress\b|\b(?:active|ongoing|started|wip)\b/],
880
882
  ["waiting", /\b(?:waiting|waits|awaiting|needs)\b/],
881
883
  ["blocked", /\bblocked\b/],
@@ -1033,12 +1035,99 @@ function linksOf(cell, options = {}) {
1033
1035
  }
1034
1036
  return links;
1035
1037
  }
1038
+ /** The heading of an item: "### `id`: Title". A dash can take the place of the colon. */
1039
+ const ITEM_HEADING = /^###\s+`([^`]+)`\s*[:–—-]\s*(.*?)\s*#*\s*$/;
1040
+ /** The other heading of an item: "### S1 · Title". The ID is one word before the middle dot. */
1041
+ const ITEM_HEADING_DOT = /^###\s+([A-Za-z0-9][\w.-]*)\s+·\s+(.*?)\s*#*\s*$/;
1036
1042
  /**
1037
- * This function gives the items of a roadmap file: one item for each row of each table with an `ID`
1038
- * column and a `Status` column. The header names match without case.
1043
+ * A field of an item heading: "- Area: Docs", "- **Area:** Docs" or "- **Area**: Docs". The label
1044
+ * matches without case.
1045
+ */
1046
+ const ITEM_FIELD = /^\s*[-*]\s+(\*\*|__)?([A-Za-z][A-Za-z ]*?)(?::\1|\1:)\s*(.*)$/;
1047
+ /** The fields of an item heading that give the optional fields of an item. */
1048
+ const ITEM_FIELDS = {
1049
+ area: "area",
1050
+ owner: "owner",
1051
+ "waits for": "needs",
1052
+ needs: "needs",
1053
+ "depends on": "needs"
1054
+ };
1055
+ /**
1056
+ * This function gives the items of the second form of a roadmap: each heading "### `id`: Title" or
1057
+ * "### id · Title". The list item "Status:" gives the status. Without it, the "##" heading above
1058
+ * the item gives the status, for example "Waiting on Mark", "Later" or "Shipped". A heading without
1059
+ * a status is not an item.
1060
+ *
1061
+ * The list items "Area:", "Owner:" and "Waits for:" give the optional fields. The list item
1062
+ * "Links:" and the other list items give the links. Fenced code is not read.
1063
+ */
1064
+ function headingItems(markdown, options) {
1065
+ const lines = String(markdown).split(/\r?\n/);
1066
+ const items = [];
1067
+ let section = "";
1068
+ let current;
1069
+ let fence = null;
1070
+ for (let index = 0; index < lines.length; index++) {
1071
+ const line = lines[index] ?? "";
1072
+ const fenceMark = /^\s*(`{3,}|~{3,})/.exec(line)?.[1];
1073
+ if (fenceMark !== void 0) {
1074
+ if (fence === null) fence = fenceMark[0] ?? null;
1075
+ else if (fenceMark[0] === fence) fence = null;
1076
+ continue;
1077
+ }
1078
+ if (fence !== null) continue;
1079
+ const heading = /^(#{1,6})\s+(.*?)\s*#*\s*$/.exec(line);
1080
+ if (heading) {
1081
+ const level = heading[1]?.length ?? 0;
1082
+ if (level > 3) continue;
1083
+ current = void 0;
1084
+ if (level === 2) section = plainText(heading[2]);
1085
+ if (level === 1) section = "";
1086
+ if (level !== 3) continue;
1087
+ const item = ITEM_HEADING.exec(line) ?? ITEM_HEADING_DOT.exec(line);
1088
+ const id = plainText(item?.[1]);
1089
+ if (!item || isEmpty(id)) continue;
1090
+ current = {
1091
+ id,
1092
+ title: item[2] ?? "",
1093
+ status: section,
1094
+ statusClass: statusClassOf(section),
1095
+ section,
1096
+ line: index + 1,
1097
+ links: []
1098
+ };
1099
+ items.push(current);
1100
+ continue;
1101
+ }
1102
+ if (!current) continue;
1103
+ const field = ITEM_FIELD.exec(line);
1104
+ const label = (field?.[2] ?? "").trim().toLowerCase();
1105
+ const value = (field?.[3] ?? "").trim();
1106
+ const key = field ? ITEM_FIELDS[label] : void 0;
1107
+ if (field && label === "status") {
1108
+ if (!isEmpty(value)) {
1109
+ current.status = value;
1110
+ current.statusClass = statusClassOf(plainText(value));
1111
+ }
1112
+ } else if (field && key !== void 0) {
1113
+ if (!isEmpty(value)) current[key] = value;
1114
+ } else if (/^\s*[-*]\s+/.test(line)) {
1115
+ const seen = new Set(current.links.map((link) => link.url));
1116
+ for (const link of linksOf(line, options)) if (!seen.has(link.url)) current.links.push(link);
1117
+ }
1118
+ }
1119
+ return items.filter((item) => item.status !== "");
1120
+ }
1121
+ /**
1122
+ * This function gives the items of a roadmap file in the order of the file. It reads two forms:
1123
+ *
1124
+ * - Each row of each table with an `ID` column and a `Status` column. The header names match without
1125
+ * case. The title comes from `Item`, else from `Title`. `Owner`, `Area` and `Needs` are optional.
1126
+ * `Where`, `Commit` and `Links` give the links.
1127
+ * - Each heading "### `id`: Title" or "### id · Title". The list item "Status:", else the "##"
1128
+ * heading above it, gives the status. The list items "Area:", "Owner:" and "Waits for:" give the
1129
+ * optional fields, and "Links:" and the other list items give the links.
1039
1130
  *
1040
- * @remarks The title comes from `Item`, else from `Title`. `Owner`, `Area` and `Needs` are optional.
1041
- * `Where`, `Commit` and `Links` give the links.
1042
1131
  * @throws RoadmapParseError when the cells of a row do not match the header
1043
1132
  */
1044
1133
  function roadmapItems(markdown, options = {}) {
@@ -1081,7 +1170,11 @@ function roadmapItems(markdown, options = {}) {
1081
1170
  items.push(item);
1082
1171
  }
1083
1172
  }
1084
- return items;
1173
+ const headings = headingItems(markdown, {
1174
+ ...options,
1175
+ file
1176
+ });
1177
+ return headings.length === 0 ? items : [...items, ...headings].sort((a, b) => a.line - b.line);
1085
1178
  }
1086
1179
  /** This function puts the roadmap items and the GitHub part into the shape of `status.json`. */
1087
1180
  function buildStatusBoard(input) {
@@ -1108,7 +1201,8 @@ function buildStatusBoard(input) {
1108
1201
  /**
1109
1202
  * This function reads the board of a repository on disk: the roadmap file, and the open work on GitHub.
1110
1203
  *
1111
- * @throws RoadmapParseError when the roadmap has an incorrect row, or no table with an ID and a Status column
1204
+ * @throws RoadmapParseError when the roadmap has an incorrect row, or no item: no table with an ID
1205
+ * and a Status column, and no item heading
1112
1206
  */
1113
1207
  async function readStatusBoard(options) {
1114
1208
  const { repoDir, roadmap = null, owner, repo, token, commit = null } = options;
@@ -1120,7 +1214,7 @@ async function readStatusBoard(options) {
1120
1214
  repository,
1121
1215
  ref: commit ?? "HEAD"
1122
1216
  });
1123
- if (items.length === 0) throw new RoadmapParseError(`${roadmap}: no table with an ID column and a Status column`);
1217
+ if (items.length === 0) throw new RoadmapParseError(`${roadmap}: no table with an ID column and a Status column, and no heading "### \`id\`: Title"`);
1124
1218
  }
1125
1219
  const github = await githubOpenWork({
1126
1220
  owner,
@@ -2264,4 +2358,4 @@ async function runCli(argv, io) {
2264
2358
  //#endregion
2265
2359
  export { GITHUB_API as $, RoadmapParseError as A, DEFAULT_CHANGELOGS as B, longDate as C, inlineMarkdown as D, escapeHtml as E, plainText as F, globFiles as G, mergeReleases as H, readStatusBoard as I, headingDate as J, gitTagDates as K, roadmapItems as L, buildStatusBoard as M, linksOf as N, safeUrl as O, markdownTables as P, npmPublishTimes as Q, splitRow as R, dayRange as S, utcDay as T, readChangelogs as U, ReleaseDataError as V, readReleases as W, originRepository as X, isShallow as Y, NPM_REGISTRY as Z, oldestFirst as _, runCli as a, headingAnchor as at, BASE_CSS as b, openGroups as c, compareVersions as ct, slugOf as d, versionOfTag as dt, GITHUB_GRAPHQL as et, statusLead as f, laneCenter as g, renderReleasesPage as h, parseBuildArgs as i, firstSentence as it, STATUS_CLASSES as j, OPEN_CLASSES as k, renderStatusPage as l, kindOf as lt, releasesLead as m, UsageError as n, githubOpenWork as nt, STATUS_SCRIPT as o, parseChangelog as ot, RELEASES_SCRIPT as p, headCommit as q, build as r, githubReleases as rt, classCounts as s, releaseBodyEntries as st, HELP as t, checkStateOf as tt, sectionsOf as u, parseVersion as ut, releaseSummary as v, shortDate as w, pageShell as x, timelineLayout as y, statusClassOf as z };
2266
2360
 
2267
- //# sourceMappingURL=build-vAps0mRE.js.map
2361
+ //# sourceMappingURL=build-CDw3NHWL.js.map