news 2026/10/5 1:09:20

Godot C#开发环境配置:用VSCode实现智能补全与调试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Godot C#开发环境配置:用VSCode实现智能补全与调试

你在用Godot写C#时被默认编辑器劝退过吗?如果是,这篇文章能帮你省下至少半天折腾时间。

最近群里好几个朋友从Unity转过来,都反映Godot自带的脚本编辑器在写C#时实在太“裸”:自动补全时灵时不灵,跨文件跳转基本靠滚轮,重命名全靠手速,想断点调试更是想都别想。这些痛点不是Godot不行,而是项目核心放在GDScript上,C#的编辑体验必须靠外部工具链补齐。我花了一整晚把VSCode配成了Godot的C#主力编辑器,乱踩一通后总算跑通,中间最坑的还不是插件问题,而是中文注释乱码,一个编码设置反反复复折腾到凌晨。这篇就把完整配置过程、每一步为什么要这么设置、以及那些不踩一次不会知道的暗坑全部写出来,从装软件到智能提示全亮,照做就能复现。

1. 为什么要折腾VSCode这套环境

1.1 自带编辑器的三个硬伤

先说结论:如果你主要用C#开发,Godot默认编辑器真的不够用。这不是我挑剔,是它设计定位决定的——Godot的脚本编辑器优先服务GDScript,C#属于次等公民。

第一个硬伤是代码补全。GDScript补全做得挺顺,但切到C#后,GetNode<Node2D>("Player")这类调用经常不给提示,要么提示特别慢,得等好几秒才出来。大型类库引用更明显,System、Linq这些命名空间下的方法,自带编辑器几乎没有智能提示,写起来基本是盲打。

第二个硬伤是跨文件导航。项目稍微大一点,十几个脚本互相引用,你想从某个调用点跳到类定义,默认编辑器做不到。常用快捷键F12、Alt+F12都不支持,只能手动搜文件名,再手动翻代码。重构功能更是缺失,比如给字段改名,只能一个个文件翻着改,改漏一个就在运行时炸给你看。

第三个硬伤是调试体验。C#项目在Godot里可以通过“调试”菜单启动,但默认编辑器的断点支持很弱,变量查看、调用栈这些基本功能都缺失。很多时候只能靠GD.Print打日志,效率低得让人怀疑人生。

1.2 VSCode在C#这条链路上强在哪里

VSCode强的地方不是它本身,而是它背后的工具链。装上微软官方的C#扩展之后,VSCode就变成了一套完整的.NET IDE:IntelliSense补全、F12跳转、重命名重构、断点调试、单元测试,全都有,而且响应速度比自带编辑器快一个量级。

再加上Godot Tools这类社区插件,你可以在VSCode里直接构建C#项目、同步外部改动,甚至不用切回Godot窗口。实际体验下来,除了场景、节点、动画这些必须回Godot编辑器操作的部分,剩下90%的代码工作都能在VSCode里完成。

还有个隐形好处:VSCode本身就是为多语言设计的。做Godot项目的同时,你可能要改Web前端、写Python工具脚本、维护Shell脚本,全部在一个编辑器里搞定。Godot自带编辑器做不到这一点,你总不能为了一个脚本再去装别的IDE。

1.3 什么情况下其实不用换

但我也想说句公道话,不是所有人都需要折腾这套环境。

如果你的项目是纯GDScript开发,或者只有几百行代码的原型验证,那就别折腾了,Godot自带编辑器完全够用,加外部编辑器反而增加负担。另外,如果你对命令行环境不熟悉,连PATH、环境变量这些东西都懒得碰,那配置VSCode的过程可能会让你劝退。这时候可以继续用默认编辑器,或者考虑直接用JetBrains Rider,它是开箱即用,只不过要付费。

我写这篇的主要目标人群是:从Unity或Visual Studio转过来、手头有C#基础、准备正经开发一个稍大尺寸Godot项目的人。对你们来说,这套环境是必须的,早配早舒服。

