跳到主要内容

欢迎来到RSS

· 阅读需 3 分钟

没错,我也要跟绝大部分bloger和互联网复兴运动guy一样安利RSS,话术也无外乎是,RSS更懂你,过滤垃圾社交媒体,重夺注意力之类的话。1

那么,什么是rss,为什么用rss?​

在2026年的今天,几乎所有的社交平台都不尽其用地要把你留在平台里面,而且绝大部分内容都是垃圾信息,看多了就会被塑造得很聪明变弱智,我当然不是说rss订阅的网站博客都是好东西,有不少也是牛鬼蛇神

但最核心的好处是,我们可以自己选择不用被喂屎,这样发现深度连结的内容,才能成为可能(比如我)😊

什么是rss?​

rss是个比社交平台还古早的技术,由网景公司在1999年开发……(我不想听🤚)

简单说它就是主动阅读器,把你自己喜欢的网络信息集成到一个阅读器上,喜欢就留着不喜欢就删掉。

比如把这串神秘代码复制进你的订阅器窗口:

https://pennameco.xyz/blog/rss.xml

(它就会在你的阅读器上显示出来) rss

有什么订阅器选择?​

我完全建议直接用Feedly 这种注册马上能用的订阅器,不过境内网络环境需要科学上网很难连上去,而且还有小广告(虽然不多),其实搞起来也很烦。

那不如一步到位,用FreshRSS直接安装到自己的电脑本地💻,在浏览器就能打开。不需要害怕什么难度,上官网下载源码,然后让ai告诉我们怎么弄就行。

(FreshRSS支持深色模式,无需多言😊)

我的RSS漫游​

不要看我这安利一大轮,我也只是用了几天(现学现卖),但是自从过渡到RSS之后,人精神了,头不痛了,不感冒了。生活都疏朗了起来😄 —- 好了,我的废话讲完了。其实以下blog都讲得比我好,我的观点和结构也是 Ctrl + C 复制他们的,不过这不重要:

你需要用 RSS,不要再拖了
不滑社群媒體還有短影音還可以幹嘛?

起码不用看广告就很爽不是吗?我就是想炫耀一下我新学会的几种语法

什么是WSL?

· 阅读需 2 分钟

顾名思义WSL(Windows Subsystem for Linux)能让你在windows上直接跑linux的代码无需安装虚拟机或双系统。类似大肠包小肠?

简单来说,它让Windows“内核”能直接解析Linux的系统调用,从而原生运行Ubuntu、Debian等Linux发行版。

作为win慢慢过渡到linux的一个试水。

当然了,如果你不需要‘adobe全家桶’或者‘zbursh’那最好就是直接注销windows,安装linux拥抱各种好用的开源软件。

虽然我吹了一大堆,但是我打开最多的其实是cmd,不过可以在cmd里面直接输入‘wsl’然后进入linux模式,这样用终端就会灵活很多。

(直接好处就是能跑linux终端,运行‘ls’这类指令,而且不用再担心c盘挤满)

wsl做不了的事​

它只是增加了linux的终端,很多基于linux的软件是跑不了的,比如MusE Sequencer(大概会变很慢)。


对了,调用终端安装东西的时候,注意保存路径,别把c盘挤爆了(事实上难以避免有些东西默认下载c盘,把他们移动到其他盘就好👌),c盘问题也算是windows的老大难了。

烦恼图片压缩📦

· 阅读需 5 分钟

看看我的画作页面,每次我打包我美好的作品,然后批量压缩的时候,我都挺可惜的。 压缩过的图片会很不精神,细节难免丢失。
如果没看过原图,那确实没什么关系,但是看过原图对比起来,诸如锐度下降,纯度下降,微妙的透明色丢失,尺寸变小都让人沮丧。

可是为什么必须压缩呢? 因为每张图片20多mb那就根本没法读取了(我只用得起3m小水管)。对于图像艺术家真的很苦恼☹️

所以目前方法是尽量用脚本批量成webp,把尺寸锁在2k(2560x1440),质量92%。别人不知道,起码自己观感好很多,读取速度也还能接受。(或者我未来能有效优化吧)

我目前用的压缩jsx是这个👇
路径是: /my-website/scripts/compress-images.js

compress-images.js

const fs = require('fs-extra');
const path = require('path');
const sharp = require('sharp');

