[文档]defblockquote(state:StateBlock,startLine:int,endLine:int,silent:bool):LOGGER.debug("entering blockquote: %s, %s, %s, %s",state,startLine,endLine,silent)oldLineMax=state.lineMaxpos=state.bMarks[startLine]+state.tShift[startLine]max=state.eMarks[startLine]# if it's indented more than 3 spaces, it should be a code blockif(state.sCount[startLine]-state.blkIndent)>=4:returnFalse# check the block quote markerifstate.srcCharCode[pos]!=0x3E:# /* > */returnFalsepos+=1# we know that it's going to be a valid blockquote,# so no point trying to find the end of it in silent modeifsilent:returnTrue# set offset past spaces and ">"initial=offset=state.sCount[startLine]+1try:second_char_code:Optional[int]=state.srcCharCode[pos]exceptIndexError:second_char_code=None# skip one optional space after '>'ifsecond_char_code==0x20:# /* space */# ' > test '# ^ -- position start of line here:pos+=1initial+=1offset+=1adjustTab=FalsespaceAfterMarker=Trueelifsecond_char_code==0x09:# /* tab */spaceAfterMarker=Trueif(state.bsCount[startLine]+offset)%4==3:# ' >\t test '# ^ -- position start of line here (tab has width==1)pos+=1initial+=1offset+=1adjustTab=Falseelse:# ' >\t test '# ^ -- position start of line here + shift bsCount slightly# to make extra space appearadjustTab=Trueelse:spaceAfterMarker=FalseoldBMarks=[state.bMarks[startLine]]state.bMarks[startLine]=poswhilepos<max:ch=state.srcCharCode[pos]ifisSpace(ch):ifch==0x09:# / tab /offset+=(4-(offset+state.bsCount[startLine]+(1ifadjustTabelse0))%4)else:offset+=1else:breakpos+=1oldBSCount=[state.bsCount[startLine]]state.bsCount[startLine]=(state.sCount[startLine]+1+(1ifspaceAfterMarkerelse0))lastLineEmpty=pos>=maxoldSCount=[state.sCount[startLine]]state.sCount[startLine]=offset-initialoldTShift=[state.tShift[startLine]]state.tShift[startLine]=pos-state.bMarks[startLine]terminatorRules=state.md.block.ruler.getRules("blockquote")oldParentType=state.parentTypestate.parentType="blockquote"# Search the end of the block## Block ends with either:# 1. an empty line outside:# ```# > test## ```# 2. an empty line inside:# ```# ># test# ```# 3. another tag:# ```# > test# - - -# ```# for (nextLine = startLine + 1; nextLine < endLine; nextLine++) {nextLine=startLine+1whilenextLine<endLine:# check if it's outdented, i.e. it's inside list item and indented# less than said list item:## ```# 1. anything# > current blockquote# 2. checking this line# ```isOutdented=state.sCount[nextLine]<state.blkIndentpos=state.bMarks[nextLine]+state.tShift[nextLine]max=state.eMarks[nextLine]ifpos>=max:# Case 1: line is not inside the blockquote, and this line is empty.breakevaluatesTrue=state.srcCharCode[pos]==0x3EandnotisOutdented# /* > */pos+=1ifevaluatesTrue:# This line is inside the blockquote.# set offset past spaces and ">"initial=offset=state.sCount[nextLine]+1# skip one optional space after '>'ifstate.srcCharCode[pos]==0x20:# /* space */# ' > test '# ^ -- position start of line here:pos+=1initial+=1offset+=1adjustTab=FalsespaceAfterMarker=Trueelifstate.srcCharCode[pos]==0x09:# /* tab */spaceAfterMarker=Trueif(state.bsCount[nextLine]+offset)%4==3:# ' >\t test '# ^ -- position start of line here (tab has width==1)pos+=1initial+=1offset+=1adjustTab=Falseelse:# ' >\t test '# ^ -- position start of line here + shift bsCount slightly# to make extra space appearadjustTab=Trueelse:spaceAfterMarker=FalseoldBMarks.append(state.bMarks[nextLine])state.bMarks[nextLine]=poswhilepos<max:ch=state.srcCharCode[pos]ifisSpace(ch):ifch==0x09:offset+=(4-(offset+state.bsCount[nextLine]+(1ifadjustTabelse0))%4)else:offset+=1else:breakpos+=1lastLineEmpty=pos>=maxoldBSCount.append(state.bsCount[nextLine])state.bsCount[nextLine]=(state.sCount[nextLine]+1+(1ifspaceAfterMarkerelse0))oldSCount.append(state.sCount[nextLine])state.sCount[nextLine]=offset-initialoldTShift.append(state.tShift[nextLine])state.tShift[nextLine]=pos-state.bMarks[nextLine]nextLine+=1continue# Case 2: line is not inside the blockquote, and the last line was empty.iflastLineEmpty:break# Case 3: another tag found.terminate=FalseforterminatorRuleinterminatorRules:ifterminatorRule(state,nextLine,endLine,True):terminate=Truebreakifterminate:# Quirk to enforce "hard termination mode" for paragraphs;# normally if you call `tokenize(state, startLine, nextLine)`,# paragraphs will look below nextLine for paragraph continuation,# but if blockquote is terminated by another tag, they shouldn'tstate.lineMax=nextLineifstate.blkIndent!=0:# state.blkIndent was non-zero, we now set it to zero,# so we need to re-calculate all offsets to appear as# if indent wasn't changedoldBMarks.append(state.bMarks[nextLine])oldBSCount.append(state.bsCount[nextLine])oldTShift.append(state.tShift[nextLine])oldSCount.append(state.sCount[nextLine])state.sCount[nextLine]-=state.blkIndentbreakoldBMarks.append(state.bMarks[nextLine])oldBSCount.append(state.bsCount[nextLine])oldTShift.append(state.tShift[nextLine])oldSCount.append(state.sCount[nextLine])# A negative indentation means that this is a paragraph continuation#state.sCount[nextLine]=-1nextLine+=1oldIndent=state.blkIndentstate.blkIndent=0token=state.push("blockquote_open","blockquote",1)token.markup=">"token.map=lines=[startLine,0]state.md.block.tokenize(state,startLine,nextLine)token=state.push("blockquote_close","blockquote",-1)token.markup=">"state.lineMax=oldLineMaxstate.parentType=oldParentTypelines[1]=state.line# Restore original tShift; this might not be necessary since the parser# has already been here, but just to make sure we can do that.fori,iteminenumerate(oldTShift):state.bMarks[i+startLine]=oldBMarks[i]state.tShift[i+startLine]=itemstate.sCount[i+startLine]=oldSCount[i]state.bsCount[i+startLine]=oldBSCount[i]state.blkIndent=oldIndentstate.lineMax+=1returnTrue