Files
timeline-svg/PROTOTYPE_TEMPLATES.md
tegwick 5bec61740b feat: add DOM-based prototype template system for full Inkscape editability
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>
2026-01-23 23:50:37 +01:00

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

  1. 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
  2. Generator Clones Prototypes

    • Each prototype is deep-cloned using DOM
    • Positioned using SVG transforms
    • Text content updated from your data
    • Appended to target containers
  3. Prototypes Hidden

    • Original prototypes are hidden (display:none) after cloning
    • Only the cloned, data-filled elements remain visible

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

  1. Open Inkscape
  2. Create new document (File → New)
  3. Set document size (recommended: 1200x800px)

Step 2: Design Your Month Prototype

  1. Create a group (Ctrl+G) and name it month-proto in the Object Properties panel
  2. Add elements:
    • Vertical line for grid separator
    • Text label for month name
  3. Style using Inkscape's fill, stroke, font tools
  4. Position at x=220 (will be translated for each month)

Step 3: Design Your Lane Prototype

  1. Create group named lane-proto
  2. Add elements:
    • Rectangle for background
    • Text label for lane name
  3. Style as desired (gradients, rounded corners, etc.)
  4. Position at y=140 (will be translated for each lane)

Step 4: Design Your Item Prototype

  1. Create group named item-proto
  2. Add elements:
    • Shape (circle, rect, path) for marker
    • Text elements for title, ID, or other fields
  3. Give text elements IDs like item-title, item-id
  4. Position at x=280, y=150

Step 5: Add Containers

  1. Create three empty groups:
    • months-container
    • lanes-container
    • items-container
  2. 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

  1. Save as Plain SVG (not Inkscape SVG)
  2. 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 month
  • marginTop: Top margin before first lane
  • monthWidth: Horizontal space for each month
  • laneHeight: Vertical space for each lane
  • laneGap: 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:

  1. Open your template-v2.svg in Inkscape
  2. Rename template elements:
    • month-templatemonth-proto
    • lane-templatelane-proto
    • item-templateitem-proto
  3. Replace {{PLACEHOLDERS}} with actual sample text
  4. Add IDs to text elements (e.g., id="item-title")
  5. Create container groups
  6. Save and test

Troubleshooting

Prototypes Not Found

Error: Template is missing required prototype elements

Solution: Ensure your SVG has groups with exact IDs:

  • month-proto
  • lane-proto
  • item-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:

  1. Use CSS classes in your prototypes, define in <style> section
  2. Or use inline SVG attributes (fill, stroke, etc.)
  3. Avoid Inkscape-specific attributes

Parse Errors

Error: Failed to parse SVG template

Solution:

  1. Save as "Plain SVG" not "Inkscape SVG"
  2. Check SVG is valid XML (balanced tags, proper nesting)
  3. Remove Inkscape-specific elements if present

Best Practices

  1. Keep Prototypes Simple - Complex nested structures may be harder to position
  2. Use CSS Classes - Easier to style consistently than inline attributes
  3. Test Incrementally - Start with basic shapes, add detail gradually
  4. Use Inkscape Layers - Keep prototypes on separate layer for organization
  5. Set Prototype Opacity - Makes them visible but distinguishable from final output
  6. 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.md for generator implementation details
  • Check README.md for 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