// ============ 配置 ============
const SKETCH_DIR = path.join(__dirname, '../static/sketch');
const BACKUP_DIR = path.join(__dirname, '../static/sketch-backup');
const MAX_WIDTH = 2560; // 最大宽度 2560px
const MAX_HEIGHT = 1440; // 最大高度 1440px
const WEBP_QUALITY = 92; // WebP 质量 92%
const WEBP_EFFORT = 6; // 压缩努力程度 0-6
// ==============================

// 支持的图片格式(会被转成 WebP)
const IMAGE_EXTS = ['.png', '.jpg', '.jpeg', '.webp', '.avif'];

// 获取文件大小
function getFileSize(filePath) {
const stats = fs.statSync(filePath);
return stats.size;
}

function formatSize(bytes) {
if (bytes < 1024) return bytes + 'B';
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + 'KB';
return (bytes / (1024 * 1024)).toFixed(2) + 'MB';
}

// 处理单张图片 - 转 WebP
async function processImage(inputPath, backupPath) {
// 备份(如果还没备份过)
if (!fs.existsSync(backupPath)) {
fs.ensureDirSync(path.dirname(backupPath));
fs.copyFileSync(inputPath, backupPath);
console.log(`📦 已备份: ${path.relative(process.cwd(), inputPath)}`);
}

const originalSize = getFileSize(inputPath);
const metadata = await sharp(inputPath).metadata();
const ext = path.extname(inputPath).toLowerCase();
const fileName = path.basename(inputPath, ext);
const dir = path.dirname(inputPath);

// 构建 WebP 输出路径
const webpPath = path.join(dir, fileName + '.webp');

// 开始处理
let pipeline = sharp(inputPath);

// 缩放(如果宽度或高度超标)
if (metadata.width > MAX_WIDTH || metadata.height > MAX_HEIGHT) {
pipeline = pipeline.resize({
width: MAX_WIDTH,
height: MAX_HEIGHT,
fit: 'inside',
kernel: 'lanczos3',
withoutEnlargement: true,
});
}

// 转换为 WebP
pipeline = pipeline.webp({
quality: WEBP_QUALITY,
alphaQuality: WEBP_QUALITY, // 透明通道质量
lossless: false,
effort: WEBP_EFFORT,
nearLossless: false,
smartSubsample: true, // 智能子采样
});

// 写入 WebP 文件
await pipeline.toFile(webpPath);

// 删除原图(如果不是 WebP)
if (ext !== '.webp') {
fs.unlinkSync(inputPath);
} else {
// 如果是 WebP,删除临时文件(实际上就是原文件)
// 但我们已经覆盖了,所以不用额外操作
}

const newSize = getFileSize(webpPath);
const saved = ((originalSize - newSize) / originalSize * 100).toFixed(1);
const ratio = (newSize / originalSize * 100).toFixed(1);

const fromExt = ext !== '.webp' ? ext.toUpperCase().replace('.', '') : 'WebP';
console.log(`🔄 ${fromExt} → WebP: ${path.basename(inputPath)}`);
console.log(` 📊 ${formatSize(originalSize)} → ${formatSize(newSize)} (${ratio}%,节省 ${saved}%)`);

return { webpPath, originalPath: inputPath };
}

// 递归扫描文件夹
async function scanDirectory(dir, backupBaseDir) {
const items = fs.readdirSync(dir);
let processed = 0;
let totalFiles = 0;
let skipped = 0;
let totalSaved = 0;
let totalOriginal = 0;
let converted = 0;

for (const item of items) {
const fullPath = path.join(dir, item);
const stat = fs.statSync(fullPath);

if (stat.isDirectory()) {
// 跳过备份目录
if (fullPath === BACKUP_DIR) continue;

const subBackupDir = path.join(backupBaseDir, item);
const result = await scanDirectory(fullPath, subBackupDir);
processed += result.processed;
totalFiles += result.totalFiles;
skipped += result.skipped;
totalSaved += result.totalSaved || 0;
totalOriginal += result.totalOriginal || 0;
converted += result.converted || 0;
} else {
const ext = path.extname(item).toLowerCase();
if (IMAGE_EXTS.includes(ext)) {
totalFiles++;
try {
const relativePath = path.relative(SKETCH_DIR, fullPath);
const backupPath = path.join(BACKUP_DIR, relativePath);

// 如果是 GIF,跳过
if (ext === '.gif') {
console.log(`⏭️ 跳过 GIF(保留动画): ${path.basename(fullPath)}`);
skipped++;
continue;
}

const originalSize = getFileSize(fullPath);
await processImage(fullPath, backupPath);

// 获取新文件大小
const fileName = path.basename(fullPath, ext);
const dir = path.dirname(fullPath);
const webpPath = path.join(dir, fileName + '.webp');
const newSize = getFileSize(webpPath);

totalSaved += (originalSize - newSize);
totalOriginal += originalSize;
converted++;
processed++;
} catch (err) {
console.error(`❌ 处理失败 ${item}:`, err.message);
}
} else {
skipped++;
}
}
}

return { processed, totalFiles, skipped, totalSaved, totalOriginal, converted };
}

