# 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 点敏捷损伤",台阶坍塌,陷阱 ``` ### 示例 3:NPC 名录 ```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 工具生成内容时参考