turbopack and app router; very annoying to work with!
This commit is contained in:
9
src/app/components/container.tsx
Normal file
9
src/app/components/container.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
export default function Container(props: { children?: React.ReactNode, ignore?: boolean }) {
|
||||
if (props.ignore)
|
||||
return <>{props.children}</>;
|
||||
return (
|
||||
<div className='container'>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
24
src/app/components/quick-links.tsx
Normal file
24
src/app/components/quick-links.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import Link from 'next/link';
|
||||
import Pages from '../../../public/external.json';
|
||||
|
||||
function QuickLinks() {
|
||||
return (
|
||||
<div className='block'>
|
||||
{
|
||||
Object.entries(Pages).map(([title, link]) => {
|
||||
const extern = link.match(/^http/) && `blue extern` || '';
|
||||
return (
|
||||
<Link
|
||||
key={link}
|
||||
href={link}
|
||||
className={`${extern} link button`}>
|
||||
{title}
|
||||
</Link>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default QuickLinks;
|
||||
40
src/app/components/recent-notes.tsx
Normal file
40
src/app/components/recent-notes.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import Link from "next/link";
|
||||
import NotesInfo from '../../../public/notes.json';
|
||||
|
||||
function RecentNotes() {
|
||||
const notes = Object.entries(NotesInfo)
|
||||
.map(([slug, note]) => {
|
||||
return {
|
||||
slug,
|
||||
title: note.title,
|
||||
mtime: new Date(note.mtime)
|
||||
}
|
||||
})
|
||||
.sort(
|
||||
(a, b) => {
|
||||
return b.mtime.getTime() - a.mtime.getTime();
|
||||
}
|
||||
);
|
||||
return (
|
||||
<div className='block'>
|
||||
<h2>Recent Notes</h2>
|
||||
<ul>
|
||||
{notes?.slice(0, 5)
|
||||
.map(({slug, title, mtime}) => {
|
||||
return (
|
||||
<li key={slug} >
|
||||
<Link href={`/notes/${slug}`}>{title}</Link>
|
||||
</li>
|
||||
);
|
||||
})
|
||||
}
|
||||
{
|
||||
notes.length > 5 &&
|
||||
<Link href='/notes'>More...</Link>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default RecentNotes;
|
||||
52
src/app/components/recent-posts.module.css
Normal file
52
src/app/components/recent-posts.module.css
Normal file
@@ -0,0 +1,52 @@
|
||||
.container {
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
border-bottom: 1px dashed var(--main-border-color);
|
||||
border-left: 1px dashed var(--main-border-color);
|
||||
padding-top: 1.25rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.block {
|
||||
margin: 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.block+.block {
|
||||
border-top: 1px dashed var(--main-border-color);
|
||||
}
|
||||
|
||||
.block:first-of-type {
|
||||
border-top-right-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.block:nth-of-type(2n) {
|
||||
background-color: var(--table-even-color);
|
||||
}
|
||||
|
||||
.block:nth-of-type(2n+1) {
|
||||
background-color: var(--table-odd-color);
|
||||
}
|
||||
|
||||
.postTitle {
|
||||
flex: 1 1 60%;
|
||||
padding: .25rem 0.75rem;
|
||||
}
|
||||
|
||||
.postDate {
|
||||
flex: 1 1;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
font-style: italic;
|
||||
font-size: 1rem;
|
||||
padding: .25rem 0.50rem;
|
||||
}
|
||||
|
||||
.more {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.more a {
|
||||
text-decoration: none;
|
||||
}
|
||||
50
src/app/components/recent-posts.tsx
Normal file
50
src/app/components/recent-posts.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import Link from "next/link";
|
||||
import { toRelativeDate } from "../lib/date";
|
||||
import style from './recent-posts.module.css';
|
||||
import PostsInfo from '../../../public/posts.json';
|
||||
|
||||
function PostBlock({ slug, otime, title }: { slug: string, otime: string, title: string }) {
|
||||
return (
|
||||
<div className={style.block}>
|
||||
<span className={style.postDate}>
|
||||
{toRelativeDate(new Date(otime))}
|
||||
</span>
|
||||
<div className={style.postTitle}>
|
||||
<Link href={`/posts/${slug}`}>
|
||||
{title}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RecentPosts() {
|
||||
const posts = Object.entries(PostsInfo).reverse();
|
||||
if (!posts.length)
|
||||
return <></>;
|
||||
return (
|
||||
<div className='block'>
|
||||
<h2>Recent Posts</h2>
|
||||
<div className={style.container}>
|
||||
{posts?.slice(0, 10)
|
||||
.map(([slug, post]: any, i: number) => {
|
||||
return (
|
||||
<PostBlock
|
||||
key={slug}
|
||||
slug={slug}
|
||||
title={post.title}
|
||||
otime={post.otime} />
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{
|
||||
posts.length > 10 &&
|
||||
<div className={style.more}>
|
||||
<Link href='/posts' >More...</Link>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default RecentPosts;
|
||||
30
src/app/components/title.module.css
Normal file
30
src/app/components/title.module.css
Normal file
@@ -0,0 +1,30 @@
|
||||
.container {
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
background-color: var(--main-background-color);
|
||||
}
|
||||
|
||||
.container .title {
|
||||
border-bottom: 1px solid #FFFFFF;
|
||||
max-width: 95%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.nav {
|
||||
padding: 0.25rem 0.75rem;
|
||||
font-size: 1.25rem;
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4);
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
margin: 0;
|
||||
height: 2.5rem;
|
||||
max-height: 2.5rem;
|
||||
min-height: 2.5rem;
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom right, #1a3a15, #09351b) no-repeat center center fixed;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
68
src/app/components/title.tsx
Normal file
68
src/app/components/title.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
'use client'
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Fragment } from 'react';
|
||||
|
||||
import style from './title.module.css';
|
||||
import SiteMap from '../../../public/sitemap.json';
|
||||
import { Sites } from '../lib/site';
|
||||
|
||||
function createPathElements(ancestors: Array<{ name: string, path: string }>) {
|
||||
let currentPath = '';
|
||||
return ancestors.map((ancestor, id) => {
|
||||
currentPath += `/${ancestor.path}`
|
||||
return (
|
||||
<Fragment key={currentPath} >
|
||||
<Link href={currentPath}>{ancestor.name}</Link>
|
||||
<> / </>
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export default function Title() {
|
||||
const pagePath = usePathname();
|
||||
const splitPath: Array<{ name: string, path: string }> = [];
|
||||
|
||||
// TODO(Paul): clean this up
|
||||
let currRoot: Sites = SiteMap.pages;
|
||||
let title: string | null = null;
|
||||
if (pagePath && pagePath !== '/') {
|
||||
const subPaths = pagePath.split('?')[0].split('#')[0].split('/');
|
||||
for (const p of subPaths.slice(1, subPaths.length)) {
|
||||
if (!p || !currRoot[p])
|
||||
continue;
|
||||
splitPath.push({ name: currRoot[p].title, path: p });
|
||||
|
||||
if (currRoot === undefined
|
||||
|| currRoot[p] === undefined
|
||||
|| currRoot[p].pages === undefined)
|
||||
break;
|
||||
currRoot = currRoot[p].pages!;
|
||||
}
|
||||
if (splitPath !== undefined && splitPath.length > 0)
|
||||
title = splitPath.pop()!.name;
|
||||
|
||||
}
|
||||
|
||||
const pathElements = splitPath && createPathElements(splitPath) || <></>;
|
||||
return (
|
||||
<>
|
||||
{/* <head>
|
||||
<title>{title && `${title} | PaulW.XYZ` || 'PaulW.XYZ'}</title>
|
||||
</head> */}
|
||||
<div className={style.container}>
|
||||
<h1 className={style.title}>
|
||||
{title || 'PaulW.XYZ'}
|
||||
</h1>
|
||||
</div>
|
||||
<div className={`${style.nav} h1`}>
|
||||
{
|
||||
title
|
||||
? <><Link href='/'>PaulW.XYZ</Link> / {pathElements}{title}</>
|
||||
: <>PaulW.XYZ /</>
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user