Octopress HTML Includes with Arguments - jekyll

I would like to include HTML snippets within blog posts and have the code in a single place. After perusing the framework I've been able to get this to work:
source
_includes
custom
foo.html
{% include custom/foo.html %}
My question: Is there a way that I can pass arguments to foo.html? I simply want to pass some strings in and output them in a formatted way and cannot figure out what I'm missing.
Thanks for your time.

You can't. But you can use some other way likes what theme does to do this.
First, set formatted style you want in custom/foo.html, for example, I add a customfooter in source/_includes/custom/footer.html:
<p>
Copyright © {{ site.time | date: "%Y" }} - {{ site.author }} -
<span class="credit">Powered by Octopress</span>
{{ site:customfooter }}
</p>
Then, set the string you want to set in _config.yml:
url: http://fann.im
customfooter: My custom footer, bala bala.
Hope this will help you.

There's no way to do this because Jekyll is static. By definition anything you could pass from one file to another file is a known value, because it must be defined at the time of site generation. Since you can't pass dynamic values, this sort of indirection doesn't make sense because you can just put the static value where it is going to be anyway.
If you have the use case of e.g. generating 10 chunks of output that are mostly similar but differ slightly, then use a plugin to accomplish the task of isolating those changes using variables. This gives you some flexibility while still putting the value into the template where it will be used.
Here's an example of a liquid tag that abstracts generating twitter bootstrap nav tabs with specific hrefs assigned.
module Jekyll
class XmlJsonTabsTag < Liquid::Tag
def initialize(tag_name, markup, tokens)
#methodname = markup.strip
super
end
def render(context)
#wondering what this syntax is? google "here document"
<<-HTML
<ul class="nav nav-tabs">
<li class="active">
JSON
</li>
<li>
XML
</li>
</ul>
HTML
end
end
end
Liquid::Template.register_tag('xmljsontabs', Jekyll::XmlJsonTabsTag)
Pass the value to use for #methodname in the liquid tag in the template:
{% xmljsontabs foo %}
Which outputs something like
<ul class="nav nav-tabs">
<li class="active">
JSON
</li>
<li>
XML
</li>
</ul>

Related

GoLang Issues displaying JSON results on HTML template

Context:
Here is Struct:
type ReverseWhoisResponse struct {
DomainsCount int `json:"domainsCount"`
DomainsList []string `json:"domainsList"`
}
After doing everything that needs to be done, this is served to via:
c.HTML(200, "example.html", gin.H{
"total": ReverseWhoisResponse.DomainsCount,
"list": ReverseWhoisResponse.DomainsList,
})
The first part, of displaying raw JSON works just by
<pre>
<span class="inner-pre">
{{ .list}}
</span>
</pre>
Issue:
However, now i'm trying to display a parsed field as well - so that i can view both raw JSON in one tab, and parsed results in another. This is how i'm attempting to do it:
<ul>
{{range .DomainsList }}
<li>
<span>{{ .list }}</span>
</li>
{{end}}
</ul>
This is because it returns a list of URLs
E.G
example1.com
example2.com
example3.com
I'm trying to parse it so it looks decent on screen so i can actually utilize it.
At the moment, i'm not getting any errors - but i'm seeing the RAW Json in the tab, but not seeing anything in Parsed tab, any ideas what's going on or some documentation i can follow for this?
The issue was outlined by #spencerconnaughton.
My issue was that i was misusing ranges.
instead of:
<ul>
{{range .DomainsList }}
<li>
<span>{{ .list }}</span>
</li>
{{end}}
</ul>
It should have been:
<ul>
{{range .list }}
<li>
<span>{{ . }}</span>
</li>
{{end}}
</ul>
Can you share the JSON you're using as input? If {{.list}} displays raw JSON, that suggests that ReverseWhoisResponse.DomainsList contains raw JSON, which suggests it isn't being parsed as you expect. Assuming your second template code block is the parsed tab, and that's receiving the the same "total" and "list" parameters as the raw JSON block, are you sure it would be passed .DomainsList and not just {.list}? Also, in the range function, do you mean to use {{.}} instead of {{.list}}? Disclaimer: I have no experience with gin, so I'm guessing on some of this stuff. :)

Can a liquid for loop contain a page variable in Jekyll?

Let's say I have a bunch of _data files that I use to create a list for specific pages. All of the pages that have these lists have a custom front matter variable of pageName. The value of pageName just so happens to match the _data file with the list.
Rather than pasting the html blocks of code into each page, I'd like to use an include to pull in a generic block of html. To do that, the include has to be dynamic or contain liquid markup to become dynamic.
That might be more context than you need, but my question boils down to this, is something like this possible:
{% for item in site.data.{{page.pageName}} %}
{{ item.label }}
{% endfor %}
Unless I'm missing something, this doesn't work so I'm wanting to know if there's a way of achieving similar functionality.
I found this similar question, but it doesn't seem to answer whether it can be used to access a page variable to build a file name.
You can use the bracket notation like this :
{% for item in site.data[page.pageName] %}

How do I inspect Pelican variables

