FNF模组开发指南:从Psych Engine搭建到叙事驱动模组创作
如果你是一位独立游戏开发者或者对《Friday Night Funkin》FNF这款现象级音乐节奏游戏及其庞大的模组Mod社区有所关注那么你一定对“Bikini-Horrors”这个名字不陌生。它早已不是简单的角色皮肤替换而是演变成了一个拥有独立世界观、原创角色和高质量原创曲目的“模组宇宙”。当社区里讨论“谁的意识又被上传了”时老玩家们会心一笑新玩家则可能一头雾水。这篇文章要解决的正是这个核心问题“Bikini-Horrors”模组系列究竟在讲一个什么故事它为何能吸引如此多的创作者和玩家我们将以最新释出的纯享曲目《pop-a-corn》为切入点不仅带你解析这个充满克苏鲁与赛博格元素的模组宇宙更会深入其技术核心——如何基于开源FNF引擎构建一个拥有完整叙事、独特美术和原创音乐的模组。对于开发者而言这远不止是“玩个Mod”。你将看到一个模组如何从创意发展为系列理解其世界观架构和叙事手法。原创内容的技术实现路径从角色动画、曲目谱面到特殊游戏机制。社区驱动的创作生态学习如何像“Bikini-Horrors”团队一样利用开源工具链和社区协作将个人兴趣项目打造成具有影响力的作品。读完本文你将能清晰地把握“Bikini-Horrors”的魅力所在并获得一套可复用的、基于FNF引擎进行高质量模组开发的技术框架与创作思路。1. “Bikini-Horrors”模组宇宙不止于换皮而是叙事驱动的新体验在众多FNF模组中“Bikini-Horrors”系列之所以脱颖而出关键在于它构建了一个自洽且持续扩展的原创世界观。它跳出了原版“Boyfriend挑战各路音乐人”的框架引入了一个更为黑暗、复杂的科幻惊悚设定。核心设定解析 这个世界观的核心矛盾围绕着“意识上传”与“现实扭曲”。在“Bikini-Horrors”的叙事中存在一个被称为“系统”或某个类似母体的虚拟空间。许多角色的“意识”被以各种方式“上传”或“困”在这个空间里他们可能保留部分记忆但形态和本质已被改变。德芙Dove作为该系列的核心角色之一她的故事线就深刻体现了这一点——她并非简单的对手而是一个意识被困于数字牢笼不断挣扎并影响现实的复杂存在。《pop-a-corn》作为一首“纯享曲目”通常指不包含完整对局故事专注于音乐和视觉表现的关卡其发布往往服务于两个目的一是补充角色设定或某个剧情片段的氛围二是展示团队在美术、动画和音效设计上的最新技术力。这首曲目的标题本身就带有一种扭曲的童趣感暗示其内容可能关联着某个角色被扭曲的童年记忆或意识碎片。对玩家而言体验“Bikini-Horrors”模组是在玩一个带有强叙事性的互动音乐短片对开发者而言研究它则是学习如何在一个节奏游戏框架内实现跨媒体的叙事表达。2. FNF模组开发基础理解引擎与工作流在深入“Bikini-Horrors”的具体实现前必须了解其基石——FNF开源引擎。目前社区主流使用的是基于HaxeFlixel框架开发的版本。Haxe是一种跨平台编程语言而Flixel是一个2D游戏框架这使得FNF模组理论上可以编译到Windows、Mac、Linux甚至网页端。核心开发组件源代码由原版游戏开发者ninjamuffin99等人开源在GitHub上。这是所有模组的起点。Psych Engine目前最流行、功能最强大的社区改良版引擎。它提供了更多便于模组开发者使用的功能如更灵活的动画系统、内置的关卡编辑器、增强的视觉特效Shader支持等。“Bikini-Horrors”这类高质量模组几乎都基于或兼容Psych Engine。开发工具链Visual Studio Code / IntelliJ IDEA用于编写Haxe代码。Adobe Animate / Krita / Aseprite用于绘制角色、背景精灵图Sprite。FL Studio / Ableton Live / Bosca Ceoil用于创作芯片音乐Chiptune、Funk等曲风。Audacity用于音频剪辑与处理。模组的基本构成 一个标准的FNF模组文件夹通常包含以下结构YourModName/ ├── assets/ │ ├── data/ # 曲目数据.json文件定义谱面、速度、事件等 │ ├── images/ # 所有图片资源角色、背景、UI等 │ ├── music/ # 音乐文件.ogg格式 │ ├── sounds/ # 音效文件.ogg格式 │ └── videos/ # 过场动画.mp4/.webm格式 ├── mods/ # 模组列表声明文件 └── _polymod_meta.json # Polymod模组加载库的元数据文件理解这个结构是创作任何自定义内容的第一步。3. 环境准备搭建你的FNF模组开发环境假设我们使用最流行的Psych Engine 0.7.1h版本作为开发基础。以下是在Windows系统上搭建环境的完整步骤。3.1 安装必要软件Git: 用于克隆代码仓库。从 git-scm.com 下载并安装。Haxe 4.2.5: Psych Engine推荐的版本。从 haxe.org 下载安装包安装时务必勾选“添加到系统路径”。Visual Studio Code: 轻量级代码编辑器。安装后需要添加Haxe扩展插件Haxe Extension Pack。3.2 获取Psych引擎源代码打开命令提示符CMD或PowerShell执行以下命令# 克隆Psych Engine官方仓库 git clone https://github.com/ShadowMario/FNF-PsychEngine cd FNF-PsychEngine # 安装Haxe依赖库 haxelib install lime haxelib install openfl haxelib install flixel haxelib run lime setup flixel haxelib run lime setup haxelib install flixel-tools haxelib install flixel-ui haxelib install hscript haxelib install polymod # ... 安装其他所有PsychEngine所需的库具体列表请参考仓库README.md haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc3.3 测试编译与运行安装完所有依赖后尝试编译游戏# 对于Windows目标平台 lime build windows如果编译成功你会在export/release/windows/bin目录下找到可执行文件。你也可以使用VSCode的调试功能直接运行。至此一个纯净的Psych Engine开发环境就搭建完成了。接下来我们将在此之上创建属于我们自己的模组。4. 创建你的第一个模组从复制结构到添加角色我们不直接复制“Bikini-Horrors”的复杂内容而是通过创建一个包含简单原创角色的迷你模组来理解整个流程。4.1 初始化模组文件夹在游戏根目录的mods文件夹下新建一个文件夹例如MyFirstHorrorMod。然后按照基础结构创建子文件夹。FNF-PsychEngine/ └── mods/ └── MyFirstHorrorMod/ ├── assets/ │ ├── data/ │ ├── images/ │ │ └── characters/ │ ├── music/ │ └── sounds/ ├── mods/ │ └── MyFirstHorrorMod.txt # 模组声明文件 └── _polymod_meta.json4.2 制作角色精灵图Sprite角色动画需要一套精灵图。以“空闲Idle”动画为例你需要绘制角色在对话时的循环动画帧通常2-4帧。将图片导出为PNG格式命名规范如MyCharacterIdle.png并放入images/characters/目录。4.3 编写角色元数据XMLPsych Engine使用XML文件定义角色的动画、位置、相机焦点等。在images/characters/下创建MyCharacter.xml。?xml version1.0 encodingutf-8? texture sprite nameMyCharacter x0 y0 width300 height400 frame-x300 frame-y400/ anim nameidle loopstrue frame name0 x0 y0/ frame name1 x300 y0/ frame name2 x600 y0/ /anim anim namesingLEFT loopsfalse frame name0 x0 y400/ /anim !-- 定义singDOWN, singUP, singRIGHT等动画 -- offsets point namecamera x0 y-100/ !-- 相机偏移 -- point namesing x0 y0/ !-- 音符判定线偏移 -- /offsets /texture这个文件告诉游戏精灵图的大小、每个动画帧的坐标、动画如何播放以及角色在屏幕上的对齐点。4.4 在曲目数据中引用角色模组的核心体验发生在“周目”Week和“曲目”Song中。我们需要创建一个曲目数据JSON文件。在assets/data/下创建pop-a-corn/文件夹致敬我们的主题然后创建pop-a-corn.json。{ song: { song: pop-a-corn, notes: [], // 谱面数组此处暂空 bpm: 150, needsVoices: true, player1: bf, // 玩家角色 player2: mycharacter, // 对手角色对应XML文件名不含后缀 gfVersion: gf, stage: stage, speed: 2.5 } }同时你需要将对应的音乐文件pop-a-corn.ogg和pop-a-corn-Instrumental.ogg放入assets/music/下的同名文件夹中。4.5 注册模组最后在mods/MyFirstHorrorMod.txt中声明模组MyFirstHorrorMod在_polymod_meta.json中定义元数据{ title: My First Horror Mod, description: A test mod inspired by horror mod aesthetics., author: YourName, version: 0.1.0 }启动游戏在“自由模式”Freeplay中你应该就能找到并游玩这首《pop-a-corn》了尽管目前它还没有谱面。5. 实现核心玩法谱面制作与事件脚本谱面是节奏游戏的灵魂。FNF使用JSON数组来定义每一个需要按下的音符。5.1 理解谱面JSON结构打开pop-a-corn.json我们来填充notes数组。一个最简单的谱面片段如下notes: [ { sectionNotes: [ // 一个小节内的音符 [0, 0, 0], // [时间戳(毫秒), 方向(0左1下2上3右), 长度(毫秒0为普通音符)] [500, 2, 0], [1000, 1, 0], [1500, 3, 0] ], lengthInSteps: 16, // 小节长度步数 typeOfSection: 0, // 小节类型 mustHitSection: true // 是否为玩家小节true则玩家唱false则对手唱 } ]手动编写JSON极其繁琐因此社区开发了强大的谱面编辑器。Psych Engine内置了编辑器你可以通过修改源代码Main.hx中的初始状态或直接在游戏内按F7调试模式开启时进入编辑器界面进行可视化编辑。5.2 添加特殊事件与脚本“Bikini-Horrors”模组的沉浸感很大程度上来自其复杂的视觉特效和剧情事件。这在Psych Engine中通过events数组实现。events: [ [ // 事件数组 [12345, [[Change Character, gf, monster-gf]]], // 在12345毫秒处将GF角色切换为monster-gf [56789, [[Play Animation, mycharacter, singLEFT, true]]], // 触发对手的特定动画 [100000, [[Camera Follow Pos, 500, 300]]] // 移动镜头焦点 ] ]更高级的效果需要编写Haxe脚本。你可以在模组文件夹中创建scripts/目录放置自定义的.hx脚本文件然后在事件中调用它们实现诸如屏幕抖动、颜色变换、滤镜切换等复杂效果这正是营造“Horror”氛围的关键。6. 运行测试与调试开发过程中频繁测试是必须的。实时重载Psych Engine支持模组资源的热重载。在游戏运行时修改完JSON、图片或音效后按Ctrl R可以重新加载当前模组无需重启游戏。调试菜单在调试模式下编译时定义debug标志游戏中按F1可以打开调试菜单用于快速跳转曲目、切换角色、无敌模式等。日志查看游戏运行日志对于排查错误至关重要。在Windows上日志通常输出在控制台窗口或logs/文件夹下的文本文件中。Haxe的编译错误也会在此显示。一个完整的测试流程是编写谱面 - 按CtrlR重载 - 游玩测试 - 发现音符 timing 不准或事件不触发 - 查看日志定位错误 - 修改代码/数据 - 再次重载测试。7. 常见问题与排查思路问题现象可能原因排查方式解决方案游戏启动崩溃提示“找不到类”Haxe依赖库未安装或版本不对检查命令行中haxelib install所有库是否成功对比Psych引擎README的版本要求重新安装指定版本的Haxe和库确保路径正确模组在游戏列表中不显示mods.txt文件命名错误或格式不对_polymod_meta.json缺失检查mods/文件夹下的.txt文件名是否与模组文件夹名一致文件内容是否为单行模组名确保文件结构正确名称无拼写错误角色图片显示为紫色/黑色方块图片路径错误或XML解析失败检查图片是否在正确路径XML中sprite的尺寸和帧坐标是否正确使用图片编辑软件确认图片尺寸仔细核对XML中的像素坐标音乐无法播放音频文件格式不是.ogg或比特率/采样率不标准确认文件格式尝试用Audacity等软件将音频导出为OGG Vorbis格式质量设置为5约160kbps统一使用.ogg格式并检查JSON中song字段名与文件名是否匹配谱面音符严重错位BPM每分钟节拍数设置错误或时间戳计算有误使用谱面编辑器重新检查BPM确认音符时间戳是毫秒且基于曲目开始时间在编辑器中播放并对照音乐调整优先使用编辑器生成时间戳而非手动计算自定义事件不触发事件JSON语法错误或事件类型字符串拼写错误检查events数组的嵌套格式对照Psych引擎Wiki上的事件列表核对事件名从一个简单事件如[Hello!]文本事件开始测试逐步复杂化8. 从模仿到创新打造“Bikini-Horrors”级别模组的最佳实践分析“Bikini-Horrors”的成功可以总结出以下对开发者至关重要的实践建议叙事先行设定驱动不要先做谱面再编故事。像设计独立游戏一样先撰写核心设定、角色小传和关键情节。这能保证所有美术、音乐和关卡设计都服务于统一的主题。建立视觉风格指南确定你的模组的主色调、光影风格和角色设计规范。是像素风还是高清手绘是冷色调的赛博格还是暖色调的复古恐怖一致性是提升质感的关键。音频设计与音乐同等重要除了高质量的原创曲目环境音效、角色语音、UI反馈音效都至关重要。它们共同构建了游戏的听觉沉浸感。使用Audacity进行降噪、均衡和混音处理。善用引擎特性但别被限制深入Psych Engine的源码了解其事件系统、着色器Shader接口。你可以通过修改Stage.hx或自定义脚本实现独一无二的视觉效果如CRT扫描线、噪点滤镜、颜色偏移等。版本控制与团队协作使用Git管理你的模组项目。即使是一个人开发Git也能帮你回溯历史版本。如果是团队合作明确分工策划、美术、谱师、程序员并使用GitHub或GitLab进行协作。迭代与社区反馈将早期可玩版本发布到GameBanana或Itch.io等FNF模组社区。积极收集玩家反馈关注他们卡关的地方、喜欢的亮点据此进行迭代。社区的传播是模组成功的重要因素。性能优化高分辨率精灵图和复杂Shader可能造成低端设备卡顿。优化图片尺寸合并小图集并对非关键特效提供设置选项。9. 总结你的意识准备好被“上传”了吗通过以上从世界观解析到技术实现的拆解我们可以看到“Bikini-Horrors”的成功并非偶然。它将一个开源节奏游戏引擎变成了一个表达克苏鲁式科幻惊悚故事的强大载体。对于玩家它提供了超越原版的深度叙事体验对于开发者它则是一个绝佳的跨媒体叙事创作沙盒。你的学习路径可以这样规划第一阶段复现。按照本文的步骤成功创建并运行一个包含自定义角色和简单谱面的模组。第二阶段解析。下载“Bikini-Horrors”或其他优秀模组仔细研究其文件结构、JSON配置和脚本理解他们如何实现某个让你惊叹的效果。第三阶段创新。基于你学到的技术构思一个属于自己的简短故事哪怕只有一个曲目并完整实现它包含独特的视觉风格和音频设计。FNF模组生态的魅力在于其极低的创作门槛和极高的表达上限。它不需要你从零开始编写一个游戏引擎而是让你可以专注于最核心的创意部分——讲故事、做音乐、画美术。现在工具链已经清晰创意的大门已经打开。是时候将你的“意识”——你的独特创意上传到这个充满可能性的数字世界了。