// ============ 主程序 ============
async function main() {
console.log('🚀 开始批量转换 WebP...\n');
console.log(`📊 最大尺寸: ${MAX_WIDTH}×${MAX_HEIGHT}px`);
console.log(`📊 WebP 质量: ${WEBP_QUALITY}%`);
console.log(`📊 压缩努力度: ${WEBP_EFFORT}/6\n`);

if (!fs.existsSync(SKETCH_DIR)) {
console.error('❌ 找不到 static/sketch 目录');
process.exit(1);
}

console.log('📊 正在扫描...');
const result = await scanDirectory(SKETCH_DIR, BACKUP_DIR);

const totalMB = (result.totalOriginal / (1024 * 1024)).toFixed(1);
const savedMB = (result.totalSaved / (1024 * 1024)).toFixed(1);
const finalMB = ((result.totalOriginal - result.totalSaved) / (1024 * 1024)).toFixed(1);
const savedPercent = result.totalOriginal > 0 ? (result.totalSaved / result.totalOriginal * 100).toFixed(1) : 0;

console.log('\n' + '='.repeat(50));
console.log(`✅ 全部完成!`);
console.log(` 📁 转换了 ${result.converted} 张图片为 WebP`);
console.log(` 📁 处理了 ${result.processed} 张图片`);
console.log(` 📁 共 ${result.totalFiles} 张图片(跳过 ${result.skipped} 张)`);
console.log(` 📊 总大小: ${totalMB}MB → ${finalMB}MB`);
console.log(` 📊 节省: ${savedMB}MB (${savedPercent}%)`);
console.log(` 📁 原图备份在: ${BACKUP_DIR}`);
console.log(`\n💡 所有图片已转换为 .webp 格式!`);
console.log(`💡 如果效果不满意,可以从备份恢复:`);
console.log(` cp -r ${BACKUP_DIR}/* ${SKETCH_DIR}/`);
}

main().catch((err) => {
console.error('❌ 程序出错:', err.message);
process.exit(1);
});

在根目录运行以下终端指令,他会生成一个备份文件夹📂,你也可以做成bat或者其他脚本。

npm run compress

以下听不懂,直接把上面的脚本扔给ai改

📌 使用前注意 依赖:fs-extra 和 sharp,运行前先装:

npm install fs-extra sharp

图片默认放在 static/sketch/ 下,如果你的图片在其他地方,修改脚本开头的 SKETCH_DIR 和 BACKUP_DIR 就行。 在 package.json 的 scripts 里加一行:

"compress": "node scripts/compress-images.js"

然后 npm run compress 就能跑了(大概)。

鸡是我们最好吃的朋友🐔

· 阅读需 2 分钟
⤵ 这是这个有益身心活动的推广,他们并没有逼我写

本文参与「BlogBlog 同乐会 - 2026 年 7 月」主题「有趣的小知识或冷门概念」,主持人刘昕。
如果你也有部落格且恰好看到这里,欢迎一起来玩。

基于广东人对于鸡的热爱,自然是要八卦一下跟鸡🐔有关的概念,比如以下的肉鸡:

什么是肉鸡🐔?​

这是一个网络安全黑话,形容黑客入侵他人的服务器(电脑)然后进行控制和破坏,那个被操控的电脑就是肉鸡。至于为什么叫‘肉鸡’而不是‘肉鸭’,大概是因为黑客也喜欢吃鸡。

而这种现象meme化之后就会变成神经肉鸡🐔,如果你能理解这是什么发神经的蠢东西的话😄
事实上也可以玩这么一个文字游戏,x + 肉鸡 =:

