<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>计算机编程技巧与心得</title><description>AndreaFrederica-SirrusStudio</description><link>https://blog.sirrus.cc/</link><language>zh_cn</language><item><title>Andrea Novel Helper - 专为小说创作者打造的 VS Code 写作增强扩展</title><link>https://blog.sirrus.cc/posts/novel-helper-introduction/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/novel-helper-introduction/</guid><description>全面介绍 Andrea Novel Helper 的核心功能，从智能写作辅助到设定集管理，从实时统计到自动化脚本，为小说创作者提供一站式写作解决方案。</description><pubDate>Mon, 24 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;官网&lt;/strong&gt;: &lt;a href=&quot;https://anh.sirrus.cc/&quot;&gt;https://anh.sirrus.cc/&lt;/a&gt; | &lt;strong&gt;文档&lt;/strong&gt;: &lt;a href=&quot;https://blog.sirrus.cc&quot;&gt;https://blog.sirrus.cc&lt;/a&gt; &amp;gt; &lt;strong&gt;最新版本&lt;/strong&gt;: 0.4.35 (2025-11-21) | &lt;strong&gt;VS Code Marketplace&lt;/strong&gt;: &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=andreafrederica.andrea-novel-helper&quot;&gt;Andrea Novel Helper&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;Andrea Novel Helper - 专为小说创作者打造的 VS Code 写作增强扩展&lt;/h1&gt;
&lt;p&gt;Andrea Novel Helper（小说助手）是一个围绕&quot;设定集/资料集&quot;组织写作资产的 VS Code 小说写作增强扩展。它将传统的写作工具与现代编辑器技术完美结合，为小说创作者提供了一个功能强大、高度可定制的一站式写作环境。&lt;/p&gt;
&lt;h2&gt;✒️ 核心写作体验&lt;/h2&gt;
&lt;h3&gt;智能统计与分析&lt;/h3&gt;
&lt;p&gt;小说助手提供全面的写作统计功能，帮助创作者更好地了解自己的写作状态：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;实时字数统计&lt;/strong&gt;：支持 CJK 字符与英文单词统计，提供多种统计标准（含标点/不含标点/词计）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;写作速度监测&lt;/strong&gt;：实时显示 CPM (每分钟字符数) 或 CPH (每小时字符数)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;统计仪表板&lt;/strong&gt;：可视化展示今日与历史写作时长、字数、平均速度及活跃度趋势&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;状态栏自定义&lt;/strong&gt;：支持详细、半精简、精简三种显示模式&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;智能排版与辅助&lt;/h3&gt;
&lt;p&gt;为了让创作者专注于内容创作，小说助手提供了多项智能排版功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;智慧回车&lt;/strong&gt;：智能处理段落换行，自动调整格式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;智慧括号&lt;/strong&gt;：成对符号自动补全与快速跳出&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动空行&lt;/strong&gt;：自动补充段间空行，保持版面整洁&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;版式设置&lt;/strong&gt;：自定义段首/段尾标点规则，适应不同写作风格&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;错别字和语法检测&lt;/strong&gt;：内置错别字和语法错误统计与识别功能&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LLM 智能校对&lt;/strong&gt;：基于大语言模型的错别字检测、语法修正和文本润色功能，提供专业的写作质量保障&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;快捷设置面板&lt;/h3&gt;
&lt;p&gt;通过命令 &lt;code&gt;andrea.quickSettings&lt;/code&gt; 或者状态栏按钮，可以快速唤起聚合菜单，无需深入 VS Code 设置即可调整常用写作选项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;排版与外观&lt;/strong&gt;：快速切换自动换行、首行缩进、段间空行、小地图及滚轮缩放&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;字体管理&lt;/strong&gt;：提供图形化的编辑器字体家族管理工具&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;智能辅助&lt;/strong&gt;：一键启停智慧回车、智慧括号、智能分组锁&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;统计配置&lt;/strong&gt;：调整字数统计单位、状态栏模式及里程碑提醒&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;规则管理&lt;/strong&gt;：图形化管理 &lt;code&gt;.wcignore&lt;/code&gt; 忽略规则&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🌍 设定集与世界观构建&lt;/h2&gt;
&lt;h3&gt;统一对象模型 (Unified Object Model)&lt;/h3&gt;
&lt;p&gt;小说助手采用创新的&lt;strong&gt;统一对象模型&lt;/strong&gt;来管理所有设定元素。无论是人物、敏感词、专有名词还是正则规则，本质上都是具有不同 &lt;code&gt;type&lt;/code&gt; 属性的角色对象。&lt;/p&gt;
&lt;h4&gt;通用特性&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;全能别名支持&lt;/strong&gt;：所有对象均支持定义别名 (Aliases)，在补全、高亮、引用查找时会自动识别主名与所有别名，并支持统一替换&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;代码级导航体验&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;跳转到定义 (Go to Definition)&lt;/strong&gt;：像查看代码定义一样，一键跳转到角色/词汇的源文件定义处&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查看引用 (Find All References)&lt;/strong&gt;：查找该角色在所有章节中的出现位置，支持列表跳转&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;智能补全与高亮&lt;/strong&gt;：所有类型的对象均支持自动补全与文中高亮显示&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可视化编辑&lt;/strong&gt;：提供统一的图形化卡片编辑器&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;引用分析&lt;/strong&gt;：支持引用索引、热力图与气泡图，分析对象在文档中的分布&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;多格式资源管理&lt;/h3&gt;
&lt;p&gt;小说助手通过&quot;包&quot;（Package）概念统一管理四大主资源类型：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;资源&lt;/th&gt;
&lt;th&gt;典型文件&lt;/th&gt;
&lt;th&gt;支持格式&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;角色&lt;/td&gt;
&lt;td&gt;&lt;code&gt;character-gallery.json5&lt;/code&gt; / &lt;code&gt;*.md&lt;/code&gt; / &lt;code&gt;*.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON5 / Markdown / TXT&lt;/td&gt;
&lt;td&gt;角色设定、别名、颜色、类型、扩展字段&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;敏感词&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sensitive-words.json5&lt;/code&gt; / &lt;code&gt;*.md&lt;/code&gt; / &lt;code&gt;*.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON5 / Markdown / TXT&lt;/td&gt;
&lt;td&gt;内容安全或需要标识的词汇集合&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;词汇&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vocabulary.json5&lt;/code&gt; / &lt;code&gt;*.md&lt;/code&gt; / &lt;code&gt;*.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON5 / Markdown / TXT&lt;/td&gt;
&lt;td&gt;世界观专有名词、术语表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;正则规则&lt;/td&gt;
&lt;td&gt;&lt;code&gt;regex-patterns.json5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON5&lt;/td&gt;
&lt;td&gt;自定义正则高亮/着色规则&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;包结构建议&lt;/h3&gt;
&lt;p&gt;推荐的组织结构：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;novel-helper/
  main/                         # 主设定包（集中核心/跨包共享设定）
    character-gallery.json5     # 主角色集合（结构化）
    world_roles.md              # 追加角色章节 (Markdown，多角色/字段)
    sensitive-words.json5       # 敏感词
    vocabulary.json5            # 词汇
    regex-patterns.json5        # 正则规则
  faction-a/                    # 阵营 / 派系 A（局部角色或补充）
    character-gallery.json5
  faction-b/                    # 阵营 / 派系 B
    character-gallery.json5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;📂 项目与文件管理&lt;/h2&gt;
