PHP and Javascript implementations of a simple markdown parser
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

InlineTests.php 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. declare(strict_types=1);
  3. use PHPUnit\Framework\TestCase;
  4. require_once __DIR__ . '/../php/markdown.php';
  5. final class InlineTests extends TestCase {
  6. private ?Markdown $parser = null;
  7. protected function setUp(): void {
  8. parent::setUp();
  9. $this->parser = Markdown::completeParser();
  10. }
  11. private function md(string $markdown): string {
  12. return $this->normalizeWhitespace($this->parser->toHTML($markdown));
  13. }
  14. private function normalizeWhitespace(string $str): string {
  15. $str = mb_eregi_replace('\\s+', ' ', $str);
  16. return trim($str);
  17. }
  18. public function test_simpleText() {
  19. $markdown = 'Lorem ipsum';
  20. $expected = 'Lorem ipsum';
  21. $actual = $this->md($markdown);
  22. $this->assertSame($expected, $actual);
  23. }
  24. public function test_strong() {
  25. $markdown = 'Lorem **ipsum** dolor **sit**';
  26. $expected = 'Lorem <strong>ipsum</strong> dolor <strong>sit</strong>';
  27. $actual = $this->md($markdown);
  28. $this->assertSame($expected, $actual);
  29. }
  30. public function test_emphasis() {
  31. $markdown = 'Lorem _ipsum_ dolor _sit_';
  32. $expected = 'Lorem <em>ipsum</em> dolor <em>sit</em>';
  33. $actual = $this->md($markdown);
  34. $this->assertSame($expected, $actual);
  35. }
  36. public function test_strongEmphasis_cleanNesting1() {
  37. $markdown = 'Lorem **ipsum *dolor* sit** amet';
  38. $expected = 'Lorem <strong>ipsum <em>dolor</em> sit</strong> amet';
  39. $actual = $this->md($markdown);
  40. $this->assertSame($expected, $actual);
  41. }
  42. public function test_strongEmphasis_cleanNesting2() {
  43. $markdown = 'Lorem *ipsum **dolor** sit* amet';
  44. $expected = 'Lorem <em>ipsum <strong>dolor</strong> sit</em> amet';
  45. $actual = $this->md($markdown);
  46. $this->assertSame($expected, $actual);
  47. }
  48. public function test_strongEmphasis_tightNesting() {
  49. $markdown = 'Lorem ***ipsum*** dolor';
  50. $expected = 'Lorem <strong><em>ipsum</em></strong> dolor';
  51. $actual = $this->md($markdown);
  52. $this->assertSame($expected, $actual);
  53. }
  54. public function test_strongEmphasis_lopsidedNesting1() {
  55. $markdown = 'Lorem ***ipsum* dolor** sit';
  56. $expected = 'Lorem <strong><em>ipsum</em> dolor</strong> sit';
  57. $actual = $this->md($markdown);
  58. $this->assertSame($expected, $actual);
  59. }
  60. public function test_strongEmphasis_lopsidedNesting2() {
  61. $markdown = 'Lorem ***ipsum** dolor* sit';
  62. $expected = 'Lorem <em><strong>ipsum</strong> dolor</em> sit';
  63. $actual = $this->md($markdown);
  64. $this->assertSame($expected, $actual);
  65. }
  66. public function test_strongEmphasis_lopsidedNesting3() {
  67. $markdown = 'Lorem **ipsum *dolor*** sit';
  68. $expected = 'Lorem <strong>ipsum <em>dolor</em></strong> sit';
  69. $actual = $this->md($markdown);
  70. $this->assertSame($expected, $actual);
  71. }
  72. public function test_strongEmphasis_lopsidedNesting4() {
  73. $markdown = 'Lorem *ipsum **dolor*** sit';
  74. $expected = 'Lorem <em>ipsum <strong>dolor</strong></em> sit';
  75. $actual = $this->md($markdown);
  76. $this->assertSame($expected, $actual);
  77. }
  78. public function test_inlineCode() {
  79. $markdown = 'Lorem `ipsum` dolor';
  80. $expected = 'Lorem <code>ipsum</code> dolor';
  81. $actual = $this->md($markdown);
  82. $this->assertSame($expected, $actual);
  83. }
  84. public function test_inlineCode_withInnerBacktick() {
  85. $markdown = 'Lorem ``ip`su`m`` dolor';
  86. $expected = 'Lorem <code>ip`su`m</code> dolor';
  87. $actual = $this->md($markdown);
  88. $this->assertSame($expected, $actual);
  89. }
  90. public function test_strikethrough_double() {
  91. $markdown = 'Lorem ~~ipsum~~ dolor';
  92. $expected = 'Lorem <s>ipsum</s> dolor';
  93. $actual = $this->md($markdown);
  94. $this->assertSame($expected, $actual);
  95. }
  96. public function test_subscript() {
  97. $markdown = 'H~2~O';
  98. $expected = 'H<sub>2</sub>O';
  99. $actual = $this->md($markdown);
  100. $this->assertSame($expected, $actual);
  101. }
  102. public function test_superscript() {
  103. $markdown = 'E=mc^2^';
  104. $expected = 'E=mc<sup>2</sup>';
  105. $actual = $this->md($markdown);
  106. $this->assertSame($expected, $actual);
  107. }
  108. public function test_highlight() {
  109. $markdown = 'Lorem ==ipsum== dolor';
  110. $expected = 'Lorem <mark>ipsum</mark> dolor';
  111. $actual = $this->md($markdown);
  112. $this->assertSame($expected, $actual);
  113. }
  114. public function test_underline() {
  115. $markdown = 'Lorem __ipsum__ dolor';
  116. $expected = 'Lorem <u>ipsum</u> dolor';
  117. $actual = $this->md($markdown);
  118. $this->assertSame($expected, $actual);
  119. }
  120. public function test_link_fullyQualified() {
  121. $markdown = 'Lorem [ipsum](https://example.com/path/page.html) dolor';
  122. $expected = 'Lorem <a href="https://example.com/path/page.html">ipsum</a> dolor';
  123. $actual = $this->md($markdown);
  124. $this->assertSame($expected, $actual);
  125. }
  126. public function test_link_relative() {
  127. $markdown = 'Lorem [ipsum](page.html) dolor';
  128. $expected = 'Lorem <a href="page.html">ipsum</a> dolor';
  129. $actual = $this->md($markdown);
  130. $this->assertSame($expected, $actual);
  131. }
  132. public function test_link_title() {
  133. $markdown = 'Lorem [ipsum](page.html "link title") dolor';
  134. $expected = 'Lorem <a href="page.html" title="link title">ipsum</a> dolor';
  135. $actual = $this->md($markdown);
  136. $this->assertSame($expected, $actual);
  137. }
  138. public function test_link_literal() {
  139. $markdown = 'Lorem <https://example.com> dolor';
  140. $expected = 'Lorem <a href="https://example.com">https://example.com</a> dolor';
  141. $actual = $this->md($markdown);
  142. $this->assertSame($expected, $actual);
  143. }
  144. public function test_link_ref() {
  145. $markdown = "Lorem [ipsum][ref] dolor\n\n[ref]: https://example.com";
  146. $expected = '<p>Lorem <a href="https://example.com">ipsum</a> dolor</p>';
  147. $actual = $this->md($markdown);
  148. $this->assertSame($expected, $actual);
  149. }
  150. public function test_link_email() {
  151. $markdown = 'Lorem [ipsum](user@example.com) dolor';
  152. $expected = 'Lorem <a href="mailto:&#117;&#115;&#101;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;">ipsum</a> dolor';
  153. $actual = $this->md($markdown);
  154. $this->assertSame($expected, $actual);
  155. }
  156. public function test_link_email_withTitle() {
  157. $markdown = 'Lorem [ipsum](user@example.com "title") dolor';
  158. $expected = 'Lorem <a href="mailto:&#117;&#115;&#101;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;" title="title">ipsum</a> dolor';
  159. $actual = $this->md($markdown);
  160. $this->assertSame($expected, $actual);
  161. }
  162. public function test_link_literalEmail() {
  163. $markdown = 'Lorem <user@example.com> dolor';
  164. $expected = 'Lorem <a href="mailto:&#117;&#115;&#101;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;">&#117;&#115;&#101;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;</a> dolor';
  165. $actual = $this->md($markdown);
  166. $this->assertSame($expected, $actual);
  167. }
  168. public function test_link_image() {
  169. $markdown = 'Lorem [![alt](image.jpg)](page.html) ipsum';
  170. $expected = 'Lorem <a href="page.html"><img src="image.jpg" alt="alt"></a> ipsum';
  171. $actual = $this->md($markdown);
  172. $this->assertSame($expected, $actual);
  173. }
  174. public function test_link_image_complex() {
  175. $markdown = 'Lorem [![alt] (image.jpg "image title")] (page.html "link title") ipsum';
  176. $expected = 'Lorem <a href="page.html" title="link title"><img src="image.jpg" alt="alt" title="image title"></a> ipsum';
  177. $actual = $this->md($markdown);
  178. $this->assertSame($expected, $actual);
  179. }
  180. public function test_image() {
  181. $markdown = 'Lorem ![alt text](image.jpg) dolor';
  182. $expected = 'Lorem <img src="image.jpg" alt="alt text"> dolor';
  183. $actual = $this->md($markdown);
  184. $this->assertSame($expected, $actual);
  185. }
  186. public function test_image_noAlt() {
  187. $markdown = 'Lorem ![](image.jpg) dolor';
  188. $expected = 'Lorem <img src="image.jpg"> dolor';
  189. $actual = $this->md($markdown);
  190. $this->assertSame($expected, $actual);
  191. }
  192. public function test_image_withTitle() {
  193. $markdown = 'Lorem ![alt text](image.jpg "image title") dolor';
  194. $expected = 'Lorem <img src="image.jpg" alt="alt text" title="image title"> dolor';
  195. $actual = $this->md($markdown);
  196. $this->assertSame($expected, $actual);
  197. }
  198. public function test_image_ref() {
  199. $markdown = "Lorem ![alt text][ref] dolor\n\n" .
  200. '[ref]: image.jpg "image title"';
  201. $expected = '<p>Lorem <img src="image.jpg" alt="alt text" title="image title"> dolor</p>';
  202. $actual = $this->md($markdown);
  203. $this->assertSame($expected, $actual);
  204. }
  205. public function test_htmlTags() {
  206. $markdown = 'Lorem <strong title=\'with " quote\' id="with \' apostrophe" lang=unquoted translate forbidden="true">ipsum</strong> dolor';
  207. $expected = 'Lorem <strong title="with &quot; quote" id="with \' apostrophe" lang="unquoted" translate>ipsum</strong> dolor';
  208. $actual = $this->md($markdown);
  209. $this->assertSame($expected, $actual);
  210. }
  211. }