# 开发和项目说明 ## 快速开始 ```bash # 安装依赖 npm install # 开发模式(同时启动 CLI 内容服务器 :3000 与 Web 前端 :5173) npm run dev # 也可分别启动 npm run dev:cli npm run dev:web # 构建(Web) npm run build # 预览构建结果 npm run preview # CLI 开发模式 npm run cli:dev # CLI 构建 npm run cli:build # 运行测试 npm test ``` ## 项目结构 ``` tttk/ ├── src/ │ ├── cli/ # CLI 工具源码 │ │ ├── commands/ # 命令实现 (serve, check, compile) │ │ ├── validate/ # tttk check 校验器(扫描、规则、诊断) │ │ ├── content-registry.ts # 内容注册表(CLI / 前端共享) │ │ ├── content-index.ts # 目录文件递归读取 │ │ ├── index.ts # CLI 入口 │ │ └── types.ts # 类型定义 │ ├── components/ # TTRPG 组件 │ │ ├── md-dice.tsx # 骰子组件 │ │ ├── md-table.tsx # 表格组件 │ │ ├── md-deck/ # 卡牌组件 │ │ ├── md-pins.tsx # 标记组件 │ │ ├── md-commander/ # 命令追踪器 │ │ ├── md-yarn-spinner.tsx # 叙事线组件 │ │ ├── Article.tsx # 文章组件 │ │ ├── Sidebar.tsx # 侧边栏 │ │ ├── FileTree.tsx # 文件树 │ │ └── utils/ # 工具函数 │ ├── markdown/ # Markdown 解析器 │ │ ├── index.ts # marked 配置 │ │ └── mermaid.ts # mermaid 支持 │ ├── data-loader/ # 数据加载器 │ ├── plotcutter/ # 剧情切割工具 │ ├── yarn-spinner/ # 叙事线解析 │ ├── App.tsx # 主应用 │ ├── main.tsx # 入口文件 │ ├── styles.css # 样式 │ ├── index.html # HTML 模板 │ └── global.d.ts # 类型声明 ├── .agents/ │ └── skills/ │ └── tttk-authoring/ # 随项目维护的 agent skill(见下文) ├── bin/ │ └── cli/ # CLI 二进制文件 ├── content/ # 示例内容 ├── docs/ # 文档 ├── package.json ├── tsconfig.json ├── tsconfig.cli.json ├── rsbuild.config.ts └── jest.config.js ``` ## Agent skills `tttk-authoring` skill 由本项目维护,源码位于 `.agents/skills/tttk-authoring/`。要让 agent 加载它,把全局 skill 目录 链接到仓库内的副本: ```bash # Windows(无需管理员权限的目录联接) cmd //c mklink /J %USERPROFILE%\.agents\skills\tttk-authoring "%CD%\.agents\skills\tttk-authoring" # macOS / Linux ln -s "$PWD/.agents/skills/tttk-authoring" ~/.agents/skills/tttk-authoring ``` `reference.md` 由 `known.ts` 生成,不要手改: ```bash npm run gen:skill-reference ``` 其余文件(`SKILL.md`、`yaml-tag.md`、`csv.md`、`layout.md`、`markdown.md`) 为手写内容。 ## 技术栈 | 类别 | 技术 | |------|------| | 前端框架 | Solid.js 1.9+ | | 构建工具 | Rsbuild | | 样式 | Tailwind CSS 4 + @tailwindcss/typography | | Markdown | marked + marked-directive + marked-alert + marked-gfm-heading-id | | 图表 | mermaid | | 测试 | Jest | | CLI | commander + chokidar | ## 开发规范 ### Solid.js 最佳实践 - **优先使用 `createEffect` 和 `createMemo`** 实现响应式 - 在 JSX 中直接引用 `props` 保持响应式 - 避免滥用 `onMount` + `createSignal` ```tsx // ✅ 推荐 const doubled = createMemo(() => count() * 2); createEffect(() => console.log(count())); // ❌ 避免 onMount(() => { const [value, setValue] = createSignal(0); }); ``` ### 组件开发 - **不使用 Shadow DOM**:使用 `noShadowDOM()` - **继承 Tailwind CSS 样式系统** - 使用 `customElement` 注册自定义元素 ```tsx import { customElement, noShadowDOM } from "solid-element"; customElement("md-dice", { key: "" }, (props, { element }) => { noShadowDOM(); // 组件逻辑 }); ``` ### 类型检查 开发完成后检查类型错误: ```bash npx tsc --noEmit ``` ### 代码风格 - 使用 TypeScript 严格模式 - 遵循 ESLint 配置(如有) - 使用 2 空格缩进 ## 添加新组件 ### 1. 创建组件文件 ```tsx // src/components/md-new-component.tsx import { customElement, noShadowDOM } from "solid-element"; import { createSignal } from "solid-js"; export interface NewComponentProps { prop1?: string; } customElement("md-new-component", { prop1: "" }, (props, { element }) => { noShadowDOM(); const [state, setState] = createSignal(""); return (
{/* 组件内容 */}
); }); ``` ### 2. 注册组件 ```tsx // src/components/index.ts import './md-new-component'; ``` ### 3. 导出类型(可选) ```tsx // src/components/index.ts export type { NewComponentProps } from './md-new-component'; ``` ## 构建配置 ### Rsbuild 配置 ```ts // rsbuild.config.ts import { defineConfig } from '@rsbuild/core'; import { pluginBabel } from '@rsbuild/plugin-babel'; import { pluginSolid } from '@rsbuild/plugin-solid'; import tailwindcss from '@tailwindcss/postcss'; export default defineConfig({ plugins: [pluginBabel(), pluginSolid()], tools: { postcss: { postcssOptions: { plugins: [tailwindcss()], }, }, }, html: { template: './src/index.html', }, }); ``` ### TypeScript 配置 - `tsconfig.json` - 主项目配置(Web) - `tsconfig.cli.json` - CLI 工具配置(Node.js) ## 测试 ```bash # 运行所有测试 npm test # 运行特定测试文件 npm test -- src/components/md-dice.test.ts # 监听模式 npm test -- --watch ``` ## 调试 开发环境由两个进程组成,必须使用不同端口: - Web 前端:rsbuild 开发服务器,端口 **5173** - CLI 内容服务器:`tttk serve`,端口 **3000**(内容 API + Journal) rsbuild 会把 `/__CONTENT_INDEX.json`、`/__COMPLETIONS.json`、`/__CONTENT_REGISTRY.json`、`/content`、`/.ttrpg` 代理到 CLI 的 3000 端口,因此必须先启动 CLI,否则前端拿不到内容。 ### Web 开发 `npm run dev` 会同时启动两个进程;也可以分开运行: ```bash # 同时启动 CLI(3000)与 Web(5173) npm run dev # 或分别启动 npm run dev:cli # CLI 内容服务器,占用 3000 npm run dev:web # Web 前端,占用 5173 # 访问 http://localhost:5173 ``` ### CLI 调试 CLI 通过 ts-node 运行,加上 `--inspect` 与 `--enable-source-maps` 后即可在编辑器中附加断点。 如需调试启动/扫描逻辑,用 `--inspect-brk` 在用户代码执行前暂停: ```bash node --inspect-brk --enable-source-maps --loader ts-node/esm ./src/cli/index.ts serve ./content # 或使用脚本(不带 --inspect-brk) npm run tttk:inspect -- serve ./content ``` 然后在 Zed / VS Code 中附加到 `localhost:9229`,或打开 `chrome://inspect`。 CLI 只监听内容目录(`.md`/`.csv`/`.yarn`/`.svg`)并重建内存中的注册表,**不会**热重载自身源码; 修改 `src/cli/**` 后需要重启进程。 ```bash # 或构建后运行 npm run cli:build node dist/cli/index.js serve ./content ``` ## 发布流程 1. 更新版本号 2. 运行测试和类型检查 3. 构建 Web 和 CLI 4. 发布到 npm ```bash npm run build npm run cli:build npm test npx tsc --noEmit npm publish ``` ## 常见问题 ### Windows 换行符 开发环境主要在 Windows 上,注意使用 CRLF 换行符。 ### 依赖安装失败 ```bash # 清理缓存 npm cache clean --force rm -rf node_modules package-lock.json npm install ``` ### 构建错误 ```bash # 检查类型 npx tsc --noEmit # 重新构建 npm run build ```