forked from
quillmatiq.com/augment
Fork of Chiri for Astro for my blog
1import { visit } from 'unist-util-visit'
2import { themeConfig } from '../config.ts'
3
4/**
5 * Rehype plugin that processes images in markdown content:
6 * - Wraps images with alt text in figure/figcaption elements
7 * - Adds data-preview attribute for image viewer functionality
8 * - Adds lazy loading for better performance
9 * - Handles multiple images in a single paragraph
10 */
11export default function rehypeImageProcessor() {
12 return (tree) => {
13 visit(tree, 'element', (node, index, parent) => {
14 if (node.tagName !== 'p') {
15 return
16 }
17 if (!parent || typeof index !== 'number') {
18 return
19 }
20
21 const imgNodes = []
22 let hasNonImageContent = false
23
24 for (const child of node.children) {
25 if (child.type === 'element' && child.tagName === 'img') {
26 imgNodes.push(child)
27 } else if (child.type !== 'text' || child.value.trim() !== '') {
28 hasNonImageContent = true
29 }
30 }
31
32 if (hasNonImageContent || imgNodes.length === 0) {
33 return
34 }
35
36 const newNodes = []
37
38 for (const imgNode of imgNodes) {
39 const alt = imgNode.properties?.alt?.trim()
40
41 // Enhanced image properties with performance optimizations
42 imgNode.properties = {
43 ...imgNode.properties,
44 'data-preview': themeConfig.post.imageViewer ? 'true' : 'false',
45 // Add lazy loading for better performance
46 loading: 'lazy',
47 // Add decoding hint for better performance
48 decoding: 'async',
49 // Add fetchpriority for critical images (first image gets high priority)
50 fetchpriority: newNodes.length === 0 ? 'high' : 'auto',
51 class: [...(imgNode.properties.class || []), 'img-placeholder']
52 }
53
54 if (!alt || alt.includes('_')) {
55 newNodes.push(imgNode)
56 continue
57 }
58
59 const figure = {
60 type: 'element',
61 tagName: 'figure',
62 properties: {
63 className: ['image-caption-wrapper']
64 },
65 children: [
66 imgNode,
67 {
68 type: 'element',
69 tagName: 'figcaption',
70 properties: {
71 className: ['img-caption']
72 },
73 children: [
74 {
75 type: 'text',
76 value: alt
77 }
78 ]
79 }
80 ]
81 }
82
83 newNodes.push(figure)
84 }
85
86 if (newNodes.length > 0) {
87 parent.children.splice(index, 1, ...newNodes)
88 return index + newNodes.length - 1
89 }
90 })
91 }
92}