Compare commits

...

10 commits

38 changed files with 180 additions and 132 deletions

View file

@ -1,17 +1,20 @@
// @ts-check // @ts-check
import { defineConfig } from "astro/config"; import { defineConfig } from "astro/config";
const setLayout = () => { //const setLayout = () => {
return function (_, file) { // return function (_, file) {
if (file.data.astro.frontmatter.layout === undefined) { // if (file.data.astro.frontmatter.layout === undefined) {
file.data.astro.frontmatter.layout = "@layouts/BaseLayout.astro"; // file.data.astro.frontmatter.layout = "@layouts/BaseLayout.astro";
} // }
}; // };
}; //};
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
markdown: { markdown: {
remarkPlugins: [setLayout], //remarkPlugins: [setLayout],
shikiConfig: {
theme: "catppuccin-latte",
},
}, },
}); });

View file

@ -0,0 +1,18 @@
---
import { getDocumentPath, getDocumentTitle, getAncestorDocuments } from "@utils/docs";
const { document } = Astro.props;
const ancestorDocuments = await getAncestorDocuments(document);
---
<div class="breadcrumbs">
<a href="/">Home</a>
{ancestorDocuments.map(document => {
const title = getDocumentTitle(document);
const path = getDocumentPath(document);
return (
<span>⟩</span>
<a href={path}>{title}</a>
);
})}
</div>

View file

@ -4,14 +4,14 @@ import { getDocumentPath, getDocumentTitle, getChildDocuments } from "@utils/doc
const { document } = Astro.props; const { document } = Astro.props;
const childDocuments = await getChildDocuments(document); const childDocuments = await getChildDocuments(document);
--- ---
<ul> <ul class="menu">
{childDocuments.map(document => { {childDocuments.map(document => {
const title = getDocumentTitle(document); const title = getDocumentTitle(document);
const path = getDocumentPath(document); const path = getDocumentPath(document);
return ( return (
<li> <li>
<a href={path}>{title}</a> <a href={path}>{title}</a>
</li> </li>
); );
})} })}

View file

@ -1,5 +1,6 @@
--- ---
const { pageTitle } = Astro.props; const { pageTitle } = Astro.props;
import "@styles/main.css";
--- ---
<html lang="en"> <html lang="en">
<head> <head>

View file

@ -1,12 +0,0 @@
---
import BaseLayout from "@layouts/BaseLayout.astro";
import DocumentMenu from "@components/DocumentMenu.astro";
import { getDocumentPath, getDocumentTitle } from "@utils/docs";
const { document } = Astro.props;
const pageTitle = getDocumentTitle(document);
---
<BaseLayout pageTitle={pageTitle}>
<slot />
<DocumentMenu document={document} />
</BaseLayout>

View file

