| | from __future__ import annotations |
| |
|
| | from collections.abc import Callable, Iterable, MutableMapping |
| | from collections.abc import MutableMapping as MutableMappingABC |
| | from pathlib import Path |
| | from typing import TYPE_CHECKING, Any, TypedDict, cast |
| |
|
| | if TYPE_CHECKING: |
| | from typing_extensions import NotRequired |
| |
|
| |
|
| | EnvType = MutableMapping[str, Any] |
| | """Type for the environment sandbox used in parsing and rendering, |
| | which stores mutable variables for use by plugins and rules. |
| | """ |
| |
|
| |
|
| | class OptionsType(TypedDict): |
| | """Options for parsing.""" |
| |
|
| | maxNesting: int |
| | """Internal protection, recursion limit.""" |
| | html: bool |
| | """Enable HTML tags in source.""" |
| | linkify: bool |
| | """Enable autoconversion of URL-like texts to links.""" |
| | typographer: bool |
| | """Enable smartquotes and replacements.""" |
| | quotes: str |
| | """Quote characters.""" |
| | xhtmlOut: bool |
| | """Use '/' to close single tags (<br />).""" |
| | breaks: bool |
| | """Convert newlines in paragraphs into <br>.""" |
| | langPrefix: str |
| | """CSS language prefix for fenced blocks.""" |
| | highlight: Callable[[str, str, str], str] | None |
| | """Highlighter function: (content, lang, attrs) -> str.""" |
| | store_labels: NotRequired[bool] |
| | """Store link label in link/image token's metadata (under Token.meta['label']). |
| | |
| | This is a Python only option, and is intended for the use of round-trip parsing. |
| | """ |
| |
|
| |
|
| | class PresetType(TypedDict): |
| | """Preset configuration for markdown-it.""" |
| |
|
| | options: OptionsType |
| | """Options for parsing.""" |
| | components: MutableMapping[str, MutableMapping[str, list[str]]] |
| | """Components for parsing and rendering.""" |
| |
|
| |
|
| | class OptionsDict(MutableMappingABC): |
| | """A dictionary, with attribute access to core markdownit configuration options.""" |
| |
|
| | |
| | |
| |
|
| | def __init__(self, options: OptionsType) -> None: |
| | self._options = cast(OptionsType, dict(options)) |
| |
|
| | def __getitem__(self, key: str) -> Any: |
| | return self._options[key] |
| |
|
| | def __setitem__(self, key: str, value: Any) -> None: |
| | self._options[key] = value |
| |
|
| | def __delitem__(self, key: str) -> None: |
| | del self._options[key] |
| |
|
| | def __iter__(self) -> Iterable[str]: |
| | return iter(self._options) |
| |
|
| | def __len__(self) -> int: |
| | return len(self._options) |
| |
|
| | def __repr__(self) -> str: |
| | return repr(self._options) |
| |
|
| | def __str__(self) -> str: |
| | return str(self._options) |
| |
|
| | @property |
| | def maxNesting(self) -> int: |
| | """Internal protection, recursion limit.""" |
| | return self._options["maxNesting"] |
| |
|
| | @maxNesting.setter |
| | def maxNesting(self, value: int) -> None: |
| | self._options["maxNesting"] = value |
| |
|
| | @property |
| | def html(self) -> bool: |
| | """Enable HTML tags in source.""" |
| | return self._options["html"] |
| |
|
| | @html.setter |
| | def html(self, value: bool) -> None: |
| | self._options["html"] = value |
| |
|
| | @property |
| | def linkify(self) -> bool: |
| | """Enable autoconversion of URL-like texts to links.""" |
| | return self._options["linkify"] |
| |
|
| | @linkify.setter |
| | def linkify(self, value: bool) -> None: |
| | self._options["linkify"] = value |
| |
|
| | @property |
| | def typographer(self) -> bool: |
| | """Enable smartquotes and replacements.""" |
| | return self._options["typographer"] |
| |
|
| | @typographer.setter |
| | def typographer(self, value: bool) -> None: |
| | self._options["typographer"] = value |
| |
|
| | @property |
| | def quotes(self) -> str: |
| | """Quote characters.""" |
| | return self._options["quotes"] |
| |
|
| | @quotes.setter |
| | def quotes(self, value: str) -> None: |
| | self._options["quotes"] = value |
| |
|
| | @property |
| | def xhtmlOut(self) -> bool: |
| | """Use '/' to close single tags (<br />).""" |
| | return self._options["xhtmlOut"] |
| |
|
| | @xhtmlOut.setter |
| | def xhtmlOut(self, value: bool) -> None: |
| | self._options["xhtmlOut"] = value |
| |
|
| | @property |
| | def breaks(self) -> bool: |
| | """Convert newlines in paragraphs into <br>.""" |
| | return self._options["breaks"] |
| |
|
| | @breaks.setter |
| | def breaks(self, value: bool) -> None: |
| | self._options["breaks"] = value |
| |
|
| | @property |
| | def langPrefix(self) -> str: |
| | """CSS language prefix for fenced blocks.""" |
| | return self._options["langPrefix"] |
| |
|
| | @langPrefix.setter |
| | def langPrefix(self, value: str) -> None: |
| | self._options["langPrefix"] = value |
| |
|
| | @property |
| | def highlight(self) -> Callable[[str, str, str], str] | None: |
| | """Highlighter function: (content, langName, langAttrs) -> escaped HTML.""" |
| | return self._options["highlight"] |
| |
|
| | @highlight.setter |
| | def highlight(self, value: Callable[[str, str, str], str] | None) -> None: |
| | self._options["highlight"] = value |
| |
|
| |
|
| | def read_fixture_file(path: str | Path) -> list[list[Any]]: |
| | text = Path(path).read_text(encoding="utf-8") |
| | tests = [] |
| | section = 0 |
| | last_pos = 0 |
| | lines = text.splitlines(keepends=True) |
| | for i in range(len(lines)): |
| | if lines[i].rstrip() == ".": |
| | if section == 0: |
| | tests.append([i, lines[i - 1].strip()]) |
| | section = 1 |
| | elif section == 1: |
| | tests[-1].append("".join(lines[last_pos + 1 : i])) |
| | section = 2 |
| | elif section == 2: |
| | tests[-1].append("".join(lines[last_pos + 1 : i])) |
| | section = 0 |
| |
|
| | last_pos = i |
| | return tests |
| |
|