VizTyp/AGENTS.md

39 KiB
Raw Permalink Blame History

AGENTS.md

Agent 工作指南 / Agent Working Guide 本文件原为新项目创建蓝图,现已记录 VizTyp 的完整实现(全部功能已完成)。 This file was a greenfield blueprint, now documents VizTyp's full implementation (all 5 phases complete).


项目概述 / Project Overview

VizTyp 是一个基于 Typst 的个人与团队知识管理系统,融合语雀的结构化知识管理与 MrDoc 的私有化部署理念,采用思源笔记风格 IDE 布局,面向 Web 和 Tauri 桌面双平台。 VizTyp is a personal and team knowledge management system based on Typst, combining Yuque's structured knowledge management with MrDoc's self-hosted philosophy, with a SiYuan-note style IDE layout, targeting both Web and Tauri desktop platforms.

核心定位 / Core Positioning

"可本地优先的语雀" + "实时可视化的 MrDoc" "Local-first Yuque + real-time visual MrDoc"

特性 / Feature 说明 / Description
本地优先 / Local-first Typst 文件存储在本地磁盘,支持 Git 版本控制,不依赖云端 (vs 语雀/MrDoc 的云端存储)
实时编译 / Real-time compilation Typst 源码通过 typst.ts WASM 在浏览器/webview 中实时编译,生成 SVG 预览 (语雀/MrDoc 均无此能力)
Typst 作为规范格式 / Typst as canonical format 开放、可编译、可版本控制,非私有格式 (vs 语雀的 Lake 私有格式 / MrDoc 的 Markdown 字符串)
可视化知识图谱 / Visual knowledge graph 基于 #include/#import 的依赖图可视化,超越语雀和 MrDoc 的隐式引用
思源风格 IDE / SiYuan-style IDE ActivityBar + LeftDock + Center(Tabs + Editor/Preview Split) + RightDock + StatusBar
双平台共享 / Dual-platform sharing Web 和桌面使用同一套 Svelte 5 前端,零重复代码

竞品对比 / Competitive Analysis

