Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/mdit_py_plugins/substitution.py: 95%

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

64 statements  

1from markdown_it import MarkdownIt 

2from markdown_it.rules_block import StateBlock 

3from markdown_it.rules_inline import StateInline 

4 

5from mdit_py_plugins.utils import is_code_block 

6 

7 

8def substitution_plugin( 

9 md: MarkdownIt, start_delimiter: str = "{", end_delimiter: str = "}" 

10) -> None: 

11 """A plugin to create substitution tokens. 

12 

13 These, token should be handled by the renderer. 

14 

15 Example:: 

16 

17 {{ block }} 

18 

19 a {{ inline }} b 

20 

21 """ 

22 

23 def _substitution_inline(state: StateInline, silent: bool) -> bool: 

24 try: 

25 if ( 

26 state.src[state.pos] != start_delimiter 

27 or state.src[state.pos + 1] != start_delimiter 

28 ): 

29 return False 

30 except IndexError: 

31 return False 

32 

33 pos = state.pos + 2 

34 found_closing = False 

35 while True: 

36 try: 

37 end = state.src.index(end_delimiter, pos) 

38 except ValueError: 

39 return False 

40 try: 

41 if state.src[end + 1] == end_delimiter: 

42 found_closing = True 

43 break 

44 except IndexError: 

45 return False 

46 pos = end + 2 

47 

48 if not found_closing: 

49 return False 

50 

51 text = state.src[state.pos + 2 : end].strip() 

52 state.pos = end + 2 

53 

54 if silent: 

55 return True 

56 

57 token = state.push("substitution_inline", "span", 0) 

58 token.block = False 

59 token.content = text 

60 token.attrSet("class", "substitution") 

61 token.attrSet("text", text) 

62 token.markup = f"{start_delimiter}{end_delimiter}" 

63 

64 return True 

65 

66 def _substitution_block( 

67 state: StateBlock, startLine: int, endLine: int, silent: bool 

68 ) -> bool: 

69 if is_code_block(state, startLine): 

70 return False 

71 

72 startPos = state.bMarks[startLine] + state.tShift[startLine] 

73 end = state.eMarks[startLine] 

74 

75 lineText = state.src[startPos:end].strip() 

76 

77 try: 

78 if ( 

79 lineText[0] != start_delimiter 

80 or lineText[1] != start_delimiter 

81 or lineText[-1] != end_delimiter 

82 or lineText[-2] != end_delimiter 

83 or len(lineText) < 5 

84 ): 

85 return False 

86 except IndexError: 

87 return False 

88 

89 text = lineText[2:-2].strip() 

90 

91 # special case if multiple on same line, e.g. {{a}}{{b}} 

92 if (end_delimiter * 2) in text: 

93 return False 

94 

95 state.line = startLine + 1 

96 

97 if silent: 

98 return True 

99 

100 token = state.push("substitution_block", "div", 0) 

101 token.block = True 

102 token.content = text 

103 token.attrSet("class", "substitution") 

104 token.attrSet("text", text) 

105 token.markup = f"{start_delimiter}{end_delimiter}" 

106 token.map = [startLine, state.line] 

107 

108 return True 

109 

110 md.block.ruler.before("fence", "substitution_block", _substitution_block) 

111 md.inline.ruler.before("escape", "substitution_inline", _substitution_inline)