Compare commits
10 Commits
c841c5c212
...
9398e9c6be
Author | SHA1 | Date |
---|---|---|
|
9398e9c6be | |
|
0c8873e576 | |
|
821ea0df16 | |
|
a2f716670c | |
|
e0d9d9fedd | |
|
5f4aa730b1 | |
|
6adcf4bd55 | |
|
5ae258317d | |
|
2d48a4c1a7 | |
|
6bb37a4741 |
|
@ -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'],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
Loading…
Reference in New Issue