@mark1russell7/site-pages 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +282 -2
- package/build/build-vAps0mRE.js +2267 -0
- package/build/build-vAps0mRE.js.map +1 -0
- package/build/cli.d.ts +1 -0
- package/build/cli.js +18 -0
- package/build/cli.js.map +1 -0
- package/build/index.d.ts +737 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +1 -0
- package/package.json +59 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mark Russell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,283 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @mark1russell7/site-pages
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This package makes two pages for the site of a GitHub repository: a release timeline and a live status page. A command at deploy time reads the sources. It writes the data as JSON, and it writes two standalone HTML pages into the built site.
|
|
4
|
+
|
|
5
|
+
- **Releases.** A timeline of the versions, with the changes, the commits and the packages of each version.
|
|
6
|
+
- **Status.** The open work of the roadmap file, the open pull requests with the state of their checks, and the open issues.
|
|
7
|
+
|
|
8
|
+
The pages need no framework, no font and no script from another server. A site can also show the JSON with its own components.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pnpm add -D @mark1russell7/site-pages
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## The command
|
|
15
|
+
|
|
16
|
+
Start the command in the root of the repository, after the build of the site:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
site-pages build --out dist --roadmap docs/ROADMAP.md
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The command writes these files into the output folder:
|
|
23
|
+
|
|
24
|
+
| File | Content |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `data/releases.json` | The versions, the newest first |
|
|
27
|
+
| `data/status.json` | The roadmap items, the open pull requests and the open issues |
|
|
28
|
+
| `releases/index.html` | The releases page |
|
|
29
|
+
| `status/index.html` | The status page |
|
|
30
|
+
|
|
31
|
+
The options:
|
|
32
|
+
|
|
33
|
+
| Option | Default | Function |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `--out <dir>` | (necessary) | The built output folder of the site |
|
|
36
|
+
| `--repo <owner/name>` | `$GITHUB_REPOSITORY`, else the remote `origin` | The repository on GitHub |
|
|
37
|
+
| `--base </name/>` | `/<name>/`, or `/` for `<owner>.github.io` | The path of the site home, for the links of the pages |
|
|
38
|
+
| `--roadmap <file>` | none | The roadmap file. Without it, the status page has only the GitHub part. |
|
|
39
|
+
| `--packages <names>` | none | npm names or a scope (`@procedures`), separated by commas, for the npm dates |
|
|
40
|
+
| `--changesets <glob>` | `packages/*/CHANGELOG.md`, else `CHANGELOG.md` | The changelog files |
|
|
41
|
+
| `--group <name>` | none | The npm name of the package whose changelog gives the versions |
|
|
42
|
+
| `--token <token>` | `$GITHUB_TOKEN` | A GitHub token with read access |
|
|
43
|
+
| `--css <file>` | none | More CSS for the pages, after the default CSS |
|
|
44
|
+
| `--site-name <name>` | the name of the repository | The name of the site in the header of the pages |
|
|
45
|
+
| `--data-only` | off | Write only the JSON files, not the pages |
|
|
46
|
+
|
|
47
|
+
The exit code is 0 after a build. It is 1 when a changelog or the roadmap is not correct, and 2 for an incorrect command line.
|
|
48
|
+
|
|
49
|
+
A failure of GitHub or npm does not stop the build. Without a token, or when GitHub does not answer, the command writes a warning. Then the data has no GitHub part, and the status page tells why.
|
|
50
|
+
|
|
51
|
+
Give the token in the environment variable `GITHUB_TOKEN`, not with `--token`. Other processes can see a command line.
|
|
52
|
+
|
|
53
|
+
## The releases
|
|
54
|
+
|
|
55
|
+
The command merges four sources by version:
|
|
56
|
+
|
|
57
|
+
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.
|
|
58
|
+
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.
|
|
59
|
+
3. **The git tags.** The tags `1.2.3`, `v1.2.3` and `name@1.2.3` give the date of a version.
|
|
60
|
+
4. **npm.** The publication time of each version of `--packages` is the last source of a date.
|
|
61
|
+
|
|
62
|
+
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.
|
|
63
|
+
|
|
64
|
+
The pipeline needs the full history for the tags and the commits. Use `fetch-depth: 0` in `actions/checkout`.
|
|
65
|
+
|
|
66
|
+
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.
|
|
67
|
+
|
|
68
|
+
The kind of a version:
|
|
69
|
+
|
|
70
|
+
| Kind | Rule |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `first` | The oldest version |
|
|
73
|
+
| `major` | `X.0.0`, with `X` of 1 or more |
|
|
74
|
+
| `minor` | The PATCH number is 0 |
|
|
75
|
+
| `patch` | All other versions |
|
|
76
|
+
|
|
77
|
+
## The status
|
|
78
|
+
|
|
79
|
+
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
|
+
|
|
81
|
+
| Column | Use |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `ID` | The ID of the item. A row without an ID is not an item. |
|
|
84
|
+
| `Status` | Free text. Its first keyword gives the class of the item. |
|
|
85
|
+
| `Item` or `Title` | The text of the item |
|
|
86
|
+
| `Owner`, `Area`, `Needs` | Optional fields |
|
|
87
|
+
| `Where`, `Commit`, `Links`, `PR` | The links: Markdown links, `#12`, `PR #12` and commit hashes in code spans |
|
|
88
|
+
|
|
89
|
+
The classes, in the sequence of the page:
|
|
90
|
+
|
|
91
|
+
| Class | Keywords |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `waiting` | waiting, waits, awaiting, needs |
|
|
94
|
+
| `blocked` | blocked |
|
|
95
|
+
| `progress` | in progress, active, ongoing, started, wip |
|
|
96
|
+
| `open` | not started, to do, and a status without a keyword |
|
|
97
|
+
| `later` | later, deferred, postponed, someday |
|
|
98
|
+
| `done` | done, shipped, merged, fixed, released, complete, closed |
|
|
99
|
+
|
|
100
|
+
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
|
+
|
|
102
|
+
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
|
+
|
|
104
|
+
## The data shapes
|
|
105
|
+
|
|
106
|
+
`data/releases.json` holds an array of `Release`, the newest version first:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
interface Release {
|
|
110
|
+
version: string;
|
|
111
|
+
date: string; // ISO 8601
|
|
112
|
+
kind: "first" | "major" | "minor" | "patch";
|
|
113
|
+
changes: Array<{ commit: string | null; text: string; packages: string[] }>; // text is inline Markdown
|
|
114
|
+
links: Array<{ label: string; url: string }>; // the GitHub release or the tag, the changelog section, npm
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`data/status.json` holds one `StatusBoardData`:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
interface StatusBoardData {
|
|
122
|
+
generatedAt: string; // ISO 8601
|
|
123
|
+
commit: string | null;
|
|
124
|
+
source: { roadmap: string | null; github: string }; // github is "owner/name"
|
|
125
|
+
items: Array<{
|
|
126
|
+
id: string;
|
|
127
|
+
title: string;
|
|
128
|
+
status: string;
|
|
129
|
+
statusClass: "waiting" | "blocked" | "progress" | "open" | "later" | "done";
|
|
130
|
+
owner?: string;
|
|
131
|
+
area?: string;
|
|
132
|
+
needs?: string;
|
|
133
|
+
section: string;
|
|
134
|
+
line: number;
|
|
135
|
+
links: Array<{ label: string; url: string }>;
|
|
136
|
+
}>;
|
|
137
|
+
pullRequests: Array<{
|
|
138
|
+
number: number;
|
|
139
|
+
title: string;
|
|
140
|
+
url: string;
|
|
141
|
+
author: string;
|
|
142
|
+
branch: string;
|
|
143
|
+
draft: boolean;
|
|
144
|
+
createdAt: string;
|
|
145
|
+
updatedAt: string;
|
|
146
|
+
labels: string[];
|
|
147
|
+
checks: "success" | "failure" | "pending" | "none";
|
|
148
|
+
}>;
|
|
149
|
+
issues: Array<{ number: number; title: string; url: string; author: string; createdAt: string; updatedAt: string; labels: string[] }>;
|
|
150
|
+
github: { available: boolean; reason?: string; totals?: { pullRequests: number; issues: number } };
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The package exports these types: `Release`, `ReleaseChange`, `StatusBoardData`, `BoardItem`, `BoardPullRequest` and `BoardIssue`.
|
|
155
|
+
|
|
156
|
+
## A site with its own components
|
|
157
|
+
|
|
158
|
+
A site can show the data with its own components, and keep its own pages:
|
|
159
|
+
|
|
160
|
+
- Start `site-pages build --data-only`. The command then writes only the JSON files.
|
|
161
|
+
- Read `<base>data/releases.json` and `<base>data/status.json` in the browser, or read the files in the build of the site.
|
|
162
|
+
- Import the types from the package: `import type { Release, StatusBoardData } from "@mark1russell7/site-pages"`.
|
|
163
|
+
|
|
164
|
+
The functions of the command are also in the package:
|
|
165
|
+
|
|
166
|
+
| Function | Result |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| `readReleases(options)` | The releases of a repository on disk, with GitHub and npm |
|
|
169
|
+
| `mergeReleases(sources)` | The releases from sources that the caller reads |
|
|
170
|
+
| `readStatusBoard(options)` | The status data of a repository on disk, with GitHub |
|
|
171
|
+
| `githubReleases`, `githubOpenWork`, `npmPublishTimes` | The data of one source. After an error, each function gives `{ available: false, reason }`. It does not throw. |
|
|
172
|
+
| `renderReleasesPage(releases, options)`, `renderStatusPage(data, options)` | The HTML of a page |
|
|
173
|
+
| `timelineLayout(releases, { width })` | The positions of the marks of the timeline |
|
|
174
|
+
|
|
175
|
+
## The look of the pages
|
|
176
|
+
|
|
177
|
+
The pages have the light and the dark colors. They obey `prefers-color-scheme`. A `data-theme="light"` or `data-theme="dark"` attribute on the `html` element has priority.
|
|
178
|
+
|
|
179
|
+
The CSS uses variables. To change them, give a CSS file with `--css`:
|
|
180
|
+
|
|
181
|
+
```css
|
|
182
|
+
:root {
|
|
183
|
+
--sp-accent: #b4232a;
|
|
184
|
+
--sp-font: "Inter", system-ui, sans-serif;
|
|
185
|
+
}
|
|
186
|
+
:root[data-theme="dark"] {
|
|
187
|
+
--sp-accent: #ff8a80;
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The variables are `--sp-bg`, `--sp-surface`, `--sp-sunken`, `--sp-fg`, `--sp-fg-2`, `--sp-muted`, `--sp-rule`, `--sp-rule-strong`, `--sp-accent`, `--sp-accent-strong` and `--sp-accent-wash`. The status colors are `--sp-good`, `--sp-warn`, `--sp-bad` and `--sp-neutral`, with `-ink` variants for text. `--sp-font`, `--sp-mono`, `--sp-radius` and `--sp-width` set the fonts and the layout.
|
|
192
|
+
|
|
193
|
+
The pages operate at a width of 390 px without horizontal scroll. The timeline scrolls in its own box. The keyboard operates all controls: the arrow keys, Home and End move between the versions, and Enter or Space selects one. Without JavaScript, the releases page shows all versions.
|
|
194
|
+
|
|
195
|
+
## A GitHub Pages workflow
|
|
196
|
+
|
|
197
|
+
This workflow builds the site, adds the two pages, and deploys. It also starts every 3 hours, so the status page stays current without a push. A scheduled run builds the newest commit of `main` that passed CI.
|
|
198
|
+
|
|
199
|
+
```yaml
|
|
200
|
+
name: Pages
|
|
201
|
+
|
|
202
|
+
on:
|
|
203
|
+
workflow_run:
|
|
204
|
+
workflows: [CI]
|
|
205
|
+
types: [completed]
|
|
206
|
+
branches: [main]
|
|
207
|
+
schedule:
|
|
208
|
+
- cron: "17 */3 * * *"
|
|
209
|
+
workflow_dispatch:
|
|
210
|
+
|
|
211
|
+
permissions:
|
|
212
|
+
contents: read
|
|
213
|
+
|
|
214
|
+
concurrency:
|
|
215
|
+
group: pages
|
|
216
|
+
cancel-in-progress: false
|
|
217
|
+
|
|
218
|
+
jobs:
|
|
219
|
+
build:
|
|
220
|
+
if: >-
|
|
221
|
+
github.event_name != 'workflow_run' ||
|
|
222
|
+
(github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push')
|
|
223
|
+
runs-on: ubuntu-latest
|
|
224
|
+
# Read access only: the status page reads the pull requests, the issues and their checks.
|
|
225
|
+
# A scheduled run reads the runs of CI to find the newest commit that passed.
|
|
226
|
+
permissions:
|
|
227
|
+
contents: read
|
|
228
|
+
issues: read
|
|
229
|
+
pull-requests: read
|
|
230
|
+
checks: read
|
|
231
|
+
statuses: read
|
|
232
|
+
actions: read
|
|
233
|
+
steps:
|
|
234
|
+
- name: Select the commit
|
|
235
|
+
id: commit
|
|
236
|
+
env:
|
|
237
|
+
GH_TOKEN: ${{ github.token }}
|
|
238
|
+
EVENT: ${{ github.event_name }}
|
|
239
|
+
RUN_SHA: ${{ github.event.workflow_run.head_sha }}
|
|
240
|
+
run: |
|
|
241
|
+
if [ "$EVENT" = "schedule" ]; then
|
|
242
|
+
sha=$(gh api "repos/$GITHUB_REPOSITORY/actions/workflows/ci.yml/runs?branch=main&event=push&status=success&per_page=1" --jq '.workflow_runs[0].head_sha // empty')
|
|
243
|
+
else
|
|
244
|
+
sha="${RUN_SHA:-$GITHUB_SHA}"
|
|
245
|
+
fi
|
|
246
|
+
if [ -z "$sha" ]; then echo "::error::No commit of main passed CI."; exit 1; fi
|
|
247
|
+
echo "sha=$sha" >> "$GITHUB_OUTPUT"
|
|
248
|
+
- uses: actions/checkout@v7
|
|
249
|
+
with:
|
|
250
|
+
ref: ${{ steps.commit.outputs.sha }}
|
|
251
|
+
fetch-depth: 0 # the tags and the history give the release dates
|
|
252
|
+
persist-credentials: false
|
|
253
|
+
- uses: pnpm/action-setup@v6
|
|
254
|
+
- uses: actions/setup-node@v7
|
|
255
|
+
with:
|
|
256
|
+
node-version: 24
|
|
257
|
+
cache: pnpm
|
|
258
|
+
- run: pnpm install --frozen-lockfile
|
|
259
|
+
- run: pnpm build # the build of the site, into dist/
|
|
260
|
+
- run: pnpm exec site-pages build --out dist --roadmap docs/ROADMAP.md
|
|
261
|
+
env:
|
|
262
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
263
|
+
- uses: actions/upload-pages-artifact@v5
|
|
264
|
+
with:
|
|
265
|
+
path: dist
|
|
266
|
+
|
|
267
|
+
deploy:
|
|
268
|
+
needs: build
|
|
269
|
+
runs-on: ubuntu-latest
|
|
270
|
+
permissions:
|
|
271
|
+
pages: write
|
|
272
|
+
id-token: write
|
|
273
|
+
environment:
|
|
274
|
+
name: github-pages
|
|
275
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
276
|
+
steps:
|
|
277
|
+
- id: deployment
|
|
278
|
+
uses: actions/deploy-pages@v5
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The token of the build job has read access only. The status page needs `contents`, `issues` and `pull-requests`. The check states need `checks` and `statuses`. The scheduled run needs `actions` to find the commit. Only the deploy job can write to Pages.
|
|
282
|
+
|
|
283
|
+
The package operates in Node.js 22 or later. The license is MIT.
|