diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d314bbb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,218 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +TimelineSvg is a browser-based system for generating multi-lane timelines as SVG graphics from CSV data. It processes everything client-side using vanilla JavaScript, with no build pipeline or backend required. The system uses a template-based architecture where SVG templates define the visual appearance and data is mapped through a project configuration file. + +**Troubleshooting**: If you encounter issues during development, check `TROUBLESHOOTING.md` first. It contains solutions for common problems including npm installation failures, CORS errors, template validation issues, and more. + +## Commands + +### Installation +```bash +make install # Install development dependencies +``` + +**Important - Node.js v24 on WSL**: If you encounter `ERR_SSL_CIPHER_OPERATION_FAILED` errors during `npm install`, this is a known issue with Node.js v24 and OpenSSL 3.x in WSL environments. The Makefile automatically applies the workaround using `NODE_OPTIONS="--openssl-legacy-provider"`. If installing manually without make: +```bash +export NODE_OPTIONS="--openssl-legacy-provider" && npm install +``` + +### Testing +```bash +npm test # Run all tests once +npm run test:watch # Run tests in watch mode +npm run test:coverage # Generate coverage report +npm run test:ui # Run Vitest UI +``` + +The project uses Vitest with jsdom for testing. Tests are located in `/test/` and cover the generator, engine, and integration scenarios. + +### Development +```bash +make serve # Start local development server (auto-detects Python/npx) +# or manually: +python3 -m http.server 8000 + +# Then open http://localhost:8000 +``` + +The application must be served via HTTP (not opened as file://) due to CORS restrictions when loading CSV, CSS, and SVG files. + +## Architecture + +### Core Components + +**1. engine.js** - Application controller and data loading +- Manages project configuration loading (auto-loads from `binect/`, `my-project/`, or `example/` folders) +- Handles CSV parsing using PapaParse library +- Manages file uploads and overrides +- Provides debug information panel +- Controls view modes (internal vs external) +- Implements zoom functionality for SVG viewer + +**2. generator.js** - Timeline rendering engine +- Implements template-v2 architecture +- Extracts template elements from `` section: `month-template`, `lane-template`, `item-template` +- Replaces placeholders with calculated values and CSV data +- Handles layout calculations (positioning months, lanes, items) +- Generates final SVG by cloning templates and replacing `{{MONTHS}}` and `{{LANES}}` macros + +**3. index.html** - UI and browser entry point +- Loads PapaParse from CDN for CSV parsing +- Provides file upload controls +- Contains viewer with zoom controls +- Shows debug information panel with field mappings and data preview + +### Data Flow + +1. **Project Configuration** (`project.json`) defines: + - Data source (CSV file path) + - Stylesheet (CSS file path) + - SVG template (template-v2.svg file path) + - Field mappings (CSV columns → timeline fields) + - Optional placeholder mappings (override default `ITEM_*` convention) + - Settings (timeline duration, etc.) + +2. **CSV Data** is parsed and mapped to timeline items: + - Required fields: `id`, `title`, `due`, `lane` + - Date parsing supports multiple formats: `YYYY-MM-DD`, `YYYY/MM/DD`, `DD.MM.YYYY` + - Items without valid title or due date are filtered out + +3. **Template System** (template-v2 architecture): + - Templates are standard SVG files editable in Inkscape, Illustrator, or Figma + - Three required template elements in `` section: + - `` - Defines month column rendering + - `` - Defines lane/epic row rendering + - `` - Defines individual task rendering + - Templates contain placeholders like `{{MONTH_X}}`, `{{LANE_NAME}}`, `{{ITEM_TITLE}}` + - Generator extracts templates, replaces placeholders, and injects into main SVG + +4. **Placeholder System**: + - Layout placeholders: `{{MONTH_X}}`, `{{LANE_Y}}`, `{{ITEM_X}}`, etc. (calculated by generator) + - Data placeholders: Automatically created from CSV columns using `ITEM_{PROPERTY}` convention + - Custom mappings: Use `placeholderMapping` in project.json to override default names (e.g., `TASK_ID` instead of `ITEM_ID`) + - All CSV properties (except `due`) are available as placeholders in templates + +### Key Concepts + +**Template-v2 Architecture**: The current system (migrated from older macro-based approach) uses proper SVG template elements that are cloned and customized. This makes templates more maintainable and editable in visual SVG editors. + +**Field Mapping**: CSV columns don't need to match exact names. The `fieldMapping` object in project.json maps CSV column names to the internal timeline model: +```json +{ + "fieldMapping": { + "id": "ID", // CSV column "ID" maps to item.id + "title": "Title", // CSV column "Title" maps to item.title + "lane": "Lane", // CSV column "Lane" maps to item.lane + "due": ["Due"] // CSV column "Due" maps to item.due (array for fallbacks) + } +} +``` + +**Placeholder Mapping**: When templates use non-standard placeholder names (common when migrating from other tools), use `placeholderMapping` to override the default `ITEM_*` convention: +```json +{ + "placeholderMapping": { + "id": "TASK_ID", // Use {{TASK_ID}} instead of {{ITEM_ID}} + "title": "TASK_NAME" // Use {{TASK_NAME}} instead of {{ITEM_TITLE}} + } +} +``` + +**Layout Constants** (generator.js:41-45): Control overall positioning +- `left: 220` - Left margin +- `top: 140` - Top margin +- `monthWidth: 120` - Width of each month column +- `laneHeight: 80` - Height of each lane/epic row +- `laneGap: 16` - Vertical gap between lanes + +**View Modes**: +- Internal view: Shows item IDs (for development/review) +- External view: Hides item IDs (for presentations/exports) + +## Project Structure + +``` +/ +├── index.html # Main application entry point +├── engine.js # Application controller & data loading +├── generator.js # SVG generation & template processing +├── vitest.config.js # Test configuration +├── test/ +│ ├── setup.js # Test environment setup +│ ├── generator.test.js # Generator unit tests +│ ├── engine.test.js # Engine unit tests +│ └── integration.test.js # End-to-end tests +├── example/ # Example project +│ ├── project.json # Project configuration +│ ├── sample.csv # Sample data +│ ├── style.css # Custom styling +│ └── template-v2.svg # SVG template +└── TEMPLATE_V2_GUIDE.md # Comprehensive template documentation +``` + +## Testing Guidelines + +When writing tests: +- Use Vitest's `describe()` and `it()` structure +- Mock browser APIs (localStorage, fetch) using jsdom +- Test template validation separately from rendering +- Test date parsing for all supported formats +- Test field mapping edge cases (missing fields, null values) +- Integration tests should cover full project loading → CSV parsing → SVG generation flow + +## Important Implementation Details + +**Template Validation** (generator.js:54-70): Always validate templates before attempting to generate SVG. Check for all three required template IDs. + +**Template Extraction** (generator.js:73-82): Use regex to extract template elements from ``. Throws error if extraction fails (indicates malformed template). + +**XML Escaping** (generator.js:216-223): Always escape user data (titles, lane names) when injecting into SVG to prevent malformed XML. + +**Date Parsing** (engine.js:385-408): Supports multiple formats with fallback to `new Date()`. Returns null for invalid dates, which causes items to be filtered out. + +**Project Base Path Resolution** (engine.js:148-157): Relative paths in project.json are resolved relative to the project folder (e.g., `example/`). This enables projects to reference their own resources. + +**Debug Information Panel**: Shows field mappings, template placeholders, and CSV preview to help diagnose configuration issues. Automatically displayed when project loads. + +## Common Development Tasks + +When adding new placeholder types: +1. Add to placeholder documentation in TEMPLATE_V2_GUIDE.md +2. Update generator.js placeholder replacement logic if needed +3. Update example templates to demonstrate usage +4. Add tests for the new placeholder type + +When modifying layout: +1. Update layout constants in generator.js:41-45 +2. Update placeholder value calculations in generateFromTemplates() +3. Update TEMPLATE_V2_GUIDE.md with new dimensions +4. Regenerate example SVGs to verify + +When adding CSV field support: +1. Update fieldMapping documentation in README.md +2. Update example project.json files +3. Add to processCsv() in engine.js +4. Update generator to expose as placeholder +5. Add tests for field mapping + +## Template Development + +See TEMPLATE_V2_GUIDE.md for comprehensive template creation and customization documentation. Key points: + +- Templates must have all three required `` elements in `` +- Use `style="display:none"` on template elements to hide them +- All placeholders use `{{UPPERCASE_NAME}}` format +- Templates are standard SVG - edit in any SVG editor +- Test templates by loading them in the UI and checking debug panel + +## Migration Notes + +The codebase uses template-v2 architecture. Legacy template-v1 (macro-based) is deprecated. When working with old projects: +- Convert macro-based templates to template-v2 format +- Move template definitions into `` section +- Update placeholder names to match conventions +- Use `placeholderMapping` if preserving legacy placeholder names diff --git a/Makefile b/Makefile index 291741e..8f95d2c 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,8 @@ help: # Development setup install: @echo "Installing development dependencies..." - npm install + @# Workaround for Node.js v24 + OpenSSL 3.x in WSL (ERR_SSL_CIPHER_OPERATION_FAILED) + @export NODE_OPTIONS="--openssl-legacy-provider" && npm install @echo "✅ Dependencies installed" # Testing targets diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md new file mode 100644 index 0000000..f22bc7b --- /dev/null +++ b/TROUBLESHOOTING.md @@ -0,0 +1,376 @@ +# Troubleshooting Guide + +This document provides solutions to common issues encountered when developing with TimelineSvg. + +## Quick Reference + +| Problem | Quick Fix | See Section | +|---------|-----------|-------------| +| `npm install` fails with SSL cipher errors in WSL | `export NODE_OPTIONS="--openssl-legacy-provider" && npm install` | [npm Install Failures](#npm-install-failures-in-wsl-with-nodejs-v24) | +| CORS errors when opening index.html | `make serve` or `python3 -m http.server 8000` | [CORS Errors](#cors-errors-when-loading-timeline) | +| "Template is missing required elements" | Check `` section has all 3 template IDs | [Template Validation](#template-validation-errors) | +| CSV loads but shows 0 valid items | Verify `fieldMapping` matches CSV column names | [CSV Data Not Loading](#csv-data-not-loading) | +| Tests failing or timing out | `make clean && make install` | [Tests Failing](#tests-failing) | + +--- + +## npm Install Failures in WSL with Node.js v24 + +### Problem Description + +**Symptoms:** +- `npm install` fails with error: `ERR_SSL_CIPHER_OPERATION_FAILED` +- Error message contains: `Provider routines:ossl_gcm_stream_update:cipher operation failed` +- May also see `ETXTBSY` (text file busy) errors during esbuild installation +- Occurs specifically in WSL (Windows Subsystem for Linux) environments +- Appears with Node.js v24.x + +**Error Example:** +``` +npm error code ERR_SSL_CIPHER_OPERATION_FAILED +npm error C09CD49A5C750000:error:1C800066:Provider routines:ossl_gcm_stream_update:cipher operation failed:../deps/openssl/openssl/providers/implementations/ciphers/ciphercommon_gcm.c:346: +``` + +### Root Cause + +Node.js v24 upgraded to OpenSSL 3.x, which introduced stricter cipher requirements and different default providers. When running in WSL, there's a compatibility issue between: +- Node.js v24's OpenSSL 3.x implementation +- WSL's kernel/filesystem handling of cryptographic operations +- npm's package extraction process (which uses encryption for tar.gz files) + +The cipher operation fails during package decompression, preventing successful installation. + +### Solution + +**Quick Fix (Recommended):** + +Use the provided Makefile, which includes the workaround: +```bash +make install +``` + +**Manual Fix:** + +If not using the Makefile, set the `NODE_OPTIONS` environment variable before running npm: +```bash +export NODE_OPTIONS="--openssl-legacy-provider" +npm install +``` + +**Permanent Fix (for your shell session):** + +Add to your `~/.bashrc` or `~/.zshrc`: +```bash +export NODE_OPTIONS="--openssl-legacy-provider" +``` + +Then reload your shell: +```bash +source ~/.bashrc +``` + +### Step-by-Step Recovery + +If you're in a broken state with partial installation: + +1. **Clean everything:** + ```bash + rm -rf node_modules package-lock.json + npm cache clean --force + ``` + +2. **Install with workaround:** + ```bash + export NODE_OPTIONS="--openssl-legacy-provider" + npm install + ``` + +3. **Verify installation:** + ```bash + npm test + ``` + + Should show: `58 passed (58)` across 3 test files + +### Alternative Solutions + +**Option A: Use Node.js v22 (LTS)** + +If you don't need Node.js v24 features: +```bash +# Using nvm (Node Version Manager) +nvm install 22 +nvm use 22 +npm install +``` + +Node.js v22 uses OpenSSL 1.1.1 and doesn't have this issue. + +**Option B: Use npm's legacy peer deps flag** + +Sometimes combining flags helps: +```bash +export NODE_OPTIONS="--openssl-legacy-provider" +npm install --legacy-peer-deps +``` + +### Prevention + +**For New Projects:** + +Update your project's documentation and Makefile to include the workaround automatically. See the current `Makefile` for reference. + +**For CI/CD:** + +Add to your CI configuration: +```yaml +# GitHub Actions example +env: + NODE_OPTIONS: "--openssl-legacy-provider" + +# GitLab CI example +variables: + NODE_OPTIONS: "--openssl-legacy-provider" +``` + +### Verification + +After applying the fix, verify with: + +```bash +# Check Node.js version +node --version # Should show v24.x.x + +# Check installation succeeded +ls -la node_modules | head -5 + +# Run tests to confirm everything works +npm test + +# Expected output: +# ✓ Test Files 3 passed (3) +# ✓ Tests 58 passed (58) +``` + +### Related Issues + +- **esbuild ETXTBSY errors**: Often occur together with SSL cipher errors. The same solution fixes both. +- **Vitest installation failures**: Vitest depends on esbuild, so the fix resolves Vitest installation issues too. + +### When This Won't Help + +This solution specifically addresses Node.js v24 + OpenSSL 3.x + WSL issues. It won't help with: +- Network connectivity problems (check `npm config get registry`) +- Permissions issues (avoid `sudo npm install`, use `nvm` instead) +- Disk space problems (check with `df -h`) +- Corrupted npm cache (run `npm cache verify`) + +--- + +## CORS Errors When Loading Timeline + +### Problem Description + +**Symptoms:** +- Opening `index.html` directly in browser (file:// protocol) +- Console shows CORS errors when trying to load CSV, CSS, or SVG files +- Timeline doesn't render, shows "Keine Timeline verfügbar" + +### Solution + +Serve the application via HTTP: + +```bash +# Using the Makefile (recommended) +make serve + +# Or manually with Python 3 +python3 -m http.server 8000 + +# Or with Python 2 +python -m SimpleHTTPServer 8000 + +# Or with Node.js/npx +npx serve -l 8000 +``` + +Then open: `http://localhost:8000` + +### Why This Happens + +Browsers enforce CORS (Cross-Origin Resource Sharing) restrictions on `file://` URLs for security. Loading external resources (CSV, CSS, SVG) requires HTTP protocol. + +--- + +## Template Validation Errors + +### Problem Description + +**Symptoms:** +- Error: "Template is missing required elements: month-template" +- Error: "Failed to extract template element" +- Template renders but with empty placeholders + +### Solution + +**Check template structure:** + +1. Open your `template-v2.svg` in a text editor +2. Verify it has a `` section +3. Ensure all three required template elements exist: + ```svg + + + + + + ``` + +4. Check that IDs are exactly as shown (case-sensitive) +5. Verify templates contain proper placeholders (e.g., `{{MONTH_X}}`, `{{LANE_NAME}}`) + +**Common mistakes:** +- Template elements outside `` section +- Incorrect `id` attributes (e.g., `month_template` instead of `month-template`) +- Missing `style="display:none"` (causes templates to show in output) +- Malformed XML/SVG (unclosed tags) + +**Quick fix:** + +Copy a working template from `example/template-v2.svg` and modify it. + +See `TEMPLATE_V2_GUIDE.md` for comprehensive template documentation. + +--- + +## CSV Data Not Loading + +### Problem Description + +**Symptoms:** +- CSV file loads but no items appear +- Debug panel shows "Valid Items: 0" +- Console shows "Keine gültigen Items gefunden" + +### Solution + +**Check field mappings:** + +1. Open debug panel in the UI (should show automatically) +2. Compare "CSV Structure Preview" headers with "Field Mapping" +3. Ensure `project.json` field mappings match your CSV column names exactly + +**Example:** + +If your CSV has: +```csv +Task_ID,Task_Name,Due_Date,Epic +``` + +Your `project.json` must have: +```json +{ + "fieldMapping": { + "id": "Task_ID", + "title": "Task_Name", + "lane": "Epic", + "due": ["Due_Date"] + } +} +``` + +**Check date formats:** + +Supported formats: +- `YYYY-MM-DD` (e.g., `2025-12-31`) +- `YYYY/MM/DD` (e.g., `2025/12/31`) +- `DD.MM.YYYY` (e.g., `31.12.2025`) + +Unsupported formats will cause items to be filtered out. + +### Verification + +Look at the debug panel: +- "Parsed Rows" should match your CSV row count +- "Valid Items" should equal "Parsed Rows" (or close to it) +- If they differ significantly, check date formats and required fields + +--- + +## Tests Failing + +### Problem Description + +**Symptoms:** +- `npm test` fails with errors +- Tests timeout or hang +- jsdom errors + +### Solution + +**Basic troubleshooting:** + +1. **Reinstall dependencies:** + ```bash + make clean + make install + ``` + +2. **Check Node.js version:** + ```bash + node --version # Should be v22+ or v24+ + ``` + +3. **Run specific test file:** + ```bash + npm test test/generator.test.js + ``` + +4. **Check test environment:** + ```bash + cat vitest.config.js + ``` + Should show `environment: 'jsdom'` + +5. **Clear Vitest cache:** + ```bash + rm -rf .vitest node_modules/.vitest + npm test + ``` + +### Expected Test Results + +All tests passing: +``` +✓ test/generator.test.js (36 tests) +✓ test/engine.test.js (7 tests) +✓ test/integration.test.js (15 tests) + +Test Files 3 passed (3) +Tests 58 passed (58) +``` + +--- + +## Need More Help? + +1. Check existing documentation: + - `README.md` - Overview and features + - `TEMPLATE_V2_GUIDE.md` - Template creation and customization + - `CLAUDE.md` - Architecture and development guide + +2. Enable debug mode: + - Debug panel shows automatically when loading projects + - Check browser console for detailed error messages + +3. Verify file paths: + - All paths in `project.json` are relative to the project folder + - Use forward slashes (`/`) not backslashes (`\`) + +4. Test with example project: + ```bash + # Open browser to http://localhost:8000 + # Example project should auto-load successfully + ``` + + If example works but your project doesn't, compare configurations.