Compare commits
3 Commits
1e5d1f13e8
...
692430f959
| Author | SHA1 | Date | |
|---|---|---|---|
| 692430f959 | |||
| 4a3f6774cc | |||
| 81c912e3ff |
2153
package-lock.json
generated
2153
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
"@types/react": "^19.1.7",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"astro": "^5.9.2",
|
||||
"astro-loader-obsidian": "^0.10.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"sharp": "^0.34.2"
|
||||
|
||||
@@ -18,6 +18,5 @@ const { date } = Astro.props;
|
||||
<style>
|
||||
time {
|
||||
font-family: "Fira Code", monospace;
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -33,7 +33,7 @@ import Blazestar from './Blazestar.astro';
|
||||
</div>
|
||||
</nav>
|
||||
<div class="h-card">
|
||||
<img class="u-photo" src="/public/photos/Bingley Business.jpg" />
|
||||
<img class="u-photo" src="/photos/Bingley Business.jpg" />
|
||||
<a class="p-name u-url" href="https://www.blazestar.net">Drew Haven</a>
|
||||
a.k.a. <span class="p-nickname">Periodic</span>
|
||||
</div>
|
||||
|
||||
65
src/components/NoteHierarchy.astro
Normal file
65
src/components/NoteHierarchy.astro
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
import { type Hierarchy } from "../lib/hierarchy.ts";
|
||||
|
||||
interface Props {
|
||||
prefix: string;
|
||||
hierarchy: Hierarchy;
|
||||
}
|
||||
|
||||
const { prefix, hierarchy } = Astro.props;
|
||||
|
||||
const pathname = Astro.url.pathname.replace(import.meta.env.BASE_URL, '/');
|
||||
|
||||
---
|
||||
{
|
||||
Object.entries(hierarchy).map(([leader, node]) => {
|
||||
const notePath = `${prefix}/${leader}`;
|
||||
const isActive = pathname === notePath;
|
||||
const linkClasses = isActive ? "active" : "";
|
||||
|
||||
if (node.children) {
|
||||
return (
|
||||
<details open={pathname.startsWith(notePath) && "true"}>
|
||||
<summary>
|
||||
{ node.id
|
||||
? <a href={notePath} class={linkClasses}>{node.title || leader}</a>
|
||||
: <span class="header-only">{node.title || leader}</span>
|
||||
}
|
||||
</summary>
|
||||
<div class="child-notes">
|
||||
{ <Astro.self prefix={notePath} hierarchy={node.children} /> }
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<a href={notePath} class={linkClasses}>
|
||||
{node.title || leader}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
<style>
|
||||
.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.child-notes {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
summary {
|
||||
.header-only {
|
||||
color: var(--color-gray)
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
29
src/components/NotesLinks.astro
Normal file
29
src/components/NotesLinks.astro
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
import { makeHierarchy } from '../lib/hierarchy';
|
||||
import { getCollection } from 'astro:content';
|
||||
import NotchedBox from './NotchedBox.astro';
|
||||
import NoteHierarchy from './NoteHierarchy.astro';
|
||||
|
||||
const notes = await getCollection('notes');
|
||||
|
||||
const hierarchy = makeHierarchy(notes.map(note => [note.id, note.data.title]));
|
||||
|
||||
const pathname = Astro.url.pathname.replace(import.meta.env.BASE_URL, '');
|
||||
const isActive = pathname.startsWith("notes");
|
||||
---
|
||||
<NotchedBox fillNotches={isActive ? 'left' : 'none'}>
|
||||
<div class="notes-header">Notes</div>
|
||||
<div class="note-links">
|
||||
<NoteHierarchy prefix="/notes" hierarchy={hierarchy} />
|
||||
</div>
|
||||
</NotchedBox>
|
||||
|
||||
<style>
|
||||
.notes-header {
|
||||
color: var(--color-light-text);
|
||||
font-size: var(--font-size-lg);
|
||||
}
|
||||
.note-links {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
import SidebarLink from './SidebarLink.astro';
|
||||
import Blazestar from './Blazestar.astro';
|
||||
import NotesLinks from './NotesLinks.astro';
|
||||
---
|
||||
|
||||
<header>
|
||||
@@ -10,6 +11,7 @@ import Blazestar from './Blazestar.astro';
|
||||
<SidebarLink href="/">Home</SidebarLink>
|
||||
<SidebarLink href="/blog">Blog</SidebarLink>
|
||||
<SidebarLink href="/about">About</SidebarLink>
|
||||
<NotesLinks />
|
||||
</div>
|
||||
<div class="social-links">
|
||||
<a href="https://mastodon.social/@periodic" target="_blank" rel="me">
|
||||
@@ -57,13 +59,12 @@ import Blazestar from './Blazestar.astro';
|
||||
gap: 16px;
|
||||
a {
|
||||
color: var(--color-light-text);
|
||||
border-bottom: 4px solid transparent;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-accent);
|
||||
border-bottom: 4px solid transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import {
|
||||
ObsidianDocumentSchema,
|
||||
ObsidianMdLoader,
|
||||
} from "astro-loader-obsidian";
|
||||
import { glob } from "astro/loaders";
|
||||
import { defineCollection, z } from "astro:content";
|
||||
|
||||
@@ -26,4 +30,15 @@ const page = defineCollection({
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog, page };
|
||||
const notes = defineCollection({
|
||||
loader: ObsidianMdLoader({
|
||||
base: "src/content/notes",
|
||||
url: "notes",
|
||||
}),
|
||||
schema: ({ image }) =>
|
||||
ObsidianDocumentSchema.extend({
|
||||
image: image().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog, page, notes };
|
||||
|
||||
@@ -26,8 +26,7 @@ they are living and growing in line with their ideals.
|
||||
- Take responsibility for your own actions.
|
||||
- Hold others accountable and responsible for their actions.
|
||||
- Give honest feedback.
|
||||
- Take the time to do good work.
|
||||
- Be proud of your work.
|
||||
- Take the time to do good work and be proud of it.
|
||||
- Be your authentic self.
|
||||
|
||||
### Sustainability and long-term thinking
|
||||
@@ -47,8 +46,7 @@ they are living and growing in line with their ideals.
|
||||
### Self-improvement
|
||||
|
||||
- Be curious and motivated to learn and understand.
|
||||
- Be open to feedback and learning.
|
||||
- Learn new things.
|
||||
- Be open to feedback.
|
||||
- Seek to understand.
|
||||
- Embrace failure as an opportunity to learn.
|
||||
- Take the time to review and retrospect.
|
||||
@@ -62,6 +62,7 @@ const posts = await getPublishedPosts( selectedTag );
|
||||
}
|
||||
.date {
|
||||
color: var(--color-gray);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
.entry {
|
||||
padding: 0.5em;
|
||||
|
||||
@@ -26,6 +26,10 @@ const { slug, title, description, pubDate, updatedDate, heroImage, tags } = Astr
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.dt-published {
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
37
src/lib/hierarchy.ts
Normal file
37
src/lib/hierarchy.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export interface HierarchyNode {
|
||||
id: string | null;
|
||||
title: string | null;
|
||||
children: Hierarchy | null;
|
||||
}
|
||||
export interface Hierarchy extends Record<string, HierarchyNode> {}
|
||||
|
||||
function addToHierarchy(
|
||||
tree: Hierarchy,
|
||||
[noteId, title]: [string, string],
|
||||
): Hierarchy {
|
||||
const path = noteId.split("/");
|
||||
if (path.length === 0) {
|
||||
return tree;
|
||||
}
|
||||
|
||||
if (!tree[path[0]]) {
|
||||
tree[path[0]] = { id: null, title: null, children: null };
|
||||
}
|
||||
let curr = tree[path[0]];
|
||||
|
||||
for (const node of path.slice(1)) {
|
||||
curr.children ||= {};
|
||||
if (!curr.children[node]) {
|
||||
curr.children[node] = { id: null, title: null, children: null };
|
||||
}
|
||||
curr = curr.children[node];
|
||||
}
|
||||
|
||||
curr.id = noteId;
|
||||
curr.title = title;
|
||||
return tree;
|
||||
}
|
||||
|
||||
export function makeHierarchy(notes: Array<[string, string]>): Hierarchy {
|
||||
return notes.reduce(addToHierarchy, {});
|
||||
}
|
||||
@@ -15,6 +15,6 @@ const { Content } = await render(about);
|
||||
<RootLayout>
|
||||
<NotchedBox fillNotches="left">
|
||||
<h1>{about.data.title}</h1>
|
||||
<Content />
|
||||
<Content />
|
||||
</NotchedBox>
|
||||
</RootLayout>
|
||||
|
||||
36
src/pages/notes/[...slug].astro
Normal file
36
src/pages/notes/[...slug].astro
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
import RootLayout from '../../layouts/RootLayout.astro';
|
||||
import NotchedBox from '../../components/NotchedBox.astro';
|
||||
import FormattedDate from '../../components/FormattedDate.astro';
|
||||
import { type CollectionEntry, getCollection } from 'astro:content';
|
||||
import { render } from 'astro:content';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const notes = await getCollection('notes');
|
||||
return notes.map((note) => ({
|
||||
params: { slug: note.id },
|
||||
props: note,
|
||||
}));
|
||||
}
|
||||
type Props = CollectionEntry<'notes'>;
|
||||
|
||||
const note = Astro.props;
|
||||
const { Content } = await render(note);
|
||||
---
|
||||
|
||||
<RootLayout>
|
||||
<NotchedBox fillNotches="left">
|
||||
<h1>{note.data.title}</h1>
|
||||
<div class="last-updated">
|
||||
Last updated <FormattedDate date={note.data.updated} />
|
||||
</div>
|
||||
<Content />
|
||||
</NotchedBox>
|
||||
</RootLayout>
|
||||
|
||||
<style>
|
||||
.last-updated {
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray);
|
||||
}
|
||||
</style>
|
||||
@@ -181,10 +181,10 @@ pre > code {
|
||||
all: unset;
|
||||
}
|
||||
blockquote {
|
||||
border-left: 4px solid var(--accent);
|
||||
padding: 0 0 0 20px;
|
||||
margin: 0px;
|
||||
font-size: 1.333em;
|
||||
border-left: 4px solid var(--color-gray);
|
||||
padding: 0 8px 0 16px;
|
||||
margin: 0;
|
||||
background-color: var(--color-space-blue-light);
|
||||
}
|
||||
hr {
|
||||
border: none;
|
||||
|
||||
Reference in New Issue
Block a user