Compare commits

...

10 Commits

2 changed files with 80 additions and 36 deletions

View File

@ -9,9 +9,16 @@ use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Process\Process; use Symfony\Component\Process\Process;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Yaml\Yaml;
final class MainController extends AbstractController final class MainController extends AbstractController
{ {
#[Route('/', 'app_root')]
public function root(): Response
{
return $this->index('.index');
}
#[Route('/sync', 'app_sync')] #[Route('/sync', 'app_sync')]
public function sync(): Response public function sync(): Response
{ {
@ -32,15 +39,18 @@ final class MainController extends AbstractController
// ---------------------------------------------- Get file contents --- // ---------------------------------------------- Get file contents ---
$fullPath = sprintf( $fullPath = sprintf(
'%s/var/data/%s', '%s/var/data/%s.md',
$this->getParameter('kernel.project_dir'), $this->getParameter('kernel.project_dir'),
$path, $path,
); );
$fs = new Filesystem(); $fs = new Filesystem();
if (!$fs->exists($fullPath)) throw $this->createNotFoundException(); $contents = $fs->exists($fullPath) ? $fs->readFile($fullPath) : null;
$contents = $fs->readFile($fullPath);
[
'data' => $metadata,
'text' => $text
] = $this->extractMetadata($contents);
// -------------------------------------------------- Get data tree --- // -------------------------------------------------- Get data tree ---
@ -52,8 +62,6 @@ final class MainController extends AbstractController
// Convert flat list into a nested tree // Convert flat list into a nested tree
$tree = []; $tree = [];
foreach ($finder as $file) { foreach ($finder as $file) {
/** @var SplFileInfo $file */
$current = &$tree; $current = &$tree;
// Dunno why it is undefined, it works // Dunno why it is undefined, it works
@ -66,16 +74,42 @@ final class MainController extends AbstractController
$current = &$current[$part]; $current = &$current[$part];
} }
$current[] = $file; $current[$file->getFilenameWithoutExtension()] = [];
//usort($current, fn($a, $b) => strcmp(implode('/', $a), implode('/', $b)));
} }
return $this->render('main/index.html.twig', [ return $this->render('main/index.html.twig', [
'path' => $path, 'path' => $path,
'contents' => $contents, 'contents' => $text,
'metadata' => $metadata,
'tree' => $tree, 'tree' => $tree,
'version' => (new Process(['git', '-C', $gitDir, 'log', '-1', '--oneline']))->mustRun()->getOutput(), 'version' => (new Process(['git', '-C', $gitDir, 'log', '-1', '--oneline']))->mustRun()->getOutput(),
]); ]);
} }
/**
* Parses all YAML metadata blocks in a given string and returns the text
* without such blocks.
*/
private function extractMetadata(?string $text): array
{
if ($text === null) return ['data' => null, 'text' => null];
$start = strpos($text, "---\n");
$end = strpos($text, "...\n", $start) ?: strpos($text, "---\n", $start + 4);
// No more moteadata, return as is. Recursion stop condition
if ($start === false or $end === false) {
return ['text' => $text, 'data' => []];
}
$yaml = Yaml::parse(substr($text, $start + 4, $end - $start - 4));
$rest = substr($text, 0, $start) . substr($text, $end + 4);
// Recurse until there's no more metadata blocks, overwriting as we go
$nextIteration = $this->extractMetadata($rest);
return [
'data' => $nextIteration['data'] + $yaml,
'text' => $nextIteration['text'],
];
}
} }

View File

@ -1,39 +1,49 @@
{% extends 'base.html.twig' %} {% extends 'base.html.twig' %}
{% block title %}{{ path }} | Gaisen{% endblock %} {% block title %}{{ metadata.title|default(path) }} | Gaisen{% endblock %}
{% macro render_tree(tree) %} {% macro render_tree(tree, prefix = '') %}
<ul> <ul>
{% for key, value in tree %} {% for name, subtree in tree %}
<li> <li>
{% if value is iterable and value|length > 0 %} <a href="{{ path('app_index', {
{{ key }} path: prefix ~ name
{{ _self.render_tree(value) }} {# Recursive call #} }) }}">
{% else %} {{ name }}
<a href="{{ path('app_index', { </a>
path: value.relativePathname {{ _self.render_tree(subtree, name ~ '/') }}
}) }}"> </li>
{{ value.filename }} {% endfor %}
</a>
{% endif %}
</li>
{% endfor %}
</ul> </ul>
{% endmacro %} {% endmacro %}
{% block body %} {% block body %}
<div class="bg-neutral-3 border-bottom w-100 p-2 fs-1 ps-3"> <div class="d-flex flex-column" style="min-height: 100vh;">
Gaisen <div class="bg-neutral-3 border-bottom fs-1 p-2 ps-3">
</div> Gaisen
<div class="d-flex flex-row">
<div class="border-end bg-neutral-2 p-3">
{{ _self.render_tree(tree) }}
</div> </div>
<div class="p-3"> <div class="d-flex flex-row flex-grow-1">
{{ contents|markdown_to_html }} <div class="border-end bg-neutral-2 p-3">
{{ _self.render_tree(tree) }}
</div>
<div class="p-3">
{% if contents is not null %}
{{ contents|markdown_to_html }}
{% else %}
<span class="text-muted">Empty</span>
{% endif %}
{% if metadata.tags is defined %}
<div class="d-flex flex-row gap-2 pt-2">
<div>tags:</div>
{% for tag in metadata.tags|default([]) %}
<div><a href="/search?q={{tag}}">{{ tag }}</a></div>
{% endfor %}
</div>
{% endif %}
</div>
</div>
<div class="bg-neutral-3 border-top p-1">
Version: <span class="text-muted">{{ version }}</span>
</div> </div>
</div>
<div class="bg-neutral-3 border-top w-100 p-2">
Version: <span class="text-muted">{{ version }}</span>
</div> </div>
{% endblock %} {% endblock %}