Skip to content

Commit 38dd459

Browse files
committed
improved gen_numbering and action
Signed-off-by: René <snooz@posteo.de>
1 parent f6204e8 commit 38dd459

3 files changed

Lines changed: 90 additions & 31 deletions

File tree

.github/workflows/pr-preview-surge.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ jobs:
4444
with:
4545
fetch-depth: 0
4646

47+
- name: Set up Python
48+
uses: actions/setup-python@v5
49+
with:
50+
python-version: '3.11'
51+
52+
- name: Check numbering and links
53+
run: python tools/gen_numbering.py
54+
working-directory: .
55+
4756
- name: Use Node.js
4857
uses: actions/setup-node@v4
4958
with:

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ __pycache__
44
results
55

66
.vscode
7-
.devcontainer
7+
.devcontainer
8+
.venv

tools/gen_numbering.py

Lines changed: 79 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,34 @@
11
import csv
2-
from pathlib import Path
2+
import difflib
3+
import io
34
import re
5+
import sys
6+
from pathlib import Path
7+
8+
9+
def write_if_changed(path: Path, content: str, *, original_content=None, encoding: str = "utf-8", label: str | None = None) -> bool:
10+
if original_content is None:
11+
if path.exists():
12+
original_content = path.read_text(encoding=encoding)
13+
else:
14+
original_content = ""
15+
old_content = original_content
16+
if old_content == content:
17+
return False
18+
display_label = str(label or path)
19+
old_lines = old_content.splitlines(keepends=True)
20+
new_lines = content.splitlines(keepends=True)
21+
diff = difflib.unified_diff(
22+
old_lines,
23+
new_lines,
24+
fromfile=f"a/{display_label}",
25+
tofile=f"b/{display_label}",
26+
)
27+
diff_output = "".join(diff)
28+
if diff_output:
29+
print(diff_output, end="" if diff_output.endswith("\n") else "\n")
30+
path.write_text(content, encoding=encoding)
31+
return True
432

533

634
def update_heading_numbers_and_generate_toc(directory: Path):
@@ -15,6 +43,13 @@ def update_heading_numbers_and_generate_toc(directory: Path):
1543
all_learning_objectives = []
1644
Path().as_posix()
1745
chapters = {}
46+
modified_paths = set()
47+
48+
def rel_label(path: Path) -> str:
49+
try:
50+
return str(path.relative_to(directory))
51+
except ValueError:
52+
return str(path)
1853

1954
for file in sorted(directory.glob("website/docs/**/*.md")):
2055
file_path = file.relative_to(Path('website/docs').resolve())
@@ -144,30 +179,39 @@ def update_heading_numbers_and_generate_toc(directory: Path):
144179
print(f"Duplicate anchor '{heading_anchor}' in '{file_path}' and '{heading_catalog[heading_anchor][0]}'")
145180
heading_catalog[heading_anchor] = (file_path, *heading)
146181

147-
with file.open("w", encoding="utf-8") as md_file:
148-
md_file.writelines(updated_lines)
182+
original_content = "".join(lines)
183+
updated_content = "".join(updated_lines)
184+
if write_if_changed(file, updated_content, original_content=original_content, label=rel_label(file)):
185+
modified_paths.add(file.resolve())
149186

150187
all_learning_objectives.extend(learning_objectives)
151188

152189
sorted_lo = sorted(all_learning_objectives, key=lambda x: x[0])
153190

154-
with (directory / "LOs.csv").open("w", encoding="utf-8") as csv_file:
155-
writer = csv.writer(csv_file)
156-
writer.writerow(["LO ID", "K Level", "Content", "Slide Number", "Done", "Notes"])
157-
writer.writerows([(f"LO-{lo_id}", f"({k_level})", lo_content, "", "", "") for lo_id, k_level, lo_content in sorted_lo])
191+
lo_csv_buffer = io.StringIO()
192+
writer = csv.writer(lo_csv_buffer)
193+
writer.writerow(["LO ID", "K Level", "Content", "Slide Number", "Done", "Notes"])
194+
writer.writerows([(f"LO-{lo_id}", f"({k_level})", lo_content, "", "", "") for lo_id, k_level, lo_content in sorted_lo])
195+
lo_csv_content = lo_csv_buffer.getvalue().replace("\r\n", "\n")
196+
lo_csv_buffer.close()
197+
lo_csv_path = directory / "LOs.csv"
198+
if write_if_changed(lo_csv_path, lo_csv_content, label=rel_label(lo_csv_path)):
199+
modified_paths.add(lo_csv_path.resolve())
158200

