Skip to content

fix(parser): reject whitespace-only scope - #56

Open
svyatov wants to merge 1 commit into
conventional-commits:mainfrom
svyatov:fix/whitespace-only-scope
Open

fix(parser): reject whitespace-only scope#56
svyatov wants to merge 1 commit into
conventional-commits:mainfrom
svyatov:fix/whitespace-only-scope

Conversation

@svyatov

@svyatov svyatov commented Jul 22, 2026

Copy link
Copy Markdown

feat( ): x parses today with a scope of " ". Spec rule 4 requires a scope to be "a noun describing a section of the codebase", and a value with no non-whitespace character is not one. @wesleytodd confirmed on #39 that this was unintended and pointed at the guard in scope(), which is the line this widens.

The change

node.value === '' becomes node.value.trim() === ''. Rejection reuses the existing abort path, so feat( ): x now fails exactly the way feat(): x already did, with the error pointing at the space.

trim() rather than the local isWhitespace from lib/type-checks.js, because trim() also covers <USP>, the Unicode Space_Separator class that the README grammar lists at line 59 but isWhitespace omits. Scopes cannot contain newlines, so trim() stripping line terminators does not matter here.

What deliberately did not change

Padded scopes still parse, padding included:

parser('feat( parser ): x')   // scope " parser "
parser('feat(http parser): x')  // scope "http parser"

Rule 4 constrains the noun, not the space around it. Rule 9 shows the spec bans whitespace explicitly where it means to ("A footer's token MUST use - in place of whitespace characters"), and no such clause exists for scope. Rejecting padding would be my judgement rather than the spec's, so I left it out. Happy to add it if you read rule 4 more strictly.

Blast radius

Only whitespace-only scopes change verdict. A body line that looks like one still falls back to text rather than failing the parse, because the rejection rewinds:

parser('fix: address major bug\n\nfoo( ) bar')  // body <text>, no throw

Tests

Three, all plain assertions so test/parser.js.snap stays untouched. One fails without the parser change; the other two pin the padded-scope and body-fallback behavior above and pass either way, on purpose.

Locally the suite goes from 34 passing to 37, standard stays clean, and npm run coverage clears the .nycrc thresholds.

Closes #39

feat( ): x parsed with a scope of " ". Spec rule 4 requires a scope to be
"a noun describing a section of the codebase", and a value with no
non-whitespace character cannot be one.

Padded scopes such as feat( parser ): x still parse, padding included.
Rule 4 constrains the noun, not the space around it, and rule 9 shows the
spec bans whitespace explicitly where it means to, so rejecting padding
would be our judgement rather than the spec's.

trim() rather than the local isWhitespace, because it also covers <USP>,
which the grammar lists at README line 59 but isWhitespace omits.

Closes conventional-commits#39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Grammar allows for whitespace-only scope

1 participant