# 核心代码块 (Core Blocks)

> **"You don't know it until you model it."**

Typedown 重新定义了 Markdown 的 **代码块 (Code Blocks)**。

在标准 Markdown 中，代码块仅用于展示代码片段。而在 Typedown 中，代码块被提升为 **语义容器 (Semantic Containers)**。它们不再仅仅是“代码”，而是用于构建系统的四大支柱：

1. **类 (Class)**: 定义数据结构 (`model`)
2. **数据 (Data)**: 实例化具体对象 (`entity`)
3. **规范 (Spec)**: 定义逻辑校验规则 (`spec`)
4. **上下文 (Context)**: 构造运行环境 (`config`)

## 1. 块签名 (Block Signatures)

为了区分这些用途，Typedown 利用代码块的首行（Info String）作为 **块签名**。每种块类型都有其特定的语法格式：

| 容器用途   | 关键字   | 签名示例             | 语义作用                           |
| :--------- | :------- | :------------------- | :--------------------------------- |
| **Model**  | `model`  | `model:User`         | **定义**: 包裹一个 Pydantic Class  |
| **Entity** | `entity` | `entity User: alice` | **实例化**: 包裹一段 YAML Data     |
| **Spec**   | `spec`   | `spec:check_age`     | **校验**: 包裹一个 Pytest Function |
| **Config** | `config` | `config:python`      | **配置**: 包裹一段 Setup Script    |

> **命名约束**: 虽然语法各异，但所有签名中的标识符（Identifier）都严格**禁止包含斜杠 `/` 或空格**（Entity 语法分隔符除外）。推荐始终使用 **snake_case** 或 **PascalCase**。

## 2. 模型块 (`model`)

`model` 块允许直接在文档中使用 Pydantic 语法定义数据架构。这实现了“渐进式形式化”——从松散的文字描述逐步演进为严格的类型定义。

````markdown
```model:UserAccount
class UserAccount(BaseModel):
    name: str
    age: int = Field(..., ge=0)
    # 使用 Reference[T] 定义引用关系
    manager: Optional[Reference["UserAccount"]] = None
    friends: List[Reference["UserAccount"]] = []
```
````

- **运行环境**: 该块在一个预装了 `pydantic` 和 `typing` 的 Python 环境中执行。
- **作用域**: 此处定义的模型注册到文件的本地作用域。冒号后的 ID（如 `UserAccount`）作为该模型的主要标识符。
- **命名约束**: 为了确保解析器的高效性，Info String 中的 ID **必须**与代码块内部定义的 Pydantic 类名完全一致。详见 [03-标识符.md](03-标识符.md)。

## 3. 实体块 (`entity`)

`entity` 块是 Typedown 中声明“数据”的主要方式。我们采用 **System ID (L1)** 与 **Handle (L2)** 分离的策略。

````markdown
<!-- UserAccount 是类型引用，alice 是实例的 Handle -->

```entity UserAccount: users-alice-v1
# 1. 签名即身份 (Signature as Identity):
# ID 由 Header 自动注入，Body 中不再重复声明 id 字段

# 2. Body: 标准 YAML 格式
name: "Alice"
age: 30

# 3. 引用语法糖: 看起来像引用列表，编译器会自动解包
friends:
  - [[bob]]
  - [[charlie]]
```
````

- **语法**: `entity <Type>: <Identifier>`
- **标识符 (Identifier)**: 冒号后的 `<Identifier>` 是该代码块定义的 **System ID (L1)**。它可以采用多种风格，内核对此一视同仁：
  - **Name Style (简名)**: 如 `alice`。简洁直观，但在大型项目中需注意命名冲突。
  - **Slug Style (扁平路径)**: 如 `users-alice-v1`。推荐用于生产环境，包含明确的命名空间和版本信息。
- **主体 (Body)**: 采用 **Strict YAML** 格式定义数据内容。
- **约束**:
  - **Single Source of Truth**: 严禁在 Body 中定义 `id` 字段。实体的唯一标识由 **块签名** 独占定义。
  - **禁止嵌套列表**: 严禁在实体定义中使用二维数组 (List of Lists)。数据结构应当被封装为独立的 Model。

## 4. 配置块 (`config`)

`config` 块用于动态配置编译上下文，通常出现在 `config.td` 文件中。

````markdown
```config:python
import sys
# 注入路径
sys.path.append("./src")
```
````

- **执行时机**: 在“链接阶段”执行。
- **作用**: 导出 Python 符号供同级目录的 `model` 或 `spec` 使用。

## 5. 规范块 (`spec`)

`spec` 块包含测试逻辑。我们统一使用冒号语法来定义规范及其 ID。

````markdown
```spec:check_adult
# 声明：此测试自动应用于所有 UserAccount 类型的实体
@target(type="UserAccount")
def validate_age(subject: UserAccount):
    # 直接针对单体进行断言，subject 已经是解析好的实例
    assert subject.age >= 18, f"User {subject.name} applies underage"
```
````

- **语法**: `spec:<Details>`。`Details` 即为此规范的 **System ID**。
- **@target 装饰器**: 声明该逻辑适用的实体范围（支持按 Type 或 Tag 过滤）。
- **参数注入**: 运行时会自动找到符合条件的实体，并将其逐一注入 `subject` 参数执行测试。

## 6. 文件头 (Front Matter)

Typedown 文件支持标准的 YAML Front Matter，用于定义文件级元数据和快捷脚本。

```yaml
---
tags: [documentation, core]
# 定义本地快捷脚本
scripts:
  test: "td test --tag=core"
  lint: "td lint ."
---
```

- **Metadata**: `tags`, `author` 等元数据可被查询系统索引。
- **Scripts**: 定义可以在该上下文运行的快捷命令，通过 `td run <script_name>` 调用。
