1# lheading (---, ==) 
    2import logging 
    3 
    4from .state_block import StateBlock 
    5 
    6LOGGER = logging.getLogger(__name__) 
    7 
    8 
    9def lheading(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: 
    10    LOGGER.debug("entering lheading: %s, %s, %s, %s", state, startLine, endLine, silent) 
    11 
    12    level = None 
    13    nextLine = startLine + 1 
    14    ruler = state.md.block.ruler 
    15    terminatorRules = ruler.getRules("paragraph") 
    16 
    17    if state.is_code_block(startLine): 
    18        return False 
    19 
    20    oldParentType = state.parentType 
    21    state.parentType = "paragraph"  # use paragraph to match terminatorRules 
    22 
    23    # jump line-by-line until empty one or EOF 
    24    while nextLine < endLine and not state.isEmpty(nextLine): 
    25        # this would be a code block normally, but after paragraph 
    26        # it's considered a lazy continuation regardless of what's there 
    27        if state.sCount[nextLine] - state.blkIndent > 3: 
    28            nextLine += 1 
    29            continue 
    30 
    31        # Check for underline in setext header 
    32        if state.sCount[nextLine] >= state.blkIndent: 
    33            pos = state.bMarks[nextLine] + state.tShift[nextLine] 
    34            maximum = state.eMarks[nextLine] 
    35 
    36            if pos < maximum: 
    37                marker = state.src[pos] 
    38 
    39                if marker in ("-", "="): 
    40                    pos = state.skipCharsStr(pos, marker) 
    41                    pos = state.skipSpaces(pos) 
    42 
    43                    # /* = */ 
    44                    if pos >= maximum: 
    45                        level = 1 if marker == "=" else 2 
    46                        break 
    47 
    48        # quirk for blockquotes, this line should already be checked by that rule 
    49        if state.sCount[nextLine] < 0: 
    50            nextLine += 1 
    51            continue 
    52 
    53        # Some tags can terminate paragraph without empty line. 
    54        terminate = False 
    55        for terminatorRule in terminatorRules: 
    56            if terminatorRule(state, nextLine, endLine, True): 
    57                terminate = True 
    58                break 
    59        if terminate: 
    60            break 
    61 
    62        nextLine += 1 
    63 
    64    if not level: 
    65        # Didn't find valid underline 
    66        return False 
    67 
    68    content = state.getLines(startLine, nextLine, state.blkIndent, False).strip() 
    69 
    70    state.line = nextLine + 1 
    71 
    72    token = state.push("heading_open", "h" + str(level), 1) 
    73    token.markup = marker 
    74    token.map = [startLine, state.line] 
    75 
    76    token = state.push("inline", "", 0) 
    77    token.content = content 
    78    token.map = [startLine, state.line - 1] 
    79    token.children = [] 
    80 
    81    token = state.push("heading_close", "h" + str(level), -1) 
    82    token.markup = marker 
    83 
    84    state.parentType = oldParentType 
    85 
    86    return True