2. 开工前先把基础环境装对

2.1 Godot本体必须选.NET版

很多人卡在第一步都没意识到:普通版Godot不支持C#。官方发布页会同时放出两个版本,一个叫Standard,一个叫.NET(旧称Mono版),你只下载Standard版是根本创建不了C#脚本的。

选择时注意几点:

  • 认准包名里带mono字样,例如Godot_v4.2.1-stable_mono_win64.zip
  • 下载.NET版后,解压出来是一个独立的可执行程序,和Standard版互不影响,可以同时保留
  • 如果你用的是Steam版Godot,注意它默认是Standard版,需要单独下载.NET版,别混淆

还要提醒一下,Godot 4.x的.NET版在首次创建C#项目时会自动生成.csproj和.sln文件,并调用dotnet命令构建,所以你还得确保第二步里的.NET SDK已经装好。不然创建脚本时会报“找不到.NET SDK”之类的错。

2.2 .NET SDK版本别弄混

Godot 4.x对.NET版本有要求,不同小版本对应的目标框架不一样,这个对应关系不搞清楚,编译阶段最容易翻车。

Godot版本对应.NET版本TargetFramework
Godot 4.0 ~ 4.2.NET 6.0net6.0
Godot 4.3+.NET 8.0net8.0

我的建议是直接装.NET 8 SDK。它本身可以构建net6.0的目标程序,前提是安装了对应的runtime或开启相应的targeting pack。最稳妥的做法是:去官网装最新的.NET 8 SDK,这样Godot 4.3直接支持,Godot 4.2也能在工程文件里把TargetFramework改成net6.0后构建。

安装完在终端里验证一下:

dotnet --version dotnet --list-sdks

如果能打印出版本号列表,说明SDK安装成功且已经加入PATH。如果提示dotnet 不是内部或外部命令,说明安装时没勾选加入环境变量,或者用的解压版SDK,需要手动把SDK的路径加到系统环境变量里。

这里再强调一个很多人忽略的点:Godot的.NET版运行时需要.NET SDK,而不仅仅是.NET Runtime。如果你只装了运行时没装SDK,VSCode里的C#智能提示可能还能用,但dotnet build会报错。所以要装完整版SDK。

2.3 VSCode插件到底装哪几个

VSCode去官网下载安装,这一般没有坑,但插件选择上容易踩雷。我目前的配置清单是:

插件名称作者用途必装指数
C# Dev KitMicrosoft提供IntelliSense、调试、测试等功能必装
.NET Extension PackMicrosoft附带的.NET工具链支持推荐
Godot Toolsgeeeg与Godot交互,构建/同步必装
Code Spell CheckerStreet Side Software拼写检查,写代码注释必备可选
Material Icon ThemePhilipp Kief文件图标美化可选

需要注意,老教程里会推荐一个单独的C#扩展(标识符ms-dotnettools.csharp),现在微软把它合并进了C# Dev Kit。我的建议是直接装C# Dev Kit全家桶,省得后续还要补。

Godot Tools插件在扩展商店搜godot tools就能找到,装完后在命令面板里会多出几个命令,比如:

  • Godot Tools: Build Project:在VSCode终端里构建当前项目
  • Godot Tools: Synchronize External Changes:同步外部文件改动到Godot
  • Godot Tools: Open Godot:启动Godot项目

如果没有这些命令,说明Godot Tools没装好,检查一下扩展是不是被禁用了。

2.4 装完先检查一件事:命令行可用

