reusing handlebars & panini partials with different data - html

I've a number of 'building blocks' I've created of my own to use when templating a site and I'm wondering how I could use Panini to re-use partials on the same page, with different data.
Say for example I have a partial which basically adds a h1 tag followed by a single p tag but I want to be able to re-use that same partial on the same page with different data each time.
This is the content of the partial file for example;
<h1> {{ h1Header }}</h1>
<p> {{ pParagraph }} </p>
The Frontmatter data in the Index file;
---
h1Header: Hello!
pParagraph: This is some text.
---
And this to call the partial into action;
{{> partial }}
Unless I'm doing something fundamentally wrong the way I'm using it at the moment would mean I'd have to create several different partials for each possible outcome.
I was wondering if there was some way of sending arguments etc. If someone can point me in the right direction with even the simplest of examples just to get a feel of what I can do and what to look into I'd be grateful.

You can pass data to your partials passing a context or parameters to your partial. You can pass different data every-time you render the partial, according to the manual.
Having a partial called test:
<h1>{{foo}}</h1>
You can render it with specific data:
{{> test foo="bar"}}
{{> test foo="foobar"}}
Which results in
<h1>foo</h1>
<h1>foobar</h1>

Related

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] %}

Sub templates inside of Jekyll

Is there an equivalent to laravel's #section('') blocks in jekyll? What I am trying to do is create a template that can condense the html shared between multiple jekyll pages. For example:
default_layout
<html>
<div class="page-content">
<div class="wrapper">
{{ content }}
</div>
</div>
</html>
page_1
---
layout: default
permalink: xxx
---
<head>
<title>My title</title>
{% include header.html %}
...
<div> <!-- A shared block between pages with different content --> </div>
....
<div> <!-- Another shared block between pages with different content --> </div>
{% include footer.html %}
</html>
It looks like the current offering of jekyll allows you to use sub-templates, but limits the {{content}} block to be a separate file that also inherits the child template. I would need to create a bunch of files that inherent one another to create the final html page (or so I think).
What worked for me in Laravel was using multiple #yield and #section statements to easily insert dynamic data into a shared template. I don't think Jekyll can do this without creating a bunch of nested sub templates, but I hope I am wrong.
Solution 1:
You could use Jekyll's include files for that.
You probably already know about includes, because you're using them in the layout file in your question.
If your shared blocks are just HTML, using an include is all you need.
But maybe (I'm not sure) the shared blocks are text, meaning you'd like to use Markdown for formatting?
By default, Jekyll doesn't render Markdown in include files, but with a little trick it's still possible to include Markdown files.
I have a site where I needed the same block of text (with formatting and links) on multiple pages, so I did this:
Put the text in a Markdown file into the _includes folder, e.g. _includes/info.md
Include that file and render the Markdown by capturing it and then using the markdownify Liquid filter:
{% capture tmp %}{% include info.md %}{% endcapture %}
{{ tmp | markdownify }}
Solution 2:
If the shared blocks are the same for certain groups of pages, maybe you want to use multiple layout files.
The best example of this would be a blog built with Jekyll:
You have a "basic" layout (navigation, sidebar, footer...) that all pages share, and which is directly used by "regular" pages.
Then, you have a second layout "inheriting" from the main one, which adds stuff like post date, tags and so on - this is used by all blog posts.
Here's a simple Jekyll example for this.

Twig escaping HTML and rendering as raw

I hope someone can assist me on this issue.
I am pulling details from a database to display on a twig template (using Symfony2) but the way in which it is saved in the db makes it difficult to interpret the HTML.
Basically, the HTML tags are already translated as entities in the table, e.g.:
<p>Bach Flower Crab Apple Remedy:&nbsp;the "cleansing" Remedy can be used both internally and externally&nbsp;</p><p><strong>
And so on. I have researched the rendering options in twig and tried the following (based on me rendering a loop of product descriptions):
{% set strategy = 'html' %}
{% autoescape 'html' %}
{{ product.description|escape('html')|raw }}
{% endautoescape %}
and also just:
{{ product.description|raw }}
The first method just echoes the existing content (as entities) and the second method just renders the HTML tags to the page as follows:
<p>Bach Flower Crab Apple Remedy: the "cleansing" Remedy can be used both internally and externally.</p><p><strong>...
So, as you can see, I cannot find a way to actually interpret the HTML tags in order to display the description as it should be.
Is there a way to do this? I can't do it in the PHP as all it's doing is sending an object to the template which is looped through:
public function showAction(Request $request, $store_id=0)
{
$max = 1000;
$repository = $this->getDoctrine()->getRepository('AppBundle:Product');
$products = $repository->getProductsByStoreId($store_id,$max);
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$products,
$request->query->get('page', 1),
20
);
$return['products'] = $pagination;
$return['categories'] = $this->getCategories();
return $this->render('AppBundle:tables:productstable.html.twig', $return);
}
Your core issue is that you do not have HTML in your database to begin with. At best Twig could be outputting some HTML entities, which will render visibly as "<p>...", and at "worst" Twig will escape the text to render it accurately as it actually is, which is "<p>...". Expecting Twig to output actual HTML which will render a paragraph is unrealistic, since that's not what your original data contains at all.
You'll have to HTML-decode that text in PHP first, and then output it in Twig with ..|raw. raw means that Twig will output it as is without further escaping it. Since it's nonsense to get the data from the database to then html_entity_decode it, you need to fix your data input here! Don't HTML encode data which is going into the database, it serves no purpose.
I think you have to write custom escaper plugin to decode html entities and use it like this:
{{ product.description|myawesomehtmlentitiesdecoder|raw }}
http://twig.sensiolabs.org/doc/filters/escape.html#custom-escapers for reference.
But generally, it's better to store HTML in database and then apply needed security filters on output.

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

How do you stop the automatic line break after templates in mediawiki?

In mediawiki, whenever you embed a template into an article, it is always proceeded by a line break (as far as I know). Is there some way to prevent this so that I may place templates next to one another without the second one being on a new line?
Use the <includeonly> tag if you didn't already, and make sure not to put any returns in your template before the </includeonly>
So
<includeonly>This is a template. </includeonly>
makes {{Template}}{{Template}} output as
This is a template. This is a template
But,
<includeonly>This is a template.
</includeonly>
makes {{Template}}{{Template}} output as
This is a template.
This is a template
Even single returns are dangerous. If template A contains:
<includeonly>{{B}}
</includeonly>
and template B contains:
<includeonly>Text
</includeonly>
then when you insert {{A}} into your page, both returns are subsequent and give paragraph break.