Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/markdown_it/utils.py: 70%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

125 statements  

1from __future__ import annotations 

2 

3from collections.abc import Iterable, MutableMapping 

4from collections.abc import MutableMapping as MutableMappingABC 

5from pathlib import Path 

6from typing import TYPE_CHECKING, Any, Callable, TypedDict, cast 

7 

8if TYPE_CHECKING: 

9 from typing_extensions import NotRequired 

10 

11 

12EnvType = MutableMapping[str, Any] # note: could use TypeAlias in python 3.10 

13"""Type for the environment sandbox used in parsing and rendering, 

14which stores mutable variables for use by plugins and rules. 

15""" 

16 

17 

18class OptionsType(TypedDict): 

19 """Options for parsing.""" 

20 

21 maxNesting: int 

22 """Internal protection, recursion limit.""" 

23 html: bool 

24 """Enable HTML tags in source.""" 

25 linkify: bool 

26 """Enable autoconversion of URL-like texts to links.""" 

27 typographer: bool 

28 """Enable smartquotes and replacements.""" 

29 quotes: str 

30 """Quote characters.""" 

31 xhtmlOut: bool 

32 """Use '/' to close single tags (<br />).""" 

33 breaks: bool 

34 """Convert newlines in paragraphs into <br>.""" 

35 langPrefix: str 

36 """CSS language prefix for fenced blocks.""" 

37 highlight: Callable[[str, str, str], str] | None 

38 """Highlighter function: (content, lang, attrs) -> str.""" 

39 store_labels: NotRequired[bool] 

40 """Store link label in link/image token's metadata (under Token.meta['label']). 

41 

42 This is a Python only option, and is intended for the use of round-trip parsing. 

43 """ 

44 

45 

46class PresetType(TypedDict): 

47 """Preset configuration for markdown-it.""" 

48 

49 options: OptionsType 

50 """Options for parsing.""" 

51 components: MutableMapping[str, MutableMapping[str, list[str]]] 

52 """Components for parsing and rendering.""" 

53 

54 

55class OptionsDict(MutableMappingABC): # type: ignore 

56 """A dictionary, with attribute access to core markdownit configuration options.""" 

57 

58 # Note: ideally we would probably just remove attribute access entirely, 

59 # but we keep it for backwards compatibility. 

60 

61 def __init__(self, options: OptionsType) -> None: 

62 self._options = cast(OptionsType, dict(options)) 

63 

64 def __getitem__(self, key: str) -> Any: 

65 return self._options[key] # type: ignore[literal-required] 

66 

67 def __setitem__(self, key: str, value: Any) -> None: 

68 self._options[key] = value # type: ignore[literal-required] 

69 

70 def __delitem__(self, key: str) -> None: 

71 del self._options[key] # type: ignore 

72 

73 def __iter__(self) -> Iterable[str]: # type: ignore 

74 return iter(self._options) 

75 

76 def __len__(self) -> int: 

77 return len(self._options) 

78 

79 def __repr__(self) -> str: 

80 return repr(self._options) 

81 

82 def __str__(self) -> str: 

83 return str(self._options) 

84 

85 @property 

86 def maxNesting(self) -> int: 

87 """Internal protection, recursion limit.""" 

88 return self._options["maxNesting"] 

89 

90 @maxNesting.setter 

91 def maxNesting(self, value: int) -> None: 

92 self._options["maxNesting"] = value 

93 

94 @property 

95 def html(self) -> bool: 

96 """Enable HTML tags in source.""" 

97 return self._options["html"] 

98 

99 @html.setter 

100 def html(self, value: bool) -> None: 

101 self._options["html"] = value 

102 

103 @property 

104 def linkify(self) -> bool: 

105 """Enable autoconversion of URL-like texts to links.""" 

106 return self._options["linkify"] 

107 

108 @linkify.setter 

109 def linkify(self, value: bool) -> None: 

110 self._options["linkify"] = value 

111 

112 @property 

113 def typographer(self) -> bool: 

114 """Enable smartquotes and replacements.""" 

115 return self._options["typographer"] 

116 

117 @typographer.setter 

118 def typographer(self, value: bool) -> None: 

119 self._options["typographer"] = value 

120 

121 @property 

122 def quotes(self) -> str: 

123 """Quote characters.""" 

124 return self._options["quotes"] 

125 

126 @quotes.setter 

127 def quotes(self, value: str) -> None: 

128 self._options["quotes"] = value 

129 

130 @property 

131 def xhtmlOut(self) -> bool: 

132 """Use '/' to close single tags (<br />).""" 

133 return self._options["xhtmlOut"] 

134 

135 @xhtmlOut.setter 

136 def xhtmlOut(self, value: bool) -> None: 

137 self._options["xhtmlOut"] = value 

138 

139 @property 

140 def breaks(self) -> bool: 

141 """Convert newlines in paragraphs into <br>.""" 

142 return self._options["breaks"] 

143 

144 @breaks.setter 

145 def breaks(self, value: bool) -> None: 

146 self._options["breaks"] = value 

147 

148 @property 

149 def langPrefix(self) -> str: 

150 """CSS language prefix for fenced blocks.""" 

151 return self._options["langPrefix"] 

152 

153 @langPrefix.setter 

154 def langPrefix(self, value: str) -> None: 

155 self._options["langPrefix"] = value 

156 

157 @property 

158 def highlight(self) -> Callable[[str, str, str], str] | None: 

159 """Highlighter function: (content, langName, langAttrs) -> escaped HTML.""" 

160 return self._options["highlight"] 

161 

162 @highlight.setter 

163 def highlight(self, value: Callable[[str, str, str], str] | None) -> None: 

164 self._options["highlight"] = value 

165 

166 

167def read_fixture_file(path: str | Path) -> list[list[Any]]: 

168 text = Path(path).read_text(encoding="utf-8") 

169 tests = [] 

170 section = 0 

171 last_pos = 0 

172 lines = text.splitlines(keepends=True) 

173 for i in range(len(lines)): 

174 if lines[i].rstrip() == ".": 

175 if section == 0: 

176 tests.append([i, lines[i - 1].strip()]) 

177 section = 1 

178 elif section == 1: 

179 tests[-1].append("".join(lines[last_pos + 1 : i])) 

180 section = 2 

181 elif section == 2: 

182 tests[-1].append("".join(lines[last_pos + 1 : i])) 

183 section = 0 

184 

185 last_pos = i 

186 return tests