
不理解为什么这么多人用都没有自动首图封面这个功能,百度搜了好久都没见到,最后害得我自己出马,以下是过程,我自己也保存记录
位置:
/theme/butterfly/scritps/fliter/random_cover.js
(其他主题自己找位置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
| /** * Random cover for posts */
'use strict'
hexo.extend.generator.register('post', locals => { // 用于记录最近使用的封面索引 const recentIndexes = [] // 最大历史记录长度 let maxHistorySize = 3
const getRandomCover = defaultCover => { if (!defaultCover) return false if (!Array.isArray(defaultCover)) return defaultCover
const coverCount = defaultCover.length if (coverCount === 1) return defaultCover[0]
// 动态计算最大历史记录长度 maxHistorySize = Math.min(coverCount - 1, 3) // 创建可用索引池 const availableIndexes = [] for (let i = 0; i < coverCount; i++) { if (!recentIndexes.includes(i)) { availableIndexes.push(i) } }
// 从可用池中随机选择 const randomIndex = availableIndexes.length > 0 ? availableIndexes[Math.floor(Math.random() * availableIndexes.length)] : Math.floor(Math.random() * coverCount)
// 更新历史记录 recentIndexes.push(randomIndex) if (recentIndexes.length > maxHistorySize) { recentIndexes.shift() }
return defaultCover[randomIndex] }
// 提取文章内容中的第一张图片 const extractFirstImage = content => { if (!content) return null // 匹配Markdown图片语法 const mdRegex = /!\[.*?\]\((.*?)\)/ const mdMatch = content.match(mdRegex) if (mdMatch && mdMatch[1]) return mdMatch[1] // 匹配HTML img标签 const htmlRegex = /<img\s+.*?src=['"](.*?)['"]/ const htmlMatch = content.match(htmlRegex) if (htmlMatch && htmlMatch[1]) return htmlMatch[1] return null }
// 处理防盗链图片 - 替换为本地路径或代理 const processAntiLeechImage = (url, postPath) => { const imgTestReg = /\.(png|jpe?g|gif|svg|webp|avif)(\?.*)?$/i // 如果是相对路径,转换为绝对路径 if (url.startsWith('/')) { return url; } // 如果是本地图片且开启了post_asset_folder if (hexo.config.post_asset_folder && !url.includes('://') && imgTestReg.test(url)) { return `${postPath}${url}`; } // 处理已知防盗链域名 const antiLeechDomains = [ 'cdn.jsdmirror.com' // 可以在此添加其他防盗链域名 ]; // 检查是否是需要处理的防盗链图片 const isAntiLeech = antiLeechDomains.some(domain => url.includes(domain)); if (isAntiLeech) { // 方案1: 使用本地代理 (需要您自己实现代理功能) // return `/image-proxy?url=${encodeURIComponent(url)}`; // 方案2: 替换为占位图 // return 'https://via.placeholder.com/800x400?text=Cover+Image'; // 方案3: 跳过不使用 return null; } return url; }
const handleImg = data => { const imgTestReg = /\.(png|jpe?g|gif|svg|webp|avif)(\?.*)?$/i let { cover: coverVal, top_img: topImg } = data
// 处理top_img路径 if (hexo.config.post_asset_folder) { if (topImg && topImg.indexOf('/') === -1 && imgTestReg.test(topImg)) { data.top_img = `${data.path}${topImg}` } }
// 如果明确设置cover为false,直接返回 if (coverVal === false) return data
let extractedCover = null // 尝试提取文章内容中的第一张图片 if (!coverVal && data.content) { extractedCover = extractFirstImage(data.content) // 处理防盗链图片 if (extractedCover) { extractedCover = processAntiLeechImage(extractedCover, data.path) } }
// 处理用户设置的封面路径 if (hexo.config.post_asset_folder && coverVal) { if (coverVal.indexOf('/') === -1 && imgTestReg.test(coverVal)) { coverVal = `${data.path}${coverVal}` } }
// 如果封面未设置,尝试使用提取的图片或随机封面 if (!coverVal) { const { cover: { default_cover: defaultCover } } = hexo.theme.config const randomCover = getRandomCover(defaultCover) // 优先使用提取的文章图片,其次使用随机封面 data.cover = extractedCover || randomCover || false } else { data.cover = coverVal }
// 如果封面是图片URL,设置封面类型 if (data.cover && (data.cover.indexOf('//') !== -1 || imgTestReg.test(data.cover))) { data.cover_type = 'img' }
return data }
// 处理文章列表 const posts = locals.posts.sort('date').toArray() const { length } = posts
return posts.map((post, i) => { if (i) post.prev = posts[i - 1] if (i < length - 1) post.next = posts[i + 1]
post.__post = true
return { data: handleImg(post), layout: 'post', path: post.path } }) })
|
配合我的语雀简直完美,自动固定连接,自动封面图,每次写个日常还要写 md 格式,关键语雀还反人类,每次复制封面图链接他都会自带超链接,还取消不掉,简直反人类,一带超链接,封面图必错,无限循环,真的折磨,现在好了,哈哈哈哈,我的博客说说