Building Project Files
هذا الالتزام موجود في:
150
venv/lib/python3.12/site-packages/mistune/renderers/markdown.py
Normal file
150
venv/lib/python3.12/site-packages/mistune/renderers/markdown.py
Normal file
@@ -0,0 +1,150 @@
|
||||
import re
|
||||
from textwrap import indent
|
||||
from typing import Any, Dict, Iterable, cast
|
||||
|
||||
from ..core import BaseRenderer, BlockState
|
||||
from ..util import strip_end
|
||||
from ._list import render_list
|
||||
|
||||
fenced_re = re.compile(r"^[`~]+", re.M)
|
||||
|
||||
|
||||
class MarkdownRenderer(BaseRenderer):
|
||||
"""A renderer to re-format Markdown text."""
|
||||
|
||||
NAME = "markdown"
|
||||
|
||||
def __call__(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> str:
|
||||
out = self.render_tokens(tokens, state)
|
||||
# special handle for line breaks
|
||||
out += "\n\n".join(self.render_referrences(state)) + "\n"
|
||||
return strip_end(out)
|
||||
|
||||
def render_referrences(self, state: BlockState) -> Iterable[str]:
|
||||
ref_links = state.env["ref_links"]
|
||||
for key in ref_links:
|
||||
attrs = ref_links[key]
|
||||
text = "[" + attrs["label"] + "]: " + attrs["url"]
|
||||
title = attrs.get("title")
|
||||
if title:
|
||||
text += ' "' + title + '"'
|
||||
yield text
|
||||
|
||||
def render_children(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
children = token["children"]
|
||||
return self.render_tokens(children, state)
|
||||
|
||||
def text(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return cast(str, token["raw"])
|
||||
|
||||
def emphasis(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return "*" + self.render_children(token, state) + "*"
|
||||
|
||||
def strong(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return "**" + self.render_children(token, state) + "**"
|
||||
|
||||
def link(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
label = cast(str, token.get("label"))
|
||||
text = self.render_children(token, state)
|
||||
out = "[" + text + "]"
|
||||
if label:
|
||||
return out + "[" + label + "]"
|
||||
|
||||
attrs = token["attrs"]
|
||||
url = attrs["url"]
|
||||
title = attrs.get("title")
|
||||
if text == url and not title:
|
||||
return "<" + text + ">"
|
||||
elif "mailto:" + text == url and not title:
|
||||
return "<" + text + ">"
|
||||
|
||||
out += "("
|
||||
if "(" in url or ")" in url:
|
||||
out += "<" + url + ">"
|
||||
else:
|
||||
out += url
|
||||
if title:
|
||||
out += ' "' + title + '"'
|
||||
return out + ")"
|
||||
|
||||
def image(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return "!" + self.link(token, state)
|
||||
|
||||
def codespan(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return "`" + cast(str, token["raw"]) + "`"
|
||||
|
||||
def linebreak(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return " \n"
|
||||
|
||||
def softbreak(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return "\n"
|
||||
|
||||
def blank_line(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return ""
|
||||
|
||||
def inline_html(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return cast(str, token["raw"])
|
||||
|
||||
def paragraph(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
text = self.render_children(token, state)
|
||||
return text + "\n\n"
|
||||
|
||||
def heading(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
level = cast(int, token["attrs"]["level"])
|
||||
marker = "#" * level
|
||||
text = self.render_children(token, state)
|
||||
return marker + " " + text + "\n\n"
|
||||
|
||||
def thematic_break(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return "***\n\n"
|
||||
|
||||
def block_text(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return self.render_children(token, state) + "\n"
|
||||
|
||||
def block_code(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
attrs = token.get("attrs", {})
|
||||
info = cast(str, attrs.get("info", ""))
|
||||
code = cast(str, token["raw"])
|
||||
if code and code[-1] != "\n":
|
||||
code += "\n"
|
||||
|
||||
marker = token.get("marker")
|
||||
if not marker:
|
||||
marker = _get_fenced_marker(code)
|
||||
marker2 = cast(str, marker)
|
||||
return marker2 + info + "\n" + code + marker2 + "\n\n"
|
||||
|
||||
def block_quote(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
text = indent(self.render_children(token, state), "> ", lambda _: True)
|
||||
text = text.rstrip("> \n")
|
||||
return text + "\n\n"
|
||||
|
||||
def block_html(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return cast(str, token["raw"]) + "\n\n"
|
||||
|
||||
def block_error(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return ""
|
||||
|
||||
def list(self, token: Dict[str, Any], state: BlockState) -> str:
|
||||
return render_list(self, token, state)
|
||||
|
||||
|
||||
def _get_fenced_marker(code: str) -> str:
|
||||
found = fenced_re.findall(code)
|
||||
if not found:
|
||||
return "```"
|
||||
|
||||
ticks = [] # `
|
||||
waves = [] # ~
|
||||
for s in found:
|
||||
if s[0] == "`":
|
||||
ticks.append(len(s))
|
||||
else:
|
||||
waves.append(len(s))
|
||||
|
||||
if not ticks:
|
||||
return "```"
|
||||
|
||||
if not waves:
|
||||
return "~~~"
|
||||
return "`" * (max(ticks) + 1)
|
المرجع في مشكلة جديدة
حظر مستخدم