Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/mistune/plugins/def_list.py: 90%

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

67 statements  

1import re 

2from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Match 

3 

4from ..util import strip_end 

5 

6if TYPE_CHECKING: 

7 from ..block_parser import BlockParser 

8 from ..core import BaseRenderer, BlockState 

9 from ..markdown import Markdown 

10 

11__all__ = ["def_list"] 

12 

13# https://michelf.ca/projects/php-markdown/extra/#def-list 

14 

15DEF_PATTERN = ( 

16 r"^(?P<def_list_head>(?:[^\n]+\n)+?)" 

17 r"\n?(?:" 

18 r"\:[ \t]+.*\n" 

19 r"(?:[^\n]+\n)*" # lazy continue line 

20 r"(?:(?:[ \t]*\n)*[ \t]+[^\n]+\n)*" 

21 r"(?:[ \t]*\n)*" 

22 r")+" 

23) 

24DEF_RE = re.compile(DEF_PATTERN, re.M) 

25DD_START_RE = re.compile(r"^:[ \t]+", re.M) 

26TRIM_RE = re.compile(r"^ {0,4}", re.M) 

27HAS_BLANK_LINE_RE = re.compile(r"\n[ \t]*\n$") 

28 

29 

30def parse_def_list(block: "BlockParser", m: Match[str], state: "BlockState") -> int: 

31 pos = m.end() 

32 children = list(_parse_def_item(block, m)) 

33 

34 m2 = DEF_RE.match(state.src, pos) 

35 while m2: 

36 children.extend(list(_parse_def_item(block, m2))) 

37 pos = m2.end() 

38 m2 = DEF_RE.match(state.src, pos) 

39 

40 state.append_token( 

41 { 

42 "type": "def_list", 

43 "children": children, 

44 } 

45 ) 

46 return pos 

47 

48 

49def _parse_def_item(block: "BlockParser", m: Match[str]) -> Iterable[Dict[str, Any]]: 

50 head = m.group("def_list_head") 

51 for line in head.splitlines(): 

52 yield { 

53 "type": "def_list_head", 

54 "text": line, 

55 } 

56 

57 src = m.group(0) 

58 end = len(head) 

59 

60 m2 = DD_START_RE.search(src, end) 

61 assert m2 is not None 

62 start = m2.start() 

63 prev_blank_line = src[end:start] == "\n" 

64 while m2: 

65 m2 = DD_START_RE.search(src, start + 1) 

66 if not m2: 

67 break 

68 

69 end = m2.start() 

70 text = src[start:end].replace(":", " ", 1) 

71 children = _process_text(block, text, prev_blank_line) 

72 prev_blank_line = bool(HAS_BLANK_LINE_RE.search(text)) 

73 yield { 

74 "type": "def_list_item", 

75 "children": children, 

76 } 

77 start = end 

78 

79 text = src[start:].replace(":", " ", 1) 

80 children = _process_text(block, text, prev_blank_line) 

81 yield { 

82 "type": "def_list_item", 

83 "children": children, 

84 } 

85 

86 

87def _process_text(block: "BlockParser", text: str, loose: bool) -> List[Any]: 

88 text = TRIM_RE.sub("", text) 

89 state = block.state_cls() 

90 state.process(strip_end(text)) 

91 # use default list rules 

92 block.parse(state, block.list_rules) 

93 tokens = state.tokens 

94 if not loose and len(tokens) == 1 and tokens[0]["type"] == "paragraph": 

95 tokens[0]["type"] = "block_text" 

96 return tokens 

97 

98 

99def render_def_list(renderer: "BaseRenderer", text: str) -> str: 

100 return "<dl>\n" + text + "</dl>\n" 

101 

102 

103def render_def_list_head(renderer: "BaseRenderer", text: str) -> str: 

104 return "<dt>" + text + "</dt>\n" 

105 

106 

107def render_def_list_item(renderer: "BaseRenderer", text: str) -> str: 

108 return "<dd>" + text + "</dd>\n" 

109 

110 

111def def_list(md: "Markdown") -> None: 

112 """A mistune plugin to support def list, spec defined at 

113 https://michelf.ca/projects/php-markdown/extra/#def-list 

114 

115 Here is an example: 

116 

117 .. code-block:: text 

118 

119 Apple 

120 : Pomaceous fruit of plants of the genus Malus in 

121 the family Rosaceae. 

122 

123 Orange 

124 : The fruit of an evergreen tree of the genus Citrus. 

125 

126 It will be converted into HTML: 

127 

128 .. code-block:: html 

129 

130 <dl> 

131 <dt>Apple</dt> 

132 <dd>Pomaceous fruit of plants of the genus Malus in 

133 the family Rosaceae.</dd> 

134 

135 <dt>Orange</dt> 

136 <dd>The fruit of an evergreen tree of the genus Citrus.</dd> 

137 </dl> 

138 

139 :param md: Markdown instance 

140 """ 

141 md.block.register("def_list", DEF_PATTERN, parse_def_list, before="paragraph") 

142 if md.renderer and md.renderer.NAME == "html": 

143 md.renderer.register("def_list", render_def_list) 

144 md.renderer.register("def_list_head", render_def_list_head) 

145 md.renderer.register("def_list_item", render_def_list_item)