159201
print(f"Total LOs: {len(sorted_lo)}")
160202
toc_entries.sort(key=lambda x: x[0])
161203

162204
readme_path = directory / "README.md"
163-
with readme_path.open("w", encoding="utf-8") as readme_file:
164-
readme_file.write("# Table of Contents\n\n")
165-
for _, toc_entry in toc_entries:
166-
toc_entry = toc_entry.replace("`](", "`](website/docs/")
167-
readme_file.write(toc_entry + "\n")
205+
readme_lines = ["# Table of Contents\n\n"]
206+
for _, toc_entry in toc_entries:
207+
toc_entry = toc_entry.replace("`](", "`](website/docs/")
208+
readme_lines.append(toc_entry + "\n")
209+
readme_content = "".join(readme_lines)
210+
if write_if_changed(readme_path, readme_content, label=rel_label(readme_path)):
211+
modified_paths.add(readme_path.resolve())
168212

169213
for file in sorted(directory.glob("website/docs/**/*.md")):
170-
file_path = file.relative_to(Path('website/docs').resolve())
214+
docs_path = file.relative_to(Path('website/docs').resolve())
171215
match = chapter_file_pattern.fullmatch(file.as_posix())
172216
if not match:
173217
continue
@@ -178,7 +222,7 @@ def update_heading_numbers_and_generate_toc(directory: Path):
178222
for lineno, line in enumerate(lines):
179223
def replace_link(match):
180224
description, link_file, anchor_name = match.groups()
181-
link_file = link_file or file_path
225+
link_file = link_file or docs_path
182226
if anchor_name in heading_catalog:
183227
file_path, numbering, title, anchor = heading_catalog[anchor_name]
184228
if title.strip() == anchor_name.strip() or anchor.endswith(anchor_name):
@@ -193,24 +237,29 @@ def replace_link(match):
193237
updated_line = re.sub(internal_link_pattern, replace_link, line)
194238
updated_lines.append(updated_line)
195239

196-
with file.open("w", encoding="utf-8") as md_file:
197-
md_file.writelines(updated_lines)
240+
original_content = "".join(lines)
241+
updated_content = "".join(updated_lines)
242+
if write_if_changed(file, updated_content, original_content=original_content, label=rel_label(file)):
243+
modified_paths.add(file.resolve())
198244

199-
with Path("website", "docs", "learning_objectives.md").open("w", encoding="utf-8") as lo_file:
200-
anchor = {}
201-
for k, v in heading_catalog.items():
202-
numbering = v[1]
203-
if len(numbering) <= 3:
204-
anchor[v[1]] = str(v[0])
205-
else:
206-
anchor[v[1]] = f'{v[0]}#{v[-1]}'
207-
lo_file.write("# Learning Objectives\n")
208-
lo_file.write(f'| ID | K-Level | Content |\n')
209-
lo_file.write(f'| --- | --- | --- |\n')
210-
for lo_id, k_level, lo_content in sorted_lo:
211-
lo_file.write(f'| [`LO-{lo_id}`]({anchor.get(lo_id.split("-")[0])}) | {k_level} | {lo_content.replace('|', '\\|')} |\n')
245+
learning_objectives_path = directory / "website" / "docs" / "learning_objectives.md"
246+
anchor = {}
247+
for k, v in heading_catalog.items():
248+
numbering = v[1]
249+
if len(numbering) <= 3:
250+
anchor[v[1]] = str(v[0])
251+
else:
252+
anchor[v[1]] = f'{v[0]}#{v[-1]}'
253+
lo_md_lines = ["# Learning Objectives\n", '| ID | K-Level | Content |\n', '| --- | --- | --- |\n']
254+
for lo_id, k_level, lo_content in sorted_lo:
255+
lo_md_lines.append(f'| [`LO-{lo_id}`]({anchor.get(lo_id.split("-")[0])}) | {k_level} | {lo_content.replace("|", "\\|")} |\n')
256+
lo_md_content = "".join(lo_md_lines)
257+
if write_if_changed(learning_objectives_path, lo_md_content, label=rel_label(learning_objectives_path)):
258+
modified_paths.add(learning_objectives_path.resolve())
212259

260+
return len(modified_paths)
213261

214262

215263
if __name__ == "__main__":
216-
update_heading_numbers_and_generate_toc(Path.cwd())
264+
fix_count = update_heading_numbers_and_generate_toc(Path.cwd())
265+
sys.exit(1 if fix_count > 0 else 0)

0 commit comments

Comments
 (0)