diff --git a/bun.lockb b/bun.lockb index 7f58294..d24d82a 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/container.tsx b/components/container.tsx index c55c1ae..39e3af7 100644 --- a/components/container.tsx +++ b/components/container.tsx @@ -1,4 +1,6 @@ -export type ChildrenType = JSX.Element | Array; +import { JSX } from "react"; + +export type ChildrenType = JSX.Element| Array; function Container(props: { children?: ChildrenType, ignore?: boolean }) { if (props.ignore) diff --git a/components/title.tsx b/components/title.tsx index 9887cdc..3c93564 100644 --- a/components/title.tsx +++ b/components/title.tsx @@ -1,20 +1,21 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; +import { Fragment } from 'react'; import style from '../styles/title.module.css'; import SiteMap from '../public/sitemap.json'; import Head from 'next/head'; -import { SiteSubPages } from '../lib/site'; +import { Sites } from '../lib/site'; function createPathElements(ancestors: Array<{ name: string, path: string }>) { let currentPath = ''; return ancestors.map((ancestor, id) => { currentPath += `/${ancestor.path}` return ( - <> - {ancestor.name} + + {ancestor.name} <> / - + ); }); } @@ -25,7 +26,8 @@ function Title() { const pagePath = router.asPath; const splitPath: Array<{ name: string, path: string }> = []; - let currRoot: SiteSubPages = SiteMap.subpages; + // TODO(Paul): clean this up + let currRoot: Sites = SiteMap.pages; let title: string | null = null; if (pagePath !== '/') { const subPaths = pagePath.split('?')[0].split('#')[0].split('/'); @@ -36,9 +38,9 @@ function Title() { if (currRoot === undefined || currRoot[p] === undefined - || currRoot[p].subpages === undefined) + || currRoot[p].pages === undefined) break; - currRoot = currRoot[p].subpages!; + currRoot = currRoot[p].pages!; } if (splitPath !== undefined && splitPath.length > 0) title = splitPath.pop()!.name; diff --git a/lib/site.ts b/lib/site.ts index 9bb3e41..9dc0c87 100644 --- a/lib/site.ts +++ b/lib/site.ts @@ -1,11 +1,11 @@ export interface Site { title: string; - subpages?: SiteSubPages; + pages?: Sites; mtime?: string; otime?: string; } -export interface SiteSubPages { +export interface Sites { [slug: string]: Site; } diff --git a/next-env.d.ts b/next-env.d.ts index 4f11a03..a4a7b3f 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/next.config.js b/next.config.ts similarity index 59% rename from next.config.js rename to next.config.ts index d4341cc..821f2bd 100644 --- a/next.config.js +++ b/next.config.ts @@ -1,14 +1,18 @@ -const config = { +import type {NextConfig } from 'next'; +import NextBundleAnalyzer from '@next/bundle-analyzer'; + +let config: NextConfig = { + reactStrictMode: true, i18n: { locales: ['en-US'], defaultLocale: 'en-US' }, + // not sure why this breaks prod build in the latest version + // aah it's so frustrating to deal with an warning log that + // shows up regardless of the config but its presence halts + // the entire thing. webpack: (config, _options) => { config.module.rules.push( - { - test: /\.ya?ml$/, - use: 'js-yaml-loader', - }, { test: /\.svg$/, use: [{ loader: '@svgr/webpack' }], @@ -25,10 +29,6 @@ const config = { test: /\.txt$/, type: 'asset/source', }, - { - resourceQuery: /raw/, - type: 'asset/source', - }, ); return config; @@ -36,10 +36,9 @@ const config = { }; if (process.env.ANALYZE) { - const bundleAnalyzer = require('@next/bundle-analyzer')({ + config = NextBundleAnalyzer({ enabled: true - }); - module.exports = bundleAnalyzer(config); -} else { - module.exports = config; + })(config); } + +export default config; diff --git a/notes/lua.md b/notes/lua.md index 092c7ee..419c0cf 100644 --- a/notes/lua.md +++ b/notes/lua.md @@ -1,15 +1,11 @@ # Lua Programming Language - -## Lua 5.4 C API - + ## Lua 5.4 Bytecode -> [!note] > These are **unstable** and may differ in different versions of the language. > They are not part of the language specification but an implementation detail, which in this case is the reference implementation. -> [!note] > The reference implementation used to have a stack based but now uses a register based VM similar to how modern real computer architectures. The instructions are 32 bits wide; every instruction has an opcode that takes up 7 bits, which leaves out 25 bits for the addresses and values. diff --git a/notes/os.md b/notes/os.md index 3b8b842..c188aa4 100644 --- a/notes/os.md +++ b/notes/os.md @@ -33,8 +33,8 @@ Open it by exceuting the following command or saving it as a shortcut: `explorer ### Video Players -- IINA +- [IINA](https://iina.io/) - video player based on mpv with native macOS UI -- mpv +- [mpv](https://mpv.io/) - mpv doesn't have a brew cask for Apple silicon; stolen-mpv exists but it is x86 only - mpv brew formula is the cli tool which works pretty well but it is not as nice as packaged applications diff --git a/notes/programming-resources.md b/notes/programming-resources.md index de40fa6..2c58795 100644 --- a/notes/programming-resources.md +++ b/notes/programming-resources.md @@ -61,3 +61,8 @@ Semi-paywalled ## UTF-8 Everywhere - http://utf8everywhere.org + +## Parsing Gigabytes of JSON per Second + +- https://arxiv.org/abs/1902.08318 [[PDF](https://arxiv.org/pdf/1902.08318)] + diff --git a/notes/steam-deck.md b/notes/steam-deck.md index 4014c41..4aebab5 100644 --- a/notes/steam-deck.md +++ b/notes/steam-deck.md @@ -17,7 +17,7 @@ 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 -```cfg +```ini #!/usr/bin/env xdg-open [Desktop] Version=1.0 @@ -27,7 +27,8 @@ 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 (Windows NT 10.0; Win64; x64; Xbox; Xbox Series X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36 Edge/20.02' --kiosk 'https://www.youtube.com/tv' Terminal=false -MimeType=text/plain; # $XDG_PATH contains the paths used to fetch icons, extensions for supported formats are optional Icon=com.youtube.tv +MimeType=text/plain; +# $XDG_PATH contains the paths used to fetch icons, extensions for supported formats are optional Icon=com.youtube.tv ``` - Firefox can also be used however the supported command-line options are diff --git a/notes/steam.md b/notes/steam.md index 4f895c3..de491e3 100644 --- a/notes/steam.md +++ b/notes/steam.md @@ -14,11 +14,11 @@ - Alternatively, SteamCMD, a command-line only version of the Steam client, can be used - [Windows - Binary](https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip) + Binary (.zip)](https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip) - [Linux - Binary](https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz) + Binary (.zip)](https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz) - [macOS - Binary](https://steamcdn-a.akamaihd.net/client/installer/steamcmd_osx.tar.gz) + Binary (.zip)](https://steamcdn-a.akamaihd.net/client/installer/steamcmd_osx.tar.gz) ## Downloading Older Depots @@ -51,4 +51,7 @@ values. - useful bot written in C# to farm trading cards for owned games that can be sold - [SteamGridDB](https://steamgriddb.com/) - - custom video game assets for games available and not available on steam + - custom video game assets for games available and not available on Steam +- [ProtonDB](https://www.protondb.com/) + - community-sourced Linux compatibility tracker + diff --git a/package.json b/package.json index fa74c03..8c074d0 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "private": true, "scripts": { "dev": "next dev", "build": "next build", @@ -7,28 +8,32 @@ }, "dependencies": { "dotenv": "^16.3.1", - "js-yaml-loader": "^1.2.2", - "next": "^13.5.1", + "highlight.js": "^11.10.0", + "next": "^15.0.4", "normalize.css": "^8.0.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-markdown": "^9.0.0", - "react-syntax-highlighter": "^15.5.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-markdown": "^9.0.1", + "rehype-autolink-headings": "^7.1.0", + "rehype-highlight": "^7.0.0", + "rehype-highlight-code-lines": "^1.0.4", + "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", + "rehype-slug": "^6.0.0", "remark-gfm": "^4.0.0", - "remark-github-admonitions-to-directives": "^2.0.0", + "remark-loader": "^6.0.0", + "remark-math": "^6.0.0", "uri-js": "^4.4.1" }, "devDependencies": { - "@next/bundle-analyzer": "^14.0.1", - "@svgr/webpack": "^6.5.1", - "@types/node": "^18.17.17", - "@types/react": "^18.2.22", - "@types/react-dom": "^18.2.7", + "@next/bundle-analyzer": "^15.0.4", + "@svgr/webpack": "^8.1.0", + "@types/node": "^22.7.4", + "@types/react": "^19.0.1", + "@types/react-dom": "^19.0.1", "@types/react-syntax-highlighter": "^15.5.7", - "eslint": "^8.49.0", - "eslint-config-next": "^13.5.1", - "typescript": "^4.9.5" + "eslint": "^9.11.1", + "eslint-config-next": "^15.0.4", + "typescript": "^5.6.2" } } diff --git a/pages/404.tsx b/pages/404.tsx index 8f285c9..a6024b1 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -4,34 +4,34 @@ import Link from 'next/link'; import style from '../styles/title.module.css'; function NotFoundPage() { - // clean this page up - return ( - <> - - 404: Not Found | PaulW.XYZ - -
-

- Page Not Found -

-
-
- PaulW.XYZ / ... ??? / 404: Not Found
-
-
-

Error 404

-

- Uh oh! The page you are looking for does not exist...
-

- Go Home - - More on HTTP status codes - -
-
- + // clean this page up + return ( + <> + + 404: Not Found | PaulW.XYZ + +
+

+ Page Not Found +

+
+
+ PaulW.XYZ / ... ??? / 404: Not Found
+
+
+

Error 404

+

+ Uh oh! The page you are looking for does not exist...
+

+ Go Home + + More on HTTP status codes + +
+
+ - ); + ); } export default NotFoundPage; diff --git a/pages/_document.tsx b/pages/_document.tsx new file mode 100644 index 0000000..b2fff8b --- /dev/null +++ b/pages/_document.tsx @@ -0,0 +1,13 @@ +import { Html, Head, Main, NextScript } from "next/document"; + +export default function Document() { + return ( + + + +
+ + + + ); +} diff --git a/pages/about.tsx b/pages/about.tsx index 05f64fa..5ab9214 100644 --- a/pages/about.tsx +++ b/pages/about.tsx @@ -5,35 +5,35 @@ import License from '../LICENSE.txt'; import Layout from '../components/layout'; function AboutPage() { - return ( - -
-

Paul's Personal Website. I go by @LambdaPaul on GitHub and @lambda_paul on X/Twitter.

-

I also have a Gitea server at git.paulw.xyz and a Pleroma (ActivityPub/Mastodon-compatible) server at social.paulw.xyz as back-ups for my GitHub and X/Twitter.

-

Why did I create this? Why do I have the back-ups?

-

- The original motivation was to just play with Next.js as it pretty much did the things I wanted web pages to do. But it came at the cost of needless complexity. As I use the JavaScript/ECMAScript/Whatever-you-want-to-call-it-script more and more, I am convinced that it is not a platform worth pursuing because the more complex it gets, the less control I have over what it does and this platform and its users seems to be okay with that sort of loss. I have been instead pivoting toward things that impressed and got me interested in working with computers.

-

Most services/products are keen on going against what Steph Ango calls File over app, a philosophy in which you prioritize data over software, and anticipate and embrace the eventual death of software. People instead want subscription services that barely support open formats and sometimes do not support exporting data to commonly used formats. The goal here is to avoid storing artifacts under locations that are easily not accessible, not under my control, and does not lock me out of using it with other software. The only reason I have not completely abandoned this is thanks to my decision to rely on Markdown files alone. Had it been reliant on any cloud software, I would have started over.

+ return ( + +
+

Paul's Personal Website. I go by @LambdaPaul on GitHub and @lambda_paul on X/Twitter.

+

I also have a Gitea server at git.paulw.xyz and a Pleroma (ActivityPub/Mastodon-compatible) server at social.paulw.xyz as back-ups for my GitHub and X/Twitter.

+

Why did I create this? Why do I have the back-ups?

+

+ The original motivation was to just play with Next.js as it pretty much did the things I wanted web pages to do. But it came at the cost of needless complexity. As I use the JavaScript/ECMAScript/Whatever-you-want-to-call-it-script more and more, I am convinced that it is not a platform worth pursuing because the more complex it gets, the less control I have over what it does and this platform and its users seems to be okay with that sort of loss. I have been instead pivoting toward things that impressed and got me interested in working with computers.

+

Most services/products are keen on going against what Steph Ango calls File over app, a philosophy in which you prioritize data over software, and anticipate and embrace the eventual death of software. People instead want subscription services that barely support open formats and sometimes do not support exporting data to commonly used formats. The goal here is to avoid storing artifacts under locations that are easily not accessible, not under my control, and does not lock me out of using it with other software. The only reason I have not completely abandoned this is thanks to my decision to rely on Markdown files alone. Had it been reliant on any cloud software, I would have started over.

-

Got any questions, concerns, or issues? Contact me via email: contact [at] paulw [dot] xyz.

-
-
-
-

Source for this site is available on GitHub: github.com/LambdaPaul/www and git.paulw.xyz/LambdaPaul/www

-

Relevant information regarding the source is available on the repo and is also provided below.

-
-
-

README

- - {ReadmeMd.replace(/^#{1,5} /g, (s: string) => { return `#${s}` })} - -
-
-

LICENSE

-
{License}
-
-
- ); +

Got any questions, concerns, or issues? Contact me via email: contact [at] paulw [dot] xyz.

+
+
+
+

Source for this site is available on GitHub: github.com/LambdaPaul/www and git.paulw.xyz/LambdaPaul/www

+

Relevant information regarding the source is available on the repo and is also provided below.

+
+
+

README

+ + {ReadmeMd.replace(/^#{1,5} /g, (s: string) => { return `#${s}` })} + +
+
+

LICENSE

+
{License}
+
+
+ ); } export default AboutPage; diff --git a/pages/notes/[note].tsx b/pages/notes/[note].tsx index 6baa914..d797205 100644 --- a/pages/notes/[note].tsx +++ b/pages/notes/[note].tsx @@ -1,10 +1,15 @@ import ReactMarkdown from 'react-markdown'; -import SyntaxHighlighter from 'react-syntax-highlighter'; -import { monokaiSublime as hlTheme } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; +import { PluggableList } from 'unified'; + import remarkGfm from 'remark-gfm'; +import remarkMath from 'remark-math'; + +import rehypeKatex from 'rehype-katex'; import rehypeRaw from 'rehype-raw'; -import remarkDirective from 'remark-directive'; -import remarkGithubAdmonitionsToDirectives from 'remark-github-admonitions-to-directives'; +import rehypeSlug from 'rehype-slug'; +import rehypeAutolinkHeadings from 'rehype-autolink-headings'; +import rehypeHighlight from 'rehype-highlight'; +import rehypeHighlightCodeLines, { type HighlightLinesOptions } from 'rehype-highlight-code-lines'; import Layout from '../../components/layout'; import readMarkdown from '../../lib/read-markdown'; @@ -12,86 +17,76 @@ import { toLocaleString } from '../../lib/date'; import NotesInfo from '../../public/notes.json'; import style from '../../styles/note.module.css'; +import 'highlight.js/styles/monokai-sublime.css'; +import 'katex/dist/katex.min.css'; interface Note { - title: string, - mtime: string, - content?: string, + title: string, + mtime: string, + content?: string, } interface Notes { - [slug: string]: Note; + [slug: string]: Note; } function Markdown({ content }: any) { - return {String(children).replace(/\n$/, '')} - ) - : - {children} - - } - }} - >{content} + const remarkPlugins: PluggableList = [ + remarkGfm, + remarkMath, + ]; + const rehypePlugins: PluggableList = [ + rehypeSlug, + rehypeAutolinkHeadings, + rehypeRaw, + rehypeHighlight, + rehypeKatex, + ]; + return + {content} + } -function Note({ note }: { note: Note } ) { - return (<> - - - Last updated: {toLocaleString(note.mtime)} - -
- -
-
- - ); +function Note({ note }: { note: Note }) { + return (<> + + + Last updated: {toLocaleString(note.mtime)} + +
+ +
+
+ + ); } export async function getStaticProps({ params }: { params: { note: string } }) { - const note: string = params.note; - const notesInfo: Notes = NotesInfo; - const noteInfo: Note = notesInfo[note]; + const note: string = params.note; + const notesInfo: Notes = NotesInfo; + const noteInfo: Note = notesInfo[note]; - return { - props: { - note: { - ...noteInfo, - content: await readMarkdown('notes', note, true) - } - } - } + return { + props: { + note: { + ...noteInfo, + content: await readMarkdown('notes', note, true) + } + } + } } export async function getStaticPaths() { - return { - paths: Object.keys(NotesInfo).map((note: string) => { - return { - params: { - note - } - } - }), - fallback: false - }; + return { + paths: Object.keys(NotesInfo).map((note: string) => { + return { + params: { + note + } + } + }), + fallback: false + }; } - export default Note; diff --git a/pages/notes/index.tsx b/pages/notes/index.tsx index 1cee385..b1ef7e8 100644 --- a/pages/notes/index.tsx +++ b/pages/notes/index.tsx @@ -6,52 +6,52 @@ import { toRelativeDate } from '../../lib/date'; import NotesInfo from '../../public/notes.json'; function NoteEntry({ note }: { note: { title: string, mtime: string, slug: string } }) { - return ( - - - - {note.title} - - - - {note.mtime && toRelativeDate(note.mtime)} - - - ); + return ( + + + + {note.title} + + + + {note.mtime && toRelativeDate(note.mtime)} + + + ); } function NotesPage() { - 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(); - } - ); + 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 ( - - { - !notes || notes.length === 0 - && <>No notes found - || - - {notes.map( - (note: any) => { - return (); - } - )} - -
- } -
- ) + return ( + + { + !notes || notes.length === 0 + && <>No notes found + || + + {notes.map( + (note: any) => { + return (); + } + )} + +
+ } +
+ ) } diff --git a/pages/posts/[post].tsx b/pages/posts/[post].tsx index 73df8c1..c93cf04 100644 --- a/pages/posts/[post].tsx +++ b/pages/posts/[post].tsx @@ -3,102 +3,113 @@ import ReactMarkdown from 'react-markdown'; import style from '../../styles/post.module.css'; import PostsInfo from '../../public/posts.json'; import readMarkdown from '../../lib/read-markdown'; -import DateTool from '../../lib/date'; +import DateTool, { toLocaleString } from '../../lib/date'; -interface Post { - title: string; - mtime: string; - otime?: string; +interface IPost { + title: string; + mtime: string; + otime?: string; } -interface Posts { - [slug: string]: Post +interface IPosts { + [slug: string]: IPost } function TimeBlock({ mtime, otime }: { mtime: string, otime: string }) { - const ampm = (h: number) => { if (h >= 12) return 'p.m.'; return 'a.m.'; }; + const ampm = (h: number) => { if (h >= 12) return 'p.m.'; return 'a.m.'; }; - const mdate = new Date(mtime); - const odate = new Date(otime); + const mdate = new Date(mtime); + const odate = new Date(otime); - const format = (date: Date) => { - const day = date.getDay(); - const ord = {DateTool.getOrdinalDaySuffix(date.getDay())}; - const month = DateTool.getFullMonth(date.getMonth()); - const year = date.getFullYear(); - const hours = date.getHours() > 12 ? date.getHours() - 12 : date.getHours(); - const minPrefix = date.getMinutes() < 10 ? '0' : ''; - const minutes = date.getMinutes(); - const twelveSfx = ampm(date.getHours()); - return <>{day}{ord} {month} {year} at {hours}:{minPrefix}{minutes} {twelveSfx} - }; + const format = (date: Date) => { + const day = date.getDay(); + const ord = {DateTool.getOrdinalDaySuffix(date.getDay())}; + const month = DateTool.getFullMonth(date.getMonth()); + const year = date.getFullYear(); + const hours = date.getHours() > 12 ? date.getHours() - 12 : date.getHours(); + const minPrefix = date.getMinutes() < 10 ? '0' : ''; + const minutes = date.getMinutes(); + const twelveSfx = ampm(date.getHours()); + return <>{day}{ord} {month} {year} at {hours}:{minPrefix}{minutes} {twelveSfx} + }; - return ( -
- { - mtime ? -
- Last updated: {format(mdate)} -
- : - <> - } -
- {format(odate)} -
-
- ); + return ( +
+ { + mtime ? +
+ Last updated: {format(mdate)} +
+ : + <> + } +
+ {format(odate)} +
+
+ ); } -function Post({ post }: { post: Post & { content: string, cover?: string, otime: string, mtime?: string } }) { - return (<> - - {
} -
-
-
- - {post.content} -
-
-
-
+function Post({ post }: { post: IPost & { content: string, cover?: string, otime: string, mtime?: string } }) { + if (!post) + return <>; + return (<> + +
+ { post.otime !== post.mtime && + + Last updated: {toLocaleString(post.mtime)} + + } + + {toLocaleString(post.otime)} + +
+ {
} +
+
+
+ {post.content} +
+
+
+
- - ); + + ); } export async function getStaticProps({ params }: any) { - const postsInfo: Posts = PostsInfo; - const post: Post = postsInfo[params.post]; - return { - props: { - post: { - ...post, - content: await readMarkdown('posts', params.post, true) - } - } - } + const postsInfo: IPosts = PostsInfo; + const post: IPost = postsInfo[params.post]; + return { + props: { + post: { + ...post, + content: await readMarkdown('posts', params.post, true) + } + } + } } export async function getStaticPaths() { - return { - paths: Object.keys(PostsInfo).map((post: string) => { - return { - params: { - post - } - } - }), - fallback: false - }; + return { + paths: Object.keys(PostsInfo).map((post: string) => { + return { + params: { + post + } + } + }), + fallback: false + }; } diff --git a/pages/posts/index.tsx b/pages/posts/index.tsx index 82365bd..e16a99b 100644 --- a/pages/posts/index.tsx +++ b/pages/posts/index.tsx @@ -4,49 +4,47 @@ import date from '../../lib/date'; import PostsInfo from '../../public/posts.json'; function PostsPage() { - return ( - - {Object.keys(PostsInfo).length && || } - - ) + return ( + + {Object.keys(PostsInfo).length && || } + + ) } function NoPosts() { - return (<>
-
**crickets**
-
No posts found...
-
Go Home
-
); + return (
+
**crickets**
+
No posts found...
+
Go Home
+
); } function Posts() { - const posts = Object.entries(PostsInfo); - return ( - <> - - - { - posts.map(([slug, post]: [string, any]) => { - return - - - - })} - -
-
{ - post.mtime && (post.mtime != post.otime) && `Updated ${date.toRelativeDate(new Date(post.mtime))}` - }
-
{date.toRelativeDate(new Date(post.otime))}
-
- {post.title} -
- - ) + const posts = Object.entries(PostsInfo); + return ( + + + { + posts.map(([slug, post]: [string, any]) => { + return ( + + + ) + }) + } + +
+
{ + post.mtime && (post.mtime != post.otime) && `Updated ${date.toRelativeDate(new Date(post.mtime))}` + }
+
{date.toRelativeDate(new Date(post.otime))}
+
+ {post.title} +
+ ) } diff --git a/pages/sitemap.tsx b/pages/sitemap.tsx index 795d225..47e59b2 100644 --- a/pages/sitemap.tsx +++ b/pages/sitemap.tsx @@ -1,46 +1,41 @@ import Link from 'next/link'; import Layout from '../components/layout'; -import { Site } from '../lib/site'; +import { Sites } from '../lib/site'; import SiteMap from '../public/sitemap.json'; -function traverseMap(head: Site, cwd = '', depth = 0) { - if (head.subpages === undefined) - return []; - let elements = []; - for (const [slug, info] of Object.entries(head.subpages)) { - if (slug === 'sitemap') - continue; - if (slug.startsWith('http://')) { - elements.push(<> -
{info.title}
-
{slug.substring(7)}
- ); - } - else if (slug.startsWith('https://')) { - elements.push(<> -
{info.title}
-
{slug.substring(8)}
- ); - } - else { - const path = `${cwd}/${slug}`; - const children = (<>
{traverseMap(info, path, depth + 1)}
); - elements.push(<> -
{info.title}
-
paulw.xyz{path}
- {children} - ); - } - } - return elements; +function Desc(props: any) { + return ( +
+
{props.term}
+
{props.details}
+ {props.children} +
+ ); +} + +function traverseMap(head?: Sites, cwd = '', depth = 0) { + if (!head) return []; + let elements = []; + for (const [slug, site] of Object.entries(head)) { + if (slug === 'sitemap') + continue; + + let details; + let list; + + const path = `${cwd}/${slug}`; + details = paulw.xyz{path}; + list = traverseMap(site.pages, path, depth + 1); + + elements.push({list}) + } + return elements; } function SiteMapPage() { - - - return -
{traverseMap(SiteMap)}
-
; + return + {traverseMap(SiteMap.pages)} + ; } export default SiteMapPage; diff --git a/public/home.json b/public/home.json index b294552..fb91a0f 100644 --- a/public/home.json +++ b/public/home.json @@ -1,20 +1,14 @@ { - "posts": { - "title": "Posts" - }, - "notes": { - "title": "Notes" - }, - "about": { - "title": "About" - }, - "sitemap": { - "title": "Site Map" - }, - "https://git.paulw.xyz": { - "title": "Git.PaulW.XYZ" - }, - "https://social.paulw.xyz": { - "title": "Social.PaulW.XYZ" - } + "posts": { + "title": "Posts" + }, + "notes": { + "title": "Notes" + }, + "about": { + "title": "About" + }, + "sitemap": { + "title": "Site Map" + } } diff --git a/public/notes.json b/public/notes.json index 659a3aa..27c014e 100644 --- a/public/notes.json +++ b/public/notes.json @@ -1 +1 @@ -{"mos-6502":{"title":"MOS 6502 Microprocessor","mtime":"2023-10-29T18:05:52.439Z"},"browsers":{"title":"Web Browsers","mtime":"2024-09-13T08:47:57.942Z"},"zilog-z80":{"title":"Zilog Z80 Microprocessor","mtime":"2023-10-29T18:07:08.579Z"},"steam":{"title":"Steam Client","mtime":"2024-10-10T04:56:04.393Z"},"programming-resources":{"title":"Programming Resources","mtime":"2024-10-10T05:04:27.709Z"},"steam-deck":{"title":"Steam Deck","mtime":"2024-10-10T05:19:16.140Z"},"lua":{"title":"Lua Programming Language","mtime":"2024-09-13T08:45:18.515Z"},"os":{"title":"Operating Systems","mtime":"2024-05-10T16:07:32.581Z"}} \ No newline at end of file +{"mos-6502":{"title":"MOS 6502 Microprocessor","mtime":"2023-10-29T18:05:52.439Z"},"zilog-z80":{"title":"Zilog Z80 Microprocessor","mtime":"2023-10-29T18:07:08.579Z"},"browsers":{"title":"Web Browsers","mtime":"2024-09-13T08:47:57.942Z"},"steam":{"title":"Steam Client","mtime":"2024-12-28T17:07:10.689Z"},"lua":{"title":"Lua Programming Language","mtime":"2024-12-28T17:00:55.719Z"},"os":{"title":"Operating Systems","mtime":"2024-12-06T18:53:52.620Z"},"steam-deck":{"title":"Steam Deck","mtime":"2024-12-28T17:10:01.709Z"},"programming-resources":{"title":"Programming Resources","mtime":"2024-12-06T19:02:37.710Z"}} \ No newline at end of file diff --git a/public/sitemap.json b/public/sitemap.json index 4210144..4158a9d 100644 --- a/public/sitemap.json +++ b/public/sitemap.json @@ -1 +1 @@ -{"title":"PaulW.XYZ","subpages":{"posts":{"title":"Posts","subpages":{}},"notes":{"title":"Notes","subpages":{"mos-6502":{"title":"MOS 6502 Microprocessor","mtime":"2023-10-29T18:05:52.439Z"},"browsers":{"title":"Web Browsers","mtime":"2024-09-13T08:47:57.942Z"},"zilog-z80":{"title":"Zilog Z80 Microprocessor","mtime":"2023-10-29T18:07:08.579Z"},"steam":{"title":"Steam Client","mtime":"2024-10-10T04:56:04.393Z"},"programming-resources":{"title":"Programming Resources","mtime":"2024-10-10T05:04:27.709Z"},"steam-deck":{"title":"Steam Deck","mtime":"2024-10-10T05:19:16.140Z"},"lua":{"title":"Lua Programming Language","mtime":"2024-09-13T08:45:18.515Z"},"os":{"title":"Operating Systems","mtime":"2024-05-10T16:07:32.581Z"}}},"about":{"title":"About"},"sitemap":{"title":"Site Map"},"https://git.paulw.xyz":{"title":"Git.PaulW.XYZ"},"https://social.paulw.xyz":{"title":"Social.PaulW.XYZ"}}} \ No newline at end of file +{"title":"PaulW.XYZ","pages":{"posts":{"title":"Posts","pages":{}},"notes":{"title":"Notes","pages":{"mos-6502":{"title":"MOS 6502 Microprocessor","mtime":"2023-10-29T18:05:52.439Z"},"zilog-z80":{"title":"Zilog Z80 Microprocessor","mtime":"2023-10-29T18:07:08.579Z"},"browsers":{"title":"Web Browsers","mtime":"2024-09-13T08:47:57.942Z"},"steam":{"title":"Steam Client","mtime":"2024-12-28T17:07:10.689Z"},"lua":{"title":"Lua Programming Language","mtime":"2024-12-28T17:00:55.719Z"},"os":{"title":"Operating Systems","mtime":"2024-12-06T18:53:52.620Z"},"steam-deck":{"title":"Steam Deck","mtime":"2024-12-28T17:10:01.709Z"},"programming-resources":{"title":"Programming Resources","mtime":"2024-12-06T19:02:37.710Z"}}},"about":{"title":"About"},"sitemap":{"title":"Site Map"}}} \ No newline at end of file diff --git a/scripts/generate-metadata.js b/scripts/generate-metadata.js index 7c5f286..5163118 100644 --- a/scripts/generate-metadata.js +++ b/scripts/generate-metadata.js @@ -122,12 +122,12 @@ async function generateSiteMap() { const sitemap = { title: 'PaulW.XYZ', - subpages: await readFilesMetadata('home') + pages: await readFilesMetadata('home') }; const pages = ['posts', 'notes']; for (const page of pages) { - sitemap.subpages[page].subpages = await readFilesMetadata(page); + sitemap.pages[page].pages = await readFilesMetadata(page); } await writeFilesMetadata(jsonFilePath('sitemap'), sitemap); diff --git a/shims.d.ts b/shims.d.ts index c98f9b1..5feba8e 100644 --- a/shims.d.ts +++ b/shims.d.ts @@ -1,8 +1,3 @@ -declare module '*.yaml' { - const record: Record; - export default record; -} - declare module '*.md' { const rawmd: string; export default rawmd; @@ -11,4 +6,4 @@ declare module '*.md' { declare module '*.txt' { const content: string; export default content; -} \ No newline at end of file +} diff --git a/styles/global.css b/styles/global.css index 25637bc..e052f11 100644 --- a/styles/global.css +++ b/styles/global.css @@ -235,9 +235,8 @@ code { } table { - display: flex; - flex-direction: column; - margin: 1rem 0; + margin: 1rem auto; + width:100%; overflow: hidden; border-radius: 0.5rem; } @@ -258,11 +257,6 @@ table tr:last-of-type border-bottom-right-radius: 0.5rem; } -table thead tr, -table tbody tr { - display: flex; -} - table tbody tr:nth-of-type(2n) { background-color: var(--table-even-color); } @@ -273,12 +267,10 @@ table tbody tr:nth-of-type(2n+1) { table thead tr th, table tbody tr td { - display: flex; - flex: 1; padding: .25rem 0.75rem; } -li { +ul li { list-style-type: square; } diff --git a/styles/post.module.css b/styles/post.module.css index d335030..230cd6d 100644 --- a/styles/post.module.css +++ b/styles/post.module.css @@ -30,4 +30,12 @@ .background.spacer { height: 25rem; -} \ No newline at end of file +} + +.time { + text-align: center; + display: block; + font-style: italic; + font-size: 1rem; + margin: 0.5rem 0.75rem; +} diff --git a/tsconfig.json b/tsconfig.json index fbb4dc9..425b523 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es2017", + "target": "es2023", "lib": [ "dom", "dom.iterable", @@ -13,7 +13,7 @@ "noEmit": true, "esModuleInterop": true, "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve",