From eafe1bf8d8c60126483d68a13c5588d65d85de04 Mon Sep 17 00:00:00 2001 From: Sourcery AI <> Date: Thu, 17 Feb 2022 00:24:57 +0000 Subject: [PATCH] 'Refactored by Sourcery' --- markdown_it/common/html_re.py | 9 +-- markdown_it/common/normalize_url.py | 22 ++----- markdown_it/common/utils.py | 7 +-- markdown_it/helpers/parse_link_destination.py | 4 +- markdown_it/helpers/parse_link_label.py | 12 ++-- markdown_it/helpers/parse_link_title.py | 2 +- markdown_it/main.py | 6 +- markdown_it/renderer.py | 62 +++++++------------ markdown_it/ruler.py | 11 ++-- markdown_it/rules_block/blockquote.py | 57 ++++++++--------- markdown_it/rules_block/fence.py | 7 +-- markdown_it/rules_block/heading.py | 4 +- markdown_it/rules_block/hr.py | 2 +- markdown_it/rules_block/html_block.py | 23 ++++--- markdown_it/rules_block/lheading.py | 17 +++-- markdown_it/rules_block/list.py | 54 ++++++---------- markdown_it/rules_block/paragraph.py | 12 ++-- markdown_it/rules_block/reference.py | 43 +++++-------- markdown_it/rules_block/state_block.py | 5 +- markdown_it/rules_block/table.py | 17 +++-- markdown_it/rules_core/replacements.py | 49 ++++++++------- markdown_it/rules_core/smartquotes.py | 42 ++++++++----- markdown_it/rules_inline/autolink.py | 2 +- markdown_it/rules_inline/balance_pairs.py | 26 +++----- markdown_it/rules_inline/emphasis.py | 4 +- markdown_it/rules_inline/entity.py | 17 +++-- markdown_it/rules_inline/link.py | 32 ++++------ markdown_it/rules_inline/state_inline.py | 30 +++++---- markdown_it/rules_inline/strikethrough.py | 4 +- markdown_it/tree.py | 14 ++--- tests/test_port/test_misc.py | 2 +- 31 files changed, 256 insertions(+), 342 deletions(-) diff --git a/markdown_it/common/html_re.py b/markdown_it/common/html_re.py index f0c336d2..54b09c1a 100644 --- a/markdown_it/common/html_re.py +++ b/markdown_it/common/html_re.py @@ -1,6 +1,7 @@ """Regexps to match html elements """ + import re attr_name = "[a-zA-Z_:][a-zA-Z0-9:._-]*" @@ -9,11 +10,11 @@ single_quoted = "'[^']*'" double_quoted = '"[^"]*"' -attr_value = "(?:" + unquoted + "|" + single_quoted + "|" + double_quoted + ")" +attr_value = f'(?:{unquoted}|{single_quoted}|{double_quoted})' -attribute = "(?:\\s+" + attr_name + "(?:\\s*=\\s*" + attr_value + ")?)" +attribute = f'(?:\\s+{attr_name}(?:\\s*=\\s*{attr_value})?)' -open_tag = "<[A-Za-z][A-Za-z0-9\\-]*" + attribute + "*\\s*\\/?>" +open_tag = f'<[A-Za-z][A-Za-z0-9\\-]*{attribute}*\\s*\\/?>' close_tag = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>" comment = "|" @@ -36,5 +37,5 @@ + cdata + ")" ) -HTML_OPEN_CLOSE_TAG_STR = "^(?:" + open_tag + "|" + close_tag + ")" +HTML_OPEN_CLOSE_TAG_STR = f'^(?:{open_tag}|{close_tag})' HTML_OPEN_CLOSE_TAG_RE = re.compile(HTML_OPEN_CLOSE_TAG_STR) diff --git a/markdown_it/common/normalize_url.py b/markdown_it/common/normalize_url.py index d150ca36..9fd44d4a 100644 --- a/markdown_it/common/normalize_url.py +++ b/markdown_it/common/normalize_url.py @@ -39,10 +39,7 @@ def unescape_char(s: str) -> str: - if s[0] == "\\": - return s[1] - else: - return html.unescape(s) + return s[1] if s[0] == "\\" else html.unescape(s) def unescape_string(s: str) -> str: @@ -76,8 +73,7 @@ def normalizeLink(url: str) -> str: ^^^^^^^^^^^ """ (scheme, netloc, path, params, query, fragment) = urlparse(url) - if scheme in RECODE_HOSTNAME_FOR: - url = urlunparse( + return urlunparse( ( scheme, unescape_normalize_uri(netloc), @@ -86,11 +82,7 @@ def normalizeLink(url: str) -> str: normalize_uri(query), unescape_normalize_uri(fragment), ) - ) - else: - url = unescape_normalize_uri(url) - - return url + ) if scheme in RECODE_HOSTNAME_FOR else unescape_normalize_uri(url) # TODO the selective encoding below should probably be done here, # something like: @@ -126,8 +118,7 @@ def normalizeLinkText(link: str) -> str: ~~~~~~~~~~~ """ (scheme, netloc, path, params, query, fragment) = urlparse(link) - if scheme in RECODE_HOSTNAME_FOR: - url = urlunparse( + return urlunparse( ( scheme, unescape_unquote(netloc), @@ -136,10 +127,7 @@ def normalizeLinkText(link: str) -> str: unquote(query), unescape_unquote(fragment), ) - ) - else: - url = unescape_unquote(link) - return url + ) if scheme in RECODE_HOSTNAME_FOR else unescape_unquote(link) # TODO the selective encoding below should probably be done here, # something like: diff --git a/markdown_it/common/utils.py b/markdown_it/common/utils.py index 8b2c4a7f..ecadceca 100644 --- a/markdown_it/common/utils.py +++ b/markdown_it/common/utils.py @@ -75,7 +75,7 @@ def isValidEntityCode(c: int) -> bool: # never used if c >= 0xFDD0 and c <= 0xFDEF: return False - if ((c & 0xFFFF) == 0xFFFF) or ((c & 0xFFFF) == 0xFFFE): + if c & 0xFFFF in [0xFFFF, 0xFFFE]: return False # control codes if c >= 0x00 and c <= 0x08: @@ -150,7 +150,7 @@ def unescapeAll(string: str) -> str: ESCAPABLE = r"""\\!"#$%&'()*+,./:;<=>?@\[\]^`{}|_~-""" -ESCAPE_CHAR = re.compile(r"\\([" + ESCAPABLE + r"])") +ESCAPE_CHAR = re.compile(f'\\\\([{ESCAPABLE}])') def stripEscape(string: str) -> str: @@ -190,8 +190,7 @@ def escapeHtml(raw: str) -> str: def escapeRE(string: str) -> str: - string = REGEXP_ESCAPE_RE.sub("\\$&", string) - return string + return REGEXP_ESCAPE_RE.sub("\\$&", string) # ////////////////////////////////////////////////////////////////////////////// diff --git a/markdown_it/helpers/parse_link_destination.py b/markdown_it/helpers/parse_link_destination.py index 74dbec08..d8f44b4c 100644 --- a/markdown_it/helpers/parse_link_destination.py +++ b/markdown_it/helpers/parse_link_destination.py @@ -62,12 +62,12 @@ def parseLinkDestination(string: str, pos: int, maximum: int) -> _Result: pos += 2 continue - if code == 0x28: # /* ( */) + if code == 0x28: level += 1 if level > 32: return result - if code == 0x29: # /* ) */) + elif code == 0x29: if level == 0: break level -= 1 diff --git a/markdown_it/helpers/parse_link_label.py b/markdown_it/helpers/parse_link_label.py index 20e3c148..cb047350 100644 --- a/markdown_it/helpers/parse_link_label.py +++ b/markdown_it/helpers/parse_link_label.py @@ -10,7 +10,6 @@ def parseLinkLabel(state: StateInline, start: int, disableNested: bool = False) -> int: - labelEnd = -1 oldPos = state.pos found = False @@ -27,17 +26,16 @@ def parseLinkLabel(state: StateInline, start: int, disableNested: bool = False) prevPos = state.pos state.md.inline.skipToken(state) - if marker == 0x5B: # /* [ */) - if prevPos == state.pos - 1: + if prevPos == state.pos - 1: + if marker == 0x5B: # increase level if we find text `[`, # which is not a part of any token level += 1 - elif disableNested: + elif disableNested: + if marker == 0x5B: state.pos = oldPos return -1 - if found: - labelEnd = state.pos - + labelEnd = state.pos if found else -1 # restore old state state.pos = oldPos diff --git a/markdown_it/helpers/parse_link_title.py b/markdown_it/helpers/parse_link_title.py index 4aa67e88..e0843066 100644 --- a/markdown_it/helpers/parse_link_title.py +++ b/markdown_it/helpers/parse_link_title.py @@ -27,7 +27,7 @@ def parseLinkTitle(string: str, pos: int, maximum: int) -> _Result: marker = charCodeAt(string, pos) # /* " */ /* ' */ /* ( */ - if marker != 0x22 and marker != 0x27 and marker != 0x28: + if marker not in [0x22, 0x27, 0x28]: return result pos += 1 diff --git a/markdown_it/main.py b/markdown_it/main.py index e87a7a44..fde2666d 100644 --- a/markdown_it/main.py +++ b/markdown_it/main.py @@ -122,11 +122,9 @@ def configure( if "components" in config: for name, component in config["components"].items(): - rules = component.get("rules", None) - if rules: + if rules := component.get("rules", None): self[name].ruler.enableOnly(rules) - rules2 = component.get("rules2", None) - if rules2: + if rules2 := component.get("rules2", None): self[name].ruler2.enableOnly(rules2) return self diff --git a/markdown_it/renderer.py b/markdown_it/renderer.py index 9e9c7751..a474f598 100644 --- a/markdown_it/renderer.py +++ b/markdown_it/renderer.py @@ -105,15 +105,12 @@ def renderInline( :param options: params of parser instance :param env: additional data from parsed input (references, for example) """ - result = "" - - for i, token in enumerate(tokens): - if token.type in self.rules: - result += self.rules[token.type](tokens, i, options, env) - else: - result += self.renderToken(tokens, i, options, env) - - return result + return "".join( + self.rules[token.type](tokens, i, options, env) + if token.type in self.rules + else self.renderToken(tokens, i, options, env) + for i, token in enumerate(tokens) + ) def renderToken( self, @@ -161,19 +158,18 @@ def renderToken( if token.block: needLf = True - if token.nesting == 1: - if idx + 1 < len(tokens): - nextToken = tokens[idx + 1] + if token.nesting == 1 and idx + 1 < len(tokens): + nextToken = tokens[idx + 1] - if nextToken.type == "inline" or nextToken.hidden: - # Block-level tag containing an inline tag. - # - needLf = False + if nextToken.type == "inline" or nextToken.hidden: + # Block-level tag containing an inline tag. + # + needLf = False - elif nextToken.nesting == -1 and nextToken.tag == token.tag: - # Opening tag + closing tag of the same type. E.g. `
  • `. - # - needLf = False + elif nextToken.nesting == -1 and nextToken.tag == token.tag: + # Opening tag + closing tag of the same type. E.g. `
  • `. + # + needLf = False result += ">\n" if needLf else ">" @@ -182,12 +178,10 @@ def renderToken( @staticmethod def renderAttrs(token: Token) -> str: """Render token attributes to string.""" - result = "" - - for key, value in token.attrItems(): - result += " " + escapeHtml(key) + '="' + escapeHtml(str(value)) + '"' - - return result + return "".join( + f' {escapeHtml(key)}' + '="' + escapeHtml(str(value)) + '"' + for key, value in token.attrItems() + ) def renderInlineAsText( self, @@ -221,13 +215,9 @@ def renderInlineAsText( def code_inline(self, tokens: Sequence[Token], idx: int, options, env) -> str: token = tokens[idx] - return ( - "" - + escapeHtml(tokens[idx].content) - + "" - ) + + ">" + escapeHtml(token.content)) + "") def code_block( self, @@ -238,13 +228,9 @@ def code_block( ) -> str: token = tokens[idx] - return ( - "" - + escapeHtml(tokens[idx].content) - + "\n" - ) + + ">" + escapeHtml(token.content)) + "\n") def fence( self, diff --git a/markdown_it/ruler.py b/markdown_it/ruler.py index 997c95dc..532f0713 100644 --- a/markdown_it/ruler.py +++ b/markdown_it/ruler.py @@ -76,10 +76,9 @@ def __init__(self): def __find__(self, name: str) -> int: """Find rule index by name""" - for i, rule in enumerate(self.__rules__): - if rule.name == name: - return i - return -1 + return next( + (i for i, rule in enumerate(self.__rules__) if rule.name == name), -1 + ) def __compile__(self) -> None: """Build rules lookup cache""" @@ -176,7 +175,7 @@ def enable(self, names: Union[str, Iterable[str]], ignoreInvalid: bool = False): idx = self.__find__(name) if (idx < 0) and ignoreInvalid: continue - if (idx < 0) and not ignoreInvalid: + if idx < 0: raise KeyError(f"Rules manager: invalid rule name {name}") self.__rules__[idx].enabled = True result.append(name) @@ -212,7 +211,7 @@ def disable(self, names: Union[str, Iterable[str]], ignoreInvalid: bool = False) idx = self.__find__(name) if (idx < 0) and ignoreInvalid: continue - if (idx < 0) and not ignoreInvalid: + if idx < 0: raise KeyError(f"Rules manager: invalid rule name {name}") self.__rules__[idx].enabled = False result.append(name) diff --git a/markdown_it/rules_block/blockquote.py b/markdown_it/rules_block/blockquote.py index c3e2d5c2..061a0bb8 100644 --- a/markdown_it/rules_block/blockquote.py +++ b/markdown_it/rules_block/blockquote.py @@ -74,17 +74,16 @@ def blockquote(state: StateBlock, startLine: int, endLine: int, silent: bool): while pos < max: ch = state.srcCharCode[pos] - if isSpace(ch): - if ch == 0x09: # / tab / - offset += ( - 4 - - (offset + state.bsCount[startLine] + (1 if adjustTab else 0)) % 4 - ) - else: - offset += 1 + if not isSpace(ch): + break + if ch == 0x09: # / tab / + offset += ( + 4 + - (offset + state.bsCount[startLine] + (1 if adjustTab else 0)) % 4 + ) else: - break + offset += 1 pos += 1 @@ -188,22 +187,21 @@ def blockquote(state: StateBlock, startLine: int, endLine: int, silent: bool): while pos < max: ch = state.srcCharCode[pos] - if isSpace(ch): - if ch == 0x09: - offset += ( - 4 - - ( - offset - + state.bsCount[nextLine] - + (1 if adjustTab else 0) - ) - % 4 - ) - else: - offset += 1 - else: + if not isSpace(ch): break + if ch == 0x09: + offset += ( + 4 + - ( + offset + + state.bsCount[nextLine] + + (1 if adjustTab else 0) + ) + % 4 + ) + else: + offset += 1 pos += 1 lastLineEmpty = pos >= max @@ -226,15 +224,10 @@ def blockquote(state: StateBlock, startLine: int, endLine: int, silent: bool): if lastLineEmpty: break - # Case 3: another tag found. - terminate = False - - for terminatorRule in terminatorRules: - if terminatorRule(state, nextLine, endLine, True): - terminate = True - break - - if terminate: + if terminate := any( + terminatorRule(state, nextLine, endLine, True) + for terminatorRule in terminatorRules + ): # Quirk to enforce "hard termination mode" for paragraphs; # normally if you call `tokenize(state, startLine, nextLine)`, # paragraphs will look below nextLine for paragraph continuation, diff --git a/markdown_it/rules_block/fence.py b/markdown_it/rules_block/fence.py index bacf54a2..c9a239d6 100644 --- a/markdown_it/rules_block/fence.py +++ b/markdown_it/rules_block/fence.py @@ -25,7 +25,7 @@ def fence(state: StateBlock, startLine: int, endLine: int, silent: bool): marker = state.srcCharCode[pos] # /* ~ */ /* ` */ - if marker != 0x7E and marker != 0x60: + if marker not in [0x7E, 0x60]: return False # scan marker length @@ -41,9 +41,8 @@ def fence(state: StateBlock, startLine: int, endLine: int, silent: bool): params = state.src[pos:maximum] # /* ` */ - if marker == 0x60: - if chr(marker) in params: - return False + if marker == 0x60 and chr(marker) in params: + return False # Since start is found, we can report success here in validation mode if silent: diff --git a/markdown_it/rules_block/heading.py b/markdown_it/rules_block/heading.py index 353520a3..4acdb62f 100644 --- a/markdown_it/rules_block/heading.py +++ b/markdown_it/rules_block/heading.py @@ -56,7 +56,7 @@ def heading(state: StateBlock, startLine: int, endLine: int, silent: bool): state.line = startLine + 1 - token = state.push("heading_open", "h" + str(level), 1) + token = state.push("heading_open", f'h{level}', 1) token.markup = "########"[:level] token.map = [startLine, state.line] @@ -65,7 +65,7 @@ def heading(state: StateBlock, startLine: int, endLine: int, silent: bool): token.map = [startLine, state.line] token.children = [] - token = state.push("heading_close", "h" + str(level), -1) + token = state.push("heading_close", f'h{level}', -1) token.markup = "########"[:level] return True diff --git a/markdown_it/rules_block/hr.py b/markdown_it/rules_block/hr.py index 01c68552..8419d94f 100644 --- a/markdown_it/rules_block/hr.py +++ b/markdown_it/rules_block/hr.py @@ -26,7 +26,7 @@ def hr(state: StateBlock, startLine: int, endLine: int, silent: bool): pos += 1 # Check hr marker: /* * */ /* - */ /* _ */ - if marker != 0x2A and marker != 0x2D and marker != 0x5F: + if marker not in [0x2A, 0x2D, 0x5F]: return False # markers can be mixed with spaces, but there should be at least 3 of them diff --git a/markdown_it/rules_block/html_block.py b/markdown_it/rules_block/html_block.py index 3bb850e5..e988e851 100644 --- a/markdown_it/rules_block/html_block.py +++ b/markdown_it/rules_block/html_block.py @@ -13,7 +13,9 @@ # last argument defines whether it can terminate a paragraph or not HTML_SEQUENCES: List[Tuple[Pattern, Pattern, bool]] = [ ( - re.compile(r"^<(script|pre|style|textarea)(?=(\s|>|$))", re.IGNORECASE), + re.compile( + r"^<(script|pre|style|textarea)(?=(\s|>|$))", re.IGNORECASE + ), re.compile(r"<\/(script|pre|style|textarea)>", re.IGNORECASE), True, ), @@ -22,11 +24,13 @@ (re.compile(r"^"), True), (re.compile(r"^"), True), ( - re.compile("^|$))", re.IGNORECASE), + re.compile( + "^|$))", re.IGNORECASE + ), re.compile(r"^$"), True, ), - (re.compile(HTML_OPEN_CLOSE_TAG_STR + "\\s*$"), re.compile(r"^$"), False), + (re.compile(f'{HTML_OPEN_CLOSE_TAG_STR}\\s*$'), re.compile(r"^$"), False), ] @@ -49,11 +53,14 @@ def html_block(state: StateBlock, startLine: int, endLine: int, silent: bool): lineText = state.src[pos:maximum] - html_seq = None - for HTML_SEQUENCE in HTML_SEQUENCES: - if HTML_SEQUENCE[0].search(lineText): - html_seq = HTML_SEQUENCE - break + html_seq = next( + ( + HTML_SEQUENCE + for HTML_SEQUENCE in HTML_SEQUENCES + if HTML_SEQUENCE[0].search(lineText) + ), + None, + ) if not html_seq: return False diff --git a/markdown_it/rules_block/lheading.py b/markdown_it/rules_block/lheading.py index f26e2af0..96b0432a 100644 --- a/markdown_it/rules_block/lheading.py +++ b/markdown_it/rules_block/lheading.py @@ -40,7 +40,7 @@ def lheading(state: StateBlock, startLine: int, endLine: int, silent: bool): marker = state.srcCharCode[pos] # /* - */ /* = */ - if marker == 0x2D or marker == 0x3D: + if marker in [0x2D, 0x3D]: pos = state.skipChars(pos, marker) pos = state.skipSpaces(pos) @@ -54,13 +54,10 @@ def lheading(state: StateBlock, startLine: int, endLine: int, silent: bool): nextLine += 1 continue - # Some tags can terminate paragraph without empty line. - terminate = False - for terminatorRule in terminatorRules: - if terminatorRule(state, nextLine, endLine, True): - terminate = True - break - if terminate: + if terminate := any( + terminatorRule(state, nextLine, endLine, True) + for terminatorRule in terminatorRules + ): break nextLine += 1 @@ -73,7 +70,7 @@ def lheading(state: StateBlock, startLine: int, endLine: int, silent: bool): state.line = nextLine + 1 - token = state.push("heading_open", "h" + str(level), 1) + token = state.push("heading_open", f'h{str(level)}', 1) token.markup = chr(marker) token.map = [startLine, state.line] @@ -82,7 +79,7 @@ def lheading(state: StateBlock, startLine: int, endLine: int, silent: bool): token.map = [startLine, state.line - 1] token.children = [] - token = state.push("heading_close", "h" + str(level), -1) + token = state.push("heading_close", f'h{str(level)}', -1) token.markup = chr(marker) state.parentType = oldParentType diff --git a/markdown_it/rules_block/list.py b/markdown_it/rules_block/list.py index f5bff688..fba68d6a 100644 --- a/markdown_it/rules_block/list.py +++ b/markdown_it/rules_block/list.py @@ -17,7 +17,7 @@ def skipBulletListMarker(state: StateBlock, startLine: int): marker = state.srcCharCode[pos] pos += 1 # Check bullet /* * */ /* - */ /* + */ - if marker != 0x2A and marker != 0x2D and marker != 0x2B: + if marker not in [0x2A, 0x2D, 0x2B]: return -1 if pos < maximum: @@ -68,7 +68,7 @@ def skipOrderedListMarker(state: StateBlock, startLine: int): continue # found valid marker: /* ) */ /* . */ - if ch == 0x29 or ch == 0x2E: + if ch in [0x29, 0x2E]: break return -1 @@ -100,7 +100,6 @@ def list_block(state: StateBlock, startLine: int, endLine: int, silent: bool): LOGGER.debug("entering list: %s, %s, %s, %s", state, startLine, endLine, silent) - isTerminatingParagraph = False tight = True # if it's indented more than 3 spaces, it should be a code block @@ -120,16 +119,11 @@ def list_block(state: StateBlock, startLine: int, endLine: int, silent: bool): ): return False - # limit conditions when list can interrupt - # a paragraph (validation mode only) - if silent and state.parentType == "paragraph": - # Next list item should still terminate previous list item - # - # This code can fail if plugins use blkIndent as well as lists, - # but I hope the spec gets fixed long before that happens. - # - if state.tShift[startLine] >= state.blkIndent: - isTerminatingParagraph = True + isTerminatingParagraph = ( + silent + and state.parentType == "paragraph" + and state.tShift[startLine] >= state.blkIndent + ) # Detect list type and position after marker posAfterMarker = skipOrderedListMarker(state, startLine) @@ -151,9 +145,11 @@ def list_block(state: StateBlock, startLine: int, endLine: int, silent: bool): # If we're starting a new unordered list right after # a paragraph, first line should not be empty. - if isTerminatingParagraph: - if state.skipSpaces(posAfterMarker) >= state.eMarks[startLine]: - return False + if ( + isTerminatingParagraph + and state.skipSpaces(posAfterMarker) >= state.eMarks[startLine] + ): + return False # We should terminate list on style change. Remember first one to compare. markerCharCode = state.srcCharCode[posAfterMarker - 1] @@ -211,12 +207,7 @@ def list_block(state: StateBlock, startLine: int, endLine: int, silent: bool): contentStart = pos - if contentStart >= maximum: - # trimming space in "- \n 3" case, indent is 1 here - indentAfterMarker = 1 - else: - indentAfterMarker = offset - initial - + indentAfterMarker = 1 if contentStart >= maximum else offset - initial # If we have more than 4 spaces, the indent is 1 # (the rest is just indented code block) if indentAfterMarker > 4: @@ -298,26 +289,19 @@ def list_block(state: StateBlock, startLine: int, endLine: int, silent: bool): if state.sCount[startLine] - state.blkIndent >= 4: break - # fail if terminating block found - terminate = False - for terminatorRule in terminatorRules: - if terminatorRule(state, nextLine, endLine, True): - terminate = True - break - - if terminate: + if terminate := any( + terminatorRule(state, nextLine, endLine, True) + for terminatorRule in terminatorRules + ): break # fail if list has another type if isOrdered: posAfterMarker = skipOrderedListMarker(state, nextLine) - if posAfterMarker < 0: - break else: posAfterMarker = skipBulletListMarker(state, nextLine) - if posAfterMarker < 0: - break - + if posAfterMarker < 0: + break if markerCharCode != state.srcCharCode[posAfterMarker - 1]: break diff --git a/markdown_it/rules_block/paragraph.py b/markdown_it/rules_block/paragraph.py index 4fee83e9..c586b250 100644 --- a/markdown_it/rules_block/paragraph.py +++ b/markdown_it/rules_block/paragraph.py @@ -36,14 +36,10 @@ def paragraph(state: StateBlock, startLine: int, endLine: int, silent: bool = Fa nextLine += 1 continue - # Some tags can terminate paragraph without empty line. - terminate = False - for terminatorRule in terminatorRules: - if terminatorRule(state, nextLine, endLine, True): - terminate = True - break - - if terminate: + if terminate := any( + terminatorRule(state, nextLine, endLine, True) + for terminatorRule in terminatorRules + ): break nextLine += 1 diff --git a/markdown_it/rules_block/reference.py b/markdown_it/rules_block/reference.py index bdd96ead..4a816961 100644 --- a/markdown_it/rules_block/reference.py +++ b/markdown_it/rules_block/reference.py @@ -57,14 +57,10 @@ def reference(state: StateBlock, startLine, _endLine, silent): nextLine += 1 continue - # Some tags can terminate paragraph without empty line. - terminate = False - for terminatorRule in terminatorRules: - if terminatorRule(state, nextLine, endLine, True): - terminate = True - break - - if terminate: + if terminate := any( + terminatorRule(state, nextLine, endLine, True) + for terminatorRule in terminatorRules + ): break nextLine += 1 @@ -101,9 +97,7 @@ def reference(state: StateBlock, startLine, _endLine, silent): ch = charCodeAt(string, pos) if ch == 0x0A: lines += 1 - elif isSpace(ch): - pass - else: + elif not isSpace(ch): break pos += 1 @@ -131,9 +125,7 @@ def reference(state: StateBlock, startLine, _endLine, silent): ch = charCodeAt(string, pos) if ch == 0x0A: lines += 1 - elif isSpace(ch): - pass - else: + elif not isSpace(ch): break pos += 1 @@ -156,18 +148,17 @@ def reference(state: StateBlock, startLine, _endLine, silent): break pos += 1 - if pos < maximum and charCodeAt(string, pos) != 0x0A: - if title: - # garbage at the end of the line after title, - # but it could still be a valid reference if we roll back - title = "" - pos = destEndPos - lines = destEndLineNo - while pos < maximum: - ch = charCodeAt(string, pos) - if not isSpace(ch): - break - pos += 1 + if pos < maximum and charCodeAt(string, pos) != 0x0A and title: + # garbage at the end of the line after title, + # but it could still be a valid reference if we roll back + title = "" + pos = destEndPos + lines = destEndLineNo + while pos < maximum: + ch = charCodeAt(string, pos) + if not isSpace(ch): + break + pos += 1 if pos < maximum and charCodeAt(string, pos) != 0x0A: # garbage at the end of the line diff --git a/markdown_it/rules_block/state_block.py b/markdown_it/rules_block/state_block.py index 69ad0c4d..f0b7a132 100644 --- a/markdown_it/rules_block/state_block.py +++ b/markdown_it/rules_block/state_block.py @@ -83,10 +83,7 @@ def __init__( if isSpace(character): indent += 1 - if character == 0x09: - offset += 4 - offset % 4 - else: - offset += 1 + offset += 4 - offset % 4 if character == 0x09 else 1 continue else: indent_found = True diff --git a/markdown_it/rules_block/table.py b/markdown_it/rules_block/table.py index 8c2c5927..491a9f91 100644 --- a/markdown_it/rules_block/table.py +++ b/markdown_it/rules_block/table.py @@ -107,7 +107,7 @@ def table(state: StateBlock, startLine: int, endLine: int, silent: bool): if not t: # allow empty columns before and after table, but not in between columns; # e.g. allow ` |---| `, disallow ` ---||--- ` - if i == 0 or i == len(columns) - 1: + if i in [0, len(columns) - 1]: continue else: return False @@ -161,7 +161,7 @@ def table(state: StateBlock, startLine: int, endLine: int, silent: bool): for i in range(len(columns)): token = state.push("th_open", "th", 1) if aligns[i]: - token.attrs = {"style": "text-align:" + aligns[i]} + token.attrs = {"style": f'text-align:{aligns[i]}'} token = state.push("inline", "", 0) # note in markdown-it this map was removed in v12.0.0 however, we keep it, @@ -180,13 +180,10 @@ def table(state: StateBlock, startLine: int, endLine: int, silent: bool): if state.sCount[nextLine] < state.blkIndent: break - terminate = False - for i in range(len(terminatorRules)): - if terminatorRules[i](state, nextLine, endLine, True): - terminate = True - break - - if terminate: + if terminate := any( + terminatorRules[i](state, nextLine, endLine, True) + for i in range(len(terminatorRules)) + ): break lineText = getLine(state, nextLine).strip() if not lineText: @@ -209,7 +206,7 @@ def table(state: StateBlock, startLine: int, endLine: int, silent: bool): for i in range(columnCount): token = state.push("td_open", "td", 1) if aligns[i]: - token.attrs = {"style": "text-align:" + aligns[i]} + token.attrs = {"style": f'text-align:{aligns[i]}'} token = state.push("inline", "", 0) # note in markdown-it this map was removed in v12.0.0 however, we keep it, diff --git a/markdown_it/rules_core/replacements.py b/markdown_it/rules_core/replacements.py index ee3b9edb..664d90a1 100644 --- a/markdown_it/rules_core/replacements.py +++ b/markdown_it/rules_core/replacements.py @@ -77,29 +77,32 @@ def replace_rare(inlineTokens: List[Token]) -> None: inside_autolink = 0 for token in inlineTokens: - if token.type == "text" and not inside_autolink: - if RARE_RE.search(token.content): - # +- -> ± - token.content = PLUS_MINUS_RE.sub("±", token.content) - - # .., ..., ....... -> … - token.content = ELLIPSIS_RE.sub("…", token.content) - - # but ?..... & !..... -> ?.. & !.. - token.content = ELLIPSIS_QUESTION_EXCLAMATION_RE.sub( - "\\1..", token.content - ) - token.content = QUESTION_EXCLAMATION_RE.sub("\\1\\1\\1", token.content) - - # ,, ,,, ,,,, -> , - token.content = COMMA_RE.sub(",", token.content) - - # em-dash - token.content = EM_DASH_RE.sub("\\1\u2014", token.content) - - # en-dash - token.content = EN_DASH_RE.sub("\\1\u2013", token.content) - token.content = EN_DASH_INDENT_RE.sub("\\1\u2013", token.content) + if ( + token.type == "text" + and not inside_autolink + and RARE_RE.search(token.content) + ): + # +- -> ± + token.content = PLUS_MINUS_RE.sub("±", token.content) + + # .., ..., ....... -> … + token.content = ELLIPSIS_RE.sub("…", token.content) + + # but ?..... & !..... -> ?.. & !.. + token.content = ELLIPSIS_QUESTION_EXCLAMATION_RE.sub( + "\\1..", token.content + ) + token.content = QUESTION_EXCLAMATION_RE.sub("\\1\\1\\1", token.content) + + # ,, ,,, ,,,, -> , + token.content = COMMA_RE.sub(",", token.content) + + # em-dash + token.content = EM_DASH_RE.sub("\\1\u2014", token.content) + + # en-dash + token.content = EN_DASH_RE.sub("\\1\u2013", token.content) + token.content = EN_DASH_INDENT_RE.sub("\\1\u2013", token.content) if token.type == "link_open" and token.info == "auto": inside_autolink -= 1 diff --git a/markdown_it/rules_core/smartquotes.py b/markdown_it/rules_core/smartquotes.py index c3211191..a94ed1e5 100644 --- a/markdown_it/rules_core/smartquotes.py +++ b/markdown_it/rules_core/smartquotes.py @@ -62,12 +62,12 @@ def process_inlines(tokens: List[Token], state: StateCore) -> None: # default to space if it's the beginning of the line lastChar = 0x20 - if t.start(0) + lastIndex - 1 >= 0: + if t.start(0) + lastIndex >= 1: lastChar = charCodeAt(text, t.start(0) + lastIndex - 1) else: for j in range(i)[::-1]: # lastChar defaults to 0x20 - if tokens[j].type == "softbreak" or tokens[j].type == "hardbreak": + if tokens[j].type in ["softbreak", "hardbreak"]: break # should skip all tokens except 'text', 'html_inline' or 'code_inline' if not tokens[j].content: @@ -85,7 +85,7 @@ def process_inlines(tokens: List[Token], state: StateCore) -> None: else: for j in range(i + 1, len(tokens)): # nextChar defaults to 0x20 - if tokens[j].type == "softbreak" or tokens[j].type == "hardbreak": + if tokens[j].type in ["softbreak", "hardbreak"]: break # should skip all tokens except 'text', 'html_inline' or 'code_inline' if not tokens[j].content: @@ -100,22 +100,32 @@ def process_inlines(tokens: List[Token], state: StateCore) -> None: isLastWhiteSpace = isWhiteSpace(lastChar) isNextWhiteSpace = isWhiteSpace(nextChar) - if isNextWhiteSpace: + if ( + not isNextWhiteSpace + and isNextPunctChar + and not isLastWhiteSpace + and not isLastPunctChar + or isNextWhiteSpace + ): canOpen = False - elif isNextPunctChar: - if not (isLastWhiteSpace or isLastPunctChar): - canOpen = False - if isLastWhiteSpace: + if ( + not isLastWhiteSpace + and isLastPunctChar + and not isNextWhiteSpace + and not isNextPunctChar + or isLastWhiteSpace + ): canClose = False - elif isLastPunctChar: - if not (isNextWhiteSpace or isNextPunctChar): - canClose = False - - if nextChar == 0x22 and t.group(0) == '"': # 0x22: " - if lastChar >= 0x30 and lastChar <= 0x39: # 0x30: 0, 0x39: 9 - # special case: 1"" - count first quote as an inch - canClose = canOpen = False + + if ( + nextChar == 0x22 + and t.group(0) == '"' + and lastChar >= 0x30 + and lastChar <= 0x39 + ): + # special case: 1"" - count first quote as an inch + canClose = canOpen = False if canOpen and canClose: # Replace quotes in the middle of punctuation sequence, but not diff --git a/markdown_it/rules_inline/autolink.py b/markdown_it/rules_inline/autolink.py index 6a55e49a..ddce1dff 100644 --- a/markdown_it/rules_inline/autolink.py +++ b/markdown_it/rules_inline/autolink.py @@ -54,7 +54,7 @@ def autolink(state: StateInline, silent: bool) -> bool: return True if EMAIL_RE.search(url) is not None: - fullUrl = state.md.normalizeLink("mailto:" + url) + fullUrl = state.md.normalizeLink(f'mailto:{url}') if not state.md.validateLink(fullUrl): return False diff --git a/markdown_it/rules_inline/balance_pairs.py b/markdown_it/rules_inline/balance_pairs.py index db622f07..e812e3dd 100644 --- a/markdown_it/rules_inline/balance_pairs.py +++ b/markdown_it/rules_inline/balance_pairs.py @@ -37,9 +37,7 @@ def processDelimiters(state: StateInline, delimiters, *args): # avoid crash if `closer.jump` is pointing outside of the array, # e.g. for strikethrough - if openerIdx < -1: - openerIdx = -1 - + openerIdx = max(openerIdx, -1) newMinOpenerIdx = openerIdx while openerIdx > minOpenerIdx: @@ -51,19 +49,11 @@ def processDelimiters(state: StateInline, delimiters, *args): if opener.open and opener.end < 0: - isOddMatch = False - - # from spec: - # - # If one of the delimiters can both open and close emphasis, then the - # sum of the lengths of the delimiter runs containing the opening and - # closing delimiters must not be a multiple of 3 unless both lengths - # are multiples of 3. - # - if opener.close or closer.open: - if (opener.length + closer.length) % 3 == 0: - if opener.length % 3 != 0 or closer.length % 3 != 0: - isOddMatch = True + isOddMatch = bool( + (opener.close or closer.open) + and (opener.length + closer.length) % 3 == 0 + and (opener.length % 3 != 0 or closer.length % 3 != 0) + ) if not isOddMatch: # If previous delimiter cannot be an opener, we can safely skip @@ -106,9 +96,7 @@ def link_pairs(state: StateInline) -> None: processDelimiters(state, state.delimiters) - curr = 0 - while curr < maximum: + for curr in range(maximum): curr_meta = tokens_meta[curr] if curr_meta and "delimiters" in curr_meta: processDelimiters(state, curr_meta["delimiters"]) - curr += 1 diff --git a/markdown_it/rules_inline/emphasis.py b/markdown_it/rules_inline/emphasis.py index ef32c8d9..a2f5af07 100644 --- a/markdown_it/rules_inline/emphasis.py +++ b/markdown_it/rules_inline/emphasis.py @@ -13,7 +13,7 @@ def tokenize(state: StateInline, silent: bool): return False # /* _ */ /* * */ - if marker != 0x5F and marker != 0x2A: + if marker not in [0x5F, 0x2A]: return False scanned = state.scanDelims(state.pos, marker == 0x2A) @@ -45,7 +45,7 @@ def _postProcess(state, delimiters): startDelim = delimiters[i] # /* _ */ /* * */ - if startDelim.marker != 0x5F and startDelim.marker != 0x2A: + if startDelim.marker not in [0x5F, 0x2A]: i -= 1 continue diff --git a/markdown_it/rules_inline/entity.py b/markdown_it/rules_inline/entity.py index 753baf27..1a01788f 100644 --- a/markdown_it/rules_inline/entity.py +++ b/markdown_it/rules_inline/entity.py @@ -21,8 +21,7 @@ def entity(state: StateInline, silent: bool): ch = state.srcCharCode[pos + 1] if ch == 0x23: # /* # */ - match = DIGITAL_RE.search(state.src[pos:]) - if match: + if match := DIGITAL_RE.search(state.src[pos:]): if not silent: match1 = match.group(1) code = ( @@ -39,14 +38,12 @@ def entity(state: StateInline, silent: bool): state.pos += len(match.group(0)) return True - else: - match = NAMED_RE.search(state.src[pos:]) - if match: - if has(entities, match.group(1)): - if not silent: - state.pending += entities[match.group(1)] - state.pos += len(match.group(0)) - return True + elif match := NAMED_RE.search(state.src[pos:]): + if has(entities, match.group(1)): + if not silent: + state.pending += entities[match.group(1)] + state.pos += len(match.group(0)) + return True if not silent: state.pending += "&" diff --git a/markdown_it/rules_inline/link.py b/markdown_it/rules_inline/link.py index 919ccf12..1455a96a 100644 --- a/markdown_it/rules_inline/link.py +++ b/markdown_it/rules_inline/link.py @@ -27,13 +27,6 @@ def link(state: StateInline, silent: bool): pos = labelEnd + 1 if pos < maximum and state.srcCharCode[pos] == 0x28: # /* ( */ - # - # Inline link - # - - # might have found a valid shortcut link, disable reference parsing - parseReference = False - # [link]( "title" ) # ^^ skipping these spaces pos += 1 @@ -69,22 +62,19 @@ def link(state: StateInline, silent: bool): # [link]( "title" ) # ^^^^^^^ parsing link title res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax) - if pos < maximum and start != pos and res.ok: - title = res.str - pos = res.pos - - # [link]( "title" ) - # ^^ skipping these spaces - while pos < maximum: - code = state.srcCharCode[pos] - if not isSpace(code) and code != 0x0A: - break - pos += 1 + if pos < maximum and start != pos and res.ok: + title = res.str + pos = res.pos - if pos >= maximum or state.srcCharCode[pos] != 0x29: # /* ) */ - # parsing a valid shortcut link failed, fallback to reference - parseReference = True + # [link]( "title" ) + # ^^ skipping these spaces + while pos < maximum: + code = state.srcCharCode[pos] + if not isSpace(code) and code != 0x0A: + break + pos += 1 + parseReference = pos >= maximum or state.srcCharCode[pos] != 0x29 pos += 1 if parseReference: diff --git a/markdown_it/rules_inline/state_inline.py b/markdown_it/rules_inline/state_inline.py index 54555411..65bf520d 100644 --- a/markdown_it/rules_inline/state_inline.py +++ b/markdown_it/rules_inline/state_inline.py @@ -128,8 +128,6 @@ def scanDelims(self, start, canSplitWord): """ pos = start - left_flanking = True - right_flanking = True maximum = self.posMax marker = self.srcCharCode[start] @@ -150,17 +148,23 @@ def scanDelims(self, start, canSplitWord): isLastWhiteSpace = isWhiteSpace(lastChar) isNextWhiteSpace = isWhiteSpace(nextChar) - if isNextWhiteSpace: - left_flanking = False - elif isNextPunctChar: - if not (isLastWhiteSpace or isLastPunctChar): - left_flanking = False - - if isLastWhiteSpace: - right_flanking = False - elif isLastPunctChar: - if not (isNextWhiteSpace or isNextPunctChar): - right_flanking = False + left_flanking = bool( + ( + isNextWhiteSpace + or not isNextPunctChar + or (isLastWhiteSpace or isLastPunctChar) + ) + and not isNextWhiteSpace + ) + + right_flanking = bool( + ( + isLastWhiteSpace + or not isLastPunctChar + or (isNextWhiteSpace or isNextPunctChar) + ) + and not isLastWhiteSpace + ) if not canSplitWord: can_open = left_flanking and ((not right_flanking) or isLastPunctChar) diff --git a/markdown_it/rules_inline/strikethrough.py b/markdown_it/rules_inline/strikethrough.py index 87af4b46..c163f1ab 100644 --- a/markdown_it/rules_inline/strikethrough.py +++ b/markdown_it/rules_inline/strikethrough.py @@ -120,8 +120,7 @@ def postProcess(state: StateInline): maximum = len(state.tokens_meta) _postProcess(state, state.delimiters) - curr = 0 - while curr < maximum: + for curr in range(maximum): try: curr_meta = tokens_meta[curr] except IndexError: @@ -129,4 +128,3 @@ def postProcess(state: StateInline): else: if curr_meta and "delimiters" in curr_meta: _postProcess(state, curr_meta["delimiters"]) - curr += 1 diff --git a/markdown_it/tree.py b/markdown_it/tree.py index edbc35e0..4cf3b94d 100644 --- a/markdown_it/tree.py +++ b/markdown_it/tree.py @@ -157,9 +157,7 @@ def siblings(self: _NodeType) -> Sequence[_NodeType]: Gets the whole group of siblings, including self. """ - if not self.parent: - return [self] - return self.parent.children + return [self] if not self.parent else self.parent.children @property def type(self) -> str: @@ -195,7 +193,7 @@ def previous_sibling(self: _NodeType) -> Optional[_NodeType]: Returns `None` if this is the first sibling. """ self_index = self.siblings.index(self) - if self_index - 1 >= 0: + if self_index >= 1: return self.siblings[self_index - 1] return None @@ -237,7 +235,7 @@ def pretty( ) -> str: """Create an XML style string of the tree.""" prefix = " " * _current - text = prefix + f"<{self.type}" + text = f'{prefix}<{self.type}' if not self.is_root and self.attrs: text += " " + " ".join(f"{k}={v!r}" for k, v in self.attrs.items()) text += ">" @@ -297,11 +295,7 @@ def attrGet(self, name: str) -> Union[None, str, int, float]: @property def map(self) -> Optional[Tuple[int, int]]: """Source map info. Format: `Tuple[ line_begin, line_end ]`""" - map_ = self._attribute_token().map - if map_: - # Type ignore because `Token`s attribute types are not perfect - return tuple(map_) # type: ignore - return None + return tuple(map_) if (map_ := self._attribute_token().map) else None @property def level(self) -> int: diff --git a/tests/test_port/test_misc.py b/tests/test_port/test_misc.py index f5f821e9..88fa65f9 100644 --- a/tests/test_port/test_misc.py +++ b/tests/test_port/test_misc.py @@ -6,7 +6,7 @@ def test_highlight_arguments(): def highlight_func(str_, lang, attrs): assert lang == "a" assert attrs == "b c d" - return "
    ==" + str_ + "==
    " + return f'
    =={str_}==
    ' conf = presets.commonmark.make() conf["options"]["highlight"] = highlight_func