news 2026/9/14 3:22:49

Qwen Code 原生 LSP 集成实战:.lsp.json 配置、lsp 工具的 12 种代码智能操作与安全模型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Qwen Code 原生 LSP 集成实战:.lsp.json 配置、lsp 工具的 12 种代码智能操作与安全模型

Qwen Code 原生 LSP 集成实战:.lsp.json 配置、lsp 工具的 12 种代码智能操作与安全模型

【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code

Qwen Code 内置了原生 Language Server Protocol(LSP)支持,让 AI Agent 能够像 IDE 一样“理解”你的代码:跳转定义、查找引用、悬停文档、诊断告警、调用层级与代码操作。本文基于官方文档 docs/users/features/lsp.md 展开,结合packages/core/src/lsp/packages/core/src/tools/lsp.ts的源码实现,系统讲清楚:如何用--experimental-lsp启用该能力、如何编写.lsp.json及各字段的确切语义、统一lsp工具暴露的全部操作及其参数约定,以及工作区信任、命令路径限制等安全机制和完整的排障路径。

一、功能定位与启用方式

1.1 LSP 带来的能力

Qwen Code 的 LSP 支持通过连接“理解你代码的语言服务器”工作。一旦通过.lsp.json(或扩展)完成配置,Qwen Code 会自动启动这些服务器,并借助它们:

  • 跳转到符号定义(go-to-definition);
  • 查找符号的所有引用(find references);
  • 获取悬停信息(文档、类型信息);
  • 查看诊断消息(错误、警告);
  • 访问代码操作(快速修复、重构);
  • 分析调用层级(call hierarchy)。

这套能力最终统一收敛到一个名为lsp的工具上,Agent 在会话中即可调用(详见第三节)。

1.2 启用:--experimental-lsp 命令行标志

LSP 目前是 Qwen Code 的实验性功能,需要显式传参启用:

qwen --experimental-lsp

从源码可以确认这一开关的真实生效逻辑:在 CLI 配置解析 中,LSP 仅在同时满足“非 bare 模式、非 provisional workspace、且显式传入--experimental-lsp”三个条件时才被置为启用:

// LSP configuration: enabled only via --experimental-lsp flag !provisionalWorkspace && !bareMode && argv.experimentalLsp === true;

也就是说,不存在配置文件级别的隐式开关,每次启动都必须带这个标志,否则lsp工具会返回 “LSP … is unavailable (LSP disabled or not initialized)”(见 LspToolInvocation.execute)。

1.3 前置条件:安装对应语言服务器

LSP 服务器是配置驱动的:你必须定义它们,Qwen Code 才会启动。各语言对应的服务器与安装命令如下:

语言语言服务器安装命令
TypeScript/JavaScripttypescript-language-servernpm install -g typescript-language-server typescript
Pythonpylsppip install python-lsp-server
Gogoplsgo install golang.org/x/tools/gopls@latest
Rustrust-analyzer通过 rustup 安装组件(rustup component add rust-analyzer)或按官方说明安装
C/C++clangd通过系统包管理器安装 LLVM/clangd
Javajdtls安装 JDTLS 与 JDK(java需在 PATH 中)

二、编写.lsp.json配置

2.1 基本格式

在项目根目录放置.lsp.json文件即可声明语言服务器。顶层每个键是一个语言标识符,其值是对应服务器的配置对象

