Faithful port of TS ``parseChangelog`` (releaseNotes.ts:316-358): split on ``^## `` headings (the first chunk — the preamble — is skipped), key each section by the normalized version from its heading line, collect only ``- ``/``* `` bullet lines (``###``/``####`` sub-headers are ignored)
(content: str)
| 40 | |
| 41 | |
| 42 | def parse_changelog(content: str) -> dict[str, list[str]]: |
| 43 | """Faithful port of TS ``parseChangelog`` (releaseNotes.ts:316-358): split on |
| 44 | ``^## `` headings (the first chunk — the preamble — is skipped), key each section by |
| 45 | the normalized version from its heading line, collect only ``- ``/``* `` bullet |
| 46 | lines (``###``/``####`` sub-headers are ignored), and keep sections with ≥1 bullet.""" |
| 47 | if not content: |
| 48 | return {} |
| 49 | release_notes: dict[str, list[str]] = {} |
| 50 | sections = re.split(r"^## ", content, flags=re.MULTILINE)[1:] |
| 51 | for section in sections: |
| 52 | lines = section.strip().split("\n") |
| 53 | if not lines: |
| 54 | continue |
| 55 | version_line = lines[0] |
| 56 | if not version_line: |
| 57 | continue |
| 58 | version = normalize_public_version(version_line) |
| 59 | if not version: |
| 60 | continue |
| 61 | notes = [] |
| 62 | for line in lines[1:]: |
| 63 | t = line.strip() |
| 64 | if t.startswith("- ") or t.startswith("* "): |
| 65 | note = t[2:].strip() |
| 66 | if note: |
| 67 | notes.append(note) |
| 68 | if notes: |
| 69 | release_notes[version] = notes |
| 70 | return release_notes |
| 71 | |
| 72 | |
| 73 | def get_release_notes_for_version(version: str, content: str) -> list[str]: |