MentionExtensionTest.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the league/commonmark package.
  5. *
  6. * (c) Colin O'Dell <colinodell@gmail.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace League\CommonMark\Tests\Functional\Extension\Mention;
  12. use League\CommonMark\Environment\Environment;
  13. use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
  14. use League\CommonMark\Extension\Mention\Generator\MentionGeneratorInterface;
  15. use League\CommonMark\Extension\Mention\Mention;
  16. use League\CommonMark\Extension\Mention\MentionExtension;
  17. use League\CommonMark\MarkdownConverter;
  18. use League\CommonMark\Node\Inline\AbstractInline;
  19. use League\CommonMark\Parser\MarkdownParser;
  20. use League\CommonMark\Xml\XmlRenderer;
  21. use League\Config\Exception\InvalidConfigurationException;
  22. use PHPUnit\Framework\TestCase;
  23. final class MentionExtensionTest extends TestCase
  24. {
  25. public function testNoConfig(): void
  26. {
  27. $input = <<<'EOT'
  28. You can follow the author of this library on GitHub - he's @colinodell!
  29. EOT;
  30. $expected = <<<'EOT'
  31. <p>You can follow the author of this library on GitHub - he's @colinodell!</p>
  32. EOT;
  33. $environment = new Environment();
  34. $environment->addExtension(new CommonMarkCoreExtension());
  35. $environment->addExtension(new MentionExtension());
  36. $converter = new MarkdownConverter($environment);
  37. $this->assertEquals($expected, $converter->convert($input));
  38. }
  39. public function testConfigStringGenerator(): void
  40. {
  41. $input = <<<'EOT'
  42. You can follow the author of this library on GitHub - he's @colinodell!
  43. EOT;
  44. $expected = <<<'EOT'
  45. <p>You can follow the author of this library on GitHub - he's <a href="https://github.com/colinodell">@colinodell</a>!</p>
  46. EOT;
  47. $environment = new Environment([
  48. 'mentions' => [
  49. 'github_handle' => [
  50. 'prefix' => '@',
  51. 'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)',
  52. 'generator' => 'https://github.com/%s',
  53. ],
  54. ],
  55. ]);
  56. $environment->addExtension(new CommonMarkCoreExtension());
  57. $environment->addExtension(new MentionExtension());
  58. $converter = new MarkdownConverter($environment);
  59. $this->assertEquals($expected, $converter->convert($input));
  60. }
  61. public function testConfigCallableGenerator(): void
  62. {
  63. $input = <<<'EOT'
  64. You can follow the author of this library on GitHub - he's @colinodell!
  65. EOT;
  66. $expected = <<<'EOT'
  67. <p>You can follow the author of this library on GitHub - he's <a href="https://github.com/colinodell">@colinodell</a>!</p>
  68. EOT;
  69. $environment = new Environment([
  70. 'mentions' => [
  71. 'github_handle' => [
  72. 'prefix' => '@',
  73. 'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)',
  74. 'generator' => static function (Mention $mention) {
  75. $mention->setUrl(\sprintf('https://github.com/%s', $mention->getIdentifier()));
  76. return $mention;
  77. },
  78. ],
  79. ],
  80. ]);
  81. $environment->addExtension(new CommonMarkCoreExtension());
  82. $environment->addExtension(new MentionExtension());
  83. $converter = new MarkdownConverter($environment);
  84. $this->assertEquals($expected, $converter->convert($input));
  85. }
  86. public function testConfigObjectImplementingMentionGeneratorInterface(): void
  87. {
  88. $input = <<<'EOT'
  89. You can follow the author of this library on GitHub - he's @colinodell!
  90. EOT;
  91. $expected = <<<'EOT'
  92. <p>You can follow the author of this library on GitHub - he's <a href="https://github.com/colinodell">@colinodell</a>!</p>
  93. EOT;
  94. $environment = new Environment([
  95. 'mentions' => [
  96. 'github_handle' => [
  97. 'prefix' => '@',
  98. 'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)',
  99. 'generator' => new class () implements MentionGeneratorInterface {
  100. public function generateMention(Mention $mention): ?AbstractInline
  101. {
  102. $mention->setUrl(\sprintf('https://github.com/%s', $mention->getIdentifier()));
  103. return $mention;
  104. }
  105. },
  106. ],
  107. ],
  108. ]);
  109. $environment->addExtension(new CommonMarkCoreExtension());
  110. $environment->addExtension(new MentionExtension());
  111. $converter = new MarkdownConverter($environment);
  112. $this->assertEquals($expected, $converter->convert($input));
  113. }
  114. public function testConfigUnknownGenerator(): void
  115. {
  116. $this->expectException(InvalidConfigurationException::class);
  117. $environment = new Environment([
  118. 'mentions' => [
  119. 'github_handle' => [
  120. 'prefix' => '@',
  121. 'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)',
  122. 'generator' => new \stdClass(),
  123. ],
  124. ],
  125. ]);
  126. $environment->addExtension(new CommonMarkCoreExtension());
  127. $environment->addExtension(new MentionExtension());
  128. $converter = new MarkdownConverter($environment);
  129. $converter->convert('');
  130. }
  131. public function testLegacySymbolOption(): void
  132. {
  133. $this->expectException(InvalidConfigurationException::class);
  134. $environment = new Environment([
  135. 'mentions' => [
  136. 'github_handle' => [
  137. 'symbol' => '@',
  138. 'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)',
  139. 'generator' => 'https://github.com/%s',
  140. ],
  141. ],
  142. ]);
  143. $environment->addExtension(new CommonMarkCoreExtension());
  144. $environment->addExtension(new MentionExtension());
  145. $converter = new MarkdownConverter($environment);
  146. $converter->convert('foo');
  147. }
  148. public function testWithFullRegexOption(): void
  149. {
  150. $this->expectException(InvalidConfigurationException::class);
  151. $environment = new Environment([
  152. 'mentions' => [
  153. 'github_handle' => [
  154. 'prefix' => '@',
  155. 'pattern' => '/[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)/i',
  156. 'generator' => 'https://github.com/%s',
  157. ],
  158. ],
  159. ]);
  160. $environment->addExtension(new CommonMarkCoreExtension());
  161. $environment->addExtension(new MentionExtension());
  162. $converter = new MarkdownConverter($environment);
  163. $converter->convert('foo');
  164. }
  165. public function testXmlRendering(): void
  166. {
  167. $input = <<<'EOT'
  168. You can follow the author of this library on GitHub - he's @colinodell!
  169. EOT;
  170. $expected = <<<'EOT'
  171. <?xml version="1.0" encoding="UTF-8"?>
  172. <document xmlns="http://commonmark.org/xml/1.0">
  173. <paragraph>
  174. <text>You can follow the author of this library on GitHub - he's </text>
  175. <link destination="https://github.com/colinodell" title="">
  176. <text>@colinodell</text>
  177. </link>
  178. <text>!</text>
  179. </paragraph>
  180. </document>
  181. EOT;
  182. $environment = new Environment([
  183. 'mentions' => [
  184. 'github_handle' => [
  185. 'prefix' => '@',
  186. 'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)',
  187. 'generator' => new class () implements MentionGeneratorInterface {
  188. public function generateMention(Mention $mention): ?AbstractInline
  189. {
  190. $mention->setUrl(\sprintf('https://github.com/%s', $mention->getIdentifier()));
  191. return $mention;
  192. }
  193. },
  194. ],
  195. ],
  196. ]);
  197. $environment->addExtension(new CommonMarkCoreExtension());
  198. $environment->addExtension(new MentionExtension());
  199. $document = (new MarkdownParser($environment))->parse($input);
  200. $xml = (new XmlRenderer($environment))->renderDocument($document)->getContent();
  201. $this->assertSame($expected, $xml);
  202. }
  203. public function testMentionLikeLabelInExistingLinks(): void
  204. {
  205. $input = <<<'EOT'
  206. Try [asking **@driesvints**](https://github.com/driesvints).
  207. EOT;
  208. $expected = <<<'EOT'
  209. <p>Try <a href="https://github.com/driesvints">asking <strong>@driesvints</strong></a>.</p>
  210. EOT;
  211. $environment = new Environment([
  212. 'mentions' => [
  213. 'username' => [
  214. 'prefix' => '@',
  215. 'pattern' => '[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)',
  216. 'generator' => 'https://github.com/user/%s',
  217. ],
  218. ],
  219. ]);
  220. $environment->addExtension(new CommonMarkCoreExtension());
  221. $environment->addExtension(new MentionExtension());
  222. $converter = new MarkdownConverter($environment);
  223. $this->assertSame($expected, $converter->convert($input)->getContent());
  224. }
  225. }