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

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

46 statements  

1import re 

2from typing import TYPE_CHECKING, Sequence 

3 

4from markdown_it import MarkdownIt 

5from markdown_it.common.utils import escapeHtml 

6from markdown_it.rules_inline import StateInline 

7 

8if TYPE_CHECKING: 

9 from markdown_it.renderer import RendererProtocol 

10 from markdown_it.token import Token 

11 from markdown_it.utils import EnvType, OptionsDict 

12 

13VALID_NAME_PATTERN = re.compile(r"^\{([a-zA-Z0-9\_\-\+\:]+)\}") 

14 

15 

16def myst_role_plugin(md: MarkdownIt) -> None: 

17 """Parse ``{role-name}`content```""" 

18 md.inline.ruler.before("backticks", "myst_role", myst_role) 

19 md.add_render_rule("myst_role", render_myst_role) 

20 

21 

22def myst_role(state: StateInline, silent: bool) -> bool: 

23 # check name 

24 match = VALID_NAME_PATTERN.match(state.src[state.pos :]) 

25 if not match: 

26 return False 

27 name = match.group(1) 

28 

29 # check for starting backslash escape 

30 try: 

31 if state.src[state.pos - 1] == "\\": 

32 # escaped (this could be improved in the case of edge case '\\{') 

33 return False 

34 except IndexError: 

35 pass 

36 

37 # scan opening tick length 

38 start = pos = state.pos + match.end() 

39 try: 

40 while state.src[pos] == "`": 

41 pos += 1 

42 except IndexError: 

43 return False 

44 

45 tick_length = pos - start 

46 if not tick_length: 

47 return False 

48 

49 # search for closing ticks 

50 match = re.search("`" * tick_length, state.src[pos + 1 :]) 

51 if not match: 

52 return False 

53 content = state.src[pos : pos + match.start() + 1].replace("\n", " ") 

54 

55 if not silent: 

56 token = state.push("myst_role", "", 0) 

57 token.meta = {"name": name} 

58 token.content = content 

59 

60 state.pos = pos + match.end() + 1 

61 

62 return True 

63 

64 

65def render_myst_role( 

66 self: "RendererProtocol", 

67 tokens: Sequence["Token"], 

68 idx: int, 

69 options: "OptionsDict", 

70 env: "EnvType", 

71) -> str: 

72 token = tokens[idx] 

73 name = token.meta.get("name", "unknown") 

74 return f'<code class="myst role">{{{name}}}[{escapeHtml(token.content)}]</code>'