Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/markdown_it/rules_core/linkify.py: 13%

89 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:07 +0000

1import re 

2 

3from ..common.utils import arrayReplaceAt 

4from ..token import Token 

5from .state_core import StateCore 

6 

7LINK_OPEN_RE = re.compile(r"^<a[>\s]", flags=re.IGNORECASE) 

8LINK_CLOSE_RE = re.compile(r"^</a\s*>", flags=re.IGNORECASE) 

9 

10HTTP_RE = re.compile(r"^http://") 

11MAILTO_RE = re.compile(r"^mailto:") 

12TEST_MAILTO_RE = re.compile(r"^mailto:", flags=re.IGNORECASE) 

13 

14 

15def isLinkOpen(string: str) -> bool: 

16 return bool(LINK_OPEN_RE.search(string)) 

17 

18 

19def isLinkClose(string: str) -> bool: 

20 return bool(LINK_CLOSE_RE.search(string)) 

21 

22 

23def linkify(state: StateCore) -> None: 

24 blockTokens = state.tokens 

25 

26 if not state.md.options.linkify: 

27 return 

28 

29 if not state.md.linkify: 

30 raise ModuleNotFoundError("Linkify enabled but not installed.") 

31 

32 for j in range(len(blockTokens)): 

33 if blockTokens[j].type != "inline" or not state.md.linkify.pretest( 

34 blockTokens[j].content 

35 ): 

36 continue 

37 

38 tokens = blockTokens[j].children 

39 

40 htmlLinkLevel = 0 

41 

42 # We scan from the end, to keep position when new tags added. 

43 # Use reversed logic in links start/end match 

44 assert tokens is not None 

45 i = len(tokens) 

46 while i >= 1: 

47 i -= 1 

48 assert isinstance(tokens, list) 

49 currentToken = tokens[i] 

50 

51 # Skip content of markdown links 

52 if currentToken.type == "link_close": 

53 i -= 1 

54 while ( 

55 tokens[i].level != currentToken.level 

56 and tokens[i].type != "link_open" 

57 ): 

58 i -= 1 

59 continue 

60 

61 # Skip content of html tag links 

62 if currentToken.type == "html_inline": 

63 if isLinkOpen(currentToken.content) and htmlLinkLevel > 0: 

64 htmlLinkLevel -= 1 

65 if isLinkClose(currentToken.content): 

66 htmlLinkLevel += 1 

67 if htmlLinkLevel > 0: 

68 continue 

69 

70 if currentToken.type == "text" and state.md.linkify.test( 

71 currentToken.content 

72 ): 

73 text = currentToken.content 

74 links = state.md.linkify.match(text) 

75 

76 # Now split string to nodes 

77 nodes = [] 

78 level = currentToken.level 

79 lastPos = 0 

80 

81 for ln in range(len(links)): 

82 url = links[ln].url 

83 fullUrl = state.md.normalizeLink(url) 

84 if not state.md.validateLink(fullUrl): 

85 continue 

86 

87 urlText = links[ln].text 

88 

89 # Linkifier might send raw hostnames like "example.com", where url 

90 # starts with domain name. So we prepend http:// in those cases, 

91 # and remove it afterwards. 

92 if not links[ln].schema: 

93 urlText = HTTP_RE.sub( 

94 "", state.md.normalizeLinkText("http://" + urlText) 

95 ) 

96 elif links[ln].schema == "mailto:" and TEST_MAILTO_RE.search( 

97 urlText 

98 ): 

99 urlText = MAILTO_RE.sub( 

100 "", state.md.normalizeLinkText("mailto:" + urlText) 

101 ) 

102 else: 

103 urlText = state.md.normalizeLinkText(urlText) 

104 

105 pos = links[ln].index 

106 

107 if pos > lastPos: 

108 token = Token("text", "", 0) 

109 token.content = text[lastPos:pos] 

110 token.level = level 

111 nodes.append(token) 

112 

113 token = Token("link_open", "a", 1) 

114 token.attrs = {"href": fullUrl} 

115 token.level = level 

116 level += 1 

117 token.markup = "linkify" 

118 token.info = "auto" 

119 nodes.append(token) 

120 

121 token = Token("text", "", 0) 

122 token.content = urlText 

123 token.level = level 

124 nodes.append(token) 

125 

126 token = Token("link_close", "a", -1) 

127 level -= 1 

128 token.level = level 

129 token.markup = "linkify" 

130 token.info = "auto" 

131 nodes.append(token) 

132 

133 lastPos = links[ln].last_index 

134 

135 if lastPos < len(text): 

136 token = Token("text", "", 0) 

137 token.content = text[lastPos:] 

138 token.level = level 

139 nodes.append(token) 

140 

141 blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes)