🖼️ added support for links to blogposts and support image sizing from .md files
Some checks failed
Build and Deploy Next.js Blog to Production / 🔍 Code Quality Checks (push) Failing after 31s
Build and Deploy Next.js Blog to Production / 🏗️ Build and Push Docker Image (push) Has been skipped
Build and Deploy Next.js Blog to Production / 🚀 Deploy to Production (push) Has been skipped
Some checks failed
Build and Deploy Next.js Blog to Production / 🔍 Code Quality Checks (push) Failing after 31s
Build and Deploy Next.js Blog to Production / 🏗️ Build and Push Docker Image (push) Has been skipped
Build and Deploy Next.js Blog to Production / 🚀 Deploy to Production (push) Has been skipped
This commit was merged in pull request #7.
This commit is contained in:
@@ -6,6 +6,7 @@ import remarkGfm from 'remark-gfm'
|
||||
import { FrontMatter, Post } from './types/frontmatter'
|
||||
import { generateExcerpt } from './utils'
|
||||
import { remarkCopyImages } from './remark-copy-images'
|
||||
import { remarkInternalLinks } from './remark-internal-links'
|
||||
|
||||
const POSTS_PATH = path.join(process.cwd(), 'content', 'blog')
|
||||
|
||||
@@ -75,6 +76,7 @@ export async function getPostBySlug(slug: string | string[]): Promise<Post | nul
|
||||
publicDir: 'public/blog',
|
||||
currentSlug: sanitized.join('/'),
|
||||
})
|
||||
.use(remarkInternalLinks)
|
||||
.process(content)
|
||||
|
||||
const processedContent = processed.toString()
|
||||
|
||||
67
lib/remark-internal-links.ts
Normal file
67
lib/remark-internal-links.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { visit } from 'unist-util-visit'
|
||||
import { Node } from 'unist'
|
||||
|
||||
interface LinkNode extends Node {
|
||||
type: 'link'
|
||||
url: string
|
||||
children: Node[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects internal blog post links:
|
||||
* - Relative paths (no http/https)
|
||||
* - Not absolute paths (doesn't start with /)
|
||||
* - Ends with .md
|
||||
*/
|
||||
function isInternalBlogLink(url: string): boolean {
|
||||
return (
|
||||
!url.startsWith('http://') &&
|
||||
!url.startsWith('https://') &&
|
||||
!url.startsWith('/') &&
|
||||
url.includes('.md')
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms internal .md links to blog routes:
|
||||
* - tech/article.md → /blog/tech/article
|
||||
* - article.md#section → /blog/article#section
|
||||
* - nested/path/post.md?ref=foo → /blog/nested/path/post?ref=foo
|
||||
*/
|
||||
function transformToBlogPath(url: string): string {
|
||||
// Split into path, hash, and query
|
||||
const hashIndex = url.indexOf('#')
|
||||
const queryIndex = url.indexOf('?')
|
||||
|
||||
let path = url
|
||||
let hash = ''
|
||||
let query = ''
|
||||
|
||||
if (hashIndex !== -1) {
|
||||
path = url.substring(0, hashIndex)
|
||||
hash = url.substring(hashIndex)
|
||||
}
|
||||
|
||||
if (queryIndex !== -1 && queryIndex < (hashIndex === -1 ? url.length : hashIndex)) {
|
||||
path = url.substring(0, queryIndex)
|
||||
query = url.substring(queryIndex, hashIndex === -1 ? url.length : hashIndex)
|
||||
}
|
||||
|
||||
// Remove .md extension
|
||||
const cleanPath = path.replace(/\.md$/, '')
|
||||
|
||||
// Build final URL
|
||||
return `/blog/${cleanPath}${query}${hash}`
|
||||
}
|
||||
|
||||
export function remarkInternalLinks() {
|
||||
return (tree: Node) => {
|
||||
visit(tree, 'link', (node: Node) => {
|
||||
const linkNode = node as LinkNode
|
||||
|
||||
if (isInternalBlogLink(linkNode.url)) {
|
||||
linkNode.url = transformToBlogPath(linkNode.url)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user