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:
22
engine.js
22
engine.js
@@ -389,7 +389,25 @@ window.timelineEngine = {
|
||||
|
||||
try {
|
||||
console.log("Generating timeline with:", items, self.config, self.template ? "template loaded" : "no template");
|
||||
const svg = window.timelineGenerator.generate(items, self.config, self.template);
|
||||
|
||||
// Auto-detect template type: prototype-based (new) or template-based (old)
|
||||
const isPrototypeBased = self.template && (
|
||||
self.template.includes('id="month-proto"') ||
|
||||
self.template.includes('id="lane-proto"') ||
|
||||
self.template.includes('id="item-proto"')
|
||||
);
|
||||
|
||||
let svg;
|
||||
if (isPrototypeBased && window.timelineGeneratorDOM) {
|
||||
console.log("Using DOM-based generator (prototype templates)");
|
||||
svg = window.timelineGeneratorDOM.generate(items, self.config, self.template);
|
||||
} else if (window.timelineGenerator) {
|
||||
console.log("Using string-based generator (template-v2)");
|
||||
svg = window.timelineGenerator.generate(items, self.config, self.template);
|
||||
} else {
|
||||
throw new Error("No timeline generator available");
|
||||
}
|
||||
|
||||
document.getElementById("viewer").innerHTML = svg;
|
||||
const dlBtn = document.getElementById("downloadSvg");
|
||||
dlBtn.disabled = false;
|
||||
@@ -405,7 +423,7 @@ window.timelineEngine = {
|
||||
} catch (error) {
|
||||
console.error("Error generating timeline:", error);
|
||||
document.getElementById("viewer").innerHTML =
|
||||
"<em style='color:#dc3545;'>Fehler beim Generieren der Timeline.</em>";
|
||||
"<em style='color:#dc3545;'>Fehler beim Generieren der Timeline: " + error.message + "</em>";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user