Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions marko/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import Iterable

from .block import Document
from .helpers import MarkoExtension as MarkoExtension
from .helpers import load_extension as load_extension
from .html_renderer import HTMLRenderer as HTMLRenderer
from .parser import Parser as Parser
from .renderer import Renderer as Renderer

__all__: list[str]

class SetupDone(Exception): ...

class Markdown:
def __init__(
self,
parser: type[Parser] = ...,
renderer: type[Renderer] = ...,
extensions: Iterable[str | MarkoExtension] | None = None,
) -> None: ...
def use(self, *extensions: str | MarkoExtension) -> None: ...
def convert(self, text: str) -> str: ...
def __call__(self, text: str) -> str: ...
def parse(self, text: str) -> Document: ...
def render(self, parsed: Document) -> str: ...

def convert(text: str) -> str: ...
def parse(text: str) -> Document: ...
def render(parsed: Document) -> str: ...
32 changes: 32 additions & 0 deletions marko/ast_renderer.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from typing import Any, overload

from marko import inline
from marko.element import Element

from .renderer import Renderer, force_delegate

class ASTRenderer(Renderer):
delegate: bool

# Narrowed return type for dict-returning renderer
def render(self, element: Element) -> dict[str, Any]: ...

@force_delegate
def render_raw_text(self, element: inline.RawText) -> dict[str, Any]: ...
@overload
def render_children(self, element: list[Element]) -> list[dict[str, Any]]: ...
@overload
def render_children(self, element: Element) -> dict[str, Any]: ...
@overload
def render_children(self, element: str) -> str: ...

class XMLRenderer(Renderer):
delegate: bool
indent: int

# Narrowed return types for str-returning renderer
def render(self, element: Element) -> str: ...
def render_children(self, element: Element) -> str: ...

def __enter__(self) -> XMLRenderer: ...
def __exit__(self, *args: Any) -> None: ...
190 changes: 190 additions & 0 deletions marko/block.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
from typing import Any, Match, NamedTuple, Sequence

from . import inline_parser
from .element import Element
from .source import Source

__all__ = [
"Document",
"CodeBlock",
"Heading",
"List",
"ListItem",
"BlankLine",
"Quote",
"FencedCode",
"ThematicBreak",
"HTMLBlock",
"LinkRefDef",
"SetextHeading",
"Paragraph",
]

class BlockElement(Element):
children: Sequence[Element]
priority: int
virtual: bool
inline_body: str
override: bool
@classmethod
def match(cls, source: Source) -> Any: ...
@classmethod
def parse(cls, source: Source) -> Any: ...
def __lt__(self, o: BlockElement) -> bool: ...

class Document(BlockElement):
virtual: bool
children: list[Element]
link_ref_defs: dict[str, tuple[str, str]]
def __init__(self) -> None: ...

class BlankLine(BlockElement):
priority: int
def __init__(self, start: int) -> None: ...
@classmethod
def match(cls, source: Source) -> bool: ...
@classmethod
def parse(cls, source: Source) -> int: ...

class Heading(BlockElement):
priority: int
pattern: Any
level: int
inline_body: str
def __init__(self, match: Match[str]) -> None: ...
@classmethod
def match(cls, source: Source) -> Match[str] | None: ...
@classmethod
def parse(cls, source: Source) -> Match[str] | None: ...

class SetextHeading(BlockElement):
virtual: bool
level: int
inline_body: str
def __init__(self, lines: list[str]) -> None: ...

class CodeBlock(BlockElement):
priority: int
children: list[Element]
lang: str
extra: str
def __init__(self, lines: str) -> None: ...
@classmethod
def match(cls, source: Source) -> str: ...
@classmethod
def parse(cls, source: Source) -> str: ...
@staticmethod
def strip_prefix(line: str, prefix: str) -> str: ...

class FencedCode(BlockElement):
priority: int
pattern: Any

class ParseInfo(NamedTuple):
prefix: str
leading: str
lang: str
extra: str

