Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/markdown_it/rules_inline/balance_pairs.py: 98%

54 statements  

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

1# For each opening emphasis-like marker find a matching closing one 

2# 

3from .state_inline import StateInline 

4 

5 

6def processDelimiters(state: StateInline, delimiters, *args): 

7 openersBottom = {} 

8 maximum = len(delimiters) 

9 

10 closerIdx = 0 

11 while closerIdx < maximum: 

12 closer = delimiters[closerIdx] 

13 

14 # Length is only used for emphasis-specific "rule of 3", 

15 # if it's not defined (in strikethrough or 3rd party plugins), 

16 # we can default it to 0 to disable those checks. 

17 # 

18 closer.length = closer.length or 0 

19 

20 if not closer.close: 

21 closerIdx += 1 

22 continue 

23 

24 # Previously calculated lower bounds (previous fails) 

25 # for each marker, each delimiter length modulo 3, 

26 # and for whether this closer can be an opener; 

27 # https://github.com/commonmark/cmark/commit/34250e12ccebdc6372b8b49c44fab57c72443460 

28 if closer.marker not in openersBottom: 

29 openersBottom[closer.marker] = [-1, -1, -1, -1, -1, -1] 

30 

31 minOpenerIdx = openersBottom[closer.marker][ 

32 (3 if closer.open else 0) + (closer.length % 3) 

33 ] 

34 

35 openerIdx = closerIdx - closer.jump - 1 

36 

37 # avoid crash if `closer.jump` is pointing outside of the array, 

38 # e.g. for strikethrough 

39 if openerIdx < -1: 

40 openerIdx = -1 

41 

42 newMinOpenerIdx = openerIdx 

43 

44 while openerIdx > minOpenerIdx: 

45 opener = delimiters[openerIdx] 

46 

47 if opener.marker != closer.marker: 

48 openerIdx -= opener.jump + 1 

49 continue 

50 

51 if opener.open and opener.end < 0: 

52 isOddMatch = False 

53 

54 # from spec: 

55 # 

56 # If one of the delimiters can both open and close emphasis, then the 

57 # sum of the lengths of the delimiter runs containing the opening and 

58 # closing delimiters must not be a multiple of 3 unless both lengths 

59 # are multiples of 3. 

60 # 

61 if opener.close or closer.open: 

62 if (opener.length + closer.length) % 3 == 0: 

63 if opener.length % 3 != 0 or closer.length % 3 != 0: 

64 isOddMatch = True 

65 

66 if not isOddMatch: 

67 # If previous delimiter cannot be an opener, we can safely skip 

68 # the entire sequence in future checks. This is required to make 

69 # sure algorithm has linear complexity (see *_*_*_*_*_... case). 

70 # 

71 if openerIdx > 0 and not delimiters[openerIdx - 1].open: 

72 lastJump = delimiters[openerIdx - 1].jump + 1 

73 else: 

74 lastJump = 0 

75 

76 closer.jump = closerIdx - openerIdx + lastJump 

77 closer.open = False 

78 opener.end = closerIdx 

79 opener.jump = lastJump 

80 opener.close = False 

81 newMinOpenerIdx = -1 

82 break 

83 

84 openerIdx -= opener.jump + 1 

85 

86 if newMinOpenerIdx != -1: 

87 # If match for this delimiter run failed, we want to set lower bound for 

88 # future lookups. This is required to make sure algorithm has linear 

89 # complexity. 

90 # 

91 # See details here: 

92 # https:#github.com/commonmark/cmark/issues/178#issuecomment-270417442 

93 # 

94 openersBottom[closer.marker][ 

95 (3 if closer.open else 0) + ((closer.length or 0) % 3) 

96 ] = newMinOpenerIdx 

97 

98 closerIdx += 1 

99 

100 

101def link_pairs(state: StateInline) -> None: 

102 tokens_meta = state.tokens_meta 

103 maximum = len(state.tokens_meta) 

104 

105 processDelimiters(state, state.delimiters) 

106 

107 curr = 0 

108 while curr < maximum: 

109 curr_meta = tokens_meta[curr] 

110 if curr_meta and "delimiters" in curr_meta: 

111 processDelimiters(state, curr_meta["delimiters"]) 

112 curr += 1