x结果
电子电子肉鸡
赛博赛博肉鸡
文化文化肉鸡
算法算法肉鸡
神经神经肉鸡
社畜社畜肉鸡
存在存在肉鸡
味觉味觉肉鸡
记忆记忆肉鸡
……发挥脑洞,任意版本😄

然后就可以在得到的缝合名词里面一顿胡扯。

比如“存在肉鸡”大概是这么个东西:
你觉得自己在生活,其实是被生活养殖。每天按时进食(上班)、保持清洁(洗澡)、偶尔放风(周末),看似自由,但围栏一直都在。你不知道养殖者是谁——可能是系统,可能是资本,可能只是“大家都这样”。你偶尔会抬头看看天空,然后低头继续吃。这就是存在肉鸡。

至于,为什么又写废话,大概是我很爱吃鸡🐔

鱼与鱼与鱼🐟️

· 阅读需 1 分钟

我很喜欢吃鱼,当然也很喜欢看鱼,各种各样的鱼,特别是放在蓝色的玻璃箱里面的鱼,看起来就很好吃🍗

至于养鱼,我应该不会去养的,我小时候养过,千禧年前后曾经风靡过养鱼热。 特别是广州,这里可是有全中国最大的观赏鱼养殖基地,还有花鸟鱼虫市场。

一个市场叫花鸟鱼虫市场,那得有多少的花鸟鱼虫😊

对了,说回来。 养鱼其实是一件很劳累的爱好,换水,养水生态,再到鱼与鱼,鱼与海藻,鱼与珊瑚,珊瑚与海藻,鱼与海藻与珊瑚,都有关系。

当然了,这只是我在瞎吹,可能严重复杂化了。对于喜欢的人,熟练的,其实就是养好水,日常清洁。

OK,简而言之,我就是喜欢吃鱼 鲟鱼 对了,来看看(想象一下)我最近拍摄的鱼鱼图鉴👀 !(鲟鱼) !(多宝鱼) !(生鱼) !(海鲈鱼) !(鲍鱼) !(鲸鱼) !(人鱼)

哈哈,还有什么好吃的鱼,欢迎大家告诉我。

绘画与数云

· 阅读需 1 分钟

前期概念设计与涂鸦速写共享一个好状态,轻松随意,相信直觉。我觉得最好的进入方式就是数云☁️。面包云,鸡腿云,人头云,马云🐎,腾讯云☁️(腾讯给我结帐)。精细化,恰恰是影响认知的最大敌人,久而久之容易导致思维僵化,所以画外包或许是很糟糕的工作(暴论👋)。 总之,放轻松,别紧张,你看我画得多丑👇 数云图

生鱼片的意识形态享乐🍣

· 阅读需 5 分钟

你爱吃生鱼片吗?我是很爱的,特别是油甘鱼🐟️,学名叫做鰤鱼,当然要是寒狮鱼🐟️那就更好了,不过我通常吃不起👋 我连不上wiki,百度又太丑,所以我找了两个我喜欢的网站链接🔗 当然,我也爱吃寿司郎的便宜刺身肉,诸如:帆立贝🐚、赤背、章鱼🐙、还有很多。

到了天气冷了,有闲钱的时候我就会订购一条油甘鱼🐟回来,自己放血,自己开鱼🔪。

说到底操作也不过是尾巴切一刀🔪,把水管针插进尾巴大动脉里面,血就会从鱼鳃那里反向涌出来,水和环境是要越冰越好🧊 切下来的整块鱼肉要包裹厨房纸,扔进冰箱冷藏熟成两天左右🥩,这样出来的生鱼片就会很好吃😋

说饿了,开始意识形态享乐环节👀 我跟ai探讨过基于列维.斯特劳斯关于生与熟的文化介入和烹饪三角理论🍳,那纯属鬼扯。