三者装完后,在VSCode里按`Ctrl+``打开终端,依次执行:

dotnet --version godot --version

godot --version能正常输出的话,说明Godot可执行文件也在PATH里。如果提示找不到,有两种解决办法:一是安装时将Godot目录加入环境变量;二是在后面配置Godot Tools时手动指定Godot路径。两种方法选一种即可,我在第3章会详细说要怎么在插件里指路径。

检查完毕,环境基础就算打牢了,下面开始正题。

3. 从新建项目到智能提示全亮

3.1 先在Godot里把项目骨架拉起来

如果你已经用Standard版建过一个GDScript项目,现在想转成C#项目,最省事的做法是你去下载.NET版Godot后,重新新建一个项目,然后把scripts、scenes、assets这些文件夹复制到新项目目录里。直接改老项目可能会遇到.csproj缺失的问题,也容易让Godot缓存混乱。

新建项目的步骤:

  1. 打开.NET版Godot,点“新建项目”
  2. 填项目名称,选好项目目录,注意渲染器选Forward+还是Mobile都行,不影响C#配置
  3. 创建完成后先别急着写逻辑,在场景面板里添加一个根节点,比如Node2D
  4. 右键根节点,选择“附加脚本”,语言选C#
  5. 保存脚本

此时Godot会自动生成三样东西:你的项目名.csproj、你的项目名.sln、以及你刚创建的.cs脚本。可以切到文件系统面板检查一下,如果没有生成.csproj,说明Godot版本不对,或者创建的不是C#脚本。

在Godot里先把项目构建一遍,菜单栏选择“项目” -> “构建”,或者直接按Ctrl+Shift+B。构建成功后再关掉Godot,进入VSCode配置。

3.2 用VSCode打开项目并做初始化

回到VSCode,用“文件 -> 打开文件夹”选择刚才的项目根目录。第一次打开会弹一个信任工作区窗口,选“是,我信任此窗口”。

打开后,左侧资源管理器里应该能看到.csproj、.sln和.cs脚本。这时候你直接点开.cs文件,如果C# Dev Kit加载正常,底部状态栏会出现“正在加载项目”的信息,等片刻后智能提示就应该可用了。

如果等了好久还是没提示,推荐先在终端手动执行一次:

dotnet restore

这会根据.csproj文件还原NuGet依赖,尤其是Godot.NET.Sdk这个包。很多智能提示问题都源于依赖没还原,环境状态是脏的。

下一步,按Ctrl+Shift+P打开命令面板,输入Godot,选Godot Tools: Build Project。它会调用dotnet build,并在输出面板里打印编译日志。这一步成功的话,说明VSCode和Godot工具链已经打通了。

3.3 在Godot编辑器设置里指定VSCode

现在只差最后一步:双击.cs文件时,让Godot用VSCode打开,而不是自带编辑器。还有调试时,能直接呼起VSCode的断点调试器。

在Godot编辑器里:

  1. 打开“编辑器”菜单 -> “编辑器设置”
  2. 在搜索框输入external
  3. 找到“文本编辑器 -> 外部 -> 使用外部编辑器”相关选项
  4. 可执行文件路径填VSCode的code.exe绝对路径,一般位于:C:\Users\你的用户名\AppData\Local\Programs\Microsoft VS Code\Code.exe
  5. 保存设置

如果你之前装了Visual Studio,可能会看到“用Visual Studio打开”之类的选项,我们直接改成VSCode。改完之后再双击任意C#脚本,Godot会直接唤起VSCode打开这个文件。

调试方面,Godot 4.x的.NET版自带一个“启动调试”的按钮,但要用VSCode调试,需要在项目根目录生成.vscode/launch.json。好消息是,装好Godot Tools插件后,命令面板里执行Godot Tools: Generate Launch Configuration,插件会自动生成。没有这个命令的版本,也可以手动创建一个.vscode/launch.json,核心配置长这样:

{ "version": "0.2.0", "configurations": [ { "name": "Godot Run", "type": "coreclr", "request": "launch", "preLaunchTask": "build", "program": "C:/Path/To/Godot_v4.2.1-stable_mono_win64.exe", "args": ["--path", "${workspaceFolder}"], "cwd": "${workspaceFolder}", "stopAtEntry": false, "console": "internalConsole" } ] }

注意program要改成你本机Godot.NET版的实际路径,preLaunchTask对应构建任务的名字。如果嫌手动配置麻烦,可以先用Godot Tools自动生成,再微调路径。

3.4 一套能直接抄的settings.json配置

最后,在项目根目录建一个.vscode/settings.json,相当于当前项目里的编辑器配置,只对项目生效,不会污染全局配置:

{ "files.encoding": "utf8", "files.autoGuessEncoding": false, "editor.formatOnSave": true, "files.eol": "\n", "[csharp]": { "editor.defaultFormatter": "ms-dotnettools.csharp" }, "dotnet.defaultSolution": "你的项目名.sln" }

这里重点解释两个容易踩坑的配置:

  • files.encoding设为utf8是必须的,Godot对UTF-8有强制要求,后面第4章会讲为什么。
  • files.autoGuessEncoding必须设为false,否则VSCode发现文件不符合UTF-8时,会自动猜编码,一猜就是GBK,反而把正常的UTF-8文件误判成中文乱码。这个开关默认是关闭的,但要确保没人改过,建议在项目级配置里显式写死。

设置完成后,回到脚本里随便敲几个字符测试,比如输入GD.Print,看看有没有自动补全。一切正常的话,恭喜你,环境主链路已经通了。

4. 中文注释乱码的避坑指南

4.1 乱码到底是怎么产生的

这个坑我栽过,值得单独开一章说。

中文注释乱码的根源是编码不统一。Godot 4.x明确规定脚本文件必须使用UTF-8编码保存,而Windows中文系统里很多编辑器默认用GBK(也就是ANSI码页936)保存。当一份GBK编码的中文注释被Godot当成UTF-8解析时,中文字符就变成了一堆乱码,反过来也一样。

还有一种特殊情况是BOM(字节顺序标记)。Windows记事本保存UTF-8文件时,会在文件开头写入三个不可见字节EF BB BF作为标记。VSCode默认保存不带BOM的UTF-8。如果项目里有的文件带BOM,有的不带,在Godot里可能出现“脚本第一行报错”或显示异常。

所以在配置环境时,必须把整个项目的编码规范锁死,所有.cs文件和GDScript文件统一用不带BOM的UTF-8。

4.2 VSCode里怎么锁死UTF-8

打开VSCode,按Ctrl+Shift+P,输入settings,打开“首选项:打开用户设置(JSON)”。在用户级别配置里加入:

{ "files.encoding": "utf8", "files.autoGuessEncoding": false, "files.encoding": "utf8", "git.autorefresh": true }

注意files.encoding在用户级设置后,新打开的所有文件都以UTF-8处理。但已经有乱码的文件不会自动变好,需要在打开文件后,看VSCode右下角的状态栏,那里会显示当前文件编码。如果是GBK,就点击它,在顶部弹出的菜单中选择“通过编码重新打开”,选UTF-8,文件就会以UTF-8重新渲染。如果内容正常了,再选“保存为编码”->“UTF-8”,覆盖保存,彻底转码。

还有一个细节:如果你的项目是从中文系统老电脑上拷贝过来的,文件名可能是GBK编码,Windows资源管理器能正常显示,但VSCode里会乱码。这种情况尽量不要手改文件名,用系统自带的Locale设置或者第三方批量改名工具转成简体中文即可,或者干脆用拼音/英文文件名,能省掉很多跨平台麻烦。

4.3 已有乱码文件怎么批量救

项目里文件多的时候,一个个手动转换太累了,推荐写个小脚本批量处理。下面是一个我自己用的Python脚本,把目录下所有.cs文件从GBK批量转换为UTF-8:

import os from pathlib import Path def convert_file(path: Path): raw = path.read_bytes() if raw.startswith(b'\xef\xbb\xbf'): raw = raw[3:] # 去掉BOM for src_enc, dst_enc in [('gbk', 'utf-8'), ('utf-8', 'utf-8-sig')]: try: text = raw.decode(src_enc) path.write_text(text, encoding='utf-8', newline='\n') print(f'转换成功: {path} ({src_enc} -> utf-8)') return except UnicodeDecodeError: continue print(f'跳过: {path} (编码无法识别)') if __name__ == '__main__': root = Path('.') for p in root.rglob('*.cs'): convert_file(p) print('批量转码完成')

运行方式:

python convert_encoding.py

这个脚本的思路是:先尝试按GBK解码,成功说明原文件大概率是GBK;解码失败则说明可能已经是UTF-8,就尝试按UTF-8解码。转换前强烈建议先把整个目录备份一份,或者用Git提交一次,避免转了一半发现某个文件本来是UTF-8带BOM,被误判成GBK又转了一遍,结果来回折腾。

转换完成后,回到VSCode打开文件确认,中文注释应该正常显示了。

4.4 行尾符和Git提交的小细节

很多人配置完环境后,会遇到另一个诡异问题:代码在本地一切正常,但一提交到Git,仓库里所有中文注释都变成乱码,或者diff里整行整行被标红。这通常不是编码问题,而是行尾符问题。

Windows默认行尾符是CRLF(回车+换行),Linux/macOS和Git默认是LF(换行)。如果项目在Windows上开发,.cs文件带CRLF,提交到Git后,Git会自动转换行尾符,有些情况会让中文字符串的字节序列和编码错位。

最简单的解决办法是,在项目根目录创建一个.gitattributes文件,强制统一行尾符:

* text=auto *.cs text eol=lf *.gd text eol=lf *.tscn text eol=lf *.tres text eol=lf

这样每次提交时,Git会把所有文本文件转成LF,避免混乱。如果你在Windows本地开发,VSCode会按LF写入文件,配合第3.4节的files.eol设置,基本不会再碰到行尾符引起的怪问题。

5. 常见问题速查与排查思路

5.1 智能提示时有时无

这是配置完后最常碰到的问题,表现是:刚打开文件时提示正常,写了一会儿就消失了,或者按`.``时完全没有弹窗。

