@@ -96,22 +96,52 @@ def conventional_types(types=[]):
9696 return types
9797
9898
99- def is_conventional (input , types = DEFAULT_TYPES , optional_scope = True , scopes : Optional [List [str ]] = None ):
99+ def conventional_regex (types = DEFAULT_TYPES , optional_scope = True , scopes : Optional [List [str ]] = None ):
100+ types = conventional_types (types )
101+
102+ types_pattern = f"^(?P<type>{ r_types (types )} )?"
103+ scope_pattern = f"(?P<scope>{ r_scope (optional_scope , scopes = scopes )} )?"
104+ delim_pattern = f"(?P<delim>{ r_delim ()} )?"
105+ subject_pattern = f"(?P<subject>{ r_subject ()} )?"
106+ body_pattern = f"(?P<body>{ r_body ()} )?"
107+ pattern = types_pattern + scope_pattern + delim_pattern + subject_pattern + body_pattern
108+
109+ return re .compile (pattern , re .MULTILINE )
110+
111+
112+ def clean_input (input : str ):
113+ """
114+ Prepares an input message for conventional commits format check.
115+ """
116+ input = strip_verbose_commit_ignored (input )
117+ input = strip_comments (input )
118+ return input
119+
120+
121+ def conventional_match (input : str , types = DEFAULT_TYPES , optional_scope = True , scopes : Optional [List [str ]] = None ):
122+ """
123+ Returns an `re.Match` object for the input against the Conventional Commits format.
124+ """
125+ input = clean_input (input )
126+ regex = conventional_regex (types , optional_scope , scopes )
127+ return regex .match (input )
128+
129+
130+ def is_conventional (input : str , types = DEFAULT_TYPES , optional_scope = True , scopes : Optional [List [str ]] = None ) -> bool :
100131 """
101132 Returns True if input matches Conventional Commits formatting
102133 https://www.conventionalcommits.org
103134
104135 Optionally provide a list of additional custom types.
105136 """
106- input = strip_verbose_commit_ignored (input )
107- input = strip_comments (input )
108- types = conventional_types (types )
109- pattern = f"^({ r_types (types )} ){ r_scope (optional_scope , scopes = scopes )} { r_delim ()} { r_subject ()} { r_body ()} "
110- regex = re .compile (pattern , re .MULTILINE )
111-
112- result = regex .match (input )
137+ result = conventional_match (input , types , optional_scope , scopes )
113138 is_valid = bool (result )
114- if is_valid and result .group ("multi" ) and not result .group ("sep" ):
139+
140+ if result and result .group ("multi" ) and not result .group ("sep" ):
141+ is_valid = False
142+ if result and not all (
143+ [result .group ("type" ), optional_scope or result .group ("scope" ), result .group ("delim" ), result .group ("subject" )]
144+ ):
115145 is_valid = False
116146
117147 return is_valid
0 commit comments