Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/mdit_py_plugins/front_matter/index.py: 98%

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  

1"""Process front matter.""" 

2 

3from markdown_it import MarkdownIt 

4from markdown_it.rules_block import StateBlock 

5 

6from mdit_py_plugins.utils import is_code_block 

7 

8 

9def front_matter_plugin(md: MarkdownIt) -> None: 

10 """Plugin ported from 

11 `markdown-it-front-matter <https://github.com/ParkSB/markdown-it-front-matter>`__. 

12 

13 It parses initial metadata, stored between opening/closing dashes: 

14 

15 .. code-block:: md 

16 

17 --- 

18 valid-front-matter: true 

19 --- 

20 

21 """ 

22 md.block.ruler.before( 

23 "table", 

24 "front_matter", 

25 _front_matter_rule, 

26 {"alt": ["paragraph", "reference", "blockquote", "list"]}, 

27 ) 

28 

29 

30def _front_matter_rule( 

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

32) -> bool: 

33 marker_chr = "-" 

34 min_markers = 3 

35 

36 auto_closed = False 

37 start = state.bMarks[startLine] + state.tShift[startLine] 

38 maximum = state.eMarks[startLine] 

39 src_len = len(state.src) 

40 

41 # Check out the first character of the first line quickly, 

42 # this should filter out non-front matter 

43 if startLine != 0 or state.src[0] != marker_chr: 

44 return False 

45 

46 # Check out the rest of the marker string 

47 # while pos <= 3 

48 pos = start + 1 

49 while pos <= maximum and pos < src_len: 

50 if state.src[pos] != marker_chr: 

51 break 

52 pos += 1 

53 

54 marker_count = pos - start 

55 

56 if marker_count < min_markers: 

57 return False 

58 

59 # Since start is found, we can report success here in validation mode 

60 if silent: 

61 return True 

62 

63 # Search for the end of the block 

64 nextLine = startLine 

65 

66 while True: 

67 nextLine += 1 

68 if nextLine >= endLine: 

69 # unclosed block should be autoclosed by end of document. 

70 return False 

71 

72 if state.src[start:maximum] == "...": 

73 break 

74 

75 start = state.bMarks[nextLine] + state.tShift[nextLine] 

76 maximum = state.eMarks[nextLine] 

77 

78 if start < maximum and state.sCount[nextLine] < state.blkIndent: 

79 # non-empty line with negative indent should stop the list: 

80 # - ``` 

81 # test 

82 break 

83 

84 if state.src[start] != marker_chr: 

85 continue 

86 

87 if is_code_block(state, nextLine): 

88 continue 

89 

90 pos = start + 1 

91 while pos < maximum: 

92 if state.src[pos] != marker_chr: 

93 break 

94 pos += 1 

95 

96 # closing code fence must be at least as long as the opening one 

97 if (pos - start) < marker_count: 

98 continue 

99 

100 # make sure tail has spaces only 

101 pos = state.skipSpaces(pos) 

102 

103 if pos < maximum: 

104 continue 

105 

106 # found! 

107 auto_closed = True 

108 break 

109 

110 old_parent = state.parentType 

111 old_line_max = state.lineMax 

112 state.parentType = "container" 

113 

114 # this will prevent lazy continuations from ever going past our end marker 

115 state.lineMax = nextLine 

116 

117 token = state.push("front_matter", "", 0) 

118 token.hidden = True 

119 token.markup = marker_chr * min_markers 

120 token.content = state.src[state.bMarks[startLine + 1] : state.eMarks[nextLine - 1]] 

121 token.block = True 

122 

123 state.parentType = old_parent 

124 state.lineMax = old_line_max 

125 state.line = nextLine + (1 if auto_closed else 0) 

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

127 

128 return True