Skip to content
Merged
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
162 changes: 110 additions & 52 deletions packages/guides-markdown/src/Markdown/Parsers/BlockQuoteParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
use RuntimeException;

use function array_shift;
use function array_values;
use function count;
use function is_string;
use function sprintf;
use function trim;

Expand All @@ -42,6 +44,40 @@ public function __construct(
) {
}

/**
* @param array<Node> $content
*
* @phpstan-assert-if-false non-empty-list $content
*/
private static function contentIsTextOnlyParagraph(array $content): bool
{
if (count($content) === 0) {
return true;
}

if ($content[0] instanceof ParagraphNode === false) {
return true;
}

$paragraphContent = $content[0]->getValue()[0]->getValue();

if (is_string($paragraphContent)) {
return true;
}

return $paragraphContent[0] instanceof PlainTextInlineNode === false;
}

/** @param array<Node> $content */
private static function contentIsNotParagraph(array $content): bool
{
if (count($content) === 0) {
return true;
}

return $content[0] instanceof ParagraphNode === false;
}

public function parse(MarkupLanguageParser $parser, NodeWalker $walker, CommonMarkNode $current): Node
{
$content = [];
Expand All @@ -61,68 +97,90 @@ public function parse(MarkupLanguageParser $parser, NodeWalker $walker, CommonMa
}

// leaving the heading node
if ($commonMarkNode instanceof BlockQuote) {
if (count($content) > 0 && $content[0] instanceof ParagraphNode && ($content[0]->getValue()[0]) instanceof InlineCompoundNode) {
$paragraphContent = $content[0]->getValue()[0]->getValue();
if (count($paragraphContent) > 0 && $paragraphContent[0] instanceof PlainTextInlineNode) {
$text = trim($paragraphContent[0]->getValue());
$newParagraphContent = $paragraphContent;
array_shift($newParagraphContent);
switch ($text) {
case '[!NOTE]':
return new AdmonitionNode(
'note',
new InlineCompoundNode([new PlainTextInlineNode('Note')]),
'Note',
$newParagraphContent,
);

case '[!TIP]':
return new AdmonitionNode(
'tip',
new InlineCompoundNode([new PlainTextInlineNode('Tip')]),
'Tip',
$newParagraphContent,
);

case '[!IMPORTANT]':
return new AdmonitionNode(
'important',
new InlineCompoundNode([new PlainTextInlineNode('Important')]),
'Important',
$newParagraphContent,
);

case '[!WARNING]':
return new AdmonitionNode(
'warning',
new InlineCompoundNode([new PlainTextInlineNode('Warning')]),
'Warning',
$newParagraphContent,
);

case '[!CAUTION]':
return new AdmonitionNode(
'caution',
new InlineCompoundNode([new PlainTextInlineNode('Caution')]),
'Caution',
$newParagraphContent,
);
}
}
if ($commonMarkNode instanceof BlockQuote === false) {
$this->logger->warning(sprintf('"%s" node is not yet supported in context %s. ', $commonMarkNode::class, 'BlockQuote'));

$content[0] = new ParagraphNode([new InlineCompoundNode($paragraphContent)]);
}
throw new RuntimeException('Unexpected end of NodeWalker');
}

if (self::contentIsNotParagraph($content)) {
return new QuoteNode($content);
}

if (self::contentIsTextOnlyParagraph($content)) {
return new QuoteNode($content);
}

$this->logger->warning(sprintf('"%s" node is not yet supported in context %s. ', $commonMarkNode::class, 'BlockQuote'));
$admonitionNode = $this->toAdmonition(array_values($content));

return $admonitionNode ?? new QuoteNode($content);
}

throw new RuntimeException('Unexpected end of NodeWalker');
}

/** @param non-empty-list<Node> $content */
private function toAdmonition(array $content): AdmonitionNode|null
{
if ($content[0] instanceof ParagraphNode === false) {
return null;
}

$paragraphContent = $content[0]->getValue()[0]->getValue();
if ($paragraphContent[0] instanceof PlainTextInlineNode === false) {
return null;
}

$text = trim($paragraphContent[0]->getValue());
$newParagraphContent = $paragraphContent;
array_shift($newParagraphContent);
$content[0] = new ParagraphNode([new InlineCompoundNode($newParagraphContent)]);

switch ($text) {
case '[!NOTE]':
return new AdmonitionNode(
'note',
new InlineCompoundNode([new PlainTextInlineNode('Note')]),
'Note',
$content,
);

case '[!TIP]':
return new AdmonitionNode(
'tip',
new InlineCompoundNode([new PlainTextInlineNode('Tip')]),
'Tip',
$content,
);

case '[!IMPORTANT]':
return new AdmonitionNode(
'important',
new InlineCompoundNode([new PlainTextInlineNode('Important')]),
'Important',
$content,
);

case '[!WARNING]':
return new AdmonitionNode(
'warning',
new InlineCompoundNode([new PlainTextInlineNode('Warning')]),
'Warning',
$content,
);

case '[!CAUTION]':
return new AdmonitionNode(
'caution',
new InlineCompoundNode([new PlainTextInlineNode('Caution')]),
'Caution',
$content,
);
}

return null;
}

