Skip to content

Commit 9faf51d

Browse files
committed
[license] Preserve literal author emails (#179)
1 parent 2db3b18 commit 9faf51d

3 files changed

Lines changed: 44 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
### Fixed
1919

20+
- Preserve literal angle brackets around maintainer emails when generating LICENSE files from composer metadata (#179)
2021
- Keep packaged `.agents` payloads exportable and synchronize packaged skills and agents with repository-relative symlink targets so consumer repositories no longer receive broken absolute machine paths (#188)
2122
- Rewrite drifted Git hooks by removing the previous target first, restore the intended `0o755` executable mode, and report unwritable hook replacements cleanly when `.git/hooks` stays locked (#190)
2223
- Keep Composer plugin command discovery compatible with consumer environments by moving unsupported Symfony Console named parameters out of command metadata/configuration and by decoupling the custom filesystem wrapper from Composer's bundled Symfony Filesystem signatures (#185)

src/License/Generator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use FastForward\DevTools\Filesystem\FilesystemInterface;
2525
use Psr\Clock\ClockInterface;
2626
use Twig\Environment;
27+
use Twig\Markup;
2728

2829
/**
2930
* Generates LICENSE files from composer.json metadata.
@@ -91,7 +92,7 @@ public function generateContent(): ?string
9192

9293
try {
9394
$content = $this->renderer->render('licenses/' . $templateFilename, [
94-
'copyright_holder' => (string) $this->composer->getAuthors(true),
95+
'copyright_holder' => new Markup((string) $this->composer->getAuthors(true), 'UTF-8'),
9596
'year' => $this->clock->now()
9697
->format('Y'),
9798
]);

tests/License/GeneratorTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,24 @@
2222
use Exception;
2323
use DateTimeImmutable;
2424
use FastForward\DevTools\Composer\Json\ComposerJsonInterface;
25+
use FastForward\DevTools\Composer\Json\Schema\Author;
2526
use FastForward\DevTools\Composer\Json\Schema\AuthorInterface;
2627
use FastForward\DevTools\Filesystem\FilesystemInterface;
2728
use FastForward\DevTools\License\Generator;
2829
use FastForward\DevTools\License\ResolverInterface;
2930
use PHPUnit\Framework\Attributes\CoversClass;
3031
use PHPUnit\Framework\Attributes\Test;
32+
use PHPUnit\Framework\Attributes\UsesClass;
3133
use PHPUnit\Framework\TestCase;
3234
use Prophecy\Argument;
3335
use Prophecy\Prophecy\ObjectProphecy;
3436
use Prophecy\PhpUnit\ProphecyTrait;
3537
use Psr\Clock\ClockInterface;
3638
use Twig\Environment;
39+
use Twig\Loader\ArrayLoader;
3740

3841
#[CoversClass(Generator::class)]
42+
#[UsesClass(Author::class)]
3943
final class GeneratorTest extends TestCase
4044
{
4145
use ProphecyTrait;
@@ -144,6 +148,43 @@ public function generateWithValidLicenseWillCreateFile(): void
144148
self::assertSame($renderedContent, $result);
145149
}
146150

151+
/**
152+
* @return void
153+
*/
154+
#[Test]
155+
public function generateContentWillPreserveLiteralAuthorEmailAngleBrackets(): void
156+
{
157+
$generator = new Generator(
158+
$this->resolver->reveal(),
159+
$this->composer->reveal(),
160+
$this->clock->reveal(),
161+
new Environment(new ArrayLoader([
162+
'licenses/mit.txt' => 'Copyright (c) {{ year }} {{ copyright_holder }}',
163+
]), [
164+
'autoescape' => 'html',
165+
]),
166+
$this->filesystem->reveal(),
167+
);
168+
169+
$this->composer->getLicense()
170+
->willReturn('MIT');
171+
$this->resolver->resolve('MIT')
172+
->willReturn('mit.txt');
173+
$this->composer->getAuthors(true)
174+
->willReturn(new Author('Felipe Sayão Lobato Abreu', 'github@mentordosnerds.com'));
175+
$this->clock->now()
176+
->willReturn(new DateTimeImmutable('2026-04-23'));
177+
178+
$content = $generator->generateContent();
179+
180+
self::assertSame(
181+
'Copyright (c) 2026 Felipe Sayão Lobato Abreu <github@mentordosnerds.com>',
182+
$content,
183+
);
184+
self::assertStringNotContainsString('&lt;', (string) $content);
185+
self::assertStringNotContainsString('&gt;', (string) $content);
186+
}
187+
147188
/**
148189
* @return void
149190
*/

0 commit comments

Comments
 (0)