1
0
mirror of https://github.com/kremalicious/blog.git synced 2024-06-25 18:56:25 +02:00

switch to astro-redirect-from

This commit is contained in:
Matthias Kretschmann 2023-09-23 18:17:47 +01:00
parent c940c9c5a3
commit 446cef9e0a
Signed by: m
GPG Key ID: 606EEEF3C479A91F
6 changed files with 113 additions and 167 deletions

View File

@ -4,7 +4,7 @@ import remarkToc from '../src/lib/remark-toc'
import react from '@astrojs/react'
import sitemap from '@astrojs/sitemap'
import expressiveCode from 'astro-expressive-code'
import redirectFrom from '../src/lib/astro-redirect-from/src'
import redirectFrom from 'astro-redirect-from'
import config from './blog.config'
import { getSlug } from '../src/lib/astro/getSlug'

View File

@ -24,7 +24,7 @@
- [📝 GitHub changelog rendering](#-github-changelog-rendering)
- [🌗 Theme Switcher](#-theme-switcher)
- [💎 SVG assets as components](#-svg-assets-as-components)
- [`redirect_from`](#redirect_from)
- [astro-redirect-from](#astro-redirect-from)
- [RSS \& JSON feeds](#rss--json-feeds)
- [✨ Development](#-development)
- [🔮 Linting](#-linting)
@ -145,15 +145,11 @@ If you want to know how this works, have a look at the respective files:
- [`scripts/create-icons/`](scripts/create-icons/)
### `redirect_from`
### astro-redirect-from
Still a remnant of the old [Jekyll](https://jekyllrb.com) days, which survived in [gatsby-redirect-from](/gatsby-redirect-from/) and now works in Astro. For all post slugs defined in a `redirect_from` frontmatter key, redirects will be put in place by Astro.
Still a remnant of the old [Jekyll](https://jekyllrb.com) days, which survived in [gatsby-redirect-from](https://kremalicious.com/gatsby-redirect-from/) and now works in Astro with [astro-redirect-from](https://kremalicious.com/astro-redirect-from/).
Before building the site, a script scans all markdown files and creates a json file under `.config/redirects.json`. This file is then imported into `astro.config.ts` under its `redirects` option.
If you want to know how, have a look at the respective files:
- [`scripts/redirect-from.ts`](scripts/redirect-from.ts)
For all post slugs defined in a `redirect_from` frontmatter key, redirects will be put in place by Astro.
### RSS & JSON feeds

154
package-lock.json generated
View File

@ -16,8 +16,9 @@
"@astrojs/ts-plugin": "^1.1.3",
"@nanostores/react": "^0.7.1",
"@rainbow-me/rainbowkit": "^1.0.11",
"astro": "^3.1.0",
"astro-expressive-code": "^0.22.2",
"astro": "^3.1.2",
"astro-expressive-code": "^0.26.0",
"astro-redirect-from": "^0.2.1",
"date-fns": "^2.30.0",
"dms2dec": "^1.1.0",
"fast-exif": "^2.0.1",
@ -338,8 +339,9 @@
}
},
"node_modules/@astrojs/telemetry": {
"version": "3.0.1",
"license": "MIT",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.0.2.tgz",
"integrity": "sha512-ef+jqCkqopCzjGfsMsr+8p56Nj6F9ZzouWcWZt+dKsqbRccI3c8K3jfkLcdq4AyfFZtKBDB6N4ZuI68g33oiOg==",
"dependencies": {
"ci-info": "^3.8.0",
"debug": "^4.3.4",
@ -356,7 +358,8 @@
},
"node_modules/@astrojs/telemetry/node_modules/is-docker": {
"version": "3.0.0",
"license": "MIT",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
"bin": {
"is-docker": "cli.js"
},
@ -369,7 +372,8 @@
},
"node_modules/@astrojs/telemetry/node_modules/is-wsl": {
"version": "3.0.0",
"license": "MIT",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.0.0.tgz",
"integrity": "sha512-TQ7xXW/fTBaz/HhGSV779AC99ocpvb9qJPuPwyIea+F+Z+htcQ1wouAA0xEQaa4saVqyP8mwkoYp5efeM/4Gbg==",
"dependencies": {
"is-docker": "^3.0.0"
},
@ -1000,9 +1004,9 @@
}
},
"node_modules/@expressive-code/core": {
"version": "0.22.2",
"resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.22.2.tgz",
"integrity": "sha512-fVfnopl4dz75KgZ8q9G6sL+GW7QAzuWnNrm4zTKRabRzwdTZ9MCUmGPJvUpxKovJ1Z4t6YIKGHTson0a7fvV5g==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.26.0.tgz",
"integrity": "sha512-hhvRbIDiUX3DI3CnX8gDCY5lgn7TzhVz8PGunAfhAoIWp0+P72NSLoaLIg4FwOXFWEomTRLfkGk2cVQrppCXmQ==",
"dependencies": {
"@ctrl/tinycolor": "^3.6.0",
"hast-util-to-html": "^8.0.4",
@ -1043,29 +1047,29 @@
}
},
"node_modules/@expressive-code/plugin-frames": {
"version": "0.22.2",
"resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.22.2.tgz",
"integrity": "sha512-Tn4COPTdySVJ6gygCCqYd0KMQXea4l6NN/9Px2uSekPDLUiE9Ff4i3005Pa1rr31m0hLBes4POnFRRmwqIu+ZA==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.26.0.tgz",
"integrity": "sha512-mFPTh8tE1mItQcfJM6F6p8aWaa4Pi+KceBMIW6IsByQZKyMGdyS+PYphn0KbUjYI2za0/DVIJdukM9XueSpJ3A==",
"dependencies": {
"@expressive-code/core": "^0.22.2",
"@expressive-code/core": "^0.26.0",
"hastscript": "^7.2.0"
}
},
"node_modules/@expressive-code/plugin-shiki": {
"version": "0.22.2",
"resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.22.2.tgz",
"integrity": "sha512-BDNkEb2OwmoL5kJJnNZ6fXk5IytZordEWGjWycEiKyHMXotJ+94S0PIIiTfVIp38H1faL+yd+kz2pF4t7ePcww==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.26.0.tgz",
"integrity": "sha512-3qCSfDSR31joT3lQLOVw+fSSNp/ZYpZP3Os8sr1ekTa4yh41SgiwWk5rYm8PhKMGOnw8nhzlknwLkcZJf20sOQ==",
"dependencies": {
"@expressive-code/core": "^0.22.2",
"@expressive-code/core": "^0.26.0",
"shiki": "^0.14.1"
}
},
"node_modules/@expressive-code/plugin-text-markers": {
"version": "0.22.2",
"resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.22.2.tgz",
"integrity": "sha512-9lMON0kVEn0LAIe9mHcXaxdwqnxCF7MR+IExyC4OGhMVEc1p8Vp7rvSxsUPjySQV2QvYNTlQOaKVi/eI5oM1Ag==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.26.0.tgz",
"integrity": "sha512-klBtYJf3liTOnhiKHNpuO9KC1vAYcANtSWz07yPnnQzCwkRo9bTkdOI+9xSViVisNiAF6TfCuoEKjlB7BmtP7A==",
"dependencies": {
"@expressive-code/core": "^0.22.2",
"@expressive-code/core": "^0.26.0",
"hastscript": "^7.2.0",
"unist-util-visit-parents": "^5.1.3"
}
@ -3947,14 +3951,14 @@
}
},
"node_modules/astro": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/astro/-/astro-3.1.0.tgz",
"integrity": "sha512-hVPZg9uDafqJbDwOwtcujwhJ6Qp3BCaIj1cvablTYI0jdYrZSvcybhIMTf8NhzK5smvZy2Bv9eEDYXLpiLDrRQ==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/astro/-/astro-3.1.2.tgz",
"integrity": "sha512-9rlKyk6Qmw50Pc188+ey7JAEYBsJGh5an46AXGPMHIdEkH6YOc4b2z9Rr+TNF8QmM/U+C2ZQFRVQyCKU4i8/pg==",
"dependencies": {
"@astrojs/compiler": "^2.1.0",
"@astrojs/internal-helpers": "0.2.0",
"@astrojs/markdown-remark": "3.2.0",
"@astrojs/telemetry": "3.0.1",
"@astrojs/telemetry": "3.0.2",
"@babel/core": "^7.22.10",
"@babel/generator": "^7.22.10",
"@babel/parser": "^7.22.10",
@ -4104,16 +4108,62 @@
}
},
"node_modules/astro-expressive-code": {
"version": "0.22.2",
"resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.22.2.tgz",
"integrity": "sha512-pmyuTJcEzfYzxPNBsIEjVNTzgWHxDGiv4D/oJusvOm30x7ETADMusqf9uYmJ6rS1jlwAgfaUWm7vTv6SaxWrSw==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.26.0.tgz",
"integrity": "sha512-ZofTdPVTu5yXFJJnwx/GDNwihufuGzUqn/sE1PqDWyDyDADsx28G8VitWH3KMVQ1tRSuc/rm6Y7MRgb/ydS1tA==",
"dependencies": {
"remark-expressive-code": "^0.22.2"
"remark-expressive-code": "^0.26.0"
},
"peerDependencies": {
"astro": "^2.0.0 || ^3.0.0-beta"
}
},
"node_modules/astro-redirect-from": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/astro-redirect-from/-/astro-redirect-from-0.2.1.tgz",
"integrity": "sha512-9pxLhutTVo7mPILrSrROmr5PkzK5qwM5116rYDK4MYEcPGDjoSieoiJ/6+0zNMUzJnmauTFHh6FNgURi16qcVg==",
"dependencies": {
"astro": ">= 3",
"globby": "^13.2.2",
"gray-matter": "^4.0.3"
},
"engines": {
"node": ">=18.14.1",
"npm": ">=6.14.0"
},
"peerDependencies": {
"astro": ">= 3"
}
},
"node_modules/astro-redirect-from/node_modules/globby": {
"version": "13.2.2",
"resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz",
"integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
"dependencies": {
"dir-glob": "^3.0.1",
"fast-glob": "^3.3.0",
"ignore": "^5.2.4",
"merge2": "^1.4.1",
"slash": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/astro-redirect-from/node_modules/slash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
"integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/astro/node_modules/@astrojs/compiler": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.1.0.tgz",
@ -4788,6 +4838,8 @@
},
"node_modules/busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dependencies": {
"streamsearch": "^1.1.0"
},
@ -5001,13 +5053,14 @@
},
"node_modules/ci-info": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
"integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/sibiraj-s"
}
],
"license": "MIT",
"engines": {
"node": ">=8"
}
@ -5844,7 +5897,6 @@
},
"node_modules/dir-glob": {
"version": "3.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"path-type": "^4.0.0"
@ -5855,7 +5907,8 @@
},
"node_modules/dlv": {
"version": "1.1.3",
"license": "MIT"
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
},
"node_modules/dms2dec": {
"version": "1.1.0",
@ -5943,7 +5996,8 @@
},
"node_modules/dset": {
"version": "3.1.2",
"license": "MIT",
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz",
"integrity": "sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==",
"engines": {
"node": ">=4"
}
@ -6958,14 +7012,14 @@
}
},
"node_modules/expressive-code": {
"version": "0.22.2",
"resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.22.2.tgz",
"integrity": "sha512-2KOsjZKx6pRLVhlIo7ikZxL0CJzuvpP4LeGcFiz7YsqUtT3ak4MgEeD1ph82FNp2isl+vnc8OZu1xoGDi9JxMw==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.26.0.tgz",
"integrity": "sha512-1290zk/uHg+1gCiM9TNVl77FZGTTkdlaXDGSJjNffwFlaO6+nF4Mi0zFLKZ0QoPfPlucOF/DwNSVNa74Dxck1g==",
"dependencies": {
"@expressive-code/core": "^0.22.2",
"@expressive-code/plugin-frames": "^0.22.2",
"@expressive-code/plugin-shiki": "^0.22.2",
"@expressive-code/plugin-text-markers": "^0.22.2"
"@expressive-code/core": "^0.26.0",
"@expressive-code/plugin-frames": "^0.26.0",
"@expressive-code/plugin-shiki": "^0.26.0",
"@expressive-code/plugin-text-markers": "^0.26.0"
}
},
"node_modules/extend": {
@ -8158,7 +8212,6 @@
},
"node_modules/ignore": {
"version": "5.2.4",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
@ -11713,7 +11766,6 @@
},
"node_modules/path-type": {
"version": "4.0.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -12857,11 +12909,11 @@
}
},
"node_modules/remark-expressive-code": {
"version": "0.22.2",
"resolved": "https://registry.npmjs.org/remark-expressive-code/-/remark-expressive-code-0.22.2.tgz",
"integrity": "sha512-NwVpKDHiHsD+3CwxDrXA6B2fNttVDK0BBnkHLPQoKNOuEokYWA9+3trZQw77txBGimNLsJQCBl/tddsHen2g8w==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/remark-expressive-code/-/remark-expressive-code-0.26.0.tgz",
"integrity": "sha512-kh50Wk+o/nNLqa1Z+IhGmhbzHZwiwNpAqcoPuQPBwTBqbleehlcw9m8PtHIwxMFhWqfhzXxtJj9TOmwc+AyHrA==",
"dependencies": {
"expressive-code": "^0.22.2",
"expressive-code": "^0.26.0",
"hast-util-to-html": "^8.0.4",
"unist-util-visit": "^4.1.2"
}
@ -13908,6 +13960,8 @@
},
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"engines": {
"node": ">=10.0.0"
}
@ -15101,8 +15155,9 @@
}
},
"node_modules/undici": {
"version": "5.23.0",
"license": "MIT",
"version": "5.25.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.25.2.tgz",
"integrity": "sha512-tch8RbCfn1UUH1PeVCXva4V8gDpGAud/w0WubD6sHC46vYQ3KDxL+xv1A2UxK0N6jrVedutuPHxe1XIoqerwMw==",
"dependencies": {
"busboy": "^1.6.0"
},
@ -16228,7 +16283,8 @@
},
"node_modules/which-pm-runs": {
"version": "1.1.0",
"license": "MIT",
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz",
"integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==",
"engines": {
"node": ">=4"
}

View File

@ -36,8 +36,9 @@
"@astrojs/ts-plugin": "^1.1.3",
"@nanostores/react": "^0.7.1",
"@rainbow-me/rainbowkit": "^1.0.11",
"astro": "^3.1.0",
"astro-expressive-code": "^0.22.2",
"astro": "^3.1.2",
"astro-expressive-code": "^0.26.0",
"astro-redirect-from": "^0.2.1",
"date-fns": "^2.30.0",
"dms2dec": "^1.1.0",
"fast-exif": "^2.0.1",

View File

@ -1,32 +0,0 @@
import { test, expect, vi } from 'vitest'
import fs from 'node:fs/promises'
import { Stats } from 'node:fs'
import { findMarkdownFilesWithRedirects } from './redirect-from'
test('findMarkdownFilesWithRedirects should generate correct redirects', async () => {
const readdirMock = vi.spyOn(fs, 'readdir')
readdirMock.mockResolvedValue(['post1.md', 'post2.md'] as any)
const statMock = vi.spyOn(fs, 'stat')
statMock.mockResolvedValue({ isFile: () => true } as Stats)
const readFileMock = vi.spyOn(fs, 'readFile')
readFileMock.mockResolvedValueOnce(
'---\nredirect_from: ["/old1", "/old2"]\nslug: /new1\n---'
)
readFileMock.mockResolvedValueOnce(
'---\nredirect_from: ["/old3"]\nslug: /new2\n---'
)
// Mock fs.writeFile to do nothing
const writeFileMock = vi.spyOn(fs, 'writeFile')
writeFileMock.mockResolvedValue()
const redirects = await findMarkdownFilesWithRedirects('some/dir')
expect(redirects).toEqual({
'/old1': '/new1',
'/old2': '/new1',
'/old3': '/new2'
})
})

View File

@ -1,75 +0,0 @@
//
// astro-redirect-from
//
import fs from 'node:fs/promises'
import path from 'node:path'
import matter from 'gray-matter'
import ora from 'ora'
import chalk from 'chalk'
const contentDir = 'content/'
const outputFilePath = '.config/redirects.json'
let fileCount = 0
type Frontmatter = { redirect_from?: string[]; slug?: string }
const spinner = ora(
`${chalk.bold('[redirect-from]')} Extract redirects`
).start()
export async function findMarkdownFilesWithRedirects(
dir: string
): Promise<{ [old: string]: string }> {
const redirects: { [old: string]: string } = {}
async function processDir(currentDir: string) {
const items = await fs.readdir(currentDir, { recursive: true })
for (const item of items) {
const itemPath = path.join(currentDir, item)
const stats = await fs.stat(itemPath)
if (
stats.isFile() &&
item.endsWith('.md') &&
!itemPath.includes('links')
) {
const fileContent = await fs.readFile(itemPath, 'utf-8')
const { data: frontmatter }: { data: Frontmatter } = matter(fileContent)
// construct slug from frontmatter or folder name
const postSlug =
frontmatter.slug || `/${itemPath.split('/')[2].substring(11)}`
// Check if the Markdown file has a redirect_from field
if (frontmatter.redirect_from) {
fileCount++
const redirectFromSlugs = frontmatter.redirect_from
for (const slug of redirectFromSlugs) {
// Add entries to the redirects object
redirects[slug] = postSlug
}
}
}
}
}
await processDir(dir)
return redirects
}
try {
const redirects = await findMarkdownFilesWithRedirects(contentDir)
const redirectsJSON = JSON.stringify(redirects, null, 2)
// Write the redirects object to the output file
await fs.writeFile(outputFilePath, redirectsJSON, 'utf-8')
spinner.succeed(
`${chalk.bold('[redirect-from]')} Extracted ${
Object.keys(redirects).length
} redirects from ${fileCount} files to ${outputFilePath}`
)
} catch (error: any) {
spinner.fail(`${chalk.bold('[redirect-from]')} ${(error as Error).message}`)
}