1*77e04223SPhilipp Schuster# SPDX-License-Identifier: Apache-2.0 2*77e04223SPhilipp Schuster 3*77e04223SPhilipp Schusterfrom gitlint.rules import LineRule, RuleViolation, CommitMessageBody 4*77e04223SPhilipp Schusterimport re 5*77e04223SPhilipp Schuster 6*77e04223SPhilipp Schuster 7*77e04223SPhilipp Schusterclass BodyMaxLineLengthEx(LineRule): 8*77e04223SPhilipp Schuster """A rule to enforce a line limit of 72 characters, except for valid cases.""" 9*77e04223SPhilipp Schuster 10*77e04223SPhilipp Schuster # A rule MUST have a human friendly name 11*77e04223SPhilipp Schuster name = "body-max-line-length-ex" 12*77e04223SPhilipp Schuster 13*77e04223SPhilipp Schuster # A rule MUST have a *unique* id. 14*77e04223SPhilipp Schuster # We recommend starting with UL (for User-defined Line-rule) 15*77e04223SPhilipp Schuster id = "UL-ll" 16*77e04223SPhilipp Schuster 17*77e04223SPhilipp Schuster # A line-rule MUST have a target (not required for CommitRules). 18*77e04223SPhilipp Schuster target = CommitMessageBody 19*77e04223SPhilipp Schuster 20*77e04223SPhilipp Schuster max_len = 72 21*77e04223SPhilipp Schuster 22*77e04223SPhilipp Schuster # Updated property as the commit messages is validated line by line. 23*77e04223SPhilipp Schuster inside_open_codeblock = False 24*77e04223SPhilipp Schuster 25*77e04223SPhilipp Schuster def validate(self, line, commit): 26*77e04223SPhilipp Schuster # Pattern allowing: 27*77e04223SPhilipp Schuster # - [0]: https://foobar 28*77e04223SPhilipp Schuster # - [0] https://foobar 29*77e04223SPhilipp Schuster # - https://foobar 30*77e04223SPhilipp Schuster link_regex = re.compile(r"^((\[[0-9]+\]:?\s?)?https?:\/\/).*$") 31*77e04223SPhilipp Schuster 32*77e04223SPhilipp Schuster is_codeblock_marker = line.startswith("```") 33*77e04223SPhilipp Schuster 34*77e04223SPhilipp Schuster inside_open_codeblock_ = self.inside_open_codeblock 35*77e04223SPhilipp Schuster if is_codeblock_marker: 36*77e04223SPhilipp Schuster self.inside_open_codeblock = not self.inside_open_codeblock 37*77e04223SPhilipp Schuster 38*77e04223SPhilipp Schuster if len(line) > self.max_len: 39*77e04223SPhilipp Schuster is_link = link_regex.match(line) 40*77e04223SPhilipp Schuster 41*77e04223SPhilipp Schuster if inside_open_codeblock_: 42*77e04223SPhilipp Schuster return 43*77e04223SPhilipp Schuster 44*77e04223SPhilipp Schuster if is_link: 45*77e04223SPhilipp Schuster return 46*77e04223SPhilipp Schuster 47*77e04223SPhilipp Schuster return [ 48*77e04223SPhilipp Schuster RuleViolation(self.id, f"Line '{line}' exceeds limit of {self.max_len}") 49*77e04223SPhilipp Schuster ] 50