这是ai说的怪话
  1. 烹饪三角:生食的“合法地位” 列维-斯特劳斯发现,几乎所有文化都通过“烹饪”来标记自己与“自然”的区别。他提出了一个经典的烹饪三角: 生的(自然):未经人类处理的原材料。 熟的(文化):通过“烤”或“煮”等手段,彻底破坏自然状态,这是最明确的文明标志。 “生食”(介于自然与文化之间):比如鱼生、腌肉、发酵食品。它们没有被火彻底改造,但在入口前经历了切割、摆盘、蘸料(文化符号) 的过程。 所以,爱吃鱼生的第一个秘密在于:它既保留了“自然”的新鲜本味(满足对原始的隐秘向往),又通过极其精致的刀工和仪式感,牢牢掌控了“文化”的主动权。 这比把肉彻底煮熟,更需要技艺和心智。
  2. 心理根源:对“快速腐败”的征服 我们爱吃猪牛鸡的熟肉,却偏爱生食鱼类和贝类,这背后有一个非常现实的结构性原因: 陆地恒温动物(猪牛鸡):体内环境温暖,一旦死亡,细菌繁殖极快,寄生虫风险高,生吃往往伴有强烈的腥臊味。 水生冷血动物(鱼虾蟹):它们生活在低温环境,死亡后腐败速度相对较慢,且鱼类寄生虫多数不适应人体体温,风险相对可控(当然,淡水产仍有风险)。 因此,人选择生食鱼类,实际上是人类在漫长试错中,摸清了“自然规律”的结构性边界。 这不是无所畏惧的野蛮,而是建立在精准知识上的、对腐朽时间的短暂胜利。
  3. 符号学意义:“原味”是一种高级文化追求 在东亚文化(尤其是日本料理)中,鱼生被赋予了极高的哲学意味: 追求“无”与“本真”:一片完美的金枪鱼刺身,极力淡化烹饪者的存在感,让食材自身说话。这和海德格尔追求的“让物如其所是地显现”有异曲同工之妙。 技术即克制:切鱼生的刀法(比如“本造”),不是为了炫技,而是为了顺应鱼肉本身的纹理。这种极致的克制,恰恰是人类文化达到高度复杂后,才会产生的审美偏好——即用最少的“文化干预”,去呈现最纯粹的“自然之美”。 总结:这是“结构”的高级玩法 回到列维-斯特劳斯的视角:人类并不满足于简单地“吃熟食”。我们伟大的心智,总是在不断地探索 “自然”与“文化”之间的灰色地带。 彻底煮熟(烤/煮)是过度介入。 茹毛饮血是毫无介入。 而鱼生,是精妙地踩在那条边界线上——生而未熟,却已是极致的文化造物。

这个观点就很蠢了,现代活剔鱼类技术的文化密度可不比铁锅炖肉低,不过大概看完已经力竭了,也不想说些什么😮‍💨

这让我联系到另一种生的食物, 鞑靼牛肉🥩, 无菌有机鸡蛋配新鲜欧洲香草🌿,地中海黑胡椒拌730天草饲高级安格斯牛肉🐮,一大轮商业包装, 简称饺子馅🥟,不煮熟的生拌饺子馅。

同样的东西,不同的“包装” 在巴黎小馆子里:它叫“Steak Tartare”,配上一颗生蛋黄,旁边搁几根炸薯条,卖你20多欧元。食客用小勺子优雅地挖着吃,谈论的是存在主义或新浪潮电影。 在北方家庭的厨房里:它叫“猪肉大葱馅”或“牛肉胡萝卜馅”,加盐、酱油、香油、姜末,顺时针搅上劲。主妇用手指沾一点尝咸淡,然后包进擀好的面皮里,下锅煮熟。 内容物几乎一样——都是调好味的、可生食级别的优质生肉糜(或许吧,不吃坏肚子没人知道,吃坏了也不代表不能生食,单纯有人好这口👌)

价格差异就体现在仪式感和环境,文化符号叠加,统称文化定价权。

所以干嘛不好好吃饭扯这么多呢?🍚 我上面扯这么一大轮,就叫做意识形态享乐😊

其实说白了,我们吃这个,明知道它就是假装高级的饺子馅,但这不正说明,我们享受的就是那套‘假装它不是’的仪式感嘛😄

椰林树影,水清沙幼🌴

· 阅读需 1 分钟

“椰林树影,水清沙幼,坐落于印度洋的世外桃源……” 以上台词出自麦兜🐷,具体是不是这样形容那个想象中的马尔代夫,我不记得了。 今天去西郊泳场游泳,实际上是去玩水,那白白的沙,咸湿的珠江海风(姑且叫海风),七月的热浪🌊。就莫名其妙地回忆起这么一句话。

没有眼镜🤓,视野朦胧,都是融在一起的色块。氛围很好,池水很脏。

我记得一个小孩,橙色的色块,没有细节,蓝绿色池水,夜空中一条白色的水线。 还有很多水,很多沙,很多黑色。 水枪好玩 晚9点结束,浑身酸软,卷蛇铺地🐍。一顿夜宵,归家睡。 经典没运动,但是愉悦心灵👋

