I am building a CLI to generate code for an homemade API framework (right now to generate the controller part).
To do so, I am using template, but I saw that the template is generating nothing (an empty file), when I use words such as package or func in the template.
I want to build the following template:
package controllers
{{- range .Methods }}
{{ if eq .Name "Create" }}
func ({{ firstChar $.ModelName }}c {{ title $.ModelName }}Controller) Get{{ title $.ModelName }}(c *gin.Context) {
{{ $.ModelName }}, err := store.Find{{ title $.ModelName }}ById(c, c.Param("id"))
if err != nil {
c.AbortWithError(http.StatusNotFound, helpers.ErrorWithCode("{{ $.ModelName }}_not_found", "The {{ $.ModelName }} does not exist", err))
return
}
c.JSON(http.StatusOK, {{ $.ModelName }})
}
{{ else if eq .Name "Get" }}
{{ else if eq .Name "GetAll" }}
{{ else if eq .Name "Update" }}
{{ else if eq .Name "Delete" }}
{{ end }}
{{- end }}
Do you have any idea of how to make template working?
It's now working, I just add template.Must before template.New and it's now working like a charm.
path := filepath.Join("templates", "controller.tmpl")
body, _ := ioutil.ReadFile(path)
tmpl := template.Must(template.New("model").Funcs(funcMap).Parse(string(body)))
var buf bytes.Buffer
err := tmpl.Execute(&buf, selectedMethods)
utils.Check(err)
src, _ := format.Source(buf.Bytes())
Related
Recently I wanted to switch my static site generator from Jekyll to Hugo. I really like Hugo, but unfortunately, the usage of some functions often bothered me.
consider the code below,
{{ $my_var := `id="demo"` }}
{{ $my_slice := (findRE `id=\"(.*)\"` $my_var 1) }}
{{ index $my_slice 0 }}
reulst:
id="demo"
expected result
demo
In the above example, I want to get the value of the group.
Please note that what is really needed is a regular representation to get the group, not a tricky use of other functions (such as replace to replace the id=" with a blank or something like that)
regex test website: https://regex101.com/
Please help me, I really spent a lot of time searching but still nothing. I found someone with the same question in Hugo-discourse, but it's been a year and still no answer.
The easiest way to do this is with replaceRE, where $1 is your group number.
{{ $my_var := `id="demo"` }}
{{ $result := replaceRE `id=\"(.*)\"` "$1" $my_var }}
{{ $result }} → "demo"
Thanks to #modInfo for the inspiration, I decided to expand the answer of replaceRE
by order
{{ $my_var := `id="demo"` }}
{{ $result := replaceRE `id=\"(.*)\"` "$1" $my_var }}
{{ $result }} → "demo"
name group
{{ $my_var := `id="demo2"` }}
{{ $result := replaceRE `id=\"(?P<my_id>.*)\"` "$my_id" $my_var }}
{{ $result }} → "demo2"
more example
{{ $my_var := `<h2 id="#demo+1-3%./2\"></h2>` }}
{{ $id := replaceRE `.*id=\"(?P<my_id>([:#a-z0-9+\-%./\\])*)\">(<a href=\"(?P<my_href>[:#a-z0-9+\-%./\\]*)\">.*)?` "$my_id" $my_var }}
{{ $id }} → #demo+1-3%./2\
{{ $href := replaceRE `.*id=\"(?P<my_id>([:#a-z0-9+\-%./\\])*)\">(<a href=\"(?P<my_href>[:#a-z0-9+\-%./\\]*)\">.*)?` "$my_href" $my_var }}
{{ $href }} → https://www.google.com/
Values.Yaml
env:
isTest: 'true'
hostData:
- isActive: true
name: a
url: testA
- isActive: true
name: A
url: testB
configmap.yaml
test:
{{- with .Values.env }}
hostData: {{ .hostData | toJson}}
isTest: {{ .isTest}}
{{- end }}
Now I want to update the url of hostData
I tried to add
test:
{{- with .Values.env }}
hostData: {{ .hostData | toJson}}
isTest: {{ .isTest}}
{{- end }}
{{- range .Values.env.hostData}}
url: https://{{ .name}}//newName
{{- end }}
But it add the url to the structure of the test
test:
hostData: [{"isActive":true,"name":A","url":"testA"},{"isActive":true,"name":"B","url":"testB"}
url AnewName
url BnewName
and didn't update the hostData-> url
This is the resuLT I want
test:
hostData: [{"isActive":true,"name":AnewName","url":"testA"},{"isActive":true,"name":"BnewName","url":"testB"}]
I tried to create also tpl file and added my logic but the problem that I didn't succeed to return yaml from the tpl
{{/*
Create hostData
*/}}
{{- define "get-hostData" -}}
{{- range .Values.env.hostData}}
hostData:
- isActive: {{ .isActive }}
name: {{ .name }}
url: {{ newUrlFromValues }}
{{- end }}
The problem that in the config it didn`t return yaml but string
{{- $test1 := include "get-hostData" . }}
maybe I need to return it as json array
It's not entirely clear to me what you want to achieve. I assume your goal is to construct the url field from the name field (although in the provided example you are altering the name instead of the url (?)). You can do it by updating the hostData before converting it to JSON:
test:
{{- with .Values.env }}
{{- range .hostData}}
{{- $url := print "https://" .name "/newName" }}
{{- $_ := set . "url" $url }}
{{- end }}
hostData: {{ .hostData | toJson }}
isTest: {{ .isTest }}
{{- end }}
I have a flask page that is for editing blog posts. It has the following vue:
<form method="POST" action="{{ url_for('edit',itemid=item.id) }}" id="text-input">
{{ form.csrf_token }}
<div style="margin-left:30px;margin-top:20px;">
Title: {{ form.title }}
</div>
<br/>
<div id="editor">
Content: {{ form.content( **{':value':'input','#input': 'update'}) }}
<div v-html="compiledMarkdown"></div>
</div>
<br/>
Category: {{ form.category|safe }}
<br/>
<input type="submit" value="Save">
</form>
<script>
new Vue({
el: '#editor',
data: {
input: "starting data"
},
computed: {
compiledMarkdown: function () {
return marked(this.input, { sanitize: true })
}
},
methods: {
update: _.debounce(function (e) {
this.input = e.target.value
}, 300)
}
});
</script>
What I would like to do is have a starting value for input based on something sent in by flask. Basically I would change input: "starting data" to input: {{ form.content.data }}. However, when I do this, it stops updating the input when I change the text in the box. I think I am kind of hardcoding the data to be whatever what in form.content.data as opposed to a string.
How can I pass this in so that it starts with the form.content.data value yet is still changeable?
The reason it didn't work was because {{ form.content.data }} appears in the template as raw text.
Thus it was trying to use something like: the brown fox jumped over the lazy dog
and this doesn't compile to a javascript object. Adding quotes around the {{ form.content.data }} like '{{ form.content.data }}' fixed it.
I need to implement pagination. Actually I have pages array, page param and per_page variable.
In my code:
pages_count := math.Floor(float64(len(pages)) / float64(per_page))
then in template I need something like (pseudocode):
{{ if .page - 2 > 0 }}
{{ $start_page := .page - 2 }}
{{ else }}
{{ $start_page := 1 }}
{{ end }}
{{ if .page + 2 >= .pages_count }}
{{ $finish_page := .page + 2 }}
{{ else }}
{{ $finish_page := .pages_count }}
{{ end }}
<ul>
{{ for $i := $start_page; $i <= $finish_page; ++$i }}
<li {{ if $i == .page }} class="current_page" {{ end }}>
$i
</li>
{{ end }}
</ul>
How to implement this correctly?
Thx
When I work with Java templates (e.g. Velocity), I find that the kinds of template logic you are asking about lead to over-complex templates. The same applied in Go.
My solution is to move logic into the view-model layer and keep the templates rather dumb. This means that the controller and view model have to do a bit more work precomputing the kinds of values that your template shows. The view model is consequently larger - but it's just simple data and is easy to unit-test.
In your specific example, you would keep the for-loop that builds up the <li> list. Everything above the <ul> open tag can be handled in the view model. So the template would just work with some precomputed data.
I've got this template that parses multiple items of a slice onto the page. It does that really well.
However, I now want to use the very same template to parse a single value of the slice, based on the range index. The slice is used in multiple files so I can't just .Execute it like Slice[1:2]
{{ $bpi := .Index}}
{{ range $i, $elmt := .Slice }}
{{ if $bpi.Equals $i }}
<div>{{ .SliceContent }}</div>
{{ end }}
{{ end }}
From what I've read is that the template isn't ment for computation, but if you've got a range index and if-statements in the html/template package it seems to me that I must be doing something wrong. I can write a FuncMap ofcourse, no problemo. But it doesn't seem right to me given these facts.
I am using something like this to conditionally include a default image or the first from a supplied slice of pictures. So I think this will provide you with the basis to do what you want. I check the slice has values, pulling the Nth item using the {{index .Slice n}} syntax as follows:
{{ $idx := 2}}
{{if .Pictures}}
<img src="{{if .Pictures}}{{index .Pictures $idx}}{{end}}" alt="supplied first picture">
{{else}}
<img src="http://fpoimg.com/200x200?text=Placeholder(FPOimg.com)" alt="default picture">
{{end}}
Therefore you can do the following:
{{ $bpi := .Index}}
{{ if .Slice }}
{{ index .Slice $bpi }}
{{ end }}