🖼️ added images support
- Should investigate how to resize the image from .md specs
This commit is contained in:
85
lib/image-utils.ts
Normal file
85
lib/image-utils.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
export async function imageExists(imagePath: string): Promise<boolean> {
|
||||
try {
|
||||
const fullPath = path.join(process.cwd(), 'public', imagePath)
|
||||
await fs.access(fullPath)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function getImageDimensions(
|
||||
imagePath: string
|
||||
): Promise<{ width: number; height: number } | null> {
|
||||
try {
|
||||
const fullPath = path.join(process.cwd(), 'public', imagePath)
|
||||
const buffer = await fs.readFile(fullPath)
|
||||
|
||||
if (imagePath.endsWith('.png')) {
|
||||
const width = buffer.readUInt32BE(16)
|
||||
const height = buffer.readUInt32BE(20)
|
||||
return { width, height }
|
||||
}
|
||||
|
||||
if (imagePath.endsWith('.jpg') || imagePath.endsWith('.jpeg')) {
|
||||
let offset = 2
|
||||
while (offset < buffer.length) {
|
||||
if (buffer[offset] !== 0xff) break
|
||||
|
||||
const marker = buffer[offset + 1]
|
||||
if (marker === 0xc0 || marker === 0xc2) {
|
||||
const height = buffer.readUInt16BE(offset + 5)
|
||||
const width = buffer.readUInt16BE(offset + 7)
|
||||
return { width, height }
|
||||
}
|
||||
|
||||
offset += 2 + buffer.readUInt16BE(offset + 2)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function getOptimizedImageUrl(
|
||||
src: string,
|
||||
width?: number,
|
||||
height?: number,
|
||||
quality: number = 75
|
||||
): string {
|
||||
const params = new URLSearchParams()
|
||||
|
||||
if (width) params.set('w', width.toString())
|
||||
if (height) params.set('h', height.toString())
|
||||
params.set('q', quality.toString())
|
||||
|
||||
const queryString = params.toString()
|
||||
return queryString ? `${src}?${queryString}` : src
|
||||
}
|
||||
|
||||
export async function getImageWithPlaceholder(
|
||||
imagePath: string
|
||||
): Promise<{ src: string; width: number; height: number; placeholder?: string }> {
|
||||
const dimensions = await getImageDimensions(imagePath)
|
||||
|
||||
if (!dimensions) {
|
||||
return {
|
||||
src: imagePath,
|
||||
width: 800,
|
||||
height: 600,
|
||||
}
|
||||
}
|
||||
|
||||
const placeholder = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='${dimensions.width}' height='${dimensions.height}'%3E%3Crect width='${dimensions.width}' height='${dimensions.height}' fill='%2318181b'/%3E%3C/svg%3E`
|
||||
|
||||
return {
|
||||
src: imagePath,
|
||||
...dimensions,
|
||||
placeholder,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user