feat: static documentation pages
This commit is contained in:
parent
fe1cf7ce8a
commit
7468aa20ab
6 changed files with 58 additions and 7 deletions
|
@ -21,3 +21,4 @@
|
||||||
**/values.dev.yaml
|
**/values.dev.yaml
|
||||||
LICENSE
|
LICENSE
|
||||||
README.md
|
README.md
|
||||||
|
static-pages/*
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// 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/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using Foxnouns.Backend.Dto;
|
using Foxnouns.Backend.Dto;
|
||||||
using Foxnouns.Backend.Utils;
|
using Foxnouns.Backend.Utils;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
@ -19,7 +20,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||||
namespace Foxnouns.Backend.Controllers;
|
namespace Foxnouns.Backend.Controllers;
|
||||||
|
|
||||||
[Route("/api/v2/meta")]
|
[Route("/api/v2/meta")]
|
||||||
public class MetaController : ApiControllerBase
|
public partial class MetaController : ApiControllerBase
|
||||||
{
|
{
|
||||||
private const string Repository = "https://codeberg.org/pronounscc/pronouns.cc";
|
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")]
|
[HttpGet("/api/v2/coffee")]
|
||||||
public IActionResult BrewCoffee() =>
|
public IActionResult BrewCoffee() =>
|
||||||
Problem("Sorry, I'm a teapot!", statusCode: StatusCodes.Status418ImATeapot);
|
Problem("Sorry, I'm a teapot!", statusCode: StatusCodes.Status418ImATeapot);
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^[a-z\-_]+$")]
|
||||||
|
private static partial Regex PageRegex();
|
||||||
}
|
}
|
||||||
|
|
1
Foxnouns.Backend/static-pages/.gitignore
vendored
Normal file
1
Foxnouns.Backend/static-pages/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*
|
|
@ -7,11 +7,7 @@ const md = new MarkdownIt({
|
||||||
linkify: true,
|
linkify: true,
|
||||||
}).disable(["heading", "lheading", "link", "table", "blockquote"]);
|
}).disable(["heading", "lheading", "link", "table", "blockquote"]);
|
||||||
|
|
||||||
const unsafeMd = new MarkdownIt({
|
const unsafeMd = new MarkdownIt();
|
||||||
html: false,
|
|
||||||
breaks: true,
|
|
||||||
linkify: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const renderMarkdown = (src: string | null) => (src ? sanitize(md.render(src)) : null);
|
export const renderMarkdown = (src: string | null) => (src ? sanitize(md.render(src)) : null);
|
||||||
|
|
||||||
|
|
14
Foxnouns.Frontend/src/routes/page/[page]/+page.server.ts
Normal file
14
Foxnouns.Frontend/src/routes/page/[page]/+page.server.ts
Normal 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 };
|
||||||
|
};
|
22
Foxnouns.Frontend/src/routes/page/[page]/+page.svelte
Normal file
22
Foxnouns.Frontend/src/routes/page/[page]/+page.svelte
Normal 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>
|
Loading…
Reference in a new issue