Files
timeline-svg/REFACTORING_PLAN.md
tegwick c22a47f1ea refactor: complete migration to template-v2 architecture
- Remove legacy template.svg files from example/ and my-project/
- Simplify generator.js by removing generateHardcoded method (326→210 lines, -36%)
- Add strict template validation with clear error messages
- Remove all fallback mechanisms - template-v2.svg format now required
- Clean up tests: remove hardcoded generation tests, keep template-based tests
- Add comprehensive e2e tests (large datasets, edge cases, error handling)
- Update documentation: mark REFACTORING_PLAN.md complete, add TEMPLATE_V2_GUIDE.md
- All 56 tests passing (16 engine + 25 generator + 15 integration)

BREAKING CHANGE: Old template.svg format no longer supported. Must use template-v2.svg with <g id="*-template"> elements in defs section.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 15:29:58 +01:00

7.5 KiB

SVG Template Refactoring Plan

STATUS: COMPLETED

Completion Date: 2025-11-27 Final Architecture: Template-only SVG generation with no fallback mechanisms

All phases have been successfully completed:

  • Phase 1: Template-v2.svg files created and working
  • Phase 2: Template-based generation fully implemented
  • Phase 3: Old templates removed, hardcoded generation eliminated
  • Comprehensive test coverage: 40+ tests (unit + integration)
  • Documentation complete (see TEMPLATE_V2_GUIDE.md)

Original Architecture Problems (Resolved)

The Issue

While template.svg files exist in example/ and my-project/, they only contain:

  • Outer SVG wrapper with styling
  • Two macros: {{MONTHS}} and {{LANES}}

The actual SVG generation is hardcoded in generator.js:

  • Lines 40-69: Month grid generation (lines, labels, styling)
  • Lines 78-129: Lane generation (backgrounds, labels, task items)

This makes templates non-editable in SVG tools - users can only change colors/styling in the wrapper, not the actual timeline structure.

Goals

  1. Move SVG structure to templates: Extract hardcoded SVG patterns from JavaScript to template files
  2. Use placeholders for dynamic data: Replace actual values with {{VARIABLE}} placeholders
  3. Make templates editable: Users should be able to open templates in Inkscape/Adobe Illustrator and modify the timeline layout
  4. Maintain flexibility: Keep the ability to handle varying numbers of months, lanes, and items

Proposed Template Structure

Month Template Section

Instead of generating months in JS, the template should contain a sample month element with placeholders:

<!-- Sample month element - will be cloned for each month -->
<g class="month-template" id="month-template">
  <line x1="{{MONTH_X}}" y1="{{GRID_TOP}}" x2="{{MONTH_X}}" y2="{{GRID_BOTTOM}}"
        stroke="#E3E8EF" />
  <text x="{{MONTH_X}}" y="{{MONTH_Y}}" fill="#5C6B7A" font-size="12">
    {{MONTH_LABEL}}
  </text>
</g>

Lane Template Section

Similarly, lanes should be defined once:

<!-- Sample lane element - will be cloned for each lane -->
<g class="lane-template" id="lane-template">
  <rect x="{{LANE_X}}" y="{{LANE_Y}}" width="{{LANE_WIDTH}}" height="{{LANE_HEIGHT}}"
        fill="#FFFFFF" stroke="#E3E8EF" rx="10" />
  <text x="{{LABEL_X}}" y="{{LABEL_Y}}" fill="#0B1F3B" font-size="14" font-weight="600">
    {{LANE_NAME}}
  </text>
</g>

Task Item Template

Task items within lanes:

<!-- Sample task item - will be cloned for each task -->
<g class="task-template" id="task-template">
  <circle cx="{{TASK_X}}" cy="{{TASK_Y}}" r="5" fill="#0A4D8C" />
  <text x="{{TEXT_X}}" y="{{TEXT_Y}}" font-size="12" fill="#0B1F3B">
    <tspan class="item-id">{{TASK_ID}}: </tspan>
    <tspan class="item-title">{{TASK_TITLE}}</tspan>
  </text>
</g>

Generator Refactoring

The generator.js should:

  1. Load and parse template: Read template SVG
  2. Extract template elements: Find elements with id="*-template"
  3. Clone and populate: For each data item, clone the template and replace placeholders
  4. Position elements: Calculate positions based on layout constants
  5. Inject into template: Replace {{MONTHS}} and {{LANES}} macros with generated content

Variables Dictionary