{ "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "extensionToLanguage": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } }

从源码结构看(LspConfigLoader.parseConfigSource),解析规则是:键(如typescript)成为该服务器负责的languages列表的唯一元素;若command是字符串则直接取它作为服务器name,否则回退为键名。

2.2 C/C++(clangd)配置

依赖条件:

  • clangd(LLVM)已安装并在 PATH 中可用;
  • 项目中存在编译数据库(compile_commands.json)或compile_flags.txt,这是 clangd 给出准确结果的前提。

示例配置:

{ "cpp": { "command": "clangd", "args": [ "--background-index", "--clang-tidy", "--header-insertion=iwyu", "--completion-style=detailed" ] } }

若编译数据库位于 build 子目录(CMake 等场景常见),需显式告知 clangd:

{ "cpp": { "command": "clangd", "args": ["--background-index", "--compile-commands-dir=build"] } }

2.3 Java(jdtls)配置

依赖条件:JDK 已安装且java在 PATH 中;JDTLS 已安装且jdtls在 PATH 中。

{ "java": { "command": "jdtls", "args": ["-configuration", ".jdtls-config", "-data", ".jdtls-workspace"] } }

注意源码中的默认常量(constants.ts):文档打开后默认仅等待 200ms(DEFAULT_LSP_DOCUMENT_OPEN_DELAY_MS),而 jdtls、clangd 这类慢服务器构建 AST/索引需要更久,Qwen Code 对首次返回空结果的文档级操作会默认等待 2000ms 再重试一次(DEFAULT_LSP_DOCUMENT_RETRY_DELAY_MS)。这解释了“刚打开项目时 Java/C++ 首次查询可能为空、稍后正常”的现象。

2.4 配置字段完整说明

必填字段:

字段类型说明
commandstring启动 LSP 服务器的命令。支持通过PATH解析的裸命令名(如clangd)和绝对路径(如/opt/llvm/bin/clangd

可选字段:

字段类型默认值说明
argsstring[][]命令行参数
transportstring"stdio"传输类型:stdiotcpsocket
envobject-环境变量(数字/布尔值会被规范化为字符串)
initializationOptionsobject-LSP 初始化选项(随initialize请求发送)
settingsobject-通过workspace/didChangeConfiguration下发的服务器设置
extensionToLanguageobject-文件扩展名到语言标识符的映射(扩展名不带.且统一小写)
workspaceFolderstring-覆盖工作区文件夹(必须位于项目根目录内,否则回退为项目根并告警)
startupTimeoutnumber10000启动超时(毫秒),默认值见 DEFAULT_LSP_STARTUP_TIMEOUT_MS
shutdownTimeoutnumber5000优雅关闭超时(毫秒),默认值见 DEFAULT_LSP_SHUTDOWN_TIMEOUT_MS
restartOnCrashbooleanfalse崩溃后自动重启
maxRestartsnumber3最大重启次数,默认值见 DEFAULT_LSP_MAX_RESTARTS
trustRequiredbooleantrue是否要求受信任工作区(见 4.2 的源码级细节)

字段解析时源码会做严格的类型规范化(buildServerConfig):args只保留字符串元素;env中非字符串值会转为字符串;startupTimeout/shutdownTimeout必须是正数,否则被丢弃并回退默认值;transport只接受stdio/tcp/socket(大小写不敏感),其余值一律回退为stdio

另外两个容易踩坑的硬性校验:

  • transportstdio但缺少command→ 该配置被丢弃并在 debug 日志中告警;
  • transporttcp/socket但缺少有效的 socket 信息(端口 1–65535,或 Unix socket 路径)→ 同样被丢弃。

2.5 TCP / Socket 传输

对于使用 TCP 或 Unix socket 传输的服务器(例如远端语言服务器),配置形如:

{ "remote-lsp": { "transport": "tcp", "socket": { "host": "127.0.0.1", "port": 9999 }, "extensionToLanguage": { ".custom": "custom" } } }

源码中 normalizeSocketOptions 同时支持三种写法:socket直接给字符串(作为 Unix socket 路径)、socket: { host, port }(TCP)、socket: { path }(Unix socket,也兼容socketPath键名)。TCP 连接还有内置的重试退避(初始 250ms、上限 1000ms,见 constants.ts#L51-L55)。

2.6 配置加载与合并的底层逻辑

理解配置如何被加载,有助于排查“配置明明写了却不生效”的问题。LspConfigLoader 的完整流程:

  1. 用户配置:只读取项目根目录下的.lsp.jsonpath.join(workspaceRoot, '.lsp.json')),文件不存在时返回空列表而不是报错;
  2. 扩展配置:遍历已启用扩展的config.lspServers(详见第五节);
  3. 合并策略:mergeConfigs 先并入扩展配置,再并入用户配置,同名(同name)服务器时用户配置覆盖扩展配置。源码注释明确说明:内置预设(built-in presets)已禁用,语言服务器必须由用户显式配置,不会自动探测安装。

还有一个值得注意的严格模式:loadUserConfigsStrict.lsp.json的每个条目做强校验(必须是对象、必须能构造出合法配置),任何一条不合法都会让整份配置加载失败并返回错误,供上层(如/lsp状态检查)提示用户修正 JSON,而不是静默忽略。

三、统一lsp工具:12 种代码智能操作

Qwen Code 将全部 LSP 能力收敛到单一工具lsp,通过operation参数区分操作。工具定义见 LspTool,支持的 12 种操作在 LspOperation 类型 中一次性声明完毕:

分组操作必需参数源码默认 limit
代码导航goToDefinitionfilePath+line+character20
findReferences同上,另有可选includeDeclaration50
goToImplementationfilePath+line+character20
符号信息hoverfilePath+line+character-
documentSymbolfilePath50
workspaceSymbolquery(可选limit20
调用层级prepareCallHierarchyfilePath+line+character20
incomingCallscallHierarchyItem(来自 prepare 的结果)20
outgoingCallscallHierarchyItem20
诊断diagnosticsfilePath-
workspaceDiagnostics无(可选limit50
代码操作codeActionsfilePath+line+character,可选endLine/endCharacter/diagnostics/codeActionKinds20

3.1 位置类操作的参数约定

goToDefinitionfindReferenceshovergoToImplementationprepareCallHierarchy这五类基于位置的操作要求精确的filePath+line+character。文档给出的关键使用建议是:如果你不知道符号的精确位置,先用workspaceSymbol(按名搜索)或documentSymbol(列出文件内符号)定位,再发起位置类操作

Operation: goToDefinition Parameters: - filePath: Path to the file - line: Line number (1-based) - character: Column number (1-based)
Operation: findReferences Parameters: - filePath: Path to the file - line: Line number (1-based) - character: Column number (1-based) - includeDeclaration: Include the declaration itself (optional)
Operation: goToImplementation Parameters: - filePath: Path to the file - line: Line number (1-based) - character: Column number (1-based)
Operation: hover Parameters: - filePath: Path to the file - line: Line number (1-based) - character: Column number (1-based)

参数校验在 validateToolParamValues 中实现,要点:

  • 行号和列号均为 1-based,源码内部再减 1 转换为 LSP 协议的 0-based 位置(resolveLocationTarget);
  • filePath支持绝对路径或工作区相对路径,也支持带://的 URI,会被规范化为file://URI(resolveUri);
  • 任意行/列参数小于 1 都会被拒绝;
  • 每个操作可通过serverName显式指定目标服务器(同一语言配置了多个服务器时),否则按“第一个返回结果的服务器胜出”策略。

3.2 符号信息

Operation: documentSymbol Parameters: - filePath: Path to the file
Operation: workspaceSymbol Parameters: - query: Search query string - limit: Maximum results (optional)

workspaceSymbol有一个源码级的加分细节(executeWorkspaceSymbols):在返回符号列表之外,还会自动对排名第一的匹配项追加一次references查询,把它的引用位置一并带回给 LLM,让 Agent 一次调用就拿到“定义位置 + 使用位置”双份上下文,减少后续轮次。

3.3 调用层级

调用层级是三步式协议:先prepareCallHierarchy拿到某个位置上的调用层级项,再把该项传给incomingCalls/outgoingCalls

Operation: prepareCallHierarchy Parameters: - filePath: Path to the file - line: Line number (1-based) - character: Column number (1-based)
Operation: incomingCalls Parameters: - callHierarchyItem: Item from prepareCallHierarchy
Operation: outgoingCalls Parameters: - callHierarchyItem: Item from prepareCallHierarchy

callHierarchyItem的完整结构(nameurirangeselectionRange为必填,kind/detail/data/serverName可选)定义在工具的 JSON Schema 中(definitions.LspCallHierarchyItem)。源码会保留prepare返回的data不透明字段原样传回给服务器——部分服务器(如 clangd)依赖它定位内部索引,手动改写该项会导致查询失败。

输出格式上,prepareCallHierarchy/incomingCalls/outgoingCalls/codeActions四类操作除了人类可读的编号列表外,还会在 LLM 可见内容中追加一个 JSON 区块formatJsonSection,lsp.ts#L943-L945),供 Agent 精确消费结构化数据;incomingCalls的结果还会标注每个调用发生的具体位置(fromRanges,最多显示 3 处,超出以+N more收尾)。

3.4 诊断

Operation: diagnostics Parameters: - filePath: Path to the file
Operation: workspaceDiagnostics Parameters: - limit: Maximum results (optional)

诊断结果按[SEVERITY] line:col (code) [source]: message的格式输出(executeDiagnostics),severity 覆盖error/warning/information/hint四级(映射表见 DIAGNOSTIC_SEVERITY_LABELS)。workspaceDiagnostics按文件分组输出,并在标题行给出“共 N 个文件 M 条问题”的汇总。

3.5 代码操作(Code Actions)

Operation: codeActions Parameters: - filePath: Path to the file - line: Start line number (1-based) - character: Start column number (1-based) - endLine: End line number (optional, defaults to line) - endCharacter: End column (optional, defaults to character) - diagnostics: Diagnostics to get actions for (optional) - codeActionKinds: Filter by action kind (optional)

line/character缺省端点默认等于起点(即“单点”范围);请求上下文固定triggerKind: 'invoked'(executeCodeActions)。支持的codeActionKinds过滤值:

  • quickfix— 错误/警告的快速修复;
  • refactor— 重构操作;
  • refactor.extract— 提取为函数/变量;
  • refactor.inline— 内联函数/变量;
  • source— 源代码级操作;
  • source.organizeImports— 整理 import;
  • source.fixAll— 修复所有可自动修复的问题。

源码中的 CODE_ACTION_KIND_LABELS 还包含refactor.rewrite,且空字符串的 kind 会被归一化为quickfix。输出列表里,服务器标记为isPreferred的项会带,携带editcommand的项会标注(has edit)/(has command)

另外,lsp工具在工具清单中是延迟加载的(shouldDefer: true,经 ToolSearch 按需载入,见 LspTool 构造参数),其工具描述明确要求 Agent:“当 LSP 可用时,优先用 LSP 作为代码智能查询的主工具,而不是先用 grep/glob”——这正是该功能的设计意图:让模型直接消费语义级结果,而非文本级搜索。

四、安全模型:工作区信任与路径限制

4.1 为什么默认要求“受信任工作区”

LSP 服务器以你的用户权限运行、并且可以执行代码(语言服务器通常会求值宏、调用 build 工具链等)。因此 Qwen Code 的默认策略是:只有受信任工作区才会启动 LSP 服务器

  • 受信任工作区:已配置的 LSP 服务器正常启动;
  • 非受信任工作区:除非服务器配置中设置了trustRequired: false,否则服务器不会启动;
  • 标记信任:在 CLI 中执行/trust命令。

源码中这一判断发生在启动前:LspServerManager 会记录 “requires trusted workspace, skipping startup”,NativeLspService 则把被跳过的服务器记入skipped列表,跳过原因固定为server_trust_required(LspServerSkipReason),这些服务器仍会出现在/lsp状态输出中以便你排查。

4.2 单服务器信任覆盖(及一个源码级细节)

你可以在特定服务器的配置中覆盖信任要求:

{ "safe-server": { "command": "safe-language-server", "args": ["--stdio"], "trustRequired": false, "extensionToLanguage": { ".safe": "safe" } } }

这里有一个文档没有明说、但对行为有实际影响的细节:从 LspConfigLoader.loadUserConfigs 与 parseUserConfigSourceStrict 的实现看,用户.lsp.json的每个条目在解析时都会被强制trustRequired: trueforceTrustRequired: true)。也就是说,项目内.lsp.json写的trustRequired: false不会放松信任要求;而扩展提供的 LSP 配置走的是不强制的路径trustRequired: false的单服务器覆盖在扩展场景下才真正生效。保守理解:项目级配置永远要求受信任工作区,这是刻意设计的安全底线。

4.3 命令路径安全

command字段只允许两类取值:可在PATH中解析的裸命令名,或绝对路径。相对路径且逃逸出工作区的命令会被直接拦截,源码中的报错文案是(LspServerManager.ts#L417):

LSP server <name> command path is unsafe: ../../outside/payload

测试用例(LspServerManager.test.ts#L545)正是用../../outside/payload这样的路径验证该拦截。对应到排障:若你的服务器不在 PATH 中,请改用绝对路径(如/opt/llvm/bin/clangd),不要尝试用../之类相对路径“绕”到别处。

五、扩展声明的 LSP 服务器(lspServers)

扩展可以在其plugin.jsonlspServers字段中提供 LSP 服务器配置,取值有两种形式:

  1. 内联对象:直接写语言键值布局的配置;
  2. 字符串路径:指向一个.lsp.json文件的相对/绝对路径。

格式与项目.lsp.json完全一致(语言为顶层键)。扩展启用时 Qwen Code 即加载这些配置(loadExtensionConfigs)。两个实现细节:

  • 字符串路径相对于扩展自身目录解析(resolveExtensionConfigPath);
  • 扩展配置中的字符串会经过变量替换(hydrateExtensionLspConfig),可用${CLAUDE_PLUGIN_ROOT}引用扩展根目录、${workspacePath}引用当前工作区,便于跨项目复用的扩展声明可移植的服务器路径。

与用户配置的合并规则如 2.6 所述:同名服务器时用户配置优先。

六、排障与调试

6.1 状态检查:/status/lsp

/status会打印一行 LSP 汇总(对应 LspStatusSnapshot 的各状态计数):

LSP: disabled LSP: enabled, 1/1 ready LSP: enabled, 0/1 ready (1 failed) LSP: enabled, no servers configured LSP: enabled, status unavailable

/lsp(实现见 lspCommand.ts)输出逐服务器明细表:

**LSP Server Status** | Server | Command | Languages | Status | |--------|---------|-----------|--------| | clangd | `clangd` | c, cpp | READY | | pyright | `pyright-langserver` | python | FAILED - startup failed |

状态机为四态:NOT_STARTED/IN_PROGRESS/READY/FAILED(LspServerStatus),FAILED 时会附带最后的error与 stderr 尾部输出。若修改了.lsp.json,客户端接口支持reinitialize重新读取配置并 reconcile 现有连接(LspClient.reinitialize)。

6.2 服务器不启动:六步排查清单

  1. 确认--experimental-lsp标志:启动时是否带了该标志(漏掉是最常见原因);
  2. 确认服务器已安装:手动执行clangd --version之类命令验证;
  3. 检查命令:服务器二进制必须在系统PATH中,或使用绝对路径;逃逸工作区的相对路径会被安全拦截(见 4.3);
  4. 检查工作区信任:未/trust前服务器不会启动;
  5. 查看日志:带--debug启动后在 debug 日志中检索 LSP 相关条目(见 6.5);
  6. 检查进程ps aux | grep <server-name>确认服务器进程是否真的存在。

常见错误信息对照:

command path is unsafe -> relative path escapes workspace, use absolute path or add to PATH command not found -> server binary not installed or not in PATH requires trusted workspace -> run /trust first LSP connection closed -> server started but exited or closed stdio before replying to initialize

6.3 性能问题(启动慢 / 大项目)

  • 大项目:考虑排除node_modules等超大目录(通过语言服务器自身参数,如 clangd 的.clangd配置或--compile-commands-dir收敛索引范围);
  • 服务器启动慢:在.lsp.json中调大该服务器的startupTimeout(默认 10000ms,见 constants.ts#L13-L14),避免默认超时先于服务器初始化完成。

6.4 查询无结果

  1. 服务器尚未就绪:仍在索引中。C/C++ 项目请确认args--background-index,且项目根(或父目录)存在compile_commands.json/compile_flags.txt;编译数据库在 build 子目录时用--compile-commands-dir=<path>指定;
  2. 文件未保存:语言服务器以磁盘内容为准,保存文件后它才能感知;
  3. 语言不对:确认该文件扩展名映射到了正确的服务器(检查extensionToLanguage);
  4. 进程不在ps aux | grep <server-name>验证(clangd / typescript-language-server / jdtls 等)。

6.5 调试日志:--debug+ 日志检索

LSP 没有独立的 debug 开关,直接复用 Qwen Code 的标准调试模式:

qwen --experimental-lsp --debug

debug 日志写入会话 debug 日志目录,检索 LSP 相关条目:

# 默认运行时目录 rg "LSP|Native LSP|clangd|connection closed" ~/.qwen/debug/latest # 或不用 ripgrep: grep -E "LSP|Native LSP|clangd|connection closed" ~/.qwen/debug/latest # 若设置了 QWEN_RUNTIME_DIR rg "LSP|Native LSP|clangd|connection closed" "$QWEN_RUNTIME_DIR/debug/latest"

有价值的日志模式:

  • [LSP] ...— 原生 LSP 服务与服务器管理器发出的日志(debugLogger 命名空间即LSP,见 LspConfigLoader.ts#L22);
  • [CONFIG] Native LSP status after discovery: ...— 会话发现到的服务器配置;
  • [CONFIG] Native LSP status after startup: ...— 启动结果,含 ready/failed 计数;
  • [STATUS] LSP status snapshot for /status: ...— debug 模式下运行/status时打印的状态快照。

6.6 clangd 专项验证

clangd 启动失败时,从项目根目录直接验证服务器本身:

clangd --version clangd --check=/path/to/file.cpp --log=verbose

C/C++ 项目通常应提供compile_commands.jsoncompile_flags.txt;编译数据库位于 build 目录时按 2.2 的方式传--compile-commands-dir。最后可用ps aux | grep clangd确认进程存活。

七、最佳实践与 FAQ

最佳实践:

  1. 全局安装语言服务器:保证所有项目可用;
  2. 按项目定制:确有需要时用项目.lsp.json覆写服务器参数;
  3. 保持服务器更新:定期升级语言服务器以获得最好的索引与诊断质量;
  4. 谨慎授予信任:只信任来源可靠的工作区。

FAQ:

  • Q:如何启用 LSP?启动时加--experimental-lspqwen --experimental-lsp

  • Q:如何知道哪些语言服务器正在运行?qwen --experimental-lsp --debug启动,然后:/status看一行汇总,/lsp看逐服务器状态表,或直接检索 debug 日志:

    rg "LSP|Native LSP|<server-name>" ~/.qwen/debug/latest # 或:grep -E "LSP|Native LSP|<server-name>" ~/.qwen/debug/latest # 若配置了 QWEN_RUNTIME_DIR: rg "LSP|Native LSP|<server-name>" "$QWEN_RUNTIME_DIR/debug/latest"

    LSP 复用 Qwen Code 标准的--debug模式,没有单独的 LSP debug 开关。

  • Q:同一文件类型能用多个语言服务器吗?可以,但每次操作只会用一个服务器的结果,第一个返回结果的服务器胜出。可用serverName参数强制指定目标服务器。

  • Q:LSP 在沙箱模式下能工作吗?LSP 服务器运行在沙箱之外以便访问你的代码,同时受工作区信任控制约束。

适用范围与限制提示:本文所述行为以当前仓库源码为准。LSP 能力当前处于实验阶段(--experimental-lsp),仅支持项目根.lsp.json与扩展lspServers两种配置来源,无内置服务器预设;workspaceFolder不得逃逸项目根;用户.lsp.json的信任要求被强制为 true。若你依赖trustRequired: false放松信任,请通过扩展配置而非项目文件来实现。

【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

STM32CubeMX安装卡在JRE缺失?精准匹配Java 17运行时指南

1. 为什么STM32CubeMX安装总卡在“JRE缺失”这一步&#xff1f;——从B站热帖乱象说起 你点开B站搜“STM32CubeMX安装教程”&#xff0c;前二十个视频里&#xff0c;至少十五个开头就是&#xff1a;“大家好&#xff0c;今天教大家安装STM32CubeMX&#xff0c;非常简单&#xf…

作者头像 李华
网站建设 2026/9/14 3:19:51

微信小程序流量主实战:星座运势与周公解梦源码改造指南

简介&#xff1a;一款以星座运势查询与周公解梦为主要功能的微信小程序源码包&#xff0c;面向小程序开发者、内容运营者和流量主变现新手&#xff0c;适用于快速搭建带有星座生肖内容矩阵的小程序场景。包内集成星座查询、星座运势、十二生肖查询、生肖运势、星座配对、生肖配…

作者头像 李华
网站建设 2026/9/14 3:16:22

IBM POWER8 S822服务器实战指南:AIX、LPAR与高可用运维

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

作者头像 李华