skills_languages are renderd correctly into its blocks

This commit is contained in:
2025-12-24 06:53:37 +01:00
parent 4782fd3f85
commit 0bae6b4b40
4 changed files with 80 additions and 22 deletions
+13 -1
View File
@@ -201,6 +201,10 @@ func (p *Paginator) PaginateMultiList(dataMap map[string]interface{}, templateNa
tracker, exists := listTrackers[trackerKey] tracker, exists := listTrackers[trackerKey]
if !exists { if !exists {
// Skip blocks with NOEMPTY flag when they have no data
if block.NoEmpty {
continue
}
// Block has no data, fill with empty items up to MAX // Block has no data, fill with empty items up to MAX
pageData[block.Name] = p.createEmptySliceWithCapacity(block.ListType, block.MaxItems) pageData[block.Name] = p.createEmptySliceWithCapacity(block.ListType, block.MaxItems)
continue continue
@@ -213,9 +217,17 @@ func (p *Paginator) PaginateMultiList(dataMap map[string]interface{}, templateNa
itemsToTake = remaining itemsToTake = remaining
} }
// Extract slice for this block and fill to capacity // Skip NOEMPTY blocks when no items remain
if block.NoEmpty && itemsToTake == 0 {
continue
}
// Extract slice for this block
blockItems := p.extractSlice(tracker.items, tracker.currentIdx, itemsToTake) blockItems := p.extractSlice(tracker.items, tracker.currentIdx, itemsToTake)
// Always fill to capacity (both normal and NOEMPTY blocks get filled when they have items)
blockItems = p.fillSliceToCapacity(blockItems, block.MaxItems) blockItems = p.fillSliceToCapacity(blockItems, block.MaxItems)
pageData[block.Name] = blockItems pageData[block.Name] = blockItems
tracker.currentIdx += itemsToTake tracker.currentIdx += itemsToTake
} }
+1
View File
@@ -20,6 +20,7 @@ type BlockMetadata struct {
MaxItems int // Maximum number of items this block can display MaxItems int // Maximum number of items this block can display
Filter string // Optional filter criteria (e.g., "learned", "unlearned", "languages") Filter string // Optional filter criteria (e.g., "learned", "unlearned", "languages")
Column int // Column number for multi-column layouts (0 if single column) Column int // Column number for multi-column layouts (0 if single column)
NoEmpty bool // If true, remove this block when it contains no items
} }
// TemplateSet contains all templates and their metadata for a format // TemplateSet contains all templates and their metadata for a format
+40 -10
View File
@@ -7,33 +7,63 @@ import (
) )
// ParseTemplateMetadata extracts block metadata from HTML comments in template content // ParseTemplateMetadata extracts block metadata from HTML comments in template content
// Format: <!-- BLOCK: name, TYPE: type, MAX: number, FILTER: filter --> // Format: <!-- BLOCK: name, TYPE: type, MAX: number, FILTER: filter, NOEMPTY -->
func ParseTemplateMetadata(templateContent string) []BlockMetadata { func ParseTemplateMetadata(templateContent string) []BlockMetadata {
blocks := []BlockMetadata{} blocks := []BlockMetadata{}
// Regex to match: <!-- BLOCK: name, TYPE: type, MAX: number, FILTER: filter --> // Simple regex to find all BLOCK comments
re := regexp.MustCompile(`<!--\s*BLOCK:\s*([^,]+),\s*TYPE:\s*([^,]+),\s*MAX:\s*(\d+)(?:,\s*FILTER:\s*([^-]+))?\s*-->`) re := regexp.MustCompile(`<!--\s*BLOCK:([^>]+)-->`)
matches := re.FindAllStringSubmatch(templateContent, -1) matches := re.FindAllStringSubmatch(templateContent, -1)
for _, match := range matches { for _, match := range matches {
if len(match) < 4 { if len(match) < 2 {
continue continue
} }
name := strings.TrimSpace(match[1]) // Parse the content of the BLOCK comment
listType := strings.TrimSpace(match[2]) blockContent := match[1]
maxItems, _ := strconv.Atoi(strings.TrimSpace(match[3]))
filter := "" // Extract BLOCK name
if len(match) > 4 && match[4] != "" { nameRe := regexp.MustCompile(`BLOCK:\s*([^,]+)`)
filter = strings.TrimSpace(match[4]) if !nameRe.MatchString(match[0]) {
continue
} }
nameMatch := nameRe.FindStringSubmatch(match[0])
name := strings.TrimSpace(nameMatch[1])
// Extract TYPE
typeRe := regexp.MustCompile(`TYPE:\s*([^,]+)`)
typeMatch := typeRe.FindStringSubmatch(blockContent)
if typeMatch == nil {
continue
}
listType := strings.TrimSpace(typeMatch[1])
// Extract MAX
maxRe := regexp.MustCompile(`MAX:\s*(\d+)`)
maxMatch := maxRe.FindStringSubmatch(blockContent)
if maxMatch == nil {
continue
}
maxItems, _ := strconv.Atoi(strings.TrimSpace(maxMatch[1]))
// Extract FILTER (optional)
filter := ""
filterRe := regexp.MustCompile(`FILTER:\s*([^,]+)`)
filterMatch := filterRe.FindStringSubmatch(blockContent)
if filterMatch != nil {
filter = strings.TrimSpace(filterMatch[1])
}
// Check for NOEMPTY flag (optional)
noEmpty := strings.Contains(blockContent, "NOEMPTY")
blocks = append(blocks, BlockMetadata{ blocks = append(blocks, BlockMetadata{
Name: name, Name: name,
ListType: listType, ListType: listType,
MaxItems: maxItems, MaxItems: maxItems,
Filter: filter, Filter: filter,
NoEmpty: noEmpty,
}) })
} }
+26 -11
View File
@@ -37,17 +37,32 @@
<tr><td>{{.Name}}{{if .Bemerkung}}:<span style="font-size: smaller;">{{.Bemerkung}}</span>{{end}}</td><td>{{if .Value}}+ {{.Value}}{{else}}&nbsp;{{end}}</td><td>{{if .PracticePoints}}{{.PracticePoints}}{{end}}</td></tr> <tr><td>{{.Name}}{{if .Bemerkung}}:<span style="font-size: smaller;">{{.Bemerkung}}</span>{{end}}</td><td>{{if .Value}}+ {{.Value}}{{else}}&nbsp;{{end}}</td><td>{{if .PracticePoints}}{{.PracticePoints}}{{end}}</td></tr>
{{end}} {{end}}
</table> </table>
<!-- BLOCK: skills_languages, TYPE: skills, MAX: 4, FILTER: language --> <div class="skills-stack">
<table class="skills-table" style="width: 100%; height: unset;"> <!-- BLOCK: skills_languages, TYPE: skills, MAX: 6, FILTER: language, NOEMPTY -->
<tr> {{if .SkillsLanguage}}{{if (index .SkillsLanguage 0).Name}}
<th>Fertigkeit</th> <table class="skills-table" style="width: 100%; height: unset;">
<th>EW</th> <tr>
<th>PP</th> <th>Fertigkeit</th>
</tr> <th>EW</th>
{{range .SkillsLanguage}} <th>PP</th>
<tr><td>{{.Name}}{{if .Bemerkung}}:<span style="font-size: smaller;">{{.Bemerkung}}</span>{{end}}</td><td>{{if .Value}}+ {{.Value}}{{else}}&nbsp;{{end}}</td><td>{{if .PracticePoints}}{{.PracticePoints}}{{end}}</td></tr> </tr>
{{end}} {{range .SkillsLanguage}}
</table> <tr><td>{{.Name}}{{if .Bemerkung}}:<span style="font-size: smaller;">{{.Bemerkung}}</span>{{end}}</td><td>{{if .Value}}+ {{.Value}}{{else}}&nbsp;{{end}}</td><td>{{if .PracticePoints}}{{.PracticePoints}}{{end}}</td></tr>
{{end}}
</table>
{{end}}{{end}}
<!-- BLOCK: skills_learned, TYPE: skills, MAX: 10, FILTER: learned -->
<table class="skills-table" style="width: 100%; height: unset;">
<tr>
<th>Fertigkeit</th>
<th>EW</th>
<th>PP</th>
</tr>
{{range .SkillsLearned}}
<tr><td>{{.Name}}{{if .Bemerkung}}:<span style="font-size: smaller;">{{.Bemerkung}}</span>{{end}}</td><td>{{if .Value}}+ {{.Value}}{{else}}&nbsp;{{end}}</td><td>{{if .PracticePoints}}{{.PracticePoints}}{{end}}</td></tr>
{{end}}
</table>
</div>
</div> </div>
</div> </div>
<!-- Right section --> <!-- Right section -->