Does Go feature a template language? - file

In Puppet it is possible to lookup variables in files using ERBs, e.g.:
<% #values.each do |val| -%>
Some stuff with <%= val %>
<% end -%>
How to do the same using Go?

The question is a bit unclear, but Go has a very powerful template engine built in: https://golang.org/pkg/text/template/
There's even a special HTML extension package of it that does automatic escaping based on context (attributes, tags, text, etc) - https://golang.org/pkg/html/template/
The above example would look something like:
{{ range .Values }}
Some stuff with {{ . }}
{{ end }}

Related

Hugo - using index with complex key to get data

Assuming the following urls.toml file in data folder:
[Group]
link = "http://example.com"
[Group.A]
link = "http://example.com"
I know that I can access the link value in Group.A in my shortcode like this:
{{ index .Site.Data.urls.Group.A "link" }}
But, I would like to access the link in a way similar to the following:
{{ index .Site.Data.urls "Group.A.link" }}
The reason for this is to enable me to pass the "Group.A.link" as a parameter to my "url" shortcode within the content markdown like this:
{{< url "Group.A.link" >}}
Otherwise, I won't be able to use nesting for logical organisation in the urls.toml data file.
Thanks in advance.
You can use nested calls of index COLLECTION "key" to narrow your way down.
Meaning,
(index (index (index .Site.Data.urls "Group") "A") "link")
would work given your urls.toml structure.
The trick is making it somewhat dynamic, so you don't need to worry too much about depth.
The snippet below might serve as a potential starting point for a shortcode. However, it doesn't have any safe-guards. I'd recommend to add a few checks to get meaningful errors/warnings if things go wrong.
{{ $path := .Get 0 }}
{{/* split the string to have indices to follow the path */}}
{{/* if $path is "A.B.C", $pathSlice wil be ["A" "B" "C"] */}}
{{ $pathSlice := split $path "." }}
{{ $currentValue := .Site.Data.urls }}
{{ range $pathSlice }}
{{/* recommended homework: check that $currentValue is a dict otherwise handle with defaults and/or warnings */}}
{{ $currentValue = index $currentValue . }}
{{ end }}
<p>et voila: {{ $currentValue }}</p>
After having looked at Hugo's code (Index function) I found a very simple solution.
If we want to pass a complex comma-separated key, all we need to do is split it when calling index. Example:
Using the url shortcode in markdown:
{{< url "Group.A.link" >}}
Code of the url shortcode:
{{ index .Site.Data.urls (split (.Get 0) ".")}}

Puppet array loop in erb template

