Refactor, update UI, and add notes

This commit is contained in:
Paul W 2022-10-04 23:41:59 -04:00
parent 3781c2c154
commit d94de055d8
No known key found for this signature in database
GPG Key ID: 5007FDE02574ED90
31 changed files with 813 additions and 265 deletions

3
.gitignore vendored
View File

@ -4,4 +4,5 @@ dist/
.DS_Store .DS_Store
.cache/ .cache/
*.bun *.bun
.env **/*.wip.md
.env

View File

@ -1,6 +1,6 @@
import Image from 'next/image'; import Image from 'next/image';
import { parse as URIparse } from 'uri-js'; import { parse as URIparse } from 'uri-js';
import date from '../util/date'; import date from '../lib/date';
import style from '../styles/github-profile.module.css'; import style from '../styles/github-profile.module.css';
function CardRow({label, children}: {label: string, children: JSX.Element | string}) { function CardRow({label, children}: {label: string, children: JSX.Element | string}) {
@ -11,6 +11,7 @@ function CardRow({label, children}: {label: string, children: JSX.Element | stri
</div> </div>
); );
} }
function GitHubProfile({user}: any) { function GitHubProfile({user}: any) {
return (<> return (<>
<div className={style.card}> <div className={style.card}>
@ -32,8 +33,8 @@ return (<>
</CardRow>} </CardRow>}
<CardRow label='Location'>{user.location}</CardRow> <CardRow label='Location'>{user.location}</CardRow>
<CardRow label='About'>{user.bio}</CardRow> <CardRow label='About'>{user.bio}</CardRow>
<CardRow label='Created'>{user.created_at ? date.prettyPrint(user.created_at) : ''}</CardRow> <CardRow label='Created'>{user.created_at ? date.toRelativeDate(user.created_at) : ''}</CardRow>
{user.updated_at && <CardRow label='Last Updated'>{user.updated_at ? date.prettyPrint(user.updated_at) : ''}</CardRow>} {user.updated_at && <CardRow label='Last Updated'>{user.updated_at ? date.toRelativeDate(user.updated_at) : ''}</CardRow>}
{user.twitter_username && <CardRow label='Twitter'> {user.twitter_username && <CardRow label='Twitter'>
<a className='link extern blue button' <a className='link extern blue button'
href={`https://twitter.com/${user.twitter_username}`}> href={`https://twitter.com/${user.twitter_username}`}>

View File

@ -8,16 +8,23 @@ type LayoutProps = {
title?: string, title?: string,
ancestors?: Array<{ name: string, path: string }> ancestors?: Array<{ name: string, path: string }>
children?: ChildrenType, children?: ChildrenType,
removeContainer?: boolean,
}; };
function Layout({ name, title, children, ancestors }: LayoutProps) { function Container(props: {children?: ChildrenType, ignore?: boolean}) {
if (props.ignore)
return <>{props.children}</>;
return <div className='container'>
{props.children}
</div>;
}
function Layout(props : LayoutProps) {
return ( return (
<> <>
<Meta name={name} ancestors={ancestors} /> <Meta name={props.name} ancestors={props.ancestors} />
<Title title={title} name={name} ancestors={ancestors} /> <Title title={props.title} name={props.name} ancestors={props.ancestors} />
<div className='container'> <Container ignore={props.removeContainer}>{props.children}</Container>
{children}
</div>
</> </>
); );
} }

View File

@ -2,7 +2,7 @@ import Head from 'next/head';
function Meta({name, ancestors} function Meta({name, ancestors}
: {name: string, ancestors?: Array<{ name: string, path: string }> }) { : {name: string, ancestors?: Array<{ name: string, path: string }> }) {
const path = () => { function path(): string {
if (!ancestors) if (!ancestors)
return name; return name;
@ -11,12 +11,12 @@ function Meta({name, ancestors}
path = `${path}${obj.name} /`; path = `${path}${obj.name} /`;
}); });
return `${path} ${name}`; return `PaulW.XYZ / ${path} ${name}`;
}; }
return ( return (
<Head> <Head>
<title>PaulW.XYZ / {path()}</title> <title>{path()}</title>
</Head> </Head>
); );
} }

View File

@ -1,7 +1,7 @@
import Link from "next/link"; import Link from "next/link";
import { NoteMeta } from "../util/slug"; import { INoteMeta } from "../lib/slug";
function RecentNotes({ notesMeta }: { notesMeta: NoteMeta[] }) { function RecentNotes({ notesMeta }: { notesMeta: INoteMeta[] }) {
return ( return (
<div className='block'> <div className='block'>
<div className='h2'>Recent Notes</div> <div className='h2'>Recent Notes</div>
@ -14,7 +14,7 @@ function RecentNotes({ notesMeta }: { notesMeta: NoteMeta[] }) {
} }
{ {
notesMeta.length > 10 && notesMeta.length > 10 &&
<div className={''}> <div>
<Link href='/notes'> <Link href='/notes'>
<a className='h5'>More...</a> <a className='h5'>More...</a>
</Link> </Link>

View File

@ -1,9 +1,9 @@
import Link from "next/link"; import Link from "next/link";
import date from "../util/date"; import date from "../lib/date";
import { PostMeta } from "../util/slug"; import { IPostMeta } from "../lib/slug";
import style from '../styles/recent-posts.module.css'; import style from '../styles/recent-posts.module.css';
function RecentPosts({ postsMeta }: { postsMeta: PostMeta[] }) { function RecentPosts({ postsMeta }: { postsMeta: IPostMeta[] }) {
if (!postsMeta.length) if (!postsMeta.length)
return <></>; return <></>;
return ( return (
@ -13,12 +13,14 @@ function RecentPosts({ postsMeta }: { postsMeta: PostMeta[] }) {
{postsMeta?.slice(0, 10) {postsMeta?.slice(0, 10)
.map((post: any) => { .map((post: any) => {
return <div className={style.block} key={post.slug}> return <div className={style.block} key={post.slug}>
<Link href={`/posts/${post.slug}`}>
<a className={`${style.postTitle} h5`}>{post.title}</a>
</Link>
<span className={style.postDate}> <span className={style.postDate}>
{date.prettyPrint(new Date(post.created_at))} {date.toRelativeDate(new Date(post.created_at))}
</span> </span>
<div className={style.postTitle}>
<Link href={`/posts/${post.slug}`}>
{post.title}
</Link>
</div>
</div> </div>
})} })}
</div> </div>

View File

@ -1,6 +1,7 @@
import style from '../styles/title.module.css';
import Link from 'next/link'; import Link from 'next/link';
import style from '../styles/title.module.css';
type propsObj = { type propsObj = {
name: string, name: string,
title?: string, title?: string,
@ -32,7 +33,6 @@ function Title({ name, title, ancestors }: propsObj) {
{title || name} {title || name}
</h1> </h1>
</div> </div>
<div className={`${style.nav} h1`}> <div className={`${style.nav} h1`}>
{name {name
? <><Link href='/'><a>PaulW.XYZ</a></Link> / {pathElements}{name}</> ? <><Link href='/'><a>PaulW.XYZ</a></Link> / {pathElements}{name}</>

View File

@ -15,7 +15,27 @@ const months = [
const ordSfx = ['','st','nd','rd','th']; const ordSfx = ['','st','nd','rd','th'];
function prettyPrint(date: Date | string): string { function toHumanReadableDate(date: Date | string, disable?: {year?: boolean, month?: boolean, day?: boolean}) {
const oDate = (typeof date === 'string')? new Date(date): date;
const year = oDate.getFullYear();
const month = months[oDate.getMonth()];
const day = oDate.getDate();
let sfx;
if (day >= 1 && day <= 3)
sfx = ordSfx[day];
else
sfx = ordSfx[4];
let out = !disable?.day ? `${day}${sfx}` : '';
out = !disable?.month ? `${out} ${month}` : out;
out = !disable?.year ? `${out} ${year}` : out;
return out;
}
function toRelativeDate(date: Date | string): string {
const oDate = (typeof date === 'string')? new Date(date): date; const oDate = (typeof date === 'string')? new Date(date): date;
const now = new Date(); const now = new Date();
@ -23,6 +43,10 @@ function prettyPrint(date: Date | string): string {
let tdiff = Math.floor(diff/1000); let tdiff = Math.floor(diff/1000);
if (tdiff < 0) {
return toHumanReadableDate(oDate);
}
if (tdiff < 60) { if (tdiff < 60) {
return `${tdiff} seconds ago`; return `${tdiff} seconds ago`;
} }
@ -40,27 +64,17 @@ function prettyPrint(date: Date | string): string {
return `Yesterday`; return `Yesterday`;
} }
const year = oDate.getFullYear(); if (oDate.getFullYear() != now.getFullYear())
const month = months[oDate.getMonth()]; return toHumanReadableDate(oDate);
const day = oDate.getDate(); return toHumanReadableDate(oDate, {year: true});
let sfx;
if (day >= 1 && day <= 3)
sfx = ordSfx[day];
else
sfx = ordSfx[4];
if (year != now.getFullYear())
return `${day}${sfx} ${month} ${year}`;
return `${day}${sfx} ${month}`;
} }
function isValid(date: any) { function isValid(date: any) {
return (new Date(date)).toString() === 'Invalid Date'; return (new Date(date)).toString() === 'Invalid Date';
} }
const DateTool = {
const d = { toRelativeDate,
prettyPrint,
isValid isValid
}; };;
export default d; export default DateTool;

35
lib/slug.d.ts vendored Normal file
View File

@ -0,0 +1,35 @@
interface IPost {
slug: string;
rawslug: string;
content: string;
title: string;
}
interface INote {
slug: string;
rawslug: string;
content: string;
title: string;
}
interface INoteMeta {
title: string;
slug: string;
last_updated?: string;
}
interface IPostMeta {
title: string;
slug: string;
created_at: string;
last_updated?: string;
}
export function getAllPosts(filter?: Array<any>): IPost[];
export function getAllNotes(filter?: Array<any>): INote[];
export function getPost(rawslug: string, filter?: Array<any>): IPost;
export function getNote(rawslug: string, filter?: Array<any>): INote;
export function getPostsMeta(): IPostMeta[];
export function getNotesMeta(): INoteMeta[];

View File

@ -2,11 +2,15 @@ const fs = require('fs');
const matter = require('gray-matter'); const matter = require('gray-matter');
const { join } = require('path'); const { join } = require('path');
const notesDir = join(process.cwd(), 'notes');
const postsDir = join(process.cwd(), 'posts');
const cacheDir = join(process.cwd(), '.cache'); const cacheDir = join(process.cwd(), '.cache');
const postsCacheFile = join(cacheDir, 'posts.meta.json');
const notesCacheFile = join(cacheDir, 'notes.meta.json'); function getDir(name) {
return join(process.cwd(), name);
}
function getCacheFileName(name) {
return join(cacheDir, `${name}.cache.json`)
}
function get(dir, rawslug, filter = []) { function get(dir, rawslug, filter = []) {
const slug = rawslug.replace(/\.md$/, ''); const slug = rawslug.replace(/\.md$/, '');
@ -39,13 +43,14 @@ function get(dir, rawslug, filter = []) {
} }
function getAllPosts(filter = []) { function getAllPosts(filter = []) {
const files = fs.readdirSync(postsDir); const files = fs.readdirSync(getDir('posts'));
return files return files
.filter(c => (!c.match(/^\.]/) && c.match(/\.md$/))) .filter(c => (!c.match(/^\.]/) && c.match(/\.md$/)))
.map(file => { .map(file => {
return get(postsDir, file, filter) return get(getDir('posts'), file, filter)
}) })
.filter(c => (c.title && c.slug && c.created_at && (new Date(c.created_at)).toString() !== 'Invalid Date'))
.sort((a, b) => { .sort((a, b) => {
const dA = new Date(a['created_at']); const dA = new Date(a['created_at']);
const dB = new Date(b['created_at']); const dB = new Date(b['created_at']);
@ -54,13 +59,14 @@ function getAllPosts(filter = []) {
} }
function getAllNotes(filter = []) { function getAllNotes(filter = []) {
const files = fs.readdirSync(notesDir); const files = fs.readdirSync(getDir('notes'));
return files return files
.filter(c => (!c.match(/^\.]/) && c.match(/\.md$/))) .filter(c => (!c.match(/^\.]/) && c.match(/\.md$/)))
.map(file => { .map(file => {
return get(notesDir, file, filter) return get(getDir('notes'), file, filter)
}) })
.filter(c => (c.title && c.slug && c.last_updated && (new Date(c.last_updated)).toString() !== 'Invalid Date'))
.sort((a, b) => { .sort((a, b) => {
const dA = new Date(a['last_updated']); const dA = new Date(a['last_updated']);
const dB = new Date(b['last_updated']); const dB = new Date(b['last_updated']);
@ -68,69 +74,59 @@ function getAllNotes(filter = []) {
}); });
} }
function cachePostsMeta() { // public access cache const cats = {
const posts = getAllPosts(['title', 'slug', 'created_at', 'last_updated']); notes: {
name: 'notes',
getAll: getAllNotes,
filter: ['title', 'slug', 'last_updated'],
},
posts: {
name: 'posts',
getAll: getAllPosts,
filter: ['title', 'slug', 'created_at', 'last_updated'],
}
};
function cacheMeta({name, getAll, filter}) {
const items = getAll(filter);
if (!fs.existsSync(cacheDir)) { if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir); fs.mkdirSync(cacheDir);
} }
fs.writeFile(postsCacheFile, JSON.stringify(posts), (e) => { fs.writeFile(getCacheFileName(name), JSON.stringify(items), (e) => {
if (e) if (e)
console.error(e); console.error(e);
}); });
return posts; return items;
} }
function cacheNotesMeta() { function getMeta(cat) {
const notes = getAllNotes(['title', 'slug', 'last_updated']);
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir);
}
fs.writeFile(notesCacheFile, JSON.stringify(notes), (e) => {
if (e)
console.error(e);
});
return notes;
}
function getMetaFromFile(name) {
try { try {
const file = fs.readFileSync(name, 'utf-8'); const file = fs.readFileSync(getCacheFileName(cat.name), 'utf-8');
return JSON.parse(file); return JSON.parse(file);
} catch (e) { } catch (e) {
if (name) if (cat.name)
return cachePostsMeta(); return cacheMeta(cat);
} }
} }
function getPostsMeta() {
return getMeta(cats.posts);
};
function getNotesMeta() {
return getMeta(cats.notes);
};
function cache() { function cache() {
cachePostsMeta(); Object.entries(cats).map(([_, v]) => {
cacheNotesMeta(); return cacheMeta(v);
});
} }
const getPostsMeta = () => { const getPost = (s, f) => {return get(getDir('posts'), s, f)};
try { const getNote = (s, f) => {return get(getDir('notes'), s, f)};
const file = fs.readFileSync(postsCacheFile, 'utf-8');
return JSON.parse(file);
} catch (e) {
return cachePostsMeta();
}
};
const getNotesMeta = () => {
try {
const file = fs.readFileSync(notesCacheFile, 'utf-8');
return JSON.parse(file);
} catch (e) {
return cacheNotesMeta();
}
};
const getPost = (s, f) => {return get(postsDir, s, f)};
const getNote = (s, f) => {return get(notesDir, s, f)};
module.exports = { module.exports = {
getAllPosts, getAllPosts,

View File

@ -4,7 +4,7 @@ module.exports = {
defaultLocale: 'en-US' defaultLocale: 'en-US'
}, },
webpack: (config, _options) => { webpack: (config, _options) => {
const { cache } = require('./util/slug'); const { cache } = require('./lib/slug');
config.plugins.push( config.plugins.push(
{ {

View File

@ -1,17 +1,43 @@
--- ---
title: MOS 6502 Microprocessor title: MOS 6502 Microprocessor
last_updated: '2022-05-16T14:26:03-04:00' last_updated: '2022-09-29T02:41:26.738Z'
--- ---
Name | 6502 <table>
--- | --- <tr>
Introduced | 1975 <td>Name</td>
Data Width | 8-bit <td>6502</td>
Address Width | 16-bit </tr>
Endianness | Little <tr>
Registers | 8-bit A, X, Y, Stack. 16-bit PC <td>Introduced</td>
Package | 40-pin DIP <td>1975</td>
Instruction Count | 56 </tr>
<tr>
<td>Data Width</td>
<td>8-bit</td>
</tr>
<tr>
<td>Address Width</td>
<td>16-bit</td>
</tr>
<tr>
<td>Endianness</td>
<td>Little</td>
</tr>
<tr>
<td>Registers</td>
<td>8-bit A, X, Y, Stack. 16-bit PC</td>
</tr>
<tr>
<td>Package</td>
<td>40-pin DIP</td>
</tr>
<tr>
<td>Instruction Count</td>
<td> 56</td>
</tr>
</table>
## Addressing Modes ## Addressing Modes
- Implied - Implied
@ -25,7 +51,7 @@ Instruction Count | 56
- Indirect, Y - Indirect, Y
## Docs ## Docs
- [WDC W65C02S NMOS Variant](https://www.westerndesigncenter.com/wdc/documentation/w65c02s.pdf) - [westerndesigncenter.com: WDC W65C02S NMOS Variant](https://www.westerndesigncenter.com/wdc/documentation/w65c02s.pdf)
- [6502.org: collection of 6502 resources](http://6502.org/) - [6502.org: collection of 6502 resources](http://6502.org/)
## Notable Usage (includes variants) ## Notable Usage (includes variants)

20
notes/nintendo-switch.md Normal file
View File

@ -0,0 +1,20 @@
---
title: Nintendo Switch
last_updated: '2022-10-02T23:01:34.000Z'
---
<a href='https://www.nintendo.com/switch' class='link button extern blue'>Official Website</a>
<a href='https://developer.nintendo.com/' class='link button extern blue'>Developer Portal</a>
## Third-party Software
- [Atmosphère](https://github.com/Atmosphere-NX/Atmosphere)
- custom firmware
## Third-party Resources
- [DekuDeals](https://www.dekudeals.com/)
- price tracker for games with support for all major US retailers
## High-level Emulators
- [yuzu](https://yuzu-emu.org/)
- [Ryujinx](https://ryujinx.org/)

49
notes/steam-deck.md Normal file
View File

@ -0,0 +1,49 @@
---
title: Steam Deck
last_updated: '2022-09-29T03:55:40.476Z'
---
<a href='https://www.steamdeck.com/' class='link button extern blue'>Official Website</a>
## Access Console-like Youtube in Gaming Mode
- Using Chromium's undocumented command-line options, the user agent can be changed to PlayStation's, Xbox's or Tizen's (Samsung's TV OS) and the application can be launched in full screen by using the `-kiosk` flag. The following XDG Desktop Configuration, for example, can be used and added as a non-Steam game while in Desktop mode for access in gaming mode.
```ini
#!/usr/bin/env xdg-open
[Desktop]
Version=1.0
Type=Application
Name=YouTube TV
GenericName=Online Video Platform
Comment=An online video-sharing, social media platform
Exec=/usr/bin/flatpak run --branch=master --arch=x86_64 --file-forwarding org.chromium.Chrome @@ %F @@ --user-agent='Mozilla/5.0 (X11; Linux x86_64; Xbox; Xbox One; Valve Steam Gamepad)' --kiosk 'https://www.youtube.com/tv'
Terminal=false
MimeType=text/plain;
Icon=com.youtube.tv # $XDG_PATH contains the paths used to fetch icons, extensions for supported formats are optional
```
- Firefox can also be used however the supported command-line options are limited.
- The URL is https://www.youtube.com/tv
- Without the user agent change, the above URL is inaccessible.
- Adblockers like uBlock Origin, AdBlock Plus (both tested) do not remove ads unlike on the desktop site.
- Choosing the Xbox user agent is recommended as button prompts match the Steam Deck's `ABXY` button layout.
- The Electron framework can be used to build a wrapper for the URL. This is the preferrable method as it supports exiting from within the application, while browsers only support manual termination from the Steam menu. E.g. (assuming you can build native linux binaries on a device)
```javascript
const { app, BrowserWindow } = require('electron');
app.whenReady()
.then(() => {
const win = new BrowserWindow({
backgroundColor: '#2e2c29',
kiosk: true
});
win.maximize();
win.loadURL('https://youtube.com/tv');
const wc = win.webContents;
wc.userAgent = 'Mozilla/5.0 (X11; Linux x86_64; Xbox; Xbox One; Valve Steam Gamepad)'
})
.catch((e) => {
console.error(e)
});
```
## Miscellaneous
- When using a dock or a hub to connect to an external display, ensure the display supports the refresh rate set on the device as some TVs and other displays only support refresh rates that are multiples of 30Hz.

View File

@ -1,17 +1,20 @@
--- ---
title: Steam Store Client title: Steam Store
last_updated: '2022-05-16T14:20:20-04:00' last_updated: '2022-09-29T03:15:58.777Z'
--- ---
<a href='https://store.steampowered.com' class='link button extern blue'>Steam Store</a>
<a href='https://developer.valvesoftware.com/wiki/SteamCMD' class='link button extern blue'>SteamCMD</a>
## Accessing the Console ## Accessing the Console
- Use the following URLs to enable the console in the GUI client: - Use the following URIs on a browser or a file manager to open GUI client with the console:
- [steam://nav/console](steam://nav/console) - `steam://nav/console`
- [steam://open/console](steam://open/console) - `steam://open/console`
- will not work if the Steam client is running in the background - will not work if the Steam client is running in the background
- The `-console` flag can be used with the client executable. - The `-console` flag can be used with the client executable.
- Alternatively, [SteamCMD](https://developer.valvesoftware.com/wiki/SteamCMD), a command-line version of the Steam client, can be used. - Alternatively, [SteamCMD.zip](https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip), a command-line only version of the Steam client, can be used.
## Console Commands ## Downloading Older Depots
Download a single depot (used to download older versions of applications/games): Download a single depot (used to download older versions of applications/games):
``` ```
@ -24,12 +27,20 @@ download_depot <appid> <depotid> [<target manifestid>] [<delta manifestid>] [<de
- [Steam Web API Documentation](https://steamcommunity.com/dev/) - [Steam Web API Documentation](https://steamcommunity.com/dev/)
- [Steamworks Documentation](https://partner.steamgames.com/doc/home) - [Steamworks Documentation](https://partner.steamgames.com/doc/home)
- [Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Main_Page)
## Unaffiliated, Useful Sites ## Third-party Resources
- [SteamDB](https://steamdb.info/) - [SteamDB](https://steamdb.info/)
- gives a lot more insight into their platform - tracks depot changes, price history, everything steam
- [SteamGifts](https://steamgifts.com/) - [SteamGifts](https://steamgifts.com/)
- giveaway Steam keys or take part in giveaways - giveaway Steam keys or take part in giveaways
- [SteamTradeMatcher](https://steamtradematcher.com/) - [SteamTradeMatcher](https://steamtradematcher.com/)
- one-to-one trading of items on Steam - one-to-one trading of items on Steam
- [ArchiSteamFarm](https://asf.justarchi.net)
- useful bot written in C# to farm trading cards for owned games that can be sold
- [IsThereAnyDeal](https://isthereanydeal.com)
- tracks game deals for steam, steam key stores and other platforms
- somewhat broken although it is being migrated and modernized, see [New ITAD](https://new.isthereanydeal.com)
- [gg.deals](https://gg.deals)
- newer than and similar to IsThereAnyDeal with modern UI

View File

@ -1,21 +1,49 @@
--- ---
title: Zilog Z80 Microprocessor title: Zilog Z80 Microprocessor
last_updated: '2022-05-16T14:23:18-04:00' last_updated: '2022-09-29T02:41:18.085Z'
--- ---
|Name | Z80 <table>
|--- | --- <tr>
|Introduced | 1976 <td>Name</td>
|Data Width | 8-bit <td>Z80</td>
|Address Width | 16-bit </tr>
|Binary Comp. | 8080A <tr>
|Endianness | Little <td>Introduced</td>
|Registers | 208 bits (18 &times; 8-bit + 4 &times; 16-bit) - Static RAM <td>1976</td>
|Package | 40-pin DIP </tr>
|Instruction Count | 158 <tr>
<td>Data Width</td>
<td>8-bit</td>
</tr>
<tr>
<td>Address Width</td>
<td>16-bit</td>
</tr>
<tr>
<td>Binary Comp.</td>
<td>8080A</td>
</tr>
<tr>
<td>Endianness</td>
<td>Little</td>
</tr>
<tr>
<td>Registers</td>
<td>208 bits (18 &times; 8-bit + 4 &times; 16-bit) - Static RAM</td>
</tr>
<tr>
<td>Package</td>
<td>40-pin DIP</td>
</tr>
<tr>
<td>Instruction Count</td>
<td>158</td>
</tr>
</table>
## Docs ## Docs
- [User Manual](http://z80.info/zip/z80cpu_um.pdf) - [z80.info: User Manual](http://z80.info/zip/z80cpu_um.pdf)
## Addressing Modes ## Addressing Modes
- Immediate - Immediate

281
package-lock.json generated
View File

@ -14,6 +14,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-markdown": "^8.0.3", "react-markdown": "^8.0.3",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",
"rehype-raw": "^6.1.1",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"uri-js": "^4.4.1" "uri-js": "^4.4.1"
}, },
@ -2523,6 +2524,11 @@
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
"dev": true "dev": true
}, },
"node_modules/@types/parse5": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
"integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g=="
},
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@ -4489,6 +4495,71 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/hast-to-hyperscript": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-10.0.1.tgz",
"integrity": "sha512-dhIVGoKCQVewFi+vz3Vt567E4ejMppS1haBRL6TEmeLeJVB1i/FJIIg/e6s1Bwn0g5qtYojHEKvyGA+OZuyifw==",
"dependencies": {
"@types/unist": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0",
"style-to-object": "^0.3.0",
"unist-util-is": "^5.0.0",
"web-namespaces": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-from-parse5": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.0.tgz",
"integrity": "sha512-m8yhANIAccpU4K6+121KpPP55sSl9/samzQSQGpb0mTExcNh2WlvjtMwSWFhg6uqD4Rr6Nfa8N6TMypQM51rzQ==",
"dependencies": {
"@types/hast": "^2.0.0",
"@types/parse5": "^6.0.0",
"@types/unist": "^2.0.0",
"hastscript": "^7.0.0",
"property-information": "^6.0.0",
"vfile": "^5.0.0",
"vfile-location": "^4.0.0",
"web-namespaces": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.0.tgz",
"integrity": "sha512-AyjlI2pTAZEOeu7GeBPZhROx0RHBnydkQIXlhnFzDi0qfXTmGUWoCYZtomHbrdrheV4VFUlPcfJ6LMF5T6sQzg==",
"dependencies": {
"@types/hast": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-from-parse5/node_modules/hastscript": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.0.2.tgz",
"integrity": "sha512-uA8ooUY4ipaBvKcMuPehTAB/YfFLSSzCwFSwT6ltJbocFUKH/GDHLN+tflq7lSRf9H86uOuxOFkh1KgIy3Gg2g==",
"dependencies": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"hast-util-parse-selector": "^3.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-parse-selector": { "node_modules/hast-util-parse-selector": {
"version": "2.2.5", "version": "2.2.5",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
@ -4498,6 +4569,45 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/hast-util-raw": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.2.tgz",
"integrity": "sha512-0x3BhhdlBcqRIKyc095lBSDvmQNMY3Eulj2PLsT5XCyKYrxssI5yr3P4Kv/PBo1s/DMkZy2voGkMXECnFCZRLQ==",
"dependencies": {
"@types/hast": "^2.0.0",
"@types/parse5": "^6.0.0",
"hast-util-from-parse5": "^7.0.0",
"hast-util-to-parse5": "^7.0.0",
"html-void-elements": "^2.0.0",
"parse5": "^6.0.0",
"unist-util-position": "^4.0.0",
"unist-util-visit": "^4.0.0",
"vfile": "^5.0.0",
"web-namespaces": "^2.0.0",
"zwitch": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-to-parse5": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.0.0.tgz",
"integrity": "sha512-YHiS6aTaZ3N0Q3nxaY/Tj98D6kM8QX5Q8xqgg8G45zR7PvWnPGPP0vcKCgb/moIydEJ/QWczVrX0JODCVeoV7A==",
"dependencies": {
"@types/hast": "^2.0.0",
"@types/parse5": "^6.0.0",
"hast-to-hyperscript": "^10.0.0",
"property-information": "^6.0.0",
"web-namespaces": "^2.0.0",
"zwitch": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-whitespace": { "node_modules/hast-util-whitespace": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz",
@ -4561,6 +4671,15 @@
"node": "*" "node": "*"
} }
}, },
"node_modules/html-void-elements": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
"integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@ -6252,6 +6371,11 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"node_modules/path-exists": { "node_modules/path-exists": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -6603,6 +6727,20 @@
"jsesc": "bin/jsesc" "jsesc": "bin/jsesc"
} }
}, },
"node_modules/rehype-raw": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz",
"integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==",
"dependencies": {
"@types/hast": "^2.0.0",
"hast-util-raw": "^7.2.0",
"unified": "^10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark-gfm": { "node_modules/remark-gfm": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz",
@ -7389,6 +7527,19 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/vfile-location": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.0.1.tgz",
"integrity": "sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==",
"dependencies": {
"@types/unist": "^2.0.0",
"vfile": "^5.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/vfile-message": { "node_modules/vfile-message": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz",
@ -7402,6 +7553,15 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
"integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -9152,6 +9312,11 @@
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
"dev": true "dev": true
}, },
"@types/parse5": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
"integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g=="
},
"@types/prop-types": { "@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@ -10586,11 +10751,93 @@
"has-symbols": "^1.0.2" "has-symbols": "^1.0.2"
} }
}, },
"hast-to-hyperscript": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-10.0.1.tgz",
"integrity": "sha512-dhIVGoKCQVewFi+vz3Vt567E4ejMppS1haBRL6TEmeLeJVB1i/FJIIg/e6s1Bwn0g5qtYojHEKvyGA+OZuyifw==",
"requires": {
"@types/unist": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0",
"style-to-object": "^0.3.0",
"unist-util-is": "^5.0.0",
"web-namespaces": "^2.0.0"
}
},
"hast-util-from-parse5": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.0.tgz",
"integrity": "sha512-m8yhANIAccpU4K6+121KpPP55sSl9/samzQSQGpb0mTExcNh2WlvjtMwSWFhg6uqD4Rr6Nfa8N6TMypQM51rzQ==",
"requires": {
"@types/hast": "^2.0.0",
"@types/parse5": "^6.0.0",
"@types/unist": "^2.0.0",
"hastscript": "^7.0.0",
"property-information": "^6.0.0",
"vfile": "^5.0.0",
"vfile-location": "^4.0.0",
"web-namespaces": "^2.0.0"
},
"dependencies": {
"hast-util-parse-selector": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.0.tgz",
"integrity": "sha512-AyjlI2pTAZEOeu7GeBPZhROx0RHBnydkQIXlhnFzDi0qfXTmGUWoCYZtomHbrdrheV4VFUlPcfJ6LMF5T6sQzg==",
"requires": {
"@types/hast": "^2.0.0"
}
},
"hastscript": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.0.2.tgz",
"integrity": "sha512-uA8ooUY4ipaBvKcMuPehTAB/YfFLSSzCwFSwT6ltJbocFUKH/GDHLN+tflq7lSRf9H86uOuxOFkh1KgIy3Gg2g==",
"requires": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"hast-util-parse-selector": "^3.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0"
}
}
}
},
"hast-util-parse-selector": { "hast-util-parse-selector": {
"version": "2.2.5", "version": "2.2.5",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
"integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ=="
}, },
"hast-util-raw": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.2.tgz",
"integrity": "sha512-0x3BhhdlBcqRIKyc095lBSDvmQNMY3Eulj2PLsT5XCyKYrxssI5yr3P4Kv/PBo1s/DMkZy2voGkMXECnFCZRLQ==",
"requires": {
"@types/hast": "^2.0.0",
"@types/parse5": "^6.0.0",
"hast-util-from-parse5": "^7.0.0",
"hast-util-to-parse5": "^7.0.0",
"html-void-elements": "^2.0.0",
"parse5": "^6.0.0",
"unist-util-position": "^4.0.0",
"unist-util-visit": "^4.0.0",
"vfile": "^5.0.0",
"web-namespaces": "^2.0.0",
"zwitch": "^2.0.0"
}
},
"hast-util-to-parse5": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.0.0.tgz",
"integrity": "sha512-YHiS6aTaZ3N0Q3nxaY/Tj98D6kM8QX5Q8xqgg8G45zR7PvWnPGPP0vcKCgb/moIydEJ/QWczVrX0JODCVeoV7A==",
"requires": {
"@types/hast": "^2.0.0",
"@types/parse5": "^6.0.0",
"hast-to-hyperscript": "^10.0.0",
"property-information": "^6.0.0",
"web-namespaces": "^2.0.0",
"zwitch": "^2.0.0"
}
},
"hast-util-whitespace": { "hast-util-whitespace": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz",
@ -10633,6 +10880,11 @@
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="
}, },
"html-void-elements": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
"integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A=="
},
"ignore": { "ignore": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@ -11745,6 +11997,11 @@
"lines-and-columns": "^1.1.6" "lines-and-columns": "^1.1.6"
} }
}, },
"parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"path-exists": { "path-exists": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -11998,6 +12255,16 @@
} }
} }
}, },
"rehype-raw": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz",
"integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==",
"requires": {
"@types/hast": "^2.0.0",
"hast-util-raw": "^7.2.0",
"unified": "^10.0.0"
}
},
"remark-gfm": { "remark-gfm": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz",
@ -12540,6 +12807,15 @@
"vfile-message": "^3.0.0" "vfile-message": "^3.0.0"
} }
}, },
"vfile-location": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.0.1.tgz",
"integrity": "sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==",
"requires": {
"@types/unist": "^2.0.0",
"vfile": "^5.0.0"
}
},
"vfile-message": { "vfile-message": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz",
@ -12549,6 +12825,11 @@
"unist-util-stringify-position": "^3.0.0" "unist-util-stringify-position": "^3.0.0"
} }
}, },
"web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
"integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="
},
"which": { "which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -15,6 +15,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-markdown": "^8.0.3", "react-markdown": "^8.0.3",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",
"rehype-raw": "^6.1.1",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"uri-js": "^4.4.1" "uri-js": "^4.4.1"
}, },

View File

@ -17,7 +17,7 @@ function AboutPage({usr}: any) {
<p>Got any questions, concerns, or issues? Contact me via email: <code>lambdapaul [at] pm [dot] me</code>.</p> <p>Got any questions, concerns, or issues? Contact me via email: <code>lambdapaul [at] pm [dot] me</code>.</p>
</section> </section>
<section className='block'> <section className='block'>
<GitHubProfile user={usr} /> {usr && <GitHubProfile user={usr} />}
</section> </section>
<hr /> <hr />
<section className='block'> <section className='block'>
@ -39,12 +39,15 @@ function AboutPage({usr}: any) {
} }
export async function getStaticProps() { export async function getStaticProps() {
const res = await fetch('https://api.github.com/users/lambdapaul'); try {
const usr = await res.json(); const res = await fetch('https://api.github.com/users/lambdapaul');
const usr = await res.json();
return { return {
props: { usr } props: { usr }
}; };
} catch (e) {
return {props: {}}
}
} }
export default AboutPage; export default AboutPage;

View File

@ -1,16 +1,33 @@
import React from 'react'; import React from 'react';
import Link from 'next/link';
import Layout from '../components/layout'; import Layout from '../components/layout';
import QuickLinks from '../components/quick-links'; import QuickLinks from '../components/quick-links';
import RecentNotes from '../components/recent-notes'; import RecentNotes from '../components/recent-notes';
import RecentPosts from '../components/recent-posts'; import RecentPosts from '../components/recent-posts';
import { getNotesMeta, getPostsMeta, NoteMeta, PostMeta } from '../util/slug'; import { getNotesMeta, getPostsMeta, INoteMeta, IPostMeta } from '../lib/slug';
function HomePage({ postsMeta, notesMeta }: { postsMeta: PostMeta[], notesMeta: NoteMeta[] }) { function Nav() {
const nav = {'Posts': '/posts', 'Notes': '/notes', 'About': '/about', };
return (
<div className='block' style={{textAlign: 'center'}}>
{
Object.entries(nav).map(([k, v]) => {
return <Link href={v}>
<a className='button green'>{k}</a>
</Link>
})
}
</div>
)
}
function HomePage({ postsMeta, notesMeta }: { postsMeta: IPostMeta[], notesMeta: INoteMeta[] }) {
return ( return (
<Layout name='' title='PaulW.XYZ'> <Layout name='' title='PaulW.XYZ'>
<Nav />
<QuickLinks /> <QuickLinks />
<RecentPosts postsMeta={postsMeta} />
<RecentNotes notesMeta={notesMeta} /> <RecentNotes notesMeta={notesMeta} />
<RecentPosts postsMeta={postsMeta} />
</Layout> </Layout>
) )
} }

View File

@ -1,9 +1,10 @@
import Layout from '../../components/layout'; import Layout from '../../components/layout';
import { getAllNotes, getNote } from '../../util/slug'; import { getAllNotes, getNote } from '../../lib/slug';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import SyntaxHighlighter from 'react-syntax-highlighter'; import SyntaxHighlighter from 'react-syntax-highlighter';
import { monokaiSublime } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; import { monokaiSublime as hlTheme } from 'react-syntax-highlighter/dist/cjs/styles/hljs';
import remarkGfm from 'remark-gfm'; import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
function Note({ note }: any) { function Note({ note }: any) {
return (<> return (<>
@ -11,6 +12,7 @@ function Note({ note }: any) {
<section className='block'> <section className='block'>
<ReactMarkdown <ReactMarkdown
remarkPlugins={[remarkGfm]} remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw]}
components={{ components={{
code({ node, inline, className, children, ...props }) { code({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '') const match = /language-(\w+)/.exec(className || '')
@ -20,7 +22,7 @@ function Note({ note }: any) {
showLineNumbers={true} showLineNumbers={true}
language={match[1]} language={match[1]}
//@ts-ignore //@ts-ignore
style={monokaiSublime} style={hlTheme}
PreTag='div' PreTag='div'
codeTagProps={{ style: { display: 'block' } }} codeTagProps={{ style: { display: 'block' } }}
customStyle={{ padding: '0', borderRadius: '1rem' }} customStyle={{ padding: '0', borderRadius: '1rem' }}
@ -40,7 +42,7 @@ function Note({ note }: any) {
} }
export async function getStaticProps({ params }: any) { export async function getStaticProps({ params }: any) {
const note = getNote(params.page); const note = getNote(params.note);
return { return {
props: { note } props: { note }
@ -53,7 +55,7 @@ export async function getStaticPaths() {
paths: notes.map((note: any) => { paths: notes.map((note: any) => {
return { return {
params: { params: {
page: note.slug note: note.slug
} }
} }
}), }),

View File

@ -1,19 +1,28 @@
import Link from 'next/link'; import Link from 'next/link';
import Layout from '../../components/layout'; import Layout from '../../components/layout';
import { getNotesMeta, NoteMeta } from '../../util/slug'; import date from '../../lib/date';
import { getNotesMeta, INoteMeta } from '../../lib/slug';
function NotesPage({ notesMeta }: { notesMeta: NoteMeta[] }) { function NotesPage({ notesMeta }: { notesMeta: INoteMeta[] }) {
return ( return (
<Layout name='Notes'> <Layout name='Notes'>
<div className='text center block'> <table>
{notesMeta && notesMeta.map((note: NoteMeta, i) => { <tbody>
return <div key={i} className='h5'> {notesMeta && notesMeta.map((note: INoteMeta, i) => {
<Link href={`/notes/${note.slug}`}> return (
{note.title} <tr key={i}>
</Link> <td style={{flex: '1 0 50%'}}>
</div> <Link href={`/notes/${note.slug}`}>
})} {note.title}
</div> </Link>
</td>
<td style={{fontStyle: 'italic'}}>
{note.last_updated && date.toRelativeDate(new Date(note.last_updated))}
</td>
</tr>
)})}
</tbody>
</table>
</Layout> </Layout>
) )
} }

View File

@ -1,18 +1,23 @@
import Layout from '../../components/layout'; import Layout from '../../components/layout';
import { getAllPosts, getPost } from '../../util/slug'; import { getAllPosts, getPost } from '../../lib/slug';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import style from '../../styles/post.module.css'; import style from '../../styles/post.module.css';
function Post({ post }: any) { // eh function Post({ post }: any) { // eh
return (<> return (<>
<Layout name={post.title} title={post.title} ancestors={[{ name: 'Posts', path: 'posts' }]}> <Layout removeContainer={true} name={post.title} title={post.title} ancestors={[{ name: 'Posts', path: 'posts' }]}>
{post.cover {<div className={style.imageBlock}
&& <div className={style.imageBlock} style={{ backgroundImage: `url(/assets/images/${post.cover})` }}></div>} style={{ backgroundImage:
post.cover ?
`url(/assets/images/${post.cover})` :
'linear-gradient(to bottom right, #565a0f, #08432c 15%, rgb(5, 39, 10) 40%, rgb(0, 22, 46) 80%)'
}}></div>}
<div className={style.spacer}></div> <div className={style.spacer}></div>
<section className={`${style.block} block`}> <section className={`${style.block} block`}>
<ReactMarkdown>{post.content}</ReactMarkdown> <div className='container'>
<ReactMarkdown>{post.content}</ReactMarkdown>
</div>
</section> </section>
<div className={style.spacer}></div>
</Layout> </Layout>
</> </>
@ -20,7 +25,7 @@ function Post({ post }: any) { // eh
} }
export async function getStaticProps({ params }: any) { export async function getStaticProps({ params }: any) {
const post = getPost(params.page); const post = getPost(params.post);
return { return {
props: { post } props: { post }
@ -33,7 +38,7 @@ export async function getStaticPaths() {
paths: posts.map((post: any) => { paths: posts.map((post: any) => {
return { return {
params: { params: {
page: post.slug post: post.slug
} }
} }
}), }),

View File

@ -1,39 +1,39 @@
import Link from 'next/link'; import Link from 'next/link';
import Layout from '../../components/layout'; import Layout from '../../components/layout';
import date from '../../util/date'; import date from '../../lib/date';
import { getPostsMeta, PostMeta } from '../../util/slug'; import { getPostsMeta, IPostMeta } from '../../lib/slug';
function PostsPage({ postsMeta }: { postsMeta: PostMeta[] }) { function PostsPage({ postsMeta }: { postsMeta: IPostMeta[] }) {
return ( return (
<Layout name='Posts'> <Layout name='Posts'>
<table className='h5'> <table>
<thead>
<tr>
<th style={{flex: '1 0 30%'}}>Name</th>
<th>Created on</th>
<th>Last Updated</th>
</tr>
</thead>
<tbody> <tbody>
{postsMeta.map((post: PostMeta, i) => { {
return <tr key={i}> postsMeta.length &&
<td style={{flex: '1 0 30%'}}> postsMeta.map((post: IPostMeta, i) => {
<Link href={`/posts/${post.slug}`}> return <tr key={i} style={{alignItems: 'center'}}>
{post.title} <td style={{display: 'inline-block', textAlign: 'right', fontSize: '0.9rem'}}>
<div style={{fontStyle: 'italics', fontSize: '.8rem'}}>{
post.last_updated && `updated ${date.toRelativeDate(new Date(post.last_updated))}`
}</div>
<div>{ date.toRelativeDate(new Date(post.created_at)) }</div>
</td>
<td style={{
flex: '1 1 60%',
alignItems: 'center',
fontFamily: `'EB Garamond', 'Garamond', 'Times New Roman', Times, serif`}}>
<Link href={`/posts/${post.slug}`} >
<a style={{textDecoration: 'none'}}>{post.title}</a>
</Link> </Link>
</td> </td>
<td>
{date.prettyPrint(new Date(post.created_at))}
</td>
<td>
{
post.last_updated
? date.prettyPrint(new Date(post.last_updated))
: '-'
}
</td>
</tr> </tr>
})} }) ||
<div className='text center'>
<div>**crickets**</div>
<div>No posts found...</div>
<div><Link href='/'><a className='link button green back'>Go Home</a></Link></div>
</div>
}
</tbody> </tbody>
</table> </table>
</Layout> </Layout>

View File

@ -1,6 +1,4 @@
{ {
"About": "/about",
"GitHub": "https://github.com/lambdapaul", "GitHub": "https://github.com/lambdapaul",
"Twitter": "https://twitter.com/lambda_paul", "Twitter": "https://twitter.com/lambda_paul"
"Notes": "/notes"
} }

View File

@ -8,6 +8,8 @@
--primary-blue: #0a82b1; --primary-blue: #0a82b1;
--secondary-blue: #05455f; --secondary-blue: #05455f;
--tertiary-blue: #05232f; --tertiary-blue: #05232f;
--table-odd-color: rgba(255, 255, 255, 0.05);
--table-even-color: rgba(255, 255, 255, 0.025);
} }
@font-face { @font-face {
@ -98,10 +100,6 @@
box-sizing: border-box; box-sizing: border-box;
} }
body {
font-family: 'Cantarell', 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
}
article, article,
aside, aside,
figcaption, figcaption,
@ -116,7 +114,8 @@ section {
} }
body { body {
margin: 0 0 4rem; font-family: 'Cantarell', 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
margin: 0 0 44px;
font-size: 18px; font-size: 18px;
font-weight: 400; font-weight: 400;
line-height: 1.5; line-height: 1.5;
@ -125,7 +124,6 @@ body {
height: 100%; height: 100%;
background-color: var(--main-background-color); background-color: var(--main-background-color);
background-size: cover; background-size: cover;
padding-bottom: 2.5rem;
} }
[tabindex="-1"]:focus { [tabindex="-1"]:focus {
@ -208,6 +206,15 @@ pre {
overflow-x: auto; overflow-x: auto;
} }
code {
overflow-x: auto;
max-width: 100%;
display: inline-block;
background-color: rgba(255, 255, 255, 0.1);
padding: 0.1rem 0.5rem;
vertical-align: bottom;
}
pre, pre,
kbd, kbd,
code { code {
@ -220,6 +227,11 @@ table {
flex-direction: column; flex-direction: column;
margin: 1rem 0; margin: 1rem 0;
overflow: hidden; overflow: hidden;
border-radius: 0.5rem;
}
table thead+tbody tr {
border-radius: 0;
} }
table thead { table thead {
@ -227,13 +239,24 @@ table thead {
z-index: -1; z-index: -1;
} }
table tbody,
table tr:last-of-type
{
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
}
table thead tr, table thead tr,
table tbody tr { table tbody tr {
display: flex; display: flex;
} }
table tbody tr+tr { table tbody tr:nth-of-type(2n) {
border-top: 1px solid #999999; background-color: var(--table-even-color);
}
table tbody tr:nth-of-type(2n+1) {
background-color: var(--table-odd-color);
} }
table thead tr th, table thead tr th,
@ -243,6 +266,10 @@ table tbody tr td {
padding: .25rem 0.75rem; padding: .25rem 0.75rem;
} }
li {
list-style-type: square;
}
.lambda-logo { .lambda-logo {
width: 256px; width: 256px;
height: 256px; height: 256px;
@ -253,28 +280,26 @@ table tbody tr td {
} }
.container { .container {
max-width: 1018px; margin: 0 0.5rem;
margin: 0 auto;
position: relative; position: relative;
} }
@media screen and (min-width: 1018px) {
.container {
max-width: 1018px;
margin: 0 auto;
position: relative;
}
}
.block { .block {
display: block; display: block;
padding: 1.5rem; padding: 0.5rem;
max-width: 100%; max-width: 100%;
margin: 1rem 0.25rem; margin: 1rem 0.25rem;
border-radius: 1rem; border-radius: 1rem;
} }
code {
overflow-x: auto;
max-width: 100%;
display: inline-block;
background-color: rgba(255, 255, 255, 0.1);
padding: 0.1rem 0.5rem;
vertical-align: bottom;
}
.button { .button {
padding: 0.2rem 1rem; padding: 0.2rem 1rem;
margin: 0.3rem 0.3rem; margin: 0.3rem 0.3rem;
@ -323,7 +348,7 @@ code {
text-align: center; text-align: center;
} }
.no-display { .none.display {
display: none; display: none;
} }
@ -363,6 +388,14 @@ code {
display: none; display: none;
} }
.sans.serif {
font-family: 'Cantarell', 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
}
.serif {
font-family: 'EB Garamond', 'Garamond', 'Times New Roman', Times, serif;
}
.monospace { .monospace {
font-family: 'Hack', 'Source Code Pro', Consolas, monospace; font-family: 'Hack', 'Source Code Pro', Consolas, monospace;
} }

View File

@ -5,21 +5,25 @@
left: 0; left: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;
margin: 0;
padding: 0;
background-size: cover; background-size: cover;
background-position: top left; background-repeat: no-repeat;
background-position: top center;
min-height: 100%; min-height: 100%;
background-attachment: fixed; background-attachment: fixed;
} }
.block { .block {
font-family: 'EB Garamond', 'Garamond', 'Times New Roman', Times, serif; font-family: 'EB Garamond', 'Garamond', 'Times New Roman', Times, serif;
background-color: rgba(13, 17, 23, 0.95); background-color: rgba(13, 17, 23, 0.99);
margin: 0 auto; margin: 0 auto;
border-radius: 0; border-radius: 0;
font-size: 1.25rem; font-size: 1.25rem;
line-height: 2rem; line-height: 2rem;
padding: 2rem 1rem;
} }
.spacer { .spacer {
height: 5rem; height: 25rem;
} }

View File

@ -1,28 +1,63 @@
.container { .container {
border-bottom-left-radius: 1rem; border-bottom-left-radius: 0.5rem;
border-bottom: 1px dashed var(--main-border-color); border-bottom: 1px dashed var(--main-border-color);
border-left: 1px dashed var(--main-border-color); border-left: 1px dashed var(--main-border-color);
padding-top: 1.5rem; padding-top: 1.25rem;
margin-left: 0.5rem; margin-left: 0.5rem;
} }
.block { .block {
padding: 0.25rem 0.5rem; margin: 0;
margin: 0 0.5rem 0.25rem 0;
border-top: 1px dashed var(--main-border-color);
position: relative; position: relative;
display: flex; display: flex;
align-items: center; 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 { .postTitle {
flex-grow: 8; font-family: 'EB Garamond', 'Garamond', 'Times New Roman', Times, serif;
padding: 0.1rem 0.2rem; flex: 1 1 60%;
padding: .25rem 0.75rem;
}
.postTitle a {
text-decoration: none;
border: 1px dotted transparent;
transition: border-width 100ms ease-in-out;
}
.postTitle a:hover {
text-decoration: none;
border-bottom: 1px dotted var(--link-color);
}
.postTitle a:focus {
text-decoration: none;
border: 1px dotted var(--link-color);
} }
.postDate { .postDate {
flex: 1 1;
display: inline-block;
text-align: right;
font-style: italic; font-style: italic;
font-size: 0.95rem; font-size: 0.9rem;
padding: .25rem 0.50rem;
} }
.more { .more {

View File

@ -11,15 +11,20 @@
} }
.nav { .nav {
white-space: pre-wrap;
padding: 0.25rem 0.75rem; padding: 0.25rem 0.75rem;
font-size: 1.5rem; font-size: 1.5rem;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4); box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4);
position: fixed; position: fixed;
bottom: 0; bottom: 0;
z-index: 1000; z-index: 1000;
left: 0;
right: 0;
margin: 0; margin: 0;
height: 2.75rem;
max-height: 2.75rem;
min-height: 2.75rem;
min-width: 100%;
width: 100%;
background: linear-gradient(to bottom right, #1a3a15, #09351b) no-repeat center center fixed; background: linear-gradient(to bottom right, #1a3a15, #09351b) no-repeat center center fixed;
overflow-y: hidden;
overflow-x: auto;
white-space: nowrap;
} }

View File

@ -24,7 +24,7 @@
"next-env.d.ts", "next-env.d.ts",
"**/*.ts", "**/*.ts",
"**/*.tsx", "**/*.tsx",
"util/slug.js" "lib/slug.js"
], ],
"exclude": [ "exclude": [
"node_modules" "node_modules"

35
util/slug.d.ts vendored
View File

@ -1,35 +0,0 @@
interface Post {
slug?: string;
rawslug?: string;
content?: string;
title?: string;
}
interface Note {
slug?: string;
rawslug?: string;
content?: string;
title?: string;
}
interface NoteMeta {
title: string;
slug: string;
last_updated: string;
}
interface PostMeta {
title: string;
slug: string;
created_at: string;
last_updated: string;
}
export function getAllPosts(filter?: Array<any>): Post[];
export function getAllNotes(filter?: Array<any>): Note[];
export function getPost(rawslug: string, filter?: Array<any>): Post;
export function getNote(rawslug: string, filter?: Array<any>): Note;
export function getPostsMeta(): PostMeta[];
export function getNotesMeta(): NoteMeta[];