feat: lots of bits n pieces
This commit is contained in:
parent
8f27f005ef
commit
0243c7f5b1
22 changed files with 2476 additions and 14349 deletions
|
@ -1,7 +1,3 @@
|
|||
{
|
||||
"extends": "next/core-web-vitals",
|
||||
"rules": {
|
||||
"@stylistic/jsx/jsx-pascal-case": "off",
|
||||
"@next/next/no-html-link-for-pages": "off"
|
||||
}
|
||||
"extends": ["next/core-web-vitals"]
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
echo Formatting...
|
||||
# npm run format
|
||||
npm run lint
|
||||
echo Successfully formatted.
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
|||
v23.4.0
|
||||
v22.15.0
|
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
|
@ -27,7 +27,6 @@
|
|||
],
|
||||
"files.autoSave": "off",
|
||||
"standard.autoFixOnSave": true,
|
||||
"prettier.enable": false,
|
||||
"editor.defaultFormatter": "standard.vscode-standard",
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||
|
@ -41,5 +40,11 @@
|
|||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "vscode.json-language-features"
|
||||
}
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "vscode.json-language-features"
|
||||
},
|
||||
}
|
|
@ -15,7 +15,7 @@ module.exports = {
|
|||
allow: '/'
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
// transform: async (config, path) => {
|
||||
// const metadata = {
|
||||
// loc: path
|
||||
|
|
16552
package-lock.json
generated
16552
package-lock.json
generated
File diff suppressed because it is too large
Load diff
24
package.json
24
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "www-aaronjy-me",
|
||||
"version": "2.0.0.0",
|
||||
"version": "2.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
@ -8,27 +8,22 @@
|
|||
"build": "next build",
|
||||
"postbuild": "next-sitemap --config next-sitemap.config.cjs",
|
||||
"start": "next start",
|
||||
"link": "npx standard",
|
||||
"format": "npx standard --fix",
|
||||
"link": "echo NOT CONFIGURED",
|
||||
"prepare": "husky",
|
||||
"test": "jest --verbose --passWithNoTests",
|
||||
"lint": "next lint",
|
||||
"export:books": "node ./util/books-as-json.js > ./tmp/books.json",
|
||||
"export:writing": "node ./util/writing-as-json.js > ./tmp/writing.json"
|
||||
},
|
||||
"standard": {
|
||||
"ignore": [
|
||||
"/tina/**/*"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@highlightjs/cdn-assets": "^11.11.1",
|
||||
"@mdx-js/mdx": "^3.1.0",
|
||||
"@mdx-js/react": "^3.1.0",
|
||||
"camelcase-keys": "^9.1.3",
|
||||
"date-fns": "^4.1.0",
|
||||
"highlight.js": "^11.11.0",
|
||||
"i": "^0.3.7",
|
||||
"next": "^14.2.6",
|
||||
"next": "^15.3.1",
|
||||
"next-mdx-remote-client": "^1.1.0",
|
||||
"next-seo": "^6.5.0",
|
||||
"node-html-parser": "^7.0.1",
|
||||
|
@ -37,8 +32,7 @@
|
|||
"react-dom": "^18",
|
||||
"rehype-code-titles": "^1.2.0",
|
||||
"rehype-prism-plus": "^2.0.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"tinacms": "^2.7.3"
|
||||
"remark-gfm": "^4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.0",
|
||||
|
@ -46,12 +40,13 @@
|
|||
"@babel/preset-react": "^7.24.7",
|
||||
"@commitlint/cli": "^19.1.0",
|
||||
"@commitlint/config-conventional": "^19.1.0",
|
||||
"@next/eslint-plugin-next": "^15.3.1",
|
||||
"@testing-library/jest-dom": "^6.4.2",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@tinacms/cli": "^1.9.3",
|
||||
"@types/jest": "^29.5.12",
|
||||
"babel-jest": "^29.7.0",
|
||||
"eslint": "^9.9.0",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-next": "15.3.1",
|
||||
"front-matter": "^4.0.2",
|
||||
"frontmatter-markdown-loader": "^3.7.0",
|
||||
"husky": "^9.0.11",
|
||||
|
@ -60,7 +55,6 @@
|
|||
"js-yaml": "^4.1.0",
|
||||
"next-sitemap": "^4.0.9",
|
||||
"react-test-renderer": "^18.3.1",
|
||||
"showdown": "^2.1.0",
|
||||
"standard": "^17.1.0"
|
||||
"showdown": "^2.1.0"
|
||||
}
|
||||
}
|
||||
|
|
2
public/admin/.gitignore
vendored
2
public/admin/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
index.html
|
||||
assets/
|
|
@ -4,37 +4,4 @@
|
|||
<url><loc>https://www.aaronjy.me/library</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/tags</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/writing</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/the-alchemist</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/the-invisible-man</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/wintering-the-power-of-rest-and-retreat-in-difficult-times</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/the-time-machine</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/when-the-moon-hits-your-eye</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/the-song-of-achilles</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/to-be-taught-if-fortunate</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/on-tyranny</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/the-dangers-of-smoking-in-bed</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/the-midnight-library</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/a-night-to-remember</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/sex-punishment</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/a-monster-calls</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/diary-of-an-oxygen-thief</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/1984</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/alices-adventures-in-wonderland</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/the-nature-of-alexander</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/eleven-kinds-of-loneliness</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/star-maker</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/stray-reflections</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/stasiland-stories-from-behind-the-berlin-wall</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/cities-that-shaped-the-ancient-world</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/animal-farm</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/one-thousand-and-one-nights-a-retelling</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/library/childhoods-end</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/writing/migrating-from-github-to-forgejo</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/writing/performance-considerations-when-writing-a-tcp-game-server-in-dotnet</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/writing/quickwrite-a-reflection-on-wintering-by-katherine-may</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/writing/deploying-aaronjy-me-on-a-google-storage-bucket</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/writing/supporting-content-file-structure-changes-on-a-static-site</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/writing/attitudes-to-reading-and-how-mine-have-changed</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me/about</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
<url><loc>https://www.aaronjy.me</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>
|
||||
</urlset>
|
|
@ -6,7 +6,7 @@ import React, { useEffect } from 'react'
|
|||
import 'highlight.js/styles/atom-one-dark.css'
|
||||
import hljs from 'highlight.js'
|
||||
|
||||
function Article ({ title, excerpt, date_published, tags, html }) {
|
||||
function Article ({ title, excerpt, datePublished, tags, html }) {
|
||||
useEffect(() => {
|
||||
hljs.highlightAll()
|
||||
}, [html])
|
||||
|
@ -21,14 +21,14 @@ function Article ({ title, excerpt, date_published, tags, html }) {
|
|||
description: excerpt,
|
||||
type: 'article',
|
||||
article: {
|
||||
publishedTime: date_published ?? null
|
||||
publishedTime: datePublished ?? null
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div>
|
||||
<Link href='./'>Back...</Link>
|
||||
{date_published && <p>{formatDate(date_published)}</p>}
|
||||
{datePublished && <p>{formatDate(datePublished)}</p>}
|
||||
<div data-test='content' dangerouslySetInnerHTML={{ __html: html }} />
|
||||
{tags && <p>Tags: {tags.join(', ')}</p>}
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@ import style from './BookReview.module.css'
|
|||
import ExternalLink from '../ExternalLink/ExternalLink'
|
||||
|
||||
function BookReview ({ review, html }) {
|
||||
const { title, image, author, description, url, tags, rating, read_date } = review
|
||||
const { title, image, author, description, url, tags, rating, readDate } = review
|
||||
|
||||
const imageUrl = image ? `${process.env.NEXT_PUBLIC_CONTENT_API_BASE_URL}/assets/${image}` : undefined
|
||||
|
||||
|
@ -24,7 +24,7 @@ function BookReview ({ review, html }) {
|
|||
description,
|
||||
type: 'article',
|
||||
article: {
|
||||
publishedTime: read_date ?? null
|
||||
publishedTime: readDate ?? null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ function BookReview ({ review, html }) {
|
|||
<span className='bold'>Genres:</span> {tags.join(',')}<br />
|
||||
</>}
|
||||
<span className='bold'>Rating:</span> {rating}/5<br />
|
||||
<span className='bold'>Read on:</span> {formatDate(read_date)}
|
||||
<span className='bold'>Read on:</span> {formatDate(readDate)}
|
||||
</p>
|
||||
<p><ExternalLink href={url}>View on The StoryGraph</ExternalLink></p>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@ export default function StaticContentList ({ entries, urlPrefix, max = 0 }) {
|
|||
<tbody>
|
||||
{entries.map((e) => (
|
||||
<tr key={e.slug}>
|
||||
<td>{!!e.date_published && <span>{formatDate(e.date_published)}</span>}</td>
|
||||
<td>{!!e.datePublished && <span>{formatDate(e.datePublished)}</span>}</td>
|
||||
<td>
|
||||
<Link href={`${urlPrefix}${e.slug}`}>{e.title}</Link>
|
||||
</td>
|
||||
|
|
|
@ -9,7 +9,7 @@ function DefaultLayout ({ children }) {
|
|||
<main className={`${style.layout}`}>
|
||||
<Header />
|
||||
<>{children}</>
|
||||
<Footer />
|
||||
<Footer />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ export const mdxComponents = {
|
|||
(async function () {
|
||||
const res = await fetchPosts([])
|
||||
const json = await res.json()
|
||||
setItems(json.data.sort((a, b) => a.date_published < b.date_published) ?? [])
|
||||
setItems(json.data.sort((a, b) => a.datePublished < b.datePublished) ?? [])
|
||||
setLoading(false)
|
||||
})()
|
||||
break
|
||||
|
@ -21,11 +21,14 @@ export const mdxComponents = {
|
|||
default:
|
||||
throw `Could not render StaticContentList: content type ${type} not supported.`
|
||||
}
|
||||
}, [])
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoading && <p>Loading...</p>}
|
||||
{isLoading && <p>Loading...</p> }
|
||||
|
||||
|
||||
|
||||
{!isLoading && <StaticContentList entries={items} urlPrefix={urlPrefix} max={max} />}
|
||||
</>
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ export async function getServerSideProps ({ params }) {
|
|||
}
|
||||
|
||||
export default function BasicPage ({ title, mdxSource }) {
|
||||
if (!mdxSource || "error" in mdxSource) {
|
||||
return <p>Something went wrong: {mdxSource?.error ?? "???"}</p>
|
||||
if (!mdxSource || 'error' in mdxSource) {
|
||||
return <p>Something went wrong: {mdxSource?.error ?? '???'}</p>
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -5,7 +5,8 @@ export default function App ({ Component, pageProps }) {
|
|||
return (
|
||||
<>
|
||||
<DefaultSeo defaultTitle='Aaron Yarborough' titleTemplate='%s | Aaron Yarborough' />
|
||||
<Component {...pageProps} />
|
||||
<Component
|
||||
{...pageProps} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export const getServerSideProps = async () => {
|
|||
|
||||
const json = await res.json()
|
||||
const posts = json.data
|
||||
.sort((a, b) => new Date(b.date_published).getTime() - new Date(a.date_published).getTime())
|
||||
.sort((a, b) => new Date(b.datePublished).getTime() - new Date(a.datePublished).getTime())
|
||||
|
||||
return {
|
||||
props: {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import showdown from 'showdown'
|
||||
import camelcaseKeys from 'camelcase-keys'
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_CONTENT_API_BASE_URL
|
||||
|
||||
|
@ -8,9 +9,23 @@ export const fetchBookReviews = async (...args) => fetchItems('book_review', ...
|
|||
export const fetchBasicPages = async (...args) => fetchItems('basic_pages', ...args)
|
||||
export const fetchCV = async (...args) => fetchItems('cv', ...args)
|
||||
|
||||
const originalFetch = globalThis.fetch
|
||||
|
||||
globalThis.fetch = async (...args) => {
|
||||
const response = await originalFetch(...args)
|
||||
|
||||
const originalJson = response.json
|
||||
|
||||
response.json = async function () {
|
||||
const data = await originalJson.call(this)
|
||||
return camelcaseKeys(data, { deep: true })
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
export async function fetchItems (type, fields = undefined, filter = undefined) {
|
||||
const url = new URL(`${baseUrl}/items/${type}`)
|
||||
// console.trace(`Getting items '${type}' with fields`, fields, 'and filter', filter)
|
||||
|
||||
if (fields?.length) {
|
||||
url.searchParams.append('fields', fields.join(','))
|
||||
|
@ -50,9 +65,7 @@ export function markdownToHtml (content) {
|
|||
}
|
||||
|
||||
async function apiFetch (...args) {
|
||||
const url = args[0]
|
||||
// @ts-ignore
|
||||
const res = await fetch(...args)
|
||||
// console.log('GET (fetch)', url, res.status, res.statusText)
|
||||
return res
|
||||
}
|
||||
|
|
1
tina/.gitignore
vendored
1
tina/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
__generated__
|
136
tina/config.js
136
tina/config.js
|
@ -1,136 +0,0 @@
|
|||
import { defineConfig } from 'tinacms'
|
||||
|
||||
// Your hosting provider likely exposes this as an environment variable
|
||||
const branch =
|
||||
process.env.GITHUB_BRANCH ||
|
||||
process.env.VERCEL_GIT_COMMIT_REF ||
|
||||
process.env.HEAD ||
|
||||
'main'
|
||||
|
||||
export default defineConfig({
|
||||
branch,
|
||||
|
||||
// Get this from tina.io
|
||||
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID,
|
||||
// Get this from tina.io
|
||||
token: process.env.TINA_TOKEN,
|
||||
|
||||
build: {
|
||||
outputFolder: 'admin',
|
||||
publicFolder: 'public'
|
||||
},
|
||||
media: {
|
||||
tina: {
|
||||
mediaRoot: '',
|
||||
publicFolder: 'public'
|
||||
}
|
||||
},
|
||||
// See docs on content modeling for more info on how to setup new content models: https://tina.io/docs/schema/
|
||||
schema: {
|
||||
collections: [
|
||||
{
|
||||
name: 'books',
|
||||
label: 'Library',
|
||||
path: 'content/books',
|
||||
match: {
|
||||
include: '*'
|
||||
},
|
||||
format: 'md',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
label: 'Title',
|
||||
isTitle: true,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'author',
|
||||
label: 'Author',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
name: 'stars',
|
||||
label: 'Stars',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'datetime',
|
||||
name: 'readDate',
|
||||
label: 'Read date',
|
||||
required: false
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'url',
|
||||
label: 'URL',
|
||||
required: false
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'thumbnailUrl',
|
||||
label: 'Thumbnail URL',
|
||||
required: false
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'tags',
|
||||
label: 'Tags',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'rich-text',
|
||||
name: 'body',
|
||||
label: 'Body',
|
||||
isBody: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'writing',
|
||||
label: 'Writing',
|
||||
path: 'content/writing',
|
||||
match: {
|
||||
include: '*'
|
||||
},
|
||||
format: 'md',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
label: 'Title',
|
||||
isTitle: true,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'datetime',
|
||||
name: 'pubdate',
|
||||
label: 'Publish Date'
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
ui: {
|
||||
component: 'textarea'
|
||||
},
|
||||
name: 'desc',
|
||||
label: 'Description'
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'tags',
|
||||
label: 'Tags',
|
||||
list: true
|
||||
},
|
||||
{
|
||||
type: 'rich-text',
|
||||
name: 'body',
|
||||
label: 'Body',
|
||||
isBody: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue