mirror of
https://github.com/timmypidashev/web.git
synced 2026-04-14 02:53:51 +00:00
Astro upgrade to v6
This commit is contained in:
@@ -8,36 +8,36 @@
|
||||
"preview": "astro preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/react": "^4.4.0",
|
||||
"@astrojs/react": "^5.0.2",
|
||||
"@astrojs/tailwind": "^6.0.2",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@types/react": "^18.3.20",
|
||||
"@types/react-dom": "^18.3.6",
|
||||
"astro": "^5.14.1",
|
||||
"tailwindcss": "^3.4.17"
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"@types/react": "^18.3.28",
|
||||
"@types/react-dom": "^18.3.7",
|
||||
"astro": "^6.1.2",
|
||||
"tailwindcss": "^3.4.19"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^4.3.6",
|
||||
"@astrojs/node": "^9.4.4",
|
||||
"@astrojs/rss": "^4.0.12",
|
||||
"@astrojs/sitemap": "^3.6.0",
|
||||
"@astrojs/mdx": "^5.0.3",
|
||||
"@astrojs/node": "^10.0.4",
|
||||
"@astrojs/rss": "^4.0.18",
|
||||
"@astrojs/sitemap": "^3.7.2",
|
||||
"@giscus/react": "^3.1.0",
|
||||
"@pilcrowjs/object-parser": "^0.0.4",
|
||||
"@react-hook/intersection-observer": "^3.1.2",
|
||||
"@rehype-pretty/transformers": "^0.13.2",
|
||||
"arctic": "^3.6.0",
|
||||
"arctic": "^3.7.0",
|
||||
"lucide-react": "^0.468.0",
|
||||
"marked": "^15.0.8",
|
||||
"marked": "^15.0.12",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-icons": "^5.6.0",
|
||||
"react-responsive": "^10.0.1",
|
||||
"reading-time": "^1.5.0",
|
||||
"rehype-pretty-code": "^0.14.1",
|
||||
"rehype-pretty-code": "^0.14.3",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"schema-dts": "^1.1.5",
|
||||
"shiki": "^3.12.2",
|
||||
"typewriter-effect": "^2.21.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
"shiki": "^3.23.0",
|
||||
"typewriter-effect": "^2.22.0",
|
||||
"unist-util-visit": "^5.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
3172
src/pnpm-lock.yaml
generated
3172
src/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
type BlogPost = {
|
||||
slug: string;
|
||||
id: string;
|
||||
data: {
|
||||
title: string;
|
||||
author: string;
|
||||
@@ -30,9 +30,9 @@ export const BlogPostList = ({ posts }: BlogPostListProps) => {
|
||||
<div className="w-full max-w-6xl mx-auto">
|
||||
<ul className="space-y-6 md:space-y-10">
|
||||
{posts.map((post) => (
|
||||
<li key={post.slug} className="group px-4 md:px-0">
|
||||
<li key={post.id} className="group px-4 md:px-0">
|
||||
<a
|
||||
href={`/blog/${post.slug}`}
|
||||
href={`/blog/${post.id}`}
|
||||
className="block"
|
||||
>
|
||||
<article className="flex flex-col md:flex-row gap-4 md:gap-8 pb-6 md:pb-10 border-b border-foreground/20 last:border-b-0 p-2 md:p-4 rounded-lg group-hover:outline group-hover:outline-2 group-hover:outline-purple transition-all duration-200">
|
||||
|
||||
@@ -11,7 +11,7 @@ export function ProjectCard({ project }: ProjectCardProps) {
|
||||
return (
|
||||
<article className="group relative h-full">
|
||||
<a
|
||||
href={`/projects/${project.slug}`}
|
||||
href={`/projects/${project.id}`}
|
||||
className="block rounded-lg border-2 border-foreground/20
|
||||
hover:border-blue transition-all duration-300
|
||||
bg-background overflow-hidden h-full flex flex-col"
|
||||
|
||||
@@ -23,7 +23,7 @@ export function ProjectList({ projects }: ProjectListProps) {
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 auto-rows-fr justify-items-center">
|
||||
{latestProjects.map(project => (
|
||||
<div key={project.slug} className="w-full max-w-md">
|
||||
<div key={project.id} className="w-full max-w-md">
|
||||
<ProjectCard project={project} />
|
||||
</div>
|
||||
))}
|
||||
@@ -37,7 +37,7 @@ export function ProjectList({ projects }: ProjectListProps) {
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 auto-rows-fr justify-items-center">
|
||||
{otherProjects.map(project => (
|
||||
<div key={project.slug} className="w-full max-w-md">
|
||||
<div key={project.id} className="w-full max-w-md">
|
||||
<ProjectCard project={project} />
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { defineCollection, z } from "astro:content";
|
||||
import { glob } from "astro/loaders";
|
||||
|
||||
export const collections = {
|
||||
blog: defineCollection({
|
||||
loader: glob({ pattern: "**/*.mdx", base: "./src/content/blog" }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
@@ -16,6 +18,7 @@ export const collections = {
|
||||
}),
|
||||
}),
|
||||
projects: defineCollection({
|
||||
loader: glob({ pattern: "**/*.mdx", base: "./src/content/projects" }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
0
src/src/content/blog/json-as-machine-code.keep
Normal file
0
src/src/content/blog/json-as-machine-code.keep
Normal file
@@ -25,6 +25,7 @@ import Advertisement from '@/content/blog/components/thinkpad-t440p-coreboot-gui
|
||||
Don't pipe anyone's scripts to **sh** blindly, including mine - <a href="https://github.com/timmypidashev/scripts" target="_blank" rel="noopener noreferrer">audit the source</a>.
|
||||
|
||||
## Getting Started
|
||||
|
||||
The Thinkpad T440p is a powerful and versatile laptop that can be further enhanced by installing coreboot,
|
||||
an open-source BIOS replacement. This guide will walk you through the process of corebooting your T440p,
|
||||
including flashing the BIOS chip and installing the necessary software.
|
||||
@@ -202,22 +203,64 @@ Configuring coreboot is really where most of your time will be spent. To help ou
|
||||
I've created several handy configs that should suit most use cases, and can be easily
|
||||
tweaked to your liking. Here is a list of whats available:
|
||||
|
||||
1. GRUB2
|
||||
### 1. GRUB2 (Recommended)
|
||||
|
||||
This configuration features GRUB2 as the bootloader, and contains 3 secondary payloads,
|
||||
which the user can opt in/out of:
|
||||
|
||||
* memtest built in
|
||||
* nvramcui built in
|
||||
* coreinfo built in
|
||||
GRUB2 is the recommended payload for most users. It boots Linux directly without needing a
|
||||
separate bootloader installation on disk. This configuration includes three secondary payloads:
|
||||
|
||||
This configuration also includes the dGPU option rom as well for T440p's featuring the gt730m on board.
|
||||
- **memtest86+** - Memory testing utility
|
||||
- **nvramcui** - CMOS/NVRAM settings editor
|
||||
- **coreinfo** - System information viewer
|
||||
|
||||
2. SeaBIOS
|
||||
If your T440p has the optional GT730M dGPU, the GRUB2 config also includes the
|
||||
necessary VGA option ROM for it.
|
||||
|
||||
3. edk2
|
||||
### 2. SeaBIOS
|
||||
|
||||
> NOTE: Show the user how to choose the appropriate config, as well as building a custom config below.
|
||||
SeaBIOS provides a traditional BIOS interface, making it the most compatible option.
|
||||
Choose this if you need to boot operating systems that expect a legacy BIOS, such
|
||||
as Windows or BSD.
|
||||
|
||||
### 3. edk2 (UEFI)
|
||||
|
||||
edk2 provides a UEFI firmware interface. Choose this if you prefer UEFI boot or
|
||||
need UEFI-specific features.
|
||||
|
||||
---
|
||||
|
||||
If using the interactive script, it will prompt you to choose a payload and apply
|
||||
a preset configuration automatically. You can also choose to open the full
|
||||
configuration menu (`make nconfig`) to customize further.
|
||||
|
||||
For manual configuration, first copy the extracted blobs into place:
|
||||
|
||||
<CommandSequence
|
||||
commands={[
|
||||
"mkdir -p ~/t440p-coreboot/coreboot/3rdparty/blobs/mainboard/lenovo/haswell",
|
||||
"mkdir -p ~/t440p-coreboot/coreboot/3rdparty/blobs/cpu/intel/haswell",
|
||||
"cp ~/t440p-coreboot/ifd.bin ~/t440p-coreboot/coreboot/3rdparty/blobs/mainboard/lenovo/haswell/descriptor.bin",
|
||||
"cp ~/t440p-coreboot/me.bin ~/t440p-coreboot/coreboot/3rdparty/blobs/mainboard/lenovo/haswell/me.bin",
|
||||
"cp ~/t440p-coreboot/gbe.bin ~/t440p-coreboot/coreboot/3rdparty/blobs/mainboard/lenovo/haswell/gbe.bin",
|
||||
"cp ~/t440p-coreboot/mrc.bin ~/t440p-coreboot/coreboot/3rdparty/blobs/cpu/intel/haswell/mrc.bin"
|
||||
]}
|
||||
description="Copy firmware blobs into the coreboot source tree"
|
||||
client:load
|
||||
/>
|
||||
|
||||
Then open the configuration menu:
|
||||
|
||||
<Command
|
||||
description="Open coreboot configuration"
|
||||
command="cd ~/t440p-coreboot/coreboot && make nconfig"
|
||||
client:load
|
||||
/>
|
||||
|
||||
Key settings to configure:
|
||||
|
||||
- **Mainboard** → Mainboard vendor: **Lenovo** → Mainboard model: **ThinkPad T440p**
|
||||
- **Chipset** → Add Intel descriptor.bin, ME firmware, and GbE configuration (set paths to your blobs)
|
||||
- **Chipset** → Add haswell MRC file (set path to mrc.bin)
|
||||
- **Payload** → Choose your preferred payload (GRUB2, SeaBIOS, or edk2)
|
||||
|
||||
## Building and Flashing
|
||||
|
||||
@@ -239,7 +282,7 @@ Once the coreboot build has completed, split the built ROM for the 8MB(bottom) c
|
||||
commands={[
|
||||
"cd ~/t440p-coreboot/coreboot/build",
|
||||
"dd if=coreboot.rom of=bottom.rom bs=1M count=8",
|
||||
"dd if=coreboot.rom of=top.rom bs=1M skin=8"
|
||||
"dd if=coreboot.rom of=top.rom bs=1M skip=8"
|
||||
]}
|
||||
description="Split the built ROM for both EEPROM chips"
|
||||
client:load
|
||||
|
||||
@@ -41,7 +41,7 @@ export function getArticleSchema(post: CollectionEntry<"blog">) {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
headline: post.data.title,
|
||||
url: `${import.meta.env.SITE}/blog/${post.slug}/`,
|
||||
url: `${import.meta.env.SITE}/blog/${post.id}/`,
|
||||
description: post.data.excerpt,
|
||||
datePublished: post.data.date.toString(),
|
||||
publisher: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import { getCollection, render } from "astro:content";
|
||||
import { Image } from "astro:assets";
|
||||
import ContentLayout from "@/layouts/content.astro";
|
||||
import { getArticleSchema } from "@/lib/structuredData";
|
||||
@@ -11,9 +11,9 @@ const { slug } = Astro.params;
|
||||
|
||||
// Fetch blog posts
|
||||
const posts = await getCollection("blog");
|
||||
const post = posts.find(post => post.slug === slug);
|
||||
const post = posts.find(post => post.id === slug);
|
||||
|
||||
if (!post || post.data.isDraft === true) {
|
||||
if (!post || (!import.meta.env.DEV && post.data.isDraft === true)) {
|
||||
return new Response(null, {
|
||||
status: 404,
|
||||
statusText: "Not found"
|
||||
@@ -21,7 +21,7 @@ if (!post || post.data.isDraft === true) {
|
||||
}
|
||||
|
||||
// Dynamically render the content
|
||||
const { Content } = await post.render();
|
||||
const { Content } = await render(post);
|
||||
|
||||
// Format the date
|
||||
const formattedDate = new Date(post.data.date).toLocaleDateString("en-US", {
|
||||
@@ -46,7 +46,7 @@ const breadcrumbsStructuredData = {
|
||||
"@type": "ListItem",
|
||||
position: 2,
|
||||
name: post.data.title,
|
||||
item: `${import.meta.env.SITE}/blog/${post.slug}/`,
|
||||
item: `${import.meta.env.SITE}/blog/${post.id}/`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ import { BlogHeader } from "@/components/blog/header";
|
||||
import { BlogPostList } from "@/components/blog/post-list";
|
||||
|
||||
const posts = (await getCollection("blog", ({ data }) => {
|
||||
return data.isDraft !== true;
|
||||
return import.meta.env.DEV || data.isDraft !== true;
|
||||
})).sort((a, b) => {
|
||||
return b.data.date.valueOf() - a.data.date.valueOf()
|
||||
}).map(post => ({
|
||||
|
||||
@@ -5,7 +5,7 @@ import ContentLayout from "@/layouts/content.astro";
|
||||
import TagList from "@/components/blog/tag-list";
|
||||
|
||||
const posts = (await getCollection("blog", ({ data }) => {
|
||||
return data.isDraft !== true;
|
||||
return import.meta.env.DEV || data.isDraft !== true;
|
||||
})).sort((a, b) => {
|
||||
return b.data.date.valueOf() - a.data.date.valueOf()
|
||||
}).map(post => ({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
export const prerender = true;
|
||||
|
||||
import { getCollection } from "astro:content";
|
||||
import { getCollection, render } from "astro:content";
|
||||
|
||||
import ContentLayout from "@/layouts/content.astro";
|
||||
import { Comments } from "@/components/blog/comments";
|
||||
@@ -9,13 +9,13 @@ import { Comments } from "@/components/blog/comments";
|
||||
export async function getStaticPaths() {
|
||||
const projects = await getCollection("projects");
|
||||
return projects.map(project => ({
|
||||
params: { slug: project.slug },
|
||||
params: { slug: project.id },
|
||||
props: { project },
|
||||
}));
|
||||
}
|
||||
|
||||
const { project } = Astro.props;
|
||||
const { Content } = await project.render();
|
||||
const { Content } = await render(project);
|
||||
---
|
||||
|
||||
<ContentLayout title={`${project.data.title} | Timothy Pidashev`}>
|
||||
|
||||
@@ -16,11 +16,11 @@ export async function GET(context: APIContext) {
|
||||
title: post.data.title,
|
||||
pubDate: post.data.date,
|
||||
description: post.data.description,
|
||||
link: `/blog/${post.slug}/`,
|
||||
link: `/blog/${post.id}/`,
|
||||
author: post.data.author,
|
||||
categories: post.data.tags,
|
||||
enclosure: post.data.image ? {
|
||||
url: new URL(`blog/${post.slug}/thumbnail.png`, context.site).toString(),
|
||||
url: new URL(`blog/${post.id}/thumbnail.png`, context.site).toString(),
|
||||
type: 'image/jpeg',
|
||||
length: 0
|
||||
} : undefined
|
||||
|
||||
Reference in New Issue
Block a user