Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use phpDocumentor\Guides\Nodes\CodeNode;

use function assert;
use function count;
use function explode;

/** @extends AbstractBlockParser<CodeNode> */
Expand All @@ -32,8 +33,11 @@ public function parse(MarkupLanguageParser $parser, NodeWalker $walker, CommonMa
assert($current instanceof IndentedCode || $current instanceof FencedCode);
$walker->next();
$codeNode = new CodeNode(explode("\n", $current->getLiteral()));
if ($current instanceof FencedCode && $current->getInfo() !== null) {
$codeNode = $codeNode->withOptions(['caption' => $current->getInfo()]);
if ($current instanceof FencedCode) {
$infoWords = $current->getInfoWords();
if (count($infoWords) !== 0 && $infoWords[0] !== '') {
$codeNode->setLanguage($infoWords[0]);
}
}

return $codeNode;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

declare(strict_types=1);

/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/

namespace phpDocumentor\Guides\Markdown\Parsers;

use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode;
use League\CommonMark\Node\NodeWalker;
use League\CommonMark\Node\NodeWalkerEvent;
use phpDocumentor\Guides\MarkupLanguageParser;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class CodeBlockParserTest extends TestCase
{
private CodeBlockParser $parser;

protected function setUp(): void
{
$this->parser = new CodeBlockParser();
}

/** @return array<string, array{string, string}> */
public static function languageProvider(): array
{
return [
'php' => ['php', 'php'],
'javascript' => ['javascript', 'javascript'],
'c++' => ['c++', 'c++'],
'first word only from info string' => ['ruby startline=1', 'ruby'],
];
}

#[DataProvider('languageProvider')]
public function test_fenced_code_block_sets_language_from_info_string(string $info, string $expectedLanguage): void
{
$fencedCode = new FencedCode(3, '`', 0);
$fencedCode->setInfo($info);
$fencedCode->setLiteral("echo \"Hello\";\n");

$result = $this->parser->parse(
$this->createMock(MarkupLanguageParser::class),
new NodeWalker($fencedCode),
$fencedCode,
);

self::assertSame($expectedLanguage, $result->getLanguage());
self::assertSame("echo \"Hello\";\n", $result->getValue());
}

public function test_fenced_code_block_without_info_has_null_language(): void
{
$fencedCode = new FencedCode(3, '`', 0);
$fencedCode->setLiteral("some code\n");

$result = $this->parser->parse(
$this->createMock(MarkupLanguageParser::class),
new NodeWalker($fencedCode),
$fencedCode,
);

self::assertNull($result->getLanguage());
self::assertSame("some code\n", $result->getValue());
}

public function test_fenced_code_block_with_empty_info_has_null_language(): void
{
$fencedCode = new FencedCode(3, '`', 0);
$fencedCode->setInfo('');
$fencedCode->setLiteral("some code\n");

$result = $this->parser->parse(
$this->createMock(MarkupLanguageParser::class),
new NodeWalker($fencedCode),
$fencedCode,
);

self::assertNull($result->getLanguage());
}

public function test_indented_code_block_has_null_language(): void
{
$indentedCode = new IndentedCode();
$indentedCode->setLiteral("some code\n");

$result = $this->parser->parse(
$this->createMock(MarkupLanguageParser::class),
new NodeWalker($indentedCode),
$indentedCode,
);

self::assertNull($result->getLanguage());
self::assertSame("some code\n", $result->getValue());
}

public function test_supports_fenced_code(): void
{
$fencedCode = new FencedCode(3, '`', 0);
$event = new NodeWalkerEvent($fencedCode, true);

self::assertTrue($this->parser->supports($event));
}

public function test_supports_indented_code(): void
{
$indentedCode = new IndentedCode();
$event = new NodeWalkerEvent($indentedCode, true);

self::assertTrue($this->parser->supports($event));
}
}
12 changes: 9 additions & 3 deletions tests/Integration/tests/markdown/code-md/expected/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,22 @@ <h2>Fenced Code Blocks</h2>
</code></pre>

</div>
<div class="section" id="fenced-code-block-with-caption">
<h2>Fenced Code Block with caption</h2>
<pre><code class="language-">procedure startSwinging(swing, child)
<div class="section" id="fenced-code-block-with-language">
<h2>Fenced Code Block with language</h2>
<pre><code class="language-pseudocode">procedure startSwinging(swing, child)
while child.isComfortable()
swing.giveGentlePush()
waitForNextIteration()
end while
end procedure
</code></pre>

</div>
<div class="section" id="fenced-code-block-with-php">
<h2>Fenced Code Block with PHP</h2>
<pre><code class="language-php">echo &quot;Hello world!&quot;;
</code></pre>

</div>
</div>
<!-- content end -->
11 changes: 9 additions & 2 deletions tests/Integration/tests/markdown/code-md/input/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@
}
```

## Fenced Code Block with caption
## Fenced Code Block with language

```pseudocode
procedure startSwinging(swing, child)
while child.isComfortable()
swing.giveGentlePush()
waitForNextIteration()
end while
end procedure
end procedure
```

## Fenced Code Block with PHP

```php
echo "Hello world!";
```
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h2>Usage</h2>
<li><strong>Hold onto the Swing:</strong> Provide support and hold onto the swing until your child is comfortably seated and ready to swing.</li>
<li>
<p><strong>Start Swinging:</strong> Give a gentle push to start the swinging motion. Observe your child&#039;s comfort level and adjust the swinging speed accordingly.</p>
<pre><code class="language-">procedure startSwinging(swing, child)
<pre><code class="language-pseudocode">procedure startSwinging(swing, child)
while child.isComfortable()
swing.giveGentlePush()
waitForNextIteration()
Expand Down