From ade7e83b0333f322a4fe8c1930342c42af8a0172 Mon Sep 17 00:00:00 2001 From: vabatta <2137077+vabatta@users.noreply.github.com> Date: Mon, 9 Mar 2026 00:22:01 +0100 Subject: [PATCH] fix(cz): enforce blank line between subject and body per spec The Conventional Commits spec requires: "body MUST begin one blank line after the description." Single-line messages (no body) are unaffected. --- dist/cz/bin/cz | 6 +++++ scripts/cz/cmd_lint.sh | 8 +++++++ scripts/cz/main_spec.sh | 50 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/dist/cz/bin/cz b/dist/cz/bin/cz index 554157e..2a4b446 100755 --- a/dist/cz/bin/cz +++ b/dist/cz/bin/cz @@ -692,6 +692,12 @@ cmd_lint() { return 1 } + local rest="${message#*$'\n'}" + [[ "$rest" != "$message" && "${rest%%$'\n'*}" != "" ]] && { + _err "body MUST begin one blank line after the description" + return 1 + } + if [[ "${BREAKING_FOOTER-unset}" == "1" ]]; then breaking_footer=true elif [[ "${BREAKING_FOOTER-unset}" == "" ]]; then diff --git a/scripts/cz/cmd_lint.sh b/scripts/cz/cmd_lint.sh index 3a4a485..677dd46 100644 --- a/scripts/cz/cmd_lint.sh +++ b/scripts/cz/cmd_lint.sh @@ -75,6 +75,14 @@ cmd_lint() { return 1 } + # Validate blank line after subject when body/footer present + # Spec: "body MUST begin one blank line after the description" + local rest="${message#*$'\n'}" + [[ "$rest" != "$message" && "${rest%%$'\n'*}" != "" ]] && { + _err "body MUST begin one blank line after the description" + return 1 + } + # Determine breaking-footer mode if [[ "${BREAKING_FOOTER-unset}" == "1" ]]; then breaking_footer=true diff --git a/scripts/cz/main_spec.sh b/scripts/cz/main_spec.sh index c23e62d..fcc57b0 100644 --- a/scripts/cz/main_spec.sh +++ b/scripts/cz/main_spec.sh @@ -97,6 +97,56 @@ Describe 'cz' End End + #─────────────────────────────────────────────────────────── + # Body blank line (spec: body MUST begin one blank line) + #─────────────────────────────────────────────────────────── + Describe 'body blank line' + It 'accepts single-line message (no body)' + Data "docs: correct spelling of CHANGELOG" + When run script "$BIN" lint + The status should be success + End + + It 'accepts message with blank line before body' + Data + #|fix: prevent racing of requests + #| + #|Introduce a request id and a reference to latest request. Dismiss + #|incoming responses other than from latest request. + End + When run script "$BIN" lint + The status should be success + End + + It 'rejects body without blank line separator' + Data + #|fix: prevent racing of requests + #|Introduce a request id and a reference to latest request. + End + When run script "$BIN" lint + The status should be failure + The stderr should include "body MUST begin one blank line after the description" + End + + It 'rejects footer without blank line separator' + Data + #|feat: allow provided config object to extend other configs + #|BREAKING CHANGE: `extends` key in config file is now used for extending other config files + End + When run script "$BIN" lint + The status should be failure + The stderr should include "body MUST begin one blank line after the description" + End + + It 'accepts message with only a trailing newline' + Data + #|docs: correct spelling of CHANGELOG + End + When run script "$BIN" lint + The status should be success + End + End + #─────────────────────────────────────────────────────────── # Invalid conventional commits #───────────────────────────────────────────────────────────