# 源码与组件 API

查询扩展如何读取语法、修改字段，以及组件可使用的动作。

## 字段 codec

`read` 从已确认的语法范围派生字段，`patch` 编码精确的源码修改。可以只安装语义而不提供视图。

### SourceDefinition

不依赖特定解析器的语义编解码器；渲染是可选能力，不负责持久化。

```ts
export interface SourceDefinition<Attrs extends object, Resource = unknown> {
    readonly nodes: readonly string[];
    readonly syntax?: InlineSyntax;
    readonly placement?: "replace" | "before";
    readonly showWhenActive?: boolean;
    readonly measureHeight?: boolean;
    readonly read: (document: SourceDocument, node: SourceNode) => Attrs | null;
    readonly source?: (document: SourceDocument, node: SourceNode) => string;
    readonly patch: (document: SourceDocument, node: SourceNode, patch: Partial<Attrs>) => SourceEdit | readonly SourceEdit[] | null;
    readonly load?: (attrs: Readonly<Attrs>, signal: AbortSignal) => MsfeNodeViewResource<Resource> | Promise<MsfeNodeViewResource<Resource>>;
    readonly renderer?: MsfeNodeViewRenderer;
}
```

**nodes** — 已确认的语法类型；提供 syntax 时使用对应的行内语法名称。

**syntax** — 此功能提供的可选简单语法声明。

**placement** — 替换单行源码，或在由源码管理的正文前放置不可编辑的控件。

**showWhenActive** — 选中源码时是否继续显示控件。

**measureHeight** — 在视口外保留已稳定替换视图的测量高度，包括错误回退；普通行内控件保持关闭。

**read** — 参数 document：权威源码。
参数 node：已确认的语法范围。
返回：从源码派生的语义字段，或回退结果。

**source** — 可选的有界源码指纹，必须覆盖所有可修改字段。

**patch** — 参数 document：权威源码。
参数 node：当前语法范围。
参数 patch：语义字段修改。
返回：精确的源码修改，或拒绝修改。

**load** — 可选的、可取消的资源加载器，由各类渲染器共享。

**renderer** — 原生渲染器；通过 addNodeView 提供组件渲染器时可省略。

## 文档与语法范围

范围使用 UTF-16 偏移，结束位置不包含在范围内。语法访问是派生查询，不代表另一份可持久化文档。

### SourceDocument

对已接受文档的只读访问，不依赖解析器和视图实现。

```ts
export interface SourceDocument extends SourceText {
    resolveReference(label: string): MarkdownReferenceResult;
}
```

**resolveReference** — 参数 label：不含方括号的原始 Markdown 引用标签。
返回：共享的引用语义，包含显式的部分解析状态。

**length** — 逻辑文本的 UTF-16 总长度。

**slice** — 参数 from：包含在范围内的起始偏移。
参数 to：不包含在范围内的结束偏移。
返回：指定范围内的精确源码。

**lineAt** — 参数 position：逻辑源码偏移。
返回：该位置所在的行。

### SourceNode

按需访问语法，不依赖特定解析器，也不分配另一份持久化 AST。

```ts
export interface SourceNode {
    readonly kind: string;
    readonly parentKind: string | null;
    readonly from: number;
    readonly to: number;
    parent(): SourceNode | null;
    child(kind: string): SourceNode | null;
    children(kind?: string): readonly SourceNode[];
}
```

**kind** — 由配置的源码适配器选定、已经确认的语法类型。

**parentKind** — 直接所属的语法类型，用于区分独立 token 和链接目标字段。

**from** — 源码起始位置，包含在范围内。

**to** — 源码结束位置，不包含在范围内。

**parent** — 返回：按需取得的已确认父语法，不分配另一份 AST。

**child** — 参数 kind：子语法类型。
返回：首个匹配的直接子节点。

**children** — 参数 kind：可选的语法类型；省略时按源码顺序遍历所有直接子节点。
返回：匹配的直接子节点。

## 节点组件

`attrs` 由源码派生。字段修改、删除和显露源码必须使用提供的受控动作；先前持有的 props 可能因文档变化失效。

### MsfeNodeViewProps

从源码派生的组件输入；所有动作都会先校验此快照，再修改源码。

```ts
export interface MsfeNodeViewProps<Attrs extends object = object, Resource = unknown> {
    readonly id: string;
    readonly attrs: Readonly<Attrs>;
    readonly readOnly: boolean;
    readonly status: "ready" | "loading" | "error";
    readonly resource: Resource | undefined;
    getRange(): MsfeSourceRange | null;
    updateAttributes(patch: Partial<Attrs>): MsfeResult;
    deleteNode(): MsfeResult;
    revealSource(): boolean;
}
```

**id** — 不受无关插入影响、可随位置映射保留的局部标识；不会作为文档标识序列化。

**attrs** — 由功能字段编解码器定义的不可变语义字段。

**readOnly** — 处于 locked 模式或编辑器只读时为 true。

**status** — 当前挂载视图持有的异步资源状态。

**resource** — 已加载的资源，不会存入 Markdown。

**getRange** — 返回：当前映射后的范围；源码已过期或视图已卸载时返回 null。

**updateAttributes** — 参数 patch：受支持的语义字段修改。
返回：对权威源码执行原子修改的结果。

**deleteNode** — 返回：沿用相同历史与只读规则的删除结果。

**revealSource** — 返回：是否成功显露当前源码并聚焦。

## 定义和解析需求

`defineSource` 创建可安装的源码协议；读取、写回、指纹和资源分别承担不同职责。不能用资源值代替持久字段。完整流程见 [节点教程](/extensions/custom-node)。

### defineSource

参数 definition：类型化源码协议。返回可安装的源码定义。

```ts
function defineSource<Attrs extends object, Resource = unknown>(definition: SourceDefinition<Attrs, Resource>): SourceSpec
```

语义查询返回 pending 时可以注册解析需求，等待已接受状态再重试。该入口不会同步扫描整篇文档。

### requestMarkdownParse

参数 state：尚未完整解析的已接受快照。记录解析需求，不会同步强制推进解析。

```ts
function requestMarkdownParse(state: EditorState): void
```

## 查询结果的处理

`editor.querySource(name, range?)` 返回 status 与 matches。每个 match 包含语义名、扩展类别 kind、字段、范围和 SourceNode；真实语法名称通过 node.kind 读取。范围参数使用 UTF-16 逻辑坐标。默认查询当前选区，不能将其当作一个全文件节点列表。

字符串工具 `decodeMarkdownString`、`decodeMarkdownDestination`、`encodeMarkdownField` 服务于不同的 Markdown 字段。保留用户原始表示时只编码被修改的字段，不对整篇文章统一格式化。位置与异步动作见 [命令 API](/api/commands)。