&lt;h3&gt;写作资源管理器&lt;/h3&gt;
&lt;p&gt;替代原生资源管理器，提供专注的写作视图：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;专注视图&lt;/strong&gt;：仅显示写作相关文件，避免干扰&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;灵活排序&lt;/strong&gt;：支持手动拖拽排序（生成稀疏索引）或自动排序&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;目录聚合&lt;/strong&gt;：自动聚合计算目录下的总字数&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文件追踪&lt;/strong&gt;：基于分片数据库的高性能文件追踪系统&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;云端同步 (WebDAV)&lt;/h3&gt;
&lt;p&gt;支持多账户 WebDAV 同步，确保写作进度安全备份：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多账户支持&lt;/strong&gt;：配置多个 WebDAV 账户&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时同步&lt;/strong&gt;：状态栏实时显示同步进度与状态&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可视化管理&lt;/strong&gt;：独立的 WebDAV 文件树视图与同步控制面板&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;冲突处理&lt;/strong&gt;：智能处理本地与云端文件冲突&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;项目配置&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;初始化向导&lt;/strong&gt;：一键生成项目结构、配置文件及忽略规则（&lt;code&gt;.gitignore&lt;/code&gt;, &lt;code&gt;.wcignore&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;项目配置文件&lt;/strong&gt;：通过 &lt;code&gt;anhproject.md&lt;/code&gt; 管理项目元信息&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🤖 自动化与扩展&lt;/h2&gt;
&lt;h3&gt;用户脚本与 MCP 运行时&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;用户脚本系统&lt;/strong&gt;：内置脚本运行器，允许用户编写自定义脚本扩展功能&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP (Model Context Protocol) 支持&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;集成 MCP 运行时，可调用外部工具与服务&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动发布场景&lt;/strong&gt;：结合浏览器自动化工具，可编写脚本实现章节自动发布到小说网站&lt;/li&gt;
&lt;li&gt;侧边栏一键运行管理&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Typst 排版导出&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;高质量输出&lt;/strong&gt;：基于 Typst 引擎导出 PDF、图片（PNG/SVG）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;模板系统&lt;/strong&gt;：内置多种模板（如论坛体），支持自定义模板开发&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;智能转换&lt;/strong&gt;：Markdown 语法自动转换为 Typst 格式，支持图片路径自动处理&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;📊 实时辅助功能&lt;/h2&gt;
&lt;h3&gt;阅读与预览&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;侧边栏预览&lt;/strong&gt;：支持 Markdown 和 TXT 格式的实时预览&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;个性化阅读&lt;/strong&gt;：支持自定义预览界面的主题与字体设置&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大纲视图&lt;/strong&gt;：支持懒加载大纲生成，提供双重大纲辅助写作&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;批注系统&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;独立侧边栏&lt;/strong&gt;：专用的批注管理视图，支持归总、跳转与快速处理&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;伏笔管理&lt;/strong&gt;：便于记录和追踪剧情伏笔&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;LLM 智能辅助（润色和生成部分位于 ANH CHAT 附件中 不随小说助手本体提供 或者您可以使用任何 Code Agent 完成这部分工作）&lt;/h3&gt;
&lt;p&gt;集成大语言模型能力，为创作者提供智能化的写作辅助：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;智能校对与润色&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;错别字检测&lt;/strong&gt;：基于 LLM 的智能错别字识别，比传统规则检测更准确 （本体集成）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;语法修正&lt;/strong&gt;：自动检测语法错误并提供修改建议 （本体集成）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文本润色&lt;/strong&gt;：优化表达方式，提升文字质量和可读性 （附加组件 Anh Chat 提供）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;风格建议&lt;/strong&gt;：根据小说类型提供风格化的修改建议 （附加组件 Anh Chat 提供）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;多语言翻译&lt;/strong&gt;：基于大模型的快速翻译工具，支持替换选区或复制结果，帮助创作者进行多语言创作 （本体集成）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;内容生成辅助&lt;/strong&gt;： （附加组件 Anh Chat 提供）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;情节建议&lt;/strong&gt;：根据当前内容提供情节发展建议&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;角色对话生成&lt;/strong&gt;：生成符合角色性格的对话内容&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;场景描写&lt;/strong&gt;：提供场景描写的参考和建议&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🎯 核心优势&lt;/h2&gt;
&lt;h3&gt;1. &lt;strong&gt;统一的工作环境&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;在熟悉的 VS Code 环境中完成所有写作工作，无需切换多个应用程序。&lt;/p&gt;
&lt;h3&gt;2. &lt;strong&gt;智能化的辅助功能&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;从自动补全到错误检测，从统计分析到格式化，特别是集成的 LLM 智能校对和润色功能，全方位提升写作效率和质量。&lt;/p&gt;
&lt;h3&gt;3. &lt;strong&gt;强大的数据管理&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&quot;统一对象模型&quot;让角色、词汇、敏感词等所有设定都能得到统一管理和高效检索。&lt;/p&gt;
&lt;h3&gt;4. &lt;strong&gt;高度可定制性&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;支持用户脚本、自定义模板、个性化设置等，满足不同创作者的特殊需求。&lt;/p&gt;
&lt;h3&gt;5. &lt;strong&gt;现代化的技术栈&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;基于 VS Code 扩展平台，享受现代化的编辑器技术和生态系统。&lt;/p&gt;
&lt;h2&gt;🆚 与传统写作软件对比&lt;/h2&gt;
&lt;p&gt;小说助手坚持&quot;稿件可见宣言&quot;，与传统闭源写作软件相比具有显著优势：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性维度&lt;/th&gt;
&lt;th&gt;Andrea Novel Helper (开源)&lt;/th&gt;
&lt;th&gt;传统闭源写作软件&lt;/th&gt;
&lt;th&gt;优势说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;数据存储&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Markdown/TXT/JSON5 (开放格式)&lt;/td&gt;
&lt;td&gt;私有数据库/封闭格式&lt;/td&gt;
&lt;td&gt;文件可被记事本直接打开，完全掌控数据&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;备份与迁移&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Git/压缩包/U 盘/网盘 (自由选择)&lt;/td&gt;
&lt;td&gt;官方迁移工具 (依赖厂商) 或者根本不提供&lt;/td&gt;
&lt;td&gt;无需特定工具，备份随心所欲&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;版本控制&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;原生支持 Git，完整的版本历史&lt;/td&gt;
&lt;td&gt;有限版本控制或无&lt;/td&gt;
&lt;td&gt;专业级的版本管理，支持分支和合并&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;协作能力&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Git 协作，透明审阅，可 diff&lt;/td&gt;
&lt;td&gt;专有协作系统 (锁定生态)&lt;/td&gt;
&lt;td&gt;开放的协作流程，不限工具和平台&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IDE 级辅助&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;智能补全、语法高亮、跳转定义、引用分析&lt;/td&gt;
&lt;td&gt;基础编辑功能&lt;/td&gt;
&lt;td&gt;享受现代 IDE 的强大辅助功能&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;定制扩展&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;用户脚本、MCP、VS Code 生态&lt;/td&gt;
&lt;td&gt;有限插件或无&lt;/td&gt;
&lt;td&gt;无限扩展可能性，社区驱动&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;云同步&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;WebDAV/Git (自由选择服务商)&lt;/td&gt;
&lt;td&gt;官方云服务 (锁定)&lt;/td&gt;
&lt;td&gt;可选择任何兼容的云存储服务&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;数据安全&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;数据完全本地，可选择在线服务&lt;/td&gt;
&lt;td&gt;数据存储在厂商服务器&lt;/td&gt;
&lt;td&gt;完全掌控数据流向和隐私安全&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;成本费用&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;完全免费 (开源 MPL-2.0)&lt;/td&gt;
&lt;td&gt;订阅制或一次性购买&lt;/td&gt;
&lt;td&gt;零成本使用，无功能限制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;技术支持&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;社区支持 + 开源透明&lt;/td&gt;
&lt;td&gt;官方支持 (依赖厂商响应)&lt;/td&gt;
&lt;td&gt;透明的源码，社区共同维护&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;平台锁定&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;跨平台 (VS Code 支持)&lt;/td&gt;
&lt;td&gt;可能限制特定平台&lt;/td&gt;
&lt;td&gt;任何支持 VS Code 的平台都能使用&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;稿件可见宣言&lt;/h3&gt;
&lt;p&gt;我们主张：&lt;strong&gt;稿件一定要可读、可备份、可协作、可迁移&lt;/strong&gt;；文件一定要归创作者所有，不做技术人质。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;稿件一定要能被记事本直接打开与编辑&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文件一定要用普通格式保存（Markdown / TXT / JSON5）&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;备份一定要随手可做（Git / 压缩包 / U 盘 / 网盘）&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;协作一定要透明（可 diff / 可审阅 / 可回滚）&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;迁移一定要不设门槛（换工具不做&quot;迁移仪式&quot;）&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;小说助手坚持开放文件与透明模型，拒绝私有封闭格式，让创作真正掌握在创作者手中。&lt;/p&gt;
&lt;h2&gt;🚀 快速开始&lt;/h2&gt;
&lt;h3&gt;安装扩展&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;在 VS Code 扩展市场中搜索 &quot;Novel Helper&quot;&lt;/li&gt;
&lt;li&gt;或访问 &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=andreafrederica.andrea-novel-helper&quot;&gt;VS Code Marketplace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;点击安装，或选择安装合集获得完整功能&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;创建新项目&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;打开命令面板（Ctrl+Shift+P）&lt;/li&gt;
&lt;li&gt;搜索并执行 &quot;Andrea Novel Helper: Initialize Project&quot;&lt;/li&gt;
&lt;li&gt;（前两步若您打开新空白工作区 可自动弹出向导）&lt;/li&gt;
&lt;li&gt;按照向导提示配置项目信息&lt;/li&gt;
&lt;li&gt;自动生成项目结构和配置文件&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;基本使用流程&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;创建角色库&lt;/strong&gt;：在包管理器中创建 &lt;code&gt;character-gallery.json5&lt;/code&gt; 或 &lt;code&gt;.md&lt;/code&gt; 文件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;添加角色设定&lt;/strong&gt;：使用可视化编辑器或直接编写 Markdown/JSON5&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开始写作&lt;/strong&gt;：在章节文件中享受智能补全和高亮功能&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查看统计&lt;/strong&gt;：通过统计面板监控写作进度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;导出作品&lt;/strong&gt;：使用 Typst 或者纯文本渲染器 导出功能生成高质量文档&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;📈 发展历程&lt;/h2&gt;
&lt;p&gt;小说助手持续快速发展，近期重要更新包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;v0.4.35 (2025-11-21)&lt;/strong&gt;：支持快捷翻译和并行缓存校验&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大幅重构异步加载与性能管线&lt;/strong&gt;：提升整体性能和响应速度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;独立组件发布&lt;/strong&gt;：Anh Chat (小说助手聊天组件) 独立发布，提供生成式 AI 功能&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;💬 社区与支持&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitHub Issues&lt;/strong&gt;：&lt;a href=&quot;https://github.com/AndreaFrederica/andrea-novel-helper/issues&quot;&gt;提交问题报告和功能请求&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QQ 群&lt;/strong&gt;：&lt;a href=&quot;https://qm.qq.com/q/SG5A3XLoSQ&quot;&gt;小说助手用户反馈和交流&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discord&lt;/strong&gt;：&lt;a href=&quot;https://discord.gg/YeVAXeKX&quot;&gt;加入社区讨论&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub Discussions&lt;/strong&gt;：&lt;a href=&quot;https://github.com/AndreaFrederica/andrea-novel-helper/discussions&quot;&gt;功能建议和经验分享&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;📄 许可证&lt;/h2&gt;
&lt;p&gt;本项目采用 &lt;a href=&quot;https://www.mozilla.org/MPL/2.0/&quot;&gt;MPL-2.0&lt;/a&gt; 许可证，允许自由使用、修改和分发。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;Andrea Novel Helper&lt;/strong&gt; 不仅仅是一个写作工具，它是现代技术与创作艺术的完美结合，为每一位小说创作者提供强大的创作支持。无论你是初出茅庐的新人，还是经验丰富的老手，都能在这里找到适合自己的创作方式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;立即体验，开启你的高效创作之旅！&lt;/strong&gt; ✨&lt;/p&gt;
</content:encoded></item><item><title>一个Typst模板</title><link>https://blog.sirrus.cc/posts/typest-temple-pub1/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/typest-temple-pub1/</guid><description>一个Typst模板使用说明</description><pubDate>Sun, 21 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;模板下载&lt;/h2&gt;
&lt;p&gt;查看 Typst 模板 源文件：&lt;a href=&quot;/downloads/novel1.typ&quot;&gt;查看 novel1.typ&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;点击下载模板源文件：&amp;lt;a href=&quot;/downloads/novel1.typ&quot; download&amp;gt;下载 novel1.typ&amp;lt;/a&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;当您二次分享时 希望您遵守模板的许可证 使用无需遵守 MIT 许可证&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;模板预览&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./img/test_01.png&quot; alt=&quot;预览1&quot; /&gt;
&lt;img src=&quot;./img/test_02.png&quot; alt=&quot;预览2&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;模板源码&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;#let theme = (
  text-font: &quot;Noto Sans SC&quot;,
  heading-font: &quot;Noto Sans SC&quot;,
  text-size: 20pt,
  category-size: 50pt,
  title-size: 30pt,
  separator-size: 50pt,
  sub-size: 12pt,
  color: rgb(&quot;#111&quot;),
  gray: rgb(&quot;#6b7280&quot;),
  line-height: 1,
  indent: 2em,
  para-spacing: 2em,
)

#let zh-paragraph() = {
  set par(justify: true, first-line-indent: theme.indent,
          leading: theme.line-height * 1em, spacing: theme.para-spacing)
  set text(lang: &quot;zh&quot;, font: theme.text-font, size: theme.text-size, fill: theme.color)
}

#let article-card(
  title, body,
  category: none, subtitle: none,
  category-size: none, title-size: none, separator-size: none, body-size: none
) = block(
  // 用 block 而不是 box：block 是可分页的
  fill: white,
  inset: 22pt,      // 内边距
  radius: 8pt,      // 圆角
  stroke: none,
  width: 440pt,     // 版心宽度（可调）
  breakable: true,  // 显式允许跨页（缺省也是可分页）
)[
  // 标题
  #set text(font: theme.heading-font, weight: &quot;bold&quot;)
  #if (category != none) [
    #text(size: if category-size != none { category-size } else { theme.category-size })[#category]
    #text(size: if separator-size != none { separator-size } else { theme.separator-size })[ ｜]
  ]
  #text(size: if title-size != none { title-size } else { theme.title-size })[#title]

  // 副标题（可选）
  #if (subtitle != none) [
    #v(6pt)
    #set text(font: theme.heading-font, size: theme.sub-size, fill: theme.gray)
    #subtitle
  ]

  #v(10pt)

  // 正文
  #set par(justify: true, first-line-indent: theme.indent,
           leading: theme.line-height * 1em, spacing: theme.para-spacing)
  #set text(lang: &quot;zh&quot;, font: theme.text-font,
            size: if body-size != none { body-size } else { theme.text-size },
            fill: theme.color)
  #body
]


