"""What's new for the Update badge (app 0.2.73): 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 `## (firmware )` section gives its bullet lines as plain text, newest first. """ import logging import re from pathlib import Path LOG = logging.getLogger('screen_manager') HEADER = re.compile(r'^## (\d+\.\d+\.\d+) \(firmware (\d+\.\d+\.\d+)\)') # A heading of level one or two ends a section; a `### ` inside one doesn't. SECTION_END = re.compile(r'^#{1,2}(\s|$)') BULLET = re.compile(r'^[-*+]\s+(.*)$') BOLD = re.compile(r'\*\*(.+?)\*\*') # *Full page*: single asterisks around text. A lone asterisk (5 * 3) or one inside a word stays (app 0.2.78). ITALIC = re.compile(r'(?= limit: return sections current = {'app': match.group(1), 'firmware': match.group(2), 'lines': []} if match else None if current: sections.append(current) elif (bullet := BULLET.match(line)) and current is not None: close() item = [bullet.group(1).strip()] elif stripped and item is not None and (line[:1].isspace() or not blank) and not line.startswith('#'): # Markdown continues a bullet with an indented line, or with any line right under it. item.append(stripped) elif stripped: close() item = None blank = not stripped close() return sections def plain(markdown): """The text of one bullet without Markdown: bold, italics and links outside code, and the code's backticks.""" parts = CODE.split(markdown) for index in range(0, len(parts), 2): parts[index] = LINK.sub(r'\1', ITALIC.sub(r'\1', BOLD.sub(r'\1', parts[index]))) return ''.join(parts).strip()