How to use continue and break keywords in golang templates? - go-templates

For example:
{{range .Users}}
{{if .IsAdmin}}
{{/* How to use "break" or "continue"? */}}
{{end}}
{{end}}
The documentation for "break" or "continue" in templates is not available in golang.org

They are not documented because they do not exist.
To make sure - check the tests for the text/template lexer: https://github.com/golang/go/blob/master/src/text/template/parse/lex_test.go

Go101 does mention (May 2021, 4+ years later):
Since Go 1.18, "break" and "continue" might be supported in range loops of Go templates.
Note: Go 1.18 should be released in Q1 2022.
That would solve issue 20531 text/template: add break and continue support.
And is currently implemented in CL 321491: html/template, text/template: implement break and continue for range loops.
This is still a work in progress for now (Q1 2021)
Update Sept. 2021: confirmed, with commit d0dd26a
html/template, text/template: implement break and continue for range loops
break and continue for range loops was accepted as a proposal in June 2017.
It was implemented in CL 66410 (Oct 2017)
but then rolled back in CL 92155 (Feb 2018) because html/template changes had not been implemented.
This CL reimplements break and continue in text/template and then adds support for them in html/template as well.

break and continue statements are part of text/template and html/template in Go 1.10 (in Beta at time of writing). From the release notes:
The new actions {{break}} and {{continue}} break out of the innermost
{{range ...}} loop, like the corresponding Go statements.
Prior releases of Go (Before 1.10) do not support break or continue statements.
Looking at the beta documentation you can see the new itemContinue and itemBreak items in the lexer, the new nodes like ContinueNode in Parser to follow the code.

You can use a variable to add a in processing check and skip any existing checks for the remainder of the loop.
// method 1
{{ $dothing := false }}
{{ range $i, $A := .List }}
{{ if $A.Check }}
{{ $dothing = true }}
{{end}}
{{ end }}
{{ if $dothing }}
// do thing
{{ end }}
// method 2
{{ $already := false }}
{{ range $i, $A := .List }}
{{ if $already }}
{{ else }}
{{ if $A.Check }}
{{ $already = true }}
// do thing
{{ end }}
{{ end }}
{{ end }}

Related

beautifulsoup: get text (including html tags) between two different tags (</h3> and <h2>)

I am trying to scrape an html file structured as follow using beautifulsoup. Basicaly, each unit is constisted of:
one <h2></h2>
one <h3></h3>
more than one <p></p>
Something like follow:
<h2>January, 2020</h2>
<h3>facility</h3>
<p>text1-1</p>
<p>text1-2</p>
<h2>April, 2020</h2>
<h3>scientists</h3>
<p>text2-1</p>
<p>text2-2</p>
<h2>June, 2020</h2>
<h3>lawyers</h3>
<p>text3-1</p>
<h2>.....
I want to get text including the <p> tags between </h3> and the next <h2>. The result should be:
for row #1:
<p>text1-1</p>
<p>text1-2</p>
for row #2:
<p>text2-1</p>
<p>text2-2</p>
for row #3:
<p>text3-1</p>
Here is what I tried so far:
num_h2 = len(soup.find_all('h2'))
for i in range(0,num_h2):
print('---------')
print(i)
p_string = ''
sibling = soup.find_all('h3')[i].find_next_sibling('p').getText()
if sibling:
p_string += sibling
else:
break
print(p_string)
The problem with this solution is that it only shows the content of the first <p> under each unit. I do not know how to find how many <p> are there to generate a for loop. Also, is there a better way to do this than using find_next_silibing()?
Maybe css selectors can help:
for s in soup.select('h3'):
for ns in (s.fetchNextSiblings()):
if ns.name == "h2":
break
else:
if ns.name == "p":
print(ns)
Output:
<p>text1-1</p>
<p>text1-2</p>
<p>text2-1</p>
<p>text2-2</p>
<p>text3-1</p>

Go template merging dictionary with a possibly empty source dictionary

In a go template I'm merging labels from project level and application level with
{{ range $k, $v := (merge $project.labels $app.labels) }}
# Do something with $k and $v.
{{end}}
Both $project.labels and $app.labels are dictionaries generated from a yaml file.
Now I want to make app.labels as an optional field, this can be done with some extra with statement but I wonder if there is an elegant way to do this.
Currently if $app.label is not defined in the yaml file I'll get:
wrong type for value; expected map[string]interface {}; got interface {}
Figured it out by adding empty dict as a default:
{{ range $k, $v := (merge $project.labels ($app.labels | default dict)) }}

Insert an if statement in go tmpl range

In my project, in the index.tmpl file is the range function defined: {{ range $index, $jb := .Jailbreaks }} which iterates through the Jailbreaks array.
I was wondering if there is a way to check if the $index is on a defined position. So for this I tried {{ if $index == 0 }} but on compiling I get the error
Error rendering index template: template: index.tmpl:63: unexpected "=" in operand
Do I have to define a function in the main.go file to complete this task?
I am working with this project for everyone who is wondering.
You are looking for {{ if eq $index 0 }}. See https://golang.org/pkg/text/template/#hdr-Actions and https://golang.org/pkg/text/template/#hdr-Functions.

