generated from coulomb/repo-seed
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>
This commit is contained in:
339
PROTOTYPE_TEMPLATES.md
Normal file
339
PROTOTYPE_TEMPLATES.md
Normal file
@@ -0,0 +1,339 @@
|
||||
# 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:
|
||||
|
||||
```xml
|
||||
<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):
|
||||
|
||||
```xml
|
||||
<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:
|
||||
```xml
|
||||
<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:
|
||||
```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:
|
||||
|
||||
```xml
|
||||
<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:
|
||||
```json
|
||||
{
|
||||
"svgTemplate": "template-proto.svg"
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Layout Settings
|
||||
|
||||
Control spacing and positioning in your project.json:
|
||||
|
||||
```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
|
||||
|
||||
```xml
|
||||
<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
|
||||
|
||||
```xml
|
||||
<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-template` → `month-proto`
|
||||
- `lane-template` → `lane-proto`
|
||||
- `item-template` → `item-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:
|
||||
```xml
|
||||
<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:
|
||||
|
||||
```json
|
||||
{
|
||||
"fieldMapping": {
|
||||
"id": "ID",
|
||||
"title": "Task Name",
|
||||
"assignee": "Owner",
|
||||
"status": "State"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then in your prototype:
|
||||
```xml
|
||||
<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 |
|
||||
Reference in New Issue
Block a user