Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/mdit_py_plugins/front_matter/index.py: 98%
64 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:15 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:15 +0000
1"""Process front matter."""
2from markdown_it import MarkdownIt
3from markdown_it.rules_block import StateBlock
5from mdit_py_plugins.utils import is_code_block
8def front_matter_plugin(md: MarkdownIt) -> None:
9 """Plugin ported from
10 `markdown-it-front-matter <https://github.com/ParkSB/markdown-it-front-matter>`__.
12 It parses initial metadata, stored between opening/closing dashes:
14 .. code-block:: md
16 ---
17 valid-front-matter: true
18 ---
20 """
21 md.block.ruler.before(
22 "table",
23 "front_matter",
24 _front_matter_rule,
25 {"alt": ["paragraph", "reference", "blockquote", "list"]},
26 )
29def _front_matter_rule(
30 state: StateBlock, startLine: int, endLine: int, silent: bool
31) -> bool:
32 marker_chr = "-"
33 min_markers = 3
35 auto_closed = False
36 start = state.bMarks[startLine] + state.tShift[startLine]
37 maximum = state.eMarks[startLine]
38 src_len = len(state.src)
40 # Check out the first character of the first line quickly,
41 # this should filter out non-front matter
42 if startLine != 0 or state.src[0] != marker_chr:
43 return False
45 # Check out the rest of the marker string
46 # while pos <= 3
47 pos = start + 1
48 while pos <= maximum and pos < src_len:
49 if state.src[pos] != marker_chr:
50 break
51 pos += 1
53 marker_count = pos - start
55 if marker_count < min_markers:
56 return False
58 # Since start is found, we can report success here in validation mode
59 if silent:
60 return True
62 # Search for the end of the block
63 nextLine = startLine
65 while True:
66 nextLine += 1
67 if nextLine >= endLine:
68 # unclosed block should be autoclosed by end of document.
69 return False
71 if state.src[start:maximum] == "...":
72 break
74 start = state.bMarks[nextLine] + state.tShift[nextLine]
75 maximum = state.eMarks[nextLine]
77 if start < maximum and state.sCount[nextLine] < state.blkIndent:
78 # non-empty line with negative indent should stop the list:
79 # - ```
80 # test
81 break
83 if state.src[start] != marker_chr:
84 continue
86 if is_code_block(state, nextLine):
87 continue
89 pos = start + 1
90 while pos < maximum:
91 if state.src[pos] != marker_chr:
92 break
93 pos += 1
95 # closing code fence must be at least as long as the opening one
96 if (pos - start) < marker_count:
97 continue
99 # make sure tail has spaces only
100 pos = state.skipSpaces(pos)
102 if pos < maximum:
103 continue
105 # found!
106 auto_closed = True
107 break
109 old_parent = state.parentType
110 old_line_max = state.lineMax
111 state.parentType = "container"
113 # this will prevent lazy continuations from ever going past our end marker
114 state.lineMax = nextLine
116 token = state.push("front_matter", "", 0)
117 token.hidden = True
118 token.markup = marker_chr * min_markers
119 token.content = state.src[state.bMarks[startLine + 1] : state.eMarks[nextLine - 1]]
120 token.block = True
122 state.parentType = old_parent
123 state.lineMax = old_line_max
124 state.line = nextLine + (1 if auto_closed else 0)
125 token.map = [startLine, state.line]
127 return True