lang: str
extra: str
children: list[Element]
def __init__(self, match: tuple[str, str, str]) -> None: ...
@classmethod
def match(cls, source: Source) -> Match[str] | None: ...
@classmethod
def parse(cls, source: Source) -> tuple[str, str, str]: ...

class ThematicBreak(BlockElement):
priority: int
pattern: Any
@classmethod
def match(cls, source: Source) -> bool: ...
@classmethod
def parse(cls, source: Source) -> ThematicBreak: ...

class HTMLBlock(BlockElement):
priority: int
body: str
def __init__(self, lines: str) -> None: ...
@classmethod
def match(cls, source: Source) -> int | bool: ...
@classmethod
def parse(cls, source: Source) -> str: ...

class Paragraph(BlockElement):
priority: int
pattern: Any
inline_body: str
def __init__(self, lines: list[str]) -> None: ...
@classmethod
def match(cls, source: Source) -> bool: ...
@staticmethod
def is_setext_heading(line: str) -> bool: ...
@classmethod
def break_paragraph(cls, source: Source, lazy: bool = False) -> bool: ...
@classmethod
def parse(cls, source: Source) -> list[str] | SetextHeading: ...

class Quote(BlockElement):
priority: int
@classmethod
def match(cls, source: Source) -> Match[str] | None: ...
@classmethod
def parse(cls, source: Source) -> Quote: ...

class List(BlockElement):
priority: int
pattern: Any

class ParseInfo(NamedTuple):
bullet: str
ordered: bool
start: int

tight: bool
ordered: bool
start: int
bullet: str
def __init__(self, info: ParseInfo) -> None: ...
@classmethod
def match(cls, source: Source) -> bool: ...
@classmethod
def parse(cls, source: Source) -> List: ...

class ListItem(BlockElement):
virtual: bool
pattern: Any

class ParseInfo(NamedTuple):
indent: int
bullet: str
mid: int

def __init__(self, info: ParseInfo) -> None: ...
@classmethod
def parse_leading(
cls, line: str, prefix_pos: int
) -> tuple[int, str, int, str]: ...
@classmethod
def match(cls, source: Source) -> bool: ...
@classmethod
def parse(cls, source: Source) -> ListItem: ...

class LinkRefDef(BlockElement):
pattern: Any

class ParseInfo(NamedTuple):
link_label: inline_parser.Group
link_dest: inline_parser.Group
link_title: inline_parser.Group
end: int

label: str
dest: str
title: str | None
def __init__(self, label: str, text: str, title: str | None = None) -> None: ...
@classmethod
def match(cls, source: Source) -> bool: ...
@classmethod
def parse(cls, source: Source) -> LinkRefDef: ...
4 changes: 3 additions & 1 deletion marko/element.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import cast

from .helpers import camel_to_snake_case


Expand Down Expand Up @@ -41,4 +43,4 @@ def __repr__(self) -> str:

return f"<{self.__class__.__name__}{children}>"
else:
return objstr(self, honor_existing=False, include=["children"])
return cast(str, objstr(self, honor_existing=False, include=["children"]))
7 changes: 7 additions & 0 deletions marko/element.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .helpers import camel_to_snake_case as camel_to_snake_case

class Element:
override: bool
@classmethod
def get_type(cls, snake_case: bool = False) -> str: ...
def __repr__(self) -> str: ...
4 changes: 2 additions & 2 deletions marko/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import re
from functools import partial
from importlib import import_module
from typing import TYPE_CHECKING, overload
from typing import TYPE_CHECKING, cast, overload

from marko.renderer import Renderer

Expand Down Expand Up @@ -129,7 +129,7 @@ def load_extension(name: str, **kwargs: Any) -> MarkoExtension:
raise ImportError(f"Extension {name} cannot be imported") from e