相关新闻

深度解析企业建设网站的一般过程:从需求梳理到上线运维的全链路指南

深度解析企业建设网站的一般过程:从需求梳理到上线运维的全链路指南

在这个数字化生存的时代,很多企业老板或者市场负责人心里都清楚,拥有一个专业的官方网站是品牌出海的基石。然而,当真正开始着手“企业建设网站的一般过程”时,往往会感到一头雾水。很多人觉得,不就是找个技术员或者外包公司,给几个页面,填点文案,然后扔上线吗?如果真…

2026/10/15 14:34:27 阅读更多 →
RAG技术解析:如何用检索增强生成解决大模型知识困境

RAG技术解析:如何用检索增强生成解决大模型知识困境

1. 从“全知全能”到“记忆有限”:大模型的根本困境如果你最近在关注大模型的应用,尤其是企业级场景,那么“RAG”这个词你一定不陌生。它几乎成了解决大模型“幻觉”和“知识陈旧”问题的标准答案。但为什么一个听起来如此基础的需求——让模…

2026/10/15 15:58:33 阅读更多 →
网站建设招聘要求:如何找到既懂技术又懂业务的靠谱开发者,避免踩坑指南

网站建设招聘要求:如何找到既懂技术又懂业务的靠谱开发者,避免踩坑指南

