# 无框架解析

不创建阅读组件，直接把 Markdown 解析为文本与语法树。

如果只需要分析 Markdown 内容，或给自己的渲染器提供语法树，可以直接使用 `@quirekit/incremark-core`。这个入口不导入 Vue/UI，也不创建可编辑视图；目前仍通过 MSFE 依赖 CodeMirror 模块。

## 1. 解析一份完整文本

文本已经接收完毕时，调用 `parseMarkdown()`：

```ts [解析完整文本]
import { parseMarkdown } from '@quirekit/incremark-core'

const state = parseMarkdown('# Hello')
const text = state.doc.toString()
```

`state` 是 CodeMirror 的只读 `EditorState`，里面包含文本、语法树及扩展维护的语义信息；它不是 HTML，也不是 mdast/hast。上面的 `text` 仍是 `# Hello`。保存时保留原始 Markdown，不要序列化 `EditorState`。

## 2. 接收陆续到来的文本

持续收到新片段时，保留同一个 `MarkdownStream`，把每个新片段交给 `append()`：

```ts [追加一个片段]
import { MarkdownStream } from '@quirekit/incremark-core'

const stream = new MarkdownStream()
stream.append('# Hello')
const complete = stream.advance(4)
const snapshot = stream.state
```

`append()` 接收新增加的部分；如果应用已经累计了完整文本，改用 `stream.update(全文)`。`advance(4)` 给解析器约 4 毫秒的额外预算，返回 `true` 表示当前文本的语法与引用分组已完成，返回 `false` 时由应用安排下一次调用。

类本身没有定时器。不要用同步循环一直等待 `true`，否则会阻塞界面。预算是协作式提示，不保证所有处理严格在 4 毫秒内结束；后续引用检查和界面渲染也需要时间。`snapshot` 可以先读取，但尚未完成时不应把它当作最终解析结果。

## 3. 读取语法树

从完成的状态中取得 Lezer 语法树：

```ts [读取语法结构]
import { syntaxTree } from '@quirekit/cm-language'

const tree = syntaxTree(state)
const description = tree.toString()
```

对于 `# Hello`，紧凑描述是 `Document(ATXHeading1(HeaderMark))`：整个文档里有一个一级标题及其 `#` 标记。自己的遍历逻辑可以通过树的 cursor、firstChild、nextSibling 读取节点和 UTF-16 范围。

`state.doc` 使用规范化换行。链接和脚注等跨块关系由扩展维护，不能仅凭某个源码前缀推断最终链接目标。树描述适合调试，不是存档格式。

## 完整函数参考

`recipes/snapshot.ts` 将第一步和第三步封装成 `inspectMarkdown(source)`，返回状态、文本和树描述。需要在自己的分析工具中复用时，可查阅这个单文件函数：

### recipes/snapshot.ts

```ts
import { parseMarkdown } from "@quirekit/incremark-core";
import { syntaxTree } from "@quirekit/cm-language";

/**
 * Parse once without mounting an editor or creating Vue components.
 * @param source - Exact Markdown supplied by the host.
 * @returns The immutable snapshot, canonical text and a compact syntax-tree description.
 */
export function inspectMarkdown(source: string) {
  const state = parseMarkdown(source);
  return { state, text: state.doc.toString(), syntax: syntaxTree(state).toString() };
}

```