I have the following Yaml:
role::test::logos::filesanddata:
logo01.jpg:
title01: 'value01'
title02: 'value02'
title03: 'value03'
title04: 'value04'
title05: 'value05'
title06: 'value06'
title07:
- title07_01: value07_01
- title07_02: value07_02
- title07_03: value07_03
- title07_04: value07_03
- title07_05: value07_04
logo02.jpg:
title01: 'value01'
Through my Class (in Puppet code) am getting the following result:
["logo01.jpg", {"title01"=>"value01", "title02"=>"value02", "title03"=>"value03", "title04"=>"value04", "title05"=>"value05", "title06"=>"value06", "title07"=>[{"title07_01"=>"value07_01"}, {"title07_02"=>"value07_02"}, {"title07_03"=>"value07_03"}, {"title07_04"=>"value07_04"}, {"title07_05"=>"value07_05}]}]
["logo02.jpg", {"title01"=>"value01"}]
I am writing a template to split the data in multiple files (so far works). I am stuck on the item "title07", how should I continue the loop from there?
<%= #arraydata[0] %>
<% #arraydata.shift -%>
<% #arraydata.each do |item| -%>
<%= item['title01'] %>
<%= item['title02'] %>
<%= item['title03'] %>
<%= item['title04'] %>
<%= item['title05'] %>
<%= item['title06'] %>
<% item['title07'].each do |inner_item| -%>
<%= inner_item['title07']['title07_01'] %>
<% end -%>
<% end -%>
Its not clear to me what the end goal is however hopefully the below example should help you unblock the issues you have
given the following hiera data:
role::test::logos::filesanddata:
logo01.jpg:
title01: 'value01'
title02: 'value02'
title03: 'value03'
title04: 'value04'
title05: 'value05'
title06: 'value06'
title07:
- title07_01: value07_01
- title07_02: value07_02
- title07_03: value07_03
- title07_04: value07_03
- title07_05: value07_04
logo02.jpg:
title01: 'value01'
The following code assuming filesanddata = lookup('role::test::logos::filesanddata')
<% #filesanddata.each_pair do |file, titles| -%>
<%- titles.each_pair do |title, values| -%>
<%- if values.is_a?(String) -%>
<%= value %>
<%- elsif value.is_a?(Array) -%>
<%# As mentioned by John Bollinger you have an array %>
<%# of hashes so we have to unpack that as well %>
<%- values.each do |value_hash| -%>
<%- value_hash.each_pair do |_, value| -%>
<%= value %>
<%- end -%>
<%- end -%>
<%- end -%>
<%- end -%>
<% end -%>
would create a file with the following content
value01
value02
value03
value04
value05
value06
value07_01
value07_02
value07_03
value07_03
value07_04
value01
There seems to be confusion both in the data and in the ERB about how the data are structured. This YAML ...
title07:
- title07_01: value07_01
- title07_02: value07_02
- title07_03: value07_03
- title07_04: value07_03
- title07_05: value07_04
... provides an array of single-key hashes as the value of the host hash's 'title07' key. That's not necessarily wrong, but it's very suspicious. It's unclear what thge array layer is supposed to be doing for you, relative to making the data a single five-element hash.
Consider the ERB presented in light of that data structure. Here ...
<% item['title07'].each do |inner_item| -%>
... item['title07'] is an array of single-key hashes, so each inner_item is one of those hashes. The one key appearing in that hash varies from hash to hash, which makes these unnecessarily difficult to work with. None of the keys is 'title07', however, so this will break:
<%= inner_item['title07']['title07_01'] %>
You would need something along the lines of
<%= inner_item['title07_01'] %>
, but accounting for the fact that the key differs from inner_item to inner_item. If you really want to try to work with that, then you might find it useful to use each_with_index instead of each, so that you can construct the needed hash key from the array index. Alternatively, you could just iterate the inner hash to get the value.
But that demonstrates some of the infelicities of that data structure. Suppose that you instead structured the data as a single multi-key hash, bypassing the array level:
title07:
title07_01: value07_01
title07_02: value07_02
title07_03: value07_03
title07_04: value07_03
title07_05: value07_04
Then iterating over the entries probably gets you what you want more directly:
<% item['title07'].each do |_, value| -%>
<%= value %>
<% end -%>
Alternatively, since the keys have a computable form you can compute the keys with which to retrieve the leaf data:
<% 1...5.each do |i| -%>
<%= item['title07']["title07_0#{i}"] %>
<% end -%>
Similar could be made to work with your array-based structure, too, but the needed expression would be more complex (and is left as an exercise).

TemplateSyntaxError - Invalid filter: 'translate' [duplicate]

I want to use AngularJS with Django however they both use {{ }} as their template tags. Is there an easy way to change one of the two to use some other custom templating tag?
For Angular 1.0 you should use the $interpolateProvider apis to configure the interpolation symbols: http://docs.angularjs.org/api/ng.$interpolateProvider.
Something like this should do the trick:
myModule.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
Keep in mind two things:
mixing server-side and client-side templates is rarely a good idea and should be used with caution. The main issues are: maintainability (hard to read) and security (double interpolation could expose a new security vector - e.g. while escaping of serverside and clientside templating by themselves might be secure, their combination might not be).
if you start using third-party directives (components) that use {{ }} in their templates then your configuration will break them. (fix pending)
While there is nothing we can do about the first issue, except for warning people, we do need to address the second issue.
you can maybe try verbatim Django template tag
and use it like this :
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
{% verbatim %}
<div ng-app="">
<p>10 is {{ 5 + 5 }}</p>
</div>
{% endverbatim %}
If you did separate sections of page properly then you can easily use angularjs tags in "raw" tag scope.
In jinja2
{% raw %}
// here you can write angularjs template tags.
{% endraw %}
In Django template (above 1.5)
{% verbatim %}
// here you can write angularjs template tags.
{% endverbatim %}
We created a very simple filter in Django 'ng' that makes it easy to mix the two:
foo.html:
...
<div>
{{ django_context_var }}
{{ 'angularScopeVar' | ng }}
{{ 'angularScopeFunction()' | ng }}
</div>
...
The ng filter looks like this:
from django import template
from django.utils import safestring
register = template.Library()
#register.filter(name='ng')
def Angularify(value):
return safestring.mark_safe('{{%s}}' % value)
So I got some great help in the Angular IRC channel today. It turns out you can change Angular's template tags very easily. The necessary snippets below should be included after your angular include (the given example appears on their mailing lists and would use (()) as the new template tags, substitute for your own):
angular.markup('(())', function(text, textNode, parentElement){
if (parentElement[0].nodeName.toLowerCase() == 'script') return;
text = text.replace(/\(\(/g,'{{').replace(/\)\)/g, '}}');
textNode.text(text);
return angular.markup('{{}}').call(this, text, textNode, parentElement);
});
angular.attrMarkup('(())', function(value, name, element){
value = value.replace(/\(\(/g,'{{').replace(/\)\)/, '}}');
element[0].setAttribute(name, value);
return angular.attrMarkup('{{}}').call(this, value, name, element);
});
Also, I was pointed to an upcoming enhancement that will expose startSymbol and endSymbol properties that can be set to whatever tags you desire.
I vote against using double parentheses (()) as template tag. It may work well as long as no function call is involved but when tried the following
ng:disabled=(($invalidWidgets.visible()))
with Firefox (10.0.2) on Mac I got a terribly long error instead of the intended logic. <[]> went well for me, at least up until now.
Edit 2012-03-29:
Please note that $invalidWidgets is deprecated. However I'd still use another wrapper than double braces. For any angular version higher than 0.10.7 (I guess) you could change the wrapper a lot easier in your app / module definition:
angular.module('YourAppName', [], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<[');
$interpolateProvider.endSymbol(']>');
});
API docs.
You could always use ng-bind instead of {{ }}
http://docs.angularjs.org/api/ng/directive/ngBind
<span ng-bind="name"></span>
I found the code below helpful. I found the code here: http://djangosnippets.org/snippets/2787/
"""
filename: angularjs.py
Usage:
{% ng Some.angular.scope.content %}
e.g.
{% load angularjs %}
<div ng-init="yourName = 'foobar'">
<p>{% ng yourName %}</p>
</div>
"""
from django import template
register = template.Library()
class AngularJS(template.Node):
def __init__(self, bits):
self.ng = bits
def render(self, ctx):
return "{{%s}}" % " ".join(self.ng[1:])
def do_angular(parser, token):
bits = token.split_contents()
return AngularJS(bits)
register.tag('ng', do_angular)
If you use django 1.5 and newer use:
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
If you are stuck with django 1.2 on appengine extend the django syntax with the verbatim template command like this ...
from django import template
register = template.Library()
class VerbatimNode(template.Node):
def __init__(self, text):
self.text = text
def render(self, context):
return self.text
#register.tag
def verbatim(parser, token):
text = []
while 1:
token = parser.tokens.pop(0)
if token.contents == 'endverbatim':
break
if token.token_type == template.TOKEN_VAR:
text.append('{{')
elif token.token_type == template.TOKEN_BLOCK:
text.append('{%')
text.append(token.contents)
if token.token_type == template.TOKEN_VAR:
text.append('}}')
elif token.token_type == template.TOKEN_BLOCK:
text.append('%}')
return VerbatimNode(''.join(text))
In your file use:
from google.appengine.ext.webapp import template
template.register_template_library('utilities.verbatim_template_tag')
Source:
http://bamboobig.blogspot.co.at/2011/09/notebook-using-jquery-templates-in.html
You can tell Django to output {{ and }}, as well as other reserved template strings by using the {% templatetag %} tag.
For instance, using {% templatetag openvariable %} would output {{.
I would stick with a solution that uses both django tags {{}} as well angularjs {{}} with a either a verbatim section or templatetag.
That is simply because you can change the way angularjs works (as mentioned) via the $interpolateProvider.startSymbol $interpolateProvider.endSymbol but if you start to use other angularjs components like the ui-bootstrap you will find that some of the templates are ALREADY built with standard angularjs tags {{ }}.
For example look at https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html.
If you do any server-side interpolation, the only correct way to do this is with <>
$interpolateProvider.startSymbol('<{').endSymbol('}>');
Anything else is an XSS vector.
This is because any Angular delimiters which are not escaped by Django can be entered by the user into the interpolated string; if someone sets their username as "{{evil_code}}", Angular will happily run it. If you use a character than Django escapes, however, this won't happen.

puppet: iterate over hash which has an array for particular values

I have a hash, built from yaml via stdlib, which includes arrays within the hash. Here is a sample of the yaml:
datacenter1:
propertyA:
- associatedItem
cage1:
serviceA:
- server1
- server2
serviceB:
- server10
backupCage:
cage2
cage2:
serviceA:
- server3
- server4
- server5
serviceB:
- server11
backupCage:
cage1
datacenter2:
cage1:
serviceA:
- server20
- server21
datacenter3:
propertyZ:
serviceD:
- server200
- server201
in this case I need to get a list of servers which offer a service within a particular datacenter in erb. Ultimately this is just going to need to output in text with some arbitrary data added for an conf file. I'm trying to get all servers providing serviceA for a given datacenter, in this example for datacenter1:
thiscommand blahblah server1
thiscommand blahblah server2
thiscommand blahblah server3
thiscommand blahblah server4
thiscommand blahblah server5
I use this map extensively for a variety of things, but this is the first case in which i can't just set a variable in puppet and iterate over that as a single array in erb.
EDIT1:
This data comes from puppet but i am trying to use it in erb via template().
EDIT2:
Note this code would never run against datacenter3, since this code is specific to datacenters which run serviceA.
Edit3:
This is the form that ended up working:
<% #hash['datacenter1'].values.each do |v| %>
<%- if v.is_a?(Hash) and v.has_key?('serviceA') -%>
<% v['serviceA'].each do |myservice| %>
thiscommand blah blah <%= myservice -%>
<% end %>
<% end %>
It is unclear if you are trying to do this within Puppet or Ruby, so here is how to do it within both.
Puppet:
$hash['datacenter1'].each |$dc_key, $dc_nest_hash| {
if $dc_nest_hash['serviceA'] {
$dc_nest_hash['serviceA'].each |$serviceA_element| {
notify { "thiscommand blahblah ${serviceA_element}": }
}
}
}
https://docs.puppet.com/puppet/4.9/function.html#each
Ruby in ERB before passed through Puppet template function (comments are elucidation for this answer; remove before actually forming template):
<% #hash['datacenter1'].each do |_, dc_nest_hash| -%>
# contents of each datacenter1 nested hash in dc_nest_hash and iterate over each hash
<%- if dc_nest_hash.key?('serviceA') -%>
<%- dc_nest_hash['serviceA'].each do |serviceA_element| -%>
# lookup serviceA key in each dc_nest_hash and iterate over elements
thiscommand blahblah <%= serviceA_element %>
<%- end -%>
<%- end -%>>
<% end -%>
https://ruby-doc.org/core-2.1.1/Object.html#method-i-enum_for
http://ruby-doc.org/core-2.1.0/Array.html#method-i-each

How do you compare variables from different tables with ruby on rails?

For example, within a model/data-set/table (technical term?) called "microposts" if I have id and user_id columns, to compare the two sets I can use
Micropost.where("user_id = ?", id)
I am wondering, however, how to do the same thing with data from different data-sets/tables/models. In this particular scenario I am trying to find all instances where a user's community variable is equal to the community variable of any microposts. I'm attempting to match the content of the strings so that all microposts are rendered that have a community variable that matches the current user's community variable. These variables are in string form as #city + #state under the column "community" in the users's and microposts's model/datasets/table. Illustrated:
users table microposts table
user_id community micropost_id content community
1 FairfieldIowa 1 blub! FairfieldIowa
2 FairfieldIowa 2 Hiiy FairfieldIowa
3 Salt Lake CityUtah 3 wwowt! Salt Lake CityUtah
4 Salt Lake CityUtah 4 hey Salt Lake CityUtah
5 FairfieldIowa 5 sweet FairfieldIowa
I thought this might work in the User model:
def communityfeed
Micropost.where("community = ?", user.community)
end
However, it is incorrect because of syntax, logic, or because "user" does not define all users, I think.
Then I defined communityfeed_items in a pages_controller as:
def home
if logged_in?
#micropost = current_user.microposts.build
#communityfeed_items = communityfeed.paginate(page: params[:page])
end
end
But I get an undefined local variable or method communityfeed error
This could be because I'm not providing any user to use the method on. Perhaps simply using a variable for all users will solve my problem, but this is something I could not find. I've tried all_users, and user, with no success. Is it possible to compare variables to render a result in this way, and if so, what is the syntax to cycle through all user/microposts and check for these matches?
I also built several partials to function together to render the microposts, however, without the #communityfeed_items variable functioning correctly, they are of little use.
_communityfeed.html.erb
<% if #communityfeed_items.any? %>
<ol class="microposts">
<%= render partial: 'shared/communityfeed_item', collection: #communityfeed_items %>
</ol>
<%= will_paginate #communityfeed_items %>
<% end %>
_communityfeed_items.html.erb
<li id="<%= communityfeed_item.id %>">
<%= link_to gravatar_for(communityfeed_item.user), communityfeed_item.user %>
<span class="user">
<%= link_to communityfeed_item.user.name, communityfeed_item.user %>
</span>
<span class="content"><%= communityfeed_item.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(communityfeed_item.created_at) %> ago.
</span>
<% if current_user?(communityfeed_item.user) %>
<%= link_to "delete", communityfeed_item, method: :delete,
confirm: "You sure?",
title: communityfeed_item.content %>
<% end %>
</li>
If I have approached this problem in a severely inefficient/impossible way, I am open to suggestions.
Thanks for your time, generosity, and expertise.

Resources