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