scriban

Scriban function to convert snake case to pascal/camel case


I'm trying to generate some C# code using Scriban templates. The DB I'm using is postgresql, so my tables and properties are all in snake_case. I managed to make a function to convert snake case to pascal case:

{{ for word in EntityName | string.split "_" -}} {{~word | string.capitalize}} {{-end}}

This does convert entity_name to the desired EntityName.

And camel case:

{{func split(en)
    ret en | string.split "_"
end}}

{{for index in 0..@split(EntityName).size -}} 
    {{-if index == 0}} {{~@split(EntityName)[index]-}} {{-else-}} {{-@split(EntityName)[index] | string.capitalize-}} {{-end-}}
{{-end}}

However, I need to use this function multiple times in my template, therefore I wanted to make a function I can use throughout the template, just like the split(en) function I use for the camel case conversion. So I could do something like this everywhere I need it:

{{ @convert(EntityName) }}

Is this possible, and if yes, how?

Any help would be appreciated!


Solution

  • I found another solution to my problem. Instead of creating functions in the template itself, I make a ScriptObject.

    public class ScribanHelper : ScriptObject
    {
        public static string ConvertToPascalCase(string word)
        {
            if (string.IsNullOrEmpty(word))
                return string.Empty;
    
            return string.Join("", word.Split('_')
                         .Select(w => w.Trim())
                         .Where(w => w.Length > 0)
                         .Select(w => w.Substring(0, 1).ToUpper() + w.Substring(1).ToLower()));
        }
    }
    

    And then I push this to the scriban context to use it in the templates.

    var context = new TemplateContext { MemberRenamer = member => member.Name };
    
    var scriptObject = new ScribanHelper();
    context.PushGlobal(scriptObject);
    
    var templateString = File.ReadAllText(templateSetting.Name);
    var template = Template.Parse(templateString);
    
    var entityScriptObject = new ScriptObject();
    entityScriptObject.Import(entity, renamer: member => member.Name);
    context.PushGlobal(entityScriptObject);
    
    var result = template.Render(context);
    

    And then I can easily use it in the templates.

    {{-func pc(name)
        ret convert_to_pascal_case name
    end}}
    
    {{@pc(EntityName)}}