IntelliJ IDEA插件开发实战:从Gradle环境搭建到语言类插件与发布全链路
简介这份《IntelliJ Platform Plugin 开发指导手册》面向 Java 开发者与 IDE 插件爱好者帮助读者从零起步掌握 IntelliJ IDEA 插件开发并逐步进阶到语言类高级插件。手册由上册、下册与附录三份文档组成内容分为四部分插件开发基础、图形化插件开发、语言类插件开发以及工具与参考资料附录覆盖插件体系结构、生命周期、事件监听、Action System、Tool Windows、语法高亮、代码补全与自定义语言解析等核心主题。资源包共 1 个 PDF 文件大小约 3.99MB结构清晰便于按模块检索学习。目前已有 876 人学习下载。读者可借助它系统理解 IntelliJ 平台 API 与 Gradle 插件配置掌握 UI 增强、框架集成、DSL 支持等实战思路并配合附录中的示例与社区资源动手实践逐步积累插件开发与调试经验。1. 从一次国际化改造说起这份手册到底解决什么问题去年接手一个老系统改造三百多个模块要批量做语言国际化人工改根本扛不住。当时第一反应就是写个 IntelliJ IDEA 插件自动扫描自定义文件类型、调翻译接口、生成 properties 和 Excel。想法很美好动手才发现网上能参考的资料少得可怜官方文档散落在几十个页面里一个 ToolWindow 的注册能折腾大半天。后来花了两个周末才把插件跑通回头一看真正卡住我的不是 Java 语法而是 IntelliJ Platform 那套扩展点、服务注册、线程模型的“黑匣子”逻辑。这份《IntelliJ Platform Plugin 开发指导手册》就是冲着这个痛点来的。它把插件开发拆成上册UI 图形化插件、下册语言类插件和附录三部分覆盖从 Gradle 环境搭建、plugin.xml 配置、Action System、ToolWindow到自定义语言解析、语法高亮、代码检查、插件签名发布、Light/Heavy 测试的完整链路。适合两类人想写框架集成、代码统计、效率工具类 UI 插件的开发者以及要做代码补全、依赖分析、DSL 支持的高级插件开发者。如果你正在用 Java 给 IDEA 做扩展又不想在官方文档的海洋里反复翻车这份手册值得跟着走一遍。2. 环境搭建与 Gradle 插件配置把 runIde 跑起来2.1 为什么选 Gradle 而不是手动配 SDKIntelliJ Platform 插件开发早期靠手动下载 SDK、配 IDEA 安装目录、写 Ant 脚本现在官方主推 Gradle IntelliJ Plugin。选它的理由很直接依赖版本自动对齐、runIde 任务一键启动沙箱 IDE、打包签名发布全流程都有对应 task。手动配 SDK 最大的坑是版本错位——你本地 IDEA 2023.1插件编译时依赖的是 2022.3 的 API跑起来就报 NoSuchMethodError。Gradle 插件通过intellij { version.set(...) }把平台版本锁死从源头避免这类玄学问题。2.2 build.gradle 最小可用配置下面是我在多个插件项目里反复用的一套配置骨架基于 Kotlin DSL 写法Groovy 同理plugins { id(java) id(org.jetbrains.intellij) version 1.17.0 // Gradle IntelliJ Plugin } group com.example version 1.0.0 repositories { mavenCentral() } intellij { version.set(2023.1) // 目标平台版本决定 API 可用范围 type.set(IC) // ICCommunity, IUUltimate plugins.set(listOf(com.intellij.java)) // 依赖的官方插件 updateSinceUntilBuild.set(true) // 自动生成 since/until build 号 } tasks { patchPluginXml { sinceBuild.set(231) // 最低兼容 build 号 untilBuild.set(241.*) // 最高兼容 build 号 } runIde { jvmArgs(-Xmx2048m) // 沙箱 IDE 内存插件重了要调大 } buildSearchableOptions { enabled false // 关掉可搜索选项构建省时间 } }逻辑说明intellij块里的version和type决定了编译时用的平台 API 和运行时沙箱 IDE 的版本。plugins列表声明你依赖哪些官方插件提供的扩展点比如做 Java 相关功能必须加com.intellij.java。patchPluginXml里的sinceBuild/untilBuild控制插件在哪些 IDEA 版本上能被安装写太窄用户装不上写太宽可能在新版上崩。参数怎么改version建议选当前主流稳定版不要追最新 EAPtype如果用到 Ultimate 独有 API如数据库工具必须设IU但打包后用户也需要 Ultimate 才能用jvmArgs默认 1024m 往往不够加载大项目时沙箱 IDE 会卡死调到 2048m 或 4096m。2.3 runIde 常见启动失败排查第一次跑./gradlew runIde大概率会遇到几种情况。一是卡在setupDependencies任务提示找不到依赖通常是网络问题导致 IDE 分发包下载失败可以手动把下载目录配到本地缓存。二是沙箱 IDE 启动后插件没加载检查plugin.xml里的idea-plugin根标签和id是否重复。三是控制台报PluginException: Cannot load plugin多半是plugin.xml里注册的扩展点类路径写错或者依赖的插件没在intellij.plugins里声明。提示runIde 启动的沙箱 IDE 和本地正式 IDEA 是隔离的配置、插件、缓存都在build/idea-sandbox下改坏了直接删目录重跑不用重装。2.4 内部工具与 plugin.xml 完整配置手册里专门有一节讲内部工具Internal Tools通过Help | Edit Custom Properties加idea.is.internaltrue开启。开启后能在菜单里找到 UI Inspector、Action 调试器、扩展点查看器调 ToolWindow 布局和 Action 注册时非常有用。plugin.xml的完整配置是另一个重点actions、extensions、applicationService、projectService、toolWindow这些标签的属性和嵌套关系手册附录里给了可直接抄的模板。我一般会把plugin.xml当成插件的“路由表”每加一个功能先想清楚挂到哪个扩展点上再回去补配置比先写代码后补配置少走很多弯路。3. 图形化插件开发Action、ToolWindow 与 UI 线程模型3.1 Action System 的注册与触发链路UI 类插件的核心是 Action。一个 Action 从用户点击到执行链路是菜单/工具栏绑定 Action ID → ActionManager 查找注册 → 构造 AnAction 实例 → 调用actionPerformed。注册方式有两种在plugin.xml里静态声明或者用ActionManager.registerAction动态注册。静态声明更常见actions action idcom.example.MyAction classcom.example.MyAction textScan Files descriptionScan custom file types add-to-group group-idToolsMenu anchorfirst/ keyboard-shortcut keymap$default first-keystrokectrl alt S/ /action /actions逻辑说明id全局唯一class指向 AnAction 子类add-to-group决定挂在哪个菜单下keyboard-shortcut绑快捷键。anchor控制插入位置first/last/before/after按需选。参数注意keymap$default表示默认键位方案如果用户自定义了键位快捷键可能被覆盖。text和description会出现在菜单和设置里写清楚用途别用 “My Action” 这种名字。3.2 ToolWindow 创建与内容面板ToolWindow 适合放常驻的统计面板、日志输出、文件扫描结果。创建步骤先在plugin.xml注册toolWindow再实现ToolWindowFactory在createToolWindowContent里往ContentFactory塞面板。public class MyToolWindowFactory implements ToolWindowFactory { Override public void createToolWindowContent(NotNull Project project, NotNull ToolWindow toolWindow) { MyPanel panel new MyPanel(project); ContentFactory factory ContentFactory.getInstance(); Content content factory.createContent(panel.getComponent(), , false); toolWindow.getContentManager().addContent(content); } }逻辑说明createContent的第二个参数是显示名第三个参数isLockable控制面板是否可被锁定。MyPanel里通常用JPanelJBTable或JBList组合注意所有 UI 操作必须在 EDTEvent Dispatch Thread上执行。参数注意toolWindow.getContentManager()可以加多个 Content用ContentManager.removeAllContents清理。如果面板要随项目切换刷新实现ToolWindowFactory.isApplicable或在ProjectManagerListener里处理。3.3 UI 线程模型与后台任务IntelliJ Platform 对线程管得很严读操作可以在后台线程写操作和 UI 更新必须在 EDT。常见翻车场景是在后台线程里直接改JBList的 model结果界面随机卡死或抛IllegalStateException。正确做法是用ApplicationManager.getApplication().invokeLater切回 EDT或者用ProgressManager.runInBackground跑耗时任务。ProgressManager.getInstance().run(new Task.Backgroundable(project, Scanning, false) { Override public void run(NotNull ProgressIndicator indicator) { ListString results scanFiles(project, indicator); // 后台执行 ApplicationManager.getApplication().invokeLater(() - { myListModel.clear(); myListModel.addAll(results); // EDT 更新 UI }); } });逻辑说明Task.Backgroundable自动处理进度条和取消逻辑indicator用来报告进度和检查取消。invokeLater把 UI 更新排到 EDT 队列。参数注意Task.Backgroundable第二个参数canBeCancelled设 true 时用户能点取消indicator.checkCanceled()要配合用。invokeLater的ModalityState默认是NON_MODAL如果弹了模态对话框要用ModalityState.defaultModalityState()。3.4 框架集成类插件的扩展点选择做框架集成比如对接某个内部构建工具时不要一上来就写 Action。先看平台有没有现成扩展点ProjectWizard适合新建项目向导Configurable适合设置页FileType适合自定义文件类型识别CompletionContributor适合补全。手册上册第 2 章列了常用扩展点清单我一般会先翻一遍能复用就不自己造。比如做代码统计直接用FileTypeManager遍历文件类型比手动扫目录稳得多。4. 语言类插件开发从 Grammar-Kit 到语法高亮与代码检查4.1 自定义语言的开发路径语言类插件比 UI 插件门槛高一截因为它涉及词法分析、语法分析、PSIProgram Structure Interface树构建。手册下册给的路径是先用 Grammar-Kit 定义 BNF 文法生成 Lexer 和 Parser再实现 PSI 元素和引用解析最后挂语法高亮、代码补全、检查。Grammar-Kit 是 IntelliJ 官方的文法工具Gradle 里加org.jetbrains.grammarkit插件配.bnf文件跑generateLexer和generateParser任务。plugins { id(org.jetbrains.grammarkit) version 2022.3.2 } tasks { generateLexer { source.set(src/main/grammars/MyLang.flex) targetDir.set(src/main/gen/com/example/lexer) targetClass.set(MyLangLexer) } generateParser { source.set(src/main/grammars/MyLang.bnf) targetRoot.set(src/main/gen) pathToParser.set(/com/example/parser/MyLangParser.java) pathToPsiRoot.set(/com/example/psi) } }逻辑说明.flex文件定义词法规则.bnf定义语法规则和 PSI 元素映射。生成代码放到src/main/gen记得在 IDE 里把这个目录标记为 Generated Sources Root。参数注意targetClass要和.flex里的%class一致pathToPsiRoot决定 PSI 接口和实现的包路径改了这个路径所有引用都要跟着改。4.2 语法高亮与 Annotator语法高亮有两种实现TextAttributesKey SyntaxHighlighter词法级或者 Annotator语义级。词法级在 Lexer 里给 Token 打类型然后在plugin.xml注册colorSettingsPage和lang.syntaxHighlighterFactory。语义级实现Annotator在annotate方法里根据 PSI 元素加高亮。public class MyAnnotator implements Annotator { Override public void annotate(NotNull PsiElement element, NotNull AnnotationHolder holder) { if (element instanceof MyKeyword) { holder.newSilentAnnotation(HighlightSeverity.INFORMATION) .range(element) .textAttributes(MyHighlightKeys.KEYWORD) .create(); } } }逻辑说明newSilentAnnotation不弹提示只改样式textAttributes引用在DefaultLanguageHighlighterColors或自定义 Key 里定义的颜色。参数注意HighlightSeverity选INFORMATION/WARNING/ERROR影响编辑器右侧标记颜色。Annotator 会被频繁调用别在里面做重计算耗时逻辑放CachedValuesManager。4.3 代码检查与 Quick Fix代码检查用LocalInspectionTool在plugin.xml注册localInspection。每个 Inspection 返回ProblemDescriptor可以附带LocalQuickFix让用户一键修复。public class MyInspection extends LocalInspectionTool { Override public ProblemDescriptor[] checkFile(NotNull PsiFile file, NotNull InspectionManager manager, boolean isOnTheFly) { ListProblemDescriptor problems new ArrayList(); file.accept(new PsiRecursiveElementVisitor() { Override public void visitElement(NotNull PsiElement element) { if (element instanceof MyBadElement) { problems.add(manager.createProblemDescriptor(element, Unresolved reference, new MyQuickFix(), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly)); } super.visitElement(element); } }); return problems.toArray(ProblemDescriptor.EMPTY_ARRAY); } }逻辑说明checkFile遍历 PSI 树发现违规元素就构造ProblemDescriptor。isOnTheFly为 true 表示实时检查false 表示批量检查。参数注意ProblemHighlightType决定标记样式GENERIC_ERROR_OR_WARNING最常用。QuickFix 的applyFix里改 PSI 必须包在WriteCommandAction里否则抛异常。4.4 引用解析与跳转语言插件里最实用的功能之一是 CtrlClick 跳转。实现PsiReferenceContributor和PsiReference在resolve方法里返回目标元素。手册下册第 3 章给了 MyBatis 插件里 XML 和 Java 接口互跳的案例核心是PsiReferenceBase的multiResolve和getVariants。这块的坑在于缓存解析结果要缓存否则大文件里每次跳转都重新遍历 PSI编辑器直接卡成幻灯片。5. 插件测试与发布Light/Heavy 测试、签名与市场发布5.1 Light 测试与 Heavy 测试怎么选手册第 5 章把测试分成两类。Light 测试用LightPlatformCodeInsightFixtureTestCase不启动完整 IDE速度快适合测 Annotator、Completion、Inspection 这类纯 PSI 逻辑。Heavy 测试用HeavyPlatformTestCase启动真实项目环境适合测涉及索引、VFS、多模块交互的场景。我一般先用 Light 覆盖 80% 的逻辑剩下涉及项目结构和索引的用 Heavy 补。public class MyInspectionTest extends LightPlatformCodeInsightFixtureTestCase { Override protected String getTestDataPath() { return src/test/testData; } public void testUnresolvedReference() { myFixture.configureByFile(badElement.my); myFixture.checkHighlighting(true, false, false); } }逻辑说明configureByFile加载测试数据文件checkHighlighting自动比对高亮结果。测试数据目录在getTestDataPath指定。参数注意checkHighlighting三个布尔参数分别控制是否检查警告、信息、弱警告。测试数据文件里用warning、error标签标注预期结果。5.2 插件签名与发布流程插件要发布到市场必须签名。手册第 4 章讲了签名原理用私钥对插件 ZIP 生成签名市场用公钥验证。Gradle 里配signPlugin任务tasks { signPlugin { certificateChain.set(file(chain.crt).readText()) privateKey.set(file(private.pem).readText()) password.set(System.getenv(PRIVATE_KEY_PASSWORD)) } publishPlugin { token.set(System.getenv(PUBLISH_TOKEN)) } }逻辑说明certificateChain和privateKey从文件读密码走环境变量。publishPlugin的 token 在市场个人页生成。参数注意私钥和密码绝对不能提交到仓库用 CI 的 secret 管理。sinceBuild/untilBuild在patchPluginXml里配好发布前跑verifyPlugin任务检查兼容性。5.3 测试常见问题排查手册第 5 章第 8 节列了一堆测试坑我挑几个高频的。一是测试日志不输出加-Didea.log.debugtrue开 DEBUG 日志。二是测试里注册的扩展点不生效检查plugin.xml是否在测试 classpath 下。三是 UI 事件没处理完就断言用UIUtil.dispatchAllInvocationEvents()强制刷新。四是测试替换服务用ServiceManager.getService前先registerService覆盖。这些在手册里都有对应条目遇到问题先翻这一节比搜论坛快。6. 一个具体技巧用内部工具调试扩展点注册最后分享一个我每次开发新插件都会走的流程用内部工具验证扩展点注册。开启idea.is.internaltrue后Tools | Internal Actions | Extensions能列出当前 IDE 所有已注册扩展点及其实现类。写完plugin.xml后先跑runIde在沙箱 IDE 里打开这个面板搜你的扩展点名称确认实现类被正确加载。如果没出现说明plugin.xml路径写错或依赖插件没声明如果出现了但功能不触发检查扩展点的order和id是否冲突。这个习惯帮我省了大量“代码明明写了却不生效”的排查时间。有一次做 CompletionContributor代码逻辑没问题但补全死活不出来用扩展点面板一看发现plugin.xml里把completion.contributor写成了completion.contributer一个字母之差编译器不报错运行时静默忽略。从那以后我每次改完plugin.xml都强制走一遍扩展点面板确认再跑功能测试。手册附录里还整理了常用系统目录、图标资源、社区链接开发时遇到 API 找不到、图标不知道放哪、想参考开源插件源码翻附录比翻官方文档快。希望这份手册能帮你少走几个我踩过的坑。本文还有配套的精品资源点击获取

相关新闻

Window11为什么出现codex桌面端频繁打不开和网络等待问题解决

Window11为什么出现codex桌面端频繁打不开和网络等待问题解决

目录 先修复 用其他AI助手解决 应用商店问题 清理缓存 等待下载完成 waiting for network 环境:window11 问题:codex运行报错/运行无反应,未打开桌面端但是又进程 先修复 用其他AI助手解决 这不失为一个方案,有次启动失败…

2026/10/9 12:06:14 阅读更多 →
【2027大数据精品毕设】基于大数据的高频电力消耗数据可视化与分析,附源码_数据可视化_数据分析_毕设选题_开题ppt_大数据项目_文档指导

【2027大数据精品毕设】基于大数据的高频电力消耗数据可视化与分析,附源码_数据可视化_数据分析_毕设选题_开题ppt_大数据项目_文档指导

💖💖作者:计算机毕业设计杰瑞 💙💙个人简介:曾长期从事计算机专业培训教学,本人也热爱上课教学,语言擅长Java、微信小程序、Python、Golang、安卓Android等,开发项目包括…

2026/10/9 12:06:14 阅读更多 →
Python print渲染8x8点阵字:从取模到终端显示全流程

Python print渲染8x8点阵字:从取模到终端显示全流程

1. 从一个打印需求说起:点阵字到底能玩出什么花样很多人第一次接触点阵字,是在老式收银机、电子秤或者公交站牌上。那种由一个个小圆点拼出来的数字和字母,远看粗糙,近看却有一种独特的机械美感。后来做嵌入式开发的朋友告诉我&am…

2026/10/9 12:05:13 阅读更多 →

最新新闻

正则表达式核心用法详解:元字符、分组与回溯实战

正则表达式核心用法详解:元字符、分组与回溯实战

正则表达式,这个听起来带着点学术味、又经常被简写成"rea"的东西,几乎是我日常开发里最离不开的一个工具。它不是某个框架或语言专属的 API,而是一种横跨几乎所有编程语言、文本编辑器、命令行工具的通用语法;写得好能一…

2026/10/9 12:36:02 阅读更多 →
C#静态构造函数“最先执行”的真相:触发机制、BeforeFieldInit与实战建议

C#静态构造函数“最先执行”的真相:触发机制、BeforeFieldInit与实战建议

上次去客户现场排查一套上位机抓取程序的卡顿问题,现象很有意思:设备开机后第一次触发某个动作,总是要卡几百毫秒,第二次之后就完全正常。我一开始怀疑是硬件握手超时或者相机连接没预热,顺着调用栈查到最后&#xff0…

2026/10/9 12:36:02 阅读更多 →
从状态图到LL(1)预测分析:词法分析与语法分析实验完整实现

从状态图到LL(1)预测分析:词法分析与语法分析实验完整实现

简介:编译原理课程中的词法分析与语法分析实验报告,适合计算机专业学生、编译原理初学者以及需要完成课程设计、实验报告撰写的人员参考。实验基于Windows与Visual C环境,采用C实现了一个可识别标识符、关键字、十进制整数及运算符分隔符的词…

2026/10/9 12:36:02 阅读更多 →
静态变量多场景串数据:误当局部复用,改局部或加调用上下文区分

静态变量多场景串数据:误当局部复用,改局部或加调用上下文区分

静态变量多场景串数据:误当局部复用,改局部或加调用上下文区分摘要:static 局部变量生命周期是全局的,跨调用保持值。若把它当"每次调用重新初始化的临时缓冲"用,在多场景/可重入/中断环境下复用&#xff0c…

2026/10/9 12:36:02 阅读更多 →
PyTorch训练CIFAR-10翻车原因与93.5%+精度实战指南

PyTorch训练CIFAR-10翻车原因与93.5%+精度实战指南

简介:本资源是一份面向深度学习初学者与计算机视觉实践者的PyTorch图像识别入门套件,聚焦CIFAR-10这一经典图像分类任务,帮助用户从数据加载、模型构建到训练部署全流程掌握CNN实战能力。压缩包共5个文件,含2个核心Python脚本&…

2026/10/9 12:36:02 阅读更多 →
BIOS显示Secure Boot已启用,Linux却报disabled?一文讲透信任链断点

BIOS显示Secure Boot已启用,Linux却报disabled?一文讲透信任链断点

1. 这个"矛盾"到底在说什么如果你同时折腾过主板固件设置和 Linux 系统,大概率撞见过这么一幕:开机按 Del 或 F2 进 BIOS,Security 那一栏里 Secure Boot 明明白白写着 Enabled,状态是 Active;结果进了系统&…

2026/10/9 12:35:01 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 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/8 21:13:17 阅读更多 →
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/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练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/9 6:17:20 阅读更多 →