ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
markdown_link_lex.py
Go to the documentation of this file.
1# SPDX-License-Identifier: MIT
2# Copyright (c) 2026 Brighton Sikarskie
3"""Structural Markdown inline-link parsing without hiding malformed prose."""
4
5from __future__ import annotations
6
7
8def split_link_destination(raw: str) -> str:
9 """Discard a Markdown link title while retaining an angle-wrapped target."""
10 raw = raw.strip()
11 if not raw:
12 return ""
13 if raw.startswith("<") and ">" in raw:
14 return raw[1 : raw.index(">")]
15 depth = 0
16 for index, char in enumerate(raw):
17 if char == "(":
18 depth += 1
19 elif char == ")" and depth:
20 depth -= 1
21 elif char.isspace() and depth == 0:
22 return raw[:index]
23 return raw
24
25
26def _balanced_target_end(line: str, start: int) -> int | None:
27 """Return the closing parenthesis for one proven-balanced destination."""
28 index = start
29 depth = 1
30 angle = False
31 escaped = False
32 while index < len(line):
33 char = line[index]
34 if escaped:
35 escaped = False
36 elif char == "\\":
37 escaped = True
38 elif char == "<" and depth == 1:
39 angle = True
40 elif char == ">" and angle:
41 angle = False
42 elif not angle and char == "(":
43 depth += 1
44 elif not angle and char == ")":
45 depth -= 1
46 if depth == 0:
47 return index
48 index += 1
49 return None
50
51
52def inline_link_targets(line: str) -> list[str]:
53 """Parse ``](destination)`` pairs with balanced parentheses."""
54 targets: list[str] = []
55 cursor = 0
56 while True:
57 opener = line.find("](", cursor)
58 if opener < 0:
59 break
60 start = opener + 2
61 end = _balanced_target_end(line, start)
62 if end is not None:
63 targets.append(split_link_destination(line[start:end]))
64 cursor = end + 1 if end is not None else start
65 return targets
66
67
68def mask_inline_link_targets(line: str) -> str:
69 """Blank balanced inline-link destinations before prose path scanning."""
70 masked = list(line)
71 cursor = 0
72 while True:
73 opener = line.find("](", cursor)
74 if opener < 0:
75 break
76 start = opener + 2
77 end = _balanced_target_end(line, start)
78 if end is not None:
79 masked[start:end] = " " * (end - start)
80 cursor = end + 1 if end is not None else start
81 return "".join(masked)