Page 1 of 1
Template engine?
Posted: Mon Jun 20, 2022 12:05 pm
by LeadGuit
Hi,
Is there a kind of "template engine" in PB? Thinking of something like e.g. Jinja or similar. Essentially creating a HTML, TXT or other file where you put in variables to replace at runtime like "Hello {{name}}".
I'm currently not intending to use it for web purposes, but more for generating things like invoices or cue sheets etc.
Best,
Mat
Re: Template engine?
Posted: Mon Jun 20, 2022 3:59 pm
by mk-soft
Simple way ...
Code: Select all
;-TOP
Global NewList Names.s()
Global Header.s = "Hello {{Name}}"
Global Titel.s
AddElement(Names())
Names() = "Tom"
AddElement(Names())
Names() = "Jerry"
ForEach Names()
Titel = ReplaceString(Header, "{{Name}}", Names())
Debug Titel
Next
Re: Template engine?
Posted: Mon Jun 20, 2022 4:29 pm
by AZJIO
Re: Template engine?
Posted: Mon Jun 20, 2022 5:17 pm
by LeadGuit
mk-soft wrote: Mon Jun 20, 2022 3:59 pm
Simple way ...
Thanks, that's definitely a way for simple use cases. The idea of the template engine would be to out logic I side of the template instead of the code - for simple replacement that here might be the way to go, but conditionals and loops In the template are the main thing I'm looking for.
AZJIO wrote: Mon Jun 20, 2022 4:29 pm
Like
this?
From what I gather through translation, it seems to go in a similar direction as mk-softs suggestion, if the source is available it would be interesting, especially the docx part.
So as different example, such as template would be like (in Jinja)
Code: Select all
{% for item in collection %}
The item name is: {{item["name"]}}
The price is {{item["price"]}}
{% if item["price"] < 50 %}
Cheap item!
{% endif %}
{% endfor %}
And the resulting render could be something like
Code: Select all
The item name is: Item A
The price is 150
The item name is: B
The price is 30
Cheap Item!
Maybe that narrows it down what I mean

Re: Template engine?
Posted: Mon Jun 20, 2022 8:10 pm
by mk-soft
Maybe write a template interpreter.
Here is a small starting point for an interpreter
Code: Select all
;-TOP beginning by mk-soft
; ***************************************************************************************
; Part Of SplitStringArray.pbi
; Link: https://www.purebasic.fr/english/viewtopic.php?t=69557
Procedure SplitParameterArray(String.s, Array Result.s(1))
Protected *String.character
Protected *Start, *End, exit, lock, do, len, temp.s, cnt, c1
Protected level
Dim Result(0)
*String = @String
If *String = 0
ProcedureReturn 0
EndIf
*Start = *String
*End = *String
c1 = 0
Repeat
If *String\c = 0
exit = #True
*End = *String
Else
If *String\c = '"'
If Not lock
lock = #True
Else
lock = #False
EndIf
EndIf
If Not lock
If *String\c = '('
If level = 0
If #True ; Get Functionname
len = (*String - *Start) / SizeOf(character)
If Len > 0
temp = PeekS(*Start, len)
ReplaceString(temp, #TAB$, " ", #PB_String_InPlace)
temp = Trim(temp)
cnt = CountString(temp, " ")
If cnt
temp = StringField(temp, cnt + 1, " ")
EndIf
Result(c1) = temp
EndIf
EndIf
*Start = *String + SizeOf(character)
EndIf
level + 1
ElseIf *String\c = ')'
level - 1
If level = 0
do = #True
exit = #True
*End = *String
EndIf
ElseIf *String\c = ',' And level = 1
do = #True
*End = *String
EndIf
EndIf
EndIf
If do
c1 + 1
If ArraySize(Result()) < c1
ReDim Result(c1 + 10)
EndIf
len = (*End - *Start) / SizeOf(character)
If Len > 0
Result(c1) = Trim(PeekS(*Start, len))
Else
Result(c1) = ""
EndIf
*Start = *String + SizeOf(character)
do = #False
EndIf
*String + SizeOf(character)
Until exit
ReDim Result(c1)
ProcedureReturn c1
EndProcedure
; ***************************************************************************************
Structure udtCollection
CollectionName.s
Map itemText.s()
Map itemValue.d()
EndStructure
Global NewList Collection.udtCollection()
Procedure.s TemplateInterpreter(Text.s, *Collection.udtCollection)
Protected r1.s, pos1, pos2, temp.s, cnt
Dim param.s(0)
With *Collection
Repeat
pos1 = FindString(text, "{{")
If pos1
r1 + Left(text, pos1 - 1)
pos2 = FindString(text, "}}", pos1)
If pos2
temp = Mid(Text, pos1 + 2, pos2 - pos1 -2)
cnt = SplitParameterArray(temp, param())
If cnt >= 1
Select param(0)
Case "itemText"
If FindMapElement(\itemText(), param(1))
r1 + \itemText()
EndIf
Case "itemValue"
If FindMapElement(\itemValue(), param(1))
Select cnt
Case 1
r1 + StrD(\itemValue())
Case 2
r1 + StrD(\itemValue(), Val(param(2)))
EndSelect
EndIf
EndSelect
EndIf
Text = Mid(text, pos2 + 2)
EndIf
Else
r1 + text
Break
EndIf
ForEver
EndWith
ProcedureReturn r1
EndProcedure
; ----
;Test
AddElement(Collection())
With Collection()
\itemText("name") = "Apple"
\itemValue("price") = 13.99
EndWith
AddElement(Collection())
With Collection()
\itemText("name") = "bears"
\itemValue("price") = 9.80
EndWith
sVal.s = "The item name is: {{itemText(name)}} " + #LF$ +
"The price is {{itemValue(price,2)}}" + #LF$ + #LF$
ForEach Collection()
Debug TemplateInterpreter(sVal, Collection())
Next
Re: Template engine?
Posted: Mon Jun 20, 2022 9:02 pm
by LeadGuit
mk-soft wrote: Mon Jun 20, 2022 8:10 pm
Maybe write a template interpreter.
Here is a small starting point for an interpreter
Thank you so much! So I'll take it that there is no (known) template engine available?
Then I'll try my hand at writing my own with your starting point (or try a different direction for the few projects I have in mind).
Thank you again