I'm modifying a Pelican template and I have the code below which adds url every time a page is found. I can see that the p object has the attributes url and title.
However I only knew this because I copied the code from another template shown below. Is there any way to inspect objects in jinja2 or Pelican to understand what information is contained within them?
{% for p in pages %}
<h1 class = "sidebar-title">
<a href="{{ SITEURL }}/{{ p.url }}">
{{ p.title }}
</a>
</h1>
https://github.com/getpelican/pelican-themes/blob/master/backdrop/templates/base.html
<li{% if p == page %} class="active"{% endif %}>{{ p.title }}</li>
I am not aware of an official resource explaining all variables, objects, attributes and properties in detail.
But for a start, I think the following start points suffice:
Common variables available for the standard templates
pelican.contents.py:
This is the module which contains (most of) the data structures pelican uses and which are made available in the templates. Have a look for properties (#property, these are functions which act like they are attributes) and attributes. At lines 367ff there are some very simple subclass definitions which could be of use.
pelican.writers.py: This module brings together the templating engine jinja2, the templates and the data to be inserted in the templates. Of special interest for you could be lines 138ff, as this seems like a good point to simply insert some small debug prints to see the real data which is present in the data structures.

Is there a way to evaluate string with liquid tags

I need to provide page content reference list (it should contain references on sections on page).
The only way which I can see is to use page.content and parse it, but I stumbled on problem with data evaluation. For example I can pull out this string from page.content: {{site.data.sdk.language}} SDK but there is no way to make jekyll process it, it outputs as is.
Also I want to make it possible to create cross-pages links (on specific section on page, but that link generated by another inclusion and doesn't persist in page.content in HTML form).
Is there any way to make it evaluate values from page.content?
P.S. I'm including piece of code which should build page content and return HTML with list (so there is no recursions).
P.P.S. I can't use submodules, because I need to run this pages on github pages.
Thanks.
Shouldn't {{ site.data.sdk.language | strip_html }} do it? I don't know, most probably I didn't understand the problem. Can you elaborate more? Maybe provide a link to a post you're referring to?
Thinking about the similar
{% assign title = site.data.sdk.language %}
which is a stock Liquid tag and does the job well, so instead of
{% section title={{site.data.sdk.language}} %}
write your code as
{% section title = site.data.sdk.language %}
The key here is that once you enter {%, you're in Liquid. Don't expect Liquid to go "Inception" all over itself. {{ is just a shorthand for "print this to output", but an parameter passing is not output, it's just reading a variable.
You should be able to also go wild and do:
{% section title = site.data.sdk.language | capitalize %}
For more re-read the docs: https://github.com/Shopify/liquid/wiki/Liquid-for-Designers

Reusable HTML component libraries in Django

I have a Django website with many pages all with their own unique content and markup (as opposed to a single template that is dynamically filled with data). These pages' templates are derived from a common "tool" template, which in turn derives from a "base" template. Each page also has a JS file which does the scripting for that page. Each pages data is spread around 3 or 4 locations:
the template
the page script (and maybe other page-specific statics)
a central "tool registry" which contains thing like the tool name, description and categories
for some tools, a set of template tags to do some HTML construction specific to that page (e.g. data to present in a table).
However, although each page has a unique layout and content, I still want to be able to share commonly used parametrised HTML "snippets" between pages. For example, one page has an input with a dropdown button that, using Bootstrap, looks like this:
<div class="input-group">
<span class="input-group-btn">
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">
Common baudrates
<span class="caret"></span>
</a>
<ul class="dropdown-menu pull-right" id="common-baudrate-list">
<li><a href='#'>9600</a></li>
<li><a href='#'>115200</a></li>
</ul>
</span>
<input class="form-control" type="text" id="baudrate-input" val="115200">
</div>
I'd like to make a re-uasable parametrised function/template/tag which allows me to put in a structure like this given something like "group ID", "list of entries", "left/right button position", "default value".
The ways I see to do it so far are:
As a template, which has a fairly limited syntax, and make it hard to do something like a list of entries like this: ['Entry 1', 'Entry 2']
As a template, passing data into the context via the view (doesn't really appeal because I'd be spreading the pages contents around even more).
As a template tag, building the HTML as a big nasty string
As a template tag using an XML library like lxml, which is a pretty flexible method, but suffers from verbose syntax, over-complexity and I still have get data into the tag from the template!
None of these seem like a neat, re-usable and loosely coupled way to deal with this (for example, if I change up to Bootstrap 4 in future, I may need to re-write these components, and I'd rather have to do it just once). Having a library of components like this will also make future pages easier to construct. Is there a canonical "right" way to do this, or even a commonly used idiom for it?
Edit to show solution implementation
Using inclusion tags as answered below by Wolph, I avoided using a clunky construction like this
{% with [1,2,3] as items %}
{% my_tag items.split %}
{% endwith %}
as follows:
#register.inclusion_tag('components/this_component.html')
def input_with_dropdown(dropdown_title, dropdown_items, default_value, group_id, button_left, *args, **kwargs):
split_char = kwargs['split_char'] if 'split_char' in kwargs else ' '
return {
'dropdown_items': dropdown_items.split(split_char),
'dropdown_title': dropdown_title,
'group_id': group_id,
'default_value' : default_value,
'button_left': button_left
}
And then passing in the variables like this:
{% input_with_dropdown 'Common baudrates' '9600 48000 115200' 115200 'baudrate-input' 0 %}
Have you taken a look at inclusion tags? https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
I believe that these would do exactly what you want, you can still specify parameters but you can just pass along a template to have it render really easily.
Example:
from django import template
register = template.Library()
#register.inclusion_tag('list_results.html')
def list_results(results):
return {
'results': results,
'count': len(results),
}
list_results.html:
Found {{ count }} results.<br>
<ul>
{% for result in results %}
<li>{{ result }}</li>
{% endfor %}
</ul>
Use templatetags and html template... Then you can reuse that HTML template...