1# HTML block 
    2from __future__ import annotations 
    3 
    4import logging 
    5import re 
    6 
    7from ..common.html_blocks import block_names 
    8from ..common.html_re import HTML_OPEN_CLOSE_TAG_STR 
    9from .state_block import StateBlock 
    10 
    11LOGGER = logging.getLogger(__name__) 
    12 
    13# An array of opening and corresponding closing sequences for html tags, 
    14# last argument defines whether it can terminate a paragraph or not 
    15HTML_SEQUENCES: list[tuple[re.Pattern[str], re.Pattern[str], bool]] = [ 
    16    ( 
    17        re.compile(r"^<(script|pre|style|textarea)(?=(\s|>|$))", re.IGNORECASE), 
    18        re.compile(r"<\/(script|pre|style|textarea)>", re.IGNORECASE), 
    19        True, 
    20    ), 
    21    (re.compile(r"^<!--"), re.compile(r"-->"), True), 
    22    (re.compile(r"^<\?"), re.compile(r"\?>"), True), 
    23    (re.compile(r"^<![A-Z]"), re.compile(r">"), True), 
    24    (re.compile(r"^<!\[CDATA\["), re.compile(r"\]\]>"), True), 
    25    ( 
    26        re.compile("^</?(" + "|".join(block_names) + ")(?=(\\s|/?>|$))", re.IGNORECASE), 
    27        re.compile(r"^$"), 
    28        True, 
    29    ), 
    30    (re.compile(HTML_OPEN_CLOSE_TAG_STR + "\\s*$"), re.compile(r"^$"), False), 
    31] 
    32 
    33 
    34def html_block(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: 
    35    LOGGER.debug( 
    36        "entering html_block: %s, %s, %s, %s", state, startLine, endLine, silent 
    37    ) 
    38    pos = state.bMarks[startLine] + state.tShift[startLine] 
    39    maximum = state.eMarks[startLine] 
    40 
    41    if state.is_code_block(startLine): 
    42        return False 
    43 
    44    if not state.md.options.get("html", None): 
    45        return False 
    46 
    47    if state.src[pos] != "<": 
    48        return False 
    49 
    50    lineText = state.src[pos:maximum] 
    51 
    52    html_seq = None 
    53    for HTML_SEQUENCE in HTML_SEQUENCES: 
    54        if HTML_SEQUENCE[0].search(lineText): 
    55            html_seq = HTML_SEQUENCE 
    56            break 
    57 
    58    if not html_seq: 
    59        return False 
    60 
    61    if silent: 
    62        # true if this sequence can be a terminator, false otherwise 
    63        return html_seq[2] 
    64 
    65    nextLine = startLine + 1 
    66 
    67    # If we are here - we detected HTML block. 
    68    # Let's roll down till block end. 
    69    if not html_seq[1].search(lineText): 
    70        while nextLine < endLine: 
    71            if state.sCount[nextLine] < state.blkIndent: 
    72                break 
    73 
    74            pos = state.bMarks[nextLine] + state.tShift[nextLine] 
    75            maximum = state.eMarks[nextLine] 
    76            lineText = state.src[pos:maximum] 
    77 
    78            if html_seq[1].search(lineText): 
    79                if len(lineText) != 0: 
    80                    nextLine += 1 
    81                break 
    82            nextLine += 1 
    83 
    84    state.line = nextLine 
    85 
    86    token = state.push("html_block", "", 0) 
    87    token.map = [startLine, nextLine] 
    88    token.content = state.getLines(startLine, nextLine, state.blkIndent, True) 
    89 
    90    return True