diff --git a/README.md b/README.md index c0fe804..b0a48a7 100644 --- a/README.md +++ b/README.md @@ -1,138 +1,78 @@ -# LLM Log Viewer +# LLM Log Dashboard -> 将 Markdown 日志文件批量转换为精美静态 HTML 页面的 Node.js 构建工具。 - - - +一个将 LLM 日志 Markdown 文件批量聚合渲染为精美静态 HTML 页面的工具。 ## 特性 -| 功能 | 描述 | -|------|------| -| **批量转换** | 自动扫描 `llm_log/` 目录,读取所有 `.md` 文件并合并输出为单页 HTML | -| **目录导航** | 侧边栏自动提取各文档的标题层级(TOC),支持平滑滚动跳转 | -| **深色模式** | 一键切换亮/暗主题,自动记忆用户偏好(localStorage) | -| **代码高亮** | 基于 highlight.js 的多语言语法着色,支持 8 种主流语言 | -| **复制按钮** | 代码块悬停时显示 Copy 按钮,点击写入剪贴板 | -| **表格美化** | GFM 表格自定义样式:圆角边框、悬停高亮、响应式横向滚动 | -| **活跃追踪** | IntersectionObserver 实时高光当前阅读章节的侧边栏链接 | -| **响应式布局** | 移动端(< 768px)自动隐藏侧边栏,显示汉堡菜单按钮 | -| **入场动画** | 页面区块淡入动画(fadeIn + translateY),提升阅读体验 | +- **批量解析**: 自动读取 `llm_log/` 目录下所有 `.md` 文件 +- **设计驱动**: 严格遵循 `ui-ux-pro-max` 设计规范体系 +- **响应式布局**: 移动端优先,适配 375px → 1440px 断点 +- **微交互**: 表格行悬停高亮、卡片悬浮上浮动画 +- **无障碍**: ARIA 语义标签、`prefers-reduced-motion` 支持 +- **零外部依赖**: 生成纯静态 HTML,字体通过 Google Fonts CDN 引入 -## 目录结构 +## 设计令牌 + +| Token | Value | Usage | +|-------|-------|-------| +| Primary | `#6366f1` | 主题色、强调色 | +| Surface | `#ffffff` | 卡片背景 | +| Background | `#f1f5f9` | 页面背景 | +| Text Primary | `#0f172a` | 主要文本 | +| Radius | 6/10/16px | 圆角层级 | +| Font Sans | Inter | 正文字体 | +| Font Mono | JetBrains Mono | 代码字体 | + +## 项目结构 ``` llm_log_frontend/ -├── build.js # 构建脚本(核心逻辑) -├── package.json # NPM 依赖配置 -├── index.html # 构建产物(静态站点) -└── llm_log/ # Markdown 源文件目录 - └── 2026-04-26.md # 示例日志文件 +├── llm_log/ # Markdown 日志文件目录 +│ └── 2026-04-26.md # 按日期命名的日志 +├── index.html # 生成的静态页面 +├── generate.js # 生成器脚本 +└── package.json ``` -## 快速开始 - -### 安装依赖 +## 使用方法 ```bash +# 安装依赖 npm install + +# 生成 HTML +npm run generate ``` -### 构建站点 +## 日志格式 -```bash -npm run build -# 或直接执行 -node build.js +将 Markdown 文件放入 `llm_log/` 目录,文件名格式为 `YYYY-MM-DD.md`: + +```markdown +| 小时 | 平均输入t/s | 平均输出t/s | 输入token总数 | 输出token总数 | token总数 | +| :---: | :---: | :---: | :---: | :---: | :---: | +| 00 | 216.04 | 26.08 | 115,105 | 5,701 | 120,806 | ``` -构建产物为项目根目录下的 `index.html`,可直接用浏览器打开,或部署至任意静态托管服务(GitHub Pages、Vercel、Netlify 等)。 +## 设计规范 -### 添加日志文件 +本项目遵循 [ui-ux-pro-max](https://github.com/anomalyco/opencode) 规范体系的核心准则: -**方式一**:在 `llm_log/` 目录中直接放入 `.md` 文件(按文件名排序) +- **排版节奏**: 16px 基准字重,1.5-1.6 行高,65-75 字最大行长 +- **间距系统**: 4/8dp 增量,保持 8px 最小触摸间距 +- **阴影层级**: sm(1px) → md(4px) → lg(10px) 递进 +- **过渡动画**: 150-300ms ease-out,支持减弱动效偏好 +- **对比度**: 文本与背景 4.5:1 以上,触摸目标 ≥44×44pt -**方式二**:在 `llm_log/` 目录下创建 `log.txt`,每行写一个相对路径: +## 预览 -``` -# llm_log/log.txt -2026-04-26.md -2026-04-25.md -../other-dir/report.md -``` +生成的页面包含: -## 技术栈 +- 粘性导航栏 + 最后更新时间 +- 卡片式日志条目,每条带日期标识 +- 表格悬停高亮,`**全天**` 行高亮突出 +- 移动端自适应表格滚动 -| 层级 | 选型 | -|------|------| -| 运行时 | Node.js >= 18 | -| Markdown 解析 | [marked](https://github.com/markedjs/marked) v12.0.2 | -| 代码高亮 | [highlight.js](https://highlightjs.org/) v11.9.0 (CDN) | -| 样式框架 | [Tailwind CSS](https://tailwindcss.com/) (CDN) | -| 字体 | Inter (Google Fonts) | +## License -## 自定义 renderer - -`build.js` 中预置了 5 个自定义渲染器,覆盖常用 Markdown 元素: - -```javascript -// 代码块:深色背景 + 复制按钮 + 语法高亮 -renderer.code = function (code, lang) { ... } - -// 行内代码:蓝底白字(亮)/ 深蓝底(暗) -renderer.codespan = function (code) { ... } - -// 表格行:悬停高亮 -renderer.tablerow = function (content) { ... } - -// 表格单元格:表头/数据格差异化样式 -renderer.tablecell = function (content, flags) { ... } - -// 表格:外层包 overflow-x-auto,响应式滚动 -renderer.table = function (header, body) { ... } -``` - -如需添加更多自定义(如 blockquote、hr 等),可按相同模式追加至 `renderer` 对象后调用 `marked.setOptions({ renderer })` 生效。 - -## 输出示例 - -构建 `index.html` 后,打开浏览器即可看到: - -- **左侧**:固定侧边栏,显示文件列表与嵌套 TOC -- **右侧**:主内容区,最大宽度 `max-w-4xl`,Inter 字体,阅读体验友好 -- **右上角**:深色模式切换按钮(太阳/月亮图标) -- **顶部**:吸顶导航栏,含移动端汉堡菜单触发按钮 - -## 部署 - -### GitHub Pages - -```bash -# 1. 确保 index.html 已提交至 git 仓库 -git add index.html -git commit -m "docs: add generated static site" - -# 2. 推送至 GitHub -git push origin main - -# 3. 在仓库 Settings > Pages > Source 选择 "main" 分支 -``` - -### 本地预览 - -```bash -# Python 静态服务器 -python -m http.server 8080 - -# 或 Node.js serve -npx serve . - -# 访问 http://localhost:8080 -``` - -## 注意事项 - -1. **Node.js 版本**:marked v12 需要 Node.js >= 18,若遇到 `EBADENGINE` 警告请升级 Node。 -2. **XSS 安全**:当前构建脚本直接拼接 Markdown 输出,适用于可信的内部日志。若需处理用户提交内容,建议在 `marked.parse()` 后串接 DOMPurify 消毒。 -3. **CDN 依赖**:样式与脚本均通过 CDN 加载,部署时请确保网络可访问 cdn.tailwindcss.com、cdnjs.cloudflare.com 等。 -4. **构建产物**:建议将 `index.html` 纳入版本管理,便于 CI/CD 自动部署和历史追溯。 +MIT \ No newline at end of file diff --git a/build.js b/build.js deleted file mode 100644 index 2f2fd08..0000000 --- a/build.js +++ /dev/null @@ -1,304 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const { marked } = require('marked'); - -// ─── Config ──────────────────────────────────────────────── -const LOG_DIR = path.join(__dirname, 'llm_log'); -const OUTPUT_FILE = path.join(__dirname, 'index.html'); - -// ─── Marked Config ───────────────────────────────────────── -const headingIds = new Map(); - -const renderer = new marked.Renderer(); -renderer.code = function (code, lang) { - const validLang = lang || 'text'; - const highlighted = highlightCode(code, validLang); - const id = 'highlight-' + Math.random().toString(36).slice(2, 8); - return `
${highlighted}`;
-};
-renderer.codespan = function (code) {
- return `${code}`;
-};
-renderer.tablerow = function (content) {
- return `${path.basename(p.filePath)}
-暂无日志记录
'; + } else { + content = logs.map(({ date, html }) => ` +加载中...
', '暂无日志记录
'); + fs.writeFileSync(OUTPUT_FILE, emptyHtml); + console.log(`Generated: ${OUTPUT_FILE}`); + return; + } + + const logs = files + .map(filePath => { + const content = readFileSafe(filePath); + if (!content) { + console.warn(`Skipping empty or unreadable file: ${filePath}`); + return null; + } + const date = path.basename(filePath, '.md'); + const html = parseMarkdown(content); + return { date, html }; + }) + .filter(Boolean); + + logs.sort((a, b) => a.date.localeCompare(b.date)); + + const html = buildHtml(logs); + fs.writeFileSync(OUTPUT_FILE, html); + + console.log(`Generated: ${OUTPUT_FILE}`); + console.log(`Processed ${logs.length} log files.`); +} + +main(); \ No newline at end of file diff --git a/index.html b/index.html index 559226b..a53a142 100644 --- a/index.html +++ b/index.html @@ -3,299 +3,699 @@ -