1# Process [link](<to> "stuff") 
    2 
    3from ..common.utils import isStrSpace, normalizeReference 
    4from .state_inline import StateInline 
    5 
    6 
    7def link(state: StateInline, silent: bool) -> bool: 
    8    href = "" 
    9    title = "" 
    10    label = None 
    11    oldPos = state.pos 
    12    maximum = state.posMax 
    13    start = state.pos 
    14    parseReference = True 
    15 
    16    if state.src[state.pos] != "[": 
    17        return False 
    18 
    19    labelStart = state.pos + 1 
    20    labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, True) 
    21 
    22    # parser failed to find ']', so it's not a valid link 
    23    if labelEnd < 0: 
    24        return False 
    25 
    26    pos = labelEnd + 1 
    27 
    28    if pos < maximum and state.src[pos] == "(": 
    29        # 
    30        # Inline link 
    31        # 
    32 
    33        # might have found a valid shortcut link, disable reference parsing 
    34        parseReference = False 
    35 
    36        # [link](  <href>  "title"  ) 
    37        #        ^^ skipping these spaces 
    38        pos += 1 
    39        while pos < maximum: 
    40            ch = state.src[pos] 
    41            if not isStrSpace(ch) and ch != "\n": 
    42                break 
    43            pos += 1 
    44 
    45        if pos >= maximum: 
    46            return False 
    47 
    48        # [link](  <href>  "title"  ) 
    49        #          ^^^^^^ parsing link destination 
    50        start = pos 
    51        res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax) 
    52        if res.ok: 
    53            href = state.md.normalizeLink(res.str) 
    54            if state.md.validateLink(href): 
    55                pos = res.pos 
    56            else: 
    57                href = "" 
    58 
    59            # [link](  <href>  "title"  ) 
    60            #                ^^ skipping these spaces 
    61            start = pos 
    62            while pos < maximum: 
    63                ch = state.src[pos] 
    64                if not isStrSpace(ch) and ch != "\n": 
    65                    break 
    66                pos += 1 
    67 
    68            # [link](  <href>  "title"  ) 
    69            #                  ^^^^^^^ parsing link title 
    70            res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax) 
    71            if pos < maximum and start != pos and res.ok: 
    72                title = res.str 
    73                pos = res.pos 
    74 
    75                # [link](  <href>  "title"  ) 
    76                #                         ^^ skipping these spaces 
    77                while pos < maximum: 
    78                    ch = state.src[pos] 
    79                    if not isStrSpace(ch) and ch != "\n": 
    80                        break 
    81                    pos += 1 
    82 
    83        if pos >= maximum or state.src[pos] != ")": 
    84            # parsing a valid shortcut link failed, fallback to reference 
    85            parseReference = True 
    86 
    87        pos += 1 
    88 
    89    if parseReference: 
    90        # 
    91        # Link reference 
    92        # 
    93        if "references" not in state.env: 
    94            return False 
    95 
    96        if pos < maximum and state.src[pos] == "[": 
    97            start = pos + 1 
    98            pos = state.md.helpers.parseLinkLabel(state, pos) 
    99            if pos >= 0: 
    100                label = state.src[start:pos] 
    101                pos += 1 
    102            else: 
    103                pos = labelEnd + 1 
    104 
    105        else: 
    106            pos = labelEnd + 1 
    107 
    108        # covers label == '' and label == undefined 
    109        # (collapsed reference link and shortcut reference link respectively) 
    110        if not label: 
    111            label = state.src[labelStart:labelEnd] 
    112 
    113        label = normalizeReference(label) 
    114 
    115        ref = state.env["references"].get(label, None) 
    116        if not ref: 
    117            state.pos = oldPos 
    118            return False 
    119 
    120        href = ref["href"] 
    121        title = ref["title"] 
    122 
    123    # 
    124    # We found the end of the link, and know for a fact it's a valid link 
    125    # so all that's left to do is to call tokenizer. 
    126    # 
    127    if not silent: 
    128        state.pos = labelStart 
    129        state.posMax = labelEnd 
    130 
    131        token = state.push("link_open", "a", 1) 
    132        token.attrs = {"href": href} 
    133 
    134        if title: 
    135            token.attrSet("title", title) 
    136 
    137        # note, this is not part of markdown-it JS, but is useful for renderers 
    138        if label and state.md.options.get("store_labels", False): 
    139            token.meta["label"] = label 
    140 
    141        state.linkLevel += 1 
    142        state.md.inline.tokenize(state) 
    143        state.linkLevel -= 1 
    144 
    145        token = state.push("link_close", "a", -1) 
    146 
    147    state.pos = pos 
    148    state.posMax = maximum 
    149    return True