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
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 = "
";
+ if (preg_match('/^<\/ul>(.*)/', $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 = "" . 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(
- '',
+ "",
parseMarkdown("* Item 1\n* Item 2")
);
}
@@ -116,50 +137,47 @@ public function testUnorderedLists(): void
public function testWithALittleBitOfEverything(): void
{
$this->assertEquals(
- 'Header!
',
+ "Header!
",
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
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
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/*