File size: 5,365 Bytes
0ad74ed |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
from __future__ import annotations
from collections.abc import MutableMapping as MutableMappingABC
from pathlib import Path
from typing import Any, Callable, Iterable, MutableMapping, TypedDict, cast
EnvType = MutableMapping[str, Any] # note: could use TypeAlias in python 3.10
"""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."""
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): # type: ignore
"""A dictionary, with attribute access to core markdownit configuration options."""
# Note: ideally we would probably just remove attribute access entirely,
# but we keep it for backwards compatibility.
def __init__(self, options: OptionsType) -> None:
self._options = cast(OptionsType, dict(options))
def __getitem__(self, key: str) -> Any:
return self._options[key] # type: ignore[literal-required]
def __setitem__(self, key: str, value: Any) -> None:
self._options[key] = value # type: ignore[literal-required]
def __delitem__(self, key: str) -> None:
del self._options[key] # type: ignore
def __iter__(self) -> Iterable[str]: # type: ignore
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
|