@ -1,7 +1,9 @@
--- ---
import { getCollection, render } from 'astro:content'; import { getCollection, render } from 'astro:content';
import DocumentLayout from "@layouts/DocumentLayout.astro"; import BaseLayout from "@layouts/BaseLayout.astro";
import DocumentMenu from "@components/DocumentMenu.astro";
import DocumentBreadcrumbs from "@components/DocumentBreadcrumbs.astro";
import { getDocumentPath, getDocumentTitle, getChildDocuments } from "@utils/docs"; import { getDocumentPath, getDocumentTitle, getChildDocuments } from "@utils/docs";
export async function getStaticPaths() { export async function getStaticPaths() {
@ -14,9 +16,11 @@ export async function getStaticPaths() {
} }
const { document } = Astro.props; const { document } = Astro.props;
const paths = await getStaticPaths(); const pageTitle = getDocumentTitle(document);
const { Content } = await render(document); const { Content } = await render(document);
--- ---
<DocumentLayout document={document}> <BaseLayout pageTitle={pageTitle}>
<DocumentBreadcrumbs document={document} />
<Content /> <Content />
</DocumentLayout> <DocumentMenu document={document} />
</BaseLayout>

18
astro/src/styles/main.css Normal file
View file

@ -0,0 +1,18 @@
html, body {
font-family: sans-serif;
}
main {
margin: 0 auto;
max-width: 600px;
line-height: 1.35;
}
.astro-code {
padding: 1rem;
}
ul.menu {
list-style: none;
padding: 0;
}

View file

@ -1,11 +1,13 @@
import type { MarkdownHeading } from "astro"; import type { MarkdownHeading } from "astro";
import { getCollection, type CollectionEntry } from "astro:content"; import { getCollection, type CollectionEntry } from "astro:content";
export function getDocumentPath(document: CollectionEntry<"documents">) { export type Document = CollectionEntry<"docs">;
return "/" + document.id.replace(/\/_index$/, "");
export function getDocumentPath(document: Document) {
return "/" + document.id.replace(/\/_index$/, "") + "/";
} }
export function getDocumentTitle(document: CollectionEntry<"documents">) { export function getDocumentTitle(document: Document) {
const headings: MarkdownHeading[] = const headings: MarkdownHeading[] =
(document.rendered?.metadata?.headings as MarkdownHeading[]) || []; (document.rendered?.metadata?.headings as MarkdownHeading[]) || [];
const firstHeading = headings[0]; const firstHeading = headings[0];
@ -17,17 +19,37 @@ export function getDocumentTitle(document: CollectionEntry<"documents">) {
return null; return null;
} }
export async function getChildDocuments( export async function getChildDocuments(parentDocument: Document | undefined) {
parentDocument: CollectionEntry<"documents"> | undefined,
) {
const documents = await getCollection("docs"); const documents = await getCollection("docs");
const basePath = const basePath =
parentDocument !== undefined ? getDocumentPath(parentDocument) : ""; parentDocument !== undefined ? getDocumentPath(parentDocument) : "/";
const pathPattern = new RegExp(`^${basePath}/[^/]+$`); const pathPattern = new RegExp(`^${basePath}[^/]+/$`);
return documents.filter((document) => { const childDocuments = documents.filter((document) => {
const documentPath = getDocumentPath(document); const path = getDocumentPath(document);
return pathPattern.test(documentPath) && documentPath !== basePath; return pathPattern.test(path) && path !== basePath;
});
return childDocuments.sort((a, b) => {
const aWeight = a.data.weight || 0;
const bWeight = b.data.weight || 0;
return aWeight - bWeight;
});
}
export async function getAncestorDocuments(document: Document) {
const documents = await getCollection("docs");
const descendantPath = getDocumentPath(document);
const ancestorDocuments = documents.filter((document) => {
const path = getDocumentPath(document);
return descendantPath.startsWith(path) && path !== descendantPath;
});
return ancestorDocuments.sort((a, b) => {
return getDocumentPath(a).length - getDocumentPath(b).length;
}); });
} }

View file

@ -7,6 +7,7 @@
"@components/*": ["src/components/*"], "@components/*": ["src/components/*"],
"@layouts/*": ["src/layouts/*"], "@layouts/*": ["src/layouts/*"],
"@pages/*": ["src/pages/*"], "@pages/*": ["src/pages/*"],
"@styles/*": ["src/styles/*"],
"@utils/*": ["src/utils/*"] "@utils/*": ["src/utils/*"]
} }
} }

View file

@ -3,10 +3,10 @@ services:
build: build:
context: docker context: docker
dockerfile: ./docker/Dockerfile dockerfile: ./docker/Dockerfile
container_name: server container_name: notes
restart: always restart: always
volumes: volumes:
- ./hugo/public:/usr/share/nginx/html:ro - ./astro/dist:/usr/share/nginx/html:ro
ports: ports:
- "42069:80" - "42069:80"

View file

@ -8,9 +8,4 @@ server {
auth_basic "Restricted"; auth_basic "Restricted";
auth_basic_user_file auth.htpasswd; auth_basic_user_file auth.htpasswd;
} }
# Disable authentication for certbot challenge dir.
location /.well-known/acme-challenge/ {
auth_basic off;
}
} }

View file

@ -1,3 +0,0 @@
# My notes
Muh notes.

View file

@ -1,3 +1,5 @@
+++ ---
weight = 9000 weight: 9000
+++ ---
# Chess

View file

@ -0,0 +1 @@
# Chess Openings

View file

@ -0,0 +1 @@
# Design

View file

@ -1,3 +1,5 @@
+++ ---
weight = 3100 weight: 3100
+++ ---
# Electronics