排查顺序:

  1. 看看底部状态栏有没有C#相关的初始化信息,如果没有,说明C# Dev Kit还没识别到你的项目
  2. 在终端执行dotnet restore,确认依赖已经还原
  3. 关闭并重新打开VSCode,让语言服务器重新加载
  4. 检查.csproj文件是否存在,如果有多个.csproj但没配置sln,C# Dev Kit可能不知道加载哪个,设置dotnet.defaultSolution可以解决
  5. 删掉缓存目录bin、obj、.vs,重新构建

我遇到过一次比较坑的情况:Godot自动生成的.csproj里RootNamespace是中文,C#的命名空间里带中文在Roslyn分析器里偶发异常,改成英文项目名后一切正常。如果你项目名起的确实比较“个性化”,可以关注一下。

5.2 编译失败的几个高频原因

编译失败时,先仔细看错误信息,然后按以下几个方向排查:

错误特征原因解决方法
MSB4132找不到.NET SDKSDK版本和TargetFramework不匹配安装对应版本SDK,或改.csproj里的TargetFramework
Godot.NET.Sdk版本冲突Godot升级后旧工程没同步打开.csproj,把Godot.NET.Sdk版本改成与你Godot版本一致
找不到Godot命名空间工程还没被正确还原执行dotnet restore,检查NuGet源
中文注释报编译错误文件编码问题按第4章方法转成UTF-8

