Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
reference.py236 linesDownload Raw Back to rules_block
1import logging2 3from ..common.utils import charCodeAt, isSpace, normalizeReference4from .state_block import StateBlock5 6LOGGER = logging.getLogger(__name__)7 8 9def reference(state: StateBlock, startLine: int, _endLine: int, silent: bool) -> bool:10    LOGGER.debug(11        "entering reference: %s, %s, %s, %s", state, startLine, _endLine, silent12    )13 14    pos = state.bMarks[startLine] + state.tShift[startLine]15    maximum = state.eMarks[startLine]16    nextLine = startLine + 117 18    if state.is_code_block(startLine):19        return False20 21    if state.src[pos] != "[":22        return False23 24    string = state.src[pos : maximum + 1]25 26    # string = state.getLines(startLine, nextLine, state.blkIndent, False).strip()27    maximum = len(string)28 29    labelEnd = None30    pos = 131    while pos < maximum:32        ch = charCodeAt(string, pos)33        if ch == 0x5B:  # /* [ */34            return False35        elif ch == 0x5D:  # /* ] */36            labelEnd = pos37            break38        elif ch == 0x0A:  # /* \n */39            if (lineContent := getNextLine(state, nextLine)) is not None:40                string += lineContent41                maximum = len(string)42                nextLine += 143        elif ch == 0x5C:  # /* \ */44            pos += 145            if (46                pos < maximum47                and charCodeAt(string, pos) == 0x0A48                and (lineContent := getNextLine(state, nextLine)) is not None49            ):50                string += lineContent51                maximum = len(string)52                nextLine += 153        pos += 154 55    if (56        labelEnd is None or labelEnd < 0 or charCodeAt(string, labelEnd + 1) != 0x3A57    ):  # /* : */58        return False59 60    # [label]:   destination   'title'61    #         ^^^ skip optional whitespace here62    pos = labelEnd + 263    while pos < maximum:64        ch = charCodeAt(string, pos)65        if ch == 0x0A:66            if (lineContent := getNextLine(state, nextLine)) is not None:67                string += lineContent68                maximum = len(string)69                nextLine += 170        elif isSpace(ch):71            pass72        else:73            break74        pos += 175 76    # [label]:   destination   'title'77    #            ^^^^^^^^^^^ parse this78    destRes = state.md.helpers.parseLinkDestination(string, pos, maximum)79    if not destRes.ok:80        return False81 82    href = state.md.normalizeLink(destRes.str)83    if not state.md.validateLink(href):84        return False85 86    pos = destRes.pos87 88    # save cursor state, we could require to rollback later89    destEndPos = pos90    destEndLineNo = nextLine91 92    # [label]:   destination   'title'93    #                       ^^^ skipping those spaces94    start = pos95    while pos < maximum:96        ch = charCodeAt(string, pos)97        if ch == 0x0A:98            if (lineContent := getNextLine(state, nextLine)) is not None:99                string += lineContent100                maximum = len(string)101                nextLine += 1102        elif isSpace(ch):103            pass104        else:105            break106        pos += 1107 108    # [label]:   destination   'title'109    #                          ^^^^^^^ parse this110    titleRes = state.md.helpers.parseLinkTitle(string, pos, maximum, None)111    while titleRes.can_continue:112        if (lineContent := getNextLine(state, nextLine)) is None:113            break114        string += lineContent115        pos = maximum116        maximum = len(string)117        nextLine += 1118        titleRes = state.md.helpers.parseLinkTitle(string, pos, maximum, titleRes)119 120    if pos < maximum and start != pos and titleRes.ok:121        title = titleRes.str122        pos = titleRes.pos123    else:124        title = ""125        pos = destEndPos126        nextLine = destEndLineNo127 128    # skip trailing spaces until the rest of the line129    while pos < maximum:130        ch = charCodeAt(string, pos)131        if not isSpace(ch):132            break133        pos += 1134 135    if pos < maximum and charCodeAt(string, pos) != 0x0A and title:136        # garbage at the end of the line after title,137        # but it could still be a valid reference if we roll back138        title = ""139        pos = destEndPos140        nextLine = destEndLineNo141        while pos < maximum:142            ch = charCodeAt(string, pos)143            if not isSpace(ch):144                break145            pos += 1146 147    if pos < maximum and charCodeAt(string, pos) != 0x0A:148        # garbage at the end of the line149        return False150 151    label = normalizeReference(string[1:labelEnd])152    if not label:153        # CommonMark 0.20 disallows empty labels154        return False155 156    # Reference can not terminate anything. This check is for safety only.157    if silent:158        return True159 160    if "references" not in state.env:161        state.env["references"] = {}162 163    state.line = nextLine164 165    # note, this is not part of markdown-it JS, but is useful for renderers166    if state.md.options.get("inline_definitions", False):167        token = state.push("definition", "", 0)168        token.meta = {169            "id": label,170            "title": title,171            "url": href,172            "label": string[1:labelEnd],173        }174        token.map = [startLine, state.line]175 176    if label not in state.env["references"]:177        state.env["references"][label] = {178            "title": title,179            "href": href,180            "map": [startLine, state.line],181        }182    else:183        state.env.setdefault("duplicate_refs", []).append(184            {185                "title": title,186                "href": href,187                "label": label,188                "map": [startLine, state.line],189            }190        )191 192    return True193 194 195def getNextLine(state: StateBlock, nextLine: int) -> None | str:196    endLine = state.lineMax197 198    if nextLine >= endLine or state.isEmpty(nextLine):199        # empty line or end of input200        return None201 202    isContinuation = False203 204    # this would be a code block normally, but after paragraph205    # it's considered a lazy continuation regardless of what's there206    if state.is_code_block(nextLine):207        isContinuation = True208 209    # quirk for blockquotes, this line should already be checked by that rule210    if state.sCount[nextLine] < 0:211        isContinuation = True212 213    if not isContinuation:214        terminatorRules = state.md.block.ruler.getRules("reference")215        oldParentType = state.parentType216        state.parentType = "reference"217 218        # Some tags can terminate paragraph without empty line.219        terminate = False220        for terminatorRule in terminatorRules:221            if terminatorRule(state, nextLine, endLine, True):222                terminate = True223                break224 225        state.parentType = oldParentType226 227        if terminate:228            # terminated by another block229            return None230 231    pos = state.bMarks[nextLine] + state.tShift[nextLine]232    maximum = state.eMarks[nextLine]233 234    # max + 1 explicitly includes the newline235    return state.src[pos : maximum + 1]236 
codekingpro/portable-devtools · Team Ai