1"""Parse link title"""
2
3from ..common.utils import charCodeAt, unescapeAll
4
5
6class _State:
7 __slots__ = ("can_continue", "marker", "ok", "pos", "str")
8
9 def __init__(self) -> None:
10 self.ok = False
11 """if `true`, this is a valid link title"""
12 self.can_continue = False
13 """if `true`, this link can be continued on the next line"""
14 self.pos = 0
15 """if `ok`, it's the position of the first character after the closing marker"""
16 self.str = ""
17 """if `ok`, it's the unescaped title"""
18 self.marker = 0
19 """expected closing marker character code"""
20
21 def __str__(self) -> str:
22 return self.str
23
24
25def parseLinkTitle(
26 string: str, start: int, maximum: int, prev_state: _State | None = None
27) -> _State:
28 """Parse link title within `str` in [start, max] range,
29 or continue previous parsing if `prev_state` is defined (equal to result of last execution).
30 """
31 pos = start
32 state = _State()
33
34 if prev_state is not None:
35 # this is a continuation of a previous parseLinkTitle call on the next line,
36 # used in reference links only
37 state.str = prev_state.str
38 state.marker = prev_state.marker
39 else:
40 if pos >= maximum:
41 return state
42
43 marker = charCodeAt(string, pos)
44
45 # /* " */ /* ' */ /* ( */
46 if marker != 0x22 and marker != 0x27 and marker != 0x28:
47 return state
48
49 start += 1
50 pos += 1
51
52 # if opening marker is "(", switch it to closing marker ")"
53 if marker == 0x28:
54 marker = 0x29
55
56 state.marker = marker
57
58 while pos < maximum:
59 code = charCodeAt(string, pos)
60 if code == state.marker:
61 state.pos = pos + 1
62 state.str += unescapeAll(string[start:pos])
63 state.ok = True
64 return state
65 elif code == 0x28 and state.marker == 0x29: # /* ( */ /* ) */
66 return state
67 elif code == 0x5C and pos + 1 < maximum: # /* \ */
68 pos += 1
69
70 pos += 1
71
72 # no closing marker found, but this link title may continue on the next line (for references)
73 state.can_continue = True
74 state.str += unescapeAll(string[start:pos])
75 return state