Hugo Pass Shortcode Variables From Pages Into sitemap.xml - variables

Currently Hugo's built-in sitemap generator only creates two field attributes for images -- image:loc and image:license. Unfortunately this does not tell Google Bots much about the images context for SEO. The fields, image:title & image:caption at minimum is needed with the other two for best practices; Otherwise it's basically dead XML code.
I am working on a site that is image-content driven and since a short code is given in each page labeled as "Featured-Image" and contains the needed variables where I would like to extract/pass into the sitemap.
Here is an example of the shortcode within a page.md:
{{<
featured-image
name ="THE_IMAGE_NAME.jpg"
featuredTitle ="THE_IMAGE_TITLE"
location ="THE_IMAGE_LOCATION"
alt ="THE_IMAGE_ALT/CAPTION"
>}}
Within the sitemap.xml is what I would like to do:
{{ $license := .Site.Params.schema.license }}
{{ range .Data.Pages }}
...
{{ range $i := .Resources.ByType "image" }}
// Below is the additional data I am wanting to get from the pages'
// shortcode named "featured-image" -- But How Do I Get It?.
{{ $caption := .Get "alt" }}
{{ $location := .Get "location"}}
{{ $title := .Get "featuredTitle"}}
<image:image>
<image:loc>{{ $i.Permalink }}</image:loc>
<image:license>{{ $license }}</image:license>
// Below are the additional attributes needed:
<image:geo_location>{{ $location }}</image:geo_location>
<image:title>{{ $title }}</image:title>
<image:caption>{{ $caption }}</image:caption>
</image:image>
...

Related

Extracting data from div tag

so im scraping data from a website and it has some data in its div tag
like this :
<div class="search-result__title">\nDonald Duck <span>\xa0|\xa0</span>\n<span class="city state" data-city="city, TX;city, TX;city, TX;city, TX" data-state="TX">STATENAME, CITYNAME\n</span>\n</div>,
I want to scrape "Donald Duck" part and state and city name after rel="nofollow"
the site contains a lot of data so name and state are different
the code that i have written is
div = soup.find_all('div', {'class':'search-result__title'})
print (div.string)
this gives me a error
"ResultSet object has no attribute '%s'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?" % key
first, use .text. Second, find_all() will return a list of elements. You need to specify the index value with either: print (div[0].text), or since you will probably have more than 1 element, just iterate through them
from bs4 import BeautifulSoup
html = '''<div class="search-result__title">\nDonald Duck <span>\xa0|\xa0</span>\n<span class="city state" data-city="city, TX;city, TX;city, TX;city, TX" data-state="TX">STATENAME, CITYNAME\n</span>\n</div>'''
soup = BeautifulSoup(html, 'html.parser')
div = soup.find_all('div', {'class':'search-result__title'})
print (div[0].text)
#OR
for each in div:
print (each.text)

I am passing a URL with area target, but everything past hashtag is missing

