From 66926bc640c96acd4ab89418e8c21167e4c9192e Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 18 Apr 2026 21:47:38 +0530 Subject: [PATCH 01/20] Updated instructions.md --- .../practice/markdown/.docs/instructions.md | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/exercises/practice/markdown/.docs/instructions.md b/exercises/practice/markdown/.docs/instructions.md index 4819b6c2..b3f3044c 100644 --- a/exercises/practice/markdown/.docs/instructions.md +++ b/exercises/practice/markdown/.docs/instructions.md @@ -2,14 +2,12 @@ Refactor a Markdown parser. -The markdown exercise is a refactoring exercise. There is code that parses a -given string with [Markdown -syntax](https://guides.github.com/features/mastering-markdown/) and returns the -associated HTML for that string. Even though this code is confusingly written -and hard to follow, somehow it works and all the tests are passing! Your -challenge is to re-write this code to make it easier to read and maintain -while still making sure that all the tests keep passing. - -It would be helpful if you made notes of what you did in your refactoring in -comments so reviewers can see that, but it isn't strictly necessary. The most -important thing is to make the code better! +The markdown exercise is a refactoring exercise. +There is code that parses a given string with [Markdown syntax][markdown] and returns the associated HTML for that string. +Even though this code is confusingly written and hard to follow, somehow it works and all the tests are passing! +Your challenge is to re-write this code to make it easier to read and maintain while still making sure that all the tests keep passing. + +It would be helpful if you made notes of what you did in your refactoring in comments so reviewers can see that, but it isn't strictly necessary. +The most important thing is to make the code better! + +[markdown]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax From bdf80100243460dab8c5b4c9ea00658acf9b4c2a Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 18 Apr 2026 21:47:50 +0530 Subject: [PATCH 02/20] Updated Tests.toml --- exercises/practice/markdown/.meta/tests.toml | 30 ++++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/exercises/practice/markdown/.meta/tests.toml b/exercises/practice/markdown/.meta/tests.toml index fecbcf50..28b7baa7 100644 --- a/exercises/practice/markdown/.meta/tests.toml +++ b/exercises/practice/markdown/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. [e75c8103-a6b8-45d9-84ad-e68520545f6e] description = "parses normal text as a paragraph" @@ -20,9 +27,26 @@ description = "with h1 header level" [d0f7a31f-6935-44ac-8a9a-1e8ab16af77f] description = "with h2 header level" +[9df3f500-0622-4696-81a7-d5babd9b5f49] +description = "with h3 header level" + +[50862777-a5e8-42e9-a3b8-4ba6fcd0ed03] +description = "with h4 header level" + +[ee1c23ac-4c86-4f2a-8b9c-403548d4ab82] +description = "with h5 header level" + [13b5f410-33f5-44f0-a6a7-cfd4ab74b5d5] description = "with h6 header level" +[6dca5d10-5c22-4e2a-ac2b-bd6f21e61939] +description = "with h7 header level" +include = false + +[81c0c4db-435e-4d77-860d-45afacdad810] +description = "h7 header level is a paragraph" +reimplements = "6dca5d10-5c22-4e2a-ac2b-bd6f21e61939" + [25288a2b-8edc-45db-84cf-0b6c6ee034d6] description = "unordered lists" From 5ac56a1db9ff42550f906b67f1584604925d81a6 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 18 Apr 2026 21:48:28 +0530 Subject: [PATCH 03/20] Added markdown in auto-sync.txt --- bin/auto-sync.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/auto-sync.txt b/bin/auto-sync.txt index ba848805..9094e760 100644 --- a/bin/auto-sync.txt +++ b/bin/auto-sync.txt @@ -45,6 +45,7 @@ line-up linked-list list-ops luhn +markdown matching-brackets meetup micro-blog From c9dfce1db1ae7e8142b80741826e9758c0bc77b0 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 18 Apr 2026 21:50:28 +0530 Subject: [PATCH 04/20] Added missing test cases and Removed strict types comments --- exercises/practice/markdown/.meta/example.php | 22 ---- exercises/practice/markdown/Markdown.php | 22 ---- exercises/practice/markdown/MarkdownTest.php | 123 ++++++++++++++---- 3 files changed, 101 insertions(+), 66 deletions(-) diff --git a/exercises/practice/markdown/.meta/example.php b/exercises/practice/markdown/.meta/example.php index 5f3a447c..b1f1fdd2 100644 --- a/exercises/practice/markdown/.meta/example.php +++ b/exercises/practice/markdown/.meta/example.php @@ -1,27 +1,5 @@ . - * - * To disable strict typing, comment out the directive below. - */ - declare(strict_types=1); function parseMarkdown($markdown) diff --git a/exercises/practice/markdown/Markdown.php b/exercises/practice/markdown/Markdown.php index 961d8914..a0ab8173 100644 --- a/exercises/practice/markdown/Markdown.php +++ b/exercises/practice/markdown/Markdown.php @@ -1,27 +1,5 @@ . - * - * To disable strict typing, comment out the directive below. - */ - declare(strict_types=1); function parseMarkdown($markdown) diff --git a/exercises/practice/markdown/MarkdownTest.php b/exercises/practice/markdown/MarkdownTest.php index 9e2c7bf5..6816ad00 100644 --- a/exercises/practice/markdown/MarkdownTest.php +++ b/exercises/practice/markdown/MarkdownTest.php @@ -1,29 +1,8 @@ . - * - * To disable strict typing, comment out the directive below. - */ - declare(strict_types=1); +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; class MarkdownTest extends TestCase @@ -33,41 +12,97 @@ public static function setUpBeforeClass(): void require_once 'Markdown.php'; } + /** uuid: e75c8103-a6b8-45d9-84ad-e68520545f6e */ + #[TestDox('parses normal text as a paragraph')] public function testParsingParagraph(): void { $this->assertEquals('

This will be a paragraph

', parseMarkdown('This will be a paragraph')); } + /** uuid: 69a4165d-9bf8-4dd7-bfdc-536eaca80a6a */ + #[TestDox('parsing italics')] public function testParsingItalics(): void { $this->assertEquals('

This will be italic

', parseMarkdown('_This will be italic_')); } + /** uuid: ec345a1d-db20-4569-a81a-172fe0cad8a1 */ + #[TestDox('parsing bold text')] public function testParsingBoldText(): void { $this->assertEquals('

This will be bold

', parseMarkdown('__This will be bold__')); } + /** uuid: 51164ed4-5641-4909-8fab-fbaa9d37d5a8 */ + #[TestDox('mixed normal, italics and bold text')] public function testMixedNormalItalicsAndBoldText(): void { $this->assertEquals('

This will be mixed

', parseMarkdown('This will _be_ __mixed__')); } + /** uuid: ad85f60d-0edd-4c6a-a9b1-73e1c4790d15 */ + #[TestDox('with h1 header level')] public function testWithH1Headerlevel(): void { $this->assertEquals('

This will be an h1

', parseMarkdown('# This will be an h1')); } + /** uuid: d0f7a31f-6935-44ac-8a9a-1e8ab16af77f */ + #[TestDox('with h2 header level')] public function testWithH2Headerlevel(): void { $this->assertEquals('

This will be an h2

', parseMarkdown('## This will be an h2')); } + /** uuid: 9df3f500-0622-4696-81a7-d5babd9b5f49 */ + # #[TestDox('with h3 header level')] + # public function testWithH3headerLevel(): void + # { + # $this->assertEquals( + # '

This will be an h3

', + # parseMarkdown('### This will be an h3') + # ); + # } +# + /** uuid: 50862777-a5e8-42e9-a3b8-4ba6fcd0ed03 */ + # #[TestDox('with h4 header level')] + # public function testWithH4headerLevel(): void + # { + # $this->assertEquals( + # '

This will be an h4

', + # parseMarkdown('#### This will be an h4') + # ); + # } +# + # /** uuid: ee1c23ac-4c86-4f2a-8b9c-403548d4ab82 */ + # #[TestDox('with h5 header level')] + # public function testWithH5headerLevel(): void + # { + # $this->assertEquals( + # '
This will be an h5
', + # parseMarkdown('##### This will be an h5') + # ); + # } + + /** uuid: 13b5f410-33f5-44f0-a6a7-cfd4ab74b5d5 */ + #[TestDox('with h6 header level')] public function testWithH6Headerlevel(): void { $this->assertEquals('
This will be an h6
', parseMarkdown('###### This will be an h6')); } + /** uuid: 81c0c4db-435e-4d77-860d-45afacdad810 */ + # #[TestDox('h7 header level is a paragraph')] + # public function testH7HeaderIsAParagraph(): void + # { + # $this->assertEquals( + # '

####### This will be an h7 but it render as paragraph

', + # parseMarkdown('####### This will be an h7 but it render as paragraph') + # ); + # } + + /** uuid: 25288a2b-8edc-45db-84cf-0b6c6ee034d6 */ + #[TestDox('unordered lists')] public function testUnorderedLists(): void { $this->assertEquals( @@ -76,6 +111,8 @@ public function testUnorderedLists(): void ); } + /** uuid: 7bf92413-df8f-4de8-9184-b724f363c3da */ + #[TestDox('With a little bit of everything')] public function testWithALittleBitOfEverything(): void { $this->assertEquals( @@ -83,4 +120,46 @@ public function testWithALittleBitOfEverything(): void parseMarkdown("# Header!\n* __Bold Item__\n* _Italic Item_") ); } + + + + /** uuid: 0b3ed1ec-3991-4b8b-8518-5cb73d4a64fe */ + # #[TestDox('with markdown symbols in the header text that should not be interpreted')] + # public function testMarkdownSymbolInHeaderText(): void + # { + # $this->assertEquals( + # '

This is a header with # and * in the text

', + # parseMarkdown('# This is a header with # and * in the text') + # ); + # } +# + # /** uuid: 113a2e58-78de-4efa-90e9-20972224d759 */ + # #[TestDox('with markdown symbols in the list item text that should not be interpreted')] + # public function testMarkdownSymbolInListItemText(): void + # { + # $this->assertEquals( + # '
  • Item 1 with a # in the text
  • Item 2 with * in the text
', + # parseMarkdown('* Item 1 with a # in the text\n* Item 2 with * in the text') + # ); + # } +# + # /** uuid: e65e46e2-17b7-4216-b3ac-f44a1b9bcdb4 */ + # #[TestDox('with markdown symbols in the paragraph text that should not be interpreted')] + # public function testMarkdownSymbolInParagraph(): void + # { + # $this->assertEquals( + # '

This is a paragraph with # and * in the text

', + # parseMarkdown('This is a paragraph with # and * in the text') + # ); + # } +# + # /** uuid: f0bbbbde-0f52-4c0c-99ec-be4c60126dd4 */ + # #[TestDox('unordered lists close properly with preceding and following lines')] + # public function testUnorderedListCloseProperlyWithPrecedingAndFollowingLines(): void + # { + # $this->assertEquals( + # '

Start a list

  • Item 1
  • Item 2

End a list

', + # parseMarkdown('# Start a list\n* Item 1\n* Item 2\nEnd a list') + # ); + # } } From 8466895f77e13e6143e7a2c468baddc026993656 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 18 Apr 2026 21:50:51 +0530 Subject: [PATCH 05/20] Updated contributor Name --- exercises/practice/markdown/.meta/config.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/exercises/practice/markdown/.meta/config.json b/exercises/practice/markdown/.meta/config.json index 294e9344..460acbed 100644 --- a/exercises/practice/markdown/.meta/config.json +++ b/exercises/practice/markdown/.meta/config.json @@ -5,7 +5,8 @@ "contributors": [ "arueckauer", "kytrinyx", - "yisraeldov" + "yisraeldov", + "Narkunan" ], "files": { "solution": [ @@ -18,5 +19,5 @@ ".meta/example.php" ] }, - "blurb": "Refactor a Markdown parser" + "blurb": "Refactor a Markdown parser." } From 3b6d9a9aeea1bc6282df5b1d86128fd5f81a0624 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sun, 19 Apr 2026 19:15:10 +0530 Subject: [PATCH 06/20] Added markdown in exclude --- phpcs.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpcs.xml b/phpcs.xml index c88f737e..ea6d8fe7 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -38,6 +38,7 @@ */.meta/*\.php */concept/* */hello-world/* + */markdown/* From 26cd14d73edb46d07a868c84fbaf838a516b1141 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sun, 19 Apr 2026 20:29:44 +0530 Subject: [PATCH 07/20] Updated markdown to works with new test cases --- exercises/practice/markdown/.meta/example.php | 46 +++-- exercises/practice/markdown/Markdown.php | 43 ++-- exercises/practice/markdown/MarkdownTest.php | 184 ++++++++++-------- 3 files changed, 161 insertions(+), 112 deletions(-) diff --git a/exercises/practice/markdown/.meta/example.php b/exercises/practice/markdown/.meta/example.php index b1f1fdd2..a0ab0761 100644 --- a/exercises/practice/markdown/.meta/example.php +++ b/exercises/practice/markdown/.meta/example.php @@ -9,51 +9,64 @@ function parseMarkdown($markdown) $isInList = false; foreach ($lines as &$line) { - if (preg_match('/^######(.*)/', $line, $matches)) { + if (preg_match('/^####### (.*)/', $line, $matches)) { + $line = "

" . trim($matches[0]) . "

"; + } elseif (preg_match('/^###### (.*)/', $line, $matches)) { $line = "
" . trim($matches[1]) . "
"; - } elseif (preg_match('/^##(.*)/', $line, $matches)) { + } elseif (preg_match('/^##### (.*)/', $line, $matches)) { + $line = "
" . trim($matches[1]) . "
"; + } elseif (preg_match('/^#### (.*)/', $line, $matches)) { + $line = "

" . trim($matches[1]) . "

"; + } elseif (preg_match('/^### (.*)/', $line, $matches)) { + $line = "

" . trim($matches[1]) . "

"; + } elseif (preg_match('/^## (.*)/', $line, $matches)) { $line = "

" . trim($matches[1]) . "

"; - } elseif (preg_match('/^#(.*)/', $line, $matches)) { + } elseif (preg_match('/^# (.*)/', $line, $matches)) { $line = "

" . trim($matches[1]) . "

"; } - if (preg_match('/\*(.*)/', $line, $matches)) { + if (preg_match('/^\s*\*(.*)/', $line, $matches)) { if (!$isInList) { $isInList = true; $isBold = false; $isItalic = false; if (preg_match('/(.*)__(.*)__(.*)/', $matches[1], $matches2)) { - $matches[1] = $matches2[1] . '' . $matches2[2] . '' . $matches2[3]; + $matches[1] = $matches2[1] . '' . $matches2[2] . '' . $matches2[3]; $isBold = true; } if (preg_match('/(.*)_(.*)_(.*)/', $matches[1], $matches3)) { - $matches[1] = $matches3[1] . '' . $matches3[2] . '' . $matches3[3]; + $matches[1] = $matches3[1] . '' . $matches3[2] . '' . $matches3[3]; $isItalic = true; } if ($isItalic || $isBold) { $line = "
  • " . trim($matches[1]) . "
  • "; } else { - $line = "
    • " . trim($matches[1]) . "

    • "; + $line = "
        "; + $line .= "
      • "; + $line .= trim($matches[1]); + $line .= "
      • "; } } else { $isBold = false; $isItalic = false; if (preg_match('/(.*)__(.*)__(.*)/', $matches[1], $matches2)) { - $matches[1] = $matches2[1] . '' . $matches2[2] . '' . $matches2[3]; + $matches[1] = $matches2[1] . '' . $matches2[2] . '' . $matches2[3]; $isBold = true; } if (preg_match('/(.*)_(.*)_(.*)/', $matches[1], $matches3)) { - $matches[1] = $matches3[1] . '' . $matches3[2] . '' . $matches3[3]; + $matches[1] = $matches3[1] . '' . $matches3[2] . '' . $matches3[3]; $isItalic = true; } if ($isItalic || $isBold) { $line = "
      • " . trim($matches[1]) . "
      • "; } else { - $line = "
      • " . trim($matches[1]) . "

      • "; + $line = "
      • "; + $line .= trim($matches[1]); + $line .= "
      • "; } } } else { @@ -64,23 +77,24 @@ function parseMarkdown($markdown) } if (!preg_match('/(.*)/', $line, $matches)) { + $line = "

      " . trim($matches[1]) . "

      "; + } else { + $line = "

      $line

      "; + } } if (preg_match('/(.*)__(.*)__(.*)/', $line, $matches)) { - $line = $matches[1] . '' . $matches[2] . '' . $matches[3]; + $line = $matches[1] . '' . $matches[2] . '' . $matches[3]; } if (preg_match('/(.*)_(.*)_(.*)/', $line, $matches)) { - $line = $matches[1] . '' . $matches[2] . '' . $matches[3]; + $line = $matches[1] . '' . $matches[2] . '' . $matches[3]; } } - $html = join($lines); - if ($isInList) { $html .= '
    '; } - return $html; } diff --git a/exercises/practice/markdown/Markdown.php b/exercises/practice/markdown/Markdown.php index a0ab8173..a0ab0761 100644 --- a/exercises/practice/markdown/Markdown.php +++ b/exercises/practice/markdown/Markdown.php @@ -9,51 +9,64 @@ function parseMarkdown($markdown) $isInList = false; foreach ($lines as &$line) { - if (preg_match('/^######(.*)/', $line, $matches)) { + if (preg_match('/^####### (.*)/', $line, $matches)) { + $line = "

    " . trim($matches[0]) . "

    "; + } elseif (preg_match('/^###### (.*)/', $line, $matches)) { $line = "
    " . trim($matches[1]) . "
    "; - } elseif (preg_match('/^##(.*)/', $line, $matches)) { + } elseif (preg_match('/^##### (.*)/', $line, $matches)) { + $line = "
    " . trim($matches[1]) . "
    "; + } elseif (preg_match('/^#### (.*)/', $line, $matches)) { + $line = "

    " . trim($matches[1]) . "

    "; + } elseif (preg_match('/^### (.*)/', $line, $matches)) { + $line = "

    " . trim($matches[1]) . "

    "; + } elseif (preg_match('/^## (.*)/', $line, $matches)) { $line = "

    " . trim($matches[1]) . "

    "; - } elseif (preg_match('/^#(.*)/', $line, $matches)) { + } elseif (preg_match('/^# (.*)/', $line, $matches)) { $line = "

    " . trim($matches[1]) . "

    "; } - if (preg_match('/\*(.*)/', $line, $matches)) { + if (preg_match('/^\s*\*(.*)/', $line, $matches)) { if (!$isInList) { $isInList = true; $isBold = false; $isItalic = false; if (preg_match('/(.*)__(.*)__(.*)/', $matches[1], $matches2)) { - $matches[1] = $matches2[1] . '' . $matches2[2] . '' . $matches2[3]; + $matches[1] = $matches2[1] . '' . $matches2[2] . '' . $matches2[3]; $isBold = true; } if (preg_match('/(.*)_(.*)_(.*)/', $matches[1], $matches3)) { - $matches[1] = $matches3[1] . '' . $matches3[2] . '' . $matches3[3]; + $matches[1] = $matches3[1] . '' . $matches3[2] . '' . $matches3[3]; $isItalic = true; } if ($isItalic || $isBold) { $line = "
    • " . trim($matches[1]) . "
    • "; } else { - $line = "
      • " . trim($matches[1]) . "

      • "; + $line = "
          "; + $line .= "
        • "; + $line .= trim($matches[1]); + $line .= "
        • "; } } else { $isBold = false; $isItalic = false; if (preg_match('/(.*)__(.*)__(.*)/', $matches[1], $matches2)) { - $matches[1] = $matches2[1] . '' . $matches2[2] . '' . $matches2[3]; + $matches[1] = $matches2[1] . '' . $matches2[2] . '' . $matches2[3]; $isBold = true; } if (preg_match('/(.*)_(.*)_(.*)/', $matches[1], $matches3)) { - $matches[1] = $matches3[1] . '' . $matches3[2] . '' . $matches3[3]; + $matches[1] = $matches3[1] . '' . $matches3[2] . '' . $matches3[3]; $isItalic = true; } if ($isItalic || $isBold) { $line = "
        • " . trim($matches[1]) . "
        • "; } else { - $line = "
        • " . trim($matches[1]) . "

        • "; + $line = "
        • "; + $line .= trim($matches[1]); + $line .= "
        • "; } } } else { @@ -64,15 +77,19 @@ function parseMarkdown($markdown) } if (!preg_match('/(.*)/', $line, $matches)) { + $line = "

        " . trim($matches[1]) . "

        "; + } else { + $line = "

        $line

        "; + } } if (preg_match('/(.*)__(.*)__(.*)/', $line, $matches)) { - $line = $matches[1] . '' . $matches[2] . '' . $matches[3]; + $line = $matches[1] . '' . $matches[2] . '' . $matches[3]; } if (preg_match('/(.*)_(.*)_(.*)/', $line, $matches)) { - $line = $matches[1] . '' . $matches[2] . '' . $matches[3]; + $line = $matches[1] . '' . $matches[2] . '' . $matches[3]; } } $html = join($lines); diff --git a/exercises/practice/markdown/MarkdownTest.php b/exercises/practice/markdown/MarkdownTest.php index 6816ad00..e9f33e67 100644 --- a/exercises/practice/markdown/MarkdownTest.php +++ b/exercises/practice/markdown/MarkdownTest.php @@ -16,97 +16,118 @@ public static function setUpBeforeClass(): void #[TestDox('parses normal text as a paragraph')] public function testParsingParagraph(): void { - $this->assertEquals('

        This will be a paragraph

        ', parseMarkdown('This will be a paragraph')); + $this->assertEquals( + "

        This will be a paragraph

        ", + parseMarkdown("This will be a paragraph") + ); } /** uuid: 69a4165d-9bf8-4dd7-bfdc-536eaca80a6a */ #[TestDox('parsing italics')] public function testParsingItalics(): void { - $this->assertEquals('

        This will be italic

        ', parseMarkdown('_This will be italic_')); + $this->assertEquals( + "

        This will be italic

        ", + parseMarkdown("_This will be italic_") + ); } /** uuid: ec345a1d-db20-4569-a81a-172fe0cad8a1 */ #[TestDox('parsing bold text')] public function testParsingBoldText(): void { - $this->assertEquals('

        This will be bold

        ', parseMarkdown('__This will be bold__')); + $this->assertEquals( + "

        This will be bold

        ", + parseMarkdown("__This will be bold__") + ); } /** uuid: 51164ed4-5641-4909-8fab-fbaa9d37d5a8 */ #[TestDox('mixed normal, italics and bold text')] public function testMixedNormalItalicsAndBoldText(): void { - $this->assertEquals('

        This will be mixed

        ', parseMarkdown('This will _be_ __mixed__')); + $this->assertEquals( + "

        This will be mixed

        ", + parseMarkdown("This will _be_ __mixed__") + ); } /** uuid: ad85f60d-0edd-4c6a-a9b1-73e1c4790d15 */ #[TestDox('with h1 header level')] public function testWithH1Headerlevel(): void { - $this->assertEquals('

        This will be an h1

        ', parseMarkdown('# This will be an h1')); + $this->assertEquals( + "

        This will be an h1

        ", + parseMarkdown("# This will be an h1") + ); } /** uuid: d0f7a31f-6935-44ac-8a9a-1e8ab16af77f */ #[TestDox('with h2 header level')] public function testWithH2Headerlevel(): void { - $this->assertEquals('

        This will be an h2

        ', parseMarkdown('## This will be an h2')); + $this->assertEquals( + "

        This will be an h2

        ", + parseMarkdown("## This will be an h2") + ); } /** uuid: 9df3f500-0622-4696-81a7-d5babd9b5f49 */ - # #[TestDox('with h3 header level')] - # public function testWithH3headerLevel(): void - # { - # $this->assertEquals( - # '

        This will be an h3

        ', - # parseMarkdown('### This will be an h3') - # ); - # } -# + #[TestDox('with h3 header level')] + public function testWithH3headerLevel(): void + { + $this->assertEquals( + "

        This will be an h3

        ", + parseMarkdown("### This will be an h3") + ); + } + /** uuid: 50862777-a5e8-42e9-a3b8-4ba6fcd0ed03 */ - # #[TestDox('with h4 header level')] - # public function testWithH4headerLevel(): void - # { - # $this->assertEquals( - # '

        This will be an h4

        ', - # parseMarkdown('#### This will be an h4') - # ); - # } -# - # /** uuid: ee1c23ac-4c86-4f2a-8b9c-403548d4ab82 */ - # #[TestDox('with h5 header level')] - # public function testWithH5headerLevel(): void - # { - # $this->assertEquals( - # '
        This will be an h5
        ', - # parseMarkdown('##### This will be an h5') - # ); - # } + #[TestDox('with h4 header level')] + public function testWithH4headerLevel(): void + { + $this->assertEquals( + "

        This will be an h4

        ", + parseMarkdown("#### This will be an h4") + ); + } + + /** uuid: ee1c23ac-4c86-4f2a-8b9c-403548d4ab82 */ + #[TestDox('with h5 header level')] + public function testWithH5headerLevel(): void + { + $this->assertEquals( + "
        This will be an h5
        ", + parseMarkdown("##### This will be an h5") + ); + } /** uuid: 13b5f410-33f5-44f0-a6a7-cfd4ab74b5d5 */ #[TestDox('with h6 header level')] public function testWithH6Headerlevel(): void { - $this->assertEquals('
        This will be an h6
        ', parseMarkdown('###### This will be an h6')); + $this->assertEquals( + "
        This will be an h6
        ", + parseMarkdown("###### This will be an h6") + ); } /** uuid: 81c0c4db-435e-4d77-860d-45afacdad810 */ - # #[TestDox('h7 header level is a paragraph')] - # public function testH7HeaderIsAParagraph(): void - # { - # $this->assertEquals( - # '

        ####### This will be an h7 but it render as paragraph

        ', - # parseMarkdown('####### This will be an h7 but it render as paragraph') - # ); - # } + #[TestDox('h7 header level is a paragraph')] + public function testH7HeaderIsAParagraph(): void + { + $this->assertEquals( + "

        ####### This will not be an h7

        ", + parseMarkdown("####### This will not be an h7") + ); + } /** uuid: 25288a2b-8edc-45db-84cf-0b6c6ee034d6 */ #[TestDox('unordered lists')] public function testUnorderedLists(): void { $this->assertEquals( - '
        • Item 1

        • Item 2

        ', + "
        • Item 1
        • Item 2
        ", parseMarkdown("* Item 1\n* Item 2") ); } @@ -116,50 +137,47 @@ public function testUnorderedLists(): void public function testWithALittleBitOfEverything(): void { $this->assertEquals( - '

        Header!

        • Bold Item
        • Italic Item
        ', + "

        Header!

        • Bold Item
        • Italic Item
        ", parseMarkdown("# Header!\n* __Bold Item__\n* _Italic Item_") ); } - - /** uuid: 0b3ed1ec-3991-4b8b-8518-5cb73d4a64fe */ - # #[TestDox('with markdown symbols in the header text that should not be interpreted')] - # public function testMarkdownSymbolInHeaderText(): void - # { - # $this->assertEquals( - # '

        This is a header with # and * in the text

        ', - # parseMarkdown('# This is a header with # and * in the text') - # ); - # } -# - # /** uuid: 113a2e58-78de-4efa-90e9-20972224d759 */ - # #[TestDox('with markdown symbols in the list item text that should not be interpreted')] - # public function testMarkdownSymbolInListItemText(): void - # { - # $this->assertEquals( - # '
        • Item 1 with a # in the text
        • Item 2 with * in the text
        ', - # parseMarkdown('* Item 1 with a # in the text\n* Item 2 with * in the text') - # ); - # } -# - # /** uuid: e65e46e2-17b7-4216-b3ac-f44a1b9bcdb4 */ - # #[TestDox('with markdown symbols in the paragraph text that should not be interpreted')] - # public function testMarkdownSymbolInParagraph(): void - # { - # $this->assertEquals( - # '

        This is a paragraph with # and * in the text

        ', - # parseMarkdown('This is a paragraph with # and * in the text') - # ); - # } + #[TestDox('with markdown symbols in the header text that should not be interpreted')] + public function testMarkdownSymbolInHeaderText(): void + { + $this->assertEquals( + "

        This is a header with # and * in the text

        ", + parseMarkdown("# This is a header with # and * in the text") + ); + } # - # /** uuid: f0bbbbde-0f52-4c0c-99ec-be4c60126dd4 */ - # #[TestDox('unordered lists close properly with preceding and following lines')] - # public function testUnorderedListCloseProperlyWithPrecedingAndFollowingLines(): void - # { - # $this->assertEquals( - # '

        Start a list

        • Item 1
        • Item 2

        End a list

        ', - # parseMarkdown('# Start a list\n* Item 1\n* Item 2\nEnd a list') - # ); - # } + /** uuid: 113a2e58-78de-4efa-90e9-20972224d759 */ + #[TestDox('with markdown symbols in the list item text that should not be interpreted')] + public function testMarkdownSymbolInListItemText(): void + { + $this->assertEquals( + "
        • Item 1 with a # in the text
        • Item 2 with * in the text
        ", + parseMarkdown("* Item 1 with a # in the text\n* Item 2 with * in the text") + ); + } + /** uuid: e65e46e2-17b7-4216-b3ac-f44a1b9bcdb4 */ + #[TestDox('with markdown symbols in the paragraph text that should not be interpreted')] + public function testMarkdownSymbolInParagraph(): void + { + $this->assertEquals( + "

        This is a paragraph with # and * in the text

        ", + parseMarkdown("This is a paragraph with # and * in the text") + ); + } + + /** uuid: f0bbbbde-0f52-4c0c-99ec-be4c60126dd4 */ + #[TestDox('unordered lists close properly with preceding and following lines')] + public function testUnorderedListCloseProperlyWithPrecedingAndFollowingLines(): void + { + $this->assertEquals( + "

        Start a list

        • Item 1
        • Item 2

        End a list

        ", + parseMarkdown("# Start a list\n* Item 1\n* Item 2\nEnd a list") + ); + } } From 2bdc0ef68c840bf3e277bb6225b7a4b369ff4387 Mon Sep 17 00:00:00 2001 From: narkunan Date: Mon, 20 Apr 2026 13:06:09 +0530 Subject: [PATCH 08/20] Removed markdown from exclude-pattern in phpcs.xml --- phpcs.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/phpcs.xml b/phpcs.xml index ea6d8fe7..c88f737e 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -38,7 +38,6 @@ */.meta/*\.php */concept/* */hello-world/* - */markdown/* From a07aca724012fdfaeb5dd30825a868d39cd9887c Mon Sep 17 00:00:00 2001 From: narkunan Date: Mon, 20 Apr 2026 13:06:33 +0530 Subject: [PATCH 09/20] Added strict types comment back --- exercises/practice/markdown/.meta/example.php | 22 +++++++++++++++++++ exercises/practice/markdown/Markdown.php | 22 +++++++++++++++++++ exercises/practice/markdown/MarkdownTest.php | 22 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/exercises/practice/markdown/.meta/example.php b/exercises/practice/markdown/.meta/example.php index a0ab0761..8f4a439b 100644 --- a/exercises/practice/markdown/.meta/example.php +++ b/exercises/practice/markdown/.meta/example.php @@ -1,5 +1,27 @@ . + * + * To disable strict typing, comment out the directive below. + */ + declare(strict_types=1); function parseMarkdown($markdown) diff --git a/exercises/practice/markdown/Markdown.php b/exercises/practice/markdown/Markdown.php index a0ab0761..8f4a439b 100644 --- a/exercises/practice/markdown/Markdown.php +++ b/exercises/practice/markdown/Markdown.php @@ -1,5 +1,27 @@ . + * + * To disable strict typing, comment out the directive below. + */ + declare(strict_types=1); function parseMarkdown($markdown) diff --git a/exercises/practice/markdown/MarkdownTest.php b/exercises/practice/markdown/MarkdownTest.php index e9f33e67..43289825 100644 --- a/exercises/practice/markdown/MarkdownTest.php +++ b/exercises/practice/markdown/MarkdownTest.php @@ -1,5 +1,27 @@ . + * + * To disable strict typing, comment out the directive below. + */ + declare(strict_types=1); use PHPUnit\Framework\Attributes\TestDox; From 2ce84ab1a22b6e203f9d68fb493cda2dd90b5173 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 25 Apr 2026 19:37:39 +0530 Subject: [PATCH 10/20] Sync matrix instructions.md --- exercises/practice/matrix/.docs/instructions.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/exercises/practice/matrix/.docs/instructions.md b/exercises/practice/matrix/.docs/instructions.md index 1b2d0f84..dadea8ac 100644 --- a/exercises/practice/matrix/.docs/instructions.md +++ b/exercises/practice/matrix/.docs/instructions.md @@ -1,7 +1,6 @@ # Instructions -Given a string representing a matrix of numbers, return the rows and columns of -that matrix. +Given a string representing a matrix of numbers, return the rows and columns of that matrix. So given a string with embedded newlines like: @@ -23,10 +22,8 @@ representing this matrix: your code should be able to spit out: -- A list of the rows, reading each row left-to-right while moving - top-to-bottom across the rows, -- A list of the columns, reading each column top-to-bottom while moving - from left-to-right. +- A list of the rows, reading each row left-to-right while moving top-to-bottom across the rows, +- A list of the columns, reading each column top-to-bottom while moving from left-to-right. The rows for our example matrix: From 4b9a2f8ea0ecef6a5b85256c0513e2dd938e31b8 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 25 Apr 2026 19:37:56 +0530 Subject: [PATCH 11/20] Added tests.toml --- exercises/practice/matrix/.meta/tests.toml | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 exercises/practice/matrix/.meta/tests.toml diff --git a/exercises/practice/matrix/.meta/tests.toml b/exercises/practice/matrix/.meta/tests.toml new file mode 100644 index 00000000..90b509c4 --- /dev/null +++ b/exercises/practice/matrix/.meta/tests.toml @@ -0,0 +1,34 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[ca733dab-9d85-4065-9ef6-a880a951dafd] +description = "extract row from one number matrix" + +[5c93ec93-80e1-4268-9fc2-63bc7d23385c] +description = "can extract row" + +[2f1aad89-ad0f-4bd2-9919-99a8bff0305a] +description = "extract row where numbers have different widths" + +[68f7f6ba-57e2-4e87-82d0-ad09889b5204] +description = "can extract row from non-square matrix with no corresponding column" + +[e8c74391-c93b-4aed-8bfe-f3c9beb89ebb] +description = "extract column from one number matrix" + +[7136bdbd-b3dc-48c4-a10c-8230976d3727] +description = "can extract column" + +[ad64f8d7-bba6-4182-8adf-0c14de3d0eca] +description = "can extract column from non-square matrix with no corresponding row" + +[9eddfa5c-8474-440e-ae0a-f018c2a0dd89] +description = "extract column where numbers have different widths" From df31c50e8c1572a4704a2bfa52b79b8ede9fc50e Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 25 Apr 2026 19:38:39 +0530 Subject: [PATCH 12/20] Added test dox and uuid in the matrix unit test file --- exercises/practice/matrix/MatrixTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/exercises/practice/matrix/MatrixTest.php b/exercises/practice/matrix/MatrixTest.php index 8616cabb..3640c219 100644 --- a/exercises/practice/matrix/MatrixTest.php +++ b/exercises/practice/matrix/MatrixTest.php @@ -24,6 +24,7 @@ declare(strict_types=1); +use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; class MatrixTest extends TestCase @@ -33,6 +34,8 @@ public static function setUpBeforeClass(): void require_once 'Matrix.php'; } + /** uuid: ca733dab-9d85-4065-9ef6-a880a951dafd */ + #[TestDox('extract row from one number matrix')] public function testExtractRowFromOneNumberMatrix(): void { $matrix = new Matrix("1"); @@ -40,6 +43,8 @@ public function testExtractRowFromOneNumberMatrix(): void $this->assertEquals([1], $matrix->getRow(1)); } + /** uuid: 5c93ec93-80e1-4268-9fc2-63bc7d23385c */ + #[TestDox('can extract row')] public function testExtractRow(): void { $matrix = new Matrix("1 2\n3 4"); @@ -47,6 +52,8 @@ public function testExtractRow(): void $this->assertEquals([3, 4], $matrix->getRow(2)); } + /** uuid: 2f1aad89-ad0f-4bd2-9919-99a8bff0305a */ + #[TestDox('extract row where numbers have different widths')] public function testExtractRowWhereNumbersHaveDifferentWidths(): void { $matrix = new Matrix("1, 2\n10 20"); @@ -54,6 +61,8 @@ public function testExtractRowWhereNumbersHaveDifferentWidths(): void $this->assertEquals([10, 20], $matrix->getRow(2)); } + /** uuid: 68f7f6ba-57e2-4e87-82d0-ad09889b5204 */ + #[TestDox('can extract row from non-square matrix with no corresponding column')] public function testExtractRowFromNonSquareMatrixWithNoMatchingColumn(): void { $matrix = new Matrix("1 2 3\n4 5 6\n7 8 9\n8 7 6"); @@ -61,6 +70,8 @@ public function testExtractRowFromNonSquareMatrixWithNoMatchingColumn(): void $this->assertEquals([8, 7, 6], $matrix->getRow(4)); } + /** uuid: e8c74391-c93b-4aed-8bfe-f3c9beb89ebb */ + #[TestDox('extract column from one number matrix')] public function testExtractColumnFromOneNumberMatrix(): void { $matrix = new Matrix("1"); @@ -68,6 +79,8 @@ public function testExtractColumnFromOneNumberMatrix(): void $this->assertEquals([1], $matrix->getColumn(1)); } + /** uuid: 7136bdbd-b3dc-48c4-a10c-8230976d3727 */ + #[TestDox('can extract column')] public function testExtractColumn(): void { $matrix = new Matrix("1 2 3\n4 5 6\n7 8 9"); @@ -75,6 +88,8 @@ public function testExtractColumn(): void $this->assertEquals([3, 6, 9], $matrix->getColumn(3)); } + /** uuid: ad64f8d7-bba6-4182-8adf-0c14de3d0eca */ + #[TestDox('can extract column from non-square matrix with no corresponding row')] public function testExtractColumnFromNonSquareMatrixWithNoMatchRow(): void { $matrix = new Matrix("1 2 3 4\n5 6 7 8\n9 8 7 6"); @@ -82,6 +97,8 @@ public function testExtractColumnFromNonSquareMatrixWithNoMatchRow(): void $this->assertEquals([4, 8, 6], $matrix->getColumn(4)); } + /** uuid: 9eddfa5c-8474-440e-ae0a-f018c2a0dd89 */ + #[TestDox('extract column where numbers have different widths')] public function testExtractColumnWhenNumbersHaveDifferentWidths(): void { $matrix = new Matrix("89 1903 3\n18 3 1\n9 41 800"); From ca05bedf9f8598cf14510638d6e7be1f4cb8b844 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 25 Apr 2026 19:39:19 +0530 Subject: [PATCH 13/20] Added matrix in the auto-sync.txt --- bin/auto-sync.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/auto-sync.txt b/bin/auto-sync.txt index 9094e760..bf8742fe 100644 --- a/bin/auto-sync.txt +++ b/bin/auto-sync.txt @@ -47,6 +47,7 @@ list-ops luhn markdown matching-brackets +matrix meetup micro-blog nucleotide-count From d1ff42c0407c243a4ec9fe17f69f40f48c923f0f Mon Sep 17 00:00:00 2001 From: narkunan Date: Sat, 25 Apr 2026 19:53:13 +0530 Subject: [PATCH 14/20] Added author detail in config.json --- exercises/practice/matrix/.meta/config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exercises/practice/matrix/.meta/config.json b/exercises/practice/matrix/.meta/config.json index 82691d14..8882a8de 100644 --- a/exercises/practice/matrix/.meta/config.json +++ b/exercises/practice/matrix/.meta/config.json @@ -1,6 +1,7 @@ { "authors": [ - "MichaelBunker" + "MichaelBunker", + "Narkunan" ], "files": { "solution": [ From 56e91569ded723640692a3d4a797f1e84588c6ad Mon Sep 17 00:00:00 2001 From: narkunan Date: Sun, 26 Apr 2026 18:01:08 +0530 Subject: [PATCH 15/20] Added source and source url in the config.json of sync-matrix --- exercises/practice/matrix/.meta/config.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exercises/practice/matrix/.meta/config.json b/exercises/practice/matrix/.meta/config.json index 8882a8de..fa1ea51d 100644 --- a/exercises/practice/matrix/.meta/config.json +++ b/exercises/practice/matrix/.meta/config.json @@ -14,5 +14,7 @@ ".meta/example.php" ] }, - "blurb": "Given a string representing a matrix of numbers, return the rows and columns of that matrix." + "blurb": "Given a string representing a matrix of numbers, return the rows and columns of that matrix.", + "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", + "source_url": "https://www.turing.edu/" } From 29be8000f239ca4be3b226505cdafe91af032098 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sun, 26 Apr 2026 18:20:57 +0530 Subject: [PATCH 16/20] Excluded strict types for matrix --- phpcs.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpcs.xml b/phpcs.xml index c88f737e..8a34e991 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -49,5 +49,6 @@ */.meta/*\.php src/* contribution/*.php + */matrix/* From 1970ec16cfe30c37bb5f1728260eb3fa4513337e Mon Sep 17 00:00:00 2001 From: narkunan Date: Sun, 26 Apr 2026 18:21:40 +0530 Subject: [PATCH 17/20] Updated Test case for matrix --- exercises/practice/matrix/MatrixTest.php | 26 ++---------------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/exercises/practice/matrix/MatrixTest.php b/exercises/practice/matrix/MatrixTest.php index 3640c219..f1863745 100644 --- a/exercises/practice/matrix/MatrixTest.php +++ b/exercises/practice/matrix/MatrixTest.php @@ -1,27 +1,5 @@ . - * - * To disable strict typing, comment out the directive below. - */ - declare(strict_types=1); use PHPUnit\Framework\Attributes\TestDox; @@ -101,8 +79,8 @@ public function testExtractColumnFromNonSquareMatrixWithNoMatchRow(): void #[TestDox('extract column where numbers have different widths')] public function testExtractColumnWhenNumbersHaveDifferentWidths(): void { - $matrix = new Matrix("89 1903 3\n18 3 1\n9 41 800"); + $matrix = new Matrix("89 1903 3\n18 3 1\n9 4 800"); - $this->assertEquals([1903, 3, 41], $matrix->getColumn(2)); + $this->assertEquals([1903, 3, 4], $matrix->getColumn(2)); } } From e191e6d625f99d19dccca8fe9691756f4e3f6cd8 Mon Sep 17 00:00:00 2001 From: narkunan Date: Sun, 26 Apr 2026 18:21:58 +0530 Subject: [PATCH 18/20] Removed strict types comments --- exercises/practice/matrix/.meta/example.php | 22 --------------------- exercises/practice/matrix/Matrix.php | 22 --------------------- 2 files changed, 44 deletions(-) diff --git a/exercises/practice/matrix/.meta/example.php b/exercises/practice/matrix/.meta/example.php index 71cf6ad3..6dc1bfb7 100644 --- a/exercises/practice/matrix/.meta/example.php +++ b/exercises/practice/matrix/.meta/example.php @@ -1,27 +1,5 @@ . - * - * To disable strict typing, comment out the directive below. - */ - declare(strict_types=1); class Matrix diff --git a/exercises/practice/matrix/Matrix.php b/exercises/practice/matrix/Matrix.php index 659a9b9a..cef1ac8f 100644 --- a/exercises/practice/matrix/Matrix.php +++ b/exercises/practice/matrix/Matrix.php @@ -1,27 +1,5 @@ . - * - * To disable strict typing, comment out the directive below. - */ - declare(strict_types=1); class Matrix From d617314a289b844e6ad23ff3debb1a9436bc5f4f Mon Sep 17 00:00:00 2001 From: narkunan Date: Sun, 26 Apr 2026 21:31:47 +0530 Subject: [PATCH 19/20] Restored phpdoc in matrix.php --- exercises/practice/matrix/Matrix.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/exercises/practice/matrix/Matrix.php b/exercises/practice/matrix/Matrix.php index cef1ac8f..659a9b9a 100644 --- a/exercises/practice/matrix/Matrix.php +++ b/exercises/practice/matrix/Matrix.php @@ -1,5 +1,27 @@ . + * + * To disable strict typing, comment out the directive below. + */ + declare(strict_types=1); class Matrix From 7ba1c647f9f1a3bf393bee77d59e9d4c00d5445c Mon Sep 17 00:00:00 2001 From: narkunan Date: Sun, 26 Apr 2026 21:32:02 +0530 Subject: [PATCH 20/20] Removed matrix from excluded pattern --- phpcs.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/phpcs.xml b/phpcs.xml index 8a34e991..c88f737e 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -49,6 +49,5 @@ */.meta/*\.php src/* contribution/*.php - */matrix/*