让人炸毛的zen缓存污染😖

· 阅读需 4 分钟

到我写完的时候,这个Qr_Code的功能已经实现了😊,就在文章的右下角! 不过欢迎大家看我怎么翻车,下面就是我的踩坑实录了,看看我是怎么一步步实现的:

本来想给小花园增加一个Qr_Code的功能🌼,docusaurus项目里面的环境和脚本都好好的,结果是渲染用的zen浏览器缓存污染,导致一直报错。我前后把我的脚本删来改去都无效,甚至把小花园的docusaurus文件夹删除,重新解压备份都无效。真的很吓人😟

除了这个问题,我还是很推荐大家用zen浏览器毕竟它侧边栏和多工作区真的很顶👍 坏蛋浏览器 不过用edge本地渲染居然什么事没有,整了几个小时,得到一个教训。

还是要多备份版本,不要任何偷懒。不然多年积累就没了。 也要保留一些好像挺落后的浏览器,不然严重误导判断。这种策略倒也不止适用于浏览器✅。

最后这个Qr_Code功能都不知道算不算实现到,显示了,报错,删掉了。回滚,什么都没实现,得到了一个教训,然后留在我认知里面曾经有一段Qr_Code. 已经实现了啦😄

这段是AI复盘,既然协作跑一轮了,那就偷懒不自己写了😄
流程大概是:

第一步
在docusaurus根目录打开终端(直接 cmd):

npm install qrcode.react

第二步 在src/components新建QrCode.js 让 AI 调取代码填写 在 src/theme 新建一个 BlogPostItem.js,让 AI 调取代码填写,把二维码挂到文章底部。

第三步 启动 npm run start,Zen 报错,Edge 正常。 开始怀疑代码、怀疑环境、怀疑人生。

第四步 删除 QrCode.js,删除 BlogPostItem.js,删除 .docusaurus,删除 node_modules/.cache,重装依赖,重启电脑,依然报错。

第五步 回滚整个项目,解压备份,依然报错。 开始觉得“小花园要塌了”。

第六步 在 Edge 打开 localhost:3000,一切正常。 意识到不是代码的问题,是 Zen 的缓存污染。

第七步 清空 Zen 所有缓存、Cookie、Service Worker、Code Cache,甚至 about:support 里重置浏览器。 依然报错。

第八步 放弃 Zen,改用 Edge 开发。 二维码功能在 Edge 上正常工作。

第九步 把 QrCode 改到最小尺寸 40,透明背景,右对齐,文案改成“神经肉鸡传播源”。 像一枚印章,安静地盖在每篇文章末尾。

第十步 决定保留这个功能,但不纠结 Zen。 把 QrCode.js 和 BlogPostItem.js 加上 .bkd 后缀,需要的时候再改回来。

功能实现了,但没完全实现。 教训比代码更值钱:

多备份版本

不要迷信单一浏览器

缓存是隐形敌人

有些问题不是你的问题,是工具的问题
---
我把跑通的脚本代码也给你们👇

QrCode.js

路径是src/components/QrCode.js

import React from 'react';
import { QRCodeSVG } from 'qrcode.react';
import { useLocation } from '@docusaurus/router';

export default function QrCode({ url, size = 50 }) {
const location = useLocation();

// 只在博客详情页显示(路径匹配 /blog/xxx)
const isBlogPost = /^\/blog\/[^/]+$/.test(location.pathname);
if (!isBlogPost) return null;

const targetUrl = url || (typeof window !== 'undefined' ? window.location.href : '');
if (!targetUrl) return null;

return (
<div style={{ margin: '12px 0', textAlign: 'right' }}>
<QRCodeSVG
value={targetUrl}
size={size}
bgColor="transparent"
fgColor="currentColor"
level="H"
/>
<p style={{ fontSize: '10px', color: 'var(--ifm-color-emphasis-600)', marginTop: '4px' }}>
扫码分享本文
</p>
</div>
);
}

BlogPostItem.js

路径是src/theme/BlogPostItem.js

import React from 'react';
import OriginalBlogPostItem from '@theme-original/BlogPostItem';
import QrCode from '@site/src/components/QrCode';

export default function BlogPostItemWrapper(props) {
return (
<>
<OriginalBlogPostItem {...props} />
<QrCode />
</>
);
}
总而言之,现在看到右下角有个小印章,超炫酷的👉