I have some links in my database that have area target in then using hashtag #. Example: www.mydomain.com/help/#howcanifixthis
When passing TXTurl www.mydomain.com/help/#howcanifixthis in a link and using Get in the form to input variable only www.mydomain.com/help/ shows up in the form. The hashtag and the area name is missing.
I have tried using htmlentities($TXTurl) and urlencode($TXTurl), and still no luck.
Here is the link the php where I am trying to pass the variable with the hashtag in it.
if($stmt->rowCount() > 0){
while($row = $stmt->fetch()){
echo "<p>" . $row["TXTlinkname"] . "</p>";
}
This is how I am inserting the links with hashtags into my database.
$sql = "INSERT IGNORE INTO TABLENAME (TXTlinkname, TXTurl)
VALUES ('$TXTlinkname', '$TXTurl')";
Here is the input fields that I am passing variables to...
<input type="text" name="TXTlinkname" value="' . htmlspecialchars($_GET["TXTlinkname"]) . '" id="TXTlinkname" class="form-control" placeholder="Type in Hyperlink Name Here..." autocomplete="off">
<input type="url" name="TXTurl" value="' . htmlspecialchars($_GET["TXTurl"]) . '" class="form-control" placeholder="Enter in the URL" autocomplete="on">
I want to be able to pass the URL variable in a link with the hashtag to the form. All My links in my database are to different URL's with the hashtag at the end of the link.
Anything past the # is not sent to he server, you can use GET variables though.

how to insert a new empty line on selected index number in an array using \n. while we loop through it using v-for and create a list

want to insert a new empty line before a selected array element while we loop through it using v-for to create a list..trying to do this using \n isn't working
<!-- this is the template part -->
<ul>
<li v-for = "ninja in ninjas" > {{ninja}}</li>
</ul>
/* this is the script part notice index no 2 in the array*/
data() {
return {
ninjas: [
'mati kahe kumhaar sey, tu kya ronday mohey',
' Ik din aisa aayega mai rondungi tohe',
'\n aaye hain toh jaayengay Raja, Rank, fkeer',
' Ik sinhaasan chodi chale, Ik baandhay zanjeer'
]
};
},
This is pretty easy to do using the <pre> tag which forces it to preserve white space, new lines, etc. This is often used for preserving formatting in code examples.
<div id="app">
<ul>
<li v-for = "ninja in ninjas" ><pre>{{ninja}}</pre></li>
</ul>
</div>
working example: https://jsfiddle.net/skribe/10yL6va8/8/
You will probably want to use css to style the text surrounded by <pre> since most browsers automatically format it differently.

How do I check if collection contains an object with a specific key in handlebars

Assuming custom_fields contains this data, and I want to find out if it has an item/object with the name = "hide_options". I want to pass this to a component.
WARNING
Using occurrences in this way is a hack. If the name isn't unique enough, you may get false-positives
[
{"id":"12","name":"hide_options","value":"true"},
{"id":"13","name":"state","value":"colorado"},
{"id":"14","name":"city","value":"colorado, springs"}
]
The closest I've come up with is this:
templates\components\products\product-view.html
{{> components/products/conditionallyVisibile
hideOptions=(occurrences (join (pluck product.custom_fields "name") ",") "hide_options")
}}
components/products/conditionallyVisibile.html
<div>
hideOptions {{ hideOptions }}
</div>
Am I missing an easier Array or Collection helper that would make this easier? Most of the Array/Collection helpers are block helpers.
EDIT:
I was missing a significantly easier way to do this via the Filter Array Helper
{{#filter product.custom_fields "hide_options" property="name"}}
{{> components/products/conditionallyVisibile hideOptions=true }}
{{else}}
{{> components/products/conditionallyVisibile hideOptions=false }}
{{/filter}}
EDIT 2:
the scalar-form of
(occurrences (join (pluck product.custom_fields "name") ",") "hide_options")
is almost-equivalent to the block-form
{{#inArray (pluck product.custom_fields 'name') 'hide_options' }}

How can I conditionally set a variable in a Go template based on an expression which may cause an error if not wrapped with an if statement

Question
How do I do something like this:
{{ $use_ssl := (ne $.Env.CERT_NAME "") }}
where $.Env.CERT_NAME may be nil/undefined. If it is nil, it gives this error:
at <ne $.Env.CERT_NAME "">: error calling ne: invalid type for comparison
Note: I have no control over the objects passed in to the Go template so have to solve this entirely within the template itself.
What I've tried
I tried to work around by first checking to see if it is non-empty:
{{ $use_ssl := ( ($.Env.CERT_NAME) && (ne $.Env.CERT_NAME "") ) }}
but it gives this error:
unexpected "&" in operand
So I switched to this, which is allowed syntactically:
{{ $use_ssl := (and ($.Env.CERT_NAME) (ne $.Env.CERT_NAME "") ) }}
but then I lose the short-circuit evaluation that I would get with the && operator and I'm back to getting this error again:
at <ne $.Env.CERT_NAME ...>: error calling ne: invalid type for comparison
Okay, I thought, if I can't do it in a nice one-liner, and Go doesn't have a ternary operator, that's fine, I'll just do it the idiomatic Go way, which is apparently if/else.
{{ if $.Env.CERT_NAME }}
{{ $use_ssl := (ne $.Env.CERT_NAME "") }}
{{ else }}
{{ $use_ssl := false }}
{{ end }}
But then of course I run into scoping issues, because if inexplicably (or at least annoyingly) creates a new variable scope (unlike in Ruby/ERB templates that I am more used to), so apparently I can't even do this:
{{ if $.Env.CERT_NAME }}
{{ $use_ssl := true }}
{{ else }}
{{ $use_ssl := false }}
{{ end }}
# $use_ssl: {{ $use_ssl }}
without getting this error now:
undefined variable "$use_ssl"
"No sweat", I thought. I'll just declare the variable in the outside scope so it will have the correct scope and the inner scope will still be able to change that variable (the one with the outer scope). (That's how it works in Ruby, by the way.)
Nope, apparently all that does is create 2 different variables with the same name but different scopes (how's that for confusing!):
{{ $use_ssl := false }}
{{ if $.Env.CERT_NAME }}
{{ $use_ssl := true }}
# $use_ssl: {{ $use_ssl }}
{{ else }}
{{ $use_ssl := false }}
{{ end }}
# $use_ssl: {{ $use_ssl }}
# $use_ssl: true
# $use_ssl: false
I've also tried inlining the if statement like this:
{{ $use_ssl := if $.Env.CERT_NAME { true } }}
but that gives this error:
unexpected <if> in command
Apparently if statements can't be used as expressions in Go like they can in Ruby?
I also get syntax errors if I try the various alternatives to the ternary operator suggested in What is the idiomatic Go equivalent of C's ternary operator?, like:
c := map[bool]int{true: 1, false: 0} [5 > 4]
And sure, you can read variables from outer scopes in inner scopes with $.something but how do you set $.something in the inner scope?
If not like that, then how??
So what have I missed? Is this even possible in a Go template?
Go templates (I'm new to them) seem very limiting. Almost everything you can do in Go itself is not possible in a template. But hopefully there is a workaround...
http://play.golang.org/p/SufZdsx-1v has a clever workaround involving creating a new object with {{$hasFemale := cell false}} and then setting a value with $hasFemale.Set true, but how can I do something like that without having access to the code that evaluates the template (where they are calling template.FuncMap)?
Others who have tried and failed
https://groups.google.com/forum/#!topic/golang-nuts/MUzNZ9dbHrg
This is the biggest (and only) problem I have with Go. I simply do not understand why this functionality has not been implemented yet.
When the template package is used in a generic context (eg. Executing
an arbitrary template file with an arbitrary json file), you might not
have the luxury of doing precalculations.
https://github.com/golang/go/issues/10608
This is probably as designed, but it would be really nice if there was a way to get the changed $v outside of the conditional.
This is the #1 template question we get over at Hugo (https://github.com/spf13/hugo). We have added a hack [$.Scratch.Set "v1" 123] to work around it for now ...
Currently working solution
If you update the scope rather than declare a variable, either by using set or by using merge you will be able to access it outside of the if clause.
{{- if eq .podKind "core" -}}
{{- $dummy := set . "matchNodePurpose" .Values.scheduling.corePods.nodeAffinity.matchNodePurpose }}
{{- else if eq .podKind "user" -}}
{{- $dummy := set . "matchNodePurpose" .Values.scheduling.userPods.nodeAffinity.matchNodePurpose }}
{{- end -}}
# Will now output what you decided within an if/else if clause
{{- .matchNodePurpose }}
Future solution (Available with Helm 2.10)
I came across the same question in the context of Helm templates which are go templates with some additional features pre-installed such as Sprig.
28 March 2018, in this pr a Terenary operator was added to Sprig, and in time Helm will have them as well solving the issue both you and I have.
terenary
true | ternary "b" "c" will return "b"
false | ternary "b" "c" will return "c"
Your fourth try would work if you'd use the assignment operator instead of the definition operator:
{{ $use_ssl := false }}
{{ if $.Env.CERT_NAME }}
{{ $use_ssl = true }} # notice the missing colon!
{{ else }}
{{ $use_ssl = false }}
{{ end }}
I think I may have found a workaround for my particular problem, though I would love to hear other answers that solve the problem more generally.
Came across this line in https://github.com/jwilder/nginx-proxy/blob/1e0b930/nginx.tmpl#L91:
{{ $default_host := or ($.Env.DEFAULT_HOST) "" }}
which gave me another idea to try. I guess the solution is to use a combination of or and set extra temporary variables...
{{ $cert_name := or $.Env.CERT_NAME "" }}
{{ $use_ssl := ne $cert_name "" }}