diff --git a/src/Controller/SnipController.php b/src/Controller/SnipController.php
index c74326c..7badff0 100644
--- a/src/Controller/SnipController.php
+++ b/src/Controller/SnipController.php
@@ -44,25 +44,25 @@ class SnipController extends AbstractController
}
#[Route('/single/{snip}', name: '_single')]
- public function single(Snip $snip): Response
+ public function single(Snip $snip, Pipeline $pl): Response
{
$this->denyAccessUnlessGranted(SnipVoter::VIEW, $snip);
$snipService = $this->snipServiceFactory->create($snip);
return $this->render('snip/single.html.twig', [
'snip' => $snip,
- 'content' => (new Pipeline())->parse($snipService->get()),
+ 'content' => $pl->parse($snipService->get()),
'branch' => $snipService->getRepo()->getCurrentBranchName(),
]);
}
#[Route('/raw/{snip}', name: '_raw')]
- public function raw(Snip $snip, Request $request): Response
+ public function raw(Snip $snip, Pipeline $pl, Request $request): Response
{
$this->denyAccessUnlessGranted(SnipVoter::VIEW, $snip);
$response = new Response(
- (new Pipeline())->clean($this->snipServiceFactory->create($snip)->get()),
+ $pl->clean($this->snipServiceFactory->create($snip)->get()),
Response::HTTP_OK,
['Content-Type' => 'text/html']
);
@@ -77,10 +77,6 @@ class SnipController extends AbstractController
}
return $response;
-// return $this->render('snip/single.html.twig', [
-// 'snip' => $snip,
-// 'content' => $this->snipServiceFactory->create($snip)->get(),
-// ]);
}
#[Route('/edit/{snip}', name: '_edit')]
diff --git a/src/Service/SnipParser/Pipeline.php b/src/Service/SnipParser/Pipeline.php
index 666ca57..cc0b37f 100644
--- a/src/Service/SnipParser/Pipeline.php
+++ b/src/Service/SnipParser/Pipeline.php
@@ -3,19 +3,28 @@
namespace App\Service\SnipParser;
use App\Service\SnipParser\Stages\HtmlEscapeStage;
+use App\Service\SnipParser\Stages\UrlReferenceStage;
use App\Service\SnipParser\Stages\ReplaceBlocksStage;
+use App\Service\SnipParser\Stages\ReplaceStage;
use League\Pipeline\PipelineBuilder;
class Pipeline
{
+ public function __construct(
+ private readonly UrlReferenceStage $referenceStage,
+ ) {}
+
public function parse(string $payload): string
{
$builder = new PipelineBuilder();
$pipeline = $builder
->add(new HtmlEscapeStage())
+ ->add(new ReplaceStage(PHP_EOL, '
'))
->add(new ReplaceBlocksStage('
', '
', '```'))
->add(new ReplaceBlocksStage('', '
', '``'))
- ->build();
+ ->add($this->referenceStage)
+ ->build()
+ ;
return $pipeline->process($payload);
}
diff --git a/src/Service/SnipParser/Stages/HtmlEscapeStage.php b/src/Service/SnipParser/Stages/HtmlEscapeStage.php
index 2760c0e..521b784 100644
--- a/src/Service/SnipParser/Stages/HtmlEscapeStage.php
+++ b/src/Service/SnipParser/Stages/HtmlEscapeStage.php
@@ -8,6 +8,7 @@ class HtmlEscapeStage implements StageInterface
{
public function __invoke(mixed $payload): string
{
- return htmlspecialchars($payload, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
+ // https://www.php.net/manual/en/function.htmlspecialchars.php
+ return htmlspecialchars($payload, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8');
}
}
\ No newline at end of file
diff --git a/src/Service/SnipParser/Stages/ReplaceStage.php b/src/Service/SnipParser/Stages/ReplaceStage.php
new file mode 100644
index 0000000..f9e4f45
--- /dev/null
+++ b/src/Service/SnipParser/Stages/ReplaceStage.php
@@ -0,0 +1,19 @@
+search, $this->replace, $payload);
+ }
+}
\ No newline at end of file
diff --git a/src/Service/SnipParser/Stages/UrlReferenceStage.php b/src/Service/SnipParser/Stages/UrlReferenceStage.php
new file mode 100644
index 0000000..fcc18c2
--- /dev/null
+++ b/src/Service/SnipParser/Stages/UrlReferenceStage.php
@@ -0,0 +1,43 @@
+replaceReferences($payload);
+ }
+
+ private function replaceReferences(mixed $payload): string
+ {
+ // replaces all references (#n) to other snips with links
+ $pattern = '/#(\d+)/';
+
+ return preg_replace_callback($pattern, function ($matches) {
+ dump($matches);
+ $snip = $this->snipRepository->find($matches[1]);
+ if ($snip === null) {
+ return sprintf('%s', $matches[0]);
+ }
+ if (!$this->security->isGranted(SnipVoter::VIEW, $snip)) {
+ return sprintf('%s', $matches[0]);
+ }
+
+ $url = $this->router->generate('snip_single', ['snip' => $snip->getId()]);
+ return sprintf('#%s', $url, $snip->getCreatedBy(), $snip->getId());
+ }, $payload);
+ }
+}
\ No newline at end of file
diff --git a/templates/snip/single.html.twig b/templates/snip/single.html.twig
index ea93e3a..20d7780 100644
--- a/templates/snip/single.html.twig
+++ b/templates/snip/single.html.twig
@@ -24,7 +24,7 @@
Current branch: {{ branch }}