现在在这个数字化浪潮汹涌的时代,很多老板或者市场部的负责人都在为建网站的事头疼。以前觉得找个程序员写几句HTML代码就能搞定,或者随便找个模板套一下就完事了。但到了2024年,网站早已不是那个简单的“线上名片”了。它是个复杂的生态系统,既要能跑得快,又要长得好看,…

2026/10/15 15:58:31 阅读更多 →

最新新闻

CANN深度解析:昇腾AI异构计算架构的核心原理与性能调优实践

CANN深度解析:昇腾AI异构计算架构的核心原理与性能调优实践

如果最近在昇腾AI处理器上跑过模型,那你大概率躲不开这个名字:CANN。我第一次接触它时,想当然地以为它和GPU上的CUDA一样——装个驱动、配好环境、调一下框架后端就能直接跑。真正上手才发现,CANN不是一个简单的驱动,也…

2026/10/17 7:06:04 阅读更多 →
Ollama+Go+词库+RAG:本地大模型应用实战拆解

Ollama+Go+词库+RAG:本地大模型应用实战拆解

本地大模型这两年已经卷到“开箱即用”了。去年我跑一个开源大模型,还得先折腾显卡驱动、CUDA、Python 环境、模型转换脚本,现在一把梭的方式是直接拉一个 Ollama 服务,命令一敲模型就跑起来了。更吸引人的是,Ollama 这边既能接入…

