129 lines
4.3 KiB
Python
129 lines
4.3 KiB
Python
"""
|
|
Module: markdown_parser.py
|
|
----------------------------
|
|
Rozšířený Markdown parser pro curses.
|
|
|
|
Podporované funkce:
|
|
1. Nadpisy (řádky začínající #) -> zobrazeny tučně a podtrženě
|
|
2. Odrážky (řádky začínající - a *) -> zobrazeny s tučným textem a symbolickou tečkou
|
|
3. Víceřádkové bloky kódu (```):
|
|
vše mezi trojitými backticky je zobrazeno s curses.A_REVERSE
|
|
4. Inline formátování:
|
|
**text** -> curses.A_BOLD
|
|
*text* -> curses.A_UNDERLINE
|
|
`text` -> curses.A_REVERSE
|
|
|
|
Poznámka: nepodporujeme vnořené značky, a parser je pouze zjednodušený.
|
|
"""
|
|
|
|
import re
|
|
import curses
|
|
|
|
def parse_markdown(text):
|
|
"""
|
|
Hlavní funkce pro rozparsování zadaného textu na seznam (segment_text, attribute).
|
|
Respektuje víceřádkové bloky kódu (```), nadpisy, odrážky a volá parse_inline pro
|
|
zpracování běžných řádků.
|
|
"""
|
|
segments = []
|
|
lines = text.splitlines()
|
|
in_code_block = False # Indikátor, zda se nacházíme uvnitř bloku ```.
|
|
|
|
for line in lines:
|
|
stripped = line.strip()
|
|
|
|
# Kontrola začátku/konce bloku kódu (```).
|
|
if stripped.startswith("```"):
|
|
# Přepínáme stav
|
|
in_code_block = not in_code_block
|
|
if in_code_block:
|
|
# Řádek obsahující samotné ```
|
|
# Pokud tam je něco navíc, ořežeme
|
|
code_block_marker = stripped[3:].strip()
|
|
# Můžeme sem zařadit logiku pro detekci jazyka, pokud by to bylo potřeba
|
|
else:
|
|
# Konec bloku kódu
|
|
pass
|
|
continue
|
|
|
|
if in_code_block:
|
|
# Ve víceřádkovém kódu každou linku zobrazíme s curses.A_REVERSE
|
|
segments.append((line + "\n", curses.A_REVERSE))
|
|
continue
|
|
|
|
# Pokud nejsme v bloku kódu, zpracujeme nadpisy, odrážky a inline formát.
|
|
if stripped.startswith("#"):
|
|
# Nadpis: zjistíme, kolik # tam je
|
|
hash_count = 0
|
|
for ch in line:
|
|
if ch == '#':
|
|
hash_count += 1
|
|
else:
|
|
break
|
|
# Obsah nadpisu za #...
|
|
content = line[hash_count:].strip()
|
|
# Atribut: tučný a podtržený
|
|
segments.append((content + "\n", curses.A_BOLD | curses.A_UNDERLINE))
|
|
elif stripped.startswith("-") or stripped.startswith("*"):
|
|
# Odrážka
|
|
content = line[1:].strip()
|
|
segments.append((" • " + content + "\n", curses.A_BOLD))
|
|
else:
|
|
# Běžný řádek -> inline formát
|
|
inline_segments = parse_inline(line)
|
|
for seg_text, seg_attr in inline_segments:
|
|
segments.append((seg_text, seg_attr))
|
|
segments.append(("\n", 0))
|
|
|
|
return segments
|
|
|
|
|
|
def parse_inline(text):
|
|
"""
|
|
Rozparsuje inline Markdown značky (tučný, kurzíva, inline kód) v jednom řádku,
|
|
vrací seznam (text, attr).
|
|
"""
|
|
segments = []
|
|
pos = 0
|
|
|
|
# Regulární výraz pro zachycení **text**, *text*, `text`
|
|
pattern = re.compile(r'(\*\*.*?\*\*|\*.*?\*|`.*?`)')
|
|
|
|
for match in pattern.finditer(text):
|
|
start, end = match.span()
|
|
if start > pos:
|
|
segments.append((text[pos:start], 0))
|
|
token = match.group(0)
|
|
if token.startswith("**") and token.endswith("**"):
|
|
content = token[2:-2]
|
|
segments.append((content, curses.A_BOLD))
|
|
elif token.startswith("*") and token.endswith("*"):
|
|
content = token[1:-1]
|
|
segments.append((content, curses.A_UNDERLINE))
|
|
elif token.startswith("`") and token.endswith("`"):
|
|
content = token[1:-1]
|
|
segments.append((content, curses.A_REVERSE))
|
|
else:
|
|
segments.append((token, 0))
|
|
pos = end
|
|
|
|
if pos < len(text):
|
|
segments.append((text[pos:], 0))
|
|
return segments
|
|
|
|
if __name__ == "__main__":
|
|
# Krátký test
|
|
sample = """# Nadpis 1
|
|
Toto je normální text s **tučným** a *kurzívou*.
|
|
- Odrážka 1
|
|
* Odrážka 2
|
|
A teď blok kódu:
|
|
ls -la echo "Hello"
|
|
Další text s `inline kódem` a ## menším nadpisem?
|
|
## Nadpis 2
|
|
"""
|
|
segs = parse_markdown(sample)
|
|
for seg, attr in segs:
|
|
# Ukázkové vypsání v terminálu (bez curses) pro debug
|
|
print(f"{repr(seg)} attr={attr}")
|