Files
timeline-svg/example/template-v2.svg
tegwick b17d6a30e4 refactor: implement template-based SVG generation
Implements the refactoring plan to move SVG structure from hardcoded JavaScript
to editable template files:

- Add template-v2.svg files with template elements in defs
- Create template elements for months, lanes, and tasks with placeholders
- Refactor generator.js to extract and clone template elements
- Add hasTemplateElements, extractTemplate, and replacePlaceholders methods
- Add generateFromTemplates method for template-based rendering
- Keep generateHardcoded method for backward compatibility
- Add comprehensive tests for new template system
- Support both v1 (hardcoded) and v2 (template-based) approaches

Benefits:
- Templates can now be edited in SVG tools (Inkscape, Adobe Illustrator)
- Visual template design with actual layout visible while editing
- Separation of presentation (SVG) and logic (JavaScript)
- Easier customization without touching code

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 09:10:18 +01:00

82 lines
3.5 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" style="background: linear-gradient(135deg, #f0f9f4 0%, #e6f7ea 100%);">
<defs>
<!-- Enhanced month indicator styling -->
<linearGradient id="monthHeaderGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#2d8659;stop-opacity:0.15"/>
<stop offset="100%" style="stop-color:#4a9b6b;stop-opacity:0.08"/>
</linearGradient>
<!-- Drop shadow for month labels -->
<filter id="textShadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="1" dy="1" stdDeviation="1.5" flood-color="#2d8659" flood-opacity="0.4"/>
</filter>
<!-- Subtle background grid pattern -->
<pattern id="bgGrid" width="40" height="40" patternUnits="userSpaceOnUse">
<rect width="40" height="40" fill="transparent"/>
<circle cx="20" cy="20" r="1" fill="#4a9b6b" opacity="0.1"/>
</pattern>
<!-- Template elements (hidden, will be cloned) -->
<g id="month-template" style="display: none;">
<line x1="{{MONTH_X}}" y1="{{GRID_TOP}}" x2="{{MONTH_X}}" y2="{{GRID_BOTTOM}}"
stroke="#4a9b6b" stroke-width="2" opacity="0.6"/>
<rect x="{{MONTH_X_OFFSET}}" y="{{MONTH_LABEL_Y_OFFSET}}" width="60" height="25"
fill="#2d8659" opacity="0.1" rx="4"/>
<text x="{{MONTH_TEXT_X}}" y="{{MONTH_LABEL_Y}}" fill="#2d8659"
font-size="13" font-weight="600">{{MONTH_LABEL}}</text>
<rect x="{{MONTH_SEP_X}}" y="{{GRID_TOP}}" width="2" height="{{GRID_HEIGHT}}"
fill="#4a9b6b" opacity="0.3"/>
</g>
<g id="lane-template" style="display: none;">
<rect x="{{LANE_X}}" y="{{LANE_Y}}" width="{{LANE_WIDTH}}" height="{{LANE_HEIGHT}}"
fill="rgba(255,255,255,0.7)" stroke="#4a9b6b" stroke-width="1" opacity="0.5" rx="8"/>
<text x="{{LABEL_X}}" y="{{LABEL_Y}}" fill="#2d8659"
font-size="14" font-weight="700">{{LANE_NAME}}</text>
</g>
<g id="task-template" style="display: none;">
<circle cx="{{TASK_X}}" cy="{{TASK_Y}}" r="6"
fill="#2d8659" stroke="#4a9b6b" stroke-width="2"/>
<text x="{{TEXT_X}}" y="{{TEXT_Y}}" font-size="12" fill="#2d8659" font-weight="500">
<tspan class="item-id">{{TASK_ID}}: </tspan>
<tspan class="item-title" fill="#1e5a3d">{{TASK_TITLE}}</tspan>
</text>
</g>
</defs>
<!-- Background with subtle pattern -->
<rect width="100%" height="100%" fill="url(#bgGrid)"/>
<!-- Enhanced month header background -->
<rect x="0" y="0" width="100%" height="130" fill="url(#monthHeaderGrad)"
stroke="#2d8659" stroke-width="1" opacity="0.6"/>
<!-- Title area with visual indicator -->
<rect x="10" y="10" width="300" height="60" fill="#ffffff"
stroke="#2d8659" stroke-width="2" rx="8" opacity="0.9"/>
<text x="20" y="35" fill="#2d8659" font-size="16" font-weight="bold" filter="url(#textShadow)">
📊 Template V2 Active
</text>
<text x="20" y="55" fill="#4a9b6b" font-size="11" font-weight="500">
Template-based rendering with cloned elements ✨
</text>
<!-- Month indicators with enhanced styling -->
<g class="enhanced-months" transform="translate(0,0)">
<rect x="0" y="75" width="100%" height="55" fill="rgba(45, 134, 89, 0.05)"
stroke="#4a9b6b" stroke-width="1"/>
{{MONTHS}}
</g>
<!-- Lane content -->
<g class="enhanced-lanes">
{{LANES}}
</g>
<!-- Decorative border -->
<rect x="1" y="1" width="calc(100% - 2)" height="calc(100% - 2)"
fill="none" stroke="#2d8659" stroke-width="2" rx="4" opacity="0.7"/>
</svg>