初始化项目版本

This commit is contained in:
Axhub Make
2026-07-29 16:04:39 +08:00
commit 4305a1082b
2629 changed files with 760590 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
# 画布读写能力参考
面向使用 Skill 的 Agent优先读写本地 `.excalidraw` 文件。用户指定画布名或画布链接时,直接定位本地画布文件;不要使用 `axhub-make canvas` CLI。
## 快速判断
| 目标 | 做法 |
|------|----------|
| 读取画布元素、批注、节点信息 | 直接读 `.excalidraw` |
| 修改画布内容 | 直接改 `.excalidraw` |
| 从用户给的画布链接定位元素 | 从链接提取画布名和元素 ID再读文件 |
| 获取画布截图 | 优先使用已有 `canvas-assets` 截图;需要当前浏览器画布时用全局截图 API |
## 文件位置
常见路径:
```text
src/prototypes/<prototype-name>/canvas.excalidraw
src/prototypes/<prototype-name>/canvas-assets/embed-<elementId>.png
```
`.excalidraw` 是 JSON。主要关注
- `elements`:所有画布元素。
- `files`:嵌入图片数据或图片元信息。
- `appState.gridSize`:整理/对齐时参考。
## 读取画布
读取过程以本地 JSON 为准。
最常用字段:
| 字段 | 用途 |
|------|------|
| `id` | 元素唯一标识,链接定位和截图文件名会用到 |
| `type` | 元素类型,如 `text``image``embeddable``arrow` |
| `x` / `y` / `width` / `height` | 位置和尺寸 |
| `isDeleted` | 为 true 时跳过 |
| `link` | 嵌入节点链接 |
| `customData` | 批注、标题、截图地址等 Axhub 扩展信息 |
| `fileId` | 图片元素对应的 `files[fileId]` |
识别常见节点:
| 类型 | 判断方式 |
|------|----------|
| 原型节点 | `type == "embeddable"``customData.resourceType == "prototype"`,或 `link`/`previewUrl` 指向原型 |
| 文档节点 | `type == "embeddable"``customData.type == "axhub-doc"``customData.resourceType == "doc"` |
| 主题节点 | `type == "embeddable"``customData.resourceType == "theme"``customData.type == "axhub-theme"` |
| Drawio 节点 | `type == "image"``customData.type == "axhub-drawio"` |
| 图片元素 | `type == "image"` |
| 批注元素 | `customData.annotation` 有值 |
Axhub 节点字段见 `axhub-nodes.md`
## CLI
没有画布专用 CLI。读取元素、节点和批注时仍以 `.excalidraw` 文件为准;需要截图时,优先使用已有 `canvas-assets` 截图或浏览器页面能力。
## 浏览器截图 API
Excalidraw 官方暴露的是导出工具方法,例如 `exportToBlob``exportToCanvas``exportToSvg`不是当前画布实例的一键截图命令。Axhub 在浏览器里的当前画布实例上封装了全局截图 API
```js
await window.__AXHUB_EXCALIDRAW_CAPTURE__.captureCanvas()
await window.__AXHUB_EXCALIDRAW_CAPTURE__.captureElement('<elementId>')
```
两个方法都返回:
```ts
{
blob: Blob
dataUrl: string
width?: number
height?: number
elementIds: string[]
}
```
可选参数:
```ts
{
exportBackground?: boolean
exportPadding?: number
maxWidthOrHeight?: number
mimeType?: string
quality?: number
width?: number
height?: number
}
```
默认导出 PNG、带背景、16px padding。`captureCanvas()` 导出当前画布所有未删除元素;`captureElement(elementId)` 只导出指定未删除元素。该能力只在画布页面打开并完成初始化后可用。
## 从链接定位
用户可能给一个带节点 ID 的画布链接。处理步骤:
1. 从 URL 中提取画布名和元素 ID。
2. 找到对应 `.excalidraw` 文件。
3.`elements` 中找同 ID 元素。
4. 如果是原型节点,预览截图通常在 `canvas-assets/embed-<elementId>.png`
5. 如果是图片元素,按 `fileId``files[fileId]`
6. 如果是嵌入节点,结合 `customData.resourceType``customData.previewUrl``customData.screenshotUrl` 判断资源来源。
## 写入画布
直接修改 `.excalidraw``elements` 数组。
### 添加元素
追加到 `elements`。必须有唯一 `id`,推荐沿用现有格式:`<timestamp>-<random>`
### 修改元素
更新目标字段后,同时更新:
- `version` 加 1
- `versionNonce` 换成新的随机整数
- `updated` 设为当前毫秒时间戳
### 删除元素
默认直接从 `elements` 中移除。不要为了删除而设置 `isDeleted: true`,这会让画布文件持续膨胀。
如果遇到历史遗留的 `isDeleted: true` 元素,读取时跳过;整理画布时可以一并移除。
### 关系检查
修改连接、容器、分组时检查引用是否仍然存在:
- `boundElements`
- `containerId`
- `startBinding` / `endBinding`
- `groupIds`
## 热更新
保存 `.excalidraw` 后,打开中的画布会通过热更新同步。完成画布写入时,交付说明里标明画布文件路径和改动内容。