2026/10/17 7:06:04 阅读更多 →
微信企业转账到零钱Java对接实战:从签名验签到结果归档

微信企业转账到零钱Java对接实战:从签名验签到结果归档

简介:本资源是一套面向Java后端开发者的企业级微信支付实战代码,聚焦微信企业付款到零钱功能的完整后台实现,适用于工资发放、奖金结算、退款处理等真实业务场景。代码基于微信商户平台API规范,涵盖签名生成、HTTPS请求构造、敏感…

2026/10/17 7:06:04 阅读更多 →
PDMS-AVEVA-E3D二次开发教程(09):.NET Addin 开发——IAddin 接口、CAF 装载配置与最小可运行 Addin

PDMS-AVEVA-E3D二次开发教程(09):.NET Addin 开发——IAddin 接口、CAF 装载配置与最小可运行 Addin

版本声明:本篇基线为 AVEVA E3D Design 3.1(文档版本线存在 1.1 / 2.1 / 3.1,教程统一以 3.1 为准);前代产品 AVEVA PDMS 自 2024 年 4 月 1 日起不再销售、不再提供支持。历史文档(PDMS 12.0 时代&#xf…

2026/10/17 7:06:04 阅读更多 →
PDMS-AVEVA-E3D二次开发教程(10):Command 机制与 UIC——把定制命令挂到菜单与工具栏

PDMS-AVEVA-E3D二次开发教程(10):Command 机制与 UIC——把定制命令挂到菜单与工具栏

版本声明:本篇基线为 AVEVA E3D Design 3.1(文档版本线存在 1.1 / 2.1 / 3.1,教程统一以 3.1 为准);前代产品 AVEVA PDMS 自 2024 年 4 月 1 日起不再销售、不再提供支持。文中命令基类、状态枚举、事件名、UIC 机制与…

2026/10/17 7:06:04 阅读更多 →
降AI工具的本质是语义重构:从检测原理到实操指南

降AI工具的本质是语义重构:从检测原理到实操指南

在内容创作这个圈子里泡久了,你一定会遇到这样一个问题:拿AI写好的稿子,一检测就标红,于是到处找“降AI工具”。我也踩过这个坑,最初以为所谓降AI就是把“重要”换成“关键”、把“因为”换成“由于”,直到…

2026/10/17 7:05:03 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →