Implements a new templating approach that allows complete visual control
in Inkscape while maintaining 100% valid SVG.
New Features:
- DOM-based generator using DOMParser and cloneNode()
- Prototype elements (month-proto, lane-proto, item-proto) instead of string templates
- Full WYSIWYG editing in Inkscape - see exactly how timeline will look
- Auto-detection of template type (prototype vs template-v2)
- Text element mapping via IDs (e.g., id="item-title")
- SVG transforms for positioning instead of placeholder replacement
Implementation:
- generator-dom.js: New DOM-based generator with cloning logic
- engine.js: Auto-detect template type and use appropriate generator
- example-proto/: Complete working example with prototype template
- PROTOTYPE_TEMPLATES.md: Comprehensive guide for creating prototype templates
Benefits:
- No string placeholders ({{PLACEHOLDER}}) needed
- Native SVG editing workflow
- Better performance (DOM manipulation vs regex)
- Easier maintenance and styling
- Backward compatible (old template-v2 still works)
Template Structure:
- Prototypes with specific IDs visible in SVG (hidden after cloning)
- Container groups for generated content
- CSS classes for styling
- Text elements with IDs matching field names
All 56 tests still passing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9.1 KiB
Prototype-Based Templates Guide
Overview
The timeline generator now supports prototype-based templates using DOM cloning. This is the recommended approach for creating custom timeline designs because:
- ✅ 100% Valid SVG - Edit directly in Inkscape with full visual control
- ✅ WYSIWYG - See exactly how your timeline will look
- ✅ No String Placeholders - No need for
{{PLACEHOLDER}}syntax - ✅ Better Performance - Uses native DOM manipulation
- ✅ Easier Maintenance - Visual editing instead of code
How It Works
-
Create Prototypes in Inkscape
- Design visual elements (month headers, lanes, items) with specific IDs
- Style them exactly as you want them to appear
- The generator will clone these elements for each data item
-
Generator Clones Prototypes
- Each prototype is deep-cloned using DOM
- Positioned using SVG transforms
- Text content updated from your data
- Appended to target containers
-
Prototypes Hidden
- Original prototypes are hidden (
display:none) after cloning - Only the cloned, data-filled elements remain visible
- Original prototypes are hidden (
Template Structure
Required Prototype Elements
Your SVG must contain these three prototype groups:
<g id="month-proto">
<!-- Month header design -->
<line x1="0" y1="120" x2="0" y2="600" class="month-grid" />
<text x="4" y="90" class="month-label">Jan 25</text>
</g>
<g id="lane-proto">
<!-- Lane/swimlane design -->
<rect x="40" y="-24" width="1000" height="80" class="lane-bg" />
<text x="56" y="-4" class="lane-label">Lane Name</text>
</g>
<g id="item-proto">
<!-- Task/item marker design -->
<circle cx="0" cy="0" r="5" class="item-marker" />
<text x="12" y="4" class="item-title">Task Title</text>
<text x="12" y="-8" class="item-id">T-123</text>
</g>
Required Container Elements
The generator will place clones in these containers (created automatically if missing):
<g id="months-container"></g>
<g id="lanes-container"></g>
<g id="items-container"></g>
Text Element Mapping
Text elements in the item prototype are matched to your data fields:
- Elements with
id="item-{fieldname}"(e.g.,id="item-title",id="item-id") - Or elements with IDs containing the field name
- Or the first
<text>element if no specific match found
Example:
<g id="item-proto">
<text id="item-title">Placeholder Title</text>
<text id="item-id">T-000</text>
<text id="item-status">TODO</text>
</g>
Will map to CSV columns based on your fieldMapping in project.json:
{
"fieldMapping": {
"title": "Title",
"id": "ID",
"status": "Status"
}
}
Creating a Prototype Template in Inkscape
Step 1: Start with a Base SVG
- Open Inkscape
- Create new document (File → New)
- Set document size (recommended: 1200x800px)
Step 2: Design Your Month Prototype
- Create a group (Ctrl+G) and name it
month-protoin the Object Properties panel - Add elements:
- Vertical line for grid separator
- Text label for month name
- Style using Inkscape's fill, stroke, font tools
- Position at x=220 (will be translated for each month)
Step 3: Design Your Lane Prototype
- Create group named
lane-proto - Add elements:
- Rectangle for background
- Text label for lane name
- Style as desired (gradients, rounded corners, etc.)
- Position at y=140 (will be translated for each lane)
Step 4: Design Your Item Prototype
- Create group named
item-proto - Add elements:
- Shape (circle, rect, path) for marker
- Text elements for title, ID, or other fields
- Give text elements IDs like
item-title,item-id - Position at x=280, y=150
Step 5: Add Containers
- Create three empty groups:
months-containerlanes-containeritems-container
- These can be anywhere - they're just containers
Step 6: Add Styles
Use Inkscape's built-in styles or add a <style> section:
<defs>
<style>
.month-label { font-family: Arial; font-size: 11px; fill: #666; }
.lane-bg { fill: #f8f9fa; stroke: #e9ecef; }
.item-marker { fill: #007bff; }
</style>
</defs>
Step 7: Save and Use
- Save as Plain SVG (not Inkscape SVG)
- Reference in your project.json:
{ "svgTemplate": "template-proto.svg" }
Configuration Options
Layout Settings
Control spacing and positioning in your project.json:
{
"settings": {
"timelineMonths": 18,
"marginLeft": 220,
"marginTop": 140,
"monthWidth": 120,
"laneHeight": 80,
"laneGap": 16
}
}
marginLeft: Left margin before first monthmarginTop: Top margin before first lanemonthWidth: Horizontal space for each monthlaneHeight: Vertical space for each lanelaneGap: Space between lanes
Examples
Example 1: Minimal Prototype Template
See example-proto/template-proto.svg for a complete working example.
Example 2: Custom Styling
<g id="item-proto">
<rect x="-8" y="-8" width="16" height="16"
fill="#007bff" rx="3" opacity="0.8"/>
<text x="12" y="4"
font-family="Arial" font-size="10px" font-weight="bold">
Task Title
</text>
</g>
Example 3: With Gradients
<defs>
<linearGradient id="laneGradient">
<stop offset="0%" stop-color="#ffffff"/>
<stop offset="100%" stop-color="#f0f0f0"/>
</linearGradient>
</defs>
<g id="lane-proto">
<rect fill="url(#laneGradient)" width="1000" height="80"/>
<text>Lane Name</text>
</g>
Migration from Template-v2
If you have existing template-v2.svg files, you can continue using them. The generator automatically detects which template type you're using:
- Prototype-based (new): Detected by
id="*-proto"elements → uses DOM generator - Template-v2 (old): Detected by
id="*-template"elements → uses string generator
To migrate:
- Open your template-v2.svg in Inkscape
- Rename template elements:
month-template→month-protolane-template→lane-protoitem-template→item-proto
- Replace
{{PLACEHOLDERS}}with actual sample text - Add IDs to text elements (e.g.,
id="item-title") - Create container groups
- Save and test
Troubleshooting
Prototypes Not Found
Error: Template is missing required prototype elements
Solution: Ensure your SVG has groups with exact IDs:
month-protolane-protoitem-proto
Check Object Properties panel in Inkscape (Ctrl+Shift+O).
Text Not Updating
Problem: Cloned items show placeholder text instead of data
Solution: Add IDs to text elements matching your field names:
<text id="item-title">Placeholder</text>
<text id="item-id">T-000</text>
Wrong Positioning
Problem: Elements appear in wrong locations
Solution: Prototypes should be positioned at a base location (e.g., x=220 for months). The generator adds transforms for each clone. Check that your marginLeft, marginTop, monthWidth, etc. settings match your prototype positions.
Styling Not Applied
Problem: Generated timeline doesn't have styles from Inkscape
Solution:
- Use CSS classes in your prototypes, define in
<style>section - Or use inline SVG attributes (fill, stroke, etc.)
- Avoid Inkscape-specific attributes
Parse Errors
Error: Failed to parse SVG template
Solution:
- Save as "Plain SVG" not "Inkscape SVG"
- Check SVG is valid XML (balanced tags, proper nesting)
- Remove Inkscape-specific elements if present
Best Practices
- Keep Prototypes Simple - Complex nested structures may be harder to position
- Use CSS Classes - Easier to style consistently than inline attributes
- Test Incrementally - Start with basic shapes, add detail gradually
- Use Inkscape Layers - Keep prototypes on separate layer for organization
- Set Prototype Opacity - Makes them visible but distinguishable from final output
- Document Your Template - Add comments or text notes explaining custom elements
Advanced: Custom Field Mapping
You can map CSV columns to any text element IDs:
{
"fieldMapping": {
"id": "ID",
"title": "Task Name",
"assignee": "Owner",
"status": "State"
}
}
Then in your prototype:
<g id="item-proto">
<text id="item-id">T-000</text>
<text id="item-title">Task placeholder</text>
<text id="item-assignee">Person</text>
<text id="item-status">Open</text>
</g>
Further Resources
- See
example-proto/for a complete working example - Read
CLAUDE.mdfor generator implementation details - Check
README.mdfor general usage instructions
Comparison: Prototype vs Template-v2
| Feature | Prototype (New) | Template-v2 (Old) |
|---|---|---|
| Inkscape Editing | ✅ Full WYSIWYG | ⚠️ Limited (placeholders) |
| Valid SVG | ✅ Yes | ✅ Yes |
| Visual Preview | ✅ See actual design | ⚠️ See placeholders |
| Syntax | Simple IDs | {{PLACEHOLDER}} |
| Performance | ✅ DOM cloning | String manipulation |
| Styling | Full Inkscape tools | CSS + inline |
| Learning Curve | Lower (visual) | Higher (syntax) |
| Recommended | ✅ Yes | For legacy only |