ttrpg-tools/docs/csv.md

433 lines
9.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CSV 编写说明
TTRPG Tools 使用带有 YAML Front Matter 的 CSV 格式来定义卡牌/表格数据。这种格式支持在 CSV 文件头部定义元数据、字段配置和共享属性。
## 文件结构
```csv
---
# YAML Front Matter可选
fields:
- name: 字段名
description: 字段描述
deck:
size: 54x86
grid: 5x8
shared_prop: 共享属性值
---
# CSV 数据
label,body,field1,field2
1内容值 1值 2
```
---
## YAML Front Matter
Front Matter 是可选的,位于文件开头,使用 `---` 包裹的 YAML 格式内容。
### 基本结构
```yaml
---
fields:
- name: name
description: 卡牌名称
- name: effect
description: 效果描述
examples: ["造成 5d6 伤害", "恢复 2d4 生命值"]
deck:
size: 63x88
grid: 5x5
bleed: 1
padding: 2
custom_prop: 自定义属性
---
```
### Front Matter 属性
#### `fields` - 字段定义
定义 CSV 中各列的含义和配置。
```yaml
fields:
- name: name # 字段名称(英文,用于 CSV 列名)
description: 卡牌名称 # 字段描述
examples: # 示例值列表(可选)
- 火球术卷轴
- 治疗药水
dataType: word # 数据类型可选word/paragraph/number/symbol/symbol_list
function: identify # 字段功能可选identify/compare/flavor/rule
```
**数据类型说明:**
| 类型 | 说明 | 示例 |
|------|------|------|
| `word` | 词语 - 短文本 | "火球术"、"战士"、"传说" |
| `paragraph` | 文本段落 - 长描述 | "造成 5d6 点火焰伤害,范围内的所有生物进行敏捷豁免" |
| `number` | 数字 - 可比较的数值 | 3、5、10 |
| `symbol` | 单一符号 - 图标/标记 | 🔥、⚔️、🛡️ |
| `symbol_list` | 符号列表 - 多个图标/标记 | 🔥🔥🔥、⚔️🛡️💫 |
**字段功能说明:**
| 功能 | 说明 | 示例 |
|------|------|------|
| `identify` | 辨识 - 用于识别卡牌身份 | 名称、编号、唯一标识 |
| `compare` | 比较 - 用于游戏机制中的数值比较 | 费用、攻击力、防御力 |
| `flavor` | 游戏风味描述 - 提供背景故事/氛围 | 背景故事、引言、lore |
| `rule` | 规则确认 - 明确游戏规则相关的信息 | 效果文本、触发条件、限制 |
#### `deck` - 卡牌显示配置
用于 `:md-deck` 组件的默认配置。
```yaml
deck:
size: 63x88 # 卡牌尺寸mm格式 "宽 x 高"
grid: 5x5 # 网格布局,格式 "列 x 行"
bleed: 1 # 出血边距mm
padding: 2 # 内边距mm
shape: rectangle # 卡牌形状rectangle/circle/hex/diamond
layers: "name:1-2,14" # 图层配置(可选)
back_layers: "" # 背面图层配置(可选)
```
图层配置语法遵循`layer:1,1-5,8f8s`格式:
- `layer`:图层名称,多个图层用空格分隔
- `1,1-5,8`:网格范围,覆盖卡牌排版网格中的指定区域。
- `f8`字体大小使用8mm字体。可选。
- `s`图层朝向有nwse东西南北四种方向描述文字上侧的朝向默认为n北方。
#### 自定义属性
可以在 Front Matter 中定义任意自定义属性,这些属性会被自动应用到所有卡牌行。
```yaml
---
game_system: 龙与地下城 5e
author: DM_Name
version: 1.0
---
```
---
## CSV 数据部分
### 基本格式
```csv
label,body,field1,field2
1内容值 1值 2
```
### 必需列
#### `label`
每行的唯一标识,用于查找和修改卡牌。
- 可以是数字:`1`, `2`, `3`
- 可以是文本:`card_001`, `npc_villager`
- 支持分组前缀:`forest_1`, `dungeon_1`
#### `body`
卡牌的主要内容,支持 Markdown 格式。
```csv
label,body
1,"### 标题
**加粗文本**
- 列表项 1
- 列表项 2"
```
### 可选列
`label``body` 外,可以定义任意自定义列,列名在 Front Matter 的 `fields` 中定义。
```csv
label,body,name,type,cost,effect
1完整内容火球术法术3造成 5d6 火焰伤害
```
---
## 变量语法
`body` 列或 Front Matter 中,可以使用 `{{prop}}` 语法引用其他列的值或 Front Matter 中的属性。
### 引用同行其他列
```csv
label,body,adj,noun
1,"**{{adj}}** 的{{noun}}",高大,战士
2,"{{adj}}的{{noun}}",矮小,法师
```
渲染后:
- 第 1 行:**高大** 的战士
- 第 2 行:矮小的法师
### 引用 Front Matter 属性
```yaml
---
game_system: D&D 5e
author: DM_Name
---
```
```csv
label,body
1,"这是一个{{game_system}}冒险,由{{author}}创建"
```
渲染后:这是一个 D&D 5e 冒险,由 DM_Name 创建
### 随机引用remix 模式)
`:md-table` 组件中,可以使用 `remix` 属性启用随机引用:
```markdown
:md-table[./data.csv]{remix=true}
```
此时 `{{prop}}` 会从所有行中随机选择一行的值,而不是使用当前行的值。
---
## 分组支持
可以使用额外的列来对数据进行分组。
```csv
group,label,body
森林小径1狼群袭击
森林小径2荆棘陷阱
森林小径3迷路
塔楼楼梯1台阶坍塌
塔楼楼梯2落石
```
`:md-table` 组件中,可以使用 `group` 属性来筛选显示特定组的数据:
```markdown
:md-table[./encounters.csv]{group="森林小径"}
```
---
## 特殊字符处理
### 包含逗号的值
使用双引号包裹:
```csv
label,body
1,"Hello, world"
```
### 包含双引号的值
使用两个双引号转义:
```csv
label,body
1,"他说:""你好"""
```
### 包含换行的值
使用双引号包裹,直接写入换行:
```csv
label,body
1,"### 标题
这是第一段
这是第二段"
```
### 包含 `#` 注释
CSV 解析器会将 `#` 开头的行视为注释,但如果 `#` 在双引号内则正常处理:
```csv
label,body
1,"# 这不是注释"
# 这是真正的注释
```
---
## 完整示例
### 示例 1魔法物品卡牌组
```csv
---
fields:
- name: name
description: 物品名称
dataType: word
function: identify
- name: type
description: 物品类型
dataType: word
function: identify
examples: [武器,防具,饰品,消耗品]
- name: rarity
description: 稀有度
dataType: word
function: compare
examples: [普通,稀有,史诗,传说]
- name: cost
description: 价格
dataType: number
function: compare
- name: effect
description: 效果描述
dataType: paragraph
function: rule
deck:
size: 63x88
grid: 5x5
shape: rectangle
game_system: D&D 5e
---
label,body,name,type,rarity,cost,effect
1,"### 火球术卷轴
一张泛黄的羊皮纸,上面绘有火焰符文。",火球术卷轴消耗品稀有150,"投掷后对 20 尺内所有生物造成 8d6 火焰伤害(敏捷豁免减半)"
2,"### 治疗药水
红色液体在玻璃瓶中翻滚,散发着温暖的光芒。",治疗药水消耗品普通50,"饮用后恢复 2d4+2 点生命值"
3,"### +1 长剑
剑刃闪烁着微光,握柄包裹着精致的皮革。",+1 长剑武器稀有300,"攻击和伤害检定 +1"
```
### 示例 2随机遭遇表
```csv
---
fields:
- name: group
description: 遭遇地点分组
- name: title
description: 遭遇标题
- name: type
description: 遭遇类型
deck:
size: 54x86
grid: 4x6
---
group,label,body,title,type
森林小径1,"### 狼群袭击
三只灰狼从灌木丛中扑出。
**交互**战斗3 只巨狼)或逃脱(敏捷检定 3/2
**风险**:失败受到 d8 撕咬伤害",狼群袭击,战斗
森林小径2,"### 荆棘陷阱
带刺藤蔓缠住你的双腿。
**交互**:挣脱(力量检定 3/2
**风险**:失败受到 1 点体质损伤",荆棘陷阱,陷阱
森林小径3,"### 迷路
浓雾弥漫,你失去了方向。
**交互**:寻找路径(感知检定 3/2
**风险**:失败受到 1 点感知损伤",迷路,事件
塔楼楼梯1,"### 台阶坍塌
脚下的石阶突然碎裂。
**交互**:保持平衡(敏捷检定 3/1
**风险**:失败受到 1 点敏捷损伤",台阶坍塌,陷阱
```
### 示例 3NPC 名录
```csv
---
fields:
- name: name
description: NPC 名称
- name: role
description: 角色定位
- name: location
description: 出现地点
deck:
size: 54x86
grid: 4x6
---
label,body,name,role,location
1,"### 老妇人玛拉
**类型**:信息提供者/商人
**位置**:村庄入口
**出售**:草药、治疗药水
**情报**:知道关于森林的警告",老妇人玛拉,商人,村庄入口
2,"### 护卫队长塞里克
**类型**:任务发布者
**位置**:酒馆二楼
**任务**:调查废弃庄园
**秘密**:知道血契的真相",塞里克,任务发布者,酒馆
```
---
## 与组件集成
### `:md-deck` 组件
```markdown
:md-deck[./magic-items.csv]{size="63x88" grid="5x5" roll=true}
```
- `roll=true`:添加随机抽卡按钮
### `:md-table` 组件
```markdown
:md-table[./encounters.csv]{group="森林小径" remix=true}
```
- `group`:筛选特定组的数据
- `remix=true`:启用随机引用模式
---
## 最佳实践
1. **使用有意义的 label**:便于后续查找和修改
2. **在 Front Matter 中定义所有字段**:便于工具理解和处理
3. **使用 `{{prop}}` 变量**:减少重复内容,支持动态组合
4. **合理使用分组**:便于筛选和管理大量数据
5. **保持 body 的 Markdown 格式一致**:确保渲染效果统一
6. **为字段添加 `examples`**:帮助 AI 工具生成内容时参考