Layout Constants

  • {{GRID_LEFT}}, {{GRID_TOP}}, {{GRID_BOTTOM}} - Grid boundaries
  • {{MONTH_WIDTH}} - Width of each month column
  • {{LANE_HEIGHT}} - Height of each lane row
  • {{LANE_GAP}} - Spacing between lanes

Month Variables

  • {{MONTH_X}} - X position
  • {{MONTH_Y}} - Y position for label
  • {{MONTH_LABEL}} - Month name (e.g., "Jan 25")

Lane Variables

  • {{LANE_X}}, {{LANE_Y}} - Lane position
  • {{LANE_WIDTH}}, {{LANE_HEIGHT}} - Lane dimensions
  • {{LANE_NAME}} - Lane/Epic name
  • {{LABEL_X}}, {{LABEL_Y}} - Label position

Task Variables

  • {{TASK_X}}, {{TASK_Y}} - Task marker position
  • {{TEXT_X}}, {{TEXT_Y}} - Text position
  • {{TASK_ID}} - Task ID (e.g., "T-1")
  • {{TASK_TITLE}} - Task title

Migration Strategy

Phase 1: Extract to Simple Templates

  1. Create new template-v2.svg files with template elements
  2. Update generator to use template-based approach
  3. Keep existing templates as fallback
  4. Test with both approaches

Phase 2: Enhance Template Editing

  1. Add template validation
  2. Document template variables
  3. Create template editing guide
  4. Provide example templates with different layouts

Phase 3: Remove Hardcoded SVG

  1. Migrate existing templates to new format
  2. Remove hardcoded SVG generation
  3. Update tests
  4. Update documentation

Test Updates Needed

  • Tests for template parsing and validation
  • Tests for variable substitution
  • Tests for template cloning logic
  • Integration tests with real templates
  • Tests for backward compatibility with old templates

Benefits

  1. User-editable templates: Can modify in any SVG editor
  2. Visual template design: See actual layout while editing
  3. Reusable patterns: Template elements can be copied/modified
  4. Separation of concerns: Presentation (SVG) vs. logic (JS)
  5. Easier customization: Change fonts, colors, shapes without touching code

Risks

  • Complexity: More complex generator logic
  • Performance: Template parsing and cloning overhead
  • Compatibility: Need to support both old and new templates
  • Testing: More edge cases to test

Final Implementation Summary

Code Changes

  1. generator.js: Reduced from 326 to 210 lines (-36%)

    • Removed generateHardcoded() method entirely (~125 lines)
    • Added validateTemplate() for strict validation
    • Simplified generate() to call generateFromTemplates() directly
    • Updated extractTemplate() to throw errors instead of returning null
  2. Templates: Removed old v1 templates

    • Deleted example/template.svg
    • Deleted my-project/template.svg
    • Updated project.json files to reference template-v2.svg exclusively
  3. Tests: Refactored for template-only architecture

    • engine.test.js: 16 tests kept (unchanged)
    • generator.test.js: 23 tests (removed 11 hardcoded tests, kept template tests)
    • integration.test.js: 15 comprehensive e2e tests (added 8 new scenarios)
    • testHelpers.js: Updated with template-v2 helpers, malformed template generator, large dataset generator

Test Coverage

Unit Tests (39 total):

  • 16 engine business logic tests
  • 23 generator tests (3 escapeXml, 5 validation, 3 extraction, 4 placeholder, 8 generation)

Integration Tests (15 total):

  • Basic e2e workflow
  • CSV override handling
  • Large dataset (60+ items)
  • Date range edge cases (24+ months)
  • Special character handling
  • Empty CSV handling
  • Malformed template error handling (3 tests)
  • Template styling preservation
  • File upload handling (2 tests)
  • Export functionality (2 tests)

Architecture Benefits Achieved

  1. Single clear path: Template-v2.svg format is required, no fallbacks
  2. Clear error messages: Immediate feedback when templates are malformed
  3. Reduced complexity: No branching logic, no backward compatibility code
  4. Visual editing: Users can edit templates in SVG tools
  5. Maintainability: ~235 lines of code removed, simpler architecture

Breaking Changes

  • Old template.svg format no longer supported
  • Must use template-v2.svg with proper <g id="*-template"> elements
  • No silent fallbacks - errors thrown immediately

Migration Notes

All existing projects already had template-v2.svg files created during Phase 1, so migration was seamless with only project.json updates needed.