diff --git a/src/Changelog.php b/src/Changelog.php index 6b06c3e..7ecc8cc 100644 --- a/src/Changelog.php +++ b/src/Changelog.php @@ -285,7 +285,7 @@ public function generate(InputInterface $input, SymfonyStyle $output): int // Group all changes to lists by type $types = $this->config->getAllowedTypes(); foreach ($commits as $commit) { - if (in_array($commit->getType(), $types)) { + if (in_array($commit->getType(), $types) || $commit->isBreakingChange()) { $itemKey = $this->getItemKey($commit->getDescription()); $breakingChanges = $commit->getBreakingChanges(); $type = (string)$commit->getType(); @@ -293,15 +293,20 @@ public function generate(InputInterface $input, SymfonyStyle $output): int $hash = $commit->getHash(); if (!empty($breakingChanges)) { foreach ($breakingChanges as $description) { + $breakingType = Configuration::$breakingChangesType; + $key = $this->getItemKey($description); + if (empty($description) || $itemKey === $key) { + $commit->setBreakingChange(true); + continue; + } // Clone commit as breaking with different description message $breakingCommit = new ConventionalCommit(); - $breakingCommit->setType($type) + $breakingCommit->setType($breakingType) ->setDescription($description) ->setScope($scope) ->setHash($hash); - $key = $this->getItemKey($description); - $changes['breaking_changes'][$scope][$key][$hash] = $breakingCommit; - $summary['breaking_changes']++; + $changes[$breakingType][$scope][$key][$hash] = $breakingCommit; + $summary[$breakingType]++; } } $changes[$type][$scope][$itemKey][$hash] = $commit; @@ -408,7 +413,6 @@ protected function getMarkdownChanges(array $changes): string $changelog .= "\n##### {$scope}\n\n"; } foreach ($items as $itemsList) { - $important = ''; $description = ''; $sha = ''; $references = ''; @@ -418,10 +422,6 @@ protected function getMarkdownChanges(array $changes): string $description = ucfirst($item->getDescription()); $refs = $item->getReferences(); - if ($item->isImportant()) { - $important = '**'; - } - if (!empty($refs)) { foreach ($refs as $ref) { $url = $this->getIssueUrl($ref); @@ -439,7 +439,7 @@ protected function getMarkdownChanges(array $changes): string if (!empty($shaGroup)) { $sha = '(' . implode(', ', $shaGroup) . ')'; } - $changelog .= Formatter::clean("* {$important}{$description}{$important} {$references} {$sha}"); + $changelog .= Formatter::clean("* {$description} {$references} {$sha}"); $changelog .= PHP_EOL; } } diff --git a/src/Configuration.php b/src/Configuration.php index 8455b0b..6c43bac 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -52,14 +52,19 @@ class Configuration 'revert' => ['label' => 'Reverts', 'description' => 'Reverts a previous commit'], ]; + /** + * Key of breaking changes. + * + * @var string + */ + public static $breakingChangesType = 'breaking_changes'; + /** * Preset of breaking changes. * * @var string[][] */ - protected $breakingPreset = [ - 'breaking_changes' => ['label' => '⚠ BREAKING CHANGES', 'description' => 'Code changes that potentially causes other components to fail'], - ]; + protected $breakingChangesPreset = ['label' => '⚠ BREAKING CHANGES', 'description' => 'Code changes that potentially causes other components to fail']; /** * Types allowed on changelog. @@ -235,7 +240,7 @@ public function fromArray(array $array) } // Add breaking changes - $params['preset'] = array_merge($this->breakingPreset, $params['preset']); + $params['preset'] = array_merge($this->getBreakingChangesPreset(), $params['preset']); // Paths $this->setRoot($params['root']); @@ -389,7 +394,7 @@ public function setIgnorePatterns(array $ignorePatterns): Configuration */ public function getPreset(): array { - return array_merge($this->breakingPreset, $this->preset); + return array_merge($this->getBreakingChangesPreset(), $this->preset); } /** @@ -498,19 +503,9 @@ public function setSkipVerify(bool $skipVerify): Configuration /** * @return \string[][] */ - public function getBreakingPreset(): array + public function getBreakingChangesPreset(): array { - return $this->breakingPreset; - } - - /** - * @param \string[][] $breakingPreset - */ - public function setBreakingPreset(array $breakingPreset): Configuration - { - $this->breakingPreset = $breakingPreset; - - return $this; + return [self::$breakingChangesType => $this->breakingChangesPreset]; } public function getCommitUrlFormat(): string diff --git a/src/Git/ConventionalCommit.php b/src/Git/ConventionalCommit.php index 4776b3c..62353ce 100644 --- a/src/Git/ConventionalCommit.php +++ b/src/Git/ConventionalCommit.php @@ -2,6 +2,7 @@ namespace ConventionalChangelog\Git; +use ConventionalChangelog\Configuration; use ConventionalChangelog\Git\Commit\Description; use ConventionalChangelog\Git\Commit\Footer; use ConventionalChangelog\Git\Commit\Scope; @@ -10,8 +11,8 @@ class ConventionalCommit extends Commit { - protected const PATTERN_HEADER = "/^(?'type'[a-z]+)(\((?'scope'.+)\))?(?'important'[!]?)[:][[:blank:]](?'description'.+)/iums"; - protected const PATTERN_FOOTER = "/(?'token'^([a-z0-9_-]+|BREAKING[[:blank:]]CHANGES?))(?'value'([:][[:blank:]]|[:]?[[:blank:]][#](?=\w)).*?)$/iums"; + protected const PATTERN_HEADER = "/^(?[a-z]+)(?[!]?)(\((?.+)\))?(?[!]?)[:][[:blank:]](?.+)/iums"; + protected const PATTERN_FOOTER = "/(?^([a-z0-9_-]+|BREAKING[[:blank:]]CHANGES?))(?([:][[:blank:]]|[:]?[[:blank:]][#](?=\w)).*?)$/iums"; /** * Sha hash. @@ -35,11 +36,11 @@ class ConventionalCommit extends Commit protected $scope; /** - * Important. + * Is breaking change. * * @var bool */ - protected $important = false; + protected $isBreakingChange = false; /** * Description. @@ -69,7 +70,7 @@ protected function parseHeader(string $header) preg_match(self::PATTERN_HEADER, $header, $matches); $this->setType((string)$matches['type']) ->setScope((string)$matches['scope']) - ->setImportant(!empty($matches['important']) ? true : false) + ->setBreakingChange(!empty($matches['breaking_before'] || !empty($matches['breaking_after'])) ? true : false) ->setDescription((string)$matches['description']); } @@ -115,7 +116,12 @@ public function isValid(): bool public function getType(): Type { - return $this->type; + $type = $this->type; + if ($this->isBreakingChange()) { + $type = new Type(Configuration::$breakingChangesType); + } + + return $type; } public function getScope(): Scope @@ -128,9 +134,9 @@ public function hasScope(): bool return !empty((string)$this->scope); } - public function isImportant(): bool + public function isBreakingChange(): bool { - return $this->important; + return $this->isBreakingChange; } public function getDescription(): Description @@ -177,7 +183,7 @@ public function getHeader(): string if ($this->hasScope()) { $header .= '(' . $this->scope . ')'; } - if ($this->important) { + if ($this->isBreakingChange) { $header .= '!'; } $header .= ': ' . $this->description; @@ -206,9 +212,9 @@ public function setScope(?string $scope): self return $this; } - public function setImportant(bool $important): self + public function setBreakingChange(bool $isBreakingChange): self { - $this->important = $important; + $this->isBreakingChange = $isBreakingChange; return $this; }