-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add new conventional commit parser
- Loading branch information
1 parent
5997ecf
commit 603f724
Showing
7 changed files
with
349 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
namespace ConventionalChangelog\Commit; | ||
|
||
use ConventionalChangelog\Type\Stringable; | ||
|
||
class Body implements Stringable | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
public $content; | ||
|
||
public function __construct(string $content) | ||
{ | ||
$this->content = $content; | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
return $this->content; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
namespace ConventionalChangelog\Commit; | ||
|
||
use ConventionalChangelog\Type\Stringable; | ||
|
||
class Description implements Stringable | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
public $content; | ||
|
||
public function __construct(string $content) | ||
{ | ||
$this->content = $content; | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
return $this->content; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
namespace ConventionalChangelog\Commit; | ||
|
||
use ConventionalChangelog\Type\Stringable; | ||
|
||
class Footer implements Stringable | ||
{ | ||
/** | ||
* Token. | ||
* | ||
* @var string | ||
*/ | ||
public $token; | ||
|
||
/** | ||
* Value. | ||
* | ||
* @var string | ||
*/ | ||
public $value; | ||
|
||
public function __construct(string $token, string $value) | ||
{ | ||
$this->token = $token; | ||
$this->value = $value; | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
return $this->token . ': ' . $this->value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
<?php | ||
|
||
namespace ConventionalChangelog\Commit; | ||
|
||
use ConventionalChangelog\Helper\Format; | ||
use ConventionalChangelog\Type\Stringable; | ||
|
||
class Parser implements Stringable | ||
{ | ||
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"; | ||
|
||
/** | ||
* Raw content. | ||
* | ||
* @var string | ||
*/ | ||
protected $raw; | ||
|
||
/** | ||
* Sha hash. | ||
* | ||
* @var string | ||
*/ | ||
protected $hash; | ||
|
||
/** | ||
* Type. | ||
* | ||
* @var Type | ||
*/ | ||
protected $type; | ||
|
||
/** | ||
* Scope. | ||
* | ||
* @var Scope | ||
*/ | ||
protected $scope; | ||
|
||
/** | ||
* Important. | ||
* | ||
* @var bool | ||
*/ | ||
protected $important = false; | ||
|
||
/** | ||
* Description. | ||
* | ||
* @var Description | ||
*/ | ||
protected $description; | ||
|
||
/** | ||
* @var Body | ||
*/ | ||
protected $body; | ||
|
||
/** | ||
* Footers. | ||
* | ||
* @var Footer[] | ||
*/ | ||
protected $footers = []; | ||
|
||
public function __construct(string $commit) | ||
{ | ||
$this->raw = Format::clean($commit); | ||
|
||
if (!$this->isValid()) { | ||
return; | ||
} | ||
|
||
$rows = explode("\n", $commit); | ||
$count = count($rows); | ||
// Commit info | ||
$this->hash = $rows[$count - 1]; | ||
$header = $rows[0]; | ||
$message = ''; | ||
// Get message | ||
foreach ($rows as $i => $row) { | ||
if ($i !== 0 && $i !== $count) { | ||
$message .= $row . "\n"; | ||
} | ||
} | ||
$this->parseHeader($header); | ||
$this->parseMessage($message); | ||
} | ||
|
||
/** | ||
* Parse header. | ||
*/ | ||
protected function parseHeader(string $header) | ||
{ | ||
preg_match(self::PATTERN_HEADER, $header, $matches); | ||
$this->type = new Type($matches['type']); | ||
$this->scope = new Scope($matches['scope']); | ||
$this->important = !empty($matches['important']) ? true : false; | ||
$this->description = new Description($matches['description']); | ||
} | ||
|
||
/** | ||
* Parse message. | ||
*/ | ||
protected function parseMessage(string $message) | ||
{ | ||
$body = Format::clean($message); | ||
if (preg_match_all(self::PATTERN_FOOTER, $body, $matches, PREG_SET_ORDER, 0)) { | ||
foreach ($matches as $match) { | ||
$footer = $match[0]; | ||
$body = str_replace($footer, '', $body); | ||
$value = ltrim($match['value'], ':'); | ||
$this->footers[] = new Footer($match['token'], $value); | ||
} | ||
} | ||
$body = Format::clean($body); | ||
$this->body = new Body($body); | ||
} | ||
|
||
public function isValid(): bool | ||
{ | ||
return preg_match(self::PATTERN_HEADER, $this->raw); | ||
} | ||
|
||
public function getRaw(): string | ||
{ | ||
return $this->raw; | ||
} | ||
|
||
public function getHash(): string | ||
{ | ||
return $this->hash; | ||
} | ||
|
||
public function getShortHash(): string | ||
{ | ||
return substr($this->hash, 0, 6); | ||
} | ||
|
||
public function getType(): Type | ||
{ | ||
return $this->type; | ||
} | ||
|
||
public function getScope(): Scope | ||
{ | ||
return $this->scope; | ||
} | ||
|
||
public function isImportant(): bool | ||
{ | ||
return $this->important; | ||
} | ||
|
||
public function getDescription(): Description | ||
{ | ||
return $this->description; | ||
} | ||
|
||
public function getBody(): Body | ||
{ | ||
return $this->body; | ||
} | ||
|
||
/** | ||
* @return Footer[] | ||
*/ | ||
public function getFooters(): array | ||
{ | ||
return $this->footers; | ||
} | ||
|
||
public function getHeader() | ||
{ | ||
$header = $this->type; | ||
if (!empty((string)$this->scope)) { | ||
$header .= '(' . $this->scope . ')'; | ||
} | ||
if ($this->important) { | ||
$header .= '!'; | ||
} | ||
$header .= ': ' . $this->description; | ||
|
||
return $header; | ||
} | ||
|
||
public function getMessage() | ||
{ | ||
$footer = implode("\n", $this->footers); | ||
|
||
return $this->body . "\n\n" . $footer; | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
$header = $this->getHeader(); | ||
$message = $this->getMessage(); | ||
$string = $header . "\n\n" . $message; | ||
|
||
return Format::clean($string); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
namespace ConventionalChangelog\Commit; | ||
|
||
use ConventionalChangelog\Helper\Format; | ||
use ConventionalChangelog\Type\Stringable; | ||
|
||
class Scope implements Stringable | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
public $content; | ||
|
||
public function __construct(string $content) | ||
{ | ||
$this->content = $content; | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
$string = $this->content; | ||
$string = preg_replace('/[_]+/m', ' ', $string); | ||
$string = ucfirst($string); | ||
$string = preg_replace('/((?<=\p{Ll})\p{Lu})|((?!\A)\p{Lu}(?>\p{Ll}))/u', ' $0', $string); | ||
$string = preg_replace('/\.(php|md|json|txt|csv|js)($|\s)/', '', $string); | ||
$string = Format::clean($string); | ||
|
||
return $string; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
namespace ConventionalChangelog\Commit; | ||
|
||
use ConventionalChangelog\Type\Stringable; | ||
|
||
class Type implements Stringable | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
public $content; | ||
|
||
public function __construct(string $content) | ||
{ | ||
$this->content = strtolower($content); | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
return $this->content; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
namespace ConventionalChangelog\Type; | ||
|
||
/** | ||
* Convertible to string. | ||
* | ||
* @internal | ||
*/ | ||
interface Stringable | ||
{ | ||
public function __toString(): string; | ||
} |