Files
homeassistant_espscreen/screen_manager/app/changelog.py
T
Max Gramser 6148dfd211 Show live values on the mockup, blink a screen to identify it, try an alert, copy and share layouts (0.2.74)
The tiles draw what Home Assistant reports (a new /api/states answers for the tiles on the page); the ···
menu gets Identify (the screen's own show_alert with flash), Copy layout from another screen, Export and
Import as JSON; the Alerts page opens with Try it (/api/alerts/test, one screen or all); the library filters
by room and hides what is placed, with lit icons for what is on; ⌘K searches screens, entities and actions;
the Update badge lists what's new from the changelog (copied into the image) and a running update shows a
progress bar with the ESPHome stage and the last log line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:30:38 +02:00

42 lines
1.4 KiB
Python

"""What's new for the Update badge (app 0.2.74): the CHANGELOG sections since a screen's firmware.
The Dockerfile copies CHANGELOG.md next to this file; a development checkout has it one folder up.
Each `## <app> (firmware <fw>)` section gives its bullet lines as plain text, newest first.
"""
import re
from pathlib import Path
HEADER = re.compile(r'^## (\d+\.\d+\.\d+) \(firmware (\d+\.\d+\.\d+)\)')
BOLD = re.compile(r'\*\*(.+?)\*\*')
CODE = re.compile(r'`([^`]*)`')
LINK = re.compile(r'\[([^\]]+)\]\([^)]+\)')
def load(path=None, limit=20):
"""[{app, firmware, lines}] for the latest sections; [] without a changelog."""
candidates = [Path(path)] if path else [Path(__file__).with_name('CHANGELOG.md'), Path(__file__).parent.parent / 'CHANGELOG.md']
for candidate in candidates:
if candidate.exists():
return parse(candidate.read_text(), limit)
return []
def parse(text, limit=20):
sections = []
for line in text.splitlines():
match = HEADER.match(line)
if match:
if len(sections) >= limit:
break
sections.append({'app': match.group(1), 'firmware': match.group(2), 'lines': []})
elif sections and line.startswith('- '):
sections[-1]['lines'].append(plain(line[2:]))
return sections
def plain(markdown):
text = BOLD.sub(r'\1', markdown)
text = CODE.sub(r'\1', text)
text = LINK.sub(r'\1', text)
return text.strip()