Skip to content

Commit 92aaa2d

Browse files
Replace root redirect with spec listing index page and build issues lists
Instead of redirecting to drafts.csswg.org, build-index.py now generates a proper index page listing all specs with their titles, last-update dates, and links to Disposition of Comments documents. Multi-level spec families are visually grouped under a shortname header. Also adds a workflow step that runs bikeshed issues-list on all .bsi and issues-*.txt source files, regenerating the Disposition of Comments HTML pages during deployment. Relates to #12054
1 parent 8700981 commit 92aaa2d

2 files changed

Lines changed: 142 additions & 10 deletions

File tree

.github/workflows/build-specs.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ jobs:
5757
SHORT_DATE="$(date --date=@"$TIMESTAMP" --utc +%F)"
5858
bikeshed -f spec "$file" "${file%Overview.bs}index.html" --md-date="$SHORT_DATE" --md-Text-Macro="BUILTBYGITHUBCI foo"
5959
done
60+
- name: Build issues lists
61+
run: |
62+
for file in ./**/*.bsi ./**/issues-*.txt; do
63+
echo " $file"
64+
bikeshed issues-list "$file" || true
65+
done
6066
- name: Build index & symlinks
6167
run: python ./bin/build-index.py
6268
- run: rm -rf ./.git{,attributes,ignore}

bin/build-index.py

Lines changed: 136 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22
All the drafts are built by the build-specs workflow itself.
33
This handles the rest of the work:
44
5-
* creates a root page that just redirects to the draft server root listing.
5+
* creates an index page listing all specs
66
* creates symlinks for unlevelled urls, linking to the appropriate levelled folder
7-
* builds timestamps.json, which provides a bunch of metadata about the specs which is consumed by some W3C tooling.
7+
* builds timestamps.json, which provides metadata about the specs
88
"""
99

10+
import glob
1011
import json
1112
import os
1213
import os.path
1314
import re
14-
import sys
1515
import subprocess
1616
from collections import defaultdict
17+
from datetime import datetime, timezone
1718

1819
import bikeshed
1920
from html.parser import HTMLParser
@@ -122,6 +123,21 @@ def create_symlink(shortname, spec_folder):
122123
pass
123124

124125

126+
def format_timestamp(ts):
127+
"""Format a Unix timestamp as a human-readable date string."""
128+
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
129+
return dt.strftime("%Y-%m-%d")
130+
131+
132+
def escape_html(text):
133+
"""Escape HTML special characters."""
134+
return (text
135+
.replace("&", "&")
136+
.replace("<", "&lt;")
137+
.replace(">", "&gt;")
138+
.replace('"', "&quot;"))
139+
140+
125141
CURRENT_WORK_EXCEPTIONS = {
126142
"css-conditional": 5,
127143
"css-easing": 2,
@@ -159,6 +175,9 @@ def create_symlink(shortname, spec_folder):
159175

160176
metadata["dir"] = entry.name
161177
metadata["currentWork"] = False
178+
issues_files = sorted(f for f in glob.glob(os.path.join(entry.path, "issues-*.html"))
179+
if not f.endswith(".bsi.html"))
180+
metadata["issues"] = [os.path.basename(f) for f in issues_files]
162181
specgroups[metadata["shortname"]].append(metadata)
163182

164183
# Reorder the specs with common shortname based on their level (or year, for
@@ -195,13 +214,120 @@ def create_symlink(shortname, spec_folder):
195214
with open('./timestamps.json', 'w') as f:
196215
json.dump(timestamps, f, indent = 2, sort_keys=True)
197216

217+
# Build the index page
218+
rows = []
219+
for shortname in sorted(specgroups.keys()):
220+
specgroup = specgroups[shortname]
221+
is_group = len(specgroup) > 1
222+
223+
if is_group:
224+
rows.append(
225+
f' <tr class="group-header">\n'
226+
f' <td colspan="2">{escape_html(shortname)}</td>\n'
227+
f' </tr>'
228+
)
229+
230+
for spec in specgroup:
231+
title = escape_html(spec["title"] or spec["dir"])
232+
current_label = ' <span class="current-work">(Current Work)</span>' if spec["currentWork"] else ""
233+
dir_name = spec["dir"]
234+
235+
ts = timestamps.get(dir_name)
236+
date_str = format_timestamp(ts) if ts else ""
237+
238+
issues_html = ""
239+
if spec["issues"]:
240+
links = []
241+
for fname in spec["issues"]:
242+
label = fname.replace("issues-", "").replace(".html", "")
243+
links.append(f'<a href="./{dir_name}/{fname}">{label}</a>')
244+
issues_html = '<br><span class="issues">DoC: ' + " \u00b7 ".join(links) + '</span>'
245+
246+
indent_class = ' class="grouped-spec"' if is_group else ""
247+
rows.append(
248+
f' <tr{indent_class}>\n'
249+
f' <td><a href="./{dir_name}/">{title}</a>{current_label}{issues_html}</td>\n'
250+
f' <td>{date_str}</td>\n'
251+
f' </tr>'
252+
)
253+
254+
rows_html = "\n".join(rows)
255+
198256
with open("./index.html", mode='w', encoding="UTF-8") as f:
199-
f.write("""
257+
f.write(f"""\
200258
<!doctype html>
201-
<meta charset=utf-8>
202-
<title>Redirecting to the Drafts listing...</title>
203-
<meta http-equiv=Refresh content="0; url='https://drafts.csswg.org'">
204-
<script>
205-
window.location.href = "https://drafts.csswg.org";
206-
</script>
259+
<html lang="en">
260+
<head>
261+
<meta charset="utf-8">
262+
<title>CSS Working Group Editor Drafts</title>
263+
<style>
264+
body {{
265+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
266+
max-width: 900px;
267+
margin: 2em auto;
268+
padding: 0 1em;
269+
color: #333;
270+
}}
271+
h1 {{
272+
border-bottom: 1px solid #ccc;
273+
padding-bottom: 0.3em;
274+
}}
275+
table {{
276+
width: 100%;
277+
border-collapse: collapse;
278+
margin-top: 1em;
279+
}}
280+
th, td {{
281+
text-align: left;
282+
padding: 0.5em 0.75em;
283+
border-bottom: 1px solid #eee;
284+
}}
285+
th {{
286+
border-bottom: 2px solid #ccc;
287+
font-weight: 600;
288+
}}
289+
td:last-child {{
290+
white-space: nowrap;
291+
color: #666;
292+
}}
293+
a {{
294+
color: #0366d6;
295+
text-decoration: none;
296+
}}
297+
a:hover {{
298+
text-decoration: underline;
299+
}}
300+
.current-work {{
301+
color: #080;
302+
font-size: 0.9em;
303+
}}
304+
.group-header td {{
305+
font-weight: 600;
306+
padding-top: 1em;
307+
border-bottom: 1px solid #ccc;
308+
}}
309+
.grouped-spec td:first-child {{
310+
padding-left: 2em;
311+
}}
312+
.issues {{
313+
font-size: 0.85em;
314+
color: #666;
315+
}}
316+
</style>
317+
</head>
318+
<body>
319+
<h1>CSS Working Group Editor Drafts</h1>
320+
<table>
321+
<thead>
322+
<tr>
323+
<th>Specification</th>
324+
<th>Last Update</th>
325+
</tr>
326+
</thead>
327+
<tbody>
328+
{rows_html}
329+
</tbody>
330+
</table>
331+
</body>
332+
</html>
207333
""")

0 commit comments

Comments
 (0)