public function supports(NodeWalkerEvent $event): bool
{
return $event->isEntering() && $event->getNode() instanceof BlockQuote;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,78 +1,79 @@
<!-- content start -->
<div class="section" id="document-title">
<h1>Document Title</h1>
<div class="alert alert-warning " role="alert">
<h4 class="alert-heading">Attention</h4>
<div class="section" id="document-title">
<h1>Document Title</h1>
<div class="alert alert-warning " role="alert">
<h4 class="alert-heading">Attention</h4>

<p>Attention content.</p>
<p>Attention content.</p>

</div>
<div class="alert alert-danger " role="alert">
<h4 class="alert-heading">Caution</h4>
</div>
<div class="alert alert-danger " role="alert">
<h4 class="alert-heading">Caution</h4>

<p>Caution content.</p>
<p>Caution content.</p>

</div>
<div class="alert alert-danger " role="alert">
<h4 class="alert-heading">Danger</h4>
</div>
<div class="alert alert-danger " role="alert">
<h4 class="alert-heading">Danger</h4>

<p>Danger content.</p>
<p>Danger content.</p>

</div>
<div class="alert alert-danger " role="alert">
<h4 class="alert-heading">Error</h4>
</div>
<div class="alert alert-danger " role="alert">
<h4 class="alert-heading">Error</h4>

<p>Error content.</p>
<p>Error content.</p>

</div>
<div class="alert alert-info " role="alert">
<h4 class="alert-heading">Hint</h4>
</div>
<div class="alert alert-info " role="alert">
<h4 class="alert-heading">Hint</h4>

<p>Hint content.</p>
<p>Hint content.</p>

</div>
<div class="alert alert-warning " role="alert">
<h4 class="alert-heading">Important</h4>
</div>
<div class="alert alert-warning " role="alert">
<h4 class="alert-heading">Important</h4>

<p>Important content.</p>
<p>Important content.</p>

</div>
<div class="alert alert-secondary " role="alert">
<h4 class="alert-heading">Note</h4>
</div>
<div class="alert alert-secondary " role="alert">
<h4 class="alert-heading">Note</h4>

<p>Note content.</p>
<p>Note content.</p>

</div>
<div class="alert alert-info " role="alert">
<h4 class="alert-heading">See also</h4>
</div>
<div class="alert alert-info " role="alert">
<h4 class="alert-heading">See also</h4>

<p>See also content.</p>
<p>See also content.</p>

</div>
<div class="alert alert-info " role="alert">
<h4 class="alert-heading">Tip</h4>
</div>
<div class="alert alert-info " role="alert">
<h4 class="alert-heading">Tip</h4>

<p>Tip content.</p>
<p>Tip content.</p>

</div>
<div class="alert alert-danger " role="alert">
<h4 class="alert-heading">Warning</h4>
</div>
<div class="alert alert-danger " role="alert">
<h4 class="alert-heading">Warning</h4>

<p>Warning content.</p>
<p>Warning content.</p>

</div>
<div class="alert alert-secondary " role="alert">
<h4 class="alert-heading">Custom Title</h4>
<p>Generic admonition content.</p>
</div>
<div class="alert alert-secondary " role="alert">
<h4 class="alert-heading">Custom Title</h4>
<p>Generic admonition content.</p>

</div>
<div class="alert alert-secondary " role="alert">
<h4 class="alert-heading">Custom Title</h4>
</div>
<div class="alert alert-info " role="alert">
<h4 class="alert-heading">Hint</h4>
<p>Lorem Ipsum Dolor.</p>
</div>
</div>
<div class="alert alert-secondary " role="alert">
<h4 class="alert-heading">Custom Title</h4>
</div>
<div class="alert alert-info " role="alert">
<h4 class="alert-heading">Hint</h4>

<p>Lorem Ipsum Dolor.</p>

</div>
<!-- content end -->
</div>
<!-- content end -->
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ <h1>Document title</h1>
</blockquote>

<div class="admonition note my-class">
<p>A Note with a class</p>

<p>A Note with a class</p>

</div>

<div class="admonition note">
<p>A note without a class</p>

<p>A note without a class</p>

</div>
</div>
<!-- content end -->
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<h1>Some Title</h1>

<div class="admonition note">
<p>No comment!</p>

<p>No comment!</p>

</div>
<div class="section" id="another-title">
<a id="alsonoomment"></a>
Expand Down
Loading
Loading