104 lines
3.8 KiB
Python
Raw Normal View History

2025-11-04 05:17:27 +01:00
import re
2025-11-04 08:09:12 +01:00
2025-11-04 05:17:27 +01:00
from pr.config import LANGUAGE_KEYWORDS
2025-11-04 08:09:12 +01:00
from pr.ui.colors import Colors
2025-11-04 05:17:27 +01:00
def highlight_code(code, language=None, syntax_highlighting=True):
if not syntax_highlighting:
return code
if not language:
2025-11-04 08:09:12 +01:00
if "def " in code or "import " in code:
language = "python"
elif "function " in code or "const " in code:
language = "javascript"
elif "public " in code or "class " in code:
language = "java"
2025-11-04 05:17:27 +01:00
if language and language in LANGUAGE_KEYWORDS:
keywords = LANGUAGE_KEYWORDS[language]
for keyword in keywords:
2025-11-04 08:09:12 +01:00
pattern = r"\b" + re.escape(keyword) + r"\b"
2025-11-04 05:17:27 +01:00
code = re.sub(pattern, f"{Colors.BLUE}{keyword}{Colors.RESET}", code)
code = re.sub(r'"([^"]*)"', f'{Colors.GREEN}"\\1"{Colors.RESET}', code)
code = re.sub(r"'([^']*)'", f"{Colors.GREEN}'\\1'{Colors.RESET}", code)
2025-11-04 08:10:37 +01:00
code = re.sub(r"#(.*)$", f"{Colors.GRAY}#\\1{Colors.RESET}", code, flags=re.MULTILINE)
code = re.sub(r"//(.*)$", f"{Colors.GRAY}//\\1{Colors.RESET}", code, flags=re.MULTILINE)
2025-11-04 05:17:27 +01:00
return code
2025-11-04 08:09:12 +01:00
2025-11-04 05:17:27 +01:00
def render_markdown(text, syntax_highlighting=True):
if not syntax_highlighting:
return text
code_blocks = []
2025-11-04 08:09:12 +01:00
2025-11-04 05:17:27 +01:00
def extract_code_block(match):
2025-11-04 08:09:12 +01:00
lang = match.group(1) or ""
2025-11-04 05:17:27 +01:00
code = match.group(2)
2025-11-04 08:09:12 +01:00
highlighted_code = highlight_code(code.strip("\n"), lang, syntax_highlighting)
2025-11-04 05:17:27 +01:00
placeholder = f"%%CODEBLOCK{len(code_blocks)}%%"
2025-11-04 08:09:12 +01:00
full_block = f"{Colors.GRAY}```{lang}{Colors.RESET}\n{highlighted_code}\n{Colors.GRAY}```{Colors.RESET}"
2025-11-04 05:17:27 +01:00
code_blocks.append(full_block)
return placeholder
2025-11-04 08:09:12 +01:00
text = re.sub(r"```(\w*)\n(.*?)\n?```", extract_code_block, text, flags=re.DOTALL)
2025-11-04 05:17:27 +01:00
inline_codes = []
2025-11-04 08:09:12 +01:00
2025-11-04 05:17:27 +01:00
def extract_inline_code(match):
code = match.group(1)
placeholder = f"%%INLINECODE{len(inline_codes)}%%"
2025-11-04 08:09:12 +01:00
inline_codes.append(f"{Colors.YELLOW}{code}{Colors.RESET}")
2025-11-04 05:17:27 +01:00
return placeholder
2025-11-04 08:09:12 +01:00
text = re.sub(r"`([^`]+)`", extract_inline_code, text)
2025-11-04 05:17:27 +01:00
2025-11-04 08:09:12 +01:00
lines = text.split("\n")
2025-11-04 05:17:27 +01:00
processed_lines = []
for line in lines:
2025-11-04 08:09:12 +01:00
if line.startswith("### "):
line = f"{Colors.BOLD}{Colors.GREEN}{line[4:]}{Colors.RESET}"
elif line.startswith("## "):
line = f"{Colors.BOLD}{Colors.BLUE}{line[3:]}{Colors.RESET}"
elif line.startswith("# "):
line = f"{Colors.BOLD}{Colors.MAGENTA}{line[2:]}{Colors.RESET}"
elif line.startswith("> "):
line = f"{Colors.CYAN}> {line[2:]}{Colors.RESET}"
elif re.match(r"^\s*[\*\-\+]\s", line):
match = re.match(r"^(\s*)([\*\-\+])(\s+.*)", line)
2025-11-04 05:17:27 +01:00
if match:
2025-11-04 08:10:37 +01:00
line = (
f"{match.group(1)}{Colors.YELLOW}{match.group(2)}{Colors.RESET}{match.group(3)}"
)
2025-11-04 08:09:12 +01:00
elif re.match(r"^\s*\d+\.\s", line):
match = re.match(r"^(\s*)(\d+\.)(\s+.*)", line)
2025-11-04 05:17:27 +01:00
if match:
2025-11-04 08:10:37 +01:00
line = (
f"{match.group(1)}{Colors.YELLOW}{match.group(2)}{Colors.RESET}{match.group(3)}"
)
2025-11-04 05:17:27 +01:00
processed_lines.append(line)
2025-11-04 08:09:12 +01:00
text = "\n".join(processed_lines)
2025-11-04 05:17:27 +01:00
2025-11-04 08:09:12 +01:00
text = re.sub(
r"\[(.*?)\]\((.*?)\)",
f"{Colors.BLUE}\\1{Colors.RESET}{Colors.GRAY}(\\2){Colors.RESET}",
text,
)
text = re.sub(r"~~(.*?)~~", f"{Colors.GRAY}\\1{Colors.RESET}", text)
text = re.sub(r"\*\*(.*?)\*\*", f"{Colors.BOLD}\\1{Colors.RESET}", text)
text = re.sub(r"__(.*?)__", f"{Colors.BOLD}\\1{Colors.RESET}", text)
text = re.sub(r"\*(.*?)\*", f"{Colors.CYAN}\\1{Colors.RESET}", text)
text = re.sub(r"_(.*?)_", f"{Colors.CYAN}\\1{Colors.RESET}", text)
2025-11-04 05:17:27 +01:00
for i, code in enumerate(inline_codes):
2025-11-04 08:09:12 +01:00
text = text.replace(f"%%INLINECODE{i}%%", code)
2025-11-04 05:17:27 +01:00
for i, block in enumerate(code_blocks):
2025-11-04 08:09:12 +01:00
text = text.replace(f"%%CODEBLOCK{i}%%", block)
2025-11-04 05:17:27 +01:00
return text