// Package encoders contains functions for rendering template.Block to a string. package encoders import ( "bytes" "fmt" "strings" "git.max-richter.dev/max/marka/renderer/utils" "git.max-richter.dev/max/marka/template" ) const emptyBlock = "\uE000" func fixRenderedBlock(input string) string { input = strings.ReplaceAll(input, "'@type':", "@type:") input = strings.ReplaceAll(input, "'@context':", "@context:") if len(input) == 0 { return emptyBlock } return input } // RenderBlock renders a single template block using the provided data. func RenderBlock(block template.Block, data map[string]any) (string, error) { if block.Type == template.MatchingBlock { return block.GetContent(), nil } value, found := utils.GetValueFromPath(data, block.Path) if !found { return "", nil // If not found and not required, return empty string } switch block.Codec { case template.CodecText: return fmt.Sprintf("%v", value), nil case template.CodecYaml: return RenderYaml(data, block) case template.CodecList: return RenderList(value, block) case template.CodecConst: return fmt.Sprintf("%v", block.Value), nil default: return "", fmt.Errorf("unknown codec: %s for path '%s'", block.Codec, block.Path) } } func Render(data map[string]any, blocks []template.Block) (string, error) { var buffer bytes.Buffer for _, block := range blocks { renderedContent, err := RenderBlock(block, data) if err != nil { return "", fmt.Errorf("failed to render block for path '%s': %w", block.Path, err) } renderedContent = fixRenderedBlock(renderedContent) buffer.WriteString(renderedContent) } outputString := buffer.String() outputString = strings.ReplaceAll(outputString, "\n\n"+emptyBlock+"\n\n", "\n\n") outputString = strings.ReplaceAll(outputString, "\n"+emptyBlock+"\n", "\n") outputString = strings.ReplaceAll(outputString, emptyBlock, "") if !strings.HasSuffix(outputString, "\n") { outputString += "\n" } return outputString, nil }