feat: static documentation pages

This commit is contained in:
sam 2024-12-25 17:53:31 -05:00
parent fe1cf7ce8a
commit 7468aa20ab
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
6 changed files with 58 additions and 7 deletions

View file

@ -21,3 +21,4 @@
**/values.dev.yaml
LICENSE
README.md
static-pages/*

View file

@ -12,6 +12,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
using System.Text.RegularExpressions;
using Foxnouns.Backend.Dto;
using Foxnouns.Backend.Utils;
using Microsoft.AspNetCore.Mvc;
@ -19,7 +20,7 @@ using Microsoft.AspNetCore.Mvc;
namespace Foxnouns.Backend.Controllers;
[Route("/api/v2/meta")]
public class MetaController : ApiControllerBase
public partial class MetaController : ApiControllerBase
{
private const string Repository = "https://codeberg.org/pronounscc/pronouns.cc";
@ -48,7 +49,23 @@ public class MetaController : ApiControllerBase
)
);
[HttpGet("page/{page}")]
public async Task<IActionResult> GetStaticPageAsync(string page, CancellationToken ct = default)
{
if (!PageRegex().IsMatch(page))
{
throw new ApiError.BadRequest("Invalid page name");
}
string path = Path.Join(Directory.GetCurrentDirectory(), "static-pages", $"{page}.md");
string text = await System.IO.File.ReadAllTextAsync(path, ct);
return Ok(text);
}
[HttpGet("/api/v2/coffee")]
public IActionResult BrewCoffee() =>
Problem("Sorry, I'm a teapot!", statusCode: StatusCodes.Status418ImATeapot);
[GeneratedRegex(@"^[a-z\-_]+$")]
private static partial Regex PageRegex();
}

View file

@ -0,0 +1 @@
*

View file

@ -7,11 +7,7 @@ const md = new MarkdownIt({
linkify: true,
}).disable(["heading", "lheading", "link", "table", "blockquote"]);
const unsafeMd = new MarkdownIt({
html: false,
breaks: true,
linkify: true,
});
const unsafeMd = new MarkdownIt();
export const renderMarkdown = (src: string | null) => (src ? sanitize(md.render(src)) : null);

View file

@ -0,0 +1,14 @@
import { baseRequest } from "$api";
import ApiError from "$api/error";
export const load = async ({ fetch, params }) => {
const resp = await baseRequest("GET", `/meta/page/${params.page}`, { fetch });
if (resp.status < 200 || resp.status > 299) {
const err = await resp.json();
if ("code" in err) throw new ApiError(err);
else throw new ApiError();
}
const pageText = await resp.text();
return { page: params.page, text: pageText };
};

View file

@ -0,0 +1,22 @@
<script lang="ts">
import { renderUnsafeMarkdown } from "$lib/markdown";
import type { PageData } from "./$types";
type Props = { data: PageData };
let { data }: Props = $props();
let md = $derived(renderUnsafeMarkdown(data.text));
let title = $derived.by(() => {
let title = data.text.split("\n")[0];
if (title.startsWith("# ")) title = title.substring("# ".length);
return title;
});
</script>
<svelte:head>
<title>{title} • pronouns.cc</title>
</svelte:head>
<div class="container">
{@html md}
</div>