View file

@ -1,3 +1,5 @@
+++ ---
weight = 1100 weight: 1100
+++ ---
# Finances

View file

@ -0,0 +1 @@
# Insurance

View file

@ -0,0 +1 @@
# Handicrafts

View file

@ -1,33 +1,5 @@
+++ ---
weight = 3000 weight: 3000
+++ ---
# Home network # Home network
## Self-hosted services
### Implemented
- NGINX reverse proxy
- Pi-hole DNS server
- Jellyfin media server
- Hugo notes website
- Lacks proper auth (currently using Basic)
### Planned
System administration:
- Vouch SSO proxy [[Github](https://github.com/vouch/vouch-proxy)]
- Provide identity management for multiple apps running on the server.
- Authentik identity provider [[Github](https://github.com/goauthentik/authentik)]
- IdP for Vouch.
- Grafana Metrics and Monitoring [[Github](https://github.com/grafana/grafana)]
- Observability.
- Laravel notes website
- Markdown files as content.
- See [Aaron Francis's blog](https://aaronfrancis.com/2021/blogging-with-markdown-in-laravel-1d45f4fa).
Services:
- Bitwarden secrets vault [[Github](https://github.com/bitwarden/server)]

View file

@ -0,0 +1 @@
# Admin

View file

@ -0,0 +1,33 @@
---
weight: -1
---
# Home network overview
## Self-hosted services
### Implemented
- NGINX reverse proxy
- Pi-hole DNS server
- Jellyfin media server
- Hugo notes website
- Lacks proper auth (currently using Basic)
## Planned features
System administration:
- Vouch SSO proxy [[Github](https://github.com/vouch/vouch-proxy)]
- Provide identity management for multiple apps running on the server.
- Authentik identity provider [[Github](https://github.com/goauthentik/authentik)]
- IdP for Vouch.
- Grafana Metrics and Monitoring [[Github](https://github.com/grafana/grafana)]
- Observability.
- Laravel notes website
- Markdown files as content.
- See [Aaron Francis's blog](https://aaronfrancis.com/2021/blogging-with-markdown-in-laravel-1d45f4fa).
Services:
- Bitwarden secrets vault [[Github](https://github.com/bitwarden/server)]

View file

@ -1,3 +1,5 @@
+++ ---
weight = 1200 weight: 1200
+++ ---
# Household

View file

@ -1,3 +1,5 @@
+++ ---
weight = 8000 weight: 8000
+++ ---
# Latin

View file

@ -0,0 +1 @@
# Lingus Latina per se Illustrata

View file

@ -1,3 +1,5 @@
+++ ---
weight = 6000 weight: 6000
+++ ---
# Parenting

View file

@ -0,0 +1 @@
# Professional

View file

@ -1,7 +1,3 @@
+++
title = 'Programming languages'
+++
# Programming languages # Programming languages
## PHP ## PHP

View file

@ -1,7 +1,3 @@
+++
title = 'Plan for this section'
+++
# Plan for this section # Plan for this section
List the various problem domains: List the various problem domains:

View file

@ -1,3 +1,5 @@
+++ ---
weight = 6100 weight: 6100
+++ ---
# Seasonal events

View file

@ -1,3 +1,5 @@
+++ ---
weight = 1000 weight: 1000
+++ ---
# Self-care

3
hugo/.gitignore vendored
View file

@ -1,3 +0,0 @@
# Build files
/public/
/resources/_gen/

View file

@ -1,5 +0,0 @@
+++
date = '{{ .Date }}'
draft = true
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
+++

View file

@ -1 +0,0 @@
@import "plugins/scrollbars";

View file

@ -1,9 +0,0 @@
baseURL = 'https://example.org/'
languageCode = 'en-us'
title = 'My Notes'
theme = 'hugo-book'
contentDir = '../docs'
ignoreLogs = ['warning-goldmark-raw-html']
[params]
BookSection = '*'

@ -1 +0,0 @@
Subproject commit 645c868cec1396548456eac68205eabbd8ca9564

View file

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
cd hugo cd astro
hugo npm run astro build
rsync -a public/* raspberrypi:/var/www/html/notes/hugo/public rsync -a dist/* raspberrypi:/srv/notes/astro/dist