feat(content): new blog post

This commit is contained in:
enscribe 2025-03-21 22:29:21 -07:00
parent 8e6df747e0
commit 28bd68c09e
No known key found for this signature in database
GPG key ID: 9BBD5C4114E25322
17 changed files with 118 additions and 40 deletions

View file

@ -24,7 +24,7 @@ export default defineConfig({
site: 'https://astro-erudite.vercel.app',
integrations: [
expressiveCode({
themes: ['min-light', 'min-dark'],
themes: ['github-light', 'github-dark'],
plugins: [pluginCollapsibleSections(), pluginLineNumbers()],
useDarkModeMediaQuery: false,
themeCssSelector: (theme) => `.${theme.name.split('-')[1]}`,
@ -44,6 +44,7 @@ export default defineConfig({
codeBackground:
'color-mix(in oklab, var(--secondary) 25%, transparent)',
frames: {
editorActiveTabForeground: 'var(--muted-foreground)',
editorActiveTabBackground:
'color-mix(in oklab, var(--secondary) 25%, transparent)',
editorActiveTabIndicatorBottomColor: 'transparent',
@ -95,8 +96,8 @@ export default defineConfig({
rehypePrettyCode,
{
theme: {
light: 'min-light',
dark: 'min-dark',
light: 'github-light',
dark: 'github-dark',
},
},
],

View file

@ -4,9 +4,9 @@ import { Badge } from '@/components/ui/badge'
import { Separator } from '@/components/ui/separator'
import { parseAuthors } from '@/lib/server-utils'
import { formatDate, readingTime } from '@/lib/utils'
import { Icon } from 'astro-icon/components'
import { Image } from 'astro:assets'
import type { CollectionEntry } from 'astro:content'
import { Icon } from 'astro-icon/components'
import Link from './Link.astro'
type Props = {

View file

@ -7,7 +7,7 @@ import { Icon } from 'astro-icon/components'
const { prevPost, nextPost } = Astro.props
---
<div class="col-start-2 grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="col-start-2 grid grid-cols-1 gap-4 sm:grid-cols-2">
<Link
href={nextPost ? `/blog/${nextPost.id}` : '#'}
class={cn(

View file

@ -43,9 +43,7 @@ const { project } = Astro.props
project.data.tags && (
<div class="flex flex-wrap gap-2">
{project.data.tags.map((tag: string) => (
<Badge variant="secondary">
{tag}
</Badge>
<Badge variant="secondary">{tag}</Badge>
))}
</div>
)

View file

@ -165,7 +165,9 @@ const PaginationComponent: React.FC<PaginationProps> = ({
<PaginationItem>
<PaginationNext
href={currentPage < totalPages ? getPageUrl(currentPage + 1) : undefined}
href={
currentPage < totalPages ? getPageUrl(currentPage + 1) : undefined
}
isDisabled={currentPage === totalPages}
/>
</PaginationItem>
@ -182,7 +184,6 @@ interface PaginationProps {
export default PaginationComponent
export {
Pagination,
PaginationContent,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

View file

@ -1,9 +0,0 @@
---
title: '2022 Post'
description: 'This a dummy post written in the year 2022.'
date: 2022-06-01
tags: ['dummy', 'placeholder']
image: './2022.png'
---
This is a dummy post written in the year 2022.

View file

@ -2,7 +2,7 @@
title: '2023 Post'
description: 'This a dummy post written in the year 2023.'
date: 2023-06-01
tags: ['dummy', 'placeholder']
tags: ['v1.0.0']
image: './2023.png'
authors: ['enscribe']
---

View file

@ -2,7 +2,7 @@
title: '2024 Post'
description: 'This a dummy post written in the year 2024 (with multiple authors).'
date: 2024-06-01
tags: ['dummy', 'placeholder']
tags: ['v1.0.0']
image: './2024.png'
authors: ['enscribe', 'jktrn']
---

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

89
src/content/blog/rehype-patch/index.mdx vendored Normal file
View file

@ -0,0 +1,89 @@
---
title: 'v1.3.0: “Patches in Production”'
description: 'Whenever you depend on Node packages with missing maintainers, patching becomes a necessary evil.'
date: 2025-03-21
tags: ['v1.3.0']
image: './1200x630.png'
authors: ['enscribe']
---
## A problem (about dead maintainers)
This post talks about changes I've made to astro-erudite in v1.3.0!
I recently found myself caught between two syntax highlighting packages that I absolutely needed for astro-erudite. On one hand, the current template uses [rehype-pretty-code](https://rehype-pretty.pages.dev/) as its main syntax highlighting solution, but due to issues with its inherent implementation and missing features that I needed, I had created a bunch of custom transformers to make it do what I wanted, and the whole setup was getting unwieldy. I then discovered [Expressive Code](https://expressive-code.com/), which had everything I wanted out of the box—collapsible code sections, terminal and editor frames, gutter comments—it was perfect! Well, almost perfect.
The primary issue was that Expressive Code doesn't support inline syntax highlighting, which is non-negotiable for me since I need my inline code snippets to look as good as my code blocks (so I could do stuff like `console.log("Hello, world!".split('').reverse().join('')){:js}`). So I opened a feature request at [expressive-code/expressive-code#250](https://github.com/expressive-code/expressive-code/issues/250) and the maintainer seemed interested, saying they'd get around to it eventually. Implementing this feature is a lot easier said than done though, and I summarized it well in another thread:
> [@jktrn](https://github.com/rehype-pretty/rehype-pretty-code/issues/247#issuecomment-2619869436): [...] expressive-code is already interested in implementing inline code support, but it would be a bit nuanced to add since it has to:
>
> - allow existing plugins to continue working normally with block-level code (without breaking changes),
> - enable new plugins to explicitly declare support for inline code,
> - and provide ways for plugins to distinguish between inline and block-level code processing.
However, I needed a solution immediately. My first thought was to use both packages together—Expressive Code for block code and rehype-pretty-code for inline code. However, importing both at the same time caused everything to break spectacularly.
## The hunt for a solution
Digging into the rehype-pretty-code docs, I noticed they had a `bypassInlineCode{:js}` option that lets you skip inline code highlighting (it was actually added in a really recent update). But what I needed was the opposite, which would be a way to make it only handle inline code and bypass blocks entirely.
So I opened a feature request at [rehype-pretty/rehype-pretty-code#247](https://github.com/rehype-pretty/rehype-pretty-code/issues/247) for a theoretical `bypassBlockCode{:js}` option. I got no response, since the repository seemed unmaintained for a bit since it seems like the maintainer has moved onto other projects.
Fast forward a few months, and user [@kelvindecosta](https://github.com/kelvindecosta) comments on my issue:
> [[@kelvindecosta]](https://github.com/rehype-pretty/rehype-pretty-code/issues/247#issuecomment-2610536000): Hey [@jktrn](https://github.com/jktrn), did you figure out a workaround for this? I'm interested in setting this up alongside expressive-code.
After I replied that I hadn't figured out a workaround yet, they sent me a brilliantly hacky solution a couple days later:
> [[@kelvindecosta]](https://github.com/rehype-pretty/rehype-pretty-code/issues/247#issuecomment-2619666231): Hey again @jktrn, I have found an unconventional way to achieve this.
>
> If you're using pnpm or bun, you can use their patch functionality to customize the contents of the `node_modules/rehype-pretty-code` package.
>
> I only recently learned about this feature, and it is a good workaround for the time being. Here are the steps:
>
> 1. Run `pnpm patch rehype-pretty-code`. This will instruct you to edit the files in a certain directory.
> 2. Patch out the `isBlockCode{:js}` function to always return `false{:js}`. This will instruct the plugin to not process any block code elements.
> 3. Run `pnpm patch-commit <path/to/files>`. This will create a nice patches folder with the right changes.
## Performing surgery on node_modules
This happened to be exactly what I needed! I went into my `node_modules` directory and made the changes manually:
```js title="node_modules rehype-pretty-code dist index.js" startLineNumber=18 ins={9} del={8}
function isInlineCode(element, parent, bypass = false) {
if (bypass) {
return false;
}
return element.tagName === "code" && isElement(parent) && parent.tagName !== "pre" || element.tagName === "inlineCode";
}
function isBlockCode(element) {
return element.tagName === "pre" && Array.isArray(element.children) && element.children.length === 1 && isElement(element.children[0]) && element.children[0].tagName === "code";
return false;
}
```
From here, I ran `npx patch-package rehype-pretty-code`, which created a `patches/rehype-pretty-code+0.14.1.patch` file with the changes I made:
```diff title="patches rehype-pretty-code+0.14.1.patch"
--- a/node_modules/rehype-pretty-code/dist/index.js
+++ b/node_modules/rehype-pretty-code/dist/index.js
@@ -22,7 +22,7 @@ function isInlineCode(element, parent, bypass = false) {
return element.tagName === "code" && isElement(parent) && parent.tagName !== "pre" || element.tagName === "inlineCode";
}
function isBlockCode(element) {
- return element.tagName === "pre" && Array.isArray(element.children) && element.children.length === 1 && isElement(element.children[0]) && element.children[0].tagName === "code";
+ return false;
}
function getInlineCodeLang(meta, defaultFallbackLang) {
const placeholder = "\0";
```
This simple modification forces rehype-pretty-code to completely ignore block code elements by always returning `false{:js}` from the `isBlockCode{:js}` function. Now Expressive Code handles all block code formatting, while rehype-pretty-code still beautifully handles my inline code. And just like that, they're working in perfect harmony!
## Please don't perform surgery on your node_modules
Absolutely do not do this for production sites (your personal blog does not count = ̄ω ̄=). Directly patching node modules is generally discouraged because patches can break with updates and create maintenance headaches down the road.
But sometimes, when you're working at the bleeding edge of web development, temporary solutions like this become necessary. The better approach would be to just wait for Expressive Code to implement inline syntax highlighting. But, since it'll take a while for reasons aforementioned, I'll stick with my janky solution. This patch buys me time until either rehype-pretty-code gets maintained again and implements the feature properly, or Expressive Code adds inline code support.
In the meantime, astro-erudite now has both beautiful code blocks and inline syntax highlighting. And now it's available for all of you to use!

View file

@ -2,7 +2,7 @@
title: 'The State of Static Blogs in 2024'
description: 'There should not be a single reason why you would need a command palette search bar to find a blog post on your own site.'
date: 2024-07-25
tags: ['webdev', 'opinion']
tags: ['v1.0.0']
image: './1200x630.png'
authors: ['enscribe']
---
@ -123,7 +123,7 @@ This is a non-exhaustive list of features I believe are essential for a friction
- The `cn(){:js}` function is a utility function which combines [clsx](https://www.npmjs.com/package/clsx) and [tailwind-merge](https://www.npmjs.com/package/tailwind-merge), two packages which allow painless conditional class addition and concatenation:
```tsx title="src/lib/utils.ts" caption="A utility function for class name concatenation" showLineNumbers
```tsx title="src lib utils.ts" caption="A utility function for class name concatenation" showLineNumbers
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
@ -134,7 +134,7 @@ This is a non-exhaustive list of features I believe are essential for a friction
This needs to be in every single template. This is an example of it being used in my `<Link>{:html}` component:
```astro showLineNumbers title="src/components/Link.astro" caption="A custom Link component with tailwind-merge and clsx" {10-15} "cn"
```astro showLineNumbers title="src components Link.astro" caption="A custom Link component with tailwind-merge and clsx" {10-15} "cn"
---
import { cn } from '@/lib/utils'

View file

@ -17,9 +17,7 @@ import { cn } from '@/lib/utils'
>
<div class="max-w-md">
<h1 class="mb-4 text-3xl font-medium">404: Page not found</h1>
<p class="prose">
Oops! The page you're looking for doesn't exist.
</p>
<p class="prose">Oops! The page you're looking for doesn't exist.</p>
</div>
<Link
href="/"

View file

@ -152,9 +152,7 @@ const authors = await parseAuthors(post.data.authors ?? [])
{headings.length > 0 && <TableOfContents headings={headings} />}
<article
class="prose col-start-2 max-w-none"
>
<article class="prose col-start-2 max-w-none">
<Content />
</article>

View file

@ -18,8 +18,10 @@ const blog = (await getCollection('blog'))
<section>
<div class="rounded-lg border">
<div class="flex flex-col space-y-1.5 p-6">
<h3 class="text-3xl font-medium leading-none">er·u·dite</h3>
<p class="text-sm text-muted-foreground">/ˈer(y)əˌdīt/ &bull; <span class="font-medium">adjective</span></p>
<h3 class="text-3xl leading-none font-medium">er·u·dite</h3>
<p class="text-muted-foreground text-sm">
/ˈer(y)əˌdīt/ &bull; <span class="font-medium">adjective</span>
</p>
</div>
<div class="p-6 pt-0">
<p class="text-muted-foreground mb-2 text-sm">

View file

@ -47,7 +47,7 @@
@font-face {
font-family: 'Geist Mono';
src: url('/fonts/GeistMonoVF.woff2') format('woff2-variations');
font-weight: 100 500;
font-weight: 100 600;
font-style: normal;
font-display: swap;
}

View file

@ -5,7 +5,7 @@
@apply text-foreground text-base leading-8 [&>*]:first:mt-0 [&>*]:last:mb-0;
p {
@apply text-foreground/80 my-5 leading-7 [&:not(:first-child)]:mt-5;
@apply text-foreground/80 my-5 leading-7 not-first:mt-5;
}
h1 {
@ -41,11 +41,11 @@
}
ul {
@apply marker:text-foreground/30 my-5 ml-6 list-disc [&>li]:mt-4;
@apply marker:text-foreground/30 my-5 ml-6 list-disc [&>li]:mt-2;
}
ol {
@apply marker:text-foreground/30 my-5 ml-6 list-decimal [&>li]:mt-4;
@apply marker:text-foreground/30 my-5 ml-6 list-decimal [&>li]:mt-2;
@apply [&[type='A']]:list-[upper-alpha] [&[type='I']]:list-[upper-roman] [&[type='a']]:list-[lower-alpha] [&[type='i']]:list-[lower-roman];
}
@ -66,11 +66,11 @@
}
.expressive-code {
@apply my-6;
@apply my-6 [&_.title]:font-medium!;
}
blockquote {
@apply my-6 border-l-2 pl-6 text-sm;
@apply [&_*]:text-muted-foreground my-6 border-l-2 pl-6;
}
hr {