Add programming-resources; swi->generic Nintendo;
Remove custom html from markdown, clean-up UI (again) Signed-off-by: Paul W. <lambdapaul@protonmail.com>
This commit is contained in:
13
components/container.tsx
Normal file
13
components/container.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
export type ChildrenType = JSX.Element | Array<ChildrenType>;
|
||||
|
||||
function Container(props: { children?: ChildrenType, ignore?: boolean }) {
|
||||
if (props.ignore)
|
||||
return <>{props.children}</>;
|
||||
return (
|
||||
<div className='container'>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Container;
|
||||
@@ -1,25 +1,18 @@
|
||||
import Title from './title';
|
||||
|
||||
type ChildrenType = JSX.Element | Array<ChildrenType>;
|
||||
import Container, { ChildrenType } from './container';
|
||||
|
||||
type LayoutProps = {
|
||||
children?: ChildrenType,
|
||||
removeContainer?: boolean,
|
||||
};
|
||||
|
||||
function Container(props: {children?: ChildrenType, ignore?: boolean}) {
|
||||
if (props.ignore)
|
||||
return <>{props.children}</>;
|
||||
return <div className='container'>
|
||||
{props.children}
|
||||
</div>;
|
||||
}
|
||||
|
||||
function Layout(props : LayoutProps) {
|
||||
function Layout(props: LayoutProps) {
|
||||
return (
|
||||
<>
|
||||
<Title />
|
||||
<Container ignore={props.removeContainer}>{props.children}</Container>
|
||||
<Container ignore={props.removeContainer}>
|
||||
{props.children}
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
import style from '../styles/lists.module.css';
|
||||
import React, { ReactElement } from 'react';
|
||||
|
||||
export interface listItem {
|
||||
[x: string]: any;
|
||||
children?: listItem[] | string[];
|
||||
url?: string;
|
||||
type?: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export function toListItem(record: Record<string, any>): listItem | null {
|
||||
if (!record.title)
|
||||
return null;
|
||||
|
||||
let children: listItem[] | string[] = [];
|
||||
if (Array.isArray(record.children) && record.children.length) {
|
||||
|
||||
let lchildren: listItem[] = [];
|
||||
let schildren: string[] = [];
|
||||
for (const child of record.children) {
|
||||
if (typeof child === 'string') {
|
||||
schildren.push(child);
|
||||
continue;
|
||||
}
|
||||
const lChild = toListItem(child);
|
||||
if (lChild)
|
||||
lchildren.push(lChild);
|
||||
}
|
||||
|
||||
if (!lchildren.length) {
|
||||
children = schildren;
|
||||
}
|
||||
else {
|
||||
children = [...lchildren, ...schildren.map((s: string): listItem => {
|
||||
return { title: s };
|
||||
})];
|
||||
}
|
||||
}
|
||||
|
||||
return Object.assign(record, {
|
||||
title: record.title,
|
||||
url: record.url,
|
||||
children: children.length ? children : undefined,
|
||||
type: record.type?.length ? record.type : undefined,
|
||||
description: record.description,
|
||||
});
|
||||
}
|
||||
|
||||
export function mapChild(
|
||||
obj: listItem | string,
|
||||
level: number,
|
||||
typeMap? : Record<string, (o: listItem) => JSX.Element>
|
||||
) {
|
||||
if (typeof obj === 'string') {
|
||||
if (obj === '')
|
||||
return <></>
|
||||
return <span className={style.listItem}>{obj}</span>
|
||||
}
|
||||
|
||||
if (obj.title === '')
|
||||
return <></>
|
||||
|
||||
const desc = obj.description
|
||||
? <span className={style.listItemDesc}>{obj.description}</span>
|
||||
: <></>;
|
||||
|
||||
if (obj.url)
|
||||
return (
|
||||
<>
|
||||
<span className={style.listItem}><a href={obj.url}>{obj.title}</a></span>
|
||||
{desc}
|
||||
</>);
|
||||
|
||||
if (!obj.children) {
|
||||
let cb;
|
||||
if (obj.type && typeMap) {
|
||||
cb = typeMap[obj.type]
|
||||
}
|
||||
|
||||
return cb
|
||||
? cb(obj)
|
||||
: (<><span className={style.listItem}>{obj.title}</span>{desc}</>);
|
||||
}
|
||||
|
||||
let title: ReactElement;
|
||||
|
||||
if (level >= 0 && level <= 4)
|
||||
title = React.createElement(`h${level + 2}`, {}, obj.title);
|
||||
else
|
||||
title = React.createElement('strong', {}, obj.title);
|
||||
|
||||
return (
|
||||
<section className={level < 4 && `block ${style.block}` || ''}>
|
||||
{title}
|
||||
{obj.description ? <p className={style.desc}>{obj.description}</p> : <></>}
|
||||
<div>
|
||||
{obj.children.map(l => mapChild(l, level + 1, typeMap))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -4,12 +4,17 @@ import Pages from '../public/external.json';
|
||||
function QuickLinks() {
|
||||
return (
|
||||
<div className='block'>
|
||||
<div className='h2'>Quick Links</div>
|
||||
<h2>Quick Links</h2>
|
||||
{
|
||||
Object.entries(Pages).map(([title, link], i) => {
|
||||
const extern = link.match(/^http/) && `blue extern` || '';
|
||||
return (
|
||||
<Link key={i} href={link} className={`${extern} link button`}>{title}</Link>
|
||||
<Link
|
||||
key={i}
|
||||
href={link}
|
||||
className={`${extern} link button`}>
|
||||
{title}
|
||||
</Link>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,22 +2,29 @@ import Link from "next/link";
|
||||
import NotesInfo from '../public/notes.json';
|
||||
|
||||
function RecentNotes() {
|
||||
const notes = Object.entries(NotesInfo);
|
||||
const notes = Object.entries(NotesInfo).reverse();
|
||||
return (
|
||||
<div className='block'>
|
||||
<div className='h2'>Recent Notes</div>
|
||||
{notes?.slice(0, 10)
|
||||
.map(([slug, note]: any) => {
|
||||
return <Link key={slug} href={`/notes/${slug}`} className={`button link`}>{note.title}</Link>
|
||||
<ul className='block'>
|
||||
<h2>Recent Notes</h2>
|
||||
{notes?.slice(0, 5)
|
||||
.map(([slug, note]: any, i: number) => {
|
||||
return (
|
||||
<li
|
||||
key={i}
|
||||
>
|
||||
<Link
|
||||
href={`/notes/${slug}`}>
|
||||
{note.title}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})
|
||||
}
|
||||
{
|
||||
notes.length > 10 &&
|
||||
<div>
|
||||
<Link href='/notes' className='h5'>More...</Link>
|
||||
</div>
|
||||
notes.length > 5 &&
|
||||
<Link href='/notes'>More...</Link>
|
||||
}
|
||||
</div>
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,46 @@
|
||||
import Link from "next/link";
|
||||
import date from "../lib/date";
|
||||
import { toRelativeDate } from "../lib/date";
|
||||
import style from '../styles/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);
|
||||
const posts = Object.entries(PostsInfo).reverse();
|
||||
if (!posts.length)
|
||||
return <></>;
|
||||
return (
|
||||
<div className='block'>
|
||||
<div className='h2'>Recent Posts</div>
|
||||
<h2>Recent Posts</h2>
|
||||
<div className={style.container}>
|
||||
{posts?.slice(0, 10)
|
||||
.map(([slug, post]: any) => {
|
||||
return <div className={style.block} key={post.slug}>
|
||||
<span className={style.postDate}>
|
||||
{date.toRelativeDate(new Date(post.otime))}
|
||||
</span>
|
||||
<div className={style.postTitle}>
|
||||
<Link href={`/posts/${slug}`}>
|
||||
{post.title}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
.map(([slug, post]: any, i: number) => {
|
||||
return (
|
||||
<PostBlock
|
||||
key={i}
|
||||
slug={slug}
|
||||
title={post.title}
|
||||
otime={post.otime} />
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{
|
||||
posts.length > 10 &&
|
||||
<div className={style.more}>
|
||||
<Link href='/posts' className='h5'>More...</Link>
|
||||
<Link href='/posts' >More...</Link>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ function createPathElements(ancestors: Array<{ name: string, path: string }>) {
|
||||
</>
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function Title() {
|
||||
|
||||
@@ -31,10 +31,12 @@ function Title() {
|
||||
const subPaths = pagePath.split('/');
|
||||
for (const p of subPaths.slice(1, subPaths.length)) {
|
||||
splitPath.push({ name: currRoot[p].title, path: p });
|
||||
|
||||
if (currRoot === undefined
|
||||
|| currRoot[p] === undefined
|
||||
|| currRoot[p].subpages !== undefined)
|
||||
currRoot = currRoot[p].subpages!;
|
||||
|| currRoot[p].subpages === undefined)
|
||||
break;
|
||||
currRoot = currRoot[p].subpages!;
|
||||
}
|
||||
if (splitPath !== undefined && splitPath.length > 0)
|
||||
title = splitPath.pop()!.name;
|
||||
@@ -53,9 +55,11 @@ function Title() {
|
||||
</h1>
|
||||
</div>
|
||||
<div className={`${style.nav} h1`}>
|
||||
{title
|
||||
? <><Link href='/'>PaulW.XYZ</Link> / {pathElements}{title}</>
|
||||
: <>PaulW.XYZ /</>}
|
||||
{
|
||||
title
|
||||
? <><Link href='/'>PaulW.XYZ</Link> / {pathElements}{title}</>
|
||||
: <>PaulW.XYZ /</>
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user