这里有个细节:Godot 4.2和4.3升级后,.csproj里的Godot.NET.Sdk版本号不会自动变。比如原来写的是4.2.1,换了4.3的Godot后必须手动改成4.3.0(具体版本以你的Godot版本为准),否则会提示SDK版本错误。

5.3 双击C#脚本还在打开Godot默认编辑器

设置完外部编辑器后还是默认编辑器,99%的情况是路径没填对,或者漏了关键选项。

回到Godot编辑器设置里,确认:

  • 搜external,找到“文本编辑器 -> 外部”
  • 启用“使用外部编辑器”开关
  • 可执行文件路径必须是Code.exe的完整路径,不能填code命令别名
  • 下方的参数设置可以直接留空,Godot默认会用{project}和{file}占位符

如果还不行,可以试一下直接通过系统的文件关联设置,右键.cs文件 -> 打开方式 -> 选择VSCode,并勾选“始终使用此应用”。这样至少能保证,无论什么场景双击文件都会在VSCode里打开。

5.4 其他问题速查表

问题可能原因处理方法
启动Godot时报缺少hostfxr.dll.NET SDK安装损坏卸载重装.NET SDK
dotnet build后程序集没更新,运行还是旧逻辑Godot没有重新加载在Godot里按Ctrl+Shift+B重新构建,或重启Godot
VSCode里调试时连不上Godot进程Godot版本与.NET SDK不匹配查看.csproj的TargetFramework,确认和Godot支持版本一致
场景里挂载C#脚本后报“找不到类型”命名空间或类名不匹配检查RootNamespace和类名,必要时刷新脚本引用
打开项目后VSCode提示“未找到.NET Extensions”缺.NET Extension Pack或.NET Install Tool安装微软的.NET Extension Pack扩展
files.encoding设置后已有文件还是乱码设置只影响新文件和重新打开的文件手动对已有文件“通过编码重新打开”,再保存