// 使用示例
#article-card(
  category: &quot;模板&quot;,
  // subtitle: [可选的副标题写这里，注释去掉即可。],
  &quot;这份 Typst 文章模板怎么用（小白向）&quot;,
  [
本模板用于排一个白底内容卡片：上方是“分类｜标题”，下面是正文。容器可自动分页，所以写长文也不用担心被截断。

一、写正文
把每个自然段直接放在这里，每两个段落之间留一个真正的空行即可。若从网页粘贴导致空行里混入全角空格，看起来空但其实不空，段落就不会分开；遇到这种情况，手动敲一个空行，或把光标放在空行里按删除直到行首没有任何字符。

二、改样式
想要无衬线风格（黑体），已默认使用 Noto Sans SC；若你电脑没有该字体，可以在上面的 theme 里把 text-font / heading-font 改成系统里存在的字体，例如 Source Han Sans SC 或 Microsoft YaHei。

三、改字号与间距
段内行距由 line-height 控制（数值越大越疏），段间距由 para-spacing 控制（例如 2em）。你也可以在调用 article-card 时单独覆盖 body-size（正文字号）。

四、改标题行
分类、标题和分隔竖线的字号分别受 category-size、title-size、separator-size 控制；留空就用 theme 里的默认值。不要分类时，把 category 参数去掉即可。

五、版心宽度
内容卡片的宽度是 440pt，可在 article-card 的 width 参数上调整；页面边距想更大，可在外部用 set page(margin: ...) 调整。

开始写作吧：把这段说明删掉，换成你的正文即可。
  ],

)

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>小说助手 安装和基础功能使用说明</title><link>https://blog.sirrus.cc/posts/novel-helper-guide-base/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/novel-helper-guide-base/</guid><description>从零开始掌握小说助手！这篇完整指南涵盖了便携安装和专业安装的双重方案，详细讲解新建书籍项目、写作资源管理、敏感词识别、智能补全、设定集管理等核心功能。</description><pubDate>Mon, 08 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;小说助手官网：&lt;/strong&gt; &lt;a href=&quot;https://anh.sirrus.cc&quot;&gt;https://anh.sirrus.cc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;安装&lt;/h1&gt;
&lt;h3&gt;便携安装（对于普通用户）&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;下载安装包&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image1.png&quot; alt=&quot;图形用户界面, 文本, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image2.png&quot; alt=&quot;图形用户界面 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;选择 是&lt;/p&gt;
&lt;p&gt;选择安装语言&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image-20250908220116057.png&quot; alt=&quot;image-20250908220116057&quot; /&gt;&lt;/p&gt;
&lt;p&gt;设置用户名密码&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image-20250908220237449.png&quot; alt=&quot;image-20250908220237449&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-03-48.png&quot; alt=&quot;Snipaste_2025-09-08_22-03-48&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-04-01.png&quot; alt=&quot;Snipaste_2025-09-08_22-04-01&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-04-11.png&quot; alt=&quot;Snipaste_2025-09-08_22-04-11&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-04-30.png&quot; alt=&quot;Snipaste_2025-09-08_22-04-30&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-04-37.png&quot; alt=&quot;Snipaste_2025-09-08_22-04-37&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-04-48.png&quot; alt=&quot;Snipaste_2025-09-08_22-04-48&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-04-57.png&quot; alt=&quot;Snipaste_2025-09-08_22-04-57&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-05-09.png&quot; alt=&quot;Snipaste_2025-09-08_22-05-09&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-05-21.png&quot; alt=&quot;Snipaste_2025-09-08_22-05-21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/Snipaste_2025-09-08_22-05-33.png&quot; alt=&quot;Snipaste_2025-09-08_22-05-33&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最后会自动在桌面上创建图标 根据提示 启动两次就自动设置为中文&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image6.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第一次启动&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image7.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第二次启动&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;显示为中文即为便携安装完成&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;全量安装（对于专业用户）&lt;/h3&gt;
&lt;h4&gt;第一步 下载 Git 和编辑器&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Git 官网：https://git-scm.com/downloads&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;加速下载（选普通下载）：&lt;a href=&quot;https://pc.qq.com/detail/13/detail_22693.html&quot;&gt;https://pc.qq.com/detail/13/detail_22693.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image8.png&quot; alt=&quot;图形用户界面, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;选择 是&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image9.png&quot; alt=&quot;电脑软件的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image10.png&quot; alt=&quot;电脑软件截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;根据情况选择&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image11.png&quot; alt=&quot;电脑软件的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;默认编辑器不会用 vim 可以用别的 （推荐 vscode）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image12.png&quot; alt=&quot;图形用户界面, 文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;（如果选择 vscode）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image13.png&quot; alt=&quot;图形用户界面, 文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image14.png&quot; alt=&quot;电脑软件的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可选第二个或者第三个&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image15.png&quot; alt=&quot;图形用户界面, 文本, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image16.png&quot; alt=&quot;图形用户界面, 文本, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image17.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;br /&gt;
Next&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image18.png&quot; alt=&quot;图形用户界面, 文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;br /&gt;
这个随便选&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image19.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;br /&gt;
Next&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image20.png&quot; alt=&quot;电脑软件的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;br /&gt;
Next&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image21.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;br /&gt;
点击安装即可&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image22.png&quot; alt=&quot;电脑游戏的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;br /&gt;
Git 安装结束&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;lt;!-- --&amp;gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;安装 VSCode&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;官网：&lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;https://code.visualstudio.com/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image23.png&quot; alt=&quot;图形用户界面, 文本, 应用程序, 聊天或短信 AI 生成的内容可能不正确。&quot; /&gt;&lt;br /&gt;
我同意 下一步&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image24.png&quot; alt=&quot;图形用户界面, 文本, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;建议全勾上&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image25.png&quot; alt=&quot;图形用户界面, 文本, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image26.png&quot; alt=&quot;图形用户界面, 文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装完成（运行）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;安装小说助手&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image27.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;点击扩展按钮 搜索 Andrea Novel Editor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image28.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装合集&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ctrl Shift P&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image29.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置语言为中文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image30.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置图标主题&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image31.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;个人建议使用 Material（当然主题 图标主题 美化 你可以自己在插件商店下载）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;使用&lt;/h1&gt;
&lt;h2&gt;新建书籍项目 &lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image32.png&quot; alt=&quot;电脑的屏幕截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/h2&gt;
&lt;p&gt;使用打开文件夹打开一个空白文件夹（这会是一本书的存储地点）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image33.png&quot; alt=&quot;截图里有图片 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们打开一个新建文件夹&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image34.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点击信任&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image35.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第一次使用 先配置 git 信息&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image36.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;输入用户名（任意（最好是英文））&lt;/p&gt;
&lt;p&gt;邮箱（最好真的能用 这个用来绑定云存储）&lt;/p&gt;
&lt;p&gt;回车即可&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image37.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;选择全局&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image38.png&quot; alt=&quot;电脑萤幕截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;会看到提示 运行向导来创建小说项目&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image39.png&quot; alt=&quot;图形用户界面 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;选择初始化仓库&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image40.png&quot; alt=&quot;图形用户界面 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;选择创建示例结构&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image41.png&quot; alt=&quot;图形用户界面, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;br /&gt;
需要云同步写作进度可以纳入 但是没必要&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image42.png&quot; alt=&quot;图形用户界面, 文本, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;根据推荐来选择即可&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image43.png&quot; alt=&quot;电脑萤幕画面 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;是 创建初始提交&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image44.png&quot; alt=&quot;图形用户界面, 文本, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;是 执行&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image45.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image46.png&quot; alt=&quot;图形用户界面, 文本, 应用程序 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;关闭即可 初始化小说项目完成&lt;/p&gt;
&lt;h2&gt;写作资源管理器（全文字数统计）&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image47.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image48.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image49.png&quot; alt=&quot;电脑萤幕截图 AI 生成的内容可能不正确。&quot; /&gt;新建文件夹 新建新的一卷&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image50.png&quot; alt=&quot;电脑萤幕截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;右键第一卷 可以选择章节排序方式（默认使用名称排序）&lt;/p&gt;
&lt;p&gt;如&lt;/p&gt;
&lt;p&gt;第一章&lt;/p&gt;
&lt;p&gt;第二章&lt;/p&gt;
&lt;p&gt;或者&lt;/p&gt;
&lt;p&gt;1 xxx&lt;/p&gt;
&lt;p&gt;2 xxx&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image51.png&quot; alt=&quot;电脑屏幕截图 AI 生成的内容可能不正确。&quot; /&gt;点击切换手动排序 可以切换成手动排序（类似传统码字软件）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image52.png&quot; alt=&quot;电脑萤幕截图 AI 生成的内容可能不正确。&quot; /&gt;点击新建文章 选择章节格式（markdown（更强大） 或者 txt）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image53.png&quot; alt=&quot;电脑萤幕截图 AI 生成的内容可能不正确。&quot; /&gt;输入文件名&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image54.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;手动排序模式下 前面的数字是第几章&lt;/p&gt;
&lt;p&gt;所有模式下 后面的数字是字数&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image55.png&quot; alt=&quot;电脑萤幕截图 AI 生成的内容可能不正确。&quot; /&gt;打开文件的情况下 点击大纲按钮打开大纲&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image56.png&quot; alt=&quot;电脑萤幕画面 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;会自动创建文件夹和文件的大纲&lt;/p&gt;
&lt;p&gt;所有的窗体都是一样的 可以拖动&lt;/p&gt;
&lt;p&gt;（编辑的时候记得保存！ 或者你开自动保存也行）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image57.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;可以自定义工作区的形状&lt;/p&gt;
&lt;h2&gt;敏感词识别&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image58.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;点击警告按钮 可以查看文章有什么问题&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image59.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;选择问题面板 查看问题&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image60.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;点击问题可以转跳到问题出处&lt;/p&gt;
&lt;h2&gt;智能补全和提示&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image61.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;设置完设定集后 输入时可以根据设定集补全&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image62.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;有设定集的内容可以高亮着色&lt;/p&gt;
&lt;p&gt;具体描述和着色参照设定集&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image63.png&quot; alt=&quot;图形用户界面 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;如果角色写了别名 可以替换为别名&lt;/p&gt;
&lt;p&gt;按住 Ctrl+鼠标左键 可以转跳到设定集&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image64.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;当前文章角色的功能类似&lt;/p&gt;
&lt;h2&gt;设定集管理器&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image65.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;点击小说助手按钮打开设定集管理器&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image66.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;右键任意目录 可以创建设定集（子目录/包）和设定集文件&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image67.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;以创建角色库为例子&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image68.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;会询问文件名&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image69.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;选择格式&lt;/p&gt;
&lt;p&gt;Md 和 json5 功能比较强大&lt;/p&gt;
&lt;p&gt;但是 md 更可读&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image70.png&quot; alt=&quot;电脑萤幕截图 AI 生成的内容可能不正确。&quot; /&gt;以 md 为例&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image71.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;md 文件中 选中文本 可以快速指定格式&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image72.png&quot; alt=&quot;图片&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点击 MPE 预览按键 打开预览&lt;/p&gt;
&lt;p&gt;修改完设定集后会自动加载&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image73.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;本着万物皆角色的理念 设定集可以描述任何东西&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image74.png&quot; alt=&quot;电脑屏幕截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;甚至支持插入图片&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image75.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;json5 格式的设定集&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image76.png&quot; alt=&quot;图形用户界面, 文本 AI 生成的内容可能不正确。&quot; /&gt;你可以把鼠标放在色块上改变颜色（记得保存）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image77.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;每天写完记得保存进度 这样你能出问题了恢复到上个版本！&lt;/p&gt;
&lt;h2&gt;写作统计&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image78.png&quot; alt=&quot;电脑萤幕的截图 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点击下面的字数统计可以打开码字统计面板&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image79.png&quot; alt=&quot;图形用户界面, 文本, 应用程序, Teams AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这是内容&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image80.png&quot; alt=&quot;图形用户界面 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;导出 预览 和 读稿器&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;%E5%B0%8F%E8%AF%B4%E5%8A%A9%E6%89%8B%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-media/media/image81.png&quot; alt=&quot;文本 AI 生成的内容可能不正确。&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点击 OpenPreview 打开预览和读稿器（测试版）&lt;/p&gt;
&lt;p&gt;点击播放即可读稿&lt;/p&gt;
&lt;h2&gt;界面美化&lt;/h2&gt;
&lt;p&gt;百度查询 vscode 美化教程&lt;/p&gt;
</content:encoded></item><item><title>VS Code Git集成与各大平台私有仓库使用指南（小说助手专用）</title><link>https://blog.sirrus.cc/posts/novel-helper-code-guide-git/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/novel-helper-code-guide-git/</guid><description>掌握VS Code Git集成，让版本控制变得简单！这篇图解指南从基础到进阶，涵盖仓库初始化、分支管理、冲突解决、历史追溯等核心功能，搭配详细的操作截图和实用技巧。同时深度解析各大代码托管平台的私有仓库创建、权限管理、CI/CD配额等实用攻略。无论是小说写作项目还是代码开发，都能让你高效管理版本历史，告别版本混乱的烦恼。</description><pubDate>Mon, 08 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;小说助手官网：&lt;/strong&gt; &lt;a href=&quot;https://anh.sirrus.cc&quot;&gt;https://anh.sirrus.cc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;VS Code Git 集成使用指南（图解）&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;适用版本：VS Code 桌面版与 Web（大部分功能相同）。默认已安装 Git（建议 &lt;code&gt;&amp;gt;= 2.0.0&lt;/code&gt;）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;🎯 特别说明：小说助手用户必读&lt;/h2&gt;
&lt;h3&gt;什么是版本管理？&lt;/h3&gt;
&lt;p&gt;版本管理就像是您小说的&quot;时光机&quot;，可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;保存写作进度&lt;/strong&gt;：每次修改都会被记录，不会丢失&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;回退到任意版本&lt;/strong&gt;：写错了可以回到之前的正确版本&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;比较修改内容&lt;/strong&gt;：清楚看到每次修改了什么&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多人协作&lt;/strong&gt;：团队成员可以同时编辑，互不干扰&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;为什么小说助手需要 Git？&lt;/h3&gt;
&lt;p&gt;小说助手已经为您创建了本地仓库，但要实现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;云端备份&lt;/strong&gt;：防止本地文件丢失&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;多设备同步&lt;/strong&gt;：在家和公司都能继续写作&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;版本回溯&lt;/strong&gt;：不满意的修改可以撤销&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;协作写作&lt;/strong&gt;：多人共同创作同一部小说&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;📋 小说助手专用 Git 工作流程&lt;/h2&gt;
&lt;h3&gt;步骤 1：查看更改&lt;/h3&gt;
&lt;p&gt;打开小说助手项目后，在 VS Code 中按 &lt;code&gt;Ctrl+Shift+G&lt;/code&gt; 进入源代码管理视图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/overview.png&quot; alt=&quot;Git 概览&quot; /&gt;&lt;/p&gt;
&lt;p&gt;您会看到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CHANGES&lt;/strong&gt;：您修改的文件列表&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;STAGED CHANGES&lt;/strong&gt;：准备提交的文件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MESSAGE&lt;/strong&gt;：提交信息的输入框&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;步骤 2：暂存更改&lt;/h3&gt;
&lt;p&gt;在 CHANGES 中点击文件旁的 &lt;code&gt;+&lt;/code&gt; 按钮，将修改添加到暂存区：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/diff.png&quot; alt=&quot;Diff 视图（左右对比）&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;小贴士&lt;/strong&gt;：绿色部分是新增内容，红色部分是删除内容&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;步骤 3：提交更改&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;在 MESSAGE 框中输入提交信息（如：&quot;更新第 5 章开头&quot;）&lt;/li&gt;
&lt;li&gt;点击 ✅ 提交按钮，或按 &lt;code&gt;Ctrl+Enter&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/scm-more-actions.png&quot; alt=&quot;更多操作菜单&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;步骤 4：推送到云端&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;点击右上角的同步按钮 🔄&lt;/li&gt;
&lt;li&gt;选择 &lt;strong&gt;Push&lt;/strong&gt; 将本地提交上传到 GitHub&lt;/li&gt;
&lt;li&gt;选择 &lt;strong&gt;Pull&lt;/strong&gt; 从 GitHub 下载最新更新&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;🔄 小说助手用户日常同步操作&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;写作前&lt;/strong&gt;：先执行 &lt;strong&gt;Pull&lt;/strong&gt; 确保获取最新版本&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;写作中&lt;/strong&gt;：每完成一个段落或章节就提交一次&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;写作后&lt;/strong&gt;：执行 &lt;strong&gt;Push&lt;/strong&gt; 保存到云端&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多设备&lt;/strong&gt;：在另一台设备上先 &lt;strong&gt;Pull&lt;/strong&gt; 获取最新内容&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这样您的小说永远不会丢失，还可以随时回到任何一个写作阶段！&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🛠️ 通用 Git 操作指南&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;安装 &lt;a href=&quot;https://git-scm.com/downloads&quot;&gt;Git&lt;/a&gt; 并确保终端能执行 &lt;code&gt;git --version&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;VS Code 通过活动栏左侧的“源代码管理”图标进入 Git 视图（快捷键：&lt;strong&gt;Windows/Linux：Ctrl+Shift+G；macOS：⌃⇧G&lt;/strong&gt;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/overview.png&quot; alt=&quot;Git 概览&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2) 打开或克隆仓库&lt;/h2&gt;
&lt;h3&gt;打开项目或克隆&lt;/h3&gt;
&lt;p&gt;首次打开时，源代码管理视图会提供“Open Folder / Clone Repository”按钮：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/firstrun-source-control.png&quot; alt=&quot;首次运行界面&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clone Repository&lt;/strong&gt;：输入远程地址（例如 GitHub）即可克隆：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/GitHub-clone-dialog.png&quot; alt=&quot;GitHub 克隆来源&quot; /&gt;
&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/set-repo-URL.png&quot; alt=&quot;在命令面板中输入仓库 URL&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;初始化本地仓库&lt;/h3&gt;
&lt;p&gt;若当前文件夹不是 Git 仓库，点击 &lt;strong&gt;Initialize Repository&lt;/strong&gt; 初始化；也可一键 &lt;strong&gt;Publish to GitHub&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/initialize-repository.png&quot; alt=&quot;初始化仓库&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3. 暂存（Stage）与提交（Commit）&lt;/h3&gt;
&lt;p&gt;在“源代码管理”视图中会分为 &lt;strong&gt;CHANGES / STAGED CHANGES / MERGE CHANGES&lt;/strong&gt; 三块。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;选择文件可在内置 &lt;strong&gt;Diff 编辑器&lt;/strong&gt; 中查看变更；右侧编辑器仍可直接修改未暂存内容。&lt;/li&gt;
&lt;li&gt;在 Diff 中间栏可以&lt;strong&gt;逐块暂存/回退&lt;/strong&gt;（Stage/Revert hunk）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/diff.png&quot; alt=&quot;Diff 视图（左右对比）&quot; /&gt;&lt;/p&gt;
&lt;p&gt;更多提交相关操作可在右上角 &lt;strong&gt;…（Views and More Actions）&lt;/strong&gt; 菜单找到：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/scm-more-actions.png&quot; alt=&quot;更多操作菜单&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;小贴士：你也可以使用 Copilot 生成提交信息（在提交输入框的按钮处），或在编辑器中查看 blame 信息（可通过设置模板自定义显示）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;4. 分支与标签（Branches &amp;amp; Tags）&lt;/h3&gt;
&lt;p&gt;通过命令面板：&lt;strong&gt;Git: Create Branch&lt;/strong&gt;、&lt;strong&gt;Git: Checkout to…&lt;/strong&gt; 创建/切换分支或检出标签；也可从状态栏分支指示器切换。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/gitbranches.png&quot; alt=&quot;分支/标签选择&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;5. 源代码控制图（Graph）&lt;/h3&gt;
&lt;p&gt;配置了远端后，可在 &lt;strong&gt;Graph&lt;/strong&gt; 里看到&lt;strong&gt;领先/落后&lt;/strong&gt;、提交流向等；右键提交可执行 &lt;strong&gt;checkout / cherry-pick&lt;/strong&gt; 等操作，点文件可直接打开该提交的 diff。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/incoming-outgoing-changes.png&quot; alt=&quot;Graph 图形视图（incoming/outgoing）&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;6. 查看历史：时间线（Timeline）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Timeline&lt;/strong&gt; 视图（资源管理器底部）统一展示文件的时间序列事件（如 Git 提交）。选择某个提交即可打开当次变更的 diff。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/timeline-view.png&quot; alt=&quot;Timeline 视图&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;7. VS Code 作为 Git 的编辑器/差异/合并工具&lt;/h3&gt;
&lt;p&gt;把 VS Code 配置为 Git 的外部工具（命令行执行）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 作为 Git 的编辑器（等待 VS Code 关闭）
git config --global core.editor &quot;code --wait&quot;