维度 / Dimension 语雀 / Yuque MrDoc (觅思文档) VizTyp
层级结构 / Hierarchy Team → Book → Doc (严格三层) Project → Doc (parent_doc 自引用) Workspace → KB → Doc (Typst #include 树)
内容/结构 / Content/Structure 解耦: 文档扁平存储, TOC 独立树 双重: parent_doc + ProjectToc JSON refs.ts 解析 #include 树 (已实现)
文档格式 / Doc format Lake (私有 block/card 格式) Markdown 字符串 (无 AST) Typst (开放, 可编译, 可 Git)
草稿/发布 / Draft/Publish body_draft vs body, status 0/1 pre_content vs content .typ.draft sidecar + publish (已实现)
权限 / Permissions Team: Admin/Member/ReadOnly; KB: reader/writer 4 级: 公开/私密/指定用户/访问码 4 级 + JWT 认证 + 协作者角色 (已实现)
实时协作 / Real-time collab 实时协同 → 降级为锁模式 无 (异步编辑 + 版本快照) typst.ts 实时 SVG 预览 + presence 轮询
知识图谱 / Knowledge graph 隐式 (文档嵌入), 无可视化 DependencyGraph.svelte 手写 SVG (已实现)
搜索 / Search 分层 scope (user→team→book) 权限感知 (预过滤 project IDs), Whoosh+jieba 权限感知全文搜索 (预过滤可见 KB, 已实现)
部署模式 / Deployment SaaS 云端 私有化部署 (Django 单体) 本地优先 (文件 + 可选同步)
技术栈 / Tech stack Java 后端 + React 前端 Django SSR + jQuery/LayUI Svelte 5 SPA + Tauri

借鉴语雀的模式 / Patterns Adopted from Yuque

  1. 解耦内容/结构 / Decoupled content/structure — 文档扁平存储, TOC 独立树, 支持重组不触碰内容
  2. 草稿/发布分离 / Draft/publish separationbody_draft vs body, status 0/1
  3. 卡片/块扩展 / Card/block extensibility — Typst 的 CeTZ/Fletcher 块已天然支持
  4. 分层搜索 scope / Hierarchical search scope — user → team → team/book
  5. 文档嵌入与引用 / Document embedding#include 实现内容嵌入

借鉴 MrDoc 的模式 / Patterns Adopted from MrDoc

  1. 4 级可见性 / 4-tier visibility — 公开/私密/指定用户/访问码
  2. 协作者角色 / Collaborator roles — 0=仅自身文档, 1=所有文档
  3. 双重表示 / Dual representationparent_doc + 序列化 TOC JSON, 支持拖拽排序
  4. 权限感知搜索 / Permission-aware search — 预过滤可见 ID 列表
  5. 文档分享令牌 / DocShare token — 独立于项目权限的单文档分享
  6. 软删除 / Soft deletestatus 枚举 + 回收站

VizTyp 的差异化优势 / VizTyp's Differentiators

  1. 实时 SVG 渲染 / Real-time SVG rendering — typst.ts WASM 编译,语雀和 MrDoc 均无
  2. Typst 规范格式 / Typst canonical format — 开放、可编译、可 Git,非 Lake 私有
  3. 可视化知识图谱 / Visual knowledge graphDependencyGraph.svelte 超越两者
  4. 本地优先 / Local-first — 文件存储在磁盘,天然 Git 兼容

知识管理架构 / Knowledge Management Architecture

三层结构 / Three-Layer Structure

借鉴语雀和 MrDoc 的核心模式,VizTyp 采用三层知识管理结构: Drawing from Yuque and MrDoc's core patterns, VizTyp adopts a three-layer knowledge management structure:

┌─────────────────────────────────────────────────────────────────┐
│  Workspace (工作空间)                                           │
│  ├── KnowledgeBase (知识库)  ← 一个 .typ 项目文件夹 / Typst project folder
│  │   ├── Document (文档)     ← 单个 .typ 文件 / single Typst file
│  │   │   ├── Sub-document    ← #include 的子文件 / included child
│  │   │   └── (无限嵌套)      ← 基于 #include 的自然树
│  │   ├── Document ...
│  │   └── TOC (目录树)        ← 解耦的独立结构树 / Decoupled structure tree
│  ├── KnowledgeBase ...
│  └── (知识库集合) / KB collection
└─────────────────────────────────────────────────────────────────┘

核心数据模型设计 / Core Data Model Design

以下类型已在 types.ts + 后端 models.rs 完整实现。前端与后端通过 api/ 客户端交互。 These types are fully implemented in types.ts + backend models.rs. Frontend↔backend via api/ client.

类型定义 / Type Definitions (planned for types.ts)

// 工作空间 / Workspace — 顶层容器 / Top-level container
interface Workspace {
  id: string;
  name: string;
  knowledgeBases: KnowledgeBase[];
  members?: WorkspaceMember[];    // 团队成员 / Team members (future)
  createdAt: number;
}

// 知识库 / KnowledgeBase — 类似语雀的 Book 或 MrDoc 的 Project
interface KnowledgeBase {
  id: string;
  name: string;
  icon?: string;
  description: string;
  rootPath: string;               // 本地文件夹路径 / Local folder path
  visibility: KBVisibility;       // 可见性 / Visibility level
  collaborators?: Collaborator[]; // 协作者 / Collaborators (future)
  toc: TOCNode[];                 // 解耦的目录树 / Decoupled TOC tree
  tags: Tag[];                    // 标签 / Tags
  createdAt: number;
  updatedAt: number;
}

// 可见性 / Visibility — 借鉴 MrDoc 4 级权限
type KBVisibility =
  | 'public'        // 公开 — 任何人可读 / Anyone can read (role=0)
  | 'private'       // 私密 — 仅所有者 + 协作者 / Owner + collaborators only (role=1)
  | 'specified'     // 指定用户可见 / Specified users (role=2)
  | 'access_code';  // 访问码可见 / Access code required (role=3)

// 目录树节点 / TOC Node — 借鉴语雀的 TOC 解耦模式
interface TOCNode {
  uuid: string;
  type: 'DOC' | 'TITLE' | 'LINK';  // 文档引用 / 纯分组 / 外部链接
  title: string;
  docId?: string;                   // type=DOC 时的文档 ID
  parentId?: string;                // 父节点 UUID (构建树)
  level: number;                    // 深度, 0=root
  sortOrder: number;                // 同级排序 / Ordering among siblings
  openByDefault?: boolean;          // 默认展开 / Expand by default
}

// 文档 / Document — 单个 Typst 文件
interface Document {
  id: string;
  kbId: string;                   // 所属知识库 / Parent KB
  title: string;
  filePath: string;               // 本地文件路径 / Local file path
  content: string;                // 发布内容 / Published content
  draftContent?: string;          // 草稿内容 / Draft content (借鉴 MrDoc pre_content)
  status: 'draft' | 'published' | 'deleted';  // 软删除 / Soft delete
  editorMode: 'typst';            // 编辑器模式 (未来可扩展)
  tags: string[];                 // 标签 / Tags
  wordCount: number;
  createdAt: number;
  updatedAt: number;
  publishedAt?: number;
}

// 协作者 / Collaborator (future)
interface Collaborator {
  userId: string;
  kbId: string;
  role: 'reader' | 'writer' | 'admin';
}

// 标签 / Tag
interface Tag {
  id: string;
  name: string;
  color?: string;
}

// 文档分享 / Document Share — 借鉴 MrDoc DocShare
interface DocShare {
  token: string;
  docId: string;
  shareType: 'public' | 'private';  // private 需访问码
  shareCode?: string;                // 私密分享的访问码
  isEnabled: boolean;
  createdAt: number;
}

// 版本历史 / Version History
interface DocVersion {
  id: string;
  docId: string;
  content: string;                // 完整快照 / Full snapshot (MrDoc 模式)
  creator: string;
  createdAt: number;
}

权限系统设计 / Permission System Design

知识库可见性 (借鉴 MrDoc) / KB Visibility (from MrDoc)

可见性 / Visibility 说明 / Description 访问控制 / Access Control
public 公开 / Public 任何人可读 / Anyone can read
private 私密 / Private 仅所有者 + 协作者 / Owner + collaborators only
specified 指定用户 / Specified users 白名单用户 / Whitelisted user IDs
access_code 访问码 / Access code 需输入访问码 (存储于 cookie/localStorage)

协作者角色 (借鉴 MrDoc + 语雀) / Collaborator Roles (from MrDoc + Yuque)

角色 / Role 能力 / Capabilities
reader 只读 / Read only
writer 创建文档, 编辑/删除自身文档 / Create docs, edit/delete own docs
admin 创建文档, 编辑所有文档, 管理知识库 / Create docs, edit all docs, manage KB

权限感知搜索 (借鉴 MrDoc) / Permission-Aware Search (from MrDoc)

搜索流程 / Search flow:
1. 获取用户可见的知识库 ID 列表 / Get visible KB ID list for user
2. 在可见范围内执行全文搜索 / Execute full-text search within visible scope
3. 返回结果带知识库上下文 / Return results with KB context

技术栈 / Tech Stack

层 / Layer 选型 / Choice 版本 / Version
前端框架 / Frontend Svelte 5 (runes 模式) + Vite Svelte ^5.55, Vite ^8.0
语言 / Language TypeScript ~6.0
代码编辑器 / Code editor CodeMirror 6 (basicSetup + 自定义思源主题) ^6.0
Typst 集成 / Typst typst.ts 运行时编译 (Mode B) @myriaddreamin/* 锁定 0.7.0
桌面外壳 / Desktop Tauri v2 @tauri-apps/cli ^2
包管理器 / Package manager Yarn (classic)
Typst 可视化 / Typst viz CeTZ + Fletcher (消费) + 自研库
全文搜索 / Full-text search (规划中 / planned) flexsearch 或 lunr

布局架构 / Layout Architecture

┌─ ActivityBar (40px) ─┬─ LeftDock (220px) ─┬─ Center Area ─────────────┬─ RightDock (260px) ─┐
│                      │                     │ TabBar (32px)             │ DockPanel           │
│  📁 知识库树          │  DocTree            │ ┌─────────┬─────────┐    │ (Outline/Diag/Mark) │
│  🔍 搜索              │  (文件导航 +        │ │ Editor  │ Preview │    │                     │
│  🔖 书签              │   右键菜单 +        │ │ (CM6)   │ (SVG)   │    │  · 大纲 Outline     │
│  🕸 依赖图             │   #include 树)      │ │         │         │    │  · 诊断 Diagnostics │
│  📤 分享 (规划中)      │                     │ │         │         │    │  · 书签 Bookmarks   │
│                      │                     │ └─────────┴─────────┘    │                     │
│   新建              │                     │                           │                     │
│  📂 打开              │                     │ (拖拽分隔条调整比例)       │                     │
│  💾 保存              │                     │                           │                     │
│  ⚙️ 设置              │                     │                           │                     │
│  🌙 主题              │                     │                           │                     │
├──────────────────────┴─────────────────────┴───────────────────────────┴─────────────────────┤
│ StatusBar (26px): 子块统计 | 字符/词/行 | 光标 Ln/Col | 选区计数 | 同步状态                     │
└──────────────────────────────────────────────────────────────────────────────────────────────┘

布局演进计划 / Layout Evolution Plan

版本 / Version LeftDock 内容 / Content 说明
早期 / Early DocTree (已打开 Tab 列表) 多 Tab 编辑, 每个 Tab 一个 .typ 文件
当前 / Current KBTree + DocTree (顶部 tab 切换) 类似语雀: 左侧显示所有知识库, 点击展开文档树; 顶部切换"知识库/已打开"
未来 / Future KBTree + 搜索 + 收藏 + 标签 类似语雀工作台

目录结构 / Directory Structure

viztyp/
├── packages/
│   └── frontend/                          # Svelte 前端 (Web + Tauri 共享)
│       ├── package.json                   # 前端依赖
│       ├── vite.config.ts                 # Vite 配置 (COOP/COEP headers, WASM exclude)
│       ├── tsconfig.json / tsconfig.app.json / tsconfig.node.json
│       ├── index.html
│       └── src/
│           ├── main.ts                    # Svelte 5 mount 入口
│           ├── App.svelte                 # 主编排器 (布局 + 状态 + 全局快捷键)
│           ├── app.css                    # CSS 变量系统 (--viztyp-*)
│           ├── lib/
│           │   ├── types.ts               # Tab + Document/KB/Workspace 接口 (已实现全部)
│           │   ├── typst-init.ts          # typst.ts WASM 初始化 (手动 compiler+renderer)
│           │   ├── Editor.svelte          # CodeMirror 6 编辑器 (+ view 逃逸口 + search 扩展)
│           │   ├── Preview.svelte         # SVG 实时预览 (debounced, 错误状态)
│           │   ├── cm-theme.ts            # CodeMirror 思源风格主题 (安全 tags)
│           │   ├── ActivityBar.svelte     # 最左侧垂直图标栏 (12 图标 + dock 切换)
│           │   ├── TabBar.svelte          # 多标签栏 (center 区域内)
│           │   ├── DocTree.svelte         # 已打开 Tab 文档树
│           │   ├── kb-tree.svelte         # 左侧知识库树 (KB → Doc 两级展开) ✅
│           │   ├── DockPanel.svelte       # 右侧 Dock (大纲/诊断/依赖图/历史/书签 5 tab)
│           │   ├── OutlinePanel.svelte    # Typst #heading 大纲
│           │   ├── DiagnosticsPanel.svelte # 编译诊断 (typst.ts)
│           │   ├── DependencyGraph.svelte # SVG 依赖图 (知识图谱核心, 手写 SVG)
│           │   ├── HistoryPanel.svelte    # 版本历史 (快照 + 恢复)
│           │   ├── StatusBar.svelte       # 底部状态栏 (统计 + 在线协作者)
│           │   ├── CommandPalette.svelte  # Ctrl+K 命令面板 (模糊搜索)
│           │   ├── SearchPanel.svelte     # 全局搜索 (KB 权限感知 + Tabs 双模式)
│           │   ├── FindReplace.svelte     # 查找替换 (CM6 内置面板)
│           │   ├── PluginManager.svelte   # 插件管理 (Alt+P, 开关切换)
│           │   ├── TagEditor.svelte       # 文档标签编辑 modal
│           │   ├── CollaboratorManager.svelte # KB 协作者管理 modal ✅
│           │   ├── SnippetSettings.svelte # CSS/JS 片段编辑器
│           │   ├── Login.svelte           # 登录/注册全屏覆盖 ✅
│           │   ├── Settings.svelte        # 设置面板 (Ctrl+,)
│           │   ├── command-registry.ts    # 命令注册系统 (去重 + 模糊搜索)
│           │   ├── theme.svelte.ts        # 主题状态 (light/dark/system)
│           │   ├── settings.svelte.ts     # 设置状态 (localStorage 持久化)
│           │   ├── auth.svelte.ts         # 认证状态 (JWT, login/register/logout) ✅
│           │   ├── kb-store.svelte.ts     # 知识库状态 (Workspace/KB/Doc, 接后端) ✅
│           │   ├── collab.svelte.ts       # 协作状态 (presence 轮询) ✅
│           │   ├── snippets.svelte.ts     # CSS/JS 片段管理 (CSS 动态注入)
│           │   ├── plugin-loader.svelte.ts # 插件加载器 + 钩子体系 (onCompile/onSave/...) ✅
│           │   ├── outline.ts             # parseOutline() — 解析 #heading
│           │   ├── refs.ts                # parseReferences() + buildDependencyGraph()
│           │   ├── stats.ts               # parseStats() — 文档统计 + CursorInfo
│           │   ├── history.ts             # 版本快照 (接后端 API)
│           │   ├── share-manager.ts       # 文档分享令牌 (接后端 API) ✅
│           │   ├── search-engine.ts       # 权限感知全文搜索 (接后端 API) ✅
│           │   ├── workspace.ts           # 导出/导入工作区 JSON (接后端 API) ✅
│           │   ├── find-replace.ts        # CM6 搜索面板辅助
│           │   ├── file-ops.ts            # openTypstFile/saveTypstFile/exportPdf/exportSvg
│           │   ├── typst-snippets.ts      # 30+ Typst slash 命令片段
│           │   ├── api/                   # ── Rust 后端 HTTP 客户端 ──
│           │   │   ├── client.ts          # fetch 封装 (JWT Bearer + access_code)
│           │   │   ├── kb-api.ts          # KB/文档/版本/标签/搜索/分享 API
│           │   │   ├── auth-api.ts        # 注册/登录/me API ✅
│           │   │   └── types.ts           # 后端对应 TS 类型
│           │   └── plugins/               # ── 内置插件 ──
│           │       ├── word-count-pro.ts  # 字数统计 Pro (onCompile 钩子)
│           │       └── auto-outline.ts    # 自动大纲 (onSave 钩子)
│           └── typst/
│               └── main.typ.ts            # 默认欢迎文档 (TS 导出, 注入虚拟 FS /main.typ)
├── server/                                # Rust HTTP 后端 (tokio + hyper, Web/Tauri 共用)
│   ├── Cargo.toml                         # tokio + hyper + serde + jsonwebtoken + sha2
│   ├── README.md                          # 后端文档 + API 表 + 打包流程
│   └── src/
│       ├── main.rs                        # tokio main + hyper server (端口 7480)
│       ├── handlers.rs                    # 手写路由 + 所有 API 端点
│       ├── store.rs                       # JSON 文件存储 (workspace/users/versions/...)
│       ├── auth.rs                        # JWT 签发/验证 + 权限校验 (4 级可见性 + 角色)
│       └── models.rs                      # Rust struct 镜像前端类型
├── typst-pkg/                              # 自研 Typst 库 (有独立 typst.toml)
│   ├── typst.toml                         # 包清单: name="viztyp" version="0.1.0" compiler="0.14.0"
│   └── src/lib.typ                        # 库入口 (version + get-version)
├── src-tauri/                             # Tauri v2 桌面外壳 (sidecar 自动启动后端)
│   ├── Cargo.toml                         # tauri + dialog/fs/shell/log 插件
│   ├── tauri.conf.json                    # CSP + externalBin (sidecar) + COOP/COEP notes
│   ├── capabilities/default.json          # core/dialog/fs/shell 权限
│   ├── COOP_COEP_NOTES.md                 # 跨源隔离处理说明
│   └── src/{lib.rs, main.rs}             # Tauri 入口 (sidecar 启动 + RunEvent::Exit 清理)
├── scripts/
│   └── build-sidecar.sh                   # 构建 server + 带 target-triple 后缀复制
├── package.json                           # 根级 (Tauri CLI + server/frontend 脚本)
├── README.md / README.zh.md               # 双语文档对
└── AGENTS.md                              # 本文件

数据流 / Data Flow

编辑器数据流 (核心) / Editor data flow (core)

.typ 源码 → CodeMirror 编辑器 → (onInput 回调) → Tab 状态更新
         → typst.ts 编译器 (WASM) → Uint8Array artifact → 渲染器 (WASM) → SVG

源码被添加到虚拟文件系统 (/main.typ),不是真实磁盘路径。 Source is added to a virtual filesystem (/main.typ), not the real disk.

知识库数据流 (目标) / KB data flow (target)

Workspace → KnowledgeBase → Document (.typ 文件)
                               │
                    ┌──────────┼──────────┐
                    ▼          ▼          ▼
              CodeMirror   typst.ts   refs.ts
              (编辑)      (编译→SVG)  (依赖树→TOC)
                    │          │          │
                    └──────────┼──────────┘
                               ▼
                    DocTree (TOC) + Outline + DependencyGraph
                               │
                    ┌──────────┼──────────┐
                    ▼          ▼          ▼
              Preview(SVG)  Search     Version History

状态管理 / State Management

项目使用 Svelte 5 runes 模式,不使用 stores。

全局状态文件 / Global state files

文件 / File 用途 / Purpose 存储 / Storage
theme.svelte.ts 主题模式 (light/dark/system) localStorage viztyp:theme
settings.svelte.ts 编辑器/预览设置 localStorage viztyp:settings
snippets.svelte.ts CSS/JS 片段管理 (CSS 动态注入) localStorage viztyp:snippets
kb-store.svelte.ts 知识库状态 (Workspace/KB/Doc, 接后端) 后端 API (server/)
auth.svelte.ts 认证状态 (JWT, login/register/logout) localStorage viztyp:token
collab.svelte.ts 协作状态 (presence 10s 轮询) 后端 API
plugin-loader.svelte.ts 插件启用状态 localStorage viztyp:plugins-enabled

App.svelte 核心状态 / Core state

tabs: Tab[]               // 所有打开的标签页
activeId: string           // 当前活跃标签 ID
showLeftDock: boolean      // 左 dock 可见性
showRightDock: boolean     // 右 dock 可见性
dockTab: DockTab           // 右 dock 活跃 tab (outline/diagnostics/deps/history/bookmarks)
cursor: CursorInfo         // 光标位置 {line, col, selectionLength}
bookmarks: number[]        // 书签行号列表
splitPercent: number       // 编辑器/预览分栏比例 (15-85)
leftDockView: 'tabs'|'kb'  // 左 dock 视图切换 (已打开 Tab | 知识库 KB 树)
diagnostics: string[]      // typst.ts 编译诊断
// 模态可见性 / Modal visibility:
showCommandPalette, showSettings, showGlobalSearch, showTagEditor,
showPluginManager, showCollaborators, showSnippets: boolean
// 通过 kb-store/auth/collab 模块管理:
// workspace, activeKbId, versions, docTags, currentUser, onlineCount

编辑器回调注册模式 / Editor callback registration pattern

Editor.svelte 使用注册回调模式与父组件通信:

  • onInput(value) — 文档变更
  • onCursorChange(info) — 光标移动
  • registerScroll(fn) — 父组件注册跳转函数
  • registerFold(fn) — 父组件注册折叠函数
<Editor
  content={activeTab.content}
  onInput={handleContentChange}
  onCursorChange={(info) => cursor = info}
  {registerScroll}
  {registerFold}
/>

项目初始化 / Project Initialization

从零创建项目的脚手架步骤 / Scaffolding steps to create the project from scratch

1. 创建 Monorepo 结构 / Create Monorepo Structure

mkdir viztyp && cd viztyp
git init

# 根级 package.json — 仅 Tauri CLI / Root package.json — Tauri CLI only
yarn init -y
yarn add -D @tauri-apps/cli@^2

2. 创建前端 / Create Frontend (Svelte 5 + Vite)

mkdir -p packages/frontend
cd packages/frontend

# Vite + Svelte 5 + TypeScript / Scaffold with Vite
yarn create vite . --template svelte-ts

# 安装核心依赖 / Install core dependencies
yarn add @myriaddreamin/typst.ts@0.7.0 \
         @myriaddreamin/typst.svelte@0.7.0 \
         @myriaddreamin/typst-ts-renderer@0.7.0 \
         @myriaddreamin/typst-ts-web-compiler@0.7.0

yarn add @codemirror/view @codemirror/state @codemirror/commands \
         @codemirror/language @codemirror/autocomplete @codemirror/search \
         @codemirror/language-data @codemirror/basic-setup @lezer/highlight

yarn add -D @tsconfig/svelte svelte-check

3. 初始化 Tauri / Initialize Tauri

cd ../..  # 回到根目录 / Back to root
yarn tauri init
# 配置 / Configure:
# - frontend dev path: packages/frontend
# - frontend build path: packages/frontend/dist
# - dev server URL: http://localhost:5173

4. 关键配置文件 / Key Configuration Files

packages/frontend/vite.config.ts

import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
  plugins: [svelte()],
  server: {
    port: 5173,
    strictPort: true,             // 与 Tauri 约定一致 / Match Tauri convention
    headers: {
      'Cross-Origin-Opener-Policy': 'same-origin',
      'Cross-Origin-Embedder-Policy': 'require-corp',
    },
  },
  optimizeDeps: {
    exclude: ['@myriaddreamin/typst-ts-web-compiler', '@myriaddreamin/typst-ts-renderer'],
  },
  worker: {
    format: 'es',
  },
});

src-tauri/tauri.conf.json (关键片段 / Key excerpts)

{
  "build": {
    "frontendDist": "../packages/frontend/dist",
    "devUrl": "http://localhost:5173"
  },
  "app": {
    "security": {
      "csp": "script-src 'self' 'wasm-unsafe-eval'",
      "headers": {
        "Cross-Origin-Opener-Policy": "same-origin",
        "Cross-Origin-Embedder-Policy": "require-corp"
      }
    }
  }
}

typst-pkg/typst.toml

name = "viztyp"
version = "0.1.0"
compiler = "0.14.0"
entrypoint = "src/lib.typ"

功能清单 / Feature Checklist

📝 文档编辑

  • 项目脚手架 (Vite + Svelte 5 + Tauri)
  • typst.ts WASM 初始化 + 字体加载
  • CodeMirror 6 编辑器 + 思源主题
  • 实时 SVG 预览 (debounced)
  • 多 Tab 编辑
  • 文件 I/O (打开/保存/导出 PDF/SVG)
  • 查找替换 (Ctrl+H)
  • 可拖拽编辑器/预览分栏

📚 知识库管理

  • Workspace/KB/Document/TOCNode 类型定义
  • 知识库状态管理 (接 Rust 后端)
  • 知识库树 (KB 列表 → 文档树两级展开)
  • Typst #include 树解析 → TOC 构建 (借鉴语雀解耦模式)
  • 草稿/发布分离 (.typ.draft sidecar)
  • 版本历史 (快照 + 恢复, MrDoc 式完整快照)
  • 标签系统 (文档级标签)
  • 文档模板 (未实现, 优先级低)

🔍 搜索与发现

  • 大纲解析 (#heading) + 跳转
  • 依赖图可视化 (DependencyGraph.svelte, 手写 SVG)
  • 编译诊断 (typst.ts)
  • 权限感知全文搜索 (预过滤可见 KB)
  • 全局搜索 (Ctrl+Shift+F, KB/Tabs 双模式)
  • 文档分享令牌 (DocShare)

👥 协作与权限

  • 用户认证 (JWT + SHA-256 密码哈希)
  • 权限系统 (4 级可见性 + 协作者角色)
  • KB 协作者管理 (reader/writer/admin)
  • 协作状态 (presence 轮询)

🔌 系统扩展

  • IDE 布局 (ActivityBar/LeftDock/RightDock/StatusBar)
  • 命令面板 (Ctrl+K)
  • 插件系统 (内置 TS 插件 + 钩子体系: onCompile/onSave/onPublish/onRender)
  • CSS/JS 片段管理
  • 工作区导出/导入 (JSON 含文档内容)
  • 主题与设置 (light/dark/system + 编辑器设置)
  • Tauri sidecar 自动启动/清理

实现状态: 除"文档模板"外全部功能已实现并通过验证 (svelte-check 0/0 + cargo build 0 warnings + vite build 通过)。


CSS 变量系统 / CSS Variable System

所有颜色/尺寸/字体通过 --viztyp-* CSS 变量管理,定义在 app.css。 All colors/sizes/fonts managed via --viztyp-* CSS variables, defined in app.css.

思源色板 (目标值, 从思源源码提取) / SiYuan Palette (target values from SiYuan source)

/* 暗色 / Dark */
--viztyp-bg-primary: #1e1e1e;      /* 编辑器背景 / Editor background */
--viztyp-bg-secondary: #262626;    /* 面板/工具栏 / Panels/toolbars */
--viztyp-bg-activity: #1e1e1e;     /* ActivityBar */
--viztyp-border-primary: #363636;  /* 边框, 0.5px 发丝线 / Borders, 0.5px hairline */
--viztyp-accent: #3573f0;          /* 强调蓝 / Accent blue */
--viztyp-text-primary: #dadada;    /* 主文字 / Primary text */
--viztyp-text-secondary: #9aa0a6;  /* 次文字 / Secondary text */

/* 尺寸 / Sizing */
--viztyp-radius: 6px;              /* 标准圆角 / Standard radius */
--viztyp-radius-large: 12px;       /* 大圆角 / Large radius */
--viztyp-activitybar-width: 42px;
--viztyp-tab-height: 42px;
--viztyp-toolbar-height: 32px;
--viztyp-statusbar-height: 32px;

/* 动画 / Animation */
--viztyp-transition: 0.2s cubic-bezier(0, 0, 0.2, 1);

思源交互设计规范 / SiYuan Interaction Design Specs

Dock 活跃态: 实心蓝药丸 (#3573f0 背景 + 白色图标), 非左边竖条
Tab 活跃态: 3px 蓝色下划线
背景分层: background #1e1e1e vs surface #262626 (两色分层)
边框: #363636, 0.5px 发丝线 (不是 1px)

Typst.ts 集成关键约定 / typst.ts Integration Rules

⚠️ 版本锁定 / Version Pinning

所有 @myriaddreamin/*必须锁定 0.7.0。混用版本会导致静默失败。 All @myriaddreamin/* packages MUST be pinned to 0.7.0. Mixing causes silent failures.

"@myriaddreamin/typst-ts-renderer": "0.7.0",
"@myriaddreamin/typst-ts-web-compiler": "0.7.0",
"@myriaddreamin/typst.svelte": "0.7.0",
"@myriaddreamin/typst.ts": "0.7.0"

WASM 资源加载 (必须用 Vite ?url) / WASM loading (MUST use Vite ?url)

import compilerWasm from '@myriaddreamin/typst-ts-web-compiler/pkg/typst_ts_web_compiler_bg.wasm?url';
import rendererWasm from '@myriaddreamin/typst-ts-renderer/pkg/typst_ts_renderer_bg.wasm?url';

硬编码路径在 Tauri 生产构建中会失效 / Hardcoded paths break in Tauri production builds.

初始化守卫 / Init Guard

setCompilerInitOptions / setRendererInitOptions 必须只调用一次,用模块级布尔标志防止 HMR 重复初始化。 Must be called exactly once. Guard with module-level boolean flag.

⚠️ 字体不内置 / Fonts Not Bundled

typst.ts 不包含字体。必须通过 loadFonts([], { assets: ['text', 'cjk'] }) 显式加载 CJK 字体。 typst.ts does NOT bundle fonts. Load CJK explicitly via loadFonts([], { assets: ['text', 'cjk'] }).


Tauri 桌面关键约定 / Tauri Desktop Rules

⚠️ COOP/COEP Headers (线程化 WASM 必须)

{
  "app": {
    "security": {
      "headers": {
        "Cross-Origin-Opener-Policy": "same-origin",
        "Cross-Origin-Embedder-Policy": "require-corp"
      }
    }
  }
}

Vite dev server 也需镜像这两个 header (已在 vite.config.ts 配置)。 Vite dev server must mirror these headers too (already configured in vite.config.ts).

CSP 必须允许 WASM / CSP Must Allow WASM

script-src 'self' 'wasm-unsafe-eval'

CodeMirror 6 约定 / CodeMirror 6 Conventions

自定义主题 / Custom Theme

编辑器使用 cm-theme.ts 中定义的 siyuanFullTheme,不使用 @codemirror/theme-one-dark。 Editor uses siyuanFullTheme from cm-theme.ts, does NOT use @codemirror/theme-one-dark.

⚠️ HighlightStyle 标签陷阱 / HighlightStyle Tag Pitfall

@lezer/highlighttags 对象中,t.functionName 不存在(不是直接属性)。会导致 TypeError: Cannot read properties of undefined (reading 'id')。 The tags object from @lezer/highlight does NOT have t.functionName (not a direct property). Causes TypeError: Cannot read properties of undefined (reading 'id').

安全的标签 / Safe tags: t.comment, t.keyword, t.string, t.number, t.variableName, t.typeName, t.operator, t.meta, t.invalid.

嵌套标签修饰器也不安全: t.function(t.variableName) 在当前版本可能未定义。 Nested tag modifiers also unsafe: t.function(t.variableName) may be undefined in current version.


键盘快捷键 / Keyboard Shortcuts

快捷键 / Shortcut 动作 / Action
Ctrl+K 命令面板 / Command palette
Ctrl+S 保存 / Save
Ctrl+N 新建标签 / New tab
Ctrl+O 打开文件 / Open file
Ctrl+W 关闭标签 / Close tab
Ctrl+J 切换主题 / Toggle theme
Ctrl+H 查找替换 / Find & replace
Ctrl+B 切换左 dock / Toggle left dock
Ctrl+, 设置 / Settings
Ctrl+Shift+F 全局搜索 / Global search
Ctrl+Shift+D 切换右 dock 到诊断 / Dock → diagnostics
Ctrl+Shift+B 切换书签 / Toggle bookmark
Alt+1 切换右 dock / Toggle right dock
Alt+G 依赖图 / Dependency graph
Alt+H 版本历史 / Version history
Alt+P 插件管理 / Plugin manager

开发命令 / Development Commands

# 根级 / Root
yarn install                                    # 安装 Tauri CLI

# 前端 / Frontend
cd packages/frontend && yarn install            # 安装前端依赖
cd packages/frontend && yarn dev                # Web 开发服务器 (Vite, port 5173)
cd packages/frontend && yarn build              # Web 生产构建
cd packages/frontend && npx svelte-check --tsconfig ./tsconfig.json  # 类型检查

# 桌面 / Desktop
yarn tauri dev                                  # 桌面开发 (Tauri + Vite)
yarn tauri build                                # 桌面生产构建 (安装包)

文档约定 / Documentation Convention ⚠️ 强制 / Mandatory

  • 双语并行:所有文档维护中英文两个版本,文件名成对出现。 All documentation is maintained in bilingual EN/ZH pairs.
    • README.md + README.zh.md
    • AGENTS.md (单文件双语 / single file bilingual)
  • 代码注释双语:源码中的注释使用中英文双语,格式为: Code comments are bilingual, formatted as:
    // 初始化 typst.ts 编译器 / Initialize typst.ts compiler
    
  • 同步更新规则:修改代码时,必须同步更新对应的文档(EN + ZH)。 When modifying code, you MUST update the corresponding docs (both EN and ZH).

常见陷阱 / Common Pitfalls

  1. Svelte 5 runes .svelte.ts 文件:状态管理文件必须用 .svelte.ts 后缀才能使用 $state/$derived 等 runes。 State management files MUST use .svelte.ts suffix to use $state/$derived runes.

  2. ViewUpdate 导入:必须从 @codemirror/view 导入,umbrella 包 codemirror 不重新导出它。 Must import from @codemirror/view, NOT from umbrella codemirror.

  3. Uint8Array → Blob:TypeScript 6 严格类型下需用 pdfData.buffer as ArrayBuffer。 Under TS6 strict mode, use pdfData.buffer as ArrayBuffer.

  4. Vite 端口锁定:Vite dev server 锁定 port 5173 (strictPort: true),与 Tauri 约定一致。 Vite dev server is locked to port 5173 (strictPort: true), matching Tauri convention.

  5. Vite dev server 后台运行:用 nohup ... &setsid bash -c '...' </dev/null 确保进程不被 shell 超时杀死。 Use nohup or setsid with </dev/null to keep dev server alive after shell timeout.

  6. TOC 与内容解耦 (借鉴语雀):不要在文档内容中硬编码目录结构,应维护独立的 TOC 树。 Following Yuque: don't hardcode TOC structure in document content; maintain a separate TOC tree.

  7. 权限感知搜索 (借鉴 MrDoc):搜索前必须预过滤用户可见的知识库 ID 列表。 Following MrDoc: always pre-filter visible KB IDs before executing search queries.


Agent 工作检查清单 / Agent Checklist

修改代码时必须 / When modifying code, you MUST:

  • 同步更新 README.mdREADME.zh.md / Sync both READMEs
  • 双语注释保持一致 / Keep bilingual comments consistent
  • 如果改了 typst.ts 相关代码,检查 @myriaddreamin/* 版本是否一致 (0.7.0) / Check version sync
  • 如果改了 WASM/渲染逻辑,验证 Web 和 Tauri 两个目标都正常 / Verify both targets
  • 如果新增 Typst 库 API,更新 typst.toml 版本号 / Bump typst.toml version
  • 如果改了 CodeMirror 主题/高亮,验证 @lezer/highlight tags 是否存在 / Validate tag existence
  • 如果改了布局/CSS,验证 --viztyp-* 变量在 light + dark 都正常 / Verify both themes
  • 如果新增知识管理模块,确保 TOC 与内容解耦 (语雀模式) / Keep TOC decoupled from content
  • 如果新增权限/搜索功能,确保权限预过滤 / Ensure permission pre-filtering
  • 运行 svelte-check 确保 0 errors / Run svelte-check for 0 errors