try:
return module.make_extension(**kwargs)
return cast(MarkoExtension, module.make_extension(**kwargs))
except AttributeError:
raise AttributeError(
f"Module {name} does not have 'make_extension' attributte."
Expand Down
50 changes: 50 additions & 0 deletions marko/helpers.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import dataclasses
from typing import Any, Callable, Container, Iterable, TypeVar, overload

from .element import Element
from .renderer import Renderer

RendererFunc = Callable[[Any, Element], Any]
TRenderer = TypeVar("TRenderer", bound=RendererFunc)
D = TypeVar("D", bound="_RendererDispatcher")

def camel_to_snake_case(name: str) -> str: ...
def is_paired(text: Iterable[str], open: str = "(", close: str = ")") -> bool: ...
def normalize_label(label: str) -> str: ...
def find_next(
text: str,
target: Container[str],
start: int = 0,
end: int | None = None,
disallowed: Container[str] = (),
) -> int: ...
def partition_by_spaces(text: str, spaces: str = " \t") -> tuple[str, str, str]: ...

@dataclasses.dataclass(frozen=True)
class MarkoExtension:
parser_mixins: list[type] = dataclasses.field(default_factory=list)
renderer_mixins: list[type] = dataclasses.field(default_factory=list)
elements: list[type[Element]] = dataclasses.field(default_factory=list)

def load_extension(name: str, **kwargs: Any) -> MarkoExtension: ...

class _RendererDispatcher:
name: str
def __init__(
self, types: type[Renderer] | tuple[type[Renderer], ...], func: RendererFunc
) -> None: ...
def dispatch(
self: D, types: type[Renderer] | tuple[type[Renderer], ...]
) -> Callable[[RendererFunc], D]: ...
def __set_name__(self, owner: type, name: str) -> None: ...
@staticmethod
def render_ast(self: Any, element: Element) -> Any: ...
def super_render(self, r: Any, element: Element) -> Any: ...
@overload
def __get__(self: D, obj: None, owner: type) -> D: ...
@overload
def __get__(self: D, obj: Renderer, owner: type) -> RendererFunc: ...

def render_dispatch(
types: type[Renderer] | tuple[type[Renderer], ...],
) -> Callable[[RendererFunc], _RendererDispatcher]: ...
38 changes: 38 additions & 0 deletions marko/html_renderer.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import Any

from . import block, inline
from .element import Element
from .renderer import Renderer

class HTMLRenderer(Renderer):
# Narrowed return types for str-returning renderer
def render(self, element: Element) -> str: ...
def render_children(self, element: Any) -> str: ...

def render_paragraph(self, element: block.Paragraph) -> str: ...
def render_list(self, element: block.List) -> str: ...
def render_list_item(self, element: block.ListItem) -> str: ...
def render_quote(self, element: block.Quote) -> str: ...
def render_fenced_code(self, element: block.FencedCode) -> str: ...
def render_code_block(self, element: block.CodeBlock) -> str: ...
def render_html_block(self, element: block.HTMLBlock) -> str: ...
def render_thematic_break(self, element: block.ThematicBreak) -> str: ...
def render_heading(self, element: block.Heading) -> str: ...
def render_setext_heading(self, element: block.SetextHeading) -> str: ...
def render_blank_line(self, element: block.BlankLine) -> str: ...
def render_link_ref_def(self, element: block.LinkRefDef) -> str: ...
def render_emphasis(self, element: inline.Emphasis) -> str: ...
def render_strong_emphasis(self, element: inline.StrongEmphasis) -> str: ...
def render_inline_html(self, element: inline.InlineHTML) -> str: ...
def render_plain_text(self, element: Any) -> str: ...
def render_link(self, element: inline.Link) -> str: ...
def render_auto_link(self, element: inline.AutoLink) -> str: ...
def render_image(self, element: inline.Image) -> str: ...
def render_literal(self, element: inline.Literal) -> str: ...
def render_raw_text(self, element: inline.RawText) -> str: ...
def render_line_break(self, element: inline.LineBreak) -> str: ...
def render_code_span(self, element: inline.CodeSpan) -> str: ...
@staticmethod
def escape_html(raw: str) -> str: ...
@staticmethod
def escape_url(raw: str) -> str: ...
Loading