81 lines
2.7 KiB
PHP
81 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Service\SnipParser\Markdown;
|
|
|
|
use App\Repository\SnipRepository;
|
|
use App\Service\SnipParser\AbstractParser;
|
|
use League\CommonMark\Event\DocumentParsedEvent;
|
|
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
|
|
use League\CommonMark\Extension\DefaultAttributes\DefaultAttributesExtension;
|
|
use League\CommonMark\Extension\Footnote\FootnoteExtension;
|
|
use League\CommonMark\Extension\Table\Table;
|
|
use League\CommonMark\GithubFlavoredMarkdownConverter;
|
|
use League\CommonMark\Node\Inline\Text;
|
|
use League\CommonMark\Node\Query;
|
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
|
use Symfony\Component\Routing\RouterInterface;
|
|
use Tempest\Highlight\CommonMark\HighlightExtension;
|
|
use Tempest\Highlight\Highlighter;
|
|
|
|
class MarkdownParser extends AbstractParser
|
|
{
|
|
public function __construct(
|
|
#[Autowire(lazy: true)] private readonly RouterInterface $router,
|
|
#[Autowire(lazy: true)] private readonly SnipRepository $snipRepo,
|
|
) {}
|
|
|
|
public function safeParseView(string $content): string
|
|
{
|
|
$config = [
|
|
'default_attributes' => [
|
|
Table::class => [
|
|
'class' => 'table table-hover',
|
|
],
|
|
Link::class => [
|
|
'class' => 'btn btn-sm btn-secondary',
|
|
],
|
|
],
|
|
];
|
|
|
|
$converter = new GithubFlavoredMarkdownConverter($config);
|
|
$converter
|
|
->getEnvironment()
|
|
->addExtension(new HighlightExtension(new Highlighter()->withGutter()))
|
|
->addExtension(new FootnoteExtension())
|
|
->addExtension(new DefaultAttributesExtension())
|
|
->addEventListener(DocumentParsedEvent::class, $this->documentParsed(...))
|
|
;
|
|
return $converter->convert($content);
|
|
}
|
|
|
|
private function documentParsed(DocumentParsedEvent $event): void
|
|
{
|
|
$document = $event->getDocument();
|
|
|
|
$linkNodes = new Query()
|
|
->where(Query::type(Link::class))
|
|
->findAll($document)
|
|
;
|
|
|
|
/** @var Link $linkNode */
|
|
foreach ($linkNodes as $linkNode) {
|
|
$url = $linkNode->getUrl();
|
|
|
|
if (!is_numeric($url)) {
|
|
continue;
|
|
}
|
|
|
|
$snip = $this->snipRepo->find($url);
|
|
if ($snip === null) {
|
|
continue;
|
|
}
|
|
$linkNode->setUrl($this->router->generate('snip_single', [
|
|
'snip' => $url,
|
|
]));
|
|
$textNode = $linkNode->firstChild();
|
|
if (!$textNode) {
|
|
$linkNode->appendChild(new Text($snip));
|
|
}
|
|
}
|
|
}
|
|
} |