Typo3 GP variables in TSSETUP

I use typo3 7.6.10
I learn how get a url variable and store it in other variable for fluid in TSSETUP:
lib.pippomio = TEXT
lib.pippomio.data = GP:cat
example url: index.php?id=10&cat=pino
I print the variable in my template:
<f:cObject typoscriptObjectPath="lib.pippomio" />
Ok it works.
Now i need to print the variable in input by Search Indexed Engine:
<input class="tx-indexedsearch-searchbox-sword" id="tx-indexedsearch-searchbox-sword" type="text" name="tx_indexedsearch_pi2[search][sword]" value="progetto">
How can i store in lib.pippomio the POST Variable "tx_indexedsearch_pi2[search][sword]" ???
I tried
lib.pippomio.data = GP:tx_indexedsearch_pi2[search][sword]
But it doesn't works.
I want to print the word searched in an other place.
You can use a pipe "|" to get it
lib.pippomio.data = GP:tx_indexedsearch_pi2|search|sword
TYPOSCRIPT Reference => getText

Jekyll Pygments Processing

I have been fighting with Jekyll and Pygments highlighting for a while now. I have pygments installed and have generated the css file, however when I run Jekyll to generate the site, the code highlighting does not appear to generate properly.
Here is some example code I have in place for processing
{% highlight php lineos %}
/**
* Passing by reference
*
* Outputs
*
* 10 - before add() call
* 10 - after add() call
* 15 - after addref() call
*/
$a = 10;
echo $a;
add($a);
echo $a;
addref($a);
echo $a;
function addref(&$a)
{
$a += 5;
}
function add($a)
{
$a += 5;
}
{% endhighlight %}
and here is what it looks like after Jekyll builds my site.
<div class="highlight"><pre><code class="php"><span class="x">/**</span>
<span class="x"> * Passing by reference</span>
<span class="x"> *</span>
<span class="x"> * Outputs</span>
<span class="x"> *</span>
<span class="x"> * 10 - before add() call</span>
<span class="x"> * 10 - after add() call</span>
<span class="x"> * 15 - after addref() call</span>
<span class="x"> */</span>
<span class="x">$a = 10;</span>
<span class="x">echo $a;</span>
<span class="x">add($a);</span>
<span class="x">echo $a;</span>
<span class="x">addref($a);</span>
<span class="x">echo $a;</span>
<span class="x"> </span>
<span class="x">function addref(&$a)</span>
<span class="x">{</span>
<span class="x"> $a += 5;</span>
<span class="x">}</span>
<span class="x"> </span>
<span class="x">function add($a)</span>
<span class="x">{</span>
<span class="x"> $a += 5;</span>
<span class="x">}</span>
</code></pre>
</div>
As you can see Jekyll seems to be marking every line as class="x" and I am not quite sure why.
I have tried using both the liquid and jekyll from the Github repos, I have even tried using redcarpet even though it has nothing to do with the liquid template processing. I have tried just about everything I can think of but cannot seem to get this to work.
This is what it actually looks like when I view my website
http://i.stack.imgur.com/kCvLN.png
I am running the following versions.
Ruby: ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-darwin11.4.2]
rdiscount: rdiscount (1.6.8)
redcarpet: redcarpet (2.2.2)
pygments: pygments.rb (0.2.13)
Liquid: liquid (2.4.1)
Jekyll: jekyll (0.11.2)
I have just gone as far as using a redcarpet_markdown.rb plugin and setting the configuration settings to use redcarpet2 and I set the extensions for redcarpet.
markdown: redcarpet2
redcarpet:
extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "strikethrough", "superscript", "with_toc_data"]
Once that was in place I changed the code highlighting to be like this
```php
/**
* Passing by reference
*
* Outputs
*
* 10 - before add() call
* 10 - after add() call
* 15 - after addref() call
*/
$a = 10;
echo $a;
add($a);
echo $a;
addref($a);
echo $a;
function addref(&$a)
{
$a += 5;
}
function add($a)
{
$a += 5;
}
```
I then tried generating the site again and I got the same result. I am not sure if this is Jekyll causing the issue or Pygments but I have been fighting with this for the last 2 days now. But I now know it is not the markdown processor.
If you have any ideas I would be more than willing to try anything.
If you want to avoid the <?php tags you can specify the Pygment option startinline
{% highlight php startinline %}
phpinfo();
{% endhighlight %}
This way it should render properly (it worked for me).
It appears you not only have to include the opening tag for the code block but with PHP you also have to include the
```php
<?php
/**
* Passing by reference
*
* Outputs
*
* 10 - before add() call
* 10 - after add() call
* 15 - after addref() call
*/
$a = 10;
echo $a;
add($a);
echo $a;
addref($a);
echo $a;
function addref(&$a)
{
$a += 5;
}
function add($a)
{
$a += 5;
}
```