# 作为 difftool / mergetool
git config --global diff.tool default-difftool
git config --global difftool.default-difftool.cmd &quot;code --wait --diff $LOCAL $REMOTE&quot;

git config --global merge.tool code
git config --global mergetool.code.cmd &quot;code --wait --merge $REMOTE $LOCAL $BASE $MERGED&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;需要确保命令行可运行 &lt;code&gt;code --help&lt;/code&gt;（macOS 可在命令面板执行 &lt;em&gt;Shell Command: Install &apos;Code&apos; command in PATH&lt;/em&gt;）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h3&gt;8. 多仓库与其他 SCM&lt;/h3&gt;
&lt;p&gt;VS Code 可同时管理多个提供方与多个仓库：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 &lt;strong&gt;… → Views&lt;/strong&gt; 勾选 &lt;strong&gt;Source Control Repositories&lt;/strong&gt; 显示多仓库面板：
&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/scm-providers-list.png&quot; alt=&quot;多仓库视图入口&quot; /&gt;&lt;/li&gt;
&lt;li&gt;通过扩展安装其他 SCM 提供方（如 SVN、Hg）：
&lt;img src=&quot;https://code.visualstudio.com/assets/docs/sourcecontrol/overview/scm-provider-category.png&quot; alt=&quot;SCM 提供方分类&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;9. 常用操作速查&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;打开源代码管理视图：&lt;strong&gt;Ctrl+Shift+G / ⌃⇧G（macOS）&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;命令面板：&lt;strong&gt;Ctrl+Shift+P / ⇧⌘P（macOS）&lt;/strong&gt; → 输入 &lt;code&gt;Git: ...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;暂存/取消暂存：在文件/区块处点击 &lt;code&gt;+&lt;/code&gt; / &lt;code&gt;-&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;提交：在顶部输入框填写信息，&lt;strong&gt;Ctrl+Enter&lt;/strong&gt; 提交&lt;/li&gt;
&lt;li&gt;比较任意两文件：资源管理器中 &lt;strong&gt;右键文件 A → Select for Compare&lt;/strong&gt;，再在文件 B 上 &lt;strong&gt;Compare with Selected&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;🌐 各大代码托管平台私有仓库使用攻略&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;适用平台：&lt;strong&gt;GitHub / GitLab.com / Bitbucket Cloud / Azure DevOps Repos / AWS CodeCommit / Gitee / Codeberg&lt;/strong&gt;
重点覆盖：创建私有仓库、邀请协作者与权限、可见性/公开设置、CI/CD 在私有仓库的配额与注意事项。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;📊 平台总览对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;平台&lt;/th&gt;
&lt;th&gt;是否支持免费私有仓库&lt;/th&gt;
&lt;th&gt;协作/成员（免费档）&lt;/th&gt;
&lt;th&gt;可见性/公开设置&lt;/th&gt;
&lt;th&gt;CI/CD（私有仓库）&lt;/th&gt;
&lt;th&gt;中国大陆可访问性&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GitHub&lt;/td&gt;
&lt;td&gt;✅ 支持&lt;/td&gt;
&lt;td&gt;个人/组织免费计划可用&lt;/td&gt;
&lt;td&gt;仓库可设为 Private / Public（企业还有 Internal）&lt;/td&gt;
&lt;td&gt;私有库享有每月&lt;strong&gt;2,000&lt;/strong&gt; Actions 分钟（Free 账号；超出按量计费）&lt;/td&gt;
&lt;td&gt;⚠️ 偶尔不稳定&lt;/td&gt;
&lt;td&gt;私有库 Actions 配额与套餐关联。&lt;a href=&quot;https://docs.github.com/get-started/learning-about-github/githubs-products&quot;&gt;GitHub Docs&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitLab.com&lt;/td&gt;
&lt;td&gt;✅ 支持&lt;/td&gt;
&lt;td&gt;Free 组&lt;strong&gt;最多 5 人&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;项目可设 Private / Internal / Public&lt;/td&gt;
&lt;td&gt;Free 组合计 &lt;strong&gt;400&lt;/strong&gt; 计算分钟/月（可自带 Runner 不计限）&lt;/td&gt;
&lt;td&gt;⚠️ 需要加速服务&lt;/td&gt;
&lt;td&gt;公共/开源与付费档配额更高；可加购分钟。&lt;a href=&quot;https://about.gitlab.com/pricing/&quot;&gt;about.gitlab.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bitbucket Cloud&lt;/td&gt;
&lt;td&gt;✅ 支持&lt;/td&gt;
&lt;td&gt;Free &lt;strong&gt;至多 5 用户&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;仓库一键勾选 &quot;Private&quot;&lt;/td&gt;
&lt;td&gt;Pipelines 随套餐变动&lt;/td&gt;
&lt;td&gt;⚠️ 偶尔不稳定&lt;/td&gt;
&lt;td&gt;Free 限 5 用户但&lt;strong&gt;无限私有仓库&lt;/strong&gt;。&lt;a href=&quot;https://www.atlassian.com/licensing/bitbucket&quot;&gt;atlassian.com&lt;/a&gt;, &lt;a href=&quot;https://support.atlassian.com/bitbucket-cloud/docs/set-repository-privacy-and-forking-options/&quot;&gt;Atlassian Support&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure DevOps Repos&lt;/td&gt;
&lt;td&gt;✅ 支持&lt;/td&gt;
&lt;td&gt;（随 Azure DevOps 用户数）&lt;/td&gt;
&lt;td&gt;项目/组织层可切换 Public/Private&lt;/td&gt;
&lt;td&gt;Azure Pipelines 随订阅配额&lt;/td&gt;
&lt;td&gt;✅ 访问顺畅&lt;/td&gt;
&lt;td&gt;官方标注&quot;&lt;strong&gt;无限量&lt;/strong&gt;私有 Git 仓库&quot;。&lt;a href=&quot;https://azure.microsoft.com/en-us/products/devops/repos&quot;&gt;Azure&lt;/a&gt;, [Microsoft Learn](https://learn.microsoft.com/en-us/azure/devops/repos/get-started/&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS CodeCommit&lt;/td&gt;
&lt;td&gt;✅ 支持&lt;/td&gt;
&lt;td&gt;按 IAM 身份授权&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;默认私有&lt;/strong&gt;，通过 IAM 控制访问&lt;/td&gt;
&lt;td&gt;与 CodeBuild/CodePipeline 集成&lt;/td&gt;
&lt;td&gt;⚠️ 需要加速服务&lt;/td&gt;
&lt;td&gt;官方定义为&quot;托管&lt;strong&gt;私有&lt;/strong&gt;Git 仓库&quot;。&lt;a href=&quot;https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html&quot;&gt;docs.aws.amazon.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gitee&lt;/td&gt;
&lt;td&gt;✅ 支持&lt;/td&gt;
&lt;td&gt;个人/组织可创建私有仓库&lt;/td&gt;
&lt;td&gt;新建时选择&quot;是否开源：公开/私有&quot;&lt;/td&gt;
&lt;td&gt;Gitee/第三方 CI 可用&lt;/td&gt;
&lt;td&gt;✅ 访问顺畅&lt;/td&gt;
&lt;td&gt;帮助中心有&quot;创建仓库/可见性&quot;指引。&lt;a href=&quot;https://gitee.com/help/articles/4120&quot;&gt;Gitee&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codeberg&lt;/td&gt;
&lt;td&gt;⚠️ 有限支持&lt;/td&gt;
&lt;td&gt;面向 FOSS 贡献者&lt;/td&gt;
&lt;td&gt;可建私有库&lt;/td&gt;
&lt;td&gt;自带 CI（Woodpecker/Forgejo Actions）&lt;/td&gt;
&lt;td&gt;❌ 访问受限&lt;/td&gt;
&lt;td&gt;私有内容&lt;strong&gt;建议 ≤ 100MB&lt;/strong&gt;（以公益使命为准）。&lt;a href=&quot;https://docs.codeberg.org/getting-started/faq/&quot;&gt;docs.codeberg.org&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h3&gt;GitHub（私有仓库）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;创建私有仓库&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;右上角 &lt;strong&gt;+&lt;/strong&gt; → &lt;strong&gt;New repository&lt;/strong&gt; → 选择 &lt;strong&gt;Visibility: Private&lt;/strong&gt; → &lt;strong&gt;Create repository&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;修改可见性&lt;/strong&gt;
仓库 &lt;strong&gt;Settings → Danger Zone → Change repository visibility&lt;/strong&gt;，可在 Private / Public 间切换&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;邀请协作与权限&lt;/strong&gt;
在仓库/组织下，添加协作者或通过团队授予权限&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;私有库 CI/CD（GitHub Actions）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;公共库与自托管 Runner 免费&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;私有库&lt;/strong&gt;按套餐享有&lt;strong&gt;每月分钟数&lt;/strong&gt;与存储配额（Free：2000 分钟/500MB）&lt;/li&gt;
&lt;li&gt;超额按量付费&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;GitLab.com（私有项目）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;私有可见性&lt;/strong&gt;
新建项目时选择 &lt;strong&gt;Private&lt;/strong&gt;，或在项目设置切换 Private / Internal / Public&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;成员与权限&lt;/strong&gt;
项目/组可邀请成员并配置角色；&lt;strong&gt;Free 组上限 5 用户&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;私有库 CI/CD（GitLab CI/CD）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt;：每&lt;strong&gt;顶级组&lt;/strong&gt;每月&lt;strong&gt;400&lt;/strong&gt; 计算分钟（共享 Runner）&lt;/li&gt;
&lt;li&gt;可&lt;strong&gt;自带 Runner&lt;/strong&gt;不占限额；可加购分钟或升级&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Bitbucket Cloud（私有仓库）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;创建私有库&lt;/strong&gt;
&lt;strong&gt;Create → Repository&lt;/strong&gt;，在仓库设置处勾选 &lt;strong&gt;This is a private repository&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;协作与权限&lt;/strong&gt;
可对个人用户或用户组授予 &lt;strong&gt;Admin/Write/Read&lt;/strong&gt; 等角色&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;计费/用户数&lt;/strong&gt;
&lt;strong&gt;Free&lt;/strong&gt; 方案&lt;strong&gt;最多 5 用户&lt;/strong&gt;，但&lt;strong&gt;无限私有仓库&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Azure DevOps Repos（私有 Git 仓库）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;特性与创建&lt;/strong&gt;
Azure Repos &lt;strong&gt;提供无限量私有 Git 仓库&lt;/strong&gt;；在项目内创建 Repo 即可&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;公开/私有&lt;/strong&gt;
项目层支持 &lt;strong&gt;Public/Private&lt;/strong&gt;；可在组织设置中调整可见性策略&lt;/p&gt;
&lt;h3&gt;AWS CodeCommit（企业级私有）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位与访问控制&lt;/strong&gt;
CodeCommit 官方定义为&lt;strong&gt;托管私有 Git 仓库&lt;/strong&gt;，访问由 &lt;strong&gt;IAM 策略&lt;/strong&gt;控制，&lt;strong&gt;默认私有&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;典型流程&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通过控制台创建仓库&lt;/li&gt;
&lt;li&gt;为开发者配置 IAM（或 SSO）&lt;/li&gt;
&lt;li&gt;选择 &lt;strong&gt;HTTPS Git 凭据&lt;/strong&gt;或 &lt;strong&gt;SSH&lt;/strong&gt; 访问&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Gitee（码云）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;创建与可见性&lt;/strong&gt;
右上角 &lt;strong&gt;+ → 新建仓库&lt;/strong&gt;，在新建页选择&quot;&lt;strong&gt;是否开源：公开/私有&lt;/strong&gt;&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;权限与开源切换&lt;/strong&gt;
企业工作台下可在&quot;功能设置 → 可见性&quot;里切换，并有角色/权限配置&lt;/p&gt;
&lt;h3&gt;Codeberg（社区公益托管）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;私有仓库政策&lt;/strong&gt;
以推动 &lt;strong&gt;FOSS&lt;/strong&gt; 为使命：私有仓库&lt;strong&gt;可用但非主要用例&lt;/strong&gt;；对活跃 FOSS 贡献者&lt;strong&gt;允许 ~100MB 私有内容&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🔧 实操速查（通用 Git + 权限）&lt;/h2&gt;
&lt;h3&gt;本地与远端连接&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 初始化并首次推送
git init
git add .
git commit -m &quot;init&quot;
git branch -M main
git remote add origin &amp;lt;你的私有仓库HTTPS或SSH地址&amp;gt;
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;常见权限/私有要点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;最小权限原则&lt;/strong&gt;：仅授予需要的读/写/管理员&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;保护主分支&lt;/strong&gt;：启用保护规则（强制 PR、评审、状态检查）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;密钥与凭据&lt;/strong&gt;：使用 &lt;strong&gt;SSH Key&lt;/strong&gt; 或平台令牌，CI 机密放入平台 &lt;strong&gt;Secrets/Variables&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI/CD 配额&lt;/strong&gt;：私有库常与套餐挂钩（分钟/存储/并发），超额需加购或自托管 Runner&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;💡 选型建议&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;个人/小团队：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想要生态丰富与招聘友好 → &lt;strong&gt;GitHub&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;更强 DevSecOps 一体化 → &lt;strong&gt;GitLab.com&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;与 Atlassian（Jira/Trello）联动 → &lt;strong&gt;Bitbucket&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;企业/合规：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Azure&lt;/strong&gt; 体系 → &lt;strong&gt;Azure DevOps Repos&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AWS&lt;/strong&gt; 体系与内网/IAM 严管 → &lt;strong&gt;CodeCommit&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;中国大陆网络体验：&lt;/strong&gt; &lt;strong&gt;Gitee&lt;/strong&gt; 作为镜像/私有托管备选&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;公益/开源情怀&lt;/strong&gt;且仅少量私密需求 → &lt;strong&gt;Codeberg&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;📚 参考与延伸&lt;/h2&gt;
&lt;h3&gt;VS Code Git 集成&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vscode.js.cn/docs/sourcecontrol/overview&quot;&gt;VS Code Git 集成官方文档（中文）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/sourcecontrol/overview&quot;&gt;VS Code Git 集成官方文档（英文）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vscode.js.cn/docs/sourcecontrol/intro-to-git&quot;&gt;Git 入门指南&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vscode.js.cn/docs/sourcecontrol/github&quot;&gt;GitHub 在 VS Code 中的使用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vscode.js.cn/docs/sourcecontrol/faq&quot;&gt;源代码管理常见问题&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;各大代码托管平台&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/repositories/creating-and-managing-repositories/creating-a-new-repository&quot;&gt;GitHub：创建仓库 / 可见性 / Actions 计费&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.gitlab.com/user/public_access/&quot;&gt;GitLab.com：可见性与权限 / 计算分钟&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.atlassian.com/bitbucket-cloud/docs/create-a-repository/&quot;&gt;Bitbucket：创建仓库 / 私有设置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/products/devops/repos&quot;&gt;Azure DevOps：私有仓库无限量&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.aws.amazon.com/codecommit/&quot;&gt;AWS CodeCommit：私有 Git 仓库&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gitee.com/help/articles/4120&quot;&gt;Gitee：创建仓库（公开/私有）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.codeberg.org/getting-started/faq/&quot;&gt;Codeberg：私有仓库政策&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;本文主要依据&lt;/strong&gt;：VS Code 官方文档《Using Git source control in VS Code》，涵盖了 Git ≥ 2.0.0 的要求、Source Control 视图、Clone/Initialize、Diff/Stage/Revert、Branches/Tags、Graph、Timeline 等功能，以及 &lt;code&gt;code --wait&lt;/code&gt; 作为编辑器/差异/合并工具的配置方法。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;配图来源&lt;/strong&gt;：所有插图均取自 VS Code 官方文档对应资源，包括 overview、first-run、clone、set-repo-url、initialize、branches、diff、graph、timeline、SCM 视图与扩展分类等页面。&lt;/p&gt;
</content:encoded></item><item><title>小说助手 0.3.25 版本发布 新功能介绍和教程</title><link>https://blog.sirrus.cc/posts/novel-helper0325/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/novel-helper0325/</guid><description>Andrea小说助手 0.3.25 版本发布 新功能介绍和教程</description><pubDate>Sun, 07 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;小说助手官网：&lt;/strong&gt; &lt;a href=&quot;https://anh.sirrus.cc&quot;&gt;https://anh.sirrus.cc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;小说助手 0.3.25 版本发布 新功能介绍和教程&lt;/h1&gt;
&lt;h2&gt;[0.3.25] - 2025-09-07&lt;/h2&gt;
&lt;h3&gt;✨ 新增&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;新增展开状态持久化功能：所有角色视图、当前文章角色视图（侧边栏和 Explorer）、包管理器视图现在都会记住用户的展开/折叠状态&lt;/li&gt;
&lt;li&gt;新增跨文档展开状态继承：切换到新文档时，如果新文档尚无展开记录，可继承上个文档的展开集合（仅对共有的节点生效）&lt;/li&gt;
&lt;li&gt;新增设置开关 &lt;code&gt;AndreaNovelHelper.docRoles.inheritExpandedFromPrevious&lt;/code&gt;：控制是否启用跨文档展开状态继承（默认开启）&lt;/li&gt;
&lt;li&gt;新增角色展开显示功能：角色节点支持展开显示详细信息，包括名称、类型、颜色等字段&lt;/li&gt;
&lt;li&gt;优化角色显示：支持角色自带 SVG 图标、角色名彩色方块标记、颜色字段可视化显示&lt;/li&gt;
&lt;li&gt;新增角色详情键图标映射：基于 JSON 配置为不同类型的角色字段显示对应的 VS Code 内置图标&lt;/li&gt;
&lt;li&gt;写作资源管理器现在支持显示参考资料（如图片、PDF 等不计入字数统计的文件）&lt;/li&gt;
&lt;li&gt;支持基于自定义分类的角色显示，可以按类型或归属进行更灵活的分组&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;🐛 修复&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;修复角色视图展开状态在重启 VS Code 后丢失的问题&lt;/li&gt;
&lt;li&gt;修复切换文档时布局被重置的问题&lt;/li&gt;
&lt;li&gt;略微优化了 Decorations 性能，减少大文件打开时的阻塞&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;🖋️ 更改&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;改进角色树视图的 ID 计算稳定性，确保展开状态正确持久化&lt;/li&gt;
&lt;li&gt;优化展开状态的存储机制，使用 workspaceState 进行跨会话持久化&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;新功能预览&lt;/h2&gt;
&lt;h3&gt;自定义分组&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%92%E8%89%B2%E6%98%BE%E7%A4%BA.png&quot; alt=&quot;自定义角色显示&quot; /&gt;
&lt;img src=&quot;./images/%E8%87%AA%E5%AE%9A%E4%B9%89%E5%88%86%E7%BB%84%E8%A7%84%E5%88%99.png&quot; alt=&quot;自定义分组&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;展开角色&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/%E8%A7%92%E8%89%B2%E5%B1%95%E5%BC%80.png&quot; alt=&quot;展开角色&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;教程部分&lt;/h2&gt;
&lt;h3&gt;图文教程-创建自定义分组&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%92%E8%89%B2%E6%98%BE%E7%A4%BA.png&quot; alt=&quot;自定义角色显示&quot; /&gt;
打开角色显示设置选项卡
&lt;img src=&quot;./images/%E8%87%AA%E5%AE%9A%E4%B9%89%E5%88%86%E7%BB%84%E8%A7%84%E5%88%99.png&quot; alt=&quot;自定义分组&quot; /&gt;
点击管理自定义分组规则进入自定义分组规则页面&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/%E6%96%B0%E5%BB%BA%E8%A7%84%E5%88%991.png&quot; alt=&quot;创建分组1&quot; /&gt;
选择添加规则后输入分组名称
&lt;img src=&quot;./images/%E6%96%B0%E5%BB%BA%E8%A7%84%E5%88%992.png&quot; alt=&quot;创建分组2&quot; /&gt;
选择匹配的类型（匹配归属还是类型）
&lt;img src=&quot;./images/%E6%96%B0%E5%BB%BA%E8%A7%84%E5%88%993.png&quot; alt=&quot;创建分组3&quot; /&gt;
输入匹配的条件(分隔符是英文逗号)
&lt;img src=&quot;./images/%E6%96%B0%E5%BB%BA%E8%A7%84%E5%88%994.png&quot; alt=&quot;创建分组4&quot; /&gt;
创建完成 页面手动刷新后即可看到新分组（这个版本暂未实现自动刷新）
&lt;img src=&quot;./images/%E6%96%B0%E5%BB%BA%E8%A7%84%E5%88%99done.png&quot; alt=&quot;创建规则Done&quot; /&gt;
创建完成后 即可看到新的分组&lt;/p&gt;
&lt;h3&gt;展开角色的描述多行文本换行的设置&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;受限于正常手段我们无法完全控制 TreeView 的 DOM，ANH 对于角色细节的描述形式是通过手动拆分为多行文本实现的，默认这个阈值是 20 字符。但是如果你使用了不同的侧边栏宽度 你会需要手动设置这个参数。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;不正确的宽度设置&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;./images/%E5%AE%BD%E5%BA%A6_%E8%BF%87%E7%AA%84.png&quot; alt=&quot;过窄&quot; /&gt;
宽度过窄，一行显示不完全
&lt;img src=&quot;./images/%E5%AE%BD%E5%BA%A6_%E6%AD%A3%E5%B8%B8.png&quot; alt=&quot;正常&quot; /&gt;
宽度正常，显示正常
&lt;img src=&quot;./images/%E5%AE%BD%E5%BA%A6_%E8%BF%87%E5%AE%BD.png&quot; alt=&quot;过宽&quot; /&gt;
宽度过宽，浪费空间&lt;/p&gt;
&lt;h4&gt;如何设置显示宽度&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;./images/%E9%85%8D%E7%BD%AE%E5%AE%BD%E5%BA%A61.png&quot; alt=&quot;宽度设置1&quot; /&gt;
进入角色设置面板（当前文章角色设置步骤相同）
&lt;img src=&quot;./images/%E9%85%8D%E7%BD%AE%E5%AE%BD%E5%BA%A62.png&quot; alt=&quot;宽度设置2&quot; /&gt;
选择 详情折行行数
&lt;img src=&quot;./images/%E9%85%8D%E7%BD%AE%E5%AE%BD%E5%BA%A63.png&quot; alt=&quot;宽度设置3&quot; /&gt;
设置为一个合适的数值
&lt;img src=&quot;./images/%E9%85%8D%E7%BD%AE%E5%AE%BD%E5%BA%A64.png&quot; alt=&quot;宽度设置4&quot; /&gt;
设置完成后手动刷新查看结果
（全部角色这边请来回切换是否跟随当前文章角色的设置来刷新，当前文章角色应该能自动刷新）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目前版本设置完宽度后需要手动刷新才能应用 将会在下个版本修正&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;角色详情展开与颜色图标&lt;/h3&gt;
&lt;h5&gt;角色详情展开&lt;/h5&gt;
&lt;p&gt;角色节点支持展开显示详细信息，便于快速查看和编辑角色属性：
&lt;img src=&quot;./images/%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%92%E8%89%B2%E6%98%BE%E7%A4%BA.png&quot; alt=&quot;自定义角色显示&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;展开机制&lt;/strong&gt;：点击角色节点旁边的展开图标（▶），可查看该角色的所有属性（如名称、类型、颜色、描述等）。
&lt;img src=&quot;./images/%E8%A7%92%E8%89%B2%E5%B1%95%E5%BC%80.png&quot; alt=&quot;展开角色&quot; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;属性排序&lt;/strong&gt;：属性按键名排序，&lt;code&gt;name&lt;/code&gt; 字段置顶，其余按字母顺序排列。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;值显示&lt;/strong&gt;：长文本自动截断显示，完整内容在悬停提示中查看；支持换行和折行显示，避免单行过长。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置开关&lt;/strong&gt;：通过 &lt;code&gt;AndreaNovelHelper.roles.details.enableRoleExpansion&lt;/code&gt; 控制是否允许角色展开（默认开启）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;根据角色颜色设置图标&lt;/h5&gt;
&lt;p&gt;为角色提供视觉化的颜色标识，提升界面辨识度：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;颜色图标&lt;/strong&gt;：如果角色对象包含 &lt;code&gt;color&lt;/code&gt;、&lt;code&gt;colour&lt;/code&gt; 或 &lt;code&gt;颜色&lt;/code&gt; 字段，系统会在角色名称前显示一个对应颜色的方块图标。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;图标优先级&lt;/strong&gt;：优先使用角色自带的 SVG 图标（如果启用 &lt;code&gt;useRoleSvgIfPresent&lt;/code&gt;）；否则使用颜色方块；最后回退到文件类型图标。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置开关&lt;/strong&gt;：通过 &lt;code&gt;AndreaNovelHelper.docRoles.display.colorizeRoleName&lt;/code&gt; 或 &lt;code&gt;AndreaNovelHelper.allRoles.display.colorizeRoleName&lt;/code&gt; 控制是否启用颜色标记（默认关闭）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;视觉效果&lt;/strong&gt;：颜色方块为 14x14 像素的圆角矩形，支持透明度和边框，提供良好的视觉反馈。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些功能增强了角色管理的交互体验，使角色列表更加直观和易于导航。配置开关允许用户根据需要启用或禁用这些特性。&lt;/p&gt;
&lt;h3&gt;Andrea Novel Helper 自定义分组规则原理&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意 在此处设置和上面通过向导设置的结果是一样的 这边仅作为配置文件结构详解&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;1. 背景与作用&lt;/h4&gt;
&lt;p&gt;自定义分组功能允许你脱离内置“类型 → 归属 → 角色”三级结构，按照自己的规则（类型、归属或正则）来对角色进行分组，便于阅读、编辑和管理。&lt;/p&gt;
&lt;h4&gt;2. 打开与作用域&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;下列配置可分别作用于两种视图：
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;allRoles&lt;/code&gt;（全部角色视图）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docRoles&lt;/code&gt;（当前文章角色视图，侧边栏 &amp;amp; Explorer）&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;配置路径（&lt;code&gt;settings.json&lt;/code&gt;）示例：&lt;pre&gt;&lt;code&gt;&quot;AndreaNovelHelper.docRoles.useCustomGroups&quot;: true,
&quot;AndreaNovelHelper.docRoles.customGroups&quot;: [ /* 自定义分组列表 */ ],
&quot;AndreaNovelHelper.allRoles.syncWithDocRoles&quot;: false,
&quot;AndreaNovelHelper.allRoles.useCustomGroups&quot;: true,
&quot;AndreaNovelHelper.allRoles.customGroups&quot;: [ /* … */ ]
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;3. 分组规则项字段&lt;/h4&gt;
&lt;p&gt;每个分组项是一个 JSON 对象，关键属性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt;：组名，会展示在树视图顶层&lt;/li&gt;
&lt;li&gt;&lt;code&gt;matchType&lt;/code&gt;: “type” | “affiliation” | “regex”&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pattern&lt;/code&gt;:
&lt;ul&gt;
&lt;li&gt;当 &lt;code&gt;matchType=type&lt;/code&gt; 或 &lt;code&gt;affiliation&lt;/code&gt; 时，支持 glob 模式（&lt;code&gt;*Important*&lt;/code&gt;）或逗号分隔列表&lt;/li&gt;
&lt;li&gt;当 &lt;code&gt;matchType=regex&lt;/code&gt; 时，必须是一个 JS 正则字面量（&lt;code&gt;/^.*魔法.*$/&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flat&lt;/code&gt; (可选，不常用)：布尔，&lt;code&gt;true&lt;/code&gt; 则该组下不再按“类型/归属”二级分组，直接平铺。一般不手动设置此字段，而是通过全局开关控制扁平化。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ignoreType&lt;/code&gt; / &lt;code&gt;ignoreAffiliation&lt;/code&gt; (可选)：布尔，若开启则该视图全局忽略二级“类型/归属”分层，仅在显示层面生效&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;战斗角色&quot;,
  &quot;matchType&quot;: &quot;type&quot;,
  &quot;pattern&quot;: &quot;战斗*,Boss&quot;
  // 注意：一般不设置 flat，而是通过全局开关控制
},
{
  &quot;name&quot;: &quot;魔法势力&quot;,
  &quot;matchType&quot;: &quot;affiliation&quot;,
  &quot;pattern&quot;: &quot;魔法森林,天空学院&quot;
},
{
  &quot;name&quot;: &quot;自定义关键词&quot;,
  &quot;matchType&quot;: &quot;regex&quot;,
  &quot;pattern&quot;: &quot;/^Reimu|Marisa$/&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;4. 匹配与分组流程&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;匹配阶段（Match）&lt;/strong&gt;&lt;br /&gt;
依照 &lt;code&gt;matchType&lt;/code&gt;，用真实的角色 &lt;code&gt;type&lt;/code&gt;、&lt;code&gt;affiliation&lt;/code&gt; 或 &lt;code&gt;regex&lt;/code&gt; 去筛选整个角色列表，不受全局的 &lt;code&gt;ignoreType&lt;/code&gt;/&lt;code&gt;ignoreAffiliation&lt;/code&gt; 开关影响，保证匹配准确。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分组阶段（Group）&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;按配置项的顺序创建顶层组&lt;/li&gt;
&lt;li&gt;匹配到的角色按全局开关决定是否在同一组内直接平铺，或继续按二级维度（类型或归属）拆分&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;其他角色（Other）&lt;/strong&gt;&lt;br /&gt;
将所有未命中的角色归入一个内置 “其他” 分组&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;5. 忽略开关的效果（推荐使用）&lt;/h4&gt;
&lt;p&gt;全局开关是控制扁平化的主要方式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ignoreType=true&lt;/code&gt;&lt;/strong&gt;：展示时不显示二级“类型”节点，所有角色直接平铺到所属顶层组。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ignoreAffiliation=true&lt;/code&gt;&lt;/strong&gt;：展示时不显示二级“归属”节点；若一个分组的 &lt;code&gt;matchType=affiliation&lt;/code&gt;，并开启忽略，则所有匹配角色也会直接平铺到该组下。&lt;/li&gt;
&lt;li&gt;这两个开关不影响匹配，只控制&lt;strong&gt;展示层级&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;推荐做法&lt;/strong&gt;：一般不手动设置每个分组的 &lt;code&gt;flat&lt;/code&gt; 字段，而是通过全局的 &lt;code&gt;ignoreType&lt;/code&gt; 和 &lt;code&gt;ignoreAffiliation&lt;/code&gt; 开关来统一控制所有分组的扁平化行为。这样更简洁且易于管理。&lt;/p&gt;
&lt;h4&gt;6. 同步与独立&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;当 &lt;code&gt;allRoles.syncWithDocRoles=true&lt;/code&gt;，全部角色视图使用同一套 &lt;code&gt;docRoles.customGroups&lt;/code&gt; 规则；&lt;/li&gt;
&lt;li&gt;若需两者分别管理，设为 &lt;code&gt;false&lt;/code&gt; 并分别配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;7. 示例配置&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// settings.json
&quot;AndreaNovelHelper.allRoles.syncWithDocRoles&quot;: false,
&quot;AndreaNovelHelper.allRoles.useCustomGroups&quot;: true,
&quot;AndreaNovelHelper.allRoles.customGroups&quot;: [
  {
    &quot;name&quot;: &quot;主角阵营&quot;,
    &quot;matchType&quot;: &quot;affiliation&quot;,
    &quot;pattern&quot;: &quot;勇者公会,救世教会&quot;
  },
  {
    &quot;name&quot;: &quot;反派&quot;,
    &quot;matchType&quot;: &quot;type&quot;,
    &quot;pattern&quot;: &quot;Boss,精英*&quot;
  }
],
// 推荐：通过全局开关控制扁平化，而不是手动设置 flat
&quot;AndreaNovelHelper.allRoles.ignoreType&quot;: false,
&quot;AndreaNovelHelper.allRoles.ignoreAffiliation&quot;: true  // 所有分组都会扁平化，不显示归属二级节点
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;8. 注意事项&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;正则模式要写完整字面量，不能省略 &lt;code&gt;/.../&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flat&lt;/code&gt; 字段可选且不常用；一般通过全局 &lt;code&gt;ignoreType&lt;/code&gt;/&lt;code&gt;ignoreAffiliation&lt;/code&gt; 开关来控制扁平化；&lt;/li&gt;
&lt;li&gt;如果一个角色同时命中多个组，按配置项先后顺序归入第一个匹配组；&lt;/li&gt;
&lt;li&gt;未在 &lt;code&gt;customGroups&lt;/code&gt; 中定义的字段会自动进入“其他”组；&lt;/li&gt;
&lt;li&gt;修改分组配置后，可通过命令面板 “配置：全部角色显示” 或 “配置：当前文章角色显示” 立即刷新视图。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
</content:encoded></item><item><title>小说助手 0.3.24 版本发布 新功能介绍和教程</title><link>https://blog.sirrus.cc/posts/novel-helper0324/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/novel-helper0324/</guid><description>Andrea小说助手 0.3.24 版本发布 新功能介绍和教程</description><pubDate>Sat, 06 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;小说助手官网：&lt;/strong&gt; &lt;a href=&quot;https://anh.sirrus.cc&quot;&gt;https://anh.sirrus.cc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;小说助手 0.3.24 版本发布 新功能介绍和教程&lt;/h1&gt;
&lt;p&gt;🎉 &lt;strong&gt;版本 0.3.24 发布成功！&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;功能预览&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./image/D3B57D863CABE2EBDE0565DE7E618BBA.png&quot; alt=&quot;快速配置写作资源管理器忽略（入口）&quot; /&gt;
&lt;img src=&quot;./image/F738666331016F96A319DE43EAFA903F.png&quot; alt=&quot;快速配置写作资源管理器忽略（主页）&quot; /&gt;
&lt;img src=&quot;./image/1050EE4492BCF9E91460EA61392896DF.png&quot; alt=&quot;快速配置写作资源管理器忽略（扩展类型）&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;📋 完成的工作&lt;/h2&gt;
&lt;h3&gt;✅ 版本更新&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;版本号&lt;/strong&gt;: 0.3.23 → 0.3.24&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;发布日期&lt;/strong&gt;: 2025-09-06&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;✅ Git 提交&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;提交信息: &lt;code&gt;feat: v0.3.24 - 新增wcignore快速设置和gitignore语法高亮，优化TimeStats性能&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;包含 15 个文件更改，1406 行新增，126 行删除&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🆕 新版本特性&lt;/h2&gt;
&lt;h3&gt;✨ 新增功能&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;wcignore 快速设置&lt;/strong&gt;: 新增了 wcignore 文件的快速设置功能&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gitignore 语法高亮&lt;/strong&gt;: 新增了 gitignore 文件的语法高亮支持&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;🐛 修复和优化&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TimeStats 性能优化&lt;/strong&gt;: 略微优化了 TimeStats 的性能，减少大文件打开时的阻塞&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异步计算改进&lt;/strong&gt;: 改进了异步计算的错误处理机制&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🔗 相关链接&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=andreafrederica.andrea-novel-helper&quot;&gt;VS Code 市场页面&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://open-vsx.org/extension/andreafrederica/andrea-novel-helper&quot;&gt;OpenVSX 市场页面&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/AndreaFrederica/andrea-novel-helper&quot;&gt;GitHub 仓库&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;新版本已经成功发布到市场，用户现在可以更新到最新版本 0.3.24 来体验这些新功能和性能优化！&lt;/p&gt;
</content:encoded></item><item><title>许可证系统测试</title><link>https://blog.sirrus.cc/posts/license-system-test/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/license-system-test/</guid><description>测试新的许可证系统功能，包括预配置许可证和自定义许可证配置</description><pubDate>Thu, 04 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;许可证系统测试&lt;/h1&gt;
&lt;p&gt;这篇文章用于测试新的许可证系统功能。&lt;/p&gt;
&lt;h2&gt;使用预配置许可证&lt;/h2&gt;
&lt;p&gt;这段代码使用 MIT 许可证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function hello() {
  console.log(&quot;Hello, World!&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这段代码使用 MPL 2.0 许可证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;interface User {
  id: number;
  name: string;
}

class UserService {
  getUser(id: number): User | null {
    // 实现获取用户逻辑
    return null;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;使用自定义许可证配置&lt;/h2&gt;
&lt;p&gt;这段代码使用自定义许可证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def process_data(data):
    &quot;&quot;&quot;处理数据的函数&quot;&quot;&quot;
    return data.strip().upper()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这段代码使用带徽章的许可证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function calculateSum(numbers) {
  return numbers.reduce((sum, num) =&amp;gt; sum + num, 0);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;手动配置许可证&lt;/h2&gt;
&lt;p&gt;使用键值对格式配置自定义许可证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def proprietary_algorithm():
    &quot;&quot;&quot;这是一个专有算法&quot;&quot;&quot;
    return &quot;secret sauce&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用完整手动配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class InternalTool {
    public static void main(String[] args) {
        System.out.println(&quot;Internal company tool&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;纯文本许可证&lt;/h2&gt;
&lt;p&gt;使用简单文本许可证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.example {
  color: red;
  font-weight: bold;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;复杂示例&lt;/h2&gt;
&lt;p&gt;使用 CC BY-NC 4.0 许可证的代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;license-demo&quot;&amp;gt;
    &amp;lt;h3&amp;gt;{{ title }}&amp;lt;/h3&amp;gt;
    &amp;lt;p&amp;gt;{{ description }}&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  name: &quot;LicenseDemo&quot;,
  props: {
    title: String,
    description: String,
  },
};
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;
.license-demo {
  padding: 1rem;
  border: 1px solid #ccc;
  border-radius: 8px;
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;没有许可证的代码&lt;/h2&gt;
&lt;p&gt;这段代码没有指定许可证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;这段代码没有许可证信息&quot;
ls -la
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>在 VS Code 扩展里安全嵌入 Vue SPA</title><link>https://blog.sirrus.cc/posts/vscode-webview-vue/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/vscode-webview-vue/</guid><description>从资源路径、CSP、安全与通信四个方面，完整示例把 Vite 构建的 Vue 单页应用嵌入 VS Code Webview。</description><pubDate>Wed, 03 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;在 VS Code 扩展里安全嵌入 Vue SPA&lt;/h1&gt;
&lt;p&gt;这篇文章以“角色卡管理器”为例，演示如何把一个由 Vite 构建的 Vue 单页应用（SPA）无缝嵌入到 VS Code 扩展的 Webview 中，并系统性解决三大痛点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;静态资源路径：确保脚本、样式、图片、动态导入都能正确加载&lt;/li&gt;
&lt;li&gt;CSP 限制：在安全的前提下允许必需的资源与请求&lt;/li&gt;
&lt;li&gt;Webview ↔ 扩展通信：与扩展后端可靠地交换数据&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;项目结构建议&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;packages/
  webview/                  # Vue + Vite 前端工程
    dist/spa/               # 产物目录（被扩展引用）
src/
  extension/                # 扩展端代码
  media/                    # 运行时辅助脚本（resource-mapper.js 等）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;扩展端通过 &lt;code&gt;localResourceRoots&lt;/code&gt; 允许访问 &lt;code&gt;dist/spa&lt;/code&gt; 与 &lt;code&gt;media&lt;/code&gt;，并把 &lt;code&gt;index.html&lt;/code&gt; 读入后重写资源路径与注入 CSP。&lt;/p&gt;
&lt;h2&gt;创建与复用 WebviewPanel&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;// 代码示例 - 基于 CC BY-NC 4.0 许可证
// Code example - Licensed under CC BY-NC 4.0
const panel = vscode.window.createWebviewPanel(
  &quot;andreaRoleCardManager&quot;,
  &quot;角色卡管理器&quot;,
  vscode.ViewColumn.One,
  {
    enableScripts: true,
    retainContextWhenHidden: true,
    localResourceRoots: [
      spaRoot,
      vscode.Uri.joinPath(ctx.extensionUri, &quot;media&quot;),
    ],
  }
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;复用面板时只需 &lt;code&gt;reveal()&lt;/code&gt; 并刷新 HTML；首次创建时请设置好 &lt;code&gt;localResourceRoots&lt;/code&gt; 与 &lt;code&gt;enableScripts&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;资源路径：一切都走 asWebviewUri&lt;/h2&gt;
&lt;p&gt;Webview 是隔离环境，磁盘路径或相对路径都不可直接用，必须通过 &lt;code&gt;webview.asWebviewUri(vscode.Uri)&lt;/code&gt; 转换成安全 URL。&lt;/p&gt;
&lt;p&gt;典型做法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;读取构建后的 &lt;code&gt;index.html&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;重写标签属性：把 &lt;code&gt;&amp;lt;script|link|img|source|video|audio|iframe&amp;gt;&lt;/code&gt; 的 &lt;code&gt;src/href&lt;/code&gt; 统一替换为 &lt;code&gt;asWebviewUri&lt;/code&gt; 生成的 URL。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;处理 JS/CSS 内的路径：补齐 &lt;code&gt;/assets/...&lt;/code&gt;、&lt;code&gt;./assets/...&lt;/code&gt;，以及 &lt;code&gt;import()&lt;/code&gt;、&lt;code&gt;url(...)&lt;/code&gt; 等动态引用。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;核心思想是“构建期 + 运行时双保险”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;构建期：用正则或解析器把常见的 &lt;code&gt;src/href&lt;/code&gt;、&lt;code&gt;/assets/&lt;/code&gt; 统一改写；&lt;/li&gt;
&lt;li&gt;运行时：注入资源映射器，拦截后续动态插入的节点与网络请求，确保依旧指向可达的 URL。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;运行时资源映射器（最小思路）&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;// 代码示例 - 基于 CC BY-NC 4.0 许可证
// Code example - Licensed under CC BY-NC 4.0

// 1) 注入全局映射：把 /assets/file → asWebviewUri 对应结果
window.__vscode_resource_map__ = { &apos;/assets/app.js&apos;: &apos;https://.../app.js&apos;, ... }
window.__vscode_resource_baseUri__ = &apos;https://.../spa&apos;

// 2) transformPath：把一切本地路径改写成上面的可达 URL
function transformPath(p) {
  // 放过 http/https/data/blob/javascript
  // /assets 与 ./assets、assets 统一拼成 baseUri + /assets/...
}

// 3) 挂钩常见入口：
// - 元素属性：HTMLScriptElement.src / HTMLLinkElement.href / HTMLImageElement.src...
// - fetch / XMLHttpRequest.open
// - MutationObserver 监听新增节点并重写
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样即使 Vue 组件在运行时动态创建 &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;，或用 &lt;code&gt;fetch(&apos;/assets/x.json&apos;)&lt;/code&gt;，也能被自动修正。&lt;/p&gt;
&lt;h2&gt;内容安全策略（CSP）&lt;/h2&gt;
&lt;p&gt;推荐策略（根据需要裁剪）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- 代码示例 - 基于 CC BY-NC 4.0 许可证 --&amp;gt;
&amp;lt;!-- Code example - Licensed under CC BY-NC 4.0 --&amp;gt;
&amp;lt;meta
  http-equiv=&quot;Content-Security-Policy&quot;
  content=&quot;
  default-src &apos;none&apos;;
  img-src {{webview.cspSource}} https: data: blob:;
  style-src {{webview.cspSource}} &apos;unsafe-inline&apos;;
  font-src {{webview.cspSource}} data:;
  script-src {{webview.cspSource}} https: &apos;unsafe-inline&apos;;
  connect-src {{webview.cspSource}} https:;
  frame-src &apos;none&apos;;
  worker-src {{webview.cspSource}} blob:;
  child-src {{webview.cspSource}} blob:;
&quot;
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{{webview.cspSource}}&lt;/code&gt; 实际运行时由 &lt;code&gt;webview.cspSource&lt;/code&gt; 替换&lt;/li&gt;
&lt;li&gt;如必须使用内联脚本，尽量控制在“注入全局数据”等极少量场景&lt;/li&gt;
&lt;li&gt;如果需要访问接口域名，请把域名加入 &lt;code&gt;connect-src&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Webview ↔ 扩展通信&lt;/h2&gt;
&lt;p&gt;前端（Webview）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 代码示例 - 基于 CC BY-NC 4.0 许可证
// Code example - Licensed under CC BY-NC 4.0
const vscode = acquireVsCodeApi();

// 请求数据
vscode.postMessage({ type: &quot;requestRoleCards&quot; });

// 接收数据
window.addEventListener(&quot;message&quot;, (e) =&amp;gt; {
  if (e.data?.type === &quot;roleCards&quot;) {
    render(e.data.list);
  }
});

// 保存
function save(list) {
  vscode.postMessage({ type: &quot;saveRoleCards&quot;, list });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;扩展端：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 代码示例 - 基于 CC BY-NC 4.0 许可证
// Code example - Licensed under CC BY-NC 4.0
panel.webview.onDidReceiveMessage(async (msg) =&amp;gt; {
  if (msg?.type === &quot;requestRoleCards&quot;) {
    panel.webview.postMessage({ type: &quot;roleCards&quot;, list });
  } else if (msg?.type === &quot;saveRoleCards&quot;) {
    // 校验并持久化
    panel.webview.postMessage({ type: &quot;saveAck&quot;, ok: true });
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;开发与调试建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;前端使用 &lt;code&gt;vite build --watch&lt;/code&gt; 连续输出到 &lt;code&gt;dist/spa&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;扩展端 F5 启动 “Extension Development Host”，重载即可验证&lt;/li&gt;
&lt;li&gt;不直接接入 Vite Dev Server（CSP 与源隔离更复杂，且与发布环境不一致）&lt;/li&gt;
&lt;li&gt;打开 Webview 开发者工具观察 Network 与 CSP 报错&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;常见问题排查&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;图片/CSS 不加载：检查 &lt;code&gt;localResourceRoots&lt;/code&gt;、路径重写、&lt;code&gt;asWebviewUri&lt;/code&gt; 是否覆盖到了&lt;/li&gt;
&lt;li&gt;前端路由 404：优先使用 Hash 路由，或自行把导航与内容托管在 Webview 内部状态&lt;/li&gt;
&lt;li&gt;CSP 报错：按报错提示补齐 &lt;code&gt;connect-src&lt;/code&gt;、&lt;code&gt;script-src&lt;/code&gt; 等来源&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;实战：预处理 HTML 与动态注入 JS 劫持（MPL-2.0）&lt;/h2&gt;
&lt;p&gt;下面给出一套可直接落地的实现，分为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;扩展端：读取构建产物的 index.html，批量重写资源路径、注入 CSP 与运行时代码，并输出给 Webview。&lt;/li&gt;
&lt;li&gt;Webview 端：动态资源映射器，拦截 DOM 属性、fetch/XMLHttpRequest、MutationObserver 等入口，统一把 /assets 等路径改写为可达 URL。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;许可说明：本文非代码部分以 CC BY-NC 4.0 授权；本小节内的“示例代码”以 Mozilla Public License 2.0（MPL-2.0）授权，你可以复制、修改并在满足 MPL-2.0 的前提下分发。&lt;/p&gt;
&lt;h3&gt;扩展端：HTML 预处理与注入（TypeScript, MPL-2.0）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;/*
 * This file is licensed under the Mozilla Public License 2.0 (MPL-2.0).
 * SPDX-License-Identifier: MPL-2.0
 */
import * as vscode from &quot;vscode&quot;;
import * as fs from &quot;fs&quot;;

export function buildHtml(
  webview: vscode.Webview,
  spaRoot: vscode.Uri,
  opts?: {
    connectSrc?: string[];
    resourceMapperScriptUri?: string; // 已通过 asWebviewUri 转换
  }
) {
  const indexHtmlPath = vscode.Uri.joinPath(spaRoot, &quot;index.html&quot;).fsPath;
  if (!fs.existsSync(indexHtmlPath)) {
    return `&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h3&amp;gt;Webview&amp;lt;/h3&amp;gt;&amp;lt;p&amp;gt;index.html 未找到：&amp;lt;code&amp;gt;${indexHtmlPath}&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;`;
  }

  let html = fs.readFileSync(indexHtmlPath, &quot;utf-8&quot;);
  html = rewriteHtmlToWebviewUris(html, webview, spaRoot);
  html = fixAllAssetUrls(html, webview, spaRoot);
  html = injectResourceMapper(
    html,
    webview,
    spaRoot,
    opts?.resourceMapperScriptUri
  );
  html = stripBaseTag(html);
  html = applyCsp(html, webview, opts?.connectSrc ?? [&quot;https:&quot;, &quot;http:&quot;]);
  return html;
}

type Attr = &quot;src&quot; | &quot;href&quot;;
function rewriteHtmlToWebviewUris(
  html: string,
  webview: vscode.Webview,
  spaRoot: vscode.Uri
): string {
  const fixRelFromVscodeWebview = (u: string) =&amp;gt;
    u.replace(/^vscode-webview:\/\/[^/]+\//i, &quot;&quot;);
  const replaceAttr = (tag: string, attr: Attr) =&amp;gt; {
    const re = new RegExp(
      `&amp;lt;${tag}\\b([^&amp;gt;]*?)\\s${attr}\\s*=\\s*(?:&quot;([^&quot;]+)&quot;|&apos;([^&apos;]+)&apos;|([^\\s&amp;gt;]+))([^&amp;gt;]*)&amp;gt;`,
      &quot;gi&quot;
    );
    html = html.replace(re, (m, pre, g1, g2, g3, post) =&amp;gt; {
      const raw = g1 ?? g2 ?? g3 ?? &quot;&quot;;
      if (/^(data:|mailto:|javascript:|#|https?:)/i.test(raw)) return m;
      const rel = fixRelFromVscodeWebview(raw).replace(/^\.\/?/, &quot;&quot;);
      const fileUri = vscode.Uri.joinPath(spaRoot, rel);
      const webUri = webview.asWebviewUri(fileUri).toString();
      const quoted =
        g1 != null ? `&quot;${webUri}&quot;` : g2 != null ? `&apos;${webUri}&apos;` : webUri;
      return `&amp;lt;${tag}${pre} ${attr}=${quoted}${post}&amp;gt;`;
    });
  };
  [&quot;script&quot;, &quot;link&quot;, &quot;img&quot;, &quot;source&quot;, &quot;video&quot;, &quot;audio&quot;, &quot;iframe&quot;].forEach(
    (t) =&amp;gt; {
      replaceAttr(t, t === &quot;link&quot; ? &quot;href&quot; : &quot;src&quot;);
    }
  );
  return html;
}

function fixAllAssetUrls(
  html: string,
  webview: vscode.Webview,
  spaRoot: vscode.Uri
): string {
  const base = webview.asWebviewUri(spaRoot).toString().replace(/\/$/, &quot;&quot;);
  html = html.replace(
    /(\s(?:href|src)\s*=\s*)([&quot;&apos;])\/assets\//gi,
    (_m, p1, q) =&amp;gt; `${p1}${q}${base}/assets/`
  );
  html = html.replace(
    /(\s(?:href|src)\s*=\s*)([&quot;&apos;])(?:\.\/)?assets\//gi,
    (_m, p1, q) =&amp;gt; `${p1}${q}${base}/assets/`
  );
  html = html.replace(
    /(import\s*\(\s*)([&quot;&apos;`])([^&quot;&apos;`]*\/assets\/[^&quot;&apos;`]*)\2/g,
    (_m, pre, q, p) =&amp;gt; `${pre}${q}${base}/${p.replace(/^\.?\//, &quot;&quot;)}${q}`
  );
  html = html.replace(/([&quot;&apos;`])\/assets\//g, `$1${base}/assets/`);
  html = html.replace(/([&quot;&apos;`])\.\/assets\//g, `$1${base}/assets/`);
  return html;
}

function injectResourceMapper(
  html: string,
  webview: vscode.Webview,
  spaRoot: vscode.Uri,
  mapperScriptUri?: string
): string {
  const baseUri = webview.asWebviewUri(spaRoot).toString().replace(/\/$/, &quot;&quot;);
  // 扫描 dist/spa/assets 目录，生成最小映射
  const assetsDir = vscode.Uri.joinPath(spaRoot, &quot;assets&quot;).fsPath;
  const resourceMap: Record&amp;lt;string, string&amp;gt; = {};
  if (fs.existsSync(assetsDir)) {
    for (const f of fs.readdirSync(assetsDir)) {
      const key = `/assets/${f}`;
      resourceMap[key] = webview
        .asWebviewUri(vscode.Uri.joinPath(spaRoot, &quot;assets&quot;, f))
        .toString();
    }
  }
  const safeMap = JSON.stringify(resourceMap)
    .replace(/&amp;lt;/g, &quot;\\u003c&quot;)
    .replace(/&amp;gt;/g, &quot;\\u003e&quot;);
  const injectedData = `&amp;lt;script&amp;gt;window.__vscode_resource_map__=${safeMap};window.__vscode_resource_baseUri__=&quot;${baseUri}&quot;;&amp;lt;\/script&amp;gt;`;
  const mapperTag = mapperScriptUri
    ? `\n&amp;lt;script src=&quot;${mapperScriptUri}&quot;&amp;gt;&amp;lt;\/script&amp;gt;`
    : &quot;&quot;;
  return html.replace(
    /&amp;lt;head([^&amp;gt;]*)&amp;gt;/i,
    `&amp;lt;head$1&amp;gt;\n${injectedData}${mapperTag}`
  );
}

function applyCsp(
  html: string,
  webview: vscode.Webview,
  connectSrc: string[] = []
): string {
  const connect = [webview.cspSource, ...connectSrc].join(&quot; &quot;);
  const csp = [
    `default-src &apos;none&apos;;`,
    `img-src ${webview.cspSource} https: data: blob:;`,
    `style-src ${webview.cspSource} &apos;unsafe-inline&apos;;`,
    `font-src ${webview.cspSource} data:;`,
    `script-src ${webview.cspSource} https: &apos;unsafe-inline&apos;;`,
    `connect-src ${connect};`,
    `frame-src &apos;none&apos;;`,
    `worker-src ${webview.cspSource} blob:;`,
    `child-src ${webview.cspSource} blob:;`,
  ].join(&quot; &quot;);
  const tag = `&amp;lt;meta http-equiv=&quot;Content-Security-Policy&quot; content=&quot;${csp}&quot;&amp;gt;`;
  return /&amp;lt;meta http-equiv=&quot;Content-Security-Policy&quot;/i.test(html)
    ? html.replace(/&amp;lt;meta http-equiv=&quot;Content-Security-Policy&quot;[^&amp;gt;]*&amp;gt;/i, tag)
    : html.replace(/&amp;lt;head([^&amp;gt;]*)&amp;gt;/i, `&amp;lt;head$1&amp;gt;\n  ${tag}`);
}

function stripBaseTag(html: string): string {
  return html.replace(/&amp;lt;base\s+[^&amp;gt;]*&amp;gt;/gi, &quot;&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用方式：在创建/复用 WebviewPanel 后，读取 &lt;code&gt;dist/spa/index.html&lt;/code&gt; 并调用 &lt;code&gt;buildHtml&lt;/code&gt;，把返回的 HTML 赋给 &lt;code&gt;panel.webview.html&lt;/code&gt; 即可。&lt;/p&gt;
&lt;h3&gt;Webview 端：动态资源映射器（JavaScript, MPL-2.0）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;/*
 * This file is licensed under the Mozilla Public License 2.0 (MPL-2.0).
 * SPDX-License-Identifier: MPL-2.0
 */
(function () {
  var resourceMap = window.__vscode_resource_map__ || {};
  var baseUri = (window.__vscode_resource_baseUri__ || &quot;&quot;).replace(/\/$/, &quot;&quot;);

  function transformPath(path) {
    if (!path || typeof path !== &quot;string&quot;) return path;
    if (path.startsWith(baseUri)) return path;
    try {
      const u = new URL(path);
      if (
        u.protocol === &quot;vscode-webview:&quot; &amp;amp;&amp;amp;
        u.pathname.startsWith(&quot;/assets/&quot;)
      ) {
        const key = u.pathname;
        return resourceMap[key] || baseUri + key;
      }
      if (/^(https?:|data:|blob:|javascript:)/i.test(u.protocol + &quot;&quot;))
        return path;
    } catch (_) {}
    if (path.startsWith(&quot;/assets/&quot;)) return resourceMap[path] || baseUri + path;
    if (path.startsWith(&quot;./assets/&quot;) || path.startsWith(&quot;assets/&quot;)) {
      const normalized = path.startsWith(&quot;./&quot;) ? path.slice(1) : &quot;/&quot; + path;
      return resourceMap[normalized] || baseUri + normalized;
    }
    if (/^(https?:|data:|blob:|javascript:)/i.test(path)) return path;
    const full = path.startsWith(&quot;/&quot;) ? path : &quot;/&quot; + path;
    return baseUri + full;
  }

  function patchURLProp(Ctor, prop) {
    try {
      const proto = Ctor &amp;amp;&amp;amp; Ctor.prototype;
      if (!proto) return;
      const desc = Object.getOwnPropertyDescriptor(proto, prop);
      if (!desc || !desc.set || !desc.get) return;
      Object.defineProperty(proto, prop, {
        configurable: true,
        enumerable: desc.enumerable,
        get() {
          return desc.get.call(this);
        },
        set(v) {
          try {
            v = transformPath(String(v));
          } catch (_) {}
          return desc.set.call(this, v);
        },
      });
    } catch (_) {}
  }

  patchURLProp(HTMLScriptElement, &quot;src&quot;);
  patchURLProp(HTMLLinkElement, &quot;href&quot;);
  patchURLProp(HTMLImageElement, &quot;src&quot;);
  patchURLProp(HTMLSourceElement, &quot;src&quot;);
  patchURLProp(HTMLIFrameElement, &quot;src&quot;);
  patchURLProp(HTMLMediaElement, &quot;src&quot;);

  const _setAttr = Element.prototype.setAttribute;
  Element.prototype.setAttribute = function (name, value) {
    try {
      if (
        typeof value === &quot;string&quot; &amp;amp;&amp;amp;
        /^(src|href|srcset)$/i.test(String(name))
      ) {
        value = transformPath(value);
      }
    } catch (_) {}
    return _setAttr.call(this, name, value);
  };

  function rewriteCssUrls(cssText) {
    if (!cssText) return cssText;
    cssText = cssText.replace(
      /url\(\s*([&apos;&quot;]?)(?!data:|blob:)(\/?\.?assets\/[^&apos;&quot;)\s?#]+(?:[?#][^&apos;&quot;)]*)?)\1\s*\)/gi,
      (_m, q, p) =&amp;gt; {
        let path = p;
        if (path.startsWith(&quot;./&quot;)) path = path.slice(1);
        if (path.startsWith(&quot;assets/&quot;)) path = &quot;/&quot; + path;
        if (!path.startsWith(&quot;/assets/&quot;)) return _m;
        const mapped = resourceMap[path] || baseUri + path;
        return &quot;url(&quot; + (q || &quot;&quot;) + mapped + (q || &quot;&quot;) + &quot;)&quot;;
      }
    );
    cssText = cssText.replace(
      /@import\s+(?:url\(\s*([&apos;&quot;]?)(\/?\.?assets\/[^&apos;\&quot;)\s;]+)\1\s*\)|([&apos;&quot;])(\/?\.?assets\/[^&apos;\&quot;)\s;]+)\3)\s*;/gi,
      (_m, q1, p1, q2, p2) =&amp;gt; {
        let path = p1 || p2;
        if (path.startsWith(&quot;./&quot;)) path = path.slice(1);
        if (path.startsWith(&quot;assets/&quot;)) path = &quot;/&quot; + path;
        if (!path.startsWith(&quot;/assets/&quot;)) return _m;
        const mapped = resourceMap[path] || baseUri + path;
        const q = q1 || q2 || &quot;&quot;;
        return &quot;@import url(&quot; + q + mapped + q + &quot;);&quot;;
      }
    );
    return cssText;
  }

  async function inlineStylesheet(linkEl) {
    try {
      if (!linkEl || linkEl.dataset.__inlined_css__) return;
      if (!/stylesheet/i.test(linkEl.rel || &quot;&quot;)) return;
      if (!linkEl.href) return;
      const href = transformPath(linkEl.href);
      const res = await fetch(href, { credentials: &quot;same-origin&quot; });
      if (!res.ok) throw new Error(&quot;css fetch &quot; + res.status);
      const css = await res.text();
      const fixed = rewriteCssUrls(css);
      const style = document.createElement(&quot;style&quot;);
      style.setAttribute(&quot;data-vscode-webview-inlined&quot;, &quot;1&quot;);
      style.textContent = fixed;
      linkEl.dataset.__inlined_css__ = &quot;1&quot;;
      linkEl.parentNode &amp;amp;&amp;amp; linkEl.parentNode.insertBefore(style, linkEl);
      linkEl.remove();
    } catch (e) {
      try {
        linkEl.href = transformPath(linkEl.href);
      } catch (_) {}
      console.warn(&quot;inlineStylesheet failed:&quot;, e);
    }
  }

  var originalFetch = window.fetch;
  if (originalFetch) {
    window.fetch = function (url, options) {
      if (typeof url === &quot;string&quot;)
        return originalFetch.call(this, transformPath(url), options);
      if (url &amp;amp;&amp;amp; typeof url.url === &quot;string&quot;) {
        var req = url;
        var newUrl = transformPath(req.url);
        if (newUrl !== req.url) {
          try {
            url = new Request(newUrl, req);
          } catch (_) {
            return originalFetch.call(
              this,
              newUrl,
              options || { method: req.method, headers: req.headers }
            );
          }
        }
      }
      return originalFetch.call(this, url, options);
    };
  }

  var X = window.XMLHttpRequest &amp;amp;&amp;amp; window.XMLHttpRequest.prototype;
  if (X &amp;amp;&amp;amp; X.open) {
    var origOpen = X.open;
    X.open = function (method, url) {
      try {
        if (typeof url === &quot;string&quot;) arguments[1] = transformPath(url);
      } catch (_) {}
      return origOpen.apply(this, arguments);
    };
  }

  if (typeof window.__vitePreload !== &quot;undefined&quot;) {
    var origPreload = window.__vitePreload;
    window.__vitePreload = function (fn, deps, path) {
      if (deps &amp;amp;&amp;amp; Array.isArray(deps)) deps = deps.map((d) =&amp;gt; transformPath(d));
      if (path) path = transformPath(path);
      return origPreload.call(this, fn, deps, path);
    };
  }

  function rewriteEl(el) {
    const tag = el.tagName;
    if (tag === &quot;LINK&quot;) {
      const rel = (el.rel || &quot;&quot;).toLowerCase();
      if (rel.includes(&quot;stylesheet&quot;)) {
        inlineStylesheet(el);
        return;
      }
      if (el.href) {
        const next = transformPath(el.href);
        if (next !== el.href) el.href = next;
      }
      return;
    }
    if (tag === &quot;SCRIPT&quot; &amp;amp;&amp;amp; el.src) {
      const next = transformPath(el.src);
      if (next !== el.src) el.src = next;
      return;
    }
    if (
      (tag === &quot;IMG&quot; ||
        tag === &quot;SOURCE&quot; ||
        tag === &quot;VIDEO&quot; ||
        tag === &quot;AUDIO&quot;) &amp;amp;&amp;amp;
      el.src
    ) {
      const next = transformPath(el.src);
      if (next !== el.src) el.src = next;
    }
    if (el.hasAttribute &amp;amp;&amp;amp; el.hasAttribute(&quot;srcset&quot;)) {
      try {
        const raw = el.getAttribute(&quot;srcset&quot;) || &quot;&quot;;
        const parts = raw
          .split(&quot;,&quot;)
          .map((p) =&amp;gt; p.trim())
          .filter(Boolean);
        const fixed = parts
          .map((p) =&amp;gt; {
            const sp = p.split(/\s+/);
            sp[0] = transformPath(sp[0]);
            return sp.join(&quot; &quot;);
          })
          .join(&quot;, &quot;);
        if (fixed !== raw) el.setAttribute(&quot;srcset&quot;, fixed);
      } catch (_) {}
    }
  }

  if (typeof MutationObserver !== &quot;undefined&quot;) {
    const mo = new MutationObserver((muts) =&amp;gt; {
      for (const m of muts) {
        if (m.type === &quot;childList&quot;) {
          m.addedNodes &amp;amp;&amp;amp;
            m.addedNodes.forEach((n) =&amp;gt; {
              if (n &amp;amp;&amp;amp; n.nodeType === 1) {
                rewriteEl(n);
                n.querySelectorAll?.(
                  &quot;link[rel],script[src],img[src],source[src],video[src],audio[src],[srcset]&quot;
                ).forEach(rewriteEl);
              }
            });
        } else if (m.type === &quot;attributes&quot;) {
          rewriteEl(/** @type {Element} */ (m.target));
        }
      }
    });
    const start = () =&amp;gt; {
      mo.observe(document.documentElement || document, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: [&quot;href&quot;, &quot;src&quot;, &quot;srcset&quot;, &quot;rel&quot;],
      });
      document
        .querySelectorAll(
          &quot;link[rel],script[src],img[src],source[src],video[src],audio[src],[srcset]&quot;
        )
        .forEach(rewriteEl);
    };
    document.readyState === &quot;loading&quot;
      ? document.addEventListener(&quot;DOMContentLoaded&quot;, start, { once: true })
      : start();
  }

  console.log(&quot;VSCode Webview resource mapper initialized&quot;);
  console.log(&quot;Base URI:&quot;, baseUri);
})();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;要点回顾：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;扩展端始终以 &lt;code&gt;webview.asWebviewUri&lt;/code&gt; 作为“真相源”；&lt;/li&gt;
&lt;li&gt;Webview 端只做兜底修复，确保动态新增节点与网络请求同样可达；&lt;/li&gt;
&lt;li&gt;两侧配合 CSP，既安全又稳定。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;以上示例代码以 MPL-2.0 授权；若你在项目中使用，请保留许可头与变更说明。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;小结&lt;/h2&gt;
&lt;p&gt;把 Vue SPA 嵌入 VS Code Webview 的关键是“资源可达且安全”。&lt;/p&gt;
&lt;p&gt;通过：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全量走 &lt;code&gt;asWebviewUri&lt;/code&gt; 暴露静态资源&lt;/li&gt;
&lt;li&gt;运行时资源映射器兜底动态引用&lt;/li&gt;
&lt;li&gt;严格且可控的 CSP 配置&lt;/li&gt;
&lt;li&gt;明确的数据通信协议&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;即可实现稳定、安全的嵌入式前端体验。后续你可以叠加数据持久化（全局存储/工作区文件）、多语言与主题适配等能力。&lt;/p&gt;
</content:encoded></item><item><title>Fuwari 博客模板使用指南(Koro Version)</title><link>https://blog.sirrus.cc/posts/guide/</link><guid isPermaLink="true">https://blog.sirrus.cc/posts/guide/</guid><description>如何使用这个博客模板。</description><pubDate>Mon, 01 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;封面图片来源: &lt;a href=&quot;https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/208fc754-890d-4adb-9753-2c963332675d/width=2048/01651-1456859105-(colour_1.5),girl,_Blue,yellow,green,cyan,purple,red,pink,_best,8k,UHD,masterpiece,male%20focus,%201boy,gloves,%20ponytail,%20long%20hair,.jpeg&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个博客模板基于 &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; 构建。对于本指南中未提及的内容，您可以在 &lt;a href=&quot;https://docs.astro.build/&quot;&gt;Astro 文档&lt;/a&gt; 中找到答案。&lt;/p&gt;
&lt;h2&gt;文章的 Front-matter&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;---
title: 我的第一篇博客文章
published: 2023-09-09
description: 这是我新 Astro 博客的第一篇文章。
image: ./cover.jpg
tags: [前端, 博客]
category: 技术
draft: false
lang: &quot;zh_cn&quot;

---
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文章标题。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;published&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文章发布日期。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文章简短描述，显示在首页。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文章封面图片路径。&amp;lt;br/&amp;gt;1. 以 &lt;code&gt;http://&lt;/code&gt; 或 &lt;code&gt;https://&lt;/code&gt; 开头：使用网络图片&amp;lt;br/&amp;gt;2. 以 &lt;code&gt;/&lt;/code&gt; 开头：使用 &lt;code&gt;public&lt;/code&gt; 目录中的图片&amp;lt;br/&amp;gt;3. 无前缀：相对于 markdown 文件的路径&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文章标签。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;category&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文章分类。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draft&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;是否为草稿，草稿不会显示。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lang&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文章语言（如 &quot;zh_cn&quot;, &quot;en&quot;, &quot;ja&quot;）。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;文章文件放置位置&lt;/h2&gt;
&lt;p&gt;您的文章文件应放置在 &lt;code&gt;src/content/posts/&lt;/code&gt; 目录中。您也可以创建子目录来更好地组织您的文章和资源。&lt;/p&gt;
&lt;h3&gt;多语言支持&lt;/h3&gt;
&lt;p&gt;对于多语言文章，请使用以下命名约定：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/
├── guide/
│   ├── cover.jpeg
│   ├── index.md          # 默认语言（中文）
│   └── index.en.md       # 英文版本
├── hello-world/
│   ├── hello-world.zh_cn.md
│   └── hello-world.en.md
└── single-post.md        # 单语言文章
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;语言切换&lt;/h2&gt;
&lt;p&gt;在顶部 Header 中全局切换语言，会自动筛选。&lt;/p&gt;
&lt;h2&gt;支持的语言&lt;/h2&gt;
&lt;p&gt;此博客模板支持以下语言：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;简体中文：&lt;code&gt;zh_cn&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;英语：&lt;code&gt;en&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;日语：&lt;code&gt;ja&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;俄文：&lt;code&gt;ru&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item></channel></rss>