上面的表格是我实际踩过坑的汇总,遇到症状直接按表查,能省不少搜索时间。尤其是“宿主解析器”相关的问题,很多人会误以为是Godot的问题,其实是.NET SDK的安装状态问题,重装一次就好了。

6. 用了一段时间后的几点体会

这套环境配置完,最直接的感受是C#开发体验回到了Visual Studio级别的状态,但VSCode更轻、更快。尤其是调试环节,配合Godot Tools生成的launch.json,直接在VSCode里打断点、看变量调用链,比在Godot自带编辑器里打GD.Print排查高效太多了。我写一个带状态同步的网络模块时,复杂逻辑全靠断点一步步跟,当场定位了3个空引用问题,要放以前用打印日志,这3个问题至少得折腾两天。

如果你也是从Unity或Visual Studio转过来的人,我非常建议你花一天时间把这套环境彻底配好。前期看着各种配置项有点烦,但对后续开发效率的提升是长期的。用顺手之后,我再补两个小建议:一是把editor.formatOnSave打开,配合.editorconfig统一代码风格,团队协作时能少很多diff噪音;二是给常用命令绑定快捷键,比如构建项目绑定成Alt+B,调试绑定成F5,用起来会顺手很多。

最后再分享一个很多人不知道的技巧:VSCode里可以给.gd脚本(GDScript)也配置外部渲染,通过Godot Tools或插件市场里的GDScript扩展,一样能获得语法高亮和基础补全。这样一来,不管C#还是GDScript,全部在一个编辑器里搞定,切项目时就不用来回换工具了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 1:08:57

Java教务系统实战:从部署到安全加固的完整工程指南

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

作者头像 李华
网站建设 2026/10/5 1:06:37

工业级MRAM存储方案:PIC18LF4685驱动MR25H40CDF实战

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

作者头像 李华
网站建设 2026/10/5 1:06:05

Oracle数据迁移到Hadoop全攻略:Sqoop实操与避坑指南

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

作者头像 李华
网站建设 2026/10/5 1:04:47

国内开源MES框架盘点与选型:从核心模块到二次开发落地

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

作者头像 李华
网站建设 2026/10/5 1:04:37

MATLAB 2023b安装配置MOSEK 10.1.25完整指南:解决License过期与路径问题

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

作者头像 李华
网站建设 2026/10/5 1:04:37

三维在线装箱DQN实战:从环境设计到训练避坑

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

作者头像 李华