claude-code-log 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_code_log-0.2.2/CHANGELOG.md +165 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/PKG-INFO +6 -3
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/README.md +4 -2
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/renderer.py +36 -16
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/templates/index.html +42 -18
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/templates/transcript.html +69 -81
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/justfile +3 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/pyproject.toml +2 -1
- claude_code_log-0.2.2/test/test_markdown_rendering.py +128 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_template_rendering.py +27 -14
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/uv.lock +12 -1
- claude_code_log-0.2.0/CHANGELOG.md +0 -73
- claude_code_log-0.2.0/test/test_markdown_rendering.py +0 -56
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/.claude/settings.local.json +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/.github/workflows/ci.yml +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/.gitignore +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/CLAUDE.md +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/LICENSE +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/__init__.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/cli.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/converter.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/models.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/parser.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/claude_code_log/py.typed +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/scripts/generate_style_guide.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/scripts/style_guide_output/index.html +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/scripts/style_guide_output/index_style_guide.html +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/scripts/style_guide_output/transcript_style_guide.html +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/README.md +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/__init__.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_command_handling.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_data/edge_cases.jsonl +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_data/representative_messages.jsonl +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_data/session_b.jsonl +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_data/todowrite_examples.jsonl +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_date_filtering.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_filtering.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_message_filtering.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_message_types.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_path_conversion.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_template_data.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_template_utils.py +0 -0
- {claude_code_log-0.2.0 → claude_code_log-0.2.2}/test/test_todowrite_rendering.py +0 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to claude-code-log will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.2] - 2025-06-16
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Static Markdown**: Render Markdown in Python to make it easier to test and not require Javascipt
|
|
13
|
+
- **Visual Design**: Make it nicer to look at
|
|
14
|
+
|
|
15
|
+
## [0.2.1] - 2025-06-15
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Table of Contents & Session Navigation**: Added comprehensive session navigation system
|
|
20
|
+
- Interactive table of contents with session summaries and quick navigation
|
|
21
|
+
- Timestamp ranges showing first-to-last timestamp for each session
|
|
22
|
+
- Session-based organization with clickable navigation links
|
|
23
|
+
- Floating "back to top" button for easy navigation
|
|
24
|
+
|
|
25
|
+
- **Token Usage Tracking**: Complete token consumption display and tracking
|
|
26
|
+
- Individual assistant messages show token usage in headers
|
|
27
|
+
- Session-level token aggregation in table of contents
|
|
28
|
+
- Detailed breakdown: Input, Output, Cache Creation, Cache Read tokens
|
|
29
|
+
- Data extracted from AssistantMessage.usage field in JSONL files
|
|
30
|
+
|
|
31
|
+
- **Enhanced Content Support**: Expanded message type and content handling
|
|
32
|
+
- **Tool Use Rendering**: Proper display of tool invocations and results
|
|
33
|
+
- **Thinking Content**: Support for Claude's internal thinking processes
|
|
34
|
+
- **Image Handling**: Display of pasted images in transcript conversations
|
|
35
|
+
- **Todo List Rendering**: Support for structured todo lists in messages
|
|
36
|
+
|
|
37
|
+
- **Project Hierarchy Processing**: Complete project management system
|
|
38
|
+
- Process entire `~/.claude/projects/` directory by default
|
|
39
|
+
- Master index page with project cards and statistics
|
|
40
|
+
- Linked navigation between index and individual project pages
|
|
41
|
+
- Project statistics including file counts and recent activity
|
|
42
|
+
|
|
43
|
+
- **Improved User Experience**: Enhanced interface and navigation
|
|
44
|
+
- Chronological ordering of all messages across sessions
|
|
45
|
+
- Session demarcation with clear visual separators
|
|
46
|
+
- Always-visible scroll-to-top button
|
|
47
|
+
- Space-efficient, content-dense layout design
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- **Default Behavior**: Changed default mode to process all projects instead of requiring explicit input
|
|
52
|
+
- `claude-code-log` now processes `~/.claude/projects/` by default
|
|
53
|
+
- Added `--all-projects` flag for explicit project processing
|
|
54
|
+
- Maintained backward compatibility for single file/directory processing
|
|
55
|
+
|
|
56
|
+
- **Output Structure**: Restructured HTML output for better organization
|
|
57
|
+
- Session-based navigation replaces simple chronological listing
|
|
58
|
+
- Enhanced template system with comprehensive session metadata
|
|
59
|
+
- Improved visual hierarchy with table of contents integration
|
|
60
|
+
|
|
61
|
+
- **Data Models**: Expanded Pydantic models for richer data representation
|
|
62
|
+
- Enhanced TranscriptEntry with proper content type handling
|
|
63
|
+
- Added UsageInfo model for token usage tracking
|
|
64
|
+
- Improved ContentItem unions for diverse content types
|
|
65
|
+
|
|
66
|
+
### Technical
|
|
67
|
+
|
|
68
|
+
- **Template System**: Major improvements to Jinja2 template architecture
|
|
69
|
+
- New session navigation template components
|
|
70
|
+
- Token usage display templates
|
|
71
|
+
- Enhanced message rendering with rich content support
|
|
72
|
+
- Responsive design improvements
|
|
73
|
+
|
|
74
|
+
- **Testing Infrastructure**: Comprehensive test coverage expansion
|
|
75
|
+
- Increased test coverage to 78%+ across all modules
|
|
76
|
+
- Added visual style guide generation
|
|
77
|
+
- Representative test data based on real transcript files
|
|
78
|
+
- Extensive test documentation in test/README.md
|
|
79
|
+
|
|
80
|
+
- **Code Quality**: Significant refactoring and quality improvements
|
|
81
|
+
- Complete Pydantic migration with proper error handling
|
|
82
|
+
- Improved type hints and function documentation
|
|
83
|
+
- Enhanced CLI interface with better argument parsing
|
|
84
|
+
- Comprehensive linting and formatting standards
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
|
|
88
|
+
- **Data Processing**: Improved robustness of transcript processing
|
|
89
|
+
- Better handling of malformed or incomplete JSONL entries
|
|
90
|
+
- More reliable session detection and grouping
|
|
91
|
+
- Enhanced error handling for edge cases in data parsing
|
|
92
|
+
- Fixed HTML escaping issues in message content
|
|
93
|
+
|
|
94
|
+
- **Template Rendering**: Resolved template and rendering issues
|
|
95
|
+
- Fixed session summary attachment logic
|
|
96
|
+
- Improved timestamp handling and formatting
|
|
97
|
+
- Better handling of mixed content types in templates
|
|
98
|
+
- Resolved CSS and styling inconsistencies
|
|
99
|
+
|
|
100
|
+
## [0.1.0]
|
|
101
|
+
|
|
102
|
+
### Added
|
|
103
|
+
|
|
104
|
+
- **Summary Message Support**: Added support for `summary` type messages in JSONL transcripts
|
|
105
|
+
- Summary messages are displayed with green styling and "Summary:" prefix
|
|
106
|
+
- Includes special CSS class `.summary` for custom styling
|
|
107
|
+
|
|
108
|
+
- **System Command Visibility**: System commands (like `init`) are now shown instead of being filtered out
|
|
109
|
+
- Commands appear in expandable `<details>` elements
|
|
110
|
+
- Shows command name in the summary (e.g., "Command: init")
|
|
111
|
+
- Full command content is revealed when expanded
|
|
112
|
+
- Uses orange styling with `.system` CSS class
|
|
113
|
+
|
|
114
|
+
- **Markdown Rendering Support**: Automatic client-side markdown rendering
|
|
115
|
+
- Uses marked.js ESM module loaded from CDN
|
|
116
|
+
- Supports GitHub Flavored Markdown (GFM)
|
|
117
|
+
- Renders headers, emphasis, code blocks, lists, links, and images
|
|
118
|
+
- Preserves existing HTML content when present
|
|
119
|
+
|
|
120
|
+
- **Enhanced CSS Styling**: New styles for better visual organization
|
|
121
|
+
- Added styles for `.summary` messages (green theme)
|
|
122
|
+
- Added styles for `.system` messages (orange theme)
|
|
123
|
+
- Added styles for `<details>` elements with proper spacing and cursor behavior
|
|
124
|
+
- Improved overall visual hierarchy
|
|
125
|
+
|
|
126
|
+
### Changed
|
|
127
|
+
|
|
128
|
+
- **System Message Filtering**: Modified system message handling logic
|
|
129
|
+
- System messages with `<command-name>` tags are no longer filtered out
|
|
130
|
+
- Added `extract_command_name()` function to parse command names
|
|
131
|
+
- Updated `is_system_message()` function to handle command messages differently
|
|
132
|
+
- Other system messages (stdout, caveats) are still filtered as before
|
|
133
|
+
|
|
134
|
+
- **Message Type Support**: Extended message type handling in `load_transcript()`
|
|
135
|
+
- Now accepts `"summary"` type in addition to `"user"` and `"assistant"`
|
|
136
|
+
- Updated message processing logic to handle different content structures
|
|
137
|
+
|
|
138
|
+
### Technical
|
|
139
|
+
|
|
140
|
+
- **Dependencies**: No new Python dependencies added
|
|
141
|
+
- marked.js is loaded via CDN for client-side rendering
|
|
142
|
+
- Maintains existing minimal dependency approach
|
|
143
|
+
|
|
144
|
+
- **Testing**: Added comprehensive test coverage
|
|
145
|
+
- New test file `test_new_features.py` with tests for:
|
|
146
|
+
- Summary message type support
|
|
147
|
+
- System command message handling
|
|
148
|
+
- Markdown script inclusion
|
|
149
|
+
- System message filtering behavior
|
|
150
|
+
- Tests use anonymized fixtures based on real transcript data
|
|
151
|
+
|
|
152
|
+
- **Code Quality**: Improved type hints and function documentation
|
|
153
|
+
- Added proper docstrings for new functions
|
|
154
|
+
- Enhanced error handling for edge cases
|
|
155
|
+
- Maintained backward compatibility with existing functionality
|
|
156
|
+
|
|
157
|
+
### Fixed
|
|
158
|
+
|
|
159
|
+
- **Message Processing**: Improved robustness of message content extraction
|
|
160
|
+
- Better handling of mixed content types in transcript files
|
|
161
|
+
- More reliable text extraction from complex message structures
|
|
162
|
+
|
|
163
|
+
## Previous Versions
|
|
164
|
+
|
|
165
|
+
Earlier versions focused on basic JSONL to HTML conversion with session demarcation and date filtering capabilities.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-log
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Convert Claude Code transcript JSONL files to HTML
|
|
5
5
|
Project-URL: Homepage, https://github.com/daaain/claude-code-log
|
|
6
6
|
Project-URL: Issues, https://github.com/daaain/claude-code-log/issues
|
|
@@ -13,6 +13,7 @@ Requires-Python: >=3.12
|
|
|
13
13
|
Requires-Dist: click>=8.0.0
|
|
14
14
|
Requires-Dist: dateparser>=1.0.0
|
|
15
15
|
Requires-Dist: jinja2>=3.0.0
|
|
16
|
+
Requires-Dist: mistune>=3.1.3
|
|
16
17
|
Requires-Dist: pydantic>=2.0.0
|
|
17
18
|
Description-Content-Type: text/markdown
|
|
18
19
|
|
|
@@ -22,6 +23,8 @@ A Python CLI tool that converts Claude Code transcript JSONL files into readable
|
|
|
22
23
|
|
|
23
24
|
## Project Overview
|
|
24
25
|
|
|
26
|
+
📋 **[View Changelog](CHANGELOG.md)** - See what's new in each release
|
|
27
|
+
|
|
25
28
|
This tool generates clean, minimalist HTML pages showing user prompts and assistant responses chronologically. It's designed to create a readable log of your Claude Code interactions with support for both individual files and entire project hierarchies.
|
|
26
29
|
|
|
27
30
|
## Quickstart
|
|
@@ -212,7 +215,7 @@ When processing all projects, the tool generates:
|
|
|
212
215
|
|
|
213
216
|
## Installation
|
|
214
217
|
|
|
215
|
-
Install using pip
|
|
218
|
+
Install using pip:
|
|
216
219
|
|
|
217
220
|
```bash
|
|
218
221
|
pip install claude-code-log
|
|
@@ -229,6 +232,6 @@ uv run claude-code-log
|
|
|
229
232
|
|
|
230
233
|
## TODO
|
|
231
234
|
|
|
232
|
-
-
|
|
235
|
+
- Show top level stats on index page – token usage added up + time of last interaction
|
|
233
236
|
- **Tool Use Preview**: Show first few lines of tool use and other collapsed details
|
|
234
237
|
- **In-page Filtering**: Client-side filtering and search
|
|
@@ -4,6 +4,8 @@ A Python CLI tool that converts Claude Code transcript JSONL files into readable
|
|
|
4
4
|
|
|
5
5
|
## Project Overview
|
|
6
6
|
|
|
7
|
+
📋 **[View Changelog](CHANGELOG.md)** - See what's new in each release
|
|
8
|
+
|
|
7
9
|
This tool generates clean, minimalist HTML pages showing user prompts and assistant responses chronologically. It's designed to create a readable log of your Claude Code interactions with support for both individual files and entire project hierarchies.
|
|
8
10
|
|
|
9
11
|
## Quickstart
|
|
@@ -194,7 +196,7 @@ When processing all projects, the tool generates:
|
|
|
194
196
|
|
|
195
197
|
## Installation
|
|
196
198
|
|
|
197
|
-
Install using pip
|
|
199
|
+
Install using pip:
|
|
198
200
|
|
|
199
201
|
```bash
|
|
200
202
|
pip install claude-code-log
|
|
@@ -211,6 +213,6 @@ uv run claude-code-log
|
|
|
211
213
|
|
|
212
214
|
## TODO
|
|
213
215
|
|
|
214
|
-
-
|
|
216
|
+
- Show top level stats on index page – token usage added up + time of last interaction
|
|
215
217
|
- **Tool Use Preview**: Show first few lines of tool use and other collapsed details
|
|
216
218
|
- **In-page Filtering**: Client-side filtering and search
|
|
@@ -6,6 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
from typing import List, Optional, Union, Dict, Any, cast
|
|
7
7
|
from datetime import datetime
|
|
8
8
|
import html
|
|
9
|
+
import mistune
|
|
9
10
|
from jinja2 import Environment, FileSystemLoader
|
|
10
11
|
|
|
11
12
|
from .models import (
|
|
@@ -36,6 +37,23 @@ def escape_html(text: str) -> str:
|
|
|
36
37
|
return html.escape(text)
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
def render_markdown(text: str) -> str:
|
|
41
|
+
"""Convert markdown text to HTML using mistune."""
|
|
42
|
+
# Configure mistune with GitHub-flavored markdown features
|
|
43
|
+
renderer = mistune.create_markdown(
|
|
44
|
+
plugins=[
|
|
45
|
+
"strikethrough",
|
|
46
|
+
"footnotes",
|
|
47
|
+
"table",
|
|
48
|
+
"url",
|
|
49
|
+
"task_lists",
|
|
50
|
+
"def_list",
|
|
51
|
+
],
|
|
52
|
+
escape=False, # Don't escape HTML since we want to render markdown properly
|
|
53
|
+
)
|
|
54
|
+
return str(renderer(text))
|
|
55
|
+
|
|
56
|
+
|
|
39
57
|
def extract_command_info(text_content: str) -> tuple[str, str, str]:
|
|
40
58
|
"""Extract command info from system message with command tags."""
|
|
41
59
|
import re
|
|
@@ -157,7 +175,7 @@ def format_tool_use_content(tool_use: ToolUseContent) -> str:
|
|
|
157
175
|
return f"""
|
|
158
176
|
<div class="tool-content tool-use">
|
|
159
177
|
<details>
|
|
160
|
-
<summary><strong
|
|
178
|
+
<summary><strong>🛠️ Tool Use:</strong> {escaped_name} (ID: {escaped_id})</summary>
|
|
161
179
|
<div class="tool-input">
|
|
162
180
|
<strong>Input:</strong>
|
|
163
181
|
<pre>{escaped_input}</pre>
|
|
@@ -182,12 +200,12 @@ def format_tool_result_content(tool_result: ToolResultContent) -> str:
|
|
|
182
200
|
content_parts.append(item.get("text", ""))
|
|
183
201
|
escaped_content = escape_html("\n".join(content_parts))
|
|
184
202
|
|
|
185
|
-
error_indicator = " (Error)" if tool_result.is_error else ""
|
|
203
|
+
error_indicator = " (🚨 Error)" if tool_result.is_error else ""
|
|
186
204
|
|
|
187
205
|
return f"""
|
|
188
206
|
<div class="tool-content tool-result">
|
|
189
207
|
<details>
|
|
190
|
-
<summary><strong
|
|
208
|
+
<summary><strong>🧰 Tool Result{error_indicator}:</strong> {escaped_id}</summary>
|
|
191
209
|
<div class="tool-input">
|
|
192
210
|
<pre>{escaped_content}</pre>
|
|
193
211
|
</div>
|
|
@@ -203,7 +221,7 @@ def format_thinking_content(thinking: ThinkingContent) -> str:
|
|
|
203
221
|
return f"""
|
|
204
222
|
<div class="tool-content thinking-content">
|
|
205
223
|
<details>
|
|
206
|
-
<summary><strong
|
|
224
|
+
<summary><strong>💭 Thinking</strong></summary>
|
|
207
225
|
<div class="thinking-text">
|
|
208
226
|
<pre>{escaped_thinking}</pre>
|
|
209
227
|
</div>
|
|
@@ -229,24 +247,26 @@ def render_message_content(
|
|
|
229
247
|
) -> str:
|
|
230
248
|
"""Render message content with proper tool use and tool result formatting."""
|
|
231
249
|
if isinstance(content, str):
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
250
|
+
if message_type == "user":
|
|
251
|
+
# User messages are shown as-is in preformatted blocks
|
|
252
|
+
escaped_text = escape_html(content)
|
|
253
|
+
return "<pre>" + escaped_text + "</pre>"
|
|
254
|
+
else:
|
|
255
|
+
# Assistant messages get markdown rendering
|
|
256
|
+
return render_markdown(content)
|
|
238
257
|
|
|
239
258
|
# content is a list of ContentItem objects
|
|
240
259
|
rendered_parts: List[str] = []
|
|
241
260
|
|
|
242
261
|
for item in content:
|
|
243
262
|
if type(item) is TextContent:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
263
|
+
if message_type == "user":
|
|
264
|
+
# User messages are shown as-is in preformatted blocks
|
|
265
|
+
escaped_text = escape_html(item.text)
|
|
266
|
+
rendered_parts.append("<pre>" + escaped_text + "</pre>")
|
|
267
|
+
else:
|
|
268
|
+
# Assistant messages get markdown rendering
|
|
269
|
+
rendered_parts.append(render_markdown(item.text))
|
|
250
270
|
elif type(item) is ToolUseContent:
|
|
251
271
|
rendered_parts.append(format_tool_use_content(item)) # type: ignore
|
|
252
272
|
elif type(item) is ToolResultContent:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang='en'>
|
|
3
|
+
|
|
3
4
|
<head>
|
|
4
5
|
<meta charset='UTF-8'>
|
|
5
6
|
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
|
|
@@ -11,43 +12,54 @@
|
|
|
11
12
|
max-width: 1200px;
|
|
12
13
|
margin: 0 auto;
|
|
13
14
|
padding: 20px;
|
|
14
|
-
background
|
|
15
|
+
background: linear-gradient(90deg, #f3d6d2, #f1dcce, #f0e4ca, #eeecc7, #e3ecc3, #d5eac0, #c6e8bd, #b9e6bc, #b6e3c5, #b3e1cf);
|
|
15
16
|
color: #333;
|
|
16
17
|
}
|
|
18
|
+
|
|
17
19
|
h1 {
|
|
18
20
|
text-align: center;
|
|
19
21
|
color: #2c3e50;
|
|
20
22
|
margin-bottom: 30px;
|
|
21
23
|
font-size: 2em;
|
|
22
24
|
}
|
|
25
|
+
|
|
23
26
|
.project-list {
|
|
24
27
|
display: grid;
|
|
25
28
|
gap: 15px;
|
|
26
29
|
}
|
|
30
|
+
|
|
27
31
|
.project-card {
|
|
28
|
-
background:
|
|
32
|
+
background-color: #ffffff66;
|
|
29
33
|
border-radius: 8px;
|
|
30
34
|
padding: 20px;
|
|
31
|
-
box-shadow:
|
|
32
|
-
border-left:
|
|
35
|
+
box-shadow: -7px -7px 10px #eeeeee44, 7px 7px 10px #00000011;
|
|
36
|
+
border-left: #ffffff66 1px solid;
|
|
37
|
+
border-top: #ffffff66 1px solid;
|
|
38
|
+
border-bottom: #00000017 1px solid;
|
|
39
|
+
border-right: #00000017 1px solid;
|
|
33
40
|
}
|
|
41
|
+
|
|
34
42
|
.project-card:hover {
|
|
35
|
-
box-shadow:
|
|
43
|
+
box-shadow: -10px -10px 15px #eeeeee66, 10px 10px 15px #00000022;
|
|
36
44
|
transform: translateY(-1px);
|
|
37
45
|
transition: all 0.2s ease;
|
|
38
46
|
}
|
|
47
|
+
|
|
39
48
|
.project-name {
|
|
40
49
|
font-size: 1.2em;
|
|
41
50
|
font-weight: 600;
|
|
42
51
|
margin-bottom: 10px;
|
|
43
52
|
}
|
|
53
|
+
|
|
44
54
|
.project-name a {
|
|
45
55
|
text-decoration: none;
|
|
46
56
|
color: #2196f3;
|
|
47
57
|
}
|
|
58
|
+
|
|
48
59
|
.project-name a:hover {
|
|
49
60
|
text-decoration: underline;
|
|
50
61
|
}
|
|
62
|
+
|
|
51
63
|
.project-stats {
|
|
52
64
|
color: #666;
|
|
53
65
|
font-size: 0.9em;
|
|
@@ -55,42 +67,53 @@
|
|
|
55
67
|
gap: 20px;
|
|
56
68
|
flex-wrap: wrap;
|
|
57
69
|
}
|
|
70
|
+
|
|
58
71
|
.stat {
|
|
59
72
|
display: flex;
|
|
60
73
|
align-items: center;
|
|
61
74
|
gap: 5px;
|
|
62
75
|
}
|
|
76
|
+
|
|
63
77
|
.summary {
|
|
64
78
|
text-align: center;
|
|
65
79
|
margin-bottom: 30px;
|
|
66
80
|
padding: 15px;
|
|
67
|
-
background:
|
|
81
|
+
background-color: #ffffff66;
|
|
68
82
|
border-radius: 8px;
|
|
69
|
-
box-shadow:
|
|
83
|
+
box-shadow: -7px -7px 10px #eeeeee44, 7px 7px 10px #00000011;
|
|
84
|
+
border-left: #ffffff66 1px solid;
|
|
85
|
+
border-top: #ffffff66 1px solid;
|
|
86
|
+
border-bottom: #00000017 1px solid;
|
|
87
|
+
border-right: #00000017 1px solid;
|
|
70
88
|
}
|
|
89
|
+
|
|
71
90
|
.summary-stats {
|
|
72
91
|
display: flex;
|
|
73
92
|
justify-content: center;
|
|
74
93
|
gap: 30px;
|
|
75
94
|
flex-wrap: wrap;
|
|
76
95
|
}
|
|
96
|
+
|
|
77
97
|
.summary-stat {
|
|
78
98
|
text-align: center;
|
|
79
99
|
}
|
|
100
|
+
|
|
80
101
|
.summary-stat .number {
|
|
81
102
|
font-size: 1.5em;
|
|
82
103
|
font-weight: 600;
|
|
83
104
|
color: #2196f3;
|
|
84
105
|
}
|
|
106
|
+
|
|
85
107
|
.summary-stat .label {
|
|
86
108
|
color: #666;
|
|
87
109
|
font-size: 0.9em;
|
|
88
110
|
}
|
|
89
111
|
</style>
|
|
90
112
|
</head>
|
|
113
|
+
|
|
91
114
|
<body>
|
|
92
115
|
<h1>{{ title }}</h1>
|
|
93
|
-
|
|
116
|
+
|
|
94
117
|
<div class='summary'>
|
|
95
118
|
<div class='summary-stats'>
|
|
96
119
|
<div class='summary-stat'>
|
|
@@ -107,20 +130,21 @@
|
|
|
107
130
|
</div>
|
|
108
131
|
</div>
|
|
109
132
|
</div>
|
|
110
|
-
|
|
133
|
+
|
|
111
134
|
<div class='project-list'>
|
|
112
135
|
{% for project in projects %}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
</div>
|
|
117
|
-
<div class='project-stats'>
|
|
118
|
-
<div class='stat'>📁 {{ project.jsonl_count }} transcript files</div>
|
|
119
|
-
<div class='stat'>💬 {{ project.message_count }} messages</div>
|
|
120
|
-
<div class='stat'>🕒 {{ project.formatted_date }}</div>
|
|
121
|
-
</div>
|
|
136
|
+
<div class='project-card'>
|
|
137
|
+
<div class='project-name'>
|
|
138
|
+
<a href='{{ project.html_file }}'>{{ project.display_name }}</a>
|
|
122
139
|
</div>
|
|
140
|
+
<div class='project-stats'>
|
|
141
|
+
<div class='stat'>📁 {{ project.jsonl_count }} transcript files</div>
|
|
142
|
+
<div class='stat'>💬 {{ project.message_count }} messages</div>
|
|
143
|
+
<div class='stat'>🕒 {{ project.formatted_date }}</div>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
123
146
|
{% endfor %}
|
|
124
147
|
</div>
|
|
125
148
|
</body>
|
|
149
|
+
|
|
126
150
|
</html>
|